1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-22 16:18:08 +02:00

Improve the promise-caching in the PDFDocument.fieldObjects getter

After PR 18845 we're accessing this getter more, hence it seems like a good idea to ensure that the initial `formInfo` access is covered as well.
While unlikely to be a problem in practice, at least theoretically that data may not be available and the code in `fieldObjects` could thus currently be *unintentionally* invoked more than once.
This commit is contained in:
Jonas Jenwald 2024-10-08 12:15:04 +02:00
parent 81cf42df47
commit e3b5ed2e40

View file

@ -1871,49 +1871,52 @@ class PDFDocument {
}
get fieldObjects() {
if (!this.formInfo.hasFields) {
return shadow(this, "fieldObjects", Promise.resolve(null));
}
const promise = this.pdfManager
.ensureDoc("formInfo")
.then(async formInfo => {
if (!formInfo.hasFields) {
return null;
}
const promise = Promise.all([
this.pdfManager.ensureDoc("annotationGlobals"),
this.pdfManager.ensureCatalog("acroForm"),
]).then(async ([annotationGlobals, acroForm]) => {
if (!annotationGlobals) {
return null;
}
const [annotationGlobals, acroForm] = await Promise.all([
this.pdfManager.ensureDoc("annotationGlobals"),
this.pdfManager.ensureCatalog("acroForm"),
]);
if (!annotationGlobals) {
return null;
}
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,
orphanFields
);
}
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,
orphanFields
);
}
const allPromises = [];
for (const [name, promises] of fieldPromises) {
allPromises.push(
Promise.all(promises).then(fields => {
fields = fields.filter(field => !!field);
if (fields.length > 0) {
allFields[name] = fields;
}
})
);
}
const allPromises = [];
for (const [name, promises] of fieldPromises) {
allPromises.push(
Promise.all(promises).then(fields => {
fields = fields.filter(field => !!field);
if (fields.length > 0) {
allFields[name] = fields;
}
})
);
}
await Promise.all(allPromises);
return { allFields, orphanFields };
});
await Promise.all(allPromises);
return { allFields, orphanFields };
});
return shadow(this, "fieldObjects", promise);
}