@bldrs-ai/conway 1.389.1221 → 1.394.1504
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -22
- package/compiled/Dist/ConwayGeomWasmNode.js +0 -0
- package/compiled/Dist/ConwayGeomWasmNodeMT.js +0 -0
- package/compiled/Dist/ConwayGeomWasmWeb.js +0 -0
- package/compiled/Dist/ConwayGeomWasmWebMT.js +1 -1
- package/compiled/Dist/ConwayGeomWasmWebMT.wasm +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNode.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmNodeMT.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWeb.js +0 -0
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.js +1 -1
- package/compiled/dependencies/conway-geom/Dist/ConwayGeomWasmWebMT.wasm +0 -0
- package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts +19 -0
- package/compiled/dependencies/conway-geom/interface/conway_geometry.d.ts.map +1 -1
- package/compiled/dependencies/conway-geom/interface/conway_geometry.js +17 -0
- package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts +6 -0
- package/compiled/dependencies/conway-geom/interface/parameters/surface_object.d.ts.map +1 -1
- package/compiled/examples/browser-bundled.cjs +1569 -51
- package/compiled/examples/cli-bundled.cjs +2790 -436
- package/compiled/examples/cli-step-bundled.cjs +1904 -229
- package/compiled/examples/validator-bundled.cjs +1569 -51
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts +2 -2
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_curve.gen.js +2 -2
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts +3 -3
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/b_spline_surface.gen.js +3 -3
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/composite_curve.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_2d.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_curve_3d.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/offset_surface.gen.js +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/presentation_style_assignment.gen.js +2 -2
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/schema_ap214.gen.js +11 -11
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/AP214E3_2010_gen/shape_aspect.gen.js +1 -1
- package/compiled/src/AP214E3_2010/ap214_command_line_main.js +7 -3
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts +181 -7
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.js +906 -137
- package/compiled/src/AP214E3_2010/ap214_geometry_extraction.test.js +10 -2
- package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_logical_attribute.test.js +114 -0
- package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts +6 -0
- package/compiled/src/AP214E3_2010/ap214_model_geometry.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/ap214_model_geometry.js +9 -0
- package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_pcurve_basis_surfaces.test.js +233 -0
- package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_sphere_vertex_loop.test.js +147 -0
- package/compiled/src/AP214E3_2010/ap214_step_model.d.ts +2 -1
- package/compiled/src/AP214E3_2010/ap214_step_model.d.ts.map +1 -1
- package/compiled/src/AP214E3_2010/ap214_step_model.js +1 -1
- package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_typed_select_enum.test.js +65 -0
- package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts +2 -0
- package/compiled/src/AP214E3_2010/ap214_unit_scale.test.d.ts.map +1 -0
- package/compiled/src/AP214E3_2010/ap214_unit_scale.test.js +111 -0
- package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ap214_streamed_open.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ap214_streamed_open.test.js +190 -0
- package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/coordination_export_order.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/coordination_export_order.test.js +110 -0
- package/compiled/src/compat/web-ifc/coordination_f64.d.ts +165 -0
- package/compiled/src/compat/web-ifc/coordination_f64.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/coordination_f64.js +286 -0
- package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/coordination_f64.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/coordination_f64.test.js +225 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts +154 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api.js +211 -3
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_deferred_open.test.js +288 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +39 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts +30 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough_factory.js +83 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.js +383 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_preview_coordination.test.js +124 -0
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts +132 -0
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ap214.js +488 -92
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +268 -0
- 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 +996 -149
- package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/ifc_api_streamed_open.test.js +129 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.d.ts +134 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.js +933 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/spatial_imposter.test.js +467 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts +187 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.js +524 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.test.js +234 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +306 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/streamed_preview_channel.js +580 -0
- package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/web_wasm_directory.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/web_wasm_directory.test.js +22 -0
- package/compiled/src/core/composed_model_skeleton.d.ts +63 -0
- package/compiled/src/core/composed_model_skeleton.d.ts.map +1 -0
- package/compiled/src/core/composed_model_skeleton.js +66 -0
- package/compiled/src/core/composed_model_skeleton.test.d.ts +2 -0
- package/compiled/src/core/composed_model_skeleton.test.d.ts.map +1 -0
- package/compiled/src/core/composed_model_skeleton.test.js +69 -0
- package/compiled/src/core/demand_geometry_queue.d.ts +147 -0
- package/compiled/src/core/demand_geometry_queue.d.ts.map +1 -0
- package/compiled/src/core/demand_geometry_queue.js +223 -0
- package/compiled/src/core/demand_geometry_queue.test.d.ts +2 -0
- package/compiled/src/core/demand_geometry_queue.test.d.ts.map +1 -0
- package/compiled/src/core/demand_geometry_queue.test.js +133 -0
- package/compiled/src/core/demand_residency_pump.d.ts +93 -0
- package/compiled/src/core/demand_residency_pump.d.ts.map +1 -0
- package/compiled/src/core/demand_residency_pump.js +120 -0
- package/compiled/src/core/demand_residency_pump.test.d.ts +2 -0
- package/compiled/src/core/demand_residency_pump.test.d.ts.map +1 -0
- package/compiled/src/core/demand_residency_pump.test.js +148 -0
- package/compiled/src/core/geometry_tile_bindings.d.ts +110 -0
- package/compiled/src/core/geometry_tile_bindings.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_bindings.js +76 -0
- package/compiled/src/core/geometry_tile_bindings.test.d.ts +2 -0
- package/compiled/src/core/geometry_tile_bindings.test.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_bindings.test.js +211 -0
- package/compiled/src/core/geometry_tile_pool.d.ts +99 -0
- package/compiled/src/core/geometry_tile_pool.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_pool.js +104 -0
- package/compiled/src/core/geometry_tile_pool.test.d.ts +2 -0
- package/compiled/src/core/geometry_tile_pool.test.d.ts.map +1 -0
- package/compiled/src/core/geometry_tile_pool.test.js +180 -0
- package/compiled/src/core/mem/chunked_pool.d.ts +116 -0
- package/compiled/src/core/mem/chunked_pool.d.ts.map +1 -0
- package/compiled/src/core/mem/chunked_pool.js +149 -0
- package/compiled/src/core/mem/chunked_pool.test.d.ts +2 -0
- package/compiled/src/core/mem/chunked_pool.test.d.ts.map +1 -0
- package/compiled/src/core/mem/chunked_pool.test.js +63 -0
- package/compiled/src/core/mem/shared_asset_pool.d.ts +82 -0
- package/compiled/src/core/mem/shared_asset_pool.d.ts.map +1 -0
- package/compiled/src/core/mem/shared_asset_pool.js +113 -0
- package/compiled/src/core/mem/shared_asset_pool.test.d.ts +2 -0
- package/compiled/src/core/mem/shared_asset_pool.test.d.ts.map +1 -0
- package/compiled/src/core/mem/shared_asset_pool.test.js +49 -0
- package/compiled/src/core/model_registry.d.ts +87 -0
- package/compiled/src/core/model_registry.d.ts.map +1 -0
- package/compiled/src/core/model_registry.js +101 -0
- package/compiled/src/core/model_registry.test.d.ts +2 -0
- package/compiled/src/core/model_registry.test.d.ts.map +1 -0
- package/compiled/src/core/model_registry.test.js +60 -0
- package/compiled/src/core/model_uri.d.ts +57 -0
- package/compiled/src/core/model_uri.d.ts.map +1 -0
- package/compiled/src/core/model_uri.js +101 -0
- package/compiled/src/core/model_uri.test.d.ts +2 -0
- package/compiled/src/core/model_uri.test.d.ts.map +1 -0
- package/compiled/src/core/model_uri.test.js +49 -0
- package/compiled/src/core/progress.d.ts +16 -2
- package/compiled/src/core/progress.d.ts.map +1 -1
- package/compiled/src/core/progress.js +31 -5
- package/compiled/src/core/progress.test.js +11 -2
- package/compiled/src/core/progress_log.d.ts +1 -0
- package/compiled/src/core/progress_log.d.ts.map +1 -1
- package/compiled/src/core/progress_log.js +7 -2
- package/compiled/src/core/progress_log.test.js +21 -0
- package/compiled/src/core/shared_byte_budget.d.ts +60 -0
- package/compiled/src/core/shared_byte_budget.d.ts.map +1 -0
- package/compiled/src/core/shared_byte_budget.js +85 -0
- package/compiled/src/core/shared_byte_budget.test.d.ts +2 -0
- package/compiled/src/core/shared_byte_budget.test.d.ts.map +1 -0
- package/compiled/src/core/shared_byte_budget.test.js +55 -0
- package/compiled/src/core/wasm_heap.d.ts +208 -0
- package/compiled/src/core/wasm_heap.d.ts.map +1 -0
- package/compiled/src/core/wasm_heap.js +417 -0
- package/compiled/src/core/wasm_heap.test.d.ts +2 -0
- package/compiled/src/core/wasm_heap.test.d.ts.map +1 -0
- package/compiled/src/core/wasm_heap.test.js +546 -0
- package/compiled/src/demand/index.d.ts +23 -0
- package/compiled/src/demand/index.d.ts.map +1 -0
- package/compiled/src/demand/index.js +22 -0
- package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.d.ts.map +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcLogical.gen.js +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.d.ts.map +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcPresentationStyleAssignment.gen.js +2 -2
- package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.d.ts.map +1 -1
- package/compiled/src/ifc/ifc4_gen/IfcRelInterferesElements.gen.js +1 -1
- package/compiled/src/ifc/ifc4_gen/schema_ifc.gen.js +2 -2
- package/compiled/src/ifc/ifc_demand_extraction.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_demand_extraction.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_demand_extraction.test.js +251 -0
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts +367 -6
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_geometry_extraction.js +1322 -389
- package/compiled/src/ifc/ifc_grid_placement.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_grid_placement.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_grid_placement.test.js +261 -0
- package/compiled/src/ifc/ifc_model_geometry.d.ts +12 -0
- package/compiled/src/ifc/ifc_model_geometry.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_model_geometry.js +15 -0
- package/compiled/src/ifc/ifc_regression_batch_main.js +210 -12
- package/compiled/src/ifc/ifc_spatial_skeleton.d.ts +145 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.js +266 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_spatial_skeleton.test.js +199 -0
- package/compiled/src/ifc/ifc_step_model.d.ts +6 -2
- package/compiled/src/ifc/ifc_step_model.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_model.js +6 -4
- package/compiled/src/ifc/ifc_step_parser.d.ts +58 -0
- package/compiled/src/ifc/ifc_step_parser.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_step_parser.js +64 -0
- package/compiled/src/ifc/ifc_stream_model.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_stream_model.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_model.test.js +70 -0
- package/compiled/src/ifc/ifc_stream_open.d.ts +131 -0
- package/compiled/src/ifc/ifc_stream_open.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_open.js +116 -0
- package/compiled/src/ifc/ifc_stream_open.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_stream_open.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_stream_open.test.js +230 -0
- package/compiled/src/ifc/ifc_tile_extractor.d.ts +84 -0
- package/compiled/src/ifc/ifc_tile_extractor.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_tile_extractor.js +134 -0
- package/compiled/src/ifc/ifc_tile_extractor.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_tile_extractor.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_tile_extractor.test.js +118 -0
- package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts +2 -0
- package/compiled/src/ifc/ifc_typed_select_enum.test.d.ts.map +1 -0
- package/compiled/src/ifc/ifc_typed_select_enum.test.js +60 -0
- package/compiled/src/index.d.ts +21 -1
- package/compiled/src/index.d.ts.map +1 -1
- package/compiled/src/index.js +28 -1
- package/compiled/src/logging/logger.d.ts +16 -2
- package/compiled/src/logging/logger.d.ts.map +1 -1
- package/compiled/src/logging/logger.js +34 -7
- package/compiled/src/logging/logger.test.js +30 -0
- package/compiled/src/mem/index.d.ts +17 -0
- package/compiled/src/mem/index.d.ts.map +1 -0
- package/compiled/src/mem/index.js +16 -0
- package/compiled/src/namespace_surface.test.d.ts +2 -0
- package/compiled/src/namespace_surface.test.d.ts.map +1 -0
- package/compiled/src/namespace_surface.test.js +43 -0
- package/compiled/src/parsing/parsing_buffer.d.ts +23 -0
- package/compiled/src/parsing/parsing_buffer.d.ts.map +1 -1
- package/compiled/src/parsing/parsing_buffer.js +31 -0
- package/compiled/src/scripts/model_report_displacement.test.d.ts +2 -0
- package/compiled/src/scripts/model_report_displacement.test.d.ts.map +1 -0
- package/compiled/src/scripts/model_report_displacement.test.js +104 -0
- package/compiled/src/scripts/render_glb_paths.test.d.ts +2 -0
- package/compiled/src/scripts/render_glb_paths.test.d.ts.map +1 -0
- package/compiled/src/scripts/render_glb_paths.test.js +115 -0
- package/compiled/src/step/indexing/step_type_indexer.d.ts +20 -0
- package/compiled/src/step/indexing/step_type_indexer.d.ts.map +1 -1
- package/compiled/src/step/indexing/step_type_indexer.js +67 -0
- package/compiled/src/step/parsing/byte_source.d.ts +153 -0
- package/compiled/src/step/parsing/byte_source.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source.js +106 -0
- package/compiled/src/step/parsing/byte_source.test.d.ts +2 -0
- package/compiled/src/step/parsing/byte_source.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source.test.js +47 -0
- package/compiled/src/step/parsing/byte_source_node.d.ts +41 -0
- package/compiled/src/step/parsing/byte_source_node.d.ts.map +1 -0
- package/compiled/src/step/parsing/byte_source_node.js +54 -0
- package/compiled/src/step/parsing/columnar_index.d.ts +103 -0
- package/compiled/src/step/parsing/columnar_index.d.ts.map +1 -0
- package/compiled/src/step/parsing/columnar_index.js +224 -0
- package/compiled/src/step/parsing/columnar_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/columnar_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/columnar_index.test.js +155 -0
- package/compiled/src/step/parsing/cross_reference_registry.d.ts +95 -0
- package/compiled/src/step/parsing/cross_reference_registry.d.ts.map +1 -0
- package/compiled/src/step/parsing/cross_reference_registry.js +91 -0
- package/compiled/src/step/parsing/cross_reference_registry.test.d.ts +2 -0
- package/compiled/src/step/parsing/cross_reference_registry.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/cross_reference_registry.test.js +66 -0
- package/compiled/src/step/parsing/decode_utf8.d.ts +15 -0
- package/compiled/src/step/parsing/decode_utf8.d.ts.map +1 -1
- package/compiled/src/step/parsing/decode_utf8.js +28 -0
- package/compiled/src/step/parsing/express_ref_scan.d.ts +20 -0
- package/compiled/src/step/parsing/express_ref_scan.d.ts.map +1 -0
- package/compiled/src/step/parsing/express_ref_scan.js +91 -0
- package/compiled/src/step/parsing/express_ref_scan.test.d.ts +2 -0
- package/compiled/src/step/parsing/express_ref_scan.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/express_ref_scan.test.js +28 -0
- package/compiled/src/step/parsing/index_sidecar.d.ts +81 -0
- package/compiled/src/step/parsing/index_sidecar.d.ts.map +1 -0
- package/compiled/src/step/parsing/index_sidecar.js +283 -0
- package/compiled/src/step/parsing/index_sidecar.test.d.ts +2 -0
- package/compiled/src/step/parsing/index_sidecar.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/index_sidecar.test.js +122 -0
- package/compiled/src/step/parsing/inf_recovery_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/inf_recovery_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/inf_recovery_index.test.js +108 -0
- package/compiled/src/step/parsing/prefix_type_index.d.ts +124 -0
- package/compiled/src/step/parsing/prefix_type_index.d.ts.map +1 -0
- package/compiled/src/step/parsing/prefix_type_index.js +207 -0
- package/compiled/src/step/parsing/prefix_type_index.test.d.ts +2 -0
- package/compiled/src/step/parsing/prefix_type_index.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/prefix_type_index.test.js +298 -0
- package/compiled/src/step/parsing/range_byte_source.d.ts +69 -0
- package/compiled/src/step/parsing/range_byte_source.d.ts.map +1 -0
- package/compiled/src/step/parsing/range_byte_source.js +78 -0
- package/compiled/src/step/parsing/range_byte_source.test.d.ts +2 -0
- package/compiled/src/step/parsing/range_byte_source.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/range_byte_source.test.js +70 -0
- package/compiled/src/step/parsing/record_event.d.ts +23 -0
- package/compiled/src/step/parsing/record_event.d.ts.map +1 -0
- package/compiled/src/step/parsing/record_event.js +1 -0
- package/compiled/src/step/parsing/record_field_cursor.d.ts +94 -0
- package/compiled/src/step/parsing/record_field_cursor.d.ts.map +1 -0
- package/compiled/src/step/parsing/record_field_cursor.js +189 -0
- package/compiled/src/step/parsing/step_deserialization_functions.d.ts +29 -0
- package/compiled/src/step/parsing/step_deserialization_functions.d.ts.map +1 -1
- package/compiled/src/step/parsing/step_deserialization_functions.js +45 -0
- package/compiled/src/step/parsing/step_deserialization_functions.test.js +59 -1
- package/compiled/src/step/parsing/step_parser.d.ts +66 -1
- package/compiled/src/step/parsing/step_parser.d.ts.map +1 -1
- package/compiled/src/step/parsing/step_parser.js +164 -10
- package/compiled/src/step/parsing/step_string_parser.js +8 -8
- package/compiled/src/step/parsing/streaming_index_builder.d.ts +141 -0
- package/compiled/src/step/parsing/streaming_index_builder.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder.js +280 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder.test.js +107 -0
- package/compiled/src/step/parsing/streaming_index_builder_async.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_index_builder_async.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_index_builder_async.test.js +109 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts +71 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.js +88 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts +2 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/streaming_record_dispatcher.test.js +66 -0
- package/compiled/src/step/parsing/uint32_sink.d.ts +72 -0
- package/compiled/src/step/parsing/uint32_sink.d.ts.map +1 -0
- package/compiled/src/step/parsing/uint32_sink.js +180 -0
- package/compiled/src/step/parsing/uint32_sink.test.d.ts +2 -0
- package/compiled/src/step/parsing/uint32_sink.test.d.ts.map +1 -0
- package/compiled/src/step/parsing/uint32_sink.test.js +199 -0
- package/compiled/src/step/step_buffer_provider.d.ts +48 -3
- package/compiled/src/step/step_buffer_provider.d.ts.map +1 -1
- package/compiled/src/step/step_buffer_provider.js +60 -11
- package/compiled/src/step/step_buffer_provider.test.js +14 -0
- package/compiled/src/step/step_entity_base.d.ts +65 -3
- package/compiled/src/step/step_entity_base.d.ts.map +1 -1
- package/compiled/src/step/step_entity_base.js +135 -3
- package/compiled/src/step/step_model_base.d.ts +221 -8
- package/compiled/src/step/step_model_base.d.ts.map +1 -1
- package/compiled/src/step/step_model_base.js +542 -7
- package/compiled/src/stream/index.d.ts +34 -0
- package/compiled/src/stream/index.d.ts.map +1 -0
- package/compiled/src/stream/index.js +32 -0
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { EntityAddress } from "./model_uri.js";
|
|
2
|
+
import { SharedByteBudget } from "./shared_byte_budget.js";
|
|
3
|
+
/**
|
|
4
|
+
* A model resolved from the registry, paired with the express ID an address
|
|
5
|
+
* selected within it.
|
|
6
|
+
*/
|
|
7
|
+
export interface ResolvedEntity<H> {
|
|
8
|
+
model: H;
|
|
9
|
+
expressID: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The set of open models in one browser session (M5 / design S3).
|
|
13
|
+
*
|
|
14
|
+
* Federation is a registry of loader instances keyed by **model URI**, all
|
|
15
|
+
* sharing one {@link SharedByteBudget} so total resident memory is bounded per
|
|
16
|
+
* browser rather than per model. An {@link EntityAddress} (`modelURI#expressID`)
|
|
17
|
+
* resolves through here to the live model handle; a URI with no registered
|
|
18
|
+
* model is the signal to open a sibling loader (its own sidecar/stream) and
|
|
19
|
+
* register it.
|
|
20
|
+
*
|
|
21
|
+
* The registry is deliberately generic over the model handle `H` — it owns
|
|
22
|
+
* identity, resolution and the shared budget, not the loader. The streaming
|
|
23
|
+
* loader registers its model instance; higher layers (the composed skeleton,
|
|
24
|
+
* the UI link layer) query through the same addresses.
|
|
25
|
+
*/
|
|
26
|
+
export declare class ModelRegistry<H> {
|
|
27
|
+
private readonly byURI_;
|
|
28
|
+
private readonly budget_;
|
|
29
|
+
/**
|
|
30
|
+
* @param budget The shared per-browser byte budget every registered model
|
|
31
|
+
* draws from.
|
|
32
|
+
*/
|
|
33
|
+
constructor(budget: SharedByteBudget);
|
|
34
|
+
/**
|
|
35
|
+
* @return {SharedByteBudget} The shared budget all registered models draw
|
|
36
|
+
* from.
|
|
37
|
+
*/
|
|
38
|
+
get budget(): SharedByteBudget;
|
|
39
|
+
/**
|
|
40
|
+
* @return {number} The number of registered models.
|
|
41
|
+
*/
|
|
42
|
+
get size(): number;
|
|
43
|
+
/**
|
|
44
|
+
* @return {IterableIterator<string>} The URIs of all registered models.
|
|
45
|
+
*/
|
|
46
|
+
uris(): IterableIterator<string>;
|
|
47
|
+
/**
|
|
48
|
+
* @return {IterableIterator<H>} The registered model handles.
|
|
49
|
+
*/
|
|
50
|
+
models(): IterableIterator<H>;
|
|
51
|
+
/**
|
|
52
|
+
* Register (or replace) the model for a URI.
|
|
53
|
+
*
|
|
54
|
+
* @param uri The model URI (no `#` fragment).
|
|
55
|
+
* @param model The model handle.
|
|
56
|
+
*/
|
|
57
|
+
register(uri: string, model: H): void;
|
|
58
|
+
/**
|
|
59
|
+
* Remove a model from the registry.
|
|
60
|
+
*
|
|
61
|
+
* @param uri The model URI.
|
|
62
|
+
* @return {boolean} True if a model was removed.
|
|
63
|
+
*/
|
|
64
|
+
unregister(uri: string): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* @param uri The model URI.
|
|
67
|
+
* @return {boolean} True if a model is registered for the URI.
|
|
68
|
+
*/
|
|
69
|
+
has(uri: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* @param uri The model URI.
|
|
72
|
+
* @return {H | undefined} The registered model, or undefined.
|
|
73
|
+
*/
|
|
74
|
+
get(uri: string): H | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Resolve an entity address to its model + express ID. Returns undefined
|
|
77
|
+
* when the address's model isn't registered — the caller's cue to open and
|
|
78
|
+
* register it, then resolve again.
|
|
79
|
+
*
|
|
80
|
+
* @param address The entity address, as a URI string or a parsed
|
|
81
|
+
* {@link EntityAddress}.
|
|
82
|
+
* @return {ResolvedEntity | undefined} The resolved model + express ID, or
|
|
83
|
+
* undefined if the model isn't registered.
|
|
84
|
+
*/
|
|
85
|
+
resolve(address: string | EntityAddress): ResolvedEntity<H> | undefined;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=model_registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_registry.d.ts","sourceRoot":"","sources":["../../../src/core/model_registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAGvD;;;GAGG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,KAAK,EAAE,CAAC,CAAA;IACR,SAAS,EAAE,MAAM,CAAA;CAClB;AAGD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,aAAa,CAAC,CAAC;IAE1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAE9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAE1C;;;OAGG;gBACU,MAAM,EAAE,gBAAgB;IAIrC;;;OAGG;IACH,IAAW,MAAM,IAAI,gBAAgB,CAEpC;IAED;;OAEG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;OAEG;IACI,IAAI,IAAI,gBAAgB,CAAC,MAAM,CAAC;IAIvC;;OAEG;IACI,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAIpC;;;;;OAKG;IACI,QAAQ,CAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAI,IAAI;IAS9C;;;;;OAKG;IACI,UAAU,CAAE,GAAG,EAAE,MAAM,GAAI,OAAO;IAIzC;;;OAGG;IACI,GAAG,CAAE,GAAG,EAAE,MAAM,GAAI,OAAO;IAIlC;;;OAGG;IACI,GAAG,CAAE,GAAG,EAAE,MAAM,GAAI,CAAC,GAAG,SAAS;IAIxC;;;;;;;;;OASG;IACI,OAAO,CAAE,OAAO,EAAE,MAAM,GAAG,aAAa,GAAI,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS;CASjF"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { parseEntityAddress } from "./model_uri.js";
|
|
2
|
+
/**
|
|
3
|
+
* The set of open models in one browser session (M5 / design S3).
|
|
4
|
+
*
|
|
5
|
+
* Federation is a registry of loader instances keyed by **model URI**, all
|
|
6
|
+
* sharing one {@link SharedByteBudget} so total resident memory is bounded per
|
|
7
|
+
* browser rather than per model. An {@link EntityAddress} (`modelURI#expressID`)
|
|
8
|
+
* resolves through here to the live model handle; a URI with no registered
|
|
9
|
+
* model is the signal to open a sibling loader (its own sidecar/stream) and
|
|
10
|
+
* register it.
|
|
11
|
+
*
|
|
12
|
+
* The registry is deliberately generic over the model handle `H` — it owns
|
|
13
|
+
* identity, resolution and the shared budget, not the loader. The streaming
|
|
14
|
+
* loader registers its model instance; higher layers (the composed skeleton,
|
|
15
|
+
* the UI link layer) query through the same addresses.
|
|
16
|
+
*/
|
|
17
|
+
export class ModelRegistry {
|
|
18
|
+
/**
|
|
19
|
+
* @param budget The shared per-browser byte budget every registered model
|
|
20
|
+
* draws from.
|
|
21
|
+
*/
|
|
22
|
+
constructor(budget) {
|
|
23
|
+
this.byURI_ = new Map();
|
|
24
|
+
this.budget_ = budget;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @return {SharedByteBudget} The shared budget all registered models draw
|
|
28
|
+
* from.
|
|
29
|
+
*/
|
|
30
|
+
get budget() {
|
|
31
|
+
return this.budget_;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @return {number} The number of registered models.
|
|
35
|
+
*/
|
|
36
|
+
get size() {
|
|
37
|
+
return this.byURI_.size;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* @return {IterableIterator<string>} The URIs of all registered models.
|
|
41
|
+
*/
|
|
42
|
+
uris() {
|
|
43
|
+
return this.byURI_.keys();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* @return {IterableIterator<H>} The registered model handles.
|
|
47
|
+
*/
|
|
48
|
+
models() {
|
|
49
|
+
return this.byURI_.values();
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Register (or replace) the model for a URI.
|
|
53
|
+
*
|
|
54
|
+
* @param uri The model URI (no `#` fragment).
|
|
55
|
+
* @param model The model handle.
|
|
56
|
+
*/
|
|
57
|
+
register(uri, model) {
|
|
58
|
+
if (uri.includes("#")) {
|
|
59
|
+
throw new Error(`Model URI must not contain '#': ${uri}`);
|
|
60
|
+
}
|
|
61
|
+
this.byURI_.set(uri, model);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Remove a model from the registry.
|
|
65
|
+
*
|
|
66
|
+
* @param uri The model URI.
|
|
67
|
+
* @return {boolean} True if a model was removed.
|
|
68
|
+
*/
|
|
69
|
+
unregister(uri) {
|
|
70
|
+
return this.byURI_.delete(uri);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* @param uri The model URI.
|
|
74
|
+
* @return {boolean} True if a model is registered for the URI.
|
|
75
|
+
*/
|
|
76
|
+
has(uri) {
|
|
77
|
+
return this.byURI_.has(uri);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* @param uri The model URI.
|
|
81
|
+
* @return {H | undefined} The registered model, or undefined.
|
|
82
|
+
*/
|
|
83
|
+
get(uri) {
|
|
84
|
+
return this.byURI_.get(uri);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Resolve an entity address to its model + express ID. Returns undefined
|
|
88
|
+
* when the address's model isn't registered — the caller's cue to open and
|
|
89
|
+
* register it, then resolve again.
|
|
90
|
+
*
|
|
91
|
+
* @param address The entity address, as a URI string or a parsed
|
|
92
|
+
* {@link EntityAddress}.
|
|
93
|
+
* @return {ResolvedEntity | undefined} The resolved model + express ID, or
|
|
94
|
+
* undefined if the model isn't registered.
|
|
95
|
+
*/
|
|
96
|
+
resolve(address) {
|
|
97
|
+
const { modelURI, expressID } = typeof address === "string" ? parseEntityAddress(address) : address;
|
|
98
|
+
const model = this.byURI_.get(modelURI);
|
|
99
|
+
return model === void 0 ? void 0 : { model, expressID };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_registry.test.d.ts","sourceRoot":"","sources":["../../../src/core/model_registry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/* eslint-disable no-magic-numbers */
|
|
2
|
+
// M5: the registry keys open models by URI, resolves universal addresses to
|
|
3
|
+
// the live model, and hands every model the one shared budget.
|
|
4
|
+
import { describe, expect, test } from "@jest/globals";
|
|
5
|
+
import { ModelRegistry } from "./model_registry.js";
|
|
6
|
+
import { SharedByteBudget } from "./shared_byte_budget.js";
|
|
7
|
+
describe("ModelRegistry", () => {
|
|
8
|
+
/**
|
|
9
|
+
* A registry with two registered fake models.
|
|
10
|
+
*
|
|
11
|
+
* @return {ModelRegistry} The populated registry.
|
|
12
|
+
*/
|
|
13
|
+
function twoModels() {
|
|
14
|
+
const registry = new ModelRegistry(new SharedByteBudget(1000));
|
|
15
|
+
registry.register("https://ex.com/a.ifc", { uri: "a" });
|
|
16
|
+
registry.register("https://ex.com/b.ifc", { uri: "b" });
|
|
17
|
+
return registry;
|
|
18
|
+
}
|
|
19
|
+
test("registers, looks up and counts models", () => {
|
|
20
|
+
const registry = twoModels();
|
|
21
|
+
expect(registry.size).toBe(2);
|
|
22
|
+
expect(registry.has("https://ex.com/a.ifc")).toBe(true);
|
|
23
|
+
expect(registry.get("https://ex.com/b.ifc")?.uri).toBe("b");
|
|
24
|
+
expect([...registry.uris()].sort()).toEqual(["https://ex.com/a.ifc", "https://ex.com/b.ifc"]);
|
|
25
|
+
});
|
|
26
|
+
test("resolves an address string to the model and express ID", () => {
|
|
27
|
+
const registry = twoModels();
|
|
28
|
+
const resolved = registry.resolve("https://ex.com/b.ifc#42");
|
|
29
|
+
expect(resolved?.model.uri).toBe("b");
|
|
30
|
+
expect(resolved?.expressID).toBe(42);
|
|
31
|
+
});
|
|
32
|
+
test("resolves a pre-parsed address object too", () => {
|
|
33
|
+
const registry = twoModels();
|
|
34
|
+
const resolved = registry.resolve({ modelURI: "https://ex.com/a.ifc", expressID: 7 });
|
|
35
|
+
expect(resolved?.model.uri).toBe("a");
|
|
36
|
+
expect(resolved?.expressID).toBe(7);
|
|
37
|
+
});
|
|
38
|
+
test("returns undefined for an unregistered model (open-then-retry cue)", () => {
|
|
39
|
+
const registry = twoModels();
|
|
40
|
+
expect(registry.resolve("https://ex.com/missing.ifc#1"))
|
|
41
|
+
.toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
test("unregister removes a model", () => {
|
|
44
|
+
const registry = twoModels();
|
|
45
|
+
expect(registry.unregister("https://ex.com/a.ifc")).toBe(true);
|
|
46
|
+
expect(registry.has("https://ex.com/a.ifc")).toBe(false);
|
|
47
|
+
expect(registry.size).toBe(1);
|
|
48
|
+
});
|
|
49
|
+
test("rejects registering a URI with a fragment", () => {
|
|
50
|
+
const registry = new ModelRegistry(new SharedByteBudget(10));
|
|
51
|
+
expect(() => registry.register("a.ifc#1", { uri: "a" })).toThrow(/#/);
|
|
52
|
+
});
|
|
53
|
+
test("exposes the one shared budget every model draws from", () => {
|
|
54
|
+
const budget = new SharedByteBudget(1000);
|
|
55
|
+
const registry = new ModelRegistry(budget);
|
|
56
|
+
expect(registry.budget).toBe(budget);
|
|
57
|
+
registry.budget.reserve(400);
|
|
58
|
+
expect(registry.budget.available).toBe(600);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-model entity addressing (M5 / design S3).
|
|
3
|
+
*
|
|
4
|
+
* Federation turns "thousands of cross-referenced files" from a loader problem
|
|
5
|
+
* into an addressing problem: every entity has a **universal address** of a
|
|
6
|
+
* model URI plus an express ID — `https://…/part-B.ifc#4022`. The engine never
|
|
7
|
+
* holds all the files; it holds a registry of models keyed by URI (see
|
|
8
|
+
* {@link ModelRegistry}) and resolves an address to a (model, expressID) pair
|
|
9
|
+
* on demand, opening a sibling loader for a URI it hasn't seen.
|
|
10
|
+
*
|
|
11
|
+
* The URI is opaque to the engine except for its `#expressID` fragment: the
|
|
12
|
+
* scheme, host, path and any version identity live entirely in the model URI,
|
|
13
|
+
* so "many versions side by side" is expressible without an engine change.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* A universal entity address: which model, and which express ID within it.
|
|
17
|
+
*/
|
|
18
|
+
export interface EntityAddress {
|
|
19
|
+
/** The model's URI (everything left of the `#expressID` fragment). */
|
|
20
|
+
modelURI: string;
|
|
21
|
+
/** The entity's express ID within that model. */
|
|
22
|
+
expressID: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Format a model URI + express ID as a single entity address URI.
|
|
26
|
+
*
|
|
27
|
+
* @param modelURI The model URI (must not itself contain a `#`).
|
|
28
|
+
* @param expressID The express ID (a non-negative integer).
|
|
29
|
+
* @return {string} The `modelURI#expressID` address.
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatEntityAddress(modelURI: string, expressID: number): string;
|
|
32
|
+
/**
|
|
33
|
+
* Parse an entity address URI into its model URI and express ID.
|
|
34
|
+
*
|
|
35
|
+
* The split is on the **last** `#`, so a fragment is required; the model URI
|
|
36
|
+
* is everything before it. A missing or non-integer fragment is an error —
|
|
37
|
+
* an address without an express ID isn't an entity address.
|
|
38
|
+
*
|
|
39
|
+
* @param uri The `modelURI#expressID` address.
|
|
40
|
+
* @return {EntityAddress} The parsed address.
|
|
41
|
+
*/
|
|
42
|
+
export declare function parseEntityAddress(uri: string): EntityAddress;
|
|
43
|
+
/**
|
|
44
|
+
* Resolve a (possibly relative) reference URI against a base model URI, so an
|
|
45
|
+
* `IfcExternalReference.Location` like `../shared/grid.ifc` becomes an absolute
|
|
46
|
+
* model URI addressable in the registry. Absolute references (with a scheme,
|
|
47
|
+
* or protocol-relative) pass through unchanged.
|
|
48
|
+
*
|
|
49
|
+
* Uses the standard URL resolver when the base is absolute; falls back to a
|
|
50
|
+
* plain path join when the base has no scheme (e.g. a bare filename in tests).
|
|
51
|
+
*
|
|
52
|
+
* @param base The base model URI the reference was found in.
|
|
53
|
+
* @param reference The reference URI (absolute or relative).
|
|
54
|
+
* @return {string} The resolved absolute reference URI.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveReference(base: string, reference: string): string;
|
|
57
|
+
//# sourceMappingURL=model_uri.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_uri.d.ts","sourceRoot":"","sources":["../../../src/core/model_uri.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAE5B,sEAAsE;IACtE,QAAQ,EAAE,MAAM,CAAA;IAEhB,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAA;CAClB;AAOD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAI,MAAM,CAWjF;AAGD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAE,GAAG,EAAE,MAAM,GAAI,aAAa,CAgB/D;AAGD;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAI,MAAM,CAgB1E"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-model entity addressing (M5 / design S3).
|
|
3
|
+
*
|
|
4
|
+
* Federation turns "thousands of cross-referenced files" from a loader problem
|
|
5
|
+
* into an addressing problem: every entity has a **universal address** of a
|
|
6
|
+
* model URI plus an express ID — `https://…/part-B.ifc#4022`. The engine never
|
|
7
|
+
* holds all the files; it holds a registry of models keyed by URI (see
|
|
8
|
+
* {@link ModelRegistry}) and resolves an address to a (model, expressID) pair
|
|
9
|
+
* on demand, opening a sibling loader for a URI it hasn't seen.
|
|
10
|
+
*
|
|
11
|
+
* The URI is opaque to the engine except for its `#expressID` fragment: the
|
|
12
|
+
* scheme, host, path and any version identity live entirely in the model URI,
|
|
13
|
+
* so "many versions side by side" is expressible without an engine change.
|
|
14
|
+
*/
|
|
15
|
+
const FRAGMENT = '#';
|
|
16
|
+
const RADIX = 10;
|
|
17
|
+
/**
|
|
18
|
+
* Format a model URI + express ID as a single entity address URI.
|
|
19
|
+
*
|
|
20
|
+
* @param modelURI The model URI (must not itself contain a `#`).
|
|
21
|
+
* @param expressID The express ID (a non-negative integer).
|
|
22
|
+
* @return {string} The `modelURI#expressID` address.
|
|
23
|
+
*/
|
|
24
|
+
export function formatEntityAddress(modelURI, expressID) {
|
|
25
|
+
if (modelURI.includes(FRAGMENT)) {
|
|
26
|
+
throw new Error(`Model URI must not contain '#': ${modelURI}`);
|
|
27
|
+
}
|
|
28
|
+
if (!Number.isInteger(expressID) || expressID < 0) {
|
|
29
|
+
throw new Error(`Invalid express ID ${expressID}`);
|
|
30
|
+
}
|
|
31
|
+
return `${modelURI}${FRAGMENT}${expressID}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parse an entity address URI into its model URI and express ID.
|
|
35
|
+
*
|
|
36
|
+
* The split is on the **last** `#`, so a fragment is required; the model URI
|
|
37
|
+
* is everything before it. A missing or non-integer fragment is an error —
|
|
38
|
+
* an address without an express ID isn't an entity address.
|
|
39
|
+
*
|
|
40
|
+
* @param uri The `modelURI#expressID` address.
|
|
41
|
+
* @return {EntityAddress} The parsed address.
|
|
42
|
+
*/
|
|
43
|
+
export function parseEntityAddress(uri) {
|
|
44
|
+
const hash = uri.lastIndexOf(FRAGMENT);
|
|
45
|
+
if (hash < 0) {
|
|
46
|
+
throw new Error(`Entity address has no '#expressID' fragment: ${uri}`);
|
|
47
|
+
}
|
|
48
|
+
const modelURI = uri.slice(0, hash);
|
|
49
|
+
const fragment = uri.slice(hash + 1);
|
|
50
|
+
if (fragment.length === 0 || !/^\d+$/.test(fragment)) {
|
|
51
|
+
throw new Error(`Entity address fragment is not an express ID: ${uri}`);
|
|
52
|
+
}
|
|
53
|
+
return { modelURI, expressID: parseInt(fragment, RADIX) };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve a (possibly relative) reference URI against a base model URI, so an
|
|
57
|
+
* `IfcExternalReference.Location` like `../shared/grid.ifc` becomes an absolute
|
|
58
|
+
* model URI addressable in the registry. Absolute references (with a scheme,
|
|
59
|
+
* or protocol-relative) pass through unchanged.
|
|
60
|
+
*
|
|
61
|
+
* Uses the standard URL resolver when the base is absolute; falls back to a
|
|
62
|
+
* plain path join when the base has no scheme (e.g. a bare filename in tests).
|
|
63
|
+
*
|
|
64
|
+
* @param base The base model URI the reference was found in.
|
|
65
|
+
* @param reference The reference URI (absolute or relative).
|
|
66
|
+
* @return {string} The resolved absolute reference URI.
|
|
67
|
+
*/
|
|
68
|
+
export function resolveReference(base, reference) {
|
|
69
|
+
// Already absolute (has a scheme like `https:` or is protocol-relative).
|
|
70
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(reference) || reference.startsWith('//')) {
|
|
71
|
+
return reference;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
return new URL(reference, base).toString();
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Base isn't a valid absolute URL (bare filename): join paths manually.
|
|
78
|
+
const slash = base.lastIndexOf('/');
|
|
79
|
+
const dir = slash < 0 ? '' : base.slice(0, slash + 1);
|
|
80
|
+
return normalizePath(dir + reference);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Collapse `.` / `..` segments in a slash-joined path (used only for the
|
|
85
|
+
* scheme-less fallback in {@link resolveReference}).
|
|
86
|
+
*
|
|
87
|
+
* @param path The path to normalise.
|
|
88
|
+
* @return {string} The normalised path.
|
|
89
|
+
*/
|
|
90
|
+
function normalizePath(path) {
|
|
91
|
+
const out = [];
|
|
92
|
+
for (const segment of path.split('/')) {
|
|
93
|
+
if (segment === '..') {
|
|
94
|
+
out.pop();
|
|
95
|
+
}
|
|
96
|
+
else if (segment !== '.') {
|
|
97
|
+
out.push(segment);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return out.join('/');
|
|
101
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model_uri.test.d.ts","sourceRoot":"","sources":["../../../src/core/model_uri.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/* eslint-disable no-magic-numbers */
|
|
2
|
+
// M5: universal entity addressing — a model URI plus an express-ID fragment —
|
|
3
|
+
// must round-trip and resolve relative references the way IFC external-ref
|
|
4
|
+
// locations demand.
|
|
5
|
+
import { describe, expect, test } from "@jest/globals";
|
|
6
|
+
import { formatEntityAddress, parseEntityAddress, resolveReference, } from "./model_uri.js";
|
|
7
|
+
describe("model URI addressing", () => {
|
|
8
|
+
test("formats and parses an entity address round-trip", () => {
|
|
9
|
+
const uri = formatEntityAddress("https://ex.com/part-B.ifc", 4022);
|
|
10
|
+
expect(uri).toBe("https://ex.com/part-B.ifc#4022");
|
|
11
|
+
const parsed = parseEntityAddress(uri);
|
|
12
|
+
expect(parsed.modelURI).toBe("https://ex.com/part-B.ifc");
|
|
13
|
+
expect(parsed.expressID).toBe(4022);
|
|
14
|
+
});
|
|
15
|
+
test("splits on the last # so the model URI keeps earlier structure", () => {
|
|
16
|
+
// (Model URIs shouldn't carry a '#', but parsing must be unambiguous.)
|
|
17
|
+
const parsed = parseEntityAddress("scheme://h/a#b#42");
|
|
18
|
+
expect(parsed.modelURI).toBe("scheme://h/a#b");
|
|
19
|
+
expect(parsed.expressID).toBe(42);
|
|
20
|
+
});
|
|
21
|
+
test("rejects formatting a model URI that contains #", () => {
|
|
22
|
+
expect(() => formatEntityAddress("a#b", 1)).toThrow(/#/);
|
|
23
|
+
});
|
|
24
|
+
test("rejects formatting a non-integer or negative express ID", () => {
|
|
25
|
+
expect(() => formatEntityAddress("a", 1.5)).toThrow();
|
|
26
|
+
expect(() => formatEntityAddress("a", -1)).toThrow();
|
|
27
|
+
});
|
|
28
|
+
test("rejects an address with no fragment or a non-numeric fragment", () => {
|
|
29
|
+
expect(() => parseEntityAddress("a.ifc")).toThrow(/fragment/);
|
|
30
|
+
expect(() => parseEntityAddress("a.ifc#")).toThrow(/express ID/);
|
|
31
|
+
expect(() => parseEntityAddress("a.ifc#x")).toThrow(/express ID/);
|
|
32
|
+
});
|
|
33
|
+
test("resolves a relative reference against an absolute base URI", () => {
|
|
34
|
+
expect(resolveReference("https://ex.com/site/plan.ifc", "../shared/grid.ifc"))
|
|
35
|
+
.toBe("https://ex.com/shared/grid.ifc");
|
|
36
|
+
expect(resolveReference("https://ex.com/site/plan.ifc", "wing-A.ifc"))
|
|
37
|
+
.toBe("https://ex.com/site/wing-A.ifc");
|
|
38
|
+
});
|
|
39
|
+
test("passes an already-absolute reference through unchanged", () => {
|
|
40
|
+
expect(resolveReference("https://ex.com/a.ifc", "https://other.org/b.ifc"))
|
|
41
|
+
.toBe("https://other.org/b.ifc");
|
|
42
|
+
});
|
|
43
|
+
test("resolves relative references against a scheme-less base", () => {
|
|
44
|
+
expect(resolveReference("project/plan.ifc", "wing-A.ifc"))
|
|
45
|
+
.toBe("project/wing-A.ifc");
|
|
46
|
+
expect(resolveReference("project/site/plan.ifc", "../grid.ifc"))
|
|
47
|
+
.toBe("project/grid.ifc");
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -27,6 +27,8 @@ export interface ProgressEvent {
|
|
|
27
27
|
readonly elapsedMs: number;
|
|
28
28
|
/** Coarse used-JS-heap sample in MB, when the environment exposes one. */
|
|
29
29
|
readonly memoryMb?: number;
|
|
30
|
+
/** Windowed source bytes currently resident, in MB (Geometry phase). */
|
|
31
|
+
readonly residentSourceMb?: number;
|
|
30
32
|
}
|
|
31
33
|
export type ProgressCallback = (event: ProgressEvent) => void;
|
|
32
34
|
/**
|
|
@@ -42,7 +44,14 @@ export declare const DEFAULT_PROGRESS_INTERVAL_MS = 100;
|
|
|
42
44
|
* repaint progress UI and timers (e.g. stall watchdogs) can fire. Used by the
|
|
43
45
|
* *Async load variants between progress ticks.
|
|
44
46
|
*
|
|
45
|
-
*
|
|
47
|
+
* Not timer-based where avoidable: background tabs clamp setTimeout to >=1s,
|
|
48
|
+
* which would collapse a cooperative parse to a ~5% duty cycle the moment
|
|
49
|
+
* the tab loses focus. scheduler.yield() (and the MessageChannel fallback)
|
|
50
|
+
* post ordinary tasks, which are not clamped — loads keep their CPU in
|
|
51
|
+
* backgrounded tabs. setTimeout remains as the last-resort fallback for
|
|
52
|
+
* environments without either (where throttling doesn't apply anyway).
|
|
53
|
+
*
|
|
54
|
+
* @return {Promise<void>} A promise resolved on the next event-loop task.
|
|
46
55
|
*/
|
|
47
56
|
export declare function yieldToEventLoop(): Promise<void>;
|
|
48
57
|
/**
|
|
@@ -61,6 +70,7 @@ export declare class ProgressTracker {
|
|
|
61
70
|
private phase_;
|
|
62
71
|
private unit_;
|
|
63
72
|
private total_;
|
|
73
|
+
private extras_;
|
|
64
74
|
/**
|
|
65
75
|
* Construct this with the callback progress events are forwarded to.
|
|
66
76
|
*
|
|
@@ -93,8 +103,11 @@ export declare class ProgressTracker {
|
|
|
93
103
|
* Report progress within the current phase; throttled.
|
|
94
104
|
*
|
|
95
105
|
* @param completed Units completed so far.
|
|
106
|
+
* @param extras Optional extras (window residency) merged into the event.
|
|
96
107
|
*/
|
|
97
|
-
update(completed: number
|
|
108
|
+
update(completed: number, extras?: {
|
|
109
|
+
residentSourceMb?: number;
|
|
110
|
+
}): void;
|
|
98
111
|
/**
|
|
99
112
|
* End the current phase, emitting an unthrottled final event with
|
|
100
113
|
* completed === total when a total is known.
|
|
@@ -107,6 +120,7 @@ export declare class ProgressTracker {
|
|
|
107
120
|
*
|
|
108
121
|
* @param completed Units completed so far.
|
|
109
122
|
* @param now Current time in ms (defaults to Date.now()).
|
|
123
|
+
* @param extras Optional extras merged into the event.
|
|
110
124
|
*/
|
|
111
125
|
private emit;
|
|
112
126
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../src/core/progress.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GACvB,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,CAAA;AAEvE,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAElF;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../src/core/progress.ts"],"names":[],"mappings":"AAGA;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GACvB,aAAa,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,CAAA;AAEvE,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAElF;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAA;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACnC;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAE,KAAK,EAAE,aAAa,KAAM,IAAI,CAAA;AAE/D;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAM,IAAI,CAAA;AAEhF,oEAAoE;AACpE,eAAO,MAAM,4BAA4B,MAAM,CAAA;AAE/C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAuBhD;AAED;;;;;;;GAOG;AACH,qBAAa,eAAe;IAgBxB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAfhC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,YAAY,CAAY;IAChC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,OAAO,CAA2C;IAE1D;;;;;OAKG;gBAEgB,UAAU,EAAE,gBAAgB,EAC5B,aAAa,GAAE,MAAqC;IAEvE;;;;OAIG;IACH,IAAW,KAAK,IAAI,aAAa,GAAG,SAAS,CAE5C;IAED;;;;;;OAMG;IACI,UAAU,CAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,MAAM,GAAI,IAAI;IAQnF;;;;;OAKG;IACI,aAAa,CAAE,KAAK,EAAE,MAAM,GAAI,IAAI;IAI3C;;;;;OAKG;IACI,MAAM,CACT,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,GAAI,IAAI;IAWlD;;;;;OAKG;IACI,QAAQ,CAAE,SAAS,CAAC,EAAE,MAAM,GAAI,IAAI;IAM3C;;;;;;OAMG;IACH,OAAO,CAAC,IAAI;CAsBb"}
|
|
@@ -6,9 +6,30 @@ export const DEFAULT_PROGRESS_INTERVAL_MS = 100;
|
|
|
6
6
|
* repaint progress UI and timers (e.g. stall watchdogs) can fire. Used by the
|
|
7
7
|
* *Async load variants between progress ticks.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* Not timer-based where avoidable: background tabs clamp setTimeout to >=1s,
|
|
10
|
+
* which would collapse a cooperative parse to a ~5% duty cycle the moment
|
|
11
|
+
* the tab loses focus. scheduler.yield() (and the MessageChannel fallback)
|
|
12
|
+
* post ordinary tasks, which are not clamped — loads keep their CPU in
|
|
13
|
+
* backgrounded tabs. setTimeout remains as the last-resort fallback for
|
|
14
|
+
* environments without either (where throttling doesn't apply anyway).
|
|
15
|
+
*
|
|
16
|
+
* @return {Promise<void>} A promise resolved on the next event-loop task.
|
|
10
17
|
*/
|
|
11
18
|
export function yieldToEventLoop() {
|
|
19
|
+
const scheduler = globalThis.scheduler;
|
|
20
|
+
if (typeof scheduler?.yield === "function") {
|
|
21
|
+
return scheduler.yield();
|
|
22
|
+
}
|
|
23
|
+
if (typeof MessageChannel === "function") {
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
const channel = new MessageChannel();
|
|
26
|
+
channel.port1.onmessage = () => {
|
|
27
|
+
channel.port1.close();
|
|
28
|
+
resolve();
|
|
29
|
+
};
|
|
30
|
+
channel.port2.postMessage(null);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
12
33
|
return new Promise((resolve) => {
|
|
13
34
|
setTimeout(resolve, 0);
|
|
14
35
|
});
|
|
@@ -69,13 +90,15 @@ export class ProgressTracker {
|
|
|
69
90
|
* Report progress within the current phase; throttled.
|
|
70
91
|
*
|
|
71
92
|
* @param completed Units completed so far.
|
|
93
|
+
* @param extras Optional extras (window residency) merged into the event.
|
|
72
94
|
*/
|
|
73
|
-
update(completed) {
|
|
95
|
+
update(completed, extras) {
|
|
96
|
+
this.extras_ = extras;
|
|
74
97
|
const now = Date.now();
|
|
75
98
|
if (now - this.lastEmitTime < this.minIntervalMs) {
|
|
76
99
|
return;
|
|
77
100
|
}
|
|
78
|
-
this.emit(completed, now);
|
|
101
|
+
this.emit(completed, now, extras);
|
|
79
102
|
}
|
|
80
103
|
/**
|
|
81
104
|
* End the current phase, emitting an unthrottled final event with
|
|
@@ -84,16 +107,18 @@ export class ProgressTracker {
|
|
|
84
107
|
* @param completed Final completed units (defaults to the phase total).
|
|
85
108
|
*/
|
|
86
109
|
endPhase(completed) {
|
|
87
|
-
this.emit(completed ?? this.total_ ?? 0);
|
|
110
|
+
this.emit(completed ?? this.total_ ?? 0, Date.now(), this.extras_);
|
|
88
111
|
this.phase_ = void 0;
|
|
112
|
+
this.extras_ = void 0;
|
|
89
113
|
}
|
|
90
114
|
/**
|
|
91
115
|
* Materialize and forward an event now, bypassing the throttle.
|
|
92
116
|
*
|
|
93
117
|
* @param completed Units completed so far.
|
|
94
118
|
* @param now Current time in ms (defaults to Date.now()).
|
|
119
|
+
* @param extras Optional extras merged into the event.
|
|
95
120
|
*/
|
|
96
|
-
emit(completed, now = Date.now()) {
|
|
121
|
+
emit(completed, now = Date.now(), extras) {
|
|
97
122
|
if (this.phase_ === void 0) {
|
|
98
123
|
return;
|
|
99
124
|
}
|
|
@@ -106,6 +131,7 @@ export class ProgressTracker {
|
|
|
106
131
|
unit: this.unit_,
|
|
107
132
|
elapsedMs: now - this.startTime,
|
|
108
133
|
memoryMb: Memory.usedHeapMb(),
|
|
134
|
+
residentSourceMb: extras?.residentSourceMb,
|
|
109
135
|
});
|
|
110
136
|
}
|
|
111
137
|
}
|
|
@@ -54,12 +54,21 @@ describe("ProgressTracker", () => {
|
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
describe("yieldToEventLoop", () => {
|
|
57
|
-
test("
|
|
57
|
+
test("does not starve queued timers", async () => {
|
|
58
|
+
// The yield posts an ordinary task (scheduler.yield / MessageChannel —
|
|
59
|
+
// deliberately NOT a timer, so background tabs' >=1s setTimeout clamp
|
|
60
|
+
// cannot collapse a cooperative parse). Message tasks can be serviced
|
|
61
|
+
// ahead of the timer queue, so a due timer is not guaranteed to run
|
|
62
|
+
// within ONE yield — the contract is that repeated yielding lets due
|
|
63
|
+
// timers fire promptly (stall watchdogs stay live during a parse).
|
|
58
64
|
let timerRan = false;
|
|
59
65
|
setTimeout(() => {
|
|
60
66
|
timerRan = true;
|
|
61
67
|
}, 0);
|
|
62
|
-
|
|
68
|
+
const MAX_YIELDS = 50;
|
|
69
|
+
for (let where = 0; where < MAX_YIELDS && !timerRan; ++where) {
|
|
70
|
+
await yieldToEventLoop();
|
|
71
|
+
}
|
|
63
72
|
expect(timerRan).toBe(true);
|
|
64
73
|
});
|
|
65
74
|
});
|