@blockcast/mmt-container 2.1.0 → 2.2.0-main.050b52fb9b00
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/README.md +29 -17
- package/dist/browser-runtime.js +1949 -374
- package/dist/browser-runtime.js.map +4 -4
- package/dist/carp-catalog.js.map +1 -1
- package/dist/catalog-fec-params.d.ts +17 -1
- package/dist/catalog-fec-params.d.ts.map +1 -1
- package/dist/catalog-fec-params.js +15 -0
- package/dist/catalog-fec-params.js.map +2 -2
- package/dist/catalog-network-source.js.map +1 -1
- package/dist/cmcd-producer.d.ts +65 -47
- package/dist/cmcd-producer.d.ts.map +1 -1
- package/dist/cmcd-producer.js +138 -109
- package/dist/cmcd-producer.js.map +2 -2
- package/dist/delivery-catalog.js +26 -16
- package/dist/delivery-catalog.js.map +2 -2
- package/dist/delta-fallback-config.js.map +1 -1
- package/dist/fec-manager.d.ts +70 -12
- package/dist/fec-manager.d.ts.map +1 -1
- package/dist/fec-manager.js +403 -58
- package/dist/fec-manager.js.map +2 -2
- package/dist/fec-state.js.map +1 -1
- package/dist/fec-worker-setup.d.ts +1 -1
- package/dist/fec-worker-setup.js +1 -1
- package/dist/fec-worker-setup.js.map +1 -1
- package/dist/held-layer-admission.js.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +2 -2
- package/dist/iso-block-locator.d.ts +48 -13
- package/dist/iso-block-locator.d.ts.map +1 -1
- package/dist/iso-block-locator.js +97 -25
- package/dist/iso-block-locator.js.map +2 -2
- package/dist/iso-bmff-timing.d.ts +10 -1
- package/dist/iso-bmff-timing.d.ts.map +1 -1
- package/dist/iso-bmff-timing.js +36 -2
- package/dist/iso-bmff-timing.js.map +2 -2
- package/dist/media-router.js.map +1 -1
- package/dist/mfu-reassembler.js +12 -19
- package/dist/mfu-reassembler.js.map +2 -2
- package/dist/mmtp-container-parser.d.ts +79 -10
- package/dist/mmtp-container-parser.d.ts.map +1 -1
- package/dist/mmtp-container-parser.js +219 -45
- package/dist/mmtp-container-parser.js.map +2 -2
- package/dist/mmtp-container-parser.no-modules.js +342 -63
- package/dist/mmtp-container-parser.no-modules.js.map +3 -3
- package/dist/mmtp-decode-pipeline.js +218 -45
- package/dist/mmtp-decode-pipeline.js.map +2 -2
- package/dist/mmtp-fec-session.d.ts +41 -3
- package/dist/mmtp-fec-session.d.ts.map +1 -1
- package/dist/mmtp-fec-session.js +118 -13
- package/dist/mmtp-fec-session.js.map +3 -3
- package/dist/mmtp-router.d.ts +43 -9
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +2006 -95
- package/dist/mmtp-router.js.map +4 -4
- package/dist/multicast-auth-catalog.js.map +1 -1
- package/dist/multicast-input.js.map +1 -1
- package/dist/multicast-manager.d.ts +28 -5
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +16116 -15005
- package/dist/multicast-manager.js.map +4 -4
- package/dist/multicast-transport.d.ts +11 -3
- package/dist/multicast-transport.d.ts.map +1 -1
- package/dist/multicast-transport.js +281 -35
- package/dist/multicast-transport.js.map +4 -4
- package/dist/multicast-unwrap.js +12 -19
- package/dist/multicast-unwrap.js.map +2 -2
- package/dist/no-modules.js +336 -59
- package/dist/no-modules.js.map +3 -3
- package/dist/repair-fetch.d.ts +36 -8
- package/dist/repair-fetch.d.ts.map +1 -1
- package/dist/repair-fetch.js +285 -26
- package/dist/repair-fetch.js.map +3 -3
- package/dist/repair-layer-subscriptions.d.ts +82 -0
- package/dist/repair-layer-subscriptions.d.ts.map +1 -0
- package/dist/repair-layer-subscriptions.js +192 -0
- package/dist/repair-layer-subscriptions.js.map +7 -0
- package/dist/signaling.js.map +2 -2
- package/dist/timestamp-codec.js +12 -19
- package/dist/timestamp-codec.js.map +2 -2
- package/dist/track-session.d.ts +1 -1
- package/dist/track-session.d.ts.map +1 -1
- package/dist/track-session.js +1 -0
- package/dist/track-session.js.map +2 -2
- package/dist/wasm-mfu-reassembler.js.map +1 -1
- package/dist/wasm-mmtp-container-parser.js +218 -45
- package/dist/wasm-mmtp-container-parser.js.map +2 -2
- package/package.json +8 -5
- package/schemas/catalog.schema.json +4 -0
- package/src/catalog-fec-params.ts +36 -1
- package/src/cmcd-producer.ts +194 -179
- package/src/fec-manager.ts +433 -32
- package/src/fec-worker-setup.ts +2 -2
- package/src/index.ts +20 -2
- package/src/iso-block-locator.ts +133 -31
- package/src/iso-bmff-timing.ts +40 -1
- package/src/mmtp-container-parser.ts +306 -29
- package/src/mmtp-fec-session.ts +115 -15
- package/src/mmtp-router.ts +629 -54
- package/src/multicast-manager.ts +70 -11
- package/src/multicast-transport.ts +44 -20
- package/src/repair-fetch.ts +363 -49
- package/src/repair-layer-subscriptions.ts +261 -0
- package/src/track-session.ts +4 -1
|
@@ -32,16 +32,28 @@ export type IsoRepairPlacement<T> = {
|
|
|
32
32
|
readonly lostSsId: number;
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
|
-
/**
|
|
35
|
+
/**
|
|
36
|
+
* Not a block this stream can use; the repair symbol is dropped. `ofSpan` is
|
|
37
|
+
* set when the repair stated only the first block of that repair-less span:
|
|
38
|
+
* the span holds more than one block, so no single repair group completes it.
|
|
39
|
+
*/
|
|
36
40
|
| {
|
|
37
41
|
readonly status: 'conflict' | 'overlap' | 'stale' | 'ahead';
|
|
38
42
|
readonly reason: string;
|
|
43
|
+
readonly ofSpan?: IsoBlockRange;
|
|
39
44
|
};
|
|
40
45
|
/**
|
|
41
46
|
* Retention: the locator is never without one. Every call that can grow it
|
|
42
47
|
* (`hold`, `placeRepair`) retires, behind the position it just saw, every
|
|
43
48
|
* block, span and held source more than `retentionBlocks` blocks back, by the
|
|
44
|
-
* one ISO horizon metric (`isoBlocksBehindLowerBound`). A
|
|
49
|
+
* one ISO horizon metric (`isoBlocksBehindLowerBound`). A held source stays
|
|
50
|
+
* while a pending hole holding it does: the hole's repair FETCH may still
|
|
51
|
+
* state its block, and closing the hole places it, so the span it leaves
|
|
52
|
+
* counts every source it received (BLO-52085). A pending hole the horizon
|
|
53
|
+
* passes stops being pending (its blocks can no longer be stated, and the
|
|
54
|
+
* release gate no longer waits for it), but keeps its sources until its
|
|
55
|
+
* owner closes it (`takeExpiredHoles`), so it still fails as the span it
|
|
56
|
+
* is. A block is measured
|
|
45
57
|
* from its last SS_ID, so it stays while any SS_ID of it is inside the
|
|
46
58
|
* horizon: a repair-less span has no length bound, and one measured from its
|
|
47
59
|
* start could be retired the moment it is created, before the sources it
|
|
@@ -82,6 +94,15 @@ export declare class IsoBlockLocator<T> {
|
|
|
82
94
|
get newest(): number | undefined;
|
|
83
95
|
/** Advance `newest` to `position` if it is newer; retires nothing. */
|
|
84
96
|
observe(position: number): void;
|
|
97
|
+
/**
|
|
98
|
+
* The newest source SS_ID noted with `noteSource` (RFC 1982 order). Unlike
|
|
99
|
+
* `newest`, a repair never moves it: a repair can run ahead of its sources,
|
|
100
|
+
* a source cannot run ahead of the sources sent before it except by
|
|
101
|
+
* reordering.
|
|
102
|
+
*/
|
|
103
|
+
get newestSource(): number | undefined;
|
|
104
|
+
/** Note a received source's SS_ID; true when it is the newest one yet. */
|
|
105
|
+
noteSource(ssId: number): boolean;
|
|
85
106
|
/** Held sources evicted by `heldCapacity` (never by the horizon itself). */
|
|
86
107
|
get heldEvicted(): number;
|
|
87
108
|
/** Number of known blocks and spans. */
|
|
@@ -95,8 +116,16 @@ export declare class IsoBlockLocator<T> {
|
|
|
95
116
|
block: IsoBlockRange;
|
|
96
117
|
esi: number;
|
|
97
118
|
} | null;
|
|
98
|
-
/** Number of pending
|
|
119
|
+
/** Number of holes not closed yet, pending or past the horizon. */
|
|
99
120
|
get holeCount(): number;
|
|
121
|
+
/**
|
|
122
|
+
* The pending holes the horizon has passed since the last call, in the
|
|
123
|
+
* order it passed them. Each is no longer pending: no repair states a block
|
|
124
|
+
* in it (that repair is `stale`, as for a span the horizon retired) and the
|
|
125
|
+
* release gate does not wait for it. Its owner must close it
|
|
126
|
+
* (`closeHolesWithin`), which turns it into a span that is not kept here.
|
|
127
|
+
*/
|
|
128
|
+
takeExpiredHoles(): IsoBlockRange[];
|
|
100
129
|
/** The stated block (never a span) ending exactly at `end`. */
|
|
101
130
|
blockEndingAt(end: number): IsoBlockRange | undefined;
|
|
102
131
|
/** The known block or span starting exactly at `start`. */
|
|
@@ -119,9 +148,11 @@ export declare class IsoBlockLocator<T> {
|
|
|
119
148
|
/**
|
|
120
149
|
* Apply one repair symbol's `(SS_Start, SSB_length)`. The first repair of a
|
|
121
150
|
* block states its range and places every held source in it; later repair
|
|
122
|
-
* symbols of the same block change nothing. A range
|
|
123
|
-
*
|
|
124
|
-
*
|
|
151
|
+
* symbols of the same block change nothing. A repair whose range is exactly
|
|
152
|
+
* a repair-less span states that span's one block. A range that contradicts
|
|
153
|
+
* a known block (a different length, or an overlap with another block or
|
|
154
|
+
* with part of a span) fails closed: the repair symbol is dropped and no
|
|
155
|
+
* block changes.
|
|
125
156
|
* A newly stated block retires behind its SS_Start (see the class note).
|
|
126
157
|
* A block so far past `newest` that stating it would retire the position
|
|
127
158
|
* `newest` is refused as `ahead`. When `newest` is a placed block's SS_Start
|
|
@@ -135,19 +166,23 @@ export declare class IsoBlockLocator<T> {
|
|
|
135
166
|
*/
|
|
136
167
|
placeRepair(start: number, length: number): IsoRepairPlacement<T>;
|
|
137
168
|
/**
|
|
138
|
-
* Turn every
|
|
139
|
-
*
|
|
140
|
-
*
|
|
169
|
+
* Turn every hole inside `[start, start + length)` into a repair-less span,
|
|
170
|
+
* claiming its held sources: its range FETCH ended, so nothing more will
|
|
171
|
+
* state its blocks. A hole the horizon passed (`takeExpiredHoles`) leaves a
|
|
172
|
+
* span that is not kept among the blocks, as the horizon would retire it at
|
|
173
|
+
* once; only `locate` finds it, until the next retirement, so its sources
|
|
174
|
+
* can be fed. Returns the spans, in SS_ID order.
|
|
141
175
|
*/
|
|
142
176
|
closeHolesWithin(start: number, length: number): {
|
|
143
177
|
block: IsoBlockRange;
|
|
144
178
|
placed: IsoPlacedSource<T>[];
|
|
145
179
|
}[];
|
|
146
180
|
/**
|
|
147
|
-
* Retire every block and span whose last SS_ID, and every held source
|
|
148
|
-
* lies more than `retentionBlocks` blocks behind
|
|
149
|
-
* lower-bound metric (`isoBlocksBehindLowerBound`)
|
|
150
|
-
* horizon uses
|
|
181
|
+
* Retire every block and span whose last SS_ID, and every held source
|
|
182
|
+
* outside a hole, lies more than `retentionBlocks` blocks behind
|
|
183
|
+
* `position`, with the shared lower-bound metric (`isoBlocksBehindLowerBound`)
|
|
184
|
+
* every ISO interleave horizon uses; a pending hole so far behind expires
|
|
185
|
+
* (`takeExpiredHoles`). Returns the retired block starts.
|
|
151
186
|
*/
|
|
152
187
|
retireBehind(position: number): number[];
|
|
153
188
|
/** Forget everything (publisher restart, track reset). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iso-block-locator.d.ts","sourceRoot":"","sources":["../src/iso-block-locator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"iso-block-locator.d.ts","sourceRoot":"","sources":["../src/iso-block-locator.ts"],"names":[],"mappings":"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"}
|
|
@@ -71,6 +71,15 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
71
71
|
this.#heldEvicted = 0;
|
|
72
72
|
/** Pending holes (see `deferIncompleteGaps`): unstated, sources still held. */
|
|
73
73
|
this.#holes = [];
|
|
74
|
+
/** Holes the horizon passed while pending: sources held until closed. */
|
|
75
|
+
this.#expired = [];
|
|
76
|
+
/** Of `#expired`, those `takeExpiredHoles` has not handed out yet. */
|
|
77
|
+
this.#newlyExpired = [];
|
|
78
|
+
/**
|
|
79
|
+
* Spans closed from expired holes: behind the horizon, so kept only for
|
|
80
|
+
* `locate` while their sources are fed, until the next retirement.
|
|
81
|
+
*/
|
|
82
|
+
this.#closedBehind = [];
|
|
74
83
|
/**
|
|
75
84
|
* Keep a gap that is missing a source as a pending hole rather than a span,
|
|
76
85
|
* so a repair FETCHed for it (draft-ramadan-moq-fec §7.5) can still state
|
|
@@ -92,7 +101,11 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
92
101
|
#retentionBlocks;
|
|
93
102
|
#heldEvicted;
|
|
94
103
|
#newest;
|
|
104
|
+
#newestSource;
|
|
95
105
|
#holes;
|
|
106
|
+
#expired;
|
|
107
|
+
#newlyExpired;
|
|
108
|
+
#closedBehind;
|
|
96
109
|
static #checkedRetention(retentionBlocks) {
|
|
97
110
|
if (!Number.isSafeInteger(retentionBlocks) || retentionBlocks <= 0) {
|
|
98
111
|
throw new Error(
|
|
@@ -129,6 +142,21 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
129
142
|
observe(position) {
|
|
130
143
|
if (this.#newest === void 0 || serial32Precedes(this.#newest, position)) this.#newest = position;
|
|
131
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* The newest source SS_ID noted with `noteSource` (RFC 1982 order). Unlike
|
|
147
|
+
* `newest`, a repair never moves it: a repair can run ahead of its sources,
|
|
148
|
+
* a source cannot run ahead of the sources sent before it except by
|
|
149
|
+
* reordering.
|
|
150
|
+
*/
|
|
151
|
+
get newestSource() {
|
|
152
|
+
return this.#newestSource;
|
|
153
|
+
}
|
|
154
|
+
/** Note a received source's SS_ID; true when it is the newest one yet. */
|
|
155
|
+
noteSource(ssId) {
|
|
156
|
+
if (this.#newestSource !== void 0 && !serial32Precedes(this.#newestSource, ssId)) return false;
|
|
157
|
+
this.#newestSource = ssId;
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
132
160
|
/** Held sources evicted by `heldCapacity` (never by the horizon itself). */
|
|
133
161
|
get heldEvicted() {
|
|
134
162
|
return this.#heldEvicted;
|
|
@@ -147,17 +175,29 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
147
175
|
}
|
|
148
176
|
/** The known block or span containing `ssId`, with its ESI. */
|
|
149
177
|
locate(ssId) {
|
|
150
|
-
for (
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
178
|
+
for (const blocks of [this.#blocks, this.#closedBehind]) {
|
|
179
|
+
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
180
|
+
const block = blocks[i];
|
|
181
|
+
if (isoBlockContains(block.start, block.length, ssId)) {
|
|
182
|
+
return { block, esi: serial32Distance(block.start, ssId) };
|
|
183
|
+
}
|
|
154
184
|
}
|
|
155
185
|
}
|
|
156
186
|
return null;
|
|
157
187
|
}
|
|
158
|
-
/** Number of pending
|
|
188
|
+
/** Number of holes not closed yet, pending or past the horizon. */
|
|
159
189
|
get holeCount() {
|
|
160
|
-
return this.#holes.length;
|
|
190
|
+
return this.#holes.length + this.#expired.length;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* The pending holes the horizon has passed since the last call, in the
|
|
194
|
+
* order it passed them. Each is no longer pending: no repair states a block
|
|
195
|
+
* in it (that repair is `stale`, as for a span the horizon retired) and the
|
|
196
|
+
* release gate does not wait for it. Its owner must close it
|
|
197
|
+
* (`closeHolesWithin`), which turns it into a span that is not kept here.
|
|
198
|
+
*/
|
|
199
|
+
takeExpiredHoles() {
|
|
200
|
+
return this.#newlyExpired.splice(0);
|
|
161
201
|
}
|
|
162
202
|
/** The stated block (never a span) ending exactly at `end`. */
|
|
163
203
|
blockEndingAt(end) {
|
|
@@ -213,9 +253,11 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
213
253
|
/**
|
|
214
254
|
* Apply one repair symbol's `(SS_Start, SSB_length)`. The first repair of a
|
|
215
255
|
* block states its range and places every held source in it; later repair
|
|
216
|
-
* symbols of the same block change nothing. A range
|
|
217
|
-
*
|
|
218
|
-
*
|
|
256
|
+
* symbols of the same block change nothing. A repair whose range is exactly
|
|
257
|
+
* a repair-less span states that span's one block. A range that contradicts
|
|
258
|
+
* a known block (a different length, or an overlap with another block or
|
|
259
|
+
* with part of a span) fails closed: the repair symbol is dropped and no
|
|
260
|
+
* block changes.
|
|
219
261
|
* A newly stated block retires behind its SS_Start (see the class note).
|
|
220
262
|
* A block so far past `newest` that stating it would retire the position
|
|
221
263
|
* `newest` is refused as `ahead`. When `newest` is a placed block's SS_Start
|
|
@@ -234,7 +276,16 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
234
276
|
const known = this.blockAt(start);
|
|
235
277
|
if (known !== void 0) {
|
|
236
278
|
if (known.span) {
|
|
237
|
-
|
|
279
|
+
if (known.length === length) {
|
|
280
|
+
const block2 = { start, length, span: false };
|
|
281
|
+
this.#blocks[this.#blocks.indexOf(known)] = block2;
|
|
282
|
+
return { status: "placed", block: block2, placed: [] };
|
|
283
|
+
}
|
|
284
|
+
return length < known.length ? {
|
|
285
|
+
status: "overlap",
|
|
286
|
+
reason: `repair block ${start}+${length} is only the first block of repair-less span ${known.start}+${known.length}`,
|
|
287
|
+
ofSpan: known
|
|
288
|
+
} : { status: "overlap", reason: `repair block ${start}+${length} runs past repair-less span ${known.start}+${known.length}` };
|
|
238
289
|
}
|
|
239
290
|
if (known.length !== length) {
|
|
240
291
|
return {
|
|
@@ -302,18 +353,28 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
302
353
|
return span === void 0 ? { status: "placed", block, placed } : { status: "placed", block, placed, span };
|
|
303
354
|
}
|
|
304
355
|
/**
|
|
305
|
-
* Turn every
|
|
306
|
-
*
|
|
307
|
-
*
|
|
356
|
+
* Turn every hole inside `[start, start + length)` into a repair-less span,
|
|
357
|
+
* claiming its held sources: its range FETCH ended, so nothing more will
|
|
358
|
+
* state its blocks. A hole the horizon passed (`takeExpiredHoles`) leaves a
|
|
359
|
+
* span that is not kept among the blocks, as the horizon would retire it at
|
|
360
|
+
* once; only `locate` finds it, until the next retirement, so its sources
|
|
361
|
+
* can be fed. Returns the spans, in SS_ID order.
|
|
308
362
|
*/
|
|
309
363
|
closeHolesWithin(start, length) {
|
|
310
364
|
const closed = [];
|
|
311
|
-
for (const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
365
|
+
for (const holes of [this.#holes, this.#expired]) {
|
|
366
|
+
for (const hole of [...holes]) {
|
|
367
|
+
if (!isoBlockContains(start, length, hole.start)) continue;
|
|
368
|
+
holes.splice(holes.indexOf(hole), 1);
|
|
369
|
+
const spanBlock = { start: hole.start, length: hole.length, span: true };
|
|
370
|
+
closed.push({ block: spanBlock, placed: this.#claim(spanBlock) });
|
|
371
|
+
if (holes === this.#holes) {
|
|
372
|
+
this.#blocks.push(spanBlock);
|
|
373
|
+
} else {
|
|
374
|
+
this.#closedBehind.push(spanBlock);
|
|
375
|
+
if (this.#newlyExpired.includes(hole)) this.#newlyExpired.splice(this.#newlyExpired.indexOf(hole), 1);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
317
378
|
}
|
|
318
379
|
return closed.sort((x, y) => serial32Distance(start, x.block.start) - serial32Distance(start, y.block.start));
|
|
319
380
|
}
|
|
@@ -327,15 +388,17 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
327
388
|
return void 0;
|
|
328
389
|
}
|
|
329
390
|
/**
|
|
330
|
-
* Retire every block and span whose last SS_ID, and every held source
|
|
331
|
-
* lies more than `retentionBlocks` blocks behind
|
|
332
|
-
* lower-bound metric (`isoBlocksBehindLowerBound`)
|
|
333
|
-
* horizon uses
|
|
391
|
+
* Retire every block and span whose last SS_ID, and every held source
|
|
392
|
+
* outside a hole, lies more than `retentionBlocks` blocks behind
|
|
393
|
+
* `position`, with the shared lower-bound metric (`isoBlocksBehindLowerBound`)
|
|
394
|
+
* every ISO interleave horizon uses; a pending hole so far behind expires
|
|
395
|
+
* (`takeExpiredHoles`). Returns the retired block starts.
|
|
334
396
|
*/
|
|
335
397
|
retireBehind(position) {
|
|
336
398
|
this.observe(position);
|
|
337
399
|
const horizon = this.#retentionBlocks;
|
|
338
400
|
const retired = [];
|
|
401
|
+
this.#closedBehind.length = 0;
|
|
339
402
|
for (let i = this.#blocks.length - 1; i >= 0; i--) {
|
|
340
403
|
const block = this.#blocks[i];
|
|
341
404
|
const last = serial32Add(block.start, block.length - 1);
|
|
@@ -347,10 +410,15 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
347
410
|
for (let i = this.#holes.length - 1; i >= 0; i--) {
|
|
348
411
|
const hole = this.#holes[i];
|
|
349
412
|
const last = serial32Add(hole.start, hole.length - 1);
|
|
350
|
-
if (isoBlocksBehindLowerBound(last, position, this.#kMax)
|
|
413
|
+
if (isoBlocksBehindLowerBound(last, position, this.#kMax) <= horizon) continue;
|
|
414
|
+
this.#holes.splice(i, 1);
|
|
415
|
+
this.#expired.push(hole);
|
|
416
|
+
this.#newlyExpired.push(hole);
|
|
351
417
|
}
|
|
352
418
|
for (const ssId of [...this.#held.keys()]) {
|
|
353
|
-
if (isoBlocksBehindLowerBound(ssId, position, this.#kMax) > horizon) this.#
|
|
419
|
+
if (isoBlocksBehindLowerBound(ssId, position, this.#kMax) > horizon && !this.#holes.some((hole) => isoBlockContains(hole.start, hole.length, ssId)) && !this.#expired.some((hole) => isoBlockContains(hole.start, hole.length, ssId))) {
|
|
420
|
+
this.#held.delete(ssId);
|
|
421
|
+
}
|
|
354
422
|
}
|
|
355
423
|
return retired;
|
|
356
424
|
}
|
|
@@ -358,9 +426,13 @@ var IsoBlockLocator = class _IsoBlockLocator {
|
|
|
358
426
|
reset() {
|
|
359
427
|
this.#blocks.length = 0;
|
|
360
428
|
this.#holes.length = 0;
|
|
429
|
+
this.#expired.length = 0;
|
|
430
|
+
this.#newlyExpired.length = 0;
|
|
431
|
+
this.#closedBehind.length = 0;
|
|
361
432
|
this.#held.clear();
|
|
362
433
|
this.#coverageEnd = void 0;
|
|
363
434
|
this.#newest = void 0;
|
|
435
|
+
this.#newestSource = void 0;
|
|
364
436
|
}
|
|
365
437
|
#claim(block) {
|
|
366
438
|
const placed = [];
|