You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
TextLayerBuilder: global selection listeners are never re-bound after the viewer that registered them is aborted while another text layer is alive #22129
Version: pdfjs-dist 6.3.289 (same code on master, web/text_layer_builder.js, checked against v6.4.299)
Setup: two PDFViewer instances on one page, each created with its own abortSignal (for example a page reader plus a modal reader).
Steps
Mount viewer A with abortSignal: a.signal and render a page with a text layer.
Mount viewer B with abortSignal: b.signal and render a page with a text layer.
Abort a (viewer A is torn down; viewer B stays).
In viewer B, press the mouse on the text layer, drag, release.
Expected: the selection works, and on pointerup the text layer drops its selecting class.
Actual: after the first mousedown, the text layer keeps selecting. With the stock CSS, .textLayer.selecting .endOfContent { top: 0 } makes endOfContent cover the whole layer (user-select: none), and .textLayer.selecting ~ .annotationLayer section { pointer-events: none } disables the link annotations. New drag selections and links on that page stop working until every text layer is gone.
Cause: #enableGlobalSelectionListener(globalAbortSignal) binds the document listeners (pointerdown, pointerup, blur, keyup, selectionchange) on AbortSignal.any([#selectionChangeAC.signal, globalAbortSignal]), where globalAbortSignal is the signal of the FIRST viewer that registered a text layer. It returns early while #selectionChangeAC is set, and #selectionChangeAC is cleared only when #textLayers.size === 0. When the first viewer's signal aborts, the listeners go away, but #selectionChangeAC stays set because viewer B's text layer is still in #textLayers, so no later call binds them again.
Possible fix: the shared listeners should not live on one viewer's signal. For example, keep each text layer's abortSignal beside its endOfContent in #textLayers; when the signal the listeners were bound with aborts, drop that viewer's layers, clear #selectionChangeAC, and if text layers remain, bind again with a remaining layer's signal. Checking only #selectionChangeAC's own signal at the next #bindMouse is not enough: the surviving viewer's existing layers never call #bindMouse again.
Activity