Merge mozilla-central and fx-team

This commit is contained in:
Ed Morley 2013-09-13 15:13:34 +01:00
commit ef26a08f6d
378 changed files with 21070 additions and 23057 deletions

View File

@ -1089,10 +1089,6 @@ pref("devtools.inspector.markupPreview", false);
pref("devtools.inspector.remote", false);
pref("devtools.inspector.show_pseudo_elements", true);
// Enable the Layout View
pref("devtools.layoutview.enabled", true);
pref("devtools.layoutview.open", false);
// Enable the Responsive UI tool
pref("devtools.responsiveUI.enabled", true);
pref("devtools.responsiveUI.no-reload-notification", false);

View File

@ -28,9 +28,8 @@ tests.testConsole = function(options) {
}
Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
function onExecute () {
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
ok(labels.length > 0, "output for pprint(window)");
function onExecute (msg) {
ok(msg, "output for pprint(window)");
hud.jsterm.once("messages-cleared", onClear);
@ -45,7 +44,7 @@ tests.testConsole = function(options) {
}
function onClear() {
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
let labels = hud.outputNode.querySelectorAll(".message");
is(labels.length, 0, "no output in console");
helpers.audit(options, [

View File

@ -19,33 +19,32 @@ XPCOMUtils.defineLazyModuleGetter(this, "console",
"resource://gre/modules/devtools/Console.jsm");
/**
* Utility to get access to the current breakpoint list
* @param dbg The debugger panel
* @returns an array of object, one for each breakpoint, where each breakpoint
* object has the following properties:
* - id: A unique identifier for the breakpoint. This is not designed to be
* shown to the user.
* - label: A unique string identifier designed to be user visible. In theory
* the label of a breakpoint could change
* - url: The URL of the source file
* - lineNumber: The line number of the breakpoint in the source file
* - lineText: The text of the line at the breakpoint
* - truncatedLineText: lineText truncated to MAX_LINE_TEXT_LENGTH
* Utility to get access to the current breakpoint list.
*
* @param DebuggerPanel dbg
* The debugger panel.
* @return array
* An array of objects, one for each breakpoint, where each breakpoint
* object has the following properties:
* - url: the URL of the source file.
* - label: a unique string identifier designed to be user visible.
* - lineNumber: the line number of the breakpoint in the source file.
* - lineText: the text of the line at the breakpoint.
* - truncatedLineText: lineText truncated to MAX_LINE_TEXT_LENGTH.
*/
function getAllBreakpoints(dbg) {
let breakpoints = [];
let sources = dbg.panelWin.DebuggerView.Sources;
let { trimUrlLength: tr } = dbg.panelWin.SourceUtils;
let sources = dbg._view.Sources;
let { trimUrlLength: trim } = dbg.panelWin.SourceUtils;
for (let source in sources) {
for (let { attachment: breakpoint } in source) {
breakpoints.push({
id: source.value + ":" + breakpoint.lineNumber,
label: source.label + ":" + breakpoint.lineNumber,
url: source.value,
lineNumber: breakpoint.lineNumber,
lineText: breakpoint.lineText,
truncatedLineText: tr(breakpoint.lineText, MAX_LINE_TEXT_LENGTH, "end")
label: source.label + ":" + breakpoint.line,
lineNumber: breakpoint.line,
lineText: breakpoint.text,
truncatedLineText: trim(breakpoint.text, MAX_LINE_TEXT_LENGTH, "end")
});
}
}
@ -70,10 +69,8 @@ gcli.addCommand({
description: gcli.lookup("breaklistDesc"),
returnType: "breakpoints",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger", { ensure_opened: true });
return dbg.then(function(dbg) {
return getAllBreakpoints(dbg);
});
let dbg = getPanel(context, "jsdebugger", { ensureOpened: true });
return dbg.then(getAllBreakpoints);
}
});
@ -151,7 +148,7 @@ gcli.addCommand({
data: function(context) {
let dbg = getPanel(context, "jsdebugger");
if (dbg) {
return dbg.panelWin.DebuggerView.Sources.values;
return dbg._view.Sources.values;
}
return [];
}
@ -166,8 +163,6 @@ gcli.addCommand({
],
returnType: "string",
exec: function(args, context) {
args.type = "line";
let dbg = getPanel(context, "jsdebugger");
if (!dbg) {
return gcli.lookup("debuggerStopped");
@ -175,13 +170,13 @@ gcli.addCommand({
let deferred = context.defer();
let position = { url: args.file, line: args.line };
dbg.addBreakpoint(position, function(aBreakpoint, aError) {
if (aError) {
deferred.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
return;
}
dbg.addBreakpoint(position).then(() => {
deferred.resolve(gcli.lookup("breakaddAdded"));
}, aError => {
deferred.resolve(gcli.lookupFormat("breakaddFailed", [aError]));
});
return deferred.promise;
}
});
@ -199,16 +194,14 @@ gcli.addCommand({
name: "selection",
lookup: function(context) {
let dbg = getPanel(context, "jsdebugger");
if (dbg == null) {
if (!dbg) {
return [];
}
return getAllBreakpoints(dbg).map(breakpoint => {
return {
name: breakpoint.label,
value: breakpoint,
description: breakpoint.truncatedLineText
};
});
return getAllBreakpoints(dbg).map(breakpoint => ({
name: breakpoint.label,
value: breakpoint,
description: breakpoint.truncatedLineText
}));
}
},
description: gcli.lookup("breakdelBreakidDesc")
@ -221,23 +214,15 @@ gcli.addCommand({
return gcli.lookup("debuggerStopped");
}
let breakpoint = dbg.getBreakpoint(
args.breakpoint.url, args.breakpoint.lineNumber);
if (breakpoint == null) {
return gcli.lookup("breakNotFound");
}
let deferred = context.defer();
try {
dbg.removeBreakpoint(breakpoint, function() {
deferred.resolve(gcli.lookup("breakdelRemoved"));
});
} catch (ex) {
console.error('Error removing breakpoint, already removed?', ex);
// If the debugger has been closed already, don't scare the user.
let position = { url: args.breakpoint.url, line: args.breakpoint.lineNumber };
dbg.removeBreakpoint(position).then(() => {
deferred.resolve(gcli.lookup("breakdelRemoved"));
}
}, () => {
deferred.resolve(gcli.lookup("breakNotFound"));
});
return deferred.promise;
}
});
@ -259,8 +244,8 @@ gcli.addCommand({
description: gcli.lookup("dbgOpen"),
params: [],
exec: function(args, context) {
return gDevTools.showToolbox(context.environment.target, "jsdebugger")
.then(() => null);
let target = context.environment.target;
return gDevTools.showToolbox(target, "jsdebugger").then(() => null);
}
});
@ -272,11 +257,11 @@ gcli.addCommand({
description: gcli.lookup("dbgClose"),
params: [],
exec: function(args, context) {
if (!getPanel(context, "jsdebugger"))
if (!getPanel(context, "jsdebugger")) {
return;
return gDevTools.closeToolbox(context.environment.target)
.then(() => null);
}
let target = context.environment.target;
return gDevTools.closeToolbox(target).then(() => null);
}
});
@ -404,17 +389,18 @@ gcli.addCommand({
returnType: "dom",
exec: function(args, context) {
let dbg = getPanel(context, "jsdebugger");
let doc = context.environment.chromeDocument;
if (!dbg) {
return gcli.lookup("debuggerClosed");
}
let sources = dbg._view.Sources.values;
let doc = context.environment.chromeDocument;
let div = createXHTMLElement(doc, "div");
let ol = createXHTMLElement(doc, "ol");
sources.forEach(function(src) {
sources.forEach(source => {
let li = createXHTMLElement(doc, "li");
li.textContent = src;
li.textContent = source;
ol.appendChild(li);
});
div.appendChild(ol);
@ -437,8 +423,8 @@ gcli.addCommand({
clientMethod: "unblackBox",
l10nPrefix: "dbgUnBlackBox"
}
].forEach(function (cmd) {
const lookup = function (id) {
].forEach(function(cmd) {
const lookup = function(id) {
return gcli.lookup(cmd.l10nPrefix + id);
};
@ -450,11 +436,12 @@ gcli.addCommand({
name: "source",
type: {
name: "selection",
data: function (context) {
data: function(context) {
let dbg = getPanel(context, "jsdebugger");
return dbg
? [s for (s of dbg._view.Sources.values)]
: [];
if (dbg) {
return dbg._view.Sources.values;
}
return [];
}
},
description: lookup("SourceDesc"),
@ -473,7 +460,7 @@ gcli.addCommand({
}
],
returnType: "dom",
exec: function (args, context) {
exec: function(args, context) {
const dbg = getPanel(context, "jsdebugger");
const doc = context.environment.chromeDocument;
if (!dbg) {
@ -482,9 +469,7 @@ gcli.addCommand({
const { promise, resolve, reject } = context.defer();
const { activeThread } = dbg._controller;
const globRegExp = args.glob
? globToRegExp(args.glob)
: null;
const globRegExp = args.glob ? globToRegExp(args.glob) : null;
// Filter the sources down to those that we will need to black box.
@ -512,12 +497,11 @@ gcli.addCommand({
const blackBoxed = [];
for (let source of toBlackBox) {
let { url } = source;
activeThread.source(source)[cmd.clientMethod](function ({ error }) {
activeThread.source(source)[cmd.clientMethod](function({ error }) {
if (error) {
blackBoxed.push(lookup("ErrorDesc") + " " + url);
blackBoxed.push(lookup("ErrorDesc") + " " + source.url);
} else {
blackBoxed.push(url);
blackBoxed.push(source.url);
}
if (toBlackBox.length === blackBoxed.length) {
@ -531,8 +515,10 @@ gcli.addCommand({
function displayResults() {
const results = doc.createElement("div");
results.textContent = lookup("NonEmptyDesc");
const list = createXHTMLElement(doc, "ul");
results.appendChild(list);
for (let result of blackBoxed) {
const item = createXHTMLElement(doc, "li");
item.textContent = result;
@ -547,23 +533,24 @@ gcli.addCommand({
});
/**
* A helper to create xhtml namespaced elements
* A helper to create xhtml namespaced elements.
*/
function createXHTMLElement(document, tagname) {
return document.createElementNS("http://www.w3.org/1999/xhtml", tagname);
}
/**
* A helper to go from a command context to a debugger panel
* A helper to go from a command context to a debugger panel.
*/
function getPanel(context, id, options = {}) {
if (context == null) {
if (!context) {
return undefined;
}
let target = context.environment.target;
if (options.ensure_opened) {
return gDevTools.showToolbox(target, id).then(function(toolbox) {
if (options.ensureOpened) {
return gDevTools.showToolbox(target, id).then(toolbox => {
return toolbox.getPanel(id);
});
} else {
@ -577,11 +564,11 @@ function getPanel(context, id, options = {}) {
}
/**
* Converts a glob to a regular expression
* Converts a glob to a regular expression.
*/
function globToRegExp(glob) {
const reStr = glob
// Escape existing regular expression syntax
// Escape existing regular expression syntax.
.replace(/\\/g, "\\\\")
.replace(/\//g, "\\/")
.replace(/\^/g, "\\^")
@ -600,7 +587,7 @@ function globToRegExp(glob) {
.replace(/\[/g, "\\[")
.replace(/\]/g, "\\]")
.replace(/\-/g, "\\-")
// Turn * into the match everything wildcard
// Turn * into the match everything wildcard.
.replace(/\*/g, ".*")
return new RegExp("^" + reStr + "$");
}

View File

@ -35,7 +35,7 @@ this.BrowserDebuggerProcess = function BrowserDebuggerProcess(aOnClose, aOnRun)
this._initServer();
this._initProfile();
this._create();
}
};
/**
* Initializes and starts a chrome debugger process.

File diff suppressed because it is too large Load Diff

View File

@ -6,23 +6,24 @@
"use strict";
const { Cc, Ci, Cu, Cr } = require("chrome");
const EventEmitter = require("devtools/shared/event-emitter");
const promise = require("sdk/core/promise");
const EventEmitter = require("devtools/shared/event-emitter");
function DebuggerPanel(iframeWindow, toolbox) {
this.panelWin = iframeWindow;
this._toolbox = toolbox;
this._destroyer = null;
this._view = this.panelWin.DebuggerView;
this._controller = this.panelWin.DebuggerController;
this._controller._target = this.target;
this._bkp = this._controller.Breakpoints;
this.highlightWhenPaused = this.highlightWhenPaused.bind(this);
this.unhighlightWhenResumed = this.unhighlightWhenResumed.bind(this);
EventEmitter.decorate(this);
}
};
exports.DebuggerPanel = DebuggerPanel;
DebuggerPanel.prototype = {
@ -32,7 +33,7 @@ DebuggerPanel.prototype = {
* @return object
* A promise that is resolved when the Debugger completes opening.
*/
open: function DebuggerPanel_open() {
open: function() {
let targetPromise;
// Local debugging needs to make the target remote.
@ -54,40 +55,41 @@ DebuggerPanel.prototype = {
})
.then(null, function onError(aReason) {
Cu.reportError("DebuggerPanel open failed. " +
reason.error + ": " + reason.message);
aReason.error + ": " + aReason.message);
});
},
// DevToolPanel API
get target() this._toolbox.target,
destroy: function() {
// Make sure this panel is not already destroyed.
if (this._destroyer) {
return this._destroyer;
}
this.target.off("thread-paused", this.highlightWhenPaused);
this.target.off("thread-resumed", this.unhighlightWhenResumed);
this.emit("destroyed");
return promise.resolve(null);
return this._destroyer = this._controller.shutdownDebugger().then(() => {
this.emit("destroyed");
});
},
// DebuggerPanel API
addBreakpoint: function() {
this._bkp.addBreakpoint.apply(this._bkp, arguments);
addBreakpoint: function(aLocation, aOptions) {
return this._controller.Breakpoints.addBreakpoint(aLocation, aOptions);
},
removeBreakpoint: function() {
this._bkp.removeBreakpoint.apply(this._bkp, arguments);
},
getBreakpoint: function() {
return this._bkp.getBreakpoint.apply(this._bkp, arguments);
},
getAllBreakpoints: function() {
return this._bkp.store;
removeBreakpoint: function(aLocation) {
return this._controller.Breakpoints.removeBreakpoint(aLocation);
},
highlightWhenPaused: function() {
this._toolbox.highlightTool("jsdebugger");
// Also raise the toolbox window if it is undocked or select the
// corresponding tab when toolbox is docked.
this._toolbox.raise();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const SOURCE_URL_DEFAULT_MAX_LENGTH = 64; // chars
const SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE = 1048576; // 1 MB in bytes
const SOURCE_URL_DEFAULT_MAX_LENGTH = 64; // chars
const STACK_FRAMES_SOURCE_URL_MAX_LENGTH = 15; // chars
const STACK_FRAMES_SOURCE_URL_TRIM_SECTION = "center";
const STACK_FRAMES_POPUP_SOURCE_URL_MAX_LENGTH = 32; // chars
@ -18,6 +18,7 @@ const BREAKPOINT_CONDITIONAL_POPUP_OFFSET_X = 7; // px
const BREAKPOINT_CONDITIONAL_POPUP_OFFSET_Y = -3; // px
const RESULTS_PANEL_POPUP_POSITION = "before_end";
const RESULTS_PANEL_MAX_RESULTS = 10;
const FILE_SEARCH_ACTION_MAX_DELAY = 300; // ms
const GLOBAL_SEARCH_EXPAND_MAX_RESULTS = 50;
const GLOBAL_SEARCH_LINE_MAX_LENGTH = 300; // chars
const GLOBAL_SEARCH_ACTION_MAX_DELAY = 1500; // ms
@ -27,8 +28,13 @@ const SEARCH_FUNCTION_FLAG = "@";
const SEARCH_TOKEN_FLAG = "#";
const SEARCH_LINE_FLAG = ":";
const SEARCH_VARIABLE_FLAG = "*";
Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
const DEFAULT_EDITOR_CONFIG = {
mode: SourceEditor.MODES.TEXT,
readOnly: true,
showLineNumbers: true,
showAnnotationRuler: true,
showOverviewRuler: true
};
/**
* Object defining the debugger view components.
@ -37,14 +43,18 @@ let DebuggerView = {
/**
* Initializes the debugger view.
*
* @param function aCallback
* Called after the view finishes initializing.
* @return object
* A promise that is resolved when the view finishes initializing.
*/
initialize: function(aCallback) {
dumpn("Initializing the DebuggerView");
initialize: function() {
if (this._startup) {
return this._startup;
}
let deferred = promise.defer();
this._startup = deferred.promise;
this._initializePanes();
this.Toolbar.initialize();
this.Options.initialize();
this.Filtering.initialize();
@ -55,19 +65,25 @@ let DebuggerView = {
this.Sources.initialize();
this.WatchExpressions.initialize();
this.GlobalSearch.initialize();
this._initializeVariablesView();
this._initializeEditor(aCallback);
this._initializeEditor(deferred.resolve);
return deferred.promise;
},
/**
* Destroys the debugger view.
*
* @param function aCallback
* Called after the view finishes destroying.
* @return object
* A promise that is resolved when the view finishes destroying.
*/
destroy: function(aCallback) {
dumpn("Destroying the DebuggerView");
destroy: function() {
if (this._shutdown) {
return this._shutdown;
}
let deferred = promise.defer();
this._shutdown = deferred.promise;
this.Toolbar.destroy();
this.Options.destroy();
@ -79,11 +95,10 @@ let DebuggerView = {
this.Sources.destroy();
this.WatchExpressions.destroy();
this.GlobalSearch.destroy();
this._destroyPanes();
this._destroyEditor();
this._destroyEditor(deferred.resolve);
aCallback();
return deferred.promise;
},
/**
@ -140,10 +155,10 @@ let DebuggerView = {
this.Variables.on("fetched", (aEvent, aType) => {
switch (aType) {
case "variables":
window.dispatchEvent(document, "Debugger:FetchedVariables");
window.emit(EVENTS.FETCHED_VARIABLES);
break;
case "properties":
window.dispatchEvent(document, "Debugger:FetchedProperties");
window.emit(EVENTS.FETCHED_PROPERTIES);
break;
}
});
@ -158,44 +173,56 @@ let DebuggerView = {
_initializeEditor: function(aCallback) {
dumpn("Initializing the DebuggerView editor");
let placeholder = document.getElementById("editor");
let config = {
mode: SourceEditor.MODES.JAVASCRIPT,
readOnly: true,
showLineNumbers: true,
showAnnotationRuler: true,
showOverviewRuler: true
};
this.editor = new SourceEditor();
this.editor.init(placeholder, config, () => {
this.editor.init(document.getElementById("editor"), DEFAULT_EDITOR_CONFIG, () => {
this._loadingText = L10N.getStr("loadingText");
this._onEditorLoad();
aCallback();
this._onEditorLoad(aCallback);
});
},
/**
* The load event handler for the source editor, also executing any necessary
* post-load operations.
*
* @param function aCallback
* Called after the editor finishes loading.
*/
_onEditorLoad: function() {
_onEditorLoad: function(aCallback) {
dumpn("Finished loading the DebuggerView editor");
DebuggerController.Breakpoints.initialize();
window.dispatchEvent(document, "Debugger:EditorLoaded", this.editor);
this.editor.focus();
DebuggerController.Breakpoints.initialize().then(() => {
window.emit(EVENTS.EDITOR_LOADED, this.editor);
aCallback();
});
},
/**
* Destroys the SourceEditor instance and also executes any necessary
* post-unload operations.
*
* @param function aCallback
* Called after the editor finishes destroying.
*/
_destroyEditor: function() {
_destroyEditor: function(aCallback) {
dumpn("Destroying the DebuggerView editor");
DebuggerController.Breakpoints.destroy();
window.dispatchEvent(document, "Debugger:EditorUnloaded", this.editor);
DebuggerController.Breakpoints.destroy().then(() => {
window.emit(EVENTS.EDITOR_UNLOADED, this.editor);
aCallback();
});
},
/**
* Sets the currently displayed text contents in the source editor.
* This resets the mode and undo stack.
*
* @param string aTextContent
* The source text content.
*/
_setEditorText: function(aTextContent = "") {
this.editor.setMode(SourceEditor.MODES.TEXT);
this.editor.setText(aTextContent);
this.editor.resetUndo();
},
/**
@ -209,7 +236,7 @@ let DebuggerView = {
* @param string aTextContent [optional]
* The source text content.
*/
setEditorMode: function(aUrl, aContentType = "", aTextContent = "") {
_setEditorMode: function(aUrl, aContentType = "", aTextContent = "") {
// Avoid setting the editor mode for very large files.
if (aTextContent.length >= SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) {
this.editor.setMode(SourceEditor.MODES.TEXT);
@ -239,144 +266,123 @@ let DebuggerView = {
/**
* Sets the currently displayed source text in the editor.
*
* To update the source editor's current caret and debug location based on
* a requested url and line, use the DebuggerView.updateEditor method.
* You should use DebuggerView.updateEditor instead. It updates the current
* caret and debug location based on a requested url and line.
*
* @param object aSource
* The source object coming from the active thread.
* @return object
* A promise that is resolved after the source text has been set.
*/
set editorSource(aSource) {
if (!this._isInitialized || this._isDestroyed || this._editorSource == aSource) {
return;
_setEditorSource: function(aSource) {
// Avoid setting the same source text in the editor again.
if (this._editorSource.url == aSource.url) {
return this._editorSource.promise;
}
dumpn("Setting the DebuggerView editor source: " + aSource.url +
", fetched: " + !!aSource._fetched);
let deferred = promise.defer();
this.editor.setMode(SourceEditor.MODES.TEXT);
this.editor.setText(L10N.getStr("loadingText"));
this.editor.resetUndo();
this._editorSource = aSource;
this._setEditorText(L10N.getStr("loadingText"));
this._editorSource = { url: aSource.url, promise: deferred.promise };
DebuggerController.SourceScripts.getTextForSource(aSource).then(([, aText]) => {
// Avoid setting an unexpected source. This may happen when fast switching
// between sources that haven't been fetched yet.
if (this._editorSource != aSource) {
DebuggerController.SourceScripts.getText(aSource).then(([, aText]) => {
// Avoid setting an unexpected source. This may happen when switching
// very fast between sources that haven't been fetched yet.
if (this._editorSource.url != aSource.url) {
return;
}
this.editor.setText(aText);
this.editor.resetUndo();
this.setEditorMode(aSource.url, aSource.contentType, aText);
// Update the editor's current caret and debug locations given by the
// currently active frame in the stack, if there's one available.
this.updateEditor();
this._setEditorText(aText);
this._setEditorMode(aSource.url, aSource.contentType, aText);
// Synchronize any other components with the currently displayed source.
DebuggerView.Sources.selectedValue = aSource.url;
DebuggerController.Breakpoints.updateEditorBreakpoints();
// Notify that we've shown a source file.
window.dispatchEvent(document, "Debugger:SourceShown", aSource);
// Resolve and notify that a source file was shown.
window.emit(EVENTS.SOURCE_SHOWN, aSource);
deferred.resolve([aSource, aText]);
},
([, aError]) => {
// Rejected.
let msg = L10N.getStr("errorLoadingText") + DevToolsUtils.safeErrorString(aError);
this.editor.setText(msg);
window.dispatchEvent(document, "Debugger:SourceErrorShown", aError);
dumpn(msg);
this._setEditorText(msg);
Cu.reportError(msg);
dumpn(msg);
// Reject and notify that there was an error showing the source file.
window.emit(EVENTS.SOURCE_ERROR_SHOWN, aSource);
deferred.reject([aSource, aError]);
});
return deferred.promise;
},
/**
* Gets the currently displayed source text in the editor.
*
* @return object
* The source object coming from the active thread.
*/
get editorSource() this._editorSource,
/**
* Update the source editor's current caret and debug location based on
* a requested url and line. If unspecified, they default to the location
* given by the currently active frame in the stack.
* a requested url and line.
*
* @param string aUrl [optional]
* @param string aUrl
* The target source url.
* @param number aLine [optional]
* The target line number in the source.
* The target line in the source.
* @param object aFlags [optional]
* Additional options for showing the source. Supported options:
* - charOffset: character offset for the caret or debug location
* - lineOffset: line offset for the caret or debug location
* - columnOffset: column offset for the caret or debug location
* - noSwitch: don't switch to the source if not currently selected
* - noCaret: don't set the caret location at the specified line
* - noDebug: don't set the debug location at the specified line
* @return object
* A promise that is resolved after the source text has been set.
*/
updateEditor: function(aUrl, aLine, aFlags = {}) {
if (!this._isInitialized || this._isDestroyed) {
return;
setEditorLocation: function(aUrl, aLine = 0, aFlags = {}) {
// Avoid trying to set a source for a url that isn't known yet.
if (!this.Sources.containsValue(aUrl)) {
return promise.reject(new Error("Unknown source for the specified URL."));
}
// If the location is not specified, default to the location given by
// the currently active frame in the stack.
if (!aUrl && !aLine) {
// If the line is not specified, default to the current frame's position,
// if available and the frame's url corresponds to the requested url.
if (!aLine) {
let cachedFrames = DebuggerController.activeThread.cachedFrames;
let currentFrame = DebuggerController.StackFrames.currentFrame;
let frame = cachedFrames[currentFrame];
if (frame) {
let { url, line } = frame.where;
this.updateEditor(url, line, { noSwitch: true });
let currentDepth = DebuggerController.StackFrames.currentFrameDepth;
let frame = cachedFrames[currentDepth];
if (frame && frame.where.url == aUrl) {
aLine = frame.where.line;
}
return;
}
dumpn("Updating the DebuggerView editor: " + aUrl + " @ " + aLine +
", flags: " + aFlags.toSource());
let sourceItem = this.Sources.getItemByValue(aUrl);
let sourceForm = sourceItem.attachment.source;
// If the currently displayed source is the requested one, update.
if (this.Sources.selectedValue == aUrl) {
set(aLine);
}
// If the requested source exists, display it and update.
else if (this.Sources.containsValue(aUrl) && !aFlags.noSwitch) {
this.Sources.selectedValue = aUrl;
set(aLine);
}
// Dumb request, invalidate the caret position and debug location.
else {
set(0);
}
// Updates the source editor's caret position and debug location.
// @param number a Line
function set(aLine) {
let editor = DebuggerView.editor;
// Handle any additional options for showing the source.
// Make sure the requested source client is shown in the editor, then
// update the source editor's caret position and debug location.
return this._setEditorSource(sourceForm).then(() => {
// Line numbers in the source editor should start from 1. If invalid
// or not specified, then don't do anything.
if (aLine < 1) {
return;
}
if (aFlags.charOffset) {
aLine += editor.getLineAtOffset(aFlags.charOffset);
aLine += this.editor.getLineAtOffset(aFlags.charOffset);
}
if (aFlags.lineOffset) {
aLine += aFlags.lineOffset;
}
if (!aFlags.noCaret) {
editor.setCaretPosition(aLine - 1, aFlags.columnOffset);
this.editor.setCaretPosition(aLine - 1, aFlags.columnOffset);
}
if (!aFlags.noDebug) {
editor.setDebugLocation(aLine - 1, aFlags.columnOffset);
this.editor.setDebugLocation(aLine - 1, aFlags.columnOffset);
}
}
});
},
/**
* Gets the text in the source editor's specified line.
*
* @param number aLine [optional]
* The line to get the text from.
* If unspecified, it defaults to the current caret position line.
* The line to get the text from. If unspecified, it defaults to
* the current caret position.
* @return string
* The specified line's text.
*/
@ -387,17 +393,6 @@ let DebuggerView = {
return this.editor.getText(start, end);
},
/**
* Gets the text in the source editor's selection bounds.
*
* @return string
* The selected text.
*/
getEditorSelectionText: function() {
let selection = this.editor.getSelection();
return this.editor.getText(selection.start, selection.end);
},
/**
* Gets the visibility state of the instruments pane.
* @return boolean
@ -461,12 +456,15 @@ let DebuggerView = {
this.Variables.empty();
if (this.editor) {
this.editor.setMode(SourceEditor.MODES.TEXT);
this.editor.setText("");
this.editor.focus();
this._editorSource = null;
this.editor.resetUndo();
this._editorSource = {};
}
},
_startup: null,
_shutdown: null,
Toolbar: null,
Options: null,
Filtering: null,
@ -478,16 +476,14 @@ let DebuggerView = {
Sources: null,
Variables: null,
WatchExpressions: null,
_editor: null,
_editorSource: null,
editor: null,
_editorSource: {},
_loadingText: "",
_sourcesPane: null,
_instrumentsPane: null,
_instrumentsPaneToggleButton: null,
_collapsePaneString: "",
_expandPaneString: "",
_isInitialized: false,
_isDestroyed: false
};
/**
@ -760,10 +756,11 @@ ResultsPanelContainer.prototype = Heritage.extend(WidgetMethods, {
*/
set hidden(aFlag) {
if (aFlag) {
this._panel.hidden = true;
this._panel.hidePopup();
} else {
this._panel.hidden = false;
this._panel.openPopup(this._anchor, this.position, this.left, this.top);
this.anchor.focus();
}
},

View File

@ -4,6 +4,7 @@
MOCHITEST_BROWSER_TESTS = \
browser_dbg_aaa_run_first_leaktest.js \
browser_dbg_bfcache.js \
browser_dbg_blackboxing-01.js \
browser_dbg_blackboxing-02.js \
browser_dbg_blackboxing-03.js \
@ -11,167 +12,172 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_blackboxing-05.js \
browser_dbg_blackboxing-06.js \
browser_dbg_blackboxing-07.js \
browser_dbg_breadcrumbs-access.js \
browser_dbg_breakpoints-actual-location.js \
browser_dbg_breakpoints-contextmenu.js \
browser_dbg_breakpoints-editor.js \
browser_dbg_breakpoints-highlight.js \
browser_dbg_breakpoints-new-script.js \
browser_dbg_breakpoints-pane.js \
browser_dbg_chrome-debugging.js \
browser_dbg_clean-exit.js \
browser_dbg_cmd.js \
browser_dbg_cmd_blackbox.js \
browser_dbg_cmd_break.js \
browser_dbg_debuggerstatement.js \
browser_dbg_cmd-blackbox.js \
browser_dbg_cmd-break.js \
browser_dbg_cmd-dbg.js \
browser_dbg_conditional-breakpoints-01.js \
browser_dbg_conditional-breakpoints-02.js \
browser_dbg_debugger-statement.js \
browser_dbg_editor-contextmenu.js \
browser_dbg_editor-mode.js \
browser_dbg_function-display-name.js \
browser_dbg_globalactor.js \
browser_dbg_iframes.js \
browser_dbg_instruments-pane-collapse.js \
browser_dbg_listaddons.js \
browser_dbg_listtabs-01.js \
browser_dbg_listtabs-02.js \
browser_dbg_tabactor-01.js \
browser_dbg_tabactor-02.js \
browser_dbg_globalactor-01.js \
browser_dbg_nav-01.js \
browser_dbg_propertyview-01.js \
browser_dbg_propertyview-02.js \
browser_dbg_propertyview-03.js \
browser_dbg_propertyview-04.js \
browser_dbg_propertyview-05.js \
browser_dbg_propertyview-06.js \
browser_dbg_propertyview-07.js \
browser_dbg_propertyview-08.js \
browser_dbg_propertyview-09.js \
browser_dbg_propertyview-10.js \
browser_dbg_propertyview-11.js \
browser_dbg_propertyview-12.js \
browser_dbg_propertyview-edit-value.js \
browser_dbg_propertyview-edit-watch.js \
browser_dbg_propertyview-data-big.js \
browser_dbg_propertyview-data-getset-01.js \
browser_dbg_propertyview-data-getset-02.js \
browser_dbg_propertyview-data.js \
browser_dbg_propertyview-filter-01.js \
browser_dbg_propertyview-filter-02.js \
browser_dbg_propertyview-filter-03.js \
browser_dbg_propertyview-filter-04.js \
browser_dbg_propertyview-filter-05.js \
browser_dbg_propertyview-filter-06.js \
browser_dbg_propertyview-filter-07.js \
browser_dbg_propertyview-filter-08.js \
browser_dbg_propertyview-reexpand.js \
$(filter disabled-temporarily--bug-782179, browser_dbg_reload-same-script.js) \
browser_dbg_reload-preferred-script.js \
browser_dbg_pane-collapse.js \
browser_dbg_panesize-inner.js \
browser_dbg_breadcrumbs-access.js \
browser_dbg_location-changes-01-simple.js \
browser_dbg_location-changes-02-blank.js \
browser_dbg_location-changes-03-new.js \
browser_dbg_location-changes-04-breakpoint.js \
browser_dbg_multiple-windows.js \
browser_dbg_navigation.js \
browser_dbg_on-pause-highlight.js \
browser_dbg_panel-size.js \
browser_dbg_pause-exceptions-01.js \
browser_dbg_pause-exceptions-02.js \
browser_dbg_pause-resume.js \
browser_dbg_pause-warning.js \
browser_dbg_progress-listener-bug.js \
browser_dbg_reload-preferred-script-01.js \
browser_dbg_reload-preferred-script-02.js \
browser_dbg_reload-preferred-script-03.js \
browser_dbg_reload-same-script.js \
browser_dbg_scripts-switching-01.js \
browser_dbg_scripts-switching-02.js \
browser_dbg_scripts-switching-03.js \
browser_dbg_search-basic-01.js \
browser_dbg_search-basic-02.js \
browser_dbg_search-basic-03.js \
browser_dbg_search-basic-04.js \
browser_dbg_search-global-01.js \
browser_dbg_search-global-02.js \
browser_dbg_search-global-03.js \
browser_dbg_search-global-04.js \
browser_dbg_search-global-05.js \
browser_dbg_search-global-06.js \
browser_dbg_search-sources-01.js \
browser_dbg_search-sources-02.js \
browser_dbg_search-sources-03.js \
browser_dbg_search-symbols.js \
browser_dbg_searchbox-help-popup-01.js \
browser_dbg_searchbox-help-popup-02.js \
browser_dbg_searchbox-parse.js \
browser_dbg_source-maps-01.js \
browser_dbg_source-maps-02.js \
browser_dbg_source-maps-03.js \
browser_dbg_sources-cache.js \
browser_dbg_sources-labels.js \
browser_dbg_sources-sorting.js \
browser_dbg_stack-01.js \
browser_dbg_stack-02.js \
browser_dbg_stack-03.js \
browser_dbg_stack-04.js \
browser_dbg_stack-05.js \
browser_dbg_location-changes.js \
browser_dbg_location-changes-new.js \
browser_dbg_location-changes-blank.js \
browser_dbg_location-changes-bp.js \
browser_dbg_sources-cache.js \
browser_dbg_scripts-switching.js \
browser_dbg_scripts-switching-02.js \
browser_dbg_scripts-switching-03.js \
browser_dbg_scripts-sorting.js \
browser_dbg_scripts-searching-01.js \
browser_dbg_scripts-searching-02.js \
browser_dbg_scripts-searching-03.js \
browser_dbg_scripts-searching-04.js \
browser_dbg_scripts-searching-05.js \
browser_dbg_scripts-searching-06.js \
browser_dbg_scripts-searching-07.js \
browser_dbg_scripts-searching-08.js \
browser_dbg_scripts-searching-files_ui.js \
browser_dbg_scripts-searching-popup.js \
browser_dbg_function-search.js \
browser_dbg_pause-resume.js \
browser_dbg_pause-warning.js \
browser_dbg_update-editor-mode.js \
browser_dbg_select-line.js \
browser_dbg_breakpoint-new-script.js \
browser_dbg_bug723069_editor-breakpoints.js \
browser_dbg_bug723071_editor-breakpoints-pane.js \
browser_dbg_bug723071_editor-breakpoints-highlight.js \
browser_dbg_bug723071_editor-breakpoints-contextmenu.js \
browser_dbg_bug740825_conditional-breakpoints-01.js \
browser_dbg_bug740825_conditional-breakpoints-02.js \
browser_dbg_bug727429_watch-expressions-01.js \
browser_dbg_bug727429_watch-expressions-02.js \
browser_dbg_bug731394_editor-contextmenu.js \
browser_dbg_bug737803_editor_actual_location.js \
browser_dbg_bug786070_hide_nonenums.js \
browser_dbg_bug868163_highight_on_pause.js \
browser_dbg_displayName.js \
browser_dbg_pause-exceptions.js \
browser_dbg_pause-exceptions-reload.js \
browser_dbg_multiple-windows.js \
browser_dbg_iframes.js \
browser_dbg_bfcache.js \
browser_dbg_progress-listener-bug.js \
browser_dbg_chrome-debugging.js \
browser_dbg_source_maps-01.js \
browser_dbg_source_maps-02.js \
browser_dbg_source_maps-03.js \
browser_dbg_stack-06.js \
browser_dbg_step-out.js \
browser_dbg_event-listeners.js \
browser_dbg_tabactor-01.js \
browser_dbg_tabactor-02.js \
browser_dbg_variables-view-01.js \
browser_dbg_variables-view-02.js \
browser_dbg_variables-view-03.js \
browser_dbg_variables-view-04.js \
browser_dbg_variables-view-05.js \
browser_dbg_variables-view-accessibility.js \
browser_dbg_variables-view-data.js \
browser_dbg_variables-view-edit-getset-01.js \
browser_dbg_variables-view-edit-getset-02.js \
browser_dbg_variables-view-edit-value.js \
browser_dbg_variables-view-edit-watch.js \
browser_dbg_variables-view-filter-01.js \
browser_dbg_variables-view-filter-02.js \
browser_dbg_variables-view-filter-03.js \
browser_dbg_variables-view-filter-04.js \
browser_dbg_variables-view-filter-05.js \
browser_dbg_variables-view-filter-pref.js \
browser_dbg_variables-view-filter-searchbox.js \
browser_dbg_variables-view-frame-parameters-01.js \
browser_dbg_variables-view-frame-parameters-02.js \
browser_dbg_variables-view-frame-parameters-03.js \
browser_dbg_variables-view-frame-with.js \
browser_dbg_variables-view-frozen-sealed-nonext.js \
browser_dbg_variables-view-hide-non-enums.js \
browser_dbg_variables-view-large-array-buffer.js \
browser_dbg_variables-view-reexpand-01.js \
browser_dbg_variables-view-reexpand-02.js \
browser_dbg_variables-view-webidl.js \
browser_dbg_watch-expressions-01.js \
browser_dbg_watch-expressions-02.js \
head.js \
$(NULL)
MOCHITEST_BROWSER_PAGES = \
browser_dbg_blackboxing.html \
blackboxing_blackboxme.js \
blackboxing_one.js \
blackboxing_two.js \
blackboxing_three.js \
browser_dbg_cmd_break.html \
browser_dbg_cmd.html \
doc_binary_search.html \
doc_blackboxing.html \
doc_cmd-break.html \
doc_cmd-dbg.html \
doc_conditional-breakpoints.html \
doc_editor-mode.html \
doc_empty-tab-01.html \
doc_empty-tab-02.html \
doc_event-listeners.html \
doc_frame-parameters.html \
doc_function-display-name.html \
doc_function-search.html \
doc_iframes.html \
doc_included-script.html \
doc_inline-debugger-statement.html \
doc_inline-script.html \
doc_large-array-buffer.html \
doc_minified.html \
doc_pause-exceptions.html \
doc_recursion-stack.html \
doc_script-switching-01.html \
doc_script-switching-02.html \
doc_step-out.html \
doc_watch-expressions.html \
doc_with-frame.html \
code_binary_search.coffee \
code_binary_search.js \
code_binary_search.map \
code_blackboxing_blackboxme.js \
code_blackboxing_one.js \
code_blackboxing_two.js \
code_blackboxing_three.js \
code_function-search-01.js \
code_function-search-02.js \
code_function-search-03.js \
code_location-changes.js \
code_math.js \
code_math.map \
code_math.min.js \
code_script-switching-01.js \
code_script-switching-02.js \
code_test-editor-mode \
testactors.js \
browser_dbg_tab1.html \
browser_dbg_tab2.html \
browser_dbg_addon1.xpi \
browser_dbg_addon2.xpi \
browser_dbg_debuggerstatement.html \
browser_dbg_stack.html \
browser_dbg_script-switching.html \
browser_dbg_script-switching-02.html \
test-script-switching-01.js \
test-script-switching-02.js \
browser_dbg_big-data.html \
browser_dbg_frame-parameters.html \
browser_dbg_update-editor-mode.html \
test-editor-mode \
browser_dbg_displayName.html \
browser_dbg_iframes.html \
browser_dbg_with-frame.html \
browser_dbg_pause-exceptions.html \
browser_dbg_breakpoint-new-script.html \
browser_dbg_conditional-breakpoints.html \
browser_dbg_watch-expressions.html \
browser_dbg_function-search-01.html \
browser_dbg_function-search-02.html \
test-function-search-01.js \
test-function-search-02.js \
test-function-search-03.js \
binary_search.html \
binary_search.coffee \
binary_search.js \
binary_search.map \
math.js \
math.min.js \
math.map \
minified.html \
test-location-changes-bp.js \
test-location-changes-bp.html \
test-step-out.html \
test-pause-exceptions-reload.html \
test-event-listeners.html \
addon1.xpi \
addon2.xpi \
$(NULL)
# Bug 888811 & bug 891176:
# Disable browser_dbg_bug883220_raise_on_pause.js due to frequent failures
# Disable browser_dbg_on-pause-raise.js due to frequent failures
# Bug 847558:
# Disable browser_dbg_chrome-create.js to fix Ubuntu hangs
ifneq (Linux,$(OS_ARCH))
MOCHITEST_BROWSER_TESTS += \
browser_dbg_bug883220_raise_on_pause.js \
browser_dbg_createChrome.js \
browser_dbg_chrome-create.js \
browser_dbg_on-pause-raise.js \
$(NULL)
else
$(browser_dbg_createChrome.js disabled to fix for ubuntu hangs, bug 847558)
endif
# Bug 895426:
@ -179,6 +185,7 @@ endif
ifneq (Darwin,$(OS_ARCH))
MOCHITEST_BROWSER_TESTS += \
browser_dbg_break-on-dom-event.js \
browser_dbg_event-listeners.js \
$(NULL)
endif

View File

@ -1,12 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<title>Browser Debugger Source Map Test</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript" src="binary_search.js"></script>
</head>
<body>
</body>
</html>

View File

@ -1 +0,0 @@
function one() { two(); }

View File

@ -1 +0,0 @@
function three() { doDebuggerStatement(); }

View File

@ -1 +0,0 @@
function two() { three(); }

View File

@ -2,72 +2,27 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This tests if the debugger leaks.
* This tests if the debugger leaks on initialization and sudden destruction.
* You can also use this initialization format as a template for other tests.
* If leaks happen here, there's something very, very fishy going on.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
function test() {
// Wait longer for this very simple test that comes first, to make sure that
// GC from previous tests does not interfere with the debugger suite.
requestLongerTimeout(2);
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
resumed = true;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
ok(aTab, "Should have a tab available.");
ok(aDebuggee, "Should have a debuggee available.");
ok(aPanel, "Should have a debugger pane available.");
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
executeSoon(startTest);
waitForSourceAndCaretAndScopes(aPanel, "-02.js", 6).then(() => {
resumeDebuggerThenCloseAndFinish(aPanel);
});
executeSoon(function() {
gDebuggee.firstCall();
});
});
function onScriptShown(aEvent)
{
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function performTest()
{
closeDebuggerAndFinish();
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
aDebuggee.firstCall();
});
}

View File

@ -1,129 +1,92 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that the debugger is updated with the correct scripts when moving
* Make sure that the debugger is updated with the correct sources when moving
* back and forward in the tab.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gSources = null;
const TAB_URL_1 = EXAMPLE_URL + "doc_script-switching-01.html";
const TAB_URL_2 = EXAMPLE_URL + "doc_recursion-stack.html";
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
let gTab, gDebuggee, gPanel, gDebugger;
let gSources;
function test() {
initDebugger(TAB_URL_1).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gSources = gDebugger.DebuggerView.Sources;
testInitialLoad();
});
}
function testInitialLoad() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
executeSoon(function() {
validateFirstPage();
testLocationChange();
});
});
gDebuggee.firstCall();
}
function testLocationChange()
{
gDebugger.DebuggerController.activeThread.resume(function() {
gDebugger.DebuggerController._target.once("navigate", function onTabNavigated(aEvent, aPacket) {
ok(true, "tabNavigated event was fired.");
info("Still attached to the tab.");
gDebugger.addEventListener("Debugger:AfterSourcesAdded", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
validateSecondPage();
testBack();
});
testFirstPage()
.then(testLocationChange)
.then(testBack)
.then(testForward)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
gDebugger.DebuggerController.client.activeTab.navigateTo(STACK_URL);
});
}
function testBack()
{
gDebugger.DebuggerController._target.once("navigate", function onTabNavigated(aEvent, aPacket) {
ok(true, "tabNavigated event was fired after going back.");
info("Still attached to the tab.");
function testFirstPage() {
info("Testing first page.");
gDebugger.addEventListener("Debugger:AfterSourcesAdded", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
// Spin the event loop before causing the debuggee to pause, to allow
// this function to return first.
executeSoon(() => gDebuggee.firstCall());
executeSoon(function() {
validateFirstPage();
testForward();
});
});
return waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6).then(() => {
validateFirstPage();
});
}
function testLocationChange() {
info("Navigating to a different page.");
return navigateActiveTabTo(gPanel, TAB_URL_2, gDebugger.EVENTS.SOURCES_ADDED).then(() => {
validateSecondPage();
});
}
function testBack() {
info("Going back.");
content.history.back();
return navigateActiveTabInHistory(gPanel, "back", gDebugger.EVENTS.SOURCES_ADDED).then(() => {
validateFirstPage();
});
}
function testForward()
{
gDebugger.DebuggerController._target.once("navigate", function onTabNavigated(aEvent, aPacket) {
ok(true, "tabNavigated event was fired after going forward.");
info("Still attached to the tab.");
gDebugger.addEventListener("Debugger:AfterSourcesAdded", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
executeSoon(function() {
validateSecondPage();
closeDebuggerAndFinish();
});
});
});
function testForward() {
info("Going forward.");
content.history.forward();
return navigateActiveTabInHistory(gPanel, "forward", gDebugger.EVENTS.SOURCES_ADDED).then(() => {
validateSecondPage();
});
}
function validateFirstPage() {
gSources = gDebugger.DebuggerView.Sources;
is(gSources.itemCount, 2,
"Found the expected number of scripts.");
ok(gDebugger.DebuggerView.Sources.containsLabel("test-script-switching-01.js"),
"Found the first script label.");
ok(gDebugger.DebuggerView.Sources.containsLabel("test-script-switching-02.js"),
"Found the second script label.");
"Found the expected number of sources.");
ok(gSources.containsLabel("code_script-switching-01.js"),
"Found the first source label.");
ok(gSources.containsLabel("code_script-switching-02.js"),
"Found the second source label.");
}
function validateSecondPage() {
gSources = gDebugger.DebuggerView.Sources;
is(gSources.itemCount, 1,
"Found the expected number of scripts.");
ok(gDebugger.DebuggerView.Sources.containsLabel("browser_dbg_stack.html"),
"Found the single script label.");
"Found the expected number of sources.");
ok(gSources.containsLabel("doc_recursion-stack.html"),
"Found the single source label.");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gSources = null;
});

View File

@ -1,27 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<title>Debugger Big Data Test</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript">
window.addEventListener("load", function() {
function test(aNumber) {
var buffer = new ArrayBuffer(aNumber);
var z = new Int8Array(buffer);
debugger;
};
function load() {
test(10000);
}
var button = document.querySelector("button");
button.addEventListener("click", load, false);
});
</script>
</head>
<body>
<button>Click me!</button>
</body>
</html>

View File

@ -5,72 +5,52 @@
* Test that if we black box a source and then refresh, it is still black boxed.
*/
const TAB_URL = EXAMPLE_URL + "binary_search.html";
const TAB_URL = EXAMPLE_URL + "doc_binary_search.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
let gTab, gDebuggee, gPanel, gDebugger;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
testBlackBoxSource();
waitForSourceShown(gPanel, ".coffee")
.then(testBlackBoxSource)
.then(testBlackBoxReload)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function testBlackBoxSource() {
once(gDebugger, "Debugger:SourceShown", function () {
const checkbox = gDebugger.document.querySelector(".side-menu-widget-item-checkbox");
ok(checkbox, "Should get the checkbox for black boxing the source");
ok(checkbox.checked, "Should not be black boxed by default");
const checkbox = gDebugger.document.querySelector(".side-menu-widget-item-checkbox");
ok(checkbox, "Should get the checkbox for black boxing the source.");
ok(checkbox.checked, "Should not be black boxed by default.");
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("blackboxchange", function (event, sourceClient) {
ok(sourceClient.isBlackBoxed, "The source should be black boxed now");
ok(!checkbox.checked, "The checkbox should no longer be checked.");
testBlackBoxReload();
});
checkbox.click();
let finished = waitForThreadEvents(gPanel, "blackboxchange").then(aSource => {
ok(aSource.isBlackBoxed, "The source should be black boxed now.");
ok(!checkbox.checked, "The checkbox should no longer be checked.");
});
checkbox.click();
return finished;
}
function testBlackBoxReload() {
once(gDebugger, "Debugger:SourceShown", function () {
return reloadActiveTab(gPanel, gDebugger.EVENTS.SOURCE_SHOWN).then(() => {
const checkbox = gDebugger.document.querySelector(".side-menu-widget-item-checkbox");
ok(checkbox, "Should get the checkbox for black boxing the source");
ok(!checkbox.checked, "Should still be black boxed");
closeDebuggerAndFinish();
ok(checkbox, "Should get the checkbox for black boxing the source.");
ok(!checkbox.checked, "Should still be black boxed.");
});
gDebuggee.location.reload();
}
function once(target, event, callback) {
target.addEventListener(event, function _listener(...args) {
target.removeEventListener(event, _listener, false);
callback.apply(null, args);
}, false);
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
});

View File

@ -6,82 +6,63 @@
* view.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
const BLACKBOXME_URL = EXAMPLE_URL + "blackboxing_blackboxme.js"
const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
const BLACKBOXME_URL = EXAMPLE_URL + "code_blackboxing_blackboxme.js"
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
let gTab, gDebuggee, gPanel, gDebugger;
let gFrames;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gFrames = gDebugger.DebuggerView.StackFrames;
testBlackBoxSource();
waitForSourceShown(gPanel, BLACKBOXME_URL)
.then(testBlackBoxSource)
.then(testBlackBoxStack)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function testBlackBoxSource() {
once(gDebugger, "Debugger:SourceShown", function () {
const checkbox = getBlackBoxCheckbox(BLACKBOXME_URL);
ok(checkbox, "Should get the checkbox for blackBoxing the source");
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("blackboxchange", function (event, sourceClient) {
ok(sourceClient.isBlackBoxed, "The source should be black boxed now");
testBlackBoxStack();
});
checkbox.click();
let finished = waitForThreadEvents(gPanel, "blackboxchange").then(aSource => {
ok(aSource.isBlackBoxed, "The source should be black boxed now.");
});
getBlackBoxCheckbox(BLACKBOXME_URL).click();
return finished;
}
function testBlackBoxStack() {
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("framesadded", function () {
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should only get 3 frames");
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 1,
"And one of them should be the combined black boxed frames");
closeDebuggerAndFinish();
let finished = waitForSourceAndCaretAndScopes(gPanel, ".html", 21).then(() => {
is(gFrames.itemCount, 3,
"Should only get 3 frames.");
is(gDebugger.document.querySelectorAll(".dbg-stackframe-black-boxed").length, 1,
"And one of them should be the combined black boxed frames.");
});
gDebuggee.runTest();
// Spin the event loop before causing the debuggee to pause, to allow
// this function to return first.
executeSoon(() => gDebuggee.runTest());
return finished;
}
function getBlackBoxCheckbox(url) {
function getBlackBoxCheckbox(aUrl) {
return gDebugger.document.querySelector(
".side-menu-widget-item[tooltiptext=\""
+ url + "\"] .side-menu-widget-item-checkbox");
}
function once(target, event, callback) {
target.addEventListener(event, function _listener(...args) {
target.removeEventListener(event, _listener, false);
callback.apply(null, args);
}, false);
".side-menu-widget-item[tooltiptext=\"" + aUrl + "\"] " +
".side-menu-widget-item-checkbox");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gFrames = null;
});

View File

@ -6,88 +6,63 @@
* view when we are already paused.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
const BLACKBOXME_URL = EXAMPLE_URL + "blackboxing_blackboxme.js"
const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
const BLACKBOXME_URL = EXAMPLE_URL + "code_blackboxing_blackboxme.js"
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
let gTab, gDebuggee, gPanel, gDebugger;
let gFrames;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gFrames = gDebugger.DebuggerView.StackFrames;
once(gDebugger, "Debugger:SourceShown", function () {
testBlackBoxStack();
});
waitForSourceAndCaretAndScopes(gPanel, ".html", 21)
.then(testBlackBoxStack)
.then(testBlackBoxSource)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
gDebuggee.runTest();
});
}
function testBlackBoxStack() {
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("framesadded", function () {
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(frames.querySelectorAll(".dbg-stackframe").length, 6,
"Should get 6 frames");
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 0,
"And none of them are black boxed");
testBlackBoxSource();
});
gDebuggee.runTest();
is(gFrames.itemCount, 6,
"Should get 6 frames.");
is(gDebugger.document.querySelectorAll(".dbg-stackframe-black-boxed").length, 0,
"And none of them are black boxed.");
}
function testBlackBoxSource() {
const checkbox = getBlackBoxCheckbox(BLACKBOXME_URL);
ok(checkbox, "Should get the checkbox for black boxing the source");
let finished = waitForThreadEvents(gPanel, "blackboxchange").then(aSource => {
ok(aSource.isBlackBoxed, "The source should be black boxed now.");
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("blackboxchange", function (event, sourceClient) {
ok(sourceClient.isBlackBoxed, "The source should be black boxed now");
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should only get 3 frames");
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 1,
"And one of them is the combined black boxed frames");
closeDebuggerAndFinish();
is(gFrames.itemCount, 3,
"Should only get 3 frames.");
is(gDebugger.document.querySelectorAll(".dbg-stackframe-black-boxed").length, 1,
"And one of them should be the combined black boxed frames.");
});
checkbox.click();
getBlackBoxCheckbox(BLACKBOXME_URL).click();
return finished;
}
function getBlackBoxCheckbox(url) {
function getBlackBoxCheckbox(aUrl) {
return gDebugger.document.querySelector(
".side-menu-widget-item[tooltiptext=\""
+ url + "\"] .side-menu-widget-item-checkbox");
}
function once(target, event, callback) {
target.addEventListener(event, function _listener(...args) {
target.removeEventListener(event, _listener, false);
callback.apply(null, args);
}, false);
".side-menu-widget-item[tooltiptext=\"" + aUrl + "\"] " +
".side-menu-widget-item-checkbox");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gFrames = null;
});

View File

@ -6,78 +6,62 @@
* for all of them.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
const BLACKBOXME_URL = EXAMPLE_URL + "code_blackboxing_blackboxme.js"
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
let gTab, gDebuggee, gPanel, gDebugger;
let gFrames;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gFrames = gDebugger.DebuggerView.StackFrames;
once(gDebugger, "Debugger:SourceShown", function () {
blackBoxSources();
});
waitForSourceShown(gPanel, BLACKBOXME_URL)
.then(blackBoxSources)
.then(testBlackBoxStack)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function blackBoxSources() {
let timesFired = 0;
const { activeThread } = gDebugger.DebuggerController;
activeThread.addListener("blackboxchange", function _onBlackBoxChange() {
if (++timesFired !== 3) {
return;
}
activeThread.removeListener("blackboxchange", _onBlackBoxChange);
activeThread.addOneTimeListener("framesadded", testStackFrames);
gDebuggee.one();
}, false);
getBlackBoxCheckbox(EXAMPLE_URL + "blackboxing_one.js").click();
getBlackBoxCheckbox(EXAMPLE_URL + "blackboxing_two.js").click();
getBlackBoxCheckbox(EXAMPLE_URL + "blackboxing_three.js").click();
let finished = waitForThreadEvents(gPanel, "blackboxchange", 3);
getBlackBoxCheckbox(EXAMPLE_URL + "code_blackboxing_one.js").click();
getBlackBoxCheckbox(EXAMPLE_URL + "code_blackboxing_two.js").click();
getBlackBoxCheckbox(EXAMPLE_URL + "code_blackboxing_three.js").click();
return finished;
}
function testStackFrames() {
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(frames.querySelectorAll(".dbg-stackframe").length, 4,
"Should get 4 frames (one -> two -> three -> doDebuggerStatement)");
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 3,
"And one, two, and three should each have their own black boxed frame.");
function testBlackBoxStack() {
let finished = waitForSourceAndCaretAndScopes(gPanel, ".html", 21).then(() => {
is(gFrames.itemCount, 4,
"Should get 4 frames (one -> two -> three -> doDebuggerStatement).");
is(gDebugger.document.querySelectorAll(".dbg-stackframe-black-boxed").length, 3,
"And 'one', 'two', and 'three' should each have their own black boxed frame.");
});
closeDebuggerAndFinish();
// Spin the event loop before causing the debuggee to pause, to allow
// this function to return first.
executeSoon(() => gDebuggee.one());
return finished;
}
function getBlackBoxCheckbox(url) {
function getBlackBoxCheckbox(aUrl) {
return gDebugger.document.querySelector(
".side-menu-widget-item[tooltiptext=\""
+ url + "\"] .side-menu-widget-item-checkbox");
}
function once(target, event, callback) {
target.addEventListener(event, function _listener(...args) {
target.removeEventListener(event, _listener, false);
callback.apply(null, args);
}, false);
".side-menu-widget-item[tooltiptext=\"" + aUrl + "\"] " +
".side-menu-widget-item-checkbox");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gFrames = null;
});

View File

@ -2,67 +2,61 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that we get a stack frame for each black boxed source, not a single one
* for all of them.
* Test that a "this source is blackboxed" message is shown when necessary
* and can be properly dismissed.
*/
const TAB_URL = EXAMPLE_URL + "binary_search.html";
const TAB_URL = EXAMPLE_URL + "doc_binary_search.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
let gTab, gDebuggee, gPanel, gDebugger;
let gDeck;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gDeck = gDebugger.document.getElementById("editor-deck");
once(gDebugger, "Debugger:SourceShown", testSourceEditorShown);
waitForSourceShown(gPanel, ".coffee")
.then(testSourceEditorShown)
.then(blackBoxSource)
.then(testBlackBoxMessageShown)
.then(clickStopBlackBoxingButton)
.then(testSourceEditorShownAgain)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function testSourceEditorShown() {
const deck = gDebugger.document.getElementById("editor-deck");
is(deck.selectedIndex, "0",
"The first item in the deck should be selected (the source editor)");
blackBoxSource();
is(gDeck.selectedIndex, "0",
"The first item in the deck should be selected (the source editor).");
}
function blackBoxSource() {
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("blackboxchange", testBlackBoxMessageShown);
let finished = waitForThreadEvents(gPanel, "blackboxchange");
getAnyBlackBoxCheckbox().click();
return finished;
}
function testBlackBoxMessageShown() {
const deck = gDebugger.document.getElementById("editor-deck");
is(deck.selectedIndex, "1",
"The second item in the deck should be selected (the black box message)");
clickStopBlackBoxingButton();
is(gDeck.selectedIndex, "1",
"The second item in the deck should be selected (the black box message).");
}
function clickStopBlackBoxingButton() {
const button = gDebugger.document.getElementById("black-boxed-message-button");
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("blackboxchange", testSourceEditorShownAgain);
button.click();
let finished = waitForThreadEvents(gPanel, "blackboxchange");
getEditorBlackboxMessageButton().click();
return finished;
}
function testSourceEditorShownAgain() {
const deck = gDebugger.document.getElementById("editor-deck");
is(deck.selectedIndex, "0",
"The first item in the deck should be selected again (the source editor)");
closeDebuggerAndFinish();
is(gDeck.selectedIndex, "0",
"The first item in the deck should be selected again (the source editor).");
}
function getAnyBlackBoxCheckbox() {
@ -70,17 +64,14 @@ function getAnyBlackBoxCheckbox() {
".side-menu-widget-item .side-menu-widget-item-checkbox");
}
function once(target, event, callback) {
target.addEventListener(event, function _listener(...args) {
target.removeEventListener(event, _listener, false);
callback.apply(null, args);
}, false);
function getEditorBlackboxMessageButton() {
return gDebugger.document.getElementById("black-boxed-message-button");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gDeck = null;
});

View File

@ -5,66 +5,52 @@
* Test that clicking the black box checkbox doesn't select that source.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
let gTab, gDebuggee, gPanel, gDebugger;
let gSources;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gSources = gDebugger.DebuggerView.Sources;
once(gDebugger, "Debugger:SourceShown", testBlackBox);
waitForSourceShown(gPanel, ".js")
.then(testBlackBox)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function testBlackBox() {
const sources = gDebugger.DebuggerView.Sources;
const selectedUrl = sources.selectedItem.attachment.source.url;
const selectedUrl = gSources.selectedValue;
const checkbox = getDifferentBlackBoxCheckbox(selectedUrl);
ok(checkbox, "We should be able to grab a checkbox");
ok(checkbox, "We should be able to grab a different checkbox.");
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("blackboxchange", function () {
is(selectedUrl,
sources.selectedItem.attachment.source.url,
"The same source should be selected");
closeDebuggerAndFinish();
let finished = waitForThreadEvents(gPanel, "blackboxchange").then(() => {
is(selectedUrl, gSources.selectedValue,
"The same source should still be selected.");
});
checkbox.click();
return finished;
}
function getDifferentBlackBoxCheckbox(url) {
function getDifferentBlackBoxCheckbox(aUrl) {
return gDebugger.document.querySelector(
".side-menu-widget-item:not([tooltiptext=\""
+ url + "\"]) .side-menu-widget-item-checkbox");
}
function once(target, event, callback) {
target.addEventListener(event, function _listener(...args) {
target.removeEventListener(event, _listener, false);
callback.apply(null, args);
}, false);
".side-menu-widget-item:not([tooltiptext=\"" + aUrl + "\"]) " +
".side-menu-widget-item-checkbox");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gSources = null;
});

View File

@ -6,81 +6,61 @@
* currently paused frame's source.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
const TAB_URL = EXAMPLE_URL + "doc_blackboxing.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
let gTab, gDebuggee, gPanel, gDebugger;
let gSources;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gSources = gDebugger.DebuggerView.Sources;
once(gDebugger, "Debugger:SourceShown", runTest);
});
}
function runTest() {
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("paused", function () {
const sources = gDebugger.DebuggerView.Sources;
const selectedUrl = sources.selectedItem.attachment.source.url;
once(gDebugger, "Debugger:SourceShown", function () {
const newSelectedUrl = sources.selectedItem.attachment.source.url;
isnot(selectedUrl, newSelectedUrl,
"Should not have the same url selected");
activeThread.addOneTimeListener("blackboxchange", function () {
isnot(sources.selectedItem.attachment.source.url,
selectedUrl,
"The selected source did not change");
closeDebuggerAndFinish();
waitForSourceAndCaretAndScopes(gPanel, ".html", 21)
.then(testBlackBox)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
getBlackBoxCheckbox(newSelectedUrl).click();
gDebuggee.runTest();
});
}
function testBlackBox() {
const selectedUrl = gSources.selectedValue;
let finished = waitForSourceShown(gPanel, "blackboxme.js").then(() => {
const newSelectedUrl = gSources.selectedValue;
isnot(selectedUrl, newSelectedUrl,
"Should not have the same url selected.");
let finished = waitForThreadEvents(gPanel, "blackboxchange").then(() => {
is(gSources.selectedValue, newSelectedUrl,
"The selected source did not change.");
});
getDifferentSource(selectedUrl).click();
getBlackBoxCheckbox(newSelectedUrl).click()
return finished;
});
gDebuggee.runTest();
gSources.selectedIndex = 0;
return finished;
}
function getDifferentSource(url) {
function getBlackBoxCheckbox(aUrl) {
return gDebugger.document.querySelector(
".side-menu-widget-item:not([tooltiptext=\""
+ url + "\"])");
}
function getBlackBoxCheckbox(url) {
return gDebugger.document.querySelector(
".side-menu-widget-item[tooltiptext=\""
+ url + "\"] .side-menu-widget-item-checkbox");
}
function once(target, event, callback) {
target.addEventListener(event, function _listener(...args) {
target.removeEventListener(event, _listener, false);
callback.apply(null, args);
}, false);
".side-menu-widget-item[tooltiptext=\"" + aUrl + "\"] " +
".side-menu-widget-item-checkbox");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gSources = null;
});

View File

@ -1,23 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<title>Browser Debugger Blackbox Test</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript" src="blackboxing_blackboxme.js"></script>
<script type="text/javascript" src="blackboxing_one.js"></script>
<script type="text/javascript" src="blackboxing_two.js"></script>
<script type="text/javascript" src="blackboxing_three.js"></script>
<script>
function runTest() {
blackboxme(doDebuggerStatement);
}
function doDebuggerStatement() {
debugger;
}
</script>
</head>
<body>
</body>
</html>

View File

@ -1,154 +1,89 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
/**
* Tests if the stackframe breadcrumbs are keyboard accessible.
*/
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gSources, gFrames;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
resumed = true;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gSources = gDebugger.DebuggerView.Sources;
gFrames = gDebugger.DebuggerView.StackFrames;
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.firstCall();
});
});
function onScriptShown(aEvent)
{
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function performTest()
{
let editor = gDebugger.DebuggerView.editor;
let sources = gDebugger.DebuggerView.Sources;
let stackframes = gDebugger.DebuggerView.StackFrames;
is(editor.getCaretPosition().line, 5,
"The source editor caret position was incorrect (1).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (1).");
is(stackframes.selectedIndex, 3,
"The currently selected stackframe is incorrect (1).");
EventUtils.sendKey("DOWN", gDebugger);
is(editor.getCaretPosition().line, 6,
"The source editor caret position was incorrect (2).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (2).");
is(stackframes.selectedIndex, 3,
"The currently selected stackframe is incorrect (2).");
EventUtils.sendKey("UP", gDebugger);
is(editor.getCaretPosition().line, 5,
"The source editor caret position was incorrect (3).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (3).");
is(stackframes.selectedIndex, 3,
"The currently selected stackframe is incorrect (3).");
EventUtils.sendMouseEvent({ type: "mousedown" },
stackframes.selectedItem.target,
gDebugger);
EventUtils.sendKey("UP", gDebugger);
is(editor.getCaretPosition().line, 5,
"The source editor caret position was incorrect (4).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (4).");
is(stackframes.selectedIndex, 2,
"The currently selected stackframe is incorrect (4).");
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
is(editor.getCaretPosition().line, 4,
"The source editor caret position was incorrect (5).");
is(sources.selectedLabel, "test-script-switching-01.js",
"The currently selected source is incorrect (5).");
is(stackframes.selectedIndex, 1,
"The currently selected stackframe is incorrect (5).");
EventUtils.sendKey("UP", gDebugger);
is(editor.getCaretPosition().line, 4,
"The source editor caret position was incorrect (6).");
is(sources.selectedLabel, "test-script-switching-01.js",
"The currently selected source is incorrect (6).");
is(stackframes.selectedIndex, 0,
"The currently selected stackframe is incorrect (6).");
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
is(editor.getCaretPosition().line, 5,
"The source editor caret position was incorrect (7).");
is(sources.selectedLabel, "test-script-switching-02.js",
"The currently selected source is incorrect (7).");
is(stackframes.selectedIndex, 3,
"The currently selected stackframe is incorrect (7).");
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
is(editor.getCaretPosition().line, 4,
"The source editor caret position was incorrect (8).");
is(sources.selectedLabel, "test-script-switching-01.js",
"The currently selected source is incorrect (8).");
is(stackframes.selectedIndex, 0,
"The currently selected stackframe is incorrect (8).");
closeDebuggerAndFinish();
});
EventUtils.sendKey("HOME", gDebugger);
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6)
.then(checkNavigationWhileNotFocused)
.then(focusCurrentStackFrame)
.then(checkNavigationWhileFocused)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
EventUtils.sendKey("END", gDebugger);
});
gDebuggee.firstCall();
});
function checkNavigationWhileNotFocused() {
checkState({ frame: 3, source: 1, line: 6 });
EventUtils.sendKey("DOWN", gDebugger);
checkState({ frame: 3, source: 1, line: 7 });
EventUtils.sendKey("UP", gDebugger);
checkState({ frame: 3, source: 1, line: 6 });
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});
function focusCurrentStackFrame() {
EventUtils.sendMouseEvent({ type: "mousedown" },
gFrames.selectedItem.target,
gDebugger);
}
function checkNavigationWhileFocused() {
let deferred = promise.defer();
EventUtils.sendKey("UP", gDebugger);
checkState({ frame: 2, source: 1, line: 6 });
waitForSourceAndCaret(gPanel, "-01.js", 5).then(() => {
checkState({ frame: 1, source: 0, line: 5 });
EventUtils.sendKey("UP", gDebugger);
checkState({ frame: 0, source: 0, line: 5 });
waitForSourceAndCaret(gPanel, "-02.js", 6).then(() => {
checkState({ frame: 3, source: 1, line: 6 });
waitForSourceAndCaret(gPanel, "-01.js", 5).then(() => {
checkState({ frame: 0, source: 0, line: 5 });
deferred.resolve();
});
EventUtils.sendKey("HOME", gDebugger)
});
EventUtils.sendKey("END", gDebugger)
});
EventUtils.sendKey("UP", gDebugger)
return deferred.promise;
}
function checkState({ frame, source, line }) {
is(gFrames.selectedIndex, frame,
"The currently selected stackframe is incorrect.");
is(gSources.selectedIndex, source,
"The currently selected source is incorrect.");
ok(isCaretPos(gPanel, line),
"The source editor caret position was incorrect.");
}
}

View File

@ -1,195 +1,228 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the break-on-dom-events request works.
*/
// Tests that the break-on-dom-events request works.
const TAB_URL = EXAMPLE_URL + "doc_event-listeners.html";
var gClient = null;
var gTab = null;
var gThreadClient = null;
var gInput = null;
var gButton = null;
const DEBUGGER_TAB_URL = EXAMPLE_URL + "test-event-listeners.html";
let gClient, gThreadClient, gInput, gButton;
function test() {
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
function test()
{
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect(function(type, traits) {
gTab = addTab(DEBUGGER_TAB_URL, function() {
attach_thread_actor_for_url(gClient,
DEBUGGER_TAB_URL,
function(threadClient) {
gThreadClient = threadClient;
gInput = content.document.querySelector("input");
gButton = content.document.querySelector("button");
testBreakOnAll();
gClient.connect((aType, aTraits) => {
is(aType, "browser",
"Root actor should identify itself as a browser.");
addTab(TAB_URL)
.then(() => attachThreadActorForUrl(gClient, TAB_URL))
.then(setupGlobals)
.then(pauseDebuggee)
.then(testBreakOnAll)
.then(testBreakOnDisabled)
.then(testBreakOnNone)
.then(testBreakOnClick)
.then(closeConnection)
.then(finish)
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
});
}
function setupGlobals(aThreadClient) {
gThreadClient = aThreadClient;
gInput = content.document.querySelector("input");
gButton = content.document.querySelector("button");
}
function pauseDebuggee() {
let deferred = promise.defer();
gClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.type, "paused",
"We should now be paused.");
is(aPacket.why.type, "debuggerStatement",
"The debugger statement was hit.");
deferred.resolve();
});
// Spin the event loop before causing the debuggee to pause, to allow
// this function to return first.
executeSoon(triggerButtonClick);
return deferred.promise;
}
// Test pause on all events.
function testBreakOnAll()
{
gClient.addOneTimeListener("paused", function(event, packet) {
is(packet.why.type, "debuggerStatement", "debugger statement was hit.");
// Test calling pauseOnDOMEvents from a paused state.
gThreadClient.pauseOnDOMEvents("*", function(packet) {
is(packet, undefined, "The pause-on-any-event request completed successfully.");
function testBreakOnAll() {
let deferred = promise.defer();
gClient.addOneTimeListener("paused", function(event, packet) {
is(packet.why.type, "pauseOnDOMEvents", "A hidden breakpoint was hit.");
is(packet.frame.callee.name, "keyupHandler", "The keyupHandler is entered.");
// Test calling pauseOnDOMEvents from a paused state.
gThreadClient.pauseOnDOMEvents("*", (aPacket) => {
is(aPacket, undefined,
"The pause-on-any-event request completed successfully.");
gClient.addOneTimeListener("paused", function(event, packet) {
is(packet.why.type, "pauseOnDOMEvents", "A hidden breakpoint was hit.");
is(packet.frame.callee.name, "clickHandler", "The clickHandler is entered.");
gClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.why.type, "pauseOnDOMEvents",
"A hidden breakpoint was hit.");
is(aPacket.frame.callee.name, "keyupHandler",
"The keyupHandler is entered.");
gClient.addOneTimeListener("paused", function(event, packet) {
is(packet.why.type, "pauseOnDOMEvents", "A hidden breakpoint was hit.");
is(packet.frame.callee.name, "onchange", "The onchange handler is entered.");
gClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.why.type, "pauseOnDOMEvents",
"A hidden breakpoint was hit.");
is(aPacket.frame.callee.name, "clickHandler",
"The clickHandler is entered.");
gThreadClient.resume(testBreakOnDisabled);
});
gClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.why.type, "pauseOnDOMEvents",
"A hidden breakpoint was hit.");
is(aPacket.frame.callee.name, "onchange",
"The onchange handler is entered.");
gThreadClient.resume(function() {
gInput.focus();
gInput.value = "foo";
gInput.blur();
});
gThreadClient.resume(deferred.resolve);
});
gThreadClient.resume(function() {
EventUtils.sendMouseEvent({ type: "click" }, gButton);
});
gThreadClient.resume(triggerInputChange);
});
gThreadClient.resume(function() {
// Make sure that the focus is not on the input box so that a focus event
// will be triggered.
window.focus();
gBrowser.selectedBrowser.focus();
gButton.focus();
// Focus the element and wait for focus event.
gInput.addEventListener("focus", function onfocus() {
gInput.removeEventListener("focus", onfocus, false);
executeSoon(function() {
EventUtils.synthesizeKey("e", { shiftKey: 1 }, content);
});
}, false);
gInput.focus();
});
gThreadClient.resume(triggerButtonClick);
});
gThreadClient.resume(triggerInputKeyup);
});
EventUtils.sendMouseEvent({ type: "click" }, gButton);
return deferred.promise;
}
// Test that removing events from the array disables them.
function testBreakOnDisabled()
{
function testBreakOnDisabled() {
let deferred = promise.defer();
// Test calling pauseOnDOMEvents from a running state.
gThreadClient.pauseOnDOMEvents(["click"], function(packet) {
is(packet.error, undefined, "The pause-on-click-only request completed successfully.");
gThreadClient.pauseOnDOMEvents(["click"], (aPacket) => {
is(aPacket.error, undefined,
"The pause-on-click-only request completed successfully.");
gClient.addListener("paused", unexpectedListener);
// This non-capturing event listener is guaranteed to run after the page's
// capturing one had a chance to execute and modify window.foobar.
gInput.addEventListener("keyup", function tempHandler() {
gInput.removeEventListener("keyup", tempHandler, false);
is(content.wrappedJSObject.foobar, "keyupHandler", "No hidden breakpoint was hit.");
once(gInput, "keyup").then(() => {
is(content.wrappedJSObject.foobar, "keyupHandler",
"No hidden breakpoint was hit.");
gClient.removeListener("paused", unexpectedListener);
testBreakOnNone();
}, false);
deferred.resolve();
});
// Make sure that the focus is not on the input box so that a focus event
// will be triggered.
window.focus();
gBrowser.selectedBrowser.focus();
gButton.focus();
// Focus the element and wait for focus event.
gInput.addEventListener("focus", function onfocus() {
gInput.removeEventListener("focus", onfocus, false);
executeSoon(function() {
EventUtils.synthesizeKey("e", { shiftKey: 1 }, content);
});
}, false);
gInput.focus();
triggerInputKeyup();
});
return deferred.promise;
}
// Test that specifying an empty event array clears all hidden breakpoints.
function testBreakOnNone()
{
function testBreakOnNone() {
let deferred = promise.defer();
// Test calling pauseOnDOMEvents from a running state.
gThreadClient.pauseOnDOMEvents([], function(packet) {
is(packet.error, undefined, "The pause-on-none request completed successfully.");
gThreadClient.pauseOnDOMEvents([], (aPacket) => {
is(aPacket.error, undefined,
"The pause-on-none request completed successfully.");
gClient.addListener("paused", unexpectedListener);
// This non-capturing event listener is guaranteed to run after the page's
// capturing one had a chance to execute and modify window.foobar.
gInput.addEventListener("keyup", function tempHandler() {
gInput.removeEventListener("keyup", tempHandler, false);
is(content.wrappedJSObject.foobar, "keyupHandler", "No hidden breakpoint was hit.");
once(gInput, "keyup").then(() => {
is(content.wrappedJSObject.foobar, "keyupHandler",
"No hidden breakpoint was hit.");
gClient.removeListener("paused", unexpectedListener);
testBreakOnClick();
}, false);
deferred.resolve();
});
// Make sure that the focus is not on the input box so that a focus event
// will be triggered.
window.focus();
gBrowser.selectedBrowser.focus();
gButton.focus();
// Focus the element and wait for focus event.
gInput.addEventListener("focus", function onfocus() {
gInput.removeEventListener("focus", onfocus, false);
executeSoon(function() {
EventUtils.synthesizeKey("g", { shiftKey: 1 }, content);
});
}, false);
gInput.focus();
triggerInputKeyup();
});
return deferred.promise;
}
function unexpectedListener(event, packet, callback) {
// Test pause on a single event.
function testBreakOnClick() {
let deferred = promise.defer();
// Test calling pauseOnDOMEvents from a running state.
gThreadClient.pauseOnDOMEvents(["click"], (aPacket) => {
is(aPacket.error, undefined,
"The pause-on-click request completed successfully.");
gClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.why.type, "pauseOnDOMEvents",
"A hidden breakpoint was hit.");
is(aPacket.frame.callee.name, "clickHandler",
"The clickHandler is entered.");
gThreadClient.resume(deferred.resolve);
});
triggerButtonClick();
});
return deferred.promise;
}
function closeConnection() {
let deferred = promise.defer();
gClient.close(deferred.resolve);
return deferred.promise;
}
function unexpectedListener() {
gClient.removeListener("paused", unexpectedListener);
ok(false, "An unexpected hidden breakpoint was hit.");
gThreadClient.resume(testBreakOnClick);
}
// Test pause on a single event.
function testBreakOnClick()
{
// Test calling pauseOnDOMEvents from a running state.
gThreadClient.pauseOnDOMEvents(["click"], function(packet) {
is(packet.error, undefined, "The pause-on-click request completed successfully.");
function triggerInputKeyup() {
// Make sure that the focus is not on the input box so that a focus event
// will be triggered.
window.focus();
gBrowser.selectedBrowser.focus();
gButton.focus();
gClient.addOneTimeListener("paused", function(event, packet) {
is(packet.why.type, "pauseOnDOMEvents", "A hidden breakpoint was hit.");
is(packet.frame.callee.name, "clickHandler", "The clickHandler is entered.");
gThreadClient.resume(function() {
gClient.close(finish);
});
// Focus the element and wait for focus event.
once(gInput, "focus").then(() => {
executeSoon(() => {
EventUtils.synthesizeKey("e", { shiftKey: 1 }, content);
});
EventUtils.sendMouseEvent({ type: "click" }, gButton);
});
gInput.focus();
}
function triggerButtonClick() {
EventUtils.sendMouseEvent({ type: "click" }, gButton)
}
function triggerInputChange() {
gInput.focus();
gInput.value = "foo";
gInput.blur();
}
registerCleanupFunction(function() {
removeTab(gTab);
gTab = null;
removeTab(gBrowser.selectedTab);
gClient = null;
gThreadClient = null;
gInput = null;

View File

@ -1,20 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'/>
<script type="text/javascript">
function runDebuggerStatement() {
debugger;
}
function myFunction() {
var a = 1;
debugger;
}
</script>
</head>
<body>
<button type="button" onclick="myFunction()">Run</button>
</body>
</html>

View File

@ -1,92 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 771452: make sure that setting a breakpoint in an inline script doesn't
// add it twice.
const TAB_URL = EXAMPLE_URL + "browser_dbg_breakpoint-new-script.html";
var gPane = null;
var gTab = null;
var gDebugger = null;
var gDebuggee = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
testAddBreakpoint();
});
}
function testAddBreakpoint()
{
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
var frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(gDebugger.DebuggerController.activeThread.state, "paused",
"The debugger statement was reached.");
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
"Should have one frame.");
gPane.addBreakpoint({ url: TAB_URL, line: 9 }, function (aResponse, bpClient) {
testResume();
});
}}, 0);
});
gDebuggee.runDebuggerStatement();
}
function testResume()
{
is(gDebugger.DebuggerController.activeThread.state, "paused",
"The breakpoint wasn't hit yet.");
let thread = gDebugger.DebuggerController.activeThread;
thread.addOneTimeListener("resumed", function() {
thread.addOneTimeListener("paused", function() {
executeSoon(testBreakpointHit);
});
EventUtils.sendMouseEvent({ type: "click" },
content.document.querySelector("button"));
});
thread.resume();
}
function testBreakpointHit()
{
is(gDebugger.DebuggerController.activeThread.state, "paused",
"The breakpoint was hit.");
let thread = gDebugger.DebuggerController.activeThread;
thread.addOneTimeListener("paused", function test(aEvent, aPacket) {
thread.addOneTimeListener("resumed", function() {
executeSoon(closeDebuggerAndFinish);
});
is(aPacket.why.type, "debuggerStatement", "Execution has advanced to the next line.");
isnot(aPacket.why.type, "breakpoint", "No ghost breakpoint was hit.");
thread.resume();
});
thread.resume();
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebugger = null;
gDebuggee = null;
});

View File

@ -0,0 +1,97 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 737803: Setting a breakpoint in a line without code should move
* the icon to the actual location.
*/
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
gBreakpointsAdded = gBreakpoints._added;
gBreakpointsRemoving = gBreakpoints._removing;
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6).then(performTest);
gDebuggee.firstCall();
});
function performTest() {
is(gBreakpointsAdded.size, 0,
"No breakpoints currently added.");
is(gBreakpointsRemoving.size, 0,
"No breakpoints currently being removed.");
is(gEditor.getBreakpoints().length, 0,
"No breakpoints currently shown in the editor.");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAdd);
gPanel.addBreakpoint({ url: gSources.selectedValue, line: 4 }).then(onBreakpointAdd);
}
let onBpDebuggerAdd = false;
let onBpEditorAdd = false;
function onBreakpointAdd(aBreakpointClient) {
ok(aBreakpointClient,
"Breakpoint added, client received.");
is(aBreakpointClient.location.url, gSources.selectedValue,
"Breakpoint client url is the same.");
is(aBreakpointClient.location.line, 6,
"Breakpoint client line is new.");
is(aBreakpointClient.requestedLocation.url, gSources.selectedValue,
"Requested location url is correct");
is(aBreakpointClient.requestedLocation.line, 4,
"Requested location line is correct");
onBpDebuggerAdd = true;
maybeFinish();
}
function onEditorBreakpointAdd(aEvent) {
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAdd);
is(gEditor.getBreakpoints().length, 1,
"There is only one breakpoint in the editor");
ok(!gBreakpoints._getAdded({ url: gSources.selectedValue, line: 4 }),
"There isn't any breakpoint added on an invalid line.");
ok(!gBreakpoints._getRemoving({ url: gSources.selectedValue, line: 4 }),
"There isn't any breakpoint removed from an invalid line.");
ok(gBreakpoints._getAdded({ url: gSources.selectedValue, line: 6 }),
"There is a breakpoint added on the actual line.");
ok(!gBreakpoints._getRemoving({ url: gSources.selectedValue, line: 6 }),
"There isn't any breakpoint removed from the actual line.");
gBreakpoints._getAdded({ url: gSources.selectedValue, line: 6 }).then(aBreakpointClient => {
is(aBreakpointClient.location.url, gSources.selectedValue,
"Breakpoint client location url is correct.");
is(aBreakpointClient.location.line, 6,
"Breakpoint client location line is correct.");
onBpEditorAdd = true;
maybeFinish();
});
}
function maybeFinish() {
info("onBpDebuggerAdd: " + onBpDebuggerAdd);
info("onBpEditorAdd: " + onBpEditorAdd);
if (onBpDebuggerAdd && onBpEditorAdd) {
resumeDebuggerThenCloseAndFinish(gPanel);
}
}
}

View File

@ -0,0 +1,322 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test if the context menu associated with each breakpoint does what it should.
*/
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gBreakpoints;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
waitForSourceShown(gPanel, "-01.js")
.then(performTestWhileNotPaused)
.then(performTestWhilePaused)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
function addBreakpoints() {
return promise.resolve(null)
.then(() => gPanel.addBreakpoint({ url: gSources.values[0], line: 5 }))
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 6 }))
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 7 }))
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 8 }))
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 9 }))
}
function performTestWhileNotPaused() {
info("Performing test while not paused...");
return addBreakpoints()
.then(initialChecks)
.then(() => checkBreakpointToggleSelf(0))
.then(() => checkBreakpointToggleOthers(0))
.then(() => checkBreakpointToggleSelf(1))
.then(() => checkBreakpointToggleOthers(1))
.then(() => checkBreakpointToggleSelf(2))
.then(() => checkBreakpointToggleOthers(2))
.then(() => checkBreakpointToggleSelf(3))
.then(() => checkBreakpointToggleOthers(3))
.then(() => checkBreakpointToggleSelf(4))
.then(() => checkBreakpointToggleOthers(4))
.then(testDeleteAll);
}
function performTestWhilePaused() {
info("Performing test while paused...");
return addBreakpoints()
.then(initialChecks)
.then(pauseAndCheck)
.then(() => checkBreakpointToggleSelf(0))
.then(() => checkBreakpointToggleOthers(0))
.then(() => checkBreakpointToggleSelf(1))
.then(() => checkBreakpointToggleOthers(1))
.then(() => checkBreakpointToggleSelf(2))
.then(() => checkBreakpointToggleOthers(2))
.then(() => checkBreakpointToggleSelf(3))
.then(() => checkBreakpointToggleOthers(3))
.then(() => checkBreakpointToggleSelf(4))
.then(() => checkBreakpointToggleOthers(4))
.then(testDeleteAll);
}
function pauseAndCheck() {
let finished = waitForSourceAndCaretAndScopes(gPanel, "-01.js", 5).then(() => {
is(gSources.selectedLabel, "code_script-switching-01.js",
"The currently selected source is incorrect (3).");
is(gSources.selectedIndex, 0,
"The currently selected source is incorrect (4).");
ok(isCaretPos(gPanel, 5),
"The editor location is correct after pausing.");
});
is(gSources.selectedLabel, "code_script-switching-02.js",
"The currently selected source is incorrect (1).");
is(gSources.selectedIndex, 1,
"The currently selected source is incorrect (2).");
ok(isCaretPos(gPanel, 9),
"The editor location is correct before pausing.");
ensureThreadClientState(gPanel, "resumed").then(() => {
EventUtils.sendMouseEvent({ type: "click" },
gDebuggee.document.querySelector("button"),
gDebuggee);
});
return finished;
}
function initialChecks() {
for (let source in gSources) {
for (let breakpoint in source) {
ok(gBreakpoints._getAdded(breakpoint.attachment),
"All breakpoint items should have corresponding promises (1).");
ok(!gBreakpoints._getRemoving(breakpoint.attachment),
"All breakpoint items should have corresponding promises (2).");
ok(breakpoint.attachment.actor,
"All breakpoint items should have corresponding promises (3).");
is(!!breakpoint.attachment.disabled, false,
"All breakpoints should initially be enabled.");
let actor = breakpoint.attachment.actor;
let prefix = "bp-cMenu-"; // "breakpoints context menu"
let enableSelfId = prefix + "enableSelf-" + actor + "-menuitem";
let disableSelfId = prefix + "disableSelf-" + actor + "-menuitem";
is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true",
"The 'Enable breakpoint' context menu item should initially be hidden'.");
ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"),
"The 'Disable breakpoint' context menu item should initially not be hidden'.");
is(breakpoint.attachment.view.checkbox.getAttribute("checked"), "true",
"All breakpoints should initially have a checked checkbox.");
}
}
}
function checkBreakpointToggleSelf(aIndex) {
let deferred = promise.defer();
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.querySelectorAll(".dbg-breakpoint")[aIndex],
gDebugger);
let selectedBreakpoint = gSources._selectedBreakpointItem;
ok(gBreakpoints._getAdded(selectedBreakpoint.attachment),
"There should be a breakpoint client available (1).");
ok(!gBreakpoints._getRemoving(selectedBreakpoint.attachment),
"There should be a breakpoint client available (2).");
ok(selectedBreakpoint.attachment.actor,
"There should be a breakpoint client available (3).");
is(!!selectedBreakpoint.attachment.disabled, false,
"The breakpoint should not be disabled yet (" + aIndex + ").");
gBreakpoints._getAdded(selectedBreakpoint.attachment).then(aBreakpointClient => {
ok(aBreakpointClient,
"There should be a breakpoint client available as a promise.");
});
let actor = selectedBreakpoint.attachment.actor;
let prefix = "bp-cMenu-"; // "breakpoints context menu"
let enableSelfId = prefix + "enableSelf-" + actor + "-menuitem";
let disableSelfId = prefix + "disableSelf-" + actor + "-menuitem";
is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true",
"The 'Enable breakpoint' context menu item should be hidden'.");
ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"),
"The 'Disable breakpoint' context menu item should not be hidden'.");
ok(isCaretPos(gPanel, selectedBreakpoint.attachment.line),
"The source editor caret position was incorrect (" + aIndex + ").");
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED).then(() => {
ok(!gBreakpoints._getAdded(selectedBreakpoint.attachment),
"There should be no breakpoint client available (4).");
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED).then(() => {
ok(gBreakpoints._getAdded(selectedBreakpoint.attachment),
"There should be a breakpoint client available (5).");
deferred.resolve();
});
// Test re-disabling this breakpoint.
gSources._onEnableSelf(selectedBreakpoint.attachment.actor);
is(selectedBreakpoint.attachment.disabled, false,
"The current breakpoint should now be enabled.")
is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true",
"The 'Enable breakpoint' context menu item should be hidden'.");
ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"),
"The 'Disable breakpoint' context menu item should not be hidden'.");
ok(selectedBreakpoint.attachment.view.checkbox.hasAttribute("checked"),
"The breakpoint should now be checked.");
});
// Test disabling this breakpoint.
gSources._onDisableSelf(selectedBreakpoint.attachment.actor);
is(selectedBreakpoint.attachment.disabled, true,
"The current breakpoint should now be disabled.")
ok(!gDebugger.document.getElementById(enableSelfId).hasAttribute("hidden"),
"The 'Enable breakpoint' context menu item should not be hidden'.");
is(gDebugger.document.getElementById(disableSelfId).getAttribute("hidden"), "true",
"The 'Disable breakpoint' context menu item should be hidden'.");
ok(!selectedBreakpoint.attachment.view.checkbox.hasAttribute("checked"),
"The breakpoint should now be unchecked.");
return deferred.promise;
}
function checkBreakpointToggleOthers(aIndex) {
let deferred = promise.defer();
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED, 4).then(() => {
let selectedBreakpoint = gSources._selectedBreakpointItem;
ok(gBreakpoints._getAdded(selectedBreakpoint.attachment),
"There should be a breakpoint client available (6).");
ok(!gBreakpoints._getRemoving(selectedBreakpoint.attachment),
"There should be a breakpoint client available (7).");
ok(selectedBreakpoint.attachment.actor,
"There should be a breakpoint client available (8).");
is(!!selectedBreakpoint.attachment.disabled, false,
"The targetted breakpoint should not have been disabled (" + aIndex + ").");
for (let source in gSources) {
for (let otherBreakpoint in source) {
if (otherBreakpoint != selectedBreakpoint) {
ok(!gBreakpoints._getAdded(otherBreakpoint.attachment),
"There should be no breakpoint client for a disabled breakpoint (9).");
is(otherBreakpoint.attachment.disabled, true,
"Non-targetted breakpoints should have been disabled (10).");
}
}
}
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED, 4).then(() => {
for (let source in gSources) {
for (let someBreakpoint in source) {
ok(gBreakpoints._getAdded(someBreakpoint.attachment),
"There should be a breakpoint client for all enabled breakpoints (11).");
is(someBreakpoint.attachment.disabled, false,
"All breakpoints should now have been enabled (12).");
}
}
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED, 5).then(() => {
for (let source in gSources) {
for (let someBreakpoint in source) {
ok(!gBreakpoints._getAdded(someBreakpoint.attachment),
"There should be no breakpoint client for a disabled breakpoint (13).");
is(someBreakpoint.attachment.disabled, true,
"All breakpoints should now have been disabled (14).");
}
}
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED, 5).then(() => {
for (let source in gSources) {
for (let someBreakpoint in source) {
ok(gBreakpoints._getAdded(someBreakpoint.attachment),
"There should be a breakpoint client for all enabled breakpoints (15).");
is(someBreakpoint.attachment.disabled, false,
"All breakpoints should now have been enabled (16).");
}
}
// Done.
deferred.resolve();
});
// Test re-enabling all breakpoints.
enableAll();
});
// Test disabling all breakpoints.
disableAll();
});
// Test re-enabling other breakpoints.
enableOthers();
});
// Test disabling other breakpoints.
disableOthers();
return deferred.promise;
}
function testDeleteAll() {
let deferred = promise.defer();
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED, 5).then(() => {
ok(!gSources._selectedBreakpointItem,
"There should be no breakpoint available after removing all breakpoints.");
for (let source in gSources) {
for (let otherBreakpoint in source) {
ok(false, "It's a trap!");
}
}
// Done.
deferred.resolve()
});
// Test deleting all breakpoints.
deleteAll();
return deferred.promise;
}
function disableOthers() {
gSources._onDisableOthers(gSources._selectedBreakpointItem.attachment.actor);
}
function enableOthers() {
gSources._onEnableOthers(gSources._selectedBreakpointItem.attachment.actor);
}
function disableAll() {
gSources._onDisableAll();
}
function enableAll() {
gSources._onEnableAll();
}
function deleteAll() {
gSources._onDeleteAll();
}
}

View File

@ -0,0 +1,331 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 723069: Test the debugger breakpoint API and connection to the
* source editor.
*/
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
gBreakpointsAdded = gBreakpoints._added;
gBreakpointsRemoving = gBreakpoints._removing;
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6).then(performTest);
gDebuggee.firstCall();
});
function performTest() {
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
is(gSources.itemCount, 2,
"Found the expected number of sources.");
is(gEditor.getText().indexOf("debugger"), 172,
"The correct source was loaded initially.");
is(gSources.selectedValue, gSources.values[1],
"The correct source is selected.");
is(gBreakpointsAdded.size, 0,
"No breakpoints currently added.");
is(gBreakpointsRemoving.size, 0,
"No breakpoints currently being removed.");
is(gEditor.getBreakpoints().length, 0,
"No breakpoints currently shown in the editor.");
ok(!gBreakpoints._getAdded({ url: "foo", line: 3 }),
"_getAdded('foo', 3) returns falsey.");
ok(!gBreakpoints._getRemoving({ url: "bar", line: 3 }),
"_getRemoving('bar', 3) returns falsey.");
is(gSources.values[1], gSources.selectedValue,
"The second source should be currently selected.");
info("Add the first breakpoint.");
let location = { url: gSources.selectedValue, line: 6 };
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddFirst);
gPanel.addBreakpoint(location).then(onBreakpointAddFirst);
}
let breakpointsAdded = 0;
let breakpointsRemoved = 0;
let editorBreakpointChanges = 0;
function onEditorBreakpointAddFirst(aEvent) {
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddFirst);
editorBreakpointChanges++;
ok(aEvent,
"breakpoint1 added to the editor.");
is(aEvent.added.length, 1,
"One breakpoint added to the editor.");
is(aEvent.removed.length, 0,
"No breakpoint was removed from the editor.");
is(aEvent.added[0].line, 5,
"Editor breakpoint line is correct.");
is(gEditor.getBreakpoints().length, 1,
"editor.getBreakpoints().length is correct.");
}
function onBreakpointAddFirst(aBreakpointClient) {
breakpointsAdded++;
ok(aBreakpointClient,
"breakpoint1 added, client received.");
is(aBreakpointClient.location.url, gSources.selectedValue,
"breakpoint1 client url is correct.");
is(aBreakpointClient.location.line, 6,
"breakpoint1 client line is correct.");
ok(gBreakpoints._getAdded(aBreakpointClient.location),
"breakpoint1 client found in the list of added breakpoints.");
ok(!gBreakpoints._getRemoving(aBreakpointClient.location),
"breakpoint1 client found in the list of removing breakpoints.");
is(gBreakpointsAdded.size, 1,
"The list of added breakpoints holds only one breakpoint.");
is(gBreakpointsRemoving.size, 0,
"The list of removing breakpoints holds no breakpoint.");
gBreakpoints._getAdded(aBreakpointClient.location).then(aClient => {
is(aClient, aBreakpointClient,
"_getAdded() returns the correct breakpoint.");
});
is(gSources.values[1], gSources.selectedValue,
"The second source should be currently selected.");
info("Remove the first breakpoint.");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveFirst);
gPanel.removeBreakpoint(aBreakpointClient.location).then(onBreakpointRemoveFirst);
}
function onEditorBreakpointRemoveFirst(aEvent) {
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveFirst);
editorBreakpointChanges++;
ok(aEvent,
"breakpoint1 removed from the editor.");
is(aEvent.added.length, 0,
"No breakpoint was added to the editor.");
is(aEvent.removed.length, 1,
"One breakpoint was removed from the editor.");
is(aEvent.removed[0].line, 5,
"Editor breakpoint line is correct.");
is(gEditor.getBreakpoints().length, 0,
"editor.getBreakpoints().length is correct.");
}
function onBreakpointRemoveFirst(aLocation) {
breakpointsRemoved++;
ok(aLocation,
"breakpoint1 removed");
is(aLocation.url, gSources.selectedValue,
"breakpoint1 removal url is correct.");
is(aLocation.line, 6,
"breakpoint1 removal line is correct.");
testBreakpointAddBackground();
}
function testBreakpointAddBackground() {
is(gBreakpointsAdded.size, 0,
"No breakpoints currently added.");
is(gBreakpointsRemoving.size, 0,
"No breakpoints currently being removed.");
is(gEditor.getBreakpoints().length, 0,
"No breakpoints currently shown in the editor.");
ok(!gBreakpoints._getAdded({ url: gSources.selectedValue, line: 6 }),
"_getAdded('gSources.selectedValue', 6) returns falsey.");
ok(!gBreakpoints._getRemoving({ url: gSources.selectedValue, line: 6 }),
"_getRemoving('gSources.selectedValue', 6) returns falsey.");
is(gSources.values[1], gSources.selectedValue,
"The second source should be currently selected.");
info("Add a breakpoint to the first source, which is not selected.");
let location = { url: gSources.values[0], line: 5 };
let options = { noEditorUpdate: true };
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddBackgroundTrap);
gPanel.addBreakpoint(location, options).then(onBreakpointAddBackground);
}
function onEditorBreakpointAddBackgroundTrap(aEvent) {
// Trap listener: no breakpoint must be added to the editor when a
// breakpoint is added to a source that is not currently selected.
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddBackgroundTrap);
editorBreakpointChanges++;
ok(false, "breakpoint2 must not be added to the editor.");
}
function onBreakpointAddBackground(aBreakpointClient, aResponseError) {
breakpointsAdded++;
ok(aBreakpointClient,
"breakpoint2 added, client received");
is(aBreakpointClient.location.url, gSources.values[0],
"breakpoint2 client url is correct.");
is(aBreakpointClient.location.line, 5,
"breakpoint2 client line is correct.");
ok(gBreakpoints._getAdded(aBreakpointClient.location),
"breakpoint2 client found in the list of added breakpoints.");
ok(!gBreakpoints._getRemoving(aBreakpointClient.location),
"breakpoint2 client found in the list of removing breakpoints.");
is(gBreakpointsAdded.size, 1,
"The list of added breakpoints holds only one breakpoint.");
is(gBreakpointsRemoving.size, 0,
"The list of removing breakpoints holds no breakpoint.");
gBreakpoints._getAdded(aBreakpointClient.location).then(aClient => {
is(aClient, aBreakpointClient,
"_getAdded() returns the correct breakpoint.");
});
is(gSources.values[1], gSources.selectedValue,
"The second source should be currently selected.");
// Remove the trap listener.
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddBackgroundTrap);
info("Switch to the first source, which is not yet selected");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddSwitch);
gEditor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onEditorTextChanged);
gSources.selectedIndex = 0;
}
function onEditorBreakpointAddSwitch(aEvent) {
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddSwitch);
editorBreakpointChanges++;
ok(aEvent,
"breakpoint2 added to the editor.");
is(aEvent.added.length, 1,
"One breakpoint added to the editor.");
is(aEvent.removed.length, 0,
"No breakpoint was removed from the editor.");
is(aEvent.added[0].line, 4,
"Editor breakpoint line is correct.");
is(gEditor.getBreakpoints().length, 1,
"editor.getBreakpoints().length is correct");
}
function onEditorTextChanged() {
// Wait for the actual text to be shown.
if (gEditor.getText() != gDebugger.L10N.getStr("loadingText")) {
onEditorTextReallyChanged();
}
}
function onEditorTextReallyChanged() {
gEditor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onEditorTextChanged);
is(gEditor.getText().indexOf("debugger"), -1,
"The second source is no longer displayed.");
is(gEditor.getText().indexOf("firstCall"), 118,
"The first source is displayed.");
is(gSources.values[0], gSources.selectedValue,
"The first source should be currently selected.");
let window = gEditor.editorElement.contentWindow;
executeSoon(() => window.mozRequestAnimationFrame(onReadyForClick));
}
function onReadyForClick() {
info("Remove the second breakpoint using the mouse.");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveSecond);
let iframe = gEditor.editorElement;
let testWin = iframe.ownerDocument.defaultView;
// Flush the layout for the iframe.
info("rect " + iframe.contentDocument.documentElement.getBoundingClientRect());
let utils = testWin
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let lineOffset = gEditor.getLineStart(4);
let coords = gEditor.getLocationAtOffset(lineOffset);
let rect = iframe.getBoundingClientRect();
let left = rect.left + 10;
let top = rect.top + coords.y + 4;
utils.sendMouseEventToWindow("mousedown", left, top, 0, 1, 0, false, 0, 0);
utils.sendMouseEventToWindow("mouseup", left, top, 0, 1, 0, false, 0, 0);
}
function onEditorBreakpointRemoveSecond(aEvent) {
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveSecond);
editorBreakpointChanges++;
ok(aEvent,
"breakpoint2 removed from the editor.");
is(aEvent.added.length, 0,
"No breakpoint was added to the editor.");
is(aEvent.removed.length, 1,
"One breakpoint was removed from the editor.");
is(aEvent.removed[0].line, 4,
"Editor breakpoint line is correct.");
is(gEditor.getBreakpoints().length, 0,
"editor.getBreakpoints().length is correct.");
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
finalCheck();
closeDebuggerAndFinish(gPanel);
});
gDebugger.gThreadClient.resume();
}
function finalCheck() {
is(gBreakpointsAdded.size, 0,
"No breakpoints currently added.");
is(gBreakpointsRemoving.size, 0,
"No breakpoints currently being removed.");
is(gEditor.getBreakpoints().length, 0,
"No breakpoints currently shown in the editor.");
ok(!gBreakpoints._getAdded({ url: gSources.values[0], line: 5 }),
"_getAdded('gSources.values[0]', 5) returns falsey.");
ok(!gBreakpoints._getRemoving({ url: gSources.values[0], line: 5 }),
"_getRemoving('gSources.values[0]', 5) returns falsey.");
ok(!gBreakpoints._getAdded({ url: gSources.values[1], line: 6 }),
"_getAdded('gSources.values[1]', 6) returns falsey.");
ok(!gBreakpoints._getRemoving({ url: gSources.values[1], line: 6 }),
"_getRemoving('gSources.values[1]', 6) returns falsey.");
ok(!gBreakpoints._getAdded({ url: "foo", line: 3 }),
"_getAdded('foo', 3) returns falsey.");
ok(!gBreakpoints._getRemoving({ url: "bar", line: 3 }),
"_getRemoving('bar', 3) returns falsey.");
is(breakpointsAdded, 2,
"Correct number of breakpoints have been added.");
is(breakpointsRemoved, 1,
"Correct number of breakpoints have been removed.");
is(editorBreakpointChanges, 4,
"Correct number of editor breakpoint changes.");
}
}

View File

@ -0,0 +1,103 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test if breakpoints are highlighted when they should.
*/
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
waitForSourceShown(gPanel, "-01.js")
.then(addBreakpoints)
.then(() => clickBreakpointAndCheck(0, 0, 5))
.then(() => clickBreakpointAndCheck(1, 1, 6))
.then(() => clickBreakpointAndCheck(2, 1, 7))
.then(() => clickBreakpointAndCheck(3, 1, 8))
.then(() => clickBreakpointAndCheck(4, 1, 9))
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
function addBreakpoints() {
return promise.resolve(null)
.then(() => initialChecks(0, 1))
.then(() => gPanel.addBreakpoint({ url: gSources.values[0], line: 5 }))
.then(() => initialChecks(0, 5))
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 6 }))
.then(() => waitForSourceShown(gPanel, "-02.js"))
.then(() => waitForCaretUpdated(gPanel, 6))
.then(() => initialChecks(1, 6))
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 7 }))
.then(() => initialChecks(1, 7))
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 8 }))
.then(() => initialChecks(1, 8))
.then(() => gPanel.addBreakpoint({ url: gSources.values[1], line: 9 }))
.then(() => initialChecks(1, 9));
}
function initialChecks(aSourceIndex, aCaretLine) {
checkEditorContents(aSourceIndex);
is(gSources.selectedLabel, gSources.items[aSourceIndex].label,
"The currently selected source label is incorrect (0).");
is(gSources.selectedValue, gSources.items[aSourceIndex].value,
"The currently selected source value is incorrect (0).");
ok(isCaretPos(gPanel, aCaretLine),
"The editor caret line and column were incorrect (0).");
}
function clickBreakpointAndCheck(aBreakpointIndex, aSourceIndex, aCaretLine) {
let finished = waitForCaretUpdated(gPanel, aCaretLine).then(() => {
checkHighlight(gSources.values[aSourceIndex], aCaretLine);
checkEditorContents(aSourceIndex);
is(gSources.selectedLabel, gSources.items[aSourceIndex].label,
"The currently selected source label is incorrect (1).");
is(gSources.selectedValue, gSources.items[aSourceIndex].value,
"The currently selected source value is incorrect (1).");
ok(isCaretPos(gPanel, aCaretLine),
"The editor caret line and column were incorrect (1).");
});
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.querySelectorAll(".dbg-breakpoint")[aBreakpointIndex],
gDebugger);
return finished;
}
function checkHighlight(aUrl, aLine) {
is(gSources._selectedBreakpointItem, gSources.getBreakpoint({ url: aUrl, line: aLine }),
"The currently selected breakpoint item is incorrect.");
is(gSources._selectedBreakpointItem.attachment.url, aUrl,
"The selected breakpoint item's source location attachment is incorrect.");
is(gSources._selectedBreakpointItem.attachment.line, aLine,
"The selected breakpoint item's source line number is incorrect.");
ok(gSources._selectedBreakpointItem.target.classList.contains("selected"),
"The selected breakpoint item's target should have a selected class.");
}
function checkEditorContents(aSourceIndex) {
if (aSourceIndex == 0) {
is(gEditor.getText().indexOf("firstCall"), 118,
"The first source is correctly displayed.");
} else {
is(gEditor.getText().indexOf("debugger"), 172,
"The second source is correctly displayed.");
}
}
}

View File

@ -0,0 +1,90 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 771452: Make sure that setting a breakpoint in an inline source doesn't
* add it twice.
*/
const TAB_URL = EXAMPLE_URL + "doc_inline-script.html";
let gTab, gDebuggee, gPanel, gDebugger;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
addBreakpoint();
});
}
function addBreakpoint() {
waitForSourceAndCaretAndScopes(gPanel, ".html", 16).then(() => {
is(gDebugger.gThreadClient.state, "paused",
"The debugger statement was reached.");
ok(isCaretPos(gPanel, 16),
"The source editor caret position is incorrect (1).");
gPanel.addBreakpoint({ url: TAB_URL, line: 20 }).then(() => {
testResume();
});
});
gDebuggee.runDebuggerStatement();
}
function testResume() {
is(gDebugger.gThreadClient.state, "paused",
"The breakpoint wasn't hit yet.");
gDebugger.gThreadClient.resume(() => {
gDebugger.gThreadClient.addOneTimeListener("paused", (aEvent, aPacket) => {
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES).then(() => {
is(aPacket.why.type, "breakpoint",
"Execution has advanced to the next breakpoint.");
isnot(aPacket.why.type, "debuggerStatement",
"The breakpoint was hit before the debugger statement.");
ok(isCaretPos(gPanel, 20),
"The source editor caret position is incorrect (2).");
testBreakpointHit();
});
});
EventUtils.sendMouseEvent({ type: "click" },
gDebuggee.document.querySelector("button"),
gDebuggee);
});
}
function testBreakpointHit() {
is(gDebugger.gThreadClient.state, "paused",
"The breakpoint was hit.");
gDebugger.gThreadClient.addOneTimeListener("paused", (aEvent, aPacket) => {
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES).then(() => {
is(aPacket.why.type, "debuggerStatement",
"Execution has advanced to the next line.");
isnot(aPacket.why.type, "breakpoint",
"No ghost breakpoint was hit.");
ok(isCaretPos(gPanel, 20),
"The source editor caret position is incorrect (3).");
resumeDebuggerThenCloseAndFinish(gPanel);
});
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
});

View File

@ -0,0 +1,255 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 723071: Test adding a pane to display the list of breakpoints across
* all sources in the debuggee.
*/
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
gBreakpointsAdded = gBreakpoints._added;
gBreakpointsRemoving = gBreakpoints._removing;
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6).then(performTest);
gDebuggee.firstCall();
});
let breakpointsAdded = 0;
let breakpointsDisabled = 0;
let breakpointsRemoved = 0;
function performTest() {
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
is(gSources.itemCount, 2,
"Found the expected number of sources.");
is(gEditor.getText().indexOf("debugger"), 172,
"The correct source was loaded initially.");
is(gSources.selectedValue, gSources.values[1],
"The correct source is selected.");
is(gBreakpointsAdded.size, 0,
"No breakpoints currently added.");
is(gBreakpointsRemoving.size, 0,
"No breakpoints currently being removed.");
is(gEditor.getBreakpoints().length, 0,
"No breakpoints currently shown in the editor.");
ok(!gBreakpoints._getAdded({ url: "foo", line: 3 }),
"_getAdded('foo', 3) returns falsey.");
ok(!gBreakpoints._getRemoving({ url: "bar", line: 3 }),
"_getRemoving('bar', 3) returns falsey.");
let breakpointsParent = gSources.widget._parent;
let breakpointsList = gSources.widget._list;
is(breakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(breakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(breakpointsList.querySelectorAll(".dbg-breakpoint").length, 0,
"No breakpoints should be visible at this point.");
addBreakpoints(true).then(() => {
is(breakpointsAdded, 3,
"Should have added 3 breakpoints so far.");
is(breakpointsDisabled, 0,
"Shouldn't have disabled anything so far.");
is(breakpointsRemoved, 0,
"Shouldn't have removed anything so far.");
is(breakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(breakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(breakpointsList.querySelectorAll(".dbg-breakpoint").length, 3,
"3 breakpoints should be visible at this point.");
disableBreakpoints().then(() => {
is(breakpointsAdded, 3,
"Should still have 3 breakpoints added so far.");
is(breakpointsDisabled, 3,
"Should have 3 disabled breakpoints.");
is(breakpointsRemoved, 0,
"Shouldn't have removed anything so far.");
is(breakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(breakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(breakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsAdded,
"Should have the same number of breakpoints in the pane.");
is(breakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsDisabled,
"Should have the same number of disabled breakpoints.");
addBreakpoints().then(() => {
is(breakpointsAdded, 3,
"Should still have only 3 breakpoints added so far.");
is(breakpointsDisabled, 3,
"Should still have 3 disabled breakpoints.");
is(breakpointsRemoved, 0,
"Shouldn't have removed anything so far.");
is(breakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(breakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(breakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsAdded,
"Since half of the breakpoints already existed, but disabled, " +
"only half of the added breakpoints are actually in the pane.");
removeBreakpoints().then(() => {
is(breakpointsRemoved, 3,
"Should have 3 removed breakpoints.");
is(breakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(breakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(breakpointsList.querySelectorAll(".dbg-breakpoint").length, 0,
"No breakpoints should be visible at this point.");
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
finalCheck();
closeDebuggerAndFinish(gPanel);
});
gDebugger.gThreadClient.resume();
});
});
});
});
function addBreakpoints(aIncrementFlag) {
let deferred = promise.defer();
gPanel.addBreakpoint({ url: gSources.selectedValue, line: 6 }).then(aClient => {
onBreakpointAdd(aClient, {
increment: aIncrementFlag,
line: 6,
text: "eval(\"debugger;\");"
});
gPanel.addBreakpoint({ url: gSources.selectedValue, line: 7 }).then(aClient => {
onBreakpointAdd(aClient, {
increment: aIncrementFlag,
line: 7,
text: "function foo() {}"
});
gPanel.addBreakpoint({ url: gSources.selectedValue, line: 9 }).then(aClient => {
onBreakpointAdd(aClient, {
increment: aIncrementFlag,
line: 9,
text: "foo();"
});
deferred.resolve();
});
});
});
return deferred.promise;
}
function disableBreakpoints() {
let deferred = promise.defer();
let nodes = breakpointsList.querySelectorAll(".dbg-breakpoint");
info("Nodes to disable: " + breakpointsAdded.length);
is(nodes.length, breakpointsAdded,
"The number of nodes to disable is incorrect.");
for (let node of nodes) {
info("Disabling breakpoint: " + node.id);
let sourceItem = gSources.getItemForElement(node);
let breakpointItem = gSources.getItemForElement.call(sourceItem, node);
info("Found data: " + breakpointItem.attachment.toSource());
gSources.disableBreakpoint(breakpointItem.attachment).then(() => {
if (++breakpointsDisabled == breakpointsAdded) {
deferred.resolve();
}
});
}
return deferred.promise;
}
function removeBreakpoints() {
let deferred = promise.defer();
let nodes = breakpointsList.querySelectorAll(".dbg-breakpoint");
info("Nodes to remove: " + breakpointsAdded.length);
is(nodes.length, breakpointsAdded,
"The number of nodes to remove is incorrect.");
for (let node of nodes) {
info("Removing breakpoint: " + node.id);
let sourceItem = gSources.getItemForElement(node);
let breakpointItem = gSources.getItemForElement.call(sourceItem, node);
info("Found data: " + breakpointItem.attachment.toSource());
gPanel.removeBreakpoint(breakpointItem.attachment).then(() => {
if (++breakpointsRemoved == breakpointsAdded) {
deferred.resolve();
}
});
}
return deferred.promise;
}
function onBreakpointAdd(aBreakpointClient, aTestData) {
if (aTestData.increment) {
breakpointsAdded++;
}
is(breakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsAdded,
aTestData.increment
? "Should have added a breakpoint in the pane."
: "Should have the same number of breakpoints in the pane.");
let id = "breakpoint-" + aBreakpointClient.actor;
let node = gDebugger.document.getElementById(id);
let line = node.getElementsByClassName("dbg-breakpoint-line")[0];
let text = node.getElementsByClassName("dbg-breakpoint-text")[0];
let check = node.querySelector("checkbox");
is(node.id, id,
"Breakpoint element " + id + " found successfully.");
is(line.getAttribute("value"), aTestData.line,
"The expected information wasn't found in the breakpoint element.");
is(text.getAttribute("value"), aTestData.text,
"The expected line text wasn't found in the breakpoint element.");
is(check.getAttribute("checked"), "true",
"The breakpoint enable checkbox is checked as expected.");
}
}
function finalCheck() {
is(gBreakpointsAdded.size, 0,
"No breakpoints currently added.");
is(gBreakpointsRemoving.size, 0,
"No breakpoints currently being removed.");
is(gEditor.getBreakpoints().length, 0,
"No breakpoints currently shown in the editor.");
}
}

View File

@ -1,308 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 723069: test the debugger breakpoint API and connection to the source
* editor.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gEditor = null;
let gSources = null;
let gBreakpoints = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.addEventListener("Debugger:SourceShown", onSourceShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.firstCall();
});
});
function onSourceShown(aEvent)
{
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
function startTest()
{
if (scriptShown && framesAdded && !testStarted) {
gDebugger.removeEventListener("Debugger:SourceShown", onSourceShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function performTest()
{
gSources = gDebugger.DebuggerView.Sources;
gEditor = gDebugger.editor;
gBreakpoints = gPane.getAllBreakpoints();
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gSources.itemCount, 2,
"Found the expected number of scripts.");
isnot(gEditor.getText().indexOf("debugger"), -1,
"The correct script was loaded initially.");
isnot(gSources.selectedValue, gSources.values[0],
"The correct script is selected");
is(Object.keys(gBreakpoints), 0, "no breakpoints");
ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddFirst);
executeSoon(function() {
gPane.addBreakpoint({url: gSources.selectedValue, line: 6}, onBreakpointAddFirst);
});
}
let breakpointsAdded = 0;
let breakpointsRemoved = 0;
let editorBreakpointChanges = 0;
function onEditorBreakpointAddFirst(aEvent)
{
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddFirst);
editorBreakpointChanges++;
ok(aEvent, "breakpoint1 added to the editor");
is(aEvent.added.length, 1, "one breakpoint added to the editor");
is(aEvent.removed.length, 0, "no breakpoint was removed from the editor");
is(aEvent.added[0].line, 5, "editor breakpoint line is correct");
is(gEditor.getBreakpoints().length, 1,
"editor.getBreakpoints().length is correct");
}
function onBreakpointAddFirst(aBreakpointClient, aResponseError)
{
breakpointsAdded++;
ok(aBreakpointClient, "breakpoint1 added, client received");
ok(!aResponseError, "breakpoint1 added without errors");
is(aBreakpointClient.location.url, gSources.selectedValue,
"breakpoint1 client url is correct");
is(aBreakpointClient.location.line, 6,
"breakpoint1 client line is correct");
executeSoon(function() {
ok(aBreakpointClient.actor in gBreakpoints,
"breakpoint1 client found in the list of debugger breakpoints");
is(Object.keys(gBreakpoints).length, 1,
"the list of debugger breakpoints holds only one breakpoint");
is(gPane.getBreakpoint(gSources.selectedValue, 6), aBreakpointClient,
"getBreakpoint returns the correct breakpoint");
info("remove the first breakpoint");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveFirst);
gPane.removeBreakpoint(aBreakpointClient, onBreakpointRemoveFirst);
});
}
function onBreakpointRemoveFirst(aLocation)
{
breakpointsRemoved++;
ok(aLocation, "breakpoint1 removed");
is(aLocation.url, gSources.selectedValue, "breakpoint1 remove: url is correct");
is(aLocation.line, 6, "breakpoint1 remove: line is correct");
executeSoon(testBreakpointAddBackground);
}
function onEditorBreakpointRemoveFirst(aEvent)
{
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveFirst);
editorBreakpointChanges++;
ok(aEvent, "breakpoint1 removed from the editor");
is(aEvent.added.length, 0, "no breakpoint was added to the editor");
is(aEvent.removed.length, 1, "one breakpoint was removed from the editor");
is(aEvent.removed[0].line, 5, "editor breakpoint line is correct");
is(gEditor.getBreakpoints().length, 0,
"editor.getBreakpoints().length is correct");
}
function testBreakpointAddBackground()
{
info("add a breakpoint to the second script which is not selected");
is(Object.keys(gBreakpoints).length, 0,
"no breakpoints in the debugger");
ok(!gPane.getBreakpoint(gSources.selectedValue, 6),
"getBreakpoint(selectedScript, 6) returns no breakpoint");
isnot(gSources.values[0], gSources.selectedValue,
"first script location is not the currently selected script");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddBackgroundTrap);
gPane.addBreakpoint({url: gSources.values[0], line: 5}, onBreakpointAddBackground);
}
function onEditorBreakpointAddBackgroundTrap(aEvent)
{
// Trap listener: no breakpoint must be added to the editor when a
// breakpoint is added to a script that is not currently selected.
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddBackgroundTrap);
editorBreakpointChanges++;
ok(false, "breakpoint2 must not be added to the editor");
}
function onBreakpointAddBackground(aBreakpointClient, aResponseError)
{
breakpointsAdded++;
ok(aBreakpointClient, "breakpoint2 added, client received");
ok(!aResponseError, "breakpoint2 added without errors");
is(aBreakpointClient.location.url, gSources.values[0],
"breakpoint2 client url is correct");
is(aBreakpointClient.location.line, 5,
"breakpoint2 client line is correct");
executeSoon(function() {
ok(aBreakpointClient.actor in gBreakpoints,
"breakpoint2 client found in the list of debugger breakpoints");
is(Object.keys(gBreakpoints).length, 1,
"one breakpoint in the debugger");
is(gPane.getBreakpoint(gSources.values[0], 5), aBreakpointClient,
"getBreakpoint(locations[0], 5) returns the correct breakpoint");
// remove the trap listener
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddBackgroundTrap);
info("switch to the second script");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddSwitch);
gEditor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onEditorTextChanged);
gSources.selectedIndex = 0;
});
}
function onEditorBreakpointAddSwitch(aEvent)
{
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointAddSwitch);
editorBreakpointChanges++;
ok(aEvent, "breakpoint2 added to the editor");
is(aEvent.added.length, 1, "one breakpoint added to the editor");
is(aEvent.removed.length, 0, "no breakpoint was removed from the editor");
is(aEvent.added[0].line, 4, "editor breakpoint line is correct");
is(gEditor.getBreakpoints().length, 1,
"editor.getBreakpoints().length is correct");
}
function onEditorTextChanged()
{
// Wait for the actual text to be shown.
if (gDebugger.editor.getText() == gDebugger.L10N.getStr("loadingText")) {
return;
}
// The requested source text has been shown, remove the event listener.
gEditor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED, onEditorTextChanged);
is(gEditor.getText().indexOf("debugger"), -1,
"The second script is no longer displayed.");
isnot(gEditor.getText().indexOf("firstCall"), -1,
"The first script is displayed.");
let window = gEditor.editorElement.contentWindow;
executeSoon(() => window.mozRequestAnimationFrame(onReadyForClick));
}
function onReadyForClick()
{
info("remove the second breakpoint using the mouse");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveSecond);
let iframe = gEditor.editorElement;
let testWin = iframe.ownerDocument.defaultView;
// flush the layout for the iframe
info("rect " + iframe.contentDocument.documentElement.getBoundingClientRect());
let utils = testWin.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
let lineOffset = gEditor.getLineStart(4);
let coords = gEditor.getLocationAtOffset(lineOffset);
let rect = iframe.getBoundingClientRect();
let left = rect.left + 10;
let top = rect.top + coords.y + 4;
utils.sendMouseEventToWindow("mousedown", left, top, 0, 1, 0, false, 0, 0);
utils.sendMouseEventToWindow("mouseup", left, top, 0, 1, 0, false, 0, 0);
}
function onEditorBreakpointRemoveSecond(aEvent)
{
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, onEditorBreakpointRemoveSecond);
editorBreakpointChanges++;
ok(aEvent, "breakpoint2 removed from the editor");
is(aEvent.added.length, 0, "no breakpoint was added to the editor");
is(aEvent.removed.length, 1, "one breakpoint was removed from the editor");
is(aEvent.removed[0].line, 4, "editor breakpoint line is correct");
is(gEditor.getBreakpoints().length, 0,
"editor.getBreakpoints().length is correct");
executeSoon(function() {
gDebugger.gClient.addOneTimeListener("resumed", function() {
finalCheck();
closeDebuggerAndFinish();
});
gDebugger.DebuggerController.activeThread.resume();
});
}
function finalCheck() {
is(Object.keys(gBreakpoints).length, 0, "no breakpoint in the debugger");
ok(!gPane.getBreakpoint(gSources.values[0], 5),
"getBreakpoint(locations[0], 5) returns no breakpoint");
}
registerCleanupFunction(function() {
removeTab(gTab);
is(breakpointsAdded, 2, "correct number of breakpoints have been added");
is(breakpointsRemoved, 1, "correct number of breakpoints have been removed");
is(editorBreakpointChanges, 4, "correct number of editor breakpoint changes");
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gSources = null;
gBreakpoints = null;
});
}

View File

@ -1,466 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test if the context menu associated with each breakpoint does what it should.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gEditor = null;
let gSources = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gSources.preferredSource = EXAMPLE_URL + "test-script-switching-02.js";
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
let { url, loaded, text } = aEvent.detail;
info("Shown source: " + url + ", loaded: " + loaded + ", text:\n" + text);
info("Shown label: " + gSources.selectedLabel);
info("All labels:" + gSources.labels);
if (url.indexOf("-02") != -1) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
performTestWhileNotPaused();
}
});
});
function addBreakpoints(callback) {
gPane.addBreakpoint({url: gSources.orderedItems[0].value, line: 5}, function(cl, err) {
gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 6}, function(cl, err) {
gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 7}, function(cl, err) {
gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 8}, function(cl, err) {
gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 9}, function(cl, err) {
callback();
});
});
});
});
});
}
function performTestWhileNotPaused()
{
info("Performing test while not paused...");
addBreakpoints(function() {
initialChecks();
checkBreakpointToggleSelf(0, function() {
checkBreakpointToggleOthers(0, function() {
checkBreakpointToggleSelf(1, function() {
checkBreakpointToggleOthers(1, function() {
checkBreakpointToggleSelf(2, function() {
checkBreakpointToggleOthers(2, function() {
checkBreakpointToggleSelf(3, function() {
checkBreakpointToggleOthers(3, function() {
checkBreakpointToggleSelf(4, function() {
checkBreakpointToggleOthers(4, function() {
testDeleteAll(function() {
performTestWhilePaused();
});
});
});
});
});
});
});
});
});
});
});
});
}
function performTestWhilePaused()
{
info("Performing test while paused...");
addBreakpoints(function() {
initialChecks();
pauseAndCheck(function() {
checkBreakpointToggleSelf(0, function() {
checkBreakpointToggleOthers(0, function() {
checkBreakpointToggleSelf(1, function() {
checkBreakpointToggleOthers(1, function() {
checkBreakpointToggleSelf(2, function() {
checkBreakpointToggleOthers(2, function() {
checkBreakpointToggleSelf(3, function() {
checkBreakpointToggleOthers(3, function() {
checkBreakpointToggleSelf(4, function() {
checkBreakpointToggleOthers(4, function() {
testDeleteAll(function() {
closeDebuggerAndFinish();
});
}, true);
});
}, true);
});
}, true);
});
}, true);
});
}, true);
});
});
});
}
function pauseAndCheck(callback) {
gDebugger.gThreadClient.addOneTimeListener("resumed", function() {
pauseAndCallback(function() {
is(gSources.selectedLabel, "test-script-switching-01.js",
"The currently selected source is incorrect (1).");
is(gSources.selectedIndex, 1,
"The currently selected source is incorrect (2).");
waitForCaretPos(4, function() {
ok(true, "The editor location is correct after pausing.");
callback();
});
});
});
}
function pauseAndCallback(callback) {
let scriptShown = false;
let framesadded = false;
let testContinued = false;
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
let url = aEvent.detail.url;
if (url.indexOf("-01") != -1) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
scriptShown = true;
executeSoon(continueTest);
}
});
gDebugger.gThreadClient.addOneTimeListener("framesadded", function() {
framesadded = true;
executeSoon(continueTest);
});
function continueTest() {
if (scriptShown && framesadded && !testContinued) {
testContinued = true;
callback();
}
}
EventUtils.sendMouseEvent({ type: "click" },
gDebuggee.document.querySelector("button"),
gDebuggee.window);
}
function initialChecks() {
for (let source in gSources) {
for (let breakpoint in source) {
let { sourceLocation: url, lineNumber: line, actor } = breakpoint.attachment;
ok(gPane.getBreakpoint(url, line),
"All breakpoint items should have corresponding clients (1).");
ok(breakpoint.attachment.actor,
"All breakpoint items should have corresponding clients (2).");
is(!!breakpoint.attachment.disabled, false,
"All breakpoints should initially be enabled.");
let prefix = "bp-cMenu-"; // "breakpoints context menu"
let enableSelfId = prefix + "enableSelf-" + actor + "-menuitem";
let disableSelfId = prefix + "disableSelf-" + actor + "-menuitem";
is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true",
"The 'Enable breakpoint' context menu item should initially be hidden'.");
ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"),
"The 'Disable breakpoint' context menu item should initially not be hidden'.");
is(breakpoint.attachment.view.checkbox.getAttribute("checked"), "true",
"All breakpoints should initially have a checked checkbox.");
}
}
}
function checkBreakpointToggleSelf(index, callback) {
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.querySelectorAll(".dbg-breakpoint")[index],
gDebugger);
let selectedBreakpoint = gSources.selectedBreakpointItem;
let { sourceLocation: url, lineNumber: line, actor } = selectedBreakpoint.attachment;
ok(gPane.getBreakpoint(url, line),
"There should be a breakpoint client available (1).");
ok(gSources.selectedBreakpointClient,
"There should be a breakpoint client available (2).");
is(!!selectedBreakpoint.attachment.disabled, false,
"The breakpoint should not be disabled yet.");
let prefix = "bp-cMenu-"; // "breakpoints context menu"
let enableSelfId = prefix + "enableSelf-" + actor + "-menuitem";
let disableSelfId = prefix + "disableSelf-" + actor + "-menuitem";
is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true",
"The 'Enable breakpoint' context menu item should be hidden'.");
ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"),
"The 'Disable breakpoint' context menu item should not be hidden'.");
waitForCaretPos(selectedBreakpoint.attachment.lineNumber - 1, function() {
ok(true, "The editor location is correct (" + index + ").");
gDebugger.addEventListener("Debugger:BreakpointHidden", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(!gPane.getBreakpoint(url, line),
"There should be no breakpoint client available (2).");
ok(!gSources.selectedBreakpointClient,
"There should be no breakpoint client available (3).");
gDebugger.addEventListener("Debugger:BreakpointShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(gPane.getBreakpoint(url, line),
"There should be a breakpoint client available (4).");
ok(gSources.selectedBreakpointClient,
"There should be a breakpoint client available (5).");
callback();
});
// Test re-disabling this breakpoint.
executeSoon(function() {
gSources._onEnableSelf(selectedBreakpoint.attachment.actor);
is(selectedBreakpoint.attachment.disabled, false,
"The current breakpoint should now be enabled.")
is(gDebugger.document.getElementById(enableSelfId).getAttribute("hidden"), "true",
"The 'Enable breakpoint' context menu item should be hidden'.");
ok(!gDebugger.document.getElementById(disableSelfId).hasAttribute("hidden"),
"The 'Disable breakpoint' context menu item should not be hidden'.");
ok(selectedBreakpoint.attachment.view.checkbox.hasAttribute("checked"),
"The breakpoint should now be checked.");
});
});
// Test disabling this breakpoint.
executeSoon(function() {
gSources._onDisableSelf(selectedBreakpoint.attachment.actor);
is(selectedBreakpoint.attachment.disabled, true,
"The current breakpoint should now be disabled.")
ok(!gDebugger.document.getElementById(enableSelfId).hasAttribute("hidden"),
"The 'Enable breakpoint' context menu item should not be hidden'.");
is(gDebugger.document.getElementById(disableSelfId).getAttribute("hidden"), "true",
"The 'Disable breakpoint' context menu item should be hidden'.");
ok(!selectedBreakpoint.attachment.view.checkbox.hasAttribute("checked"),
"The breakpoint should now be unchecked.");
});
});
}
function checkBreakpointToggleOthers(index, callback, whilePaused) {
let count = 4
gDebugger.addEventListener("Debugger:BreakpointHidden", function _onEvent(aEvent) {
info(count + " breakpoints remain to be hidden...");
if (!(--count)) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(true, "All breakpoints except one were hidden.");
let selectedBreakpoint = gSources.selectedBreakpointItem;
let { sourceLocation: url, lineNumber: line, actor } = selectedBreakpoint.attachment;
ok(gPane.getBreakpoint(url, line),
"There should be a breakpoint client available (6).");
ok(gSources.selectedBreakpointClient,
"There should be a breakpoint client available (7).");
is(!!selectedBreakpoint.attachment.disabled, false,
"The targetted breakpoint should not have been disabled.");
for (let source in gSources) {
for (let otherBreakpoint in source) {
if (otherBreakpoint != selectedBreakpoint) {
ok(!gPane.getBreakpoint(
otherBreakpoint.attachment.sourceLocation,
otherBreakpoint.attachment.lineNumber),
"There should be no breakpoint client for a disabled breakpoint (8).");
is(otherBreakpoint.attachment.disabled, true,
"Non-targetted breakpoints should have been disabled (9).");
}
}
}
count = 4;
gDebugger.addEventListener("Debugger:BreakpointShown", function _onEvent(aEvent) {
info(count + " breakpoints remain to be reshown...");
if (!(--count)) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(true, "All breakpoints are now reshown.");
for (let source in gSources) {
for (let someBreakpoint in source) {
ok(gPane.getBreakpoint(
someBreakpoint.attachment.sourceLocation,
someBreakpoint.attachment.lineNumber),
"There should be a breakpoint client for all enabled breakpoints (10).");
is(someBreakpoint.attachment.disabled, false,
"All breakpoints should now have been enabled (11).");
}
}
count = 5;
gDebugger.addEventListener("Debugger:BreakpointHidden", function _onEvent(aEvent) {
info(count + " breakpoints remain to be rehidden...");
if (!(--count)) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(true, "All breakpoints are now rehidden.");
for (let source in gSources) {
for (let someBreakpoint in source) {
ok(!gPane.getBreakpoint(
someBreakpoint.attachment.sourceLocation,
someBreakpoint.attachment.lineNumber),
"There should be no breakpoint client for a disabled breakpoint (12).");
is(someBreakpoint.attachment.disabled, true,
"All breakpoints should now have been disabled (13).");
}
}
count = 5;
gDebugger.addEventListener("Debugger:BreakpointShown", function _onEvent(aEvent) {
info(count + " breakpoints remain to be reshown...");
if (!(--count)) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(true, "All breakpoints are now rehidden.");
for (let source in gSources) {
for (let someBreakpoint in source) {
ok(gPane.getBreakpoint(
someBreakpoint.attachment.sourceLocation,
someBreakpoint.attachment.lineNumber),
"There should be a breakpoint client for all enabled breakpoints (14).");
is(someBreakpoint.attachment.disabled, false,
"All breakpoints should now have been enabled (15).");
}
}
// Done.
if (!whilePaused) {
gDebugger.gThreadClient.addOneTimeListener("resumed", callback);
} else {
callback();
}
}
});
// Test re-enabling all breakpoints.
enableAll();
}
});
// Test disabling all breakpoints.
if (!whilePaused) {
gDebugger.gThreadClient.addOneTimeListener("resumed", disableAll);
} else {
disableAll();
}
}
});
// Test re-enabling other breakpoints.
enableOthers();
}
});
// Test disabling other breakpoints.
if (!whilePaused) {
gDebugger.gThreadClient.addOneTimeListener("resumed", disableOthers);
} else {
disableOthers();
}
}
function testDeleteAll(callback) {
let count = 5
gDebugger.addEventListener("Debugger:BreakpointHidden", function _onEvent(aEvent) {
info(count + " breakpoints remain to be hidden...");
if (!(--count)) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(true, "All breakpoints were hidden.");
ok(!gSources.selectedBreakpointItem,
"There should be no breakpoint item available (16).");
ok(!gSources.selectedBreakpointClient,
"There should be no breakpoint client available (17).");
for (let source in gSources) {
for (let otherBreakpoint in source) {
ok(false, "It's a trap!");
}
}
// Done.
callback();
}
});
// Test deleting all breakpoints.
deleteAll();
}
function disableOthers() {
gSources._onDisableOthers(gSources.selectedBreakpointItem.attachment.actor);
}
function enableOthers() {
gSources._onEnableOthers(gSources.selectedBreakpointItem.attachment.actor);
}
function disableAll() {
gSources._onDisableAll(gSources.selectedBreakpointItem.attachment.actor);
}
function enableAll() {
gSources._onEnableAll(gSources.selectedBreakpointItem.attachment.actor);
}
function deleteAll() {
gSources._onDeleteAll(gSources.selectedBreakpointItem.attachment.actor);
}
function waitForCaretPos(number, callback)
{
// Poll every few milliseconds until the source editor line is active.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
if (++count > 50) {
ok(false, "Timed out while polling for the line.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if (gEditor.getCaretPosition().line != number) {
return;
}
// We got the source editor at the expected line, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gSources = null;
});
}

View File

@ -1,224 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test if breakpoints are highlighted when they should.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gEditor = null;
let gSources = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gSources.preferredSource = EXAMPLE_URL + "test-script-switching-02.js";
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
let { url, loaded, text } = aEvent.detail;
info("Shown source: " + url + ", loaded: " + loaded + ", text:\n" + text);
info("Shown label: " + gSources.selectedLabel);
info("All labels:" + gSources.labels);
if (url.indexOf("-02") != -1) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
performTest();
}
});
});
function performTest()
{
initialChecks();
gPane.addBreakpoint({url: gSources.orderedItems[0].value, line: 5}, function(cl, err) {
initialChecks();
gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 6}, function(cl, err) {
initialChecks();
gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 7}, function(cl, err) {
initialChecks();
gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 8}, function(cl, err) {
initialChecks();
gPane.addBreakpoint({url: gSources.orderedItems[1].value, line: 9}, function(cl, err) {
initialChecks();
testHighlight1();
});
});
});
});
});
}
function initialChecks() {
is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (0).");
is(gEditor.getCaretPosition().line, 0,
"The editor caret line was incorrect (0).");
is(gEditor.getCaretPosition().col, 0,
"The editor caret column was incorrect (0).");
}
function testHighlight1() {
gSources.highlightBreakpoint(gSources.orderedItems[0].value, 5);
checkHighlight(gSources.orderedItems[0].value, 5);
is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (1).");
is(gEditor.getCaretPosition().line, 0,
"The editor caret line was incorrect (1).");
is(gEditor.getCaretPosition().col, 0,
"The editor caret column was incorrect (1).");
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.querySelectorAll(".dbg-breakpoint")[0],
gDebugger);
waitForCaretPos(4, function() {
ok(true, "The editor location is correct (1).");
testHighlight2();
});
}
function testHighlight2() {
gSources.highlightBreakpoint(gSources.orderedItems[1].value, 6);
checkHighlight(gSources.orderedItems[1].value, 6);
is(gSources.selectedValue, gSources.orderedItems[0].value,
"The currently selected source is incorrect (2).");
is(gEditor.getCaretPosition().line, 4,
"The editor caret line was incorrect (2).");
is(gEditor.getCaretPosition().col, 0,
"The editor caret column was incorrect (2).");
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.querySelectorAll(".dbg-breakpoint")[1],
gDebugger);
waitForCaretPos(5, function() {
ok(true, "The editor location is correct (2).");
testHighlight3();
});
}
function testHighlight3() {
gSources.highlightBreakpoint(gSources.orderedItems[1].value, 7);
checkHighlight(gSources.orderedItems[1].value, 7);
is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (3).");
is(gEditor.getCaretPosition().line, 5,
"The editor caret line was incorrect (3).");
is(gEditor.getCaretPosition().col, 0,
"The editor caret column was incorrect (3).");
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.querySelectorAll(".dbg-breakpoint")[2],
gDebugger);
waitForCaretPos(6, function() {
ok(true, "The editor location is correct (3).");
testHighlight4();
});
}
function testHighlight4() {
gSources.highlightBreakpoint(gSources.orderedItems[1].value, 8);
checkHighlight(gSources.orderedItems[1].value, 8);
is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (4).");
is(gEditor.getCaretPosition().line, 6,
"The editor caret line was incorrect (4).");
is(gEditor.getCaretPosition().col, 0,
"The editor caret column was incorrect (4).");
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.querySelectorAll(".dbg-breakpoint")[3],
gDebugger);
waitForCaretPos(7, function() {
ok(true, "The editor location is correct (4).");
testHighlight5();
});
}
function testHighlight5() {
gSources.highlightBreakpoint(gSources.orderedItems[1].value, 9);
checkHighlight(gSources.orderedItems[1].value, 9);
is(gSources.selectedValue, gSources.orderedItems[1].value,
"The currently selected source is incorrect (5).");
is(gEditor.getCaretPosition().line, 7,
"The editor caret line was incorrect (5).");
is(gEditor.getCaretPosition().col, 0,
"The editor caret column was incorrect (5).");
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.querySelectorAll(".dbg-breakpoint")[4],
gDebugger);
waitForCaretPos(8, function() {
ok(true, "The editor location is correct (5).");
closeDebuggerAndFinish();
});
}
function checkHighlight(aUrl, aLine) {
is(gSources.selectedBreakpointItem, gSources.getBreakpoint(aUrl, aLine),
"The currently selected breakpoint item is incorrect.");
is(gSources.selectedBreakpointClient, gPane.getBreakpoint(aUrl, aLine),
"The currently selected breakpoint client is incorrect.");
is(gSources.selectedBreakpointItem.attachment.sourceLocation, aUrl,
"The selected breakpoint item's source location attachment is incorrect.");
is(gSources.selectedBreakpointItem.attachment.lineNumber, aLine,
"The selected breakpoint item's source line number is incorrect.");
ok(gSources.selectedBreakpointItem.target.classList.contains("selected"),
"The selected breakpoint item's target should have a selected class.");
}
function waitForCaretPos(number, callback)
{
// Poll every few milliseconds until the source editor line is active.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
if (++count > 50) {
ok(false, "Timed out while polling for the line.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if (gEditor.getCaretPosition().line != number) {
return;
}
// We got the source editor at the expected line, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gSources = null;
});
}

View File

@ -1,301 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 723071: test adding a pane to display the list of breakpoints across
* all scripts in the debuggee.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gEditor = null;
let gSources = null;
let gBreakpoints = null;
let gBreakpointsParent = null;
let gBreakpointsList = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.firstCall();
});
});
function onScriptShown(aEvent)
{
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
let breakpointsAdded = 0;
let breakpointsDisabled = 0;
let breakpointsRemoved = 0;
function performTest()
{
gEditor = gDebugger.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gPane.getAllBreakpoints();
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gSources.itemCount, 2,
"Found the expected number of scripts.");
isnot(gEditor.getText().indexOf("debugger"), -1,
"The correct script was loaded initially.");
isnot(gSources.selectedValue, gSources.values[0],
"The correct script is selected");
is(Object.keys(gBreakpoints).length, 0, "no breakpoints");
ok(!gPane.getBreakpoint("chocolate", 3), "getBreakpoint('chocolate', 3) returns falsey");
is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
gBreakpointsParent = gSources.widget._parent;
gBreakpointsList = gSources.widget._list;
is(gBreakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(gBreakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, 0,
"No breakpoints should be visible at this point.");
addBreakpoints(function() {
is(breakpointsAdded, 3,
"Should have added 3 breakpoints so far.");
is(breakpointsDisabled, 0,
"Shouldn't have disabled anything so far.");
is(breakpointsRemoved, 0,
"Shouldn't have removed anything so far.");
is(gBreakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(gBreakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, 3,
"3 breakpoints should be visible at this point.");
disableBreakpoints(function() {
is(breakpointsAdded, 3,
"Should still have 3 breakpoints added so far.");
is(breakpointsDisabled, 3,
"Should have 3 disabled breakpoints.");
is(breakpointsRemoved, 0,
"Shouldn't have removed anything so far.");
is(gBreakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(gBreakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsAdded,
"Should have the same number of breakpoints in the pane.");
is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsDisabled,
"Should have the same number of disabled breakpoints.");
addBreakpoints(function() {
is(breakpointsAdded, 3,
"Should still have only 3 breakpoints added so far.");
is(breakpointsDisabled, 3,
"Should still have 3 disabled breakpoints.");
is(breakpointsRemoved, 0,
"Shouldn't have removed anything so far.");
is(gBreakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(gBreakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsAdded,
"Since half of the breakpoints already existed, but disabled, " +
"only half of the added breakpoints are actually in the pane.");
removeBreakpoints(function() {
is(breakpointsRemoved, 3,
"Should have 3 removed breakpoints.");
is(gBreakpointsParent.childNodes.length, 1, // one sources list
"Found junk in the breakpoints container.");
is(gBreakpointsList.childNodes.length, 1, // one sources group
"Found junk in the breakpoints container.");
is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, 0,
"No breakpoints should be visible at this point.");
executeSoon(function() {
gDebugger.gClient.addOneTimeListener("resumed", function() {
finalCheck();
closeDebuggerAndFinish();
});
gDebugger.DebuggerController.activeThread.resume();
});
});
});
});
}, true);
function addBreakpoints(callback, increment)
{
let line;
executeSoon(function()
{
line = 6;
gPane.addBreakpoint({url: gSources.selectedValue, line: line},
function(cl, err) {
onBreakpointAdd.call({ increment: increment, line: line }, cl, err);
line = 7;
gPane.addBreakpoint({url: gSources.selectedValue, line: line},
function(cl, err) {
onBreakpointAdd.call({ increment: increment, line: line }, cl, err);
line = 9;
gPane.addBreakpoint({url: gSources.selectedValue, line: line},
function(cl, err) {
onBreakpointAdd.call({ increment: increment, line: line }, cl, err);
executeSoon(function() {
callback();
});
});
});
});
});
}
function disableBreakpoints(callback)
{
let nodes = Array.slice(gBreakpointsList.querySelectorAll(".dbg-breakpoint"));
info("Nodes to disable: " + breakpointsAdded);
is(nodes.length, breakpointsAdded,
"The number of nodes to disable is incorrect.");
Array.forEach(nodes, function(bkp) {
info("Disabling breakpoint: " + bkp.id);
let sourceItem = gSources.getItemForElement(bkp);
let breakpointItem = gSources.getItemForElement.call(sourceItem, bkp);
let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
info("Found data: " + breakpointItem.attachment.toSource());
gSources.disableBreakpoint(url, line, { callback: function() {
if (++breakpointsDisabled !== breakpointsAdded) {
return;
}
executeSoon(function() {
callback();
});
}});
});
}
function removeBreakpoints(callback)
{
let nodes = Array.slice(gBreakpointsList.querySelectorAll(".dbg-breakpoint"));
info("Nodes to remove: " + breakpointsAdded);
is(nodes.length, breakpointsAdded,
"The number of nodes to remove is incorrect.");
Array.forEach(nodes, function(bkp) {
info("Removing breakpoint: " + bkp.id);
let sourceItem = gSources.getItemForElement(bkp);
let breakpointItem = gSources.getItemForElement.call(sourceItem, bkp);
let { sourceLocation: url, lineNumber: line } = breakpointItem.attachment;
info("Found data: " + breakpointItem.attachment.toSource());
gPane.removeBreakpoint(gPane.getBreakpoint(url, line), function() {
if (++breakpointsRemoved !== breakpointsAdded) {
return;
}
executeSoon(function() {
callback();
});
});
});
}
function onBreakpointAdd(aBreakpointClient, aResponseError)
{
if (this.increment) {
breakpointsAdded++;
}
is(gBreakpointsList.querySelectorAll(".dbg-breakpoint").length, breakpointsAdded,
this.increment ? "Should have added a breakpoint in the pane."
: "Should have the same number of breakpoints in the pane.");
let id = "breakpoint-" + aBreakpointClient.actor;
let bkp = gDebugger.document.getElementById(id);
let line = bkp.getElementsByClassName("dbg-breakpoint-line")[0];
let text = bkp.getElementsByClassName("dbg-breakpoint-text")[0];
let check = bkp.querySelector("checkbox");
is(bkp.id, id,
"Breakpoint element " + id + " found successfully.");
is(line.getAttribute("value"), this.line,
"The expected information wasn't found in the breakpoint element.");
is(text.getAttribute("value"), gDebugger.DebuggerView.getEditorLineText(this.line - 1).trim(),
"The expected line text wasn't found in the breakpoint element.");
is(check.getAttribute("checked"), "true",
"The breakpoint enable checkbox is checked as expected.");
}
}
function finalCheck() {
is(Object.keys(gBreakpoints).length, 0, "no breakpoint in the debugger");
ok(!gPane.getBreakpoint(gSources.values[0], 5),
"getBreakpoint(locations[0], 5) returns no breakpoint");
}
registerCleanupFunction(function() {
is(breakpointsAdded, 3, "correct number of breakpoints have been added");
is(breakpointsDisabled, 3, "correct number of breakpoints have been disabled");
is(breakpointsRemoved, 3, "correct number of breakpoints have been removed");
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gSources = null;
gBreakpoints = null;
gBreakpointsParent = null;
gBreakpointsList = null;
});
}

View File

@ -1,241 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 727429: test the debugger watch expressions.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_watch-expressions.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gWatch = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gWatch = gDebugger.DebuggerView.WatchExpressions;
gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
performTest();
});
function performTest()
{
is(gWatch.getAllStrings().length, 0,
"There should initially be no watch expressions");
addAndCheckExpressions(1, 0, "a");
addAndCheckExpressions(2, 0, "b");
addAndCheckExpressions(3, 0, "c");
removeAndCheckExpression(2, 1, "a");
removeAndCheckExpression(1, 0, "a");
addAndCheckExpressions(2, 0, "", true);
gDebugger.editor.focus();
is(gWatch.getAllStrings().length, 1,
"Empty watch expressions are automatically removed");
addAndCheckExpressions(2, 0, "a", true);
gDebugger.editor.focus();
is(gWatch.getAllStrings().length, 1,
"Duplicate watch expressions are automatically removed");
addAndCheckExpressions(2, 0, "a\t", true);
addAndCheckExpressions(2, 0, "a\r", true);
addAndCheckExpressions(2, 0, "a\n", true);
gDebugger.editor.focus();
is(gWatch.getAllStrings().length, 1,
"Duplicate watch expressions are automatically removed");
addAndCheckExpressions(2, 0, "\ta", true);
addAndCheckExpressions(2, 0, "\ra", true);
addAndCheckExpressions(2, 0, "\na", true);
gDebugger.editor.focus();
is(gWatch.getAllStrings().length, 1,
"Duplicate watch expressions are automatically removed");
addAndCheckCustomExpression(2, 0, "bazΩΩka");
addAndCheckCustomExpression(3, 0, "bambøøcha");
EventUtils.sendMouseEvent({ type: "click" },
gWatch.getItemAtIndex(0).attachment.closeNode,
gDebugger);
is(gWatch.getAllStrings().length, 2,
"Watch expressions are removed when the close button is pressed");
is(gWatch.getAllStrings()[0], "bazΩΩka",
"The expression at index " + 0 + " should be correct (1)");
is(gWatch.getAllStrings()[1], "a",
"The expression at index " + 1 + " should be correct (2)");
EventUtils.sendMouseEvent({ type: "click" },
gWatch.getItemAtIndex(0).attachment.closeNode,
gDebugger);
is(gWatch.getAllStrings().length, 1,
"Watch expressions are removed when the close button is pressed");
is(gWatch.getAllStrings()[0], "a",
"The expression at index " + 0 + " should be correct (3)");
EventUtils.sendMouseEvent({ type: "click" },
gWatch.getItemAtIndex(0).attachment.closeNode,
gDebugger);
is(gWatch.getAllStrings().length, 0,
"Watch expressions are removed when the close button is pressed");
EventUtils.sendMouseEvent({ type: "click" },
gWatch.widget._parent,
gDebugger);
is(gWatch.getAllStrings().length, 1,
"Watch expressions are added when the view container is pressed");
closeDebuggerAndFinish();
}
function addAndCheckCustomExpression(total, index, string, noBlur) {
addAndCheckExpressions(total, index, "", true);
for (let i = 0; i < string.length; i++) {
EventUtils.sendChar(string[i], gDebugger);
}
gDebugger.editor.focus();
let element = gWatch.getItemAtIndex(index).target;
is(gWatch.getItemAtIndex(index).attachment.initialExpression, "",
"The initial expression at index " + index + " should be correct (1)");
is(gWatch.getItemForElement(element).attachment.initialExpression, "",
"The initial expression at index " + index + " should be correct (2)");
is(gWatch.getItemAtIndex(index).attachment.currentExpression, string,
"The expression at index " + index + " should be correct (1)");
is(gWatch.getItemForElement(element).attachment.currentExpression, string,
"The expression at index " + index + " should be correct (2)");
is(gWatch.getString(index), string,
"The expression at index " + index + " should be correct (3)");
is(gWatch.getAllStrings()[index], string,
"The expression at index " + index + " should be correct (4)");
}
function addAndCheckExpressions(total, index, string, noBlur) {
gWatch.addExpression(string);
is(gWatch.getAllStrings().length, total,
"There should be " + total + " watch expressions available (1)");
is(gWatch.itemCount, total,
"There should be " + total + " watch expressions available (2)");
ok(gWatch.getItemAtIndex(index),
"The expression at index " + index + " should be available");
is(gWatch.getItemAtIndex(index).attachment.initialExpression, string,
"The expression at index " + index + " should have an initial expression");
let element = gWatch.getItemAtIndex(index).target;
ok(element,
"There should be a new expression item in the view");
ok(gWatch.getItemForElement(element),
"The watch expression item should be accessible");
is(gWatch.getItemForElement(element), gWatch.getItemAtIndex(index),
"The correct watch expression item was accessed");
ok(gWatch.widget.getItemAtIndex(index) instanceof XULElement,
"The correct watch expression element was accessed (1)");
is(element, gWatch.widget.getItemAtIndex(index),
"The correct watch expression element was accessed (2)");
is(gWatch.getItemForElement(element).attachment.arrowNode.hidden, false,
"The arrow node should be visible");
is(gWatch.getItemForElement(element).attachment.closeNode.hidden, false,
"The close button should be visible");
is(gWatch.getItemForElement(element).attachment.inputNode.getAttribute("focused"), "true",
"The textbox input should be focused");
is(gDebugger.DebuggerView.Variables.parentNode.scrollTop, 0,
"The variables view should be scrolled to top");
is(gWatch.orderedItems[0], gWatch.getItemAtIndex(index),
"The correct watch expression was added to the cache (1)");
is(gWatch.orderedItems[0], gWatch.getItemForElement(element),
"The correct watch expression was added to the cache (2)");
if (!noBlur) {
gDebugger.editor.focus();
is(gWatch.getItemAtIndex(index).attachment.initialExpression, string,
"The initial expression at index " + index + " should be correct (1)");
is(gWatch.getItemForElement(element).attachment.initialExpression, string,
"The initial expression at index " + index + " should be correct (2)");
is(gWatch.getItemAtIndex(index).attachment.currentExpression, string,
"The expression at index " + index + " should be correct (1)");
is(gWatch.getItemForElement(element).attachment.currentExpression, string,
"The expression at index " + index + " should be correct (2)");
is(gWatch.getString(index), string,
"The expression at index " + index + " should be correct (3)");
is(gWatch.getAllStrings()[index], string,
"The expression at index " + index + " should be correct (4)");
}
}
function removeAndCheckExpression(total, index, string) {
gWatch.removeAt(index);
is(gWatch.getAllStrings().length, total,
"There should be " + total + " watch expressions available (1)");
is(gWatch.itemCount, total,
"There should be " + total + " watch expressions available (2)");
ok(gWatch.getItemAtIndex(index),
"The expression at index " + index + " should still be available");
is(gWatch.getItemAtIndex(index).attachment.initialExpression, string,
"The expression at index " + index + " should still have an initial expression");
let element = gWatch.getItemAtIndex(index).target;
is(gWatch.getItemAtIndex(index).attachment.initialExpression, string,
"The initial expression at index " + index + " should be correct (1)");
is(gWatch.getItemForElement(element).attachment.initialExpression, string,
"The initial expression at index " + index + " should be correct (2)");
is(gWatch.getItemAtIndex(index).attachment.currentExpression, string,
"The expression at index " + index + " should be correct (1)");
is(gWatch.getItemForElement(element).attachment.currentExpression, string,
"The expression at index " + index + " should be correct (2)");
is(gWatch.getString(index), string,
"The expression at index " + index + " should be correct (3)");
is(gWatch.getAllStrings()[index], string,
"The expression at index " + index + " should be correct (4)");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gWatch = null;
});
}

View File

@ -1,127 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 731394: test the debugger source editor default context menu.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
function test()
{
let contextMenu = null;
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.addEventListener("Debugger:SourceShown", onSourceShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded",
onFramesAdded);
executeSoon(function() {
gDebuggee.firstCall();
});
});
function onFramesAdded(aEvent) {
framesAdded = true;
executeSoon(startTest);
}
function onSourceShown(aEvent) {
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
testStarted = true;
gDebugger.removeEventListener("Debugger:SourceShown", onSourceShown);
executeSoon(performTest);
}
}
function performTest()
{
let scripts = gDebugger.DebuggerView.Sources;
let editor = gDebugger.editor;
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(scripts.itemCount, 2,
"Found the expected number of scripts.");
isnot(editor.getText().indexOf("debugger"), -1,
"The correct script was loaded initially.");
isnot(editor.getText().indexOf("\u263a"), -1,
"Unicode characters are converted correctly.");
contextMenu = gDebugger.document.getElementById("sourceEditorContextMenu");
ok(contextMenu, "source editor context menupopup");
ok(editor.readOnly, "editor is read only");
editor.focus();
editor.setSelection(0, 10);
contextMenu.addEventListener("popupshown", function onPopupShown() {
contextMenu.removeEventListener("popupshown", onPopupShown, false);
executeSoon(testContextMenu);
}, false);
contextMenu.openPopup(editor.editorElement, "overlap", 0, 0, true, false);
}
function testContextMenu()
{
let document = gDebugger.document;
ok(document.getElementById("editMenuCommands"),
"#editMenuCommands found");
ok(!document.getElementById("editMenuKeys"),
"#editMenuKeys not found");
ok(document.getElementById("sourceEditorCommands"),
"#sourceEditorCommands found");
// Map command ids to their expected disabled state.
let commands = {"se-cmd-undo": true, "se-cmd-redo": true,
"se-cmd-cut": true, "se-cmd-paste": true,
"se-cmd-delete": true, "cmd_findAgain": true,
"cmd_findPrevious": true, "cmd_find": false,
"cmd_gotoLine": false, "cmd_copy": false,
"se-cmd-selectAll": false};
for (let id in commands) {
is(document.getElementById(id).hasAttribute("disabled"), commands[id],
id + " hasAttribute('disabled') check");
}
executeSoon(function() {
contextMenu.hidePopup();
closeDebuggerAndFinish();
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});
}

View File

@ -1,121 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 737803: Setting a breakpoint in a line without code should move
* the icon to the actual location.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gSources = null;
let gEditor = null;
let gBreakpoints = null;
function test() {
let scriptShown = false;
let framesAdded = false;
let testStarted = false;
let resumed = false;
debug_tab_pane(TAB_URL, function (aTab, aDebuggee, aPane) {
gTab = aTab;
gPane = aPane;
gDebuggee = aDebuggee;
gDebugger = gPane.panelWin;
resumed = true;
gDebugger.addEventListener("Debugger:SourceShown", onSourceShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function () {
framesAdded = true;
executeSoon(startTest);
});
executeSoon(function () {
gDebuggee.firstCall();
});
});
function onSourceShown(aEvent) {
scriptShown = aEvent.detail.url.indexOf("-02.js") != -1;
executeSoon(startTest);
}
function startTest() {
if (scriptShown && framesAdded && resumed && !testStarted) {
gDebugger.removeEventListener("Debugger:SourceShown", onSourceShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function performTest() {
gSources = gDebugger.DebuggerView.Sources;
gEditor = gDebugger.editor;
gBreakpoints = gPane.getAllBreakpoints();
is(Object.keys(gBreakpoints), 0, "There are no breakpoints");
gEditor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
onEditorBreakpointAdd);
let location = { url: gSources.selectedValue, line: 4 };
executeSoon(function () {
gPane.addBreakpoint(location, onBreakpointAdd);
});
}
let onBpDebuggerAdd = false;
let onBpEditorAdd = false;
function onBreakpointAdd(aBpClient) {
is(aBpClient.location.url, gSources.selectedValue, "URL is the same");
is(aBpClient.location.line, 6, "Line number is new");
is(aBpClient.requestedLocation.line, 4, "Requested location is correct");
onBpDebuggerAdd = true;
tryFinish();
}
function onEditorBreakpointAdd(aEvent) {
gEditor.removeEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE,
onEditorBreakpointAdd);
is(gEditor.getBreakpoints().length, 1,
"There is only one breakpoint in the editor");
ok(!gPane.getBreakpoint(gSources.selectedValue, 4),
"There are no breakpoints on an invalid line");
let br = gPane.getBreakpoint(gSources.selectedValue, 6);
is(br.location.url, gSources.selectedValue, "URL is correct");
is(br.location.line, 6, "Line number is correct");
onBpEditorAdd = true;
tryFinish();
}
function tryFinish() {
info("onBpDebuggerAdd: " + onBpDebuggerAdd);
info("onBpEditorAdd: " + onBpEditorAdd);
if (onBpDebuggerAdd && onBpEditorAdd) {
closeDebuggerAndFinish();
}
}
registerCleanupFunction(function () {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gSources = null;
gEditor = null;
gBreakpoints = null;
});
}

View File

@ -1,393 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 740825: test the debugger conditional breakpoints.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_conditional-breakpoints.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gEditor = null;
let gSources = null;
let gBreakpoints = null;
requestLongerTimeout(2);
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
resumed = true;
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.ermahgerd(); // ermahgerd!!
});
});
function onScriptShown(aEvent)
{
scriptShown = aEvent.detail.url.indexOf("conditional-breakpoints") != -1;
executeSoon(startTest);
}
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: addBreakpoints }, 0);
}
}
function performTest()
{
gEditor = gDebugger.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gPane.getAllBreakpoints();
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gSources.itemCount, 1,
"Found the expected number of scripts.");
isnot(gEditor.getText().indexOf("ermahgerd"), -1,
"The correct script was loaded initially.");
is(gSources.selectedValue, gSources.values[0],
"The correct script is selected");
is(Object.keys(gBreakpoints).length, 13, "thirteen breakpoints");
ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
is(gEditor.getBreakpoints().length, 13, "thirteen breakpoints in the editor");
executeSoon(test1);
}
function test1(callback)
{
resumeAndTestBreakpoint(gSources.selectedValue, 14, test2);
}
function test2(callback)
{
resumeAndTestBreakpoint(gSources.selectedValue, 15, test3);
}
function test3(callback)
{
resumeAndTestBreakpoint(gSources.selectedValue, 16, test4);
}
function test4(callback)
{
resumeAndTestBreakpoint(gSources.selectedValue, 17, test5);
}
function test5(callback)
{
resumeAndTestBreakpoint(gSources.selectedValue, 18, test6);
}
function test6(callback)
{
resumeAndTestBreakpoint(gSources.selectedValue, 19, test7);
}
function test7(callback)
{
resumeAndTestBreakpoint(gSources.selectedValue, 21, test8);
}
function test8(callback)
{
resumeAndTestBreakpoint(gSources.selectedValue, 22, test9);
}
function test9(callback)
{
resumeAndTestBreakpoint(gSources.selectedValue, 23, test10);
}
function test10(callback)
{
gDebugger.addEventListener("Debugger:AfterFramesCleared", function listener() {
gDebugger.removeEventListener("Debugger:AfterFramesCleared", listener, true);
isnot(gSources.selectedItem, null,
"There should be a selected script in the scripts pane.")
is(gSources.selectedBreakpointItem, null,
"There should be no selected breakpoint in the scripts pane.")
is(gSources.selectedBreakpointClient, null,
"There should be no selected client in the scripts pane.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
is(gDebugger.DebuggerView.StackFrames.widget._list.querySelectorAll(".dbg-stackframe").length, 0,
"There should be no visible stackframes.");
is(gDebugger.DebuggerView.Sources.widget._list.querySelectorAll(".dbg-breakpoint").length, 13,
"There should be thirteen visible breakpoints.");
testReload();
}, true);
gDebugger.DebuggerController.activeThread.resume();
}
function resumeAndTestBreakpoint(url, line, callback)
{
resume(line, function() {
waitForCaretPos(line - 1, function() {
testBreakpoint(gSources.selectedBreakpointItem, gSources.selectedBreakpointClient, url, line, true);
callback();
});
});
}
function testBreakpoint(aBreakpointItem, aBreakpointClient, url, line, editor)
{
is(aBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
"The breakpoint on line " + line + " wasn't added on the correct source.");
is(aBreakpointItem.attachment.lineNumber, line,
"The breakpoint on line " + line + " wasn't found.");
is(!!aBreakpointItem.attachment.disabled, false,
"The breakpoint on line " + line + " should be enabled.");
is(!!aBreakpointItem.attachment.openPopupFlag, false,
"The breakpoint on line " + line + " should not open a popup.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
is(aBreakpointClient.location.url, url,
"The breakpoint's client url is correct");
is(aBreakpointClient.location.line, line,
"The breakpoint's client line is correct");
isnot(aBreakpointClient.conditionalExpression, undefined,
"The breakpoint on line " + line + " should have a conditional expression.");
if (editor) {
is(gEditor.getCaretPosition().line + 1, line,
"The editor caret position is not situated on the proper line.");
is(gEditor.getCaretPosition().col, 0,
"The editor caret position is not situated on the proper column.");
}
}
function addBreakpoints(callback)
{
let currentUrl = gDebugger.DebuggerView.Sources.selectedValue;
gPane.addBreakpoint({ url: currentUrl, line: 12 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 13 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 14 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 15 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 16 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 17 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 18 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 19 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 20 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 21 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 22 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 23 }, function() {
gPane.addBreakpoint({ url: currentUrl, line: 24 }, function() {
performTest();
}, {
conditionalExpression: "b"
});
}, {
conditionalExpression: "a !== null"
});
}, {
conditionalExpression: "a !== undefined"
});
}, {
conditionalExpression: "a"
});
}, {
conditionalExpression: "(function() { return false; })()"
});
}, {
conditionalExpression: "(function() {})"
});
}, {
conditionalExpression: "({})"
});
}, {
conditionalExpression: "/regexp/"
});
}, {
conditionalExpression: "'nasu'"
});
}, {
conditionalExpression: "true"
});
}, {
conditionalExpression: "42"
});
}, {
conditionalExpression: "null"
});
}, {
conditionalExpression: "undefined"
});
}
function testReload()
{
info("Testing reload...");
function _get(url, line) {
return [
gDebugger.DebuggerView.Sources.getBreakpoint(url, line),
gDebugger.DebuggerController.Breakpoints.getBreakpoint(url, line),
url,
line,
];
}
gDebugger.addEventListener("Debugger:SourceShown", function _onSourceShown() {
gDebugger.removeEventListener("Debugger:SourceShown", _onSourceShown);
waitForBreakpoints(13, function() {
testBreakpoint.apply(this, _get(gSources.selectedValue, 14));
testBreakpoint.apply(this, _get(gSources.selectedValue, 15));
testBreakpoint.apply(this, _get(gSources.selectedValue, 16));
testBreakpoint.apply(this, _get(gSources.selectedValue, 17));
testBreakpoint.apply(this, _get(gSources.selectedValue, 18));
testBreakpoint.apply(this, _get(gSources.selectedValue, 19));
testBreakpoint.apply(this, _get(gSources.selectedValue, 21));
testBreakpoint.apply(this, _get(gSources.selectedValue, 22));
testBreakpoint.apply(this, _get(gSources.selectedValue, 23));
isnot(gSources.selectedItem, null,
"There should be a selected script in the scripts pane.")
is(gSources.selectedBreakpointItem, null,
"There should be no selected breakpoint in the scripts pane.")
is(gSources.selectedBreakpointClient, null,
"There should be no selected client in the scripts pane.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
closeDebuggerAndFinish();
});
});
finalCheck();
gDebugger.DebuggerController.client.activeTab.reload();
}
function finalCheck() {
isnot(gEditor.getText().indexOf("ermahgerd"), -1,
"The correct script is still loaded.");
is(gSources.selectedValue, gSources.values[0],
"The correct script is still selected");
}
function resume(expected, callback) {
gDebugger.DebuggerController.activeThread.addOneTimeListener("resumed", function() {
waitForBreakpoint(expected, callback);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
let bogusClient = {
location: {
url: null,
line: null
}
};
function waitForBreakpoint(expected, callback) {
// Poll every few milliseconds until expected breakpoint is hit.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
if (++count > 50) {
ok(false, "Timed out while polling for the breakpoint.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if ((gSources.selectedBreakpointClient !== expected) &&
(gSources.selectedBreakpointClient || bogusClient).location.line !== expected) {
return;
}
// We arrived at the expected line, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
function waitForBreakpoints(total, callback)
{
// Poll every few milliseconds until the breakpoints are retrieved.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
if (++count > 50) {
ok(false, "Timed out while polling for the breakpoints.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if (gSources.widget._list.querySelectorAll(".dbg-breakpoint").length != total) {
return;
}
// We got all the breakpoints, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
function waitForCaretPos(number, callback)
{
// Poll every few milliseconds until the source editor line is active.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
if (++count > 50) {
ok(false, "Timed out while polling for the line.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if (gEditor.getCaretPosition().line != number) {
return;
}
// We got the source editor at the expected line, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gSources = null;
gBreakpoints = null;
});
}

View File

@ -1,583 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 740825: test the debugger conditional breakpoints.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_conditional-breakpoints.html";
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gEditor = null;
let gSources = null;
let gBreakpoints = null;
requestLongerTimeout(2);
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebugger.addEventListener("Debugger:SourceShown", onScriptShown);
gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
resumed = true;
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
executeSoon(startTest);
});
executeSoon(function() {
gDebuggee.ermahgerd(); // ermahgerd!!
});
});
function onScriptShown(aEvent)
{
scriptShown = aEvent.detail.url.indexOf("conditional-breakpoints") != -1;
executeSoon(startTest);
}
function startTest()
{
if (scriptShown && framesAdded && resumed && !testStarted) {
gDebugger.removeEventListener("Debugger:SourceShown", onScriptShown);
testStarted = true;
Services.tm.currentThread.dispatch({ run: performTest }, 0);
}
}
function performTest()
{
gEditor = gDebugger.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gPane.getAllBreakpoints();
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(gSources.itemCount, 1,
"Found the expected number of scripts.");
isnot(gEditor.getText().indexOf("ermahgerd"), -1,
"The correct script was loaded initially.");
is(gSources.selectedValue, gSources.values[0],
"The correct script is selected");
is(Object.keys(gBreakpoints), 0, "no breakpoints");
ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
is(gEditor.getBreakpoints().length, 0, "no breakpoints in the editor");
executeSoon(addBreakpoint1);
}
function addBreakpoint1()
{
gPane.addBreakpoint({ url: gSources.selectedValue, line: 12 });
waitForBreakpoint(12, function() {
waitForCaretPos(10, function() {
waitForPopup(false, function() {
testBreakpoint(gSources.selectedBreakpointItem,
gSources.selectedBreakpointClient,
gSources.selectedValue, 12, false, false, false);
executeSoon(addBreakpoint2);
});
});
});
}
function addBreakpoint2()
{
gSources._editorContextMenuLineNumber = 12;
gSources._onCmdAddBreakpoint();
waitForBreakpoint(13, function() {
waitForCaretPos(12, function() {
waitForPopup(false, function() {
testBreakpoint(gSources.selectedBreakpointItem,
gSources.selectedBreakpointClient,
gSources.selectedValue, 13, false, false, true);
executeSoon(modBreakpoint2);
});
});
});
}
function modBreakpoint2()
{
gSources._editorContextMenuLineNumber = 12;
gSources._onCmdAddConditionalBreakpoint();
waitForBreakpoint(13, function() {
waitForCaretPos(12, function() {
waitForPopup(true, function() {
testBreakpoint(gSources.selectedBreakpointItem,
gSources.selectedBreakpointClient,
gSources.selectedValue, 13, true, true, true);
executeSoon(addBreakpoint3);
});
});
});
}
function addBreakpoint3()
{
gSources._editorContextMenuLineNumber = 13;
gSources._onCmdAddConditionalBreakpoint();
waitForBreakpoint(14, function() {
waitForCaretPos(13, function() {
waitForPopup(true, function() {
testBreakpoint(gSources.selectedBreakpointItem,
gSources.selectedBreakpointClient,
gSources.selectedValue, 14, true, true, true);
executeSoon(modBreakpoint3);
});
});
});
}
function modBreakpoint3()
{
write("bamboocha");
EventUtils.sendKey("RETURN", gDebugger);
waitForBreakpoint(14, function() {
waitForCaretPos(13, function() {
waitForPopup(false, function() {
is(gSources.selectedBreakpointClient.conditionalExpression, "bamboocha",
"The bamboocha expression wasn't fonud on the conditional breakpoint");
executeSoon(setContextMenu);
});
});
});
}
function setContextMenu()
{
let contextMenu = gDebugger.document.getElementById("sourceEditorContextMenu");
info("Testing source editor popup...");
contextMenu.addEventListener("popupshown", function onPopupShown() {
contextMenu.removeEventListener("popupshown", onPopupShown, false);
info("Source editor popup shown...");
contextMenu.addEventListener("popuphidden", function onPopupHidden() {
contextMenu.removeEventListener("popuphidden", onPopupHidden, false);
info("Source editor popup hidden...");
is(gSources._editorContextMenuLineNumber, 14,
"The context menu line number is incorrect after the popup was hidden.");
executeSoon(addBreakpoint4);
}, false);
is(gSources._editorContextMenuLineNumber, 14,
"The context menu line number is incorrect after the popup was shown.");
contextMenu.hidePopup();
}, false);
is(gSources._editorContextMenuLineNumber, -1,
"The context menu line number was incorrect before the popup was shown.");
gSources._editorContextMenuLineNumber = 14;
contextMenu.openPopup(gEditor.editorElement, "overlap", 0, 0, true, false);
}
function addBreakpoint4()
{
gEditor.setCaretPosition(14);
gSources._onCmdAddBreakpoint();
waitForBreakpoint(15, function() {
waitForCaretPos(14, function() {
waitForPopup(false, function() {
testBreakpoint(gSources.selectedBreakpointItem,
gSources.selectedBreakpointClient,
gSources.selectedValue, 15, false, false, true);
executeSoon(delBreakpoint4);
});
});
});
}
function delBreakpoint4()
{
gEditor.setCaretPosition(14);
gSources._onCmdAddBreakpoint();
waitForBreakpoint(null, function() {
waitForCaretPos(14, function() {
waitForPopup(false, function() {
is(gSources.selectedBreakpointItem, null,
"There should be no selected breakpoint in the breakpoints pane.")
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
executeSoon(moveHighlight1);
});
});
});
}
function moveHighlight1()
{
gEditor.setCaretPosition(13);
waitForBreakpoint(14, function() {
waitForCaretPos(13, function() {
waitForPopup(false, function() {
testBreakpoint(gSources.selectedBreakpointItem,
gSources.selectedBreakpointClient,
gSources.selectedValue, 14, false, true, true);
executeSoon(testHighlights1);
});
});
});
}
function testHighlights1()
{
isnot(gSources.selectedBreakpointItem, null,
"There should be a selected breakpoint in the breakpoints pane.");
is(gSources.selectedBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
"The selected breakpoint should have the correct location.");
is(gSources.selectedBreakpointItem.attachment.lineNumber, 14,
"The selected breakpoint should have the correct line number.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
is(gEditor.getCaretPosition().line, 13,
"The source editor caret position should be at line 13");
is(gEditor.getCaretPosition().col, 0,
"The source editor caret position should be at column 0");
gEditor.setCaretPosition(12);
waitForCaretPos(12, function() {
waitForPopup(false, function() {
isnot(gSources.selectedBreakpointItem, null,
"There should be a selected breakpoint in the breakpoints pane.");
is(gSources.selectedBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
"The selected breakpoint should have the correct location.");
is(gSources.selectedBreakpointItem.attachment.lineNumber, 13,
"The selected breakpoint should have the correct line number.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
is(gEditor.getCaretPosition().line, 12,
"The source editor caret position should be at line 12");
is(gEditor.getCaretPosition().col, 0,
"The source editor caret position should be at column 0");
gEditor.setCaretPosition(11);
waitForCaretPos(11, function() {
waitForPopup(false, function() {
isnot(gSources.selectedBreakpointItem, null,
"There should be a selected breakpoint in the breakpoints pane.");
is(gSources.selectedBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
"The selected breakpoint should have the correct location.");
is(gSources.selectedBreakpointItem.attachment.lineNumber, 12,
"The selected breakpoint should have the correct line number.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
is(gEditor.getCaretPosition().line, 11,
"The source editor caret position should be at line 11");
is(gEditor.getCaretPosition().col, 0,
"The source editor caret position should be at column 0");
gEditor.setCaretPosition(10);
waitForCaretPos(10, function() {
waitForPopup(false, function() {
is(gSources.selectedBreakpointItem, null,
"There should not be a selected breakpoint in the breakpoints pane.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
is(gEditor.getCaretPosition().line, 10,
"The source editor caret position should be at line 10");
is(gEditor.getCaretPosition().col, 0,
"The source editor caret position should be at column 0");
gEditor.setCaretPosition(14);
waitForCaretPos(14, function() {
waitForPopup(false, function() {
is(gSources.selectedBreakpointItem, null,
"There should not be a selected breakpoint in the breakpoints pane.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
is(gEditor.getCaretPosition().line, 14,
"The source editor caret position should be at line 14");
is(gEditor.getCaretPosition().col, 0,
"The source editor caret position should be at column 0");
executeSoon(testHighlights2);
});
});
});
});
});
});
});
});
}
function testHighlights2()
{
EventUtils.sendMouseEvent({ type: "click" },
gSources.widget._list.querySelectorAll(".dbg-breakpoint")[2],
gDebugger);
waitForCaretPos(13, function() {
waitForPopup(true, function() {
isnot(gSources.selectedBreakpointItem, null,
"There should be a selected breakpoint in the breakpoints pane.");
is(gSources.selectedBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
"The selected breakpoint should have the correct location.");
is(gSources.selectedBreakpointItem.attachment.lineNumber, 14,
"The selected breakpoint should have the correct line number.");
is(gSources._conditionalPopupVisible, true,
"The breakpoint conditional expression popup should be shown.");
is(gEditor.getCaretPosition().line, 13,
"The source editor caret position should be at line 13");
is(gEditor.getCaretPosition().col, 0,
"The source editor caret position should be at column 0");
EventUtils.sendMouseEvent({ type: "click" },
gSources.widget._list.querySelectorAll(".dbg-breakpoint")[1],
gDebugger);
waitForCaretPos(12, function() {
waitForPopup(true, function() {
isnot(gSources.selectedBreakpointItem, null,
"There should be a selected breakpoint in the breakpoints pane.");
is(gSources.selectedBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
"The selected breakpoint should have the correct location.");
is(gSources.selectedBreakpointItem.attachment.lineNumber, 13,
"The selected breakpoint should have the correct line number.");
is(gSources._conditionalPopupVisible, true,
"The breakpoint conditional expression popup should be shown.");
is(gEditor.getCaretPosition().line, 12,
"The source editor caret position should be at line 12");
is(gEditor.getCaretPosition().col, 0,
"The source editor caret position should be at column 0");
EventUtils.sendMouseEvent({ type: "click" },
gSources.widget._list.querySelectorAll(".dbg-breakpoint")[0],
gDebugger);
waitForCaretPos(11, function() {
waitForPopup(false, function() {
isnot(gSources.selectedBreakpointItem, null,
"There should be a selected breakpoint in the breakpoints pane.");
is(gSources.selectedBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
"The selected breakpoint should have the correct location.");
is(gSources.selectedBreakpointItem.attachment.lineNumber, 12,
"The selected breakpoint should have the correct line number.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should be shown.");
is(gEditor.getCaretPosition().line, 11,
"The source editor caret position should be at line 11");
is(gEditor.getCaretPosition().col, 0,
"The source editor caret position should be at column 0");
executeSoon(delBreakpoint2);
});
});
});
});
});
});
}
function delBreakpoint2()
{
gSources._editorContextMenuLineNumber = 12;
gSources._onCmdAddBreakpoint();
waitForBreakpoint(null, function() {
waitForPopup(false, function() {
is(gSources.selectedBreakpointItem, null,
"There should be no selected breakpoint in the breakpoints pane.")
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
executeSoon(delBreakpoint3);
});
});
}
function delBreakpoint3()
{
gSources._editorContextMenuLineNumber = 13;
gSources._onCmdAddBreakpoint();
waitForBreakpoint(null, function() {
waitForPopup(false, function() {
is(gSources.selectedBreakpointItem, null,
"There should be no selected breakpoint in the breakpoints pane.")
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
executeSoon(testBreakpoints);
});
});
}
function testBreakpoints()
{
is(Object.keys(gBreakpoints).length, 1, "one breakpoint");
ok(!gPane.getBreakpoint("foo", 3), "getBreakpoint('foo', 3) returns falsey");
is(gEditor.getBreakpoints().length, 1, "one breakpoint in the editor");
closeDebuggerAndFinish();
}
function testBreakpoint(aBreakpointItem, aBreakpointClient, url, line, popup, conditional, editor)
{
is(aBreakpointItem.attachment.sourceLocation, gSources.selectedValue,
"The breakpoint on line " + line + " wasn't added on the correct source.");
is(aBreakpointItem.attachment.lineNumber, line,
"The breakpoint on line " + line + " wasn't found.");
is(!aBreakpointItem.attachment.disabled, true,
"The breakpoint on line " + line + " should be enabled.");
is(gSources._conditionalPopupVisible, popup,
"The breakpoint conditional expression popup should " + (popup ? "" : "not ") + "be shown.");
is(aBreakpointClient.location.url, url,
"The breakpoint's client url is correct");
is(aBreakpointClient.location.line, line,
"The breakpoint's client line is correct");
if (conditional) {
isnot(aBreakpointClient.conditionalExpression, undefined,
"The breakpoint on line " + line + " should have a conditional expression.");
} else {
is(aBreakpointClient.conditionalExpression, undefined,
"The breakpoint on line " + line + " should not have a conditional expression.");
}
if (editor) {
is(gEditor.getCaretPosition().line + 1, line,
"The editor caret position is not situated on the proper line.");
is(gEditor.getCaretPosition().col, 0,
"The editor caret position is not situated on the proper column.");
}
}
let bogusClient = {
location: {
url: null,
line: null
}
};
function waitForBreakpoint(expected, callback) {
// Poll every few milliseconds until expected breakpoint is hit.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
if (++count > 50) {
ok(false, "Timed out while polling for the breakpoint.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if ((gSources.selectedBreakpointClient !== expected) &&
(gSources.selectedBreakpointClient || bogusClient).location.line !== expected) {
return;
}
// We arrived at the expected line, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
function waitForCaretPos(number, callback)
{
// Poll every few milliseconds until the source editor line is active.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
if (++count > 50) {
ok(false, "Timed out while polling for the line.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if (gEditor.getCaretPosition().line != number) {
return;
}
// We got the source editor at the expected line, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
function waitForPopup(state, callback)
{
// Poll every few milliseconds until the expression popup is shown.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
if (++count > 50) {
ok(false, "Timed out while polling for the popup.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if (gSources._conditionalPopupVisible != state) {
return;
}
// We got the expression popup at the expected state, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
function clear() {
gSources._cbTextbox.focus();
gSources._cbTextbox.value = "";
}
function write(text) {
clear();
append(text);
}
function append(text) {
gSources._cbTextbox.focus();
for (let i = 0; i < text.length; i++) {
EventUtils.sendChar(text[i], gDebugger);
}
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gSources = null;
gBreakpoints = null;
});
}

View File

@ -1,129 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
function test() {
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
testNonEnumProperties();
});
}
function testNonEnumProperties() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
let testScope = gDebugger.DebuggerView.Variables.addScope("test-scope");
let testVar = testScope.addItem("foo");
testVar.addItems({
foo: {
value: "bar",
enumerable: true
},
bar: {
value: "foo",
enumerable: false
}
});
// Expand the variable.
testScope.expand();
testVar.expand();
executeSoon(function() {
let details = testVar._enum;
let nonenum = testVar._nonenum;
is(details.childNodes.length, 1,
"There should be just one property in the .details container.");
ok(details.hasAttribute("open"),
".details container should be visible.");
ok(nonenum.hasAttribute("open"),
".nonenum container should be visible.");
is(nonenum.childNodes.length, 1,
"There should be just one property in the .nonenum container.");
// Uncheck 'show hidden properties'.
gDebugger.DebuggerView.Options._showVariablesOnlyEnumItem.setAttribute("checked", "true");
gDebugger.DebuggerView.Options._toggleShowVariablesOnlyEnum();
executeSoon(function() {
ok(details.hasAttribute("open"),
".details container should stay visible.");
ok(!nonenum.hasAttribute("open"),
".nonenum container should become hidden.");
// Check 'show hidden properties'.
gDebugger.DebuggerView.Options._showVariablesOnlyEnumItem.setAttribute("checked", "false");
gDebugger.DebuggerView.Options._toggleShowVariablesOnlyEnum();
executeSoon(function() {
ok(details.hasAttribute("open"),
".details container should stay visible.");
ok(nonenum.hasAttribute("open"),
".nonenum container should become visible.");
// Collapse the variable.
testVar.collapse();
executeSoon(function() {
ok(!details.hasAttribute("open"),
".details container should be hidden.");
ok(!nonenum.hasAttribute("open"),
".nonenum container should be hidden.");
// Uncheck 'show hidden properties'.
gDebugger.DebuggerView.Options._showVariablesOnlyEnumItem.setAttribute("checked", "true");
gDebugger.DebuggerView.Options._toggleShowVariablesOnlyEnum();
executeSoon(function() {
ok(!details.hasAttribute("open"),
".details container should stay hidden.");
ok(!nonenum.hasAttribute("open"),
".nonenum container should stay hidden.");
// Check 'show hidden properties'.
gDebugger.DebuggerView.Options._showVariablesOnlyEnumItem.setAttribute("checked", "false");
gDebugger.DebuggerView.Options._toggleShowVariablesOnlyEnum();
executeSoon(function() {
gDebugger.DebuggerController.activeThread.resume(function() {
closeDebuggerAndFinish();
});
});
});
});
});
});
});
}}, 0);
});
gDebuggee.simpleCall();
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

View File

@ -1,78 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that debugger's tab is highlighted when it is paused and not the
// currently selected tool.
var gTab = null;
var gDebugger = null;
var gToolbox = null;
var gToolboxTab = null;
function test() {
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebugger = aPane.panelWin;
gToolbox = aPane._toolbox;
gToolboxTab = gToolbox.doc.getElementById("toolbox-tab-jsdebugger");
testPause();
});
}
function testPause() {
is(gDebugger.DebuggerController.activeThread.paused, false,
"Should be running after debug_tab_pane.");
gDebugger.DebuggerController.activeThread.addOneTimeListener("paused", function() {
Services.tm.currentThread.dispatch({ run: function() {
gToolbox.selectTool("webconsole").then(() => {
ok(gToolboxTab.classList.contains("highlighted"),
"The highlighted class is present");
ok(!gToolboxTab.hasAttribute("selected") ||
gToolboxTab.getAttribute("selected") != "true",
"The tab is not selected");
}).then(() => gToolbox.selectTool("jsdebugger")).then(() => {
ok(gToolboxTab.classList.contains("highlighted"),
"The highlighted class is present");
ok(gToolboxTab.hasAttribute("selected") &&
gToolboxTab.getAttribute("selected") == "true",
"and the tab is selected, so the orange glow will not be present.");
}).then(testResume);
}}, 0);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
function testResume() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("resumed", function() {
Services.tm.currentThread.dispatch({ run: function() {
gToolbox.selectTool("webconsole").then(() => {
ok(!gToolboxTab.classList.contains("highlighted"),
"The highlighted class is not present now after the resume");
ok(!gToolboxTab.hasAttribute("selected") ||
gToolboxTab.getAttribute("selected") != "true",
"The tab is not selected");
}).then(closeDebuggerAndFinish);
}}, 0);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
registerCleanupFunction(function() {
removeTab(gTab);
gTab = null;
gDebugger = null;
gToolbox = null;
gToolboxTab = null;
});

View File

@ -1,134 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that debugger's tab is highlighted when it is paused and not the
// currently selected tool.
var gTab = null;
var gTab2 = null;
var gDebugger = null;
var gToolbox = null;
var gToolboxTab = null;
var gFocusedWindow = null;
promise._reportErrors = true;
function test() {
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebugger = aPane.panelWin;
gToolbox = aPane._toolbox;
gToolboxTab = gToolbox.doc.getElementById("toolbox-tab-jsdebugger");
gBrowser.selectedTab = gTab2 = gBrowser.addTab();
executeSoon(function() {
is(gBrowser.selectedTab, gTab2, "Debugger's tab is not the selected tab.");
gFocusedWindow = window;
testPause();
});
});
}
function focusMainWindow() {
// Make sure toolbox is not focused.
window.addEventListener("focus", onFocus, true);
// execute soon to avoid any race conditions between toolbox and main window
// getting focused.
executeSoon(() => {
window.focus();
});
}
function onFocus() {
window.removeEventListener("focus", onFocus, true);
info("main window focused.")
gFocusedWindow = window;
testPause();
}
function testPause() {
is(gDebugger.DebuggerController.activeThread.paused, false,
"Should be running after debug_tab_pane.");
is(gFocusedWindow, window, "Main window is the top level window before pause");
if (gToolbox.hostType == devtools.Toolbox.HostType.WINDOW) {
gToolbox._host._window.onfocus = () => {
gFocusedWindow = gToolbox._host._window;
};
}
gDebugger.DebuggerController.activeThread.addOneTimeListener("paused", function() {
Services.tm.currentThread.dispatch({ run: function() {
if (gToolbox.hostType == devtools.Toolbox.HostType.WINDOW) {
is(gFocusedWindow, gToolbox._host._window,
"Toolbox window is the top level window on pause.");
}
else {
is(gBrowser.selectedTab, gTab, "Debugger's tab got selected.");
}
gToolbox.selectTool("webconsole").then(() => {
ok(gToolboxTab.classList.contains("highlighted"),
"The highlighted class is present");
ok(!gToolboxTab.hasAttribute("selected") ||
gToolboxTab.getAttribute("selected") != "true",
"The tab is not selected");
}).then(() => gToolbox.selectTool("jsdebugger")).then(() => {
ok(gToolboxTab.classList.contains("highlighted"),
"The highlighted class is present");
ok(gToolboxTab.hasAttribute("selected") &&
gToolboxTab.getAttribute("selected") == "true",
"and the tab is selected, so the orange glow will not be present.");
}).then(testResume);
}}, 0);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
function testResume() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("resumed", function() {
Services.tm.currentThread.dispatch({ run: function() {
gToolbox.selectTool("webconsole").then(() => {
ok(!gToolboxTab.classList.contains("highlighted"),
"The highlighted class is not present now after the resume");
ok(!gToolboxTab.hasAttribute("selected") ||
gToolboxTab.getAttribute("selected") != "true",
"The tab is not selected");
}).then(maybeEndTest);
}}, 0);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
function maybeEndTest() {
if (gToolbox.hostType == devtools.Toolbox.HostType.WINDOW) {
gToolbox.switchHost(devtools.Toolbox.HostType.BOTTOM)
.then(closeDebuggerAndFinish);
}
else {
info("switching to toolbox window.")
gToolbox.switchHost(devtools.Toolbox.HostType.WINDOW).then(focusMainWindow).then(null, console.error);
}
}
registerCleanupFunction(function() {
Services.prefs.setCharPref("devtools.toolbox.host", devtools.Toolbox.HostType.BOTTOM);
removeTab(gTab);
removeTab(gTab2);
gTab = null;
gTab2 = null;
gDebugger = null;
gToolbox = null;
gToolboxTab = null;
gFocusedWindow = null;
});

View File

@ -1,32 +1,26 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that a chrome debugger can be created in a new process.
*/
// Tests that a chrome debugger can be created in a new process.
var gProcess = null;
var gTab = null;
var gDebuggee = null;
let gProcess;
function test() {
// Windows XP test slaves are terribly slow at this test.
requestLongerTimeout(4);
debug_chrome(STACK_URL, aOnClosing, function(aTab, aDebuggee, aProcess) {
gTab = aTab;
gDebuggee = aDebuggee;
initChromeDebugger(aOnClose).then(aProcess => {
gProcess = aProcess;
info("Starting test");
testSimpleCall();
info("Starting test...");
performTest();
});
}
function testSimpleCall() {
function performTest() {
Services.tm.currentThread.dispatch({ run: function() {
ok(gProcess._dbgProcess,
"The remote debugger process wasn't created properly!");
ok(gProcess._dbgProcess.isRunning,
@ -68,7 +62,7 @@ function testSimpleCall() {
}}, 0);
}
function aOnClosing() {
function aOnClose() {
ok(!gProcess._dbgProcess.isRunning,
"The remote debugger process isn't closed as it should be!");
is(gProcess._dbgProcess.exitValue, (Services.appinfo.OS == "WINNT" ? 0 : 256),
@ -80,14 +74,9 @@ function aOnClosing() {
info("profile rootDir: " + gProcess._dbgProfile.rootDir.path);
info("profile name: " + gProcess._dbgProfile.name);
executeSoon(function() {
finish();
});
finish();
}
registerCleanupFunction(function() {
removeTab(gTab);
gProcess = null;
gTab = null;
gDebuggee = null;
});

View File

@ -1,68 +1,92 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that chrome debugging works.
*/
// Tests that chrome debugging works.
const TAB_URL = EXAMPLE_URL + "doc_inline-debugger-statement.html";
var gClient = null;
var gTab = null;
var gMozillaTab = null;
var gThreadClient = null;
var gNewGlobal = false;
var gAttached = false;
var gChromeSource = false;
let gClient, gThreadClient;
let gAttached = promise.defer();
let gNewGlobal = promise.defer()
let gNewChromeSource = promise.defer()
const DEBUGGER_TAB_URL = EXAMPLE_URL + "browser_dbg_debuggerstatement.html";
function test() {
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
function test()
{
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect(function(aType, aTraits) {
gTab = addTab(DEBUGGER_TAB_URL, function() {
gClient.listTabs(function(aResponse) {
let dbg = aResponse.chromeDebugger;
ok(dbg, "Found a chrome debugging actor.");
gClient.connect((aType, aTraits) => {
is(aType, "browser",
"Root actor should identify itself as a browser.");
gClient.addOneTimeListener("newGlobal", function() gNewGlobal = true);
gClient.addListener("newSource", onNewSource);
gClient.attachThread(dbg, function(aResponse, aThreadClient) {
gThreadClient = aThreadClient;
ok(!aResponse.error, "Attached to the chrome debugger.");
gAttached = true;
// Ensure that a new global will be created.
gMozillaTab = gBrowser.addTab("about:mozilla");
finish_test();
});
promise.all([gAttached.promise, gNewGlobal.promise, gNewChromeSource.promise])
.then(resumeAndCloseConnection)
.then(finish)
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
testChromeActor();
});
}
function testChromeActor() {
gClient.listTabs(aResponse => {
ok(aResponse.chromeDebugger.contains("chromeDebugger"),
"Chrome debugger actor should identify itself accordingly.");
gClient.addListener("newGlobal", onNewGlobal);
gClient.addListener("newSource", onNewSource);
gClient.attachThread(aResponse.chromeDebugger, (aResponse, aThreadClient) => {
gThreadClient = aThreadClient;
if (aResponse.error) {
ok(false, "Couldn't attach to the chrome debugger.");
gAttached.reject();
} else {
ok(true, "Attached to the chrome debugger.");
gAttached.resolve();
// Ensure that a new chrome global will be created.
gBrowser.selectedTab = gBrowser.addTab("about:mozilla");
}
});
});
}
function onNewSource(aEvent, aPacket)
{
gChromeSource = aPacket.source.url.startsWith("chrome:");
finish_test();
function onNewGlobal() {
ok(true, "Received a new chrome global.");
gClient.removeListener("newGlobal", onNewGlobal);
gNewGlobal.resolve();
}
function finish_test()
{
if (!gAttached || !gChromeSource) {
return;
function onNewSource(aEvent, aPacket) {
if (aPacket.source.url.startsWith("chrome:")) {
ok(true, "Received a new chrome source: " + aPacket.source.url);
gClient.removeListener("newSource", onNewSource);
gNewChromeSource.resolve();
}
gClient.removeListener("newSource", onNewSource);
gThreadClient.resume(function(aResponse) {
removeTab(gMozillaTab);
removeTab(gTab);
gClient.close(function() {
ok(gNewGlobal, "Received newGlobal event.");
ok(gChromeSource, "Received newSource event for a chrome: script.");
finish();
});
});
}
function resumeAndCloseConnection() {
let deferred = promise.defer();
gThreadClient.resume(() => gClient.close(deferred.resolve));
return deferred.promise;
}
registerCleanupFunction(function() {
removeTab(gBrowser.selectedTab);
gClient = null;
gThreadClient = null;
gAttached = null;
gNewGlobal = null;
gNewChromeSource = null;
});

View File

@ -1,43 +1,39 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that closing a tab with the debugger in a paused state exits cleanly.
*/
// Test that closing a tab with the debugger in a paused state exits cleanly.
let gTab, gDebuggee, gPanel, gDebugger;
var gPane = null;
var gTab = null;
var gDebugger = null;
const DEBUGGER_TAB_URL = EXAMPLE_URL + "browser_dbg_debuggerstatement.html";
const TAB_URL = EXAMPLE_URL + "doc_inline-debugger-statement.html";
function test() {
debug_tab_pane(DEBUGGER_TAB_URL, function(aTab, aDebuggee, aPane) {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
testCleanExit();
});
}
function testCleanExit() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
waitForSourceAndCaretAndScopes(gPanel, ".html", 16).then(() => {
is(gDebugger.gThreadClient.paused, true,
"Should be paused after the debugger statement.");
is(gDebugger.DebuggerController.activeThread.paused, true,
"Should be paused after the debugger statement.");
closeDebuggerAndFinish();
}}, 0);
closeDebuggerAndFinish(gPanel, { whilePaused: true });
});
gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
gDebuggee.runDebuggerStatement();
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
});

View File

@ -0,0 +1,134 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the 'dbg blackbox' and 'dbg unblackbox' commands work as
* they should.
*/
const TEST_URL = EXAMPLE_URL + "doc_blackboxing.html";
const BLACKBOXME_URL = EXAMPLE_URL + "code_blackboxing_blackboxme.js";
const BLACKBOXONE_URL = EXAMPLE_URL + "code_blackboxing_one.js";
const BLACKBOXTWO_URL = EXAMPLE_URL + "code_blackboxing_two.js";
const BLACKBOXTHREE_URL = EXAMPLE_URL + "code_blackboxing_three.js";
let gPanel, gDebugger, gThreadClient;
let gOptions;
function test() {
helpers.addTabWithToolbar(TEST_URL, function(aOptions) {
gOptions = aOptions;
return gDevTools.showToolbox(aOptions.target, "jsdebugger")
.then(setupGlobals)
.then(waitForDebuggerSources)
.then(testBlackBoxSource)
.then(testUnBlackBoxSource)
.then(testBlackBoxGlob)
.then(testUnBlackBoxGlob)
.then(testBlackBoxInvert)
.then(testUnBlackBoxInvert)
.then(() => closeDebuggerAndFinish(gPanel, { noTabRemoval: true }))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function setupGlobals(aToolbox) {
gPanel = aToolbox.getCurrentPanel();
gDebugger = gPanel.panelWin;
gThreadClient = gDebugger.gThreadClient;
}
function waitForDebuggerSources() {
return waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
}
function testBlackBoxSource() {
return cmd("dbg blackbox " + BLACKBOXME_URL).then(() => {
const checkbox = getBlackBoxCheckbox(BLACKBOXME_URL);
ok(!checkbox.checked,
"Should be able to black box a specific source.");
});
}
function testUnBlackBoxSource() {
return cmd("dbg unblackbox " + BLACKBOXME_URL).then(() => {
const checkbox = getBlackBoxCheckbox(BLACKBOXME_URL);
ok(checkbox.checked,
"Should be able to stop black boxing a specific source.");
});
}
function testBlackBoxGlob() {
return cmd("dbg blackbox --glob *blackboxing_t*.js", 2,
[/blackboxing_three\.js/g, /blackboxing_two\.js/g]).then(() => {
ok(getBlackBoxCheckbox(BLACKBOXME_URL).checked,
"blackboxme should not be black boxed because it doesn't match the glob.");
ok(getBlackBoxCheckbox(BLACKBOXONE_URL).checked,
"blackbox_one should not be black boxed because it doesn't match the glob.");
ok(!getBlackBoxCheckbox(BLACKBOXTWO_URL).checked,
"blackbox_two should be black boxed because it matches the glob.");
ok(!getBlackBoxCheckbox(BLACKBOXTHREE_URL).checked,
"blackbox_three should be black boxed because it matches the glob.");
});
}
function testUnBlackBoxGlob() {
return cmd("dbg unblackbox --glob *blackboxing_t*.js", 2).then(() => {
ok(getBlackBoxCheckbox(BLACKBOXTWO_URL).checked,
"blackbox_two should be un-black boxed because it matches the glob.");
ok(getBlackBoxCheckbox(BLACKBOXTHREE_URL).checked,
"blackbox_three should be un-black boxed because it matches the glob.");
});
}
function testBlackBoxInvert() {
return cmd("dbg blackbox --invert --glob *blackboxing_t*.js", 3,
[/blackboxing_three\.js/g, /blackboxing_two\.js/g]).then(() => {
ok(!getBlackBoxCheckbox(BLACKBOXME_URL).checked,
"blackboxme should be black boxed because it doesn't match the glob.");
ok(!getBlackBoxCheckbox(BLACKBOXONE_URL).checked,
"blackbox_one should be black boxed because it doesn't match the glob.");
ok(!getBlackBoxCheckbox(TEST_URL).checked,
"TEST_URL should be black boxed because it doesn't match the glob.");
ok(getBlackBoxCheckbox(BLACKBOXTWO_URL).checked,
"blackbox_two should not be black boxed because it matches the glob.");
ok(getBlackBoxCheckbox(BLACKBOXTHREE_URL).checked,
"blackbox_three should not be black boxed because it matches the glob.");
});
}
function testUnBlackBoxInvert() {
return cmd("dbg unblackbox --invert --glob *blackboxing_t*.js", 3).then(() => {
ok(getBlackBoxCheckbox(BLACKBOXME_URL).checked,
"blackboxme should be un-black boxed because it does not match the glob.");
ok(getBlackBoxCheckbox(BLACKBOXONE_URL).checked,
"blackbox_one should be un-black boxed because it does not match the glob.");
ok(getBlackBoxCheckbox(TEST_URL).checked,
"TEST_URL should be un-black boxed because it doesn't match the glob.");
});
}
registerCleanupFunction(function() {
gOptions = null;
gPanel = null;
gDebugger = null;
gThreadClient = null;
});
function cmd(aTyped, aEventRepeat = 1, aOutput = "") {
return promise.all([
waitForThreadEvents(gPanel, "blackboxchange", aEventRepeat),
helpers.audit(gOptions, [{ setup: aTyped, output: aOutput, exec: {} }])
]);
}
function getBlackBoxCheckbox(url) {
return gDebugger.document.querySelector(
".side-menu-widget-item[tooltiptext=\"" + url + "\"] " +
".side-menu-widget-item-checkbox");
}

View File

@ -0,0 +1,204 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the break commands works as they should.
*/
const TAB_URL = EXAMPLE_URL + "doc_cmd-break.html";
function test() {
let gPanel, gDebugger, gThreadClient;
let gLineNumber;
helpers.addTabWithToolbar(TAB_URL, aOptions => {
return helpers.audit(aOptions, [
{
setup: 'break',
check: {
input: 'break',
hints: ' add line',
markup: 'IIIII',
status: 'ERROR',
}
},
{
setup: 'break add',
check: {
input: 'break add',
hints: ' line',
markup: 'IIIIIVIII',
status: 'ERROR'
}
},
{
setup: 'break add line',
check: {
input: 'break add line',
hints: ' <file> <line>',
markup: 'VVVVVVVVVVVVVV',
status: 'ERROR'
}
},
{
name: 'open toolbox',
setup: function() {
return initDebugger(gBrowser.selectedTab).then(([aTab, aDebuggee, aPanel]) => {
// Spin the event loop before causing the debuggee to pause, to allow
// this function to return first.
executeSoon(() => aDebuggee.firstCall());
return waitForSourceAndCaretAndScopes(aPanel, ".html", 17).then(() => {
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gThreadClient = gPanel.panelWin.gThreadClient;
gLineNumber = '' + aOptions.window.wrappedJSObject.gLineNumber;
});
});
},
post: function() {
ok(gThreadClient, "Debugger client exists.");
is(gLineNumber, 14, "gLineNumber is correct.");
},
},
{
name: 'break add line .../doc_cmd-break.html 14',
setup: function() {
// We have to setup in a function to allow gLineNumber to be initialized.
let line = 'break add line ' + TAB_URL + ' ' + gLineNumber;
return helpers.setInput(aOptions, line);
},
check: {
hints: '',
status: 'VALID',
message: '',
args: {
file: { value: TAB_URL, message: '' },
line: { value: 14 }
}
},
exec: {
output: 'Added breakpoint',
completed: false
}
},
{
setup: 'break add line ' + TAB_URL + ' 17',
check: {
hints: '',
status: 'VALID',
message: '',
args: {
file: { value: TAB_URL, message: '' },
line: { value: 17 }
}
},
exec: {
output: 'Added breakpoint',
completed: false
}
},
{
setup: 'break list',
check: {
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
},
exec: {
output: [
/Source/, /Remove/,
/doc_cmd-break\.html:14/,
/doc_cmd-break\.html:17/
]
}
},
{
name: 'cleanup',
setup: function() {
let deferred = promise.defer();
gThreadClient.resume(deferred.resolve);
return deferred.promise;
}
},
{
setup: 'break del 14',
check: {
input: 'break del 14',
hints: ' -> doc_cmd-break.html:14',
markup: 'VVVVVVVVVVII',
status: 'ERROR',
args: {
breakpoint: {
status: 'INCOMPLETE',
message: ''
}
}
}
},
{
setup: 'break del doc_cmd-break.html:14',
check: {
input: 'break del doc_cmd-break.html:14',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
breakpoint: { arg: ' doc_cmd-break.html:14' },
}
},
exec: {
output: 'Breakpoint removed',
completed: false
}
},
{
setup: 'break list',
check: {
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
},
exec: {
output: [
/Source/, /Remove/,
/doc_cmd-break\.html:17/
]
}
},
{
setup: 'break del doc_cmd-break.html:17',
check: {
input: 'break del doc_cmd-break.html:17',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
breakpoint: { arg: ' doc_cmd-break.html:17' },
}
},
exec: {
output: 'Breakpoint removed',
completed: false
}
},
{
setup: 'break list',
check: {
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
},
exec: {
output: 'No breakpoints set'
},
post: function() {
return teardown(gPanel, { noTabRemoval: true });
}
},
]);
}).then(finish);
}

View File

@ -0,0 +1,101 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the debugger commands work as they should.
*/
const TEST_URI = EXAMPLE_URL + "doc_cmd-dbg.html";
function test() {
return Task.spawn(function() {
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
yield helpers.audit(options, [{
setup: "dbg open",
exec: { output: "", completed: false }
}]);
let [gTab, gDebuggee, gPanel] = yield initDebugger(gBrowser.selectedTab);
let gDebugger = gPanel.panelWin;
let gThreadClient = gDebugger.gThreadClient;
yield helpers.audit(options, [{
setup: "dbg list",
exec: { output: /doc_cmd-dbg.html/ }
}]);
let button = gDebuggee.document.querySelector("input[type=button]");
let output = gDebuggee.document.querySelector("input[type=text]");
let cmd = function(aTyped, aState) {
return promise.all([
waitForThreadEvents(gPanel, aState),
helpers.audit(options, [{ setup: aTyped, exec: { output: "" } }])
]);
};
let click = function(aElement, aState) {
return promise.all([
waitForThreadEvents(gPanel, aState),
executeSoon(() => EventUtils.sendMouseEvent({ type: "click" }, aElement, gDebuggee))
]);
}
yield cmd("dbg interrupt", "paused");
is(gThreadClient.state, "paused", "Debugger is paused.");
yield cmd("dbg continue", "resumed");
isnot(gThreadClient.state, "paused", "Debugger has continued.");
yield click(button, "paused");
is(gThreadClient.state, "paused", "Debugger is paused again.");
yield cmd("dbg step in", "paused");
yield cmd("dbg step in", "paused");
yield cmd("dbg step in", "paused");
is(output.value, "step in", "Debugger stepped in.");
yield cmd("dbg step over", "paused");
is(output.value, "step over", "Debugger stepped over.");
yield cmd("dbg step out", "paused");
is(output.value, "step out", "Debugger stepped out.");
yield cmd("dbg continue", "paused");
is(output.value, "dbg continue", "Debugger continued.");
let closeDebugger = function() {
let deferred = promise.defer();
helpers.audit(options, [{
setup: "dbg close",
completed: false,
exec: { output: "" }
}])
.then(() => {
let toolbox = gDevTools.getToolbox(options.target);
if (!toolbox) {
ok(true, "Debugger is closed.");
deferred.resolve();
} else {
toolbox.on("destroyed", () => {
ok(true, "Debugger just closed.");
deferred.resolve();
});
}
});
return deferred.promise;
};
// We close the debugger twice to ensure 'dbg close' doesn't error when
// toolbox is already closed. See bug 884638 for more info.
yield closeDebugger();
yield closeDebugger();
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
}

View File

@ -1,48 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="application/javascript;version=1.7"/>
let output;
function init() {
output = document.querySelector("input");
output.value = "";
}
function doit() {
debugger;
stepIntoMe(); // step in
output.value = "dbg continue";
debugger;
}
function stepIntoMe() {
output.value = "step in"; // step in
stepOverMe(); // step over
let x = 0; // step out
output.value = "step out";
}
function stepOverMe() {
output.value = "step over";
}
</script>
</head>
<body onload="init()">
<input type="text" value=""/>
<input type="button" value="DOIT" onclick="doit()"/>
<br />
Use this file to test the following commands:
<ul>
<li>dbg interrupt</li>
<li>dbg continue</li>
<li>dbg step over</li>
<li>dbg step in</li>
<li>dbg step out</li>
</ul>
</body>
</html>

View File

@ -1,106 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
let Task = Cu.import("resource://gre/modules/Task.jsm", {}).Task;
return Task.spawn(function() {
const TEST_URI = "http://example.com/browser/browser/devtools/debugger/" +
"test/browser_dbg_cmd.html";
let options = yield helpers.openTab(TEST_URI);
yield helpers.openToolbar(options);
yield helpers.audit(options, [{
setup: "dbg open",
exec: { output: "", completed: false }
}]);
let toolbox = yield gDevTools.showToolbox(options.target, "jsdebugger");
let dbg = toolbox.getCurrentPanel();
ok(dbg, "DebuggerPanel exists");
// Wait for the initial resume...
let resumeDeferred = promise.defer();
dbg.panelWin.gClient.addOneTimeListener("resumed", () => {
resumeDeferred.resolve();
});
yield resumeDeferred.promise;
yield helpers.audit(options, [{
setup: "dbg list",
exec: { output: /browser_dbg_cmd.html/ }
}]);
// exec a command with GCLI to resume the debugger and wait until it stops
let cmd = function(typed) {
let cmdDeferred = promise.defer();
dbg._controller.activeThread.addOneTimeListener("paused", ev => {
cmdDeferred.resolve();
});
helpers.audit(options, [{
setup: typed,
exec: { output: "" }
}]).then(null, cmdDeferred.reject);
return cmdDeferred.promise;
};
yield cmd("dbg interrupt");
let interruptDeferred = promise.defer();
ok(true, "debugger is paused");
dbg._controller.activeThread.addOneTimeListener("resumed", () => {
ok(true, "debugger continued");
dbg._controller.activeThread.addOneTimeListener("paused", () => {
interruptDeferred.resolve();
});
let btnDoit = options.window.document.querySelector("input[type=button]");
EventUtils.sendMouseEvent({ type:"click" }, btnDoit);
});
helpers.audit(options, [{
setup: "dbg continue",
exec: { output: "" }
}]);
yield interruptDeferred.promise;
yield cmd("dbg step in");
yield cmd("dbg step in");
yield cmd("dbg step in");
let output = options.window.document.querySelector("input[type=text]");
is(output.value, "step in", "debugger stepped in");
yield cmd("dbg step over");
is(output.value, "step over", "debugger stepped over");
yield cmd("dbg step out");
is(output.value, "step out", "debugger stepped out");
yield cmd("dbg continue");
is(output.value, "dbg continue", "debugger continued");
let closeDebugger = function() {
let closeDeferred = promise.defer();
helpers.audit(options, [{
setup: "dbg close",
completed: false,
exec: { output: "" }
}]).then(function() {
let closeToolbox = gDevTools.getToolbox(options.target);
if (!closeToolbox) {
ok(true, "Debugger is closed.");
closeDeferred.resolve();
} else {
closeToolbox.on("destroyed", () => {
ok(true, "Debugger just closed.");
closeDeferred.resolve();
});
}
});
return closeDeferred.promise;
};
// We close the debugger twice to ensure 'dbg close' doesn't error when
// toolbox is already closed. See bug 884638 for more info.
yield closeDebugger();
yield closeDebugger();
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
}).then(finish, helpers.handleError);
}

View File

@ -1,173 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the 'dbg blackbox' and 'dbg unblackbox' commands work as they
// should.
const TEST_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
const BLACKBOXME_URL = EXAMPLE_URL + "blackboxing_blackboxme.js";
const BLACKBOXONE_URL = EXAMPLE_URL + "blackboxing_one.js";
const BLACKBOXTWO_URL = EXAMPLE_URL + "blackboxing_two.js";
const BLACKBOXTHREE_URL = EXAMPLE_URL + "blackboxing_three.js";
let gcli = Cu.import("resource://gre/modules/devtools/gcli.jsm", {}).gcli;
let gTarget;
let gPanel;
let gOptions;
let gDebugger;
let gClient;
let gThreadClient;
let gTab;
function cmd(typed, expectedNumEvents=1, output=null) {
const deferred = promise.defer();
let timesFired = 0;
gThreadClient.addListener("blackboxchange", function _onBlackBoxChange() {
if (++timesFired === expectedNumEvents) {
gThreadClient.removeListener("blackboxchange", _onBlackBoxChange);
deferred.resolve();
}
});
let audit = {
setup: typed,
exec: {}
};
if (output) {
audit.output = output;
}
return helpers.audit(gOptions, [audit]).then(function() {
return deferred.promise;
});
}
function test() {
helpers.addTabWithToolbar(TEST_URL, function(options) {
gOptions = options;
gTarget = options.target;
return gDevTools.showToolbox(options.target, "jsdebugger")
.then(setupGlobals)
.then(waitForDebuggerSources)
.then(testBlackBoxSource)
.then(testUnBlackBoxSource)
.then(testBlackBoxGlob)
.then(testUnBlackBoxGlob)
.then(testBlackBoxInvert)
.then(testUnBlackBoxInvert)
.then(null, function (error) {
ok(false, "Got an error: " + error.message + "\n" + error.stack);
})
.then(finishUp);
});
}
function setupGlobals(toolbox) {
gTab = gBrowser.selectedTab;
gPanel = toolbox.getCurrentPanel();
gDebugger = gPanel.panelWin;
gClient = gDebugger.gClient;
gThreadClient = gClient.activeThread;
}
function waitForDebuggerSources() {
const deferred = promise.defer();
gDebugger.addEventListener("Debugger:SourceShown", function _onSourceShown() {
gDebugger.removeEventListener("Debugger:SourceShown", _onSourceShown, false);
deferred.resolve();
}, false);
return deferred.promise;
}
function testBlackBoxSource() {
return cmd("dbg blackbox " + BLACKBOXME_URL)
.then(function () {
const checkbox = getBlackBoxCheckbox(BLACKBOXME_URL);
ok(!checkbox.checked,
"Should be able to black box a specific source");
});
}
function testUnBlackBoxSource() {
return cmd("dbg unblackbox " + BLACKBOXME_URL)
.then(function () {
const checkbox = getBlackBoxCheckbox(BLACKBOXME_URL);
ok(checkbox.checked,
"Should be able to stop black boxing a specific source");
});
}
function testBlackBoxGlob() {
return cmd("dbg blackbox --glob *blackboxing_t*.js", 2,
[/blackboxing_three\.js/g, /blackboxing_two\.js/g])
.then(function () {
ok(getBlackBoxCheckbox(BLACKBOXME_URL).checked,
"blackboxme should not be black boxed because it doesn't match the glob");
ok(getBlackBoxCheckbox(BLACKBOXONE_URL).checked,
"blackbox_one should not be black boxed because it doesn't match the glob");
ok(!getBlackBoxCheckbox(BLACKBOXTWO_URL).checked,
"blackbox_two should be black boxed because it matches the glob");
ok(!getBlackBoxCheckbox(BLACKBOXTHREE_URL).checked,
"blackbox_three should be black boxed because it matches the glob");
});
}
function testUnBlackBoxGlob() {
return cmd("dbg unblackbox --glob *blackboxing_t*.js", 2)
.then(function () {
ok(getBlackBoxCheckbox(BLACKBOXTWO_URL).checked,
"blackbox_two should be un-black boxed because it matches the glob");
ok(getBlackBoxCheckbox(BLACKBOXTHREE_URL).checked,
"blackbox_three should be un-black boxed because it matches the glob");
});
}
function testBlackBoxInvert() {
return cmd("dbg blackbox --invert --glob *blackboxing_t*.js", 3,
[/blackboxing_three\.js/g, /blackboxing_two\.js/g])
.then(function () {
ok(!getBlackBoxCheckbox(BLACKBOXME_URL).checked,
"blackboxme should be black boxed because it doesn't match the glob");
ok(!getBlackBoxCheckbox(BLACKBOXONE_URL).checked,
"blackbox_one should be black boxed because it doesn't match the glob");
ok(!getBlackBoxCheckbox(TEST_URL).checked,
"TEST_URL should be black boxed because it doesn't match the glob");
ok(getBlackBoxCheckbox(BLACKBOXTWO_URL).checked,
"blackbox_two should not be black boxed because it matches the glob");
ok(getBlackBoxCheckbox(BLACKBOXTHREE_URL).checked,
"blackbox_three should not be black boxed because it matches the glob");
});
}
function testUnBlackBoxInvert() {
return cmd("dbg unblackbox --invert --glob *blackboxing_t*.js", 3)
.then(function () {
ok(getBlackBoxCheckbox(BLACKBOXME_URL).checked,
"blackboxme should be un-black boxed because it does not match the glob");
ok(getBlackBoxCheckbox(BLACKBOXONE_URL).checked,
"blackbox_one should be un-black boxed because it does not match the glob");
ok(getBlackBoxCheckbox(TEST_URL).checked,
"TEST_URL should be un-black boxed because it doesn't match the glob");
});
}
function finishUp() {
gTarget = null;
gPanel = null;
gOptions = null;
gClient = null;
gThreadClient = null;
gDebugger = null;
closeDebuggerAndFinish();
}
function getBlackBoxCheckbox(url) {
return gDebugger.document.querySelector(
".side-menu-widget-item[tooltiptext=\""
+ url + "\"] .side-menu-widget-item-checkbox");
}

View File

@ -1,19 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Browser GCLI break command test</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript">
function firstCall() {
eval("window.line0 = Error().lineNumber; secondCall();");
}
function secondCall() {
eval("debugger;");
}
</script>
</head>
<body>
</body>
</html>

View File

@ -1,220 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the break command works as it should
const TEST_URI = "http://example.com/browser/browser/devtools/debugger/" +
"test/browser_dbg_cmd_break.html";
function test() {
helpers.addTabWithToolbar(TEST_URI, function(options) {
// To help us run later commands, and clear up after ourselves
let client, line0;
return helpers.audit(options, [
{
setup: 'break',
check: {
input: 'break',
hints: ' add line',
markup: 'IIIII',
status: 'ERROR',
},
},
{
setup: 'break add',
check: {
input: 'break add',
hints: ' line',
markup: 'IIIIIVIII',
status: 'ERROR'
},
},
{
setup: 'break add line',
check: {
input: 'break add line',
hints: ' <file> <line>',
markup: 'VVVVVVVVVVVVVV',
status: 'ERROR'
},
},
{
name: 'open toolbox',
setup: function() {
var deferred = promise.defer();
var openDone = gDevTools.showToolbox(options.target, "jsdebugger");
openDone.then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
ok(dbg, "DebuggerPanel exists");
// Wait for the initial resume...
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
info("Starting tests");
client = dbg.panelWin.gClient;
client.activeThread.addOneTimeListener("framesadded", function() {
line0 = '' + options.window.wrappedJSObject.line0;
deferred.resolve();
});
// Trigger newScript notifications using eval.
content.wrappedJSObject.firstCall();
});
});
return deferred.promise;
},
post: function() {
ok(client, "Debugger client exists");
is(line0, 10, "line0 is 10");
},
},
{
name: 'break add line .../browser_dbg_cmd_break.html 10',
setup: function() {
// We have to setup in a function to allow line0 to be initialized
let line = 'break add line ' + TEST_URI + ' ' + line0;
return helpers.setInput(options, line);
},
check: {
hints: '',
status: 'VALID',
message: '',
args: {
file: { value: TEST_URI, message: '' },
line: { value: 10 }
}
},
exec: {
output: 'Added breakpoint',
completed: false
},
},
{
setup: 'break add line http://example.com/browser/browser/devtools/debugger/test/browser_dbg_cmd_break.html 13',
check: {
hints: '',
status: 'VALID',
message: '',
args: {
file: { value: TEST_URI, message: '' },
line: { value: 13 }
}
},
exec: {
output: 'Added breakpoint',
completed: false
},
},
{
setup: 'break list',
check: {
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
},
exec: {
output: [
/Source/, /Remove/,
/cmd_break\.html:10/,
/cmd_break\.html:13/
]
},
},
{
name: 'cleanup',
setup: function() {
// a.k.a "return client.activeThread.resume();"
var deferred = promise.defer();
client.activeThread.resume(function() {
deferred.resolve();
});
return deferred.promise;
},
},
{
setup: 'break del 0',
check: {
input: 'break del 0',
hints: ' -> browser_dbg_cmd_break.html:10',
markup: 'VVVVVVVVVVI',
status: 'ERROR',
args: {
breakpoint: {
status: 'INCOMPLETE',
message: ''
},
}
},
},
{
setup: 'break del browser_dbg_cmd_break.html:10',
check: {
input: 'break del browser_dbg_cmd_break.html:10',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
breakpoint: { arg: ' browser_dbg_cmd_break.html:10' },
}
},
exec: {
output: 'Breakpoint removed',
completed: false
},
},
{
setup: 'break list',
check: {
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
},
exec: {
output: [
/Source/, /Remove/,
/browser_dbg_cmd_break\.html:13/
]
},
},
{
setup: 'break del browser_dbg_cmd_break.html:13',
check: {
input: 'break del browser_dbg_cmd_break.html:13',
hints: '',
markup: 'VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV',
status: 'VALID',
args: {
breakpoint: { arg: ' browser_dbg_cmd_break.html:13' },
}
},
exec: {
output: 'Breakpoint removed',
completed: false
},
},
{
setup: 'break list',
check: {
input: 'break list',
hints: '',
markup: 'VVVVVVVVVV',
status: 'VALID'
},
exec: {
output: 'No breakpoints set'
},
post: function() {
client = undefined;
let toolbox = gDevTools.getToolbox(options.target);
return toolbox.destroy();
}
},
]);
}).then(finish);
}

View File

@ -0,0 +1,218 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 740825: Test the debugger conditional breakpoints.
*/
const TAB_URL = EXAMPLE_URL + "doc_conditional-breakpoints.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
gBreakpointsAdded = gBreakpoints._added;
gBreakpointsRemoving = gBreakpoints._removing;
waitForSourceAndCaretAndScopes(gPanel, ".html", 17)
.then(() => addBreakpoints())
.then(() => initialChecks())
.then(() => resumeAndTestBreakpoint(20))
.then(() => resumeAndTestBreakpoint(21))
.then(() => resumeAndTestBreakpoint(22))
.then(() => resumeAndTestBreakpoint(23))
.then(() => resumeAndTestBreakpoint(24))
.then(() => resumeAndTestBreakpoint(25))
.then(() => resumeAndTestBreakpoint(27))
.then(() => resumeAndTestBreakpoint(28))
.then(() => resumeAndTestBreakpoint(29))
.then(() => resumeAndTestNoBreakpoint())
.then(() => reloadActiveTab(gPanel, gDebugger.EVENTS.BREAKPOINT_SHOWN, 13))
.then(() => ensureThreadClientState(gPanel, "resumed"))
.then(() => testAfterReload())
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
gDebuggee.ermahgerd();
});
function addBreakpoints() {
return promise.resolve(null)
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 18 }))
.then(aClient => aClient.conditionalExpression = "undefined")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 19 }))
.then(aClient => aClient.conditionalExpression = "null")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 20 }))
.then(aClient => aClient.conditionalExpression = "42")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 21 }))
.then(aClient => aClient.conditionalExpression = "true")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 22 }))
.then(aClient => aClient.conditionalExpression = "'nasu'")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 23 }))
.then(aClient => aClient.conditionalExpression = "/regexp/")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 24 }))
.then(aClient => aClient.conditionalExpression = "({})")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 25 }))
.then(aClient => aClient.conditionalExpression = "(function() {})")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 26 }))
.then(aClient => aClient.conditionalExpression = "(function() { return false; })()")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 27 }))
.then(aClient => aClient.conditionalExpression = "a")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 28 }))
.then(aClient => aClient.conditionalExpression = "a !== undefined")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 29 }))
.then(aClient => aClient.conditionalExpression = "a !== null")
.then(() => gPanel.addBreakpoint({ url: gSources.selectedValue, line: 30 }))
.then(aClient => aClient.conditionalExpression = "b")
}
function initialChecks() {
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
is(gSources.itemCount, 1,
"Found the expected number of sources.");
is(gEditor.getText().indexOf("ermahgerd"), 253,
"The correct source was loaded initially.");
is(gSources.selectedValue, gSources.values[0],
"The correct source is selected.");
is(gBreakpointsAdded.size, 13,
"13 breakpoints currently added.");
is(gBreakpointsRemoving.size, 0,
"No breakpoints currently being removed.");
is(gEditor.getBreakpoints().length, 13,
"13 breakpoints currently shown in the editor.");
ok(!gBreakpoints._getAdded({ url: "foo", line: 3 }),
"_getAdded('foo', 3) returns falsey.");
ok(!gBreakpoints._getRemoving({ url: "bar", line: 3 }),
"_getRemoving('bar', 3) returns falsey.");
}
function resumeAndTestBreakpoint(aLine) {
let finished = waitForCaretUpdated(gPanel, aLine).then(() => testBreakpoint(aLine));
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
return finished;
}
function resumeAndTestNoBreakpoint() {
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
is(gSources.itemCount, 1,
"Found the expected number of sources.");
is(gEditor.getText().indexOf("ermahgerd"), 253,
"The correct source was loaded initially.");
is(gSources.selectedValue, gSources.values[0],
"The correct source is selected.");
ok(gSources.selectedItem,
"There should be a selected source in the sources pane.")
ok(!gSources._selectedBreakpointItem,
"There should be no selected breakpoint in the sources pane.")
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
is(gDebugger.document.querySelectorAll(".dbg-stackframe").length, 0,
"There should be no visible stackframes.");
is(gDebugger.document.querySelectorAll(".dbg-breakpoint").length, 13,
"There should be thirteen visible breakpoints.");
});
gDebugger.gThreadClient.resume();
return finished;
}
function testBreakpoint(aLine, aHighlightBreakpoint) {
// Highlight the breakpoint only if required.
if (aHighlightBreakpoint) {
let finished = waitForCaretUpdated(gPanel, aLine).then(() => testBreakpoint(aLine));
gSources.highlightBreakpoint({ url: gSources.selectedValue, line: aLine });
return finished;
}
let selectedUrl = gSources.selectedValue;
let selectedBreakpoint = gSources._selectedBreakpointItem;
ok(selectedUrl,
"There should be a selected item in the sources pane.");
ok(selectedBreakpoint,
"There should be a selected brekapoint in the sources pane.");
is(selectedBreakpoint.attachment.url, selectedUrl,
"The breakpoint on line " + aLine + " wasn't added on the correct source.");
is(selectedBreakpoint.attachment.line, aLine,
"The breakpoint on line " + aLine + " wasn't found.");
is(!!selectedBreakpoint.attachment.disabled, false,
"The breakpoint on line " + aLine + " should be enabled.");
is(!!selectedBreakpoint.attachment.openPopup, false,
"The breakpoint on line " + aLine + " should not have opened a popup.");
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not have been shown.");
return gBreakpoints._getAdded(selectedBreakpoint.attachment).then(aBreakpointClient => {
is(aBreakpointClient.location.url, selectedUrl,
"The breakpoint's client url is correct");
is(aBreakpointClient.location.line, aLine,
"The breakpoint's client line is correct");
isnot(aBreakpointClient.conditionalExpression, undefined,
"The breakpoint on line " + aLine + " should have a conditional expression.");
ok(isCaretPos(gPanel, aLine),
"The editor caret position is not properly set.");
});
}
function testAfterReload() {
let selectedUrl = gSources.selectedValue;
let selectedBreakpoint = gSources._selectedBreakpointItem;
ok(selectedUrl,
"There should be a selected item in the sources pane after reload.");
ok(!selectedBreakpoint,
"There should be no selected brekapoint in the sources pane after reload.");
return promise.resolve(null)
.then(() => testBreakpoint(18, true))
.then(() => testBreakpoint(19, true))
.then(() => testBreakpoint(20, true))
.then(() => testBreakpoint(21, true))
.then(() => testBreakpoint(22, true))
.then(() => testBreakpoint(23, true))
.then(() => testBreakpoint(24, true))
.then(() => testBreakpoint(25, true))
.then(() => testBreakpoint(26, true))
.then(() => testBreakpoint(27, true))
.then(() => testBreakpoint(28, true))
.then(() => testBreakpoint(29, true))
.then(() => testBreakpoint(30, true))
.then(() => {
is(gSources.itemCount, 1,
"Found the expected number of sources.");
is(gEditor.getText().indexOf("ermahgerd"), 253,
"The correct source was loaded again.");
is(gSources.selectedValue, gSources.values[0],
"The correct source is selected.");
ok(gSources.selectedItem,
"There should be a selected source in the sources pane.")
ok(gSources._selectedBreakpointItem,
"There should be a selected breakpoint in the sources pane.")
is(gSources._conditionalPopupVisible, false,
"The breakpoint conditional expression popup should not be shown.");
});
}
}

View File

@ -0,0 +1,196 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 740825: Test the debugger conditional breakpoints.
*/
const TAB_URL = EXAMPLE_URL + "doc_conditional-breakpoints.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
gBreakpointsAdded = gBreakpoints._added;
gBreakpointsRemoving = gBreakpoints._removing;
waitForSourceAndCaretAndScopes(gPanel, ".html", 17)
.then(() => initialChecks())
.then(() => addBreakpoint1())
.then(() => testBreakpoint(18, false, false, undefined))
.then(() => addBreakpoint2())
.then(() => testBreakpoint(19, false, false, undefined))
.then(() => modBreakpoint2())
.then(() => testBreakpoint(19, false, true, undefined))
.then(() => addBreakpoint3())
.then(() => testBreakpoint(20, true, false, undefined))
.then(() => modBreakpoint3())
.then(() => testBreakpoint(20, true, false, "bamboocha"))
.then(() => addBreakpoint4())
.then(() => testBreakpoint(21, false, false, undefined))
.then(() => delBreakpoint4())
.then(() => setCaretPosition(18))
.then(() => testBreakpoint(18, false, false, undefined))
.then(() => setCaretPosition(19))
.then(() => testBreakpoint(19, false, false, undefined))
.then(() => setCaretPosition(20))
.then(() => testBreakpoint(20, true, false, "bamboocha"))
.then(() => setCaretPosition(17))
.then(() => testNoBreakpoint(17))
.then(() => setCaretPosition(21))
.then(() => testNoBreakpoint(21))
.then(() => clickOnBreakpoint(0))
.then(() => testBreakpoint(18, false, false, undefined))
.then(() => clickOnBreakpoint(1))
.then(() => testBreakpoint(19, false, false, undefined))
.then(() => clickOnBreakpoint(2))
.then(() => testBreakpoint(20, true, true, "bamboocha"))
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
gDebuggee.ermahgerd();
});
function initialChecks() {
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
is(gSources.itemCount, 1,
"Found the expected number of sources.");
is(gEditor.getText().indexOf("ermahgerd"), 253,
"The correct source was loaded initially.");
is(gSources.selectedValue, gSources.values[0],
"The correct source is selected.");
is(gBreakpointsAdded.size, 0,
"No breakpoints currently added.");
is(gBreakpointsRemoving.size, 0,
"No breakpoints currently being removed.");
is(gEditor.getBreakpoints().length, 0,
"No breakpoints currently shown in the editor.");
ok(!gBreakpoints._getAdded({ url: "foo", line: 3 }),
"_getAdded('foo', 3) returns falsey.");
ok(!gBreakpoints._getRemoving({ url: "bar", line: 3 }),
"_getRemoving('bar', 3) returns falsey.");
}
function addBreakpoint1() {
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED);
gPanel.addBreakpoint({ url: gSources.selectedValue, line: 18 });
return finished;
}
function addBreakpoint2() {
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED);
setContextPosition(19);
gSources._onCmdAddBreakpoint();
return finished;
}
function modBreakpoint2() {
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.CONDITIONAL_BREAKPOINT_POPUP_SHOWING);
setContextPosition(19);
gSources._onCmdAddConditionalBreakpoint();
return finished;
}
function addBreakpoint3() {
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED);
setContextPosition(20);
gSources._onCmdAddConditionalBreakpoint();
return finished;
}
function modBreakpoint3() {
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.CONDITIONAL_BREAKPOINT_POPUP_HIDING);
typeText(gSources._cbTextbox, "bamboocha");
EventUtils.sendKey("RETURN", gDebugger);
return finished;
}
function addBreakpoint4() {
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_ADDED);
setContextPosition(21);
gSources._onCmdAddBreakpoint();
return finished;
}
function delBreakpoint4() {
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.BREAKPOINT_REMOVED);
setContextPosition(21);
gSources._onCmdAddBreakpoint();
return finished;
}
function testBreakpoint(aLine, aOpenPopupFlag, aPopupVisible, aConditionalExpression) {
let selectedUrl = gSources.selectedValue;
let selectedBreakpoint = gSources._selectedBreakpointItem;
ok(selectedUrl,
"There should be a selected item in the sources pane.");
ok(selectedBreakpoint,
"There should be a selected brekapoint in the sources pane.");
is(selectedBreakpoint.attachment.url, selectedUrl,
"The breakpoint on line " + aLine + " wasn't added on the correct source.");
is(selectedBreakpoint.attachment.line, aLine,
"The breakpoint on line " + aLine + " wasn't found.");
is(!!selectedBreakpoint.attachment.disabled, false,
"The breakpoint on line " + aLine + " should be enabled.");
is(!!selectedBreakpoint.attachment.openPopup, aOpenPopupFlag,
"The breakpoint on line " + aLine + " should have a correct popup state (1).");
is(gSources._conditionalPopupVisible, aPopupVisible,
"The breakpoint on line " + aLine + " should have a correct popup state (2).");
return gBreakpoints._getAdded(selectedBreakpoint.attachment).then(aBreakpointClient => {
is(aBreakpointClient.location.url, selectedUrl,
"The breakpoint's client url is correct");
is(aBreakpointClient.location.line, aLine,
"The breakpoint's client line is correct");
is(aBreakpointClient.conditionalExpression, aConditionalExpression,
"The breakpoint on line " + aLine + " should have a correct conditional expression.");
is("conditionalExpression" in aBreakpointClient, !!aConditionalExpression,
"The breakpoint on line " + aLine + " should have a correct conditional state.");
ok(isCaretPos(gPanel, aLine),
"The editor caret position is not properly set.");
});
}
function testNoBreakpoint(aLine) {
let selectedUrl = gSources.selectedValue;
let selectedBreakpoint = gSources._selectedBreakpointItem;
ok(selectedUrl,
"There should be a selected item in the sources pane for line " + aLine + ".");
ok(!selectedBreakpoint,
"There should be no selected brekapoint in the sources pane for line " + aLine + ".");
ok(isCaretPos(gPanel, aLine),
"The editor caret position is not properly set.");
}
function setCaretPosition(aLine) {
gEditor.setCaretPosition(aLine - 1);
}
function setContextPosition(aLine) {
gSources._editorContextMenuLineNumber = aLine - 1;
}
function clickOnBreakpoint(aIndex) {
EventUtils.sendMouseEvent({ type: "click" },
gDebugger.document.querySelectorAll(".dbg-breakpoint")[aIndex],
gDebugger);
}
}

View File

@ -0,0 +1,89 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests the behavior of the debugger statement.
*/
const TAB_URL = EXAMPLE_URL + "doc_inline-debugger-statement.html";
let gClient;
function test() {
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect((aType, aTraits) => {
is(aType, "browser",
"Root actor should identify itself as a browser.");
addTab(TAB_URL)
.then(() => attachTabActorForUrl(gClient, TAB_URL))
.then(testEarlyDebuggerStatement)
.then(testDebuggerStatement)
.then(closeConnection)
.then(finish)
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function testEarlyDebuggerStatement([aGrip, aResponse]) {
let deferred = promise.defer();
let onPaused = function(aEvent, aPacket) {
ok(false, "Pause shouldn't be called before we've attached!");
deferred.reject();
};
gClient.addListener("paused", onPaused);
// This should continue without nesting an event loop and calling
// the onPaused hook, because we haven't attached yet.
let debuggee = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject;
debuggee.runDebuggerStatement();
gClient.removeListener("paused", onPaused);
// Now attach and resume...
gClient.request({ to: aResponse.threadActor, type: "attach" }, () => {
gClient.request({ to: aResponse.threadActor, type: "resume" }, () => {
ok(true, "Pause wasn't called before we've attached.");
deferred.resolve([aGrip, aResponse]);
});
});
return deferred.promise;
}
function testDebuggerStatement([aGrip, aResponse]) {
let deferred = promise.defer();
gClient.addListener("paused", (aEvent, aPacket) => {
gClient.request({ to: aResponse.threadActor, type: "resume" }, () => {
ok(true, "The pause handler was triggered on a debugger statement.");
deferred.resolve();
});
});
// Reach around the debugging protocol and execute the debugger statement.
let debuggee = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject;
debuggee.runDebuggerStatement();
}
function closeConnection() {
let deferred = promise.defer();
gClient.close(deferred.resolve);
return deferred.promise;
}
registerCleanupFunction(function() {
removeTab(gBrowser.selectedTab);
gClient = null;
});

View File

@ -1,18 +0,0 @@
<!DOCTYPE HTML>
<html>
<head><meta charset='utf-8'/><title>Browser Debugger Test Tab</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript">
function runDebuggerStatement()
{
debugger;
}
</script>
</head>
<body></body>
</html>

View File

@ -1,70 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests the behavior of the debugger statement.
var gClient = null;
var gTab = null;
const DEBUGGER_TAB_URL = EXAMPLE_URL + "browser_dbg_debuggerstatement.html";
function test()
{
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect(function(aType, aTraits) {
gTab = addTab(DEBUGGER_TAB_URL, function() {
attach_tab_actor_for_url(gClient, DEBUGGER_TAB_URL, function(actor, response) {
test_early_debugger_statement(response);
});
});
});
}
function test_early_debugger_statement(aActor)
{
let paused = function(aEvent, aPacket) {
ok(false, "Pause shouldn't be called before we've attached!\n");
finish_test();
};
gClient.addListener("paused", paused);
// This should continue without nesting an event loop and calling
// the onPaused hook, because we haven't attached yet.
gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
gClient.removeListener("paused", paused);
// Now attach and resume...
gClient.request({ to: aActor.threadActor, type: "attach" }, function(aResponse) {
gClient.request({ to: aActor.threadActor, type: "resume" }, function(aResponse) {
test_debugger_statement(aActor);
});
});
}
function test_debugger_statement(aActor)
{
var stopped = false;
gClient.addListener("paused", function(aEvent, aPacket) {
stopped = true;
gClient.request({ to: aActor.threadActor, type: "resume" }, function() {
finish_test();
});
});
// Reach around the debugging protocol and execute the debugger
// statement.
gTab.linkedBrowser.contentWindow.wrappedJSObject.runDebuggerStatement();
ok(stopped, "Should trigger the pause handler on a debugger statement.");
}
function finish_test()
{
removeTab(gTab);
gClient.close(function() {
finish();
});
}

View File

@ -1,29 +0,0 @@
<!DOCTYPE HTML>
<html>
<head><meta charset='utf-8'/><title>Browser Debugger Test Tab</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript">
var a = function() {
return function() {
debugger;
}
}
var anon = a();
anon.displayName = "anonFunc";
var inferred = a();
function evalCall() {
eval("anon();");
eval("inferred();");
}
</script>
</head>
<body></body>
</html>

View File

@ -1,78 +0,0 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests that anonymous functions appear in the stack frame list with either
// their displayName property or a SpiderMonkey-inferred name.
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
const TAB_URL = EXAMPLE_URL + "browser_dbg_displayName.html";
function test() {
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
testAnonCall();
});
}
function testAnonCall() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
let frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should have three frames.");
is(frames.querySelector("#stackframe-0 .dbg-stackframe-title").getAttribute("value"),
"anonFunc", "Frame name should be anonFunc");
testInferredName();
}}, 0);
});
gDebuggee.evalCall();
}
function testInferredName() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
let frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should have three frames.");
is(frames.querySelector("#stackframe-0 .dbg-stackframe-title").getAttribute("value"),
"a/<", "Frame name should be a/<");
resumeAndFinish();
}}, 0);
});
gDebugger.DebuggerController.activeThread.resume();
}
function resumeAndFinish() {
gDebugger.DebuggerController.activeThread.resume(function() {
removeTab(gTab);
gPane = null;
gDebuggee = null;
finish();
});
}

View File

@ -0,0 +1,78 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 731394: Test the debugger source editor default context menu.
*/
const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gContextMenu;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gContextMenu = gDebugger.document.getElementById("sourceEditorContextMenu");
waitForSourceAndCaretAndScopes(gPanel, "-02.js", 6).then(performTest);
gDebuggee.firstCall();
});
function performTest() {
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
is(gSources.itemCount, 2,
"Found the expected number of sources.");
is(gEditor.getText().indexOf("debugger"), 172,
"The correct source was loaded initially.");
is(gSources.selectedValue, gSources.values[1],
"The correct source is selected.");
is(gEditor.getText().indexOf("\u263a"), 162,
"Unicode characters are converted correctly.");
ok(gContextMenu,
"The source editor's context menupopup is available.");
ok(gEditor.readOnly,
"The source editor is read only.");
gEditor.focus();
gEditor.setSelection(0, 10);
once(gContextMenu, "popupshown").then(testContextMenu);
gContextMenu.openPopup(gEditor.editorElement, "overlap", 0, 0, true, false);
}
function testContextMenu() {
let document = gDebugger.document;
ok(document.getElementById("editMenuCommands"),
"#editMenuCommands found.");
ok(!document.getElementById("editMenuKeys"),
"#editMenuKeys not found.");
ok(document.getElementById("sourceEditorCommands"),
"#sourceEditorCommands found.");
// Map command ids to their expected disabled state.
let commands = {"se-cmd-undo": true, "se-cmd-redo": true,
"se-cmd-cut": true, "se-cmd-paste": true,
"se-cmd-delete": true, "cmd_findAgain": true,
"cmd_findPrevious": true, "cmd_find": false,
"cmd_gotoLine": false, "cmd_copy": false,
"se-cmd-selectAll": false};
for (let id in commands) {
is(document.getElementById(id).hasAttribute("disabled"), commands[id],
"The element with id: " + id + " hasAttribute('disabled').");
}
gContextMenu.hidePopup();
resumeDebuggerThenCloseAndFinish(gPanel);
}
}

View File

@ -0,0 +1,93 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that updating the editor mode sets the right highlighting engine,
* and source URIs with extra query parameters also get the right engine.
*/
const TAB_URL = EXAMPLE_URL + "doc_editor-mode.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
waitForSourceAndCaretAndScopes(gPanel, "code_test-editor-mode", 5)
.then(testInitialSource)
.then(testSwitch1)
.then(testSwitch2)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
gDebuggee.firstCall();
});
}
function testInitialSource() {
is(gSources.itemCount, 3,
"Found the expected number of sources.");
is(gEditor.getMode(), SourceEditor.MODES.TEXT,
"Found the expected editor mode.");
is(gEditor.getText().search(/firstCall/), -1,
"The first source is not displayed.");
is(gEditor.getText().search(/debugger/), 141,
"The second source is displayed.");
is(gEditor.getText().search(/banana/), -1,
"The third source is not displayed.");
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
gSources.selectedLabel = "code_script-switching-01.js";
return finished;
}
function testSwitch1() {
is(gSources.itemCount, 3,
"Found the expected number of sources.");
is(gEditor.getMode(), SourceEditor.MODES.JAVASCRIPT,
"Found the expected editor mode.");
is(gEditor.getText().search(/firstCall/), 118,
"The first source is displayed.");
is(gEditor.getText().search(/debugger/), -1,
"The second source is not displayed.");
is(gEditor.getText().search(/banana/), -1,
"The third source is not displayed.");
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.SOURCE_SHOWN);
gSources.selectedLabel = "doc_editor-mode.html";
return finished;
}
function testSwitch2() {
is(gSources.itemCount, 3,
"Found the expected number of sources.");
is(gEditor.getMode(), SourceEditor.MODES.HTML,
"Found the expected editor mode.");
is(gEditor.getText().search(/firstCall/), -1,
"The first source is not displayed.");
is(gEditor.getText().search(/debugger/), -1,
"The second source is not displayed.");
is(gEditor.getText().search(/banana/), 443,
"The third source is displayed.");
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
});

View File

@ -1,91 +1,126 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the eventListeners request works.
*/
// Tests that the eventListeners request works.
const TAB_URL = EXAMPLE_URL + "doc_event-listeners.html";
var gClient = null;
var gTab = null;
var gThreadClient = null;
const DEBUGGER_TAB_URL = EXAMPLE_URL + "test-event-listeners.html";
let gClient;
function test() {
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
function test()
{
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect(function(aType, aTraits) {
gTab = addTab(DEBUGGER_TAB_URL, function() {
attach_thread_actor_for_url(gClient,
DEBUGGER_TAB_URL,
function(threadClient) {
gThreadClient = threadClient;
testEventListeners();
gClient.connect((aType, aTraits) => {
is(aType, "browser",
"Root actor should identify itself as a browser.");
addTab(TAB_URL)
.then(() => attachThreadActorForUrl(gClient, TAB_URL))
.then(pauseDebuggee)
.then(testEventListeners)
.then(closeConnection)
.then(finish)
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
});
}
function testEventListeners()
{
gClient.addOneTimeListener("paused", function(aEvent, aPacket) {
is(aPacket.why.type, "debuggerStatement", "debugger statement was hit.");
gThreadClient.eventListeners(function(aPacket) {
is(aPacket.listeners.length, 3, "Found all event listeners.");
let types = [];
for (let l of aPacket.listeners) {
let node = l.node;
ok(node, "There is a node property.");
ok(node.object, "There is a node object property.");
ok(node.selector == "window" ||
content.document.querySelectorAll(node.selector).length == 1,
"The node property is a unique CSS selector");
ok(l.function, "There is a function property.");
is(l.function.type, "object", "The function form is of type 'object'.");
is(l.function.class, "Function", "The function form is of class 'Function'.");
is(l.function.url, DEBUGGER_TAB_URL, "The function url is correct.");
is(l.allowsUntrusted, true,
"allowsUntrusted property has the right value.");
is(l.inSystemEventGroup, false,
"inSystemEventGroup property has the right value.");
function pauseDebuggee(aThreadClient) {
let deferred = promise.defer();
types.push(l.type);
gClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.type, "paused",
"We should now be paused.");
is(aPacket.why.type, "debuggerStatement",
"The debugger statement was hit.");
if (l.type == "keyup") {
is(l.capturing, true, "Capturing property has the right value.");
is(l.isEventHandler, false,
"isEventHandler property has the right value.");
} else if (l.type == "load") {
is(l.capturing, false, "Capturing property has the right value.");
is(l.isEventHandler, false,
"isEventHandler property has the right value.");
} else {
is(l.capturing, false, "Capturing property has the right value.");
is(l.isEventHandler, true,
"isEventHandler property has the right value.");
}
deferred.resolve(aThreadClient);
});
// Spin the event loop before causing the debuggee to pause, to allow
// this function to return first.
executeSoon(() => {
EventUtils.sendMouseEvent({ type: "click" },
content.document.querySelector("button"),
content);
});
return deferred.promise;
}
function testEventListeners(aThreadClient) {
let deferred = promise.defer();
aThreadClient.eventListeners(aPacket => {
is(aPacket.listeners.length, 3,
"Found all event listeners.");
let types = [];
for (let l of aPacket.listeners) {
let node = l.node;
ok(node, "There is a node property.");
ok(node.object, "There is a node object property.");
ok(node.selector == "window" ||
content.document.querySelectorAll(node.selector).length == 1,
"The node property is a unique CSS selector.");
let func = l.function;
ok(func, "There is a function property.");
is(func.type, "object", "The function form is of type 'object'.");
is(func.class, "Function", "The function form is of class 'Function'.");
is(func.url, TAB_URL, "The function url is correct.");
is(l.allowsUntrusted, true,
"'allowsUntrusted' property has the right value.");
is(l.inSystemEventGroup, false,
"'inSystemEventGroup' property has the right value.");
types.push(l.type);
if (l.type == "keyup") {
is(l.capturing, true,
"Capturing property has the right value.");
is(l.isEventHandler, false,
"'isEventHandler' property has the right value.");
} else if (l.type == "load") {
is(l.capturing, false,
"Capturing property has the right value.");
is(l.isEventHandler, false,
"'isEventHandler' property has the right value.");
} else {
is(l.capturing, false,
"Capturing property has the right value.");
is(l.isEventHandler, true,
"'isEventHandler' property has the right value.");
}
ok(types.indexOf("click") != -1, "Found the click handler.");
ok(types.indexOf("change") != -1, "Found the change handler.");
ok(types.indexOf("keyup") != -1, "Found the keyup handler.");
finish_test();
});
}
ok(types.indexOf("click") != -1, "Found the click handler.");
ok(types.indexOf("change") != -1, "Found the change handler.");
ok(types.indexOf("keyup") != -1, "Found the keyup handler.");
aThreadClient.resume(deferred.resolve);
});
EventUtils.sendMouseEvent({ type: "click" },
content.document.querySelector("button"));
return deferred.promise;
}
function finish_test()
{
gThreadClient.resume(function() {
gClient.close(finish);
});
function closeConnection() {
let deferred = promise.defer();
gClient.close(deferred.resolve);
return deferred.promise;
}
registerCleanupFunction(function() {
removeTab(gTab);
gTab = null;
removeTab(gBrowser.selectedTab);
gClient = null;
gThreadClient = null;
});

View File

@ -1,36 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<title>Debugger Function Call Parameter Test</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript">
window.addEventListener("load", function() {
function test(aArg, bArg, cArg, dArg, eArg, fArg) {
var a = 1;
var b = { a: a };
var c = { a: 1, b: "beta", c: true, d: b };
var myVar = {
_prop: 42,
get prop() { return this._prop; },
set prop(val) { this._prop = val; }
};
debugger;
}
function load() {
var a = { a: 1, b: "beta", c: true };
var e = eval("test(a, 'beta', 3, false, null)");
}
var button = document.querySelector("button");
button.addEventListener("click", load, false);
var buttonAsProto = Object.create(button);
});
</script>
</head>
<body>
<button>Click me!</button>
</body>
</html>

View File

@ -0,0 +1,63 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that anonymous functions appear in the stack frame list with either
* their displayName property or a SpiderMonkey-inferred name.
*/
const TAB_URL = EXAMPLE_URL + "doc_function-display-name.html";
let gTab, gDebuggee, gPanel, gDebugger;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
testAnonCall();
});
}
function testAnonCall() {
waitForSourceAndCaretAndScopes(gPanel, ".html", 15).then(() => {
ok(isCaretPos(gPanel, 15),
"The source editor caret position was incorrect.");
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
is(gDebugger.document.querySelectorAll(".dbg-stackframe").length, 3,
"Should have three frames.");
is(gDebugger.document.querySelector("#stackframe-0 .dbg-stackframe-title").getAttribute("value"),
"anonFunc", "Frame name should be 'anonFunc'.");
testInferredName();
});
gDebuggee.evalCall();
}
function testInferredName() {
waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES).then(() => {
ok(isCaretPos(gPanel, 15),
"The source editor caret position was incorrect.");
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
is(gDebugger.document.querySelectorAll(".dbg-stackframe").length, 3,
"Should have three frames.");
is(gDebugger.document.querySelector("#stackframe-0 .dbg-stackframe-title").getAttribute("value"),
"a/<", "Frame name should be 'a/<'.");
resumeDebuggerThenCloseAndFinish(gPanel);
});
gDebugger.gThreadClient.resume();
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
});

View File

@ -1,17 +0,0 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset='utf-8'/>
<title>Browser Debugger Function Search</title>
<script type="text/javascript" src="test-function-search-01.js"></script>
<script type="text/javascript" src="test-function-search-02.js"></script>
<script type="text/javascript" src="test-function-search-03.js"></script>
</head>
<body>
<p>Peanut butter jelly time!</p>
</body>
</html>

View File

@ -1,29 +0,0 @@
<!DOCTYPE HTML>
<html>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<head>
<meta charset='utf-8'/>
<title>Browser Debugger Function Search</title>
<script type="text/javascript" src="test-function-search-01.js"></script>
<script type="text/javascript" src="test-function-search-02.js"></script>
<script type="text/javascript" src="test-function-search-03.js"></script>
</head>
<body>
<p>Peanut butter jelly time!</p>
<script type="text/javascript;version=1.8">
function inline() {}
let arrow = () => {}
let foo = bar => {}
let foo2 = bar2 = baz2 => 42;
setTimeout((foo, bar, baz) => {});
setTimeout((foo, bar, baz) => 42);
</script>
</body>
</html>

View File

@ -1,499 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TAB_URL = EXAMPLE_URL + "browser_dbg_function-search-02.html";
/**
* Tests if the function searching works properly.
*/
let gPane = null;
let gTab = null;
let gDebuggee = null;
let gDebugger = null;
let gEditor = null;
let gSources = null;
let gSearchBox = null;
let gFilteredFunctions = null;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
Services.tm.currentThread.dispatch({ run: testFunctionsFilter }, 0);
});
});
}
function testFunctionsFilter()
{
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
gFilteredFunctions = gDebugger.DebuggerView.FilteredFunctions;
htmlSearch(function() {
showSource("test-function-search-01.js", function() {
firstSearch(function() {
showSource("test-function-search-02.js", function() {
secondSearch(function() {
showSource("test-function-search-03.js", function() {
thirdSearch(function() {
saveSearch(function() {
filterSearch(function() {
bogusSearch(function() {
anotherSearch(function() {
emptySearch(function() {
closeDebuggerAndFinish();
});
})
})
});
});
});
});
});
});
});
});
});
}
function htmlSearch(callback) {
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
info("Current script url:\n" + gSources.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
ok(gFilteredFunctions.selectedValue,
"An item should be selected in the filtered functions view");
ok(gFilteredFunctions.selectedLabel,
"An item should be selected in the filtered functions view");
let url = gSources.selectedValue;
if (url.indexOf("-02.html") != -1) {
executeSoon(function() {
let expectedResults = [
["inline", "-02.html", "", 16, 15],
["arrow", "-02.html", "", 17, 10],
["foo", "-02.html", "", 19, 10],
["foo2", "-02.html", "", 20, 10],
["bar2", "-02.html", "", 20, 17]
];
for (let [label, value, description, line, col] of expectedResults) {
is(gFilteredFunctions.selectedItem.label,
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
ok(gFilteredFunctions.selectedItem.value.contains(value),
"The corect value (" + value + ") is attached.");
is(gFilteredFunctions.selectedItem.description, description,
"The corect description (" + description + ") is currently shown.");
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
ok(gEditor.getCaretPosition().line == line &&
gEditor.getCaretPosition().col == col,
"The editor didn't jump to the correct line.");
ok(gSources.selectedLabel, label,
"The current source isn't the correct one, according to the label.");
ok(gSources.selectedValue, value,
"The current source isn't the correct one, according to the value.");
EventUtils.sendKey("DOWN", gDebugger);
}
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
gEditor.getCaretPosition().col == expectedResults[0][4],
"The editor didn't jump to the correct line again.");
executeSoon(callback);
});
} else {
ok(false, "How did you get here? Go away, you.");
}
});
write("@");
}
function firstSearch(callback) {
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
info("Current script url:\n" + gSources.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
ok(gFilteredFunctions.selectedValue,
"An item should be selected in the filtered functions view");
ok(gFilteredFunctions.selectedLabel,
"An item should be selected in the filtered functions view");
let url = gSources.selectedValue;
if (url.indexOf("-01.js") != -1) {
executeSoon(function() {
let s = " " + gDebugger.L10N.getStr("functionSearchSeparatorLabel") + " ";
let expectedResults = [
["test", "-01.js", "", 3, 9],
["anonymousExpression", "-01.js", "test.prototype", 8, 2],
["namedExpression" + s + "NAME", "-01.js", "test.prototype", 10, 2],
["a_test", "-01.js", "foo", 21, 2],
["n_test" + s + "x", "-01.js", "foo", 23, 2],
["a_test", "-01.js", "foo.sub", 26, 4],
["n_test" + s + "y", "-01.js", "foo.sub", 28, 4],
["a_test", "-01.js", "foo.sub.sub", 31, 6],
["n_test" + s + "z", "-01.js", "foo.sub.sub", 33, 6],
["test_SAME_NAME", "-01.js", "foo.sub.sub.sub", 36, 8]
];
for (let [label, value, description, line, col] of expectedResults) {
is(gFilteredFunctions.selectedItem.label,
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
ok(gFilteredFunctions.selectedItem.value.contains(value),
"The corect value (" + value + ") is attached.");
is(gFilteredFunctions.selectedItem.description, description,
"The corect description (" + description + ") is currently shown.");
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
ok(gEditor.getCaretPosition().line == line &&
gEditor.getCaretPosition().col == col,
"The editor didn't jump to the correct line.");
ok(gSources.selectedLabel, label,
"The current source isn't the correct one, according to the label.");
ok(gSources.selectedValue, value,
"The current source isn't the correct one, according to the value.");
EventUtils.sendKey("DOWN", gDebugger);
}
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
gEditor.getCaretPosition().col == expectedResults[0][4],
"The editor didn't jump to the correct line again.");
executeSoon(callback);
});
} else {
ok(false, "How did you get here? Go away, you.");
}
});
write("@");
}
function secondSearch(callback) {
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
info("Current script url:\n" + gSources.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
ok(gFilteredFunctions.selectedValue,
"An item should be selected in the filtered functions view");
ok(gFilteredFunctions.selectedLabel,
"An item should be selected in the filtered functions view");
let url = gSources.selectedValue;
if (url.indexOf("-02.js") != -1) {
executeSoon(function() {
let s = " " + gDebugger.L10N.getStr("functionSearchSeparatorLabel") + " ";
let expectedResults = [
["test2", "-02.js", "", 3, 4],
["test3" + s + "test3_NAME", "-02.js", "", 7, 4],
["test4_SAME_NAME", "-02.js", "", 10, 4],
["x" + s + "X", "-02.js", "test.prototype", 13, 0],
["y" + s + "Y", "-02.js", "test.prototype.sub", 15, 0],
["z" + s + "Z", "-02.js", "test.prototype.sub.sub", 17, 0],
["t", "-02.js", "test.prototype.sub.sub.sub", 19, 0],
["x", "-02.js", "", 19, 31],
["y", "-02.js", "", 19, 40],
["z", "-02.js", "", 19, 49]
];
for (let [label, value, description, line, col] of expectedResults) {
is(gFilteredFunctions.selectedItem.label,
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
ok(gFilteredFunctions.selectedItem.value.contains(value),
"The corect value (" + value + ") is attached.");
is(gFilteredFunctions.selectedItem.description, description,
"The corect description (" + description + ") is currently shown.");
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
ok(gEditor.getCaretPosition().line == line &&
gEditor.getCaretPosition().col == col,
"The editor didn't jump to the correct line.");
ok(gSources.selectedLabel, label,
"The current source isn't the correct one, according to the label.");
ok(gSources.selectedValue, value,
"The current source isn't the correct one, according to the value.");
EventUtils.sendKey("DOWN", gDebugger);
}
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
gEditor.getCaretPosition().col == expectedResults[0][4],
"The editor didn't jump to the correct line again.");
executeSoon(callback);
});
} else {
ok(false, "How did you get here? Go away, you.");
}
});
write("@");
}
function thirdSearch(callback) {
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
info("Current script url:\n" + gSources.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
ok(gFilteredFunctions.selectedValue,
"An item should be selected in the filtered functions view");
ok(gFilteredFunctions.selectedLabel,
"An item should be selected in the filtered functions view");
let url = gSources.selectedValue;
if (url.indexOf("-03.js") != -1) {
executeSoon(function() {
let s = " " + gDebugger.L10N.getStr("functionSearchSeparatorLabel") + " ";
let expectedResults = [
["namedEventListener", "-03.js", "", 3, 42],
["a" + s + "A", "-03.js", "bar", 9, 4],
["b" + s + "B", "-03.js", "bar.alpha", 14, 4],
["c" + s + "C", "-03.js", "bar.alpha.beta", 19, 4],
["d" + s + "D", "-03.js", "theta", 24, 4],
["fun", "-03.js", "", 28, 6],
["foo", "-03.js", "", 28, 12],
["bar", "-03.js", "", 28, 18],
["t_foo", "-03.js", "", 28, 24],
["w_bar" + s + "baz", "-03.js", "window", 28, 37]
];
for (let [label, value, description, line, col] of expectedResults) {
is(gFilteredFunctions.selectedItem.label,
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
ok(gFilteredFunctions.selectedItem.value.contains(value),
"The corect value (" + value + ") is attached.");
is(gFilteredFunctions.selectedItem.description, description,
"The corect description (" + description + ") is currently shown.");
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
ok(gEditor.getCaretPosition().line == line &&
gEditor.getCaretPosition().col == col,
"The editor didn't jump to the correct line.");
ok(gSources.selectedLabel, label,
"The current source isn't the correct one, according to the label.");
ok(gSources.selectedValue, value,
"The current source isn't the correct one, according to the value.");
EventUtils.sendKey("DOWN", gDebugger);
}
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
gEditor.getCaretPosition().col == expectedResults[0][4],
"The editor didn't jump to the correct line again.");
executeSoon(callback);
});
} else {
ok(false, "How did you get here? Go away, you.");
}
});
write("@");
}
function filterSearch(callback) {
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
info("Current script url:\n" + gSources.selectedValue + "\n");
info("Debugger editor text:\n" + gEditor.getText() + "\n");
ok(gFilteredFunctions.selectedValue,
"An item should be selected in the filtered functions view");
ok(gFilteredFunctions.selectedLabel,
"An item should be selected in the filtered functions view");
let url = gSources.selectedValue;
if (url.indexOf("-03.js") != -1) {
executeSoon(function() {
let s = " " + gDebugger.L10N.getStr("functionSearchSeparatorLabel") + " ";
let expectedResults = [
["namedEventListener", "-03.js", "", 3, 42],
["a" + s + "A", "-03.js", "bar", 9, 4],
["bar", "-03.js", "", 28, 18],
["w_bar" + s + "baz", "-03.js", "window", 28, 37],
["test3" + s + "test3_NAME", "-02.js", "", 7, 4],
["test4_SAME_NAME", "-02.js", "", 10, 4],
["anonymousExpression", "-01.js", "test.prototype", 8, 2],
["namedExpression" + s + "NAME", "-01.js", "test.prototype", 10, 2],
["a_test", "-01.js", "foo", 21, 2],
["a_test", "-01.js", "foo.sub", 26, 4]
];
for (let [label, value, description, line, col] of expectedResults) {
is(gFilteredFunctions.selectedItem.label,
gDebugger.SourceUtils.trimUrlLength(label + "()"),
"The corect label (" + label + ") is currently selected.");
ok(gFilteredFunctions.selectedItem.value.contains(value),
"The corect value (" + value + ") is attached.");
is(gFilteredFunctions.selectedItem.description, description,
"The corect description (" + description + ") is currently shown.");
info("Editor caret position: " + gEditor.getCaretPosition().toSource());
ok(gEditor.getCaretPosition().line == line &&
gEditor.getCaretPosition().col == col,
"The editor didn't jump to the correct line.");
ok(gSources.selectedLabel, label,
"The current source isn't the correct one, according to the label.");
ok(gSources.selectedValue, value,
"The current source isn't the correct one, according to the value.");
EventUtils.sendKey("DOWN", gDebugger);
}
ok(gEditor.getCaretPosition().line == expectedResults[0][3] &&
gEditor.getCaretPosition().col == expectedResults[0][4],
"The editor didn't jump to the correct line again.");
executeSoon(callback);
});
} else {
ok(false, "How did you get here? Go away, you.");
}
});
write("@a");
}
function bogusSearch(callback) {
gDebugger.addEventListener("popuphidden", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(true, "Popup was successfully hidden after no matches were found!");
executeSoon(callback);
});
write("@bogus");
}
function anotherSearch(callback) {
gDebugger.addEventListener("popupshown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(true, "Popup was successfully shown after some matches were found!");
executeSoon(callback);
});
write("@NAME");
}
function emptySearch(callback) {
gDebugger.addEventListener("popuphidden", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
ok(true, "Popup was successfully hidden when nothing was searched!");
executeSoon(callback);
});
clear();
}
function showSource(label, callback) {
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
executeSoon(callback);
});
gSources.selectedLabel = label;
}
function saveSearch(callback) {
gDebugger.addEventListener("popuphidden", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
executeSoon(callback);
});
if (Math.random() >= 0.5) {
EventUtils.sendKey("RETURN", gDebugger);
} else {
EventUtils.sendMouseEvent({ type: "click" },
gFilteredFunctions.selectedItem.target,
gDebugger);
}
}
function waitForCaretPos(number, callback)
{
// Poll every few milliseconds until the source editor line is active.
let count = 0;
let intervalID = window.setInterval(function() {
info("count: " + count + " ");
info("caret: " + gEditor.getCaretPosition().line);
if (++count > 50) {
ok(false, "Timed out while polling for the line.");
window.clearInterval(intervalID);
return closeDebuggerAndFinish();
}
if (gEditor.getCaretPosition().line != number) {
return;
}
// We got the source editor at the expected line, it's safe to callback.
window.clearInterval(intervalID);
callback();
}, 100);
}
function clear() {
gSearchBox.focus();
gSearchBox.value = "";
}
function write(text) {
clear();
append(text);
}
function backspace(times) {
for (let i = 0; i < times; i++) {
EventUtils.sendKey("BACK_SPACE", gDebugger);
}
}
function append(text) {
gSearchBox.focus();
for (let i = 0; i < text.length; i++) {
EventUtils.sendChar(text[i], gDebugger);
}
info("Editor caret position: " + gEditor.getCaretPosition().toSource() + "\n");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
gEditor = null;
gSources = null;
gSearchBox = null;
gFilteredFunctions = null;
});

View File

@ -5,61 +5,69 @@
* Check extension-added global actor API.
*/
var gClient = null;
const CHROME_URL = "chrome://mochitests/content/browser/browser/devtools/debugger/test/"
const ACTORS_URL = CHROME_URL + "testactors.js";
function test()
{
DebuggerServer.addActors("chrome://mochitests/content/browser/browser/devtools/debugger/test/testactors.js");
function test() {
let gClient;
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
DebuggerServer.addActors(ACTORS_URL);
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect(function(aType, aTraits) {
is(aType, "browser", "Root actor should identify itself as a browser.");
gClient.listTabs(function(aResponse) {
gClient.connect((aType, aTraits) => {
is(aType, "browser",
"Root actor should identify itself as a browser.");
gClient.listTabs(aResponse => {
let globalActor = aResponse.testGlobalActor1;
ok(globalActor, "Found the test tab actor.")
ok(globalActor.indexOf("testone") >= 0,
"testTabActor's actorPrefix should be used.");
gClient.request({ to: globalActor, type: "ping" }, function(aResponse) {
ok(globalActor.contains("test_one"),
"testGlobalActor1's actorPrefix should be used.");
gClient.request({ to: globalActor, type: "ping" }, aResponse => {
is(aResponse.pong, "pong", "Actor should respond to requests.");
// Send another ping to see if the same actor is used.
gClient.request({ to: globalActor, type: "ping" }, function(aResponse) {
gClient.request({ to: globalActor, type: "ping" }, aResponse => {
is(aResponse.pong, "pong", "Actor should respond to requests.");
// Make sure that lazily-created actors are created only once.
let conn = transport._serverConnection;
// First we look for the pool of global actors.
let extraPools = conn._extraPools;
let globalPool;
for (let pool of extraPools) {
if (Object.keys(pool._actors).some(function(elem) {
if (Object.keys(pool._actors).some(e => {
// Tab actors are in the global pool.
let re = new RegExp(conn._prefix + "tab", "g");
return elem.match(re) !== null;
return e.match(re) !== null;
})) {
globalPool = pool;
break;
}
}
// Then we look if the global pool contains only one test actor.
let actorPrefix = conn._prefix + "testone";
let actorPrefix = conn._prefix + "test_one";
let actors = Object.keys(globalPool._actors).join();
info("Global actors: " + actors);
isnot(actors.indexOf(actorPrefix), -1, "The test actor exists in the pool.");
is(actors.indexOf(actorPrefix), actors.lastIndexOf(actorPrefix),
"Only one actor exists in the pool.");
finish_test();
isnot(actors.indexOf(actorPrefix), -1,
"The test actor exists in the pool.");
is(actors.indexOf(actorPrefix), actors.lastIndexOf(actorPrefix),
"Only one actor exists in the pool.");
gClient.close(finish);
});
});
});
});
}
function finish_test()
{
gClient.close(function() {
finish();
});
}

View File

@ -1,12 +0,0 @@
<!DOCTYPE HTML>
<html>
<head><meta charset='utf-8'/><title>Browser Debugger IFrame Test Tab</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
</head>
<body>
<iframe src="browser_dbg_debuggerstatement.html"></iframe>
</body>
</html>

View File

@ -1,67 +1,67 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that iframes can be added as debuggees.
*/
// Tests that iframes can be added as debuggees.
var gPane = null;
var gTab = null;
var gDebugger = null;
const TEST_URL = EXAMPLE_URL + "browser_dbg_iframes.html";
const TAB_URL = EXAMPLE_URL + "doc_iframes.html";
function test() {
debug_tab_pane(TEST_URL, function(aTab, aDebuggee, aPane) {
let gTab, gDebuggee, gPanel, gDebugger;
let gIframe, gEditor, gSources, gFrames;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gIframe = gDebuggee.frames[0];
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gFrames = gDebugger.DebuggerView.StackFrames;
is(gDebugger.DebuggerController.activeThread.paused, false,
"Should be running after debug_tab_pane.");
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
let frames = gDebugger.DebuggerView.StackFrames.widget._list;
let childNodes = frames.childNodes;
is(gDebugger.DebuggerController.activeThread.paused, true,
"Should be paused after an interrupt request.");
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
"Should have one frame in the stack.");
gDebugger.DebuggerController.activeThread.addOneTimeListener("resumed", function() {
Services.tm.currentThread.dispatch({ run: function() {
closeDebuggerAndFinish();
}}, 0);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}}, 0);
});
let iframe = gTab.linkedBrowser.contentWindow.wrappedJSObject.frames[0];
is(iframe.document.title, "Browser Debugger Test Tab", "Found the iframe");
function handler() {
if (iframe.document.readyState != "complete") {
return;
}
iframe.window.removeEventListener("load", handler, false);
executeSoon(iframe.runDebuggerStatement);
};
iframe.window.addEventListener("load", handler, false);
handler();
waitForSourceShown(gPanel, "inline-debugger-statement.html")
.then(checkIframeSource)
.then(checkIframePause)
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebugger = null;
});
function checkIframeSource() {
is(gDebugger.gThreadClient.paused, false,
"Should be running after starting the test.");
ok(isCaretPos(gPanel, 1),
"The source editor caret position was incorrect.");
is(gFrames.itemCount, 0,
"Should have only no frames.");
is(gSources.itemCount, 1,
"Found the expected number of entries in the sources widget.");
is(gEditor.getText().indexOf("debugger"), 348,
"The correct source was loaded initially.");
is(gSources.selectedLabel, "doc_inline-debugger-statement.html",
"The currently selected source label is incorrect.");
is(gSources.selectedValue, gSources.values[0],
"The currently selected source value is incorrect.");
}
function checkIframePause() {
// Spin the event loop before causing the debuggee to pause, to allow
// this function to return first.
executeSoon(() => gIframe.runDebuggerStatement());
return waitForCaretAndScopes(gPanel, 16).then(() => {
is(gDebugger.gThreadClient.paused, true,
"Should be paused after an interrupt request.");
ok(isCaretPos(gPanel, 16),
"The source editor caret position was incorrect.");
is(gFrames.itemCount, 1,
"Should have only one frame.");
});
}
}

View File

@ -1,29 +1,32 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the debugger panes collapse properly.
*/
// Tests that the debugger panes collapse properly.
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var gView = null;
let gTab, gDebuggee, gPanel, gDebugger;
let gPrefs, gOptions;
function test() {
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gView = gDebugger.DebuggerView;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gPrefs = gDebugger.Prefs;
gOptions = gDebugger.DebuggerView.Options;
testPanesState();
gView.toggleInstrumentsPane({ visible: true, animated: false });
gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
testInstrumentsPaneCollapse();
testPanesStartupPref();
closeDebuggerAndFinish(gPanel);
});
}
@ -36,9 +39,9 @@ function testPanesState() {
ok(instrumentsPane.hasAttribute("pane-collapsed") &&
instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
"The debugger view instruments pane should initially be hidden.");
is(gDebugger.Prefs.panesVisibleOnStartup, false,
is(gPrefs.panesVisibleOnStartup, false,
"The debugger view instruments pane should initially be preffed as hidden.");
isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
isnot(gOptions._showPanesOnStartupItem.getAttribute("checked"), "true",
"The options menu item should not be checked.");
}
@ -49,7 +52,7 @@ function testInstrumentsPaneCollapse() {
gDebugger.document.getElementById("instruments-pane-toggle");
let width = parseInt(instrumentsPane.getAttribute("width"));
is(width, gDebugger.Prefs.instrumentsWidth,
is(width, gPrefs.instrumentsWidth,
"The instruments pane has an incorrect width.");
is(instrumentsPane.style.marginLeft, "0px",
"The instruments pane has an incorrect left margin.");
@ -61,15 +64,15 @@ function testInstrumentsPaneCollapse() {
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
"The instruments pane should at this point be visible.");
gView.toggleInstrumentsPane({ visible: false, animated: true });
gDebugger.DebuggerView.toggleInstrumentsPane({ visible: false, animated: true });
is(gDebugger.Prefs.panesVisibleOnStartup, false,
is(gPrefs.panesVisibleOnStartup, false,
"The debugger view panes should still initially be preffed as hidden.");
isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
isnot(gOptions._showPanesOnStartupItem.getAttribute("checked"), "true",
"The options menu item should still not be checked.");
let margin = -(width + 1) + "px";
is(width, gDebugger.Prefs.instrumentsWidth,
is(width, gPrefs.instrumentsWidth,
"The instruments pane has an incorrect width after collapsing.");
is(instrumentsPane.style.marginLeft, margin,
"The instruments pane has an incorrect left margin after collapsing.");
@ -81,14 +84,14 @@ function testInstrumentsPaneCollapse() {
instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
"The instruments pane should not be visible after collapsing.");
gView.toggleInstrumentsPane({ visible: true, animated: false });
gDebugger.DebuggerView.toggleInstrumentsPane({ visible: true, animated: false });
is(gDebugger.Prefs.panesVisibleOnStartup, false,
is(gPrefs.panesVisibleOnStartup, false,
"The debugger view panes should still initially be preffed as hidden.");
isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
isnot(gOptions._showPanesOnStartupItem.getAttribute("checked"), "true",
"The options menu item should still not be checked.");
is(width, gDebugger.Prefs.instrumentsWidth,
is(width, gPrefs.instrumentsWidth,
"The instruments pane has an incorrect width after uncollapsing.");
is(instrumentsPane.style.marginLeft, "0px",
"The instruments pane has an incorrect left margin after uncollapsing.");
@ -107,53 +110,45 @@ function testPanesStartupPref() {
let instrumentsPaneToggleButton =
gDebugger.document.getElementById("instruments-pane-toggle");
is(gDebugger.Prefs.panesVisibleOnStartup, false,
is(gPrefs.panesVisibleOnStartup, false,
"The debugger view panes should still initially be preffed as hidden.");
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
"The debugger instruments pane should at this point be visible.");
is(gDebugger.Prefs.panesVisibleOnStartup, false,
is(gPrefs.panesVisibleOnStartup, false,
"The debugger view panes should initially be preffed as hidden.");
isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
isnot(gOptions._showPanesOnStartupItem.getAttribute("checked"), "true",
"The options menu item should still not be checked.");
gDebugger.DebuggerView.Options._showPanesOnStartupItem.setAttribute("checked", "true");
gDebugger.DebuggerView.Options._toggleShowPanesOnStartup();
gOptions._showPanesOnStartupItem.setAttribute("checked", "true");
gOptions._toggleShowPanesOnStartup();
executeSoon(function() {
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
"The debugger instruments pane should at this point be visible.");
is(gDebugger.Prefs.panesVisibleOnStartup, true,
"The debugger view panes should now be preffed as visible.");
is(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
"The options menu item should now be checked.");
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
"The debugger instruments pane should at this point be visible.");
is(gPrefs.panesVisibleOnStartup, true,
"The debugger view panes should now be preffed as visible.");
is(gOptions._showPanesOnStartupItem.getAttribute("checked"), "true",
"The options menu item should now be checked.");
gDebugger.DebuggerView.Options._showPanesOnStartupItem.setAttribute("checked", "false");
gDebugger.DebuggerView.Options._toggleShowPanesOnStartup();
gOptions._showPanesOnStartupItem.setAttribute("checked", "false");
gOptions._toggleShowPanesOnStartup();
executeSoon(function() {
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
"The debugger instruments pane should at this point be visible.");
is(gDebugger.Prefs.panesVisibleOnStartup, false,
"The debugger view panes should now be preffed as hidden.");
isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
"The options menu item should now be unchecked.");
executeSoon(function() {
closeDebuggerAndFinish();
});
});
});
ok(!instrumentsPane.hasAttribute("pane-collapsed") &&
!instrumentsPaneToggleButton.hasAttribute("pane-collapsed"),
"The debugger instruments pane should at this point be visible.");
is(gPrefs.panesVisibleOnStartup, false,
"The debugger view panes should now be preffed as hidden.");
isnot(gOptions._showPanesOnStartupItem.getAttribute("checked"), "true",
"The options menu item should now be unchecked.");
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gView = null;
gPrefs = null;
gOptions = null;
});

View File

@ -1,100 +1,114 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Make sure the listAddons request works as specified.
/**
* Make sure the listAddons request works as specified.
*/
const ADDON1_URL = EXAMPLE_URL + "addon1.xpi";
const ADDON2_URL = EXAMPLE_URL + "addon2.xpi";
var gAddon1 = null;
var gAddon1Actor = null;
let gAddon1, gAddon1Actor, gAddon2, gAddon2Actor, gClient;
var gAddon2 = null;
var gAddon2Actor = null;
function test() {
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
var gClient = null;
function test()
{
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect(function (aType, aTraits) {
is(aType, "browser", "Root actor should identify itself as a browser.");
test_first_addon();
})
gClient.connect((aType, aTraits) => {
is(aType, "browser",
"Root actor should identify itself as a browser.");
promise.resolve(null)
.then(testFirstAddon)
.then(testSecondAddon)
.then(testRemoveFirstAddon)
.then(testRemoveSecondAddon)
.then(closeConnection)
.then(finish)
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function test_first_addon()
{
function testFirstAddon() {
let addonListChanged = false;
gClient.addOneTimeListener("addonListChanged", function () {
gClient.addOneTimeListener("addonListChanged", () => {
addonListChanged = true;
});
addAddon(ADDON1_URL, function(aAddon) {
return addAddon(ADDON1_URL).then(aAddon => {
gAddon1 = aAddon;
gClient.listAddons(function(aResponse) {
for each (let addon in aResponse.addons) {
if (addon.url == ADDON1_URL) {
gAddon1Actor = addon.actor;
}
}
return getAddonActorForUrl(gClient, ADDON1_URL).then(aGrip => {
ok(!addonListChanged, "Should not yet be notified that list of addons changed.");
ok(gAddon1Actor, "Should find an addon actor for addon1.");
test_second_addon();
ok(aGrip, "Should find an addon actor for addon1.");
gAddon1Actor = aGrip.actor;
});
});
}
function test_second_addon()
{
function testSecondAddon() {
let addonListChanged = false;
gClient.addOneTimeListener("addonListChanged", function () {
addonListChanged = true;
});
addAddon(ADDON2_URL, function(aAddon) {
return addAddon(ADDON2_URL).then(aAddon => {
gAddon2 = aAddon;
gClient.listAddons(function(aResponse) {
let foundAddon1 = false;
for each (let addon in aResponse.addons) {
if (addon.url == ADDON1_URL) {
is(addon.actor, gAddon1Actor, "Addon1's actor shouldn't have changed.");
foundAddon1 = true;
}
if (addon.url == ADDON2_URL) {
gAddon2Actor = addon.actor;
}
}
ok(addonListChanged, "Should be notified that list of addons changed.");
ok(foundAddon1, "Should find an addon actor for addon1.");
ok(gAddon2Actor, "Should find an actor for addon2.");
test_remove_addon();
return getAddonActorForUrl(gClient, ADDON1_URL).then(aFirstGrip => {
return getAddonActorForUrl(gClient, ADDON2_URL).then(aSecondGrip => {
ok(addonListChanged, "Should be notified that list of addons changed.");
is(aFirstGrip.actor, gAddon1Actor, "First addon's actor shouldn't have changed.");
ok(aSecondGrip, "Should find a addon actor for the second addon.");
gAddon2Actor = aSecondGrip.actor;
});
});
});
}
function test_remove_addon()
{
function testRemoveFirstAddon() {
let addonListChanged = false;
gClient.addOneTimeListener("addonListChanged", function () {
addonListChanged = true;
});
removeAddon(gAddon1, function() {
gClient.listAddons(function(aResponse) {
let foundAddon1 = false;
for each (let addon in aResponse.addons) {
if (addon.url == ADDON1_URL) {
foundAddon1 = true;
}
}
removeAddon(gAddon1).then(() => {
return getAddonActorForUrl(gClient, ADDON1_URL).then(aGrip => {
ok(addonListChanged, "Should be notified that list of addons changed.");
ok(!foundAddon1, "Addon1 should be gone");
finish_test();
ok(!aGrip, "Shouldn't find a addon actor for the first addon anymore.");
});
});
}
function finish_test()
{
removeAddon(gAddon2, function() {
gClient.close(function() {
finish();
function testRemoveSecondAddon() {
let addonListChanged = false;
gClient.addOneTimeListener("addonListChanged", function () {
addonListChanged = true;
});
removeAddon(gAddon2).then(() => {
return getAddonActorForUrl(gClient, ADDON2_URL).then(aGrip => {
ok(addonListChanged, "Should be notified that list of addons changed.");
ok(!aGrip, "Shouldn't find a addon actor for the second addon anymore.");
});
});
}
function closeConnection() {
let deferred = promise.defer();
gClient.close(deferred.resolve);
return deferred.promise;
}
registerCleanupFunction(function() {
gAddon1 = null;
gAddon1Actor = null;
gAddon2 = null;
gAddon2Actor = null;
gClient = null;
});

View File

@ -1,102 +1,101 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Make sure the listTabs request works as specified.
/**
* Make sure the listTabs request works as specified.
*/
var gTab1 = null;
var gTab1Actor = null;
const TAB1_URL = EXAMPLE_URL + "doc_empty-tab-01.html";
const TAB2_URL = EXAMPLE_URL + "doc_empty-tab-02.html";
var gTab2 = null;
var gTab2Actor = null;
let gTab1, gTab1Actor, gTab2, gTab2Actor, gClient;
var gClient = null;
function test() {
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
function test()
{
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect(function(aType, aTraits) {
is(aType, "browser", "Root actor should identify itself as a browser.");
test_first_tab();
gClient.connect((aType, aTraits) => {
is(aType, "browser",
"Root actor should identify itself as a browser.");
promise.resolve(null)
.then(testFirstTab)
.then(testSecondTab)
.then(testRemoveTab)
.then(testAttachRemovedTab)
.then(closeConnection)
.then(finish)
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
/**
* Verify that a new tab shows up in a listTabs call.
*/
function test_first_tab()
{
gTab1 = addTab(TAB1_URL, function() {
gClient.listTabs(function(aResponse) {
for each (let tab in aResponse.tabs) {
if (tab.url == TAB1_URL) {
gTab1Actor = tab.actor;
}
}
ok(gTab1Actor, "Should find a tab actor for tab1.");
test_second_tab();
function testFirstTab() {
return addTab(TAB1_URL).then(aTab => {
gTab1 = aTab;
return getTabActorForUrl(gClient, TAB1_URL).then(aGrip => {
ok(aGrip, "Should find a tab actor for the first tab.");
gTab1Actor = aGrip.actor;
});
});
}
function test_second_tab()
{
gTab2 = addTab(TAB2_URL, function() {
gClient.listTabs(function(aResponse) {
// Verify that tab1 has the same actor it used to.
let foundTab1 = false;
for each (let tab in aResponse.tabs) {
if (tab.url == TAB1_URL) {
is(tab.actor, gTab1Actor, "Tab1's actor shouldn't have changed.");
foundTab1 = true;
}
if (tab.url == TAB2_URL) {
gTab2Actor = tab.actor;
}
}
ok(foundTab1, "Should have found an actor for tab 1.");
ok(gTab2Actor != null, "Should find an actor for tab2.");
function testSecondTab() {
return addTab(TAB2_URL).then(aTab => {
gTab2 = aTab;
test_remove_tab();
return getTabActorForUrl(gClient, TAB1_URL).then(aFirstGrip => {
return getTabActorForUrl(gClient, TAB2_URL).then(aSecondGrip => {
is(aFirstGrip.actor, gTab1Actor, "First tab's actor shouldn't have changed.");
ok(aSecondGrip, "Should find a tab actor for the second tab.");
gTab2Actor = aSecondGrip.actor;
});
});
});
}
function test_remove_tab()
{
removeTab(gTab1);
function testRemoveTab() {
return removeTab(gTab1).then(() => {
return getTabActorForUrl(gClient, TAB1_URL).then(aGrip => {
ok(!aGrip, "Shouldn't find a tab actor for the first tab anymore.");
});
});
}
function testAttachRemovedTab() {
return removeTab(gTab2).then(() => {
let deferred = promise.defer();
gClient.addListener("paused", (aEvent, aPacket) => {
ok(false, "Attaching to an exited tab actor shouldn't generate a pause.");
deferred.reject();
});
gClient.request({ to: gTab2Actor, type: "attach" }, aResponse => {
is(aResponse.type, "exited", "Tab should consider itself exited.");
deferred.resolve();
});
return deferred.promise;
});
}
function closeConnection() {
let deferred = promise.defer();
gClient.close(deferred.resolve);
return deferred.promise;
}
registerCleanupFunction(function() {
gTab1 = null;
gClient.listTabs(function(aResponse) {
// Verify that tab1 is no longer included in listTabs.
let foundTab1 = false;
for each (let tab in aResponse.tabs) {
if (tab.url == TAB1_URL) {
ok(false, "Tab1 should be gone.");
}
}
ok(!foundTab1, "Tab1 should be gone.");
test_attach_removed_tab();
});
}
function test_attach_removed_tab()
{
removeTab(gTab2);
gTab1Actor = null;
gTab2 = null;
gClient.addListener("paused", function(aEvent, aPacket) {
ok(false, "Attaching to an exited tab actor shouldn't generate a pause.");
finish_test();
});
gClient.request({ to: gTab2Actor, type: "attach" }, function(aResponse) {
is(aResponse.type, "exited", "Tab should consider itself exited.");
finish_test();
});
}
function finish_test()
{
gClient.close(function() {
finish();
});
}
gTab2Actor = null;
gClient = null;
});

View File

@ -1,17 +1,19 @@
/* 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/. */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Make sure the root actor's live tab list implementation works as specified.
/**
* Make sure the root actor's live tab list implementation works as specified.
*/
let gTestPage = "data:text/html;charset=utf-8," + encodeURIComponent(
"<title>JS Debugger BrowserTabList test page</title><body>Yo.</body>");
let testPage = ("data:text/html;charset=utf-8,"
+ encodeURIComponent("<title>JS Debugger BrowserTabList test page</title>" +
"<body>Yo.</body>"));
// The tablist object whose behavior we observe.
let tabList;
let firstActor, actorA;
let tabA, tabB, tabC;
let newWin;
let gTabList;
let gFirstActor, gActorA;
let gTabA, gTabB, gTabC;
let gNewWindow;
// Stock onListChanged handler.
let onListChangedCount = 0;
function onListChangedHandler() {
@ -19,144 +21,190 @@ function onListChangedHandler() {
}
function test() {
tabList = new DebuggerServer.BrowserTabList("fake DebuggerServerConnection");
tabList._testing = true;
tabList.onListChanged = onListChangedHandler;
checkSingleTab(function () {
is(onListChangedCount, 0, "onListChanged handler call count");
tabA = addTab(testPage, onTabA);
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
gTabList = new DebuggerServer.BrowserTabList("fake DebuggerServerConnection");
gTabList._testing = true;
gTabList.onListChanged = onListChangedHandler;
checkSingleTab()
.then(addTabA)
.then(testTabA)
.then(addTabB)
.then(testTabB)
.then(removeTabA)
.then(testTabClosed)
.then(addTabC)
.then(testTabC)
.then(removeTabC)
.then(testNewWindow)
.then(removeNewWindow)
.then(testWindowClosed)
.then(removeTabB)
.then(checkSingleTab)
.then(finish);
}
function checkSingleTab() {
return gTabList.getList().then(aTabActors => {
is(aTabActors.length, 1, "initial tab list: contains initial tab");
gFirstActor = aTabActors[0];
is(gFirstActor.url, "about:blank", "initial tab list: initial tab URL is 'about:blank'");
is(gFirstActor.title, "New Tab", "initial tab list: initial tab title is 'New Tab'");
});
}
function checkSingleTab(callback) {
tabList.getList().then(function (tabActors) {
is(tabActors.length, 1, "initial tab list: contains initial tab");
firstActor = tabActors[0];
is(firstActor.url, "about:blank", "initial tab list: initial tab URL is 'about:blank'");
is(firstActor.title, "New Tab", "initial tab list: initial tab title is 'New Tab'");
callback();
function addTabA() {
return addTab(gTestPage).then(aTab => {
gTabA = aTab;
});
}
function onTabA() {
function testTabA() {
is(onListChangedCount, 1, "onListChanged handler call count");
tabList.getList().then(function (tabActors) {
tabActors = new Set(tabActors);
is(tabActors.size, 2, "tabA opened: two tabs in list");
ok(tabActors.has(firstActor), "tabA opened: initial tab present");
return gTabList.getList().then(aTabActors => {
let tabActors = new Set(aTabActors);
is(tabActors.size, 2, "gTabA opened: two tabs in list");
ok(tabActors.has(gFirstActor), "gTabA opened: initial tab present");
info("actors: " + [a.url for (a of tabActors)]);
actorA = [a for (a of tabActors) if (a !== firstActor)][0];
ok(actorA.url.match(/^data:text\/html;/), "tabA opened: new tab URL");
is(actorA.title, "JS Debugger BrowserTabList test page", "tabA opened: new tab title");
tabB = addTab(testPage, onTabB);
gActorA = [a for (a of tabActors) if (a !== gFirstActor)][0];
ok(gActorA.url.match(/^data:text\/html;/), "gTabA opened: new tab URL");
is(gActorA.title, "JS Debugger BrowserTabList test page", "gTabA opened: new tab title");
});
}
function onTabB() {
function addTabB() {
return addTab(gTestPage).then(aTab => {
gTabB = aTab;
});
}
function testTabB() {
is(onListChangedCount, 2, "onListChanged handler call count");
tabList.getList().then(function (tabActors) {
tabActors = new Set(tabActors);
is(tabActors.size, 3, "tabB opened: three tabs in list");
// Test normal close.
gBrowser.tabContainer.addEventListener("TabClose", function onClose(aEvent) {
gBrowser.tabContainer.removeEventListener("TabClose", onClose, false);
ok(!aEvent.detail, "This was a normal tab close");
// Let the actor's TabClose handler finish first.
executeSoon(testTabClose);
}, false);
gBrowser.removeTab(tabA);
return gTabList.getList().then(aTabActors => {
let tabActors = new Set(aTabActors);
is(tabActors.size, 3, "gTabB opened: three tabs in list");
});
}
function testTabClose() {
function removeTabA() {
let deferred = promise.defer();
once(gBrowser.tabContainer, "TabClose").then(aEvent => {
ok(!aEvent.detail, "This was a normal tab close");
// Let the actor's TabClose handler finish first.
executeSoon(deferred.resolve);
}, false);
removeTab(gTabA);
return deferred.promise;
}
function testTabClosed() {
is(onListChangedCount, 3, "onListChanged handler call count");
tabList.getList().then(function (tabActors) {
tabActors = new Set(tabActors);
is(tabActors.size, 2, "tabA closed: two tabs in list");
ok(tabActors.has(firstActor), "tabA closed: initial tab present");
gTabList.getList().then(aTabActors => {
let tabActors = new Set(aTabActors);
is(tabActors.size, 2, "gTabA closed: two tabs in list");
ok(tabActors.has(gFirstActor), "gTabA closed: initial tab present");
info("actors: " + [a.url for (a of tabActors)]);
actorA = [a for (a of tabActors) if (a !== firstActor)][0];
ok(actorA.url.match(/^data:text\/html;/), "tabA closed: new tab URL");
is(actorA.title, "JS Debugger BrowserTabList test page", "tabA closed: new tab title");
// Test tab close by moving tab to a window.
tabC = addTab(testPage, onTabC);
gActorA = [a for (a of tabActors) if (a !== gFirstActor)][0];
ok(gActorA.url.match(/^data:text\/html;/), "gTabA closed: new tab URL");
is(gActorA.title, "JS Debugger BrowserTabList test page", "gTabA closed: new tab title");
});
}
function onTabC() {
function addTabC() {
return addTab(gTestPage).then(aTab => {
gTabC = aTab;
});
}
function testTabC() {
is(onListChangedCount, 4, "onListChanged handler call count");
tabList.getList().then(function (tabActors) {
tabActors = new Set(tabActors);
is(tabActors.size, 3, "tabC opened: three tabs in list");
gBrowser.tabContainer.addEventListener("TabClose", function onClose2(aEvent) {
gBrowser.tabContainer.removeEventListener("TabClose", onClose2, false);
ok(aEvent.detail, "This was a tab closed by moving");
// Let the actor's TabClose handler finish first.
executeSoon(testWindowClose);
}, false);
newWin = gBrowser.replaceTabWithWindow(tabC);
gTabList.getList().then(aTabActors => {
let tabActors = new Set(aTabActors);
is(tabActors.size, 3, "gTabC opened: three tabs in list");
});
}
function testWindowClose() {
function removeTabC() {
let deferred = promise.defer();
once(gBrowser.tabContainer, "TabClose").then(aEvent => {
ok(aEvent.detail, "This was a tab closed by moving");
// Let the actor's TabClose handler finish first.
executeSoon(deferred.resolve);
}, false);
gNewWindow = gBrowser.replaceTabWithWindow(gTabC);
return deferred.promise;
}
function testNewWindow() {
is(onListChangedCount, 5, "onListChanged handler call count");
tabList.getList().then(function (tabActors) {
tabActors = new Set(tabActors);
is(tabActors.size, 3, "tabC closed: three tabs in list");
ok(tabActors.has(firstActor), "tabC closed: initial tab present");
return gTabList.getList().then(aTabActors => {
let tabActors = new Set(aTabActors);
is(tabActors.size, 3, "gTabC closed: three tabs in list");
ok(tabActors.has(gFirstActor), "gTabC closed: initial tab present");
info("actors: " + [a.url for (a of tabActors)]);
actorA = [a for (a of tabActors) if (a !== firstActor)][0];
ok(actorA.url.match(/^data:text\/html;/), "tabC closed: new tab URL");
is(actorA.title, "JS Debugger BrowserTabList test page", "tabC closed: new tab title");
// Cleanup.
newWin.addEventListener("unload", function onUnload(aEvent) {
newWin.removeEventListener("unload", onUnload, false);
ok(!aEvent.detail, "This was a normal window close");
// Let the actor's TabClose handler finish first.
executeSoon(checkWindowClose);
}, false);
newWin.close();
gActorA = [a for (a of tabActors) if (a !== gFirstActor)][0];
ok(gActorA.url.match(/^data:text\/html;/), "gTabC closed: new tab URL");
is(gActorA.title, "JS Debugger BrowserTabList test page", "gTabC closed: new tab title");
});
}
function checkWindowClose() {
function removeNewWindow() {
let deferred = promise.defer();
once(gNewWindow, "unload").then(aEvent => {
ok(!aEvent.detail, "This was a normal window close");
// Let the actor's TabClose handler finish first.
executeSoon(deferred.resolve);
}, false);
gNewWindow.close();
return deferred.promise;
}
function testWindowClosed() {
is(onListChangedCount, 6, "onListChanged handler call count");
// Check that closing a XUL window leaves the other actors intact.
tabList.getList().then(function (tabActors) {
tabActors = new Set(tabActors);
is(tabActors.size, 2, "newWin closed: two tabs in list");
ok(tabActors.has(firstActor), "newWin closed: initial tab present");
return gTabList.getList().then(aTabActors => {
let tabActors = new Set(aTabActors);
is(tabActors.size, 2, "gNewWindow closed: two tabs in list");
ok(tabActors.has(gFirstActor), "gNewWindow closed: initial tab present");
info("actors: " + [a.url for (a of tabActors)]);
actorA = [a for (a of tabActors) if (a !== firstActor)][0];
ok(actorA.url.match(/^data:text\/html;/), "newWin closed: new tab URL");
is(actorA.title, "JS Debugger BrowserTabList test page", "newWin closed: new tab title");
// Test normal close.
gBrowser.tabContainer.addEventListener("TabClose", function onClose(aEvent) {
gBrowser.tabContainer.removeEventListener("TabClose", onClose, false);
ok(!aEvent.detail, "This was a normal tab close");
// Let the actor's TabClose handler finish first.
executeSoon(finishTest);
}, false);
gBrowser.removeTab(tabB);
gActorA = [a for (a of tabActors) if (a !== gFirstActor)][0];
ok(gActorA.url.match(/^data:text\/html;/), "gNewWindow closed: new tab URL");
is(gActorA.title, "JS Debugger BrowserTabList test page", "gNewWindow closed: new tab title");
});
}
function finishTest() {
checkSingleTab(finish);
function removeTabB() {
let deferred = promise.defer();
once(gBrowser.tabContainer, "TabClose").then(aEvent => {
ok(!aEvent.detail, "This was a normal tab close");
// Let the actor's TabClose handler finish first.
executeSoon(deferred.resolve);
}, false);
removeTab(gTabB);
return deferred.promise;
}

View File

@ -0,0 +1,78 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that changing the tab location URL works.
*/
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gFrames;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gFrames = gDebugger.DebuggerView.StackFrames;
waitForSourceAndCaretAndScopes(gPanel, ".html", 14).then(performTest);
gDebuggee.simpleCall();
});
}
function performTest() {
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
is(gFrames.itemCount, 1,
"Should have only one frame.");
is(gSources.itemCount, 1,
"Found the expected number of entries in the sources widget.");
isnot(gSources.selectedLabel, null,
"There should be a selected source label.");
isnot(gSources.selectedValue, null,
"There should be a selected source value.");
isnot(gEditor.getText().length, 0,
"The source editor should have some text displayed.");
isnot(gEditor.getText(), gDebugger.L10N.getStr("loadingText"),
"The source editor text should not be 'Loading...'");
is(gSources.widget.getAttribute("label"), "doc_recursion-stack.html",
"The sources widget should have a correct label attribute.");
is(gSources.widget.getAttribute("tooltiptext"), "example.com test",
"The sources widget should have a correct tooltip text attribute.");
is(gDebugger.document.querySelectorAll(".side-menu-widget-empty-notice-container").length, 0,
"The sources widget should not display any notice at this point (1).");
is(gDebugger.document.querySelectorAll(".side-menu-widget-empty-notice").length, 0,
"The sources widget should not display any notice at this point (2).");
is(gDebugger.document.querySelector(".side-menu-widget-empty-notice > label"), null,
"The sources widget should not display a notice at this point (3).");
gDebugger.gThreadClient.resume(() => {
testLocationChange();
});
}
function testLocationChange() {
navigateActiveTabTo(gPanel, "about:blank", gDebugger.EVENTS.SOURCES_ADDED).then(() => {
closeDebuggerAndFinish(gPanel);
});
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
gFrames = null;
});

View File

@ -0,0 +1,71 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that changing the tab location URL to a page with no sources works.
*/
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gFrames;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gFrames = gDebugger.DebuggerView.StackFrames;
waitForSourceAndCaretAndScopes(gPanel, ".html", 14).then(testLocationChange);
gDebuggee.simpleCall();
});
}
function testLocationChange() {
navigateActiveTabTo(gPanel, "about:blank", gDebugger.EVENTS.SOURCES_ADDED).then(() => {
isnot(gDebugger.gThreadClient.state, "paused",
"Should not be paused after a tab navigation.");
is(gFrames.itemCount, 0,
"Should have no frames.");
is(gSources.itemCount, 0,
"Found no entries in the sources widget.");
is(gSources.selectedLabel, "",
"There should be no selected source label.");
is(gSources.selectedValue, "",
"There should be no selected source value.");
is(gEditor.getText().length, 0,
"The source editor should not have any text displayed.");
is(gSources.widget.getAttribute("label"), gDebugger.L10N.getStr("noSourcesText"),
"The sources widget should display a notice that there are no sources availalble.");
is(gSources.widget.getAttribute("tooltiptext"), "",
"The sources widget shouldn't have any tooltip text attribute when there are no sources available.");
is(gDebugger.document.querySelectorAll(".side-menu-widget-empty-notice-container").length, 1,
"The sources widget should now display a notice (1).");
is(gDebugger.document.querySelectorAll(".side-menu-widget-empty-notice").length, 1,
"The sources widget should now display a notice (2).");
is(gDebugger.document.querySelector(".side-menu-widget-empty-notice").getAttribute("value"),
gSources.widget.getAttribute("label"),
"The sources widget should now display a notice (3).");
closeDebuggerAndFinish(gPanel);
});
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
gFrames = null;
});

View File

@ -0,0 +1,73 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that changing the tab location URL to a page with other sources works.
*/
const TAB_URL_1 = EXAMPLE_URL + "doc_recursion-stack.html";
const TAB_URL_2 = EXAMPLE_URL + "doc_iframes.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gFrames;
function test() {
initDebugger(TAB_URL_1).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gFrames = gDebugger.DebuggerView.StackFrames;
waitForSourceAndCaretAndScopes(gPanel, ".html", 14).then(testLocationChange);
gDebuggee.simpleCall();
});
}
function testLocationChange() {
navigateActiveTabTo(gPanel, TAB_URL_2, gDebugger.EVENTS.SOURCES_ADDED).then(() => {
isnot(gDebugger.gThreadClient.state, "paused",
"Should not be paused after a tab navigation.");
is(gFrames.itemCount, 0,
"Should have no frames.");
is(gSources.itemCount, 1,
"Found the expected number of entries in the sources widget.");
is(gSources.selectedLabel, "doc_inline-debugger-statement.html",
"There should be a selected source label.");
is(gSources.selectedValue, EXAMPLE_URL + "doc_inline-debugger-statement.html",
"There should be a selected source value.");
isnot(gEditor.getText().length, 0,
"The source editor should have some text displayed.");
is(gEditor.getText(), gDebugger.L10N.getStr("loadingText"),
"The source editor text should not be 'Loading...'");
is(gSources.widget.getAttribute("label"), "doc_inline-debugger-statement.html",
"The sources widget should have a correct label attribute.");
is(gSources.widget.getAttribute("tooltiptext"), "example.com test",
"The sources widget should have a correct tooltip text attribute.");
is(gDebugger.document.querySelectorAll(".side-menu-widget-empty-notice-container").length, 0,
"The sources widget should not display any notice at this point (1).");
is(gDebugger.document.querySelectorAll(".side-menu-widget-empty-notice").length, 0,
"The sources widget should not display any notice at this point (2).");
is(gDebugger.document.querySelector(".side-menu-widget-empty-notice > label"), null,
"The sources widget should not display a notice at this point (3).");
closeDebuggerAndFinish(gPanel);
});
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
gFrames = null;
});

View File

@ -0,0 +1,197 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that reloading a page with a breakpoint set does not cause it to
* fire more than once.
*/
const TAB_URL = EXAMPLE_URL + "doc_included-script.html";
const SOURCE_URL = EXAMPLE_URL + "code_location-changes.js";
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
waitForSourceAndCaretAndScopes(gPanel, ".html", 17).then(addBreakpoint);
gDebuggee.runDebuggerStatement();
});
}
function addBreakpoint() {
waitForSourceAndCaret(gPanel, ".js", 5).then(() => {
ok(true,
"Switched to the desired function when adding a breakpoint " +
"but not passing { noEditorUpdate: true } as an option.");
testResume();
});
gPanel.addBreakpoint({ url: SOURCE_URL, line: 5 });
}
function testResume() {
is(gDebugger.gThreadClient.state, "paused",
"The breakpoint wasn't hit yet (1).");
is(gSources.selectedValue, SOURCE_URL,
"The currently shown source is incorrect (1).");
ok(isCaretPos(gPanel, 5),
"The source editor caret position is incorrect (1).");
gDebugger.gThreadClient.resume(testClick);
}
function testClick() {
isnot(gDebugger.gThreadClient.state, "paused",
"The breakpoint wasn't hit yet (2).");
is(gSources.selectedValue, SOURCE_URL,
"The currently shown source is incorrect (2).");
ok(isCaretPos(gPanel, 5),
"The source editor caret position is incorrect (2).");
gDebugger.gThreadClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.why.type, "breakpoint",
"Execution has advanced to the breakpoint.");
isnot(aPacket.why.type, "debuggerStatement",
"The breakpoint was hit before the debugger statement.");
afterBreakpointHit();
});
EventUtils.sendMouseEvent({ type: "click" },
gDebuggee.document.querySelector("button"),
gDebuggee);
}
function afterBreakpointHit() {
is(gDebugger.gThreadClient.state, "paused",
"The breakpoint was hit (3).");
is(gSources.selectedValue, SOURCE_URL,
"The currently shown source is incorrect (3).");
ok(isCaretPos(gPanel, 5),
"The source editor caret position is incorrect (3).");
gDebugger.gThreadClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.why.type, "debuggerStatement",
"Execution has advanced to the next line.");
isnot(aPacket.why.type, "breakpoint",
"No ghost breakpoint was hit.");
ensureCaretAt(gPanel, 6, 1, true).then(afterDebuggerStatementHit);
});
gDebugger.gThreadClient.resume();
}
function afterDebuggerStatementHit() {
is(gDebugger.gThreadClient.state, "paused",
"The debugger statement was hit (4).");
is(gSources.selectedValue, SOURCE_URL,
"The currently shown source is incorrect (4).");
ok(isCaretPos(gPanel, 6),
"The source editor caret position is incorrect (4).");
reloadActiveTab(gPanel, gDebugger.EVENTS.SOURCE_SHOWN)
.then(() => ensureThreadClientState(gPanel, "resumed"))
.then(() => testClickAgain());
}
function testClickAgain() {
isnot(gDebugger.gThreadClient.state, "paused",
"The breakpoint wasn't hit yet (5).");
is(gSources.selectedValue, SOURCE_URL,
"The currently shown source is incorrect (5).");
ok(isCaretPos(gPanel, 1),
"The source editor caret position is incorrect (5).");
gDebugger.gThreadClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.why.type, "breakpoint",
"Execution has advanced to the breakpoint.");
isnot(aPacket.why.type, "debuggerStatement",
"The breakpoint was hit before the debugger statement.");
ensureCaretAt(gPanel, 5, 1, true).then(afterBreakpointHitAgain);
});
EventUtils.sendMouseEvent({ type: "click" },
gDebuggee.document.querySelector("button"),
gDebuggee);
}
function afterBreakpointHitAgain() {
is(gDebugger.gThreadClient.state, "paused",
"The breakpoint was hit (6).");
is(gSources.selectedValue, SOURCE_URL,
"The currently shown source is incorrect (6).");
ok(isCaretPos(gPanel, 5),
"The source editor caret position is incorrect (6).");
gDebugger.gThreadClient.addOneTimeListener("paused", (aEvent, aPacket) => {
is(aPacket.why.type, "debuggerStatement",
"Execution has advanced to the next line.");
isnot(aPacket.why.type, "breakpoint",
"No ghost breakpoint was hit.");
ensureCaretAt(gPanel, 6, 1, true).then(afterDebuggerStatementHitAgain);
});
gDebugger.gThreadClient.resume();
}
function afterDebuggerStatementHitAgain() {
is(gDebugger.gThreadClient.state, "paused",
"The debugger statement was hit (7).");
is(gSources.selectedValue, SOURCE_URL,
"The currently shown source is incorrect (7).");
ok(isCaretPos(gPanel, 6),
"The source editor caret position is incorrect (7).");
showSecondSource();
}
function showSecondSource() {
gDebugger.once(gDebugger.EVENTS.SOURCE_SHOWN, () => {
is(gEditor.getText().indexOf("debugger"), 447,
"The correct source is shown in the source editor.")
is(gEditor.getBreakpoints().length, 0,
"No breakpoints should be shown for the second source.");
ensureCaretAt(gPanel, 1, 1, true).then(showFirstSourceAgain);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.querySelectorAll(".side-menu-widget-item-contents")[1],
gDebugger);
}
function showFirstSourceAgain() {
gDebugger.once(gDebugger.EVENTS.SOURCE_SHOWN, () => {
is(gEditor.getText().indexOf("debugger"), 148,
"The correct source is shown in the source editor.")
is(gEditor.getBreakpoints().length, 1,
"One breakpoint should be shown for the first source.");
ensureCaretAt(gPanel, 6, 1, true).then(() => resumeDebuggerThenCloseAndFinish(gPanel));
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.querySelectorAll(".side-menu-widget-item-contents")[0],
gDebugger);
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
});

View File

@ -1,108 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that changing the tab location URL to a page with no scripts works.
*/
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
let url = aEvent.detail.url;
if (url.indexOf("browser_dbg_stack") != -1) {
scriptShown = true;
gDebugger.removeEventListener(aEvent.type, _onEvent);
runTest();
}
});
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
runTest();
});
gDebuggee.simpleCall();
});
function runTest()
{
if (scriptShown && framesAdded) {
Services.tm.currentThread.dispatch({ run: testSimpleCall }, 0);
}
}
}
function testSimpleCall() {
var frames = gDebugger.DebuggerView.StackFrames.widget._list,
childNodes = frames.childNodes;
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
"Should have only one frame.");
is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
"All children should be frames.");
isnot(gDebugger.DebuggerView.Sources.selectedValue, null,
"There should be a selected script.");
isnot(gDebugger.editor.getText().length, 0,
"The source editor should have some text displayed.");
isnot(gDebugger.editor.getText(), gDebugger.L10N.getStr("loadingText"),
"The source editor text should not be 'Loading...'");
testLocationChange();
}
function testLocationChange()
{
gDebugger.DebuggerController.activeThread.resume(function() {
gDebugger.DebuggerController._target.once("navigate", function onTabNavigated(aEvent, aPacket) {
ok(true, "tabNavigated event was fired.");
info("Still attached to the tab.");
gDebugger.addEventListener("Debugger:AfterSourcesAdded", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
is(gDebugger.DebuggerView.Sources.selectedValue, "",
"There should be no selected script.");
is(gDebugger.editor.getText().length, 0,
"The source editor not have any text displayed.");
let menulist = gDebugger.DebuggerView.Sources.widget;
let noScripts = gDebugger.L10N.getStr("noSourcesText");
is(menulist.getAttribute("label"), noScripts,
"The menulist should display a notice that there are no scripts availalble.");
is(menulist.getAttribute("tooltiptext"), "",
"The menulist shouldn't have any tooltip text attributed when there are no scripts available.");
closeDebuggerAndFinish();
});
});
gDebugger.DebuggerController.client.activeTab.navigateTo("about:blank");
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

View File

@ -1,163 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that reloading a page with a breakpoint set does not cause it to
* fire more than once.
*/
const TAB_URL = EXAMPLE_URL + "test-location-changes-bp.html";
const SCRIPT_URL = EXAMPLE_URL + "test-location-changes-bp.js";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
var sourcesShown = false;
var tabNavigated = false;
function test()
{
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
testAddBreakpoint();
});
}
function testAddBreakpoint()
{
let controller = gDebugger.DebuggerController;
controller.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({ run: function() {
var frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(controller.activeThread.state, "paused",
"The debugger statement was reached.");
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
"Should have one frame.");
gPane.addBreakpoint({ url: SCRIPT_URL, line: 5 }, testResume);
}}, 0);
});
gDebuggee.runDebuggerStatement();
}
function testResume()
{
is(gDebugger.DebuggerController.activeThread.state, "paused",
"The breakpoint wasn't hit yet.");
let thread = gDebugger.DebuggerController.activeThread;
thread.addOneTimeListener("resumed", function() {
thread.addOneTimeListener("paused", function() {
executeSoon(testBreakpointHit);
});
EventUtils.sendMouseEvent({ type: "click" },
content.document.querySelector("button"));
});
thread.resume();
}
function testBreakpointHit()
{
is(gDebugger.DebuggerController.activeThread.state, "paused",
"The breakpoint was hit.");
let thread = gDebugger.DebuggerController.activeThread;
thread.addOneTimeListener("paused", function test(aEvent, aPacket) {
thread.addOneTimeListener("resumed", function() {
executeSoon(testReloadPage);
});
is(aPacket.why.type, "debuggerStatement", "Execution has advanced to the next line.");
isnot(aPacket.why.type, "breakpoint", "No ghost breakpoint was hit.");
thread.resume();
});
thread.resume();
}
function testReloadPage()
{
let controller = gDebugger.DebuggerController;
controller._target.once("navigate", function onTabNavigated(aEvent, aPacket) {
tabNavigated = true;
ok(true, "tabNavigated event was fired.");
info("Still attached to the tab.");
clickAgain();
});
gDebugger.addEventListener("Debugger:SourceShown", function onSourcesShown() {
sourcesShown = true;
gDebugger.removeEventListener("Debugger:SourceShown", onSourcesShown);
clickAgain();
});
gDebugger.DebuggerController.client.activeTab.reload();
}
function clickAgain()
{
if (!sourcesShown || !tabNavigated) {
return;
}
let controller = gDebugger.DebuggerController;
controller.activeThread.addOneTimeListener("paused", function(aEvent, aPacket) {
is(aPacket.why.type, "breakpoint",
"The breakpoint was hit.");
let thread = gDebugger.DebuggerController.activeThread;
thread.addOneTimeListener("paused", function test(aEvent, aPacket) {
thread.addOneTimeListener("resumed", function() {
executeSoon(closeDebuggerAndFinish);
});
is(aPacket.why.type, "debuggerStatement", "Execution has advanced to the next line.");
isnot(aPacket.why.type, "breakpoint", "No ghost breakpoint was hit.");
thread.resume();
});
thread.resume();
});
EventUtils.sendMouseEvent({ type: "click" },
content.document.querySelector("button"));
}
function testBreakpointHitAfterReload()
{
is(gDebugger.DebuggerController.activeThread.state, "paused",
"The breakpoint was hit.");
let thread = gDebugger.DebuggerController.activeThread;
thread.addOneTimeListener("paused", function test(aEvent, aPacket) {
thread.addOneTimeListener("resumed", function() {
executeSoon(closeDebuggerAndFinish);
});
is(aPacket.why.type, "debuggerStatement", "Execution has advanced to the next line.");
isnot(aPacket.why.type, "breakpoint", "No ghost breakpoint was hit.");
thread.resume();
});
thread.resume();
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

View File

@ -1,109 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that changing the tab location URL to a page with other scripts works.
*/
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
let url = aEvent.detail.url;
if (url.indexOf("browser_dbg_stack") != -1) {
scriptShown = true;
gDebugger.removeEventListener(aEvent.type, _onEvent);
runTest();
}
});
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
framesAdded = true;
runTest();
});
gDebuggee.simpleCall();
});
function runTest()
{
if (scriptShown && framesAdded) {
Services.tm.currentThread.dispatch({ run: testSimpleCall }, 0);
}
}
}
function testSimpleCall() {
var frames = gDebugger.DebuggerView.StackFrames.widget._list,
childNodes = frames.childNodes;
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
"Should have only one frame.");
is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
"All children should be frames.");
isnot(gDebugger.DebuggerView.Sources.selectedValue, null,
"There should be a selected script.");
isnot(gDebugger.editor.getText().length, 0,
"The source editor should have some text displayed.");
isnot(gDebugger.editor.getText(), gDebugger.L10N.getStr("loadingText"),
"The source editor text should not be 'Loading...'");
testLocationChange();
}
function testLocationChange()
{
gDebugger.DebuggerController.activeThread.resume(function() {
gDebugger.DebuggerController._target.once("navigate", function onTabNavigated(aEvent, aPacket) {
ok(true, "tabNavigated event was fired.");
info("Still attached to the tab.");
gDebugger.addEventListener("Debugger:SourceShown", function _onEvent(aEvent) {
gDebugger.removeEventListener(aEvent.type, _onEvent);
isnot(gDebugger.DebuggerView.Sources.selectedValue, null,
"There should be a selected script.");
isnot(gDebugger.editor.getText().length, 0,
"The source editor should have some text displayed.");
let menulist = gDebugger.DebuggerView.Sources.widget;
let noScripts = gDebugger.L10N.getStr("noSourcesText");
isnot(menulist.getAttribute("label"), noScripts,
"The menulist should not display a notice that there are no scripts availalble.");
isnot(menulist.getAttribute("tooltiptext"), "",
"The menulist should have a tooltip text attributed.");
closeDebuggerAndFinish();
});
});
let newLocation = EXAMPLE_URL + "browser_dbg_iframes.html";
gDebugger.DebuggerController.client.activeTab.navigateTo(newLocation);
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

View File

@ -1,69 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that changing the tab location URL works.
*/
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
function test()
{
debug_tab_pane(STACK_URL, function(aTab, aDebuggee, aPane) {
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
testSimpleCall();
});
}
function testSimpleCall() {
gDebugger.DebuggerController.activeThread.addOneTimeListener("framesadded", function() {
Services.tm.currentThread.dispatch({
run: function() {
var frames = gDebugger.DebuggerView.StackFrames.widget._list,
childNodes = frames.childNodes;
is(gDebugger.DebuggerController.activeThread.state, "paused",
"Should only be getting stack frames while paused.");
is(frames.querySelectorAll(".dbg-stackframe").length, 1,
"Should have only one frame.");
is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
"All children should be frames.");
testLocationChange();
}
}, 0);
});
gDebuggee.simpleCall();
}
function testLocationChange()
{
gDebugger.DebuggerController.activeThread.resume(function() {
gDebugger.DebuggerController._target.once("navigate", function onTabNavigated(aEvent, aPacket) {
ok(true, "tabNavigated event was fired.");
info("Still attached to the tab.");
closeDebuggerAndFinish();
});
gDebugger.DebuggerController.client.activeTab.navigateTo(TAB1_URL);
});
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

View File

@ -1,45 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// We make sure the menuitems in the application menubar
// are checked.
function test() {
var tab1 = addTab("about:blank", function() {
var tab2 = addTab("about:blank", function() {
gBrowser.selectedTab = tab2;
let pane = DebuggerUI.toggleDebugger();
ok(pane, "toggleDebugger() should return a pane.");
let frame = pane._frame;
wait_for_connect_and_resume(function() {
let cmd = document.getElementById("Tools:Debugger");
is(cmd.getAttribute("checked"), "true", "<command Tools:Debugger> is checked.");
gBrowser.selectedTab = tab1;
is(cmd.getAttribute("checked"), "false", "<command Tools:Debugger> is unchecked after tab switch.");
gBrowser.selectedTab = tab2;
is(cmd.getAttribute("checked"), "true", "<command Tools:Debugger> is checked.");
let pane = DebuggerUI.toggleDebugger();
is(cmd.getAttribute("checked"), "false", "<command Tools:Debugger> is unchecked once closed.");
});
window.addEventListener("Debugger:Shutdown", function dbgShutdown() {
window.removeEventListener("Debugger:Shutdown", dbgShutdown, true);
removeTab(tab1);
removeTab(tab2);
finish();
}, true);
});
});
}

View File

@ -1,142 +1,164 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Make sure that the debugger attaches to the right tab when multiple windows
// are open.
/**
* Make sure that the debugger attaches to the right tab when multiple windows
* are open.
*/
var gTab1 = null;
var gTab1Actor = null;
const TAB1_URL = EXAMPLE_URL + "doc_script-switching-01.html";
const TAB2_URL = EXAMPLE_URL + "doc_script-switching-02.html";
var gSecondWindow = null;
let gNewTab, gNewWindow;
let gClient;
var gClient = null;
var windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
function test() {
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
function test()
{
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect(function(aType, aTraits) {
is(aType, "browser", "Root actor should identify itself as a browser.");
test_first_tab();
gClient.connect((aType, aTraits) => {
is(aType, "browser",
"Root actor should identify itself as a browser.");
promise.resolve(null)
.then(() => addTab(TAB1_URL))
.then(testFirstTab)
.then(() => addWindow(TAB2_URL))
.then(testNewWindow)
.then(testFocusFirst)
.then(testRemoveTab)
.then(closeConnection)
.then(finish)
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function test_first_tab()
{
gTab1 = addTab(TAB1_URL, function() {
gClient.listTabs(function(aResponse) {
for each (let tab in aResponse.tabs) {
if (tab.url == TAB1_URL) {
gTab1Actor = tab.actor;
}
}
ok(gTab1Actor, "Should find a tab actor for tab1.");
is(aResponse.selected, 1, "Tab1 is selected.");
test_open_window();
function testFirstTab(aTab) {
let deferred = promise.defer();
gNewTab = aTab;
ok(!!gNewTab, "Second tab created.");
gClient.listTabs(aResponse => {
let tabActor = aResponse.tabs.filter(aGrip => aGrip.url == TAB1_URL).pop();
ok(tabActor,
"Should find a tab actor for the first tab.");
is(aResponse.selected, 1,
"The first tab is selected.");
deferred.resolve();
});
return deferred.promise;
}
function testNewWindow(aWindow) {
let deferred = promise.defer();
gNewWindow = aWindow;
ok(!!gNewWindow, "Second window created.");
gNewWindow.focus();
let topWindow = Services.wm.getMostRecentWindow("navigator:browser");
is(topWindow, gNewWindow,
"The second window is on top.");
let isActive = promise.defer();
let isLoaded = promise.defer();
promise.all([isActive.promise, isLoaded.promise]).then(() => {
gNewWindow.BrowserChromeTest.runWhenReady(() => {
gClient.listTabs(aResponse => {
is(aResponse.selected, 2,
"The second tab is selected.");
deferred.resolve();
});
});
});
}
function test_open_window()
{
gSecondWindow = window.open(TAB2_URL, "secondWindow");
ok(!!gSecondWindow, "Second window created.");
gSecondWindow.focus();
let top = windowMediator.getMostRecentWindow("navigator:browser");
var main2 = gSecondWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
is(top, main2, "The second window is on top.");
let gotLoad = false;
let gotActivate = (Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager).activeWindow == main2);
function maybeWindowLoadedAndActive() {
if (gotLoad && gotActivate) {
top.BrowserChromeTest.runWhenReady(function() {
executeSoon(function() {
gClient.listTabs(function(aResponse) {
is(aResponse.selected, 2, "Tab2 is selected.");
test_focus_first();
});
});
})
}
}
if (!gotActivate) {
main2.addEventListener("activate", function() {
main2.removeEventListener("activate", arguments.callee, true);
gotActivate = true;
maybeWindowLoadedAndActive();
},
true
);
}
main2.document.addEventListener("load", function(e) {
if (e.target.documentURI != TAB2_URL) {
let focusManager = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
if (focusManager.activeWindow != gNewWindow) {
gNewWindow.addEventListener("activate", function onActivate(aEvent) {
if (aEvent.target != gNewWindow) {
return;
}
main2.document.removeEventListener("load", arguments.callee, true);
gotLoad = true;
maybeWindowLoadedAndActive();
},
true
);
}
gNewWindow.removeEventListener("activate", onActivate, true);
isActive.resolve();
}, true);
} else {
isActive.resolve();
}
function test_focus_first()
{
window.content.addEventListener("focus", function onFocus() {
window.content.removeEventListener("focus", onFocus, false);
let top = windowMediator.getMostRecentWindow("navigator:browser");
var main1 = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
is(top, main1, "The first window is on top.");
gClient.listTabs(function(aResponse) {
is(aResponse.selected, 1, "Tab1 is selected after focusing on it.");
test_remove_tab();
});
}, false);
window.content.focus();
}
function test_remove_tab()
{
gSecondWindow.close();
gSecondWindow = null;
removeTab(gTab1);
gTab1 = null;
gClient.listTabs(function(aResponse) {
// Verify that tabs are no longer included in listTabs.
let foundTab1 = false;
let foundTab2 = false;
for (let tab of aResponse.tabs) {
if (tab.url == TAB1_URL) {
foundTab1 = true;
} else if (tab.url == TAB2_URL) {
foundTab2 = true;
let contentLocation = gNewWindow.content.location.href;
if (contentLocation != TAB2_URL) {
gNewWindow.document.addEventListener("load", function onLoad(aEvent) {
if (aEvent.target.documentURI != TAB2_URL) {
return;
}
}
gNewWindow.document.removeEventListener("load", onLoad, true);
isLoaded.resolve();
}, true);
} else {
isLoaded.resolve();
}
return deferred.promise;
}
function testFocusFirst() {
let deferred = promise.defer();
once(window.content, "focus").then(() => {
let topWindow = Services.wm.getMostRecentWindow("navigator:browser");
is(top, getDOMWindow(window),
"The first window is on top.");
gClient.listTabs(aResponse => {
is(aResponse.selected, 1,
"The first tab is selected after focusing on it.");
deferred.resolve();
});
});
window.content.focus();
return deferred.promise;
}
function testRemoveTab() {
gNewWindow.close();
removeTab(gNewTab);
gClient.listTabs(aResponse => {
// Verify that tabs are no longer included in listTabs.
let foundTab1 = aResponse.tabs.some(aGrip => aGrip.url == TAB1_URL);
let foundTab2 = aResponse.tabs.some(aGrip => aGrip.url == TAB2_URL);
ok(!foundTab1, "Tab1 should be gone.");
ok(!foundTab2, "Tab2 should be gone.");
is(aResponse.selected, 0, "The original tab is selected.");
finish_test();
is(aResponse.selected, 0,
"The original tab is selected.");
});
}
function finish_test()
{
gClient.close(function() {
finish();
});
function closeConnection() {
let deferred = promise.defer();
gClient.close(deferred.resolve);
return deferred.promise;
}
registerCleanupFunction(function() {
gNewTab = null;
gNewWindow = null;
gClient = null;
});

View File

@ -1,54 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Check tab attach/navigation.
*/
var gTab1 = null;
var gTab1Actor = null;
var gClient = null;
function test()
{
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect(function(aType, aTraits) {
is(aType, "browser", "Root actor should identify itself as a browser.");
get_tab();
});
}
function get_tab()
{
gTab1 = addTab(TAB1_URL, function() {
get_tab_actor_for_url(gClient, TAB1_URL, function(aGrip) {
gTab1Actor = aGrip.actor;
gClient.request({ to: aGrip.actor, type: "attach" }, function(aResponse) {
gClient.addListener("tabNavigated", function onTabNavigated(aEvent, aPacket) {
dump("onTabNavigated state " + aPacket.state + "\n");
if (aPacket.state == "start") {
return;
}
gClient.removeListener("tabNavigated", onTabNavigated);
is(aPacket.url, TAB2_URL, "Got a tab navigation notification.");
gClient.addOneTimeListener("tabDetached", function (aEvent, aPacket) {
ok(true, "Got a tab detach notification.");
finish_test();
});
removeTab(gTab1);
});
gTab1.linkedBrowser.loadURI(TAB2_URL);
});
});
});
}
function finish_test()
{
gClient.close(function() {
finish();
});
}

View File

@ -0,0 +1,71 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Check tab attach/navigation.
*/
const TAB1_URL = EXAMPLE_URL + "doc_empty-tab-01.html";
const TAB2_URL = EXAMPLE_URL + "doc_empty-tab-02.html";
let gClient;
function test() {
if (!DebuggerServer.initialized) {
DebuggerServer.init(() => true);
DebuggerServer.addBrowserActors();
}
let transport = DebuggerServer.connectPipe();
gClient = new DebuggerClient(transport);
gClient.connect((aType, aTraits) => {
is(aType, "browser",
"Root actor should identify itself as a browser.");
addTab(TAB1_URL)
.then(() => attachTabActorForUrl(gClient, TAB1_URL))
.then(testNavigate)
.then(testDetach)
.then(finish)
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function testNavigate() {
let outstanding = [promise.defer(), promise.defer()];
gClient.addListener("tabNavigated", function onTabNavigated(aEvent, aPacket) {
is(aPacket.url, TAB2_URL,
"Got a tab navigation notification.");
if (aPacket.state == "start") {
ok(true, "Tab started to navigate.");
outstanding[0].resolve();
} else {
ok(true, "Tab finished navigating.");
gClient.removeListener("tabNavigated", onTabNavigated);
outstanding[1].resolve();
}
});
gBrowser.selectedTab.linkedBrowser.loadURI(TAB2_URL);
return promise.all(outstanding.map(e => e.promise));
}
function testDetach() {
let deferred = promise.defer();
gClient.addOneTimeListener("tabDetached", () => {
ok(true, "Got a tab detach notification.");
gClient.close(deferred.resolve);
});
removeTab(gBrowser.selectedTab);
return deferred.promise;
}
registerCleanupFunction(function() {
gClient = null;
});

View File

@ -0,0 +1,75 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that debugger's tab is highlighted when it is paused and not the
* currently selected tool.
*/
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gToolbox, gToolboxTab;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gToolbox = gPanel._toolbox;
gToolboxTab = gToolbox.doc.getElementById("toolbox-tab-jsdebugger");
waitForSourceShown(gPanel, ".html").then(testPause);
});
}
function testPause() {
is(gDebugger.gThreadClient.paused, false,
"Should be running after starting test.");
gDebugger.gThreadClient.addOneTimeListener("paused", () => {
gToolbox.selectTool("webconsole").then(() => {
ok(gToolboxTab.classList.contains("highlighted"),
"The highlighted class is present");
ok(!gToolboxTab.hasAttribute("selected") ||
gToolboxTab.getAttribute("selected") != "true",
"The tab is not selected");
}).then(() => gToolbox.selectTool("jsdebugger")).then(() => {
ok(gToolboxTab.classList.contains("highlighted"),
"The highlighted class is present");
ok(gToolboxTab.hasAttribute("selected") &&
gToolboxTab.getAttribute("selected") == "true",
"...and the tab is selected, so the glow will not be present.");
}).then(testResume);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
function testResume() {
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
gToolbox.selectTool("webconsole").then(() => {
ok(!gToolboxTab.classList.contains("highlighted"),
"The highlighted class is not present now after the resume");
ok(!gToolboxTab.hasAttribute("selected") ||
gToolboxTab.getAttribute("selected") != "true",
"The tab is not selected");
}).then(() => closeDebuggerAndFinish(gPanel));
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gToolbox = null;
gToolboxTab = null;
});

View File

@ -0,0 +1,141 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the toolbox is raised when the debugger gets paused.
*/
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gNewTab, gFocusedWindow, gToolbox, gToolboxTab;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gToolbox = gPanel._toolbox;
gToolboxTab = gToolbox.doc.getElementById("toolbox-tab-jsdebugger");
waitForSourceShown(gPanel, ".html").then(performTest);
});
}
function performTest() {
addTab(TAB_URL).then(aTab => {
isnot(aTab, gTab,
"The newly added tab is different from the debugger's tab.");
is(gBrowser.selectedTab, aTab,
"Debugger's tab is not the selected tab.");
gNewTab = aTab;
gFocusedWindow = window;
testPause();
});
}
function focusMainWindow() {
// Make sure toolbox is not focused.
window.addEventListener("focus", onFocus, true);
info("Focusing main window.")
// Execute soon to avoid any race conditions between toolbox and main window
// getting focused.
executeSoon(() => {
window.focus();
});
}
function onFocus() {
window.removeEventListener("focus", onFocus, true);
info("Main window focused.")
gFocusedWindow = window;
testPause();
}
function testPause() {
is(gDebugger.gThreadClient.paused, false,
"Should be running after starting the test.");
is(gFocusedWindow, window,
"Main window is the top level window before pause.");
if (gToolbox.hostType == devtools.Toolbox.HostType.WINDOW) {
gToolbox._host._window.onfocus = () => {
gFocusedWindow = gToolbox._host._window;
};
}
gDebugger.gThreadClient.addOneTimeListener("paused", () => {
if (gToolbox.hostType == devtools.Toolbox.HostType.WINDOW) {
is(gFocusedWindow, gToolbox._host._window,
"Toolbox window is the top level window on pause.");
} else {
is(gBrowser.selectedTab, gTab,
"Debugger's tab got selected.");
}
gToolbox.selectTool("webconsole").then(() => {
ok(gToolboxTab.classList.contains("highlighted"),
"The highlighted class is present");
ok(!gToolboxTab.hasAttribute("selected") ||
gToolboxTab.getAttribute("selected") != "true",
"The tab is not selected");
}).then(() => gToolbox.selectTool("jsdebugger")).then(() => {
ok(gToolboxTab.classList.contains("highlighted"),
"The highlighted class is present");
ok(gToolboxTab.hasAttribute("selected") &&
gToolboxTab.getAttribute("selected") == "true",
"...and the tab is selected, so the glow will not be present.");
}).then(testResume);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
function testResume() {
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
gToolbox.selectTool("webconsole").then(() => {
ok(!gToolboxTab.classList.contains("highlighted"),
"The highlighted class is not present now after the resume");
ok(!gToolboxTab.hasAttribute("selected") ||
gToolboxTab.getAttribute("selected") != "true",
"The tab is not selected");
}).then(maybeEndTest);
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
}
function maybeEndTest() {
if (gToolbox.hostType == devtools.Toolbox.HostType.BOTTOM) {
info("Switching to a toolbox window host.");
gToolbox.switchHost(devtools.Toolbox.HostType.WINDOW).then(focusMainWindow);
} else {
info("Switching to main window host.");
gToolbox.switchHost(devtools.Toolbox.HostType.BOTTOM).then(() => closeDebuggerAndFinish(gPanel));
}
}
registerCleanupFunction(function() {
// Revert to the default toolbox host, so that the following tests proceed
// normally and not inside a non-default host.
Services.prefs.setCharPref("devtools.toolbox.host", devtools.Toolbox.HostType.BOTTOM);
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
removeTab(gNewTab);
gNewTab = null;
gFocusedWindow = null;
gToolbox = null;
gToolboxTab = null;
});

View File

@ -0,0 +1,83 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that the sources and instruments panels widths are properly
* remembered when the debugger closes.
*/
const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gPrefs, gSources, gInstruments;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gPrefs = gDebugger.Prefs;
gSources = gDebugger.document.getElementById("sources-pane");
gInstruments = gDebugger.document.getElementById("instruments-pane");
waitForSourceShown(gPanel, ".html").then(performTest);
});
function performTest() {
let preferredSw = Services.prefs.getIntPref("devtools.debugger.ui.panes-sources-width");
let preferredIw = Services.prefs.getIntPref("devtools.debugger.ui.panes-instruments-width");
let someWidth1, someWidth2;
do {
someWidth1 = parseInt(Math.random() * 200) + 100;
someWidth2 = parseInt(Math.random() * 300) + 100;
} while ((someWidth1 == preferredSw) || (someWidth2 == preferredIw));
info("Preferred sources width: " + preferredSw);
info("Preferred instruments width: " + preferredIw);
info("Generated sources width: " + someWidth1);
info("Generated instruments width: " + someWidth2);
ok(gPrefs.sourcesWidth,
"The debugger preferences should have a saved sourcesWidth value.");
ok(gPrefs.instrumentsWidth,
"The debugger preferences should have a saved instrumentsWidth value.");
is(gPrefs.sourcesWidth, preferredSw,
"The debugger preferences should have a correct sourcesWidth value.");
is(gPrefs.instrumentsWidth, preferredIw,
"The debugger preferences should have a correct instrumentsWidth value.");
is(gSources.getAttribute("width"), gPrefs.sourcesWidth,
"The sources pane width should be the same as the preferred value.");
is(gInstruments.getAttribute("width"), gPrefs.instrumentsWidth,
"The instruments pane width should be the same as the preferred value.");
gSources.setAttribute("width", someWidth1);
gInstruments.setAttribute("width", someWidth2);
is(gPrefs.sourcesWidth, preferredSw,
"The sources pane width pref should still be the same as the preferred value.");
is(gPrefs.instrumentsWidth, preferredIw,
"The instruments pane width pref should still be the same as the preferred value.");
isnot(gSources.getAttribute("width"), gPrefs.sourcesWidth,
"The sources pane width should not be the preferred value anymore.");
isnot(gInstruments.getAttribute("width"), gPrefs.instrumentsWidth,
"The instruments pane width should not be the preferred value anymore.");
teardown(gPanel).then(() => {
is(gPrefs.sourcesWidth, someWidth1,
"The sources pane width should have been saved by now.");
is(gPrefs.instrumentsWidth, someWidth2,
"The instruments pane width should have been saved by now.");
// Cleanup after ourselves!
Services.prefs.setIntPref("devtools.debugger.ui.panes-sources-width", preferredSw);
Services.prefs.setIntPref("devtools.debugger.ui.panes-instruments-width", preferredIw);
finish();
});
}
}

View File

@ -1,77 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
function test() {
var tab1 = addTab(TAB1_URL, function() {
gBrowser.selectedTab = tab1;
let target1 = TargetFactory.forTab(tab1);
ok(!gDevTools.getToolbox(target1),
"Shouldn't have a debugger panel for this tab yet.");
gDevTools.showToolbox(target1, "jsdebugger").then(function(toolbox) {
let dbg = toolbox.getCurrentPanel();
ok(dbg, "We should have a debugger panel.");
let preferredSw = Services.prefs.getIntPref("devtools.debugger.ui.panes-sources-width");
let preferredIw = Services.prefs.getIntPref("devtools.debugger.ui.panes-instruments-width");
let someWidth1, someWidth2;
do {
someWidth1 = parseInt(Math.random() * 200) + 100;
someWidth2 = parseInt(Math.random() * 200) + 100;
} while (someWidth1 == preferredSw ||
someWidth2 == preferredIw)
let someWidth1 = parseInt(Math.random() * 200) + 100;
let someWidth2 = parseInt(Math.random() * 200) + 100;
info("Preferred sources width: " + preferredSw);
info("Preferred instruments width: " + preferredIw);
info("Generated sources width: " + someWidth1);
info("Generated instruments width: " + someWidth2);
let content = dbg.panelWin;
let sources;
let instruments;
wait_for_connect_and_resume(function() {
ok(content.Prefs.sourcesWidth,
"The debugger preferences should have a saved sourcesWidth value.");
ok(content.Prefs.instrumentsWidth,
"The debugger preferences should have a saved instrumentsWidth value.");
sources = content.document.getElementById("sources-pane");
instruments = content.document.getElementById("instruments-pane");
is(content.Prefs.sourcesWidth, sources.getAttribute("width"),
"The sources pane width should be the same as the preferred value.");
is(content.Prefs.instrumentsWidth, instruments.getAttribute("width"),
"The instruments pane width should be the same as the preferred value.");
sources.setAttribute("width", someWidth1);
instruments.setAttribute("width", someWidth2);
removeTab(tab1);
}, tab1);
window.addEventListener("Debugger:Shutdown", function dbgShutdown() {
window.removeEventListener("Debugger:Shutdown", dbgShutdown, true);
is(content.Prefs.sourcesWidth, sources.getAttribute("width"),
"The sources pane width should have been saved by now.");
is(content.Prefs.instrumentsWidth, instruments.getAttribute("width"),
"The instruments pane width should have been saved by now.");
// Cleanup after ourselves!
Services.prefs.setIntPref("devtools.debugger.ui.panes-sources-width", preferredSw);
Services.prefs.setIntPref("devtools.debugger.ui.panes-instruments-width", preferredIw);
finish();
}, true);
});
});
}

View File

@ -0,0 +1,245 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that pausing on exceptions works.
*/
const TAB_URL = EXAMPLE_URL + "doc_pause-exceptions.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gFrames, gVariables, gPrefs, gOptions;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gFrames = gDebugger.DebuggerView.StackFrames;
gVariables = gDebugger.DebuggerView.Variables;
gPrefs = gDebugger.Prefs;
gOptions = gDebugger.DebuggerView.Options;
is(gPrefs.pauseOnExceptions, false,
"The pause-on-exceptions pref should be disabled by default.");
isnot(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
"The pause-on-exceptions menu item should not be checked.");
testPauseOnExceptionsDisabled()
.then(enablePauseOnExceptions)
.then(disableIgnoreCaughtExceptions)
.then(testPauseOnExceptionsEnabled)
.then(disablePauseOnExceptions)
.then(enableIgnoreCaughtExceptions)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function testPauseOnExceptionsDisabled() {
let finished = waitForCaretAndScopes(gPanel, 26).then(() => {
info("Testing disabled pause-on-exceptions.");
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused (1).");
ok(isCaretPos(gPanel, 26),
"Should be paused on the debugger statement (1).");
let innerScope = gVariables.getScopeAtIndex(0);
let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
is(gFrames.itemCount, 1,
"Should have one frame.");
is(gVariables._store.length, 3,
"Should have three scopes.");
is(innerNodes[0].querySelector(".name").getAttribute("value"), "this",
"Should have the right property name for 'this'.");
is(innerNodes[0].querySelector(".value").getAttribute("value"), "HTMLButtonElement",
"Should have the right property value for 'this'.");
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
isnot(gDebugger.gThreadClient.state, "paused",
"Should not be paused after resuming.");
ok(isCaretPos(gPanel, 26),
"Should be idle on the debugger statement.");
ok(true, "Frames were cleared, debugger didn't pause again.");
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
return finished;
});
EventUtils.sendMouseEvent({ type: "click" },
gDebuggee.document.querySelector("button"),
gDebuggee);
return finished;
}
function testPauseOnExceptionsEnabled() {
let finished = waitForCaretAndScopes(gPanel, 19).then(() => {
info("Testing enabled pause-on-exceptions.");
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
ok(isCaretPos(gPanel, 19),
"Should be paused on the debugger statement.");
let innerScope = gVariables.getScopeAtIndex(0);
let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
is(gFrames.itemCount, 1,
"Should have one frame.");
is(gVariables._store.length, 3,
"Should have three scopes.");
is(innerNodes[0].querySelector(".name").getAttribute("value"), "<exception>",
"Should have the right property name for <exception>.");
is(innerNodes[0].querySelector(".value").getAttribute("value"), "Error",
"Should have the right property value for <exception>.");
let finished = waitForCaretAndScopes(gPanel, 26).then(() => {
info("Testing enabled pause-on-exceptions and resumed after pause.");
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
ok(isCaretPos(gPanel, 26),
"Should be paused on the debugger statement.");
let innerScope = gVariables.getScopeAtIndex(0);
let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
is(gFrames.itemCount, 1,
"Should have one frame.");
is(gVariables._store.length, 3,
"Should have three scopes.");
is(innerNodes[0].querySelector(".name").getAttribute("value"), "this",
"Should have the right property name for 'this'.");
is(innerNodes[0].querySelector(".value").getAttribute("value"), "HTMLButtonElement",
"Should have the right property value for 'this'.");
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
isnot(gDebugger.gThreadClient.state, "paused",
"Should not be paused after resuming.");
ok(isCaretPos(gPanel, 26),
"Should be idle on the debugger statement.");
ok(true, "Frames were cleared, debugger didn't pause again.");
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
return finished;
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
return finished;
});
EventUtils.sendMouseEvent({ type: "click" },
gDebuggee.document.querySelector("button"),
gDebuggee);
return finished;
}
function enablePauseOnExceptions() {
let deferred = promise.defer();
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
is(gPrefs.pauseOnExceptions, true,
"The pause-on-exceptions pref should now be enabled.");
is(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
"The pause-on-exceptions menu item should now be checked.");
ok(true, "Pausing on exceptions was enabled.");
deferred.resolve();
});
gOptions._pauseOnExceptionsItem.setAttribute("checked", "true");
gOptions._togglePauseOnExceptions();
return deferred.promise;
}
function disablePauseOnExceptions() {
let deferred = promise.defer();
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
is(gPrefs.pauseOnExceptions, false,
"The pause-on-exceptions pref should now be disabled.");
isnot(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
"The pause-on-exceptions menu item should now be unchecked.");
ok(true, "Pausing on exceptions was disabled.");
deferred.resolve();
});
gOptions._pauseOnExceptionsItem.setAttribute("checked", "false");
gOptions._togglePauseOnExceptions();
return deferred.promise;
}
function enableIgnoreCaughtExceptions() {
let deferred = promise.defer();
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
is(gPrefs.ignoreCaughtExceptions, true,
"The ignore-caught-exceptions pref should now be enabled.");
is(gOptions._ignoreCaughtExceptionsItem.getAttribute("checked"), "true",
"The ignore-caught-exceptions menu item should now be checked.");
ok(true, "Ignore caught exceptions was enabled.");
deferred.resolve();
});
gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "true");
gOptions._toggleIgnoreCaughtExceptions();
return deferred.promise;
}
function disableIgnoreCaughtExceptions() {
let deferred = promise.defer();
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
is(gPrefs.ignoreCaughtExceptions, false,
"The ignore-caught-exceptions pref should now be disabled.");
isnot(gOptions._ignoreCaughtExceptionsItem.getAttribute("checked"), "true",
"The ignore-caught-exceptions menu item should now be unchecked.");
ok(true, "Ignore caught exceptions was disabled.");
deferred.resolve();
});
gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "false");
gOptions._toggleIgnoreCaughtExceptions();
return deferred.promise;
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gFrames = null;
gVariables = null;
gPrefs = null;
gOptions = null;
});

View File

@ -0,0 +1,201 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure that pausing on exceptions works after reload.
*/
const TAB_URL = EXAMPLE_URL + "doc_pause-exceptions.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gFrames, gVariables, gPrefs, gOptions;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gFrames = gDebugger.DebuggerView.StackFrames;
gVariables = gDebugger.DebuggerView.Variables;
gPrefs = gDebugger.Prefs;
gOptions = gDebugger.DebuggerView.Options;
is(gPrefs.pauseOnExceptions, false,
"The pause-on-exceptions pref should be disabled by default.");
isnot(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
"The pause-on-exceptions menu item should not be checked.");
enablePauseOnExceptions()
.then(disableIgnoreCaughtExceptions)
.then(() => reloadActiveTab(gPanel, gDebugger.EVENTS.SOURCE_SHOWN))
.then(() => ensureThreadClientState(gPanel, "resumed"))
.then(testPauseOnExceptionsAfterReload)
.then(disablePauseOnExceptions)
.then(enableIgnoreCaughtExceptions)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function testPauseOnExceptionsAfterReload() {
let finished = waitForCaretAndScopes(gPanel, 19).then(() => {
info("Testing enabled pause-on-exceptions.");
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
ok(isCaretPos(gPanel, 19),
"Should be paused on the debugger statement.");
let innerScope = gVariables.getScopeAtIndex(0);
let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
is(gFrames.itemCount, 1,
"Should have one frame.");
is(gVariables._store.length, 3,
"Should have three scopes.");
is(innerNodes[0].querySelector(".name").getAttribute("value"), "<exception>",
"Should have the right property name for <exception>.");
is(innerNodes[0].querySelector(".value").getAttribute("value"), "Error",
"Should have the right property value for <exception>.");
let finished = waitForCaretAndScopes(gPanel, 26).then(() => {
info("Testing enabled pause-on-exceptions and resumed after pause.");
is(gDebugger.gThreadClient.state, "paused",
"Should only be getting stack frames while paused.");
ok(isCaretPos(gPanel, 26),
"Should be paused on the debugger statement.");
let innerScope = gVariables.getScopeAtIndex(0);
let innerNodes = innerScope.target.querySelector(".variables-view-element-details").childNodes;
is(gFrames.itemCount, 1,
"Should have one frame.");
is(gVariables._store.length, 3,
"Should have three scopes.");
is(innerNodes[0].querySelector(".name").getAttribute("value"), "this",
"Should have the right property name for 'this'.");
is(innerNodes[0].querySelector(".value").getAttribute("value"), "HTMLButtonElement",
"Should have the right property value for 'this'.");
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
isnot(gDebugger.gThreadClient.state, "paused",
"Should not be paused after resuming.");
ok(isCaretPos(gPanel, 26),
"Should be idle on the debugger statement.");
ok(true, "Frames were cleared, debugger didn't pause again.");
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
return finished;
});
EventUtils.sendMouseEvent({ type: "mousedown" },
gDebugger.document.getElementById("resume"),
gDebugger);
return finished;
});
EventUtils.sendMouseEvent({ type: "click" },
gDebuggee.document.querySelector("button"),
gDebuggee.window);
return finished;
}
function enablePauseOnExceptions() {
let deferred = promise.defer();
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
is(gPrefs.pauseOnExceptions, true,
"The pause-on-exceptions pref should now be enabled.");
is(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
"The pause-on-exceptions menu item should now be checked.");
ok(true, "Pausing on exceptions was enabled.");
deferred.resolve();
});
gOptions._pauseOnExceptionsItem.setAttribute("checked", "true");
gOptions._togglePauseOnExceptions();
return deferred.promise;
}
function disablePauseOnExceptions() {
let deferred = promise.defer();
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
is(gPrefs.pauseOnExceptions, false,
"The pause-on-exceptions pref should now be disabled.");
isnot(gOptions._pauseOnExceptionsItem.getAttribute("checked"), "true",
"The pause-on-exceptions menu item should now be unchecked.");
ok(true, "Pausing on exceptions was disabled.");
deferred.resolve();
});
gOptions._pauseOnExceptionsItem.setAttribute("checked", "false");
gOptions._togglePauseOnExceptions();
return deferred.promise;
}
function enableIgnoreCaughtExceptions() {
let deferred = promise.defer();
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
is(gPrefs.ignoreCaughtExceptions, true,
"The ignore-caught-exceptions pref should now be enabled.");
is(gOptions._ignoreCaughtExceptionsItem.getAttribute("checked"), "true",
"The ignore-caught-exceptions menu item should now be checked.");
ok(true, "Ignore caught exceptions was enabled.");
deferred.resolve();
});
gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "true");
gOptions._toggleIgnoreCaughtExceptions();
return deferred.promise;
}
function disableIgnoreCaughtExceptions() {
let deferred = promise.defer();
gDebugger.gThreadClient.addOneTimeListener("resumed", () => {
is(gPrefs.ignoreCaughtExceptions, false,
"The ignore-caught-exceptions pref should now be disabled.");
isnot(gOptions._ignoreCaughtExceptionsItem.getAttribute("checked"), "true",
"The ignore-caught-exceptions menu item should now be unchecked.");
ok(true, "Ignore caught exceptions was disabled.");
deferred.resolve();
});
gOptions._ignoreCaughtExceptionsItem.setAttribute("checked", "false");
gOptions._toggleIgnoreCaughtExceptions();
return deferred.promise;
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gFrames = null;
gVariables = null;
gPrefs = null;
gOptions = null;
});

Some files were not shown because too many files have changed in this diff Show More