From a4786c96898de09cb6174f4abe6b7d19009d1cb6 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald <jonas.jenwald@gmail.com> Date: Wed, 23 Dec 2020 11:39:54 +0100 Subject: [PATCH] [Scripting] Await manually triggered `dispatchEventInSandbox` calls in the viewer Given that the `dispatchEventInSandbox` method (on the scripting-classes) is asynchronous, there's a very real risk that the events won't be dispatched/handled until *after* their associated functionality has actually run (with the "Will..." events being particularily susceptible to this issue). To reduce the likelihood of that happening, we can simply `await` the `dispatchEventInSandbox` calls as necessary. A couple of methods are now marked as `async` to support these changes, however that shouldn't be a problem as far as I can tell. *Please note:* Given that the browser "beforeprint"/"afterprint" events are *synchronous*, we unfortunately cannot await the `WillPrint`/`DidPrint` event dispatching. To fix this properly the web-platform would need support for asynchronous printing, and we'll thus have to hope that things work correctly anyway. --- web/app.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/web/app.js b/web/app.js index 6040dc854..21266514b 100644 --- a/web/app.js +++ b/web/app.js @@ -1013,7 +1013,7 @@ const PDFViewerApplication = { .catch(downloadByUrl); // Error occurred, try downloading with the URL. }, - save({ sourceEventType = "download" } = {}) { + async save({ sourceEventType = "download" } = {}) { if (this._saveInProgress) { return; } @@ -1036,12 +1036,13 @@ const PDFViewerApplication = { this.download({ sourceEventType }); return; } - this._scriptingInstance?.scripting.dispatchEventInSandbox({ + this._saveInProgress = true; + + await this._scriptingInstance?.scripting.dispatchEventInSandbox({ id: "doc", name: "WillSave", }); - this._saveInProgress = true; this.pdfDocument .saveDocument(this.pdfDocument.annotationStorage) .then(data => { @@ -1051,8 +1052,8 @@ const PDFViewerApplication = { .catch(() => { this.download({ sourceEventType }); }) - .finally(() => { - this._scriptingInstance?.scripting.dispatchEventInSandbox({ + .finally(async () => { + await this._scriptingInstance?.scripting.dispatchEventInSandbox({ id: "doc", name: "DidSave", }); @@ -1614,7 +1615,7 @@ const PDFViewerApplication = { return; } - scripting.dispatchEventInSandbox({ + await scripting.dispatchEventInSandbox({ id: "doc", name: "Open", }); @@ -1967,6 +1968,8 @@ const PDFViewerApplication = { }, beforePrint() { + // Given that the "beforeprint" browser event is synchronous, we + // unfortunately cannot await the scripting event dispatching here. this._scriptingInstance?.scripting.dispatchEventInSandbox({ id: "doc", name: "WillPrint", @@ -2033,6 +2036,8 @@ const PDFViewerApplication = { }, afterPrint() { + // Given that the "afterprint" browser event is synchronous, we + // unfortunately cannot await the scripting event dispatching here. this._scriptingInstance?.scripting.dispatchEventInSandbox({ id: "doc", name: "DidPrint",