edfcore 0.3.19 → 0.3.20

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.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,26 @@ 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.3.20
10
+
11
+ - **Fixed** `byteSource` refusing an `ArrayBuffer` that crossed a realm boundary — an iframe, an
12
+ Electron contextBridge, jsdom, a Node `vm` context. The guard tested `bytes instanceof
13
+ ArrayBuffer`, which is false for a buffer created in another realm, so a real, fully usable
14
+ 552-byte file was rejected.
15
+ - The message made it worse twice over. `describe()` had no buffer branch, so it called the
16
+ ArrayBuffer **"a plain object"** — pointing the reader at the wrong problem entirely — and then
17
+ advised them to "pass ... the ArrayBuffer itself", which is exactly what they had done. Nothing
18
+ in it suggested the workaround that does work, `new Uint8Array(thatBuffer)`.
19
+ - **This was the last realm-unsafe `instanceof` on a cross-realm value in the package**, and it sat
20
+ twelve lines above the comment explaining why `instanceof` is wrong here, beside `isByteArray`,
21
+ which was rewritten off `instanceof` in 0.2.23 for this exact reason. The `SharedArrayBuffer`
22
+ half of the same expression already used the built-in tag. So a cross-realm `Uint8Array` was
23
+ accepted while the buffer behind it was not.
24
+ - Both halves now test `Object.prototype.toString`, which reads `Symbol.toStringTag` off the buffer
25
+ prototype and is a value every realm agrees on. It admits nothing new: a plain object, an Array,
26
+ a string and a number all report a different tag, and `Int8Array` is still refused for the
27
+ documented reason. `describe()` names buffers, so any future refusal says what it actually got.
28
+
9
29
  ## 0.3.19
10
30
 
11
31
  **Two places where content was dropped under a diagnostic saying it was not.** Both are annotation
@@ -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.3.19";
112
+ export declare const VERSION = "0.3.20";
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.3.19';
82
+ export const VERSION = '0.3.20';
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;AAe3D,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,CAsCtE"}
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;AAkC3D,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,CAoCtE"}
package/dist/io/bytes.js CHANGED
@@ -21,8 +21,26 @@ function describe(value) {
21
21
  return Object.prototype.toString.call(value).slice(8, -1);
22
22
  if (Array.isArray(value))
23
23
  return 'a plain Array';
24
+ // Buffers are named too. Without this a refusal called them "a plain object", which sent the
25
+ // reader looking for the wrong problem entirely.
26
+ if (BUFFER_TAGS.has(Object.prototype.toString.call(value))) {
27
+ return Object.prototype.toString.call(value).slice(8, -1);
28
+ }
24
29
  return typeof value === 'object' ? 'a plain object' : `a ${typeof value}`;
25
30
  }
31
+ /**
32
+ * The built-in tags, not `instanceof`.
33
+ *
34
+ * A tag comes from `Symbol.toStringTag` on the buffer prototype and every realm agrees on it;
35
+ * `instanceof ArrayBuffer` is false for a buffer that crossed a realm boundary — an iframe, an
36
+ * Electron contextBridge, jsdom, a Node `vm` context. Until 0.3.20 the ArrayBuffer half of the
37
+ * guard below used `instanceof` while the SharedArrayBuffer half already used the tag, so a real,
38
+ * fully usable ArrayBuffer from another realm was refused as "a plain object" and told to "pass
39
+ * the ArrayBuffer itself" — which is what the caller had done. `new Uint8Array(thatBuffer)` was
40
+ * accepted, because `isByteArray` twelve lines below was rewritten in 0.2.23 for this exact
41
+ * reason and this one was missed.
42
+ */
43
+ const BUFFER_TAGS = new Set(['[object ArrayBuffer]', '[object SharedArrayBuffer]']);
26
44
  export function byteSource(bytes) {
27
45
  // Refused at CONSTRUCTION, because the alternative is worse than an error. `new Uint8Array(x)`
28
46
  // accepts almost anything: a string, a plain object and `null` all yield an empty array, and a
@@ -33,8 +51,7 @@ export function byteSource(bytes) {
33
51
  // `Int8Array` is rejected too, and deliberately: it has one byte per element so it passes any
34
52
  // length check, and its already-signed elements are sign-extended a second time during decode
35
53
  // (see `assertExactRead`). Fabricated microvolts, with no error anywhere.
36
- const isBuffer = bytes instanceof ArrayBuffer ||
37
- Object.prototype.toString.call(bytes) === '[object SharedArrayBuffer]';
54
+ const isBuffer = BUFFER_TAGS.has(Object.prototype.toString.call(bytes));
38
55
  if (!isBuffer && !isByteArray(bytes)) {
39
56
  throw new EdfSourceError(`byteSource() needs an ArrayBuffer or a Uint8Array, received ${describe(bytes)}. ` +
40
57
  'Next: pass `new Uint8Array(await blob.arrayBuffer())`, `await readFile(path)`, or the ' +
@@ -1 +1 @@
1
- {"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/io/bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE5F;;;GAGG;AACH,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IAC5C,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACzF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,eAAe,CAAC;IACjD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,OAAO,KAAK,EAAE,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAA+B;IACxD,+FAA+F;IAC/F,+FAA+F;IAC/F,+FAA+F;IAC/F,gGAAgG;IAChG,4FAA4F;IAC5F,EAAE;IACF,8FAA8F;IAC9F,8FAA8F;IAC9F,0EAA0E;IAC1E,MAAM,QAAQ,GACZ,KAAK,YAAY,WAAW;QAC5B,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,4BAA4B,CAAC;IACzE,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,cAAc,CACtB,+DAA+D,QAAQ,CAAC,KAAK,CAAC,IAAI;YAChF,wFAAwF;YACxF,wFAAwF;YACxF,4EAA4E,EAC9E,EAAE,MAAM,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAClC,CAAC;IACJ,CAAC;IAED,2FAA2F;IAC3F,oFAAoF;IACpF,MAAM,IAAI,GAAe,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAoB,CAAC,CAAC;IAC3F,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IAEnC,OAAO;QACL,UAAU;QACV,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc,EAAE,OAAqB;YAC9D,cAAc,CAAC,OAAO,CAAC,CAAC;YACxB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;YAC5C,iFAAiF;YACjF,+EAA+E;YAC/E,OAAO,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACjF,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"bytes.js","sourceRoot":"","sources":["../../src/io/bytes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE5F;;;GAGG;AACH,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IAC5C,IAAI,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACzF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,eAAe,CAAC;IACjD,6FAA6F;IAC7F,iDAAiD;IACjD,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAC3D,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,OAAO,KAAK,EAAE,CAAC;AAC5E,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,sBAAsB,EAAE,4BAA4B,CAAC,CAAC,CAAC;AAEpF,MAAM,UAAU,UAAU,CAAC,KAA+B;IACxD,+FAA+F;IAC/F,+FAA+F;IAC/F,+FAA+F;IAC/F,gGAAgG;IAChG,4FAA4F;IAC5F,EAAE;IACF,8FAA8F;IAC9F,8FAA8F;IAC9F,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACxE,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,cAAc,CACtB,+DAA+D,QAAQ,CAAC,KAAK,CAAC,IAAI;YAChF,wFAAwF;YACxF,wFAAwF;YACxF,4EAA4E,EAC9E,EAAE,MAAM,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,CAClC,CAAC;IACJ,CAAC;IAED,2FAA2F;IAC3F,oFAAoF;IACpF,MAAM,IAAI,GAAe,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAoB,CAAC,CAAC;IAC3F,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IAEnC,OAAO;QACL,UAAU;QACV,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc,EAAE,OAAqB;YAC9D,cAAc,CAAC,OAAO,CAAC,CAAC;YACxB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;YAC5C,iFAAiF;YACjF,+EAA+E;YAC/E,OAAO,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACjF,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edfcore",
3
- "version": "0.3.19",
3
+ "version": "0.3.20",
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.3.19';
96
+ export const VERSION = '0.3.20';
package/src/io/bytes.ts CHANGED
@@ -20,9 +20,28 @@ function describe(value: unknown): string {
20
20
  if (value === undefined) return 'undefined';
21
21
  if (ArrayBuffer.isView(value)) return Object.prototype.toString.call(value).slice(8, -1);
22
22
  if (Array.isArray(value)) return 'a plain Array';
23
+ // Buffers are named too. Without this a refusal called them "a plain object", which sent the
24
+ // reader looking for the wrong problem entirely.
25
+ if (BUFFER_TAGS.has(Object.prototype.toString.call(value))) {
26
+ return Object.prototype.toString.call(value).slice(8, -1);
27
+ }
23
28
  return typeof value === 'object' ? 'a plain object' : `a ${typeof value}`;
24
29
  }
25
30
 
31
+ /**
32
+ * The built-in tags, not `instanceof`.
33
+ *
34
+ * A tag comes from `Symbol.toStringTag` on the buffer prototype and every realm agrees on it;
35
+ * `instanceof ArrayBuffer` is false for a buffer that crossed a realm boundary — an iframe, an
36
+ * Electron contextBridge, jsdom, a Node `vm` context. Until 0.3.20 the ArrayBuffer half of the
37
+ * guard below used `instanceof` while the SharedArrayBuffer half already used the tag, so a real,
38
+ * fully usable ArrayBuffer from another realm was refused as "a plain object" and told to "pass
39
+ * the ArrayBuffer itself" — which is what the caller had done. `new Uint8Array(thatBuffer)` was
40
+ * accepted, because `isByteArray` twelve lines below was rewritten in 0.2.23 for this exact
41
+ * reason and this one was missed.
42
+ */
43
+ const BUFFER_TAGS = new Set(['[object ArrayBuffer]', '[object SharedArrayBuffer]']);
44
+
26
45
  export function byteSource(bytes: ArrayBuffer | Uint8Array): ByteSource {
27
46
  // Refused at CONSTRUCTION, because the alternative is worse than an error. `new Uint8Array(x)`
28
47
  // accepts almost anything: a string, a plain object and `null` all yield an empty array, and a
@@ -33,9 +52,7 @@ export function byteSource(bytes: ArrayBuffer | Uint8Array): ByteSource {
33
52
  // `Int8Array` is rejected too, and deliberately: it has one byte per element so it passes any
34
53
  // length check, and its already-signed elements are sign-extended a second time during decode
35
54
  // (see `assertExactRead`). Fabricated microvolts, with no error anywhere.
36
- const isBuffer =
37
- bytes instanceof ArrayBuffer ||
38
- Object.prototype.toString.call(bytes) === '[object SharedArrayBuffer]';
55
+ const isBuffer = BUFFER_TAGS.has(Object.prototype.toString.call(bytes));
39
56
  if (!isBuffer && !isByteArray(bytes)) {
40
57
  throw new EdfSourceError(
41
58
  `byteSource() needs an ArrayBuffer or a Uint8Array, received ${describe(bytes)}. ` +