pdf-lite 1.6.3 → 1.6.4

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.
@@ -32,7 +32,7 @@ export class PdfButtonFormField extends PdfFormField {
32
32
  resolved = 'Off';
33
33
  }
34
34
  else {
35
- resolved = states.find((s) => s !== 'Off') ?? 'Yes';
35
+ resolved = states.find((s) => s !== 'Off') ?? strVal;
36
36
  }
37
37
  this.content.set('V', new PdfName(resolved));
38
38
  fieldParent?.content.set('V', new PdfName(resolved));
@@ -519,7 +519,7 @@ export class PdfFormField extends PdfWidgetAnnotation {
519
519
  get appearanceStates() {
520
520
  const n = this.appearanceStreamDict?.get('N');
521
521
  if (n instanceof PdfDictionary) {
522
- return Array.from(n.entries(), ([key]) => key);
522
+ return n.keys().map((k) => k.value);
523
523
  }
524
524
  return [];
525
525
  }
@@ -13,11 +13,14 @@ export function* bytesToPdfObjects(bytes) {
13
13
  const decoder = new PdfDecoder();
14
14
  for (const chunk of bytes) {
15
15
  tokeniser.feedBytes(chunk);
16
+ // Feed all tokens from this chunk first, then drain completed objects
17
+ // once. Draining after every token is O(n²) because each failed parse
18
+ // attempt re-reads all accumulated tokens for the current partial object.
16
19
  for (const token of tokeniser.nextItems()) {
17
20
  decoder.feed(token);
18
- for (const obj of decoder.nextItems()) {
19
- yield obj;
20
- }
21
+ }
22
+ for (const obj of decoder.nextItems()) {
23
+ yield obj;
21
24
  }
22
25
  }
23
26
  tokeniser.eof = true;
@@ -79,11 +82,14 @@ export async function* pdfDecoderAsync(input) {
79
82
  const decoder = new PdfDecoder();
80
83
  for await (const chunk of input) {
81
84
  tokeniser.feedBytes(chunk);
85
+ // Feed all tokens from this chunk first, then drain completed objects
86
+ // once. Draining after every token is O(n²) because each failed parse
87
+ // attempt re-reads all accumulated tokens for the current partial object.
82
88
  for (const token of tokeniser.nextItems()) {
83
89
  decoder.feed(token);
84
- for (const obj of decoder.nextItems()) {
85
- yield obj;
86
- }
90
+ }
91
+ for (const obj of decoder.nextItems()) {
92
+ yield obj;
87
93
  }
88
94
  }
89
95
  tokeniser.eof = true;
@@ -8,6 +8,7 @@ export declare class PdfDictionary<T extends PdfDictionaryEntries = PdfDictionar
8
8
  #private;
9
9
  innerTokens: PdfToken[];
10
10
  constructor(entries?: T | PdfDictionaryMap);
11
+ keys(): PdfName[];
11
12
  get<K extends Extract<keyof T, string>>(key: PdfName<K> | K): T[K] | undefined;
12
13
  set<K extends Extract<keyof T, string>>(key: PdfName<K> | K, value: T[K]): void;
13
14
  delete<K extends Extract<keyof T, string>>(key: PdfName<K> | K): void;
@@ -16,6 +16,9 @@ export class PdfDictionary extends PdfObject {
16
16
  }
17
17
  }
18
18
  }
19
+ keys() {
20
+ return Array.from(this.#entries.keys());
21
+ }
19
22
  get(key) {
20
23
  if (key instanceof PdfName) {
21
24
  return this.#entries.get(key);
@@ -70,8 +70,13 @@ export declare abstract class IncrementalParser<I, O> extends Parser<I, O> {
70
70
  */
71
71
  protected compact(): void;
72
72
  /**
73
- * Override to customize when to compact the buffer
74
- * By default, compacts when more than 1000 items have been consumed
73
+ * Override to customize when to compact the buffer.
74
+ * Compacts when more than 1000 items have been consumed AND we've consumed
75
+ * at least half the buffer. The second condition prevents O(n²) behaviour
76
+ * when a single large chunk is fed all at once: without it, compact() is
77
+ * called O(n/1000) times, each copying O(n) elements → O(n²) total.
78
+ * By requiring bufferIndex ≥ buffer.length/2 we ensure at most O(log n)
79
+ * compactions, for O(n) total copies.
75
80
  *
76
81
  * @returns boolean indicating whether to compact the buffer
77
82
  */
@@ -139,13 +139,19 @@ export class IncrementalParser extends Parser {
139
139
  }
140
140
  }
141
141
  /**
142
- * Override to customize when to compact the buffer
143
- * By default, compacts when more than 1000 items have been consumed
142
+ * Override to customize when to compact the buffer.
143
+ * Compacts when more than 1000 items have been consumed AND we've consumed
144
+ * at least half the buffer. The second condition prevents O(n²) behaviour
145
+ * when a single large chunk is fed all at once: without it, compact() is
146
+ * called O(n/1000) times, each copying O(n) elements → O(n²) total.
147
+ * By requiring bufferIndex ≥ buffer.length/2 we ensure at most O(log n)
148
+ * compactions, for O(n) total copies.
144
149
  *
145
150
  * @returns boolean indicating whether to compact the buffer
146
151
  */
147
152
  canCompact() {
148
- return this.bufferIndex > 1000;
153
+ return (this.bufferIndex >= 1000 &&
154
+ this.bufferIndex >= this.buffer.length >> 1);
149
155
  }
150
156
  /**
151
157
  * Generates parsed output items from the buffer.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdf-lite",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "exports": {