@oasys/oecs 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +12 -4
  3. package/dist/core/ecs/ecs_memory.d.cts +6 -6
  4. package/dist/core/ecs/ecs_memory.d.ts +6 -6
  5. package/dist/core/ecs/ecs_memory.d.ts.map +1 -1
  6. package/dist/core/store/allocator.d.cts +44 -19
  7. package/dist/core/store/allocator.d.ts +44 -19
  8. package/dist/core/store/allocator.d.ts.map +1 -1
  9. package/dist/core/store/column_store.d.cts +1 -1
  10. package/dist/core/store/column_store.d.ts +1 -1
  11. package/dist/core/store/extend.d.ts.map +1 -1
  12. package/dist/core/store/grow.d.ts.map +1 -1
  13. package/dist/core/store/layout_ops.d.cts +18 -0
  14. package/dist/core/store/layout_ops.d.ts +18 -0
  15. package/dist/core/store/layout_ops.d.ts.map +1 -1
  16. package/dist/dev_flag.d.ts.map +1 -1
  17. package/dist/extensions/editor/index.development.cjs +1 -0
  18. package/dist/extensions/editor/index.development.js +239 -0
  19. package/dist/extensions/reactive/index.development.cjs +1 -0
  20. package/dist/extensions/reactive/index.development.js +215 -0
  21. package/dist/extensions/solid/index.development.cjs +1 -0
  22. package/dist/extensions/solid/index.development.js +40 -0
  23. package/dist/{host_commands-BI8pEmjH.js → host_commands-3jyFfWNg.js} +2 -2
  24. package/dist/{host_commands-CxhpzMx9.cjs → host_commands-DNf0f6ko.cjs} +1 -1
  25. package/dist/index.cjs +1 -1
  26. package/dist/index.d.cts +1 -1
  27. package/dist/index.d.ts +1 -1
  28. package/dist/index.development.cjs +1 -0
  29. package/dist/index.development.js +8119 -0
  30. package/dist/index.js +195 -192
  31. package/dist/internal-C9jjL90H.js +2485 -0
  32. package/dist/internal-RZN14uMw.cjs +2 -0
  33. package/dist/internal.cjs +1 -1
  34. package/dist/internal.development.cjs +1 -0
  35. package/dist/internal.development.js +24 -0
  36. package/dist/internal.js +1 -1
  37. package/dist/interop-DqxleBo7.js +18 -0
  38. package/dist/interop-T1HZ-Dpa.cjs +1 -0
  39. package/dist/kernel-Cz2Kxlwl.js +240 -0
  40. package/dist/kernel-sw7ScKWu.cjs +1 -0
  41. package/dist/primitives.development.cjs +1 -0
  42. package/dist/primitives.development.js +45 -0
  43. package/dist/reactive/index.development.cjs +1 -0
  44. package/dist/reactive/index.development.js +18 -0
  45. package/dist/shallow-9S1pY_Iw.js +159 -0
  46. package/dist/shallow-C5YmTbtb.cjs +1 -0
  47. package/dist/shared-BMXh9hxm.cjs +1 -0
  48. package/dist/{shared-BU1Cd40h.js → shared-DQKK0i-E.js} +38 -32
  49. package/dist/shared.cjs +1 -1
  50. package/dist/shared.d.cts +1 -1
  51. package/dist/shared.d.ts +1 -1
  52. package/dist/shared.development.cjs +1 -0
  53. package/dist/shared.development.js +7 -0
  54. package/dist/shared.js +1 -1
  55. package/dist/version.d.cts +1 -1
  56. package/dist/version.d.ts +1 -1
  57. package/package.json +31 -2
  58. package/dist/shared-BymrGTyR.cjs +0 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,58 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.3] — 2026-07-09
9
+
10
+ ### Fixed — heap columns back on V8's fast element-access path (~5× iteration)
11
+
12
+ - The pure-TS **heap profile** (`heapArraybufferAllocator` — the default backing)
13
+ now reserves its store as a **fixed, non-resizable `ArrayBuffer`** at the full
14
+ cap instead of a growable one resized via `.resize()`. V8 has no fast
15
+ element-access path for TypedArray views over a **resizable/growable**
16
+ `ArrayBuffer` — every `col[i]` re-checks the mutable length — so iterating a
17
+ column was ~4× slower than over a fixed buffer (measured on V8 13.6, an
18
+ isolated `col[i] *= 2` loop: ~0.37G vs ~1.6G element-accesses/s). This
19
+ silently regressed every iteration-bound system ~5× from 0.3.x (a
20
+ cross-library bench had oecs at ~85k op/s on the `packed_5` scenario vs
21
+ ~407k at 0.3.1); 0.5.3 restores it (~420k, measured against 0.5.2 in a
22
+ same-toolchain A/B: 85.9k → 422.7k op/s).
23
+ - The fixed buffer faults pages in lazily, so RSS tracks real use, not the
24
+ reservation (a 256 MiB default cap on a 1000-entity world stays a few MiB
25
+ resident — measured ~4 MiB RSS, within ~1 MiB of the old resizable buffer).
26
+ Growth remains in place: the store relocates columns within the pre-reserved
27
+ buffer, so the buffer identity never changes and every existing view stays
28
+ valid —
29
+ `isInPlace: true` and ADR-0008's entity-index-hoist-across-grow invariant hold
30
+ unchanged. The store keys its tail cursor off the header `capacity` (the
31
+ logical high-water) rather than `buffer.byteLength` (now always the cap).
32
+ - Only the heap backing changed. The `growable_sab` / `wasm_memory` backings
33
+ keep their resizable buffers and page-rounded tail layout byte-for-byte
34
+ (their determinism/layout goldens are unchanged).
35
+
36
+ ## [0.5.2] — 2026-07-08
37
+
38
+ ### Added — a guards-on build and an explicit dev entry
39
+
40
+ - **`@oasys/oecs/dev`** — the same public API as `@oasys/oecs` with the `__DEV__`
41
+ guards left **on**, for a direct guards-on import (browser/CDN, quick debugging,
42
+ or bundlers that don't auto-select conditions).
43
+ - **`development` export condition** — dev-mode bundlers (`vite dev`,
44
+ `webpack --mode development`) now resolve `@oasys/oecs` (and every subpath) to a
45
+ guards-on build automatically; production-mode builds resolve to the stripped
46
+ build as before.
47
+ - npm now ships a **dual build** (`scripts/build.mjs`): the default `*.js`/`*.cjs`
48
+ are the stripped production artifacts (unchanged), alongside new guards-on
49
+ `*.development.js`/`*.development.cjs`.
50
+ - New guide: [Development guards & production builds](docs/PRODUCTION.md).
51
+
52
+ ### Changed — dev-guard default is now production on JSR/Deno
53
+
54
+ - Raw-source (JSR/Deno) consumers now default to `__DEV__ = false` (**production —
55
+ guards off, no per-frame tax**), matching npm's default. Previously the raw path
56
+ defaulted to guards-on. To enable the guards while developing on Deno, set
57
+ `globalThis.__DEV__ = true` **before the first import**. The `globalThis.__DEV__`
58
+ override is unchanged; only the default flipped. (`dev_flag.ts`)
59
+
8
60
  ## [0.5.1] — 2026-07-06
9
61
 
10
62
  ### Changed (breaking) — one attach grammar
package/README.md CHANGED
@@ -168,7 +168,8 @@ The core is `@oasys/oecs`; everything else is opt-in and costs nothing until imp
168
168
 
169
169
  | Import | What it is |
170
170
  | --- | --- |
171
- | `@oasys/oecs` | the ECS — pure-TS heap profile by default |
171
+ | `@oasys/oecs` | the ECS — pure-TS heap profile by default (production build; dev guards stripped) |
172
+ | `@oasys/oecs/dev` | the same ECS with the dev guards **on** — for a direct guards-on import; see [Dev vs prod](#dev-vs-prod) |
172
173
  | `@oasys/oecs/shared` | opt-in `SharedArrayBuffer` allocators for worker offload / a WASM backend (needs COOP/COEP) |
173
174
  | `@oasys/oecs/reactive` | zero-dependency reactive kernel (`signal`/`computed`/`effect`, reactive collections) |
174
175
  | `@oasys/oecs/reactive-sync` | ECS→reactive bridge — publishes only dirty entities/columns |
@@ -182,9 +183,16 @@ The core is `@oasys/oecs`; everything else is opt-in and costs nothing until imp
182
183
  A compile-time `__DEV__` flag gates every runtime check — bounds and liveness checks, duplicate-system
183
184
  detection, registration validation, and the system access checker (`reads`/`writes`). These are
184
185
  **tree-shaken out of production builds**, so treat "throws in dev" as a development tripwire, not a
185
- production guarantee. (Raw-source consumers JSR/Deno get `__DEV__ = true` by default; set
186
- `globalThis.__DEV__ = false` to opt out.) The scheduler's cycle detection and constructor-option
187
- validation (timestep, memory options, relation cardinality) are always active.
186
+ production guarantee. The scheduler's cycle detection and constructor-option validation (timestep,
187
+ memory options, relation cardinality) are always active.
188
+
189
+ **Production is the default on both channels; you opt *into* the guards.** On **npm**, `@oasys/oecs`
190
+ is the stripped production build — dev-mode bundlers (`vite dev`, `webpack --mode development`) pick
191
+ the guards-on build automatically via the `development` export condition, or import `@oasys/oecs/dev`
192
+ for it directly. On **JSR/Deno** (raw source, no bundler) the default is also production
193
+ (`__DEV__ = false`); set `globalThis.__DEV__ = true` before the first import to turn the guards on
194
+ while developing. Full details — including the browser/CDN and manual-override paths — are in the
195
+ [**Development guards & production builds**](docs/PRODUCTION.md) guide.
188
196
 
189
197
  ## Documentation
190
198
 
@@ -43,12 +43,12 @@ export type WasmMemoryArm = {
43
43
  readonly initialPages?: number;
44
44
  readonly memory?: never;
45
45
  };
46
- /** Pure-TS **heap** backing (#643 / ADR-0018 §1B): a plain resizable
47
- * `ArrayBuffer` instead of a `SharedArrayBuffer`. Needs no cross-origin
48
- * isolation (COOP/COEP) and is the intended default for embedders that can't
49
- * set those headers (the oecs profile). Trade-off: no worker offload and no
50
- * WASM compute backend — both require a transferable `SharedArrayBuffer`. An
51
- * empty `{}` takes the default 256 MiB growable cap. */
46
+ /** Pure-TS **heap** backing (#643 / ADR-0018 §1B): a plain fixed (non-resizable)
47
+ * `ArrayBuffer` reserved at the cap up front, instead of a `SharedArrayBuffer`.
48
+ * Needs no cross-origin isolation (COOP/COEP) and is the intended default for
49
+ * embedders that can't set those headers (the oecs profile). Trade-off: no
50
+ * worker offload and no WASM compute backend — both require a transferable
51
+ * `SharedArrayBuffer`. An empty `{}` takes the default 256 MiB cap. */
52
52
  export interface HeapMemoryArm {
53
53
  /** Byte ceiling of the growable heap backing. Default
54
54
  * `DEFAULT_ECS_CAP_BYTES` (256 MiB), same hard-ceiling semantics as the
@@ -43,12 +43,12 @@ export type WasmMemoryArm = {
43
43
  readonly initialPages?: number;
44
44
  readonly memory?: never;
45
45
  };
46
- /** Pure-TS **heap** backing (#643 / ADR-0018 §1B): a plain resizable
47
- * `ArrayBuffer` instead of a `SharedArrayBuffer`. Needs no cross-origin
48
- * isolation (COOP/COEP) and is the intended default for embedders that can't
49
- * set those headers (the oecs profile). Trade-off: no worker offload and no
50
- * WASM compute backend — both require a transferable `SharedArrayBuffer`. An
51
- * empty `{}` takes the default 256 MiB growable cap. */
46
+ /** Pure-TS **heap** backing (#643 / ADR-0018 §1B): a plain fixed (non-resizable)
47
+ * `ArrayBuffer` reserved at the cap up front, instead of a `SharedArrayBuffer`.
48
+ * Needs no cross-origin isolation (COOP/COEP) and is the intended default for
49
+ * embedders that can't set those headers (the oecs profile). Trade-off: no
50
+ * worker offload and no WASM compute backend — both require a transferable
51
+ * `SharedArrayBuffer`. An empty `{}` takes the default 256 MiB cap. */
52
52
  export interface HeapMemoryArm {
53
53
  /** Byte ceiling of the growable heap backing. Default
54
54
  * `DEFAULT_ECS_CAP_BYTES` (256 MiB), same hard-ceiling semantics as the
@@ -1 +1 @@
1
- {"version":3,"file":"ecs_memory.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/ecs_memory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ecs_memory.d.ts","sourceRoot":"","sources":["../../../src/core/ecs/ecs_memory.ts"],"names":[],"mappings":"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"}
@@ -58,10 +58,11 @@ export interface BufferAllocator {
58
58
  /** Returns a buffer of byteLength >= `bytes`. The historical name is
59
59
  * "SAB", but the return is `ArrayBufferLike`: `growableSabAllocator` /
60
60
  * `wasmMemoryAllocator` produce a `SharedArrayBuffer` (the SAB profile),
61
- * while `heapArraybufferAllocator` produces a plain resizable
62
- * `ArrayBuffer` (the pure-TS heap profile — no cross-origin isolation
63
- * required). The store layer treats the backing uniformly; only the
64
- * WASM/worker boundary narrows back to `SharedArrayBuffer`. */
61
+ * while `heapArraybufferAllocator` produces a plain fixed (non-resizable)
62
+ * `ArrayBuffer` reserved at the cap (the pure-TS heap profile — no
63
+ * cross-origin isolation required). The store layer treats the backing
64
+ * uniformly; only the WASM/worker boundary narrows back to
65
+ * `SharedArrayBuffer`. */
65
66
  (bytes: number): ArrayBufferLike;
66
67
  readonly isInPlace?: boolean;
67
68
  }
@@ -74,9 +75,11 @@ export interface BufferAllocator {
74
75
  * return it; `DEFAULT_SAB_ALLOCATOR` keeps the wide `BufferAllocator` type and
75
76
  * therefore cannot typecheck where a live-Store backing is required. Non-in-place
76
77
  * allocators remain valid for snapshot/test sizing only. The brand says nothing
77
- * about *shared* vs *heap* backing — `heapArraybufferAllocator`'s resizable
78
- * `ArrayBuffer` is just as in-place as a growable SAB (`.resize()` preserves
79
- * existing views exactly like `SharedArrayBuffer.prototype.grow`).
78
+ * about *shared* vs *heap* backing — `heapArraybufferAllocator`'s fixed
79
+ * `ArrayBuffer` is just as in-place as a growable SAB: it is reserved at the full
80
+ * cap up front and never moves, so grow/extend relocate columns *within* it
81
+ * (`copyWithin`) rather than resizing the buffer — existing views stay valid, the
82
+ * same guarantee `SharedArrayBuffer.prototype.grow` gives by resizing in place.
80
83
  */
81
84
  export type InPlaceBufferAllocator = BufferAllocator & {
82
85
  readonly isInPlace: true;
@@ -177,20 +180,42 @@ export declare const DEFAULT_SAB_ALLOCATOR: BufferAllocator;
177
180
  */
178
181
  export declare function growableSabAllocator(maxBytes?: number): InPlaceBufferAllocator;
179
182
  /**
180
- * Allocator that backs the store by a single growable **plain `ArrayBuffer`**
181
- * (created with `{ maxByteLength: maxBytes }`, grown via `.resize()`). This is
182
- * the pure-TS **heap profile** — the oecs default and the answer to ADR-0018's
183
+ * Allocator that backs the store by a single **fixed (non-resizable) plain
184
+ * `ArrayBuffer`** reserved at the full `maxBytes` cap up front. This is the
185
+ * pure-TS **heap profile** — the oecs default and the answer to ADR-0018's
183
186
  * deferred §1B: no `SharedArrayBuffer`, hence no cross-origin isolation
184
187
  * (COOP/COEP) requirement, and no worker/WASM transfer (single-process worlds
185
- * only). Otherwise identical to `growableSabAllocator`:
186
- *
187
- * - `isInPlace: true`. A resizable `ArrayBuffer`'s `.resize()` keeps the
188
- * same buffer object and preserves existing TypedArray/DataView views, so
189
- * the store's `extend`/`grow` fast path carries column views forward
190
- * unchanged exactly as `SharedArrayBuffer.prototype.grow` does. ADR-0008's
191
- * entity-index-hoist-across-grow invariant holds identically.
192
- * - same 256 MiB default cap with hard-ceiling semantics (#380): reaching it
193
- * signals runaway growth upstream, not a limit to route around.
188
+ * only).
189
+ *
190
+ * WHY FIXED, NOT RESIZABLE (the 0.5.3 iteration-perf fix): V8 has no fast
191
+ * element-access path for TypedArray views over a **resizable/growable**
192
+ * `ArrayBuffer` — every `col[i]` re-checks bounds against the buffer's mutable
193
+ * length, a ~4× per-element tax measured on V8 13.6 (an isolated `col[i] *= 2`
194
+ * loop: fixed `ArrayBuffer` ~1.6G vs a view over a resizable buffer ~0.37G
195
+ * element-accesses/s). oecs 0.3.x gave each column its own fixed buffer and sat
196
+ * mid-pack among SoA ECS libs; the 0.5.0 switch to one resizable arena silently
197
+ * regressed all iteration-bound systems ~5× (the cross-library `packed_5`
198
+ * scenario: 0.5.2 ~86k op/s → 0.5.3 ~420k). A fixed buffer restores the fast path.
199
+ *
200
+ * How growth still works in place: the cap is reserved as one fixed buffer at
201
+ * construction. A resizable buffer was originally chosen so `.resize()` could
202
+ * grow in place without moving views; a fixed buffer never moves EITHER — the
203
+ * store's grow/extend relocate columns to the tail *within* this buffer
204
+ * (`copyWithin`), so the buffer object and every existing view stay valid.
205
+ * `isInPlace: true` therefore still holds, and ADR-0008's
206
+ * entity-index-hoist-across-grow invariant is preserved. The store keys its
207
+ * tail cursor off the header `capacity` (the logical high-water), NOT
208
+ * `buffer.byteLength` — which is now always `maxBytes` (the same decoupling the
209
+ * wasm page-rounded allocator already relied on).
210
+ *
211
+ * - Memory cost is unchanged: a fixed `ArrayBuffer(maxBytes)` faults pages in
212
+ * lazily (untouched pages cost no RSS), exactly like the resizable buffer's
213
+ * `maxByteLength` reservation — a 256 MiB reservation on a 1000-entity world
214
+ * stays a few MiB resident (measured ~4 MiB RSS, within ~1 MiB of the old
215
+ * resizable buffer).
216
+ * - same 256 MiB default cap with hard-ceiling semantics (#380): a request
217
+ * past `maxBytes` throws `StoreCapExceededError` — runaway growth signal,
218
+ * not a limit to route around.
194
219
  *
195
220
  * Why a non-shared buffer suffices: `Atomics` live only on the cross-thread
196
221
  * command/event/action rings, never on the core store path, so a single-process
@@ -58,10 +58,11 @@ export interface BufferAllocator {
58
58
  /** Returns a buffer of byteLength >= `bytes`. The historical name is
59
59
  * "SAB", but the return is `ArrayBufferLike`: `growableSabAllocator` /
60
60
  * `wasmMemoryAllocator` produce a `SharedArrayBuffer` (the SAB profile),
61
- * while `heapArraybufferAllocator` produces a plain resizable
62
- * `ArrayBuffer` (the pure-TS heap profile — no cross-origin isolation
63
- * required). The store layer treats the backing uniformly; only the
64
- * WASM/worker boundary narrows back to `SharedArrayBuffer`. */
61
+ * while `heapArraybufferAllocator` produces a plain fixed (non-resizable)
62
+ * `ArrayBuffer` reserved at the cap (the pure-TS heap profile — no
63
+ * cross-origin isolation required). The store layer treats the backing
64
+ * uniformly; only the WASM/worker boundary narrows back to
65
+ * `SharedArrayBuffer`. */
65
66
  (bytes: number): ArrayBufferLike;
66
67
  readonly isInPlace?: boolean;
67
68
  }
@@ -74,9 +75,11 @@ export interface BufferAllocator {
74
75
  * return it; `DEFAULT_SAB_ALLOCATOR` keeps the wide `BufferAllocator` type and
75
76
  * therefore cannot typecheck where a live-Store backing is required. Non-in-place
76
77
  * allocators remain valid for snapshot/test sizing only. The brand says nothing
77
- * about *shared* vs *heap* backing — `heapArraybufferAllocator`'s resizable
78
- * `ArrayBuffer` is just as in-place as a growable SAB (`.resize()` preserves
79
- * existing views exactly like `SharedArrayBuffer.prototype.grow`).
78
+ * about *shared* vs *heap* backing — `heapArraybufferAllocator`'s fixed
79
+ * `ArrayBuffer` is just as in-place as a growable SAB: it is reserved at the full
80
+ * cap up front and never moves, so grow/extend relocate columns *within* it
81
+ * (`copyWithin`) rather than resizing the buffer — existing views stay valid, the
82
+ * same guarantee `SharedArrayBuffer.prototype.grow` gives by resizing in place.
80
83
  */
81
84
  export type InPlaceBufferAllocator = BufferAllocator & {
82
85
  readonly isInPlace: true;
@@ -177,20 +180,42 @@ export declare const DEFAULT_SAB_ALLOCATOR: BufferAllocator;
177
180
  */
178
181
  export declare function growableSabAllocator(maxBytes?: number): InPlaceBufferAllocator;
179
182
  /**
180
- * Allocator that backs the store by a single growable **plain `ArrayBuffer`**
181
- * (created with `{ maxByteLength: maxBytes }`, grown via `.resize()`). This is
182
- * the pure-TS **heap profile** — the oecs default and the answer to ADR-0018's
183
+ * Allocator that backs the store by a single **fixed (non-resizable) plain
184
+ * `ArrayBuffer`** reserved at the full `maxBytes` cap up front. This is the
185
+ * pure-TS **heap profile** — the oecs default and the answer to ADR-0018's
183
186
  * deferred §1B: no `SharedArrayBuffer`, hence no cross-origin isolation
184
187
  * (COOP/COEP) requirement, and no worker/WASM transfer (single-process worlds
185
- * only). Otherwise identical to `growableSabAllocator`:
186
- *
187
- * - `isInPlace: true`. A resizable `ArrayBuffer`'s `.resize()` keeps the
188
- * same buffer object and preserves existing TypedArray/DataView views, so
189
- * the store's `extend`/`grow` fast path carries column views forward
190
- * unchanged exactly as `SharedArrayBuffer.prototype.grow` does. ADR-0008's
191
- * entity-index-hoist-across-grow invariant holds identically.
192
- * - same 256 MiB default cap with hard-ceiling semantics (#380): reaching it
193
- * signals runaway growth upstream, not a limit to route around.
188
+ * only).
189
+ *
190
+ * WHY FIXED, NOT RESIZABLE (the 0.5.3 iteration-perf fix): V8 has no fast
191
+ * element-access path for TypedArray views over a **resizable/growable**
192
+ * `ArrayBuffer` — every `col[i]` re-checks bounds against the buffer's mutable
193
+ * length, a ~4× per-element tax measured on V8 13.6 (an isolated `col[i] *= 2`
194
+ * loop: fixed `ArrayBuffer` ~1.6G vs a view over a resizable buffer ~0.37G
195
+ * element-accesses/s). oecs 0.3.x gave each column its own fixed buffer and sat
196
+ * mid-pack among SoA ECS libs; the 0.5.0 switch to one resizable arena silently
197
+ * regressed all iteration-bound systems ~5× (the cross-library `packed_5`
198
+ * scenario: 0.5.2 ~86k op/s → 0.5.3 ~420k). A fixed buffer restores the fast path.
199
+ *
200
+ * How growth still works in place: the cap is reserved as one fixed buffer at
201
+ * construction. A resizable buffer was originally chosen so `.resize()` could
202
+ * grow in place without moving views; a fixed buffer never moves EITHER — the
203
+ * store's grow/extend relocate columns to the tail *within* this buffer
204
+ * (`copyWithin`), so the buffer object and every existing view stay valid.
205
+ * `isInPlace: true` therefore still holds, and ADR-0008's
206
+ * entity-index-hoist-across-grow invariant is preserved. The store keys its
207
+ * tail cursor off the header `capacity` (the logical high-water), NOT
208
+ * `buffer.byteLength` — which is now always `maxBytes` (the same decoupling the
209
+ * wasm page-rounded allocator already relied on).
210
+ *
211
+ * - Memory cost is unchanged: a fixed `ArrayBuffer(maxBytes)` faults pages in
212
+ * lazily (untouched pages cost no RSS), exactly like the resizable buffer's
213
+ * `maxByteLength` reservation — a 256 MiB reservation on a 1000-entity world
214
+ * stays a few MiB resident (measured ~4 MiB RSS, within ~1 MiB of the old
215
+ * resizable buffer).
216
+ * - same 256 MiB default cap with hard-ceiling semantics (#380): a request
217
+ * past `maxBytes` throws `StoreCapExceededError` — runaway growth signal,
218
+ * not a limit to route around.
194
219
  *
195
220
  * Why a non-shared buffer suffices: `Atomics` live only on the cross-thread
196
221
  * command/event/action rings, never on the core store path, so a single-process
@@ -1 +1 @@
1
- {"version":3,"file":"allocator.d.ts","sourceRoot":"","sources":["../../../src/core/store/allocator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;;;mEAM+D;IAC/D,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,sBAAsB,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CAAE,CAAC;AAEpF;;;;;;;GAOG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;aAG9B,cAAc,EAAE,MAAM;IACtC;6DACyD;aACzC,QAAQ,EAAE,MAAM,GAAG,IAAI;gBAJvC,OAAO,EAAE,MAAM,EACC,cAAc,EAAE,MAAM;IACtC;6DACyD;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvC,OAAO,CAAC,EAAE,YAAY;CAKvB;AAED;;;;;;oEAMoE;AACpE,qBAAa,mBAAoB,SAAQ,KAAK;;CAe7C;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,EAAE,eAGnC,CAAC;AA+DF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,MAA0B,GAAG,sBAAsB,CA6BjG;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB,CACvC,QAAQ,GAAE,MAA0B,GAClC,sBAAsB,CAuBxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,GAAG,sBAAsB,CA6DtF"}
1
+ {"version":3,"file":"allocator.d.ts","sourceRoot":"","sources":["../../../src/core/store/allocator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;;;;8BAO0B;IAC1B,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,sBAAsB,GAAG,eAAe,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;CAAE,CAAC;AAEpF;;;;;;;GAOG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;aAG9B,cAAc,EAAE,MAAM;IACtC;6DACyD;aACzC,QAAQ,EAAE,MAAM,GAAG,IAAI;gBAJvC,OAAO,EAAE,MAAM,EACC,cAAc,EAAE,MAAM;IACtC;6DACyD;IACzC,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvC,OAAO,CAAC,EAAE,YAAY;CAKvB;AAED;;;;;;oEAMoE;AACpE,qBAAa,mBAAoB,SAAQ,KAAK;;CAe7C;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,EAAE,eAGnC,CAAC;AAgEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwDG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,MAA0B,GAAG,sBAAsB,CA6BjG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,wBAAwB,CACvC,QAAQ,GAAE,MAA0B,GAClC,sBAAsB,CAsBxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,GAAG,sBAAsB,CA6DtF"}
@@ -51,7 +51,7 @@ export interface ArchetypeViews {
51
51
  }
52
52
  export interface ColumnStore {
53
53
  /** The backing buffer. `ArrayBufferLike` because the store is backing-agnostic:
54
- * a `SharedArrayBuffer` for the SAB/WASM/worker profile, or a plain resizable
54
+ * a `SharedArrayBuffer` for the SAB/WASM/worker profile, or a plain fixed
55
55
  * `ArrayBuffer` for the pure-TS heap profile (`heapArraybufferAllocator`).
56
56
  * Consumers that genuinely require sharing (worker transfer, WASM memory)
57
57
  * narrow back to `SharedArrayBuffer` at their boundary. */
@@ -51,7 +51,7 @@ export interface ArchetypeViews {
51
51
  }
52
52
  export interface ColumnStore {
53
53
  /** The backing buffer. `ArrayBufferLike` because the store is backing-agnostic:
54
- * a `SharedArrayBuffer` for the SAB/WASM/worker profile, or a plain resizable
54
+ * a `SharedArrayBuffer` for the SAB/WASM/worker profile, or a plain fixed
55
55
  * `ArrayBuffer` for the pure-TS heap profile (`heapArraybufferAllocator`).
56
56
  * Consumers that genuinely require sharing (worker transfer, WASM memory)
57
57
  * narrow back to `SharedArrayBuffer` at their boundary. */
@@ -1 +1 @@
1
- {"version":3,"file":"extend.d.ts","sourceRoot":"","sources":["../../../src/core/store/extend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAEN,KAAK,aAAa,EAElB,KAAK,WAAW,EAGhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAMnD,OAAO,EAIN,KAAK,iBAAiB,EAEtB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,UAAU;IAC1B;gEAC4D;IAC5D,QAAQ,CAAC,aAAa,EAAE,SAAS,aAAa,EAAE,CAAC;IACjD;;oEAEgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;;;2EAKuE;IACvE,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CACjC;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI3B;AAED;;;;;;;;;sCASsC;AACtC,wBAAgB,iBAAiB,CAChC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,UAAU,EAChB,SAAS,CAAC,EAAE,eAAe,GACzB,YAAY,CAoId"}
1
+ {"version":3,"file":"extend.d.ts","sourceRoot":"","sources":["../../../src/core/store/extend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAEN,KAAK,aAAa,EAElB,KAAK,WAAW,EAGhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAMnD,OAAO,EAKN,KAAK,iBAAiB,EAEtB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,UAAU;IAC1B;gEAC4D;IAC5D,QAAQ,CAAC,aAAa,EAAE,SAAS,aAAa,EAAE,CAAC;IACjD;;oEAEgE;IAChE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;;;2EAKuE;IACvE,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CACjC;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI3B;AAED;;;;;;;;;sCASsC;AACtC,wBAAgB,iBAAiB,CAChC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,UAAU,EAChB,SAAS,CAAC,EAAE,eAAe,GACzB,YAAY,CAoId"}
@@ -1 +1 @@
1
- {"version":3,"file":"grow.d.ts","sourceRoot":"","sources":["../../../src/core/store/grow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AASH,OAAO,EAIN,KAAK,WAAW,EAGhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAIN,KAAK,iBAAiB,EAEtB,MAAM,cAAc,CAAC;AAMtB,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAClD;AAED;mEACmE;AACnE,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;6DAGyD;IACzD,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;2BACuB;IACvB,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAyJD,qBAAa,cAAe,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI3B;AAED;;;;;;sEAMsE;AACtE,wBAAgB,eAAe,CAC9B,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,QAAQ,EACd,SAAS,CAAC,EAAE,eAAe,GACzB,UAAU,CAmGZ"}
1
+ {"version":3,"file":"grow.d.ts","sourceRoot":"","sources":["../../../src/core/store/grow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AASH,OAAO,EAIN,KAAK,WAAW,EAGhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAKN,KAAK,iBAAiB,EAEtB,MAAM,cAAc,CAAC;AAMtB,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,QAAQ;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAC;CAClD;AAED;mEACmE;AACnE,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;6DAGyD;IACzD,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC;2BACuB;IACvB,QAAQ,CAAC,iBAAiB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AA4JD,qBAAa,cAAe,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI3B;AAED;;;;;;sEAMsE;AACtE,wBAAgB,eAAe,CAC9B,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,QAAQ,EACd,SAAS,CAAC,EAAE,eAAe,GACzB,UAAU,CAmGZ"}
@@ -50,6 +50,24 @@ export declare function growBufferInPlace(old: ColumnStoreInternal, newTotal: nu
50
50
  grownBuffer: ArrayBufferLike;
51
51
  newView: DataView;
52
52
  };
53
+ /**
54
+ * Byte offset where the next appended column region begins — the tail cursor
55
+ * the in-place grow/extend paths pass to `layoutColumnsAtTail`.
56
+ *
57
+ * For the growable-SAB and wasm backings the buffer is sized to the live extent
58
+ * (`SharedArrayBuffer.grow` resizes exactly; wasm rounds up to a page, and its
59
+ * fast path deliberately lands new regions past that page-rounded tail), so
60
+ * `buffer.byteLength` IS the tail. For the pure-TS **heap** backing (0.5.3) the
61
+ * buffer is a FIXED `ArrayBuffer` reserved at the full cap for V8 fast-path
62
+ * element access, so its `byteLength` is `maxBytes`, NOT the used size — the
63
+ * true tail is the header `capacity` (the logical high-water; new columns land
64
+ * in still-zero fixed-buffer space just past the last live column).
65
+ *
66
+ * A plain (non-shared) `ArrayBuffer` is uniquely the heap profile's fixed
67
+ * reservation — every other in-place backing is a `SharedArrayBuffer`. Keying
68
+ * off the backing keeps the SAB/wasm layouts byte-for-byte unchanged.
69
+ */
70
+ export declare function tailCursorBytes(old: ColumnStoreInternal): number;
53
71
  /**
54
72
  * Derive `CreateColumnStoreOptions` from an old ColumnStore so a slow-path realloc
55
73
  * preserves the same set of optional regions at the same byte offsets in the
@@ -50,6 +50,24 @@ export declare function growBufferInPlace(old: ColumnStoreInternal, newTotal: nu
50
50
  grownBuffer: ArrayBufferLike;
51
51
  newView: DataView;
52
52
  };
53
+ /**
54
+ * Byte offset where the next appended column region begins — the tail cursor
55
+ * the in-place grow/extend paths pass to `layoutColumnsAtTail`.
56
+ *
57
+ * For the growable-SAB and wasm backings the buffer is sized to the live extent
58
+ * (`SharedArrayBuffer.grow` resizes exactly; wasm rounds up to a page, and its
59
+ * fast path deliberately lands new regions past that page-rounded tail), so
60
+ * `buffer.byteLength` IS the tail. For the pure-TS **heap** backing (0.5.3) the
61
+ * buffer is a FIXED `ArrayBuffer` reserved at the full cap for V8 fast-path
62
+ * element access, so its `byteLength` is `maxBytes`, NOT the used size — the
63
+ * true tail is the header `capacity` (the logical high-water; new columns land
64
+ * in still-zero fixed-buffer space just past the last live column).
65
+ *
66
+ * A plain (non-shared) `ArrayBuffer` is uniquely the heap profile's fixed
67
+ * reservation — every other in-place backing is a `SharedArrayBuffer`. Keying
68
+ * off the backing keeps the SAB/wasm layouts byte-for-byte unchanged.
69
+ */
70
+ export declare function tailCursorBytes(old: ColumnStoreInternal): number;
53
71
  /**
54
72
  * Derive `CreateColumnStoreOptions` from an old ColumnStore so a slow-path realloc
55
73
  * preserves the same set of optional regions at the same byte offsets in the
@@ -1 +1 @@
1
- {"version":3,"file":"layout_ops.d.ts","sourceRoot":"","sources":["../../../src/core/store/layout_ops.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"layout_ops.d.ts","sourceRoot":"","sources":["../../../src/core/store/layout_ops.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"dev_flag.d.ts","sourceRoot":"","sources":["../src/dev_flag.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,GAAG,EAAE,OAAyD,CAAC"}
1
+ {"version":3,"file":"dev_flag.d.ts","sourceRoot":"","sources":["../src/dev_flag.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,GAAG,EAAE,OAA0D,CAAC"}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function o(r,t,e){return`${r}:${t.id}:${e}`}const a=new WeakMap;class h{constructor(t,e){this.readField=t,this.shadow=e,a.set(this,{forward:[],inverse:[]})}staged=new Map;get _txn(){return a.get(this)}spawn(t,e){const s={kind:"despawn",eid:0};return this._txn.inverse.push(s),this._txn.forward.push({kind:"spawn",components:t,onSpawned:n=>{s.eid=n,e?.(n)}}),this}despawn(t,e){const s={kind:"despawn",eid:t};return this._txn.forward.push(s),this._txn.inverse.push({kind:"spawn",components:e,onSpawned:n=>{s.eid=n}}),this}setField(t,e,s,n){const i=o(t,e,s),d=this.staged.get(i)??this.shadow.get(i)??this.readField(t,e,s)??0;return this.staged.set(i,n),this._txn.forward.push({kind:"set_field",eid:t,def:e,field:s,value:n}),this._txn.inverse.push({kind:"set_field",eid:t,def:e,field:s,value:d}),this}add(t,e,s){return this._txn.forward.push({kind:"add_component",eid:t,def:e,values:s}),this._txn.inverse.push({kind:"remove_component",eid:t,def:e}),this}remove(t,e,s){return this._txn.forward.push({kind:"remove_component",eid:t,def:e}),this._txn.inverse.push({kind:"add_component",eid:t,def:e,values:s}),this}disable(t){return this._txn.forward.push({kind:"disable",eid:t}),this._txn.inverse.push({kind:"enable",eid:t}),this}enable(t){return this._txn.forward.push({kind:"enable",eid:t}),this._txn.inverse.push({kind:"disable",eid:t}),this}}class u{constructor(t,e){this.queue=t,this.readField=e}undoStack=[];redoStack=[];listeners=[];shadow=new Map;transaction(t){const e=new h(this.readField,this.shadow);return t(e),this.commit(a.get(e))}spawn(t,e){return this.transaction(s=>s.spawn(t,e))}despawn(t,e){return this.transaction(s=>s.despawn(t,e))}setField(t,e,s,n){return this.transaction(i=>i.setField(t,e,s,n))}add(t,e,s){return this.transaction(n=>n.add(t,e,s))}remove(t,e,s){return this.transaction(n=>n.remove(t,e,s))}disable(t){return this.transaction(e=>e.disable(t))}enable(t){return this.transaction(e=>e.enable(t))}undo(){const t=this.undoStack.pop();if(t===void 0)return!1;const e=t.inverse.slice().reverse();for(const s of e)this.queue.push(s);return this.applyShadow(e),this.redoStack.push(t),this.notify(),!0}redo(){const t=this.redoStack.pop();if(t===void 0)return!1;for(const e of t.forward)this.queue.push(e);return this.applyShadow(t.forward),this.undoStack.push(t),this.notify(),!0}clear(){this.undoStack.length=0,this.redoStack.length=0,this.shadow.clear(),this.notify()}depths(){return{undo:this.undoStack.length,redo:this.redoStack.length}}get canUndo(){return this.undoStack.length>0}get canRedo(){return this.redoStack.length>0}onChange(t){return this.listeners.push(t),()=>{const e=this.listeners.indexOf(t);e!==-1&&this.listeners.splice(e,1)}}notify(){for(const t of this.listeners.slice())t()}committedField(t,e,s){return this.readField(t,e,s)}pendingField(t,e,s){const n=o(t,e,s),i=this.shadow.get(n);if(i===void 0)return;const d=this.readField(t,e,s);if(d===i||d===void 0){this.shadow.delete(n);return}return i}commit(t){if(t.forward.length===0)return t;for(const e of t.forward)this.queue.push(e);return this.applyShadow(t.forward),this.undoStack.push(t),this.redoStack.length=0,this.notify(),t}applyShadow(t){for(const e of t)e.kind==="set_field"&&this.shadow.set(o(e.eid,e.def,e.field),e.value)}}function c(r,t,e,s,n){return{get value(){return n!==void 0?n():r.committedField(t,e,s)},set(i){r.setField(t,e,s,i)},get pending(){return r.pendingField(t,e,s)}}}exports.Editor=u;exports.TransactionBuilder=h;exports.fieldHandle=c;