Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix missing annotation parent in using the one from the Fields entry #18845

Merged
merged 1 commit into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class AnnotationFactory {
* @params {Object} annotationGlobals
* @param {Object} idFactory
* @param {boolean} [collectFields]
* @param {Object} [orphanFields]
* @param {Object} [pageRef]
* @returns {Promise} A promise that is resolved with an {Annotation}
* instance.
Expand All @@ -122,6 +123,7 @@ class AnnotationFactory {
annotationGlobals,
idFactory,
collectFields,
orphanFields,
calixteman marked this conversation as resolved.
Show resolved Hide resolved
pageRef
) {
const pageIndex = collectFields
Expand All @@ -134,6 +136,7 @@ class AnnotationFactory {
annotationGlobals,
idFactory,
collectFields,
orphanFields,
pageIndex,
pageRef,
]);
Expand All @@ -148,6 +151,7 @@ class AnnotationFactory {
annotationGlobals,
idFactory,
collectFields = false,
orphanFields = null,
pageIndex = null,
pageRef = null
) {
Expand All @@ -173,6 +177,7 @@ class AnnotationFactory {
id,
annotationGlobals,
collectFields,
orphanFields,
needAppearances:
!collectFields && acroForm.get("NeedAppearances") === true,
pageIndex,
Expand Down Expand Up @@ -623,7 +628,11 @@ function getTransformMatrix(rect, bbox, matrix) {

class Annotation {
constructor(params) {
const { dict, xref, annotationGlobals } = params;
const { dict, xref, annotationGlobals, ref, orphanFields } = params;
const parentRef = orphanFields?.get(ref);
if (parentRef) {
dict.set("Parent", parentRef);
}

this.setTitle(dict.get("T"));
this.setContents(dict.get("Contents"));
Expand Down Expand Up @@ -3172,6 +3181,11 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
}
}

if (!this.parent) {
// If there is no parent then we must set the value in the field.
dict.set("V", name);
}

dict.set("AS", name);
dict.set("M", `D:${getModificationDate()}`);
if (flags !== undefined) {
Expand Down
38 changes: 30 additions & 8 deletions src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -787,12 +787,16 @@ class Page {
if (annots.length === 0) {
return annots;
}
const annotationGlobals =
await this.pdfManager.ensureDoc("annotationGlobals");

const [annotationGlobals, fieldObjects] = await Promise.all([
this.pdfManager.ensureDoc("annotationGlobals"),
this.pdfManager.ensureDoc("fieldObjects"),
]);
if (!annotationGlobals) {
return [];
}

const orphanFields = fieldObjects?.orphanFields;
const annotationPromises = [];
for (const annotationRef of annots) {
annotationPromises.push(
Expand All @@ -802,6 +806,7 @@ class Page {
annotationGlobals,
this._localIdFactory,
/* collectFields */ false,
orphanFields,
this.ref
).catch(function (reason) {
warn(`_parsedAnnotations: "${reason}".`);
Expand Down Expand Up @@ -1776,10 +1781,12 @@ class PDFDocument {

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

Expand All @@ -1797,7 +1804,7 @@ class PDFDocument {
} else {
let obj = field;
while (true) {
obj = obj.getRaw("Parent");
obj = obj.getRaw("Parent") || parentRef;
if (obj instanceof Ref) {
if (visitedRefs.has(obj)) {
break;
Expand All @@ -1815,6 +1822,15 @@ class PDFDocument {
}
}

if (
parentRef &&
!field.has("Parent") &&
isName(field.get("Subtype"), "Widget")
) {
// We've a parent from the Fields array, but the field hasn't.
orphanFields.put(fieldRef, parentRef);
}

if (!promises.has(name)) {
promises.set(name, []);
}
Expand All @@ -1825,6 +1841,7 @@ class PDFDocument {
annotationGlobals,
/* idFactory = */ null,
/* collectFields */ true,
orphanFields,
/* pageRef */ null
)
.then(annotation => annotation?.getFieldObject())
Expand All @@ -1842,10 +1859,12 @@ class PDFDocument {
for (const kid of kids) {
await this.#collectFieldObjects(
name,
fieldRef,
kid,
promises,
annotationGlobals,
visitedRefs
visitedRefs,
orphanFields
);
}
}
Expand All @@ -1867,13 +1886,16 @@ class PDFDocument {
const visitedRefs = new RefSet();
const allFields = Object.create(null);
const fieldPromises = new Map();
const orphanFields = new RefSetCache();
for (const fieldRef of await acroForm.getAsync("Fields")) {
await this.#collectFieldObjects(
"",
null,
fieldRef,
fieldPromises,
annotationGlobals,
visitedRefs
visitedRefs,
orphanFields
);
}

Expand All @@ -1890,7 +1912,7 @@ class PDFDocument {
}

await Promise.all(allPromises);
return allFields;
return { allFields, orphanFields };
});

return shadow(this, "fieldObjects", promise);
Expand All @@ -1914,7 +1936,7 @@ class PDFDocument {
return true;
}
if (fieldObjects) {
return Object.values(fieldObjects).some(fieldObject =>
return Object.values(fieldObjects.allFields).some(fieldObject =>
fieldObject.some(object => object.actions !== null)
);
}
Expand Down
4 changes: 3 additions & 1 deletion src/core/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,9 @@ class WorkerMessageHandler {
});

handler.on("GetFieldObjects", function (data) {
return pdfManager.ensureDoc("fieldObjects");
return pdfManager
.ensureDoc("fieldObjects")
.then(fieldObjects => fieldObjects?.allFields || null);
});

handler.on("HasJSActions", function (data) {
Expand Down
1 change: 1 addition & 0 deletions test/pdfs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -673,3 +673,4 @@
!highlight_popup.pdf
!issue18072.pdf
!stamps.pdf
!issue15096.pdf
Binary file added test/pdfs/issue15096.pdf
Binary file not shown.
17 changes: 17 additions & 0 deletions test/test_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10667,5 +10667,22 @@
"popupRef": "44R"
}
}
},
{
"id": "issue15096",
"file": "pdfs/issue15096.pdf",
"md5": "5c3515177acd6e146d177adac802277d",
"rounds": 1,
"type": "eq",
"save": true,
"annotations": true,
"annotationStorage": {
"62R": {
"value": true
},
"66R": {
"value": false
}
}
}
]
2 changes: 1 addition & 1 deletion test/unit/document_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ describe("document", function () {

acroForm.set("Fields", [parentRef]);
pdfDocument = getDocument(acroForm, xref);
fields = await pdfDocument.fieldObjects;
fields = (await pdfDocument.fieldObjects).allFields;

for (const [name, objs] of Object.entries(fields)) {
fields[name] = objs.map(obj => obj.id);
Expand Down