1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const ResourceCommand = require("resource://devtools/shared/commands/resource/resource-command.js");
module.exports = async function ({ targetCommand, targetFront, onAvailable }) {
const isBrowserToolbox =
targetCommand.descriptorFront.isBrowserProcessDescriptor;
const isNonTopLevelFrameTarget =
!targetFront.isTopLevel &&
targetFront.targetType === targetCommand.TYPES.FRAME;
if (isBrowserToolbox && isNonTopLevelFrameTarget) {
// In the BrowserToolbox, non-top-level frame targets are already
// debugged via content-process targets.
return;
}
// Wait for the thread actor to be attached, otherwise getFront(thread) will throw for worker targets
// This is because worker target are still kind of descriptors and are only resolved into real target
// after being attached. And the thread actor ID is only retrieved and available after being attached.
await targetFront.onThreadAttached;
if (targetFront.isDestroyed()) {
return;
}
const threadFront = await targetFront.getFront("thread");
let isInterrupted = false;
const onPausedPacket = packet => {
// If paused by an explicit interrupt, which are generated by the
// slow script dialog and internal events such as setting
// breakpoints, ignore the event.
const { why } = packet;
if (why.type === "interrupted" && !why.onNext) {
isInterrupted = true;
return;
}
// Ignore attached events because they are not useful to the user.
if (why.type == "alreadyPaused" || why.type == "attached") {
return;
}
onAvailable([
{
resourceType: ResourceCommand.TYPES.THREAD_STATE,
state: "paused",
why,
frame: packet.frame,
},
]);
};
threadFront.on("paused", onPausedPacket);
threadFront.on("resumed", () => {
// NOTE: the client suppresses resumed events while interrupted
// to prevent unintentional behavior.
// see [client docs](devtools/client/debugger/src/client/README.md#interrupted) for more information.
if (isInterrupted) {
isInterrupted = false;
return;
}
onAvailable([
{
resourceType: ResourceCommand.TYPES.THREAD_STATE,
state: "resumed",
},
]);
});
// Notify about already paused thread
const pausedPacket = threadFront.getLastPausePacket();
if (pausedPacket) {
onPausedPacket(pausedPacket);
}
};
|