diff --git a/src/scripting_api/app_utils.js b/src/scripting_api/app_utils.js index d9a727a65..b46f8ea26 100644 --- a/src/scripting_api/app_utils.js +++ b/src/scripting_api/app_utils.js @@ -21,8 +21,14 @@ const FORMS_VERSION = 21.00720099; const USERACTIVATION_CALLBACKID = 0; const USERACTIVATION_MAXTIME_VALIDITY = 5000; +function serializeError(error) { + const value = `${error.toString()}\n${error.stack}`; + return { command: "error", value }; +} + export { FORMS_VERSION, + serializeError, USERACTIVATION_CALLBACKID, USERACTIVATION_MAXTIME_VALIDITY, VIEWER_TYPE, diff --git a/src/scripting_api/doc.js b/src/scripting_api/doc.js index e63566614..86da32249 100644 --- a/src/scripting_api/doc.js +++ b/src/scripting_api/doc.js @@ -16,6 +16,7 @@ import { createActionsMap } from "./common.js"; import { PDFObject } from "./pdf_object.js"; import { PrintParams } from "./print_params.js"; +import { serializeError } from "./app_utils.js"; import { ZoomType } from "./constants.js"; const DOC_EXTERNAL = false; @@ -126,20 +127,29 @@ class Doc extends PDFObject { } _dispatchDocEvent(name) { - if (name === "Open") { - this._disableSaving = true; - this._runActions("OpenAction"); - this._disableSaving = false; - } else if (name === "WillPrint") { - this._disablePrinting = true; - this._runActions(name); - this._disablePrinting = false; - } else if (name === "WillSave") { - this._disableSaving = true; - this._runActions(name); - this._disableSaving = false; - } else { - this._runActions(name); + switch (name) { + case "Open": + this._disableSaving = true; + this._runActions("OpenAction"); + this._disableSaving = false; + break; + case "WillPrint": + this._disablePrinting = true; + try { + this._runActions(name); + } catch (error) { + this._send(serializeError(error)); + } + this._send({ command: "WillPrintFinished" }); + this._disablePrinting = false; + break; + case "WillSave": + this._disableSaving = true; + this._runActions(name); + this._disableSaving = false; + break; + default: + this._runActions(name); } } diff --git a/src/scripting_api/initialization.js b/src/scripting_api/initialization.js index 7355d58c5..be941ed0c 100644 --- a/src/scripting_api/initialization.js +++ b/src/scripting_api/initialization.js @@ -34,6 +34,7 @@ import { Color } from "./color.js"; import { Console } from "./console.js"; import { Doc } from "./doc.js"; import { ProxyHandler } from "./proxy.js"; +import { serializeError } from "./app_utils.js"; import { Util } from "./util.js"; function initSandbox(params) { @@ -214,8 +215,7 @@ function initSandbox(params) { try { functions[name](args); } catch (error) { - const value = `${error.toString()}\n${error.stack}`; - send({ command: "error", value }); + send(serializeError(error)); } }; } diff --git a/web/pdf_scripting_manager.js b/web/pdf_scripting_manager.js index 459c7050d..3e7658e49 100644 --- a/web/pdf_scripting_manager.js +++ b/web/pdf_scripting_manager.js @@ -51,6 +51,8 @@ class PDFScriptingManager { #scripting = null; + #willPrintCapability = null; + /** * @param {PDFScriptingManagerOptions} options */ @@ -203,10 +205,23 @@ class PDFScriptingManager { } async dispatchWillPrint() { - return this.#scripting?.dispatchEventInSandbox({ - id: "doc", - name: "WillPrint", - }); + if (!this.#scripting) { + return; + } + await this.#willPrintCapability?.promise; + this.#willPrintCapability = new PromiseCapability(); + try { + await this.#scripting.dispatchEventInSandbox({ + id: "doc", + name: "WillPrint", + }); + } catch (ex) { + this.#willPrintCapability.resolve(); + this.#willPrintCapability = null; + throw ex; + } + + await this.#willPrintCapability.promise; } async dispatchDidPrint() { @@ -306,6 +321,10 @@ class PDFScriptingManager { pdfViewer.decreaseScale(); } break; + case "WillPrintFinished": + this.#willPrintCapability?.resolve(); + this.#willPrintCapability = null; + break; } return; } @@ -432,6 +451,9 @@ class PDFScriptingManager { await this.#scripting.destroySandbox(); } catch {} + this.#willPrintCapability?.reject(new Error("Scripting destroyed.")); + this.#willPrintCapability = null; + for (const [name, listener] of this._internalEvents) { this.#eventBus._off(name, listener); }