@bldrs-ai/conway 1.443.1325 → 1.445.1339

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 (51) hide show
  1. package/compiled/Dist/ConwayGeomWasmNode.js +0 -0
  2. package/compiled/Dist/ConwayGeomWasmNodeMT.js +0 -0
  3. package/compiled/Dist/ConwayGeomWasmWeb.js +0 -0
  4. package/compiled/Dist/ConwayGeomWasmWebMT.wasm +0 -0
  5. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNode.js +0 -0
  6. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNodeMT.js +0 -0
  7. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWeb.js +0 -0
  8. package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.wasm +0 -0
  9. package/compiled/examples/browser-bundled.cjs +62 -8
  10. package/compiled/examples/cli-bundled.cjs +137 -23
  11. package/compiled/examples/cli-step-bundled.cjs +156 -28
  12. package/compiled/examples/validator-bundled.cjs +62 -8
  13. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts.map +1 -1
  14. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.js +153 -23
  15. package/compiled/src/AP214E3_2010/ap214_geometry_extraction.test.js +6 -1
  16. package/compiled/src/compat/web-ifc/coordination_f64.d.ts +12 -0
  17. package/compiled/src/compat/web-ifc/coordination_f64.d.ts.map +1 -1
  18. package/compiled/src/compat/web-ifc/coordination_f64.js +13 -0
  19. package/compiled/src/compat/web-ifc/ifc_api.d.ts +13 -0
  20. package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
  21. package/compiled/src/compat/web-ifc/ifc_api.js +19 -0
  22. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +9 -0
  23. package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
  24. package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts +2 -0
  25. package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts.map +1 -0
  26. package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.js +124 -0
  27. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts +10 -0
  28. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts.map +1 -1
  29. package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.js +35 -2
  30. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +20 -0
  31. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
  32. package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +56 -2
  33. package/compiled/src/ifc/ifc_geometry_extraction.d.ts +5 -4
  34. package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
  35. package/compiled/src/ifc/ifc_geometry_extraction.js +60 -16
  36. package/compiled/src/step/parsing/decode_utf8.d.ts +15 -0
  37. package/compiled/src/step/parsing/decode_utf8.d.ts.map +1 -1
  38. package/compiled/src/step/parsing/decode_utf8.js +28 -0
  39. package/compiled/src/step/parsing/step_string_parser.js +8 -8
  40. package/compiled/src/step/parsing/uint32_sink.d.ts +37 -0
  41. package/compiled/src/step/parsing/uint32_sink.d.ts.map +1 -0
  42. package/compiled/src/step/parsing/uint32_sink.js +50 -0
  43. package/compiled/src/step/parsing/uint32_sink.test.d.ts +2 -0
  44. package/compiled/src/step/parsing/uint32_sink.test.d.ts.map +1 -0
  45. package/compiled/src/step/parsing/uint32_sink.test.js +77 -0
  46. package/compiled/src/step/step_entity_base.d.ts +20 -0
  47. package/compiled/src/step/step_entity_base.d.ts.map +1 -1
  48. package/compiled/src/step/step_entity_base.js +42 -1
  49. package/compiled/src/version/version.js +1 -1
  50. package/compiled/tsconfig.tsbuildinfo +1 -1
  51. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import { BlendMode, } from "../../dependencies/conway-geom/index.js";
2
+ import { Uint32Sink } from "../step/parsing/uint32_sink.js";
2
3
  import { exponentToRoughness } from "../core/canonical_material.js";
3
4
  import { CanonicalMeshType } from "../core/canonical_mesh.js";
4
5
  import { yieldToEventLoop } from "../core/progress.js";
@@ -108,6 +109,12 @@ export function extractColorOrFactorMultiply(from, surfaceColor, alpha = 1) {
108
109
  * Handles Geometry data extraction from a populated IfcStepModel
109
110
  * Can export to OBJ, GLTF (Draco), GLB (Draco)
110
111
  */
112
+ /**
113
+ * Starting capacities for the reused polygonal-faceset sinks: enough that a
114
+ * typical faceset never reallocates, while still growing for outliers.
115
+ */
116
+ const POLYGONAL_INDEX_SINK_CAPACITY = 65536;
117
+ const POLYGONAL_FACE_SINK_CAPACITY = 16384;
111
118
  export class IfcGeometryExtraction {
112
119
  constructor(conwayModel, model, limitCSGDepth = true, csgDepthLimit = 20, lowMemoryMode = false) {
113
120
  this.conwayModel = conwayModel;
@@ -115,6 +122,13 @@ export class IfcGeometryExtraction {
115
122
  this.limitCSGDepth = limitCSGDepth;
116
123
  this.csgDepthLimit = csgDepthLimit;
117
124
  this.lowMemoryMode = lowMemoryMode;
125
+ /* Reused across polygonal-faceset extractions; see extractPolygonalFaceSet. */
126
+ this.polygonalIndexSink_ = new Uint32Sink(POLYGONAL_INDEX_SINK_CAPACITY);
127
+ this.polygonalStartIndexSink_ = new Uint32Sink(POLYGONAL_FACE_SINK_CAPACITY);
128
+ this.polygonalFaceOffsetSink_ = new Uint32Sink(POLYGONAL_FACE_SINK_CAPACITY);
129
+ this.polygonalStartOffsetSink_ = new Uint32Sink(POLYGONAL_FACE_SINK_CAPACITY);
130
+ /* Guards the sinks against a re-entrant faceset extraction. */
131
+ this.polygonalSinksInUse_ = false;
118
132
  this.TWO_DIMENSIONS = 2;
119
133
  this.THREE_DIMENSIONS = 3;
120
134
  this.circleSegments = 12;
@@ -525,11 +539,30 @@ export class IfcGeometryExtraction {
525
539
  */
526
540
  extractPolygonalFaceSet(entity, temporary = false, isRelVoid = false) {
527
541
  const result = ExtractResult.COMPLETE;
528
- // Temporary storage for indices and start indices
529
- const allIndices = [];
530
- const allStartIndices = [];
531
- const polygonalFaceBufferOffsets = [];
532
- const startIndicesBufferOffsets = [];
542
+ // Reusable typed sinks. A tessellated model can carry millions of
543
+ // IfcIndexedPolygonalFace records, and the boxed `Array< number >`
544
+ // this loop used to build per face — which the generated CoordIndex
545
+ // getter also cached on the face, keeping it alive — dominated both
546
+ // GC time and retained heap during extraction. Indices are parsed
547
+ // straight from the STEP buffer into these instead, reused across
548
+ // facesets.
549
+ // The sinks are extractor-scoped, so a nested faceset extraction
550
+ // reached from inside this one would silently clobber them. Nothing
551
+ // in the window between reset and the wasm copies below recurses
552
+ // today (the face loop only parses), so this guards the invariant
553
+ // rather than a live bug — fail loudly if that ever changes.
554
+ if (this.polygonalSinksInUse_) {
555
+ throw new Error("extractPolygonalFaceSet re-entered: the shared index sinks are already in use");
556
+ }
557
+ this.polygonalSinksInUse_ = true;
558
+ const allIndices = this.polygonalIndexSink_;
559
+ const allStartIndices = this.polygonalStartIndexSink_;
560
+ const polygonalFaceBufferOffsets = this.polygonalFaceOffsetSink_;
561
+ const startIndicesBufferOffsets = this.polygonalStartOffsetSink_;
562
+ allIndices.reset();
563
+ allStartIndices.reset();
564
+ polygonalFaceBufferOffsets.reset();
565
+ startIndicesBufferOffsets.reset();
533
566
  let indicesPerFace = -1;
534
567
  // Prepare indices and start indices for all faces
535
568
  entity.Faces.forEach((polygonalFace) => {
@@ -539,35 +572,43 @@ export class IfcGeometryExtraction {
539
572
  startIndicesBufferOffsets.push(allStartIndices.length);
540
573
  let coordIndex = 0;
541
574
  if (polygonalFace instanceof IfcIndexedPolygonalFaceWithVoids) {
575
+ // Voided faces are rare; keep the straightforward getter path.
542
576
  indicesPerFace = polygonalFace.CoordIndex.length;
543
577
  allStartIndices.push(0);
544
578
  coordIndex += indicesPerFace;
545
- allIndices.push(...polygonalFace.CoordIndex);
579
+ for (const index of polygonalFace.CoordIndex) {
580
+ allIndices.push(index);
581
+ }
546
582
  polygonalFace.InnerCoordIndices.forEach((innerIndices) => {
547
583
  allStartIndices.push(coordIndex);
548
- allIndices.push(...innerIndices);
584
+ for (const index of innerIndices) {
585
+ allIndices.push(index);
586
+ }
549
587
  coordIndex += innerIndices.length;
550
588
  });
551
589
  }
552
590
  else {
553
- indicesPerFace = polygonalFace.CoordIndex.length;
591
+ // CoordIndex is vtable offset 0 on IfcIndexedPolygonalFace (see
592
+ // its generated getter) — parsed in place, never allocated or cached.
593
+ indicesPerFace = polygonalFace.extractIntegerArrayInto(0, 0, 3, allIndices);
554
594
  allStartIndices.push(0);
555
- allIndices.push(...polygonalFace.CoordIndex);
556
595
  }
557
596
  });
558
597
  // Add the final entry
559
598
  polygonalFaceBufferOffsets.push(allIndices.length);
560
599
  startIndicesBufferOffsets.push(allStartIndices.length);
561
- // Convert to typed arrays for transfer to WebAssembly
562
- const indicesArray = new Uint32Array(allIndices);
600
+ // Views over exactly the appended elements — no intermediate copy.
601
+ const indicesArray = allIndices.view;
563
602
  const indicesArrayPtr = this.arrayToWasmHeap(indicesArray);
564
- const startIndicesArray = new Uint32Array(allStartIndices);
603
+ const startIndicesArray = allStartIndices.view;
565
604
  const startIndicesArrayPtr = this.arrayToWasmHeap(startIndicesArray);
566
- const polygonalFaceBufferOffsetsArray = new Uint32Array(polygonalFaceBufferOffsets);
605
+ const polygonalFaceBufferOffsetsArray = polygonalFaceBufferOffsets.view;
567
606
  const polygonalFaceBufferOffsetsArrayPtr = this.arrayToWasmHeap(polygonalFaceBufferOffsetsArray);
568
- const startIndicesBufferOffsetsArray = new Uint32Array(startIndicesBufferOffsets);
607
+ const startIndicesBufferOffsetsArray = startIndicesBufferOffsets.view;
569
608
  const startIndicesBufferOffsetsArrayPtr = this.arrayToWasmHeap(startIndicesBufferOffsetsArray);
570
- const polygonalFaceVector = this.wasmModule.buildIndexedPolygonalFaceVector(indicesArrayPtr, indicesArray.length, startIndicesArrayPtr, polygonalFaceBufferOffsetsArrayPtr, polygonalFaceBufferOffsets.length, startIndicesBufferOffsetsArrayPtr, startIndicesBufferOffsets.length);
609
+ const polygonalFaceVector = this.wasmModule.buildIndexedPolygonalFaceVector(indicesArrayPtr, indicesArray.length, startIndicesArrayPtr, polygonalFaceBufferOffsetsArrayPtr, polygonalFaceBufferOffsetsArray.length, startIndicesBufferOffsetsArrayPtr, startIndicesBufferOffsetsArray.length);
610
+ // Sink contents are now copied into wasm; the sinks are free again.
611
+ this.polygonalSinksInUse_ = false;
571
612
  const pointsParseBuffer = this.conwayModel.nativeParseBuffer();
572
613
  if (!entity.Coordinates.extractParseBuffer(0, 0, 0, pointsParseBuffer, this.wasmModule, true)) {
573
614
  pointsParseBuffer.resize(0);
@@ -614,7 +655,10 @@ export class IfcGeometryExtraction {
614
655
  const arrayPtr = this.wasmModule._malloc(numBytes);
615
656
  // Create a new Uint8Array view on the Wasm memory buffer, then set the array to it
616
657
  const arrayWasm = new Uint8Array(this.wasmModule.HEAPU8.buffer, arrayPtr, numBytes);
617
- arrayWasm.set(new Uint8Array(array.buffer));
658
+ // Honour the view's own window: subarray() results share their parent's
659
+ // backing buffer, so copying `array.buffer` wholesale would read the
660
+ // wrong bytes (and the wrong length) for a view.
661
+ arrayWasm.set(new Uint8Array(array.buffer, array.byteOffset, numBytes));
618
662
  return arrayPtr;
619
663
  }
620
664
  /**
@@ -27,6 +27,21 @@
27
27
  * @return The decoded string.
28
28
  */
29
29
  export declare function decodeUtf8(view: Uint8Array): string;
30
+ /**
31
+ * Decode the raw byte run of a STEP string literal.
32
+ *
33
+ * ISO 10303-21 says raw (non-\X\-escaped) bytes are ISO 8859-1, but modern
34
+ * exporters routinely write UTF-8 (and some, like Onshape's ST-Developer,
35
+ * write outright invalid sequences). The lenient default decoder mapped every
36
+ * non-UTF-8 byte to U+FFFD, so a spec-conformant latin-1 'Küche' surfaced as
37
+ * 'K�che' in product names and titles. Decode as strict UTF-8 first (the
38
+ * common modern case, and unambiguous when it validates), and fall back to
39
+ * exact ISO 8859-1 (byte = code point, which cannot fail) when it doesn't.
40
+ *
41
+ * @param view The bytes of the string literal's raw run.
42
+ * @return The decoded string.
43
+ */
44
+ export declare function decodeStepString(view: Uint8Array): string;
30
45
  /**
31
46
  * Install a global, idempotent `TextDecoder.prototype.decode` shim that copies a
32
47
  * view out of a resizable/growable buffer before decoding. This covers decodes
@@ -1 +1 @@
1
- {"version":3,"file":"decode_utf8.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/decode_utf8.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA+BH;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEnD;AAID;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,IAAI,IAAI,CAqBtD"}
1
+ {"version":3,"file":"decode_utf8.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/decode_utf8.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AA+BH;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEnD;AAID;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAczD;AAID;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,IAAI,IAAI,CAqBtD"}
@@ -54,6 +54,34 @@ function copyOutOfResizable(view) {
54
54
  export function decodeUtf8(view) {
55
55
  return decoder.decode(decodeNeedsCopy(view.buffer) ? view.slice() : view);
56
56
  }
57
+ const strictUtf8Decoder = new TextDecoder('utf-8', { fatal: true });
58
+ /**
59
+ * Decode the raw byte run of a STEP string literal.
60
+ *
61
+ * ISO 10303-21 says raw (non-\X\-escaped) bytes are ISO 8859-1, but modern
62
+ * exporters routinely write UTF-8 (and some, like Onshape's ST-Developer,
63
+ * write outright invalid sequences). The lenient default decoder mapped every
64
+ * non-UTF-8 byte to U+FFFD, so a spec-conformant latin-1 'Küche' surfaced as
65
+ * 'K�che' in product names and titles. Decode as strict UTF-8 first (the
66
+ * common modern case, and unambiguous when it validates), and fall back to
67
+ * exact ISO 8859-1 (byte = code point, which cannot fail) when it doesn't.
68
+ *
69
+ * @param view The bytes of the string literal's raw run.
70
+ * @return The decoded string.
71
+ */
72
+ export function decodeStepString(view) {
73
+ const bytes = decodeNeedsCopy(view.buffer) ? view.slice() : view;
74
+ try {
75
+ return strictUtf8Decoder.decode(bytes);
76
+ }
77
+ catch {
78
+ let result = '';
79
+ for (let where = 0; where < bytes.length; ++where) {
80
+ result += String.fromCharCode(bytes[where]);
81
+ }
82
+ return result;
83
+ }
84
+ }
57
85
  let shimInstalled = false;
58
86
  /**
59
87
  * Install a global, idempotent `TextDecoder.prototype.decode` shim that copies a
@@ -1,6 +1,6 @@
1
1
  import ParsingConstants from "../../parsing/parsing_constants.js";
2
2
  import ParsingDfa16Table from "../../parsing/parsing_dfa_16table.js";
3
- import { decodeUtf8, installResizableTextDecoderShim } from "./decode_utf8.js";
3
+ import { decodeStepString, installResizableTextDecoderShim } from "./decode_utf8.js";
4
4
  // Emscripten 6's browser wasm heap is a resizable ArrayBuffer, on which strict
5
5
  // browsers' TextDecoder.decode() throws — including the glue's own UTF8ToString
6
6
  // during geometry extraction. Install the global copy-first shim as the STEP
@@ -76,7 +76,7 @@ class StepStringParser extends ParsingDfa16Table {
76
76
  if (nextCursor < endCursor && input[nextCursor] === QUOTE) {
77
77
  result ??= "";
78
78
  if (cursor > reificationIndex) {
79
- result += decodeUtf8(input.subarray(reificationIndex, cursor - 1));
79
+ result += decodeStepString(input.subarray(reificationIndex, cursor - 1));
80
80
  }
81
81
  result += "'";
82
82
  cursor = nextCursor + 1;
@@ -84,7 +84,7 @@ class StepStringParser extends ParsingDfa16Table {
84
84
  }
85
85
  else {
86
86
  result ??= "";
87
- result += decodeUtf8(input.subarray(reificationIndex, cursor));
87
+ result += decodeStepString(input.subarray(reificationIndex, cursor));
88
88
  return result;
89
89
  }
90
90
  }
@@ -111,7 +111,7 @@ class StepStringParser extends ParsingDfa16Table {
111
111
  const nextChar2 = input[nextCursor2];
112
112
  if (nextChar2 !== BSLASH) {
113
113
  result ??= "";
114
- result += decodeUtf8(input.subarray(reificationIndex, cursor));
114
+ result += decodeStepString(input.subarray(reificationIndex, cursor));
115
115
  cursor = nextCursor2 + 1;
116
116
  break;
117
117
  }
@@ -124,7 +124,7 @@ class StepStringParser extends ParsingDfa16Table {
124
124
  return result;
125
125
  }
126
126
  result ??= "";
127
- result += decodeUtf8(input.subarray(reificationIndex, cursor));
127
+ result += decodeStepString(input.subarray(reificationIndex, cursor));
128
128
  codePage = nextChar3 - A;
129
129
  cursor = nextCursor3 + 1;
130
130
  reificationIndex = cursor;
@@ -138,7 +138,7 @@ class StepStringParser extends ParsingDfa16Table {
138
138
  const nextChar2 = input[nextCursor2];
139
139
  if (nextChar2 !== BSLASH) {
140
140
  result ??= "";
141
- result += decodeUtf8(input.subarray(reificationIndex, cursor));
141
+ result += decodeStepString(input.subarray(reificationIndex, cursor));
142
142
  cursor = nextCursor2 + 1;
143
143
  break;
144
144
  }
@@ -148,7 +148,7 @@ class StepStringParser extends ParsingDfa16Table {
148
148
  }
149
149
  const nextChar3 = input[nextCursor3];
150
150
  result ??= "";
151
- result += decodeUtf8(input.subarray(reificationIndex, cursor));
151
+ result += decodeStepString(input.subarray(reificationIndex, cursor));
152
152
  /* eslint-disable no-magic-numbers */
153
153
  if (nextChar3 < 127) {
154
154
  result += String.fromCharCode(nextChar3);
@@ -171,7 +171,7 @@ class StepStringParser extends ParsingDfa16Table {
171
171
  }
172
172
  const nextChar2 = input[nextCursor2];
173
173
  result ??= "";
174
- result += decodeUtf8(input.subarray(reificationIndex, cursor));
174
+ result += decodeStepString(input.subarray(reificationIndex, cursor));
175
175
  const hexParserTil0 = (count) => {
176
176
  if (nextCursor2 + 1 >= endCursor || input[nextCursor2 + 1] !== BSLASH) {
177
177
  return false;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Growable Uint32Array append sink.
3
+ *
4
+ * Exists so hot extraction loops can parse integer list fields straight
5
+ * out of the STEP buffer into one reusable typed array, instead of
6
+ * allocating (and caching) a boxed `Array< number >` per record. On
7
+ * tessellated IFC4 models that difference is structural: a large
8
+ * polygonal-faceset model carries millions of IfcIndexedPolygonalFace
9
+ * records, and a per-record array for each is the dominant source of
10
+ * both GC time and retained heap during geometry extraction.
11
+ */
12
+ export declare class Uint32Sink {
13
+ private data_;
14
+ private length_;
15
+ /**
16
+ * @param initialCapacity Initial element capacity.
17
+ */
18
+ constructor(initialCapacity?: number);
19
+ /** @return {number} Element count appended since the last reset. */
20
+ get length(): number;
21
+ /**
22
+ * A view of exactly the appended elements. Only valid until the next
23
+ * append (which may reallocate) — copy it if it must outlive that.
24
+ *
25
+ * @return {Uint32Array} View over [0, length).
26
+ */
27
+ get view(): Uint32Array;
28
+ /** Drop all appended elements, keeping the allocated capacity. */
29
+ reset(): void;
30
+ /**
31
+ * Append one value, growing geometrically when full.
32
+ *
33
+ * @param value The value to append.
34
+ */
35
+ push(value: number): void;
36
+ }
37
+ //# sourceMappingURL=uint32_sink.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint32_sink.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/uint32_sink.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,qBAAa,UAAU;IAErB,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,OAAO,CAAY;IAE3B;;OAEG;gBACU,eAAe,GAAE,MAAa;IAI3C,oEAAoE;IACpE,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;;;;OAKG;IACH,IAAW,IAAI,IAAI,WAAW,CAE7B;IAED,kEAAkE;IAC3D,KAAK,IAAI,IAAI;IAIpB;;;;OAIG;IACI,IAAI,CAAE,KAAK,EAAE,MAAM,GAAI,IAAI;CAanC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Growable Uint32Array append sink.
3
+ *
4
+ * Exists so hot extraction loops can parse integer list fields straight
5
+ * out of the STEP buffer into one reusable typed array, instead of
6
+ * allocating (and caching) a boxed `Array< number >` per record. On
7
+ * tessellated IFC4 models that difference is structural: a large
8
+ * polygonal-faceset model carries millions of IfcIndexedPolygonalFace
9
+ * records, and a per-record array for each is the dominant source of
10
+ * both GC time and retained heap during geometry extraction.
11
+ */
12
+ export class Uint32Sink {
13
+ /**
14
+ * @param initialCapacity Initial element capacity.
15
+ */
16
+ constructor(initialCapacity = 1024) {
17
+ this.length_ = 0;
18
+ this.data_ = new Uint32Array(Math.max(1, initialCapacity));
19
+ }
20
+ /** @return {number} Element count appended since the last reset. */
21
+ get length() {
22
+ return this.length_;
23
+ }
24
+ /**
25
+ * A view of exactly the appended elements. Only valid until the next
26
+ * append (which may reallocate) — copy it if it must outlive that.
27
+ *
28
+ * @return {Uint32Array} View over [0, length).
29
+ */
30
+ get view() {
31
+ return this.data_.subarray(0, this.length_);
32
+ }
33
+ /** Drop all appended elements, keeping the allocated capacity. */
34
+ reset() {
35
+ this.length_ = 0;
36
+ }
37
+ /**
38
+ * Append one value, growing geometrically when full.
39
+ *
40
+ * @param value The value to append.
41
+ */
42
+ push(value) {
43
+ if (this.length_ === this.data_.length) {
44
+ const grown = new Uint32Array(this.data_.length * 2);
45
+ grown.set(this.data_);
46
+ this.data_ = grown;
47
+ }
48
+ this.data_[this.length_++] = value;
49
+ }
50
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=uint32_sink.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uint32_sink.test.d.ts","sourceRoot":"","sources":["../../../../src/step/parsing/uint32_sink.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,77 @@
1
+ /* eslint-disable no-magic-numbers */
2
+ // Uint32Sink backs the polygonal-faceset extraction fast path, and
3
+ // extractIntegerArrayInto must stay exactly equivalent to the generated
4
+ // array getters it replaces there — including for a real model's faces.
5
+ import * as fs from "fs";
6
+ import { beforeAll, describe, expect, test } from "@jest/globals";
7
+ import { IfcAPI } from "../../compat/web-ifc/ifc_api.js";
8
+ import { IfcIndexedPolygonalFace, IfcIndexedPolygonalFaceWithVoids, } from "../../ifc/ifc4_gen/index.js";
9
+ import { Uint32Sink } from "./uint32_sink.js";
10
+ describe("Uint32Sink", () => {
11
+ test("appends, grows past its initial capacity, and views exactly its length", () => {
12
+ const sink = new Uint32Sink(2);
13
+ expect(sink.length).toBe(0);
14
+ expect(Array.from(sink.view)).toEqual([]);
15
+ for (let where = 0; where < 10; ++where) {
16
+ sink.push(where * 3);
17
+ }
18
+ expect(sink.length).toBe(10);
19
+ expect(Array.from(sink.view)).toEqual([0, 3, 6, 9, 12, 15, 18, 21, 24, 27]);
20
+ });
21
+ test("reset drops elements but keeps capacity for reuse", () => {
22
+ const sink = new Uint32Sink(4);
23
+ sink.push(11);
24
+ sink.push(22);
25
+ sink.reset();
26
+ expect(sink.length).toBe(0);
27
+ expect(Array.from(sink.view)).toEqual([]);
28
+ sink.push(33);
29
+ expect(Array.from(sink.view)).toEqual([33]);
30
+ });
31
+ });
32
+ describe("extractIntegerArrayInto", () => {
33
+ let api;
34
+ let modelID;
35
+ /**
36
+ * The faces the extraction fast path actually covers: voided faces
37
+ * keep the getter path in production, so exclude them here too.
38
+ *
39
+ * @return {IfcIndexedPolygonalFace[]} Non-voided faces of the fixture.
40
+ */
41
+ function plainFaces() {
42
+ // The passthrough holds the proxy tuple; the StepModel is its head.
43
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
+ const model = api.models.get(modelID).model[0];
45
+ return Array.from(model.types(IfcIndexedPolygonalFace))
46
+ .filter((face) => !(face instanceof IfcIndexedPolygonalFaceWithVoids));
47
+ }
48
+ beforeAll(async () => {
49
+ api = new IfcAPI();
50
+ await api.Init();
51
+ modelID = api.OpenModel(new Uint8Array(fs.readFileSync("data/index.ifc")), { COORDINATE_TO_ORIGIN: true, USE_FAST_BOOLS: true });
52
+ }, 120000);
53
+ test("matches the generated CoordIndex getter on every face of a real model", () => {
54
+ const faces = plainFaces();
55
+ expect(faces.length).toBeGreaterThan(0);
56
+ const sink = new Uint32Sink(4);
57
+ for (const face of faces) {
58
+ // The getter caches, so read it first and compare the in-place
59
+ // parse against it — the fast path must be a drop-in.
60
+ const expected = face.CoordIndex;
61
+ sink.reset();
62
+ const count = face.extractIntegerArrayInto(0, 0, 3, sink);
63
+ expect(count).toBe(expected.length);
64
+ expect(Array.from(sink.view)).toEqual(expected);
65
+ }
66
+ }, 120000);
67
+ test("appends consecutively across records into one sink", () => {
68
+ const faces = plainFaces();
69
+ const sink = new Uint32Sink(4);
70
+ const expected = [];
71
+ for (const face of faces) {
72
+ face.extractIntegerArrayInto(0, 0, 3, sink);
73
+ expected.push(...face.CoordIndex);
74
+ }
75
+ expect(Array.from(sink.view)).toEqual(expected);
76
+ }, 120000);
77
+ });
@@ -3,6 +3,7 @@ import { Entity } from "../core/entity.js";
3
3
  import { EntityDescription, EntityFieldsDescription } from "../core/entity_description.js";
4
4
  import { EntityFieldDescription } from "../core/entity_field_description.js";
5
5
  import { WasmModule } from "../core/native_types.js";
6
+ import { Uint32Sink } from "./parsing/uint32_sink.js";
6
7
  import { StepEntityConstructorAbstract } from "./step_entity_constructor.js";
7
8
  import StepEntityInternalReference from "./step_entity_internal_reference.js";
8
9
  import StepModelBase from "./step_model_base.js";
@@ -307,6 +308,25 @@ export default abstract class StepEntityBase<EntityTypeIDs extends number> imple
307
308
  * @return {boolean} True if this extracts, false (usually because this is optional)
308
309
  */
309
310
  extractParseBuffer(offset: number, baseOffset: number, depth: number, result: ParseBuffer, module: WasmModule, optional: boolean): boolean;
311
+ /**
312
+ * Append an unsigned-integer list field straight from the STEP buffer
313
+ * into `sink`, without materialising an intermediate `Array< number >`.
314
+ *
315
+ * Semantically identical to the generated array getters (same
316
+ * optional handling, same element extraction, same "incorrectly
317
+ * typed" error), but it neither allocates nor caches a per-record
318
+ * array — the caller owns one reusable sink for the whole batch. On
319
+ * tessellated models this removes millions of short-lived arrays and
320
+ * the retained heap that goes with them; see Uint32Sink.
321
+ *
322
+ * @param offset The offset in the vtable to extract from.
323
+ * @param baseOffset The base offset of the class in the vtable.
324
+ * @param depth The depth in the inheritance hierarchy.
325
+ * @param sink Receives the appended values.
326
+ * @return {number} How many values were appended (0 when the field is
327
+ * unset/optional-null).
328
+ */
329
+ extractIntegerArrayInto(offset: number, baseOffset: number, depth: number, sink: Uint32Sink): number;
310
330
  /**
311
331
  * Extract a number at the particular vtable offset (i.e. the position
312
332
  * in the matching step object).
@@ -1 +1 @@
1
- {"version":3,"file":"step_entity_base.d.ts","sourceRoot":"","sources":["../../../src/step/step_entity_base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"step_entity_base.d.ts","sourceRoot":"","sources":["../../../src/step/step_entity_base.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { stepExtractArray, stepExtractBinary, stepExtractBoolean, stepExtractInlineElemement, stepExtractLogical, stepExtractNumber, stepExtractOptional, stepExtractReference, stepExtractString, } from "./parsing/step_deserialization_functions.js";
1
+ import { skipValue, stepExtractArray, stepExtractArrayBegin, stepExtractArrayToken, stepExtractBinary, stepExtractBoolean, stepExtractInlineElemement, stepExtractLogical, stepExtractNumber, stepExtractOptional, stepExtractReference, stepExtractString, } from "./parsing/step_deserialization_functions.js";
2
2
  import { stepBufferBase } from "./step_buffer_provider.js";
3
3
  var IfcTokenType;
4
4
  (function (IfcTokenType) {
@@ -449,6 +449,47 @@ export default class StepEntityBase {
449
449
  module.HEAPU8.set(buffer.subarray(cursor, endCursor), dataPtr);
450
450
  return true;
451
451
  }
452
+ /**
453
+ * Append an unsigned-integer list field straight from the STEP buffer
454
+ * into `sink`, without materialising an intermediate `Array< number >`.
455
+ *
456
+ * Semantically identical to the generated array getters (same
457
+ * optional handling, same element extraction, same "incorrectly
458
+ * typed" error), but it neither allocates nor caches a per-record
459
+ * array — the caller owns one reusable sink for the whole batch. On
460
+ * tessellated models this removes millions of short-lived arrays and
461
+ * the retained heap that goes with them; see Uint32Sink.
462
+ *
463
+ * @param offset The offset in the vtable to extract from.
464
+ * @param baseOffset The base offset of the class in the vtable.
465
+ * @param depth The depth in the inheritance hierarchy.
466
+ * @param sink Receives the appended values.
467
+ * @return {number} How many values were appended (0 when the field is
468
+ * unset/optional-null).
469
+ */
470
+ extractIntegerArrayInto(offset, baseOffset, depth, sink) {
471
+ let cursor = this.getOffsetCursor(offset, baseOffset, depth);
472
+ const buffer = this.buffer;
473
+ const endCursor = buffer.length;
474
+ if (stepExtractOptional(buffer, cursor, endCursor) === null) {
475
+ return 0;
476
+ }
477
+ let count = 0;
478
+ let signedCursor0 = stepExtractArrayBegin(buffer, cursor, endCursor);
479
+ cursor = Math.abs(signedCursor0);
480
+ while (signedCursor0 >= 0) {
481
+ const value = stepExtractNumber(buffer, cursor, endCursor);
482
+ if (value === void 0) {
483
+ throw new Error("Value in STEP was incorrectly typed");
484
+ }
485
+ cursor = skipValue(buffer, cursor, endCursor);
486
+ sink.push(value);
487
+ ++count;
488
+ signedCursor0 = stepExtractArrayToken(buffer, cursor, endCursor);
489
+ cursor = Math.abs(signedCursor0);
490
+ }
491
+ return count;
492
+ }
452
493
  /**
453
494
  * Extract a number at the particular vtable offset (i.e. the position
454
495
  * in the matching step object).
@@ -5,5 +5,5 @@
5
5
  // only the first segment (major) is meaningful and is the one CI carries forward.
6
6
  // Must stay in `vN.N.N` shape: the CI stamp regex, scripts/updateVersion.mjs, and
7
7
  // statistics.ts all match `v\d+\.\d+\.\d+`.
8
- const versionString = 'Conway v1.443.1325';
8
+ const versionString = 'Conway v1.445.1339';
9
9
  export { versionString };