@elaraai/east 1.0.83 → 1.0.85

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.
Files changed (252) hide show
  1. package/dist/src/analyze.d.ts.map +1 -1
  2. package/dist/src/analyze.js +48 -0
  3. package/dist/src/analyze.js.map +1 -1
  4. package/dist/src/ast_to_ir.coerce_to.spec.js +4 -4
  5. package/dist/src/ast_to_ir.coerce_to.spec.js.map +1 -1
  6. package/dist/src/ast_to_ir.d.ts +6 -1
  7. package/dist/src/ast_to_ir.d.ts.map +1 -1
  8. package/dist/src/ast_to_ir.js +20 -7
  9. package/dist/src/ast_to_ir.js.map +1 -1
  10. package/dist/src/builtins.d.ts +1 -1
  11. package/dist/src/builtins.d.ts.map +1 -1
  12. package/dist/src/builtins.js +52 -0
  13. package/dist/src/builtins.js.map +1 -1
  14. package/dist/src/codegen/canonical.d.ts +37 -0
  15. package/dist/src/codegen/canonical.d.ts.map +1 -0
  16. package/dist/src/codegen/canonical.js +208 -0
  17. package/dist/src/codegen/canonical.js.map +1 -0
  18. package/dist/src/codegen/codegen.spec.js +132 -201
  19. package/dist/src/codegen/codegen.spec.js.map +1 -1
  20. package/dist/src/codegen/printer.d.ts.map +1 -1
  21. package/dist/src/codegen/printer.js +142 -24
  22. package/dist/src/codegen/printer.js.map +1 -1
  23. package/dist/src/codegen/spellings.d.ts +4 -1
  24. package/dist/src/codegen/spellings.d.ts.map +1 -1
  25. package/dist/src/codegen/spellings.js +5 -1
  26. package/dist/src/codegen/spellings.js.map +1 -1
  27. package/dist/src/compile/builtins/index.d.ts.map +1 -1
  28. package/dist/src/compile/builtins/index.js +2 -0
  29. package/dist/src/compile/builtins/index.js.map +1 -1
  30. package/dist/src/compile/builtins/primitives.d.ts.map +1 -1
  31. package/dist/src/compile/builtins/primitives.js +2 -1
  32. package/dist/src/compile/builtins/primitives.js.map +1 -1
  33. package/dist/src/compile/builtins/query.d.ts +10 -0
  34. package/dist/src/compile/builtins/query.d.ts.map +1 -0
  35. package/dist/src/compile/builtins/query.js +5 -0
  36. package/dist/src/compile/builtins/query.js.map +1 -0
  37. package/dist/src/expr/block.d.ts.map +1 -1
  38. package/dist/src/expr/block.js +2 -1
  39. package/dist/src/expr/block.js.map +1 -1
  40. package/dist/src/expr/index.d.ts +75 -47
  41. package/dist/src/expr/index.d.ts.map +1 -1
  42. package/dist/src/expr/index.js +31 -0
  43. package/dist/src/expr/index.js.map +1 -1
  44. package/dist/src/expr/libs/datetime.d.ts +20 -20
  45. package/dist/src/expr/libs/datetime.d.ts.map +1 -1
  46. package/dist/src/expr/libs/datetime.js +208 -167
  47. package/dist/src/expr/libs/datetime.js.map +1 -1
  48. package/dist/src/expr/libs/float.d.ts +15 -15
  49. package/dist/src/expr/libs/float.d.ts.map +1 -1
  50. package/dist/src/expr/libs/float.js +298 -267
  51. package/dist/src/expr/libs/float.js.map +1 -1
  52. package/dist/src/expr/libs/integer.d.ts +12 -12
  53. package/dist/src/expr/libs/integer.d.ts.map +1 -1
  54. package/dist/src/expr/libs/integer.js +219 -194
  55. package/dist/src/expr/libs/integer.js.map +1 -1
  56. package/dist/src/expr/libs/lazy.d.ts +28 -0
  57. package/dist/src/expr/libs/lazy.d.ts.map +1 -0
  58. package/dist/src/expr/libs/lazy.js +55 -0
  59. package/dist/src/expr/libs/lazy.js.map +1 -0
  60. package/dist/src/expr/libs/lazy.spec.d.ts +6 -0
  61. package/dist/src/expr/libs/lazy.spec.d.ts.map +1 -0
  62. package/dist/src/expr/libs/lazy.spec.js +102 -0
  63. package/dist/src/expr/libs/lazy.spec.js.map +1 -0
  64. package/dist/src/expr/query.d.ts +60 -0
  65. package/dist/src/expr/query.d.ts.map +1 -0
  66. package/dist/src/expr/query.js +84 -0
  67. package/dist/src/expr/query.js.map +1 -0
  68. package/dist/src/index.d.ts +3 -0
  69. package/dist/src/index.d.ts.map +1 -1
  70. package/dist/src/index.js +3 -0
  71. package/dist/src/index.js.map +1 -1
  72. package/dist/src/internal.d.ts +4 -0
  73. package/dist/src/internal.d.ts.map +1 -1
  74. package/dist/src/internal.js +9 -0
  75. package/dist/src/internal.js.map +1 -1
  76. package/dist/src/location.d.ts +22 -0
  77. package/dist/src/location.d.ts.map +1 -1
  78. package/dist/src/location.js +31 -0
  79. package/dist/src/location.js.map +1 -1
  80. package/dist/src/naming.d.ts +12 -7
  81. package/dist/src/naming.d.ts.map +1 -1
  82. package/dist/src/naming.js +30 -13
  83. package/dist/src/naming.js.map +1 -1
  84. package/dist/src/naming.spec.js +49 -0
  85. package/dist/src/naming.spec.js.map +1 -1
  86. package/dist/src/portable.spec.d.ts +6 -0
  87. package/dist/src/portable.spec.d.ts.map +1 -0
  88. package/dist/src/portable.spec.js +181 -0
  89. package/dist/src/portable.spec.js.map +1 -0
  90. package/dist/src/query/evaluate.d.ts +98 -0
  91. package/dist/src/query/evaluate.d.ts.map +1 -0
  92. package/dist/src/query/evaluate.js +193 -0
  93. package/dist/src/query/evaluate.js.map +1 -0
  94. package/dist/src/query/index.d.ts +17 -0
  95. package/dist/src/query/index.d.ts.map +1 -0
  96. package/dist/src/query/index.js +17 -0
  97. package/dist/src/query/index.js.map +1 -0
  98. package/dist/src/query/jq/catalog.d.ts +174 -0
  99. package/dist/src/query/jq/catalog.d.ts.map +1 -0
  100. package/dist/src/query/jq/catalog.js +1740 -0
  101. package/dist/src/query/jq/catalog.js.map +1 -0
  102. package/dist/src/query/jq/check.d.ts +210 -0
  103. package/dist/src/query/jq/check.d.ts.map +1 -0
  104. package/dist/src/query/jq/check.js +2261 -0
  105. package/dist/src/query/jq/check.js.map +1 -0
  106. package/dist/src/query/jq/complete.d.ts +89 -0
  107. package/dist/src/query/jq/complete.d.ts.map +1 -0
  108. package/dist/src/query/jq/complete.js +320 -0
  109. package/dist/src/query/jq/complete.js.map +1 -0
  110. package/dist/src/query/jq/describe.d.ts +53 -0
  111. package/dist/src/query/jq/describe.d.ts.map +1 -0
  112. package/dist/src/query/jq/describe.js +149 -0
  113. package/dist/src/query/jq/describe.js.map +1 -0
  114. package/dist/src/query/jq/lex.d.ts +118 -0
  115. package/dist/src/query/jq/lex.d.ts.map +1 -0
  116. package/dist/src/query/jq/lex.js +371 -0
  117. package/dist/src/query/jq/lex.js.map +1 -0
  118. package/dist/src/query/jq/literals.d.ts +49 -0
  119. package/dist/src/query/jq/literals.d.ts.map +1 -0
  120. package/dist/src/query/jq/literals.js +78 -0
  121. package/dist/src/query/jq/literals.js.map +1 -0
  122. package/dist/src/query/jq/messages.d.ts +126 -0
  123. package/dist/src/query/jq/messages.d.ts.map +1 -0
  124. package/dist/src/query/jq/messages.js +172 -0
  125. package/dist/src/query/jq/messages.js.map +1 -0
  126. package/dist/src/query/jq/parse.d.ts +70 -0
  127. package/dist/src/query/jq/parse.d.ts.map +1 -0
  128. package/dist/src/query/jq/parse.js +1013 -0
  129. package/dist/src/query/jq/parse.js.map +1 -0
  130. package/dist/src/query/jq/print.d.ts +59 -0
  131. package/dist/src/query/jq/print.d.ts.map +1 -0
  132. package/dist/src/query/jq/print.js +587 -0
  133. package/dist/src/query/jq/print.js.map +1 -0
  134. package/dist/src/query/jq/shapes.d.ts +345 -0
  135. package/dist/src/query/jq/shapes.d.ts.map +1 -0
  136. package/dist/src/query/jq/shapes.js +584 -0
  137. package/dist/src/query/jq/shapes.js.map +1 -0
  138. package/dist/src/query/jq/spans.d.ts +133 -0
  139. package/dist/src/query/jq/spans.d.ts.map +1 -0
  140. package/dist/src/query/jq/spans.js +195 -0
  141. package/dist/src/query/jq/spans.js.map +1 -0
  142. package/dist/src/query/jq/split.d.ts +334 -0
  143. package/dist/src/query/jq/split.d.ts.map +1 -0
  144. package/dist/src/query/jq/split.js +2108 -0
  145. package/dist/src/query/jq/split.js.map +1 -0
  146. package/dist/src/query/jq/strftime.d.ts +20 -0
  147. package/dist/src/query/jq/strftime.d.ts.map +1 -0
  148. package/dist/src/query/jq/strftime.js +65 -0
  149. package/dist/src/query/jq/strftime.js.map +1 -0
  150. package/dist/src/query/jq/summary.d.ts +139 -0
  151. package/dist/src/query/jq/summary.d.ts.map +1 -0
  152. package/dist/src/query/jq/summary.js +222 -0
  153. package/dist/src/query/jq/summary.js.map +1 -0
  154. package/dist/src/query/jq/translate-builtins.d.ts +21 -0
  155. package/dist/src/query/jq/translate-builtins.d.ts.map +1 -0
  156. package/dist/src/query/jq/translate-builtins.js +1873 -0
  157. package/dist/src/query/jq/translate-builtins.js.map +1 -0
  158. package/dist/src/query/jq/translate.d.ts +627 -0
  159. package/dist/src/query/jq/translate.d.ts.map +1 -0
  160. package/dist/src/query/jq/translate.js +3364 -0
  161. package/dist/src/query/jq/translate.js.map +1 -0
  162. package/dist/src/query/types.d.ts +505 -0
  163. package/dist/src/query/types.d.ts.map +1 -0
  164. package/dist/src/query/types.js +231 -0
  165. package/dist/src/query/types.js.map +1 -0
  166. package/dist/src/runner_exec.d.ts +134 -0
  167. package/dist/src/runner_exec.d.ts.map +1 -0
  168. package/dist/src/runner_exec.js +371 -0
  169. package/dist/src/runner_exec.js.map +1 -0
  170. package/dist/src/runner_exec.spec.d.ts +6 -0
  171. package/dist/src/runner_exec.spec.d.ts.map +1 -0
  172. package/dist/src/runner_exec.spec.js +198 -0
  173. package/dist/src/runner_exec.spec.js.map +1 -0
  174. package/dist/src/runner_io.d.ts +370 -0
  175. package/dist/src/runner_io.d.ts.map +1 -0
  176. package/dist/src/runner_io.js +563 -0
  177. package/dist/src/runner_io.js.map +1 -0
  178. package/dist/src/runner_io.spec.d.ts +6 -0
  179. package/dist/src/runner_io.spec.d.ts.map +1 -0
  180. package/dist/src/runner_io.spec.js +224 -0
  181. package/dist/src/runner_io.spec.js.map +1 -0
  182. package/dist/src/runner_merge.d.ts +95 -0
  183. package/dist/src/runner_merge.d.ts.map +1 -0
  184. package/dist/src/runner_merge.js +238 -0
  185. package/dist/src/runner_merge.js.map +1 -0
  186. package/dist/src/runner_protocol.d.ts +60 -6
  187. package/dist/src/runner_protocol.d.ts.map +1 -1
  188. package/dist/src/runner_protocol.js +48 -6
  189. package/dist/src/runner_protocol.js.map +1 -1
  190. package/dist/src/serialization/beast2/index.d.ts +2 -2
  191. package/dist/src/serialization/beast2/index.d.ts.map +1 -1
  192. package/dist/src/serialization/beast2/index.js +1 -1
  193. package/dist/src/serialization/beast2/index.js.map +1 -1
  194. package/dist/src/serialization/beast2/v5/frames.d.ts +10 -6
  195. package/dist/src/serialization/beast2/v5/frames.d.ts.map +1 -1
  196. package/dist/src/serialization/beast2/v5/frames.js +10 -6
  197. package/dist/src/serialization/beast2/v5/frames.js.map +1 -1
  198. package/dist/src/serialization/beast2/v5/frames.spec.d.ts +6 -0
  199. package/dist/src/serialization/beast2/v5/frames.spec.d.ts.map +1 -0
  200. package/dist/src/serialization/beast2/v5/frames.spec.js +42 -0
  201. package/dist/src/serialization/beast2/v5/frames.spec.js.map +1 -0
  202. package/dist/src/serialization/beast2/v5/index.spec.js +108 -0
  203. package/dist/src/serialization/beast2/v5/index.spec.js.map +1 -1
  204. package/dist/src/serialization/beast2/v5/lazy.d.ts +74 -7
  205. package/dist/src/serialization/beast2/v5/lazy.d.ts.map +1 -1
  206. package/dist/src/serialization/beast2/v5/lazy.js +129 -27
  207. package/dist/src/serialization/beast2/v5/lazy.js.map +1 -1
  208. package/dist/src/serialization/beast2/v5/lazy.spec.js +251 -16
  209. package/dist/src/serialization/beast2/v5/lazy.spec.js.map +1 -1
  210. package/dist/src/serialization/beast2/v5/stream.d.ts +139 -23
  211. package/dist/src/serialization/beast2/v5/stream.d.ts.map +1 -1
  212. package/dist/src/serialization/beast2/v5/stream.js +196 -44
  213. package/dist/src/serialization/beast2/v5/stream.js.map +1 -1
  214. package/dist/src/serialization/beast2/v5/type-section.d.ts.map +1 -1
  215. package/dist/src/serialization/beast2/v5/type-section.js +25 -12
  216. package/dist/src/serialization/beast2/v5/type-section.js.map +1 -1
  217. package/dist/src/serialization/beast2/v5/type-section.spec.d.ts +6 -0
  218. package/dist/src/serialization/beast2/v5/type-section.spec.d.ts.map +1 -0
  219. package/dist/src/serialization/beast2/v5/type-section.spec.js +41 -0
  220. package/dist/src/serialization/beast2/v5/type-section.spec.js.map +1 -0
  221. package/dist/src/serialization/beast2/v5/weight.d.ts +36 -0
  222. package/dist/src/serialization/beast2/v5/weight.d.ts.map +1 -0
  223. package/dist/src/serialization/beast2/v5/weight.js +238 -0
  224. package/dist/src/serialization/beast2/v5/weight.js.map +1 -0
  225. package/dist/src/serialization/crc32.d.ts +38 -0
  226. package/dist/src/serialization/crc32.d.ts.map +1 -0
  227. package/dist/src/serialization/crc32.js +70 -0
  228. package/dist/src/serialization/crc32.js.map +1 -0
  229. package/dist/src/serialization/crc32.spec.d.ts +6 -0
  230. package/dist/src/serialization/crc32.spec.d.ts.map +1 -0
  231. package/dist/src/serialization/crc32.spec.js +92 -0
  232. package/dist/src/serialization/crc32.spec.js.map +1 -0
  233. package/dist/src/serialization/east-inferred.spec.js +4 -0
  234. package/dist/src/serialization/east-inferred.spec.js.map +1 -1
  235. package/dist/src/serialization/east.d.ts.map +1 -1
  236. package/dist/src/serialization/east.js +134 -110
  237. package/dist/src/serialization/east.js.map +1 -1
  238. package/dist/src/serialization/east.spec.js +185 -4
  239. package/dist/src/serialization/east.spec.js.map +1 -1
  240. package/dist/src/serialization/east_text.d.ts +25 -0
  241. package/dist/src/serialization/east_text.d.ts.map +1 -0
  242. package/dist/src/serialization/east_text.js +29 -0
  243. package/dist/src/serialization/east_text.js.map +1 -0
  244. package/dist/src/serialization/index.d.ts +1 -1
  245. package/dist/src/serialization/index.d.ts.map +1 -1
  246. package/dist/src/serialization/index.js +1 -1
  247. package/dist/src/serialization/index.js.map +1 -1
  248. package/dist/src/types.d.ts +1 -1
  249. package/dist/src/types.d.ts.map +1 -1
  250. package/dist/src/types.js +7 -6
  251. package/dist/src/types.js.map +1 -1
  252. package/package.json +7 -4
@@ -405,6 +405,35 @@ export declare function encodeBeast2PagedFor<T extends EastType>(type: T | EastT
405
405
  * @throws {TypeError} When `type` is not an Array, Set or Dict type.
406
406
  */
407
407
  export declare function iterBeast2SegmentsFor<T extends EastType>(type: T | EastTypeValue, options?: Beast2DecodeOptions): (data: Uint8Array) => Generator<ValueTypeOf<T>>;
408
+ /** Options accepted by {@link openBeast2PagesFor}: the decode options, and
409
+ * what the reader's cache keeps. */
410
+ export type Beast2PagesOptions = Beast2DecodeOptions & {
411
+ /**
412
+ * The decoded weight, in bytes, that the cache of the reader's element and
413
+ * keyed reads keeps of the segments they decode (v5/SPEC.md, "The pager's
414
+ * cache"). Defaults to 256 MiB. The segment read last always stays, so `1`
415
+ * keeps exactly one.
416
+ */
417
+ cacheBytes?: number;
418
+ };
419
+ /** What a {@link Beast2Pages}' cache has done, and what it holds: the figures
420
+ * east-c's pager keeps (`east_beast2_pages_cache_stats`). */
421
+ export type Beast2PagesCacheStats = {
422
+ /** Element and keyed reads a segment the cache held served. */
423
+ hits: number;
424
+ /** Segments let go, least recently used first, to keep within the budget. */
425
+ evictions: number;
426
+ /** Segments dropped behind a run of reads in key order. */
427
+ droppedBehind: number;
428
+ /** The segments it holds. */
429
+ segments: number;
430
+ /** Their decoded weight. */
431
+ weight: number;
432
+ /** The most decoded weight it has held. */
433
+ peakWeight: number;
434
+ /** Its budget, in decoded weight. */
435
+ budget: number;
436
+ };
408
437
  /**
409
438
  * Random access over an indexed, self-contained v5 collection blob.
410
439
  *
@@ -412,9 +441,12 @@ export declare function iterBeast2SegmentsFor<T extends EastType>(type: T | East
412
441
  * {@link segment} seeks to and decodes exactly one segment. Requires the blob
413
442
  * to carry an index (written by default by {@link Beast2Writer}); random
414
443
  * access additionally requires self-contained segments. The element and keyed
415
- * read paths ({@link element} / {@link get}) reuse decoded segments through a
416
- * small LRU, so a read loop over neighbouring rows decodes each segment once
417
- * rather than once per element; {@link segment} itself always decodes fresh.
444
+ * read paths ({@link element} / {@link get}) keep the segments they decode in
445
+ * a cache of the reader's own — up to `cacheBytes` of decoded weight, least
446
+ * recently used first, and dropping behind reads in key order (v5/SPEC.md,
447
+ * "The pager's cache") — so a read loop over neighbouring rows decodes each
448
+ * segment once rather than once per element; {@link segment} itself always
449
+ * decodes fresh.
418
450
  *
419
451
  * The blob is either a whole `Uint8Array` or a {@link Beast2SyncRangeReader}:
420
452
  * through a reader the open reads only the tail (footer + index) and the
@@ -464,18 +496,72 @@ export declare class Beast2Pages<T extends EastType = EastType> {
464
496
  private fenceDec;
465
497
  /** The decoder of a manifest's stored fence bytes, built on first use. */
466
498
  private manifestFenceDec;
467
- /** Decoded segments kept hot for the element and keyed read paths, keyed
468
- * by segment index in LRU order (mirrors east-c's `B2V5_PAGES_LRU`).
469
- * Only {@link element} and {@link get} route through it — the public
470
- * {@link segment} stays a fresh decode, so a caller mutating its result
471
- * cannot poison the cache. `first`/`last` carry a Set/Dict segment's key
472
- * range so a hit can maintain the caller's order threading without a
473
- * container walk. */
499
+ /** The decoded segments the element and keyed reads keep, by segment
500
+ * index, least recently used first: the Map's order is the recency list,
501
+ * and a hit moves its segment last. Only {@link element} and {@link get}
502
+ * route through it: every scan — {@link segment}, {@link segmentDisjoint},
503
+ * {@link slice} — decodes fresh. Its segments decode frozen, so a caller
504
+ * cannot change what a later read is served through what one read
505
+ * returned (#1129). `first`/`last` carry a Set/Dict segment's key range so
506
+ * a hit can maintain the caller's order threading without a container
507
+ * walk. */
474
508
  private readonly segmentCache;
509
+ /** The cache's budget, in decoded weight. */
510
+ private readonly cacheBudget;
511
+ /** The decoded weight of the segments the cache holds. */
512
+ private cacheWeight;
513
+ /** What the cache has done — see {@link cacheStats}. */
514
+ private cacheHits;
515
+ private cacheEvictions;
516
+ private cacheDropped;
517
+ private cachePeak;
518
+ /** Weighs a decoded segment; built on the first decode the cache keeps. */
519
+ private weighSegment;
520
+ /** Drop-behind: the segment the last miss read (-1 before any), the run's
521
+ * misses so far, its first included, the first segment of the run not yet
522
+ * dropped behind, and what the run marks the segments its misses decode. */
523
+ private runLast;
524
+ private runMisses;
525
+ private runNextDrop;
526
+ private runId;
527
+ /** Segments decoded so far — see {@link segmentsDecoded}. */
528
+ private decodes;
529
+ /** Fences probed so far — see {@link fencesProbed}. */
530
+ private probes;
531
+ /** The first key of each Set or Dict segment probed so far, by segment
532
+ * index — see {@link firstKey}. */
533
+ private readonly keptFences;
475
534
  /** @internal Use {@link openBeast2PagesFor}. */
476
- constructor(source: Uint8Array | Beast2SyncRangeReader | Beast2ManifestSource, typeValue: EastTypeValue, options?: Beast2DecodeOptions);
535
+ constructor(source: Uint8Array | Beast2SyncRangeReader | Beast2ManifestSource, typeValue: EastTypeValue, options?: Beast2PagesOptions);
477
536
  /** Number of segments in the blob. */
478
537
  get segmentCount(): number;
538
+ /**
539
+ * The segment decodes this reader has made: one per segment it decoded, and
540
+ * none for a read its kept segments served. A count above
541
+ * {@link segmentCount} says its reads decoded a segment again. With
542
+ * {@link fencesProbed}, what a reader's reads came to — the account east-c's
543
+ * pager keeps too.
544
+ */
545
+ get segmentsDecoded(): number;
546
+ /** The segment fences this reader has probed: each segment's first key it
547
+ * decoded without the segment. A Set or Dict fence is probed once, whether
548
+ * its keyed reads verify the fences or {@link fence} asks for one, and kept,
549
+ * so asking for it again probes nothing; an Array's is probed each time. */
550
+ get fencesProbed(): number;
551
+ /**
552
+ * What the cache of the element and keyed reads has done, and what it holds
553
+ * now: the figures east-c's pager keeps, by the same rules (v5/SPEC.md, "The
554
+ * pager's cache").
555
+ */
556
+ get cacheStats(): Beast2PagesCacheStats;
557
+ /**
558
+ * Lets every segment the cache holds go, and forgets the run of reads in key
559
+ * order they were in: what a lazy value does once it has read its
560
+ * collection whole, after which its reads never come here again.
561
+ *
562
+ * @internal
563
+ */
564
+ clearCache(): void;
479
565
  /** Reads segment `i`'s frame — exactly its wire bytes, from its index
480
566
  * offset to the next segment's (or the terminator) — and opens its
481
567
  * logical chunk. The only place segment bytes are fetched, so a ranged
@@ -500,24 +586,48 @@ export declare class Beast2Pages<T extends EastType = EastType> {
500
586
  * violates strict ascending order.
501
587
  */
502
588
  segment(i: number): ValueTypeOf<T>;
503
- /** Seeks to and decodes segment `i`, threading the caller's order state. */
589
+ /** Seeks to and decodes segment `i`, threading the caller's order state.
590
+ * `freeze` decodes it frozen whatever the pager was opened with: the
591
+ * cache's segments are shared by every read they serve (#1129). */
504
592
  private decodeSegmentCore;
505
- /** Decodes segment `i` through the LRU cache, threading the caller's
506
- * order state exactly as a fresh decode would: a hit replays the
507
- * boundary-ascent check against the cached segment's first key and
508
- * advances `order` to its last. Serves {@link element} and {@link get}
509
- * only — see {@link segmentCache}. */
593
+ /** Decodes segment `i` through the cache, threading the caller's order
594
+ * state exactly as a fresh decode would: a hit replays the boundary-ascent
595
+ * check against the cached segment's first key and advances `order` to its
596
+ * last. A miss steps the run of misses ({@link runStep}), decodes the
597
+ * segment frozen — every read it serves shares it — and weighs it, and the
598
+ * least recently used go until the cache is within its budget; the newest
599
+ * never does, so one segment over budget still caches. Serves
600
+ * {@link element} and {@link get} only — see {@link segmentCache}. */
510
601
  private segmentCached;
602
+ /** A miss reading segment `s`: it continues the run of misses when it reads
603
+ * one or two segments past the last — a join's lookups can skip a segment
604
+ * holding no key they want — and starts a run otherwise. From the run's
605
+ * fourth miss on ({@link RUN_DROPS_FROM}), what the run itself decoded, from
606
+ * its first segment to two before `s`, is let go: a reader in key order
607
+ * keeps the segment it is in and the one before. A reader at random lands
608
+ * one or two past its last miss with odds of about 2 in the segment count
609
+ * S, so three such misses in a row are (2/S)³ — 1 in 80,000 over 87
610
+ * segments. Hits never touch the run. */
611
+ private runStep;
612
+ /** Lets cached segment `k` go. */
613
+ private letGo;
614
+ /** Segment `i`'s first key or element, probed ({@link probeFirstKey}) and
615
+ * counted. A Set element or Dict key is immutable, so a Set or Dict fence
616
+ * is kept and handed out again without a probe; an Array's first element
617
+ * may be a container its caller changes, so it is probed afresh each time.
618
+ * East values are never `undefined`, which marks a fence not yet kept. */
619
+ private firstKey;
511
620
  /** Decodes just the first key/element of segment `i` — a bounded probe
512
621
  * (a prefix of the frame read and inflated, one element decode), not a
513
622
  * whole-segment decode. A first key wider than the probe grows it; the
514
623
  * final attempt reads the frame whole, so corruption is still reported
515
624
  * with the frame's own error. */
516
- private firstKey;
625
+ private probeFirstKey;
517
626
  /**
518
627
  * Probes segment `i`'s fence: its first Dict key, Set element, or Array
519
628
  * element, decoded without decoding the rest of the segment (one frame
520
- * inflate, one element decode).
629
+ * inflate, one element decode). A Set or Dict fence is probed once per
630
+ * reader and kept, so asking for it again reads nothing.
521
631
  *
522
632
  * For Set/Dict roots the fences bound each segment's canonical key range —
523
633
  * segment `i` holds exactly the keys in `[fence(i), fence(i+1))` — which is
@@ -607,7 +717,11 @@ export declare class Beast2Pages<T extends EastType = EastType> {
607
717
  /**
608
718
  * Looks up one Set element or Dict value by key (Set/Dict roots only):
609
719
  * binary-searches the verified segment fences for the only segment whose
610
- * range can hold the key, decodes it, and scans for an East-equal match.
720
+ * range can hold the key, decodes it (or takes it from the cache), and looks
721
+ * the key up in it. A segment is a SortedSet or SortedMap under the same
722
+ * East comparator, so the lookup is its B-tree's, O(log m) in a segment of m
723
+ * keys — as east-c looks a key up in its segment — and never a walk of the
724
+ * segment's entries.
611
725
  *
612
726
  * @param key - the Set element or Dict key to look up
613
727
  * @returns the Dict value (or the stored Set element) for `key`, or
@@ -627,9 +741,11 @@ export declare class Beast2Pages<T extends EastType = EastType> {
627
741
  * whose fences are already decoded, so a keyed read touches exactly one.
628
742
  *
629
743
  * @param type - the collection type (Array/Set/Dict)
630
- * @param options - decode options (platform functions for decoded functions)
631
- * @returns a function opening a blob for paged reads
744
+ * @param options - decode options (platform functions for decoded functions),
745
+ * and the decoded weight the reader's cache keeps (`cacheBytes`)
746
+ * @returns a function opening a blob for paged reads, which throws a
747
+ * `TypeError` when `cacheBytes` is negative or not a number
632
748
  * @throws {TypeError} When `type` is not an Array, Set or Dict type.
633
749
  */
634
- export declare function openBeast2PagesFor<T extends EastType>(type: T | EastTypeValue, options?: Beast2DecodeOptions): (source: Uint8Array | Beast2SyncRangeReader | Beast2ManifestSource) => Beast2Pages<T>;
750
+ export declare function openBeast2PagesFor<T extends EastType>(type: T | EastTypeValue, options?: Beast2PagesOptions): (source: Uint8Array | Beast2SyncRangeReader | Beast2ManifestSource) => Beast2Pages<T>;
635
751
  //# sourceMappingURL=stream.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/stream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../../../src/serialization/beast2/v5/stream.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,7 @@ import { MAGIC_BYTES_V5, TAG_NEW, createV5EncodeContext, buildV5Encoder, buildV5
41
41
  import { TAG_OR_TERMINATOR_FRAME, bytesReader, isBeast2SyncRangeReader, readExact, readU64LE, readBeast2ExtentsSync } from "./range.js";
42
42
  import { SegmentCutter, decodeBeast2FenceFor } from "./boundary.js";
43
43
  import { isBeast2ManifestSource } from "./manifest.js";
44
+ import { decodedWeightFor } from "./weight.js";
44
45
  /** Validates that a root type is streamable and returns its kind. */
45
46
  function checkSegmented(typeValue) {
46
47
  if (!isSegmentedRoot(typeValue)) {
@@ -914,12 +915,15 @@ export function iterBeast2SegmentsFor(type, options) {
914
915
  // =============================================================================
915
916
  // Paging reader
916
917
  // =============================================================================
917
- /** Decoded segments retained by a {@link Beast2Pages} for its element and
918
- * keyed read paths (mirrors east-c's `B2V5_PAGES_LRU`): a keyed/indexed
919
- * read loop over neighbouring rows then decodes each segment once instead
920
- * of once per element. Bounded — at most this many decoded segments live
921
- * per reader. */
922
- const SEGMENT_CACHE_CAPACITY = 4;
918
+ /** The decoded weight a {@link Beast2Pages}' cache keeps by default: enough
919
+ * for any input the query planner reads whole in each piece, which decodes to
920
+ * at most about 16 times its stored 16 MiB (v5/SPEC.md, "The pager's
921
+ * cache"). */
922
+ const PAGES_CACHE_BYTES_DEFAULT = 256 * 1024 * 1024;
923
+ /** The misses of a run — its first, then each one or two segments past the
924
+ * last — from which it drops what it passed: one keyed read can straddle a
925
+ * segment boundary, and four misses in order are not chance. */
926
+ const RUN_DROPS_FROM = 4;
923
927
  /** The bytes a fence probe reads first: the frame header plus enough of the
924
928
  * payload for the first key of any ordinary row. A key that does not fit
925
929
  * grows the probe fourfold until it does, the final attempt reading the
@@ -932,9 +936,12 @@ const FENCE_PROBE_BYTES = 4096;
932
936
  * {@link segment} seeks to and decodes exactly one segment. Requires the blob
933
937
  * to carry an index (written by default by {@link Beast2Writer}); random
934
938
  * access additionally requires self-contained segments. The element and keyed
935
- * read paths ({@link element} / {@link get}) reuse decoded segments through a
936
- * small LRU, so a read loop over neighbouring rows decodes each segment once
937
- * rather than once per element; {@link segment} itself always decodes fresh.
939
+ * read paths ({@link element} / {@link get}) keep the segments they decode in
940
+ * a cache of the reader's own — up to `cacheBytes` of decoded weight, least
941
+ * recently used first, and dropping behind reads in key order (v5/SPEC.md,
942
+ * "The pager's cache") — so a read loop over neighbouring rows decodes each
943
+ * segment once rather than once per element; {@link segment} itself always
944
+ * decodes fresh.
938
945
  *
939
946
  * The blob is either a whole `Uint8Array` or a {@link Beast2SyncRangeReader}:
940
947
  * through a reader the open reads only the tail (footer + index) and the
@@ -984,16 +991,48 @@ export class Beast2Pages {
984
991
  fenceDec = null;
985
992
  /** The decoder of a manifest's stored fence bytes, built on first use. */
986
993
  manifestFenceDec = null;
987
- /** Decoded segments kept hot for the element and keyed read paths, keyed
988
- * by segment index in LRU order (mirrors east-c's `B2V5_PAGES_LRU`).
989
- * Only {@link element} and {@link get} route through it — the public
990
- * {@link segment} stays a fresh decode, so a caller mutating its result
991
- * cannot poison the cache. `first`/`last` carry a Set/Dict segment's key
992
- * range so a hit can maintain the caller's order threading without a
993
- * container walk. */
994
+ /** The decoded segments the element and keyed reads keep, by segment
995
+ * index, least recently used first: the Map's order is the recency list,
996
+ * and a hit moves its segment last. Only {@link element} and {@link get}
997
+ * route through it: every scan — {@link segment}, {@link segmentDisjoint},
998
+ * {@link slice} — decodes fresh. Its segments decode frozen, so a caller
999
+ * cannot change what a later read is served through what one read
1000
+ * returned (#1129). `first`/`last` carry a Set/Dict segment's key range so
1001
+ * a hit can maintain the caller's order threading without a container
1002
+ * walk. */
994
1003
  segmentCache = new Map();
1004
+ /** The cache's budget, in decoded weight. */
1005
+ cacheBudget;
1006
+ /** The decoded weight of the segments the cache holds. */
1007
+ cacheWeight = 0;
1008
+ /** What the cache has done — see {@link cacheStats}. */
1009
+ cacheHits = 0;
1010
+ cacheEvictions = 0;
1011
+ cacheDropped = 0;
1012
+ cachePeak = 0;
1013
+ /** Weighs a decoded segment; built on the first decode the cache keeps. */
1014
+ weighSegment = null;
1015
+ /** Drop-behind: the segment the last miss read (-1 before any), the run's
1016
+ * misses so far, its first included, the first segment of the run not yet
1017
+ * dropped behind, and what the run marks the segments its misses decode. */
1018
+ runLast = -1;
1019
+ runMisses = 0;
1020
+ runNextDrop = 0;
1021
+ runId = 0;
1022
+ /** Segments decoded so far — see {@link segmentsDecoded}. */
1023
+ decodes = 0;
1024
+ /** Fences probed so far — see {@link fencesProbed}. */
1025
+ probes = 0;
1026
+ /** The first key of each Set or Dict segment probed so far, by segment
1027
+ * index — see {@link firstKey}. */
1028
+ keptFences = [];
995
1029
  /** @internal Use {@link openBeast2PagesFor}. */
996
1030
  constructor(source, typeValue, options) {
1031
+ const cacheBytes = options?.cacheBytes ?? PAGES_CACHE_BYTES_DEFAULT;
1032
+ if (!(cacheBytes >= 0)) {
1033
+ throw new TypeError(`beast2 v5: cacheBytes is a decoded weight in bytes, 0 or more, not ${cacheBytes}`);
1034
+ }
1035
+ this.cacheBudget = cacheBytes;
997
1036
  let kind;
998
1037
  let sourceMap;
999
1038
  let index;
@@ -1057,6 +1096,51 @@ export class Beast2Pages {
1057
1096
  get segmentCount() {
1058
1097
  return this.indexData.offsets.length;
1059
1098
  }
1099
+ /**
1100
+ * The segment decodes this reader has made: one per segment it decoded, and
1101
+ * none for a read its kept segments served. A count above
1102
+ * {@link segmentCount} says its reads decoded a segment again. With
1103
+ * {@link fencesProbed}, what a reader's reads came to — the account east-c's
1104
+ * pager keeps too.
1105
+ */
1106
+ get segmentsDecoded() {
1107
+ return this.decodes;
1108
+ }
1109
+ /** The segment fences this reader has probed: each segment's first key it
1110
+ * decoded without the segment. A Set or Dict fence is probed once, whether
1111
+ * its keyed reads verify the fences or {@link fence} asks for one, and kept,
1112
+ * so asking for it again probes nothing; an Array's is probed each time. */
1113
+ get fencesProbed() {
1114
+ return this.probes;
1115
+ }
1116
+ /**
1117
+ * What the cache of the element and keyed reads has done, and what it holds
1118
+ * now: the figures east-c's pager keeps, by the same rules (v5/SPEC.md, "The
1119
+ * pager's cache").
1120
+ */
1121
+ get cacheStats() {
1122
+ return {
1123
+ hits: this.cacheHits,
1124
+ evictions: this.cacheEvictions,
1125
+ droppedBehind: this.cacheDropped,
1126
+ segments: this.segmentCache.size,
1127
+ weight: this.cacheWeight,
1128
+ peakWeight: this.cachePeak,
1129
+ budget: this.cacheBudget,
1130
+ };
1131
+ }
1132
+ /**
1133
+ * Lets every segment the cache holds go, and forgets the run of reads in key
1134
+ * order they were in: what a lazy value does once it has read its
1135
+ * collection whole, after which its reads never come here again.
1136
+ *
1137
+ * @internal
1138
+ */
1139
+ clearCache() {
1140
+ this.segmentCache.clear();
1141
+ this.cacheWeight = 0;
1142
+ this.runLast = -1;
1143
+ }
1060
1144
  /** Reads segment `i`'s frame — exactly its wire bytes, from its index
1061
1145
  * offset to the next segment's (or the terminator) — and opens its
1062
1146
  * logical chunk. The only place segment bytes are fetched, so a ranged
@@ -1102,8 +1186,10 @@ export class Beast2Pages {
1102
1186
  const order = this.kind === "Array" ? undefined : { prev: undefined, has: false };
1103
1187
  return this.decodeSegmentCore(i, order);
1104
1188
  }
1105
- /** Seeks to and decodes segment `i`, threading the caller's order state. */
1106
- decodeSegmentCore(i, order) {
1189
+ /** Seeks to and decodes segment `i`, threading the caller's order state.
1190
+ * `freeze` decodes it frozen whatever the pager was opened with: the
1191
+ * cache's segments are shared by every read they serve (#1129). */
1192
+ decodeSegmentCore(i, order, freeze = false) {
1107
1193
  if (!this.selfContained) {
1108
1194
  throw new Error(`beast2 v5: blob has cross-segment aliasing — random access needs self-contained segments`);
1109
1195
  }
@@ -1115,23 +1201,28 @@ export class Beast2Pages {
1115
1201
  if (n !== this.indexData.counts[i]) {
1116
1202
  throw new Error(`beast2 v5: segment ${i} declares ${n} elements, index says ${this.indexData.counts[i]}`);
1117
1203
  }
1118
- const ctx = { containers: [], sourceMap: this.sourceMap, frozen: this.platform?.frozen ?? false, ...buildPlatformContext(this.platform) };
1204
+ const ctx = { containers: [], sourceMap: this.sourceMap, frozen: freeze || (this.platform?.frozen ?? false), ...buildPlatformContext(this.platform) };
1119
1205
  const value = this.decodeSegment(reader, ctx, n, order);
1120
1206
  if (reader.offset !== reader.buffer.length) {
1121
1207
  throw new Error(`beast2 v5: ${reader.buffer.length - reader.offset} logical bytes after segment ${i}`);
1122
1208
  }
1209
+ this.decodes++;
1123
1210
  return value;
1124
1211
  }
1125
- /** Decodes segment `i` through the LRU cache, threading the caller's
1126
- * order state exactly as a fresh decode would: a hit replays the
1127
- * boundary-ascent check against the cached segment's first key and
1128
- * advances `order` to its last. Serves {@link element} and {@link get}
1129
- * only — see {@link segmentCache}. */
1212
+ /** Decodes segment `i` through the cache, threading the caller's order
1213
+ * state exactly as a fresh decode would: a hit replays the boundary-ascent
1214
+ * check against the cached segment's first key and advances `order` to its
1215
+ * last. A miss steps the run of misses ({@link runStep}), decodes the
1216
+ * segment frozen — every read it serves shares it — and weighs it, and the
1217
+ * least recently used go until the cache is within its budget; the newest
1218
+ * never does, so one segment over budget still caches. Serves
1219
+ * {@link element} and {@link get} only — see {@link segmentCache}. */
1130
1220
  segmentCached(i, order) {
1131
1221
  const hit = this.segmentCache.get(i);
1132
1222
  if (hit !== undefined) {
1133
1223
  this.segmentCache.delete(i);
1134
- this.segmentCache.set(i, hit); // refresh recency
1224
+ this.segmentCache.set(i, hit); // the most recently used goes last
1225
+ this.cacheHits++;
1135
1226
  if (order !== undefined && this.orderCmp !== null) {
1136
1227
  if (order.has && this.orderCmp(order.prev, hit.first) >= 0) {
1137
1228
  throw new Error(`beast2 v5: ${this.kind === "Dict" ? "Dict keys" : "Set elements"} are not strictly ascending in East order — the wire must hold the canonical value (corrupt or pre-contract blob)`);
@@ -1141,7 +1232,8 @@ export class Beast2Pages {
1141
1232
  }
1142
1233
  return hit.seg;
1143
1234
  }
1144
- const seg = this.decodeSegmentCore(i, order);
1235
+ this.runStep(i);
1236
+ const seg = this.decodeSegmentCore(i, order, true);
1145
1237
  let first;
1146
1238
  let last;
1147
1239
  if (this.kind !== "Array") {
@@ -1150,18 +1242,76 @@ export class Beast2Pages {
1150
1242
  // order state on the segment's last key.
1151
1243
  last = order?.prev;
1152
1244
  }
1153
- this.segmentCache.set(i, { seg, first, last });
1154
- if (this.segmentCache.size > SEGMENT_CACHE_CAPACITY) {
1155
- this.segmentCache.delete(this.segmentCache.keys().next().value);
1245
+ this.weighSegment ??= decodedWeightFor(this.typeValue);
1246
+ const weight = this.weighSegment(seg);
1247
+ this.segmentCache.set(i, { seg, first, last, weight, run: this.runId });
1248
+ this.cacheWeight += weight;
1249
+ for (const [k, entry] of this.segmentCache) {
1250
+ if (this.cacheWeight <= this.cacheBudget || k === i)
1251
+ break;
1252
+ this.letGo(k, entry);
1253
+ this.cacheEvictions++;
1156
1254
  }
1255
+ if (this.cacheWeight > this.cachePeak)
1256
+ this.cachePeak = this.cacheWeight;
1157
1257
  return seg;
1158
1258
  }
1259
+ /** A miss reading segment `s`: it continues the run of misses when it reads
1260
+ * one or two segments past the last — a join's lookups can skip a segment
1261
+ * holding no key they want — and starts a run otherwise. From the run's
1262
+ * fourth miss on ({@link RUN_DROPS_FROM}), what the run itself decoded, from
1263
+ * its first segment to two before `s`, is let go: a reader in key order
1264
+ * keeps the segment it is in and the one before. A reader at random lands
1265
+ * one or two past its last miss with odds of about 2 in the segment count
1266
+ * S, so three such misses in a row are (2/S)³ — 1 in 80,000 over 87
1267
+ * segments. Hits never touch the run. */
1268
+ runStep(s) {
1269
+ const last = this.runLast;
1270
+ this.runLast = s;
1271
+ if (last < 0 || s <= last || s - last > 2) {
1272
+ this.runId++;
1273
+ this.runMisses = 1;
1274
+ this.runNextDrop = s;
1275
+ return;
1276
+ }
1277
+ if (++this.runMisses < RUN_DROPS_FROM)
1278
+ return;
1279
+ for (let k = this.runNextDrop; k + 2 <= s; k++) {
1280
+ const entry = this.segmentCache.get(k);
1281
+ if (entry !== undefined && entry.run === this.runId) {
1282
+ this.letGo(k, entry);
1283
+ this.cacheDropped++;
1284
+ }
1285
+ }
1286
+ if (s - 1 > this.runNextDrop)
1287
+ this.runNextDrop = s - 1;
1288
+ }
1289
+ /** Lets cached segment `k` go. */
1290
+ letGo(k, entry) {
1291
+ this.segmentCache.delete(k);
1292
+ this.cacheWeight -= entry.weight;
1293
+ }
1294
+ /** Segment `i`'s first key or element, probed ({@link probeFirstKey}) and
1295
+ * counted. A Set element or Dict key is immutable, so a Set or Dict fence
1296
+ * is kept and handed out again without a probe; an Array's first element
1297
+ * may be a container its caller changes, so it is probed afresh each time.
1298
+ * East values are never `undefined`, which marks a fence not yet kept. */
1299
+ firstKey(i) {
1300
+ const kept = this.keptFences[i];
1301
+ if (kept !== undefined)
1302
+ return kept;
1303
+ const fence = this.probeFirstKey(i);
1304
+ this.probes++;
1305
+ if (this.kind !== "Array")
1306
+ this.keptFences[i] = fence;
1307
+ return fence;
1308
+ }
1159
1309
  /** Decodes just the first key/element of segment `i` — a bounded probe
1160
1310
  * (a prefix of the frame read and inflated, one element decode), not a
1161
1311
  * whole-segment decode. A first key wider than the probe grows it; the
1162
1312
  * final attempt reads the frame whole, so corruption is still reported
1163
1313
  * with the frame's own error. */
1164
- firstKey(i) {
1314
+ probeFirstKey(i) {
1165
1315
  // A manifest stores every fence already, so a bisect over one reads no
1166
1316
  // segment bytes at all — the whole point of carrying them.
1167
1317
  if (this.manifestSource !== null) {
@@ -1202,7 +1352,8 @@ export class Beast2Pages {
1202
1352
  /**
1203
1353
  * Probes segment `i`'s fence: its first Dict key, Set element, or Array
1204
1354
  * element, decoded without decoding the rest of the segment (one frame
1205
- * inflate, one element decode).
1355
+ * inflate, one element decode). A Set or Dict fence is probed once per
1356
+ * reader and kept, so asking for it again reads nothing.
1206
1357
  *
1207
1358
  * For Set/Dict roots the fences bound each segment's canonical key range —
1208
1359
  * segment `i` holds exactly the keys in `[fence(i), fence(i+1))` — which is
@@ -1426,7 +1577,11 @@ export class Beast2Pages {
1426
1577
  /**
1427
1578
  * Looks up one Set element or Dict value by key (Set/Dict roots only):
1428
1579
  * binary-searches the verified segment fences for the only segment whose
1429
- * range can hold the key, decodes it, and scans for an East-equal match.
1580
+ * range can hold the key, decodes it (or takes it from the cache), and looks
1581
+ * the key up in it. A segment is a SortedSet or SortedMap under the same
1582
+ * East comparator, so the lookup is its B-tree's, O(log m) in a segment of m
1583
+ * keys — as east-c looks a key up in its segment — and never a walk of the
1584
+ * segment's entries.
1430
1585
  *
1431
1586
  * @param key - the Set element or Dict key to look up
1432
1587
  * @returns the Dict value (or the stored Set element) for `key`, or
@@ -1447,17 +1602,12 @@ export class Beast2Pages {
1447
1602
  const order = { prev: undefined, has: false };
1448
1603
  const segment = this.decodeDisjoint(this.segmentFor(key), order, fences, true);
1449
1604
  if (this.kind === "Set") {
1450
- for (const item of segment) {
1451
- if (this.orderCmp(item, key) === 0)
1452
- return item;
1453
- }
1454
- return undefined;
1455
- }
1456
- for (const [k, v] of segment.entries()) {
1457
- if (this.orderCmp(k, key) === 0)
1458
- return v;
1605
+ // The stored element, not the key asked with: the least at or above it,
1606
+ // when that one is East-equal to it.
1607
+ const at = segment.keys(key).next();
1608
+ return !at.done && this.orderCmp(at.value, key) === 0 ? at.value : undefined;
1459
1609
  }
1460
- return undefined;
1610
+ return segment.get(key);
1461
1611
  }
1462
1612
  }
1463
1613
  /**
@@ -1470,8 +1620,10 @@ export class Beast2Pages {
1470
1620
  * whose fences are already decoded, so a keyed read touches exactly one.
1471
1621
  *
1472
1622
  * @param type - the collection type (Array/Set/Dict)
1473
- * @param options - decode options (platform functions for decoded functions)
1474
- * @returns a function opening a blob for paged reads
1623
+ * @param options - decode options (platform functions for decoded functions),
1624
+ * and the decoded weight the reader's cache keeps (`cacheBytes`)
1625
+ * @returns a function opening a blob for paged reads, which throws a
1626
+ * `TypeError` when `cacheBytes` is negative or not a number
1475
1627
  * @throws {TypeError} When `type` is not an Array, Set or Dict type.
1476
1628
  */
1477
1629
  export function openBeast2PagesFor(type, options) {