зеркало из https://github.com/mozilla/pjs.git
merge m-c to fx-team
This commit is contained in:
Коммит
07f0680ff2
|
@ -77,10 +77,8 @@ let gBrowserThumbnails = {
|
|||
},
|
||||
|
||||
_capture: function Thumbnails_capture(aBrowser) {
|
||||
if (this._shouldCapture(aBrowser)) {
|
||||
let canvas = this._pageThumbs.capture(aBrowser.contentWindow);
|
||||
this._pageThumbs.store(aBrowser.currentURI.spec, canvas);
|
||||
}
|
||||
if (this._shouldCapture(aBrowser))
|
||||
this._pageThumbs.captureAndStore(aBrowser);
|
||||
},
|
||||
|
||||
_delayedCapture: function Thumbnails_delayedCapture(aBrowser) {
|
||||
|
|
|
@ -1228,12 +1228,12 @@ function BrowserStartup() {
|
|||
if ("arguments" in window && window.arguments[0])
|
||||
uriToLoad = window.arguments[0];
|
||||
|
||||
var isLoadingBlank = uriToLoad == "about:blank";
|
||||
var isLoadingBlank = isBlankPageURL(uriToLoad);
|
||||
var mustLoadSidebar = false;
|
||||
|
||||
prepareForStartup();
|
||||
|
||||
if (uriToLoad && !isLoadingBlank) {
|
||||
if (uriToLoad && uriToLoad != "about:blank") {
|
||||
if (uriToLoad instanceof Ci.nsISupportsArray) {
|
||||
let count = uriToLoad.Count();
|
||||
let specs = [];
|
||||
|
|
|
@ -72,11 +72,13 @@ let PageThumbs = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Creates a canvas containing a thumbnail depicting the given window.
|
||||
* Captures a thumbnail for the given window.
|
||||
* @param aWindow The DOM window to capture a thumbnail from.
|
||||
* @return The newly created canvas containing the image data.
|
||||
* @param aCallback The function to be called when the thumbnail has been
|
||||
* captured. The first argument will be the data stream
|
||||
* containing the image data.
|
||||
*/
|
||||
capture: function PageThumbs_capture(aWindow) {
|
||||
capture: function PageThumbs_capture(aWindow, aCallback) {
|
||||
let telemetryCaptureTime = new Date();
|
||||
let [sw, sh, scale] = this._determineCropSize(aWindow);
|
||||
|
||||
|
@ -94,48 +96,43 @@ let PageThumbs = {
|
|||
// We couldn't draw to the canvas for some reason.
|
||||
}
|
||||
|
||||
Services.telemetry.getHistogramById("FX_THUMBNAILS_CAPTURE_TIME_MS")
|
||||
let telemetry = Services.telemetry;
|
||||
telemetry.getHistogramById("FX_THUMBNAILS_CAPTURE_TIME_MS")
|
||||
.add(new Date() - telemetryCaptureTime);
|
||||
|
||||
return canvas;
|
||||
canvas.mozFetchAsStream(aCallback, this.contentType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stores the image data contained in the given canvas to the underlying
|
||||
* storage.
|
||||
* @param aKey The key to use for the storage.
|
||||
* @param aCanvas The canvas containing the thumbnail's image data.
|
||||
* @param aCallback The function to be called when the canvas data has been
|
||||
* stored (optional).
|
||||
* Captures a thumbnail for the given browser and stores it to the cache.
|
||||
* @param aBrowser The browser to capture a thumbnail for.
|
||||
* @param aCallback The function to be called when finished (optional).
|
||||
*/
|
||||
store: function PageThumbs_store(aKey, aCanvas, aCallback) {
|
||||
let telemetryStoreTime = new Date();
|
||||
captureAndStore: function PageThumbs_captureAndStore(aBrowser, aCallback) {
|
||||
this.capture(aBrowser.contentWindow, function (aInputStream) {
|
||||
let telemetryStoreTime = new Date();
|
||||
|
||||
function finish(aSuccessful) {
|
||||
if (aSuccessful) {
|
||||
Services.telemetry.getHistogramById("FX_THUMBNAILS_STORE_TIME_MS")
|
||||
.add(new Date() - telemetryStoreTime);
|
||||
function finish(aSuccessful) {
|
||||
if (aSuccessful) {
|
||||
Services.telemetry.getHistogramById("FX_THUMBNAILS_STORE_TIME_MS")
|
||||
.add(new Date() - telemetryStoreTime);
|
||||
}
|
||||
|
||||
if (aCallback)
|
||||
aCallback(aSuccessful);
|
||||
}
|
||||
|
||||
if (aCallback)
|
||||
aCallback(aSuccessful);
|
||||
}
|
||||
// Get a writeable cache entry.
|
||||
PageThumbsCache.getWriteEntry(aBrowser.currentURI.spec, function (aEntry) {
|
||||
if (!aEntry) {
|
||||
finish(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
// Get a writeable cache entry.
|
||||
PageThumbsCache.getWriteEntry(aKey, function (aEntry) {
|
||||
if (!aEntry) {
|
||||
finish(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract image data from the canvas.
|
||||
self._readImageData(aCanvas, function (aData) {
|
||||
let outputStream = aEntry.openOutputStream(0);
|
||||
|
||||
// Write the image data to the cache entry.
|
||||
NetUtil.asyncCopy(aData, outputStream, function (aResult) {
|
||||
NetUtil.asyncCopy(aInputStream, outputStream, function (aResult) {
|
||||
let success = Components.isSuccessCode(aResult);
|
||||
if (success)
|
||||
aEntry.markValid();
|
||||
|
@ -147,21 +144,6 @@ let PageThumbs = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Reads the image data from a given canvas and passes it to the callback.
|
||||
* @param aCanvas The canvas to read the image data from.
|
||||
* @param aCallback The function that the image data is passed to.
|
||||
*/
|
||||
_readImageData: function PageThumbs_readImageData(aCanvas, aCallback) {
|
||||
let dataUri = aCanvas.toDataURL(PageThumbs.contentType, "");
|
||||
let uri = Services.io.newURI(dataUri, "UTF8", null);
|
||||
|
||||
NetUtil.asyncFetch(uri, function (aData, aResult) {
|
||||
if (Components.isSuccessCode(aResult) && aData && aData.available())
|
||||
aCallback(aData);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines the crop size for a given content window.
|
||||
* @param aWindow The content window.
|
||||
|
|
|
@ -94,15 +94,12 @@ function whenLoaded(aElement, aCallback) {
|
|||
* @param aMessage The info message to print when comparing the pixel color.
|
||||
*/
|
||||
function captureAndCheckColor(aRed, aGreen, aBlue, aMessage) {
|
||||
let window = gBrowser.selectedTab.linkedBrowser.contentWindow;
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
let key = Date.now();
|
||||
let data = PageThumbs.capture(window);
|
||||
|
||||
// Store the thumbnail in the cache.
|
||||
PageThumbs.store(key, data, function () {
|
||||
// Capture the screenshot.
|
||||
PageThumbs.captureAndStore(browser, function () {
|
||||
let width = 100, height = 100;
|
||||
let thumb = PageThumbs.getThumbnailURL(key, width, height);
|
||||
let thumb = PageThumbs.getThumbnailURL(browser.currentURI.spec, width, height);
|
||||
|
||||
getXULDocument(function (aDocument) {
|
||||
let htmlns = "http://www.w3.org/1999/xhtml";
|
||||
|
|
|
@ -93,16 +93,16 @@ DebuggerView.Stackframes = {
|
|||
let resume = document.getElementById("resume");
|
||||
let status = document.getElementById("status");
|
||||
|
||||
// if we're paused, show a pause label and disable the resume button
|
||||
// If we're paused, show a pause label and a resume label on the button.
|
||||
if (aState === "paused") {
|
||||
status.textContent = DebuggerView.getStr("pausedState");
|
||||
resume.disabled = false;
|
||||
resume.label = DebuggerView.getStr("resumeLabel");
|
||||
} else if (aState === "attached") {
|
||||
// if we're attached, do the opposite
|
||||
// If we're attached, do the opposite.
|
||||
status.textContent = DebuggerView.getStr("runningState");
|
||||
resume.disabled = true;
|
||||
resume.label = DebuggerView.getStr("pauseLabel");
|
||||
} else {
|
||||
// no valid state parameter
|
||||
// No valid state parameter.
|
||||
status.textContent = "";
|
||||
}
|
||||
},
|
||||
|
@ -272,10 +272,14 @@ DebuggerView.Stackframes = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Listener handling the resume button click event.
|
||||
* Listener handling the pause/resume button click event.
|
||||
*/
|
||||
_onResumeButtonClick: function DVF__onResumeButtonClick() {
|
||||
ThreadState.activeThread.resume();
|
||||
if (ThreadState.activeThread.paused) {
|
||||
ThreadState.activeThread.resume();
|
||||
} else {
|
||||
ThreadState.activeThread.interrupt();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1092,6 +1096,17 @@ DebuggerView.Scripts = {
|
|||
return script;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the list of URIs for scripts in the page.
|
||||
*/
|
||||
scriptLocations: function DVS_scriptLocations() {
|
||||
let locations = [];
|
||||
for (let i = 0; i < this._scripts.itemCount; i++) {
|
||||
locations.push(this._scripts.getItemAtIndex(i).value);
|
||||
}
|
||||
return locations;
|
||||
},
|
||||
|
||||
/**
|
||||
* The cached click listener for the scripts container.
|
||||
*/
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<div id="body" class="vbox flex">
|
||||
<xul:toolbar id="dbg-toolbar">
|
||||
<xul:button id="close">&debuggerUI.closeButton;</xul:button>
|
||||
<xul:button id="resume">&debuggerUI.resumeButton;</xul:button>
|
||||
<xul:button id="resume"/>
|
||||
<xul:menulist id="scripts"/>
|
||||
</xul:toolbar>
|
||||
<div id="dbg-content" class="hbox flex">
|
||||
|
|
|
@ -69,6 +69,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_dbg_stack-04.js \
|
||||
browser_dbg_location-changes.js \
|
||||
browser_dbg_script-switching.js \
|
||||
browser_dbg_pause-resume.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/* 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.debuggerWindow;
|
||||
|
||||
testPause();
|
||||
});
|
||||
}
|
||||
|
||||
function testPause() {
|
||||
is(gDebugger.StackFrames.activeThread.paused, false,
|
||||
"Should be running after debug_tab_pane.");
|
||||
|
||||
let button = gDebugger.document.getElementById("resume");
|
||||
is(button.label, gDebugger.DebuggerView.getStr("pauseLabel"),
|
||||
"Button label should be pause when running.");
|
||||
|
||||
gPane.activeThread.addOneTimeListener("paused", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
let frames = gDebugger.DebuggerView.Stackframes._frames;
|
||||
let childNodes = frames.childNodes;
|
||||
|
||||
is(gDebugger.StackFrames.activeThread.paused, true,
|
||||
"Should be paused after an interrupt request.");
|
||||
|
||||
is(button.label, gDebugger.DebuggerView.getStr("resumeLabel"),
|
||||
"Button label should be resume when paused.");
|
||||
|
||||
is(frames.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
"Should have no frames when paused in the main loop.");
|
||||
|
||||
testResume();
|
||||
}}, 0);
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
gDebugger.document.getElementById("resume"),
|
||||
gDebugger);
|
||||
}
|
||||
|
||||
function testResume() {
|
||||
gPane.activeThread.addOneTimeListener("resumed", function() {
|
||||
Services.tm.currentThread.dispatch({ run: function() {
|
||||
|
||||
is(gDebugger.StackFrames.activeThread.paused, false,
|
||||
"Should be paused after an interrupt request.");
|
||||
|
||||
let button = gDebugger.document.getElementById("resume");
|
||||
is(button.label, gDebugger.DebuggerView.getStr("pauseLabel"),
|
||||
"Button label should be pause when running.");
|
||||
|
||||
removeTab(gTab);
|
||||
finish();
|
||||
}}, 0);
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
gDebugger.document.getElementById("resume"),
|
||||
gDebugger);
|
||||
}
|
|
@ -55,8 +55,10 @@ function testFrameParameters()
|
|||
localNodes[1].expand();
|
||||
|
||||
// Poll every few milliseconds until the properties are retrieved.
|
||||
// It's important to set the timer in the chrome window, because the
|
||||
// content window timers are disabled while the debuggee is paused.
|
||||
let count = 0;
|
||||
let intervalID = content.setInterval(function(){
|
||||
let intervalID = window.setInterval(function(){
|
||||
if (++count > 50) {
|
||||
ok(false, "Timed out while polling for the properties.");
|
||||
resumeAndFinish();
|
||||
|
@ -64,7 +66,7 @@ function testFrameParameters()
|
|||
if (!localNodes[0].fetched || !localNodes[1].fetched) {
|
||||
return;
|
||||
}
|
||||
content.clearInterval(intervalID);
|
||||
window.clearInterval(intervalID);
|
||||
is(localNodes[0].querySelector(".property > .title > .key")
|
||||
.textContent, "__proto__ ",
|
||||
"Should have the right property name for __proto__.");
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Mihai Sucan <mihai.sucan@gmail.com> (original author)
|
||||
* Kenny Heaton <kennyheaton@gmail.com>
|
||||
* Spyros Livathinos <livathinos.spyros@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -75,6 +76,8 @@ const ORION_EVENTS = {
|
|||
ContextMenu: "ContextMenu",
|
||||
TextChanged: "ModelChanged",
|
||||
Selection: "Selection",
|
||||
Focus: "Focus",
|
||||
Blur: "Blur",
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Mihai Sucan <mihai.sucan@gmail.com> (original author)
|
||||
* Spyros Livathinos <livathinos.spyros@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -150,6 +151,16 @@ SourceEditor.EVENTS = {
|
|||
* Both ranges are objects which hold two properties: start and end.
|
||||
*/
|
||||
SELECTION: "Selection",
|
||||
|
||||
/**
|
||||
* The focus event is fired when the editor is focused.
|
||||
*/
|
||||
FOCUS: "Focus",
|
||||
|
||||
/**
|
||||
* The blur event is fired when the editor goes out of focus.
|
||||
*/
|
||||
BLUR: "Blur",
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,6 +54,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_bug695035_middle_click_paste.js \
|
||||
browser_bug687160_line_api.js \
|
||||
browser_bug650345_find.js \
|
||||
browser_bug703692_focus_blur.js \
|
||||
head.js \
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource:///modules/source-editor.jsm", tempScope);
|
||||
let SourceEditor = tempScope.SourceEditor;
|
||||
|
||||
let testWin;
|
||||
let editor;
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
|
||||
"<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
|
||||
" title='Test for bug 703692' width='600' height='500'><hbox flex='1'/></window>";
|
||||
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
||||
|
||||
testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
|
||||
testWin.addEventListener("load", function onWindowLoad() {
|
||||
testWin.removeEventListener("load", onWindowLoad, false);
|
||||
waitForFocus(initEditor, testWin);
|
||||
}, false);
|
||||
}
|
||||
|
||||
function initEditor()
|
||||
{
|
||||
let hbox = testWin.document.querySelector("hbox");
|
||||
|
||||
editor = new SourceEditor();
|
||||
editor.init(hbox, {}, editorLoaded);
|
||||
}
|
||||
|
||||
function editorLoaded()
|
||||
{
|
||||
let focusHandler = function(aEvent) {
|
||||
editor.removeEventListener(SourceEditor.EVENTS.FOCUS, focusHandler);
|
||||
editor.addEventListener(SourceEditor.EVENTS.BLUR, blurHandler);
|
||||
|
||||
ok(aEvent, "Focus event fired");
|
||||
window.focus();
|
||||
};
|
||||
|
||||
let blurHandler = function(aEvent) {
|
||||
editor.removeEventListener(SourceEditor.EVENTS.BLUR, blurHandler);
|
||||
|
||||
ok(aEvent, "Blur event fired");
|
||||
executeSoon(testEnd);
|
||||
}
|
||||
|
||||
editor.addEventListener(SourceEditor.EVENTS.FOCUS, focusHandler);
|
||||
|
||||
editor.focus();
|
||||
}
|
||||
|
||||
function testEnd()
|
||||
{
|
||||
if (editor) {
|
||||
editor.destroy();
|
||||
}
|
||||
if (testWin) {
|
||||
testWin.close();
|
||||
}
|
||||
testWin = editor = null;
|
||||
|
||||
waitForFocus(finish, window);
|
||||
}
|
|
@ -125,3 +125,139 @@ gcli.addCommand({
|
|||
document.defaultView.InspectorUI.openInspectorUI(args.node);
|
||||
}
|
||||
});
|
||||
|
||||
let breakpoints = [];
|
||||
|
||||
/**
|
||||
* 'break' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "break",
|
||||
description: gcli.lookup("breakDesc"),
|
||||
manual: gcli.lookup("breakManual")
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'break list' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "break list",
|
||||
description: gcli.lookup("breaklistDesc"),
|
||||
returnType: "html",
|
||||
exec: function(args, context) {
|
||||
if (breakpoints.length === 0) {
|
||||
return gcli.lookup("breaklistNone");
|
||||
}
|
||||
|
||||
let reply = gcli.lookup("breaklistIntro");
|
||||
reply += "<ol>";
|
||||
breakpoints.forEach(function(breakpoint) {
|
||||
let text = gcli.lookupFormat("breaklistLineEntry",
|
||||
[breakpoint.file, breakpoint.line]);
|
||||
reply += "<li>" + text + "</li>";
|
||||
});
|
||||
reply += "</ol>";
|
||||
return reply;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'break add' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "break add",
|
||||
description: gcli.lookup("breakaddDesc"),
|
||||
manual: gcli.lookup("breakaddManual")
|
||||
});
|
||||
|
||||
/**
|
||||
* 'break add line' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "break add line",
|
||||
description: gcli.lookup("breakaddlineDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "file",
|
||||
type: {
|
||||
name: "selection",
|
||||
data: function() {
|
||||
let win = HUDService.currentContext();
|
||||
let dbg = win.DebuggerUI.getDebugger(win.gBrowser.selectedTab);
|
||||
let files = [];
|
||||
if (dbg) {
|
||||
let scriptsView = dbg.frame.contentWindow.DebuggerView.Scripts;
|
||||
for each (let script in scriptsView.scriptLocations()) {
|
||||
files.push(script);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
},
|
||||
description: gcli.lookup("breakaddlineFileDesc")
|
||||
},
|
||||
{
|
||||
name: "line",
|
||||
type: { name: "number", min: 1, step: 10 },
|
||||
description: gcli.lookup("breakaddlineLineDesc")
|
||||
}
|
||||
],
|
||||
returnType: "html",
|
||||
exec: function(args, context) {
|
||||
args.type = "line";
|
||||
let win = HUDService.currentContext();
|
||||
let dbg = win.DebuggerUI.getDebugger(win.gBrowser.selectedTab);
|
||||
if (!dbg) {
|
||||
return gcli.lookup("breakaddDebuggerStopped");
|
||||
}
|
||||
var promise = context.createPromise();
|
||||
let position = { url: args.file, line: args.line };
|
||||
dbg.activeThread.setBreakpoint(position, function(aResponse, aBpClient) {
|
||||
if (aResponse.error) {
|
||||
promise.resolve(gcli.lookupFormat("breakaddFailed",
|
||||
[ aResponse.error ]));
|
||||
return;
|
||||
}
|
||||
args.client = aBpClient;
|
||||
breakpoints.push(args);
|
||||
promise.resolve(gcli.lookup("breakaddAdded"));
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'break del' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "break del",
|
||||
description: gcli.lookup("breakdelDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "breakid",
|
||||
type: {
|
||||
name: "number",
|
||||
min: 0,
|
||||
max: function() { return breakpoints.length - 1; }
|
||||
},
|
||||
description: gcli.lookup("breakdelBreakidDesc")
|
||||
}
|
||||
],
|
||||
returnType: "html",
|
||||
exec: function(args, context) {
|
||||
let breakpoint = breakpoints.splice(args.breakid, 1)[0];
|
||||
var promise = context.createPromise();
|
||||
try {
|
||||
breakpoint.client.remove(function(aResponse) {
|
||||
promise.resolve(gcli.lookup("breakdelRemoved"));
|
||||
});
|
||||
} catch (ex) {
|
||||
// If the debugger has been closed already, don't scare the user.
|
||||
promise.resolve(gcli.lookup("breakdelRemoved"));
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -154,6 +154,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_webconsole_bug_622303_persistent_filters.js \
|
||||
browser_webconsole_window_zombie.js \
|
||||
browser_cached_messages.js \
|
||||
browser_gcli_break.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -228,6 +229,7 @@ _BROWSER_TEST_PAGES = \
|
|||
test-bug-658368-time-methods.html \
|
||||
test-webconsole-error-observer.html \
|
||||
test-for-of.html \
|
||||
browser_gcli_break.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<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>
|
|
@ -0,0 +1,104 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// For more information on GCLI see:
|
||||
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
|
||||
// - https://wiki.mozilla.org/DevTools/Features/GCLI
|
||||
|
||||
// Tests that the break command works as it should
|
||||
|
||||
let tempScope = {};
|
||||
Components.utils.import("resource:///modules/gcli.jsm", tempScope);
|
||||
let gcli = tempScope.gcli;
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/browser_gcli_break.html";
|
||||
registerCleanupFunction(function() {
|
||||
gcliterm = undefined;
|
||||
requisition = undefined;
|
||||
|
||||
Services.prefs.clearUserPref("devtools.gcli.enable");
|
||||
});
|
||||
|
||||
function test() {
|
||||
Services.prefs.setBoolPref("devtools.gcli.enable", true);
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("DOMContentLoaded", onLoad, false);
|
||||
}
|
||||
|
||||
let gcliterm;
|
||||
let requisition;
|
||||
|
||||
function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
|
||||
try {
|
||||
openConsole();
|
||||
|
||||
let hud = HUDService.getHudByWindow(content);
|
||||
gcliterm = hud.gcliterm;
|
||||
requisition = gcliterm.opts.requisition;
|
||||
|
||||
testSetup();
|
||||
testCreateCommands();
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "Caught exception: " + ex)
|
||||
gcli._internal.console.error("Test Failure", ex);
|
||||
closeConsole();
|
||||
finishTest();
|
||||
}
|
||||
}
|
||||
|
||||
function testSetup() {
|
||||
ok(gcliterm, "We have a GCLI term");
|
||||
ok(requisition, "We have a Requisition");
|
||||
}
|
||||
|
||||
function testCreateCommands() {
|
||||
type("brea");
|
||||
is(gcliterm.completeNode.textContent, " break", "Completion for 'brea'");
|
||||
is(requisition.getStatus().toString(), "ERROR", "brea is ERROR");
|
||||
|
||||
type("break");
|
||||
is(requisition.getStatus().toString(), "ERROR", "break is ERROR");
|
||||
|
||||
type("break add");
|
||||
is(requisition.getStatus().toString(), "ERROR", "break add is ERROR");
|
||||
|
||||
type("break add line");
|
||||
is(requisition.getStatus().toString(), "ERROR", "break add line is ERROR");
|
||||
|
||||
let pane = DebuggerUI.toggleDebugger();
|
||||
pane.onConnected = function test_onConnected(aPane) {
|
||||
// Wait for the initial resume.
|
||||
aPane.debuggerWindow.gClient.addOneTimeListener("resumed", function() {
|
||||
delete aPane.onConnected;
|
||||
aPane.debuggerWindow.gClient.activeThread.addOneTimeListener("scriptsadded", function() {
|
||||
type("break add line " + TEST_URI + " " + content.wrappedJSObject.line0);
|
||||
is(requisition.getStatus().toString(), "VALID", "break add line is VALID");
|
||||
requisition.exec();
|
||||
|
||||
type("break list");
|
||||
is(requisition.getStatus().toString(), "VALID", "break list is VALID");
|
||||
requisition.exec();
|
||||
|
||||
aPane.debuggerWindow.gClient.activeThread.resume(function() {
|
||||
type("break del 0");
|
||||
is(requisition.getStatus().toString(), "VALID", "break del 0 is VALID");
|
||||
requisition.exec();
|
||||
|
||||
closeConsole();
|
||||
finishTest();
|
||||
});
|
||||
});
|
||||
// Trigger newScript notifications using eval.
|
||||
content.wrappedJSObject.firstCall();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function type(command) {
|
||||
gcliterm.inputNode.value = command.slice(0, -1);
|
||||
gcliterm.inputNode.focus();
|
||||
EventUtils.synthesizeKey(command.slice(-1), {});
|
||||
}
|
|
@ -19,12 +19,6 @@
|
|||
- button that closes the debugger UI. -->
|
||||
<!ENTITY debuggerUI.closeButton "Close">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.resumeButton): This is the label for the
|
||||
- button that resumes the debugger, after it has reached a paused state. In
|
||||
- a paused state the debugger can be used to inspect stack frames, local,
|
||||
- variables etc. -->
|
||||
<!ENTITY debuggerUI.resumeButton "Resume">
|
||||
|
||||
<!-- LOCALIZATION NOTE (debuggerUI.stackTitle): This is the label for the
|
||||
- widget that displays the call stack frames in the debugger. -->
|
||||
<!ENTITY debuggerUI.stackTitle "Call stack">
|
||||
|
|
|
@ -6,6 +6,14 @@
|
|||
# A good criteria is the language in which you'd find the best
|
||||
# documentation on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (pauseLabel): The label that is displayed on the pause
|
||||
# button when the debugger is in a running state.
|
||||
pauseLabel=Pause
|
||||
|
||||
# LOCALIZATION NOTE (resumeLabel): The label that is displayed on the pause
|
||||
# button when the debugger is in a paused state.
|
||||
resumeLabel=Resume
|
||||
|
||||
# LOCALIZATION NOTE (pausedState): The label that is displayed when the
|
||||
# debugger is in a paused state.
|
||||
pausedState=Paused
|
||||
|
|
|
@ -56,6 +56,75 @@ inspectNodeDesc=CSS selector
|
|||
# on what it does.
|
||||
inspectNodeManual=A CSS selector for use with Document.querySelector which identifies a single element
|
||||
|
||||
# LOCALIZATION NOTE (breakDesc) A very short string used to describe the
|
||||
# function of the break command.
|
||||
breakDesc=Manage breakpoints
|
||||
|
||||
# LOCALIZATION NOTE (breakManual) A longer description describing the
|
||||
# set of commands that control breakpoints.
|
||||
breakManual=Commands to list, add and remove breakpoints
|
||||
|
||||
# LOCALIZATION NOTE (breaklistDesc) A very short string used to describe the
|
||||
# function of the 'break list' command.
|
||||
breaklistDesc=Display known breakpoints
|
||||
|
||||
# LOCALIZATION NOTE (breaklistLineEntry) Used in the output of the 'break list'
|
||||
# command to display a single line breakpoint.
|
||||
# %1$S=script URL, %2$S=line number
|
||||
breaklistLineEntry=Line breakpoint at %1$S:%2$S
|
||||
|
||||
# LOCALIZATION NOTE (breaklistNone) Used in the output of the 'break list'
|
||||
# command to explain that the list is empty.
|
||||
breaklistNone=No breakpoints set
|
||||
|
||||
# LOCALIZATION NOTE (breaklistIntro) Used in the output of the 'break list'
|
||||
# command to preface the list contents.
|
||||
breaklistIntro=The following breakpoints are set:
|
||||
|
||||
# LOCALIZATION NOTE (breakaddAdded) Used in the output of the 'break add'
|
||||
# command to explain that a breakpoint was added.
|
||||
breakaddAdded=Added breakpoint
|
||||
|
||||
# LOCALIZATION NOTE (breakaddFailed) Used in the output of the 'break add'
|
||||
# command to explain that a breakpoint could not be added.
|
||||
breakaddFailed=Could not set breakpoint: %S
|
||||
|
||||
# LOCALIZATION NOTE (breakaddDesc) A very short string used to describe the
|
||||
# function of the 'break add' command.
|
||||
breakaddDesc=Add a breakpoint
|
||||
|
||||
# LOCALIZATION NOTE (breakaddManual) A longer description describing the
|
||||
# set of commands that are responsible for adding breakpoints.
|
||||
breakaddManual=Breakpoint types supported: line
|
||||
|
||||
# LOCALIZATION NOTE (breakaddDebuggerStopped) Used in the output of the
|
||||
# 'break add' command to explain that the debugger must be opened first.
|
||||
breakaddDebuggerStopped=The debugger must be opened before setting breakpoints
|
||||
|
||||
# LOCALIZATION NOTE (breakaddlineDesc) A very short string used to describe the
|
||||
# function of the 'break add line' command.
|
||||
breakaddlineDesc=Add a line breakpoint
|
||||
|
||||
# LOCALIZATION NOTE (breakaddlineFileDesc) A very short string used to describe
|
||||
# the function of the file parameter in the 'break add line' command.
|
||||
breakaddlineFileDesc=JS file URI
|
||||
|
||||
# LOCALIZATION NOTE (breakaddlineLineDesc) A very short string used to describe
|
||||
# the function of the line parameter in the 'break add line' command.
|
||||
breakaddlineLineDesc=Line number
|
||||
|
||||
# LOCALIZATION NOTE (breakdelDesc) A very short string used to describe the
|
||||
# function of the 'break del' command.
|
||||
breakdelDesc=Remove a breakpoint
|
||||
|
||||
# LOCALIZATION NOTE (breakdelBreakidDesc) A very short string used to describe
|
||||
# the function of the index parameter in the 'break del' command.
|
||||
breakdelBreakidDesc=Index of breakpoint
|
||||
|
||||
# LOCALIZATION NOTE (breakdelRemoved) Used in the output of the 'break del'
|
||||
# command to explain that a breakpoint was removed.
|
||||
breakdelRemoved=Breakpoint removed
|
||||
|
||||
# LOCALIZATION NOTE (consolecloseDesc) A very short description of the
|
||||
# 'console close' command. This string is designed to be shown in a menu
|
||||
# alongside the command name, which is why it should be as short as possible.
|
||||
|
|
|
@ -172,7 +172,7 @@ PrivateBrowsingStorage.prototype = {
|
|||
* Clears the storage and removes all values.
|
||||
*/
|
||||
clear: function PrivateBrowsingStorage_clear() {
|
||||
this._data.listkeys().forEach(function (akey) {
|
||||
this._data.listkeys().forEach(function (aKey) {
|
||||
this._data.del(aKey);
|
||||
}, this);
|
||||
}
|
||||
|
|
|
@ -194,6 +194,16 @@ const ThreadStateTypes = {
|
|||
"detached": "detached"
|
||||
};
|
||||
|
||||
/**
|
||||
* Set of protocol messages that are sent by the server without a prior request
|
||||
* by the client.
|
||||
*/
|
||||
const UnsolicitedNotifications = {
|
||||
"newScript": "newScript",
|
||||
"tabDetached": "tabDetached",
|
||||
"tabNavigated": "tabNavigated"
|
||||
};
|
||||
|
||||
/**
|
||||
* Set of debug protocol request types that specify the protocol request being
|
||||
* sent to the server.
|
||||
|
@ -204,6 +214,7 @@ const DebugProtocolTypes = {
|
|||
"delete": "delete",
|
||||
"detach": "detach",
|
||||
"frames": "frames",
|
||||
"interrupt": "interrupt",
|
||||
"listTabs": "listTabs",
|
||||
"nameAndParameters": "nameAndParameters",
|
||||
"ownPropertyNames": "ownPropertyNames",
|
||||
|
@ -408,12 +419,15 @@ DebuggerClient.prototype = {
|
|||
|
||||
try {
|
||||
if (!aPacket.from) {
|
||||
dumpn("Server did not specify an actor, dropping packet: " + JSON.stringify(aPacket));
|
||||
Cu.reportError("Server did not specify an actor, dropping packet: " +
|
||||
JSON.stringify(aPacket));
|
||||
return;
|
||||
}
|
||||
|
||||
let onResponse;
|
||||
if (aPacket.from in this._activeRequests) {
|
||||
// Don't count unsolicited notifications as responses.
|
||||
if (aPacket.from in this._activeRequests &&
|
||||
!(aPacket.type in UnsolicitedNotifications)) {
|
||||
onResponse = this._activeRequests[aPacket.from].onResponse;
|
||||
delete this._activeRequests[aPacket.from];
|
||||
}
|
||||
|
@ -509,12 +523,13 @@ function ThreadClient(aClient, aActor) {
|
|||
ThreadClient.prototype = {
|
||||
_state: "paused",
|
||||
get state() { return this._state; },
|
||||
get paused() { return this._state === "paused"; },
|
||||
|
||||
_actor: null,
|
||||
get actor() { return this._actor; },
|
||||
|
||||
_assertPaused: function TC_assertPaused(aCommand) {
|
||||
if (this._state !== "paused") {
|
||||
if (!this.paused) {
|
||||
throw aCommand + " command sent while not paused.";
|
||||
}
|
||||
},
|
||||
|
@ -545,6 +560,21 @@ ThreadClient.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Interrupt a running thread.
|
||||
*
|
||||
* @param function aOnResponse
|
||||
* Called with the response packet.
|
||||
*/
|
||||
interrupt: function TC_interrupt(aOnResponse) {
|
||||
let packet = { to: this._actor, type: DebugProtocolTypes.interrupt };
|
||||
this._client.request(packet, function(aResponse) {
|
||||
if (aOnResponse) {
|
||||
aOnResponse(aResponse);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a clientEvaluate packet to the debuggee. Response
|
||||
* will be a resume packet.
|
||||
|
@ -595,24 +625,49 @@ ThreadClient.prototype = {
|
|||
* Request to set a breakpoint in the specified location.
|
||||
*
|
||||
* @param aLocation object
|
||||
* The source location object where the breakpoint
|
||||
* will be set.
|
||||
* The source location object where the breakpoint will be set.
|
||||
* @param aOnResponse integer
|
||||
* Called with the thread's response.
|
||||
*/
|
||||
setBreakpoint: function TC_setBreakpoint(aLocation, aOnResponse) {
|
||||
this._assertPaused("setBreakpoint");
|
||||
// A helper function that sets the breakpoint.
|
||||
let doSetBreakpoint = function _doSetBreakpoint(aCallback) {
|
||||
let packet = { to: this._actor, type: DebugProtocolTypes.setBreakpoint,
|
||||
location: aLocation };
|
||||
this._client.request(packet, function (aResponse) {
|
||||
if (aOnResponse) {
|
||||
if (aResponse.error) {
|
||||
if (aCallback) {
|
||||
aCallback(aOnResponse.bind(undefined, aResponse));
|
||||
} else {
|
||||
aOnResponse(aResponse);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let bpClient = new BreakpointClient(this._client, aResponse.actor);
|
||||
if (aCallback) {
|
||||
aCallback(aOnResponse(aResponse, bpClient));
|
||||
} else {
|
||||
aOnResponse(aResponse, bpClient);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
|
||||
let self = this;
|
||||
let packet = { to: this._actor, type: DebugProtocolTypes.setBreakpoint,
|
||||
location: aLocation };
|
||||
this._client.request(packet, function (aResponse) {
|
||||
if (aOnResponse) {
|
||||
let bpClient = new BreakpointClient(self._client,
|
||||
aResponse.actor);
|
||||
aOnResponse(aResponse, bpClient);
|
||||
}
|
||||
});
|
||||
// If the debuggee is paused, just set the breakpoint.
|
||||
if (this.paused) {
|
||||
doSetBreakpoint();
|
||||
return;
|
||||
}
|
||||
// Otherwise, force a pause in order to set the breakpoint.
|
||||
this.interrupt(function(aResponse) {
|
||||
if (aResponse.error) {
|
||||
// Can't set the breakpoint if pausing failed.
|
||||
aOnResponse(aResponse);
|
||||
return;
|
||||
}
|
||||
doSetBreakpoint(this.resume.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -696,8 +751,7 @@ ThreadClient.prototype = {
|
|||
* true if there are more stack frames available on the server.
|
||||
*/
|
||||
get moreFrames() {
|
||||
return this.state === "paused"
|
||||
&& (!this._frameCache || this._frameCache.length == 0
|
||||
return this.paused && (!this._frameCache || this._frameCache.length == 0
|
||||
|| !this._frameCache[this._frameCache.length - 1].oldest);
|
||||
},
|
||||
|
||||
|
|
|
@ -365,25 +365,25 @@ BrowserTabActor.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Suppresses content-initiated events. Called right before entering the
|
||||
* nested event loop.
|
||||
* Prepare to enter a nested event loop by disabling debuggee events.
|
||||
*/
|
||||
preNest: function BTA_preNest() {
|
||||
this.browser.contentWindow
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.suppressEventHandling(true);
|
||||
let windowUtils = this.browser.contentWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
windowUtils.suppressEventHandling(true);
|
||||
windowUtils.suspendTimeouts();
|
||||
},
|
||||
|
||||
/**
|
||||
* Re-enables content-initiated events. Called right after exiting the
|
||||
* nested event loop.
|
||||
* Prepare to exit a nested event loop by enabling debuggee events.
|
||||
*/
|
||||
postNest: function BTA_postNest(aNestData) {
|
||||
this.browser.contentWindow
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.suppressEventHandling(false);
|
||||
let windowUtils = this.browser.contentWindow
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
windowUtils.resumeTimeouts();
|
||||
windowUtils.suppressEventHandling(false);
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,8 +49,8 @@
|
|||
* of debuggees.
|
||||
*
|
||||
* @param aHooks object
|
||||
* An object with preNest and postNest methods that can be called when
|
||||
* entering and exiting a nested event loop.
|
||||
* An object with preNest and postNest methods for calling when entering
|
||||
* and exiting a nested event loop.
|
||||
*/
|
||||
function ThreadActor(aHooks)
|
||||
{
|
||||
|
@ -176,7 +176,7 @@ ThreadActor.prototype = {
|
|||
// now.
|
||||
return null;
|
||||
} catch(e) {
|
||||
dumpn(e);
|
||||
Cu.reportError(e);
|
||||
return { error: "notAttached", message: e.toString() };
|
||||
}
|
||||
},
|
||||
|
@ -286,10 +286,8 @@ ThreadActor.prototype = {
|
|||
}
|
||||
|
||||
let location = aRequest.location;
|
||||
// TODO: deal with actualLocation being different from the provided location
|
||||
if (!this._scripts[location.url] || location.line < 0) {
|
||||
return { from: this.actorID,
|
||||
error: "noScript" };
|
||||
return { error: "noScript" };
|
||||
}
|
||||
// Fetch the list of scripts in that url.
|
||||
let scripts = this._scripts[location.url];
|
||||
|
@ -307,19 +305,69 @@ ThreadActor.prototype = {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!script) {
|
||||
return { from: this.actorID,
|
||||
error: "noScript" };
|
||||
return { error: "noScript" };
|
||||
}
|
||||
|
||||
script = this._getInnermostContainer(script, location.line);
|
||||
let bpActor = new BreakpointActor(script, this);
|
||||
this.breakpointActorPool.addActor(bpActor);
|
||||
var offsets = script.getLineOffsets(location.line);
|
||||
for (var i = 0; i < offsets.length; i++) {
|
||||
|
||||
let offsets = script.getLineOffsets(location.line);
|
||||
let codeFound = false;
|
||||
for (let i = 0; i < offsets.length; i++) {
|
||||
script.setBreakpoint(offsets[i], bpActor);
|
||||
codeFound = true;
|
||||
}
|
||||
let packet = { from: this.actorID,
|
||||
actor: bpActor.actorID };
|
||||
return packet;
|
||||
|
||||
let actualLocation;
|
||||
if (offsets.length == 0) {
|
||||
// No code at that line in any script, skipping forward.
|
||||
let lines = script.getAllOffsets();
|
||||
for (let line = location.line; line < lines.length; ++line) {
|
||||
if (lines[line]) {
|
||||
for (let i = 0; i < lines[line].length; i++) {
|
||||
script.setBreakpoint(lines[line][i], bpActor);
|
||||
codeFound = true;
|
||||
}
|
||||
actualLocation = location;
|
||||
actualLocation.line = line;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!codeFound) {
|
||||
bpActor.onDelete();
|
||||
return { error: "noCodeAtLineColumn" };
|
||||
}
|
||||
|
||||
return { actor: bpActor.actorID, actualLocation: actualLocation };
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the innermost script that contains this line, by looking through child
|
||||
* scripts of the supplied script.
|
||||
*
|
||||
* @param aScript Debugger.Script
|
||||
* The source script.
|
||||
* @param aLine number
|
||||
* The line number.
|
||||
*/
|
||||
_getInnermostContainer: function TA__getInnermostContainer(aScript, aLine) {
|
||||
let children = aScript.getChildScripts();
|
||||
if (children.length > 0) {
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let child = children[i];
|
||||
// Stop when the first script that contains this location is found.
|
||||
if (child.startLine <= aLine &&
|
||||
child.startLine + child.lineCount > aLine) {
|
||||
return this._getInnermostContainer(child, aLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Location not found in children, this is the innermost containing script.
|
||||
return aScript;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -346,6 +394,46 @@ ThreadActor.prototype = {
|
|||
return packet;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handle a protocol request to pause the debuggee.
|
||||
*/
|
||||
onInterrupt: function TA_onScripts(aRequest) {
|
||||
if (this.state == "exited") {
|
||||
return { type: "exited" };
|
||||
} else if (this.state == "paused") {
|
||||
// TODO: return the actual reason for the existing pause.
|
||||
return { type: "paused", why: { type: "alreadyPaused" } };
|
||||
} else if (this.state != "running") {
|
||||
return { error: "wrongState",
|
||||
message: "Received interrupt request in " + this.state +
|
||||
" state." };
|
||||
}
|
||||
|
||||
try {
|
||||
// Put ourselves in the paused state.
|
||||
let packet = this._paused();
|
||||
if (!packet) {
|
||||
return { error: "notInterrupted" };
|
||||
}
|
||||
packet.why = { type: "interrupted" };
|
||||
|
||||
// Send the response to the interrupt request now (rather than
|
||||
// returning it), because we're going to start a nested event loop
|
||||
// here.
|
||||
this.conn.send(packet);
|
||||
|
||||
// Start a nested event loop.
|
||||
this._nest();
|
||||
|
||||
// We already sent a response to this request, don't send one
|
||||
// now.
|
||||
return null;
|
||||
} catch(e) {
|
||||
Cu.reportError(e);
|
||||
return { error: "notInterrupted", message: e.toString() };
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the Debug.Frame for a frame mentioned by the protocol.
|
||||
*/
|
||||
|
@ -626,7 +714,8 @@ ThreadActor.prototype = {
|
|||
this.conn.send(packet);
|
||||
return this._nest();
|
||||
} catch(e) {
|
||||
dumpn("Got an exception during onDebuggerStatement: " + e + ': ' + e.stack);
|
||||
Cu.reportError("Got an exception during onDebuggerStatement: " + e +
|
||||
": " + e.stack);
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
@ -645,10 +734,6 @@ ThreadActor.prototype = {
|
|||
* The function object that the ew code is part of.
|
||||
*/
|
||||
onNewScript: function TA_onNewScript(aScript, aFunction) {
|
||||
dumpn("Got a new script:" + aScript + ", url: " + aScript.url +
|
||||
", startLine: " + aScript.startLine + ", lineCount: " +
|
||||
aScript.lineCount + ", strictMode: " + aScript.strictMode +
|
||||
", function: " + aFunction);
|
||||
// Use a sparse array for storing the scripts for each URL in order to
|
||||
// optimize retrieval. XXX: in case this is not fast enough for very large
|
||||
// files with too many scripts, we could sort the hash of script locations
|
||||
|
@ -670,6 +755,7 @@ ThreadActor.prototype.requestTypes = {
|
|||
"resume": ThreadActor.prototype.onResume,
|
||||
"clientEvaluate": ThreadActor.prototype.onClientEvaluate,
|
||||
"frames": ThreadActor.prototype.onFrames,
|
||||
"interrupt": ThreadActor.prototype.onInterrupt,
|
||||
"releaseMany": ThreadActor.prototype.onReleaseMany,
|
||||
"setBreakpoint": ThreadActor.prototype.onSetBreakpoint,
|
||||
"scripts": ThreadActor.prototype.onScripts
|
||||
|
@ -1079,7 +1165,7 @@ BreakpointActor.prototype = {
|
|||
this.conn.send(packet);
|
||||
return this.threadActor._nest();
|
||||
} catch(e) {
|
||||
dumpn("Got an exception during hit: " + e + ': ' + e.stack);
|
||||
Cu.reportError("Got an exception during hit: " + e + ': ' + e.stack);
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
@ -1232,4 +1318,3 @@ EnvironmentActor.prototype.requestTypes = {
|
|||
"assign": EnvironmentActor.prototype.onAssign,
|
||||
"bindings": EnvironmentActor.prototype.onBindings
|
||||
};
|
||||
|
||||
|
|
|
@ -432,7 +432,7 @@ DebuggerServerConnection.prototype = {
|
|||
try {
|
||||
ret = actor.requestTypes[aPacket.type].bind(actor)(aPacket);
|
||||
} catch(e) {
|
||||
dumpn(e);
|
||||
Cu.reportError(e);
|
||||
ret = { error: "unknownError",
|
||||
message: "An unknown error has occurred while processing request." };
|
||||
}
|
||||
|
|
|
@ -46,8 +46,7 @@ function test_simple_breakpoint()
|
|||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume(function () {
|
||||
});
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting breakpoints when the debuggee is running works.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestGlobalClientAndResume(gClient, "test-stack", function (aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_breakpoint_running();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_breakpoint_running()
|
||||
{
|
||||
let path = getFilePath('test_breakpoint-01.js');
|
||||
|
||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||
"var a = 1;\n" + // line0 + 1
|
||||
"var b = 2;\n"); // line0 + 2
|
||||
|
||||
// Setting the breakpoint later should interrupt the debuggee.
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "interrupted");
|
||||
});
|
||||
|
||||
gThreadClient.setBreakpoint({ url: path, line: gDebuggee.line0 + 3}, function(aResponse) {
|
||||
// Eval scripts don't stick around long enough for the breakpoint to be set,
|
||||
// so just make sure we got the expected response from the actor.
|
||||
do_check_eq(aResponse.error, "noScript");
|
||||
|
||||
do_execute_soon(function() {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line without code will skip forward.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestGlobalClientAndResume(gClient,
|
||||
"test-stack",
|
||||
function (aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_skip_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_skip_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let path = getFilePath('test_breakpoint-03.js');
|
||||
let location = { url: path, line: gDebuggee.line0 + 3};
|
||||
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.url, location.url);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||
"debugger;\n" + // line0 + 1
|
||||
"var a = 1;\n" + // line0 + 2
|
||||
"// A comment.\n" + // line0 + 3
|
||||
"var b = 2;\n"); // line0 + 4
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line in a child script works.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestGlobalClientAndResume(gClient,
|
||||
"test-stack",
|
||||
function (aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_child_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let path = getFilePath('test_breakpoint-04.js');
|
||||
let location = { url: path, line: gDebuggee.line0 + 3};
|
||||
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// actualLocation is not returned when breakpoints don't skip forward.
|
||||
do_check_eq(aResponse.actualLocation, undefined);
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2
|
||||
" this.b = 2;\n" + // line0 + 3
|
||||
"}\n" + // line0 + 4
|
||||
"debugger;\n" + // line0 + 5
|
||||
"foo();\n"); // line0 + 6
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line without code in a child script
|
||||
* will skip forward.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestGlobalClientAndResume(gClient,
|
||||
"test-stack",
|
||||
function (aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_skip_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_child_skip_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let path = getFilePath('test_breakpoint-05.js');
|
||||
let location = { url: path, line: gDebuggee.line0 + 3};
|
||||
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.url, location.url);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2
|
||||
" // A comment.\n" + // line0 + 3
|
||||
" this.b = 2;\n" + // line0 + 4
|
||||
"}\n" + // line0 + 5
|
||||
"debugger;\n" + // line0 + 6
|
||||
"foo();\n"); // line0 + 7
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line without code in a deeply-nested
|
||||
* child script will skip forward.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestGlobalClientAndResume(gClient,
|
||||
"test-stack",
|
||||
function (aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_nested_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_nested_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let path = getFilePath('test_breakpoint-06.js');
|
||||
let location = { url: path, line: gDebuggee.line0 + 5};
|
||||
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.url, location.url);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" function bar() {\n" + // line0 + 2
|
||||
" function baz() {\n" + // line0 + 3
|
||||
" this.a = 1;\n" + // line0 + 4
|
||||
" // A comment.\n" + // line0 + 5
|
||||
" this.b = 2;\n" + // line0 + 6
|
||||
" }\n" + // line0 + 7
|
||||
" baz();\n" + // line0 + 8
|
||||
" }\n" + // line0 + 9
|
||||
" bar();\n" + // line0 + 10
|
||||
"}\n" + // line0 + 11
|
||||
"debugger;\n" + // line0 + 12
|
||||
"foo();\n"); // line0 + 13
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line without code in the second child
|
||||
* script will skip forward.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestGlobalClientAndResume(gClient,
|
||||
"test-stack",
|
||||
function (aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_second_child_skip_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_second_child_skip_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let path = getFilePath('test_breakpoint-07.js');
|
||||
let location = { url: path, line: gDebuggee.line0 + 6};
|
||||
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.url, location.url);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" bar();\n" + // line0 + 2
|
||||
"}\n" + // line0 + 3
|
||||
"function bar() {\n" + // line0 + 4
|
||||
" this.a = 1;\n" + // line0 + 5
|
||||
" // A comment.\n" + // line0 + 6
|
||||
" this.b = 2;\n" + // line0 + 7
|
||||
"}\n" + // line0 + 8
|
||||
"debugger;\n" + // line0 + 9
|
||||
"foo();\n"); // line0 + 10
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line without code in a child script
|
||||
* will skip forward, in a file with two scripts.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestGlobalClientAndResume(gClient,
|
||||
"test-stack",
|
||||
function (aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_skip_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_child_skip_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let path = getFilePath('test_breakpoint-08.js');
|
||||
let location = { url: path, line: gDebuggee.line0 + 3};
|
||||
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// Check that the breakpoint has properly skipped forward one line.
|
||||
do_check_eq(aResponse.actualLocation.url, location.url);
|
||||
do_check_eq(aResponse.actualLocation.line, location.line + 1);
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, 1);
|
||||
do_check_eq(gDebuggee.b, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||
"function foo() {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2
|
||||
" // A comment.\n" + // line0 + 3
|
||||
" this.b = 2;\n" + // line0 + 4
|
||||
"}\n"); // line0 + 5
|
||||
gDebuggee.eval("var line1 = Error().lineNumber;\n" +
|
||||
"debugger;\n" + // line1 + 1
|
||||
"foo();\n"); // line1 + 2
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that removing a breakpoint works.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestGlobalClientAndResume(gClient,
|
||||
"test-stack",
|
||||
function (aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_remove_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_remove_breakpoint()
|
||||
{
|
||||
let done = false;
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let path = getFilePath('test_breakpoint-09.js');
|
||||
let location = { url: path, line: gDebuggee.line0 + 1};
|
||||
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.a, undefined);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
done = true;
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// The breakpoint should not be hit again.
|
||||
gThreadClient.resume(function () {
|
||||
do_check_true(false);
|
||||
});
|
||||
});
|
||||
gThreadClient.resume();
|
||||
});
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||
"function foo(stop) {\n" + // line0 + 1
|
||||
" this.a = 1;\n" + // line0 + 2
|
||||
" if (stop) return;\n" + // line0 + 3
|
||||
" delete this.a;\n" + // line0 + 4
|
||||
" foo(true);\n" + // line0 + 5
|
||||
"}\n" + // line0 + 6
|
||||
"debugger;\n" + // line1 + 7
|
||||
"foo();\n"); // line1 + 8
|
||||
if (!done) {
|
||||
do_check_true(false);
|
||||
}
|
||||
finishClient(gClient);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check that setting a breakpoint in a line with multiple entry points
|
||||
* triggers no matter which entry point we reach.
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gThreadClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestDebuggerServer();
|
||||
gDebuggee = addTestGlobal("test-stack");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function () {
|
||||
attachTestGlobalClientAndResume(gClient,
|
||||
"test-stack",
|
||||
function (aResponse, aThreadClient) {
|
||||
gThreadClient = aThreadClient;
|
||||
test_child_breakpoint();
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_child_breakpoint()
|
||||
{
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
let path = getFilePath('test_breakpoint-10.js');
|
||||
let location = { url: path, line: gDebuggee.line0 + 3};
|
||||
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
||||
// actualLocation is not returned when breakpoints don't skip forward.
|
||||
do_check_eq(aResponse.actualLocation, undefined);
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.i, 0);
|
||||
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.type, "paused");
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||
// Check that the breakpoint worked.
|
||||
do_check_eq(gDebuggee.i, 1);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
gThreadClient.resume(function () {
|
||||
finishClient(gClient);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Continue until the breakpoint is hit again.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
// Continue until the breakpoint is hit.
|
||||
gThreadClient.resume();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||
"debugger;\n" + // line0 + 1
|
||||
"var a, i = 0;\n" + // line0 + 2
|
||||
"for (i = 1; i <= 2; i++) {\n" + // line0 + 3
|
||||
" a = i;\n" + // line0 + 4
|
||||
"}\n"); // line0 + 5
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var gClient;
|
||||
var gDebuggee;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
DebuggerServer.addActors("resource://test/testactors.js");
|
||||
|
||||
DebuggerServer.init();
|
||||
gDebuggee = testGlobal("test-1");
|
||||
DebuggerServer.addTestGlobal(gDebuggee);
|
||||
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
gClient = new DebuggerClient(transport);
|
||||
gClient.connect(function(aType, aTraits) {
|
||||
getTestGlobalContext(gClient, "test-1", function(aContext) {
|
||||
test_attach(aContext);
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_attach(aContext)
|
||||
{
|
||||
gClient.attachThread(aContext.actor, function(aResponse, aThreadClient) {
|
||||
do_check_eq(aThreadClient.paused, true);
|
||||
aThreadClient.resume(function() {
|
||||
test_interrupt();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function test_interrupt()
|
||||
{
|
||||
do_check_eq(gClient.activeThread.paused, false);
|
||||
gClient.activeThread.interrupt(function(aResponse) {
|
||||
do_check_eq(gClient.activeThread.paused, true);
|
||||
gClient.activeThread.resume(function() {
|
||||
do_check_eq(gClient.activeThread.paused, false);
|
||||
cleanup();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
gClient.addListener("closed", function(aEvent) {
|
||||
do_test_finished();
|
||||
});
|
||||
gClient.close();
|
||||
}
|
||||
|
|
@ -34,8 +34,18 @@ tail =
|
|||
[test_eval-04.js]
|
||||
[test_eval-05.js]
|
||||
[test_breakpoint-01.js]
|
||||
[test_breakpoint-02.js]
|
||||
[test_breakpoint-03.js]
|
||||
[test_breakpoint-04.js]
|
||||
[test_breakpoint-05.js]
|
||||
[test_breakpoint-06.js]
|
||||
[test_breakpoint-07.js]
|
||||
[test_breakpoint-08.js]
|
||||
[test_breakpoint-09.js]
|
||||
[test_breakpoint-10.js]
|
||||
[test_listscripts-01.js]
|
||||
[test_objectgrips-01.js]
|
||||
[test_objectgrips-02.js]
|
||||
[test_objectgrips-03.js]
|
||||
[test_objectgrips-04.js]
|
||||
[test_interrupt.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче