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

View File

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