Change NameOrNumberTree.getAll to return a Map rather than an Object

Given that we're (almost) always iterating through the result of the `getAll`-calls, using a `Map` seems nicer overall since it's more suited to iteration compared to a regular Object.

Also, add a couple of `Dict`-checks in existing code touched by this patch, since it really cannot hurt to prevent *potential* errors in a corrupt PDF document.
This commit is contained in:
Jonas Jenwald 2021-04-21 12:14:33 +02:00
parent 57a1ea840f
commit 83f7009e4b
2 changed files with 21 additions and 23 deletions

View File

@ -514,9 +514,8 @@ class Catalog {
const obj = this._readDests(),
dests = Object.create(null);
if (obj instanceof NameTree) {
const names = obj.getAll();
for (const name in names) {
dests[name] = fetchDestination(names[name]);
for (const [key, value] of obj.getAll()) {
dests[key] = fetchDestination(value);
}
} else if (obj instanceof Dict) {
obj.forEach(function (key, value) {
@ -582,8 +581,9 @@ class Catalog {
currentIndex = 1;
for (let i = 0, ii = this.numPages; i < ii; i++) {
if (i in nums) {
const labelDict = nums[i];
const labelDict = nums.get(i);
if (labelDict !== undefined) {
if (!isDict(labelDict)) {
throw new FormatError("PageLabel is not a dictionary.");
}
@ -879,15 +879,14 @@ class Catalog {
const obj = this._catDict.get("Names");
let attachments = null;
if (obj && obj.has("EmbeddedFiles")) {
if (obj instanceof Dict && obj.has("EmbeddedFiles")) {
const nameTree = new NameTree(obj.getRaw("EmbeddedFiles"), this.xref);
const names = nameTree.getAll();
for (const name in names) {
const fs = new FileSpec(names[name], this.xref);
for (const [key, value] of nameTree.getAll()) {
const fs = new FileSpec(value, this.xref);
if (!attachments) {
attachments = Object.create(null);
}
attachments[stringToPDFString(name)] = fs.serializable;
attachments[stringToPDFString(key)] = fs.serializable;
}
}
return shadow(this, "attachments", attachments);
@ -916,15 +915,13 @@ class Catalog {
javaScript.set(name, stringToPDFString(js));
}
if (obj && obj.has("JavaScript")) {
if (obj instanceof Dict && obj.has("JavaScript")) {
const nameTree = new NameTree(obj.getRaw("JavaScript"), this.xref);
const names = nameTree.getAll();
for (const name in names) {
for (const [key, value] of nameTree.getAll()) {
// We don't use most JavaScript in PDF documents. This code is
// defensive so we don't cause errors on document load.
const jsDict = names[name];
if (isDict(jsDict)) {
appendIfJavaScriptDict(name, jsDict);
if (value instanceof Dict) {
appendIfJavaScriptDict(key, value);
}
}
}

View File

@ -32,9 +32,9 @@ class NameOrNumberTree {
}
getAll() {
const dict = Object.create(null);
const map = new Map();
if (!this.root) {
return dict;
return map;
}
const xref = this.xref;
// Reading Name/Number tree.
@ -59,13 +59,14 @@ class NameOrNumberTree {
continue;
}
const entries = obj.get(this._type);
if (Array.isArray(entries)) {
for (let i = 0, ii = entries.length; i < ii; i += 2) {
dict[xref.fetchIfRef(entries[i])] = xref.fetchIfRef(entries[i + 1]);
}
if (!Array.isArray(entries)) {
continue;
}
for (let i = 0, ii = entries.length; i < ii; i += 2) {
map.set(xref.fetchIfRef(entries[i]), xref.fetchIfRef(entries[i + 1]));
}
}
return dict;
return map;
}
get(key) {