@bldrs-ai/conway 1.511.1441 → 1.513.1447

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 (39) hide show
  1. package/compiled/examples/browser-bundled.cjs +82 -16
  2. package/compiled/examples/cli-bundled.cjs +98 -23
  3. package/compiled/examples/cli-step-bundled.cjs +82 -16
  4. package/compiled/examples/validator-bundled.cjs +82 -16
  5. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +3 -2
  6. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
  7. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +69 -25
  8. package/compiled/src/compat/web-ifc/parse_aabb_imposter.d.ts +41 -0
  9. package/compiled/src/compat/web-ifc/parse_aabb_imposter.d.ts.map +1 -0
  10. package/compiled/src/compat/web-ifc/parse_aabb_imposter.js +161 -0
  11. package/compiled/src/compat/web-ifc/parse_aabb_imposter.test.d.ts +2 -0
  12. package/compiled/src/compat/web-ifc/parse_aabb_imposter.test.d.ts.map +1 -0
  13. package/compiled/src/compat/web-ifc/parse_aabb_imposter.test.js +39 -0
  14. package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +13 -0
  15. package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -1
  16. package/compiled/src/core/progress.d.ts +8 -1
  17. package/compiled/src/core/progress.d.ts.map +1 -1
  18. package/compiled/src/core/progress.js +9 -4
  19. package/compiled/src/core/progress_log.d.ts +1 -0
  20. package/compiled/src/core/progress_log.d.ts.map +1 -1
  21. package/compiled/src/core/progress_log.js +7 -2
  22. package/compiled/src/core/progress_log.test.js +21 -0
  23. package/compiled/src/ifc/ifc_stream_open.test.js +60 -0
  24. package/compiled/src/step/parsing/step_parser.d.ts +2 -2
  25. package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
  26. package/compiled/src/step/parsing/step_parser.js +8 -2
  27. package/compiled/src/step/parsing/streaming_index_builder.d.ts +4 -4
  28. package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -1
  29. package/compiled/src/step/step_buffer_provider.d.ts +4 -3
  30. package/compiled/src/step/step_buffer_provider.d.ts.map +1 -1
  31. package/compiled/src/step/step_buffer_provider.js +4 -3
  32. package/compiled/src/step/step_entity_base.d.ts.map +1 -1
  33. package/compiled/src/step/step_entity_base.js +9 -0
  34. package/compiled/src/step/step_model_base.d.ts +9 -0
  35. package/compiled/src/step/step_model_base.d.ts.map +1 -1
  36. package/compiled/src/step/step_model_base.js +72 -13
  37. package/compiled/src/version/version.js +1 -1
  38. package/compiled/tsconfig.tsbuildinfo +1 -1
  39. package/package.json +1 -1
@@ -30,7 +30,7 @@ var import_node_process = require("node:process");
30
30
  var readline = __toESM(require("node:readline"), 1);
31
31
 
32
32
  // compiled/src/version/version.js
33
- var versionString = "Conway v1.511.1441";
33
+ var versionString = "Conway v1.513.1447";
34
34
 
35
35
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
36
36
  var wasmType = "";
@@ -2910,7 +2910,10 @@ var StepParser = class extends StepHeaderParser {
2910
2910
  if (!charws(SEMICOLON)) {
2911
2911
  return syntaxError();
2912
2912
  }
2913
- onRecordIndexed?.(topLevelCount, expressID, 0);
2913
+ {
2914
+ const recordLen = input2.address - startElement2;
2915
+ onRecordIndexed?.(topLevelCount, expressID, 0, input2.buffer.subarray(input2.cursor - recordLen, input2.cursor));
2916
+ }
2914
2917
  ++topLevelCount;
2915
2918
  pushEntry({
2916
2919
  address: startElement2,
@@ -3000,7 +3003,10 @@ var StepParser = class extends StepHeaderParser {
3000
3003
  if (!charws(SEMICOLON)) {
3001
3004
  return syntaxError();
3002
3005
  }
3003
- onRecordIndexed?.(topLevelCount, expressID, foundItem);
3006
+ {
3007
+ const recordLen = input2.address - startElement;
3008
+ onRecordIndexed?.(topLevelCount, expressID, foundItem, input2.buffer.subarray(input2.cursor - recordLen, input2.cursor));
3009
+ }
3004
3010
  ++topLevelCount;
3005
3011
  pushEntry({
3006
3012
  address: startElement,
@@ -5532,6 +5538,9 @@ var StepModelBase = class {
5532
5538
  if (element.vtableIndex === void 0 && !this.populateVtableEntryRaw(element)) {
5533
5539
  return void 0;
5534
5540
  }
5541
+ if (element.buffer === void 0) {
5542
+ this.populateBufferEntry(localID);
5543
+ }
5535
5544
  const vtable = element.vtable;
5536
5545
  const buffer = element.buffer;
5537
5546
  if (vtable === void 0 || buffer === void 0 || offset >= (element.vtableCount ?? 0)) {
@@ -5601,6 +5610,11 @@ var StepModelBase = class {
5601
5610
  }
5602
5611
  const element = this.entry(localID);
5603
5612
  element.buffer = this.bufferProvider_.acquire(element.address, element.length).buffer;
5613
+ if (element.multiMapping !== void 0) {
5614
+ for (const mapped of element.multiMapping) {
5615
+ mapped.buffer = this.bufferProvider_.acquire(mapped.address, mapped.length).buffer;
5616
+ }
5617
+ }
5604
5618
  }
5605
5619
  /**
5606
5620
  * Get the size in bytes of the backing buffer for this.
@@ -5721,24 +5735,39 @@ var StepModelBase = class {
5721
5735
  if (!this.isSourceExternal) {
5722
5736
  return seen;
5723
5737
  }
5724
- const stack = [localID];
5738
+ const frontier = [];
5739
+ const enqueue = (id) => {
5740
+ if (id < this.count_ && !seen.has(id)) {
5741
+ frontier.push(id);
5742
+ }
5743
+ };
5744
+ enqueue(localID);
5725
5745
  if (extraLocalIDs !== void 0) {
5726
5746
  for (const extra of extraLocalIDs) {
5727
- stack.push(extra);
5747
+ enqueue(extra);
5728
5748
  }
5729
5749
  }
5730
- while (stack.length > 0) {
5731
- const id = stack.pop();
5732
- if (seen.has(id) || id >= this.count_) {
5733
- continue;
5750
+ while (frontier.length > 0) {
5751
+ const wave = [];
5752
+ for (const id of frontier) {
5753
+ if (seen.has(id) || id >= this.count_) {
5754
+ continue;
5755
+ }
5756
+ seen.add(id);
5757
+ this.pinByLocalID(id);
5758
+ wave.push(id);
5759
+ }
5760
+ frontier.length = 0;
5761
+ if (wave.length === 0) {
5762
+ break;
5734
5763
  }
5735
- seen.add(id);
5736
- await this.ensureResidentByLocalID(id);
5737
- this.pinByLocalID(id);
5738
- for (const expressID of this.scanRecordRefs_(id)) {
5739
- const referenced = this.expressIDMap_.get(expressID);
5740
- if (referenced !== void 0 && !seen.has(referenced)) {
5741
- stack.push(referenced);
5764
+ await Promise.all(wave.map((id) => this.ensureResidentByLocalID(id)));
5765
+ for (const id of wave) {
5766
+ for (const expressID of this.scanRecordRefs_(id)) {
5767
+ const referenced = this.expressIDMap_.get(expressID);
5768
+ if (referenced !== void 0 && !seen.has(referenced)) {
5769
+ frontier.push(referenced);
5770
+ }
5742
5771
  }
5743
5772
  }
5744
5773
  }
@@ -5767,6 +5796,35 @@ var StepModelBase = class {
5767
5796
  }
5768
5797
  this.bufferProvider_.unpinRange?.(this.address_[localID], this.length_[localID]);
5769
5798
  }
5799
+ /**
5800
+ * Drop captured source-window views on `localIDs` so the LRU can
5801
+ * evict those chunks. Vtables stay — `acquire` of the same
5802
+ * `(address, length)` is at a stable base. The next
5803
+ * `ensureResident` + field read rematerialises the view.
5804
+ *
5805
+ * @param localIDs Records whose `buffer` views to drop.
5806
+ */
5807
+ releaseSourceViews(localIDs) {
5808
+ if (!this.isSourceExternal) {
5809
+ return;
5810
+ }
5811
+ for (const localID of localIDs) {
5812
+ if (localID >= this.count_) {
5813
+ continue;
5814
+ }
5815
+ const item = this.complexEntries_?.get(localID) ?? this.descriptorCache_[localID];
5816
+ if (item === void 0) {
5817
+ continue;
5818
+ }
5819
+ item.buffer = void 0;
5820
+ if (item.multiMapping !== void 0) {
5821
+ for (const mapped of item.multiMapping) {
5822
+ mapped.buffer = void 0;
5823
+ }
5824
+ }
5825
+ }
5826
+ releaseScratchParsingBuffer();
5827
+ }
5770
5828
  /**
5771
5829
  * Unpin every local ID in `localIDs` (best-effort; missing IDs are
5772
5830
  * ignored). Use after {@link ensureResidentClosureByLocalID}, which
@@ -11230,6 +11288,7 @@ var StepEntityBase = class {
11230
11288
  */
11231
11289
  extractParseBuffer(offset, baseOffset, depth, result, module2, optional) {
11232
11290
  offset -= this.multiReference_ !== void 0 ? baseOffset : 0;
11291
+ this.guaranteeBuffer();
11233
11292
  const internalReference = this.guaranteeVTable(depth);
11234
11293
  if (offset >= internalReference.vtableCount) {
11235
11294
  throw new Error("Couldn't read field due to too few fields in record");
@@ -11342,6 +11401,7 @@ var StepEntityBase = class {
11342
11401
  * @return {Uint8Array} The buffer for this.
11343
11402
  */
11344
11403
  get buffer() {
11404
+ this.guaranteeBuffer();
11345
11405
  return this.internalReference_.buffer;
11346
11406
  }
11347
11407
  /**
@@ -11432,6 +11492,9 @@ var StepEntityBase = class {
11432
11492
  throw new Error("Entity does not have matching table entry to read from model");
11433
11493
  }
11434
11494
  }
11495
+ if (classReference.buffer === void 0) {
11496
+ this.model.populateBufferEntry(this.localID);
11497
+ }
11435
11498
  this.internalReference_.buffer = classReference.buffer;
11436
11499
  return classReference;
11437
11500
  }
@@ -11442,6 +11505,9 @@ var StepEntityBase = class {
11442
11505
  throw new Error("Entity does not have matching table entry to read from model");
11443
11506
  }
11444
11507
  }
11508
+ if (internalReference.buffer === void 0) {
11509
+ this.guaranteeBuffer();
11510
+ }
11445
11511
  return internalReference;
11446
11512
  }
11447
11513
  /**
@@ -14965,7 +14965,7 @@ ${t5.join("\n")}` : "";
14965
14965
  var import_process = require("process");
14966
14966
 
14967
14967
  // compiled/src/version/version.js
14968
- var versionString = "Conway v1.511.1441";
14968
+ var versionString = "Conway v1.513.1447";
14969
14969
 
14970
14970
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
14971
14971
  function pThreadsAllowed() {
@@ -16397,13 +16397,15 @@ var ProgressTracker = class {
16397
16397
  * Report progress within the current phase; throttled.
16398
16398
  *
16399
16399
  * @param completed Units completed so far.
16400
+ * @param extras Optional extras (window residency) merged into the event.
16400
16401
  */
16401
- update(completed) {
16402
+ update(completed, extras) {
16403
+ this.extras_ = extras;
16402
16404
  const now = Date.now();
16403
16405
  if (now - this.lastEmitTime < this.minIntervalMs) {
16404
16406
  return;
16405
16407
  }
16406
- this.emit(completed, now);
16408
+ this.emit(completed, now, extras);
16407
16409
  }
16408
16410
  /**
16409
16411
  * End the current phase, emitting an unthrottled final event with
@@ -16412,16 +16414,18 @@ var ProgressTracker = class {
16412
16414
  * @param completed Final completed units (defaults to the phase total).
16413
16415
  */
16414
16416
  endPhase(completed) {
16415
- this.emit(completed ?? this.total_ ?? 0);
16417
+ this.emit(completed ?? this.total_ ?? 0, Date.now(), this.extras_);
16416
16418
  this.phase_ = void 0;
16419
+ this.extras_ = void 0;
16417
16420
  }
16418
16421
  /**
16419
16422
  * Materialize and forward an event now, bypassing the throttle.
16420
16423
  *
16421
16424
  * @param completed Units completed so far.
16422
16425
  * @param now Current time in ms (defaults to Date.now()).
16426
+ * @param extras Optional extras merged into the event.
16423
16427
  */
16424
- emit(completed, now = Date.now()) {
16428
+ emit(completed, now = Date.now(), extras) {
16425
16429
  if (this.phase_ === void 0) {
16426
16430
  return;
16427
16431
  }
@@ -16433,7 +16437,8 @@ var ProgressTracker = class {
16433
16437
  total,
16434
16438
  unit: this.unit_,
16435
16439
  elapsedMs: now - this.startTime,
16436
- memoryMb: Memory.usedHeapMb()
16440
+ memoryMb: Memory.usedHeapMb(),
16441
+ residentSourceMb: extras?.residentSourceMb
16437
16442
  });
16438
16443
  }
16439
16444
  };
@@ -18741,7 +18746,10 @@ var StepParser = class extends StepHeaderParser {
18741
18746
  if (!charws(SEMICOLON)) {
18742
18747
  return syntaxError();
18743
18748
  }
18744
- onRecordIndexed?.(topLevelCount, expressID, 0);
18749
+ {
18750
+ const recordLen = input.address - startElement2;
18751
+ onRecordIndexed?.(topLevelCount, expressID, 0, input.buffer.subarray(input.cursor - recordLen, input.cursor));
18752
+ }
18745
18753
  ++topLevelCount;
18746
18754
  pushEntry({
18747
18755
  address: startElement2,
@@ -18831,7 +18839,10 @@ var StepParser = class extends StepHeaderParser {
18831
18839
  if (!charws(SEMICOLON)) {
18832
18840
  return syntaxError();
18833
18841
  }
18834
- onRecordIndexed?.(topLevelCount, expressID, foundItem);
18842
+ {
18843
+ const recordLen = input.address - startElement;
18844
+ onRecordIndexed?.(topLevelCount, expressID, foundItem, input.buffer.subarray(input.cursor - recordLen, input.cursor));
18845
+ }
18835
18846
  ++topLevelCount;
18836
18847
  pushEntry({
18837
18848
  address: startElement,
@@ -21410,6 +21421,9 @@ var StepModelBase = class {
21410
21421
  if (element.vtableIndex === void 0 && !this.populateVtableEntryRaw(element)) {
21411
21422
  return void 0;
21412
21423
  }
21424
+ if (element.buffer === void 0) {
21425
+ this.populateBufferEntry(localID);
21426
+ }
21413
21427
  const vtable = element.vtable;
21414
21428
  const buffer = element.buffer;
21415
21429
  if (vtable === void 0 || buffer === void 0 || offset >= (element.vtableCount ?? 0)) {
@@ -21479,6 +21493,11 @@ var StepModelBase = class {
21479
21493
  }
21480
21494
  const element = this.entry(localID);
21481
21495
  element.buffer = this.bufferProvider_.acquire(element.address, element.length).buffer;
21496
+ if (element.multiMapping !== void 0) {
21497
+ for (const mapped of element.multiMapping) {
21498
+ mapped.buffer = this.bufferProvider_.acquire(mapped.address, mapped.length).buffer;
21499
+ }
21500
+ }
21482
21501
  }
21483
21502
  /**
21484
21503
  * Get the size in bytes of the backing buffer for this.
@@ -21599,24 +21618,39 @@ var StepModelBase = class {
21599
21618
  if (!this.isSourceExternal) {
21600
21619
  return seen;
21601
21620
  }
21602
- const stack = [localID];
21621
+ const frontier = [];
21622
+ const enqueue = (id) => {
21623
+ if (id < this.count_ && !seen.has(id)) {
21624
+ frontier.push(id);
21625
+ }
21626
+ };
21627
+ enqueue(localID);
21603
21628
  if (extraLocalIDs !== void 0) {
21604
21629
  for (const extra of extraLocalIDs) {
21605
- stack.push(extra);
21630
+ enqueue(extra);
21606
21631
  }
21607
21632
  }
21608
- while (stack.length > 0) {
21609
- const id = stack.pop();
21610
- if (seen.has(id) || id >= this.count_) {
21611
- continue;
21633
+ while (frontier.length > 0) {
21634
+ const wave = [];
21635
+ for (const id of frontier) {
21636
+ if (seen.has(id) || id >= this.count_) {
21637
+ continue;
21638
+ }
21639
+ seen.add(id);
21640
+ this.pinByLocalID(id);
21641
+ wave.push(id);
21642
+ }
21643
+ frontier.length = 0;
21644
+ if (wave.length === 0) {
21645
+ break;
21612
21646
  }
21613
- seen.add(id);
21614
- await this.ensureResidentByLocalID(id);
21615
- this.pinByLocalID(id);
21616
- for (const expressID of this.scanRecordRefs_(id)) {
21617
- const referenced = this.expressIDMap_.get(expressID);
21618
- if (referenced !== void 0 && !seen.has(referenced)) {
21619
- stack.push(referenced);
21647
+ await Promise.all(wave.map((id) => this.ensureResidentByLocalID(id)));
21648
+ for (const id of wave) {
21649
+ for (const expressID of this.scanRecordRefs_(id)) {
21650
+ const referenced = this.expressIDMap_.get(expressID);
21651
+ if (referenced !== void 0 && !seen.has(referenced)) {
21652
+ frontier.push(referenced);
21653
+ }
21620
21654
  }
21621
21655
  }
21622
21656
  }
@@ -21645,6 +21679,35 @@ var StepModelBase = class {
21645
21679
  }
21646
21680
  this.bufferProvider_.unpinRange?.(this.address_[localID], this.length_[localID]);
21647
21681
  }
21682
+ /**
21683
+ * Drop captured source-window views on `localIDs` so the LRU can
21684
+ * evict those chunks. Vtables stay — `acquire` of the same
21685
+ * `(address, length)` is at a stable base. The next
21686
+ * `ensureResident` + field read rematerialises the view.
21687
+ *
21688
+ * @param localIDs Records whose `buffer` views to drop.
21689
+ */
21690
+ releaseSourceViews(localIDs) {
21691
+ if (!this.isSourceExternal) {
21692
+ return;
21693
+ }
21694
+ for (const localID of localIDs) {
21695
+ if (localID >= this.count_) {
21696
+ continue;
21697
+ }
21698
+ const item = this.complexEntries_?.get(localID) ?? this.descriptorCache_[localID];
21699
+ if (item === void 0) {
21700
+ continue;
21701
+ }
21702
+ item.buffer = void 0;
21703
+ if (item.multiMapping !== void 0) {
21704
+ for (const mapped of item.multiMapping) {
21705
+ mapped.buffer = void 0;
21706
+ }
21707
+ }
21708
+ }
21709
+ releaseScratchParsingBuffer();
21710
+ }
21648
21711
  /**
21649
21712
  * Unpin every local ID in `localIDs` (best-effort; missing IDs are
21650
21713
  * ignored). Use after {@link ensureResidentClosureByLocalID}, which
@@ -27108,6 +27171,7 @@ var StepEntityBase = class {
27108
27171
  */
27109
27172
  extractParseBuffer(offset, baseOffset, depth, result, module2, optional) {
27110
27173
  offset -= this.multiReference_ !== void 0 ? baseOffset : 0;
27174
+ this.guaranteeBuffer();
27111
27175
  const internalReference = this.guaranteeVTable(depth);
27112
27176
  if (offset >= internalReference.vtableCount) {
27113
27177
  throw new Error("Couldn't read field due to too few fields in record");
@@ -27220,6 +27284,7 @@ var StepEntityBase = class {
27220
27284
  * @return {Uint8Array} The buffer for this.
27221
27285
  */
27222
27286
  get buffer() {
27287
+ this.guaranteeBuffer();
27223
27288
  return this.internalReference_.buffer;
27224
27289
  }
27225
27290
  /**
@@ -27310,6 +27375,9 @@ var StepEntityBase = class {
27310
27375
  throw new Error("Entity does not have matching table entry to read from model");
27311
27376
  }
27312
27377
  }
27378
+ if (classReference.buffer === void 0) {
27379
+ this.model.populateBufferEntry(this.localID);
27380
+ }
27313
27381
  this.internalReference_.buffer = classReference.buffer;
27314
27382
  return classReference;
27315
27383
  }
@@ -27320,6 +27388,9 @@ var StepEntityBase = class {
27320
27388
  throw new Error("Entity does not have matching table entry to read from model");
27321
27389
  }
27322
27390
  }
27391
+ if (internalReference.buffer === void 0) {
27392
+ this.guaranteeBuffer();
27393
+ }
27323
27394
  return internalReference;
27324
27395
  }
27325
27396
  /**
@@ -93385,12 +93456,13 @@ function heapDeltaSuffix(state) {
93385
93456
  function formatStageLine(state, final) {
93386
93457
  const duration = state.lastElapsedMs - state.startElapsedMs;
93387
93458
  const heap = heapDeltaSuffix(state);
93459
+ const window2 = state.residentSourceMb !== void 0 ? `, window=${formatMb(state.residentSourceMb)} MB` : "";
93388
93460
  const determinate = state.percent !== void 0;
93389
93461
  if (final && !(determinate && state.percent < PERCENT)) {
93390
- return `${state.label}: ${formatSeconds(duration)}${heap}`;
93462
+ return `${state.label}: ${formatSeconds(duration)}${heap}${window2}`;
93391
93463
  }
93392
93464
  const bar = formatBar(determinate ? state.percent : void 0);
93393
- return `${state.label} ${bar} ${formatSeconds(duration)}${heap}`;
93465
+ return `${state.label} ${bar} ${formatSeconds(duration)}${heap}${window2}`;
93394
93466
  }
93395
93467
  var LoadLogAccumulator = class {
93396
93468
  constructor() {
@@ -93439,6 +93511,9 @@ var LoadLogAccumulator = class {
93439
93511
  current.startHeapMb ??= event.memoryMb;
93440
93512
  current.lastHeapMb = event.memoryMb;
93441
93513
  }
93514
+ if (event.residentSourceMb !== void 0) {
93515
+ current.residentSourceMb = event.residentSourceMb;
93516
+ }
93442
93517
  if (event.total !== void 0 && event.total > 0) {
93443
93518
  current.percent = event.completed / event.total * PERCENT;
93444
93519
  }
@@ -15943,7 +15943,7 @@ var ParsingBuffer = class {
15943
15943
  };
15944
15944
 
15945
15945
  // compiled/src/version/version.js
15946
- var versionString = "Conway v1.511.1441";
15946
+ var versionString = "Conway v1.513.1447";
15947
15947
 
15948
15948
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
15949
15949
  function pThreadsAllowed() {
@@ -18649,7 +18649,10 @@ var StepParser = class extends StepHeaderParser {
18649
18649
  if (!charws(SEMICOLON)) {
18650
18650
  return syntaxError();
18651
18651
  }
18652
- onRecordIndexed?.(topLevelCount, expressID, 0);
18652
+ {
18653
+ const recordLen = input.address - startElement2;
18654
+ onRecordIndexed?.(topLevelCount, expressID, 0, input.buffer.subarray(input.cursor - recordLen, input.cursor));
18655
+ }
18653
18656
  ++topLevelCount;
18654
18657
  pushEntry({
18655
18658
  address: startElement2,
@@ -18739,7 +18742,10 @@ var StepParser = class extends StepHeaderParser {
18739
18742
  if (!charws(SEMICOLON)) {
18740
18743
  return syntaxError();
18741
18744
  }
18742
- onRecordIndexed?.(topLevelCount, expressID, foundItem);
18745
+ {
18746
+ const recordLen = input.address - startElement;
18747
+ onRecordIndexed?.(topLevelCount, expressID, foundItem, input.buffer.subarray(input.cursor - recordLen, input.cursor));
18748
+ }
18743
18749
  ++topLevelCount;
18744
18750
  pushEntry({
18745
18751
  address: startElement,
@@ -21154,6 +21160,9 @@ var StepModelBase = class {
21154
21160
  if (element.vtableIndex === void 0 && !this.populateVtableEntryRaw(element)) {
21155
21161
  return void 0;
21156
21162
  }
21163
+ if (element.buffer === void 0) {
21164
+ this.populateBufferEntry(localID);
21165
+ }
21157
21166
  const vtable = element.vtable;
21158
21167
  const buffer = element.buffer;
21159
21168
  if (vtable === void 0 || buffer === void 0 || offset >= (element.vtableCount ?? 0)) {
@@ -21223,6 +21232,11 @@ var StepModelBase = class {
21223
21232
  }
21224
21233
  const element = this.entry(localID);
21225
21234
  element.buffer = this.bufferProvider_.acquire(element.address, element.length).buffer;
21235
+ if (element.multiMapping !== void 0) {
21236
+ for (const mapped of element.multiMapping) {
21237
+ mapped.buffer = this.bufferProvider_.acquire(mapped.address, mapped.length).buffer;
21238
+ }
21239
+ }
21226
21240
  }
21227
21241
  /**
21228
21242
  * Get the size in bytes of the backing buffer for this.
@@ -21343,24 +21357,39 @@ var StepModelBase = class {
21343
21357
  if (!this.isSourceExternal) {
21344
21358
  return seen;
21345
21359
  }
21346
- const stack = [localID];
21360
+ const frontier = [];
21361
+ const enqueue = (id) => {
21362
+ if (id < this.count_ && !seen.has(id)) {
21363
+ frontier.push(id);
21364
+ }
21365
+ };
21366
+ enqueue(localID);
21347
21367
  if (extraLocalIDs !== void 0) {
21348
21368
  for (const extra of extraLocalIDs) {
21349
- stack.push(extra);
21369
+ enqueue(extra);
21350
21370
  }
21351
21371
  }
21352
- while (stack.length > 0) {
21353
- const id = stack.pop();
21354
- if (seen.has(id) || id >= this.count_) {
21355
- continue;
21372
+ while (frontier.length > 0) {
21373
+ const wave = [];
21374
+ for (const id of frontier) {
21375
+ if (seen.has(id) || id >= this.count_) {
21376
+ continue;
21377
+ }
21378
+ seen.add(id);
21379
+ this.pinByLocalID(id);
21380
+ wave.push(id);
21381
+ }
21382
+ frontier.length = 0;
21383
+ if (wave.length === 0) {
21384
+ break;
21356
21385
  }
21357
- seen.add(id);
21358
- await this.ensureResidentByLocalID(id);
21359
- this.pinByLocalID(id);
21360
- for (const expressID of this.scanRecordRefs_(id)) {
21361
- const referenced = this.expressIDMap_.get(expressID);
21362
- if (referenced !== void 0 && !seen.has(referenced)) {
21363
- stack.push(referenced);
21386
+ await Promise.all(wave.map((id) => this.ensureResidentByLocalID(id)));
21387
+ for (const id of wave) {
21388
+ for (const expressID of this.scanRecordRefs_(id)) {
21389
+ const referenced = this.expressIDMap_.get(expressID);
21390
+ if (referenced !== void 0 && !seen.has(referenced)) {
21391
+ frontier.push(referenced);
21392
+ }
21364
21393
  }
21365
21394
  }
21366
21395
  }
@@ -21389,6 +21418,35 @@ var StepModelBase = class {
21389
21418
  }
21390
21419
  this.bufferProvider_.unpinRange?.(this.address_[localID], this.length_[localID]);
21391
21420
  }
21421
+ /**
21422
+ * Drop captured source-window views on `localIDs` so the LRU can
21423
+ * evict those chunks. Vtables stay — `acquire` of the same
21424
+ * `(address, length)` is at a stable base. The next
21425
+ * `ensureResident` + field read rematerialises the view.
21426
+ *
21427
+ * @param localIDs Records whose `buffer` views to drop.
21428
+ */
21429
+ releaseSourceViews(localIDs) {
21430
+ if (!this.isSourceExternal) {
21431
+ return;
21432
+ }
21433
+ for (const localID of localIDs) {
21434
+ if (localID >= this.count_) {
21435
+ continue;
21436
+ }
21437
+ const item = this.complexEntries_?.get(localID) ?? this.descriptorCache_[localID];
21438
+ if (item === void 0) {
21439
+ continue;
21440
+ }
21441
+ item.buffer = void 0;
21442
+ if (item.multiMapping !== void 0) {
21443
+ for (const mapped of item.multiMapping) {
21444
+ mapped.buffer = void 0;
21445
+ }
21446
+ }
21447
+ }
21448
+ releaseScratchParsingBuffer();
21449
+ }
21392
21450
  /**
21393
21451
  * Unpin every local ID in `localIDs` (best-effort; missing IDs are
21394
21452
  * ignored). Use after {@link ensureResidentClosureByLocalID}, which
@@ -23035,6 +23093,7 @@ var StepEntityBase = class {
23035
23093
  */
23036
23094
  extractParseBuffer(offset, baseOffset, depth, result, module2, optional) {
23037
23095
  offset -= this.multiReference_ !== void 0 ? baseOffset : 0;
23096
+ this.guaranteeBuffer();
23038
23097
  const internalReference = this.guaranteeVTable(depth);
23039
23098
  if (offset >= internalReference.vtableCount) {
23040
23099
  throw new Error("Couldn't read field due to too few fields in record");
@@ -23147,6 +23206,7 @@ var StepEntityBase = class {
23147
23206
  * @return {Uint8Array} The buffer for this.
23148
23207
  */
23149
23208
  get buffer() {
23209
+ this.guaranteeBuffer();
23150
23210
  return this.internalReference_.buffer;
23151
23211
  }
23152
23212
  /**
@@ -23237,6 +23297,9 @@ var StepEntityBase = class {
23237
23297
  throw new Error("Entity does not have matching table entry to read from model");
23238
23298
  }
23239
23299
  }
23300
+ if (classReference.buffer === void 0) {
23301
+ this.model.populateBufferEntry(this.localID);
23302
+ }
23240
23303
  this.internalReference_.buffer = classReference.buffer;
23241
23304
  return classReference;
23242
23305
  }
@@ -23247,6 +23310,9 @@ var StepEntityBase = class {
23247
23310
  throw new Error("Entity does not have matching table entry to read from model");
23248
23311
  }
23249
23312
  }
23313
+ if (internalReference.buffer === void 0) {
23314
+ this.guaranteeBuffer();
23315
+ }
23250
23316
  return internalReference;
23251
23317
  }
23252
23318
  /**