/* 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", packet => { // 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); } };