зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1529163 - Wait for all threads in debugger client, r=jlast.
--HG-- extra : rebase_source : 6ba3159c47a69befbcf98950240ed072b25a8c5d
This commit is contained in:
Родитель
8fbd4d6692
Коммит
53443837f2
|
@ -49,8 +49,6 @@ let breakpoints: { [string]: Object };
|
||||||
let eventBreakpoints: ?EventListenerActiveList;
|
let eventBreakpoints: ?EventListenerActiveList;
|
||||||
let supportsWasm: boolean;
|
let supportsWasm: boolean;
|
||||||
|
|
||||||
let shouldWaitForWorkers = false;
|
|
||||||
|
|
||||||
type Dependencies = {
|
type Dependencies = {
|
||||||
threadFront: ThreadFront,
|
threadFront: ThreadFront,
|
||||||
tabTarget: TabTarget,
|
tabTarget: TabTarget,
|
||||||
|
@ -121,15 +119,23 @@ function listWorkerThreadFronts() {
|
||||||
return (Object.values(workerClients): any).map(({ thread }) => thread);
|
return (Object.values(workerClients): any).map(({ thread }) => thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
function forEachWorkerThread(iteratee) {
|
function forEachThread(iteratee) {
|
||||||
const promises = listWorkerThreadFronts().map(thread => iteratee(thread));
|
// We have to be careful here to atomically initiate the operation on every
|
||||||
|
// thread, with no intervening await. Otherwise, other code could run and
|
||||||
// Do not return promises for the caller to wait on unless a flag is set.
|
// trigger additional thread operations. Requests on server threads will
|
||||||
// Currently, worker threads are not guaranteed to respond to all requests,
|
// resolve in FIFO order, and this could result in client and server state
|
||||||
// if we send a request while they are shutting down. See bug 1529163.
|
// going out of sync.
|
||||||
if (shouldWaitForWorkers) {
|
const mainThreadPromise = iteratee(threadFront);
|
||||||
return Promise.all(promises);
|
const workerPromises = listWorkerThreadFronts().map(t => {
|
||||||
}
|
try {
|
||||||
|
iteratee(t);
|
||||||
|
} catch (e) {
|
||||||
|
// If a worker thread shuts down while sending the message then it will
|
||||||
|
// throw. Ignore these errors.
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Promise.all([mainThreadPromise, ...workerPromises]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function resume(thread: string): Promise<*> {
|
function resume(thread: string): Promise<*> {
|
||||||
|
@ -186,10 +192,6 @@ function locationKey(location: BreakpointLocation) {
|
||||||
return `${(sourceUrl: any)}:${(sourceId: any)}:${line}:${(column: any)}`;
|
return `${(sourceUrl: any)}:${(sourceId: any)}:${line}:${(column: any)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function waitForWorkers(shouldWait: boolean) {
|
|
||||||
shouldWaitForWorkers = shouldWait;
|
|
||||||
}
|
|
||||||
|
|
||||||
function detachWorkers() {
|
function detachWorkers() {
|
||||||
for (const thread of listWorkerThreadFronts()) {
|
for (const thread of listWorkerThreadFronts()) {
|
||||||
thread.detach();
|
thread.detach();
|
||||||
|
@ -217,7 +219,7 @@ function hasBreakpoint(location: BreakpointLocation) {
|
||||||
return !!breakpoints[locationKey(location)];
|
return !!breakpoints[locationKey(location)];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setBreakpoint(
|
function setBreakpoint(
|
||||||
location: BreakpointLocation,
|
location: BreakpointLocation,
|
||||||
options: BreakpointOptions
|
options: BreakpointOptions
|
||||||
) {
|
) {
|
||||||
|
@ -225,27 +227,14 @@ async function setBreakpoint(
|
||||||
options = maybeGenerateLogGroupId(options);
|
options = maybeGenerateLogGroupId(options);
|
||||||
breakpoints[locationKey(location)] = { location, options };
|
breakpoints[locationKey(location)] = { location, options };
|
||||||
|
|
||||||
// We have to be careful here to atomically initiate the setBreakpoint() call
|
return forEachThread(thread => thread.setBreakpoint(location, options));
|
||||||
// on every thread, with no intervening await. Otherwise, other code could run
|
|
||||||
// and change or remove the breakpoint before we finish calling setBreakpoint
|
|
||||||
// on all threads. Requests on server threads will resolve in FIFO order, and
|
|
||||||
// this could result in the breakpoint state here being out of sync with the
|
|
||||||
// breakpoints that are installed in the server.
|
|
||||||
const mainThreadPromise = threadFront.setBreakpoint(location, options);
|
|
||||||
|
|
||||||
await forEachWorkerThread(thread => thread.setBreakpoint(location, options));
|
|
||||||
await mainThreadPromise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function removeBreakpoint(location: PendingLocation) {
|
function removeBreakpoint(location: PendingLocation) {
|
||||||
maybeClearLogpoint((location: any));
|
maybeClearLogpoint((location: any));
|
||||||
delete breakpoints[locationKey((location: any))];
|
delete breakpoints[locationKey((location: any))];
|
||||||
|
|
||||||
// Delay waiting on this promise, for the same reason as in setBreakpoint.
|
return forEachThread(thread => thread.removeBreakpoint(location));
|
||||||
const mainThreadPromise = threadFront.removeBreakpoint(location);
|
|
||||||
|
|
||||||
await forEachWorkerThread(thread => thread.removeBreakpoint(location));
|
|
||||||
await mainThreadPromise;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function evaluateInFrame(script: Script, options: EvaluateParam) {
|
async function evaluateInFrame(script: Script, options: EvaluateParam) {
|
||||||
|
@ -325,20 +314,15 @@ async function getFrameScopes(frame: Frame): Promise<*> {
|
||||||
return sourceThreadFront.getEnvironment(frame.id);
|
return sourceThreadFront.getEnvironment(frame.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pauseOnExceptions(
|
function pauseOnExceptions(
|
||||||
shouldPauseOnExceptions: boolean,
|
shouldPauseOnExceptions: boolean,
|
||||||
shouldPauseOnCaughtExceptions: boolean
|
shouldPauseOnCaughtExceptions: boolean
|
||||||
): Promise<*> {
|
): Promise<*> {
|
||||||
await threadFront.pauseOnExceptions(
|
return forEachThread(thread =>
|
||||||
shouldPauseOnExceptions,
|
|
||||||
// Providing opposite value because server
|
|
||||||
// uses "shouldIgnoreCaughtExceptions"
|
|
||||||
!shouldPauseOnCaughtExceptions
|
|
||||||
);
|
|
||||||
|
|
||||||
await forEachWorkerThread(thread =>
|
|
||||||
thread.pauseOnExceptions(
|
thread.pauseOnExceptions(
|
||||||
shouldPauseOnExceptions,
|
shouldPauseOnExceptions,
|
||||||
|
// Providing opposite value because server
|
||||||
|
// uses "shouldIgnoreCaughtExceptions"
|
||||||
!shouldPauseOnCaughtExceptions
|
!shouldPauseOnCaughtExceptions
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -357,20 +341,18 @@ async function blackBox(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setSkipPausing(shouldSkip: boolean) {
|
function setSkipPausing(shouldSkip: boolean) {
|
||||||
await threadFront.skipBreakpoints(shouldSkip);
|
return forEachThread(thread => thread.skipBreakpoints(shouldSkip));
|
||||||
await forEachWorkerThread(thread => thread.skipBreakpoints(shouldSkip));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function interrupt(thread: string): Promise<*> {
|
function interrupt(thread: string): Promise<*> {
|
||||||
return lookupThreadFront(thread).interrupt();
|
return lookupThreadFront(thread).interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setEventListenerBreakpoints(ids: string[]) {
|
function setEventListenerBreakpoints(ids: string[]) {
|
||||||
eventBreakpoints = ids;
|
eventBreakpoints = ids;
|
||||||
|
|
||||||
await threadFront.setActiveEventBreakpoints(ids);
|
return forEachThread(thread => thread.setActiveEventBreakpoints(ids));
|
||||||
await forEachWorkerThread(thread => thread.setActiveEventBreakpoints(ids));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
|
@ -563,7 +545,6 @@ const clientCommands = {
|
||||||
setSkipPausing,
|
setSkipPausing,
|
||||||
setEventListenerBreakpoints,
|
setEventListenerBreakpoints,
|
||||||
getEventListenerBreakpointTypes,
|
getEventListenerBreakpointTypes,
|
||||||
waitForWorkers,
|
|
||||||
detachWorkers,
|
detachWorkers,
|
||||||
hasWasmSupport,
|
hasWasmSupport,
|
||||||
lookupConsoleClient,
|
lookupConsoleClient,
|
||||||
|
|
|
@ -9,11 +9,6 @@ add_task(async function() {
|
||||||
|
|
||||||
const workerSource = findSource(dbg, "simple-worker.js");
|
const workerSource = findSource(dbg, "simple-worker.js");
|
||||||
|
|
||||||
// NOTE: by default we do not wait on worker
|
|
||||||
// commands to complete because the thread could be
|
|
||||||
// shutting down.
|
|
||||||
dbg.client.waitForWorkers(true);
|
|
||||||
|
|
||||||
await selectSource(dbg, "simple-worker.js");
|
await selectSource(dbg, "simple-worker.js");
|
||||||
await waitForSelectedSource(dbg, "simple-worker.js");
|
await waitForSelectedSource(dbg, "simple-worker.js");
|
||||||
await addBreakpoint(dbg, workerSource, 1);
|
await addBreakpoint(dbg, workerSource, 1);
|
||||||
|
|
|
@ -44,11 +44,6 @@ add_task(async function() {
|
||||||
const dbg = await initDebugger("doc-windowless-workers.html");
|
const dbg = await initDebugger("doc-windowless-workers.html");
|
||||||
const mainThread = dbg.toolbox.threadFront.actor;
|
const mainThread = dbg.toolbox.threadFront.actor;
|
||||||
|
|
||||||
// NOTE: by default we do not wait on worker
|
|
||||||
// commands to complete because the thread could be
|
|
||||||
// shutting down.
|
|
||||||
dbg.client.waitForWorkers(true);
|
|
||||||
|
|
||||||
const workers = await getWorkers(dbg);
|
const workers = await getWorkers(dbg);
|
||||||
ok(workers.length == 2, "Got two workers");
|
ok(workers.length == 2, "Got two workers");
|
||||||
const thread1 = workers[0].actor;
|
const thread1 = workers[0].actor;
|
||||||
|
|
|
@ -531,7 +531,6 @@ async function initDebugger(url, ...sources) {
|
||||||
await clearDebuggerPreferences();
|
await clearDebuggerPreferences();
|
||||||
const toolbox = await openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
|
const toolbox = await openNewTabAndToolbox(EXAMPLE_URL + url, "jsdebugger");
|
||||||
const dbg = createDebuggerContext(toolbox);
|
const dbg = createDebuggerContext(toolbox);
|
||||||
dbg.client.waitForWorkers(false);
|
|
||||||
|
|
||||||
await waitForSources(dbg, ...sources);
|
await waitForSources(dbg, ...sources);
|
||||||
return dbg;
|
return dbg;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче