зеркало из https://github.com/mozilla/gecko-dev.git
merge m-c to fx-team
This commit is contained in:
Коммит
d33a6e661f
|
@ -23,6 +23,10 @@ function test() {
|
||||||
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
Services.prefs.clearUserPref("browser.sessionstore.interval");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
waitForSaveState(setup);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup() {
|
||||||
// We'll clear all closed windows to make sure our state is clean
|
// We'll clear all closed windows to make sure our state is clean
|
||||||
// forgetClosedWindow doesn't trigger a delayed save
|
// forgetClosedWindow doesn't trigger a delayed save
|
||||||
while (ss.getClosedWindowCount()) {
|
while (ss.getClosedWindowCount()) {
|
||||||
|
|
|
@ -1191,6 +1191,10 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||||
// dontAdjustTray - (boolean) if true, do not adjust the tray.
|
// dontAdjustTray - (boolean) if true, do not adjust the tray.
|
||||||
addAppTab: function GroupItem_addAppTab(xulTab, options) {
|
addAppTab: function GroupItem_addAppTab(xulTab, options) {
|
||||||
GroupItems.getAppTabFavIconUrl(xulTab, function(iconUrl) {
|
GroupItems.getAppTabFavIconUrl(xulTab, function(iconUrl) {
|
||||||
|
// The tab might have been removed or unpinned while waiting.
|
||||||
|
if (xulTab.closing || !xulTab.parentNode || !xulTab.pinned)
|
||||||
|
return;
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
let $appTab = iQ("<img>")
|
let $appTab = iQ("<img>")
|
||||||
.addClass("appTabIcon")
|
.addClass("appTabIcon")
|
||||||
|
|
|
@ -578,6 +578,7 @@ DebuggerUI.prototype = {
|
||||||
script.contentType = aContentType;
|
script.contentType = aContentType;
|
||||||
elt.setUserData("sourceScript", script, null);
|
elt.setUserData("sourceScript", script, null);
|
||||||
dbg._updateEditorBreakpoints();
|
dbg._updateEditorBreakpoints();
|
||||||
|
dbg.debuggerWindow.StackFrames.updateEditor();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -280,6 +280,27 @@ DebuggerView.Stackframes = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener handling the step over button click event.
|
||||||
|
*/
|
||||||
|
_onStepOverClick: function DVF__onStepOverClick() {
|
||||||
|
ThreadState.activeThread.stepOver();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener handling the step in button click event.
|
||||||
|
*/
|
||||||
|
_onStepInClick: function DVF__onStepInClick() {
|
||||||
|
ThreadState.activeThread.stepIn();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener handling the step out button click event.
|
||||||
|
*/
|
||||||
|
_onStepOutClick: function DVF__onStepOutClick() {
|
||||||
|
ThreadState.activeThread.stepOut();
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies if the active thread has more frames which need to be loaded.
|
* Specifies if the active thread has more frames which need to be loaded.
|
||||||
*/
|
*/
|
||||||
|
@ -296,10 +317,16 @@ DebuggerView.Stackframes = {
|
||||||
initialize: function DVF_initialize() {
|
initialize: function DVF_initialize() {
|
||||||
let close = document.getElementById("close");
|
let close = document.getElementById("close");
|
||||||
let resume = document.getElementById("resume");
|
let resume = document.getElementById("resume");
|
||||||
|
let stepOver = document.getElementById("step-over");
|
||||||
|
let stepIn = document.getElementById("step-in");
|
||||||
|
let stepOut = document.getElementById("step-out");
|
||||||
let frames = document.getElementById("stackframes");
|
let frames = document.getElementById("stackframes");
|
||||||
|
|
||||||
close.addEventListener("click", this._onCloseButtonClick, false);
|
close.addEventListener("click", this._onCloseButtonClick, false);
|
||||||
resume.addEventListener("click", this._onResumeButtonClick, false);
|
resume.addEventListener("click", this._onResumeButtonClick, false);
|
||||||
|
stepOver.addEventListener("click", this._onStepOverClick, false);
|
||||||
|
stepIn.addEventListener("click", this._onStepInClick, false);
|
||||||
|
stepOut.addEventListener("click", this._onStepOutClick, false);
|
||||||
frames.addEventListener("scroll", this._onFramesScroll, false);
|
frames.addEventListener("scroll", this._onFramesScroll, false);
|
||||||
window.addEventListener("resize", this._onFramesScroll, false);
|
window.addEventListener("resize", this._onFramesScroll, false);
|
||||||
|
|
||||||
|
@ -312,10 +339,16 @@ DebuggerView.Stackframes = {
|
||||||
destroy: function DVF_destroy() {
|
destroy: function DVF_destroy() {
|
||||||
let close = document.getElementById("close");
|
let close = document.getElementById("close");
|
||||||
let resume = document.getElementById("resume");
|
let resume = document.getElementById("resume");
|
||||||
|
let stepOver = document.getElementById("step-over");
|
||||||
|
let stepIn = document.getElementById("step-in");
|
||||||
|
let stepOut = document.getElementById("step-out");
|
||||||
let frames = this._frames;
|
let frames = this._frames;
|
||||||
|
|
||||||
close.removeEventListener("click", this._onCloseButtonClick, false);
|
close.removeEventListener("click", this._onCloseButtonClick, false);
|
||||||
resume.removeEventListener("click", this._onResumeButtonClick, false);
|
resume.removeEventListener("click", this._onResumeButtonClick, false);
|
||||||
|
stepOver.removeEventListener("click", this._onStepOverClick, false);
|
||||||
|
stepIn.removeEventListener("click", this._onStepInClick, false);
|
||||||
|
stepOut.removeEventListener("click", this._onStepOutClick, false);
|
||||||
frames.removeEventListener("click", this._onFramesClick, false);
|
frames.removeEventListener("click", this._onFramesClick, false);
|
||||||
frames.removeEventListener("scroll", this._onFramesScroll, false);
|
frames.removeEventListener("scroll", this._onFramesScroll, false);
|
||||||
window.removeEventListener("resize", this._onFramesScroll, false);
|
window.removeEventListener("resize", this._onFramesScroll, false);
|
||||||
|
@ -1198,3 +1231,6 @@ let DVF = DebuggerView.Stackframes;
|
||||||
DVF._onFramesScroll = DVF._onFramesScroll.bind(DVF);
|
DVF._onFramesScroll = DVF._onFramesScroll.bind(DVF);
|
||||||
DVF._onCloseButtonClick = DVF._onCloseButtonClick.bind(DVF);
|
DVF._onCloseButtonClick = DVF._onCloseButtonClick.bind(DVF);
|
||||||
DVF._onResumeButtonClick = DVF._onResumeButtonClick.bind(DVF);
|
DVF._onResumeButtonClick = DVF._onResumeButtonClick.bind(DVF);
|
||||||
|
DVF._onStepOverClick = DVF._onStepOverClick.bind(DVF);
|
||||||
|
DVF._onStepInClick = DVF._onStepInClick.bind(DVF);
|
||||||
|
DVF._onStepOutClick = DVF._onStepOutClick.bind(DVF);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
* Dave Camp <dcamp@mozilla.com>
|
* Dave Camp <dcamp@mozilla.com>
|
||||||
* Panos Astithas <past@mozilla.com>
|
* Panos Astithas <past@mozilla.com>
|
||||||
* Victor Porof <vporof@mozilla.com>
|
* Victor Porof <vporof@mozilla.com>
|
||||||
|
* Mihai Sucan <mihai.sucan@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* 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
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
@ -175,6 +176,7 @@ var StackFrames = {
|
||||||
|
|
||||||
this.activeThread = aThreadClient;
|
this.activeThread = aThreadClient;
|
||||||
aThreadClient.addListener("paused", this.onPaused);
|
aThreadClient.addListener("paused", this.onPaused);
|
||||||
|
aThreadClient.addListener("resumed", this.onResume);
|
||||||
aThreadClient.addListener("framesadded", this.onFrames);
|
aThreadClient.addListener("framesadded", this.onFrames);
|
||||||
aThreadClient.addListener("framescleared", this.onFramesCleared);
|
aThreadClient.addListener("framescleared", this.onFramesCleared);
|
||||||
this.onFramesCleared();
|
this.onFramesCleared();
|
||||||
|
@ -186,6 +188,7 @@ var StackFrames = {
|
||||||
*/
|
*/
|
||||||
disconnect: function TS_disconnect() {
|
disconnect: function TS_disconnect() {
|
||||||
this.activeThread.removeListener("paused", this.onPaused);
|
this.activeThread.removeListener("paused", this.onPaused);
|
||||||
|
this.activeThread.removeListener("resumed", this.onResume);
|
||||||
this.activeThread.removeListener("framesadded", this.onFrames);
|
this.activeThread.removeListener("framesadded", this.onFrames);
|
||||||
this.activeThread.removeListener("framescleared", this.onFramesCleared);
|
this.activeThread.removeListener("framescleared", this.onFramesCleared);
|
||||||
},
|
},
|
||||||
|
@ -197,6 +200,13 @@ var StackFrames = {
|
||||||
this.activeThread.fillFrames(this.pageSize);
|
this.activeThread.fillFrames(this.pageSize);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for the thread client's resumed notification.
|
||||||
|
*/
|
||||||
|
onResume: function SF_onResume() {
|
||||||
|
window.editor.setDebugLocation(-1);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for the thread client's framesadded notification.
|
* Handler for the thread client's framesadded notification.
|
||||||
*/
|
*/
|
||||||
|
@ -265,11 +275,15 @@ var StackFrames = {
|
||||||
// Move the editor's caret to the proper line.
|
// Move the editor's caret to the proper line.
|
||||||
if (DebuggerView.Scripts.isSelected(frame.where.url) && frame.where.line) {
|
if (DebuggerView.Scripts.isSelected(frame.where.url) && frame.where.line) {
|
||||||
window.editor.setCaretPosition(frame.where.line - 1);
|
window.editor.setCaretPosition(frame.where.line - 1);
|
||||||
|
window.editor.setDebugLocation(frame.where.line - 1);
|
||||||
} else if (DebuggerView.Scripts.contains(frame.where.url)) {
|
} else if (DebuggerView.Scripts.contains(frame.where.url)) {
|
||||||
DebuggerView.Scripts.selectScript(frame.where.url);
|
DebuggerView.Scripts.selectScript(frame.where.url);
|
||||||
SourceScripts.onChange({ target: DebuggerView.Scripts._scripts });
|
SourceScripts.onChange({ target: DebuggerView.Scripts._scripts });
|
||||||
window.editor.setCaretPosition(frame.where.line - 1);
|
window.editor.setCaretPosition(frame.where.line - 1);
|
||||||
|
} else {
|
||||||
|
window.editor.setDebugLocation(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the local variables.
|
// Display the local variables.
|
||||||
let localScope = DebuggerView.Properties.localScope;
|
let localScope = DebuggerView.Properties.localScope;
|
||||||
localScope.empty();
|
localScope.empty();
|
||||||
|
@ -301,6 +315,28 @@ var StackFrames = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the source editor current debug location based on the selected frame
|
||||||
|
* and script.
|
||||||
|
*/
|
||||||
|
updateEditor: function SF_updateEditor() {
|
||||||
|
if (this.selectedFrame === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let frame = this.activeThread.cachedFrames[this.selectedFrame];
|
||||||
|
if (!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the editor's caret to the proper line.
|
||||||
|
if (DebuggerView.Scripts.isSelected(frame.where.url) && frame.where.line) {
|
||||||
|
window.editor.setDebugLocation(frame.where.line - 1);
|
||||||
|
} else {
|
||||||
|
window.editor.setDebugLocation(-1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_addExpander: function SF_addExpander(aVar, aObject) {
|
_addExpander: function SF_addExpander(aVar, aObject) {
|
||||||
// No need for expansion for null and undefined values, but we do need them
|
// No need for expansion for null and undefined values, but we do need them
|
||||||
// for frame.arguments which is a regular array.
|
// for frame.arguments which is a regular array.
|
||||||
|
@ -408,6 +444,7 @@ var StackFrames = {
|
||||||
};
|
};
|
||||||
|
|
||||||
StackFrames.onPaused = StackFrames.onPaused.bind(StackFrames);
|
StackFrames.onPaused = StackFrames.onPaused.bind(StackFrames);
|
||||||
|
StackFrames.onResume = StackFrames.onResume.bind(StackFrames);
|
||||||
StackFrames.onFrames = StackFrames.onFrames.bind(StackFrames);
|
StackFrames.onFrames = StackFrames.onFrames.bind(StackFrames);
|
||||||
StackFrames.onFramesCleared = StackFrames.onFramesCleared.bind(StackFrames);
|
StackFrames.onFramesCleared = StackFrames.onFramesCleared.bind(StackFrames);
|
||||||
StackFrames.onClick = StackFrames.onClick.bind(StackFrames);
|
StackFrames.onClick = StackFrames.onClick.bind(StackFrames);
|
||||||
|
@ -614,6 +651,7 @@ var SourceScripts = {
|
||||||
} else {
|
} else {
|
||||||
window.editor.setText(aScript.text);
|
window.editor.setText(aScript.text);
|
||||||
window.updateEditorBreakpoints();
|
window.updateEditorBreakpoints();
|
||||||
|
StackFrames.updateEditor();
|
||||||
}
|
}
|
||||||
window.editor.resetUndo();
|
window.editor.resetUndo();
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,9 @@
|
||||||
<xul:toolbar id="dbg-toolbar">
|
<xul:toolbar id="dbg-toolbar">
|
||||||
<xul:button id="close">&debuggerUI.closeButton;</xul:button>
|
<xul:button id="close">&debuggerUI.closeButton;</xul:button>
|
||||||
<xul:button id="resume"/>
|
<xul:button id="resume"/>
|
||||||
|
<xul:button id="step-over">&debuggerUI.stepOverButton;</xul:button>
|
||||||
|
<xul:button id="step-in">&debuggerUI.stepInButton;</xul:button>
|
||||||
|
<xul:button id="step-out">&debuggerUI.stepOutButton;</xul:button>
|
||||||
<xul:menulist id="scripts"/>
|
<xul:menulist id="scripts"/>
|
||||||
</xul:toolbar>
|
</xul:toolbar>
|
||||||
<div id="dbg-content" class="hbox flex">
|
<div id="dbg-content" class="hbox flex">
|
||||||
|
|
|
@ -67,6 +67,7 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_dbg_stack-02.js \
|
browser_dbg_stack-02.js \
|
||||||
browser_dbg_stack-03.js \
|
browser_dbg_stack-03.js \
|
||||||
browser_dbg_stack-04.js \
|
browser_dbg_stack-04.js \
|
||||||
|
browser_dbg_stack-05.js \
|
||||||
browser_dbg_location-changes.js \
|
browser_dbg_location-changes.js \
|
||||||
browser_dbg_script-switching.js \
|
browser_dbg_script-switching.js \
|
||||||
browser_dbg_pause-resume.js \
|
browser_dbg_pause-resume.js \
|
||||||
|
|
|
@ -61,6 +61,9 @@ function testScriptsDisplay() {
|
||||||
ok(gDebugger.editor.getText().search(/debugger/) != -1,
|
ok(gDebugger.editor.getText().search(/debugger/) != -1,
|
||||||
"The correct script was loaded initially.");
|
"The correct script was loaded initially.");
|
||||||
|
|
||||||
|
is(gDebugger.editor.getDebugLocation(), 5,
|
||||||
|
"editor debugger location is correct.");
|
||||||
|
|
||||||
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
||||||
function onChange() {
|
function onChange() {
|
||||||
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
gDebugger.editor.removeEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
||||||
|
@ -83,6 +86,9 @@ function testSwitchPaused()
|
||||||
ok(gDebugger.editor.getText().search(/firstCall/) != -1,
|
ok(gDebugger.editor.getText().search(/firstCall/) != -1,
|
||||||
"The first script is displayed.");
|
"The first script is displayed.");
|
||||||
|
|
||||||
|
is(gDebugger.editor.getDebugLocation(), -1,
|
||||||
|
"editor debugger location has been cleared.");
|
||||||
|
|
||||||
gDebugger.StackFrames.activeThread.resume(function() {
|
gDebugger.StackFrames.activeThread.resume(function() {
|
||||||
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
gDebugger.editor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
|
||||||
function onSecondChange() {
|
function onSecondChange() {
|
||||||
|
@ -103,6 +109,9 @@ function testSwitchRunning()
|
||||||
ok(gDebugger.editor.getText().search(/firstCall/) == -1,
|
ok(gDebugger.editor.getText().search(/firstCall/) == -1,
|
||||||
"The first script is no longer displayed.");
|
"The first script is no longer displayed.");
|
||||||
|
|
||||||
|
is(gDebugger.editor.getDebugLocation(), -1,
|
||||||
|
"editor debugger location is still -1.");
|
||||||
|
|
||||||
closeDebuggerAndFinish(gTab);
|
closeDebuggerAndFinish(gTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +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/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Test that switching between stack frames properly sets the current debugger
|
||||||
|
// location in the source editor.
|
||||||
|
|
||||||
|
const TAB_URL = EXAMPLE_URL + "browser_dbg_script-switching.html";
|
||||||
|
|
||||||
|
var gPane = null;
|
||||||
|
var gTab = null;
|
||||||
|
var gDebuggee = null;
|
||||||
|
var gDebugger = null;
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
|
||||||
|
gTab = aTab;
|
||||||
|
gDebuggee = aDebuggee;
|
||||||
|
gPane = aPane;
|
||||||
|
gDebugger = gPane.debuggerWindow;
|
||||||
|
|
||||||
|
testRecurse();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testRecurse() {
|
||||||
|
gPane.activeThread.addOneTimeListener("scriptsadded", function() {
|
||||||
|
Services.tm.currentThread.dispatch({ run: function() {
|
||||||
|
let frames = gDebugger.DebuggerView.Stackframes._frames;
|
||||||
|
let childNodes = frames.childNodes;
|
||||||
|
|
||||||
|
is(frames.querySelectorAll(".dbg-stackframe").length, 4,
|
||||||
|
"Correct number of frames.");
|
||||||
|
|
||||||
|
is(childNodes.length, frames.querySelectorAll(".dbg-stackframe").length,
|
||||||
|
"All children should be frames.");
|
||||||
|
|
||||||
|
ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
|
||||||
|
"First frame should be selected by default.");
|
||||||
|
|
||||||
|
ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
|
||||||
|
"Third frame should not be selected.");
|
||||||
|
|
||||||
|
is(gDebugger.editor.getDebugLocation(), 5,
|
||||||
|
"editor debugger location is correct.");
|
||||||
|
|
||||||
|
EventUtils.sendMouseEvent({ type: "click" },
|
||||||
|
frames.querySelector("#stackframe-2"),
|
||||||
|
gDebugger);
|
||||||
|
|
||||||
|
ok(!frames.querySelector("#stackframe-0").classList.contains("selected"),
|
||||||
|
"First frame should not be selected after click.");
|
||||||
|
|
||||||
|
ok(frames.querySelector("#stackframe-2").classList.contains("selected"),
|
||||||
|
"Third frame should be selected after click.");
|
||||||
|
|
||||||
|
is(gDebugger.editor.getDebugLocation(), 4,
|
||||||
|
"editor debugger location is correct after click.");
|
||||||
|
|
||||||
|
EventUtils.sendMouseEvent({ type: "click" },
|
||||||
|
frames.querySelector("#stackframe-0 .dbg-stackframe-name"),
|
||||||
|
gDebugger);
|
||||||
|
|
||||||
|
ok(frames.querySelector("#stackframe-0").classList.contains("selected"),
|
||||||
|
"First frame should be selected after click inside the first frame.");
|
||||||
|
|
||||||
|
ok(!frames.querySelector("#stackframe-2").classList.contains("selected"),
|
||||||
|
"Third frame should not be selected after click inside the first frame.");
|
||||||
|
|
||||||
|
is(gDebugger.editor.getDebugLocation(), 5,
|
||||||
|
"editor debugger location is correct (frame 0 again).");
|
||||||
|
|
||||||
|
gDebugger.StackFrames.activeThread.resume(function() {
|
||||||
|
is(gDebugger.editor.getDebugLocation(), -1,
|
||||||
|
"editor debugger location is correct after resume.");
|
||||||
|
closeDebuggerAndFinish(gTab);
|
||||||
|
});
|
||||||
|
}}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.firstCall();
|
||||||
|
}
|
||||||
|
|
||||||
|
registerCleanupFunction(function() {
|
||||||
|
removeTab(gTab);
|
||||||
|
gPane = null;
|
||||||
|
gTab = null;
|
||||||
|
gDebuggee = null;
|
||||||
|
gDebugger = null;
|
||||||
|
});
|
|
@ -1247,6 +1247,10 @@ InspectorUI.prototype = {
|
||||||
if (computed) {
|
if (computed) {
|
||||||
computed.parentNode.removeChild(computed);
|
computed.parentNode.removeChild(computed);
|
||||||
}
|
}
|
||||||
|
let autosizer = node.querySelector(".autosizer");
|
||||||
|
if (autosizer) {
|
||||||
|
autosizer.parentNode.removeChild(autosizer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let text = node.textContent;
|
let text = node.textContent;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
* Spyros Livathinos <livathinos.spyros@gmail.com>
|
* Spyros Livathinos <livathinos.spyros@gmail.com>
|
||||||
* Allen Eubank <adeubank@gmail.com>
|
* Allen Eubank <adeubank@gmail.com>
|
||||||
* Girish Sharma <scrapmachines@gmail.com>
|
* Girish Sharma <scrapmachines@gmail.com>
|
||||||
|
* Pranav Ravichandran <prp.1111@gmail.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* 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
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
@ -112,6 +113,7 @@ const ORION_ANNOTATION_TYPES = {
|
||||||
breakpoint: "orion.annotation.breakpoint",
|
breakpoint: "orion.annotation.breakpoint",
|
||||||
task: "orion.annotation.task",
|
task: "orion.annotation.task",
|
||||||
currentLine: "orion.annotation.currentLine",
|
currentLine: "orion.annotation.currentLine",
|
||||||
|
debugLocation: "mozilla.annotation.debugLocation",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,6 +152,17 @@ const DEFAULT_KEYBINDINGS = [
|
||||||
ctrl: Services.appinfo.OS == "Darwin",
|
ctrl: Services.appinfo.OS == "Darwin",
|
||||||
alt: true,
|
alt: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
action: "Comment",
|
||||||
|
code: Ci.nsIDOMKeyEvent.DOM_VK_SLASH,
|
||||||
|
accel: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
action: "Uncomment",
|
||||||
|
code: Ci.nsIDOMKeyEvent.DOM_VK_SLASH,
|
||||||
|
accel: true,
|
||||||
|
shift: true,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = ["SourceEditor"];
|
var EXPORTED_SYMBOLS = ["SourceEditor"];
|
||||||
|
@ -342,12 +355,7 @@ SourceEditor.prototype = {
|
||||||
{styleClass: "ruler annotations"});
|
{styleClass: "ruler annotations"});
|
||||||
this._annotationRuler.onClick = this._annotationRulerClick.bind(this);
|
this._annotationRuler.onClick = this._annotationRulerClick.bind(this);
|
||||||
this._annotationRuler.addAnnotationType(ORION_ANNOTATION_TYPES.breakpoint);
|
this._annotationRuler.addAnnotationType(ORION_ANNOTATION_TYPES.breakpoint);
|
||||||
this._annotationRuler.setMultiAnnotation({
|
this._annotationRuler.addAnnotationType(ORION_ANNOTATION_TYPES.debugLocation);
|
||||||
html: "<div class='annotationHTML multiple'></div>"
|
|
||||||
});
|
|
||||||
this._annotationRuler.setMultiAnnotationOverlay({
|
|
||||||
html: "<div class='annotationHTML overlay'></div>"
|
|
||||||
});
|
|
||||||
this._view.addRuler(this._annotationRuler);
|
this._view.addRuler(this._annotationRuler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +381,7 @@ SourceEditor.prototype = {
|
||||||
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
|
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
|
||||||
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
|
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
|
||||||
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.breakpoint);
|
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.breakpoint);
|
||||||
|
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.debugLocation);
|
||||||
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.task);
|
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.task);
|
||||||
this._view.addRuler(this._overviewRuler);
|
this._view.addRuler(this._overviewRuler);
|
||||||
}
|
}
|
||||||
|
@ -394,6 +403,8 @@ SourceEditor.prototype = {
|
||||||
"Find Previous Occurrence": [this.ui.findPrevious, this.ui],
|
"Find Previous Occurrence": [this.ui.findPrevious, this.ui],
|
||||||
"Goto Line...": [this.ui.gotoLine, this.ui],
|
"Goto Line...": [this.ui.gotoLine, this.ui],
|
||||||
"Move Lines Down": [this._moveLines, this],
|
"Move Lines Down": [this._moveLines, this],
|
||||||
|
"Comment": [this._doComment, this],
|
||||||
|
"Uncomment": [this._doUncomment, this],
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let name in actions) {
|
for (let name in actions) {
|
||||||
|
@ -486,7 +497,7 @@ SourceEditor.prototype = {
|
||||||
let selection = this.getSelection();
|
let selection = this.getSelection();
|
||||||
let model = this._model;
|
let model = this._model;
|
||||||
let firstLine = model.getLineAtOffset(selection.start);
|
let firstLine = model.getLineAtOffset(selection.start);
|
||||||
let firstLineStart = model.getLineStart(firstLine);
|
let firstLineStart = this.getLineStart(firstLine);
|
||||||
let lastLineOffset = selection.end > selection.start ?
|
let lastLineOffset = selection.end > selection.start ?
|
||||||
selection.end - 1 : selection.end;
|
selection.end - 1 : selection.end;
|
||||||
let lastLine = model.getLineAtOffset(lastLineOffset);
|
let lastLine = model.getLineAtOffset(lastLineOffset);
|
||||||
|
@ -501,7 +512,7 @@ SourceEditor.prototype = {
|
||||||
// Do selection indentation.
|
// Do selection indentation.
|
||||||
if (firstLine != lastLine) {
|
if (firstLine != lastLine) {
|
||||||
let lines = [""];
|
let lines = [""];
|
||||||
let lastLineEnd = model.getLineEnd(lastLine, true);
|
let lastLineEnd = this.getLineEnd(lastLine, true);
|
||||||
let selectedLines = lastLine - firstLine + 1;
|
let selectedLines = lastLine - firstLine + 1;
|
||||||
|
|
||||||
for (let i = firstLine; i <= lastLine; i++) {
|
for (let i = firstLine; i <= lastLine; i++) {
|
||||||
|
@ -558,9 +569,9 @@ SourceEditor.prototype = {
|
||||||
lines.push(line.substring(indent.length));
|
lines.push(line.substring(indent.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
let firstLineStart = model.getLineStart(firstLine);
|
let firstLineStart = this.getLineStart(firstLine);
|
||||||
let lastLineStart = model.getLineStart(lastLine);
|
let lastLineStart = this.getLineStart(lastLine);
|
||||||
let lastLineEnd = model.getLineEnd(lastLine, true);
|
let lastLineEnd = this.getLineEnd(lastLine, true);
|
||||||
|
|
||||||
this.startCompoundChange();
|
this.startCompoundChange();
|
||||||
|
|
||||||
|
@ -602,7 +613,7 @@ SourceEditor.prototype = {
|
||||||
let model = this._model;
|
let model = this._model;
|
||||||
let lineIndex = model.getLineAtOffset(selection.start);
|
let lineIndex = model.getLineAtOffset(selection.start);
|
||||||
let lineText = model.getLine(lineIndex, true);
|
let lineText = model.getLine(lineIndex, true);
|
||||||
let lineStart = model.getLineStart(lineIndex);
|
let lineStart = this.getLineStart(lineIndex);
|
||||||
let index = 0;
|
let index = 0;
|
||||||
let lineOffset = selection.start - lineStart;
|
let lineOffset = selection.start - lineStart;
|
||||||
while (index < lineOffset && /[ \t]/.test(lineText.charAt(index))) {
|
while (index < lineOffset && /[ \t]/.test(lineText.charAt(index))) {
|
||||||
|
@ -646,8 +657,8 @@ SourceEditor.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastLine = model.getLineAtOffset(selection.end);
|
let lastLine = model.getLineAtOffset(selection.end);
|
||||||
let firstLineStart = model.getLineStart(firstLine);
|
let firstLineStart = this.getLineStart(firstLine);
|
||||||
let lastLineStart = model.getLineStart(lastLine);
|
let lastLineStart = this.getLineStart(lastLine);
|
||||||
if (selection.start != selection.end && lastLineStart == selection.end) {
|
if (selection.start != selection.end && lastLineStart == selection.end) {
|
||||||
lastLine--;
|
lastLine--;
|
||||||
}
|
}
|
||||||
|
@ -655,17 +666,17 @@ SourceEditor.prototype = {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastLineEnd = model.getLineEnd(lastLine, true);
|
let lastLineEnd = this.getLineEnd(lastLine, true);
|
||||||
let text = this.getText(firstLineStart, lastLineEnd);
|
let text = this.getText(firstLineStart, lastLineEnd);
|
||||||
|
|
||||||
if (aLineAbove) {
|
if (aLineAbove) {
|
||||||
let aboveLine = firstLine - 1;
|
let aboveLine = firstLine - 1;
|
||||||
let aboveLineStart = model.getLineStart(aboveLine);
|
let aboveLineStart = this.getLineStart(aboveLine);
|
||||||
|
|
||||||
this.startCompoundChange();
|
this.startCompoundChange();
|
||||||
if (lastLine == (this.getLineCount() - 1)) {
|
if (lastLine == (this.getLineCount() - 1)) {
|
||||||
let delimiterStart = model.getLineEnd(aboveLine);
|
let delimiterStart = this.getLineEnd(aboveLine);
|
||||||
let delimiterEnd = model.getLineEnd(aboveLine, true);
|
let delimiterEnd = this.getLineEnd(aboveLine, true);
|
||||||
let lineDelimiter = this.getText(delimiterStart, delimiterEnd);
|
let lineDelimiter = this.getText(delimiterStart, delimiterEnd);
|
||||||
text += lineDelimiter;
|
text += lineDelimiter;
|
||||||
this.setText("", firstLineStart - lineDelimiter.length, lastLineEnd);
|
this.setText("", firstLineStart - lineDelimiter.length, lastLineEnd);
|
||||||
|
@ -677,12 +688,12 @@ SourceEditor.prototype = {
|
||||||
this.setSelection(aboveLineStart, aboveLineStart + text.length);
|
this.setSelection(aboveLineStart, aboveLineStart + text.length);
|
||||||
} else {
|
} else {
|
||||||
let belowLine = lastLine + 1;
|
let belowLine = lastLine + 1;
|
||||||
let belowLineEnd = model.getLineEnd(belowLine, true);
|
let belowLineEnd = this.getLineEnd(belowLine, true);
|
||||||
|
|
||||||
let insertAt = belowLineEnd - lastLineEnd + firstLineStart;
|
let insertAt = belowLineEnd - lastLineEnd + firstLineStart;
|
||||||
let lineDelimiter = "";
|
let lineDelimiter = "";
|
||||||
if (belowLine == this.getLineCount() - 1) {
|
if (belowLine == this.getLineCount() - 1) {
|
||||||
let delimiterStart = model.getLineEnd(lastLine);
|
let delimiterStart = this.getLineEnd(lastLine);
|
||||||
lineDelimiter = this.getText(delimiterStart, lastLineEnd);
|
lineDelimiter = this.getText(delimiterStart, lastLineEnd);
|
||||||
text = lineDelimiter + text.substr(0, text.length -
|
text = lineDelimiter + text.substr(0, text.length -
|
||||||
lineDelimiter.length);
|
lineDelimiter.length);
|
||||||
|
@ -803,8 +814,8 @@ SourceEditor.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let line = model.getLineAtOffset(newSelection.start);
|
let line = model.getLineAtOffset(newSelection.start);
|
||||||
let lineStart = model.getLineStart(line);
|
let lineStart = this.getLineStart(line);
|
||||||
let lineEnd = model.getLineEnd(line);
|
let lineEnd = this.getLineEnd(line);
|
||||||
|
|
||||||
let title = oldAnnotation ? oldAnnotation.title :
|
let title = oldAnnotation ? oldAnnotation.title :
|
||||||
SourceEditorUI.strings.GetStringFromName("annotation.currentLine");
|
SourceEditorUI.strings.GetStringFromName("annotation.currentLine");
|
||||||
|
@ -846,9 +857,9 @@ SourceEditor.prototype = {
|
||||||
let selectionLineStart = model.getLineAtOffset(selection.start);
|
let selectionLineStart = model.getLineAtOffset(selection.start);
|
||||||
let selectionLineEnd = model.getLineAtOffset(selection.end);
|
let selectionLineEnd = model.getLineAtOffset(selection.end);
|
||||||
let newStart = aLineIndex <= selectionLineStart ?
|
let newStart = aLineIndex <= selectionLineStart ?
|
||||||
model.getLineStart(aLineIndex) : selection.start;
|
this.getLineStart(aLineIndex) : selection.start;
|
||||||
let newEnd = aLineIndex <= selectionLineStart ?
|
let newEnd = aLineIndex <= selectionLineStart ?
|
||||||
selection.end : model.getLineEnd(aLineIndex);
|
selection.end : this.getLineEnd(aLineIndex);
|
||||||
this.setSelection(newStart, newEnd);
|
this.setSelection(newStart, newEnd);
|
||||||
} else {
|
} else {
|
||||||
this.setCaretPosition(aLineIndex);
|
this.setCaretPosition(aLineIndex);
|
||||||
|
@ -871,8 +882,8 @@ SourceEditor.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let newStart = this._model.getLineStart(aLineIndex);
|
let newStart = this.getLineStart(aLineIndex);
|
||||||
let newEnd = this._model.getLineEnd(aLineIndex);
|
let newEnd = this.getLineEnd(aLineIndex);
|
||||||
this.setSelection(newStart, newEnd);
|
this.setSelection(newStart, newEnd);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -897,6 +908,7 @@ SourceEditor.prototype = {
|
||||||
styler.addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
|
styler.addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
|
||||||
styler.addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
|
styler.addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
|
||||||
styler.addAnnotationType(ORION_ANNOTATION_TYPES.task);
|
styler.addAnnotationType(ORION_ANNOTATION_TYPES.task);
|
||||||
|
styler.addAnnotationType(ORION_ANNOTATION_TYPES.debugLocation);
|
||||||
|
|
||||||
if (this._config.highlightCurrentLine) {
|
if (this._config.highlightCurrentLine) {
|
||||||
styler.addAnnotationType(ORION_ANNOTATION_TYPES.currentLine);
|
styler.addAnnotationType(ORION_ANNOTATION_TYPES.currentLine);
|
||||||
|
@ -946,8 +958,8 @@ SourceEditor.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lineStart = this._model.getLineStart(aLineIndex);
|
let lineStart = this.getLineStart(aLineIndex);
|
||||||
let lineEnd = this._model.getLineEnd(aLineIndex);
|
let lineEnd = this.getLineEnd(aLineIndex);
|
||||||
let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
|
let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
|
||||||
if (annotations.length > 0) {
|
if (annotations.length > 0) {
|
||||||
this.removeBreakpoint(aLineIndex);
|
this.removeBreakpoint(aLineIndex);
|
||||||
|
@ -973,8 +985,8 @@ SourceEditor.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let model = this._model;
|
let model = this._model;
|
||||||
let lineStart = model.getLineStart(aLineIndex);
|
let lineStart = this.getLineStart(aLineIndex);
|
||||||
let lineEnd = model.getLineEnd(aLineIndex);
|
let lineEnd = this.getLineEnd(aLineIndex);
|
||||||
let annotations = this._annotationModel.getAnnotations(lineStart, lineEnd);
|
let annotations = this._annotationModel.getAnnotations(lineStart, lineEnd);
|
||||||
let annotation = annotations.next();
|
let annotation = annotations.next();
|
||||||
|
|
||||||
|
@ -997,6 +1009,158 @@ SourceEditor.prototype = {
|
||||||
return this._iframe;
|
return this._iframe;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to retrieve the strings used for comments in the current
|
||||||
|
* editor mode.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @return object
|
||||||
|
* An object that holds the following properties:
|
||||||
|
* - line: the comment string used for the start of a single line
|
||||||
|
* comment.
|
||||||
|
* - blockStart: the comment string used for the start of a comment
|
||||||
|
* block.
|
||||||
|
* - blockEnd: the comment string used for the end of a block comment.
|
||||||
|
* Null is returned for unsupported editor modes.
|
||||||
|
*/
|
||||||
|
_getCommentStrings: function SE__getCommentStrings()
|
||||||
|
{
|
||||||
|
let line = "";
|
||||||
|
let blockCommentStart = "";
|
||||||
|
let blockCommentEnd = "";
|
||||||
|
|
||||||
|
switch (this.getMode()) {
|
||||||
|
case SourceEditor.MODES.JAVASCRIPT:
|
||||||
|
line = "//";
|
||||||
|
blockCommentStart = "/*";
|
||||||
|
blockCommentEnd = "*/";
|
||||||
|
break;
|
||||||
|
case SourceEditor.MODES.CSS:
|
||||||
|
blockCommentStart = "/*";
|
||||||
|
blockCommentEnd = "*/";
|
||||||
|
break;
|
||||||
|
case SourceEditor.MODES.HTML:
|
||||||
|
case SourceEditor.MODES.XML:
|
||||||
|
blockCommentStart = "<!--";
|
||||||
|
blockCommentEnd = "-->";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {line: line, blockStart: blockCommentStart, blockEnd: blockCommentEnd};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap the selected text in comments. If nothing is selected the current
|
||||||
|
* caret line is commented out. Single line and block comments depend on the
|
||||||
|
* current editor mode.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_doComment: function SE__doComment()
|
||||||
|
{
|
||||||
|
if (this.readOnly) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let commentObject = this._getCommentStrings();
|
||||||
|
if (!commentObject) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let selection = this.getSelection();
|
||||||
|
|
||||||
|
if (selection.start == selection.end) {
|
||||||
|
let selectionLine = this._model.getLineAtOffset(selection.start);
|
||||||
|
let lineStartOffset = this.getLineStart(selectionLine);
|
||||||
|
if (commentObject.line) {
|
||||||
|
this.setText(commentObject.line, lineStartOffset, lineStartOffset);
|
||||||
|
} else {
|
||||||
|
let lineEndOffset = this.getLineEnd(selectionLine);
|
||||||
|
this.startCompoundChange();
|
||||||
|
this.setText(commentObject.blockStart, lineStartOffset, lineStartOffset);
|
||||||
|
this.setText(commentObject.blockEnd,
|
||||||
|
lineEndOffset + commentObject.blockStart.length,
|
||||||
|
lineEndOffset + commentObject.blockStart.length);
|
||||||
|
this.endCompoundChange();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.startCompoundChange();
|
||||||
|
this.setText(commentObject.blockStart, selection.start, selection.start);
|
||||||
|
this.setText(commentObject.blockEnd,
|
||||||
|
selection.end + commentObject.blockStart.length,
|
||||||
|
selection.end + commentObject.blockStart.length);
|
||||||
|
this.endCompoundChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uncomment the selected text. If nothing is selected the current caret line
|
||||||
|
* is umcommented. Single line and block comments depend on the current editor
|
||||||
|
* mode.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_doUncomment: function SE__doUncomment()
|
||||||
|
{
|
||||||
|
if (this.readOnly) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let commentObject = this._getCommentStrings();
|
||||||
|
if (!commentObject) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let selection = this.getSelection();
|
||||||
|
let firstLine = this._model.getLineAtOffset(selection.start);
|
||||||
|
let lastLine = this._model.getLineAtOffset(selection.end);
|
||||||
|
|
||||||
|
// Uncomment a block of text.
|
||||||
|
let firstLineText = this._model.getLine(firstLine);
|
||||||
|
let lastLineText = this._model.getLine(lastLine);
|
||||||
|
let openIndex = firstLineText.indexOf(commentObject.blockStart);
|
||||||
|
let closeIndex = lastLineText.lastIndexOf(commentObject.blockEnd);
|
||||||
|
if (openIndex != -1 && closeIndex != -1) {
|
||||||
|
let firstLineStartOffset = this.getLineStart(firstLine);
|
||||||
|
let lastLineStartOffset = this.getLineStart(lastLine);
|
||||||
|
let openOffset = firstLineStartOffset + openIndex;
|
||||||
|
let closeOffset = lastLineStartOffset + closeIndex;
|
||||||
|
|
||||||
|
this.startCompoundChange();
|
||||||
|
this.setText("", closeOffset, closeOffset + commentObject.blockEnd.length);
|
||||||
|
this.setText("", openOffset, openOffset + commentObject.blockStart.length);
|
||||||
|
this.endCompoundChange();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!commentObject.line) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the selected text is not a block of comment, then uncomment each line.
|
||||||
|
this.startCompoundChange();
|
||||||
|
let lineCaret = firstLine;
|
||||||
|
while (lineCaret <= lastLine) {
|
||||||
|
let currentLine = this._model.getLine(lineCaret);
|
||||||
|
let lineStart = this.getLineStart(lineCaret);
|
||||||
|
let openIndex = currentLine.indexOf(commentObject.line);
|
||||||
|
let openOffset = lineStart + openIndex;
|
||||||
|
let textUntilComment = this.getText(lineStart, openOffset);
|
||||||
|
if (openIndex != -1 &&
|
||||||
|
(!textUntilComment || /^\s+$/.test(textUntilComment))) {
|
||||||
|
this.setText("", openOffset, openOffset + commentObject.line.length);
|
||||||
|
}
|
||||||
|
lineCaret++;
|
||||||
|
}
|
||||||
|
this.endCompoundChange();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an event listener to the editor. You can use one of the known events.
|
* Add an event listener to the editor. You can use one of the known events.
|
||||||
*
|
*
|
||||||
|
@ -1216,6 +1380,37 @@ SourceEditor.prototype = {
|
||||||
return this._view.getText(aStart, aEnd);
|
return this._view.getText(aStart, aEnd);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the start character offset of the line with index aLineIndex.
|
||||||
|
*
|
||||||
|
* @param number aLineIndex
|
||||||
|
* Zero based index of the line.
|
||||||
|
* @return number
|
||||||
|
* Line start offset or -1 if out of range.
|
||||||
|
*/
|
||||||
|
getLineStart: function SE_getLineStart(aLineIndex)
|
||||||
|
{
|
||||||
|
return this._model.getLineStart(aLineIndex);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the end character offset of the line with index aLineIndex,
|
||||||
|
* excluding the end offset. When the line delimiter is present,
|
||||||
|
* the offset is the start offset of the next line or the char count.
|
||||||
|
* Otherwise, it is the offset of the line delimiter.
|
||||||
|
*
|
||||||
|
* @param number aLineIndex
|
||||||
|
* Zero based index of the line.
|
||||||
|
* @param boolean [aIncludeDelimiter = false]
|
||||||
|
* Optional, whether or not to include the line delimiter.
|
||||||
|
* @return number
|
||||||
|
* Line end offset or -1 if out of range.
|
||||||
|
*/
|
||||||
|
getLineEnd: function SE_getLineEnd(aLineIndex, aIncludeDelimiter)
|
||||||
|
{
|
||||||
|
return this._model.getLineEnd(aLineIndex, aIncludeDelimiter);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of characters in the editor content.
|
* Get the number of characters in the editor content.
|
||||||
*
|
*
|
||||||
|
@ -1323,7 +1518,7 @@ SourceEditor.prototype = {
|
||||||
{
|
{
|
||||||
let offset = this.getCaretOffset();
|
let offset = this.getCaretOffset();
|
||||||
let line = this._model.getLineAtOffset(offset);
|
let line = this._model.getLineAtOffset(offset);
|
||||||
let lineStart = this._model.getLineStart(line);
|
let lineStart = this.getLineStart(line);
|
||||||
let column = offset - lineStart;
|
let column = offset - lineStart;
|
||||||
return {line: line, col: column};
|
return {line: line, col: column};
|
||||||
},
|
},
|
||||||
|
@ -1350,7 +1545,7 @@ SourceEditor.prototype = {
|
||||||
let halfVisible = Math.round(linesVisible/2);
|
let halfVisible = Math.round(linesVisible/2);
|
||||||
let firstVisible = this.getTopIndex();
|
let firstVisible = this.getTopIndex();
|
||||||
let lastVisible = this._view.getBottomIndex();
|
let lastVisible = this._view.getBottomIndex();
|
||||||
let caretOffset = this._model.getLineStart(aLine) + (aColumn || 0);
|
let caretOffset = this.getLineStart(aLine) + (aColumn || 0);
|
||||||
|
|
||||||
this._view.setSelection(caretOffset, caretOffset, false);
|
this._view.setSelection(caretOffset, caretOffset, false);
|
||||||
|
|
||||||
|
@ -1495,6 +1690,65 @@ SourceEditor.prototype = {
|
||||||
return this._view.getOptions("readonly");
|
return this._view.getOptions("readonly");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the current debugger location at the given line index. This is useful in
|
||||||
|
* a debugger or in any other context where the user needs to track the
|
||||||
|
* current state, where a debugger-like environment is at.
|
||||||
|
*
|
||||||
|
* @param number aLineIndex
|
||||||
|
* Line index of the current debugger location, starting from 0.
|
||||||
|
* Use any negative number to clear the current location.
|
||||||
|
*/
|
||||||
|
setDebugLocation: function SE_setDebugLocation(aLineIndex)
|
||||||
|
{
|
||||||
|
let annotations = this._getAnnotationsByType("debugLocation", 0,
|
||||||
|
this.getCharCount());
|
||||||
|
if (annotations.length > 0) {
|
||||||
|
annotations.forEach(this._annotationModel.removeAnnotation,
|
||||||
|
this._annotationModel);
|
||||||
|
}
|
||||||
|
if (aLineIndex < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let lineStart = this._model.getLineStart(aLineIndex);
|
||||||
|
let lineEnd = this._model.getLineEnd(aLineIndex);
|
||||||
|
let lineText = this._model.getLine(aLineIndex);
|
||||||
|
let title = SourceEditorUI.strings.
|
||||||
|
formatStringFromName("annotation.debugLocation.title",
|
||||||
|
[lineText], 1);
|
||||||
|
|
||||||
|
let annotation = {
|
||||||
|
type: ORION_ANNOTATION_TYPES.debugLocation,
|
||||||
|
start: lineStart,
|
||||||
|
end: lineEnd,
|
||||||
|
title: title,
|
||||||
|
style: {styleClass: "annotation debugLocation"},
|
||||||
|
html: "<div class='annotationHTML debugLocation'></div>",
|
||||||
|
overviewStyle: {styleClass: "annotationOverview debugLocation"},
|
||||||
|
rangeStyle: {styleClass: "annotationRange debugLocation"},
|
||||||
|
lineStyle: {styleClass: "annotationLine debugLocation"},
|
||||||
|
};
|
||||||
|
this._annotationModel.addAnnotation(annotation);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the current debugger line index configured for this editor.
|
||||||
|
*
|
||||||
|
* @return number
|
||||||
|
* The line index starting from 0 where the current debugger is
|
||||||
|
* paused. If no debugger location has been set -1 is returned.
|
||||||
|
*/
|
||||||
|
getDebugLocation: function SE_getDebugLocation()
|
||||||
|
{
|
||||||
|
let annotations = this._getAnnotationsByType("debugLocation", 0,
|
||||||
|
this.getCharCount());
|
||||||
|
if (annotations.length > 0) {
|
||||||
|
return this._model.getLineAtOffset(annotations[0].start);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a breakpoint at the given line index.
|
* Add a breakpoint at the given line index.
|
||||||
*
|
*
|
||||||
|
@ -1505,8 +1759,8 @@ SourceEditor.prototype = {
|
||||||
*/
|
*/
|
||||||
addBreakpoint: function SE_addBreakpoint(aLineIndex, aCondition)
|
addBreakpoint: function SE_addBreakpoint(aLineIndex, aCondition)
|
||||||
{
|
{
|
||||||
let lineStart = this._model.getLineStart(aLineIndex);
|
let lineStart = this.getLineStart(aLineIndex);
|
||||||
let lineEnd = this._model.getLineEnd(aLineIndex);
|
let lineEnd = this.getLineEnd(aLineIndex);
|
||||||
|
|
||||||
let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
|
let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
|
||||||
if (annotations.length > 0) {
|
if (annotations.length > 0) {
|
||||||
|
@ -1550,8 +1804,8 @@ SourceEditor.prototype = {
|
||||||
*/
|
*/
|
||||||
removeBreakpoint: function SE_removeBreakpoint(aLineIndex)
|
removeBreakpoint: function SE_removeBreakpoint(aLineIndex)
|
||||||
{
|
{
|
||||||
let lineStart = this._model.getLineStart(aLineIndex);
|
let lineStart = this.getLineStart(aLineIndex);
|
||||||
let lineEnd = this._model.getLineEnd(aLineIndex);
|
let lineEnd = this.getLineEnd(aLineIndex);
|
||||||
|
|
||||||
let event = {
|
let event = {
|
||||||
type: SourceEditor.EVENTS.BREAKPOINT_CHANGE,
|
type: SourceEditor.EVENTS.BREAKPOINT_CHANGE,
|
||||||
|
|
|
@ -61,6 +61,8 @@ _BROWSER_TEST_FILES = \
|
||||||
browser_bug725618_moveLines_shortcut.js \
|
browser_bug725618_moveLines_shortcut.js \
|
||||||
browser_bug700893_dirty_state.js \
|
browser_bug700893_dirty_state.js \
|
||||||
browser_bug729480_line_vertical_align.js \
|
browser_bug729480_line_vertical_align.js \
|
||||||
|
browser_bug725430_comment_uncomment.js \
|
||||||
|
browser_bug731721_debugger_stepping.js \
|
||||||
head.js \
|
head.js \
|
||||||
|
|
||||||
libs:: $(_BROWSER_TEST_FILES)
|
libs:: $(_BROWSER_TEST_FILES)
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
/* 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";
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
|
||||||
|
let temp = {};
|
||||||
|
Cu.import("resource:///modules/source-editor.jsm", temp);
|
||||||
|
let SourceEditor = temp.SourceEditor;
|
||||||
|
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
let editor;
|
||||||
|
|
||||||
|
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 725430' width='600' height='500'><hbox flex='1'/></window>";
|
||||||
|
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
||||||
|
|
||||||
|
let 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, {showLineNumbers: true}, editorLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
function editorLoaded()
|
||||||
|
{
|
||||||
|
editor.focus();
|
||||||
|
let text = "firstline\nsecondline\nthirdline\nfourthline";
|
||||||
|
|
||||||
|
editor.setMode(SourceEditor.MODES.JAVASCRIPT);
|
||||||
|
editor.setText(text)
|
||||||
|
|
||||||
|
editor.setCaretPosition(0);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
|
||||||
|
is(editor.getText(), "//" + text, "JS Single line Commenting Works");
|
||||||
|
editor.undo();
|
||||||
|
is(editor.getText(), text, "Undo Single Line Commenting action works");
|
||||||
|
editor.redo();
|
||||||
|
is(editor.getText(), "//" + text, "Redo works");
|
||||||
|
editor.setCaretPosition(0);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
|
||||||
|
is(editor.getText(), text, "JS Single Line Uncommenting works");
|
||||||
|
|
||||||
|
editor.setText(text);
|
||||||
|
|
||||||
|
EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
|
||||||
|
is(editor.getText(), "/*" + text + "*/", "JS Block Commenting works");
|
||||||
|
editor.undo();
|
||||||
|
is(editor.getText(), text, "Undo Block Commenting action works");
|
||||||
|
editor.redo();
|
||||||
|
is(editor.getText(), "/*" + text + "*/", "Redo works");
|
||||||
|
EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
|
||||||
|
is(editor.getText(), text, "JS Block Uncommenting works");
|
||||||
|
editor.undo();
|
||||||
|
is(editor.getText(), "/*" + text + "*/", "Undo Block Uncommenting works");
|
||||||
|
editor.redo();
|
||||||
|
is(editor.getText(), text, "Redo works");
|
||||||
|
|
||||||
|
let regText = "//firstline\n // secondline\nthird//line\nfourthline//";
|
||||||
|
let expText = "firstline\n secondline\nthird//line\nfourthline//";
|
||||||
|
editor.setText(regText);
|
||||||
|
EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
|
||||||
|
is(editor.getText(), expText, "JS Multiple Line Uncommenting works");
|
||||||
|
editor.undo();
|
||||||
|
is(editor.getText(), regText, "Undo Multiple Line Uncommenting works");
|
||||||
|
editor.redo();
|
||||||
|
is(editor.getText(), expText, "Redo works");
|
||||||
|
|
||||||
|
editor.setMode(SourceEditor.MODES.CSS);
|
||||||
|
editor.setText(text);
|
||||||
|
|
||||||
|
expText = "/*firstline*/\nsecondline\nthirdline\nfourthline";
|
||||||
|
editor.setCaretPosition(0);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
|
||||||
|
is(editor.getText(), expText, "CSS Commenting without selection works");
|
||||||
|
editor.setCaretPosition(0);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
|
||||||
|
is(editor.getText(), text, "CSS Uncommenting without selection works");
|
||||||
|
|
||||||
|
editor.setText(text);
|
||||||
|
|
||||||
|
EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
|
||||||
|
is(editor.getText(), "/*" + text + "*/", "CSS Multiple Line Commenting works");
|
||||||
|
EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
|
||||||
|
is(editor.getText(), text, "CSS Multiple Line Uncommenting works");
|
||||||
|
|
||||||
|
editor.setMode(SourceEditor.MODES.HTML);
|
||||||
|
editor.setText(text);
|
||||||
|
|
||||||
|
expText = "<!--firstline-->\nsecondline\nthirdline\nfourthline";
|
||||||
|
editor.setCaretPosition(0);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
|
||||||
|
is(editor.getText(), expText, "HTML Commenting without selection works");
|
||||||
|
editor.setCaretPosition(0);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
|
||||||
|
is(editor.getText(), text, "HTML Uncommenting without selection works");
|
||||||
|
|
||||||
|
editor.setText(text);
|
||||||
|
|
||||||
|
EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
|
||||||
|
is(editor.getText(), "<!--" + text + "-->", "HTML Multiple Line Commenting works");
|
||||||
|
EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
|
||||||
|
is(editor.getText(), text, "HTML Multiple Line Uncommenting works");
|
||||||
|
|
||||||
|
editor.setMode(SourceEditor.MODES.TEXT);
|
||||||
|
editor.setText(text);
|
||||||
|
|
||||||
|
editor.setCaretPosition(0);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
|
||||||
|
is(editor.getText(), text, "Commenting disabled in Text mode");
|
||||||
|
editor.setText("//" + text);
|
||||||
|
EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
|
||||||
|
is(editor.getText(), "//" + text, "Uncommenting disabled in Text mode");
|
||||||
|
|
||||||
|
editor.setText(text);
|
||||||
|
editor.readOnly = true;
|
||||||
|
|
||||||
|
editor.setCaretPosition(0);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true}, testWin);
|
||||||
|
is(editor.getText(), text, "Commenting disabled in ReadOnly mode");
|
||||||
|
editor.setText("//" + text);
|
||||||
|
EventUtils.synthesizeKey("VK_A", {accelKey: true}, testWin);
|
||||||
|
EventUtils.synthesizeKey("/", {accelKey: true, shiftKey: true}, testWin);
|
||||||
|
is(editor.getText(), "//" + text, "Uncommenting disabled in ReadOnly mode");
|
||||||
|
|
||||||
|
editor.destroy();
|
||||||
|
|
||||||
|
testWin.close();
|
||||||
|
testWin = editor = null;
|
||||||
|
|
||||||
|
waitForFocus(finish, window);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* 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";
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
|
||||||
|
let temp = {};
|
||||||
|
Cu.import("resource:///modules/source-editor.jsm", temp);
|
||||||
|
let SourceEditor = temp.SourceEditor;
|
||||||
|
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
let editor;
|
||||||
|
|
||||||
|
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 731721' width='600' height='500'><hbox flex='1'/></window>";
|
||||||
|
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
|
||||||
|
|
||||||
|
let 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, {showAnnotationRuler: true}, editorLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
function editorLoaded()
|
||||||
|
{
|
||||||
|
editor.focus();
|
||||||
|
|
||||||
|
editor.setText("line1\nline2\nline3\nline4");
|
||||||
|
|
||||||
|
is(editor.getDebugLocation(), -1, "no debugger location");
|
||||||
|
|
||||||
|
editor.setDebugLocation(1);
|
||||||
|
is(editor.getDebugLocation(), 1, "set debugger location works");
|
||||||
|
|
||||||
|
editor.setDebugLocation(3);
|
||||||
|
is(editor.getDebugLocation(), 3, "change debugger location works");
|
||||||
|
|
||||||
|
editor.setDebugLocation(-1);
|
||||||
|
is(editor.getDebugLocation(), -1, "clear debugger location works");
|
||||||
|
|
||||||
|
editor.destroy();
|
||||||
|
|
||||||
|
testWin.close();
|
||||||
|
testWin = editor = null;
|
||||||
|
|
||||||
|
waitForFocus(finish, window);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1375,6 +1375,7 @@ InplaceEditor.prototype = {
|
||||||
// up to the client), and b) without tweaking the style of the
|
// up to the client), and b) without tweaking the style of the
|
||||||
// original element, it might wrap differently or something.
|
// original element, it might wrap differently or something.
|
||||||
this._measurement = this.doc.createElementNS(HTML_NS, "span");
|
this._measurement = this.doc.createElementNS(HTML_NS, "span");
|
||||||
|
this._measurement.className = "autosizer";
|
||||||
this.elt.parentNode.appendChild(this._measurement);
|
this.elt.parentNode.appendChild(this._measurement);
|
||||||
let style = this._measurement.style;
|
let style = this._measurement.style;
|
||||||
style.visibility = "hidden";
|
style.visibility = "hidden";
|
||||||
|
|
|
@ -44,6 +44,7 @@ function whenHighlighting() {
|
||||||
"Highlighting a node that's not already visible should trigger a reset!");
|
"Highlighting a node that's not already visible should trigger a reset!");
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
|
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
|
||||||
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
|
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
|
||||||
presenter.highlightNode(null);
|
presenter.highlightNode(null);
|
||||||
});
|
});
|
||||||
|
@ -56,14 +57,13 @@ function whenUnhighlighting() {
|
||||||
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
|
Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
|
||||||
Services.obs.addObserver(cleanup, DESTROYED, false);
|
Services.obs.addObserver(cleanup, DESTROYED, false);
|
||||||
InspectorUI.closeInspectorUI();
|
InspectorUI.closeInspectorUI();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
|
|
||||||
Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
|
|
||||||
Services.obs.removeObserver(cleanup, DESTROYED);
|
Services.obs.removeObserver(cleanup, DESTROYED);
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
finish();
|
finish();
|
||||||
|
|
|
@ -43,6 +43,7 @@ function whenHighlighting() {
|
||||||
"Highlighting a node that's already visible shouldn't trigger a reset.");
|
"Highlighting a node that's already visible shouldn't trigger a reset.");
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
|
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
|
||||||
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
|
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
|
||||||
presenter.highlightNode(null);
|
presenter.highlightNode(null);
|
||||||
});
|
});
|
||||||
|
@ -55,14 +56,13 @@ function whenUnhighlighting() {
|
||||||
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
|
Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
|
||||||
Services.obs.addObserver(cleanup, DESTROYED, false);
|
Services.obs.addObserver(cleanup, DESTROYED, false);
|
||||||
InspectorUI.closeInspectorUI();
|
InspectorUI.closeInspectorUI();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
|
|
||||||
Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
|
|
||||||
Services.obs.removeObserver(cleanup, DESTROYED);
|
Services.obs.removeObserver(cleanup, DESTROYED);
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
finish();
|
finish();
|
||||||
|
|
|
@ -38,6 +38,7 @@ function whenHighlighting() {
|
||||||
"After highlighting a node, it should be highlighted. D'oh.");
|
"After highlighting a node, it should be highlighted. D'oh.");
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
|
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
|
||||||
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
|
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
|
||||||
presenter.highlightNodeAt(-1, -1);
|
presenter.highlightNodeAt(-1, -1);
|
||||||
});
|
});
|
||||||
|
@ -50,14 +51,13 @@ function whenUnhighlighting() {
|
||||||
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
|
Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
|
||||||
Services.obs.addObserver(cleanup, DESTROYED, false);
|
Services.obs.addObserver(cleanup, DESTROYED, false);
|
||||||
InspectorUI.closeInspectorUI();
|
InspectorUI.closeInspectorUI();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
|
|
||||||
Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
|
|
||||||
Services.obs.removeObserver(cleanup, DESTROYED);
|
Services.obs.removeObserver(cleanup, DESTROYED);
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
finish();
|
finish();
|
||||||
|
|
|
@ -38,6 +38,7 @@ function whenHighlighting() {
|
||||||
"After highlighting a node, it should be highlighted. D'oh.");
|
"After highlighting a node, it should be highlighted. D'oh.");
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
|
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
|
||||||
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
|
Services.obs.addObserver(whenUnhighlighting, UNHIGHLIGHTING, false);
|
||||||
presenter.highlightNodeFor(-1);
|
presenter.highlightNodeFor(-1);
|
||||||
});
|
});
|
||||||
|
@ -50,14 +51,13 @@ function whenUnhighlighting() {
|
||||||
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
"After unhighlighting a node, it shouldn't be highlighted anymore. D'oh.");
|
||||||
|
|
||||||
executeSoon(function() {
|
executeSoon(function() {
|
||||||
|
Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
|
||||||
Services.obs.addObserver(cleanup, DESTROYED, false);
|
Services.obs.addObserver(cleanup, DESTROYED, false);
|
||||||
InspectorUI.closeInspectorUI();
|
InspectorUI.closeInspectorUI();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
Services.obs.removeObserver(whenHighlighting, HIGHLIGHTING);
|
|
||||||
Services.obs.removeObserver(whenUnhighlighting, UNHIGHLIGHTING);
|
|
||||||
Services.obs.removeObserver(cleanup, DESTROYED);
|
Services.obs.removeObserver(cleanup, DESTROYED);
|
||||||
gBrowser.removeCurrentTab();
|
gBrowser.removeCurrentTab();
|
||||||
finish();
|
finish();
|
||||||
|
|
|
@ -19,6 +19,18 @@
|
||||||
- button that closes the debugger UI. -->
|
- button that closes the debugger UI. -->
|
||||||
<!ENTITY debuggerUI.closeButton "Close">
|
<!ENTITY debuggerUI.closeButton "Close">
|
||||||
|
|
||||||
|
<!-- LOCALIZATION NOTE (debuggerUI.stepOverButton): This is the label for the
|
||||||
|
- button that steps over a function call. -->
|
||||||
|
<!ENTITY debuggerUI.stepOverButton "Step Over">
|
||||||
|
|
||||||
|
<!-- LOCALIZATION NOTE (debuggerUI.stepInButton): This is the label for the
|
||||||
|
- button that steps into a function call. -->
|
||||||
|
<!ENTITY debuggerUI.stepInButton "Step In">
|
||||||
|
|
||||||
|
<!-- LOCALIZATION NOTE (debuggerUI.stepOutButton): This is the label for the
|
||||||
|
- button that steps out of a function call. -->
|
||||||
|
<!ENTITY debuggerUI.stepOutButton "Step Out">
|
||||||
|
|
||||||
<!-- LOCALIZATION NOTE (debuggerUI.stackTitle): This is the label for the
|
<!-- LOCALIZATION NOTE (debuggerUI.stackTitle): This is the label for the
|
||||||
- widget that displays the call stack frames in the debugger. -->
|
- widget that displays the call stack frames in the debugger. -->
|
||||||
<!ENTITY debuggerUI.stackTitle "Call stack">
|
<!ENTITY debuggerUI.stackTitle "Call stack">
|
||||||
|
|
|
@ -38,3 +38,9 @@ annotation.breakpoint.title=Breakpoint: %S
|
||||||
# a tooltip displayed in any of the editor gutters when the user hovers the
|
# a tooltip displayed in any of the editor gutters when the user hovers the
|
||||||
# current line.
|
# current line.
|
||||||
annotation.currentLine=Current line
|
annotation.currentLine=Current line
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (annotation.debugLocation.title): This is the text shown in
|
||||||
|
# a tooltip displayed in any of the editor gutters when the user hovers the
|
||||||
|
# current debugger location. The debugger can pause the JavaScript execution at
|
||||||
|
# user-defined lines.
|
||||||
|
annotation.debugLocation.title=Current step: %S
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 203 B |
|
@ -61,6 +61,9 @@
|
||||||
.annotationHTML.breakpoint {
|
.annotationHTML.breakpoint {
|
||||||
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
|
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
|
||||||
}
|
}
|
||||||
|
.annotationHTML.debugLocation {
|
||||||
|
background-image: url("chrome://browser/skin/devtools/orion-debug-location.png");
|
||||||
|
}
|
||||||
|
|
||||||
/* Styles for the overview ruler */
|
/* Styles for the overview ruler */
|
||||||
.annotationOverview {
|
.annotationOverview {
|
||||||
|
@ -77,6 +80,10 @@
|
||||||
background-color: lightblue;
|
background-color: lightblue;
|
||||||
border: 1px solid blue;
|
border: 1px solid blue;
|
||||||
}
|
}
|
||||||
|
.annotationOverview.debugLocation {
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid green;
|
||||||
|
}
|
||||||
.annotationOverview.currentBracket {
|
.annotationOverview.currentBracket {
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
border: 1px solid red;
|
border: 1px solid red;
|
||||||
|
|
|
@ -98,6 +98,7 @@ browser.jar:
|
||||||
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||||
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
||||||
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
||||||
|
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
||||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png)
|
skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png)
|
||||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png)
|
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png)
|
||||||
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png (devtools/breadcrumbs/ltr-end-selected.png)
|
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png (devtools/breadcrumbs/ltr-end-selected.png)
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 203 B |
|
@ -61,6 +61,9 @@
|
||||||
.annotationHTML.breakpoint {
|
.annotationHTML.breakpoint {
|
||||||
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
|
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
|
||||||
}
|
}
|
||||||
|
.annotationHTML.debugLocation {
|
||||||
|
background-image: url("chrome://browser/skin/devtools/orion-debug-location.png");
|
||||||
|
}
|
||||||
|
|
||||||
/* Styles for the overview ruler */
|
/* Styles for the overview ruler */
|
||||||
.annotationOverview {
|
.annotationOverview {
|
||||||
|
@ -77,6 +80,10 @@
|
||||||
background-color: lightblue;
|
background-color: lightblue;
|
||||||
border: 1px solid blue;
|
border: 1px solid blue;
|
||||||
}
|
}
|
||||||
|
.annotationOverview.debugLocation {
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid green;
|
||||||
|
}
|
||||||
.annotationOverview.currentBracket {
|
.annotationOverview.currentBracket {
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
border: 1px solid red;
|
border: 1px solid red;
|
||||||
|
|
|
@ -134,6 +134,7 @@ browser.jar:
|
||||||
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||||
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
||||||
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
||||||
|
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
||||||
skin/classic/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
|
skin/classic/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
|
||||||
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||||
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 203 B |
|
@ -61,6 +61,9 @@
|
||||||
.annotationHTML.breakpoint {
|
.annotationHTML.breakpoint {
|
||||||
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
|
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
|
||||||
}
|
}
|
||||||
|
.annotationHTML.debugLocation {
|
||||||
|
background-image: url("chrome://browser/skin/devtools/orion-debug-location.png");
|
||||||
|
}
|
||||||
|
|
||||||
/* Styles for the overview ruler */
|
/* Styles for the overview ruler */
|
||||||
.annotationOverview {
|
.annotationOverview {
|
||||||
|
@ -77,6 +80,10 @@
|
||||||
background-color: lightblue;
|
background-color: lightblue;
|
||||||
border: 1px solid blue;
|
border: 1px solid blue;
|
||||||
}
|
}
|
||||||
|
.annotationOverview.debugLocation {
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid green;
|
||||||
|
}
|
||||||
.annotationOverview.currentBracket {
|
.annotationOverview.currentBracket {
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
border: 1px solid red;
|
border: 1px solid red;
|
||||||
|
|
|
@ -121,6 +121,7 @@ browser.jar:
|
||||||
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||||
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
|
||||||
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
||||||
|
skin/classic/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
||||||
skin/classic/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
|
skin/classic/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
|
||||||
skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||||
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||||
|
@ -293,6 +294,7 @@ browser.jar:
|
||||||
skin/classic/aero/browser/devtools/orion-container.css (devtools/orion-container.css)
|
skin/classic/aero/browser/devtools/orion-container.css (devtools/orion-container.css)
|
||||||
skin/classic/aero/browser/devtools/orion-task.png (devtools/orion-task.png)
|
skin/classic/aero/browser/devtools/orion-task.png (devtools/orion-task.png)
|
||||||
skin/classic/aero/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
skin/classic/aero/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
|
||||||
|
skin/classic/aero/browser/devtools/orion-debug-location.png (devtools/orion-debug-location.png)
|
||||||
skin/classic/aero/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
|
skin/classic/aero/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
|
||||||
skin/classic/aero/browser/devtools/webconsole.css (devtools/webconsole.css)
|
skin/classic/aero/browser/devtools/webconsole.css (devtools/webconsole.css)
|
||||||
skin/classic/aero/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
skin/classic/aero/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
|
||||||
|
|
|
@ -541,12 +541,16 @@ ThreadClient.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resume a paused thread.
|
* Resume a paused thread. If the optional aLimit parameter is present, then
|
||||||
|
* the thread will also pause when that limit is reached.
|
||||||
*
|
*
|
||||||
* @param function aOnResponse
|
* @param function aOnResponse
|
||||||
* Called with the response packet.
|
* Called with the response packet.
|
||||||
|
* @param [optional] object aLimit
|
||||||
|
* An object with a type property set to the appropriate limit (next,
|
||||||
|
* step, or finish) per the remote debugging protocol specification.
|
||||||
*/
|
*/
|
||||||
resume: function TC_resume(aOnResponse) {
|
resume: function TC_resume(aOnResponse, aLimit) {
|
||||||
this._assertPaused("resume");
|
this._assertPaused("resume");
|
||||||
|
|
||||||
// Put the client in a tentative "resuming" state so we can prevent
|
// Put the client in a tentative "resuming" state so we can prevent
|
||||||
|
@ -554,7 +558,8 @@ ThreadClient.prototype = {
|
||||||
this._state = "resuming";
|
this._state = "resuming";
|
||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
let packet = { to: this._actor, type: DebugProtocolTypes.resume };
|
let packet = { to: this._actor, type: DebugProtocolTypes.resume,
|
||||||
|
resumeLimit: aLimit };
|
||||||
this._client.request(packet, function(aResponse) {
|
this._client.request(packet, function(aResponse) {
|
||||||
if (aResponse.error) {
|
if (aResponse.error) {
|
||||||
// There was an error resuming, back to paused state.
|
// There was an error resuming, back to paused state.
|
||||||
|
@ -566,6 +571,36 @@ ThreadClient.prototype = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step over a function call.
|
||||||
|
*
|
||||||
|
* @param function aOnResponse
|
||||||
|
* Called with the response packet.
|
||||||
|
*/
|
||||||
|
stepOver: function TC_stepOver(aOnResponse) {
|
||||||
|
this.resume(aOnResponse, { type: "next" });
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step into a function call.
|
||||||
|
*
|
||||||
|
* @param function aOnResponse
|
||||||
|
* Called with the response packet.
|
||||||
|
*/
|
||||||
|
stepIn: function TC_stepIn(aOnResponse) {
|
||||||
|
this.resume(aOnResponse, { type: "step" });
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Step out of a function call.
|
||||||
|
*
|
||||||
|
* @param function aOnResponse
|
||||||
|
* Called with the response packet.
|
||||||
|
*/
|
||||||
|
stepOut: function TC_stepOut(aOnResponse) {
|
||||||
|
this.resume(aOnResponse, { type: "finish" });
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interrupt a running thread.
|
* Interrupt a running thread.
|
||||||
*
|
*
|
||||||
|
|
|
@ -197,12 +197,130 @@ ThreadActor.prototype = {
|
||||||
return { type: "detached" };
|
return { type: "detached" };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause the debuggee, by entering a nested event loop, and return a 'paused'
|
||||||
|
* packet to the client.
|
||||||
|
*
|
||||||
|
* @param Debugger.Frame aFrame
|
||||||
|
* The newest debuggee frame in the stack.
|
||||||
|
* @param object aReason
|
||||||
|
* An object with a 'type' property containing the reason for the pause.
|
||||||
|
*/
|
||||||
|
_pauseAndRespond: function TA__pauseAndRespond(aFrame, aReason) {
|
||||||
|
try {
|
||||||
|
let packet = this._paused(aFrame);
|
||||||
|
if (!packet) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
packet.why = aReason;
|
||||||
|
this.conn.send(packet);
|
||||||
|
return this._nest();
|
||||||
|
} catch(e) {
|
||||||
|
Cu.reportError("Got an exception during TA__pauseAndRespond: " + e +
|
||||||
|
": " + e.stack);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a protocol request to resume execution of the debuggee.
|
||||||
|
*/
|
||||||
onResume: function TA_onResume(aRequest) {
|
onResume: function TA_onResume(aRequest) {
|
||||||
|
if (aRequest && aRequest.forceCompletion) {
|
||||||
|
// TODO: remove this when Debugger.Frame.prototype.pop is implemented in
|
||||||
|
// bug 736733.
|
||||||
|
if (typeof this.frame.pop != "function") {
|
||||||
|
return { error: "notImplemented",
|
||||||
|
message: "forced completion is not yet implemented." };
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dbg.getNewestFrame().pop(aRequest.completionValue);
|
||||||
|
let packet = this._resumed();
|
||||||
|
DebuggerServer.xpcInspector.exitNestedEventLoop();
|
||||||
|
return { type: "resumeLimit", frameFinished: aRequest.forceCompletion };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aRequest && aRequest.resumeLimit) {
|
||||||
|
// Bind these methods because some of the hooks are called with 'this'
|
||||||
|
// set to the current frame.
|
||||||
|
let pauseAndRespond = this._pauseAndRespond.bind(this);
|
||||||
|
let createValueGrip = this.createValueGrip.bind(this);
|
||||||
|
|
||||||
|
let startFrame = this._youngestFrame;
|
||||||
|
let startLine;
|
||||||
|
if (this._youngestFrame.script) {
|
||||||
|
let offset = this._youngestFrame.offset;
|
||||||
|
startLine = this._youngestFrame.script.getOffsetLine(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the JS hook functions for stepping.
|
||||||
|
|
||||||
|
let onEnterFrame = function TA_onEnterFrame(aFrame) {
|
||||||
|
return pauseAndRespond(aFrame, { type: "resumeLimit" });
|
||||||
|
};
|
||||||
|
|
||||||
|
let onPop = function TA_onPop(aCompletion) {
|
||||||
|
// onPop is called with 'this' set to the current frame.
|
||||||
|
|
||||||
|
// Note that we're popping this frame; we need to watch for
|
||||||
|
// subsequent step events on its caller.
|
||||||
|
this.reportedPop = true;
|
||||||
|
|
||||||
|
return pauseAndRespond(this, { type: "resumeLimit" });
|
||||||
|
}
|
||||||
|
|
||||||
|
let onStep = function TA_onStep() {
|
||||||
|
// onStep is called with 'this' set to the current frame.
|
||||||
|
|
||||||
|
// If we've changed frame or line, then report that.
|
||||||
|
if (this !== startFrame ||
|
||||||
|
(this.script &&
|
||||||
|
this.script.getOffsetLine(this.offset) != startLine)) {
|
||||||
|
return pauseAndRespond(this, { type: "resumeLimit" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, let execution continue.
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (aRequest.resumeLimit.type) {
|
||||||
|
case "step":
|
||||||
|
this.dbg.onEnterFrame = onEnterFrame;
|
||||||
|
// Fall through.
|
||||||
|
case "next":
|
||||||
|
let stepFrame = this._getNextStepFrame(startFrame);
|
||||||
|
if (stepFrame) {
|
||||||
|
stepFrame.onStep = onStep;
|
||||||
|
stepFrame.onPop = onPop;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "finish":
|
||||||
|
stepFrame = this._getNextStepFrame(startFrame);
|
||||||
|
if (stepFrame) {
|
||||||
|
stepFrame.onPop = onPop;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return { error: "badParameterType",
|
||||||
|
message: "Unknown resumeLimit type" };
|
||||||
|
}
|
||||||
|
}
|
||||||
let packet = this._resumed();
|
let packet = this._resumed();
|
||||||
DebuggerServer.xpcInspector.exitNestedEventLoop();
|
DebuggerServer.xpcInspector.exitNestedEventLoop();
|
||||||
return packet;
|
return packet;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method that returns the next frame when stepping.
|
||||||
|
*/
|
||||||
|
_getNextStepFrame: function TA__getNextStepFrame(aFrame) {
|
||||||
|
let stepFrame = aFrame.reportedPop ? aFrame.older : aFrame;
|
||||||
|
if (!stepFrame || !stepFrame.script) {
|
||||||
|
stepFrame = null;
|
||||||
|
}
|
||||||
|
return stepFrame;
|
||||||
|
},
|
||||||
|
|
||||||
onClientEvaluate: function TA_onClientEvaluate(aRequest) {
|
onClientEvaluate: function TA_onClientEvaluate(aRequest) {
|
||||||
if (this.state !== "paused") {
|
if (this.state !== "paused") {
|
||||||
return { error: "wrongState",
|
return { error: "wrongState",
|
||||||
|
@ -472,6 +590,13 @@ ThreadActor.prototype = {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear stepping hooks.
|
||||||
|
this.dbg.onEnterFrame = undefined;
|
||||||
|
if (aFrame) {
|
||||||
|
aFrame.onStep = undefined;
|
||||||
|
aFrame.onPop = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
this._state = "paused";
|
this._state = "paused";
|
||||||
|
|
||||||
// Save the pause frame (if any) as the youngest frame for
|
// Save the pause frame (if any) as the youngest frame for
|
||||||
|
@ -730,19 +855,7 @@ ThreadActor.prototype = {
|
||||||
* The stack frame that contained the debugger statement.
|
* The stack frame that contained the debugger statement.
|
||||||
*/
|
*/
|
||||||
onDebuggerStatement: function TA_onDebuggerStatement(aFrame) {
|
onDebuggerStatement: function TA_onDebuggerStatement(aFrame) {
|
||||||
try {
|
return this._pauseAndRespond(aFrame, { type: "debuggerStatement" });
|
||||||
let packet = this._paused(aFrame);
|
|
||||||
if (!packet) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
packet.why = { type: "debuggerStatement" };
|
|
||||||
this.conn.send(packet);
|
|
||||||
return this._nest();
|
|
||||||
} catch(e) {
|
|
||||||
Cu.reportError("Got an exception during onDebuggerStatement: " + e +
|
|
||||||
": " + e.stack);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1153,9 +1266,21 @@ FrameActor.prototype = {
|
||||||
* The protocol request object.
|
* The protocol request object.
|
||||||
*/
|
*/
|
||||||
onPop: function FA_onPop(aRequest) {
|
onPop: function FA_onPop(aRequest) {
|
||||||
|
// TODO: remove this when Debugger.Frame.prototype.pop is implemented
|
||||||
|
if (typeof this.frame.pop != "function") {
|
||||||
return { error: "notImplemented",
|
return { error: "notImplemented",
|
||||||
message: "Popping frames is not yet implemented." };
|
message: "Popping frames is not yet implemented." };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (this.frame != this.threadActor.dbg.getNewestFrame()) {
|
||||||
|
this.threadActor.dbg.getNewestFrame().pop();
|
||||||
|
}
|
||||||
|
this.frame.pop(aRequest.completionValue);
|
||||||
|
|
||||||
|
// TODO: return the watches property when frame pop watch actors are
|
||||||
|
// implemented.
|
||||||
|
return { from: this.actorID };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
FrameActor.prototype.requestTypes = {
|
FrameActor.prototype.requestTypes = {
|
||||||
|
@ -1189,19 +1314,9 @@ BreakpointActor.prototype = {
|
||||||
* The stack frame that contained the breakpoint.
|
* The stack frame that contained the breakpoint.
|
||||||
*/
|
*/
|
||||||
hit: function BA_hit(aFrame) {
|
hit: function BA_hit(aFrame) {
|
||||||
try {
|
// TODO: add the rest of the breakpoints on that line (bug 676602).
|
||||||
let packet = this.threadActor._paused(aFrame);
|
let reason = { type: "breakpoint", actors: [ this.actorID ] };
|
||||||
if (!packet) {
|
return this.threadActor._pauseAndRespond(aFrame, reason);
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
// TODO: add the rest of the breakpoints on that line.
|
|
||||||
packet.why = { type: "breakpoint", actors: [ this.actorID ] };
|
|
||||||
this.conn.send(packet);
|
|
||||||
return this.threadActor._nest();
|
|
||||||
} catch(e) {
|
|
||||||
Cu.reportError("Got an exception during hit: " + e + ': ' + e.stack);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,7 +15,9 @@ function run_test()
|
||||||
gDebuggee = addTestGlobal("test-stack");
|
gDebuggee = addTestGlobal("test-stack");
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
gClient.connect(function () {
|
gClient.connect(function () {
|
||||||
attachTestGlobalClientAndResume(gClient, "test-stack", function (aResponse, aThreadClient) {
|
attachTestGlobalClientAndResume(gClient,
|
||||||
|
"test-stack",
|
||||||
|
function (aResponse, aThreadClient) {
|
||||||
gThreadClient = aThreadClient;
|
gThreadClient = aThreadClient;
|
||||||
test_simple_breakpoint();
|
test_simple_breakpoint();
|
||||||
});
|
});
|
||||||
|
@ -27,10 +29,13 @@ function test_simple_breakpoint()
|
||||||
{
|
{
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
let path = getFilePath('test_breakpoint-01.js');
|
let path = getFilePath('test_breakpoint-01.js');
|
||||||
gThreadClient.setBreakpoint({ url: path, line: gDebuggee.line0 + 3}, function (aResponse, bpClient) {
|
let location = { url: path, line: gDebuggee.line0 + 3};
|
||||||
|
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
// Check the return value.
|
// Check the return value.
|
||||||
do_check_eq(aPacket.type, "paused");
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.url, path);
|
||||||
|
do_check_eq(aPacket.frame.where.line, location.line);
|
||||||
do_check_eq(aPacket.why.type, "breakpoint");
|
do_check_eq(aPacket.why.type, "breakpoint");
|
||||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||||
// Check that the breakpoint worked.
|
// Check that the breakpoint worked.
|
||||||
|
|
|
@ -15,7 +15,9 @@ function run_test()
|
||||||
gDebuggee = addTestGlobal("test-stack");
|
gDebuggee = addTestGlobal("test-stack");
|
||||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
gClient.connect(function () {
|
gClient.connect(function () {
|
||||||
attachTestGlobalClientAndResume(gClient, "test-stack", function (aResponse, aThreadClient) {
|
attachTestGlobalClientAndResume(gClient,
|
||||||
|
"test-stack",
|
||||||
|
function (aResponse, aThreadClient) {
|
||||||
gThreadClient = aThreadClient;
|
gThreadClient = aThreadClient;
|
||||||
test_breakpoint_running();
|
test_breakpoint_running();
|
||||||
});
|
});
|
||||||
|
@ -26,6 +28,7 @@ function run_test()
|
||||||
function test_breakpoint_running()
|
function test_breakpoint_running()
|
||||||
{
|
{
|
||||||
let path = getFilePath('test_breakpoint-01.js');
|
let path = getFilePath('test_breakpoint-01.js');
|
||||||
|
let location = { url: path, line: gDebuggee.line0 + 3};
|
||||||
|
|
||||||
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||||
"var a = 1;\n" + // line0 + 1
|
"var a = 1;\n" + // line0 + 1
|
||||||
|
@ -34,10 +37,12 @@ function test_breakpoint_running()
|
||||||
// Setting the breakpoint later should interrupt the debuggee.
|
// Setting the breakpoint later should interrupt the debuggee.
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
do_check_eq(aPacket.type, "paused");
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.url, path);
|
||||||
|
do_check_eq(aPacket.frame.where.line, location);
|
||||||
do_check_eq(aPacket.why.type, "interrupted");
|
do_check_eq(aPacket.why.type, "interrupted");
|
||||||
});
|
});
|
||||||
|
|
||||||
gThreadClient.setBreakpoint({ url: path, line: gDebuggee.line0 + 3}, function(aResponse) {
|
gThreadClient.setBreakpoint(location, function(aResponse) {
|
||||||
// Eval scripts don't stick around long enough for the breakpoint to be set,
|
// 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.
|
// so just make sure we got the expected response from the actor.
|
||||||
do_check_eq(aResponse.error, "noScript");
|
do_check_eq(aResponse.error, "noScript");
|
||||||
|
|
|
@ -37,6 +37,8 @@ function test_skip_breakpoint()
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
// Check the return value.
|
// Check the return value.
|
||||||
do_check_eq(aPacket.type, "paused");
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.url, path);
|
||||||
|
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||||
do_check_eq(aPacket.why.type, "breakpoint");
|
do_check_eq(aPacket.why.type, "breakpoint");
|
||||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||||
// Check that the breakpoint worked.
|
// Check that the breakpoint worked.
|
||||||
|
|
|
@ -36,6 +36,8 @@ function test_child_breakpoint()
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
// Check the return value.
|
// Check the return value.
|
||||||
do_check_eq(aPacket.type, "paused");
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.url, path);
|
||||||
|
do_check_eq(aPacket.frame.where.line, location.line);
|
||||||
do_check_eq(aPacket.why.type, "breakpoint");
|
do_check_eq(aPacket.why.type, "breakpoint");
|
||||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||||
// Check that the breakpoint worked.
|
// Check that the breakpoint worked.
|
||||||
|
|
|
@ -38,6 +38,8 @@ function test_child_skip_breakpoint()
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
// Check the return value.
|
// Check the return value.
|
||||||
do_check_eq(aPacket.type, "paused");
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.url, path);
|
||||||
|
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||||
do_check_eq(aPacket.why.type, "breakpoint");
|
do_check_eq(aPacket.why.type, "breakpoint");
|
||||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||||
// Check that the breakpoint worked.
|
// Check that the breakpoint worked.
|
||||||
|
|
|
@ -38,6 +38,8 @@ function test_nested_breakpoint()
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
// Check the return value.
|
// Check the return value.
|
||||||
do_check_eq(aPacket.type, "paused");
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.url, path);
|
||||||
|
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||||
do_check_eq(aPacket.why.type, "breakpoint");
|
do_check_eq(aPacket.why.type, "breakpoint");
|
||||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||||
// Check that the breakpoint worked.
|
// Check that the breakpoint worked.
|
||||||
|
|
|
@ -38,6 +38,8 @@ function test_second_child_skip_breakpoint()
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
// Check the return value.
|
// Check the return value.
|
||||||
do_check_eq(aPacket.type, "paused");
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.url, path);
|
||||||
|
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||||
do_check_eq(aPacket.why.type, "breakpoint");
|
do_check_eq(aPacket.why.type, "breakpoint");
|
||||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||||
// Check that the breakpoint worked.
|
// Check that the breakpoint worked.
|
||||||
|
|
|
@ -38,6 +38,8 @@ function test_child_skip_breakpoint()
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
// Check the return value.
|
// Check the return value.
|
||||||
do_check_eq(aPacket.type, "paused");
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.url, path);
|
||||||
|
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||||
do_check_eq(aPacket.why.type, "breakpoint");
|
do_check_eq(aPacket.why.type, "breakpoint");
|
||||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||||
// Check that the breakpoint worked.
|
// Check that the breakpoint worked.
|
||||||
|
|
|
@ -32,9 +32,14 @@ function test_remove_breakpoint()
|
||||||
let path = getFilePath('test_breakpoint-09.js');
|
let path = getFilePath('test_breakpoint-09.js');
|
||||||
let location = { url: path, line: gDebuggee.line0 + 1};
|
let location = { url: path, line: gDebuggee.line0 + 1};
|
||||||
gThreadClient.setBreakpoint(location, function (aResponse, bpClient) {
|
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) {
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
// Check the return value.
|
// Check the return value.
|
||||||
do_check_eq(aPacket.type, "paused");
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.url, path);
|
||||||
|
do_check_eq(aPacket.frame.where.line, location.line + 1);
|
||||||
do_check_eq(aPacket.why.type, "breakpoint");
|
do_check_eq(aPacket.why.type, "breakpoint");
|
||||||
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
do_check_eq(aPacket.why.actors[0], bpClient.actor);
|
||||||
// Check that the breakpoint worked.
|
// Check that the breakpoint worked.
|
||||||
|
@ -43,7 +48,8 @@ function test_remove_breakpoint()
|
||||||
// Remove the breakpoint.
|
// Remove the breakpoint.
|
||||||
bpClient.remove(function (aResponse) {
|
bpClient.remove(function (aResponse) {
|
||||||
done = true;
|
done = true;
|
||||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
gThreadClient.addOneTimeListener("paused",
|
||||||
|
function (aEvent, aPacket) {
|
||||||
// The breakpoint should not be hit again.
|
// The breakpoint should not be hit again.
|
||||||
gThreadClient.resume(function () {
|
gThreadClient.resume(function () {
|
||||||
do_check_true(false);
|
do_check_true(false);
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check basic step-over functionality.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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_simple_stepping();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_simple_stepping()
|
||||||
|
{
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
// Check the return value.
|
||||||
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 2);
|
||||||
|
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||||
|
// Check that stepping worked.
|
||||||
|
do_check_eq(gDebuggee.a, undefined);
|
||||||
|
do_check_eq(gDebuggee.b, undefined);
|
||||||
|
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
// Check the return value.
|
||||||
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
|
||||||
|
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||||
|
// Check that stepping worked.
|
||||||
|
do_check_eq(gDebuggee.a, 1);
|
||||||
|
do_check_eq(gDebuggee.b, undefined);
|
||||||
|
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
// Check the return value.
|
||||||
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
// When leaving a stack frame the line number doesn't change.
|
||||||
|
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
|
||||||
|
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||||
|
// Check that stepping worked.
|
||||||
|
do_check_eq(gDebuggee.a, 1);
|
||||||
|
do_check_eq(gDebuggee.b, 2);
|
||||||
|
|
||||||
|
gThreadClient.resume(function () {
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
gThreadClient.stepOver();
|
||||||
|
});
|
||||||
|
gThreadClient.stepOver();
|
||||||
|
|
||||||
|
});
|
||||||
|
gThreadClient.stepOver();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||||
|
"debugger;\n" + // line0 + 1
|
||||||
|
"var a = 1;\n" + // line0 + 2
|
||||||
|
"var b = 2;\n"); // line0 + 3
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check basic step-in functionality.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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_simple_stepping();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_simple_stepping()
|
||||||
|
{
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
// Check the return value.
|
||||||
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 2);
|
||||||
|
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||||
|
// Check that stepping worked.
|
||||||
|
do_check_eq(gDebuggee.a, undefined);
|
||||||
|
do_check_eq(gDebuggee.b, undefined);
|
||||||
|
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
// Check the return value.
|
||||||
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
|
||||||
|
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||||
|
// Check that stepping worked.
|
||||||
|
do_check_eq(gDebuggee.a, 1);
|
||||||
|
do_check_eq(gDebuggee.b, undefined);
|
||||||
|
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
// Check the return value.
|
||||||
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
// When leaving a stack frame the line number doesn't change.
|
||||||
|
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 3);
|
||||||
|
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||||
|
// Check that stepping worked.
|
||||||
|
do_check_eq(gDebuggee.a, 1);
|
||||||
|
do_check_eq(gDebuggee.b, 2);
|
||||||
|
|
||||||
|
gThreadClient.resume(function () {
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
gThreadClient.stepIn();
|
||||||
|
});
|
||||||
|
gThreadClient.stepIn();
|
||||||
|
|
||||||
|
});
|
||||||
|
gThreadClient.stepIn();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||||
|
"debugger;\n" + // line0 + 1
|
||||||
|
"var a = 1;\n" + // line0 + 2
|
||||||
|
"var b = 2;\n"); // line0 + 3
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check basic step-out functionality.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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_simple_stepping();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_simple_stepping()
|
||||||
|
{
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
// Check the return value.
|
||||||
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 4);
|
||||||
|
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||||
|
// Check that stepping worked.
|
||||||
|
do_check_eq(gDebuggee.a, 1);
|
||||||
|
do_check_eq(gDebuggee.b, 2);
|
||||||
|
|
||||||
|
gThreadClient.resume(function () {
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
gThreadClient.stepOut();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||||
|
"function f() {\n" + // line0 + 1
|
||||||
|
" debugger;\n" + // line0 + 2
|
||||||
|
" this.a = 1;\n" + // line0 + 3
|
||||||
|
" this.b = 2;\n" + // line0 + 4
|
||||||
|
"}\n" + // line0 + 5
|
||||||
|
"f();\n"); // line0 + 6
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that stepping over a function call does not pause inside the function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
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_simple_stepping();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_simple_stepping()
|
||||||
|
{
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
// Check the return value.
|
||||||
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 5);
|
||||||
|
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||||
|
// Check that stepping worked.
|
||||||
|
do_check_eq(gDebuggee.a, undefined);
|
||||||
|
do_check_eq(gDebuggee.b, undefined);
|
||||||
|
|
||||||
|
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||||
|
// Check the return value.
|
||||||
|
do_check_eq(aPacket.type, "paused");
|
||||||
|
do_check_eq(aPacket.frame.where.line, gDebuggee.line0 + 6);
|
||||||
|
do_check_eq(aPacket.why.type, "resumeLimit");
|
||||||
|
// Check that stepping worked.
|
||||||
|
do_check_eq(gDebuggee.a, 1);
|
||||||
|
do_check_eq(gDebuggee.b, undefined);
|
||||||
|
|
||||||
|
gThreadClient.resume(function () {
|
||||||
|
finishClient(gClient);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
gThreadClient.stepOver();
|
||||||
|
|
||||||
|
});
|
||||||
|
gThreadClient.stepOver();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
gDebuggee.eval("var line0 = Error().lineNumber;\n" +
|
||||||
|
"function f() {\n" + // line0 + 1
|
||||||
|
" this.a = 1;\n" + // line0 + 2
|
||||||
|
"}\n" + // line0 + 3
|
||||||
|
"debugger;\n" + // line0 + 4
|
||||||
|
"f();\n" + // line0 + 5
|
||||||
|
"let b = 2;\n"); // line0 + 6
|
||||||
|
}
|
|
@ -49,3 +49,7 @@ tail =
|
||||||
[test_objectgrips-03.js]
|
[test_objectgrips-03.js]
|
||||||
[test_objectgrips-04.js]
|
[test_objectgrips-04.js]
|
||||||
[test_interrupt.js]
|
[test_interrupt.js]
|
||||||
|
[test_stepping-01.js]
|
||||||
|
[test_stepping-02.js]
|
||||||
|
[test_stepping-03.js]
|
||||||
|
[test_stepping-04.js]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче