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 +20 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/io/bytes.d.ts.map +1 -1
- package/dist/io/bytes.js +19 -2
- package/dist/io/bytes.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/io/bytes.ts +20 -3
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
|
package/dist/constants.d.ts
CHANGED
|
@@ -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.
|
|
112
|
+
export declare const VERSION = "0.3.20";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
package/dist/io/bytes.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
|
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 ' +
|
package/dist/io/bytes.js.map
CHANGED
|
@@ -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,
|
|
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
package/src/constants.ts
CHANGED
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)}. ` +
|