Merge pull request #19674 from Snuffleupagus/core-document-more-async

Introduce more `async` code in the `src/core/document.js` file
This commit is contained in:
Jonas Jenwald 2025-03-17 21:40:16 +01:00 committed by GitHub
commit 00e3a4d87a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -251,20 +251,20 @@ class Page {
/** /**
* @returns {Promise<BaseStream>} * @returns {Promise<BaseStream>}
*/ */
getContentStream() { async getContentStream() {
return this.pdfManager.ensure(this, "content").then(content => { const content = await this.pdfManager.ensure(this, "content");
if (content instanceof BaseStream) {
return content; if (content instanceof BaseStream) {
} return content;
if (Array.isArray(content)) { }
return new StreamsSequenceStream( if (Array.isArray(content)) {
content, return new StreamsSequenceStream(
this._onSubStreamError.bind(this) content,
); this._onSubStreamError.bind(this)
} );
// Replace non-existent page content with empty content. }
return new NullStream(); // Replace non-existent page content with empty content.
}); return new NullStream();
} }
get xfaData() { get xfaData() {
@ -375,7 +375,7 @@ class Page {
} }
} }
save(handler, task, annotationStorage, changes) { async save(handler, task, annotationStorage, changes) {
const partialEvaluator = new PartialEvaluator({ const partialEvaluator = new PartialEvaluator({
xref: this.xref, xref: this.xref,
handler, handler,
@ -392,37 +392,34 @@ class Page {
// Fetch the page's annotations and save the content // Fetch the page's annotations and save the content
// in case of interactive form fields. // in case of interactive form fields.
return this._parsedAnnotations.then(function (annotations) { const annotations = await this._parsedAnnotations;
const promises = [];
for (const annotation of annotations) {
promises.push(
annotation
.save(partialEvaluator, task, annotationStorage, changes)
.catch(function (reason) {
warn(
"save - ignoring annotation data during " +
`"${task.name}" task: "${reason}".`
);
return null;
})
);
}
return Promise.all(promises); const promises = [];
}); for (const annotation of annotations) {
promises.push(
annotation
.save(partialEvaluator, task, annotationStorage, changes)
.catch(function (reason) {
warn(
"save - ignoring annotation data during " +
`"${task.name}" task: "${reason}".`
);
return null;
})
);
}
return Promise.all(promises);
} }
loadResources(keys) { async loadResources(keys) {
// TODO: add async `_getInheritableProperty` and remove this. // TODO: add async `_getInheritableProperty` and remove this.
this.resourcesPromise ||= this.pdfManager.ensure(this, "resources"); await (this.resourcesPromise ??= this.pdfManager.ensure(this, "resources"));
return this.resourcesPromise.then(() => { const objectLoader = new ObjectLoader(this.resources, keys, this.xref);
const objectLoader = new ObjectLoader(this.resources, keys, this.xref); await objectLoader.load();
return objectLoader.load();
});
} }
getOperatorList({ async getOperatorList({
handler, handler,
sink, sink,
task, task,
@ -527,7 +524,7 @@ class Page {
const pageListPromise = Promise.all([ const pageListPromise = Promise.all([
contentStreamPromise, contentStreamPromise,
resourcesPromise, resourcesPromise,
]).then(([contentStream]) => { ]).then(async ([contentStream]) => {
const opList = new OperatorList(intent, sink); const opList = new OperatorList(intent, sink);
handler.send("StartRenderPage", { handler.send("StartRenderPage", {
@ -539,109 +536,102 @@ class Page {
cacheKey, cacheKey,
}); });
return partialEvaluator await partialEvaluator.getOperatorList({
.getOperatorList({ stream: contentStream,
stream: contentStream, task,
task, resources: this.resources,
resources: this.resources, operatorList: opList,
operatorList: opList, });
}) return opList;
.then(() => opList);
}); });
// Fetch the page's annotations and add their operator lists to the // Fetch the page's annotations and add their operator lists to the
// page's operator list to render them. // page's operator list to render them.
return Promise.all([ // eslint-disable-next-line prefer-const
let [pageOpList, annotations, newAnnotations] = await Promise.all([
pageListPromise, pageListPromise,
this._parsedAnnotations, this._parsedAnnotations,
newAnnotationsPromise, newAnnotationsPromise,
]).then(function ([pageOpList, annotations, newAnnotations]) { ]);
if (newAnnotations) {
// Some annotations can already exist (if it has the refToReplace if (newAnnotations) {
// property). In this case, we replace the old annotation by the new // Some annotations can already exist (if it has the refToReplace
// one. // property). In this case, we replace the old annotation by the new one.
annotations = annotations.filter( annotations = annotations.filter(
a => !(a.ref && deletedAnnotations.has(a.ref)) a => !(a.ref && deletedAnnotations.has(a.ref))
); );
for (let i = 0, ii = newAnnotations.length; i < ii; i++) { for (let i = 0, ii = newAnnotations.length; i < ii; i++) {
const newAnnotation = newAnnotations[i]; const newAnnotation = newAnnotations[i];
if (newAnnotation.refToReplace) { if (newAnnotation.refToReplace) {
const j = annotations.findIndex( const j = annotations.findIndex(
a => a.ref && isRefsEqual(a.ref, newAnnotation.refToReplace) a => a.ref && isRefsEqual(a.ref, newAnnotation.refToReplace)
); );
if (j >= 0) { if (j >= 0) {
annotations.splice(j, 1, newAnnotation); annotations.splice(j, 1, newAnnotation);
newAnnotations.splice(i--, 1); newAnnotations.splice(i--, 1);
ii--; ii--;
}
} }
} }
annotations = annotations.concat(newAnnotations);
} }
annotations = annotations.concat(newAnnotations);
}
if (
annotations.length === 0 ||
intent & RenderingIntentFlag.ANNOTATIONS_DISABLE
) {
pageOpList.flush(/* lastChunk = */ true);
return { length: pageOpList.totalLength };
}
const renderForms = !!(intent & RenderingIntentFlag.ANNOTATIONS_FORMS),
isEditing = !!(intent & RenderingIntentFlag.IS_EDITING),
intentAny = !!(intent & RenderingIntentFlag.ANY),
intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY),
intentPrint = !!(intent & RenderingIntentFlag.PRINT);
// Collect the operator list promises for the annotations. Each promise
// is resolved with the complete operator list for a single annotation.
const opListPromises = [];
for (const annotation of annotations) {
if ( if (
annotations.length === 0 || intentAny ||
intent & RenderingIntentFlag.ANNOTATIONS_DISABLE (intentDisplay &&
annotation.mustBeViewed(annotationStorage, renderForms) &&
annotation.mustBeViewedWhenEditing(isEditing, modifiedIds)) ||
(intentPrint && annotation.mustBePrinted(annotationStorage))
) { ) {
pageOpList.flush(/* lastChunk = */ true); opListPromises.push(
return { length: pageOpList.totalLength }; annotation
} .getOperatorList(partialEvaluator, task, intent, annotationStorage)
const renderForms = !!(intent & RenderingIntentFlag.ANNOTATIONS_FORMS), .catch(function (reason) {
isEditing = !!(intent & RenderingIntentFlag.IS_EDITING), warn(
intentAny = !!(intent & RenderingIntentFlag.ANY), "getOperatorList - ignoring annotation data during " +
intentDisplay = !!(intent & RenderingIntentFlag.DISPLAY), `"${task.name}" task: "${reason}".`
intentPrint = !!(intent & RenderingIntentFlag.PRINT); );
return {
// Collect the operator list promises for the annotations. Each promise opList: null,
// is resolved with the complete operator list for a single annotation. separateForm: false,
const opListPromises = []; separateCanvas: false,
for (const annotation of annotations) { };
if ( })
intentAny ||
(intentDisplay &&
annotation.mustBeViewed(annotationStorage, renderForms) &&
annotation.mustBeViewedWhenEditing(isEditing, modifiedIds)) ||
(intentPrint && annotation.mustBePrinted(annotationStorage))
) {
opListPromises.push(
annotation
.getOperatorList(
partialEvaluator,
task,
intent,
annotationStorage
)
.catch(function (reason) {
warn(
"getOperatorList - ignoring annotation data during " +
`"${task.name}" task: "${reason}".`
);
return {
opList: null,
separateForm: false,
separateCanvas: false,
};
})
);
}
}
return Promise.all(opListPromises).then(function (opLists) {
let form = false,
canvas = false;
for (const { opList, separateForm, separateCanvas } of opLists) {
pageOpList.addOpList(opList);
form ||= separateForm;
canvas ||= separateCanvas;
}
pageOpList.flush(
/* lastChunk = */ true,
/* separateAnnots = */ { form, canvas }
); );
return { length: pageOpList.totalLength }; }
}); }
});
const opLists = await Promise.all(opListPromises);
let form = false,
canvas = false;
for (const { opList, separateForm, separateCanvas } of opLists) {
pageOpList.addOpList(opList);
form ||= separateForm;
canvas ||= separateCanvas;
}
pageOpList.flush(
/* lastChunk = */ true,
/* separateAnnots = */ { form, canvas }
);
return { length: pageOpList.totalLength };
} }
async extractTextContent({ async extractTextContent({