Bug 1967931 - Avoid blocking rendering for devtools pauses. r=smaug,devtools-reviewers,nchevobbe

This regresses browser_dbg-scroll-run-to-completion.js, but I think we
should either suppress rendering or not suppress it, not doing some
weird in-between thing. So for now given the discussion on the bug it's
probably acceptable.

Differential Revision: https://phabricator.services.mozilla.com/D250772
This commit is contained in:
Emilio Cobos Álvarez
2025-05-24 10:12:15 +00:00
committed by ealvarez@mozilla.com
parent 923625d5f0
commit abfb41e00a
6 changed files with 35 additions and 12 deletions

View File

@@ -197,6 +197,7 @@ fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and
fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and/or labeled
["browser_dbg-scroll-run-to-completion.js"]
skip-if = ["true"] # See bug 1968387
["browser_dbg-scrolling-with-search.js"]

View File

@@ -228,6 +228,9 @@ class PausedDebuggerOverlay {
// document's setSuppressedEventListener interface to still be able to act on mouse
// events (they'll be handled by the `handleEvent` method)
this.env.window.document.setSuppressedEventListener(this);
// Ensure layout is initialized so that we show the highlighter no matter what,
// even if the page is not done loading, see bug 1580394.
this.env.window.document.documentElement?.getBoundingClientRect();
return true;
}

View File

@@ -89,8 +89,7 @@ class EventLoop {
// - exiting this EventLoop unblocks its "enter" method and moves lastNestRequestor to the next requestor (if any)
// - we go back to the first step, and attempt to exit the new lastNestRequestor if it is resolved, etc...
if (xpcInspector.eventLoopNestLevel > 0) {
const { resolved } = xpcInspector.lastNestRequestor;
if (resolved) {
if (xpcInspector.lastNestRequestor.resolved) {
xpcInspector.exitNestedEventLoop();
}
}
@@ -198,29 +197,40 @@ class EventLoop {
* Prepare to enter a nested event loop by disabling debuggee events.
*/
preEnter() {
const docShells = [];
const preEnterData = [];
// Disable events in all open windows.
for (const window of this.getAllWindowDebuggees()) {
const { windowUtils } = window;
const { windowUtils, document } = window;
const wasPaused = !!document?.pausedByDevTools;
if (document) {
document.pausedByDevTools = true;
}
windowUtils.suppressEventHandling(true);
windowUtils.suspendTimeouts();
docShells.push(window.docShell);
preEnterData.push({
docShell: window.docShell,
wasPaused,
});
}
return docShells;
return preEnterData;
}
/**
* Prepare to exit a nested event loop by enabling debuggee events.
*/
postExit(pausedDocShells) {
postExit(preEnterData) {
// Enable events in all window paused in preEnter
for (const docShell of pausedDocShells) {
for (const { docShell, wasPaused } of preEnterData) {
// Do not try to resume documents which are in destruction
// as resume methods would throw
if (docShell.isBeingDestroyed()) {
continue;
}
const { windowUtils } = docShell.domWindow;
const window = docShell.domWindow;
const { windowUtils, document } = window;
if (document) {
document.pausedByDevTools = wasPaused;
}
windowUtils.resumeTimeouts();
windowUtils.suppressEventHandling(false);
}

View File

@@ -1408,6 +1408,7 @@ Document::Document(const char* aContentType)
mHasHadDefaultView(false),
mStyleSheetChangeEventsEnabled(false),
mDevToolsAnonymousAndShadowEventsEnabled(false),
mPausedByDevTools(false),
mIsSrcdocDocument(false),
mHasDisplayDocument(false),
mFontFaceSetDirty(true),
@@ -7415,7 +7416,8 @@ bool Document::IsRenderingSuppressed() const {
}
// The user agent believes that updating the rendering of doc's node navigable
// would have no visible effect.
if (!IsEventHandlingEnabled() && !IsBeingUsedAsImage() && !mDisplayDocument) {
if (!IsEventHandlingEnabled() && !IsBeingUsedAsImage() && !mDisplayDocument &&
!mPausedByDevTools) {
return true;
}
if (!mPresShell || !mPresShell->DidInitialize()) {

View File

@@ -3609,17 +3609,17 @@ class Document : public nsINode,
void SetStyleSheetChangeEventsEnabled(bool aValue) {
mStyleSheetChangeEventsEnabled = aValue;
}
bool StyleSheetChangeEventsEnabled() const {
return mStyleSheetChangeEventsEnabled;
}
void SetDevToolsAnonymousAndShadowEventsEnabled(bool aValue) {
mDevToolsAnonymousAndShadowEventsEnabled = aValue;
}
bool DevToolsAnonymousAndShadowEventsEnabled() const {
return mDevToolsAnonymousAndShadowEventsEnabled;
}
void SetPausedByDevTools(bool aValue) { mPausedByDevTools = aValue; }
bool PausedByDevTools() const { return mPausedByDevTools; }
already_AddRefed<Promise> BlockParsing(Promise& aPromise,
const BlockParsingOptions& aOptions,
@@ -4889,6 +4889,10 @@ class Document : public nsINode,
// will be dispatched for this document.
bool mDevToolsAnonymousAndShadowEventsEnabled : 1;
// Whether DevTools is pausing the page (in which case we don't really want to
// stop rendering).
bool mPausedByDevTools : 1;
// Whether the document was created by a srcdoc iframe.
bool mIsSrcdocDocument : 1;

View File

@@ -443,6 +443,9 @@ partial interface Document {
[ChromeOnly]
attribute boolean devToolsAnonymousAndShadowEventsEnabled;
[ChromeOnly]
attribute boolean pausedByDevTools;
[ChromeOnly, BinaryName="contentLanguageForBindings"] readonly attribute DOMString contentLanguage;
[ChromeOnly] readonly attribute nsILoadGroup? documentLoadGroup;