From 82fc2c94f05cb352c3aaa869bf2094df8f476533 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Tue, 24 Feb 2026 13:03:09 +0100 Subject: [PATCH] Include transfers correctly in the "GetOperatorList" message (PR 16588 follow-up) Currently the transfers aren't actually being used with the "GetOperatorList" message, since the placement of the parameter is wrong; note the method signature: https://github.com/mozilla/pdf.js/blob/909a700afa004167bb05bc3d67ed113e74a71729/src/shared/message_handler.js#L219-L229 This goes back to PR 16588, which added the transfers parameter, and unfortunately we all missed that :-( Simply fixing the parameter isn't enough however, since that broke printing of Stamp-editors (and possibly others). The solution here is to *not* transfer data during printing, given that a single `PrintAnnotationStorage` instance is being used for all pages. --- src/display/annotation_storage.js | 14 ++++++++++---- src/display/api.js | 1 + test/driver.js | 8 +++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/display/annotation_storage.js b/src/display/annotation_storage.js index 94063073a..e0736b301 100644 --- a/src/display/annotation_storage.js +++ b/src/display/annotation_storage.js @@ -330,15 +330,21 @@ class AnnotationStorage { * contents. (Necessary since printing is triggered synchronously in browsers.) */ class PrintAnnotationStorage extends AnnotationStorage { - #serializable; + #serializable = SerializableEmpty; constructor(parent) { super(); - const { map, hash, transfer } = parent.serializable; + + const { serializable } = parent; + if (serializable === SerializableEmpty) { + return; + } + const { map, hash, transfer } = serializable; // Create a *copy* of the data, since Objects are passed by reference in JS. const clone = structuredClone(map, transfer ? { transfer } : null); - - this.#serializable = { map: clone, hash, transfer }; + // The `PrintAnnotationStorage` instance is re-used for all pages, + // hence we cannot transfer the data since that breaks printing. + this.#serializable = { map: clone, hash, transfer: [] }; } /** diff --git a/src/display/api.js b/src/display/api.js index 19cbbaeed..004970e68 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -1898,6 +1898,7 @@ class PDFPageProxy { annotationStorage: map, modifiedIds, }, + /* queueingStrategy = */ undefined, transfer ); const reader = readableStream.getReader(); diff --git a/test/driver.js b/test/driver.js index 612832b09..5336ff7a9 100644 --- a/test/driver.js +++ b/test/driver.js @@ -803,6 +803,10 @@ class Driver { } task.pdfDoc = doc; + if (!task.save && task.print && task.annotationStorage) { + doc.annotationStorage._setValues(task.annotationStorage); + task.printAnnotationStorage = doc.annotationStorage.print; + } task.optionalContentConfigPromise = doc.getOptionalContentConfig({ intent: task.print ? "print" : "display", }); @@ -969,7 +973,7 @@ class Driver { pageColors = null, partialCrop = null; - if (task.annotationStorage) { + if (!task.print && task.annotationStorage) { task.pdfDoc.annotationStorage._setValues(task.annotationStorage); } @@ -1079,6 +1083,8 @@ class Driver { } else if (renderPrint) { if (task.annotationStorage) { renderContext.annotationMode = AnnotationMode.ENABLE_STORAGE; + renderContext.printAnnotationStorage = + task.printAnnotationStorage; } renderContext.intent = "print"; }