@bldrs-ai/conway 1.530.1503 → 1.535.1506

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 (27) hide show
  1. package/compiled/examples/browser-bundled.cjs +260 -3
  2. package/compiled/examples/cli-bundled.cjs +390 -27
  3. package/compiled/examples/cli-step-bundled.cjs +1 -1
  4. package/compiled/examples/validator-bundled.cjs +260 -3
  5. package/compiled/src/compat/web-ifc/ifc_api.d.ts +50 -0
  6. package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
  7. package/compiled/src/compat/web-ifc/ifc_api.js +32 -0
  8. package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.js +303 -0
  9. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +9 -0
  10. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
  11. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +52 -4
  12. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
  13. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +246 -22
  14. package/compiled/src/ifc/geometry_residency.d.ts +170 -0
  15. package/compiled/src/ifc/geometry_residency.d.ts.map +1 -0
  16. package/compiled/src/ifc/geometry_residency.js +363 -0
  17. package/compiled/src/ifc/ifc_model_geometry.d.ts.map +1 -1
  18. package/compiled/src/ifc/ifc_model_geometry.js +17 -2
  19. package/compiled/src/ifc/ifc_scene_builder.d.ts +93 -0
  20. package/compiled/src/ifc/ifc_scene_builder.d.ts.map +1 -1
  21. package/compiled/src/ifc/ifc_scene_builder.js +143 -27
  22. package/compiled/src/ifc/ifc_step_model.d.ts +2 -0
  23. package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
  24. package/compiled/src/ifc/ifc_step_model.js +4 -0
  25. package/compiled/src/version/version.js +1 -1
  26. package/compiled/tsconfig.tsbuildinfo +1 -1
  27. 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.530.1503";
33
+ var versionString = "Conway v1.535.1506";
34
34
 
35
35
  // compiled/dependencies/conway-geom/interface/conway_geometry.js
36
36
  var wasmType = "";
@@ -71239,6 +71239,257 @@ var CanonicalMeshType;
71239
71239
  CanonicalMeshType2[CanonicalMeshType2["BUFFER_GEOMETRY"] = 0] = "BUFFER_GEOMETRY";
71240
71240
  })(CanonicalMeshType || (CanonicalMeshType = {}));
71241
71241
 
71242
+ // compiled/src/ifc/geometry_residency.js
71243
+ var BYTES_PER_VERTEX_ELEMENT = 8;
71244
+ var BYTES_PER_INDEX_ELEMENT = 4;
71245
+ var VOID_STORE_BIT = 1;
71246
+ var BYTES_PER_MIB = 1024 * 1024;
71247
+ var GeometryResidency = class {
71248
+ constructor() {
71249
+ this.budgetBytes_ = Number.POSITIVE_INFINITY;
71250
+ this.liveBytes_ = 0;
71251
+ this.everEvicted_ = false;
71252
+ this.order_ = /* @__PURE__ */ new Map();
71253
+ this.natives_ = /* @__PURE__ */ new Map();
71254
+ this.stores_ = [];
71255
+ }
71256
+ /**
71257
+ * @return {boolean} Whether a finite budget is configured. Every hook below
71258
+ * returns immediately when this is false, so an unbudgeted model pays one
71259
+ * predictable-branch per geometry add and lookup rather than the
71260
+ * bookkeeping — `getByLocalID` is on the scene-walk hot path.
71261
+ */
71262
+ get enabled() {
71263
+ return this.budgetBytes_ !== Number.POSITIVE_INFINITY;
71264
+ }
71265
+ /**
71266
+ * @return {number} The configured budget in bytes, or Infinity.
71267
+ */
71268
+ get budgetBytes() {
71269
+ return this.budgetBytes_;
71270
+ }
71271
+ /**
71272
+ * @return {number} Bytes currently accounted resident.
71273
+ */
71274
+ get liveBytes() {
71275
+ return this.liveBytes_;
71276
+ }
71277
+ /**
71278
+ * @return {number} How many assets are tracked.
71279
+ */
71280
+ get residentCount() {
71281
+ return this.order_.size;
71282
+ }
71283
+ /**
71284
+ * @return {boolean} Whether this model has ever had geometry evicted.
71285
+ */
71286
+ get everEvicted() {
71287
+ return this.everEvicted_;
71288
+ }
71289
+ /**
71290
+ * Register a store so a budget enabled later can see what it already
71291
+ * holds.
71292
+ *
71293
+ * @param store The store.
71294
+ */
71295
+ registerStore(store) {
71296
+ this.stores_.push(store);
71297
+ }
71298
+ /**
71299
+ * Set the budget. A non-finite or non-positive value disables eviction,
71300
+ * which is the default and the behaviour every consumer had before this
71301
+ * existed.
71302
+ *
71303
+ * Raising or lowering it takes effect at the next eviction pass rather than
71304
+ * immediately, so a caller that lowers the budget mid-load does not stall
71305
+ * the current batch freeing memory.
71306
+ *
71307
+ * **Enabling seeds from what is already cached.** The bookkeeping is fed
71308
+ * by `noteAdded`, which no-ops while unlimited, so a model that pumped
71309
+ * batches before a budget arrived — or one whose budget was disabled and
71310
+ * re-enabled — would start counting from zero and evict nothing until it
71311
+ * had extracted a budget's worth MORE geometry. The pre-existing residency
71312
+ * would sit there permanently while liveBytes reported the ceiling was
71313
+ * satisfied. That is precisely the case SetGeometryBudget exists for: a
71314
+ * tab already under pressure.
71315
+ *
71316
+ * Seeding takes the stores in iteration order, which is extraction order,
71317
+ * so the recency order it produces is oldest-first — the right guess when
71318
+ * no better information survived.
71319
+ *
71320
+ * @param bytes The new ceiling, or Infinity to disable.
71321
+ */
71322
+ setBudgetBytes(bytes) {
71323
+ if (!Number.isFinite(bytes) || bytes <= 0) {
71324
+ this.budgetBytes_ = Number.POSITIVE_INFINITY;
71325
+ this.order_.clear();
71326
+ this.natives_.clear();
71327
+ this.liveBytes_ = 0;
71328
+ return;
71329
+ }
71330
+ const wasDisabled = !this.enabled;
71331
+ this.budgetBytes_ = bytes;
71332
+ if (wasDisabled) {
71333
+ this.seedFromStores_();
71334
+ }
71335
+ }
71336
+ /**
71337
+ * Account for everything the stores already hold, for a budget enabled
71338
+ * after extraction has started.
71339
+ */
71340
+ seedFromStores_() {
71341
+ for (const store of this.stores_) {
71342
+ for (const mesh of store) {
71343
+ this.noteAdded(store, mesh);
71344
+ }
71345
+ }
71346
+ }
71347
+ /**
71348
+ * Record an asset as resident, or refresh one being replaced.
71349
+ *
71350
+ * @param store The store holding it.
71351
+ * @param mesh The mesh added.
71352
+ */
71353
+ noteAdded(store, mesh) {
71354
+ if (!this.enabled) {
71355
+ return;
71356
+ }
71357
+ const key = residencyKey(store, mesh.localID);
71358
+ if (this.order_.has(key)) {
71359
+ this.releaseKey_(key);
71360
+ }
71361
+ if (mesh.type !== CanonicalMeshType.BUFFER_GEOMETRY) {
71362
+ return;
71363
+ }
71364
+ const native = mesh.geometry;
71365
+ const tracked = this.natives_.get(native);
71366
+ if (tracked !== void 0) {
71367
+ tracked.keys.add(key);
71368
+ } else {
71369
+ const bytes = meshBytes(mesh);
71370
+ this.natives_.set(native, { bytes, keys: /* @__PURE__ */ new Set([key]) });
71371
+ this.liveBytes_ += bytes;
71372
+ }
71373
+ this.order_.set(key, { store, native });
71374
+ }
71375
+ /**
71376
+ * Drop one key's reference, reporting whether the native it names is now
71377
+ * unreferenced and therefore safe to free.
71378
+ *
71379
+ * @param key The composite key.
71380
+ * @return {boolean} True when this was the last reference.
71381
+ */
71382
+ releaseKey_(key) {
71383
+ const entry = this.order_.get(key);
71384
+ this.order_.delete(key);
71385
+ if (entry === void 0) {
71386
+ return true;
71387
+ }
71388
+ const tracked = this.natives_.get(entry.native);
71389
+ if (tracked === void 0) {
71390
+ return true;
71391
+ }
71392
+ tracked.keys.delete(key);
71393
+ if (tracked.keys.size > 0) {
71394
+ return false;
71395
+ }
71396
+ this.liveBytes_ -= tracked.bytes;
71397
+ this.natives_.delete(entry.native);
71398
+ return true;
71399
+ }
71400
+ /**
71401
+ * Whether freeing the native behind a store entry is safe — false while
71402
+ * another cached mesh still references the same native.
71403
+ *
71404
+ * @param store The store.
71405
+ * @param localID The asset's local ID.
71406
+ * @return {boolean} True when the caller should free the native.
71407
+ */
71408
+ releaseReference(store, localID) {
71409
+ if (!this.enabled) {
71410
+ return true;
71411
+ }
71412
+ return this.releaseKey_(residencyKey(store, localID));
71413
+ }
71414
+ /**
71415
+ * Record a use, moving the asset to the most-recent end.
71416
+ *
71417
+ * @param store The store queried.
71418
+ * @param localID The asset's local ID.
71419
+ */
71420
+ noteUsed(store, localID) {
71421
+ if (!this.enabled) {
71422
+ return;
71423
+ }
71424
+ const key = residencyKey(store, localID);
71425
+ const existing = this.order_.get(key);
71426
+ if (existing === void 0) {
71427
+ return;
71428
+ }
71429
+ this.order_.delete(key);
71430
+ this.order_.set(key, existing);
71431
+ }
71432
+ /**
71433
+ * Stop accounting for an asset something else freed — an explicit delete,
71434
+ * or the extractor reclaiming its own temporaries. Without this the budget
71435
+ * would keep charging for bytes nobody holds and evict live assets to make
71436
+ * room for them.
71437
+ *
71438
+ * @param store The store it was in.
71439
+ * @param localID The asset's local ID.
71440
+ */
71441
+ noteRemoved(store, localID) {
71442
+ if (!this.enabled) {
71443
+ return;
71444
+ }
71445
+ this.releaseKey_(residencyKey(store, localID));
71446
+ }
71447
+ /**
71448
+ * Evict least-recently-used assets until the live set fits the budget.
71449
+ *
71450
+ * @return {{evicted: number, freedBytes: number}} What this pass reclaimed.
71451
+ */
71452
+ evictToBudget() {
71453
+ if (!this.enabled) {
71454
+ return { evicted: 0, freedBytes: 0 };
71455
+ }
71456
+ let evicted = 0;
71457
+ let freedBytes = 0;
71458
+ for (const [key, entry] of this.order_) {
71459
+ if (this.liveBytes_ <= this.budgetBytes_) {
71460
+ break;
71461
+ }
71462
+ const localID = localIDOf(key);
71463
+ const bytes = this.natives_.get(entry.native)?.bytes ?? 0;
71464
+ entry.store.delete(localID);
71465
+ this.everEvicted_ = true;
71466
+ ++evicted;
71467
+ freedBytes += bytes;
71468
+ }
71469
+ return { evicted, freedBytes };
71470
+ }
71471
+ };
71472
+ function residencyKey(store, localID) {
71473
+ return localID * 2 + (store.isVoid ? VOID_STORE_BIT : 0);
71474
+ }
71475
+ function localIDOf(key) {
71476
+ return (key - key % 2) / 2;
71477
+ }
71478
+ function meshBytes(mesh) {
71479
+ if (mesh.type !== CanonicalMeshType.BUFFER_GEOMETRY) {
71480
+ return 0;
71481
+ }
71482
+ try {
71483
+ const allocated = mesh.geometry.getAllocationSize?.();
71484
+ if (typeof allocated === "number" && allocated > 0) {
71485
+ return allocated;
71486
+ }
71487
+ return mesh.geometry.GetVertexDataSize() * BYTES_PER_VERTEX_ELEMENT + mesh.geometry.GetIndexDataSize() * BYTES_PER_INDEX_ELEMENT;
71488
+ } catch {
71489
+ return 0;
71490
+ }
71491
+ }
71492
+
71242
71493
  // compiled/src/core/canonical_material.js
71243
71494
  var ROUGNESS_CONVERSION_FACTOR = 2;
71244
71495
  function roughnessToExponent(roughness) {
@@ -71318,6 +71569,7 @@ var IfcModelGeometry = class {
71318
71569
  this.model = model2;
71319
71570
  this.isVoid = isVoid;
71320
71571
  this.meshes_ = /* @__PURE__ */ new Map();
71572
+ model2.geometryResidency.registerStore(this);
71321
71573
  }
71322
71574
  /**
71323
71575
  * Get the number of items in this.
@@ -71334,7 +71586,8 @@ var IfcModelGeometry = class {
71334
71586
  for (const [key, value] of this.meshes_) {
71335
71587
  if (value.temporary) {
71336
71588
  this.meshes_.delete(key);
71337
- if (value.type === CanonicalMeshType.BUFFER_GEOMETRY) {
71589
+ const isLastReference = this.model.geometryResidency.releaseReference(this, key);
71590
+ if (value.type === CanonicalMeshType.BUFFER_GEOMETRY && isLastReference) {
71338
71591
  value.geometry.delete();
71339
71592
  }
71340
71593
  }
@@ -71362,6 +71615,7 @@ var IfcModelGeometry = class {
71362
71615
  mesh.geometry.GetVertexData();
71363
71616
  }
71364
71617
  this.meshes_.set(mesh.localID, mesh);
71618
+ this.model.geometryResidency.noteAdded(this, mesh);
71365
71619
  }
71366
71620
  /**
71367
71621
  * Drop the mesh for a particular local ID
@@ -71372,7 +71626,8 @@ var IfcModelGeometry = class {
71372
71626
  const value = this.meshes_.get(localID);
71373
71627
  if (value !== void 0) {
71374
71628
  this.meshes_.delete(localID);
71375
- if (value.type === CanonicalMeshType.BUFFER_GEOMETRY) {
71629
+ const isLastReference = this.model.geometryResidency.releaseReference(this, localID);
71630
+ if (value.type === CanonicalMeshType.BUFFER_GEOMETRY && isLastReference) {
71376
71631
  value.geometry.delete();
71377
71632
  }
71378
71633
  }
@@ -71384,6 +71639,7 @@ var IfcModelGeometry = class {
71384
71639
  * @return {CanonicalMesh | undefined}
71385
71640
  */
71386
71641
  getByLocalID(localID) {
71642
+ this.model.geometryResidency.noteUsed(this, localID);
71387
71643
  return this.meshes_.get(localID);
71388
71644
  }
71389
71645
  /**
@@ -71844,6 +72100,7 @@ var IfcStepModel = class extends step_model_base_default {
71844
72100
  constructor(buffer, elementIndex, provider) {
71845
72101
  super(schema_ifc_gen_default, buffer, elementIndex, provider);
71846
72102
  this.externalMappingType = ifc_step_external_mapping_default;
72103
+ this.geometryResidency = new GeometryResidency();
71847
72104
  this.geometry = new IfcModelGeometry(this);
71848
72105
  this.voidGeometry = new IfcModelGeometry(this, true);
71849
72106
  this.profiles = new IfcModelProfile(this);