Skip to content

Commit b1440a1

Browse files
Merge pull request #11312 from Snuffleupagus/async-getPageDict
Convert `Catalog.getPageDict` to an `async` method
2 parents 668650d + 79d7c00 commit b1440a1

File tree

1 file changed

+66
-80
lines changed

1 file changed

+66
-80
lines changed

src/core/obj.js

Lines changed: 66 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
*/
1515

1616
import {
17-
assert, bytesToString, createPromiseCapability, createValidAbsoluteUrl,
18-
FormatError, info, InvalidPDFException, isBool, isNum, isString,
19-
PermissionFlag, shadow, stringToPDFString, stringToUTF8String, unreachable,
20-
warn
17+
assert, bytesToString, createValidAbsoluteUrl, FormatError, info,
18+
InvalidPDFException, isBool, isNum, isString, PermissionFlag, shadow,
19+
stringToPDFString, stringToUTF8String, unreachable, warn
2120
} from '../shared/util';
2221
import {
2322
clearPrimitiveCaches, Cmd, Dict, isCmd, isDict, isName, isRef, isRefsEqual,
@@ -680,99 +679,86 @@ class Catalog {
680679
});
681680
}
682681

683-
getPageDict(pageIndex) {
684-
const capability = createPromiseCapability();
682+
async getPageDict(pageIndex) {
685683
const nodesToVisit = [this.catDict.getRaw('Pages')];
686684
const xref = this.xref, pageKidsCountCache = this.pageKidsCountCache;
687685
let count, currentPageIndex = 0;
688686

689-
function next() {
690-
while (nodesToVisit.length) {
691-
const currentNode = nodesToVisit.pop();
687+
while (nodesToVisit.length) {
688+
const currentNode = nodesToVisit.pop();
692689

693-
if (isRef(currentNode)) {
694-
count = pageKidsCountCache.get(currentNode);
695-
// Skip nodes where the page can't be.
696-
if (count > 0 && currentPageIndex + count < pageIndex) {
697-
currentPageIndex += count;
698-
continue;
699-
}
690+
if (currentNode instanceof Ref) {
691+
count = pageKidsCountCache.get(currentNode);
692+
// Skip nodes where the page can't be.
693+
if (count > 0 && currentPageIndex + count < pageIndex) {
694+
currentPageIndex += count;
695+
continue;
696+
}
697+
const obj = await xref.fetchAsync(currentNode);
700698

701-
xref.fetchAsync(currentNode).then(function(obj) {
702-
if (isDict(obj, 'Page') || (isDict(obj) && !obj.has('Kids'))) {
703-
if (pageIndex === currentPageIndex) {
704-
// Cache the Page reference, since it can *greatly* improve
705-
// performance by reducing redundant lookups in long documents
706-
// where all nodes are found at *one* level of the tree.
707-
if (currentNode && !pageKidsCountCache.has(currentNode)) {
708-
pageKidsCountCache.put(currentNode, 1);
709-
}
710-
capability.resolve([obj, currentNode]);
711-
} else {
712-
currentPageIndex++;
713-
next();
714-
}
715-
return;
699+
if ((obj instanceof Dict) && (isName(obj.get('Type'), 'Page') ||
700+
(!obj.has('Type') && !obj.has('Kids')))) {
701+
if (pageIndex === currentPageIndex) {
702+
// Cache the Page reference, since it can *greatly* improve
703+
// performance by reducing redundant lookups in long documents
704+
// where all nodes are found at *one* level of the tree.
705+
if (currentNode && !pageKidsCountCache.has(currentNode)) {
706+
pageKidsCountCache.put(currentNode, 1);
716707
}
717-
nodesToVisit.push(obj);
718-
next();
719-
}, capability.reject);
720-
return;
708+
return [obj, currentNode];
709+
}
710+
currentPageIndex++;
711+
continue;
721712
}
713+
nodesToVisit.push(obj);
714+
continue;
715+
}
722716

723-
// Must be a child page dictionary.
724-
if (!isDict(currentNode)) {
725-
capability.reject(new FormatError(
726-
'Page dictionary kid reference points to wrong type of object.'));
727-
return;
728-
}
717+
// Must be a child page dictionary.
718+
if (!(currentNode instanceof Dict)) {
719+
throw new FormatError(
720+
'Page dictionary kid reference points to wrong type of object.');
721+
}
729722

730-
count = currentNode.get('Count');
731-
if (Number.isInteger(count) && count >= 0) {
732-
// Cache the Kids count, since it can reduce redundant lookups in
733-
// documents where all nodes are found at *one* level of the tree.
734-
const objId = currentNode.objId;
735-
if (objId && !pageKidsCountCache.has(objId)) {
736-
pageKidsCountCache.put(objId, count);
737-
}
738-
// Skip nodes where the page can't be.
739-
if (currentPageIndex + count <= pageIndex) {
740-
currentPageIndex += count;
741-
continue;
742-
}
723+
count = currentNode.get('Count');
724+
if (Number.isInteger(count) && count >= 0) {
725+
// Cache the Kids count, since it can reduce redundant lookups in
726+
// documents where all nodes are found at *one* level of the tree.
727+
const objId = currentNode.objId;
728+
if (objId && !pageKidsCountCache.has(objId)) {
729+
pageKidsCountCache.put(objId, count);
743730
}
731+
// Skip nodes where the page can't be.
732+
if (currentPageIndex + count <= pageIndex) {
733+
currentPageIndex += count;
734+
continue;
735+
}
736+
}
744737

745-
const kids = currentNode.get('Kids');
746-
if (!Array.isArray(kids)) {
747-
// Prevent errors in corrupt PDF documents that violate the
748-
// specification by *inlining* Page dicts directly in the Kids
749-
// array, rather than using indirect objects (fixes issue9540.pdf).
750-
if (isName(currentNode.get('Type'), 'Page') ||
751-
(!currentNode.has('Type') && currentNode.has('Contents'))) {
752-
if (currentPageIndex === pageIndex) {
753-
capability.resolve([currentNode, null]);
754-
return;
755-
}
756-
currentPageIndex++;
757-
continue;
738+
const kids = currentNode.get('Kids');
739+
if (!Array.isArray(kids)) {
740+
// Prevent errors in corrupt PDF documents that violate the
741+
// specification by *inlining* Page dicts directly in the Kids
742+
// array, rather than using indirect objects (fixes issue9540.pdf).
743+
if (isName(currentNode.get('Type'), 'Page') ||
744+
(!currentNode.has('Type') && currentNode.has('Contents'))) {
745+
if (currentPageIndex === pageIndex) {
746+
return [currentNode, null];
758747
}
759-
760-
capability.reject(new FormatError(
761-
'Page dictionary kids object is not an array.'));
762-
return;
748+
currentPageIndex++;
749+
continue;
763750
}
751+
throw new FormatError('Page dictionary kids object is not an array.');
752+
}
764753

765-
// Always check all `Kids` nodes, to avoid getting stuck in an empty
766-
// node further down in the tree (see issue5644.pdf, issue8088.pdf),
767-
// and to ensure that we actually find the correct `Page` dict.
768-
for (let last = kids.length - 1; last >= 0; last--) {
769-
nodesToVisit.push(kids[last]);
770-
}
754+
// Always check all `Kids` nodes, to avoid getting stuck in an empty
755+
// node further down in the tree (see issue5644.pdf, issue8088.pdf),
756+
// and to ensure that we actually find the correct `Page` dict.
757+
for (let last = kids.length - 1; last >= 0; last--) {
758+
nodesToVisit.push(kids[last]);
771759
}
772-
capability.reject(new Error(`Page index ${pageIndex} not found.`));
773760
}
774-
next();
775-
return capability.promise;
761+
throw new Error(`Page index ${pageIndex} not found.`);
776762
}
777763

778764
getPageIndex(pageRef) {

0 commit comments

Comments
 (0)