Skip to content

Commit 71370d0

Browse files
committed
Support destinations in NameTrees with encoded keys (issue 14847)
Initially I considered updating the `NameOrNumberTree`-implementation to handle encoded keys, however that quickly became somewhat messy (especially in the `NameOrNumberTree.get`-method) since only NameTrees using string-keys. Hence the easiest solution, as far as I'm concerned, was thus to just update the `Catalog.destinations`-getter instead. Please note that in the referenced PDF document the `Catalog.destination`-method will thus fallback to fetch all destinations, which should be fine since this is the very first case of encoded keys that we've seen. Also changes the `NameOrNumberTree.getAll`-method to prevent a possible run-time error, although we've so far not seen such a case, for any non-Array Kids-entries found in a NameTree/NumberTree. Finally, to improve overall consistency and to hopefully prevent future bugs, the patch also updates a couple of other `NameTree` call-sites to correctly handle encoded keys. (Note that the `Catalog.attachments`-getter was already doing this.)
1 parent 981cd5b commit 71370d0

File tree

5 files changed

+24
-6
lines changed

5 files changed

+24
-6
lines changed

src/core/catalog.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ class Catalog {
566566
for (const [key, value] of obj.getAll()) {
567567
const dest = fetchDestination(value);
568568
if (dest) {
569-
dests[key] = dest;
569+
dests[stringToPDFString(key)] = dest;
570570
}
571571
}
572572
} else if (obj instanceof Dict) {
@@ -954,7 +954,7 @@ class Catalog {
954954
if (!xfaImages) {
955955
xfaImages = new Dict(this.xref);
956956
}
957-
xfaImages.set(key, value);
957+
xfaImages.set(stringToPDFString(key), value);
958958
}
959959
}
960960
return shadow(this, "xfaImages", xfaImages);
@@ -988,7 +988,7 @@ class Catalog {
988988
if (obj instanceof Dict && obj.has("JavaScript")) {
989989
const nameTree = new NameTree(obj.getRaw("JavaScript"), this.xref);
990990
for (const [key, value] of nameTree.getAll()) {
991-
appendIfJavaScriptDict(key, value);
991+
appendIfJavaScriptDict(stringToPDFString(key), value);
992992
}
993993
}
994994
// Append OpenAction "JavaScript" actions, if any, to the JavaScript map.

src/core/name_number_tree.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ class NameOrNumberTree {
4848
}
4949
if (obj.has("Kids")) {
5050
const kids = obj.get("Kids");
51-
for (let i = 0, ii = kids.length; i < ii; i++) {
52-
const kid = kids[i];
51+
if (!Array.isArray(kids)) {
52+
continue;
53+
}
54+
for (const kid of kids) {
5355
if (processed.has(kid)) {
5456
throw new FormatError(`Duplicate entry in "${this._type}" tree.`);
5557
}
@@ -103,7 +105,7 @@ class NameOrNumberTree {
103105
} else if (key > xref.fetchIfRef(limits[1])) {
104106
l = m + 1;
105107
} else {
106-
kidsOrEntries = xref.fetchIfRef(kids[m]);
108+
kidsOrEntries = kid;
107109
break;
108110
}
109111
}

test/pdfs/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
!issue7544.pdf
5454
!issue7507.pdf
5555
!issue6931_reduced.pdf
56+
!issue14847.pdf
5657
!doc_actions.pdf
5758
!issue7580.pdf
5859
!issue7598.pdf

test/pdfs/issue14847.pdf

85 KB
Binary file not shown.

test/unit/api_spec.js

+15
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,21 @@ describe("api", function () {
10041004
await loadingTask.destroy();
10051005
});
10061006

1007+
it("gets a destination, from /Names (NameTree) dictionary with keys using PDFDocEncoding (issue 14847)", async function () {
1008+
const loadingTask = getDocument(buildGetDocumentParams("issue14847.pdf"));
1009+
const pdfDoc = await loadingTask.promise;
1010+
const destination = await pdfDoc.getDestination("index");
1011+
expect(destination).toEqual([
1012+
{ num: 10, gen: 0 },
1013+
{ name: "XYZ" },
1014+
85.039,
1015+
728.504,
1016+
null,
1017+
]);
1018+
1019+
await loadingTask.destroy();
1020+
});
1021+
10071022
it("gets non-string destination", async function () {
10081023
let numberPromise = pdfDocument.getDestination(4.3);
10091024
let booleanPromise = pdfDocument.getDestination(true);

0 commit comments

Comments
 (0)