зеркало из https://github.com/mozilla/gecko-dev.git
merge m-c to fx-team
This commit is contained in:
Коммит
fc3315fbfe
|
@ -1103,6 +1103,8 @@ let RemoteDebugger = {
|
||||||
DebuggerServer.registerModule("devtools/server/actors/inspector");
|
DebuggerServer.registerModule("devtools/server/actors/inspector");
|
||||||
DebuggerServer.registerModule("devtools/server/actors/styleeditor");
|
DebuggerServer.registerModule("devtools/server/actors/styleeditor");
|
||||||
DebuggerServer.registerModule("devtools/server/actors/stylesheets");
|
DebuggerServer.registerModule("devtools/server/actors/stylesheets");
|
||||||
|
DebuggerServer.registerModule("devtools/server/actors/tracer");
|
||||||
|
DebuggerServer.registerModule("devtools/server/actors/webgl");
|
||||||
}
|
}
|
||||||
DebuggerServer.addActors('chrome://browser/content/dbg-browser-actors.js');
|
DebuggerServer.addActors('chrome://browser/content/dbg-browser-actors.js');
|
||||||
DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/webapps.js");
|
DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/webapps.js");
|
||||||
|
|
|
@ -235,7 +235,7 @@ let DebuggerController = {
|
||||||
if (target.chrome) {
|
if (target.chrome) {
|
||||||
this._startChromeDebugging(chromeDebugger, startedDebugging.resolve);
|
this._startChromeDebugging(chromeDebugger, startedDebugging.resolve);
|
||||||
} else {
|
} else {
|
||||||
this._startDebuggingTab(threadActor, startedDebugging.resolve);
|
this._startDebuggingTab(startedDebugging.resolve);
|
||||||
const startedTracing = promise.defer();
|
const startedTracing = promise.defer();
|
||||||
this._startTracingTab(traceActor, startedTracing.resolve);
|
this._startTracingTab(traceActor, startedTracing.resolve);
|
||||||
|
|
||||||
|
@ -339,13 +339,13 @@ let DebuggerController = {
|
||||||
/**
|
/**
|
||||||
* Sets up a debugging session.
|
* Sets up a debugging session.
|
||||||
*
|
*
|
||||||
* @param string aThreadActor
|
|
||||||
* The remote protocol grip of the tab.
|
|
||||||
* @param function aCallback
|
* @param function aCallback
|
||||||
* A function to invoke once the client attaches to the active thread.
|
* A function to invoke once the client attaches to the active thread.
|
||||||
*/
|
*/
|
||||||
_startDebuggingTab: function(aThreadActor, aCallback) {
|
_startDebuggingTab: function(aCallback) {
|
||||||
this.client.attachThread(aThreadActor, (aResponse, aThreadClient) => {
|
this._target.activeTab.attachThread({
|
||||||
|
useSourceMaps: Prefs.sourceMapsEnabled
|
||||||
|
}, (aResponse, aThreadClient) => {
|
||||||
if (!aThreadClient) {
|
if (!aThreadClient) {
|
||||||
Cu.reportError("Couldn't attach to thread: " + aResponse.error);
|
Cu.reportError("Couldn't attach to thread: " + aResponse.error);
|
||||||
return;
|
return;
|
||||||
|
@ -355,12 +355,14 @@ let DebuggerController = {
|
||||||
this.ThreadState.connect();
|
this.ThreadState.connect();
|
||||||
this.StackFrames.connect();
|
this.StackFrames.connect();
|
||||||
this.SourceScripts.connect();
|
this.SourceScripts.connect();
|
||||||
aThreadClient.resume(this._ensureResumptionOrder);
|
if (aThreadClient.paused) {
|
||||||
|
aThreadClient.resume(this._ensureResumptionOrder);
|
||||||
|
}
|
||||||
|
|
||||||
if (aCallback) {
|
if (aCallback) {
|
||||||
aCallback();
|
aCallback();
|
||||||
}
|
}
|
||||||
}, { useSourceMaps: Prefs.sourceMapsEnabled });
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -382,7 +384,9 @@ let DebuggerController = {
|
||||||
this.ThreadState.connect();
|
this.ThreadState.connect();
|
||||||
this.StackFrames.connect();
|
this.StackFrames.connect();
|
||||||
this.SourceScripts.connect();
|
this.SourceScripts.connect();
|
||||||
aThreadClient.resume(this._ensureResumptionOrder);
|
if (aThreadClient.paused) {
|
||||||
|
aThreadClient.resume(this._ensureResumptionOrder);
|
||||||
|
}
|
||||||
|
|
||||||
if (aCallback) {
|
if (aCallback) {
|
||||||
aCallback();
|
aCallback();
|
||||||
|
@ -419,7 +423,7 @@ let DebuggerController = {
|
||||||
* away old sources and get them again.
|
* away old sources and get them again.
|
||||||
*/
|
*/
|
||||||
reconfigureThread: function(aUseSourceMaps) {
|
reconfigureThread: function(aUseSourceMaps) {
|
||||||
this.client.reconfigureThread({ useSourceMaps: aUseSourceMaps }, aResponse => {
|
this.activeThread.reconfigure({ useSourceMaps: aUseSourceMaps }, aResponse => {
|
||||||
if (aResponse.error) {
|
if (aResponse.error) {
|
||||||
let msg = "Couldn't reconfigure thread: " + aResponse.message;
|
let msg = "Couldn't reconfigure thread: " + aResponse.message;
|
||||||
Cu.reportError(msg);
|
Cu.reportError(msg);
|
||||||
|
@ -432,8 +436,10 @@ let DebuggerController = {
|
||||||
this.SourceScripts.handleTabNavigation();
|
this.SourceScripts.handleTabNavigation();
|
||||||
|
|
||||||
// Update the stack frame list.
|
// Update the stack frame list.
|
||||||
this.activeThread._clearFrames();
|
if (this.activeThread.paused) {
|
||||||
this.activeThread.fillFrames(CALL_STACK_PAGE_SIZE);
|
this.activeThread._clearFrames();
|
||||||
|
this.activeThread.fillFrames(CALL_STACK_PAGE_SIZE);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ function test() {
|
||||||
is(gEvents.itemCount, 0, "There should be no events before reloading.");
|
is(gEvents.itemCount, 0, "There should be no events before reloading.");
|
||||||
|
|
||||||
let reloaded = waitForSourcesAfterReload();
|
let reloaded = waitForSourcesAfterReload();
|
||||||
gDebugger.gClient.activeTab.reload();
|
gDebugger.DebuggerController._target.activeTab.reload();
|
||||||
|
|
||||||
is(gEvents.itemCount, 0, "There should be no events while reloading.");
|
is(gEvents.itemCount, 0, "There should be no events while reloading.");
|
||||||
yield reloaded;
|
yield reloaded;
|
||||||
|
|
|
@ -47,7 +47,7 @@ function test() {
|
||||||
|
|
||||||
let reloading = once(gDebugger.gTarget, "will-navigate");
|
let reloading = once(gDebugger.gTarget, "will-navigate");
|
||||||
let reloaded = waitForSourcesAfterReload();
|
let reloaded = waitForSourcesAfterReload();
|
||||||
gDebugger.gClient.activeTab.reload();
|
gDebugger.DebuggerController._target.activeTab.reload();
|
||||||
|
|
||||||
yield reloading;
|
yield reloading;
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ function test() {
|
||||||
|
|
||||||
let reloading = once(gDebugger.gTarget, "will-navigate");
|
let reloading = once(gDebugger.gTarget, "will-navigate");
|
||||||
let reloaded = waitForSourcesAfterReload();
|
let reloaded = waitForSourcesAfterReload();
|
||||||
gDebugger.gClient.activeTab.reload();
|
gDebugger.DebuggerController._target.activeTab.reload();
|
||||||
|
|
||||||
yield reloading;
|
yield reloading;
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ function testBreakOnAll() {
|
||||||
|
|
||||||
// Test calling pauseOnDOMEvents from a paused state.
|
// Test calling pauseOnDOMEvents from a paused state.
|
||||||
gThreadClient.pauseOnDOMEvents("*", (aPacket) => {
|
gThreadClient.pauseOnDOMEvents("*", (aPacket) => {
|
||||||
is(aPacket, undefined,
|
is(aPacket.error, undefined,
|
||||||
"The pause-on-any-event request completed successfully.");
|
"The pause-on-any-event request completed successfully.");
|
||||||
|
|
||||||
gClient.addOneTimeListener("paused", (aEvent, aPacket) => {
|
gClient.addOneTimeListener("paused", (aEvent, aPacket) => {
|
||||||
|
|
|
@ -8,12 +8,11 @@
|
||||||
const TAB_URL = EXAMPLE_URL + "doc_binary_search.html";
|
const TAB_URL = EXAMPLE_URL + "doc_binary_search.html";
|
||||||
const JS_URL = EXAMPLE_URL + "code_binary_search.js";
|
const JS_URL = EXAMPLE_URL + "code_binary_search.js";
|
||||||
|
|
||||||
let gTab, gDebuggee, gPanel, gDebugger;
|
let gDebuggee, gPanel, gDebugger, gEditor;
|
||||||
let gEditor, gSources, gFrames, gPrefs, gOptions;
|
let gSources, gFrames, gPrefs, gOptions;
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||||
gTab = aTab;
|
|
||||||
gDebuggee = aDebuggee;
|
gDebuggee = aDebuggee;
|
||||||
gPanel = aPanel;
|
gPanel = aPanel;
|
||||||
gDebugger = gPanel.panelWin;
|
gDebugger = gPanel.panelWin;
|
||||||
|
@ -26,7 +25,6 @@ function test() {
|
||||||
waitForSourceShown(gPanel, ".coffee")
|
waitForSourceShown(gPanel, ".coffee")
|
||||||
.then(testToggleGeneratedSource)
|
.then(testToggleGeneratedSource)
|
||||||
.then(testSetBreakpoint)
|
.then(testSetBreakpoint)
|
||||||
.then(testHitBreakpoint)
|
|
||||||
.then(testToggleOnPause)
|
.then(testToggleOnPause)
|
||||||
.then(testResume)
|
.then(testResume)
|
||||||
.then(() => closeDebuggerAndFinish(gPanel))
|
.then(() => closeDebuggerAndFinish(gPanel))
|
||||||
|
@ -68,34 +66,23 @@ function testSetBreakpoint() {
|
||||||
ok(!aResponse.error,
|
ok(!aResponse.error,
|
||||||
"Should be able to set a breakpoint in a js file.");
|
"Should be able to set a breakpoint in a js file.");
|
||||||
|
|
||||||
deferred.resolve();
|
gDebugger.gClient.addOneTimeListener("resumed", () => {
|
||||||
});
|
waitForCaretAndScopes(gPanel, 7).then(() => {
|
||||||
|
// Make sure that we have JavaScript stack frames.
|
||||||
|
is(gFrames.itemCount, 1,
|
||||||
|
"Should have only one frame.");
|
||||||
|
is(gFrames.getItemAtIndex(0).attachment.url.indexOf(".coffee"), -1,
|
||||||
|
"First frame should not be a coffee source frame.");
|
||||||
|
isnot(gFrames.getItemAtIndex(0).attachment.url.indexOf(".js"), -1,
|
||||||
|
"First frame should be a JS frame.");
|
||||||
|
|
||||||
return deferred.promise;
|
deferred.resolve();
|
||||||
}
|
});
|
||||||
|
|
||||||
function testHitBreakpoint() {
|
// This will cause the breakpoint to be hit, and put us back in the
|
||||||
let deferred = promise.defer();
|
// paused state.
|
||||||
|
gDebuggee.binary_search([0, 2, 3, 5, 7, 10], 5);
|
||||||
gDebugger.gThreadClient.resume(aResponse => {
|
|
||||||
ok(!aResponse.error, "Shouldn't get an error resuming.");
|
|
||||||
is(aResponse.type, "resumed", "Type should be 'resumed'.");
|
|
||||||
|
|
||||||
waitForCaretAndScopes(gPanel, 7).then(() => {
|
|
||||||
// Make sure that we have JavaScript stack frames.
|
|
||||||
is(gFrames.itemCount, 1,
|
|
||||||
"Should have only one frame.");
|
|
||||||
is(gFrames.getItemAtIndex(0).attachment.url.indexOf(".coffee"), -1,
|
|
||||||
"First frame should not be a coffee source frame.");
|
|
||||||
isnot(gFrames.getItemAtIndex(0).attachment.url.indexOf(".js"), -1,
|
|
||||||
"First frame should be a JS frame.");
|
|
||||||
|
|
||||||
deferred.resolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// This will cause the breakpoint to be hit, and put us back in the
|
|
||||||
// paused state.
|
|
||||||
gDebuggee.binary_search([0, 2, 3, 5, 7, 10], 5);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
|
@ -148,7 +135,6 @@ function testResume() {
|
||||||
}
|
}
|
||||||
|
|
||||||
registerCleanupFunction(function() {
|
registerCleanupFunction(function() {
|
||||||
gTab = null;
|
|
||||||
gDebuggee = null;
|
gDebuggee = null;
|
||||||
gPanel = null;
|
gPanel = null;
|
||||||
gDebugger = null;
|
gDebugger = null;
|
||||||
|
|
|
@ -8,12 +8,11 @@
|
||||||
const TAB_URL = EXAMPLE_URL + "doc_minified.html";
|
const TAB_URL = EXAMPLE_URL + "doc_minified.html";
|
||||||
const JS_URL = EXAMPLE_URL + "code_math.js";
|
const JS_URL = EXAMPLE_URL + "code_math.js";
|
||||||
|
|
||||||
let gTab, gDebuggee, gPanel, gDebugger;
|
let gDebuggee, gPanel, gDebugger;
|
||||||
let gEditor, gSources, gFrames;
|
let gEditor, gSources, gFrames;
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||||
gTab = aTab;
|
|
||||||
gDebuggee = aDebuggee;
|
gDebuggee = aDebuggee;
|
||||||
gPanel = aPanel;
|
gPanel = aPanel;
|
||||||
gDebugger = gPanel.panelWin;
|
gDebugger = gPanel.panelWin;
|
||||||
|
@ -24,7 +23,6 @@ function test() {
|
||||||
waitForSourceShown(gPanel, JS_URL)
|
waitForSourceShown(gPanel, JS_URL)
|
||||||
.then(checkInitialSource)
|
.then(checkInitialSource)
|
||||||
.then(testSetBreakpoint)
|
.then(testSetBreakpoint)
|
||||||
.then(testHitBreakpoint)
|
|
||||||
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
|
.then(() => resumeDebuggerThenCloseAndFinish(gPanel))
|
||||||
.then(null, aError => {
|
.then(null, aError => {
|
||||||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||||
|
@ -45,50 +43,35 @@ function checkInitialSource() {
|
||||||
function testSetBreakpoint() {
|
function testSetBreakpoint() {
|
||||||
let deferred = promise.defer();
|
let deferred = promise.defer();
|
||||||
|
|
||||||
gDebugger.gThreadClient.interrupt(aResponse => {
|
gDebugger.gThreadClient.setBreakpoint({ url: JS_URL, line: 30, column: 21 }, aResponse => {
|
||||||
gDebugger.gThreadClient.setBreakpoint({ url: JS_URL, line: 30, column: 21 }, aResponse => {
|
ok(!aResponse.error,
|
||||||
ok(!aResponse.error,
|
"Should be able to set a breakpoint in a js file.");
|
||||||
"Should be able to set a breakpoint in a js file.");
|
ok(!aResponse.actualLocation,
|
||||||
ok(!aResponse.actualLocation,
|
"Should be able to set a breakpoint on line 30 and column 10.");
|
||||||
"Should be able to set a breakpoint on line 30 and column 10.");
|
|
||||||
|
|
||||||
deferred.resolve();
|
gDebugger.gClient.addOneTimeListener("resumed", () => {
|
||||||
|
waitForCaretAndScopes(gPanel, 30).then(() => {
|
||||||
|
// Make sure that we have the right stack frames.
|
||||||
|
is(gFrames.itemCount, 9,
|
||||||
|
"Should have nine frames.");
|
||||||
|
is(gFrames.getItemAtIndex(0).attachment.url.indexOf(".min.js"), -1,
|
||||||
|
"First frame should not be a minified JS frame.");
|
||||||
|
isnot(gFrames.getItemAtIndex(0).attachment.url.indexOf(".js"), -1,
|
||||||
|
"First frame should be a JS frame.");
|
||||||
|
|
||||||
|
deferred.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
// This will cause the breakpoint to be hit, and put us back in the
|
||||||
|
// paused state.
|
||||||
|
gDebuggee.arithmetic();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testHitBreakpoint() {
|
|
||||||
let deferred = promise.defer();
|
|
||||||
|
|
||||||
gDebugger.gThreadClient.resume(aResponse => {
|
|
||||||
ok(!aResponse.error, "Shouldn't get an error resuming.");
|
|
||||||
is(aResponse.type, "resumed", "Type should be 'resumed'.");
|
|
||||||
|
|
||||||
waitForCaretAndScopes(gPanel, 30).then(() => {
|
|
||||||
// Make sure that we have the right stack frames.
|
|
||||||
is(gFrames.itemCount, 9,
|
|
||||||
"Should have nine frames.");
|
|
||||||
is(gFrames.getItemAtIndex(0).attachment.url.indexOf(".min.js"), -1,
|
|
||||||
"First frame should not be a minified JS frame.");
|
|
||||||
isnot(gFrames.getItemAtIndex(0).attachment.url.indexOf(".js"), -1,
|
|
||||||
"First frame should be a JS frame.");
|
|
||||||
|
|
||||||
deferred.resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
// This will cause the breakpoint to be hit, and put us back in the
|
|
||||||
// paused state.
|
|
||||||
gDebuggee.arithmetic();
|
|
||||||
});
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
registerCleanupFunction(function() {
|
registerCleanupFunction(function() {
|
||||||
gTab = null;
|
|
||||||
gDebuggee = null;
|
gDebuggee = null;
|
||||||
gPanel = null;
|
gPanel = null;
|
||||||
gDebugger = null;
|
gDebugger = null;
|
||||||
|
|
|
@ -101,7 +101,7 @@ function testSetBreakpoint() {
|
||||||
|
|
||||||
function reloadPage() {
|
function reloadPage() {
|
||||||
let loaded = waitForSourceAndCaret(gPanel, ".js", 3);
|
let loaded = waitForSourceAndCaret(gPanel, ".js", 3);
|
||||||
gDebugger.gClient.activeTab.reload();
|
gDebugger.DebuggerController._target.activeTab.reload();
|
||||||
return loaded.then(() => ok(true, "Page was reloaded and execution resumed."));
|
return loaded.then(() => ok(true, "Page was reloaded and execution resumed."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -410,7 +410,7 @@ function ensureThreadClientState(aPanel, aState) {
|
||||||
|
|
||||||
function navigateActiveTabTo(aPanel, aUrl, aWaitForEventName, aEventRepeat) {
|
function navigateActiveTabTo(aPanel, aUrl, aWaitForEventName, aEventRepeat) {
|
||||||
let finished = waitForDebuggerEvents(aPanel, aWaitForEventName, aEventRepeat);
|
let finished = waitForDebuggerEvents(aPanel, aWaitForEventName, aEventRepeat);
|
||||||
let activeTab = aPanel.panelWin.gClient.activeTab;
|
let activeTab = aPanel.panelWin.DebuggerController._target.activeTab;
|
||||||
aUrl ? activeTab.navigateTo(aUrl) : activeTab.reload();
|
aUrl ? activeTab.navigateTo(aUrl) : activeTab.reload();
|
||||||
return finished;
|
return finished;
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,6 +284,7 @@ TabTarget.prototype = {
|
||||||
this._remote.reject("Unable to attach to the tab");
|
this._remote.reject("Unable to attach to the tab");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.activeTab = aTabClient;
|
||||||
this.threadActor = aResponse.threadActor;
|
this.threadActor = aResponse.threadActor;
|
||||||
this._remote.resolve(null);
|
this._remote.resolve(null);
|
||||||
});
|
});
|
||||||
|
@ -444,11 +445,14 @@ TabTarget.prototype = {
|
||||||
this._teardownListeners();
|
this._teardownListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cleanupAndResolve = () => {
|
||||||
|
this._cleanup();
|
||||||
|
this._destroyer.resolve(null);
|
||||||
|
};
|
||||||
// If this target was not remoted, the promise will be resolved before the
|
// If this target was not remoted, the promise will be resolved before the
|
||||||
// function returns.
|
// function returns.
|
||||||
if (this._tab && !this._client) {
|
if (this._tab && !this._client) {
|
||||||
this._cleanup();
|
cleanupAndResolve();
|
||||||
this._destroyer.resolve(null);
|
|
||||||
} else if (this._client) {
|
} else if (this._client) {
|
||||||
// If, on the other hand, this target was remoted, the promise will be
|
// If, on the other hand, this target was remoted, the promise will be
|
||||||
// resolved after the remote connection is closed.
|
// resolved after the remote connection is closed.
|
||||||
|
@ -457,15 +461,15 @@ TabTarget.prototype = {
|
||||||
if (this.isLocalTab) {
|
if (this.isLocalTab) {
|
||||||
// We started with a local tab and created the client ourselves, so we
|
// We started with a local tab and created the client ourselves, so we
|
||||||
// should close it.
|
// should close it.
|
||||||
this._client.close(() => {
|
this._client.close(cleanupAndResolve);
|
||||||
this._cleanup();
|
|
||||||
this._destroyer.resolve(null);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// The client was handed to us, so we are not responsible for closing
|
// The client was handed to us, so we are not responsible for closing
|
||||||
// it.
|
// it. We just need to detach from the tab, if already attached.
|
||||||
this._cleanup();
|
if (this.activeTab) {
|
||||||
this._destroyer.resolve(null);
|
this.activeTab.detach(cleanupAndResolve);
|
||||||
|
} else {
|
||||||
|
cleanupAndResolve();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,6 +485,7 @@ TabTarget.prototype = {
|
||||||
} else {
|
} else {
|
||||||
promiseTargets.delete(this._form);
|
promiseTargets.delete(this._form);
|
||||||
}
|
}
|
||||||
|
this.activeTab = null;
|
||||||
this._client = null;
|
this._client = null;
|
||||||
this._tab = null;
|
this._tab = null;
|
||||||
this._form = null;
|
this._form = null;
|
||||||
|
|
|
@ -212,7 +212,7 @@ OptionsPanel.prototype = {
|
||||||
}.bind(menulist));
|
}.bind(menulist));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.target.client.attachTab(this.target.client.activeTab._actor, (response) => {
|
this.target.client.attachTab(this.target.activeTab._actor, (response) => {
|
||||||
this._origJavascriptEnabled = response.javascriptEnabled;
|
this._origJavascriptEnabled = response.javascriptEnabled;
|
||||||
this._origCacheEnabled = response.cacheEnabled;
|
this._origCacheEnabled = response.cacheEnabled;
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ OptionsPanel.prototype = {
|
||||||
"javascriptEnabled": !checked
|
"javascriptEnabled": !checked
|
||||||
};
|
};
|
||||||
|
|
||||||
this.target.client.reconfigureTab(options);
|
this.target.activeTab.reconfigure(options);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -264,7 +264,7 @@ OptionsPanel.prototype = {
|
||||||
"cacheEnabled": !checked
|
"cacheEnabled": !checked
|
||||||
};
|
};
|
||||||
|
|
||||||
this.target.client.reconfigureTab(options);
|
this.target.activeTab.reconfigure(options);
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
|
@ -291,7 +291,7 @@ OptionsPanel.prototype = {
|
||||||
"cacheEnabled": this._origCacheEnabled,
|
"cacheEnabled": this._origCacheEnabled,
|
||||||
"javascriptEnabled": this._origJavascriptEnabled
|
"javascriptEnabled": this._origJavascriptEnabled
|
||||||
};
|
};
|
||||||
this.target.client.reconfigureTab(options, () => {
|
this.target.activeTab.reconfigure(options, () => {
|
||||||
this.toolbox = null;
|
this.toolbox = null;
|
||||||
deferred.resolve();
|
deferred.resolve();
|
||||||
}, true);
|
}, true);
|
||||||
|
|
|
@ -1217,7 +1217,7 @@ Toolbox.prototype = {
|
||||||
outstanding.push(panel.destroy());
|
outstanding.push(panel.destroy());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// We don't want to stop here if any panel fail to close.
|
// We don't want to stop here if any panel fail to close.
|
||||||
console.error(e);
|
console.error("Panel " + id + ":", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,12 +229,12 @@ function navigateInHistory(aTarget, aDirection, aWaitForTargetEvent = "navigate"
|
||||||
}
|
}
|
||||||
|
|
||||||
function navigate(aTarget, aUrl, aWaitForTargetEvent = "navigate") {
|
function navigate(aTarget, aUrl, aWaitForTargetEvent = "navigate") {
|
||||||
executeSoon(() => aTarget.client.activeTab.navigateTo(aUrl));
|
executeSoon(() => aTarget.activeTab.navigateTo(aUrl));
|
||||||
return once(aTarget, aWaitForTargetEvent);
|
return once(aTarget, aWaitForTargetEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reload(aTarget, aWaitForTargetEvent = "navigate") {
|
function reload(aTarget, aWaitForTargetEvent = "navigate") {
|
||||||
executeSoon(() => aTarget.client.activeTab.reload());
|
executeSoon(() => aTarget.activeTab.reload());
|
||||||
return once(aTarget, aWaitForTargetEvent);
|
return once(aTarget, aWaitForTargetEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,9 @@ BreadcrumbsWidget.prototype = {
|
||||||
// Repeated calls to ensureElementIsVisible would interfere with each other
|
// Repeated calls to ensureElementIsVisible would interfere with each other
|
||||||
// and may sometimes result in incorrect scroll positions.
|
// and may sometimes result in incorrect scroll positions.
|
||||||
setNamedTimeout("breadcrumb-select", ENSURE_SELECTION_VISIBLE_DELAY, () => {
|
setNamedTimeout("breadcrumb-select", ENSURE_SELECTION_VISIBLE_DELAY, () => {
|
||||||
this._list.ensureElementIsVisible(aElement);
|
if (this._list.ensureElementIsVisible) {
|
||||||
|
this._list.ensureElementIsVisible(aElement);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -4866,6 +4866,34 @@
|
||||||
"n_buckets": "1000",
|
"n_buckets": "1000",
|
||||||
"description": "The time (in milliseconds) that it took to display a selected source to the user."
|
"description": "The time (in milliseconds) that it took to display a selected source to the user."
|
||||||
},
|
},
|
||||||
|
"DEVTOOLS_DEBUGGER_RDP_LOCAL_RECONFIGURETAB_MS": {
|
||||||
|
"expires_in_version": "never",
|
||||||
|
"kind": "exponential",
|
||||||
|
"high": "10000",
|
||||||
|
"n_buckets": "1000",
|
||||||
|
"description": "The time (in milliseconds) that it took a 'reconfigure tab' request to go round trip."
|
||||||
|
},
|
||||||
|
"DEVTOOLS_DEBUGGER_RDP_REMOTE_RECONFIGURETAB_MS": {
|
||||||
|
"expires_in_version": "never",
|
||||||
|
"kind": "exponential",
|
||||||
|
"high": "10000",
|
||||||
|
"n_buckets": "1000",
|
||||||
|
"description": "The time (in milliseconds) that it took a 'reconfigure tab' request to go round trip."
|
||||||
|
},
|
||||||
|
"DEVTOOLS_DEBUGGER_RDP_LOCAL_RECONFIGURETHREAD_MS": {
|
||||||
|
"expires_in_version": "never",
|
||||||
|
"kind": "exponential",
|
||||||
|
"high": "10000",
|
||||||
|
"n_buckets": "1000",
|
||||||
|
"description": "The time (in milliseconds) that it took a 'reconfigure thread' request to go round trip."
|
||||||
|
},
|
||||||
|
"DEVTOOLS_DEBUGGER_RDP_REMOTE_RECONFIGURETHREAD_MS": {
|
||||||
|
"expires_in_version": "never",
|
||||||
|
"kind": "exponential",
|
||||||
|
"high": "10000",
|
||||||
|
"n_buckets": "1000",
|
||||||
|
"description": "The time (in milliseconds) that it took a 'reconfigure thread' request to go round trip."
|
||||||
|
},
|
||||||
"WEBRTC_ICE_SUCCESS_RATE": {
|
"WEBRTC_ICE_SUCCESS_RATE": {
|
||||||
"expires_in_version": "never",
|
"expires_in_version": "never",
|
||||||
"kind": "boolean",
|
"kind": "boolean",
|
||||||
|
|
|
@ -234,9 +234,12 @@ this.DebuggerClient = function (aTransport)
|
||||||
{
|
{
|
||||||
this._transport = aTransport;
|
this._transport = aTransport;
|
||||||
this._transport.hooks = this;
|
this._transport.hooks = this;
|
||||||
this._threadClients = {};
|
|
||||||
this._tabClients = {};
|
// Map actor ID to client instance for each actor type.
|
||||||
this._consoleClients = {};
|
this._threadClients = new Map;
|
||||||
|
this._tabClients = new Map;
|
||||||
|
this._tracerClients = new Map;
|
||||||
|
this._consoleClients = new Map;
|
||||||
|
|
||||||
this._pendingRequests = [];
|
this._pendingRequests = [];
|
||||||
this._activeRequests = new Map;
|
this._activeRequests = new Map;
|
||||||
|
@ -281,7 +284,7 @@ this.DebuggerClient = function (aTransport)
|
||||||
*/
|
*/
|
||||||
DebuggerClient.requester = function (aPacketSkeleton,
|
DebuggerClient.requester = function (aPacketSkeleton,
|
||||||
{ telemetry, before, after }) {
|
{ telemetry, before, after }) {
|
||||||
return function (...args) {
|
return DevToolsUtils.makeInfallible(function (...args) {
|
||||||
let histogram, startTime;
|
let histogram, startTime;
|
||||||
if (telemetry) {
|
if (telemetry) {
|
||||||
let transportType = this._transport.onOutputStreamReady === undefined
|
let transportType = this._transport.onOutputStreamReady === undefined
|
||||||
|
@ -311,7 +314,7 @@ DebuggerClient.requester = function (aPacketSkeleton,
|
||||||
outgoingPacket = before.call(this, outgoingPacket);
|
outgoingPacket = before.call(this, outgoingPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.request(outgoingPacket, function (aResponse) {
|
this.request(outgoingPacket, DevToolsUtils.makeInfallible(function (aResponse) {
|
||||||
if (after) {
|
if (after) {
|
||||||
let { from } = aResponse;
|
let { from } = aResponse;
|
||||||
aResponse = after.call(this, aResponse);
|
aResponse = after.call(this, aResponse);
|
||||||
|
@ -323,19 +326,15 @@ DebuggerClient.requester = function (aPacketSkeleton,
|
||||||
// The callback is always the last parameter.
|
// The callback is always the last parameter.
|
||||||
let thisCallback = args[maxPosition + 1];
|
let thisCallback = args[maxPosition + 1];
|
||||||
if (thisCallback) {
|
if (thisCallback) {
|
||||||
try {
|
thisCallback(aResponse);
|
||||||
thisCallback(aResponse);
|
|
||||||
} catch (e) {
|
|
||||||
DevToolsUtils.reportException("DebuggerClient.requester callback", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (histogram) {
|
if (histogram) {
|
||||||
histogram.add(+new Date - startTime);
|
histogram.add(+new Date - startTime);
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this), "DebuggerClient.requester request callback"));
|
||||||
|
|
||||||
};
|
}, "DebuggerClient.requester");
|
||||||
};
|
};
|
||||||
|
|
||||||
function args(aPos) {
|
function args(aPos) {
|
||||||
|
@ -390,43 +389,35 @@ DebuggerClient.prototype = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this function, we're using the hoisting behavior of nested
|
const detachClients = (clientMap, next) => {
|
||||||
// function definitions to write the code in the order it will actually
|
const clients = clientMap.values();
|
||||||
// execute. So converting to arrow functions to get rid of 'self' would
|
const total = clientMap.size;
|
||||||
// be unhelpful here.
|
let numFinished = 0;
|
||||||
let self = this;
|
|
||||||
|
|
||||||
let continuation = function () {
|
if (total == 0) {
|
||||||
self._consoleClients = {};
|
next();
|
||||||
detachThread();
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for each (let client in this._consoleClients) {
|
|
||||||
continuation = client.close.bind(client, continuation);
|
|
||||||
}
|
|
||||||
|
|
||||||
continuation();
|
|
||||||
|
|
||||||
function detachThread() {
|
|
||||||
if (self.activeThread) {
|
|
||||||
self.activeThread.detach(detachTab);
|
|
||||||
} else {
|
|
||||||
detachTab();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function detachTab() {
|
for (let client of clients) {
|
||||||
if (self.activeTab) {
|
let method = client instanceof WebConsoleClient ? "close" : "detach";
|
||||||
self.activeTab.detach(closeTransport);
|
client[method](() => {
|
||||||
} else {
|
if (++numFinished === total) {
|
||||||
closeTransport();
|
clientMap.clear();
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function closeTransport() {
|
detachClients(this._consoleClients, () => {
|
||||||
self._transport.close();
|
detachClients(this._threadClients, () => {
|
||||||
self._transport = null;
|
detachClients(this._tabClients, () => {
|
||||||
}
|
this._transport.close();
|
||||||
|
this._transport = null;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -451,6 +442,16 @@ DebuggerClient.prototype = {
|
||||||
* (which will be undefined on error).
|
* (which will be undefined on error).
|
||||||
*/
|
*/
|
||||||
attachTab: function (aTabActor, aOnResponse) {
|
attachTab: function (aTabActor, aOnResponse) {
|
||||||
|
if (this._tabClients.has(aTabActor)) {
|
||||||
|
let cachedTab = this._tabClients.get(aTabActor);
|
||||||
|
let cachedResponse = {
|
||||||
|
cacheEnabled: cachedTab.cacheEnabled,
|
||||||
|
javascriptEnabled: cachedTab.javascriptEnabled
|
||||||
|
};
|
||||||
|
setTimeout(() => aOnResponse(cachedResponse, cachedTab), 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let packet = {
|
let packet = {
|
||||||
to: aTabActor,
|
to: aTabActor,
|
||||||
type: "attach"
|
type: "attach"
|
||||||
|
@ -458,9 +459,8 @@ DebuggerClient.prototype = {
|
||||||
this.request(packet, (aResponse) => {
|
this.request(packet, (aResponse) => {
|
||||||
let tabClient;
|
let tabClient;
|
||||||
if (!aResponse.error) {
|
if (!aResponse.error) {
|
||||||
tabClient = new TabClient(this, aTabActor);
|
tabClient = new TabClient(this, aResponse);
|
||||||
this._tabClients[aTabActor] = tabClient;
|
this._tabClients.set(aTabActor, tabClient);
|
||||||
this.activeTab = tabClient;
|
|
||||||
}
|
}
|
||||||
aOnResponse(aResponse, tabClient);
|
aOnResponse(aResponse, tabClient);
|
||||||
});
|
});
|
||||||
|
@ -479,6 +479,11 @@ DebuggerClient.prototype = {
|
||||||
*/
|
*/
|
||||||
attachConsole:
|
attachConsole:
|
||||||
function (aConsoleActor, aListeners, aOnResponse) {
|
function (aConsoleActor, aListeners, aOnResponse) {
|
||||||
|
if (this._consoleClients.has(aConsoleActor)) {
|
||||||
|
setTimeout(() => aOnResponse({}, this._consoleClients.get(aConsoleActor)), 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let packet = {
|
let packet = {
|
||||||
to: aConsoleActor,
|
to: aConsoleActor,
|
||||||
type: "startListeners",
|
type: "startListeners",
|
||||||
|
@ -489,14 +494,14 @@ DebuggerClient.prototype = {
|
||||||
let consoleClient;
|
let consoleClient;
|
||||||
if (!aResponse.error) {
|
if (!aResponse.error) {
|
||||||
consoleClient = new WebConsoleClient(this, aConsoleActor);
|
consoleClient = new WebConsoleClient(this, aConsoleActor);
|
||||||
this._consoleClients[aConsoleActor] = consoleClient;
|
this._consoleClients.set(aConsoleActor, consoleClient);
|
||||||
}
|
}
|
||||||
aOnResponse(aResponse, consoleClient);
|
aOnResponse(aResponse, consoleClient);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach to a thread actor.
|
* Attach to a global-scoped thread actor for chrome debugging.
|
||||||
*
|
*
|
||||||
* @param string aThreadActor
|
* @param string aThreadActor
|
||||||
* The actor ID for the thread to attach.
|
* The actor ID for the thread to attach.
|
||||||
|
@ -508,7 +513,12 @@ DebuggerClient.prototype = {
|
||||||
* - useSourceMaps: whether to use source maps or not.
|
* - useSourceMaps: whether to use source maps or not.
|
||||||
*/
|
*/
|
||||||
attachThread: function (aThreadActor, aOnResponse, aOptions={}) {
|
attachThread: function (aThreadActor, aOnResponse, aOptions={}) {
|
||||||
let packet = {
|
if (this._threadClients.has(aThreadActor)) {
|
||||||
|
setTimeout(() => aOnResponse({}, this._threadClients.get(aThreadActor)), 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let packet = {
|
||||||
to: aThreadActor,
|
to: aThreadActor,
|
||||||
type: "attach",
|
type: "attach",
|
||||||
options: aOptions
|
options: aOptions
|
||||||
|
@ -516,8 +526,7 @@ DebuggerClient.prototype = {
|
||||||
this.request(packet, (aResponse) => {
|
this.request(packet, (aResponse) => {
|
||||||
if (!aResponse.error) {
|
if (!aResponse.error) {
|
||||||
var threadClient = new ThreadClient(this, aThreadActor);
|
var threadClient = new ThreadClient(this, aThreadActor);
|
||||||
this._threadClients[aThreadActor] = threadClient;
|
this._threadClients.set(aThreadActor, threadClient);
|
||||||
this.activeThread = threadClient;
|
|
||||||
}
|
}
|
||||||
aOnResponse(aResponse, threadClient);
|
aOnResponse(aResponse, threadClient);
|
||||||
});
|
});
|
||||||
|
@ -533,52 +542,24 @@ DebuggerClient.prototype = {
|
||||||
* (which will be undefined on error).
|
* (which will be undefined on error).
|
||||||
*/
|
*/
|
||||||
attachTracer: function (aTraceActor, aOnResponse) {
|
attachTracer: function (aTraceActor, aOnResponse) {
|
||||||
|
if (this._tracerClients.has(aTraceActor)) {
|
||||||
|
setTimeout(() => aOnResponse({}, this._tracerClients.get(aTraceActor)), 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let packet = {
|
let packet = {
|
||||||
to: aTraceActor,
|
to: aTraceActor,
|
||||||
type: "attach"
|
type: "attach"
|
||||||
};
|
};
|
||||||
this.request(packet, (aResponse) => {
|
this.request(packet, (aResponse) => {
|
||||||
if (!aResponse.error) {
|
if (!aResponse.error) {
|
||||||
let traceClient = new TraceClient(this, aTraceActor);
|
var traceClient = new TraceClient(this, aTraceActor);
|
||||||
aOnResponse(aResponse, traceClient);
|
this._tracerClients.set(aTraceActor, traceClient);
|
||||||
}
|
}
|
||||||
|
aOnResponse(aResponse, traceClient);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Reconfigure a thread actor.
|
|
||||||
*
|
|
||||||
* @param object aOptions
|
|
||||||
* A dictionary object of the new options to use in the thread actor.
|
|
||||||
* @param function aOnResponse
|
|
||||||
* Called with the response packet.
|
|
||||||
*/
|
|
||||||
reconfigureThread: function (aOptions, aOnResponse) {
|
|
||||||
let packet = {
|
|
||||||
to: this.activeThread._actor,
|
|
||||||
type: "reconfigure",
|
|
||||||
options: aOptions
|
|
||||||
};
|
|
||||||
this.request(packet, aOnResponse);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reconfigure a tab actor.
|
|
||||||
*
|
|
||||||
* @param object aOptions
|
|
||||||
* A dictionary object of the new options to use in the tab actor.
|
|
||||||
* @param function aOnResponse
|
|
||||||
* Called with the response packet.
|
|
||||||
*/
|
|
||||||
reconfigureTab: function (aOptions, aOnResponse) {
|
|
||||||
let packet = {
|
|
||||||
to: this.activeTab._actor,
|
|
||||||
type: "reconfigure",
|
|
||||||
options: aOptions
|
|
||||||
};
|
|
||||||
this.request(packet, aOnResponse);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release an object actor.
|
* Release an object actor.
|
||||||
*
|
*
|
||||||
|
@ -697,17 +678,18 @@ DebuggerClient.prototype = {
|
||||||
|
|
||||||
// Packets that indicate thread state changes get special treatment.
|
// Packets that indicate thread state changes get special treatment.
|
||||||
if (aPacket.type in ThreadStateTypes &&
|
if (aPacket.type in ThreadStateTypes &&
|
||||||
aPacket.from in this._threadClients) {
|
this._threadClients.has(aPacket.from)) {
|
||||||
this._threadClients[aPacket.from]._onThreadState(aPacket);
|
this._threadClients.get(aPacket.from)._onThreadState(aPacket);
|
||||||
}
|
}
|
||||||
// On navigation the server resumes, so the client must resume as well.
|
// On navigation the server resumes, so the client must resume as well.
|
||||||
// We achieve that by generating a fake resumption packet that triggers
|
// We achieve that by generating a fake resumption packet that triggers
|
||||||
// the client's thread state change listeners.
|
// the client's thread state change listeners.
|
||||||
if (this.activeThread &&
|
if (aPacket.type == UnsolicitedNotifications.tabNavigated &&
|
||||||
aPacket.type == UnsolicitedNotifications.tabNavigated &&
|
this._tabClients.has(aPacket.from) &&
|
||||||
aPacket.from in this._tabClients) {
|
this._tabClients.get(aPacket.from).thread) {
|
||||||
let resumption = { from: this.activeThread._actor, type: "resumed" };
|
let thread = this._tabClients.get(aPacket.from).thread;
|
||||||
this.activeThread._onThreadState(resumption);
|
let resumption = { from: thread._actor, type: "resumed" };
|
||||||
|
thread._onThreadState(resumption);
|
||||||
}
|
}
|
||||||
// Only try to notify listeners on events, not responses to requests
|
// Only try to notify listeners on events, not responses to requests
|
||||||
// that lack a packet type.
|
// that lack a packet type.
|
||||||
|
@ -959,18 +941,52 @@ SSProto.translatePacket = function (aPacket, aReplacePacket, aExtraPacket,
|
||||||
*
|
*
|
||||||
* @param aClient DebuggerClient
|
* @param aClient DebuggerClient
|
||||||
* The debugger client parent.
|
* The debugger client parent.
|
||||||
* @param aActor string
|
* @param aForm object
|
||||||
* The actor ID for this tab.
|
* The protocol form for this tab.
|
||||||
*/
|
*/
|
||||||
function TabClient(aClient, aActor) {
|
function TabClient(aClient, aForm) {
|
||||||
this._client = aClient;
|
this.client = aClient;
|
||||||
this._actor = aActor;
|
this._actor = aForm.from;
|
||||||
this.request = this._client.request;
|
this._threadActor = aForm.threadActor;
|
||||||
|
this.javascriptEnabled = aForm.javascriptEnabled;
|
||||||
|
this.cacheEnabled = aForm.cacheEnabled;
|
||||||
|
this.thread = null;
|
||||||
|
this.request = this.client.request;
|
||||||
}
|
}
|
||||||
|
|
||||||
TabClient.prototype = {
|
TabClient.prototype = {
|
||||||
get actor() { return this._actor },
|
get actor() { return this._actor },
|
||||||
get _transport() { return this._client._transport; },
|
get _transport() { return this.client._transport; },
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attach to a thread actor.
|
||||||
|
*
|
||||||
|
* @param object aOptions
|
||||||
|
* Configuration options.
|
||||||
|
* - useSourceMaps: whether to use source maps or not.
|
||||||
|
* @param function aOnResponse
|
||||||
|
* Called with the response packet and a ThreadClient
|
||||||
|
* (which will be undefined on error).
|
||||||
|
*/
|
||||||
|
attachThread: function(aOptions={}, aOnResponse) {
|
||||||
|
if (this.thread) {
|
||||||
|
setTimeout(() => aOnResponse({}, this.thread), 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let packet = {
|
||||||
|
to: this._threadActor,
|
||||||
|
type: "attach",
|
||||||
|
options: aOptions
|
||||||
|
};
|
||||||
|
this.request(packet, (aResponse) => {
|
||||||
|
if (!aResponse.error) {
|
||||||
|
this.thread = new ThreadClient(this, this._threadActor);
|
||||||
|
this.client._threadClients.set(this._threadActor, this.thread);
|
||||||
|
}
|
||||||
|
aOnResponse(aResponse, this.thread);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach the client from the tab actor.
|
* Detach the client from the tab actor.
|
||||||
|
@ -981,11 +997,14 @@ TabClient.prototype = {
|
||||||
detach: DebuggerClient.requester({
|
detach: DebuggerClient.requester({
|
||||||
type: "detach"
|
type: "detach"
|
||||||
}, {
|
}, {
|
||||||
after: function (aResponse) {
|
before: function (aPacket) {
|
||||||
if (this.activeTab === this._client._tabClients[this.actor]) {
|
if (this.thread) {
|
||||||
this.activeTab = undefined;
|
this.thread.detach();
|
||||||
}
|
}
|
||||||
delete this._client._tabClients[this.actor];
|
return aPacket;
|
||||||
|
},
|
||||||
|
after: function (aResponse) {
|
||||||
|
this.client._tabClients.delete(this.actor);
|
||||||
return aResponse;
|
return aResponse;
|
||||||
},
|
},
|
||||||
telemetry: "TABDETACH"
|
telemetry: "TABDETACH"
|
||||||
|
@ -1012,6 +1031,21 @@ TabClient.prototype = {
|
||||||
}, {
|
}, {
|
||||||
telemetry: "NAVIGATETO"
|
telemetry: "NAVIGATETO"
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reconfigure the tab actor.
|
||||||
|
*
|
||||||
|
* @param object aOptions
|
||||||
|
* A dictionary object of the new options to use in the tab actor.
|
||||||
|
* @param function aOnResponse
|
||||||
|
* Called with the response packet.
|
||||||
|
*/
|
||||||
|
reconfigure: DebuggerClient.requester({
|
||||||
|
type: "reconfigure",
|
||||||
|
options: args(0)
|
||||||
|
}, {
|
||||||
|
telemetry: "RECONFIGURETAB"
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
eventSource(TabClient.prototype);
|
eventSource(TabClient.prototype);
|
||||||
|
@ -1077,19 +1111,21 @@ RootClient.prototype = {
|
||||||
* is a front to the thread actor created in the server side, hiding the
|
* is a front to the thread actor created in the server side, hiding the
|
||||||
* protocol details in a traditional JavaScript API.
|
* protocol details in a traditional JavaScript API.
|
||||||
*
|
*
|
||||||
* @param aClient DebuggerClient
|
* @param aClient DebuggerClient|TabClient
|
||||||
* The debugger client parent.
|
* The parent of the thread (tab for tab-scoped debuggers, DebuggerClient
|
||||||
|
* for chrome debuggers).
|
||||||
* @param aActor string
|
* @param aActor string
|
||||||
* The actor ID for this thread.
|
* The actor ID for this thread.
|
||||||
*/
|
*/
|
||||||
function ThreadClient(aClient, aActor) {
|
function ThreadClient(aClient, aActor) {
|
||||||
this._client = aClient;
|
this._parent = aClient;
|
||||||
|
this.client = aClient instanceof DebuggerClient ? aClient : aClient.client;
|
||||||
this._actor = aActor;
|
this._actor = aActor;
|
||||||
this._frameCache = [];
|
this._frameCache = [];
|
||||||
this._scriptCache = {};
|
this._scriptCache = {};
|
||||||
this._pauseGrips = {};
|
this._pauseGrips = {};
|
||||||
this._threadGrips = {};
|
this._threadGrips = {};
|
||||||
this.request = this._client.request;
|
this.request = this.client.request;
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadClient.prototype = {
|
ThreadClient.prototype = {
|
||||||
|
@ -1104,12 +1140,12 @@ ThreadClient.prototype = {
|
||||||
_actor: null,
|
_actor: null,
|
||||||
get actor() { return this._actor; },
|
get actor() { return this._actor; },
|
||||||
|
|
||||||
get compat() { return this._client.compat; },
|
get compat() { return this.client.compat; },
|
||||||
get _transport() { return this._client._transport; },
|
get _transport() { return this.client._transport; },
|
||||||
|
|
||||||
_assertPaused: function (aCommand) {
|
_assertPaused: function (aCommand) {
|
||||||
if (!this.paused) {
|
if (!this.paused) {
|
||||||
throw Error(aCommand + " command sent while not paused.");
|
throw Error(aCommand + " command sent while not paused. Currently " + this._state);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1156,6 +1192,21 @@ ThreadClient.prototype = {
|
||||||
telemetry: "RESUME"
|
telemetry: "RESUME"
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reconfigure the thread actor.
|
||||||
|
*
|
||||||
|
* @param object aOptions
|
||||||
|
* A dictionary object of the new options to use in the thread actor.
|
||||||
|
* @param function aOnResponse
|
||||||
|
* Called with the response packet.
|
||||||
|
*/
|
||||||
|
reconfigure: DebuggerClient.requester({
|
||||||
|
type: "reconfigure",
|
||||||
|
options: args(0)
|
||||||
|
}, {
|
||||||
|
telemetry: "RECONFIGURETHREAD"
|
||||||
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resume a paused thread.
|
* Resume a paused thread.
|
||||||
*/
|
*/
|
||||||
|
@ -1222,7 +1273,7 @@ ThreadClient.prototype = {
|
||||||
// If the debuggee is paused, we have to send the flag via a reconfigure
|
// If the debuggee is paused, we have to send the flag via a reconfigure
|
||||||
// request.
|
// request.
|
||||||
if (this.paused) {
|
if (this.paused) {
|
||||||
this._client.reconfigureThread({
|
this.reconfigure({
|
||||||
pauseOnExceptions: aPauseOnExceptions,
|
pauseOnExceptions: aPauseOnExceptions,
|
||||||
ignoreCaughtExceptions: aIgnoreCaughtExceptions
|
ignoreCaughtExceptions: aIgnoreCaughtExceptions
|
||||||
}, aOnResponse);
|
}, aOnResponse);
|
||||||
|
@ -1256,12 +1307,16 @@ ThreadClient.prototype = {
|
||||||
// If the debuggee is paused, the value of the array will be communicated in
|
// If the debuggee is paused, the value of the array will be communicated in
|
||||||
// the next resumption. Otherwise we have to force a pause in order to send
|
// the next resumption. Otherwise we have to force a pause in order to send
|
||||||
// the array.
|
// the array.
|
||||||
if (this.paused)
|
if (this.paused) {
|
||||||
return void setTimeout(onResponse, 0);
|
setTimeout(() => onResponse({}), 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.interrupt(response => {
|
this.interrupt(response => {
|
||||||
// Can't continue if pausing failed.
|
// Can't continue if pausing failed.
|
||||||
if (response.error)
|
if (response.error) {
|
||||||
return void onResponse(response);
|
onResponse(response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.resume(onResponse);
|
this.resume(onResponse);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1310,10 +1365,8 @@ ThreadClient.prototype = {
|
||||||
type: "detach"
|
type: "detach"
|
||||||
}, {
|
}, {
|
||||||
after: function (aResponse) {
|
after: function (aResponse) {
|
||||||
if (this.activeThread === this._client._threadClients[this.actor]) {
|
this.client._threadClients.delete(this.actor);
|
||||||
this.activeThread = null;
|
this._parent.thread = null;
|
||||||
}
|
|
||||||
delete this._client._threadClients[this.actor];
|
|
||||||
return aResponse;
|
return aResponse;
|
||||||
},
|
},
|
||||||
telemetry: "THREADDETACH"
|
telemetry: "THREADDETACH"
|
||||||
|
@ -1332,11 +1385,11 @@ ThreadClient.prototype = {
|
||||||
let doSetBreakpoint = function (aCallback) {
|
let doSetBreakpoint = function (aCallback) {
|
||||||
let packet = { to: this._actor, type: "setBreakpoint",
|
let packet = { to: this._actor, type: "setBreakpoint",
|
||||||
location: aLocation };
|
location: aLocation };
|
||||||
this._client.request(packet, function (aResponse) {
|
this.client.request(packet, function (aResponse) {
|
||||||
// Ignoring errors, since the user may be setting a breakpoint in a
|
// Ignoring errors, since the user may be setting a breakpoint in a
|
||||||
// dead script that will reappear on a page reload.
|
// dead script that will reappear on a page reload.
|
||||||
if (aOnResponse) {
|
if (aOnResponse) {
|
||||||
let bpClient = new BreakpointClient(this._client, aResponse.actor,
|
let bpClient = new BreakpointClient(this.client, aResponse.actor,
|
||||||
aLocation);
|
aLocation);
|
||||||
if (aCallback) {
|
if (aCallback) {
|
||||||
aCallback(aOnResponse(aResponse, bpClient));
|
aCallback(aOnResponse(aResponse, bpClient));
|
||||||
|
@ -1570,7 +1623,7 @@ ThreadClient.prototype = {
|
||||||
return this._pauseGrips[aGrip.actor];
|
return this._pauseGrips[aGrip.actor];
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = new ObjectClient(this._client, aGrip);
|
let client = new ObjectClient(this.client, aGrip);
|
||||||
this._pauseGrips[aGrip.actor] = client;
|
this._pauseGrips[aGrip.actor] = client;
|
||||||
return client;
|
return client;
|
||||||
},
|
},
|
||||||
|
@ -1590,7 +1643,7 @@ ThreadClient.prototype = {
|
||||||
return this[aGripCacheName][aGrip.actor];
|
return this[aGripCacheName][aGrip.actor];
|
||||||
}
|
}
|
||||||
|
|
||||||
let client = new LongStringClient(this._client, aGrip);
|
let client = new LongStringClient(this.client, aGrip);
|
||||||
this[aGripCacheName][aGrip.actor] = client;
|
this[aGripCacheName][aGrip.actor] = client;
|
||||||
return client;
|
return client;
|
||||||
},
|
},
|
||||||
|
@ -1655,14 +1708,14 @@ ThreadClient.prototype = {
|
||||||
this._clearFrames();
|
this._clearFrames();
|
||||||
this._clearPauseGrips();
|
this._clearPauseGrips();
|
||||||
aPacket.type === ThreadStateTypes.detached && this._clearThreadGrips();
|
aPacket.type === ThreadStateTypes.detached && this._clearThreadGrips();
|
||||||
this._client._eventsEnabled && this.notify(aPacket.type, aPacket);
|
this.client._eventsEnabled && this.notify(aPacket.type, aPacket);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an EnvironmentClient instance for the given environment actor form.
|
* Return an EnvironmentClient instance for the given environment actor form.
|
||||||
*/
|
*/
|
||||||
environment: function (aForm) {
|
environment: function (aForm) {
|
||||||
return new EnvironmentClient(this._client, aForm);
|
return new EnvironmentClient(this.client, aForm);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1673,8 +1726,7 @@ ThreadClient.prototype = {
|
||||||
return this._threadGrips[aForm.actor];
|
return this._threadGrips[aForm.actor];
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._threadGrips[aForm.actor] = new SourceClient(this._client,
|
return this._threadGrips[aForm.actor] = new SourceClient(this, aForm);
|
||||||
aForm);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1724,8 +1776,15 @@ TraceClient.prototype = {
|
||||||
/**
|
/**
|
||||||
* Detach from the trace actor.
|
* Detach from the trace actor.
|
||||||
*/
|
*/
|
||||||
detach: DebuggerClient.requester({ type: "detach" },
|
detach: DebuggerClient.requester({
|
||||||
{ telemetry: "TRACERDETACH" }),
|
type: "detach"
|
||||||
|
}, {
|
||||||
|
after: function (aResponse) {
|
||||||
|
this._client._tracerClients.delete(this.actor);
|
||||||
|
return aResponse;
|
||||||
|
},
|
||||||
|
telemetry: "TRACERDETACH"
|
||||||
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a new trace.
|
* Start a new trace.
|
||||||
|
@ -1964,8 +2023,8 @@ LongStringClient.prototype = {
|
||||||
/**
|
/**
|
||||||
* A SourceClient provides a way to access the source text of a script.
|
* A SourceClient provides a way to access the source text of a script.
|
||||||
*
|
*
|
||||||
* @param aClient DebuggerClient
|
* @param aClient ThreadClient
|
||||||
* The debugger client parent.
|
* The thread client parent.
|
||||||
* @param aForm Object
|
* @param aForm Object
|
||||||
* The form sent across the remote debugging protocol.
|
* The form sent across the remote debugging protocol.
|
||||||
*/
|
*/
|
||||||
|
@ -1973,12 +2032,12 @@ function SourceClient(aClient, aForm) {
|
||||||
this._form = aForm;
|
this._form = aForm;
|
||||||
this._isBlackBoxed = aForm.isBlackBoxed;
|
this._isBlackBoxed = aForm.isBlackBoxed;
|
||||||
this._isPrettyPrinted = aForm.isPrettyPrinted;
|
this._isPrettyPrinted = aForm.isPrettyPrinted;
|
||||||
this._client = aClient;
|
this._activeThread = aClient;
|
||||||
|
this._client = aClient.client;
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceClient.prototype = {
|
SourceClient.prototype = {
|
||||||
get _transport() this._client._transport,
|
get _transport() this._client._transport,
|
||||||
get _activeThread() this._client.activeThread,
|
|
||||||
get isBlackBoxed() this._isBlackBoxed,
|
get isBlackBoxed() this._isBlackBoxed,
|
||||||
get isPrettyPrinted() this._isPrettyPrinted,
|
get isPrettyPrinted() this._isPrettyPrinted,
|
||||||
get actor() this._form.actor,
|
get actor() this._form.actor,
|
||||||
|
@ -2089,8 +2148,7 @@ SourceClient.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let { contentType, source } = aResponse;
|
let { contentType, source } = aResponse;
|
||||||
let longString = this._client.activeThread.threadLongString(
|
let longString = this._activeThread.threadLongString(source);
|
||||||
source);
|
|
||||||
longString.substring(0, longString.length, function (aResponse) {
|
longString.substring(0, longString.length, function (aResponse) {
|
||||||
if (aResponse.error) {
|
if (aResponse.error) {
|
||||||
aCallback(aResponse);
|
aCallback(aResponse);
|
||||||
|
|
|
@ -655,8 +655,6 @@ ThreadActor.prototype = {
|
||||||
this.onResume();
|
this.onResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._state = "exited";
|
|
||||||
|
|
||||||
this.clearDebuggees();
|
this.clearDebuggees();
|
||||||
this.conn.removeActorPool(this._threadLifetimePool);
|
this.conn.removeActorPool(this._threadLifetimePool);
|
||||||
this._threadLifetimePool = null;
|
this._threadLifetimePool = null;
|
||||||
|
@ -682,6 +680,7 @@ ThreadActor.prototype = {
|
||||||
*/
|
*/
|
||||||
exit: function () {
|
exit: function () {
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
|
this._state = "exited";
|
||||||
},
|
},
|
||||||
|
|
||||||
// Request handlers
|
// Request handlers
|
||||||
|
@ -691,7 +690,8 @@ ThreadActor.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.state !== "detached") {
|
if (this.state !== "detached") {
|
||||||
return { error: "wrongState" };
|
return { error: "wrongState",
|
||||||
|
message: "Current state is " + this.state };
|
||||||
}
|
}
|
||||||
|
|
||||||
this._state = "attached";
|
this._state = "attached";
|
||||||
|
@ -741,6 +741,8 @@ ThreadActor.prototype = {
|
||||||
|
|
||||||
onDetach: function (aRequest) {
|
onDetach: function (aRequest) {
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
|
this._state = "detached";
|
||||||
|
|
||||||
dumpn("ThreadActor.prototype.onDetach: returning 'detached' packet");
|
dumpn("ThreadActor.prototype.onDetach: returning 'detached' packet");
|
||||||
return {
|
return {
|
||||||
type: "detached"
|
type: "detached"
|
||||||
|
|
|
@ -677,7 +677,7 @@ WebappsActor.prototype = {
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
deferred.resolve({
|
deferred.resolve({
|
||||||
error: "noIcon",
|
error: "noIcon",
|
||||||
message: "The icon file '" + iconURL + "' doesn't exists"
|
message: "The icon file '" + iconURL + "' doesn't exist"
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -890,26 +890,24 @@ BrowserTabActor.prototype = {
|
||||||
*/
|
*/
|
||||||
onWindowCreated:
|
onWindowCreated:
|
||||||
makeInfallible(function BTA_onWindowCreated(evt) {
|
makeInfallible(function BTA_onWindowCreated(evt) {
|
||||||
if (evt.target === this.browser.contentDocument) {
|
// pageshow events for non-persisted pages have already been handled by a
|
||||||
// pageshow events for non-persisted pages have already been handled by a
|
// prior DOMWindowCreated event.
|
||||||
// prior DOMWindowCreated event.
|
if (!this._attached || (evt.type == "pageshow" && !evt.persisted)) {
|
||||||
if (evt.type == "pageshow" && !evt.persisted) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
if (evt.target === this.browser.contentDocument ) {
|
||||||
if (this._attached) {
|
this.threadActor.clearDebuggees();
|
||||||
this.threadActor.clearDebuggees();
|
if (this.threadActor.dbg) {
|
||||||
if (this.threadActor.dbg) {
|
this.threadActor.dbg.enabled = true;
|
||||||
this.threadActor.dbg.enabled = true;
|
this.threadActor.global = evt.target.defaultView.wrappedJSObject;
|
||||||
this.threadActor.maybePauseOnExceptions();
|
this.threadActor.maybePauseOnExceptions();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._attached) {
|
// Refresh the debuggee list when a new window object appears (top window or
|
||||||
this.threadActor.global = evt.target.defaultView.wrappedJSObject;
|
// iframe).
|
||||||
if (this.threadActor.attached) {
|
if (this.threadActor.attached) {
|
||||||
this.threadActor.findGlobals();
|
this.threadActor.findGlobals();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, "BrowserTabActor.prototype.onWindowCreated"),
|
}, "BrowserTabActor.prototype.onWindowCreated"),
|
||||||
|
|
||||||
|
|
|
@ -376,6 +376,7 @@ var DebuggerServer = {
|
||||||
this.registerModule("devtools/server/actors/webgl");
|
this.registerModule("devtools/server/actors/webgl");
|
||||||
this.registerModule("devtools/server/actors/stylesheets");
|
this.registerModule("devtools/server/actors/stylesheets");
|
||||||
this.registerModule("devtools/server/actors/styleeditor");
|
this.registerModule("devtools/server/actors/styleeditor");
|
||||||
|
this.registerModule("devtools/server/actors/tracer");
|
||||||
}
|
}
|
||||||
if (!("ContentAppActor" in DebuggerServer)) {
|
if (!("ContentAppActor" in DebuggerServer)) {
|
||||||
this.addActors("resource://gre/modules/devtools/server/actors/childtab.js");
|
this.addActors("resource://gre/modules/devtools/server/actors/childtab.js");
|
||||||
|
|
|
@ -154,9 +154,10 @@ function attachTestTab(aClient, aTitle, aCallback) {
|
||||||
// thread.
|
// thread.
|
||||||
function attachTestThread(aClient, aTitle, aCallback) {
|
function attachTestThread(aClient, aTitle, aCallback) {
|
||||||
attachTestTab(aClient, aTitle, function (aResponse, aTabClient) {
|
attachTestTab(aClient, aTitle, function (aResponse, aTabClient) {
|
||||||
aClient.attachThread(aResponse.threadActor, function (aResponse, aThreadClient) {
|
function onAttach(aResponse, aThreadClient) {
|
||||||
aCallback(aResponse, aTabClient, aThreadClient);
|
aCallback(aResponse, aTabClient, aThreadClient);
|
||||||
}, { useSourceMaps: true });
|
}
|
||||||
|
aTabClient.attachThread({ useSourceMaps: true }, onAttach);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,15 +14,15 @@ function run_test()
|
||||||
gClient = new DebuggerClient(transport);
|
gClient = new DebuggerClient(transport);
|
||||||
gClient.connect(function(aType, aTraits) {
|
gClient.connect(function(aType, aTraits) {
|
||||||
attachTestTab(gClient, "test-1", function(aReply, aTabClient) {
|
attachTestTab(gClient, "test-1", function(aReply, aTabClient) {
|
||||||
test_attach(aReply.threadActor);
|
test_attach(aTabClient);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
do_test_pending();
|
do_test_pending();
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_attach(aThreadActorID)
|
function test_attach(aTabClient)
|
||||||
{
|
{
|
||||||
gClient.attachThread(aThreadActorID, function(aResponse, aThreadClient) {
|
aTabClient.attachThread({}, function(aResponse, aThreadClient) {
|
||||||
do_check_eq(aThreadClient.state, "paused");
|
do_check_eq(aThreadClient.state, "paused");
|
||||||
aThreadClient.resume(cleanup);
|
aThreadClient.resume(cleanup);
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,12 +43,12 @@ function setUpCode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBreakpoint() {
|
function setBreakpoint() {
|
||||||
|
gClient.addOneTimeListener("resumed", runCode);
|
||||||
gThreadClient.setBreakpoint({
|
gThreadClient.setBreakpoint({
|
||||||
url: URL,
|
url: URL,
|
||||||
line: 1
|
line: 1
|
||||||
}, ({ error }) => {
|
}, ({ error }) => {
|
||||||
do_check_true(!error);
|
do_check_true(!error);
|
||||||
gThreadClient.resume(runCode);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
Cu.import("resource://gre/modules/devtools/dbg-client.jsm");
|
||||||
|
|
||||||
var gClient;
|
var gClient;
|
||||||
|
var gTabClient;
|
||||||
var gDebuggee;
|
var gDebuggee;
|
||||||
|
|
||||||
function run_test()
|
function run_test()
|
||||||
|
@ -17,6 +18,7 @@ function run_test()
|
||||||
gClient = new DebuggerClient(transport);
|
gClient = new DebuggerClient(transport);
|
||||||
gClient.connect(function(aType, aTraits) {
|
gClient.connect(function(aType, aTraits) {
|
||||||
attachTestTab(gClient, "test-1", function(aReply, aTabClient) {
|
attachTestTab(gClient, "test-1", function(aReply, aTabClient) {
|
||||||
|
gTabClient = aTabClient;
|
||||||
test_threadAttach(aReply.threadActor);
|
test_threadAttach(aReply.threadActor);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -26,7 +28,7 @@ function run_test()
|
||||||
function test_threadAttach(aThreadActorID)
|
function test_threadAttach(aThreadActorID)
|
||||||
{
|
{
|
||||||
do_print("Trying to attach to thread " + aThreadActorID);
|
do_print("Trying to attach to thread " + aThreadActorID);
|
||||||
gClient.attachThread(aThreadActorID, function(aResponse, aThreadClient) {
|
gTabClient.attachThread({}, function(aResponse, aThreadClient) {
|
||||||
do_check_eq(aThreadClient.state, "paused");
|
do_check_eq(aThreadClient.state, "paused");
|
||||||
do_check_eq(aThreadClient.actor, aThreadActorID);
|
do_check_eq(aThreadClient.actor, aThreadActorID);
|
||||||
aThreadClient.resume(function() {
|
aThreadClient.resume(function() {
|
||||||
|
|
|
@ -20,21 +20,21 @@ function run_test()
|
||||||
|
|
||||||
function test_attach(aResponse, aTabClient)
|
function test_attach(aResponse, aTabClient)
|
||||||
{
|
{
|
||||||
gClient.attachThread(aResponse.threadActor, function(aResponse, aThreadClient) {
|
aTabClient.attachThread({}, function(aResponse, aThreadClient) {
|
||||||
do_check_eq(aThreadClient.paused, true);
|
do_check_eq(aThreadClient.paused, true);
|
||||||
aThreadClient.resume(function() {
|
aThreadClient.resume(function() {
|
||||||
test_interrupt();
|
test_interrupt(aThreadClient);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_interrupt()
|
function test_interrupt(aThreadClient)
|
||||||
{
|
{
|
||||||
do_check_eq(gClient.activeThread.paused, false);
|
do_check_eq(aThreadClient.paused, false);
|
||||||
gClient.activeThread.interrupt(function(aResponse) {
|
aThreadClient.interrupt(function(aResponse) {
|
||||||
do_check_eq(gClient.activeThread.paused, true);
|
do_check_eq(aThreadClient.paused, true);
|
||||||
gClient.activeThread.resume(function() {
|
aThreadClient.resume(function() {
|
||||||
do_check_eq(gClient.activeThread.paused, false);
|
do_check_eq(aThreadClient.paused, false);
|
||||||
cleanup();
|
cleanup();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// Test that we can detect nested event loops in tabs with the same URL.
|
// Test that we can detect nested event loops in tabs with the same URL.
|
||||||
|
|
||||||
const { defer } = devtools.require("sdk/core/promise");
|
const { defer } = devtools.require("sdk/core/promise");
|
||||||
var gClient1, gClient2;
|
var gClient1, gClient2, gThreadClient1, gThreadClient2;
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
initTestDebuggerServer();
|
initTestDebuggerServer();
|
||||||
|
@ -15,6 +15,7 @@ function run_test() {
|
||||||
gClient1 = new DebuggerClient(DebuggerServer.connectPipe());
|
gClient1 = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
gClient1.connect(function () {
|
gClient1.connect(function () {
|
||||||
attachTestThread(gClient1, "test-nesting1", function (aResponse, aTabClient, aThreadClient) {
|
attachTestThread(gClient1, "test-nesting1", function (aResponse, aTabClient, aThreadClient) {
|
||||||
|
gThreadClient1 = aThreadClient;
|
||||||
start_second_connection();
|
start_second_connection();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -25,6 +26,7 @@ function start_second_connection() {
|
||||||
gClient2 = new DebuggerClient(DebuggerServer.connectPipe());
|
gClient2 = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
gClient2.connect(function () {
|
gClient2.connect(function () {
|
||||||
attachTestThread(gClient2, "test-nesting1", function (aResponse, aTabClient, aThreadClient) {
|
attachTestThread(gClient2, "test-nesting1", function (aResponse, aTabClient, aThreadClient) {
|
||||||
|
gThreadClient2 = aThreadClient;
|
||||||
test_nesting();
|
test_nesting();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -33,15 +35,15 @@ function start_second_connection() {
|
||||||
function test_nesting() {
|
function test_nesting() {
|
||||||
const { resolve, reject, promise } = defer();
|
const { resolve, reject, promise } = defer();
|
||||||
|
|
||||||
gClient1.activeThread.resume(aResponse => {
|
gThreadClient1.resume(aResponse => {
|
||||||
do_check_eq(aResponse.error, "wrongOrder");
|
do_check_eq(aResponse.error, "wrongOrder");
|
||||||
gClient2.activeThread.resume(aResponse => {
|
gThreadClient2.resume(aResponse => {
|
||||||
do_check_true(!aResponse.error);
|
do_check_true(!aResponse.error);
|
||||||
do_check_eq(aResponse.from, gClient2.activeThread.actor);
|
do_check_eq(aResponse.from, gThreadClient2.actor);
|
||||||
|
|
||||||
gClient1.activeThread.resume(aResponse => {
|
gThreadClient1.resume(aResponse => {
|
||||||
do_check_true(!aResponse.error);
|
do_check_true(!aResponse.error);
|
||||||
do_check_eq(aResponse.from, gClient1.activeThread.actor);
|
do_check_eq(aResponse.from, gThreadClient1.actor);
|
||||||
|
|
||||||
gClient1.close(() => finishClient(gClient2));
|
gClient1.close(() => finishClient(gClient2));
|
||||||
});
|
});
|
||||||
|
|
|
@ -59,7 +59,7 @@ function test_definition_site(func, obj) {
|
||||||
|
|
||||||
function test_bad_definition_site(obj) {
|
function test_bad_definition_site(obj) {
|
||||||
try {
|
try {
|
||||||
obj.getDefinitionSite(() => do_check_true(false));
|
obj._client.request("definitionSite", () => do_check_true(false));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
gThreadClient.resume(() => finishClient(gClient));
|
gThreadClient.resume(() => finishClient(gClient));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that reattaching to a previously detached thread works.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var gClient, gDebuggee, gThreadClient, gTabClient;
|
||||||
|
|
||||||
|
function run_test()
|
||||||
|
{
|
||||||
|
initTestDebuggerServer();
|
||||||
|
gDebuggee = testGlobal("test-reattach");
|
||||||
|
DebuggerServer.addTestGlobal(gDebuggee);
|
||||||
|
|
||||||
|
let transport = DebuggerServer.connectPipe();
|
||||||
|
gClient = new DebuggerClient(transport);
|
||||||
|
gClient.connect(() => {
|
||||||
|
attachTestTab(gClient, "test-reattach", (aReply, aTabClient) => {
|
||||||
|
gTabClient = aTabClient;
|
||||||
|
test_attach();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_attach()
|
||||||
|
{
|
||||||
|
gTabClient.attachThread({}, (aResponse, aThreadClient) => {
|
||||||
|
do_check_eq(aThreadClient.state, "paused");
|
||||||
|
gThreadClient = aThreadClient;
|
||||||
|
aThreadClient.resume(test_detach);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_detach()
|
||||||
|
{
|
||||||
|
gThreadClient.detach(() => {
|
||||||
|
do_check_eq(gThreadClient.state, "detached");
|
||||||
|
do_check_eq(gTabClient.thread, null);
|
||||||
|
test_reattach();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_reattach()
|
||||||
|
{
|
||||||
|
gTabClient.attachThread({}, (aResponse, aThreadClient) => {
|
||||||
|
do_check_neq(gThreadClient, aThreadClient);
|
||||||
|
do_check_eq(aThreadClient.state, "paused");
|
||||||
|
do_check_eq(gTabClient.thread, aThreadClient);
|
||||||
|
aThreadClient.resume(cleanup);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanup()
|
||||||
|
{
|
||||||
|
gClient.close(do_test_finished);
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ reason = bug 821285
|
||||||
[test_dbgglobal.js]
|
[test_dbgglobal.js]
|
||||||
[test_dbgclient_debuggerstatement.js]
|
[test_dbgclient_debuggerstatement.js]
|
||||||
[test_attach.js]
|
[test_attach.js]
|
||||||
|
[test_reattach-thread.js]
|
||||||
[test_blackboxing-01.js]
|
[test_blackboxing-01.js]
|
||||||
[test_blackboxing-02.js]
|
[test_blackboxing-02.js]
|
||||||
[test_blackboxing-03.js]
|
[test_blackboxing-03.js]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче