edfcore 0.3.41 → 0.3.43
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 +33 -0
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/decode/physical.js +2 -2
- package/dist/decode/physical.js.map +1 -1
- package/dist/io/cached.d.ts.map +1 -1
- package/dist/io/cached.js +24 -3
- package/dist/io/cached.js.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/decode/physical.ts +2 -2
- package/src/io/cached.ts +25 -3
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,39 @@ 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.43
|
|
10
|
+
|
|
11
|
+
- **Fixed** `cachedSource` letting one reader's abort cancel unrelated concurrent readers. A block
|
|
12
|
+
read serves every reader of that block — the dedup is the point — but it carried the FIRST
|
|
13
|
+
caller's options, `signal` included. Aborting one reader rejected the others, **including a
|
|
14
|
+
reader that passed no signal at all**, with `AbortError: The read was aborted through
|
|
15
|
+
options.signal` describing something that never happened to it.
|
|
16
|
+
- That is the ordinary stale-request pattern in a viewer: the user scrolls, the app aborts the
|
|
17
|
+
window they left and issues the new one. Both land in the same 1 MiB block, and the **fresh**
|
|
18
|
+
window is the one that dies. Because the message reads as self-cancellation, the app's own
|
|
19
|
+
`catch` swallows it — a blank panel and no error anywhere. Which reader died depended on which
|
|
20
|
+
touched the block first.
|
|
21
|
+
- The shared read no longer carries a signal. `read` already polls each caller's own signal before
|
|
22
|
+
and after the block joins, so an aborting caller still rejects promptly; it simply no longer
|
|
23
|
+
decides for anyone else. The cost is that an abort does not tear down the underlying request,
|
|
24
|
+
which is the right trade for a read other readers are waiting on — the bytes are valid and
|
|
25
|
+
already paid for, so they are admitted to the cache and a later read is served from it.
|
|
26
|
+
- One underlying read per block, exactly as before. `maxMaterializeBytes` still travels with the
|
|
27
|
+
shared read, because that one genuinely is a property of the fetch rather than of a caller.
|
|
28
|
+
|
|
29
|
+
## 0.3.42
|
|
30
|
+
|
|
31
|
+
- **Fixed** `toPhysical` and `clampToDigitalRange` reporting a *"NaN-byte maxMaterializeBytes
|
|
32
|
+
budget"* — the exact message 0.3.21 says it eliminated — and advising the caller to "produce
|
|
33
|
+
fewer samples per call", which no sample count can satisfy against `NaN`.
|
|
34
|
+
- 0.3.21 routed four budget reads through one resolver and **missed a fifth**: `decode/physical.ts`
|
|
35
|
+
carries its own copy of the guard, and grepping for the option's name found the four in the I/O
|
|
36
|
+
and scan paths. They are the only two allocating primitives on the public surface that never
|
|
37
|
+
validated it.
|
|
38
|
+
- Both now go through `resolveMaterializeBudget`, so a non-finite or negative value is a plain
|
|
39
|
+
`RangeError` naming `options.maxMaterializeBytes` and pointing at the expression that produced
|
|
40
|
+
it. A real budget still refuses a too-large allocation exactly as before, which is asserted.
|
|
41
|
+
|
|
9
42
|
## 0.3.41
|
|
10
43
|
|
|
11
44
|
- **Fixed** `mergeChunks` refusing an overlap with *"chunk 1 is preceded by a gap of -0.2 s"* — a
|
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.43";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
package/dist/decode/physical.js
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
* read: EDFlib clamps silently when it loads samples, edfcore does not, and reproducing that
|
|
9
9
|
* behaviour has to be something a caller asks for explicitly.
|
|
10
10
|
*/
|
|
11
|
-
import { DEFAULT_MAX_MATERIALIZE_BYTES } from '../constants.js';
|
|
12
11
|
import { EdfBudgetError, EdfScalingError } from '../errors.js';
|
|
12
|
+
import { resolveMaterializeBudget } from '../options.js';
|
|
13
13
|
const BYTES_PER_FLOAT64 = 8;
|
|
14
14
|
const BYTES_PER_INT32 = 4;
|
|
15
15
|
/** The physical dimension that marks a log-compressed channel (EDFlib `edffloat.html`). */
|
|
16
16
|
const LOG_TRANSFORMED_DIMENSION = 'Filtered';
|
|
17
17
|
function assertWithinBudget(requiredBytes, what, options) {
|
|
18
|
-
const budgetBytes = options?.maxMaterializeBytes
|
|
18
|
+
const budgetBytes = resolveMaterializeBudget(options?.maxMaterializeBytes);
|
|
19
19
|
if (requiredBytes <= budgetBytes)
|
|
20
20
|
return;
|
|
21
21
|
throw new EdfBudgetError(`Producing ${what} needs a ${requiredBytes}-byte array, above the ${budgetBytes}-byte ` +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"physical.js","sourceRoot":"","sources":["../../src/decode/physical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"physical.js","sourceRoot":"","sources":["../../src/decode/physical.ts"],"names":[],"mappings":"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"}
|
package/dist/io/cached.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cached.d.ts","sourceRoot":"","sources":["../../src/io/cached.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AAmBzE,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"cached.d.ts","sourceRoot":"","sources":["../../src/io/cached.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AAmBzE,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,UAAU,CA4InF"}
|
package/dist/io/cached.js
CHANGED
|
@@ -65,10 +65,31 @@ export function cachedSource(source, options) {
|
|
|
65
65
|
cachedBytes += block.byteLength;
|
|
66
66
|
evict();
|
|
67
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* The shared block read, deliberately WITHOUT the caller's signal.
|
|
70
|
+
*
|
|
71
|
+
* One block read serves every concurrent reader of that block, so letting one of them cancel it
|
|
72
|
+
* cancels the others. A viewer using the ordinary stale-request pattern — abort the controller
|
|
73
|
+
* for the window the user scrolled away from — killed the FRESH window whenever both landed in
|
|
74
|
+
* the same block, with `AbortError: The read was aborted through options.signal` describing
|
|
75
|
+
* something that never happened to it. A reader that passed no signal at all was rejected the
|
|
76
|
+
* same way, and because the message reads as self-cancellation the app's own `catch` swallows
|
|
77
|
+
* it: a blank panel and no error anywhere. Which reader died depended on which touched the
|
|
78
|
+
* block first (fixed in 0.3.43).
|
|
79
|
+
*
|
|
80
|
+
* `read` already polls each caller's own signal before and after `Promise.all`, so an aborting
|
|
81
|
+
* caller still rejects promptly — it simply no longer decides for anyone else. The cost is that
|
|
82
|
+
* an abort does not tear down the underlying request, which is the right trade for a read whose
|
|
83
|
+
* result other readers are waiting on: the bytes are valid and already paid for, so they are
|
|
84
|
+
* admitted to the cache.
|
|
85
|
+
*/
|
|
68
86
|
async function fetchBlock(index, options) {
|
|
69
87
|
const start = index * blockBytes;
|
|
70
88
|
const length = Math.min(blockBytes, byteLength - start);
|
|
71
|
-
|
|
89
|
+
const shared = options?.maxMaterializeBytes === undefined
|
|
90
|
+
? undefined
|
|
91
|
+
: { maxMaterializeBytes: options.maxMaterializeBytes };
|
|
92
|
+
return assertExactRead(await source.read(start, length, shared), start, length);
|
|
72
93
|
}
|
|
73
94
|
function blockFor(index, options) {
|
|
74
95
|
const cached = blocks.get(index);
|
|
@@ -78,8 +99,8 @@ export function cachedSource(source, options) {
|
|
|
78
99
|
return Promise.resolve(cached);
|
|
79
100
|
}
|
|
80
101
|
const pending = inflight.get(index);
|
|
81
|
-
// Deduped readers share
|
|
82
|
-
//
|
|
102
|
+
// Deduped readers share one underlying read, which is the whole point. They no longer share a
|
|
103
|
+
// signal — see `fetchBlock`.
|
|
83
104
|
if (pending !== undefined)
|
|
84
105
|
return pending;
|
|
85
106
|
const started = fetchBlock(index, options)
|
package/dist/io/cached.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cached.js","sourceRoot":"","sources":["../../src/io/cached.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/E,MAAM,mBAAmB,GAAG,IAAI,GAAG,IAAI,CAAC;AACxC,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,yFAAyF;AACzF,SAAS,WAAW,CAAC,MAAkB;IACrC,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc,EAAE,OAAqB;YAC9D,OAAO,eAAe,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACrF,CAAC;QACD,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAkB,EAAE,OAAsB;IACrE,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CACvB,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAClF,CAAC;IACF,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAClC,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC,CACxF,CAAC;IACF,0FAA0F;IAC1F,6FAA6F;IAC7F,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAC3D,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;IAE/C,wFAAwF;IACxF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;IACxD,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,SAAS,KAAK;QACZ,2FAA2F;QAC3F,0CAA0C;QAC1C,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YACpC,IAAI,WAAW,IAAI,QAAQ;gBAAE,OAAO;YACpC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACrB,WAAW,IAAI,KAAK,CAAC,UAAU,CAAC;QAClC,CAAC;IACH,CAAC;IAED,gGAAgG;IAChG,iGAAiG;IACjG,+FAA+F;IAC/F,qFAAqF;IACrF,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,SAAS,KAAK,CAAC,KAAa,EAAE,KAAiB;QAC7C,IAAI,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO;QACxC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACzB,WAAW,IAAI,KAAK,CAAC,UAAU,CAAC;QAChC,KAAK,EAAE,CAAC;IACV,CAAC;IAED,KAAK,UAAU,UAAU,CAAC,KAAa,EAAE,OAAqB;QAC5D,MAAM,KAAK,GAAG,KAAK,GAAG,UAAU,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,KAAK,CAAC,CAAC;QACxD,OAAO,eAAe,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"cached.js","sourceRoot":"","sources":["../../src/io/cached.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/E,MAAM,mBAAmB,GAAG,IAAI,GAAG,IAAI,CAAC;AACxC,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,yFAAyF;AACzF,SAAS,WAAW,CAAC,MAAkB;IACrC,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAc,EAAE,OAAqB;YAC9D,OAAO,eAAe,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACrF,CAAC;QACD,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAkB,EAAE,OAAsB;IACrE,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CACvB,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAClF,CAAC;IACF,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAClC,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,mBAAmB,CAAC,CAAC,CACxF,CAAC;IACF,0FAA0F;IAC1F,6FAA6F;IAC7F,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAC3D,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;IAE/C,wFAAwF;IACxF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA+B,CAAC;IACxD,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,SAAS,KAAK;QACZ,2FAA2F;QAC3F,0CAA0C;QAC1C,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YACpC,IAAI,WAAW,IAAI,QAAQ;gBAAE,OAAO;YACpC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACrB,WAAW,IAAI,KAAK,CAAC,UAAU,CAAC;QAClC,CAAC;IACH,CAAC;IAED,gGAAgG;IAChG,iGAAiG;IACjG,+FAA+F;IAC/F,qFAAqF;IACrF,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,SAAS,KAAK,CAAC,KAAa,EAAE,KAAiB;QAC7C,IAAI,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO;QACxC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACzB,WAAW,IAAI,KAAK,CAAC,UAAU,CAAC;QAChC,KAAK,EAAE,CAAC;IACV,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,UAAU,UAAU,CAAC,KAAa,EAAE,OAAqB;QAC5D,MAAM,KAAK,GAAG,KAAK,GAAG,UAAU,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,KAAK,CAAC,CAAC;QACxD,MAAM,MAAM,GACV,OAAO,EAAE,mBAAmB,KAAK,SAAS;YACxC,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,EAAE,mBAAmB,EAAE,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAC3D,OAAO,eAAe,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAClF,CAAC;IAED,SAAS,QAAQ,CAAC,KAAa,EAAE,OAAqB;QACpD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACrB,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC1B,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,8FAA8F;QAC9F,6BAA6B;QAC7B,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,OAAO,CAAC;QAE1C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC;aACvC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACd,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACpB,OAAO,KAAK,CAAC;QACf,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QACL,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC7B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,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,IAAI,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;YAC3C,0FAA0F;YAC1F,wFAAwF;YACxF,6FAA6F;YAC7F,6FAA6F;YAC7F,4FAA4F;YAC5F,WAAW;YACX,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;gBACtB,OAAO,eAAe,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACrF,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;YACjE,MAAM,OAAO,GAA+B,EAAE,CAAC;YAC/C,KAAK,IAAI,KAAK,GAAG,UAAU,EAAE,KAAK,IAAI,SAAS,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;gBAC5D,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;YACzC,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC5C,cAAc,CAAC,OAAO,CAAC,CAAC;YAExB,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;YACnC,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;gBACnD,MAAM,UAAU,GAAG,CAAC,UAAU,GAAG,QAAQ,CAAC,GAAG,UAAU,CAAC;gBACxD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAC1C,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC;gBACpE,IAAI,EAAE,IAAI,IAAI;oBAAE,SAAS;gBACzB,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,GAAG,UAAU,EAAE,EAAE,GAAG,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC,CAAC;YAC7E,CAAC;YACD,OAAO,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC9C,CAAC;QACD,KAAK,CAAC,KAAK;YACT,4FAA4F;YAC5F,8EAA8E;YAC9E,MAAM,GAAG,IAAI,CAAC;YACd,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,QAAQ,CAAC,KAAK,EAAE,CAAC;YACjB,WAAW,GAAG,CAAC,CAAC;YAChB,MAAM,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
package/src/decode/physical.ts
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
* behaviour has to be something a caller asks for explicitly.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { DEFAULT_MAX_MATERIALIZE_BYTES } from '../constants.js';
|
|
13
12
|
import { EdfBudgetError, EdfScalingError } from '../errors.js';
|
|
13
|
+
import { resolveMaterializeBudget } from '../options.js';
|
|
14
14
|
import type { EdfDiagnosticCode, EdfSignal } from '../types.js';
|
|
15
15
|
import type { MaterializeOptions } from './digital.js';
|
|
16
16
|
|
|
@@ -40,7 +40,7 @@ function assertWithinBudget(
|
|
|
40
40
|
what: string,
|
|
41
41
|
options: MaterializeOptions | undefined,
|
|
42
42
|
): void {
|
|
43
|
-
const budgetBytes = options?.maxMaterializeBytes
|
|
43
|
+
const budgetBytes = resolveMaterializeBudget(options?.maxMaterializeBytes);
|
|
44
44
|
if (requiredBytes <= budgetBytes) return;
|
|
45
45
|
throw new EdfBudgetError(
|
|
46
46
|
`Producing ${what} needs a ${requiredBytes}-byte array, above the ${budgetBytes}-byte ` +
|
package/src/io/cached.ts
CHANGED
|
@@ -78,10 +78,32 @@ export function cachedSource(source: ByteSource, options?: CacheOptions): ByteSo
|
|
|
78
78
|
evict();
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* The shared block read, deliberately WITHOUT the caller's signal.
|
|
83
|
+
*
|
|
84
|
+
* One block read serves every concurrent reader of that block, so letting one of them cancel it
|
|
85
|
+
* cancels the others. A viewer using the ordinary stale-request pattern — abort the controller
|
|
86
|
+
* for the window the user scrolled away from — killed the FRESH window whenever both landed in
|
|
87
|
+
* the same block, with `AbortError: The read was aborted through options.signal` describing
|
|
88
|
+
* something that never happened to it. A reader that passed no signal at all was rejected the
|
|
89
|
+
* same way, and because the message reads as self-cancellation the app's own `catch` swallows
|
|
90
|
+
* it: a blank panel and no error anywhere. Which reader died depended on which touched the
|
|
91
|
+
* block first (fixed in 0.3.43).
|
|
92
|
+
*
|
|
93
|
+
* `read` already polls each caller's own signal before and after `Promise.all`, so an aborting
|
|
94
|
+
* caller still rejects promptly — it simply no longer decides for anyone else. The cost is that
|
|
95
|
+
* an abort does not tear down the underlying request, which is the right trade for a read whose
|
|
96
|
+
* result other readers are waiting on: the bytes are valid and already paid for, so they are
|
|
97
|
+
* admitted to the cache.
|
|
98
|
+
*/
|
|
81
99
|
async function fetchBlock(index: number, options?: ReadOptions): Promise<Uint8Array> {
|
|
82
100
|
const start = index * blockBytes;
|
|
83
101
|
const length = Math.min(blockBytes, byteLength - start);
|
|
84
|
-
|
|
102
|
+
const shared: ReadOptions | undefined =
|
|
103
|
+
options?.maxMaterializeBytes === undefined
|
|
104
|
+
? undefined
|
|
105
|
+
: { maxMaterializeBytes: options.maxMaterializeBytes };
|
|
106
|
+
return assertExactRead(await source.read(start, length, shared), start, length);
|
|
85
107
|
}
|
|
86
108
|
|
|
87
109
|
function blockFor(index: number, options?: ReadOptions): Promise<Uint8Array> {
|
|
@@ -92,8 +114,8 @@ export function cachedSource(source: ByteSource, options?: CacheOptions): ByteSo
|
|
|
92
114
|
return Promise.resolve(cached);
|
|
93
115
|
}
|
|
94
116
|
const pending = inflight.get(index);
|
|
95
|
-
// Deduped readers share
|
|
96
|
-
//
|
|
117
|
+
// Deduped readers share one underlying read, which is the whole point. They no longer share a
|
|
118
|
+
// signal — see `fetchBlock`.
|
|
97
119
|
if (pending !== undefined) return pending;
|
|
98
120
|
|
|
99
121
|
const started = fetchBlock(index, options)
|