@forgeax/engine-ecs 0.0.0-dev.8d955ade1c79
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/LICENSE +202 -0
- package/README.md +278 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/__fixtures__/field-shape-fixture.d.ts +16 -0
- package/dist/__fixtures__/field-shape-fixture.d.ts.map +1 -0
- package/dist/__tests__/__fixtures__/inspect-scripts.snapshot.d.ts +3 -0
- package/dist/__tests__/__fixtures__/inspect-scripts.snapshot.d.ts.map +1 -0
- package/dist/__tests__/archetype.unit.test.d.ts +2 -0
- package/dist/__tests__/archetype.unit.test.d.ts.map +1 -0
- package/dist/__tests__/array-handle-element.test-d.d.ts +2 -0
- package/dist/__tests__/array-handle-element.test-d.d.ts.map +1 -0
- package/dist/__tests__/buffer-array-vocab.test-d.d.ts +2 -0
- package/dist/__tests__/buffer-array-vocab.test-d.d.ts.map +1 -0
- package/dist/__tests__/buffer-field-input-widen.unit.test.d.ts +2 -0
- package/dist/__tests__/buffer-field-input-widen.unit.test.d.ts.map +1 -0
- package/dist/__tests__/buffer-pool.test-d.d.ts +2 -0
- package/dist/__tests__/buffer-pool.test-d.d.ts.map +1 -0
- package/dist/__tests__/change-detection.unit.test.d.ts +2 -0
- package/dist/__tests__/change-detection.unit.test.d.ts.map +1 -0
- package/dist/__tests__/command-buffer.test.d.ts +2 -0
- package/dist/__tests__/command-buffer.test.d.ts.map +1 -0
- package/dist/__tests__/commands-deferred.unit.test.d.ts +2 -0
- package/dist/__tests__/commands-deferred.unit.test.d.ts.map +1 -0
- package/dist/__tests__/component-catalog.test.d.ts +2 -0
- package/dist/__tests__/component-catalog.test.d.ts.map +1 -0
- package/dist/__tests__/component-definition-identity.unit.test.d.ts +2 -0
- package/dist/__tests__/component-definition-identity.unit.test.d.ts.map +1 -0
- package/dist/__tests__/component-nan-preflight.unit.test.d.ts +2 -0
- package/dist/__tests__/component-nan-preflight.unit.test.d.ts.map +1 -0
- package/dist/__tests__/component-schema.test-d.d.ts +2 -0
- package/dist/__tests__/component-schema.test-d.d.ts.map +1 -0
- package/dist/__tests__/component-schema.test.d.ts +2 -0
- package/dist/__tests__/component-schema.test.d.ts.map +1 -0
- package/dist/__tests__/define-component-options.test-d.d.ts +2 -0
- package/dist/__tests__/define-component-options.test-d.d.ts.map +1 -0
- package/dist/__tests__/deprecated-vocab-rejection.unit.test.d.ts +2 -0
- package/dist/__tests__/deprecated-vocab-rejection.unit.test.d.ts.map +1 -0
- package/dist/__tests__/despawn-all.unit.test.d.ts +2 -0
- package/dist/__tests__/despawn-all.unit.test.d.ts.map +1 -0
- package/dist/__tests__/ecs-core-reduction.characterization.test.d.ts +2 -0
- package/dist/__tests__/ecs-core-reduction.characterization.test.d.ts.map +1 -0
- package/dist/__tests__/ecs-core-reduction.perf.test.d.ts +2 -0
- package/dist/__tests__/ecs-core-reduction.perf.test.d.ts.map +1 -0
- package/dist/__tests__/ecs-error-code-31.test-d.d.ts +2 -0
- package/dist/__tests__/ecs-error-code-31.test-d.d.ts.map +1 -0
- package/dist/__tests__/entity-disabling.unit.test.d.ts +2 -0
- package/dist/__tests__/entity-disabling.unit.test.d.ts.map +1 -0
- package/dist/__tests__/entity-handle-codec-parity.unit.test.d.ts +2 -0
- package/dist/__tests__/entity-handle-codec-parity.unit.test.d.ts.map +1 -0
- package/dist/__tests__/errors.unit.test.d.ts +2 -0
- package/dist/__tests__/errors.unit.test.d.ts.map +1 -0
- package/dist/__tests__/execution-conflict-boundary.unit.test.d.ts +2 -0
- package/dist/__tests__/execution-conflict-boundary.unit.test.d.ts.map +1 -0
- package/dist/__tests__/execution-shared-storage.unit.test.d.ts +2 -0
- package/dist/__tests__/execution-shared-storage.unit.test.d.ts.map +1 -0
- package/dist/__tests__/externalization-portable-value.unit.test.d.ts +2 -0
- package/dist/__tests__/externalization-portable-value.unit.test.d.ts.map +1 -0
- package/dist/__tests__/externalization-projection.unit.test.d.ts +2 -0
- package/dist/__tests__/externalization-projection.unit.test.d.ts.map +1 -0
- package/dist/__tests__/externalization-render-read-lease.test-d.d.ts +2 -0
- package/dist/__tests__/externalization-render-read-lease.test-d.d.ts.map +1 -0
- package/dist/__tests__/externalization-render-read-lease.unit.test.d.ts +2 -0
- package/dist/__tests__/externalization-render-read-lease.unit.test.d.ts.map +1 -0
- package/dist/__tests__/externalization-root-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/externalization-root-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/field-enum-labels-reflection.test.d.ts +2 -0
- package/dist/__tests__/field-enum-labels-reflection.test.d.ts.map +1 -0
- package/dist/__tests__/field-shape-fixture.test.d.ts +2 -0
- package/dist/__tests__/field-shape-fixture.test.d.ts.map +1 -0
- package/dist/__tests__/field-transient-reflection.test.d.ts +2 -0
- package/dist/__tests__/field-transient-reflection.test.d.ts.map +1 -0
- package/dist/__tests__/field-value-type.test-d.d.ts +2 -0
- package/dist/__tests__/field-value-type.test-d.d.ts.map +1 -0
- package/dist/__tests__/fixed-update.unit.test.d.ts +2 -0
- package/dist/__tests__/fixed-update.unit.test.d.ts.map +1 -0
- package/dist/__tests__/handle.test-d.d.ts +2 -0
- package/dist/__tests__/handle.test-d.d.ts.map +1 -0
- package/dist/__tests__/hierarchy.unit.test.d.ts +2 -0
- package/dist/__tests__/hierarchy.unit.test.d.ts.map +1 -0
- package/dist/__tests__/managed-array-vocab.test-d.d.ts +2 -0
- package/dist/__tests__/managed-array-vocab.test-d.d.ts.map +1 -0
- package/dist/__tests__/minimal-example.test-d.d.ts +2 -0
- package/dist/__tests__/minimal-example.test-d.d.ts.map +1 -0
- package/dist/__tests__/name-read-types.test-d.d.ts +2 -0
- package/dist/__tests__/name-read-types.test-d.d.ts.map +1 -0
- package/dist/__tests__/plugin-service.test.d.ts +2 -0
- package/dist/__tests__/plugin-service.test.d.ts.map +1 -0
- package/dist/__tests__/query-combinations.unit.test.d.ts +2 -0
- package/dist/__tests__/query-combinations.unit.test.d.ts.map +1 -0
- package/dist/__tests__/query-light-extract-flat-column-ratio.perf.test.d.ts +2 -0
- package/dist/__tests__/query-light-extract-flat-column-ratio.perf.test.d.ts.map +1 -0
- package/dist/__tests__/query-storage-trends.perf.test.d.ts +2 -0
- package/dist/__tests__/query-storage-trends.perf.test.d.ts.map +1 -0
- package/dist/__tests__/query-trs-flat-column-ratio.perf.test.d.ts +2 -0
- package/dist/__tests__/query-trs-flat-column-ratio.perf.test.d.ts.map +1 -0
- package/dist/__tests__/query.unit.test.d.ts +2 -0
- package/dist/__tests__/query.unit.test.d.ts.map +1 -0
- package/dist/__tests__/relationship-index.perf.test.d.ts +2 -0
- package/dist/__tests__/relationship-index.perf.test.d.ts.map +1 -0
- package/dist/__tests__/relationship-index.test.d.ts +2 -0
- package/dist/__tests__/relationship-index.test.d.ts.map +1 -0
- package/dist/__tests__/scalar-field-type-owner.test-d.d.ts +2 -0
- package/dist/__tests__/scalar-field-type-owner.test-d.d.ts.map +1 -0
- package/dist/__tests__/schedule-determinism.unit.test.d.ts +2 -0
- package/dist/__tests__/schedule-determinism.unit.test.d.ts.map +1 -0
- package/dist/__tests__/schedule-inspection.unit.test.d.ts +2 -0
- package/dist/__tests__/schedule-inspection.unit.test.d.ts.map +1 -0
- package/dist/__tests__/schedule-scope-error.unit.test.d.ts +2 -0
- package/dist/__tests__/schedule-scope-error.unit.test.d.ts.map +1 -0
- package/dist/__tests__/schedule-token.unit.test.d.ts +2 -0
- package/dist/__tests__/schedule-token.unit.test.d.ts.map +1 -0
- package/dist/__tests__/schema-vocab.test-d.d.ts +2 -0
- package/dist/__tests__/schema-vocab.test-d.d.ts.map +1 -0
- package/dist/__tests__/serialization.unit.test.d.ts +2 -0
- package/dist/__tests__/serialization.unit.test.d.ts.map +1 -0
- package/dist/__tests__/shared-kernel-eligibility.test-d.d.ts +2 -0
- package/dist/__tests__/shared-kernel-eligibility.test-d.d.ts.map +1 -0
- package/dist/__tests__/shared-kernel-eligibility.unit.test.d.ts +2 -0
- package/dist/__tests__/shared-kernel-eligibility.unit.test.d.ts.map +1 -0
- package/dist/__tests__/shared-ref-store.unit.test.d.ts +2 -0
- package/dist/__tests__/shared-ref-store.unit.test.d.ts.map +1 -0
- package/dist/__tests__/sparse-tag.unit.test.d.ts +2 -0
- package/dist/__tests__/sparse-tag.unit.test.d.ts.map +1 -0
- package/dist/__tests__/spawn-field-error.test-d.d.ts +2 -0
- package/dist/__tests__/spawn-field-error.test-d.d.ts.map +1 -0
- package/dist/__tests__/stale-error.test-d.d.ts +2 -0
- package/dist/__tests__/stale-error.test-d.d.ts.map +1 -0
- package/dist/__tests__/string-view-symmetry.test-d.d.ts +2 -0
- package/dist/__tests__/string-view-symmetry.test-d.d.ts.map +1 -0
- package/dist/__tests__/string-vocab.test-d.d.ts +2 -0
- package/dist/__tests__/string-vocab.test-d.d.ts.map +1 -0
- package/dist/__tests__/structure-epoch-boundaries.unit.test.d.ts +2 -0
- package/dist/__tests__/structure-epoch-boundaries.unit.test.d.ts.map +1 -0
- package/dist/__tests__/structure-epoch.unit.test.d.ts +2 -0
- package/dist/__tests__/structure-epoch.unit.test.d.ts.map +1 -0
- package/dist/__tests__/table-archetype-mapping.unit.test.d.ts +2 -0
- package/dist/__tests__/table-archetype-mapping.unit.test.d.ts.map +1 -0
- package/dist/__tests__/time.unit.test.d.ts +2 -0
- package/dist/__tests__/time.unit.test.d.ts.map +1 -0
- package/dist/__tests__/types.test-d.d.ts +2 -0
- package/dist/__tests__/types.test-d.d.ts.map +1 -0
- package/dist/__tests__/unique-ref-store.unit.test.d.ts +2 -0
- package/dist/__tests__/unique-ref-store.unit.test.d.ts.map +1 -0
- package/dist/__tests__/utils/handle-numeric.d.ts +14 -0
- package/dist/__tests__/utils/handle-numeric.d.ts.map +1 -0
- package/dist/__tests__/validation-root-surface.unit.test.d.ts +2 -0
- package/dist/__tests__/validation-root-surface.unit.test.d.ts.map +1 -0
- package/dist/__tests__/visibility-atomic-write.unit.test.d.ts +2 -0
- package/dist/__tests__/visibility-atomic-write.unit.test.d.ts.map +1 -0
- package/dist/__tests__/world-change-journal.unit.test.d.ts +2 -0
- package/dist/__tests__/world-change-journal.unit.test.d.ts.map +1 -0
- package/dist/__tests__/world-characterization.unit.test.d.ts +2 -0
- package/dist/__tests__/world-characterization.unit.test.d.ts.map +1 -0
- package/dist/__tests__/world-consumer-inference.test-d.d.ts +2 -0
- package/dist/__tests__/world-consumer-inference.test-d.d.ts.map +1 -0
- package/dist/__tests__/world-health.contract.test.d.ts +2 -0
- package/dist/__tests__/world-health.contract.test.d.ts.map +1 -0
- package/dist/__tests__/world-inspection.test.d.ts +2 -0
- package/dist/__tests__/world-inspection.test.d.ts.map +1 -0
- package/dist/__tests__/world-internal-identity.unit.test.d.ts +2 -0
- package/dist/__tests__/world-internal-identity.unit.test.d.ts.map +1 -0
- package/dist/__tests__/world-managed-roundtrip.unit.test.d.ts +2 -0
- package/dist/__tests__/world-managed-roundtrip.unit.test.d.ts.map +1 -0
- package/dist/__tests__/world-scheduling.m4.test.d.ts +2 -0
- package/dist/__tests__/world-scheduling.m4.test.d.ts.map +1 -0
- package/dist/__tests__/world-unique-roundtrip.unit.test.d.ts +2 -0
- package/dist/__tests__/world-unique-roundtrip.unit.test.d.ts.map +1 -0
- package/dist/__tests__/world.test-d.d.ts +2 -0
- package/dist/__tests__/world.test-d.d.ts.map +1 -0
- package/dist/buffer-pool.d.ts +109 -0
- package/dist/buffer-pool.d.ts.map +1 -0
- package/dist/commands.d.ts +93 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/component-default-fallback.d.ts +88 -0
- package/dist/component-default-fallback.d.ts.map +1 -0
- package/dist/component-schema.d.ts +34 -0
- package/dist/component-schema.d.ts.map +1 -0
- package/dist/component-value-validate.d.ts +29 -0
- package/dist/component-value-validate.d.ts.map +1 -0
- package/dist/component.d.ts +581 -0
- package/dist/component.d.ts.map +1 -0
- package/dist/entity-handle.d.ts +68 -0
- package/dist/entity-handle.d.ts.map +1 -0
- package/dist/entity.d.ts +86 -0
- package/dist/entity.d.ts.map +1 -0
- package/dist/errors/query-and-component-errors.d.ts +132 -0
- package/dist/errors/query-and-component-errors.d.ts.map +1 -0
- package/dist/errors/relationship-errors.d.ts +112 -0
- package/dist/errors/relationship-errors.d.ts.map +1 -0
- package/dist/errors/sprite-and-shared-errors.d.ts +107 -0
- package/dist/errors/sprite-and-shared-errors.d.ts.map +1 -0
- package/dist/errors/validation-errors.d.ts +229 -0
- package/dist/errors/validation-errors.d.ts.map +1 -0
- package/dist/errors.d.ts +763 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/execution/shared-kernel.d.ts +106 -0
- package/dist/execution/shared-kernel.d.ts.map +1 -0
- package/dist/externalization/index.d.ts +31 -0
- package/dist/externalization/index.d.ts.map +1 -0
- package/dist/externalization/index.mjs +298 -0
- package/dist/externalization/index.mjs.map +1 -0
- package/dist/index.d.ts +261 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +7422 -0
- package/dist/index.mjs.map +1 -0
- package/dist/internal.mjs +479 -0
- package/dist/internal.mjs.map +1 -0
- package/dist/plugin-service.d.ts +11 -0
- package/dist/plugin-service.d.ts.map +1 -0
- package/dist/projection/index.d.ts +103 -0
- package/dist/projection/index.d.ts.map +1 -0
- package/dist/projection/index.mjs +615 -0
- package/dist/projection/index.mjs.map +1 -0
- package/dist/query/query.d.ts +58 -0
- package/dist/query/query.d.ts.map +1 -0
- package/dist/relationship-index.d.ts +81 -0
- package/dist/relationship-index.d.ts.map +1 -0
- package/dist/resource.d.ts +70 -0
- package/dist/resource.d.ts.map +1 -0
- package/dist/schedule-token.d.ts +16 -0
- package/dist/schedule-token.d.ts.map +1 -0
- package/dist/schedule.d.ts +271 -0
- package/dist/schedule.d.ts.map +1 -0
- package/dist/shared-ref-store.d.ts +144 -0
- package/dist/shared-ref-store.d.ts.map +1 -0
- package/dist/shared.d.ts +3 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.mjs +364 -0
- package/dist/shared.mjs.map +1 -0
- package/dist/storage/archetype-graph.d.ts +54 -0
- package/dist/storage/archetype-graph.d.ts.map +1 -0
- package/dist/storage/archetype.d.ts +23 -0
- package/dist/storage/archetype.d.ts.map +1 -0
- package/dist/storage/change-detection.d.ts +40 -0
- package/dist/storage/change-detection.d.ts.map +1 -0
- package/dist/storage/column.d.ts +111 -0
- package/dist/storage/column.d.ts.map +1 -0
- package/dist/storage/table.d.ts +29 -0
- package/dist/storage/table.d.ts.map +1 -0
- package/dist/time.d.ts +57 -0
- package/dist/time.d.ts.map +1 -0
- package/dist/unique-ref-store.d.ts +105 -0
- package/dist/unique-ref-store.d.ts.map +1 -0
- package/dist/world-change-journal.d.ts +34 -0
- package/dist/world-change-journal.d.ts.map +1 -0
- package/dist/world-component-access.d.ts +265 -0
- package/dist/world-component-access.d.ts.map +1 -0
- package/dist/world-component-storage.d.ts +282 -0
- package/dist/world-component-storage.d.ts.map +1 -0
- package/dist/world-core.d.ts +39 -0
- package/dist/world-core.d.ts.map +1 -0
- package/dist/world-entity-lifecycle.d.ts +30 -0
- package/dist/world-entity-lifecycle.d.ts.map +1 -0
- package/dist/world-internal.d.ts +14 -0
- package/dist/world-internal.d.ts.map +1 -0
- package/dist/world-scheduling.d.ts +30 -0
- package/dist/world-scheduling.d.ts.map +1 -0
- package/dist/world.d.ts +620 -0
- package/dist/world.d.ts.map +1 -0
- package/package.json +77 -0
- package/src/__fixtures__/field-shape-fixture.ts +30 -0
- package/src/__tests__/__fixtures__/inspect-scripts.snapshot.ts +2 -0
- package/src/__tests__/archetype.unit.test.ts +1837 -0
- package/src/__tests__/array-handle-element.test-d.ts +34 -0
- package/src/__tests__/buffer-array-vocab.test-d.ts +53 -0
- package/src/__tests__/buffer-field-input-widen.unit.test.ts +99 -0
- package/src/__tests__/buffer-pool.test-d.ts +32 -0
- package/src/__tests__/change-detection.unit.test.ts +86 -0
- package/src/__tests__/command-buffer.test.ts +179 -0
- package/src/__tests__/commands-deferred.unit.test.ts +68 -0
- package/src/__tests__/component-catalog.test.ts +59 -0
- package/src/__tests__/component-definition-identity.unit.test.ts +24 -0
- package/src/__tests__/component-nan-preflight.unit.test.ts +186 -0
- package/src/__tests__/component-schema.test-d.ts +119 -0
- package/src/__tests__/component-schema.test.ts +55 -0
- package/src/__tests__/define-component-options.test-d.ts +35 -0
- package/src/__tests__/deprecated-vocab-rejection.unit.test.ts +59 -0
- package/src/__tests__/despawn-all.unit.test.ts +17 -0
- package/src/__tests__/ecs-core-reduction.characterization.test.ts +130 -0
- package/src/__tests__/ecs-core-reduction.perf.test.ts +260 -0
- package/src/__tests__/ecs-error-code-31.test-d.ts +42 -0
- package/src/__tests__/entity-disabling.unit.test.ts +37 -0
- package/src/__tests__/entity-handle-codec-parity.unit.test.ts +126 -0
- package/src/__tests__/errors.unit.test.ts +1456 -0
- package/src/__tests__/execution-conflict-boundary.unit.test.ts +123 -0
- package/src/__tests__/execution-shared-storage.unit.test.ts +40 -0
- package/src/__tests__/externalization-portable-value.unit.test.ts +275 -0
- package/src/__tests__/externalization-projection.unit.test.ts +325 -0
- package/src/__tests__/externalization-render-read-lease.test-d.ts +30 -0
- package/src/__tests__/externalization-render-read-lease.unit.test.ts +79 -0
- package/src/__tests__/externalization-root-surface.unit.test.ts +33 -0
- package/src/__tests__/field-enum-labels-reflection.test.ts +66 -0
- package/src/__tests__/field-shape-fixture.test.ts +61 -0
- package/src/__tests__/field-transient-reflection.test.ts +59 -0
- package/src/__tests__/field-value-type.test-d.ts +57 -0
- package/src/__tests__/fixed-update.unit.test.ts +78 -0
- package/src/__tests__/handle.test-d.ts +86 -0
- package/src/__tests__/hierarchy.unit.test.ts +2534 -0
- package/src/__tests__/managed-array-vocab.test-d.ts +137 -0
- package/src/__tests__/minimal-example.test-d.ts +42 -0
- package/src/__tests__/name-read-types.test-d.ts +72 -0
- package/src/__tests__/plugin-service.test.ts +13 -0
- package/src/__tests__/query-combinations.unit.test.ts +42 -0
- package/src/__tests__/query-light-extract-flat-column-ratio.perf.test.ts +252 -0
- package/src/__tests__/query-storage-trends.perf.test.ts +104 -0
- package/src/__tests__/query-trs-flat-column-ratio.perf.test.ts +194 -0
- package/src/__tests__/query.unit.test.ts +196 -0
- package/src/__tests__/relationship-index.perf.test.ts +126 -0
- package/src/__tests__/relationship-index.test.ts +70 -0
- package/src/__tests__/scalar-field-type-owner.test-d.ts +71 -0
- package/src/__tests__/schedule-determinism.unit.test.ts +36 -0
- package/src/__tests__/schedule-inspection.unit.test.ts +81 -0
- package/src/__tests__/schedule-scope-error.unit.test.ts +63 -0
- package/src/__tests__/schedule-token.unit.test.ts +54 -0
- package/src/__tests__/schema-vocab.test-d.ts +103 -0
- package/src/__tests__/serialization.unit.test.ts +2740 -0
- package/src/__tests__/shared-kernel-eligibility.test-d.ts +18 -0
- package/src/__tests__/shared-kernel-eligibility.unit.test.ts +78 -0
- package/src/__tests__/shared-ref-store.unit.test.ts +646 -0
- package/src/__tests__/sparse-tag.unit.test.ts +201 -0
- package/src/__tests__/spawn-field-error.test-d.ts +41 -0
- package/src/__tests__/stale-error.test-d.ts +208 -0
- package/src/__tests__/string-view-symmetry.test-d.ts +26 -0
- package/src/__tests__/string-vocab.test-d.ts +49 -0
- package/src/__tests__/structure-epoch-boundaries.unit.test.ts +39 -0
- package/src/__tests__/structure-epoch.unit.test.ts +48 -0
- package/src/__tests__/table-archetype-mapping.unit.test.ts +78 -0
- package/src/__tests__/time.unit.test.ts +79 -0
- package/src/__tests__/types.test-d.ts +38 -0
- package/src/__tests__/unique-ref-store.unit.test.ts +348 -0
- package/src/__tests__/utils/handle-numeric.ts +30 -0
- package/src/__tests__/validation-root-surface.unit.test.ts +15 -0
- package/src/__tests__/visibility-atomic-write.unit.test.ts +82 -0
- package/src/__tests__/world-change-journal.unit.test.ts +97 -0
- package/src/__tests__/world-characterization.unit.test.ts +408 -0
- package/src/__tests__/world-consumer-inference.test-d.ts +16 -0
- package/src/__tests__/world-health.contract.test.ts +87 -0
- package/src/__tests__/world-inspection.test.ts +37 -0
- package/src/__tests__/world-internal-identity.unit.test.ts +17 -0
- package/src/__tests__/world-managed-roundtrip.unit.test.ts +98 -0
- package/src/__tests__/world-scheduling.m4.test.ts +52 -0
- package/src/__tests__/world-unique-roundtrip.unit.test.ts +357 -0
- package/src/__tests__/world.test-d.ts +156 -0
- package/src/buffer-pool.ts +357 -0
- package/src/commands.ts +644 -0
- package/src/component-default-fallback.ts +236 -0
- package/src/component-schema.ts +92 -0
- package/src/component-value-validate.ts +135 -0
- package/src/component.ts +1268 -0
- package/src/entity-handle.ts +104 -0
- package/src/entity.ts +140 -0
- package/src/errors/query-and-component-errors.ts +200 -0
- package/src/errors/relationship-errors.ts +198 -0
- package/src/errors/sprite-and-shared-errors.ts +231 -0
- package/src/errors/validation-errors.ts +506 -0
- package/src/errors.ts +1464 -0
- package/src/execution/shared-kernel.ts +392 -0
- package/src/externalization/index.ts +170 -0
- package/src/index.ts +414 -0
- package/src/plugin-service.ts +35 -0
- package/src/projection/index.ts +318 -0
- package/src/query/query.ts +606 -0
- package/src/relationship-index.ts +175 -0
- package/src/resource.ts +106 -0
- package/src/schedule-token.ts +40 -0
- package/src/schedule.ts +846 -0
- package/src/shared-ref-store.ts +418 -0
- package/src/shared.ts +23 -0
- package/src/storage/archetype-graph.ts +166 -0
- package/src/storage/archetype.ts +78 -0
- package/src/storage/change-detection.ts +231 -0
- package/src/storage/column.ts +247 -0
- package/src/storage/table.ts +153 -0
- package/src/time.ts +122 -0
- package/src/unique-ref-store.ts +278 -0
- package/src/world-change-journal.ts +84 -0
- package/src/world-component-access.ts +1421 -0
- package/src/world-component-storage.ts +1178 -0
- package/src/world-core.ts +74 -0
- package/src/world-entity-lifecycle.ts +539 -0
- package/src/world-internal.ts +75 -0
- package/src/world-scheduling.ts +499 -0
- package/src/world.ts +1399 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
// @forgeax/engine-ecs - BufferPool (M2, plan-decisions D-5 / D-6 / D-7).
|
|
2
|
+
//
|
|
3
|
+
// Backing store for `buffer:<bytes>` schema-vocab fields. Each `buffer:<N>`
|
|
4
|
+
// slot is a managed Uint8Array view; the pool keeps eight size-class
|
|
5
|
+
// free-lists (radix 4) and uses ArrayBuffer.transfer for cross-bucket
|
|
6
|
+
// growth. The integer `id` returned by `alloc` is the runtime stand-in for
|
|
7
|
+
// the buffer slot; archetype columns store the `id` as u32 (M4 carry-over
|
|
8
|
+
// reuses this id across archetype migrate without copying bytes).
|
|
9
|
+
//
|
|
10
|
+
// §contract — managed handles are operational, not persistent
|
|
11
|
+
// Spec: docs/specs/2026-06-14-ecs-managed-lifecycle-ssot-design.md §3.3.
|
|
12
|
+
// The slot id never escapes ECS internals — there is no public Handle<Buffer>
|
|
13
|
+
// surface today. There is no generation tag on BufferPool; `release` is
|
|
14
|
+
// typed `Result<void, never>` (no stale-slot error arm) and the dual
|
|
15
|
+
// guards live at packages/ecs/src/__tests__/buffer-pool.test-d.ts (compile
|
|
16
|
+
// time) + packages/ecs/README.md §"Managed handles are operational, not
|
|
17
|
+
// persistent" (AI-user-facing). Should a future feat introduce a public
|
|
18
|
+
// Handle<Buffer> surface, this design (no gen tag) MUST be re-debated —
|
|
19
|
+
// the silent-resolve contract that UniqueRefStore tolerates relies on
|
|
20
|
+
// the holder being a single ECS field, not a free-floating cache; a
|
|
21
|
+
// public Handle<Buffer> changes that calculus.
|
|
22
|
+
//
|
|
23
|
+
// Design contract (frozen by plan-decisions):
|
|
24
|
+
// D-5 size-class 8 buckets (radix 4):
|
|
25
|
+
// 16 / 64 / 256 / 1K / 4K / 16K / 64K / 256K bytes.
|
|
26
|
+
// Allocation rounds up to the smallest bucket >= byteLength; alloc(0)
|
|
27
|
+
// is legal and returns a zero-length view (no bucket touched).
|
|
28
|
+
// Requests > 256K surface 'managed-buffer-out-of-bounds'.
|
|
29
|
+
// D-6 grow(id, newBytes) returns Result<Uint8Array, EcsError> - never
|
|
30
|
+
// throws, never mutates the prior view in place. Cross-bucket growth
|
|
31
|
+
// detaches the old ArrayBuffer (ES2024 transfer when available, copy
|
|
32
|
+
// fallback otherwise) and installs a fresh view backed by the new
|
|
33
|
+
// bucket's ArrayBuffer; same-bucket growth re-slices the existing
|
|
34
|
+
// backing buffer to the new byteLength.
|
|
35
|
+
// D-7 v1 forbids shrink (newBytes < current -> err); newBytes == current
|
|
36
|
+
// is a legal no-op that returns the same view. Bucket free-lists are
|
|
37
|
+
// NEVER trimmed - released slots stay parked on their bucket forever
|
|
38
|
+
// in v1 (memory bloat is acceptable until M5/M6 telemetry).
|
|
39
|
+
//
|
|
40
|
+
// The pool is a `class` rather than a frozen module-level singleton because
|
|
41
|
+
// World owns one BufferPool per instance; M2 wires it into the release loop
|
|
42
|
+
// alongside UniqueRefStore (D-2 - per-World lifecycle).
|
|
43
|
+
|
|
44
|
+
import { err, ok, type Result } from '@forgeax/engine-types';
|
|
45
|
+
import { ManagedBufferOutOfBoundsError, ManagedBufferShrinkNotSupportedError } from './errors';
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Size-class bucket boundaries in bytes (D-5, radix 4). Frozen tuple - the
|
|
49
|
+
* order is load-bearing: bucket index = ascending position in the array.
|
|
50
|
+
*
|
|
51
|
+
* `alloc(byteLength)` rounds up to `SIZE_CLASSES[i]` for the smallest `i`
|
|
52
|
+
* with `byteLength <= SIZE_CLASSES[i]`. byteLength === 0 is the special path
|
|
53
|
+
* (no bucket); byteLength > SIZE_CLASSES[7] (262_144) returns
|
|
54
|
+
* `managed-buffer-out-of-bounds`.
|
|
55
|
+
*/
|
|
56
|
+
export const SIZE_CLASSES: readonly number[] = Object.freeze([
|
|
57
|
+
16, 64, 256, 1024, 4096, 16384, 65536, 262144,
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
/** Result envelope for a fresh alloc - id + initial view. */
|
|
61
|
+
export interface BufferAllocResult {
|
|
62
|
+
/** Stable slot id; archetype columns store this u32 in their `buffer:<N>` field. */
|
|
63
|
+
readonly id: number;
|
|
64
|
+
/** Live Uint8Array view of length `byteLength` (D-5 rounding visible only via `view.buffer.byteLength`). */
|
|
65
|
+
readonly view: Uint8Array;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Module-level cache for `ArrayBuffer.prototype.transfer` support.
|
|
70
|
+
*
|
|
71
|
+
* Mirrors `column.ts` HAS_TRANSFER probe: ES2024 transfer is the zero-copy
|
|
72
|
+
* fast path on Node 22+ / dawn-node / modern browsers; the fallback re-allocs
|
|
73
|
+
* + byte-copies. Both paths preserve the byte-equal carry-over invariant
|
|
74
|
+
* (AC-07).
|
|
75
|
+
*/
|
|
76
|
+
const HAS_TRANSFER: boolean =
|
|
77
|
+
typeof (ArrayBuffer.prototype as { transfer?: unknown }).transfer === 'function';
|
|
78
|
+
|
|
79
|
+
interface SlotState {
|
|
80
|
+
/** Bucket index in SIZE_CLASSES, or -1 for the alloc(0) zero-length slot. */
|
|
81
|
+
sizeClassIdx: number;
|
|
82
|
+
/** Underlying ArrayBuffer for the slot's current bucket (zero-length for sizeClassIdx === -1). */
|
|
83
|
+
buffer: ArrayBuffer;
|
|
84
|
+
/** Live view; sliced to `byteLength <= buffer.byteLength`. */
|
|
85
|
+
view: Uint8Array;
|
|
86
|
+
/** Logical byteLength (== view.byteLength). */
|
|
87
|
+
byteLength: number;
|
|
88
|
+
/** false when the slot has been released and its id is parked on the free-list. */
|
|
89
|
+
live: boolean;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Round `byteLength` up to a bucket index. Returns -1 for the legal zero
|
|
94
|
+
* path; returns `SIZE_CLASSES.length` (out-of-range) for byteLength larger
|
|
95
|
+
* than the top bucket so the caller can route a clean
|
|
96
|
+
* `managed-buffer-out-of-bounds` error.
|
|
97
|
+
*/
|
|
98
|
+
function bucketIndex(byteLength: number): number {
|
|
99
|
+
if (byteLength === 0) return -1;
|
|
100
|
+
for (let i = 0; i < SIZE_CLASSES.length; i++) {
|
|
101
|
+
const b = SIZE_CLASSES[i];
|
|
102
|
+
if (b !== undefined && byteLength <= b) return i;
|
|
103
|
+
}
|
|
104
|
+
return SIZE_CLASSES.length;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Per-(slot id) managed Uint8Array store backing the `buffer:<bytes>` schema
|
|
109
|
+
* vocab keyword. Eight size-class free-lists (radix 4); cross-bucket growth
|
|
110
|
+
* uses `ArrayBuffer.transfer` when available with a copy fallback for older
|
|
111
|
+
* runtimes.
|
|
112
|
+
*
|
|
113
|
+
* AI users do not interact with `BufferPool` directly - it sits behind
|
|
114
|
+
* `world.get(e, C).<bufferField>` and the M4 carry-over migrate path. The
|
|
115
|
+
* pool is exposed as a class so World can hold one instance per
|
|
116
|
+
* `new World()` (D-2 per-World lifecycle).
|
|
117
|
+
*/
|
|
118
|
+
export class BufferPool {
|
|
119
|
+
private readonly slots = new Map<number, SlotState>();
|
|
120
|
+
/**
|
|
121
|
+
* Per-bucket free-lists: `freeBuckets[i]` is a LIFO stack of slot ids
|
|
122
|
+
* whose backing buffer is parked on bucket `i`. Released slots stay on
|
|
123
|
+
* their original bucket's free-list - v1 never moves a slot between
|
|
124
|
+
* buckets on release (D-7 no trim).
|
|
125
|
+
*/
|
|
126
|
+
private readonly freeBuckets: number[][] = SIZE_CLASSES.map(() => [] as number[]);
|
|
127
|
+
private nextId = 1;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Allocate a managed buffer slot of at least `byteLength` bytes.
|
|
131
|
+
*
|
|
132
|
+
* Routes:
|
|
133
|
+
* - byteLength < 0 -> not in current contract (caller responsibility).
|
|
134
|
+
* - byteLength == 0 -> ok({ id, view: zero-length Uint8Array }) (no bucket).
|
|
135
|
+
* - byteLength <= 262144 -> ok({ id, view }), bucket = smallest >= byteLength.
|
|
136
|
+
* - byteLength > 262144 -> err(managed-buffer-out-of-bounds).
|
|
137
|
+
*
|
|
138
|
+
* D-5: size classes are radix-4 (16 / 64 / 256 / 1K / 4K / 16K / 64K / 256K).
|
|
139
|
+
* Free-list pop reuses the most recently released slot id at the same bucket;
|
|
140
|
+
* miss falls through to a fresh allocation.
|
|
141
|
+
*/
|
|
142
|
+
alloc(byteLength: number): Result<BufferAllocResult, ManagedBufferOutOfBoundsError> {
|
|
143
|
+
if (byteLength === 0) {
|
|
144
|
+
const id = this.nextId++;
|
|
145
|
+
const buffer = new ArrayBuffer(0);
|
|
146
|
+
const view = new Uint8Array(buffer);
|
|
147
|
+
this.slots.set(id, { sizeClassIdx: -1, buffer, view, byteLength: 0, live: true });
|
|
148
|
+
return ok({ id, view });
|
|
149
|
+
}
|
|
150
|
+
const idx = bucketIndex(byteLength);
|
|
151
|
+
if (idx === SIZE_CLASSES.length) {
|
|
152
|
+
return err(
|
|
153
|
+
new ManagedBufferOutOfBoundsError(byteLength, SIZE_CLASSES[SIZE_CLASSES.length - 1] ?? 0),
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
const bucketBytes = SIZE_CLASSES[idx];
|
|
157
|
+
/* istanbul ignore next -- bucketIndex returns < SIZE_CLASSES.length here */
|
|
158
|
+
if (bucketBytes === undefined) {
|
|
159
|
+
return err(new ManagedBufferOutOfBoundsError(byteLength, 0));
|
|
160
|
+
}
|
|
161
|
+
// Free-list reuse path: pop the most recently released slot of this bucket.
|
|
162
|
+
const free = this.freeBuckets[idx];
|
|
163
|
+
if (free !== undefined && free.length > 0) {
|
|
164
|
+
const id = free.pop() as number;
|
|
165
|
+
const slot = this.slots.get(id);
|
|
166
|
+
/* istanbul ignore next -- freeBuckets only carries ids that exist in slots */
|
|
167
|
+
if (slot === undefined) {
|
|
168
|
+
return err(new ManagedBufferOutOfBoundsError(byteLength, 0));
|
|
169
|
+
}
|
|
170
|
+
// Re-slice the parked buffer to the new logical length; bucket buffer
|
|
171
|
+
// is reused as-is (D-7 no realloc on release).
|
|
172
|
+
slot.byteLength = byteLength;
|
|
173
|
+
slot.view = new Uint8Array(slot.buffer, 0, byteLength);
|
|
174
|
+
slot.live = true;
|
|
175
|
+
// Defensively clear bytes so AI users never see stale data from the
|
|
176
|
+
// prior tenant of the slot.
|
|
177
|
+
new Uint8Array(slot.buffer).fill(0);
|
|
178
|
+
return ok({ id, view: slot.view });
|
|
179
|
+
}
|
|
180
|
+
// Fresh allocation: bucket bytes (rounded up) -> sliced view of byteLength.
|
|
181
|
+
const id = this.nextId++;
|
|
182
|
+
const buffer = new ArrayBuffer(bucketBytes);
|
|
183
|
+
const view = new Uint8Array(buffer, 0, byteLength);
|
|
184
|
+
this.slots.set(id, {
|
|
185
|
+
sizeClassIdx: idx,
|
|
186
|
+
buffer,
|
|
187
|
+
view,
|
|
188
|
+
byteLength,
|
|
189
|
+
live: true,
|
|
190
|
+
});
|
|
191
|
+
return ok({ id, view });
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Grow slot `id` to `newBytes`. Returns the post-grow Uint8Array view.
|
|
196
|
+
*
|
|
197
|
+
* Routes (D-6 / D-7):
|
|
198
|
+
* - newBytes < current -> err(managed-buffer-shrink-not-supported).
|
|
199
|
+
* - newBytes == current -> ok(current view) (no-op, identity preserved).
|
|
200
|
+
* - newBytes > current && same bucket -> ok(re-sliced view) (no transfer).
|
|
201
|
+
* - newBytes > current && cross bucket -> ok(new view) backed by a fresh
|
|
202
|
+
* bucket buffer; the prior ArrayBuffer is detached via transfer (ES2024)
|
|
203
|
+
* or replaced via allocate-and-copy fallback. Old `view`s captured by
|
|
204
|
+
* the caller become detached / orphaned - callers must use `pool.view(id)`
|
|
205
|
+
* after grow to read the refreshed view (the `release` loop refreshes
|
|
206
|
+
* automatically).
|
|
207
|
+
* - newBytes > 262144 -> err(managed-buffer-out-of-bounds).
|
|
208
|
+
*/
|
|
209
|
+
grow(
|
|
210
|
+
id: number,
|
|
211
|
+
newBytes: number,
|
|
212
|
+
): Result<Uint8Array, ManagedBufferShrinkNotSupportedError | ManagedBufferOutOfBoundsError> {
|
|
213
|
+
const slot = this.slots.get(id);
|
|
214
|
+
if (slot === undefined) {
|
|
215
|
+
// Treat unknown id as out-of-bounds against a 0-byte slot (closes the
|
|
216
|
+
// surface; AI users hit this only on use-after-release of a slot id).
|
|
217
|
+
return err(new ManagedBufferOutOfBoundsError(newBytes, 0));
|
|
218
|
+
}
|
|
219
|
+
if (newBytes < slot.byteLength) {
|
|
220
|
+
return err(new ManagedBufferShrinkNotSupportedError(newBytes, slot.byteLength));
|
|
221
|
+
}
|
|
222
|
+
if (newBytes === slot.byteLength) {
|
|
223
|
+
return ok(slot.view);
|
|
224
|
+
}
|
|
225
|
+
const newIdx = bucketIndex(newBytes);
|
|
226
|
+
if (newIdx === SIZE_CLASSES.length) {
|
|
227
|
+
return err(
|
|
228
|
+
new ManagedBufferOutOfBoundsError(newBytes, SIZE_CLASSES[SIZE_CLASSES.length - 1] ?? 0),
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
if (newIdx === slot.sizeClassIdx) {
|
|
232
|
+
// Same bucket: re-slice the existing backing ArrayBuffer to the new
|
|
233
|
+
// logical length. No transfer; old view stays valid until next grow.
|
|
234
|
+
slot.byteLength = newBytes;
|
|
235
|
+
slot.view = new Uint8Array(slot.buffer, 0, newBytes);
|
|
236
|
+
return ok(slot.view);
|
|
237
|
+
}
|
|
238
|
+
// Cross-bucket: detach old buffer + carry old bytes into the new bucket.
|
|
239
|
+
const newBucketBytes = SIZE_CLASSES[newIdx] as number;
|
|
240
|
+
const oldByteLength = slot.byteLength;
|
|
241
|
+
let nextBuffer: ArrayBuffer;
|
|
242
|
+
if (HAS_TRANSFER) {
|
|
243
|
+
// ES2024 transfer: copy contents into a fresh ArrayBuffer of the new
|
|
244
|
+
// bucket size and detach the source. The transferred buffer keeps the
|
|
245
|
+
// old prefix bytes intact.
|
|
246
|
+
nextBuffer = (
|
|
247
|
+
slot.buffer as unknown as { transfer(newByteLength: number): ArrayBuffer }
|
|
248
|
+
).transfer(newBucketBytes);
|
|
249
|
+
} /* istanbul ignore next -- fallback only on runtimes without ES2024 transfer() */ else {
|
|
250
|
+
nextBuffer = new ArrayBuffer(newBucketBytes);
|
|
251
|
+
new Uint8Array(nextBuffer).set(new Uint8Array(slot.buffer, 0, oldByteLength));
|
|
252
|
+
}
|
|
253
|
+
slot.sizeClassIdx = newIdx;
|
|
254
|
+
slot.buffer = nextBuffer;
|
|
255
|
+
slot.byteLength = newBytes;
|
|
256
|
+
slot.view = new Uint8Array(nextBuffer, 0, newBytes);
|
|
257
|
+
return ok(slot.view);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Release slot `id` back to its bucket's free-list. Releasing an unknown id
|
|
262
|
+
* is a no-op - World's release loop drives this and idempotency keeps the
|
|
263
|
+
* despawn chain free of bookkeeping noise. Bucket free-lists are NEVER
|
|
264
|
+
* trimmed in v1 (D-7 no trim).
|
|
265
|
+
*/
|
|
266
|
+
release(id: number): Result<void, never> {
|
|
267
|
+
const slot = this.slots.get(id);
|
|
268
|
+
if (slot === undefined) return ok(undefined);
|
|
269
|
+
if (!slot.live) return ok(undefined);
|
|
270
|
+
slot.live = false;
|
|
271
|
+
if (slot.sizeClassIdx >= 0) {
|
|
272
|
+
const bucket = this.freeBuckets[slot.sizeClassIdx];
|
|
273
|
+
if (bucket !== undefined) bucket.push(id);
|
|
274
|
+
} else {
|
|
275
|
+
// Zero-length slot: nothing to park; drop the slot record entirely so
|
|
276
|
+
// the id is not retained.
|
|
277
|
+
this.slots.delete(id);
|
|
278
|
+
}
|
|
279
|
+
return ok(undefined);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Return the live view for slot `id`. Used by World after `grow` to
|
|
284
|
+
* refresh the column's stored view reference. Returns a zero-length view
|
|
285
|
+
* for unknown / released ids so callers never crash on use-after-release.
|
|
286
|
+
*/
|
|
287
|
+
view(id: number): Uint8Array {
|
|
288
|
+
const slot = this.slots.get(id);
|
|
289
|
+
if (slot === undefined || !slot.live) return new Uint8Array(0);
|
|
290
|
+
return slot.view;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Return the bucket-rounded byte capacity for slot `id` --- i.e.
|
|
295
|
+
* `SIZE_CLASSES[slot.sizeClassIdx]`. Used by managed-buffer view callers
|
|
296
|
+
* (D-4 no-cache: re-queried per accessor). Returns `0` for the zero-length
|
|
297
|
+
* (`alloc(0)`) slot; returns `0` for unknown / released ids (mirrors
|
|
298
|
+
* `view(id)` use-after-release semantics).
|
|
299
|
+
*/
|
|
300
|
+
byteCapacity(id: number): number {
|
|
301
|
+
const slot = this.slots.get(id);
|
|
302
|
+
if (slot === undefined || !slot.live) return 0;
|
|
303
|
+
if (slot.sizeClassIdx < 0) return 0;
|
|
304
|
+
return SIZE_CLASSES[slot.sizeClassIdx] ?? 0;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Reset the logical byteLength of slot `id` to `newByteLength` while
|
|
309
|
+
* keeping the same bucket allocation (no transfer, no release). Only
|
|
310
|
+
* legal when `newByteLength <= bucketBytes`; the slot's bucket index
|
|
311
|
+
* does not move (D-7 v1 forbids cross-bucket shrink). Used by managed-
|
|
312
|
+
* buffer clear paths so the slot retains its `byteCapacity` while the
|
|
313
|
+
* live view becomes zero-length. Bytes past the new logical length are
|
|
314
|
+
* zero-filled defensively.
|
|
315
|
+
*
|
|
316
|
+
* Returns `err(ManagedBufferShrinkNotSupportedError)` when called on a
|
|
317
|
+
* `sizeClassIdx === -1` slot (alloc(0)) with `newByteLength > 0`, or
|
|
318
|
+
* when `newByteLength` exceeds the bucket capacity.
|
|
319
|
+
*/
|
|
320
|
+
setLogicalLength(
|
|
321
|
+
id: number,
|
|
322
|
+
newByteLength: number,
|
|
323
|
+
): Result<Uint8Array, ManagedBufferShrinkNotSupportedError | ManagedBufferOutOfBoundsError> {
|
|
324
|
+
const slot = this.slots.get(id);
|
|
325
|
+
if (slot === undefined) {
|
|
326
|
+
return err(new ManagedBufferOutOfBoundsError(newByteLength, 0));
|
|
327
|
+
}
|
|
328
|
+
if (slot.sizeClassIdx < 0) {
|
|
329
|
+
// alloc(0) slot has no bucket; only newByteLength === 0 is legal.
|
|
330
|
+
if (newByteLength === 0) {
|
|
331
|
+
slot.byteLength = 0;
|
|
332
|
+
slot.view = new Uint8Array(slot.buffer);
|
|
333
|
+
return ok(slot.view);
|
|
334
|
+
}
|
|
335
|
+
return err(new ManagedBufferOutOfBoundsError(newByteLength, 0));
|
|
336
|
+
}
|
|
337
|
+
const bucketBytes = SIZE_CLASSES[slot.sizeClassIdx] ?? 0;
|
|
338
|
+
if (newByteLength > bucketBytes) {
|
|
339
|
+
return err(new ManagedBufferOutOfBoundsError(newByteLength, bucketBytes));
|
|
340
|
+
}
|
|
341
|
+
// Zero-fill the prefix bytes that fall past the new logical length so
|
|
342
|
+
// AI users never see stale tail bytes through a future grow.
|
|
343
|
+
if (newByteLength < slot.byteLength) {
|
|
344
|
+
new Uint8Array(slot.buffer, newByteLength, slot.byteLength - newByteLength).fill(0);
|
|
345
|
+
}
|
|
346
|
+
slot.byteLength = newByteLength;
|
|
347
|
+
slot.view = new Uint8Array(slot.buffer, 0, newByteLength);
|
|
348
|
+
return ok(slot.view);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** @internal Diagnostic count of live slots. Exposed for tests + inspector. */
|
|
352
|
+
_liveCount(): number {
|
|
353
|
+
let n = 0;
|
|
354
|
+
for (const s of this.slots.values()) if (s.live) n += 1;
|
|
355
|
+
return n;
|
|
356
|
+
}
|
|
357
|
+
}
|