From dacf8bb0d1af9ace9d309ec132cae1147ede481f Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Fri, 28 Jun 2024 21:31:12 +0200 Subject: [PATCH] Take into account PageOpen and PageClose actions which are present in some fields --- src/scripting_api/doc.js | 42 +++++++++++++++++++--- test/integration/scripting_spec.mjs | 54 ++++++++++++++++++++++++++++ test/pdfs/.gitignore | 1 + test/pdfs/issue18305.pdf | Bin 0 -> 7999 bytes 4 files changed, 92 insertions(+), 5 deletions(-) create mode 100755 test/pdfs/issue18305.pdf diff --git a/src/scripting_api/doc.js b/src/scripting_api/doc.js index bbc4c4d9f..a9cbe90d8 100644 --- a/src/scripting_api/doc.js +++ b/src/scripting_api/doc.js @@ -96,10 +96,11 @@ class Doc extends PDFObject { this._zoom = data.zoom || 100; this._actions = createActionsMap(data.actions); this._globalEval = data.globalEval; - this._pageActions = new Map(); + this._pageActions = null; this._userActivation = false; this._disablePrinting = false; this._disableSaving = false; + this._otherPageActions = null; } _initActions() { @@ -155,16 +156,19 @@ class Doc extends PDFObject { _dispatchPageEvent(name, actions, pageNumber) { if (name === "PageOpen") { + this._pageActions ||= new Map(); if (!this._pageActions.has(pageNumber)) { this._pageActions.set(pageNumber, createActionsMap(actions)); } this._pageNum = pageNumber - 1; } - actions = this._pageActions.get(pageNumber)?.get(name); - if (actions) { - for (const action of actions) { - this._globalEval(action); + for (const acts of [this._pageActions, this._otherPageActions]) { + actions = acts?.get(pageNumber)?.get(name); + if (actions) { + for (const action of actions) { + this._globalEval(action); + } } } } @@ -182,6 +186,34 @@ class Doc extends PDFObject { this._fields.set(name, field); this._fieldNames.push(name); this._numFields++; + + // Fields on a page can have PageOpen/PageClose actions. + const po = field.obj._actions.get("PageOpen"); + const pc = field.obj._actions.get("PageClose"); + if (po || pc) { + this._otherPageActions ||= new Map(); + let actions = this._otherPageActions.get(field.obj._page + 1); + if (!actions) { + actions = new Map(); + this._otherPageActions.set(field.obj._page + 1, actions); + } + if (po) { + let poActions = actions.get("PageOpen"); + if (!poActions) { + poActions = []; + actions.set("PageOpen", poActions); + } + poActions.push(...po); + } + if (pc) { + let pcActions = actions.get("PageClose"); + if (!pcActions) { + pcActions = []; + actions.set("PageClose", pcActions); + } + pcActions.push(...pc); + } + } } _getDate(date) { diff --git a/test/integration/scripting_spec.mjs b/test/integration/scripting_spec.mjs index 50e2cfe96..ed71e1580 100644 --- a/test/integration/scripting_spec.mjs +++ b/test/integration/scripting_spec.mjs @@ -2456,4 +2456,58 @@ describe("Interaction", () => { ); }); }); + + describe("PageOpen and PageClose actions in fields", () => { + let pages; + let otherPages; + + beforeAll(async () => { + otherPages = await Promise.all( + global.integrationSessions.map(async session => + session.browser.newPage() + ) + ); + pages = await loadAndWait("issue18305.pdf", getSelector("7R")); + }); + + afterAll(async () => { + await closePages(pages); + await Promise.all(otherPages.map(page => page.close())); + }); + + it("must check that PageOpen/PageClose actions are correctly executed", async () => { + await Promise.all( + pages.map(async ([browserName, page], i) => { + await page.waitForFunction( + "window.PDFViewerApplication.scriptingReady === true" + ); + + const buttonSelector = `[data-annotation-id="25R"`; + await page.waitForSelector(buttonSelector, { + timeout: 0, + }); + + const inputSelector = getSelector("7R"); + let text = await page.$eval(inputSelector, el => el.value); + expect(text).withContext(`In ${browserName}`).toEqual(""); + + text = await actAndWaitForInput( + page, + inputSelector, + () => scrollIntoView(page, buttonSelector), + false + ); + expect(text).withContext(`In ${browserName}`).toEqual("PageOpen"); + + text = await actAndWaitForInput( + page, + inputSelector, + () => scrollIntoView(page, inputSelector), + false + ); + expect(text).withContext(`In ${browserName}`).toEqual("PageClose"); + }) + ); + }); + }); }); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 2c6cad459..b92b8e391 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -651,3 +651,4 @@ !pdfjs_wikipedia.pdf !bug1539074.pdf !bug1539074.1.pdf +!issue18305.pdf diff --git a/test/pdfs/issue18305.pdf b/test/pdfs/issue18305.pdf new file mode 100755 index 0000000000000000000000000000000000000000..fee93b6e1d45ab892592fbca0b83afa58c056766 GIT binary patch literal 7999 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 literal 0 HcmV?d00001