1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-24 09:08:07 +02:00

[JS] Fix few bugs present in the pdf for issue #14862

- since resetForm function reset a field value a calculateNow is consequently triggered.
  But the calculate callback can itself call resetForm, hence an infinite recursive loop.
  So basically, prevent calculeNow to be triggered by itself.
- in Firefox, the letters entered in some fields were duplicated: "AaBb" instead of "AB".
  It was mainly because beforeInput was triggering a Keystroke which was itself triggering
  an input value update and then the input event was triggered.
  So in order to avoid that, beforeInput calls preventDefault and then it's up to the JS to
  handle the event.
- fields have a property valueAsString which returns the value as a string. In the
  implementation it was wrongly used to store the formatted value of a field (2€ when the user
  entered 2). So this patch implements correctly valueAsString.
- non-rendered fields can be updated in using JS but when they're, they must take some properties
  in the annotationStorage. It was implemented for field values, but it wasn't for
  display, colors, ...
- it fixes #14862 and #14705.
This commit is contained in:
Calixte Denizet 2022-05-02 19:28:00 +02:00
parent 85b7e60425
commit 094ff38da0
14 changed files with 558 additions and 205 deletions

View file

@ -237,7 +237,7 @@ describe("Interaction", () => {
await page.click("[data-annotation-id='402R']");
await Promise.all(
["16", "22", "19", "05", "27"].map(id =>
["16", "22", "19", "05"].map(id =>
page.waitForFunction(
`document.querySelector("#\\\\34 ${id}R").value === ""`
)
@ -256,11 +256,14 @@ describe("Interaction", () => {
text = await page.$eval("#\\34 05R", el => el.value);
expect(text).toEqual("");
const sum = await page.$eval("#\\34 27R", el => el.value);
expect(sum).toEqual("");
checked = await page.$eval("#\\34 49R", el => el.checked);
expect(checked).toEqual(false);
const visibility = await page.$eval(
"#\\34 27R",
el => getComputedStyle(el).visibility
);
expect(visibility).toEqual("hidden");
})
);
});
@ -1137,4 +1140,166 @@ describe("Interaction", () => {
);
});
});
describe("in issue14862.pdf", () => {
let pages;
beforeAll(async () => {
pages = await loadAndWait("issue14862.pdf", "#\\32 7R");
pages.map(async ([, page]) => {
page.on("dialog", async dialog => {
await dialog.dismiss();
});
});
});
afterAll(async () => {
await closePages(pages);
});
it("must convert input in uppercase", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await page.waitForFunction(
"window.PDFViewerApplication.scriptingReady === true"
);
await page.type("#\\32 7R", "Hello", { delay: 100 });
await page.waitForFunction(
`document.querySelector("#\\\\32 7R").value !== "Hello"`
);
let text = await page.$eval("#\\32 7R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("HELLO");
await page.type("#\\32 7R", " world", { delay: 100 });
await page.waitForFunction(
`document.querySelector("#\\\\32 7R").value !== "HELLO world"`
);
text = await page.$eval("#\\32 7R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("HELLO WORLD");
await page.keyboard.press("Backspace");
await page.keyboard.press("Backspace");
await page.waitForFunction(
`document.querySelector("#\\\\32 7R").value !== "HELLO WORLD"`
);
text = await page.$eval("#\\32 7R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("HELLO WOR");
await page.type("#\\32 7R", "12.dL", { delay: 100 });
await page.waitForFunction(
`document.querySelector("#\\\\32 7R").value !== "HELLO WOR"`
);
text = await page.$eval("#\\32 7R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("HELLO WORDL");
await page.type("#\\32 7R", " ", { delay: 100 });
await page.keyboard.down("Control");
await page.keyboard.press("Backspace");
await page.keyboard.up("Control");
await page.waitForFunction(
`document.querySelector("#\\\\32 7R").value !== "HELLO WORDL "`
);
text = await page.$eval("#\\32 7R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("HELLO ");
await page.$eval("#\\32 7R", el => {
// Select LL
el.selectionStart = 2;
el.selectionEnd = 4;
});
await page.keyboard.press("a");
text = await page.$eval("#\\32 7R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("HEAO ");
})
);
});
it("must check that an infinite loop is not triggered", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await page.waitForFunction(
"window.PDFViewerApplication.scriptingReady === true"
);
await page.type("#\\32 8R", "Hello", { delay: 100 });
await page.waitForFunction(
`document.querySelector("#\\\\32 8R").value !== "123"`
);
let text = await page.$eval("#\\32 8R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("Hello123");
// The action will trigger a calculateNow which itself
// will trigger a resetForm (inducing a calculateNow) and a
// calculateNow.
await page.click("[data-annotation-id='31R']");
await page.waitForFunction(
`document.querySelector("#\\\\32 8R").value !== "Hello123"`
);
// Without preventing against infinite loop the field is empty.
text = await page.$eval("#\\32 8R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("123");
})
);
});
});
describe("in issue14705.pdf", () => {
let pages;
beforeAll(async () => {
pages = await loadAndWait("issue14705.pdf", "#\\32 9R");
pages.map(async ([, page]) => {
page.on("dialog", async dialog => {
await dialog.dismiss();
});
});
});
afterAll(async () => {
await closePages(pages);
});
it("must check that field value is correctly updated", async () => {
await Promise.all(
pages.map(async ([browserName, page]) => {
await page.waitForFunction(
"window.PDFViewerApplication.scriptingReady === true"
);
await page.type("#\\32 9R", "Hello World", { delay: 100 });
await page.click("#\\32 7R");
await page.waitForFunction(
`document.querySelector("#\\\\32 9R").value !== "Hello World"`
);
let text = await page.$eval("#\\32 9R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("checked");
await page.click("#\\32 7R");
await page.waitForFunction(
`document.querySelector("#\\\\32 9R").value !== "checked"`
);
text = await page.$eval("#\\32 9R", el => el.value);
expect(text).withContext(`In ${browserName}`).toEqual("unchecked");
})
);
});
});
});

View file

@ -520,3 +520,5 @@
!issue14502.pdf
!issue13211.pdf
!issue14627.pdf
!issue14862.pdf
!issue14705.pdf

BIN
test/pdfs/issue14705.pdf Normal file

Binary file not shown.

BIN
test/pdfs/issue14862.pdf Executable file

Binary file not shown.

View file

@ -1320,7 +1320,7 @@ describe("api", function () {
{
id: "25R",
value: "",
defaultValue: null,
defaultValue: "",
multiline: false,
password: false,
charLimit: null,

View file

@ -89,7 +89,7 @@ describe("Scripting", function () {
return s;
}
const number = 123;
const expected = (((number - 1) * number) / 2).toString();
const expected = ((number - 1) * number) / 2;
const refId = getId();
const data = {
@ -120,7 +120,8 @@ describe("Scripting", function () {
expect(send_queue.has(refId)).toEqual(true);
expect(send_queue.get(refId)).toEqual({
id: refId,
valueAsString: expected,
value: expected,
formattedValue: null,
});
});
});
@ -406,6 +407,7 @@ describe("Scripting", function () {
expect(send_queue.get(refId)).toEqual({
id: refId,
value: "hella",
selRange: [5, 5],
});
});
@ -478,7 +480,7 @@ describe("Scripting", function () {
expect(send_queue.get(refId1)).toEqual({
id: refId1,
value: "world",
valueAsString: "world",
formattedValue: null,
});
});
});
@ -799,7 +801,7 @@ describe("Scripting", function () {
expect(send_queue.get(refId)).toEqual({
id: refId,
value: "123456.789",
valueAsString: "123456.789",
formattedValue: null,
});
});
@ -978,7 +980,7 @@ describe("Scripting", function () {
expect(send_queue.get(refId)).toEqual({
id: refId,
value: "321",
valueAsString: "321",
formattedValue: null,
});
});
@ -1076,7 +1078,7 @@ describe("Scripting", function () {
expect(send_queue.get(refIds[3])).toEqual({
id: refIds[3],
value: 1,
valueAsString: "1",
formattedValue: null,
});
await sandbox.dispatchEventInSandbox({
@ -1089,7 +1091,7 @@ describe("Scripting", function () {
expect(send_queue.get(refIds[3])).toEqual({
id: refIds[3],
value: 3,
valueAsString: "3",
formattedValue: null,
});
await sandbox.dispatchEventInSandbox({
@ -1102,7 +1104,7 @@ describe("Scripting", function () {
expect(send_queue.get(refIds[3])).toEqual({
id: refIds[3],
value: 6,
valueAsString: "6",
formattedValue: null,
});
});
});
@ -1137,7 +1139,8 @@ describe("Scripting", function () {
selStart: 0,
selEnd: 0,
});
expect(send_queue.has(refId)).toEqual(false);
expect(send_queue.has(refId)).toEqual(true);
send_queue.delete(refId);
await sandbox.dispatchEventInSandbox({
id: refId,
@ -1148,7 +1151,8 @@ describe("Scripting", function () {
selStart: 1,
selEnd: 1,
});
expect(send_queue.has(refId)).toEqual(false);
expect(send_queue.has(refId)).toEqual(true);
send_queue.delete(refId);
await sandbox.dispatchEventInSandbox({
id: refId,
@ -1159,7 +1163,8 @@ describe("Scripting", function () {
selStart: 2,
selEnd: 2,
});
expect(send_queue.has(refId)).toEqual(false);
expect(send_queue.has(refId)).toEqual(true);
send_queue.delete(refId);
await sandbox.dispatchEventInSandbox({
id: refId,
@ -1187,7 +1192,8 @@ describe("Scripting", function () {
selStart: 3,
selEnd: 3,
});
expect(send_queue.has(refId)).toEqual(false);
expect(send_queue.has(refId)).toEqual(true);
send_queue.delete(refId);
await sandbox.dispatchEventInSandbox({
id: refId,
@ -1200,7 +1206,8 @@ describe("Scripting", function () {
expect(send_queue.has(refId)).toEqual(true);
expect(send_queue.get(refId)).toEqual({
id: refId,
valueAsString: "3F?0",
value: "3F?0",
formattedValue: null,
});
});
});
@ -1242,7 +1249,8 @@ describe("Scripting", function () {
selStart: i,
selEnd: i,
});
expect(send_queue.has(refId)).toEqual(false);
expect(send_queue.has(refId)).toEqual(true);
send_queue.delete(refId);
value += change;
}
@ -1301,7 +1309,8 @@ describe("Scripting", function () {
selStart: i,
selEnd: i,
});
expect(send_queue.has(refId)).toEqual(false);
expect(send_queue.has(refId)).toEqual(true);
send_queue.delete(refId);
value += change;
}
@ -1360,7 +1369,8 @@ describe("Scripting", function () {
selStart: i,
selEnd: i,
});
expect(send_queue.has(refId)).toEqual(false);
expect(send_queue.has(refId)).toEqual(true);
send_queue.delete(refId);
value += change;
}