From 799a57e0fb75dd37432638be78d2885535247bfb Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sat, 22 Aug 2026 15:39:15 +0200 Subject: [PATCH] Fix inconsistencies with the `Page.prototype.#replaceIdByRef` method This private method has two call-sites, which provide *different* `deletedAnnotations` parameters; see - https://github.com/mozilla/pdf.js/blob/0f26334f9d6f96119f6e5164fb65832fbbde7344/src/core/document.js#L378-L384 - https://github.com/mozilla/pdf.js/blob/0f26334f9d6f96119f6e5164fb65832fbbde7344/src/core/document.js#L534-L539 Thanks to the similarities between the `RefMap` and `RefSet` classes this inconsistency hasn't caused any bugs, as far as I know, but it should still be fixed. Given how the `deletedAnnotations` is being used, a `RefSet` really seems to be the "correct" data-structure to use here since we only need to track references. Finally, make use of an early `continue` to reduce overall indentation and thus shorten the code in the `Page.prototype.#replaceIdByRef` method. --- src/core/document.js | 69 ++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/src/core/document.js b/src/core/document.js index 7e1adf0a68316..53a238cabb424 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -327,44 +327,45 @@ class Page { async #replaceIdByRef(annotations, deletedAnnotations, existingAnnotations) { const promises = []; for (const annotation of annotations) { - if (annotation.id) { - const ref = Ref.fromString(annotation.id); - if (!ref) { - warn(`A non-linked annotation cannot be modified: ${annotation.id}`); - continue; - } - if (annotation.deleted) { - deletedAnnotations.put(ref, ref); - if (annotation.popupRef) { - const popupRef = Ref.fromString(annotation.popupRef); - if (popupRef) { - deletedAnnotations.put(popupRef, popupRef); - } - } - continue; - } - if (annotation.popup?.deleted) { + if (!annotation.id) { + continue; + } + const ref = Ref.fromString(annotation.id); + if (!ref) { + warn(`A non-linked annotation cannot be modified: ${annotation.id}`); + continue; + } + if (annotation.deleted) { + deletedAnnotations.put(ref); + if (annotation.popupRef) { const popupRef = Ref.fromString(annotation.popupRef); if (popupRef) { - deletedAnnotations.put(popupRef, popupRef); + deletedAnnotations.put(popupRef); } } - existingAnnotations?.put(ref); - annotation.ref = ref; - promises.push( - this.xref.fetchAsync(ref).then( - obj => { - if (obj instanceof Dict) { - annotation.oldAnnotation = obj.clone(); - } - }, - () => { - warn(`Cannot fetch \`oldAnnotation\` for: ${ref}.`); - } - ) - ); - delete annotation.id; + continue; + } + if (annotation.popup?.deleted) { + const popupRef = Ref.fromString(annotation.popupRef); + if (popupRef) { + deletedAnnotations.put(popupRef); + } } + existingAnnotations?.put(ref); + annotation.ref = ref; + promises.push( + this.xref.fetchAsync(ref).then( + obj => { + if (obj instanceof Dict) { + annotation.oldAnnotation = obj.clone(); + } + }, + () => { + warn(`Cannot fetch \`oldAnnotation\` for: ${ref}.`); + } + ) + ); + delete annotation.id; } await Promise.all(promises); } @@ -375,7 +376,7 @@ class Page { } const partialEvaluator = this.#createPartialEvaluator(handler); - const deletedAnnotations = new RefMap(); + const deletedAnnotations = new RefSet(); const existingAnnotations = new RefSet(); await this.#replaceIdByRef( annotations,