Merge pull request #17271 from calixteman/maif

Get the field name from its parent when it doesn't have one when collecting fields (bug 1864136)
This commit is contained in:
calixteman 2023-11-13 15:57:42 +01:00 committed by GitHub
commit 787d092ecb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 118 additions and 4 deletions

View File

@ -1711,12 +1711,19 @@ 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;
@ -1724,6 +1731,25 @@ class PDFDocument {
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)) {
@ -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
);
}
}
}
@ -1769,6 +1801,7 @@ 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")) {
@ -1776,7 +1809,8 @@ class PDFDocument {
"",
fieldRef,
fieldPromises,
annotationGlobals
annotationGlobals,
visitedRefs
);
}

View File

@ -16,6 +16,7 @@
import {
clearInput,
closePages,
getAnnotationStorage,
getComputedStyleSelector,
getFirstSerialized,
getQuerySelector,
@ -24,6 +25,7 @@ import {
kbSelectAll,
loadAndWait,
scrollIntoView,
waitForEntryInStorage,
} from "./test_utils.mjs";
describe("Interaction", () => {
@ -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 },
});
})
);
});
});
});

View File

@ -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`);
@ -398,6 +420,7 @@ export {
clearInput,
closePages,
dragAndDropAnnotation,
getAnnotationStorage,
getComputedStyleSelector,
getEditorDimensions,
getEditors,
@ -427,6 +450,7 @@ export {
scrollIntoView,
serializeBitmapDimensions,
waitForAnnotationEditorLayer,
waitForEntryInStorage,
waitForEvent,
waitForSelectedEditor,
waitForSerialized,