From b643c0fcfbd176810bac8061f506d6e0c179ab6a Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Wed, 3 Apr 2024 22:24:17 +0200 Subject: [PATCH] Use the string value of the field when calling the Format callback (bug 1889122) --- src/scripting_api/event.js | 14 +++++++--- test/integration/scripting_spec.mjs | 38 ++++++++++++++++++++++++++++ test/integration/test_utils.mjs | 11 ++++++++ test/pdfs/.gitignore | 1 + test/pdfs/bug1889122.pdf | Bin 0 -> 6498 bytes web/pdf_scripting_manager.js | 24 ++++++++++++++++++ 6 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 test/pdfs/bug1889122.pdf diff --git a/src/scripting_api/event.js b/src/scripting_api/event.js index c3f73b263..2df21a923 100644 --- a/src/scripting_api/event.js +++ b/src/scripting_api/event.js @@ -81,6 +81,15 @@ class EventDispatcher { } dispatch(baseEvent) { + if ( + typeof PDFJSDev !== "undefined" && + PDFJSDev.test("TESTING") && + baseEvent.name === "sandboxtripbegin" + ) { + this._externalCall("send", [{ command: "sandboxTripEnd" }]); + return; + } + const id = baseEvent.id; if (!(id in this._objects)) { let event; @@ -233,7 +242,7 @@ class EventDispatcher { // Run format actions if any for all the fields. const event = (globalThis.event = new Event({})); for (const source of Object.values(this._objects)) { - event.value = source.obj.value; + event.value = source.obj._getValue(); this.runActions(source, source, event, "Format"); } } @@ -245,8 +254,7 @@ class EventDispatcher { this.runCalculate(source, event); - const savedValue = source.obj._getValue(); - event.value = source.obj.value; + const savedValue = (event.value = source.obj._getValue()); let formattedValue = null; if (this.runActions(source, source, event, "Format")) { diff --git a/test/integration/scripting_spec.mjs b/test/integration/scripting_spec.mjs index 5f29be1ef..aef75c74e 100644 --- a/test/integration/scripting_spec.mjs +++ b/test/integration/scripting_spec.mjs @@ -27,6 +27,7 @@ import { loadAndWait, scrollIntoView, waitForEntryInStorage, + waitForSandboxTrip, waitForTimeout, } from "./test_utils.mjs"; @@ -2367,4 +2368,41 @@ describe("Interaction", () => { ); }); }); + + describe("Textfield with a zip code starting with 0", () => { + let pages; + let otherPages; + + beforeAll(async () => { + otherPages = await Promise.all( + global.integrationSessions.map(async session => + session.browser.newPage() + ) + ); + pages = await loadAndWait("bug1889122.pdf", getSelector("24R")); + }); + + afterAll(async () => { + await closePages(pages); + await Promise.all(otherPages.map(page => page.close())); + }); + + it("must check the zip code is correctly formatted", async () => { + await Promise.all( + pages.map(async ([browserName, page], i) => { + await page.waitForFunction( + "window.PDFViewerApplication.scriptingReady === true" + ); + + await page.click(getSelector("24R")); + await page.type(getSelector("24R"), "01234", { delay: 10 }); + await page.keyboard.press("Tab"); + await waitForSandboxTrip(page); + + const text = await page.$eval(getSelector("24R"), el => el.value); + expect(text).withContext(`In ${browserName}`).toEqual("01234"); + }) + ); + }); + }); }); diff --git a/test/integration/test_utils.mjs b/test/integration/test_utils.mjs index 34718bb42..cf1f48fdc 100644 --- a/test/integration/test_utils.mjs +++ b/test/integration/test_utils.mjs @@ -85,6 +85,16 @@ function closePages(pages) { ); } +async function waitForSandboxTrip(page) { + const handle = await page.evaluateHandle(() => [ + new Promise(resolve => { + window.addEventListener("sandboxtripend", resolve, { once: true }); + window.PDFViewerApplication.pdfScriptingManager.sandboxTrip(); + }), + ]); + await awaitPromise(handle); +} + function waitForTimeout(milliseconds) { /** * Wait for the given number of milliseconds. @@ -583,6 +593,7 @@ export { waitForAnnotationEditorLayer, waitForEntryInStorage, waitForEvent, + waitForSandboxTrip, waitForSelectedEditor, waitForSerialized, waitForStorageEntries, diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index b3649ac87..03c815040 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -639,3 +639,4 @@ !issue17808.pdf !issue17871_bottom_right.pdf !issue17871_top_right.pdf +!bug1889122.pdf diff --git a/test/pdfs/bug1889122.pdf b/test/pdfs/bug1889122.pdf new file mode 100644 index 0000000000000000000000000000000000000000..18a5dbb9c256c4429555064ee041669e6052b2d2 GIT binary patch literal 6498 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 literal 0 HcmV?d00001 diff --git a/web/pdf_scripting_manager.js b/web/pdf_scripting_manager.js index f0c8ce91e..3dfb7c130 100644 --- a/web/pdf_scripting_manager.js +++ b/web/pdf_scripting_manager.js @@ -58,6 +58,19 @@ class PDFScriptingManager { this.#eventBus = eventBus; this.#externalServices = externalServices; this.#docProperties = docProperties; + + if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) { + Object.defineProperty(this, "sandboxTrip", { + value: () => + setTimeout( + () => + this.#scripting?.dispatchEventInSandbox({ + name: "sandboxtripbegin", + }), + 0 + ), + }); + } } setViewer(pdfViewer) { @@ -258,6 +271,17 @@ class PDFScriptingManager { const { id, siblings, command, value } = detail; if (!id) { + if ( + typeof PDFJSDev !== "undefined" && + PDFJSDev.test("TESTING") && + command === "sandboxTripEnd" + ) { + window.setTimeout(() => { + window.dispatchEvent(new CustomEvent("sandboxtripend")); + }, 0); + return; + } + switch (command) { case "clear": console.clear();