UNPKG

23.8 kBJavaScriptView Raw
1/**
2 * @licstart The following is the entire license notice for the
3 * JavaScript code in this page
4 *
5 * Copyright 2022 Mozilla Foundation
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * @licend The above is the entire license notice for the
20 * JavaScript code in this page
21 */
22"use strict";
23
24Object.defineProperty(exports, "__esModule", {
25 value: true
26});
27exports.XRef = void 0;
28
29var _util = require("../shared/util.js");
30
31var _primitives = require("./primitives.js");
32
33var _core_utils = require("./core_utils.js");
34
35var _parser = require("./parser.js");
36
37var _base_stream = require("./base_stream.js");
38
39var _crypto = require("./crypto.js");
40
41class XRef {
42 constructor(stream, pdfManager) {
43 this.stream = stream;
44 this.pdfManager = pdfManager;
45 this.entries = [];
46 this.xrefstms = Object.create(null);
47 this._cacheMap = new Map();
48 this._pendingRefs = new _primitives.RefSet();
49 this.stats = new _core_utils.DocStats(pdfManager.msgHandler);
50 this._newRefNum = null;
51 }
52
53 getNewRef() {
54 if (this._newRefNum === null) {
55 this._newRefNum = this.entries.length || 1;
56 }
57
58 return _primitives.Ref.get(this._newRefNum++, 0);
59 }
60
61 resetNewRef() {
62 this._newRefNum = null;
63 }
64
65 setStartXRef(startXRef) {
66 this.startXRefQueue = [startXRef];
67 }
68
69 parse(recoveryMode = false) {
70 let trailerDict;
71
72 if (!recoveryMode) {
73 trailerDict = this.readXRef();
74 } else {
75 (0, _util.warn)("Indexing all PDF objects");
76 trailerDict = this.indexObjects();
77 }
78
79 trailerDict.assignXref(this);
80 this.trailer = trailerDict;
81 let encrypt;
82
83 try {
84 encrypt = trailerDict.get("Encrypt");
85 } catch (ex) {
86 if (ex instanceof _core_utils.MissingDataException) {
87 throw ex;
88 }
89
90 (0, _util.warn)(`XRef.parse - Invalid "Encrypt" reference: "${ex}".`);
91 }
92
93 if (encrypt instanceof _primitives.Dict) {
94 const ids = trailerDict.get("ID");
95 const fileId = ids && ids.length ? ids[0] : "";
96 encrypt.suppressEncryption = true;
97 this.encrypt = new _crypto.CipherTransformFactory(encrypt, fileId, this.pdfManager.password);
98 }
99
100 let root;
101
102 try {
103 root = trailerDict.get("Root");
104 } catch (ex) {
105 if (ex instanceof _core_utils.MissingDataException) {
106 throw ex;
107 }
108
109 (0, _util.warn)(`XRef.parse - Invalid "Root" reference: "${ex}".`);
110 }
111
112 if (root instanceof _primitives.Dict) {
113 try {
114 const pages = root.get("Pages");
115
116 if (pages instanceof _primitives.Dict) {
117 this.root = root;
118 return;
119 }
120 } catch (ex) {
121 if (ex instanceof _core_utils.MissingDataException) {
122 throw ex;
123 }
124
125 (0, _util.warn)(`XRef.parse - Invalid "Pages" reference: "${ex}".`);
126 }
127 }
128
129 if (!recoveryMode) {
130 throw new _core_utils.XRefParseException();
131 }
132
133 throw new _util.InvalidPDFException("Invalid Root reference.");
134 }
135
136 processXRefTable(parser) {
137 if (!("tableState" in this)) {
138 this.tableState = {
139 entryNum: 0,
140 streamPos: parser.lexer.stream.pos,
141 parserBuf1: parser.buf1,
142 parserBuf2: parser.buf2
143 };
144 }
145
146 const obj = this.readXRefTable(parser);
147
148 if (!(0, _primitives.isCmd)(obj, "trailer")) {
149 throw new _util.FormatError("Invalid XRef table: could not find trailer dictionary");
150 }
151
152 let dict = parser.getObj();
153
154 if (!(dict instanceof _primitives.Dict) && dict.dict) {
155 dict = dict.dict;
156 }
157
158 if (!(dict instanceof _primitives.Dict)) {
159 throw new _util.FormatError("Invalid XRef table: could not parse trailer dictionary");
160 }
161
162 delete this.tableState;
163 return dict;
164 }
165
166 readXRefTable(parser) {
167 const stream = parser.lexer.stream;
168 const tableState = this.tableState;
169 stream.pos = tableState.streamPos;
170 parser.buf1 = tableState.parserBuf1;
171 parser.buf2 = tableState.parserBuf2;
172 let obj;
173
174 while (true) {
175 if (!("firstEntryNum" in tableState) || !("entryCount" in tableState)) {
176 if ((0, _primitives.isCmd)(obj = parser.getObj(), "trailer")) {
177 break;
178 }
179
180 tableState.firstEntryNum = obj;
181 tableState.entryCount = parser.getObj();
182 }
183
184 let first = tableState.firstEntryNum;
185 const count = tableState.entryCount;
186
187 if (!Number.isInteger(first) || !Number.isInteger(count)) {
188 throw new _util.FormatError("Invalid XRef table: wrong types in subsection header");
189 }
190
191 for (let i = tableState.entryNum; i < count; i++) {
192 tableState.streamPos = stream.pos;
193 tableState.entryNum = i;
194 tableState.parserBuf1 = parser.buf1;
195 tableState.parserBuf2 = parser.buf2;
196 const entry = {};
197 entry.offset = parser.getObj();
198 entry.gen = parser.getObj();
199 const type = parser.getObj();
200
201 if (type instanceof _primitives.Cmd) {
202 switch (type.cmd) {
203 case "f":
204 entry.free = true;
205 break;
206
207 case "n":
208 entry.uncompressed = true;
209 break;
210 }
211 }
212
213 if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.gen) || !(entry.free || entry.uncompressed)) {
214 throw new _util.FormatError(`Invalid entry in XRef subsection: ${first}, ${count}`);
215 }
216
217 if (i === 0 && entry.free && first === 1) {
218 first = 0;
219 }
220
221 if (!this.entries[i + first]) {
222 this.entries[i + first] = entry;
223 }
224 }
225
226 tableState.entryNum = 0;
227 tableState.streamPos = stream.pos;
228 tableState.parserBuf1 = parser.buf1;
229 tableState.parserBuf2 = parser.buf2;
230 delete tableState.firstEntryNum;
231 delete tableState.entryCount;
232 }
233
234 if (this.entries[0] && !this.entries[0].free) {
235 throw new _util.FormatError("Invalid XRef table: unexpected first object");
236 }
237
238 return obj;
239 }
240
241 processXRefStream(stream) {
242 if (!("streamState" in this)) {
243 const streamParameters = stream.dict;
244 const byteWidths = streamParameters.get("W");
245 let range = streamParameters.get("Index");
246
247 if (!range) {
248 range = [0, streamParameters.get("Size")];
249 }
250
251 this.streamState = {
252 entryRanges: range,
253 byteWidths,
254 entryNum: 0,
255 streamPos: stream.pos
256 };
257 }
258
259 this.readXRefStream(stream);
260 delete this.streamState;
261 return stream.dict;
262 }
263
264 readXRefStream(stream) {
265 const streamState = this.streamState;
266 stream.pos = streamState.streamPos;
267 const [typeFieldWidth, offsetFieldWidth, generationFieldWidth] = streamState.byteWidths;
268 const entryRanges = streamState.entryRanges;
269
270 while (entryRanges.length > 0) {
271 const [first, n] = entryRanges;
272
273 if (!Number.isInteger(first) || !Number.isInteger(n)) {
274 throw new _util.FormatError(`Invalid XRef range fields: ${first}, ${n}`);
275 }
276
277 if (!Number.isInteger(typeFieldWidth) || !Number.isInteger(offsetFieldWidth) || !Number.isInteger(generationFieldWidth)) {
278 throw new _util.FormatError(`Invalid XRef entry fields length: ${first}, ${n}`);
279 }
280
281 for (let i = streamState.entryNum; i < n; ++i) {
282 streamState.entryNum = i;
283 streamState.streamPos = stream.pos;
284 let type = 0,
285 offset = 0,
286 generation = 0;
287
288 for (let j = 0; j < typeFieldWidth; ++j) {
289 const typeByte = stream.getByte();
290
291 if (typeByte === -1) {
292 throw new _util.FormatError("Invalid XRef byteWidths 'type'.");
293 }
294
295 type = type << 8 | typeByte;
296 }
297
298 if (typeFieldWidth === 0) {
299 type = 1;
300 }
301
302 for (let j = 0; j < offsetFieldWidth; ++j) {
303 const offsetByte = stream.getByte();
304
305 if (offsetByte === -1) {
306 throw new _util.FormatError("Invalid XRef byteWidths 'offset'.");
307 }
308
309 offset = offset << 8 | offsetByte;
310 }
311
312 for (let j = 0; j < generationFieldWidth; ++j) {
313 const generationByte = stream.getByte();
314
315 if (generationByte === -1) {
316 throw new _util.FormatError("Invalid XRef byteWidths 'generation'.");
317 }
318
319 generation = generation << 8 | generationByte;
320 }
321
322 const entry = {};
323 entry.offset = offset;
324 entry.gen = generation;
325
326 switch (type) {
327 case 0:
328 entry.free = true;
329 break;
330
331 case 1:
332 entry.uncompressed = true;
333 break;
334
335 case 2:
336 break;
337
338 default:
339 throw new _util.FormatError(`Invalid XRef entry type: ${type}`);
340 }
341
342 if (!this.entries[first + i]) {
343 this.entries[first + i] = entry;
344 }
345 }
346
347 streamState.entryNum = 0;
348 streamState.streamPos = stream.pos;
349 entryRanges.splice(0, 2);
350 }
351 }
352
353 indexObjects() {
354 const TAB = 0x9,
355 LF = 0xa,
356 CR = 0xd,
357 SPACE = 0x20;
358 const PERCENT = 0x25,
359 LT = 0x3c;
360
361 function readToken(data, offset) {
362 let token = "",
363 ch = data[offset];
364
365 while (ch !== LF && ch !== CR && ch !== LT) {
366 if (++offset >= data.length) {
367 break;
368 }
369
370 token += String.fromCharCode(ch);
371 ch = data[offset];
372 }
373
374 return token;
375 }
376
377 function skipUntil(data, offset, what) {
378 const length = what.length,
379 dataLength = data.length;
380 let skipped = 0;
381
382 while (offset < dataLength) {
383 let i = 0;
384
385 while (i < length && data[offset + i] === what[i]) {
386 ++i;
387 }
388
389 if (i >= length) {
390 break;
391 }
392
393 offset++;
394 skipped++;
395 }
396
397 return skipped;
398 }
399
400 const objRegExp = /^(\d+)\s+(\d+)\s+obj\b/;
401 const endobjRegExp = /\bendobj[\b\s]$/;
402 const nestedObjRegExp = /\s+(\d+\s+\d+\s+obj[\b\s<])$/;
403 const CHECK_CONTENT_LENGTH = 25;
404 const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
405 const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]);
406 const objBytes = new Uint8Array([111, 98, 106]);
407 const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
408 this.entries.length = 0;
409
410 this._cacheMap.clear();
411
412 const stream = this.stream;
413 stream.pos = 0;
414 const buffer = stream.getBytes(),
415 length = buffer.length;
416 let position = stream.start;
417 const trailers = [],
418 xrefStms = [];
419
420 while (position < length) {
421 let ch = buffer[position];
422
423 if (ch === TAB || ch === LF || ch === CR || ch === SPACE) {
424 ++position;
425 continue;
426 }
427
428 if (ch === PERCENT) {
429 do {
430 ++position;
431
432 if (position >= length) {
433 break;
434 }
435
436 ch = buffer[position];
437 } while (ch !== LF && ch !== CR);
438
439 continue;
440 }
441
442 const token = readToken(buffer, position);
443 let m;
444
445 if (token.startsWith("xref") && (token.length === 4 || /\s/.test(token[4]))) {
446 position += skipUntil(buffer, position, trailerBytes);
447 trailers.push(position);
448 position += skipUntil(buffer, position, startxrefBytes);
449 } else if (m = objRegExp.exec(token)) {
450 const num = m[1] | 0,
451 gen = m[2] | 0;
452 let contentLength,
453 startPos = position + token.length,
454 updateEntries = false;
455
456 if (!this.entries[num]) {
457 updateEntries = true;
458 } else if (this.entries[num].gen === gen) {
459 try {
460 const parser = new _parser.Parser({
461 lexer: new _parser.Lexer(stream.makeSubStream(startPos))
462 });
463 parser.getObj();
464 updateEntries = true;
465 } catch (ex) {
466 if (ex instanceof _core_utils.ParserEOFException) {
467 (0, _util.warn)(`indexObjects -- checking object (${token}): "${ex}".`);
468 } else {
469 updateEntries = true;
470 }
471 }
472 }
473
474 if (updateEntries) {
475 this.entries[num] = {
476 offset: position - stream.start,
477 gen,
478 uncompressed: true
479 };
480 }
481
482 while (startPos < buffer.length) {
483 const endPos = startPos + skipUntil(buffer, startPos, objBytes) + 4;
484 contentLength = endPos - position;
485 const checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, startPos);
486 const tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos));
487
488 if (endobjRegExp.test(tokenStr)) {
489 break;
490 } else {
491 const objToken = nestedObjRegExp.exec(tokenStr);
492
493 if (objToken && objToken[1]) {
494 (0, _util.warn)('indexObjects: Found new "obj" inside of another "obj", ' + 'caused by missing "endobj" -- trying to recover.');
495 contentLength -= objToken[1].length;
496 break;
497 }
498 }
499
500 startPos = endPos;
501 }
502
503 const content = buffer.subarray(position, position + contentLength);
504 const xrefTagOffset = skipUntil(content, 0, xrefBytes);
505
506 if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) {
507 xrefStms.push(position - stream.start);
508 this.xrefstms[position - stream.start] = 1;
509 }
510
511 position += contentLength;
512 } else if (token.startsWith("trailer") && (token.length === 7 || /\s/.test(token[7]))) {
513 trailers.push(position);
514 position += skipUntil(buffer, position, startxrefBytes);
515 } else {
516 position += token.length + 1;
517 }
518 }
519
520 for (let i = 0, ii = xrefStms.length; i < ii; ++i) {
521 this.startXRefQueue.push(xrefStms[i]);
522 this.readXRef(true);
523 }
524
525 let trailerDict;
526
527 for (let i = 0, ii = trailers.length; i < ii; ++i) {
528 stream.pos = trailers[i];
529 const parser = new _parser.Parser({
530 lexer: new _parser.Lexer(stream),
531 xref: this,
532 allowStreams: true,
533 recoveryMode: true
534 });
535 const obj = parser.getObj();
536
537 if (!(0, _primitives.isCmd)(obj, "trailer")) {
538 continue;
539 }
540
541 const dict = parser.getObj();
542
543 if (!(dict instanceof _primitives.Dict)) {
544 continue;
545 }
546
547 try {
548 const rootDict = dict.get("Root");
549
550 if (!(rootDict instanceof _primitives.Dict)) {
551 continue;
552 }
553
554 const pagesDict = rootDict.get("Pages");
555
556 if (!(pagesDict instanceof _primitives.Dict)) {
557 continue;
558 }
559
560 const pagesCount = pagesDict.get("Count");
561
562 if (!Number.isInteger(pagesCount)) {
563 continue;
564 }
565 } catch (ex) {
566 continue;
567 }
568
569 if (dict.has("ID")) {
570 return dict;
571 }
572
573 trailerDict = dict;
574 }
575
576 if (trailerDict) {
577 return trailerDict;
578 }
579
580 if (this.topDict) {
581 return this.topDict;
582 }
583
584 throw new _util.InvalidPDFException("Invalid PDF structure.");
585 }
586
587 readXRef(recoveryMode = false) {
588 const stream = this.stream;
589 const startXRefParsedCache = new Set();
590
591 try {
592 while (this.startXRefQueue.length) {
593 const startXRef = this.startXRefQueue[0];
594
595 if (startXRefParsedCache.has(startXRef)) {
596 (0, _util.warn)("readXRef - skipping XRef table since it was already parsed.");
597 this.startXRefQueue.shift();
598 continue;
599 }
600
601 startXRefParsedCache.add(startXRef);
602 stream.pos = startXRef + stream.start;
603 const parser = new _parser.Parser({
604 lexer: new _parser.Lexer(stream),
605 xref: this,
606 allowStreams: true
607 });
608 let obj = parser.getObj();
609 let dict;
610
611 if ((0, _primitives.isCmd)(obj, "xref")) {
612 dict = this.processXRefTable(parser);
613
614 if (!this.topDict) {
615 this.topDict = dict;
616 }
617
618 obj = dict.get("XRefStm");
619
620 if (Number.isInteger(obj)) {
621 const pos = obj;
622
623 if (!(pos in this.xrefstms)) {
624 this.xrefstms[pos] = 1;
625 this.startXRefQueue.push(pos);
626 }
627 }
628 } else if (Number.isInteger(obj)) {
629 if (!Number.isInteger(parser.getObj()) || !(0, _primitives.isCmd)(parser.getObj(), "obj") || !((obj = parser.getObj()) instanceof _base_stream.BaseStream)) {
630 throw new _util.FormatError("Invalid XRef stream");
631 }
632
633 dict = this.processXRefStream(obj);
634
635 if (!this.topDict) {
636 this.topDict = dict;
637 }
638
639 if (!dict) {
640 throw new _util.FormatError("Failed to read XRef stream");
641 }
642 } else {
643 throw new _util.FormatError("Invalid XRef stream header");
644 }
645
646 obj = dict.get("Prev");
647
648 if (Number.isInteger(obj)) {
649 this.startXRefQueue.push(obj);
650 } else if (obj instanceof _primitives.Ref) {
651 this.startXRefQueue.push(obj.num);
652 }
653
654 this.startXRefQueue.shift();
655 }
656
657 return this.topDict;
658 } catch (e) {
659 if (e instanceof _core_utils.MissingDataException) {
660 throw e;
661 }
662
663 (0, _util.info)("(while reading XRef): " + e);
664 this.startXRefQueue.shift();
665 }
666
667 if (recoveryMode) {
668 return undefined;
669 }
670
671 throw new _core_utils.XRefParseException();
672 }
673
674 getEntry(i) {
675 const xrefEntry = this.entries[i];
676
677 if (xrefEntry && !xrefEntry.free && xrefEntry.offset) {
678 return xrefEntry;
679 }
680
681 return null;
682 }
683
684 fetchIfRef(obj, suppressEncryption = false) {
685 if (obj instanceof _primitives.Ref) {
686 return this.fetch(obj, suppressEncryption);
687 }
688
689 return obj;
690 }
691
692 fetch(ref, suppressEncryption = false) {
693 if (!(ref instanceof _primitives.Ref)) {
694 throw new Error("ref object is not a reference");
695 }
696
697 const num = ref.num;
698
699 const cacheEntry = this._cacheMap.get(num);
700
701 if (cacheEntry !== undefined) {
702 if (cacheEntry instanceof _primitives.Dict && !cacheEntry.objId) {
703 cacheEntry.objId = ref.toString();
704 }
705
706 return cacheEntry;
707 }
708
709 let xrefEntry = this.getEntry(num);
710
711 if (xrefEntry === null) {
712 this._cacheMap.set(num, xrefEntry);
713
714 return xrefEntry;
715 }
716
717 if (this._pendingRefs.has(ref)) {
718 this._pendingRefs.remove(ref);
719
720 (0, _util.warn)(`Ignoring circular reference: ${ref}.`);
721 return _primitives.CIRCULAR_REF;
722 }
723
724 this._pendingRefs.put(ref);
725
726 try {
727 if (xrefEntry.uncompressed) {
728 xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption);
729 } else {
730 xrefEntry = this.fetchCompressed(ref, xrefEntry, suppressEncryption);
731 }
732
733 this._pendingRefs.remove(ref);
734 } catch (ex) {
735 this._pendingRefs.remove(ref);
736
737 throw ex;
738 }
739
740 if (xrefEntry instanceof _primitives.Dict) {
741 xrefEntry.objId = ref.toString();
742 } else if (xrefEntry instanceof _base_stream.BaseStream) {
743 xrefEntry.dict.objId = ref.toString();
744 }
745
746 return xrefEntry;
747 }
748
749 fetchUncompressed(ref, xrefEntry, suppressEncryption = false) {
750 const gen = ref.gen;
751 let num = ref.num;
752
753 if (xrefEntry.gen !== gen) {
754 throw new _core_utils.XRefEntryException(`Inconsistent generation in XRef: ${ref}`);
755 }
756
757 const stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start);
758 const parser = new _parser.Parser({
759 lexer: new _parser.Lexer(stream),
760 xref: this,
761 allowStreams: true
762 });
763 const obj1 = parser.getObj();
764 const obj2 = parser.getObj();
765 const obj3 = parser.getObj();
766
767 if (obj1 !== num || obj2 !== gen || !(obj3 instanceof _primitives.Cmd)) {
768 throw new _core_utils.XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`);
769 }
770
771 if (obj3.cmd !== "obj") {
772 if (obj3.cmd.startsWith("obj")) {
773 num = parseInt(obj3.cmd.substring(3), 10);
774
775 if (!Number.isNaN(num)) {
776 return num;
777 }
778 }
779
780 throw new _core_utils.XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`);
781 }
782
783 if (this.encrypt && !suppressEncryption) {
784 xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen));
785 } else {
786 xrefEntry = parser.getObj();
787 }
788
789 if (!(xrefEntry instanceof _base_stream.BaseStream)) {
790 this._cacheMap.set(num, xrefEntry);
791 }
792
793 return xrefEntry;
794 }
795
796 fetchCompressed(ref, xrefEntry, suppressEncryption = false) {
797 const tableOffset = xrefEntry.offset;
798 const stream = this.fetch(_primitives.Ref.get(tableOffset, 0));
799
800 if (!(stream instanceof _base_stream.BaseStream)) {
801 throw new _util.FormatError("bad ObjStm stream");
802 }
803
804 const first = stream.dict.get("First");
805 const n = stream.dict.get("N");
806
807 if (!Number.isInteger(first) || !Number.isInteger(n)) {
808 throw new _util.FormatError("invalid first and n parameters for ObjStm stream");
809 }
810
811 let parser = new _parser.Parser({
812 lexer: new _parser.Lexer(stream),
813 xref: this,
814 allowStreams: true
815 });
816 const nums = new Array(n);
817 const offsets = new Array(n);
818
819 for (let i = 0; i < n; ++i) {
820 const num = parser.getObj();
821
822 if (!Number.isInteger(num)) {
823 throw new _util.FormatError(`invalid object number in the ObjStm stream: ${num}`);
824 }
825
826 const offset = parser.getObj();
827
828 if (!Number.isInteger(offset)) {
829 throw new _util.FormatError(`invalid object offset in the ObjStm stream: ${offset}`);
830 }
831
832 nums[i] = num;
833 offsets[i] = offset;
834 }
835
836 const start = (stream.start || 0) + first;
837 const entries = new Array(n);
838
839 for (let i = 0; i < n; ++i) {
840 const length = i < n - 1 ? offsets[i + 1] - offsets[i] : undefined;
841
842 if (length < 0) {
843 throw new _util.FormatError("Invalid offset in the ObjStm stream.");
844 }
845
846 parser = new _parser.Parser({
847 lexer: new _parser.Lexer(stream.makeSubStream(start + offsets[i], length, stream.dict)),
848 xref: this,
849 allowStreams: true
850 });
851 const obj = parser.getObj();
852 entries[i] = obj;
853
854 if (obj instanceof _base_stream.BaseStream) {
855 continue;
856 }
857
858 const num = nums[i],
859 entry = this.entries[num];
860
861 if (entry && entry.offset === tableOffset && entry.gen === i) {
862 this._cacheMap.set(num, obj);
863 }
864 }
865
866 xrefEntry = entries[xrefEntry.gen];
867
868 if (xrefEntry === undefined) {
869 throw new _core_utils.XRefEntryException(`Bad (compressed) XRef entry: ${ref}`);
870 }
871
872 return xrefEntry;
873 }
874
875 async fetchIfRefAsync(obj, suppressEncryption) {
876 if (obj instanceof _primitives.Ref) {
877 return this.fetchAsync(obj, suppressEncryption);
878 }
879
880 return obj;
881 }
882
883 async fetchAsync(ref, suppressEncryption) {
884 try {
885 return this.fetch(ref, suppressEncryption);
886 } catch (ex) {
887 if (!(ex instanceof _core_utils.MissingDataException)) {
888 throw ex;
889 }
890
891 await this.pdfManager.requestRange(ex.begin, ex.end);
892 return this.fetchAsync(ref, suppressEncryption);
893 }
894 }
895
896 getCatalogObj() {
897 return this.root;
898 }
899
900}
901
902exports.XRef = XRef;
\No newline at end of file