From 2a337082c0f52143ba13d8c7ffc164930f94f03f Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Fri, 29 Nov 2024 17:28:21 +0100 Subject: [PATCH] Build date consistently (in term of tz) when executing some embedded JS (bug 1934157) The date was create in UTC+0 and then amended in using set-Month/Date which take into account the user timezone. With this patch we build all the date in the user timezone. --- src/scripting_api/util.js | 50 ++++++++++++++++++---------- test/integration/scripting_spec.mjs | 38 +++++++++++++++++++++ test/pdfs/.gitignore | 1 + test/pdfs/bug1934157.pdf | Bin 0 -> 7065 bytes test/unit/scripting_spec.js | 9 ++--- 5 files changed, 76 insertions(+), 22 deletions(-) create mode 100755 test/pdfs/bug1934157.pdf diff --git a/src/scripting_api/util.js b/src/scripting_api/util.js index cd2f2a6b4..66f014c50 100644 --- a/src/scripting_api/util.js +++ b/src/scripting_api/util.js @@ -349,53 +349,53 @@ class Util extends PDFObject { this.#dateActionsCache.set(cFormat, actions); cFormat.replaceAll( /(d+)|(m+)|(y+)|(H+)|(M+)|(s+)/g, - function (match, d, m, y, H, M, s) { + function (_match, d, m, y, H, M, s) { if (d) { - actions.push((n, date) => { + actions.push((n, data) => { if (n >= 1 && n <= 31) { - date.setDate(n); + data.day = n; return true; } return false; }); } else if (m) { - actions.push((n, date) => { + actions.push((n, data) => { if (n >= 1 && n <= 12) { - date.setMonth(n - 1); + data.month = n - 1; return true; } return false; }); } else if (y) { - actions.push((n, date) => { + actions.push((n, data) => { if (n < 50) { n += 2000; } else if (n < 100) { n += 1900; } - date.setYear(n); + data.year = n; return true; }); } else if (H) { - actions.push((n, date) => { + actions.push((n, data) => { if (n >= 0 && n <= 23) { - date.setHours(n); + data.hours = n; return true; } return false; }); } else if (M) { - actions.push((n, date) => { + actions.push((n, data) => { if (n >= 0 && n <= 59) { - date.setMinutes(n); + data.minutes = n; return true; } return false; }); } else if (s) { - actions.push((n, date) => { + actions.push((n, data) => { if (n >= 0 && n <= 59) { - date.setSeconds(n); + data.seconds = n; return true; } return false; @@ -409,10 +409,17 @@ class Util extends PDFObject { const number = /\d+/g; let i = 0; let array; - const date = new Date(0); + const data = { + year: new Date().getFullYear(), + month: 0, + day: 1, + hours: 12, + minutes: 0, + seconds: 0, + }; while ((array = number.exec(cDate)) !== null) { if (i < actions.length) { - if (!actions[i++](parseInt(array[0]), date)) { + if (!actions[i++](parseInt(array[0]), data)) { return null; } } else { @@ -424,7 +431,14 @@ class Util extends PDFObject { return null; } - return date; + return new Date( + data.year, + data.month, + data.day, + data.hours, + data.minutes, + data.seconds + ); } scand(cFormat, cDate) { @@ -605,10 +619,10 @@ class Util extends PDFObject { } const data = { - year: 2000, + year: new Date().getFullYear(), month: 0, day: 1, - hours: 0, + hours: 12, minutes: 0, seconds: 0, am: null, diff --git a/test/integration/scripting_spec.mjs b/test/integration/scripting_spec.mjs index 1228e4ff1..0a157479b 100644 --- a/test/integration/scripting_spec.mjs +++ b/test/integration/scripting_spec.mjs @@ -2522,4 +2522,42 @@ describe("Interaction", () => { ); }); }); + + describe("Date creation must be timezone consistent", () => { + let pages; + + beforeAll(async () => { + pages = await loadAndWait("bug1934157.pdf", "[data-annotation-id='24R']"); + }); + + afterAll(async () => { + await closePages(pages); + }); + + it("must check that date entered by the user is consistent", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + if (browserName === "firefox") { + // Skip the test for Firefox as it doesn't support the timezone + // feature yet with BiDi. + // See https://github.com/puppeteer/puppeteer/issues/13344. + // TODO: Remove this check once the issue is fixed. + return; + } + + await waitForScripting(page); + + await page.emulateTimezone("Pacific/Honolulu"); + + const expectedDate = "02/01/2000"; + await page.type(getSelector("24R"), expectedDate); + await page.click(getSelector("25R")); + await waitForSandboxTrip(page); + + const date = await page.$eval(getSelector("24R"), el => el.value); + expect(date).withContext(`In ${browserName}`).toEqual(expectedDate); + }) + ); + }); + }); }); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 89657327d..9419dafdc 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -683,3 +683,4 @@ !issue18956.pdf !issue19083.pdf !issue19120.pdf +!bug1934157.pdf diff --git a/test/pdfs/bug1934157.pdf b/test/pdfs/bug1934157.pdf new file mode 100755 index 0000000000000000000000000000000000000000..f0feacbccbff2a943b1b79d62557af94c4b9d510 GIT binary patch literal 7065 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 LgQEQQlb!zn^mEa6 literal 0 HcmV?d00001 diff --git a/test/unit/scripting_spec.js b/test/unit/scripting_spec.js index 94ed4aa7f..9ce2699d4 100644 --- a/test/unit/scripting_spec.js +++ b/test/unit/scripting_spec.js @@ -245,10 +245,10 @@ describe("Scripting", function () { expect(new Date(value)).toEqual(date); value = await myeval(`util.scand("mmddyyyy", "07/15/2007").toString()`); - expect(new Date(value)).toEqual(new Date("07/15/2007")); + expect(new Date(value)).toEqual(new Date("07/15/2007 12:00:00")); value = await myeval(`util.scand("mmddyyyy", "07a15b2007").toString()`); - expect(new Date(value)).toEqual(new Date("07/15/2007")); + expect(new Date(value)).toEqual(new Date("07/15/2007 12:00:00")); }); }); @@ -630,8 +630,9 @@ describe("Scripting", function () { ); }; - await check("05", "dd", "2000/01/05"); - await check("12", "mm", "2000/12/01"); + const year = new Date().getFullYear(); + await check("05", "dd", `${year}/01/05`); + await check("12", "mm", `${year}/12/01`); await check("2022", "yyyy", "2022/01/01"); await check("a1$9bbbb21", "dd/mm/yyyy", "2021/09/01"); await check("1/2/2024", "dd/mm/yyyy", "2024/02/01");