From 922d57631bbaabfed767ba64fb63ebb89d9811ea Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 13 Jul 2026 11:20:15 +0200 Subject: [PATCH] Rebuild missing AcroForm fields --- src/core/editor/pdf_editor.js | 6 +++--- test/unit/api_spec.js | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/core/editor/pdf_editor.js b/src/core/editor/pdf_editor.js index 1cfff4200..49f10c79c 100644 --- a/src/core/editor/pdf_editor.js +++ b/src/core/editor/pdf_editor.js @@ -1209,7 +1209,7 @@ class PDFEditor { annotationDict.get("FT"), "Sig" ); - const parentRef = annotationDict.get("Parent") || null; + const parentRef = annotationDict.getRaw("Parent") || null; // We remove the parent to avoid visiting it when cloning the // annotation. // It'll be fixed later in #mergeAcroForms when merging the @@ -2109,14 +2109,14 @@ class PDFEditor { * If the document has some fields but no Fields entry in the AcroForm, we * need to fix that by creating a Fields entry with the oldest parent field * for each field. - * @param {Map} fieldToParent + * @param {RefSetCache} fieldToParent * @param {XRef} xref * @returns {Array} */ #fixFields(fieldToParent, xref) { const newFields = []; const processed = new RefSet(); - for (const [fieldRef, parentRef] of fieldToParent) { + for (const [fieldRef, parentRef] of fieldToParent.items()) { if (!parentRef) { newFields.push(fieldRef); continue; diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index ce44fd7f3..03b5b9794 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -7501,6 +7501,32 @@ small scripts as well as for`); return fontIndex < 0 ? null : operatorList.argsArray[fontIndex][0]; }; + it("rebuilds a missing AcroForm Fields array", async function () { + const data = assemblePdf([ + "1 0 obj\n<< /Type /Catalog /Pages 2 0 R /AcroForm 6 0 R >>\nendobj\n", + "2 0 obj\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\nendobj\n", + "3 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 100 100] " + + "/Annots [4 0 R] >>\nendobj\n", + "4 0 obj\n<< /Type /Annot /Subtype /Widget /Rect [0 0 20 10] " + + "/Parent 5 0 R >>\nendobj\n", + "5 0 obj\n<< /FT /Tx /T (group) /Kids [4 0 R] >>\nendobj\n", + "6 0 obj\n<< /DA (/Helv 10 Tf) >>\nendobj\n", + ]); + + let loadingTask = getDocument({ data }); + let pdfDoc = await loadingTask.promise; + const extracted = await pdfDoc.extractPages([{ document: null }]); + expect(extracted).not.toBeNull(); + await loadingTask.destroy(); + + loadingTask = getDocument({ data: extracted }); + pdfDoc = await loadingTask.promise; + expect(Object.keys(await pdfDoc.getFieldObjects())).toEqual(["group"]); + const annotations = await (await pdfDoc.getPage(1)).getAnnotations(); + expect(annotations[0].fieldName).toEqual("group"); + await loadingTask.destroy(); + }); + it("extract page 2 and check AcroForm Fields T entries", async function () { let loadingTask = getDocument( buildGetDocumentParams("form_two_pages.pdf")