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 b4de951e1..d8515d1c7 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -640,3 +640,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 000000000..18a5dbb9c Binary files /dev/null and b/test/pdfs/bug1889122.pdf differ 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();