Merge pull request #20888 from calixteman/debugger_skip_ops

Add the possibility to skip some ops in the debug view
This commit is contained in:
Tim van der Meij 2026-03-16 20:36:48 +01:00 committed by GitHub
commit 0a2c030c8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 77 additions and 23 deletions

View File

@ -786,9 +786,15 @@ class CanvasGraphics {
let fnId, fnArgs;
while (true) {
if (stepper !== undefined && i === stepper.nextBreakPoint) {
stepper.breakIt(i, continueCallback);
return i;
if (stepper !== undefined) {
if (i === stepper.nextBreakPoint) {
stepper.breakIt(i, continueCallback);
return i;
}
if (stepper.shouldSkip(i)) {
i++;
continue;
}
}
if (!operationsFilter || operationsFilter(i)) {

View File

@ -659,6 +659,10 @@ class Stepper {
this.goTo(idx);
}
shouldSkip(idx) {
return false;
}
goTo(idx) {
const allRows = this.panel.getElementsByClassName("line");
for (const row of allRows) {

View File

@ -159,7 +159,7 @@
&::before {
content: "●";
color: var(--changed-color);
font-size: 0.75em;
font-size: 0.9em;
opacity: 0;
}
@ -167,9 +167,17 @@
opacity: 0.4;
}
&.active::before {
&[data-bp="pause"]::before {
opacity: 1;
}
&[data-bp="skip"]::before {
content: "✕";
opacity: 1;
}
}
.op-line.op-skipped > :not(.bp-gutter) {
opacity: 0.4;
}
.op-line.paused {
background: var(--paused-bg);
@ -194,9 +202,16 @@
.bp-gutter:hover::before {
color: ButtonBorder;
}
.bp-gutter.active::before {
.bp-gutter[data-bp="pause"]::before {
color: ButtonText;
}
.bp-gutter[data-bp="skip"]::before {
color: ButtonText;
}
.op-line.op-skipped > :not(.bp-gutter) {
opacity: 1;
color: GrayText;
}
/* Color swatch preserves the actual PDF color value. */
.color-swatch {

View File

@ -23,6 +23,11 @@ for (const [name, id] of Object.entries(OPS)) {
OPS_TO_NAME[id] = name;
}
const BreakpointType = {
PAUSE: 0,
SKIP: 1,
};
// Single hidden color input reused for all swatch pickers.
const colorPickerInput = document.createElement("input");
colorPickerInput.type = "color";
@ -408,7 +413,8 @@ class DrawOpsView {
#selectedLine = null;
#breakpoints = new Set();
// Map<opIndex, BreakpointType>
#breakpoints = new Map();
#originalColors = new Map();
@ -553,27 +559,40 @@ class DrawOpsView {
line.ariaSelected = "false";
line.tabIndex = i === 0 ? 0 : -1;
// Breakpoint gutter — click to toggle a red-bullet breakpoint.
// Breakpoint gutter — click cycles: none → pause (●) → skip (✕) → none.
const gutter = document.createElement("span");
gutter.className = "bp-gutter";
gutter.role = "checkbox";
gutter.tabIndex = 0;
gutter.ariaLabel = "Breakpoint";
const isInitiallyActive = this.#breakpoints.has(i);
gutter.ariaChecked = String(isInitiallyActive);
if (isInitiallyActive) {
gutter.classList.add("active");
const initBpType = this.#breakpoints.get(i);
if (initBpType === BreakpointType.PAUSE) {
gutter.dataset.bp = "pause";
gutter.ariaChecked = "true";
} else if (initBpType === BreakpointType.SKIP) {
gutter.dataset.bp = "skip";
gutter.ariaChecked = "mixed";
line.classList.add("op-skipped");
} else {
gutter.ariaChecked = "false";
}
gutter.addEventListener("click", e => {
e.stopPropagation();
if (this.#breakpoints.has(i)) {
this.#breakpoints.delete(i);
gutter.classList.remove("active");
gutter.ariaChecked = "false";
} else {
this.#breakpoints.add(i);
gutter.classList.add("active");
const current = this.#breakpoints.get(i);
if (current === undefined) {
this.#breakpoints.set(i, BreakpointType.PAUSE);
gutter.dataset.bp = "pause";
gutter.ariaChecked = "true";
} else if (current === BreakpointType.PAUSE) {
this.#breakpoints.set(i, BreakpointType.SKIP);
gutter.dataset.bp = "skip";
gutter.ariaChecked = "mixed";
line.classList.add("op-skipped");
} else {
this.#breakpoints.delete(i);
delete gutter.dataset.bp;
gutter.ariaChecked = "false";
line.classList.remove("op-skipped");
}
});
gutter.addEventListener("keydown", e => {
@ -656,4 +675,4 @@ class DrawOpsView {
}
}
export { DrawOpsView };
export { BreakpointType, DrawOpsView };

View File

@ -13,9 +13,9 @@
* limitations under the License.
*/
import { BreakpointType, DrawOpsView } from "./draw_ops_view.js";
import { CanvasContextDetailsView } from "./canvas_context_details_view.js";
import { DOMCanvasFactory } from "pdfjs/display/canvas_factory.js";
import { DrawOpsView } from "./draw_ops_view.js";
import { SplitView } from "./split_view.js";
// Stepper for pausing/stepping through op list rendering.
@ -61,10 +61,20 @@ class ViewerStepper {
cb();
}
shouldSkip(i) {
return (
globalThis.StepperManager._breakpoints.get(i) === BreakpointType.SKIP
);
}
#findNextAfter(idx) {
let next = null;
for (const bp of globalThis.StepperManager._breakpoints) {
if (bp > idx && (next === null || bp < next)) {
for (const [bp, type] of globalThis.StepperManager._breakpoints) {
if (
type === BreakpointType.PAUSE &&
bp > idx &&
(next === null || bp < next)
) {
next = bp;
}
}