microcbor 1.2.0 → 1.2.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.
@@ -13,6 +13,8 @@ export declare class Decoder<T extends CBORValue = CBORValue> implements AsyncIt
13
13
  private readonly constantView;
14
14
  private readonly iter;
15
15
  private readonly onFree?;
16
+ private readonly touchedChunks;
17
+ private readonly freedChunks;
16
18
  constructor(source: AsyncIterable<Uint8Array>, options?: AsyncDecodeOptions);
17
19
  [Symbol.asyncIterator]: () => this;
18
20
  private allocate;
@@ -8,6 +8,8 @@ export class Decoder {
8
8
  this.chunks = [];
9
9
  this.constantBuffer = new ArrayBuffer(8);
10
10
  this.constantView = new DataView(this.constantBuffer);
11
+ this.touchedChunks = new WeakSet();
12
+ this.freedChunks = new WeakSet();
11
13
  this[_a] = () => this;
12
14
  this.constant = (size, f) => {
13
15
  return async () => {
@@ -30,6 +32,16 @@ export class Decoder {
30
32
  this.iter = source[Symbol.asyncIterator]();
31
33
  }
32
34
  async allocate(size) {
35
+ // If we need more data, first call onFree for all touched chunks
36
+ // This allows the transform stream to provide more chunks
37
+ if (this.byteLength < size && this.onFree !== undefined) {
38
+ for (const chunk of this.chunks) {
39
+ if (this.touchedChunks.has(chunk) && !this.freedChunks.has(chunk)) {
40
+ this.freedChunks.add(chunk);
41
+ this.onFree(chunk);
42
+ }
43
+ }
44
+ }
33
45
  while (this.byteLength < size) {
34
46
  const { done, value } = await this.iter.next();
35
47
  if (done) {
@@ -38,6 +50,12 @@ export class Decoder {
38
50
  else {
39
51
  this.chunks.push(value);
40
52
  this.byteLength += value.byteLength;
53
+ // If we still need more data after adding this chunk,
54
+ // immediately call onFree to allow the next chunk to flow
55
+ if (this.byteLength < size && this.onFree !== undefined && !this.freedChunks.has(value)) {
56
+ this.freedChunks.add(value);
57
+ this.onFree(value);
58
+ }
41
59
  }
42
60
  }
43
61
  }
@@ -49,6 +67,10 @@ export class Decoder {
49
67
  let deleteCount = 0;
50
68
  for (let i = 0; byteLength < target.byteLength; i++) {
51
69
  const chunk = this.chunks[i];
70
+ // Track which chunks we touched
71
+ if (!this.touchedChunks.has(chunk)) {
72
+ this.touchedChunks.add(chunk);
73
+ }
52
74
  const capacity = target.byteLength - byteLength;
53
75
  const length = chunk.byteLength - this.offset;
54
76
  if (length <= capacity) {
@@ -67,9 +89,14 @@ export class Decoder {
67
89
  this.byteLength -= capacity;
68
90
  }
69
91
  }
92
+ // Call onFree for chunks that are being removed (fully consumed)
70
93
  if (this.onFree !== undefined) {
71
94
  for (let i = 0; i < deleteCount; i++) {
72
- this.onFree(this.chunks[i]);
95
+ const chunk = this.chunks[i];
96
+ if (!this.freedChunks.has(chunk)) {
97
+ this.freedChunks.add(chunk);
98
+ this.onFree(chunk);
99
+ }
73
100
  }
74
101
  }
75
102
  this.chunks.splice(0, deleteCount);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "microcbor",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "lib"
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "homepage": "https://github.com/joeltg/microcbor#readme",
34
34
  "devDependencies": {
35
- "@ava/typescript": "^5.0.0",
35
+ "@ava/typescript": "^6.0.0",
36
36
  "@types/node": "^22.13.9",
37
37
  "ava": "^6.2.0",
38
38
  "cbor": "^10.0.3",