Pass the global signal the text layer builder in order to remove all the listeners defined here

The goal of this patch is to remove the noice we've in the logs:
```
 0:09.36 INFO Console message: [JavaScript Warning: "Script terminated by timeout at:
reset@resource://pdf.js/web/viewer.mjs:11773:7
EventListener.handleEvent*#enableGlobalSelectionListener@resource://pdf.js/web/viewer.mjs:11787:12
render@resource://pdf.js/web/viewer.mjs:11716:20
async*#renderTextLayer@resource://pdf.js/web/viewer.mjs:12108:28
draw/resultPromise<@resource://pdf.js/web/viewer.mjs:12575:53
promise callback*draw@resource://pdf.js/web/viewer.mjs:12570:8
renderView@resource://pdf.js/web/viewer.mjs:7872:14
forceRendering/<@resource://pdf.js/web/viewer.mjs:13963:29
" {file: "resource://pdf.js/web/viewer.mjs" line: 11773}]
```
This commit is contained in:
Calixte Denizet 2026-03-20 14:25:36 +01:00
parent 5bdeb79b09
commit e1f02be670
No known key found for this signature in database
GPG Key ID: 0C5442631EE0691F
3 changed files with 45 additions and 16 deletions

View File

@ -108,6 +108,7 @@ import { XfaLayerBuilder } from "./xfa_layer_builder.js";
* text that look like URLs. The default value is `true`.
* @property {CommentManager} [commentManager] - The comment manager instance.
* to.
* @property {AbortSignal} [abortSignal]
*/
const DEFAULT_LAYER_PROPERTIES =
@ -135,6 +136,8 @@ const LAYERS_ORDER = new Map([
]);
class PDFPageView extends BasePDFPageView {
#abortSignal = null;
#annotationMode = AnnotationMode.ENABLE_FORMS;
#canvasWrapper = null;
@ -181,6 +184,7 @@ class PDFPageView extends BasePDFPageView {
this.renderingId = "page" + this.id;
this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES;
this.#abortSignal = options.abortSignal || null;
this.pdfPage = null;
this.pageLabel = null;
@ -285,6 +289,7 @@ class PDFPageView extends BasePDFPageView {
defaultViewport: this.viewport,
id,
layerProperties: this.#layerProperties,
abortSignal: this.#abortSignal,
scale: this.scale,
optionalContentConfigPromise: this._optionalContentConfigPromise,
textLayerMode: this.#textLayerMode,
@ -1056,6 +1061,7 @@ class PDFPageView extends BasePDFPageView {
this.#addLayer(textLayerDiv, "textLayer");
this.l10n.resume();
},
abortSignal: this.#abortSignal,
});
}

View File

@ -253,6 +253,8 @@ class PDFViewer {
#enableAutoLinking = true;
#abortSignal = null;
#eventAbortController = null;
#minDurationToUpdateCanvas = 0;
@ -385,6 +387,7 @@ class PDFViewer {
}
const { abortSignal } = options;
this.#abortSignal = abortSignal || null;
abortSignal?.addEventListener(
"abort",
() => {
@ -1068,6 +1071,7 @@ class PDFViewer {
enableAutoLinking: this.#enableAutoLinking,
minDurationToUpdateCanvas: this.#minDurationToUpdateCanvas,
commentManager: this.#commentManager,
abortSignal: this.#abortSignal,
});
this._pages.push(pageView);
}

View File

@ -33,6 +33,7 @@ import { removeNullCharacters } from "./ui_utils.js";
* @property {TextAccessibilityManager} [accessibilityManager]
* @property {boolean} [enablePermissions]
* @property {function} [onAppend]
* @property {AbortSignal} [abortSignal]
*/
/**
@ -48,6 +49,8 @@ import { removeNullCharacters } from "./ui_utils.js";
* contain text that matches the PDF text they are overlaying.
*/
class TextLayerBuilder {
#abortSignal = null;
#enablePermissions = false;
#onAppend = null;
@ -69,12 +72,14 @@ class TextLayerBuilder {
accessibilityManager = null,
enablePermissions = false,
onAppend = null,
abortSignal = null,
}) {
this.pdfPage = pdfPage;
this.highlighter = highlighter;
this.accessibilityManager = accessibilityManager;
this.#enablePermissions = enablePermissions === true;
this.#onAppend = onAppend;
this.#abortSignal = abortSignal;
this.div = document.createElement("div");
this.div.tabIndex = 0;
@ -163,24 +168,33 @@ class TextLayerBuilder {
*/
#bindMouse(end) {
const { div } = this;
const abortSignal = this.#abortSignal;
div.addEventListener("mousedown", () => {
div.classList.add("selecting");
});
div.addEventListener(
"mousedown",
() => {
div.classList.add("selecting");
},
{ signal: abortSignal }
);
div.addEventListener("copy", event => {
if (!this.#enablePermissions) {
const selection = document.getSelection();
event.clipboardData.setData(
"text/plain",
removeNullCharacters(normalizeUnicode(selection.toString()))
);
}
stopEvent(event);
});
div.addEventListener(
"copy",
event => {
if (!this.#enablePermissions) {
const selection = document.getSelection();
event.clipboardData.setData(
"text/plain",
removeNullCharacters(normalizeUnicode(selection.toString()))
);
}
stopEvent(event);
},
{ signal: abortSignal }
);
TextLayerBuilder.#textLayers.set(div, end);
TextLayerBuilder.#enableGlobalSelectionListener();
TextLayerBuilder.#enableGlobalSelectionListener(abortSignal);
}
static #removeGlobalSelectionListener(textLayerDiv) {
@ -192,13 +206,18 @@ class TextLayerBuilder {
}
}
static #enableGlobalSelectionListener() {
static #enableGlobalSelectionListener(globalAbortSignal) {
if (this.#selectionChangeAbortController) {
// document-level event listeners already installed
return;
}
this.#selectionChangeAbortController = new AbortController();
const { signal } = this.#selectionChangeAbortController;
const signal = globalAbortSignal
? AbortSignal.any([
this.#selectionChangeAbortController.signal,
globalAbortSignal,
])
: this.#selectionChangeAbortController.signal;
const reset = (end, textLayer) => {
if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {