edfcore 0.5.64 → 0.5.66

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.
@@ -109,5 +109,5 @@ export declare const SIGNAL_FIELD_BLOCK_OFFSETS: {
109
109
  readonly reserved: 224;
110
110
  };
111
111
  /** Published package version. Kept in sync with package.json by a test. */
112
- export declare const VERSION = "0.5.64";
112
+ export declare const VERSION = "0.5.66";
113
113
  //# sourceMappingURL=constants.d.ts.map
package/dist/constants.js CHANGED
@@ -79,5 +79,5 @@ export const SIGNAL_FIELD_BLOCK_OFFSETS = {
79
79
  reserved: 224,
80
80
  };
81
81
  /** Published package version. Kept in sync with package.json by a test. */
82
- export const VERSION = '0.5.64';
82
+ export const VERSION = '0.5.66';
83
83
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../src/io/bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,aAAa,CAAC;AAsD3D;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,CAkDtE"}
1
+ {"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../src/io/bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,aAAa,CAAC;AAsD3D;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,CAyDtE"}
package/dist/io/bytes.js CHANGED
@@ -102,6 +102,14 @@ export function byteSource(bytes) {
102
102
  async read(offset, length, options) {
103
103
  throwIfAborted(options);
104
104
  assertReadRange(offset, length, byteLength);
105
+ // `view.byteLength` is live: it follows a `resize`, and it reads 0 once the buffer has
106
+ // been transferred away. A detached view makes `subarray` throw a bare `TypeError` —
107
+ // "Cannot perform Construct on a detached ArrayBuffer" — which is outside the error model
108
+ // this package promises, and it escapes from a source that was perfectly good when it was
109
+ // built. Handed to the guard below instead, it is the same short read a buffer that shrank
110
+ // already earns, with the same message and the same fields on it.
111
+ if (view.byteLength === 0)
112
+ return assertExactRead(new Uint8Array(0), offset, length);
105
113
  // `subarray` is relative to this view, so a Uint8Array handed in with a non-zero
106
114
  // byteOffset over a larger buffer is respected with no offset arithmetic here.
107
115
  return assertExactRead(view.subarray(offset, offset + length), offset, length);
@@ -1 +1 @@
1
- {"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/io/bytes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/io/bytes.ts"],"names":[],"mappings":"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"}
package/docs/CHANGELOG.md CHANGED
@@ -6,6 +6,45 @@ alone does not tell you whether you were affected.
6
6
  edfcore is pre-1.0. Patch releases have carried behaviour changes where the old behaviour was a
7
7
  defect; those are called out below.
8
8
 
9
+ ## 0.5.66
10
+
11
+ - **Fixed** a bare `TypeError` escaping `byteSource`. When the caller's buffer was transferred away
12
+ after the source was built — `postMessage(bytes, [bytes.buffer])`, which is how a recording gets
13
+ handed to a worker — the next read reached `view.subarray()` on a detached view and threw
14
+ `Cannot perform Construct on a detached ArrayBuffer`. 0.5.62 refuses a buffer that is already
15
+ detached at construction; this is the same buffer detached one line later, and construction
16
+ cannot see it coming.
17
+ - The escape is the part that matters. `tests/README.md` states the safety property as "for any
18
+ byte sequence, edfcore either parses it or throws an `EdfError`", and `fuzz.test.ts` calls
19
+ anything else a leak: "a bare `TypeError`, an 'undefined is not a function', or a `RangeError`
20
+ out of an allocation are all failures, not tolerated outcomes". A `catch` branching on
21
+ `isEdfError` fell through to a rethrow, from a source that was perfectly good when it was made.
22
+ - `view.byteLength` follows the buffer — it reads 0 once the bytes are gone, and it follows a
23
+ `resize` — so the read now hands the empty result to the same guard a buffer that shrank already
24
+ goes through. The refusal is an `EdfSourceError` with `offset`, `requestedLength` and
25
+ `receivedLength: 0` on it, which is what it was for every other way of losing the bytes. A
26
+ zero-length read still succeeds, because it asked for nothing.
27
+
28
+ ## 0.5.65
29
+
30
+ - **Added** the question two of the three bundled adapters already answer, asked of the third.
31
+ `blobSource` is shrunk under an open source in `source-contract.test.ts` — "a `File` whose
32
+ backing file changed on disk since the picker ran" — and `fileHandleSource` gets the same
33
+ treatment against a file that turned out shorter than it was built for. `byteSource` was never
34
+ asked, because until recently there was nothing to ask: an `ArrayBuffer` was a fixed extent for
35
+ its whole life, so measuring it once at construction stayed true.
36
+ - It is not fixed any more. `resize` changes the length in place and `transfer` takes the bytes
37
+ away, and both leave the caller holding a `Uint8Array` that looks exactly as it did.
38
+ - `when-the-bytes-move.test.ts` gives the three outcomes, which differ. SHRINKING is caught by the
39
+ contract guard every read goes through, with both numbers on the refusal — including mid-
40
+ recording, where a header has already been read and a reader would otherwise decode whatever is
41
+ left as the records it asked for. TRANSFERRING is refused at construction, since 0.5.62. GROWING
42
+ is invisible, and that is the answer rather than a defect: `byteLength` is the extent the caller
43
+ presented, and a source that silently grew would change what `header.recordCount` means for a
44
+ file already open.
45
+ - The adapters are read off `src/io/` rather than listed, so a fourth fails this file until it says
46
+ which of the three it does.
47
+
9
48
  ## 0.5.64
10
49
 
11
50
  - **Added** the reading half of "edfcore reads, it does not write". `reads-not-writes.test.ts`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edfcore",
3
- "version": "0.5.64",
3
+ "version": "0.5.66",
4
4
  "description": "Modern, typed, zero-dependency reader for EDF, EDF+, BDF and BDF+ biosignal files. Works in browsers and Node with true random access.",
5
5
  "keywords": [
6
6
  "edf",
package/src/constants.ts CHANGED
@@ -93,4 +93,4 @@ export const SIGNAL_FIELD_BLOCK_OFFSETS = {
93
93
  } as const;
94
94
 
95
95
  /** Published package version. Kept in sync with package.json by a test. */
96
- export const VERSION = '0.5.64';
96
+ export const VERSION = '0.5.66';
package/src/io/bytes.ts CHANGED
@@ -112,6 +112,13 @@ export function byteSource(bytes: ArrayBuffer | Uint8Array): ByteSource {
112
112
  async read(offset: number, length: number, options?: ReadOptions): Promise<Uint8Array> {
113
113
  throwIfAborted(options);
114
114
  assertReadRange(offset, length, byteLength);
115
+ // `view.byteLength` is live: it follows a `resize`, and it reads 0 once the buffer has
116
+ // been transferred away. A detached view makes `subarray` throw a bare `TypeError` —
117
+ // "Cannot perform Construct on a detached ArrayBuffer" — which is outside the error model
118
+ // this package promises, and it escapes from a source that was perfectly good when it was
119
+ // built. Handed to the guard below instead, it is the same short read a buffer that shrank
120
+ // already earns, with the same message and the same fields on it.
121
+ if (view.byteLength === 0) return assertExactRead(new Uint8Array(0), offset, length);
115
122
  // `subarray` is relative to this view, so a Uint8Array handed in with a non-zero
116
123
  // byteOffset over a larger buffer is respected with no offset arithmetic here.
117
124
  return assertExactRead(view.subarray(offset, offset + length), offset, length);