diff --git a/src/display/api.js b/src/display/api.js index ba5dd87cf8ee0..48de0601c4f48 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -2127,6 +2127,10 @@ class WorkerTransport { this.setupMessageHandler(); } + get loadingTaskSettled() { + return this.loadingTask._capability.settled; + } + destroy() { if (this.destroyCapability) { return this.destroyCapability.promise; @@ -2154,6 +2158,18 @@ class WorkerTransport { // We also need to wait for the worker to finish its long running tasks. const terminated = this.messageHandler.sendWithPromise("Terminate", null); waitOn.push(terminated); + // Allow `AnnotationStorage`-related clean-up when destroying the document. + if (this.loadingTaskSettled) { + const annotationStorageResetModified = this.loadingTask.promise + .then(pdfDocument => { + // Avoid initializing the `annotationStorage` if it doesn't exist. + if (pdfDocument.hasOwnProperty("annotationStorage")) { + pdfDocument.annotationStorage.resetModified(); + } + }) + .catch(() => {}); + waitOn.push(annotationStorageResetModified); + } Promise.all(waitOn).then(() => { this.commonObjs.clear(); this.fontLoader.clear(); diff --git a/web/app.js b/web/app.js index df37f0c669778..80a67da559787 100644 --- a/web/app.js +++ b/web/app.js @@ -1060,6 +1060,14 @@ const PDFViewerApplication = { }); }, + downloadOrSave(options) { + if (this.pdfDocument?.annotationStorage.size > 0) { + this.save(options); + } else { + this.download(options); + } + }, + /** * For PDF documents that contain e.g. forms and javaScript, we should only * trigger the fallback bar once the user has interacted with the page. @@ -1279,14 +1287,6 @@ const PDFViewerApplication = { this.pdfLinkService.setDocument(pdfDocument, baseDocumentUrl); this.pdfDocumentProperties.setDocument(pdfDocument, this.url); - const annotationStorage = pdfDocument.annotationStorage; - annotationStorage.onSetModified = function () { - window.addEventListener("beforeunload", beforeUnload); - }; - annotationStorage.onResetModified = function () { - window.removeEventListener("beforeunload", beforeUnload); - }; - const pdfViewer = this.pdfViewer; pdfViewer.setDocument(pdfDocument); const { firstPagePromise, onePageRendered, pagesPromise } = pdfViewer; @@ -1314,6 +1314,7 @@ const PDFViewerApplication = { firstPagePromise.then(pdfPage => { this.loadingBar.setWidth(this.appConfig.viewerContainer); + this._initializeAnnotationStorageCallbacks(pdfDocument); Promise.all([ animationStarted, @@ -1870,6 +1871,23 @@ const PDFViewerApplication = { } }, + /** + * @private + */ + _initializeAnnotationStorageCallbacks(pdfDocument) { + if (pdfDocument !== this.pdfDocument) { + return; + } + const { annotationStorage } = pdfDocument; + + annotationStorage.onSetModified = function () { + window.addEventListener("beforeunload", beforeUnload); + }; + annotationStorage.onResetModified = function () { + window.removeEventListener("beforeunload", beforeUnload); + }; + }, + setInitialView( storedHash, { rotation, sidebarView, scrollMode, spreadMode } = {} @@ -2712,21 +2730,11 @@ function webViewerPresentationMode() { function webViewerPrint() { PDFViewerApplication.triggerPrinting(); } -function webViewerDownloadOrSave(sourceEventType) { - if ( - PDFViewerApplication.pdfDocument && - PDFViewerApplication.pdfDocument.annotationStorage.size > 0 - ) { - PDFViewerApplication.save({ sourceEventType }); - } else { - PDFViewerApplication.download({ sourceEventType }); - } -} function webViewerDownload() { - webViewerDownloadOrSave("download"); + PDFViewerApplication.downloadOrSave({ sourceEventType: "download" }); } function webViewerSave() { - webViewerDownloadOrSave("save"); + PDFViewerApplication.downloadOrSave({ sourceEventType: "save" }); } function webViewerFirstPage() { if (PDFViewerApplication.pdfDocument) {