Skip to content

Commit

Permalink
Merge pull request #17271 from calixteman/maif
Browse files Browse the repository at this point in the history
Get the field name from its parent when it doesn't have one when collecting fields (bug 1864136)
  • Loading branch information
calixteman authored Nov 13, 2023
2 parents 096c5fe + 09b4fe6 commit 787d092
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 4 deletions.
42 changes: 38 additions & 4 deletions src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -1711,19 +1711,45 @@ class PDFDocument {
: clearGlobalCaches();
}

async #collectFieldObjects(name, fieldRef, promises, annotationGlobals) {
async #collectFieldObjects(
name,
fieldRef,
promises,
annotationGlobals,
visitedRefs
) {
const { xref } = this;

if (!(fieldRef instanceof Ref)) {
if (!(fieldRef instanceof Ref) || visitedRefs.has(fieldRef)) {
return;
}
visitedRefs.put(fieldRef);
const field = await xref.fetchAsync(fieldRef);
if (!(field instanceof Dict)) {
return;
}
if (field.has("T")) {
const partName = stringToPDFString(await field.getAsync("T"));
name = name === "" ? partName : `${name}.${partName}`;
} else {
let obj = field;
while (true) {
obj = obj.getRaw("Parent");
if (obj instanceof Ref) {
if (visitedRefs.has(obj)) {
break;
}
obj = await xref.fetchAsync(obj);
}
if (!(obj instanceof Dict)) {
break;
}
if (obj.has("T")) {
const partName = stringToPDFString(await obj.getAsync("T"));
name = name === "" ? partName : `${name}.${partName}`;
break;
}
}
}

if (!promises.has(name)) {
Expand Down Expand Up @@ -1751,7 +1777,13 @@ class PDFDocument {
const kids = await field.getAsync("Kids");
if (Array.isArray(kids)) {
for (const kid of kids) {
await this.#collectFieldObjects(name, kid, promises, annotationGlobals);
await this.#collectFieldObjects(
name,
kid,
promises,
annotationGlobals,
visitedRefs
);
}
}
}
Expand All @@ -1769,14 +1801,16 @@ class PDFDocument {
return null;
}

const visitedRefs = new RefSet();
const allFields = Object.create(null);
const fieldPromises = new Map();
for (const fieldRef of await acroForm.getAsync("Fields")) {
await this.#collectFieldObjects(
"",
fieldRef,
fieldPromises,
annotationGlobals
annotationGlobals,
visitedRefs
);
}

Expand Down
56 changes: 56 additions & 0 deletions test/integration/scripting_spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import {
clearInput,
closePages,
getAnnotationStorage,
getComputedStyleSelector,
getFirstSerialized,
getQuerySelector,
Expand All @@ -24,6 +25,7 @@ import {
kbSelectAll,
loadAndWait,
scrollIntoView,
waitForEntryInStorage,
} from "./test_utils.mjs";

describe("Interaction", () => {
Expand Down Expand Up @@ -2225,4 +2227,58 @@ describe("Interaction", () => {
);
});
});

describe("Radio button without T value", () => {
let pages;
let otherPages;

beforeAll(async () => {
otherPages = await Promise.all(
global.integrationSessions.map(async session =>
session.browser.newPage()
)
);
pages = await loadAndWait("bug1860602.pdf", getSelector("22R"));
});

afterAll(async () => {
await closePages(pages);
await Promise.all(otherPages.map(page => page.close()));
});

it("must check that only one radio is selected", async () => {
await Promise.all(
pages.map(async ([browserName, page], i) => {
await page.waitForFunction(
"window.PDFViewerApplication.scriptingReady === true"
);
await scrollIntoView(page, getSelector("22R"));

await page.click(getSelector("25R"));
await waitForEntryInStorage(page, "25R", { value: true });

let storage = await getAnnotationStorage(page);
expect(storage)
.withContext(`In ${browserName}`)
.toEqual({
"22R": { value: false },
"25R": { value: true },
"28R": { value: false },
});

await page.click(getSelector("22R"));
await waitForEntryInStorage(page, "22R", { value: true });

storage = await getAnnotationStorage(page);
expect(storage)
.withContext(`In ${browserName}`)
.toEqual({
"22R": { value: true },
"25R": { value: false },
"28R": { value: false },
});
})
);
});
});
});
24 changes: 24 additions & 0 deletions test/integration/test_utils.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,28 @@ async function getFirstSerialized(page, filter = undefined) {
return (await getSerialized(page, filter))[0];
}

function getAnnotationStorage(page) {
return page.evaluate(() =>
Object.fromEntries(
window.PDFViewerApplication.pdfDocument.annotationStorage.serializable.map?.entries() ||
[]
)
);
}

function waitForEntryInStorage(page, key, value) {
return page.waitForFunction(
(k, v) => {
const { map } =
window.PDFViewerApplication.pdfDocument.annotationStorage.serializable;
return map && JSON.stringify(map.get(k)) === v;
},
{},
key,
JSON.stringify(value)
);
}

function getEditors(page, kind) {
return page.evaluate(aKind => {
const elements = document.querySelectorAll(`.${aKind}Editor`);
Expand Down Expand Up @@ -398,6 +420,7 @@ export {
clearInput,
closePages,
dragAndDropAnnotation,
getAnnotationStorage,
getComputedStyleSelector,
getEditorDimensions,
getEditors,
Expand Down Expand Up @@ -427,6 +450,7 @@ export {
scrollIntoView,
serializeBitmapDimensions,
waitForAnnotationEditorLayer,
waitForEntryInStorage,
waitForEvent,
waitForSelectedEditor,
waitForSerialized,
Expand Down

0 comments on commit 787d092

Please sign in to comment.