pdf-lite 1.6.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -46,7 +46,7 @@ export class PdfDefaultAppearance extends PdfString {
46
46
  return `/${this._fontName} ${this._fontSize} Tf ${this._colorOp}`;
47
47
  }
48
48
  static parse(da) {
49
- const fontMatch = da.match(/\/(\w+)\s+([\d.]+)\s+Tf/);
49
+ const fontMatch = da.match(/\/([\w-]+)\s+([\d.]+)\s+Tf/);
50
50
  if (!fontMatch)
51
51
  return null;
52
52
  const fontName = fontMatch[1];
@@ -94,6 +94,9 @@ export declare class PdfStream<T extends PdfDictionary = PdfDictionary> extends
94
94
  static fromString(data: string): PdfStream;
95
95
  }
96
96
  export declare class PdfObjStream extends PdfStream {
97
+ private _parsedObjects?;
98
+ set raw(data: ByteArray);
99
+ get raw(): ByteArray;
97
100
  constructor(options: {
98
101
  header: PdfDictionary;
99
102
  original: ByteArray | string;
@@ -101,6 +104,7 @@ export declare class PdfObjStream extends PdfStream {
101
104
  });
102
105
  static fromObjects(objects: Iterable<PdfIndirectObject>): PdfObjStream;
103
106
  getObjectStream(): Generator<PdfIndirectObject>;
107
+ private getParsedObjects;
104
108
  getObject(options: {
105
109
  objectNumber: number;
106
110
  }): PdfIndirectObject | undefined;
@@ -486,6 +486,14 @@ export class PdfStream extends PdfObject {
486
486
  }
487
487
  }
488
488
  export class PdfObjStream extends PdfStream {
489
+ _parsedObjects;
490
+ set raw(data) {
491
+ super.raw = data;
492
+ this._parsedObjects = undefined;
493
+ }
494
+ get raw() {
495
+ return super.raw;
496
+ }
489
497
  constructor(options) {
490
498
  super(options);
491
499
  if (!this.isType('ObjStm')) {
@@ -548,8 +556,11 @@ export class PdfObjStream extends PdfStream {
548
556
  const { value: obj, done } = reader.next();
549
557
  if (done)
550
558
  break;
551
- if (obj instanceof PdfNumber) {
552
- // Collect object numbers and byte offsets
559
+ if (obj instanceof PdfNumber &&
560
+ (totalObjects === 0 || numbers.length < totalObjects * 2)) {
561
+ // Collect object numbers and byte offsets from the header section.
562
+ // Stop once we have all 2*N pairs so that object values that happen
563
+ // to be plain integers are not mistakenly treated as header entries.
553
564
  numbers.push(obj);
554
565
  }
555
566
  else {
@@ -574,16 +585,20 @@ export class PdfObjStream extends PdfStream {
574
585
  }
575
586
  }
576
587
  }
577
- getObject(options) {
578
- for (const obj of this.getObjectStream()) {
579
- if (obj.objectNumber === options.objectNumber) {
580
- return obj;
588
+ getParsedObjects() {
589
+ if (!this._parsedObjects) {
590
+ this._parsedObjects = new Map();
591
+ for (const obj of this.getObjectStream()) {
592
+ this._parsedObjects.set(obj.objectNumber, obj);
581
593
  }
582
594
  }
583
- return undefined;
595
+ return this._parsedObjects;
596
+ }
597
+ getObject(options) {
598
+ return this.getParsedObjects().get(options.objectNumber);
584
599
  }
585
600
  getObjects() {
586
- return Array.from(this.getObjectStream());
601
+ return Array.from(this.getParsedObjects().values());
587
602
  }
588
603
  cloneImpl() {
589
604
  return new PdfObjStream({
@@ -42,7 +42,9 @@ export declare class PdfDocument extends PdfObject implements IPdfObjectResolver
42
42
  private originalSecurityHandler?;
43
43
  private hasEncryptionDictionary?;
44
44
  private _resolvedCache;
45
+ private _objStreamCache;
45
46
  private _committing;
47
+ private _updating;
46
48
  private _finalized;
47
49
  private _signed;
48
50
  /**
@@ -50,7 +50,9 @@ export class PdfDocument extends PdfObject {
50
50
  originalSecurityHandler;
51
51
  hasEncryptionDictionary = false;
52
52
  _resolvedCache = new Map();
53
+ _objStreamCache = new Map();
53
54
  _committing = false;
55
+ _updating = false;
54
56
  _finalized = false;
55
57
  _signed = false;
56
58
  /**
@@ -452,6 +454,14 @@ export class PdfDocument extends PdfObject {
452
454
  continue;
453
455
  }
454
456
  if (obj.isModified()) {
457
+ // Pre-register any new objects referenced by obj before
458
+ // cloning so the clone gets correct object numbers.
459
+ // Without this, proxy references (objectNumber = -1) get
460
+ // frozen into the clone as "-1 0 R" — a dangling reference.
461
+ const missing = this.collectMissingReferences(obj);
462
+ if (missing.length > 0) {
463
+ this.add(...missing);
464
+ }
455
465
  const adding = obj.clone();
456
466
  this.add(adding);
457
467
  adding.setModified(false);
@@ -573,19 +583,21 @@ export class PdfDocument extends PdfObject {
573
583
  if (!(xrefEntry instanceof PdfXRefStreamCompressedEntry)) {
574
584
  throw new Error('Cannot find object inside object stream via PdfDocument.findObject');
575
585
  }
576
- const objectStreamIndirect = this.findUncompressedObject({
577
- objectNumber: xrefEntry.objectStreamNumber.value,
578
- })?.clone();
579
- if (!objectStreamIndirect) {
580
- throw new Error(`Cannot find object stream ${xrefEntry.objectStreamNumber.value} for object ${options.objectNumber}`);
581
- }
582
- const objectStream = objectStreamIndirect.content
583
- .as(PdfStream)
584
- .parseAs(PdfObjStream);
585
- const decompressedObject = objectStream.getObject({
586
- objectNumber: options.objectNumber,
587
- });
588
- return decompressedObject;
586
+ const streamNumber = xrefEntry.objectStreamNumber.value;
587
+ let objectStream = this._objStreamCache.get(streamNumber);
588
+ if (!objectStream) {
589
+ const objectStreamIndirect = this.findUncompressedObject({
590
+ objectNumber: streamNumber,
591
+ });
592
+ if (!objectStreamIndirect) {
593
+ throw new Error(`Cannot find object stream ${streamNumber} for object ${options.objectNumber}`);
594
+ }
595
+ objectStream = objectStreamIndirect.content
596
+ .as(PdfStream)
597
+ .parseAs(PdfObjStream);
598
+ this._objStreamCache.set(streamNumber, objectStream);
599
+ }
600
+ return objectStream.getObject({ objectNumber: options.objectNumber });
589
601
  }
590
602
  /**
591
603
  * Finds an uncompressed indirect object by its object number.
@@ -880,20 +892,28 @@ export class PdfDocument extends PdfObject {
880
892
  * Performs a full update cycle to ensure all revisions are consistent and offsets are correct.
881
893
  */
882
894
  update() {
883
- this.commitIncrementalUpdates();
884
- this.flushResolvedCache();
885
- this.registerNewReferences();
886
- this.calculateOffsets();
887
- this.updateRevisions();
888
- // Second pass: xref binary may have changed size (e.g. FlateDecode removed
889
- // from xref stream), shifting objects that follow it. Recalculate so entry
890
- // byteOffset refs hold the new positions, then rebuild the xref binary once
891
- // more so the baked bytes match those positions.
892
- this.calculateOffsets();
893
- this.updateRevisions();
894
- // Third pass: confirm positions are stable (xref binary size should not
895
- // change again because W widths and entry count are the same).
896
- this.calculateOffsets();
895
+ if (this._updating)
896
+ return;
897
+ this._updating = true;
898
+ try {
899
+ this.commitIncrementalUpdates();
900
+ this.flushResolvedCache();
901
+ this.registerNewReferences();
902
+ this.calculateOffsets();
903
+ this.updateRevisions();
904
+ // Second pass: xref binary may have changed size (e.g. FlateDecode removed
905
+ // from xref stream), shifting objects that follow it. Recalculate so entry
906
+ // byteOffset refs hold the new positions, then rebuild the xref binary once
907
+ // more so the baked bytes match those positions.
908
+ this.calculateOffsets();
909
+ this.updateRevisions();
910
+ // Third pass: confirm positions are stable (xref binary size should not
911
+ // change again because W widths and entry count are the same).
912
+ this.calculateOffsets();
913
+ }
914
+ finally {
915
+ this._updating = false;
916
+ }
897
917
  }
898
918
  /**
899
919
  * Walks all objects in the document and registers any newly created
@@ -907,9 +927,11 @@ export class PdfDocument extends PdfObject {
907
927
  }
908
928
  }
909
929
  flushResolvedCache() {
930
+ const existing = new Set(this.objects);
910
931
  for (const [, obj] of this._resolvedCache) {
911
- if (obj.isModified() && !this.objects.includes(obj)) {
932
+ if (obj.isModified() && !existing.has(obj)) {
912
933
  this.add(obj);
934
+ existing.add(obj);
913
935
  }
914
936
  }
915
937
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdf-lite",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "exports": {