@bldrs-ai/conway 1.536.1507 → 1.543.1513
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/compiled/examples/browser-bundled.cjs +39 -5
- package/compiled/examples/cli-bundled.cjs +197 -22
- package/compiled/examples/cli-step-bundled.cjs +39 -5
- package/compiled/examples/validator-bundled.cjs +39 -5
- package/compiled/src/compat/web-ifc/geometry_shard_coordination.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/geometry_shard_coordination.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/geometry_shard_coordination.test.js +236 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts +26 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api.js +33 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +6 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.js +264 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +116 -5
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +256 -85
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts +79 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/store_preview_channel.js +237 -14
- package/compiled/src/compat/web-ifc/store_preview_channel.test.js +270 -1
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +106 -1
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/streamed_preview_channel.js +269 -17
- package/compiled/src/core/progress_log.d.ts +75 -2
- package/compiled/src/core/progress_log.d.ts.map +1 -1
- package/compiled/src/core/progress_log.js +59 -2
- package/compiled/src/core/progress_log.test.js +75 -1
- package/compiled/src/ifc/dangling_placement_error.d.ts +35 -0
- package/compiled/src/ifc/dangling_placement_error.d.ts.map +1 -0
- package/compiled/src/ifc/dangling_placement_error.js +38 -0
- package/compiled/src/ifc/geometry_dispatch.d.ts +74 -3
- package/compiled/src/ifc/geometry_dispatch.d.ts.map +1 -1
- package/compiled/src/ifc/geometry_dispatch.js +261 -5
- package/compiled/src/ifc/geometry_dispatch.test.js +147 -1
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts +54 -0
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_geometry_extraction.js +153 -20
- package/compiled/src/index.d.ts +1 -1
- package/compiled/src/index.d.ts.map +1 -1
- package/compiled/src/index.js +1 -1
- package/compiled/src/step/dangling_reference_error.d.ts +34 -0
- package/compiled/src/step/dangling_reference_error.d.ts.map +1 -0
- package/compiled/src/step/dangling_reference_error.js +36 -0
- package/compiled/src/step/step_entity_base.d.ts +17 -0
- package/compiled/src/step/step_entity_base.d.ts.map +1 -1
- package/compiled/src/step/step_entity_base.js +28 -4
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -13,11 +13,14 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Model: Arty_Z7.stp — AP214, 38.1 MB, SolidWorks 2021 (SwSTEP 2.0)
|
|
15
15
|
* Parsing [0%................100%] 3.2s, +210 MB heap
|
|
16
|
+
* Preview: first mesh 0.275s, 539 emitted, 12 deferred (11 on placements), 8 retried
|
|
16
17
|
* Geometry [0%........56%] 41.0s, +388 MB heap
|
|
17
18
|
* Total: 44.7s, 512 → 1110 MB heap
|
|
18
19
|
*
|
|
19
20
|
* Stage lines own only their deltas (duration, heap growth); Total is not
|
|
20
21
|
* additive — it is a separate before/after wall-clock + heap observation.
|
|
22
|
+
* The Preview line is not a stage either — it reports what the parse-time
|
|
23
|
+
* preview delivered while Parsing ran (see {@link formatPreviewLine}).
|
|
21
24
|
*/
|
|
22
25
|
/** What a header parse can tell us before the full file parse (issue #301). */
|
|
23
26
|
export interface ModelInfo {
|
|
@@ -79,6 +82,62 @@ export declare function formatMb(megabytes: number): string;
|
|
|
79
82
|
* SolidWorks 2021 (SwSTEP 2.0)"
|
|
80
83
|
*/
|
|
81
84
|
export declare function formatModelLine(info: ModelInfo): string;
|
|
85
|
+
/**
|
|
86
|
+
* What a parse-time preview channel delivered — structurally typed against
|
|
87
|
+
* both channels' `previewYield` (compat/web-ifc/{store,streamed}_preview_
|
|
88
|
+
* channel.ts) so this module stays import-free.
|
|
89
|
+
*/
|
|
90
|
+
export interface PreviewYieldLike {
|
|
91
|
+
/**
|
|
92
|
+
* Ms from the channel starting to the first mesh handed to the consumer;
|
|
93
|
+
* undefined when it never emitted one.
|
|
94
|
+
*/
|
|
95
|
+
firstMeshMs?: number;
|
|
96
|
+
/**
|
|
97
|
+
* Preview meshes actually handed to the consumer. Distinct from
|
|
98
|
+
* {@link emitted}: one unit can yield several meshes, and a unit with no
|
|
99
|
+
* representation yields none at all, so reporting only units produced the
|
|
100
|
+
* self-contradicting "no mesh, 20 emitted" (codex round 2 on #543).
|
|
101
|
+
*/
|
|
102
|
+
meshes: number;
|
|
103
|
+
/**
|
|
104
|
+
* Units the preview EXTRACTED — attempted and got a non-throwing answer
|
|
105
|
+
* from. Not a count of what reached the screen; that is
|
|
106
|
+
* {@link meshes}. This is the counter the channel's `maxUnits` cap
|
|
107
|
+
* measures, which is why it stays unit-shaped.
|
|
108
|
+
*/
|
|
109
|
+
emitted: number;
|
|
110
|
+
deferred: number;
|
|
111
|
+
deferredOnPlacement: number;
|
|
112
|
+
retried: number;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* The preview line: time-to-first-pixel, and why the preview delivered what
|
|
116
|
+
* it did.
|
|
117
|
+
*
|
|
118
|
+
* First pixels are the number that decides whether a first-time visitor
|
|
119
|
+
* sees their building or a blank canvas, and until conway#542 it was
|
|
120
|
+
* judged by eye — measurable only in a Node harness nobody runs in
|
|
121
|
+
* production. The deferral split is what makes a blank first load
|
|
122
|
+
* attributable rather than merely observed: a ratio near 1.0 ON PLACEMENTS
|
|
123
|
+
* is the file-layout case (an exporter that writes the leaf points and
|
|
124
|
+
* directions a product's placement chain bottoms out in toward the tail of
|
|
125
|
+
* the file), and anything else is a different problem wearing the same
|
|
126
|
+
* blank screen. `retried` is the second-look count — a retry path that has
|
|
127
|
+
* silently stopped firing shows up here rather than merely as a slower
|
|
128
|
+
* load.
|
|
129
|
+
*
|
|
130
|
+
* Meshes and units are reported separately because they diverge in both
|
|
131
|
+
* directions: one unit can place several meshes, and a unit with no
|
|
132
|
+
* representation (a site, a storey) extracts cleanly while placing none.
|
|
133
|
+
* Folding them into one "emitted" number let the line say "no mesh, 20
|
|
134
|
+
* emitted" about the same load (codex round 2 on #543).
|
|
135
|
+
*
|
|
136
|
+
* @param preview The channel's reported yield.
|
|
137
|
+
* @return {string} e.g. "Preview: first mesh 0.275s, 1750 meshes from 539
|
|
138
|
+
* units, 12 deferred (11 on placements), 8 retried"
|
|
139
|
+
*/
|
|
140
|
+
export declare function formatPreviewLine(preview: PreviewYieldLike): string;
|
|
82
141
|
/**
|
|
83
142
|
* Accumulates progress events into the normalized text report: a live
|
|
84
143
|
* current-stage line while a stage runs, a frozen line per finished stage,
|
|
@@ -96,6 +155,7 @@ export declare class LoadLogAccumulator {
|
|
|
96
155
|
private firstHeapMb_;
|
|
97
156
|
private lastHeapMb_;
|
|
98
157
|
private modelLine_;
|
|
158
|
+
private previewLine_;
|
|
99
159
|
/**
|
|
100
160
|
* Record the model line (from header info) — kept with the report.
|
|
101
161
|
*
|
|
@@ -103,6 +163,18 @@ export declare class LoadLogAccumulator {
|
|
|
103
163
|
* @return {string} The formatted model line.
|
|
104
164
|
*/
|
|
105
165
|
setModelInfo(info: ModelInfo): string;
|
|
166
|
+
/**
|
|
167
|
+
* Record what the parse-time preview delivered — kept with the report
|
|
168
|
+
* and rendered between the stage lines and Total.
|
|
169
|
+
*
|
|
170
|
+
* Not a stage: the preview runs *inside* Parsing, so feeding it through
|
|
171
|
+
* onProgress would close the Parsing stage and reopen it, splitting one
|
|
172
|
+
* parse across two lines.
|
|
173
|
+
*
|
|
174
|
+
* @param preview The channel's reported yield.
|
|
175
|
+
* @return {string} The formatted preview line.
|
|
176
|
+
*/
|
|
177
|
+
setPreviewStats(preview: PreviewYieldLike): string;
|
|
106
178
|
/**
|
|
107
179
|
* Feed one progress event; returns the finished stage's line when this
|
|
108
180
|
* event closed a stage (so callers can mirror it to a console/log once).
|
|
@@ -141,8 +213,9 @@ export declare class LoadLogAccumulator {
|
|
|
141
213
|
*/
|
|
142
214
|
totalLine(): string;
|
|
143
215
|
/**
|
|
144
|
-
* The full report: model line (if known), finished stage lines,
|
|
145
|
-
*
|
|
216
|
+
* The full report: model line (if known), finished stage lines, the
|
|
217
|
+
* preview line (if reported), then the Total line. Call
|
|
218
|
+
* closeCurrentStage() first at load end.
|
|
146
219
|
*
|
|
147
220
|
* @return {string[]} All report lines.
|
|
148
221
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress_log.d.ts","sourceRoot":"","sources":["../../../src/core/progress_log.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"progress_log.d.ts","sourceRoot":"","sources":["../../../src/core/progress_log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,+EAA+E;AAC/E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAqBD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAE,KAAK,EAAE,MAAM,GAAI,MAAM,CAQlD;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAE,OAAO,CAAC,EAAE,MAAM,GAAI,MAAM,CASpD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAE,YAAY,EAAE,MAAM,GAAI,MAAM,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAE,SAAS,EAAE,MAAM,GAAI,MAAM,CAEpD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAE,IAAI,EAAE,SAAS,GAAI,MAAM,CA0BzD;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,iBAAiB,CAAE,OAAO,EAAE,gBAAgB,GAAI,MAAM,CAUrE;AA6DD;;;;;;;;GAQG;AACH,qBAAa,kBAAkB;IAE7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,eAAe,CAAoB;IAC3C,OAAO,CAAC,cAAc,CAAY;IAClC,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,YAAY,CAAoB;IAExC;;;;;OAKG;IACI,YAAY,CAAE,IAAI,EAAE,SAAS,GAAI,MAAM;IAM9C;;;;;;;;;;OAUG;IACI,eAAe,CAAE,OAAO,EAAE,gBAAgB,GAAI,MAAM;IAM3D;;;;;;OAMG;IACI,UAAU,CAAE,KAAK,EAAE,iBAAiB,GAAI,MAAM,GAAG,SAAS;IAiDjE;;;;;;;;OAQG;IACI,iBAAiB,CAAE,WAAW,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAI,MAAM,GAAG,SAAS;IAuBzF;;;;OAIG;IACI,WAAW,IAAI,MAAM,GAAG,SAAS;IAQxC;;;;OAIG;IACI,aAAa,IAAI,MAAM,EAAE;IAIhC;;;;;OAKG;IACI,SAAS,IAAI,MAAM;IAY1B;;;;;;OAMG;IACI,QAAQ,IAAI,MAAM,EAAE;CAiB5B"}
|
|
@@ -13,11 +13,14 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Model: Arty_Z7.stp — AP214, 38.1 MB, SolidWorks 2021 (SwSTEP 2.0)
|
|
15
15
|
* Parsing [0%................100%] 3.2s, +210 MB heap
|
|
16
|
+
* Preview: first mesh 0.275s, 539 emitted, 12 deferred (11 on placements), 8 retried
|
|
16
17
|
* Geometry [0%........56%] 41.0s, +388 MB heap
|
|
17
18
|
* Total: 44.7s, 512 → 1110 MB heap
|
|
18
19
|
*
|
|
19
20
|
* Stage lines own only their deltas (duration, heap growth); Total is not
|
|
20
21
|
* additive — it is a separate before/after wall-clock + heap observation.
|
|
22
|
+
* The Preview line is not a stage either — it reports what the parse-time
|
|
23
|
+
* preview delivered while Parsing ran (see {@link formatPreviewLine}).
|
|
21
24
|
*/
|
|
22
25
|
/** Display labels for the phase taxonomy; unknown phases title-case as-is. */
|
|
23
26
|
const STAGE_LABELS = {
|
|
@@ -112,6 +115,41 @@ export function formatModelLine(info) {
|
|
|
112
115
|
const detail = parts.length > 0 ? ` — ${parts.join(', ')}` : '';
|
|
113
116
|
return `Model: ${name}${detail}`;
|
|
114
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* The preview line: time-to-first-pixel, and why the preview delivered what
|
|
120
|
+
* it did.
|
|
121
|
+
*
|
|
122
|
+
* First pixels are the number that decides whether a first-time visitor
|
|
123
|
+
* sees their building or a blank canvas, and until conway#542 it was
|
|
124
|
+
* judged by eye — measurable only in a Node harness nobody runs in
|
|
125
|
+
* production. The deferral split is what makes a blank first load
|
|
126
|
+
* attributable rather than merely observed: a ratio near 1.0 ON PLACEMENTS
|
|
127
|
+
* is the file-layout case (an exporter that writes the leaf points and
|
|
128
|
+
* directions a product's placement chain bottoms out in toward the tail of
|
|
129
|
+
* the file), and anything else is a different problem wearing the same
|
|
130
|
+
* blank screen. `retried` is the second-look count — a retry path that has
|
|
131
|
+
* silently stopped firing shows up here rather than merely as a slower
|
|
132
|
+
* load.
|
|
133
|
+
*
|
|
134
|
+
* Meshes and units are reported separately because they diverge in both
|
|
135
|
+
* directions: one unit can place several meshes, and a unit with no
|
|
136
|
+
* representation (a site, a storey) extracts cleanly while placing none.
|
|
137
|
+
* Folding them into one "emitted" number let the line say "no mesh, 20
|
|
138
|
+
* emitted" about the same load (codex round 2 on #543).
|
|
139
|
+
*
|
|
140
|
+
* @param preview The channel's reported yield.
|
|
141
|
+
* @return {string} e.g. "Preview: first mesh 0.275s, 1750 meshes from 539
|
|
142
|
+
* units, 12 deferred (11 on placements), 8 retried"
|
|
143
|
+
*/
|
|
144
|
+
export function formatPreviewLine(preview) {
|
|
145
|
+
const first = preview.firstMeshMs !== void 0 ?
|
|
146
|
+
`first mesh ${formatSeconds(preview.firstMeshMs)}` : 'no mesh';
|
|
147
|
+
return `Preview: ${first}, ${preview.meshes} meshes ` +
|
|
148
|
+
`from ${preview.emitted} units, ` +
|
|
149
|
+
`${preview.deferred} deferred ` +
|
|
150
|
+
`(${preview.deferredOnPlacement} on placements), ` +
|
|
151
|
+
`${preview.retried} retried`;
|
|
152
|
+
}
|
|
115
153
|
/**
|
|
116
154
|
* The signed heap-delta suffix for a stage, byte precision, e.g.
|
|
117
155
|
* ", +663.000000 MB heap" — empty when memory wasn't sampled.
|
|
@@ -178,6 +216,21 @@ export class LoadLogAccumulator {
|
|
|
178
216
|
this.modelLine_ = formatModelLine(info);
|
|
179
217
|
return this.modelLine_;
|
|
180
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* Record what the parse-time preview delivered — kept with the report
|
|
221
|
+
* and rendered between the stage lines and Total.
|
|
222
|
+
*
|
|
223
|
+
* Not a stage: the preview runs *inside* Parsing, so feeding it through
|
|
224
|
+
* onProgress would close the Parsing stage and reopen it, splitting one
|
|
225
|
+
* parse across two lines.
|
|
226
|
+
*
|
|
227
|
+
* @param preview The channel's reported yield.
|
|
228
|
+
* @return {string} The formatted preview line.
|
|
229
|
+
*/
|
|
230
|
+
setPreviewStats(preview) {
|
|
231
|
+
this.previewLine_ = formatPreviewLine(preview);
|
|
232
|
+
return this.previewLine_;
|
|
233
|
+
}
|
|
181
234
|
/**
|
|
182
235
|
* Feed one progress event; returns the finished stage's line when this
|
|
183
236
|
* event closed a stage (so callers can mirror it to a console/log once).
|
|
@@ -281,8 +334,9 @@ export class LoadLogAccumulator {
|
|
|
281
334
|
return `Total: ${formatSeconds(duration)}${heap}`;
|
|
282
335
|
}
|
|
283
336
|
/**
|
|
284
|
-
* The full report: model line (if known), finished stage lines,
|
|
285
|
-
*
|
|
337
|
+
* The full report: model line (if known), finished stage lines, the
|
|
338
|
+
* preview line (if reported), then the Total line. Call
|
|
339
|
+
* closeCurrentStage() first at load end.
|
|
286
340
|
*
|
|
287
341
|
* @return {string[]} All report lines.
|
|
288
342
|
*/
|
|
@@ -292,6 +346,9 @@ export class LoadLogAccumulator {
|
|
|
292
346
|
lines.push(this.modelLine_);
|
|
293
347
|
}
|
|
294
348
|
lines.push(...this.finished_);
|
|
349
|
+
if (this.previewLine_ !== void 0) {
|
|
350
|
+
lines.push(this.previewLine_);
|
|
351
|
+
}
|
|
295
352
|
lines.push(this.totalLine());
|
|
296
353
|
return lines;
|
|
297
354
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "@jest/globals";
|
|
2
|
-
import { LoadLogAccumulator, formatBar, formatMb, formatModelLine, formatSeconds, stageLabel, } from "./progress_log.js";
|
|
2
|
+
import { LoadLogAccumulator, formatBar, formatMb, formatModelLine, formatPreviewLine, formatSeconds, stageLabel, } from "./progress_log.js";
|
|
3
3
|
const HALF_PERCENT = 56;
|
|
4
4
|
const HALF_DOTS = 9;
|
|
5
5
|
const SAMPLE_MS = 3210;
|
|
@@ -108,3 +108,77 @@ describe("LoadLogAccumulator", () => {
|
|
|
108
108
|
expect(log.totalLine()).toBe("Total: 12.400s");
|
|
109
109
|
});
|
|
110
110
|
});
|
|
111
|
+
describe("formatPreviewLine", () => {
|
|
112
|
+
test("reports time-to-first-pixel and the deferral split", () => {
|
|
113
|
+
expect(formatPreviewLine({
|
|
114
|
+
firstMeshMs: 275,
|
|
115
|
+
meshes: 1750,
|
|
116
|
+
emitted: 539,
|
|
117
|
+
deferred: 12,
|
|
118
|
+
deferredOnPlacement: 11,
|
|
119
|
+
retried: 8,
|
|
120
|
+
})).toBe("Preview: first mesh 0.275s, 1750 meshes from 539 units, " +
|
|
121
|
+
"12 deferred (11 on placements), 8 retried");
|
|
122
|
+
});
|
|
123
|
+
test("separates meshes delivered from units extracted", () => {
|
|
124
|
+
// Codex round 2 on #543. `emitted` counts units extraction ACCEPTED,
|
|
125
|
+
// and a unit that extracts cleanly can still place nothing: an IfcSite
|
|
126
|
+
// or IfcBuildingStorey has no Representation, so
|
|
127
|
+
// extractProductGeometry returns early while
|
|
128
|
+
// extractProductGeometryByLocalID still answers true. Folded into one
|
|
129
|
+
// number, the line contradicted itself -- "no mesh, 20 emitted" -- so
|
|
130
|
+
// meshes and units are reported separately and the mesh count is what
|
|
131
|
+
// firstMeshMs is consistent with.
|
|
132
|
+
expect(formatPreviewLine({
|
|
133
|
+
meshes: 0,
|
|
134
|
+
emitted: 20,
|
|
135
|
+
deferred: 0,
|
|
136
|
+
deferredOnPlacement: 0,
|
|
137
|
+
retried: 0,
|
|
138
|
+
})).toBe("Preview: no mesh, 0 meshes from 20 units, " +
|
|
139
|
+
"0 deferred (0 on placements), 0 retried");
|
|
140
|
+
});
|
|
141
|
+
test("says so when the preview never emitted a mesh", () => {
|
|
142
|
+
// The load this line exists for: 532 attempts, one mesh's worth of
|
|
143
|
+
// nothing, and a deferral ratio of 1.0 on placements is what names the
|
|
144
|
+
// cause as file layout rather than "the preview is slow" (conway#542).
|
|
145
|
+
expect(formatPreviewLine({
|
|
146
|
+
meshes: 0,
|
|
147
|
+
emitted: 0,
|
|
148
|
+
deferred: 532,
|
|
149
|
+
deferredOnPlacement: 531,
|
|
150
|
+
retried: 0,
|
|
151
|
+
})).toBe("Preview: no mesh, 0 meshes from 0 units, " +
|
|
152
|
+
"532 deferred (531 on placements), 0 retried");
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
describe("LoadLogAccumulator preview line", () => {
|
|
156
|
+
test("renders between the stage lines and Total, and only when set", () => {
|
|
157
|
+
const log = new LoadLogAccumulator();
|
|
158
|
+
log.onProgress({ phase: "dataParse", completed: 0, elapsedMs: 0 });
|
|
159
|
+
log.onProgress({ phase: "dataParse", completed: 1, total: 1, elapsedMs: 1000 });
|
|
160
|
+
log.closeCurrentStage();
|
|
161
|
+
expect(log.allLines()).toEqual([
|
|
162
|
+
"Parsing: 1.000s",
|
|
163
|
+
"Total: 1.000s",
|
|
164
|
+
]);
|
|
165
|
+
log.setPreviewStats({
|
|
166
|
+
firstMeshMs: 275,
|
|
167
|
+
meshes: 6,
|
|
168
|
+
emitted: 4,
|
|
169
|
+
deferred: 0,
|
|
170
|
+
deferredOnPlacement: 0,
|
|
171
|
+
retried: 0,
|
|
172
|
+
});
|
|
173
|
+
// The preview runs INSIDE Parsing, so it is not a stage — feeding it
|
|
174
|
+
// through onProgress would close Parsing and reopen it, splitting one
|
|
175
|
+
// parse across two lines.
|
|
176
|
+
expect(log.allLines()).toEqual([
|
|
177
|
+
"Parsing: 1.000s",
|
|
178
|
+
"Preview: first mesh 0.275s, 6 meshes from 4 units, " +
|
|
179
|
+
"0 deferred (0 on placements), 0 retried",
|
|
180
|
+
"Total: 1.000s",
|
|
181
|
+
]);
|
|
182
|
+
expect(log.finishedLines()).toEqual(["Parsing: 1.000s"]);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A product whose placement chain is not in the scanned prefix yet.
|
|
3
|
+
*
|
|
4
|
+
* Thrown by `extractPlacementStrict_` under `deferDanglingPlacements`, and
|
|
5
|
+
* caught by the parse-time preview channels, which treat it — like any throw
|
|
6
|
+
* from a product extract — as "not yet extractable, leave it to the durable
|
|
7
|
+
* pump".
|
|
8
|
+
*
|
|
9
|
+
* Strictly "not in the prefix YET": the tag is applied only when the
|
|
10
|
+
* underlying throw is a `DanglingReferenceError`, i.e. the placement chain
|
|
11
|
+
* referenced a record the index does not hold. A placement that is present
|
|
12
|
+
* but broken (wrong entity type, a select that is not an axis placement)
|
|
13
|
+
* propagates untagged, because the channels use this tag to decide what to
|
|
14
|
+
* retry, and retrying a permanently broken placement also keeps the early
|
|
15
|
+
* generation-preemption trigger alive for nothing.
|
|
16
|
+
*
|
|
17
|
+
* It exists only so that catch can ATTRIBUTE the deferral. The preview emits
|
|
18
|
+
* a product once its whole closure sits inside the prefix, and Revit writes
|
|
19
|
+
* per-product placements toward the file tail, so on those files early ticks
|
|
20
|
+
* meet long runs of products that all defer and the user sees nothing until
|
|
21
|
+
* the parse is nearly done. Whether a given blank preview is that, or
|
|
22
|
+
* something else entirely, decides whether sharding the parse would help it
|
|
23
|
+
* at all — so the distinction has to be measurable rather than inferred from
|
|
24
|
+
* a comment (conway#542).
|
|
25
|
+
*/
|
|
26
|
+
export declare class DanglingPlacementError extends Error {
|
|
27
|
+
readonly productLocalID: number;
|
|
28
|
+
readonly cause: unknown;
|
|
29
|
+
/**
|
|
30
|
+
* @param productLocalID The product that could not be placed.
|
|
31
|
+
* @param cause The underlying dangling-reference error.
|
|
32
|
+
*/
|
|
33
|
+
constructor(productLocalID: number, cause: unknown);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=dangling_placement_error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dangling_placement_error.d.ts","sourceRoot":"","sources":["../../../src/ifc/dangling_placement_error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;aAM7B,cAAc,EAAE,MAAM;aACtB,KAAK,EAAE,OAAO;IANhC;;;OAGG;gBAEe,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,OAAO;CAQjC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A product whose placement chain is not in the scanned prefix yet.
|
|
3
|
+
*
|
|
4
|
+
* Thrown by `extractPlacementStrict_` under `deferDanglingPlacements`, and
|
|
5
|
+
* caught by the parse-time preview channels, which treat it — like any throw
|
|
6
|
+
* from a product extract — as "not yet extractable, leave it to the durable
|
|
7
|
+
* pump".
|
|
8
|
+
*
|
|
9
|
+
* Strictly "not in the prefix YET": the tag is applied only when the
|
|
10
|
+
* underlying throw is a `DanglingReferenceError`, i.e. the placement chain
|
|
11
|
+
* referenced a record the index does not hold. A placement that is present
|
|
12
|
+
* but broken (wrong entity type, a select that is not an axis placement)
|
|
13
|
+
* propagates untagged, because the channels use this tag to decide what to
|
|
14
|
+
* retry, and retrying a permanently broken placement also keeps the early
|
|
15
|
+
* generation-preemption trigger alive for nothing.
|
|
16
|
+
*
|
|
17
|
+
* It exists only so that catch can ATTRIBUTE the deferral. The preview emits
|
|
18
|
+
* a product once its whole closure sits inside the prefix, and Revit writes
|
|
19
|
+
* per-product placements toward the file tail, so on those files early ticks
|
|
20
|
+
* meet long runs of products that all defer and the user sees nothing until
|
|
21
|
+
* the parse is nearly done. Whether a given blank preview is that, or
|
|
22
|
+
* something else entirely, decides whether sharding the parse would help it
|
|
23
|
+
* at all — so the distinction has to be measurable rather than inferred from
|
|
24
|
+
* a comment (conway#542).
|
|
25
|
+
*/
|
|
26
|
+
export class DanglingPlacementError extends Error {
|
|
27
|
+
/**
|
|
28
|
+
* @param productLocalID The product that could not be placed.
|
|
29
|
+
* @param cause The underlying dangling-reference error.
|
|
30
|
+
*/
|
|
31
|
+
constructor(productLocalID, cause) {
|
|
32
|
+
super(`product ${productLocalID} placement is not resolvable in this ` +
|
|
33
|
+
`prefix: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
34
|
+
this.productLocalID = productLocalID;
|
|
35
|
+
this.cause = cause;
|
|
36
|
+
this.name = 'DanglingPlacementError';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -44,9 +44,17 @@ import IfcStepModel from "./ifc_step_model.js";
|
|
|
44
44
|
* then to the product's own local ID, which is unique and therefore places
|
|
45
45
|
* that product positionally rather than pretending to know better.
|
|
46
46
|
*
|
|
47
|
-
* Total, and deliberately so: a product whose
|
|
48
|
-
* a usable key rather than aborting a load. A
|
|
49
|
-
* duplicated extraction; a thrown error costs the
|
|
47
|
+
* Total for attribute failures, and deliberately so: a product whose
|
|
48
|
+
* attributes do not resolve gets a usable key rather than aborting a load. A
|
|
49
|
+
* wrong placement costs a duplicated extraction; a thrown error costs the
|
|
50
|
+
* model. That is safe precisely because an unresolvable attribute is a
|
|
51
|
+
* property of the FILE — every worker sees it and takes the same fallback.
|
|
52
|
+
*
|
|
53
|
+
* A NON-RESIDENT read is not: it is a property of one worker's paging, and a
|
|
54
|
+
* fallback taken for it is a key another worker will not agree with. Those
|
|
55
|
+
* propagate. On a windowed source, call {@link computeDispatchKeys} rather
|
|
56
|
+
* than this — it pages the walk's closure first, so the only way to reach
|
|
57
|
+
* that throw is a defect in the paging itself.
|
|
50
58
|
*
|
|
51
59
|
* @param model The model to read attributes from.
|
|
52
60
|
* @param productLocalID The product's local ID.
|
|
@@ -65,4 +73,67 @@ export declare function geometryDispatchKey(model: IfcStepModel, productLocalID:
|
|
|
65
73
|
* @return {number} The owning shard index.
|
|
66
74
|
*/
|
|
67
75
|
export declare function shardOfDispatchKey(key: number, shardCount: number): number;
|
|
76
|
+
/**
|
|
77
|
+
* Dispatch keys for a worklist, computed with the source bytes guaranteed
|
|
78
|
+
* present. Parallel to the worklist — `keys[i]` places `localIDs[i]`.
|
|
79
|
+
*
|
|
80
|
+
* **This is what makes a windowed source shardable.** Called inline,
|
|
81
|
+
* {@link geometryDispatchKey} reads records as it walks; on a windowed
|
|
82
|
+
* source a record that is not paged in throws, and the walk would fall back
|
|
83
|
+
* to the product's own local ID — so *which* products fell back would depend
|
|
84
|
+
* on which chunks that worker happened to hold. Two workers then disagree
|
|
85
|
+
* about a product, and both moduli select it (extracted twice) or neither
|
|
86
|
+
* (dropped silently). Paging the walk's own closure first removes the
|
|
87
|
+
* dependence: every worker reads the same bytes and computes the same key.
|
|
88
|
+
*
|
|
89
|
+
* A fully resident source takes the direct walk — there is nothing to page,
|
|
90
|
+
* and the keys are identical by construction rather than by agreement, which
|
|
91
|
+
* is what the paired windowed/resident fixtures assert.
|
|
92
|
+
*
|
|
93
|
+
* **Aligned to the worklist, not indexed by local ID.** Keys are wanted for
|
|
94
|
+
* products and for rel-aggregates' relating objects — tens of thousands of
|
|
95
|
+
* entries — and the consumer filters the worklist in order, so there is
|
|
96
|
+
* nothing to look up. A column over local IDs would be 37 MB on PSB's 9.4 M
|
|
97
|
+
* records to carry ~24 k useful ones.
|
|
98
|
+
*
|
|
99
|
+
* @param model The model to read attributes from.
|
|
100
|
+
* @param localIDs The worklist, in the order the consumer will filter it.
|
|
101
|
+
* @param waveSize Products whose closure is pinned at once.
|
|
102
|
+
* @return {Promise<Uint32Array>} Keys aligned to `localIDs`.
|
|
103
|
+
*/
|
|
104
|
+
export declare function computeDispatchKeys(model: IfcStepModel, localIDs: readonly number[], waveSize?: number): Promise<Uint32Array>;
|
|
105
|
+
/**
|
|
106
|
+
* The local IDs an aggregate pass should be PLACED by — each
|
|
107
|
+
* `IfcRelAggregates`' relating object, paged first on a windowed source.
|
|
108
|
+
*
|
|
109
|
+
* A rel-aggregates entry is not an `IfcProduct`, so keying on the
|
|
110
|
+
* relationship record itself falls straight through
|
|
111
|
+
* {@link geometryDispatchKey} to its own local ID and shards by file
|
|
112
|
+
* position while claiming to place by representation. The assembly whose
|
|
113
|
+
* geometry the pass actually builds is the relating object, and that is what
|
|
114
|
+
* has to agree across workers.
|
|
115
|
+
*
|
|
116
|
+
* An aggregate whose relating object does not resolve keys by its own local
|
|
117
|
+
* ID — the same file-wide fallback the product walk takes, and the same
|
|
118
|
+
* reason it is safe.
|
|
119
|
+
*
|
|
120
|
+
* @param model The model to read attributes from.
|
|
121
|
+
* @param aggregateLocalIDs The `IfcRelAggregates` worklist, in order.
|
|
122
|
+
* @param waveSize Records whose bytes are pinned at once.
|
|
123
|
+
* @return {Promise<number[]>} Seeds aligned to `aggregateLocalIDs`.
|
|
124
|
+
*/
|
|
125
|
+
export declare function computeRelatingLocalIDs(model: IfcStepModel, aggregateLocalIDs: readonly number[], waveSize?: number): Promise<number[]>;
|
|
126
|
+
/**
|
|
127
|
+
* One aggregate's relating object, or the aggregate itself when it does not
|
|
128
|
+
* resolve.
|
|
129
|
+
*
|
|
130
|
+
* Reads the aggregate's record, so a windowed caller must have paged it —
|
|
131
|
+
* {@link computeRelatingLocalIDs} is that caller. Exported for the resident
|
|
132
|
+
* path, which has nothing to page.
|
|
133
|
+
*
|
|
134
|
+
* @param model The model to read attributes from.
|
|
135
|
+
* @param aggregateLocalID The `IfcRelAggregates` record.
|
|
136
|
+
* @return {number} The local ID to key by.
|
|
137
|
+
*/
|
|
138
|
+
export declare function relatingLocalIDOf(model: IfcStepModel, aggregateLocalID: number): number;
|
|
68
139
|
//# sourceMappingURL=geometry_dispatch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geometry_dispatch.d.ts","sourceRoot":"","sources":["../../../src/ifc/geometry_dispatch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"geometry_dispatch.d.ts","sourceRoot":"","sources":["../../../src/ifc/geometry_dispatch.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,kBAAkB,CAAA;AAU3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mBAAmB,CAC/B,KAAK,EAAE,YAAY,EACnB,cAAc,EAAE,MAAM,GAAI,MAAM,CAuCnC;AAGD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAI,MAAM,CAS5E;AA8BD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,mBAAmB,CACrC,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,GAAE,MAA2B,GAAI,OAAO,CAAE,WAAW,CAAE,CAyClE;AAsKD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,uBAAuB,CACzC,KAAK,EAAE,YAAY,EACnB,iBAAiB,EAAE,SAAS,MAAM,EAAE,EACpC,QAAQ,GAAE,MAA2B,GAAI,OAAO,CAAE,MAAM,EAAE,CAAE,CAoC/D;AAGD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAE,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,GAAI,MAAM,CAUzF"}
|