@ecsia/core 0.1.0

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 (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -0
  3. package/dist/bitmask/bitmask.d.ts +21 -0
  4. package/dist/bitmask/bitmask.d.ts.map +1 -0
  5. package/dist/bitmask/bitmask.js +103 -0
  6. package/dist/bitmask/bitmask.js.map +1 -0
  7. package/dist/bitmask/index.d.ts +3 -0
  8. package/dist/bitmask/index.d.ts.map +1 -0
  9. package/dist/bitmask/index.js +2 -0
  10. package/dist/bitmask/index.js.map +1 -0
  11. package/dist/component/accessor.d.ts +40 -0
  12. package/dist/component/accessor.d.ts.map +1 -0
  13. package/dist/component/accessor.js +220 -0
  14. package/dist/component/accessor.js.map +1 -0
  15. package/dist/component/column-set.d.ts +20 -0
  16. package/dist/component/column-set.d.ts.map +1 -0
  17. package/dist/component/column-set.js +60 -0
  18. package/dist/component/column-set.js.map +1 -0
  19. package/dist/component/define.d.ts +23 -0
  20. package/dist/component/define.d.ts.map +1 -0
  21. package/dist/component/define.js +155 -0
  22. package/dist/component/define.js.map +1 -0
  23. package/dist/component/descriptors.d.ts +3 -0
  24. package/dist/component/descriptors.d.ts.map +1 -0
  25. package/dist/component/descriptors.js +147 -0
  26. package/dist/component/descriptors.js.map +1 -0
  27. package/dist/component/index.d.ts +10 -0
  28. package/dist/component/index.d.ts.map +1 -0
  29. package/dist/component/index.js +6 -0
  30. package/dist/component/index.js.map +1 -0
  31. package/dist/component/sidecar.d.ts +58 -0
  32. package/dist/component/sidecar.d.ts.map +1 -0
  33. package/dist/component/sidecar.js +136 -0
  34. package/dist/component/sidecar.js.map +1 -0
  35. package/dist/config.d.ts +55 -0
  36. package/dist/config.d.ts.map +1 -0
  37. package/dist/config.js +70 -0
  38. package/dist/config.js.map +1 -0
  39. package/dist/entity/codec.d.ts +45 -0
  40. package/dist/entity/codec.d.ts.map +1 -0
  41. package/dist/entity/codec.js +53 -0
  42. package/dist/entity/codec.js.map +1 -0
  43. package/dist/entity/index-allocator.d.ts +46 -0
  44. package/dist/entity/index-allocator.d.ts.map +1 -0
  45. package/dist/entity/index-allocator.js +121 -0
  46. package/dist/entity/index-allocator.js.map +1 -0
  47. package/dist/entity/index.d.ts +13 -0
  48. package/dist/entity/index.d.ts.map +1 -0
  49. package/dist/entity/index.js +7 -0
  50. package/dist/entity/index.js.map +1 -0
  51. package/dist/entity/record.d.ts +28 -0
  52. package/dist/entity/record.d.ts.map +1 -0
  53. package/dist/entity/record.js +42 -0
  54. package/dist/entity/record.js.map +1 -0
  55. package/dist/entity/ref.d.ts +70 -0
  56. package/dist/entity/ref.d.ts.map +1 -0
  57. package/dist/entity/ref.js +104 -0
  58. package/dist/entity/ref.js.map +1 -0
  59. package/dist/entity/reservation.d.ts +12 -0
  60. package/dist/entity/reservation.d.ts.map +1 -0
  61. package/dist/entity/reservation.js +28 -0
  62. package/dist/entity/reservation.js.map +1 -0
  63. package/dist/entity/store.d.ts +60 -0
  64. package/dist/entity/store.d.ts.map +1 -0
  65. package/dist/entity/store.js +193 -0
  66. package/dist/entity/store.js.map +1 -0
  67. package/dist/env.d.ts +2 -0
  68. package/dist/env.d.ts.map +1 -0
  69. package/dist/env.js +12 -0
  70. package/dist/env.js.map +1 -0
  71. package/dist/ids.d.ts +9 -0
  72. package/dist/ids.d.ts.map +1 -0
  73. package/dist/ids.js +8 -0
  74. package/dist/ids.js.map +1 -0
  75. package/dist/index.d.ts +29 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +33 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/inspect-surface.d.ts +27 -0
  80. package/dist/inspect-surface.d.ts.map +1 -0
  81. package/dist/inspect-surface.js +14 -0
  82. package/dist/inspect-surface.js.map +1 -0
  83. package/dist/internal.d.ts +19 -0
  84. package/dist/internal.d.ts.map +1 -0
  85. package/dist/internal.js +19 -0
  86. package/dist/internal.js.map +1 -0
  87. package/dist/memory/allocU32.d.ts +25 -0
  88. package/dist/memory/allocU32.d.ts.map +1 -0
  89. package/dist/memory/allocU32.js +95 -0
  90. package/dist/memory/allocU32.js.map +1 -0
  91. package/dist/memory/buffers.d.ts +94 -0
  92. package/dist/memory/buffers.d.ts.map +1 -0
  93. package/dist/memory/buffers.js +308 -0
  94. package/dist/memory/buffers.js.map +1 -0
  95. package/dist/memory/index.d.ts +7 -0
  96. package/dist/memory/index.d.ts.map +1 -0
  97. package/dist/memory/index.js +4 -0
  98. package/dist/memory/index.js.map +1 -0
  99. package/dist/memory/layout.d.ts +37 -0
  100. package/dist/memory/layout.d.ts.map +1 -0
  101. package/dist/memory/layout.js +116 -0
  102. package/dist/memory/layout.js.map +1 -0
  103. package/dist/query/compile.d.ts +73 -0
  104. package/dist/query/compile.d.ts.map +1 -0
  105. package/dist/query/compile.js +158 -0
  106. package/dist/query/compile.js.map +1 -0
  107. package/dist/query/engine.d.ts +48 -0
  108. package/dist/query/engine.d.ts.map +1 -0
  109. package/dist/query/engine.js +230 -0
  110. package/dist/query/engine.js.map +1 -0
  111. package/dist/query/index.d.ts +8 -0
  112. package/dist/query/index.d.ts.map +1 -0
  113. package/dist/query/index.js +10 -0
  114. package/dist/query/index.js.map +1 -0
  115. package/dist/query/live-query.d.ts +122 -0
  116. package/dist/query/live-query.d.ts.map +1 -0
  117. package/dist/query/live-query.js +543 -0
  118. package/dist/query/live-query.js.map +1 -0
  119. package/dist/query/sparse-set.d.ts +18 -0
  120. package/dist/query/sparse-set.d.ts.map +1 -0
  121. package/dist/query/sparse-set.js +126 -0
  122. package/dist/query/sparse-set.js.map +1 -0
  123. package/dist/reactivity/change-version.d.ts +19 -0
  124. package/dist/reactivity/change-version.d.ts.map +1 -0
  125. package/dist/reactivity/change-version.js +76 -0
  126. package/dist/reactivity/change-version.js.map +1 -0
  127. package/dist/reactivity/index.d.ts +12 -0
  128. package/dist/reactivity/index.d.ts.map +1 -0
  129. package/dist/reactivity/index.js +12 -0
  130. package/dist/reactivity/index.js.map +1 -0
  131. package/dist/reactivity/log.d.ts +83 -0
  132. package/dist/reactivity/log.d.ts.map +1 -0
  133. package/dist/reactivity/log.js +260 -0
  134. package/dist/reactivity/log.js.map +1 -0
  135. package/dist/reactivity/observer-commands.d.ts +40 -0
  136. package/dist/reactivity/observer-commands.d.ts.map +1 -0
  137. package/dist/reactivity/observer-commands.js +111 -0
  138. package/dist/reactivity/observer-commands.js.map +1 -0
  139. package/dist/reactivity/observers.d.ts +50 -0
  140. package/dist/reactivity/observers.d.ts.map +1 -0
  141. package/dist/reactivity/observers.js +127 -0
  142. package/dist/reactivity/observers.js.map +1 -0
  143. package/dist/reactivity/reactivity.d.ts +141 -0
  144. package/dist/reactivity/reactivity.d.ts.map +1 -0
  145. package/dist/reactivity/reactivity.js +479 -0
  146. package/dist/reactivity/reactivity.js.map +1 -0
  147. package/dist/reactivity/structural-journal.d.ts +30 -0
  148. package/dist/reactivity/structural-journal.d.ts.map +1 -0
  149. package/dist/reactivity/structural-journal.js +77 -0
  150. package/dist/reactivity/structural-journal.js.map +1 -0
  151. package/dist/registry.d.ts +26 -0
  152. package/dist/registry.d.ts.map +1 -0
  153. package/dist/registry.js +58 -0
  154. package/dist/registry.js.map +1 -0
  155. package/dist/serialize-surface.d.ts +170 -0
  156. package/dist/serialize-surface.d.ts.map +1 -0
  157. package/dist/serialize-surface.js +6 -0
  158. package/dist/serialize-surface.js.map +1 -0
  159. package/dist/storage/archetype.d.ts +38 -0
  160. package/dist/storage/archetype.d.ts.map +1 -0
  161. package/dist/storage/archetype.js +47 -0
  162. package/dist/storage/archetype.js.map +1 -0
  163. package/dist/storage/cold-store.d.ts +41 -0
  164. package/dist/storage/cold-store.d.ts.map +1 -0
  165. package/dist/storage/cold-store.js +100 -0
  166. package/dist/storage/cold-store.js.map +1 -0
  167. package/dist/storage/index.d.ts +10 -0
  168. package/dist/storage/index.d.ts.map +1 -0
  169. package/dist/storage/index.js +5 -0
  170. package/dist/storage/index.js.map +1 -0
  171. package/dist/storage/signature.d.ts +27 -0
  172. package/dist/storage/signature.d.ts.map +1 -0
  173. package/dist/storage/signature.js +115 -0
  174. package/dist/storage/signature.js.map +1 -0
  175. package/dist/storage/storage.d.ts +72 -0
  176. package/dist/storage/storage.d.ts.map +1 -0
  177. package/dist/storage/storage.js +192 -0
  178. package/dist/storage/storage.js.map +1 -0
  179. package/dist/storage/store.d.ts +88 -0
  180. package/dist/storage/store.d.ts.map +1 -0
  181. package/dist/storage/store.js +473 -0
  182. package/dist/storage/store.js.map +1 -0
  183. package/dist/util/stable-index.d.ts +29 -0
  184. package/dist/util/stable-index.d.ts.map +1 -0
  185. package/dist/util/stable-index.js +51 -0
  186. package/dist/util/stable-index.js.map +1 -0
  187. package/dist/world.d.ts +262 -0
  188. package/dist/world.d.ts.map +1 -0
  189. package/dist/world.js +831 -0
  190. package/dist/world.js.map +1 -0
  191. package/package.json +52 -0
@@ -0,0 +1,126 @@
1
+ // The per-query result container: a SAB-capable Uint32Array sparse set storing
2
+ // ENTITY INDICES (not full handles — the index is the stable maintenance key, matching the bitmask
3
+ // and the entity record addressing). O(1) add/remove/has, dense iteration, no duplicates.
4
+ //
5
+ // `dense`/`sparse` are u32 regions allocated through Buffers.region so they are SAB-backed when
6
+ // threaded and length-track on the primary grow path. `current` is read-only to workers (they
7
+ // iterate matchingArchetypes rows), so no atomics on the iteration path. Sizing is lazy: the
8
+ // set grows to the entity-index high-water as entities are added, never eagerly to maxEntities.
9
+ import { isSharedBacking } from '../memory/buffers.js';
10
+ const GROWTH = 2;
11
+ export class SparseSetU32 {
12
+ #dense;
13
+ #sparse;
14
+ #size = 0;
15
+ #capacity;
16
+ #denseRegion;
17
+ #sparseRegion;
18
+ #buffers;
19
+ #maxEntities;
20
+ constructor(buffers, denseKey, sparseKey, initialCapacity, maxEntities) {
21
+ this.#buffers = buffers;
22
+ this.#maxEntities = maxEntities;
23
+ const cap = Math.max(1, Math.min(initialCapacity, maxEntities));
24
+ this.#capacity = cap;
25
+ this.#denseRegion = buffers.region(denseKey, 'u32', cap, { maxLength: maxEntities });
26
+ this.#sparseRegion = buffers.region(sparseKey, 'u32', cap, { maxLength: maxEntities });
27
+ this.#dense = this.#denseRegion.view;
28
+ this.#sparse = this.#sparseRegion.view;
29
+ }
30
+ get size() {
31
+ return this.#size;
32
+ }
33
+ /** sparse[index] points into dense; the slot is valid iff dense[pos] === index AND pos < size. */
34
+ has(index) {
35
+ if (index >= this.#capacity)
36
+ return false;
37
+ const pos = this.#sparse[index];
38
+ return pos < this.#size && this.#dense[pos] === index;
39
+ }
40
+ /** O(1); idempotent (has-guarded so no dup). Grows the addressable space lazily. */
41
+ add(index) {
42
+ if (this.has(index))
43
+ return;
44
+ this.#ensureCapacity(index + 1);
45
+ const pos = this.#size;
46
+ this.#dense[pos] = index;
47
+ this.#sparse[index] = pos;
48
+ this.#size = pos + 1;
49
+ }
50
+ /** O(1) swap-and-pop within dense. No-op if absent. */
51
+ remove(index) {
52
+ if (!this.has(index))
53
+ return;
54
+ const pos = this.#sparse[index];
55
+ const last = this.#size - 1;
56
+ const lastIndex = this.#dense[last];
57
+ this.#dense[pos] = lastIndex;
58
+ this.#sparse[lastIndex] = pos;
59
+ this.#size = last;
60
+ }
61
+ clear() {
62
+ this.#size = 0;
63
+ }
64
+ /** Dense iteration over dense[0..size). Values are entity indices. */
65
+ *[Symbol.iterator]() {
66
+ for (let i = 0; i < this.#size; i++)
67
+ yield this.#dense[i];
68
+ }
69
+ /** A live view of the dense prefix [0..size) — zero-copy; callers must not mutate it. */
70
+ denseView() {
71
+ return this.#dense.subarray(0, this.#size);
72
+ }
73
+ #ensureCapacity(need) {
74
+ if (need <= this.#capacity)
75
+ return;
76
+ let next = this.#capacity;
77
+ while (next < need)
78
+ next = Math.min(this.#maxEntities, next * GROWTH);
79
+ if (next < need)
80
+ next = need;
81
+ // Both regions length-track on the primary path; re-publish the view for the fallback path too.
82
+ growRegion(this.#buffers, this.#denseRegion, next);
83
+ growRegion(this.#buffers, this.#sparseRegion, next);
84
+ this.#dense = this.#denseRegion.view;
85
+ this.#sparse = this.#sparseRegion.view;
86
+ this.#capacity = next;
87
+ }
88
+ }
89
+ // Region growth: Buffers.grow takes a Column; a Region is grown by re-wrapping through the same
90
+ // doubling backing. The region's backing is resizable on the primary path, so we resize in place and
91
+ // re-read the (auto-widening) length-tracking view. On a non-resizable backing we re-allocate + copy.
92
+ function growRegion(buffers, region, newLength) {
93
+ const bytesPerElem = Uint32Array.BYTES_PER_ELEMENT;
94
+ const required = newLength * bytesPerElem;
95
+ if (required <= region.backing.byteLength)
96
+ return;
97
+ const growable = region.backing;
98
+ const resizeFn = growable.grow ?? growable.resize;
99
+ const max = growable.maxByteLength;
100
+ if (typeof resizeFn === 'function' && typeof max === 'number') {
101
+ let target = region.backing.byteLength > 0 ? region.backing.byteLength : required;
102
+ while (target < required)
103
+ target = target * GROWTH;
104
+ target = Math.min(target, max);
105
+ if (target >= required) {
106
+ try {
107
+ resizeFn.call(growable, target);
108
+ region.view = new Uint32Array(region.backing);
109
+ return;
110
+ }
111
+ catch {
112
+ // fall through to the re-allocate path
113
+ }
114
+ }
115
+ }
116
+ // Fallback: re-allocate a fresh backing and copy. Serial-flush only; workers never maintain.
117
+ const isShared = isSharedBacking(region.backing);
118
+ const fresh = isShared
119
+ ? new SharedArrayBuffer(required)
120
+ : new ArrayBuffer(required);
121
+ const freshView = new Uint32Array(fresh);
122
+ freshView.set(region.view);
123
+ region.backing = fresh;
124
+ region.view = freshView;
125
+ }
126
+ //# sourceMappingURL=sparse-set.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sparse-set.js","sourceRoot":"","sources":["../../src/query/sparse-set.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Buffers } from '../memory/index.js';
2
+ /** Synthetic component id keying the changeVersion column (never in any signature). */
3
+ declare const CHANGE_VERSION_COMPONENT_ID = 4294967293;
4
+ export declare class ChangeVersionStore {
5
+ #private;
6
+ /** Whether trackWrite stamps at all: false ⇒ zero stamp memory, zero stamp stores. */
7
+ enabled: boolean;
8
+ constructor(buffers: Buffers, initialCapacity: number);
9
+ /**: record `tick` at entity `index`. No-op when stamping is disabled. */
10
+ stamp(index: number, tick: number): void;
11
+ /**: the tick at which the entity was last stamped (0 if never / no column). */
12
+ versionAt(index: number): number;
13
+ /**: `changeVersion[index] > since` (strict — a caller at T ignores its own T). */
14
+ changedSince(index: number, since: number): boolean;
15
+ /**: reset the column to 0 at a serial flush (once per ~2.27 years). */
16
+ resetAll(): void;
17
+ }
18
+ export { CHANGE_VERSION_COMPONENT_ID };
19
+ //# sourceMappingURL=change-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change-version.d.ts","sourceRoot":"","sources":["../../src/reactivity/change-version.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,oBAAoB,CAAA;AAKpE,uFAAuF;AACvF,QAAA,MAAM,2BAA2B,aAAc,CAAA;AAE/C,qBAAa,kBAAkB;;IAK7B,sFAAsF;IACtF,OAAO,UAAQ;gBAEH,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM;IAmBrD,yEAAyE;IACzE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAOxC,+EAA+E;IAC/E,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAQhC,kFAAkF;IAClF,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO;IAInD,uEAAuE;IACvE,QAAQ,IAAI,IAAI;CAGjB;AAED,OAAO,EAAE,2BAA2B,EAAE,CAAA"}
@@ -0,0 +1,76 @@
1
+ // Per-ENTITY changeVersion column. A single u32 column addressed by ENTITY INDEX
2
+ // (the stable index part of the generational handle), stamped with the world frame tick whenever any
3
+ // component of that entity is written. This is the mechanism for the PUBLIC `.changed`-since-tick
4
+ // predicate and the delta serializer ONLY — it is NEVER consulted by the Changed query FILTER (that is
5
+ // the write log, / T3).
6
+ //
7
+ // Why ENTITY INDEX, not (archetype, row): the stamp must FOLLOW the entity across relocations. A value
8
+ // written to an entity that THEN migrates (own add/remove) or is relocated by a sibling's swap-remove
9
+ // must remain visible to the delta's changed-row scan. A (archetype,row)
10
+ // stamp is left behind when the row moves; an entity-index stamp is invariant across every relocation
11
+ // (the index is stable for the entity's lifetime — only the archetype/row beneath it move).
12
+ //
13
+ // LAZILY allocated: the column exists only once `enabled` is true (at least one `.changed` predicate
14
+ // consumer or a delta serializer is attached). The column is allocated through Buffers.column so
15
+ // it inherits the length-tracking resizable-SAB grow path, keyed by a synthetic id, and is NOT a
16
+ // member of any arch.columnSets, so store.ts #ensureRowCapacity never touches it. It SELF-GROWS on
17
+ // demand inside stamp() — buffers.grow(col, index+1) on the first out-of-capacity touch.
18
+ import { makeColumnLayout } from '../memory/index.js';
19
+ const VERSION_LAYOUT = makeColumnLayout('u32', 1, 0);
20
+ /** Synthetic component id keying the changeVersion column (never in any signature). */
21
+ const CHANGE_VERSION_COMPONENT_ID = 0xffff_fffd;
22
+ export class ChangeVersionStore {
23
+ #buffers;
24
+ #initialCapacity;
25
+ /** The single changeVersion column, addressed by entity index (lazily allocated). */
26
+ #column = null;
27
+ /** Whether trackWrite stamps at all: false ⇒ zero stamp memory, zero stamp stores. */
28
+ enabled = false;
29
+ constructor(buffers, initialCapacity) {
30
+ this.#buffers = buffers;
31
+ this.#initialCapacity = Math.max(1, initialCapacity);
32
+ }
33
+ #key() {
34
+ return `${CHANGE_VERSION_COMPONENT_ID}.0`;
35
+ }
36
+ /** The column, allocating it on first touch. */
37
+ #ensureColumn() {
38
+ let col = this.#column;
39
+ if (col === null) {
40
+ col = this.#buffers.column(this.#key(), VERSION_LAYOUT, this.#initialCapacity);
41
+ this.#column = col;
42
+ }
43
+ return col;
44
+ }
45
+ /**: record `tick` at entity `index`. No-op when stamping is disabled. */
46
+ stamp(index, tick) {
47
+ if (!this.enabled)
48
+ return;
49
+ const col = this.#ensureColumn();
50
+ if (index >= col.capacity())
51
+ this.#buffers.grow(col, index + 1);
52
+ col.view[index] = tick >>> 0;
53
+ }
54
+ /**: the tick at which the entity was last stamped (0 if never / no column). */
55
+ versionAt(index) {
56
+ if (!this.enabled)
57
+ return 0;
58
+ const col = this.#column;
59
+ if (col === null)
60
+ return 0;
61
+ if (index >= col.capacity())
62
+ return 0;
63
+ return col.view[index];
64
+ }
65
+ /**: `changeVersion[index] > since` (strict — a caller at T ignores its own T). */
66
+ changedSince(index, since) {
67
+ return this.versionAt(index) > since;
68
+ }
69
+ /**: reset the column to 0 at a serial flush (once per ~2.27 years). */
70
+ resetAll() {
71
+ if (this.#column !== null)
72
+ this.#column.view.fill(0);
73
+ }
74
+ }
75
+ export { CHANGE_VERSION_COMPONENT_ID };
76
+ //# sourceMappingURL=change-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change-version.js","sourceRoot":"","sources":["../../src/reactivity/change-version.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,qGAAqG;AACrG,kGAAkG;AAClG,uGAAuG;AACvG,wBAAwB;AACxB,EAAE;AACF,uGAAuG;AACvG,sGAAsG;AACtG,yEAAyE;AACzE,sGAAsG;AACtG,4FAA4F;AAC5F,EAAE;AACF,qGAAqG;AACrG,iGAAiG;AACjG,iGAAiG;AACjG,mGAAmG;AACnG,yFAAyF;AAGzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAErD,MAAM,cAAc,GAAG,gBAAgB,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;AAEpD,uFAAuF;AACvF,MAAM,2BAA2B,GAAG,WAAW,CAAA;AAE/C,MAAM,OAAO,kBAAkB;IACpB,QAAQ,CAAS;IACjB,gBAAgB,CAAQ;IACjC,qFAAqF;IACrF,OAAO,GAAkB,IAAI,CAAA;IAC7B,sFAAsF;IACtF,OAAO,GAAG,KAAK,CAAA;IAEf,YAAY,OAAgB,EAAE,eAAuB;QACnD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,CAAA;IACtD,CAAC;IAED,IAAI;QACF,OAAO,GAAG,2BAA2B,IAAiB,CAAA;IACxD,CAAC;IAED,gDAAgD;IAChD,aAAa;QACX,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAA;QACtB,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAA;YAC9E,IAAI,CAAC,OAAO,GAAG,GAAG,CAAA;QACpB,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,yEAAyE;IACzE,KAAK,CAAC,KAAa,EAAE,IAAY;QAC/B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,aAAa,EAAE,CAAA;QAChC,IAAI,KAAK,IAAI,GAAG,CAAC,QAAQ,EAAE;YAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAC9D;QAAC,GAAG,CAAC,IAAoB,CAAC,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,CAAA;IAChD,CAAC;IAED,+EAA+E;IAC/E,SAAS,CAAC,KAAa;QACrB,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,CAAA;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAA;QACxB,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,CAAC,CAAA;QAC1B,IAAI,KAAK,IAAI,GAAG,CAAC,QAAQ,EAAE;YAAE,OAAO,CAAC,CAAA;QACrC,OAAQ,GAAG,CAAC,IAAoB,CAAC,KAAK,CAAW,CAAA;IACnD,CAAC;IAED,kFAAkF;IAClF,YAAY,CAAC,KAAa,EAAE,KAAa;QACvC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,KAAK,CAAA;IACtC,CAAC;IAED,uEAAuE;IACvE,QAAQ;QACN,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;YAAG,IAAI,CAAC,OAAO,CAAC,IAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACvE,CAAC;CACF;AAED,OAAO,EAAE,2BAA2B,EAAE,CAAA"}
@@ -0,0 +1,12 @@
1
+ export { Reactivity } from './reactivity.js';
2
+ export type { ReactivityDeps } from './reactivity.js';
3
+ export { LogRing, WriteCorral, ShapeKind, OVERFLOW_SENTINEL, nextPow2 } from './log.js';
4
+ export type { LogPointer } from './log.js';
5
+ export { ChangeVersionStore } from './change-version.js';
6
+ export { StructuralJournal } from './structural-journal.js';
7
+ export type { StructuralRecord } from './structural-journal.js';
8
+ export { ObserverCommandBuffer } from './observer-commands.js';
9
+ export type { ObserverCommandApply } from './observer-commands.js';
10
+ export { ObserverRegistry, onAdd, onRemove, onChange } from './observers.js';
11
+ export type { ObserverKind, ObserverHandle, ObserverTerm, ObserverContext, ObserverHandler, ObserverDeps, } from './observers.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reactivity/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAErD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AACvF,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAC9D,YAAY,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAElE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAC5E,YAAY,EACV,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,eAAe,EACf,eAAe,EACf,YAAY,GACb,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,12 @@
1
+ // @ecsia/core reactivity subsystem. Owns the write log + shape log (the ring-log
2
+ // infrastructure driving the Changed query filter with no per-field atomic), the per-row
3
+ // changeVersion stamps (the public .changed predicate + delta serializer), and the deferred
4
+ // observers. Wired by the world: fills the trackWrite stub, the enqueueRemoveLog stub, and the
5
+ // LiveQuery.changed()/eachChanged() stubs.
6
+ export { Reactivity } from './reactivity.js';
7
+ export { LogRing, WriteCorral, ShapeKind, OVERFLOW_SENTINEL, nextPow2 } from './log.js';
8
+ export { ChangeVersionStore } from './change-version.js';
9
+ export { StructuralJournal } from './structural-journal.js';
10
+ export { ObserverCommandBuffer } from './observer-commands.js';
11
+ export { ObserverRegistry, onAdd, onRemove, onChange } from './observers.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reactivity/index.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,yFAAyF;AACzF,4FAA4F;AAC5F,+FAA+F;AAC/F,2CAA2C;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAG5C,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAGvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAG3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAG9D,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,83 @@
1
+ import type { Buffers } from '../memory/index.js';
2
+ /** ShapeKind ordinals — SHARED across command Op / serialization DeltaOp / reactivity. */
3
+ export declare enum ShapeKind {
4
+ Create = 0,
5
+ Destroy = 1,
6
+ Add = 2,
7
+ Remove = 3,
8
+ AddPair = 4,
9
+ RemovePair = 5,
10
+ SetPayload = 6
11
+ }
12
+ /** A consumer scans only entries appended since its last read. One per Changed filter / observer. */
13
+ export interface LogPointer {
14
+ readonly log: 'write' | 'shape';
15
+ /** Last ring slot (in WORDS) this consumer has read up to, exclusive. */
16
+ cursor: number;
17
+ /** Ring generation observed at last read. */
18
+ generation: number;
19
+ /** Spill entries (in WORDS) consumed so far. */
20
+ spillCursor: number;
21
+ }
22
+ /** Sentinel handed to a visit callback when the ring wrapped past a consumer's cursor. */
23
+ export declare const OVERFLOW_SENTINEL = -1;
24
+ /**
25
+ * One log ring. Generic over entry word-count (1 or 2 for write; 2 or 3 for shape — ). The ring
26
+ * length is interpreted in WORDS; `entryWords` is the stride of one logical entry.
27
+ */
28
+ export declare class LogRing {
29
+ #private;
30
+ readonly kind: 'write' | 'shape';
31
+ readonly entryWords: number;
32
+ ring: Uint32Array;
33
+ readonly header: Int32Array;
34
+ /** Main-thread spill: a growable JS array, NOT ring-bounded. Drained after the ring. */
35
+ readonly spill: number[];
36
+ constructor(params: {
37
+ buffers: Buffers;
38
+ kind: 'write' | 'shape';
39
+ entryWords: number;
40
+ capacityEntries: number;
41
+ keyPrefix: string;
42
+ shrinkRings: boolean;
43
+ });
44
+ /** Current ring length in words (the capacity the rolling head wraps against). */
45
+ get ringWords(): number;
46
+ /** Append one already-packed entry (1..3 words). Main thread only. Spills on overflow. */
47
+ push(words: readonly number[]): void;
48
+ /** Append a raw word directly (the corral-merge fast path). Routes to ring or spill. */
49
+ pushWord(word: number): void;
50
+ /** A fresh pointer positioned at the CURRENT head (a late subscriber sees only forward events). */
51
+ makePointer(): LogPointer;
52
+ /**: does this consumer have anything new to read? */
53
+ hasUpdatesSince(ptr: LogPointer): boolean;
54
+ /**
55
+ *: visit each entry (as a contiguous word-window into ring or spill) appended since
56
+ * `ptr`. `visit` receives the BASE offset and a source array. On a generation mismatch it receives
57
+ * the OVERFLOW_SENTINEL once and the pointer is conservatively advanced.
58
+ */
59
+ consume(ptr: LogPointer, visit: (source: Int32Array | Uint32Array | number[], base: number) => void, headLimit?: number): void;
60
+ /**: record this frame's peak and schedule a next-frame resize if it spilled. */
61
+ observePeak(): void;
62
+ /**
63
+ * / `minConsumerCursor` is the smallest cursor over all consumers
64
+ * (so the ring is not recycled past a lagging pointer). Applies a pending resize first.
65
+ */
66
+ frameReset(minConsumerCursor: number): void;
67
+ }
68
+ /**
69
+ * A per-worker write-log staging arena: a plain ArrayBuffer-backed Uint32Array the worker
70
+ * pushes into with no atomics, grown by allocate-copy on its own thread. In single-thread mode there
71
+ * is exactly one corral (the main "worker"); it is merged trivially every wave.
72
+ */
73
+ export declare class WriteCorral {
74
+ #private;
75
+ count: number;
76
+ constructor(initialEntries?: number);
77
+ get data(): Uint32Array;
78
+ /** O(1) push; grows by allocate-copy if full — never throws, never touches a shared ring. */
79
+ push(word: number): void;
80
+ reset(): void;
81
+ }
82
+ export declare function nextPow2(n: number): number;
83
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/reactivity/log.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,oBAAoB,CAAA;AAGpE,0FAA0F;AAC1F,oBAAY,SAAS;IACnB,MAAM,IAAI;IACV,OAAO,IAAI;IACX,GAAG,IAAI;IACP,MAAM,IAAI;IACV,OAAO,IAAI;IACX,UAAU,IAAI;IACd,UAAU,IAAI;CACf;AAED,qGAAqG;AACrG,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAA;IAC/B,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAA;IACd,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAA;IAClB,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,0FAA0F;AAC1F,eAAO,MAAM,iBAAiB,KAAK,CAAA;AAYnC;;;GAGG;AACH,qBAAa,OAAO;;IAClB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAM3B,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;IAC3B,wFAAwF;IACxF,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAK;gBAMjB,MAAM,EAAE;QAClB,OAAO,EAAE,OAAO,CAAA;QAChB,IAAI,EAAE,OAAO,GAAG,OAAO,CAAA;QACvB,UAAU,EAAE,MAAM,CAAA;QAClB,eAAe,EAAE,MAAM,CAAA;QACvB,SAAS,EAAE,MAAM,CAAA;QACjB,WAAW,EAAE,OAAO,CAAA;KACrB;IAkBD,kFAAkF;IAClF,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,0FAA0F;IAC1F,IAAI,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;IAkBpC,wFAAwF;IACxF,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAc5B,mGAAmG;IACnG,WAAW,IAAI,UAAU;IASzB,qDAAqD;IACrD,eAAe,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO;IASzC;;;;OAIG;IACH,OAAO,CACL,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,EAC1E,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI;IAgCP,gFAAgF;IAChF,WAAW,IAAI,IAAI;IAenB;;;OAGG;IACH,UAAU,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI;CA+C5C;AAED;;;;GAIG;AACH,qBAAa,WAAW;;IAEtB,KAAK,SAAI;gBAEG,cAAc,SAAO;IAIjC,IAAI,IAAI,IAAI,WAAW,CAEtB;IAED,6FAA6F;IAC7F,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IASxB,KAAK,IAAI,IAAI;CAGd;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1C"}
@@ -0,0 +1,260 @@
1
+ // The two reactivity rings: the write log (field-mutation journal) and the
2
+ // shape log (structural-change journal). Both are plain SAB|AB rings with a 4-word Atomics-capable
3
+ // header, a per-consumer LogPointer cursor protocol, per-worker write corrals merged
4
+ // serially, and a recoverable main-thread spill on overflow.
5
+ //
6
+ // Single-threaded executor: there is one logical "worker" (the main thread). The corral machinery
7
+ // is allocated and merged trivially so the multi-worker merge slots in unchanged.
8
+ import { isSharedBacking } from '../memory/buffers.js';
9
+ /** ShapeKind ordinals — SHARED across command Op / serialization DeltaOp / reactivity. */
10
+ export var ShapeKind;
11
+ (function (ShapeKind) {
12
+ ShapeKind[ShapeKind["Create"] = 0] = "Create";
13
+ ShapeKind[ShapeKind["Destroy"] = 1] = "Destroy";
14
+ ShapeKind[ShapeKind["Add"] = 2] = "Add";
15
+ ShapeKind[ShapeKind["Remove"] = 3] = "Remove";
16
+ ShapeKind[ShapeKind["AddPair"] = 4] = "AddPair";
17
+ ShapeKind[ShapeKind["RemovePair"] = 5] = "RemovePair";
18
+ ShapeKind[ShapeKind["SetPayload"] = 6] = "SetPayload";
19
+ })(ShapeKind || (ShapeKind = {}));
20
+ /** Sentinel handed to a visit callback when the ring wrapped past a consumer's cursor. */
21
+ export const OVERFLOW_SENTINEL = -1;
22
+ // Header word offsets. The header is an Int32Array of length 4.
23
+ const H_HEAD = 0; // next ring slot to write (monotonic within frame, in WORDS)
24
+ const H_GENERATION = 1; // ring-rollover counter (the only atomically-read word)
25
+ const H_SPILL_COUNT = 2; // entries currently in spill (in WORDS)
26
+ const H_PEAK = 3; // high-water mark of words appended this frame
27
+ /**
28
+ * One log ring. Generic over entry word-count (1 or 2 for write; 2 or 3 for shape — ). The ring
29
+ * length is interpreted in WORDS; `entryWords` is the stride of one logical entry.
30
+ */
31
+ export class LogRing {
32
+ kind;
33
+ entryWords;
34
+ #buffers;
35
+ #ringKey;
36
+ #headerKey;
37
+ #maxLength;
38
+ #ringRegion;
39
+ ring;
40
+ header;
41
+ /** Main-thread spill: a growable JS array, NOT ring-bounded. Drained after the ring. */
42
+ spill = [];
43
+ /** Words appended this frame across ring + spill (peak tracking). */
44
+ #framePushCount = 0;
45
+ #resize = { pendingResize: 0 };
46
+ #shrinkRings;
47
+ constructor(params) {
48
+ this.#buffers = params.buffers;
49
+ this.kind = params.kind;
50
+ this.entryWords = params.entryWords;
51
+ this.#shrinkRings = params.shrinkRings;
52
+ const capacityWords = Math.max(params.entryWords, params.capacityEntries * params.entryWords);
53
+ this.#maxLength = capacityWords;
54
+ this.#ringKey = `${params.keyPrefix}.ring`;
55
+ this.#headerKey = `${params.keyPrefix}.header`;
56
+ // A generous reservation so the
57
+ this.#ringRegion = params.buffers.region(this.#ringKey, 'u32', capacityWords, {
58
+ maxLength: capacityWords * 16,
59
+ });
60
+ this.ring = this.#ringRegion.view;
61
+ const headerRegion = params.buffers.region(this.#headerKey, 'i32', 4, { fixed: true });
62
+ this.header = headerRegion.view;
63
+ }
64
+ /** Current ring length in words (the capacity the rolling head wraps against). */
65
+ get ringWords() {
66
+ return this.ring.length;
67
+ }
68
+ /** Append one already-packed entry (1..3 words). Main thread only. Spills on overflow. */
69
+ push(words) {
70
+ const h = this.header;
71
+ let head = h[H_HEAD];
72
+ if (head + this.entryWords > this.ring.length) {
73
+ // Ring full this frame → spill, never throw.
74
+ for (let i = 0; i < this.entryWords; i++)
75
+ this.spill.push(words[i]);
76
+ h[H_SPILL_COUNT] = h[H_SPILL_COUNT] + this.entryWords;
77
+ this.#framePushCount += this.entryWords;
78
+ if (this.#framePushCount > h[H_PEAK])
79
+ h[H_PEAK] = this.#framePushCount;
80
+ return;
81
+ }
82
+ for (let i = 0; i < this.entryWords; i++)
83
+ this.ring[head + i] = words[i];
84
+ head += this.entryWords;
85
+ h[H_HEAD] = head;
86
+ this.#framePushCount += this.entryWords;
87
+ if (this.#framePushCount > h[H_PEAK])
88
+ h[H_PEAK] = this.#framePushCount;
89
+ }
90
+ /** Append a raw word directly (the corral-merge fast path). Routes to ring or spill. */
91
+ pushWord(word) {
92
+ const h = this.header;
93
+ const head = h[H_HEAD];
94
+ if (head >= this.ring.length) {
95
+ this.spill.push(word);
96
+ h[H_SPILL_COUNT] = h[H_SPILL_COUNT] + 1;
97
+ }
98
+ else {
99
+ this.ring[head] = word;
100
+ h[H_HEAD] = head + 1;
101
+ }
102
+ this.#framePushCount += 1;
103
+ if (this.#framePushCount > h[H_PEAK])
104
+ h[H_PEAK] = this.#framePushCount;
105
+ }
106
+ /** A fresh pointer positioned at the CURRENT head (a late subscriber sees only forward events). */
107
+ makePointer() {
108
+ return {
109
+ log: this.kind,
110
+ cursor: this.header[H_HEAD],
111
+ generation: this.header[H_GENERATION],
112
+ spillCursor: this.header[H_SPILL_COUNT],
113
+ };
114
+ }
115
+ /**: does this consumer have anything new to read? */
116
+ hasUpdatesSince(ptr) {
117
+ const h = this.header;
118
+ return (h[H_HEAD] !== ptr.cursor ||
119
+ h[H_GENERATION] !== ptr.generation ||
120
+ h[H_SPILL_COUNT] !== ptr.spillCursor);
121
+ }
122
+ /**
123
+ *: visit each entry (as a contiguous word-window into ring or spill) appended since
124
+ * `ptr`. `visit` receives the BASE offset and a source array. On a generation mismatch it receives
125
+ * the OVERFLOW_SENTINEL once and the pointer is conservatively advanced.
126
+ */
127
+ consume(ptr, visit, headLimit) {
128
+ const h = this.header;
129
+ // The ONE atomic read per consumer per frame. Plain load in single-thread; Atomics on SAB.
130
+ const curGen = Atomics.load(h, H_GENERATION);
131
+ const ringHead = h[H_HEAD];
132
+ const spillHead = h[H_SPILL_COUNT];
133
+ if (curGen !== ptr.generation) {
134
+ visit([OVERFLOW_SENTINEL], 0);
135
+ ptr.cursor = ringHead;
136
+ ptr.generation = curGen;
137
+ ptr.spillCursor = spillHead;
138
+ return;
139
+ }
140
+ // `headLimit` bounds the ring scan to a head snapshotted at drain entry, so
141
+ // entries appended DURING this drain (observer-issued writes) are deferred to the next drain — no
142
+ // intra-drain write-cascade. The spill is likewise pinned to its snapshot, carried via spillCursor
143
+ // semantics (a snapshot below the limit leaves later spill entries unread until the next pass).
144
+ const curHead = headLimit !== undefined && headLimit < ringHead ? headLimit : ringHead;
145
+ for (let slot = ptr.cursor; slot < curHead; slot += this.entryWords) {
146
+ visit(this.ring, slot);
147
+ }
148
+ ptr.cursor = curHead;
149
+ if (headLimit !== undefined && headLimit < ringHead) {
150
+ // A bounded drain does NOT advance past the spill (the snapshot predates any in-drain spill).
151
+ return;
152
+ }
153
+ for (let slot = ptr.spillCursor; slot < spillHead; slot += this.entryWords) {
154
+ visit(this.spill, slot);
155
+ }
156
+ ptr.spillCursor = spillHead;
157
+ }
158
+ /**: record this frame's peak and schedule a next-frame resize if it spilled. */
159
+ observePeak() {
160
+ const h = this.header;
161
+ const peak = Math.max(h[H_PEAK], h[H_HEAD] + h[H_SPILL_COUNT]);
162
+ const R = this.ring.length;
163
+ if (peak > R) {
164
+ this.#resize.pendingResize = nextPow2(peak * 2);
165
+ }
166
+ else if (this.#shrinkRings && peak < R / 4 && R > this.#minRing()) {
167
+ this.#resize.pendingResize = Math.max(this.#minRing(), nextPow2(Math.floor(R / 2)));
168
+ }
169
+ }
170
+ #minRing() {
171
+ return Math.max(this.entryWords, this.#maxLength);
172
+ }
173
+ /**
174
+ * / `minConsumerCursor` is the smallest cursor over all consumers
175
+ * (so the ring is not recycled past a lagging pointer). Applies a pending resize first.
176
+ */
177
+ frameReset(minConsumerCursor) {
178
+ const h = this.header;
179
+ if (this.#resize.pendingResize > 0) {
180
+ this.#applyResize(this.#resize.pendingResize);
181
+ this.#resize.pendingResize = 0;
182
+ }
183
+ // Spill is drained by every consumer (CONSUME ) before reset; clear it now.
184
+ this.spill.length = 0;
185
+ h[H_SPILL_COUNT] = 0;
186
+ h[H_PEAK] = 0;
187
+ this.#framePushCount = 0;
188
+ if (minConsumerCursor >= h[H_HEAD]) {
189
+ // All consumers caught up: recycle the ring from slot 0 with no wrap, no generation bump.
190
+ h[H_HEAD] = 0;
191
+ }
192
+ // else: leave entries in place; a lagging consumer reads them before the next reset recycles.
193
+ }
194
+ #applyResize(targetWords) {
195
+ const region = this.#ringRegion;
196
+ const required = targetWords * Uint32Array.BYTES_PER_ELEMENT;
197
+ if (required <= region.backing.byteLength) {
198
+ this.ring = region.view;
199
+ return;
200
+ }
201
+ const growable = region.backing;
202
+ const resizeFn = growable.grow ?? growable.resize;
203
+ const max = growable.maxByteLength;
204
+ if (typeof resizeFn === 'function' && typeof max === 'number' && required <= max) {
205
+ try {
206
+ resizeFn.call(growable, required);
207
+ this.ring = new Uint32Array(region.backing);
208
+ return;
209
+ }
210
+ catch {
211
+ // fall through to re-allocate
212
+ }
213
+ }
214
+ const isShared = isSharedBacking(region.backing);
215
+ const fresh = isShared
216
+ ? new SharedArrayBuffer(required)
217
+ : new ArrayBuffer(required);
218
+ const freshView = new Uint32Array(fresh);
219
+ freshView.set(region.view);
220
+ region.backing = fresh;
221
+ region.view = freshView;
222
+ this.ring = freshView;
223
+ }
224
+ }
225
+ /**
226
+ * A per-worker write-log staging arena: a plain ArrayBuffer-backed Uint32Array the worker
227
+ * pushes into with no atomics, grown by allocate-copy on its own thread. In single-thread mode there
228
+ * is exactly one corral (the main "worker"); it is merged trivially every wave.
229
+ */
230
+ export class WriteCorral {
231
+ #data;
232
+ count = 0;
233
+ constructor(initialEntries = 4096) {
234
+ this.#data = new Uint32Array(Math.max(1, initialEntries));
235
+ }
236
+ get data() {
237
+ return this.#data;
238
+ }
239
+ /** O(1) push; grows by allocate-copy if full — never throws, never touches a shared ring. */
240
+ push(word) {
241
+ if (this.count >= this.#data.length) {
242
+ const grown = new Uint32Array(this.#data.length * 2);
243
+ grown.set(this.#data);
244
+ this.#data = grown;
245
+ }
246
+ this.#data[this.count++] = word;
247
+ }
248
+ reset() {
249
+ this.count = 0;
250
+ }
251
+ }
252
+ export function nextPow2(n) {
253
+ if (n <= 1)
254
+ return 1;
255
+ let p = 1;
256
+ while (p < n)
257
+ p *= 2;
258
+ return p;
259
+ }
260
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/reactivity/log.ts"],"names":[],"mappings":"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"}