@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.
- package/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/bitmask/bitmask.d.ts +21 -0
- package/dist/bitmask/bitmask.d.ts.map +1 -0
- package/dist/bitmask/bitmask.js +103 -0
- package/dist/bitmask/bitmask.js.map +1 -0
- package/dist/bitmask/index.d.ts +3 -0
- package/dist/bitmask/index.d.ts.map +1 -0
- package/dist/bitmask/index.js +2 -0
- package/dist/bitmask/index.js.map +1 -0
- package/dist/component/accessor.d.ts +40 -0
- package/dist/component/accessor.d.ts.map +1 -0
- package/dist/component/accessor.js +220 -0
- package/dist/component/accessor.js.map +1 -0
- package/dist/component/column-set.d.ts +20 -0
- package/dist/component/column-set.d.ts.map +1 -0
- package/dist/component/column-set.js +60 -0
- package/dist/component/column-set.js.map +1 -0
- package/dist/component/define.d.ts +23 -0
- package/dist/component/define.d.ts.map +1 -0
- package/dist/component/define.js +155 -0
- package/dist/component/define.js.map +1 -0
- package/dist/component/descriptors.d.ts +3 -0
- package/dist/component/descriptors.d.ts.map +1 -0
- package/dist/component/descriptors.js +147 -0
- package/dist/component/descriptors.js.map +1 -0
- package/dist/component/index.d.ts +10 -0
- package/dist/component/index.d.ts.map +1 -0
- package/dist/component/index.js +6 -0
- package/dist/component/index.js.map +1 -0
- package/dist/component/sidecar.d.ts +58 -0
- package/dist/component/sidecar.d.ts.map +1 -0
- package/dist/component/sidecar.js +136 -0
- package/dist/component/sidecar.js.map +1 -0
- package/dist/config.d.ts +55 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +70 -0
- package/dist/config.js.map +1 -0
- package/dist/entity/codec.d.ts +45 -0
- package/dist/entity/codec.d.ts.map +1 -0
- package/dist/entity/codec.js +53 -0
- package/dist/entity/codec.js.map +1 -0
- package/dist/entity/index-allocator.d.ts +46 -0
- package/dist/entity/index-allocator.d.ts.map +1 -0
- package/dist/entity/index-allocator.js +121 -0
- package/dist/entity/index-allocator.js.map +1 -0
- package/dist/entity/index.d.ts +13 -0
- package/dist/entity/index.d.ts.map +1 -0
- package/dist/entity/index.js +7 -0
- package/dist/entity/index.js.map +1 -0
- package/dist/entity/record.d.ts +28 -0
- package/dist/entity/record.d.ts.map +1 -0
- package/dist/entity/record.js +42 -0
- package/dist/entity/record.js.map +1 -0
- package/dist/entity/ref.d.ts +70 -0
- package/dist/entity/ref.d.ts.map +1 -0
- package/dist/entity/ref.js +104 -0
- package/dist/entity/ref.js.map +1 -0
- package/dist/entity/reservation.d.ts +12 -0
- package/dist/entity/reservation.d.ts.map +1 -0
- package/dist/entity/reservation.js +28 -0
- package/dist/entity/reservation.js.map +1 -0
- package/dist/entity/store.d.ts +60 -0
- package/dist/entity/store.d.ts.map +1 -0
- package/dist/entity/store.js +193 -0
- package/dist/entity/store.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +12 -0
- package/dist/env.js.map +1 -0
- package/dist/ids.d.ts +9 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +8 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect-surface.d.ts +27 -0
- package/dist/inspect-surface.d.ts.map +1 -0
- package/dist/inspect-surface.js +14 -0
- package/dist/inspect-surface.js.map +1 -0
- package/dist/internal.d.ts +19 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +19 -0
- package/dist/internal.js.map +1 -0
- package/dist/memory/allocU32.d.ts +25 -0
- package/dist/memory/allocU32.d.ts.map +1 -0
- package/dist/memory/allocU32.js +95 -0
- package/dist/memory/allocU32.js.map +1 -0
- package/dist/memory/buffers.d.ts +94 -0
- package/dist/memory/buffers.d.ts.map +1 -0
- package/dist/memory/buffers.js +308 -0
- package/dist/memory/buffers.js.map +1 -0
- package/dist/memory/index.d.ts +7 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +4 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/layout.d.ts +37 -0
- package/dist/memory/layout.d.ts.map +1 -0
- package/dist/memory/layout.js +116 -0
- package/dist/memory/layout.js.map +1 -0
- package/dist/query/compile.d.ts +73 -0
- package/dist/query/compile.d.ts.map +1 -0
- package/dist/query/compile.js +158 -0
- package/dist/query/compile.js.map +1 -0
- package/dist/query/engine.d.ts +48 -0
- package/dist/query/engine.d.ts.map +1 -0
- package/dist/query/engine.js +230 -0
- package/dist/query/engine.js.map +1 -0
- package/dist/query/index.d.ts +8 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +10 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/live-query.d.ts +122 -0
- package/dist/query/live-query.d.ts.map +1 -0
- package/dist/query/live-query.js +543 -0
- package/dist/query/live-query.js.map +1 -0
- package/dist/query/sparse-set.d.ts +18 -0
- package/dist/query/sparse-set.d.ts.map +1 -0
- package/dist/query/sparse-set.js +126 -0
- package/dist/query/sparse-set.js.map +1 -0
- package/dist/reactivity/change-version.d.ts +19 -0
- package/dist/reactivity/change-version.d.ts.map +1 -0
- package/dist/reactivity/change-version.js +76 -0
- package/dist/reactivity/change-version.js.map +1 -0
- package/dist/reactivity/index.d.ts +12 -0
- package/dist/reactivity/index.d.ts.map +1 -0
- package/dist/reactivity/index.js +12 -0
- package/dist/reactivity/index.js.map +1 -0
- package/dist/reactivity/log.d.ts +83 -0
- package/dist/reactivity/log.d.ts.map +1 -0
- package/dist/reactivity/log.js +260 -0
- package/dist/reactivity/log.js.map +1 -0
- package/dist/reactivity/observer-commands.d.ts +40 -0
- package/dist/reactivity/observer-commands.d.ts.map +1 -0
- package/dist/reactivity/observer-commands.js +111 -0
- package/dist/reactivity/observer-commands.js.map +1 -0
- package/dist/reactivity/observers.d.ts +50 -0
- package/dist/reactivity/observers.d.ts.map +1 -0
- package/dist/reactivity/observers.js +127 -0
- package/dist/reactivity/observers.js.map +1 -0
- package/dist/reactivity/reactivity.d.ts +141 -0
- package/dist/reactivity/reactivity.d.ts.map +1 -0
- package/dist/reactivity/reactivity.js +479 -0
- package/dist/reactivity/reactivity.js.map +1 -0
- package/dist/reactivity/structural-journal.d.ts +30 -0
- package/dist/reactivity/structural-journal.d.ts.map +1 -0
- package/dist/reactivity/structural-journal.js +77 -0
- package/dist/reactivity/structural-journal.js.map +1 -0
- package/dist/registry.d.ts +26 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +58 -0
- package/dist/registry.js.map +1 -0
- package/dist/serialize-surface.d.ts +170 -0
- package/dist/serialize-surface.d.ts.map +1 -0
- package/dist/serialize-surface.js +6 -0
- package/dist/serialize-surface.js.map +1 -0
- package/dist/storage/archetype.d.ts +38 -0
- package/dist/storage/archetype.d.ts.map +1 -0
- package/dist/storage/archetype.js +47 -0
- package/dist/storage/archetype.js.map +1 -0
- package/dist/storage/cold-store.d.ts +41 -0
- package/dist/storage/cold-store.d.ts.map +1 -0
- package/dist/storage/cold-store.js +100 -0
- package/dist/storage/cold-store.js.map +1 -0
- package/dist/storage/index.d.ts +10 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/signature.d.ts +27 -0
- package/dist/storage/signature.d.ts.map +1 -0
- package/dist/storage/signature.js +115 -0
- package/dist/storage/signature.js.map +1 -0
- package/dist/storage/storage.d.ts +72 -0
- package/dist/storage/storage.d.ts.map +1 -0
- package/dist/storage/storage.js +192 -0
- package/dist/storage/storage.js.map +1 -0
- package/dist/storage/store.d.ts +88 -0
- package/dist/storage/store.d.ts.map +1 -0
- package/dist/storage/store.js +473 -0
- package/dist/storage/store.js.map +1 -0
- package/dist/util/stable-index.d.ts +29 -0
- package/dist/util/stable-index.d.ts.map +1 -0
- package/dist/util/stable-index.js +51 -0
- package/dist/util/stable-index.js.map +1 -0
- package/dist/world.d.ts +262 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +831 -0
- package/dist/world.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
// The reactivity facade: owns the write log + shape log, the per-row changeVersion
|
|
2
|
+
// columns, the deferred observers, and the query-flavor hooks. It fills the trackWrite stub, the
|
|
3
|
+
// enqueueRemoveLog stub, and the LiveQuery.changed()/eachChanged() stubs — wiring the dual
|
|
4
|
+
// mechanism the spec mandates:
|
|
5
|
+
// - the WRITE LOG drives the `.changed` query FILTER (drainChanged);
|
|
6
|
+
// - the per-row changeVersion drives the PUBLIC changedSince predicate + delta serializer.
|
|
7
|
+
// They never read each other's mechanism.
|
|
8
|
+
import { LogRing, OVERFLOW_SENTINEL, ShapeKind, WriteCorral } from './log.js';
|
|
9
|
+
import { ChangeVersionStore } from './change-version.js';
|
|
10
|
+
import { StructuralJournal } from './structural-journal.js';
|
|
11
|
+
import { ObserverRegistry } from './observers.js';
|
|
12
|
+
export class Reactivity {
|
|
13
|
+
#deps;
|
|
14
|
+
#writeLog;
|
|
15
|
+
#shapeLog;
|
|
16
|
+
#changeVersion;
|
|
17
|
+
#structuralJournal;
|
|
18
|
+
#observers;
|
|
19
|
+
#corral;
|
|
20
|
+
/** One per LiveQuery that declares the `changed` flavor (lazily allocated). */
|
|
21
|
+
#changedFlavors = new WeakMap();
|
|
22
|
+
/** Strong list of every changed-flavor pointer, so frame-recycle can rewind lagging cursors. */
|
|
23
|
+
#changedPointers = [];
|
|
24
|
+
#indexMask;
|
|
25
|
+
#componentIdBits;
|
|
26
|
+
#wide;
|
|
27
|
+
// Saved consumer pointers for the serial drains.
|
|
28
|
+
#maintainShapePtr;
|
|
29
|
+
#observerShapePtr;
|
|
30
|
+
#observerWritePtr;
|
|
31
|
+
// Filled by the world wiring so MAINTAIN_STRUCTURAL + observer "all present" can re-test entities.
|
|
32
|
+
#maintainHook = null;
|
|
33
|
+
#currentMembers = null;
|
|
34
|
+
#spilledThisFrame = false;
|
|
35
|
+
/** True iff the write log has a consumer (a changed-flavor pointer or a change observer); else the
|
|
36
|
+
* per-write push is dead (recomputed on (de)registration, not per write). */
|
|
37
|
+
#writeLogActive = false;
|
|
38
|
+
constructor(deps) {
|
|
39
|
+
this.#deps = deps;
|
|
40
|
+
this.#wide = deps.logEntryWords === 2;
|
|
41
|
+
this.#indexMask = deps.indexBits >= 32 ? 0xffffffff : ((1 << deps.indexBits) - 1) >>> 0;
|
|
42
|
+
this.#componentIdBits = 32 - deps.indexBits;
|
|
43
|
+
// One-word write entry / two-word shape entry by default; wide worlds add a word each.
|
|
44
|
+
const writeWords = this.#wide ? 2 : 1;
|
|
45
|
+
const shapeWords = this.#wide ? 3 : 2;
|
|
46
|
+
this.#writeLog = new LogRing({
|
|
47
|
+
buffers: deps.buffers,
|
|
48
|
+
kind: 'write',
|
|
49
|
+
entryWords: writeWords,
|
|
50
|
+
capacityEntries: deps.maxWritesPerFrame,
|
|
51
|
+
keyPrefix: 'reactivity.log.write',
|
|
52
|
+
shrinkRings: deps.shrinkRings,
|
|
53
|
+
});
|
|
54
|
+
this.#shapeLog = new LogRing({
|
|
55
|
+
buffers: deps.buffers,
|
|
56
|
+
kind: 'shape',
|
|
57
|
+
entryWords: shapeWords,
|
|
58
|
+
capacityEntries: deps.maxShapeChangesPerFrame,
|
|
59
|
+
keyPrefix: 'reactivity.log.shape',
|
|
60
|
+
shrinkRings: deps.shrinkRings,
|
|
61
|
+
});
|
|
62
|
+
this.#changeVersion = new ChangeVersionStore(deps.buffers, Math.min(64, deps.maxEntities));
|
|
63
|
+
this.#structuralJournal = new StructuralJournal(Math.max(1024, deps.maxShapeChangesPerFrame));
|
|
64
|
+
this.#corral = new WriteCorral();
|
|
65
|
+
const obsDeps = {
|
|
66
|
+
idOf: deps.idOf,
|
|
67
|
+
holdsAll: deps.holdsAll,
|
|
68
|
+
refOf: deps.refOf,
|
|
69
|
+
tick: deps.tick,
|
|
70
|
+
};
|
|
71
|
+
this.#observers = new ObserverRegistry(obsDeps);
|
|
72
|
+
this.#maintainShapePtr = this.#shapeLog.makePointer();
|
|
73
|
+
this.#observerShapePtr = this.#shapeLog.makePointer();
|
|
74
|
+
this.#observerWritePtr = this.#writeLog.makePointer();
|
|
75
|
+
}
|
|
76
|
+
/** Late-bind the single-entity maintenance hook (the query engine's maintainEntity). */
|
|
77
|
+
setMaintainHook(fn) {
|
|
78
|
+
this.#maintainHook = fn;
|
|
79
|
+
}
|
|
80
|
+
/** Late-bind a "current matching members across all queries" source for the conservative path. */
|
|
81
|
+
setCurrentMembersSource(fn) {
|
|
82
|
+
this.#currentMembers = fn;
|
|
83
|
+
}
|
|
84
|
+
// --- entry packing -------------------------------------------
|
|
85
|
+
#packWriteEntry(index, componentId) {
|
|
86
|
+
if (this.#wide)
|
|
87
|
+
return [index >>> 0, componentId >>> 0];
|
|
88
|
+
return [(((componentId << this.#deps.indexBits) | (index & this.#indexMask)) >>> 0)];
|
|
89
|
+
}
|
|
90
|
+
#unpackWrite(source, base) {
|
|
91
|
+
if (this.#wide) {
|
|
92
|
+
return { index: source[base] >>> 0, componentId: source[base + 1] >>> 0 };
|
|
93
|
+
}
|
|
94
|
+
const w = source[base];
|
|
95
|
+
return { index: w & this.#indexMask, componentId: (w >>> this.#deps.indexBits) >>> 0 };
|
|
96
|
+
}
|
|
97
|
+
#packShapeEntry(index, componentId, kind, targetIndex = 0) {
|
|
98
|
+
if (this.#wide) {
|
|
99
|
+
const a = index >>> 0;
|
|
100
|
+
const c = (((targetIndex << 3) | (kind & 0x7)) >>> 0);
|
|
101
|
+
return [a, componentId >>> 0, c];
|
|
102
|
+
}
|
|
103
|
+
const a = (((componentId << this.#deps.indexBits) | (index & this.#indexMask)) >>> 0);
|
|
104
|
+
const b = (((targetIndex << 3) | (kind & 0x7)) >>> 0);
|
|
105
|
+
return [a, b];
|
|
106
|
+
}
|
|
107
|
+
#unpackShape(source, base) {
|
|
108
|
+
if (this.#wide) {
|
|
109
|
+
const a = source[base];
|
|
110
|
+
const componentId = source[base + 1] >>> 0;
|
|
111
|
+
const c = source[base + 2];
|
|
112
|
+
return { index: a >>> 0, componentId, kind: (c & 0x7), target: c >>> 3 };
|
|
113
|
+
}
|
|
114
|
+
const a = source[base];
|
|
115
|
+
const b = source[base + 1];
|
|
116
|
+
return {
|
|
117
|
+
index: a & this.#indexMask,
|
|
118
|
+
componentId: (a >>> this.#deps.indexBits) >>> 0,
|
|
119
|
+
kind: (b & 0x7),
|
|
120
|
+
target: b >>> 3,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// --- hot-path hooks -------------------------------------
|
|
124
|
+
/** +: push the write entry (when a consumer exists) and stamp changeVersion (when enabled).
|
|
125
|
+
* Single-thread. The write log is read ONLY by changed-flavor query pointers and change observers; with
|
|
126
|
+
* neither present every appended word is dead (rewound at frame-recycle), so the push is a pure cost on
|
|
127
|
+
* the iteration hot path. Gate it on `#writeLogActive` (recomputed on flavor/observer (de)registration) —
|
|
128
|
+
* a semantics-preserving fast-out, since a later-attached changed flavor's pointer starts at the live head
|
|
129
|
+
* and sees only writes after it attaches. Pack the word inline (no per-write array). */
|
|
130
|
+
trackWrite(index, componentId, fieldIndex) {
|
|
131
|
+
if (this.#writeLogActive) {
|
|
132
|
+
// Main thread: append directly to the ring. (Worker corrals merge at mergeCorrals — .)
|
|
133
|
+
if (this.#wide) {
|
|
134
|
+
this.#writeLog.pushWord(index >>> 0);
|
|
135
|
+
this.#writeLog.pushWord(componentId >>> 0);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
this.#writeLog.pushWord((((componentId << this.#deps.indexBits) | (index & this.#indexMask)) >>> 0));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (this.#changeVersion.enabled) {
|
|
142
|
+
// fieldIndex affects only field-granular stamping (deferred); component-granular default
|
|
143
|
+
// stamps the whole-entity slot regardless of which component/field changed. Keyed by entity INDEX
|
|
144
|
+
// so the stamp follows the entity across any later relocation.
|
|
145
|
+
void fieldIndex;
|
|
146
|
+
this.#changeVersion.stamp(index, this.#deps.tick());
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**: append one shape entry. Main thread only, O(1). */
|
|
150
|
+
trackShape(index, componentId, kind) {
|
|
151
|
+
this.#shapeLog.push(this.#packShapeEntry(index, componentId, kind));
|
|
152
|
+
// Persistent since-T mirror for the delta serializer. Resolve the
|
|
153
|
+
// FULL handle NOW — for Destroy this hook runs BEFORE identity invalidation,
|
|
154
|
+
// so the dying handle is still recoverable. No-op until a delta serializer enables journaling.
|
|
155
|
+
if (this.#structuralJournal.enabled) {
|
|
156
|
+
this.#structuralJournal.record(this.#deps.tick(), kind, this.#deps.resolveHandle(index), componentId, 0);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**: carries the target index in word B/C. */
|
|
160
|
+
trackShapePair(index, pairId, targetIndex, kind) {
|
|
161
|
+
this.#shapeLog.push(this.#packShapeEntry(index, pairId, kind, targetIndex));
|
|
162
|
+
if (this.#structuralJournal.enabled) {
|
|
163
|
+
this.#structuralJournal.record(this.#deps.tick(), kind, this.#deps.resolveHandle(index), pairId, this.#deps.resolveHandle(targetIndex));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* _PAYLOAD: a non-exclusive overflow pair's payload changed on an already-live pair. This is
|
|
168
|
+
* NOT a membership change (no shape-log entry, no add/remove observer), but it IS a structural delta
|
|
169
|
+
* the since-T stream must carry, so we record it in the persistent journal only
|
|
170
|
+
* (overflow payload changes are explicit OP_PAIR_PAYLOAD records).
|
|
171
|
+
*/
|
|
172
|
+
trackShapeSetPayload(index, pairId, targetIndex) {
|
|
173
|
+
if (this.#structuralJournal.enabled) {
|
|
174
|
+
this.#structuralJournal.record(this.#deps.tick(), ShapeKind.SetPayload, this.#deps.resolveHandle(index), pairId, this.#deps.resolveHandle(targetIndex));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* The enqueueRemoveLog stub body: storage calls this for each component in fromArch \ toArch at
|
|
179
|
+
* a migration, and for each held component at despawn (BEFORE removeRow + identity invalidation,
|
|
180
|
+
* ). It emits a shape-log Remove entry — the single source for onRemove dispatch + Removed
|
|
181
|
+
* delta maintenance.
|
|
182
|
+
*/
|
|
183
|
+
enqueueRemoveLog(index, componentId) {
|
|
184
|
+
this.trackShape(index, componentId, ShapeKind.Remove);
|
|
185
|
+
}
|
|
186
|
+
// --- public predicate + delta ---------------------------------------
|
|
187
|
+
/** Enable per-row changeVersion stamping (a `.changed` predicate consumer / serializer exists). */
|
|
188
|
+
enableChangeVersion() {
|
|
189
|
+
this.#changeVersion.enabled = true;
|
|
190
|
+
this.#deps.tracking.active = true;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Enable the persistent structural journal (the since-T STRUCTURAL source). A delta serializer
|
|
194
|
+
* that includes the structural section calls this once at construction — it is the structural twin of
|
|
195
|
+
* `enableChangeVersion`. Until then, zero record cost.
|
|
196
|
+
*/
|
|
197
|
+
enableStructuralJournal() {
|
|
198
|
+
this.#structuralJournal.enabled = true;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* /: the structural ops committed with tick > since, in commit order, as portable full-handle
|
|
202
|
+
* records. `gap` is true when `since` predates the bounded journal's live window (the caller must
|
|
203
|
+
* resync from a fresh snapshot — the no-partial-apply delta-gap rule).
|
|
204
|
+
*/
|
|
205
|
+
drainStructuralSince(since) {
|
|
206
|
+
return this.#structuralJournal.drainSince(since);
|
|
207
|
+
}
|
|
208
|
+
/**: "did any component on `handle` change since tick `since`?" (strict >). */
|
|
209
|
+
changedSince(handle, since) {
|
|
210
|
+
const index = handle & this.#indexMask;
|
|
211
|
+
return this.#changeVersion.changedSince(index, since);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* /: rows of `archetypeId` whose ENTITY's stamp is > since (the delta-serializer scan).
|
|
215
|
+
* `indexOfRow` maps a live row of the archetype to its entity index — the stamp is keyed by entity
|
|
216
|
+
* index (it follows the entity across relocations), so we resolve each row's current occupant.
|
|
217
|
+
*/
|
|
218
|
+
*changedRows(_archetypeId, since, count, indexOfRow) {
|
|
219
|
+
for (let row = 0; row < count; row++) {
|
|
220
|
+
if (this.#changeVersion.changedSince(indexOfRow(row), since))
|
|
221
|
+
yield row;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
currentTick() {
|
|
225
|
+
return this.#deps.tick();
|
|
226
|
+
}
|
|
227
|
+
// --- observers --------------------------------------------------------
|
|
228
|
+
/** Recompute the write-log fast-out flag after any consumer (de)registers. Also refreshes the
|
|
229
|
+
* accessor's shared `tracking.active` cell: true iff trackWrite would do real work (a write-log
|
|
230
|
+
* consumer exists OR changeVersion stamping is enabled). When false the setter skips the whole chain. */
|
|
231
|
+
#refreshWriteLogActive() {
|
|
232
|
+
this.#writeLogActive = this.#changedPointers.length > 0 || this.#observers.hasChangeObservers;
|
|
233
|
+
this.#deps.tracking.active = this.#writeLogActive || this.#changeVersion.enabled;
|
|
234
|
+
}
|
|
235
|
+
observe(term, handler) {
|
|
236
|
+
const handle = this.#observers.observe(term, handler);
|
|
237
|
+
this.#refreshWriteLogActive();
|
|
238
|
+
const dispose = handle.dispose;
|
|
239
|
+
return {
|
|
240
|
+
id: handle.id,
|
|
241
|
+
dispose: () => {
|
|
242
|
+
dispose();
|
|
243
|
+
this.#refreshWriteLogActive();
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/**: is there a remove-observer on `componentId` (gates deferred row reclaim)? */
|
|
248
|
+
hasRemoveObserver(componentId) {
|
|
249
|
+
return this.#observers.hasKindFor('remove', componentId);
|
|
250
|
+
}
|
|
251
|
+
// --- query-flavor hooks ---------------------
|
|
252
|
+
/**
|
|
253
|
+
*: allocate the `changed` flavor's LogPointer + dedup bitset for `q`. `added`/`removed` lists
|
|
254
|
+
* are owned by the LiveQuery itself and filled by maintenance; this hook wires only `changed`.
|
|
255
|
+
*/
|
|
256
|
+
attachChangedFlavor(q, componentIds) {
|
|
257
|
+
this.enableChangeVersion();
|
|
258
|
+
if (this.#changedFlavors.has(q))
|
|
259
|
+
return;
|
|
260
|
+
const ptr = this.#writeLog.makePointer();
|
|
261
|
+
this.#changedPointers.push(ptr);
|
|
262
|
+
this.#changedFlavors.set(q, {
|
|
263
|
+
ptr,
|
|
264
|
+
dedup: new Uint8Array(Math.min(64, this.#deps.maxEntities)),
|
|
265
|
+
out: new Uint32Array(64),
|
|
266
|
+
componentIds: new Set(componentIds),
|
|
267
|
+
});
|
|
268
|
+
this.#refreshWriteLogActive();
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* _CHANGED: drain `q`'s write-log pointer, returning this frame's changed indices (deduped,
|
|
272
|
+
* intersected with `q.current` and the query's filtered components). Write-log driven — never
|
|
273
|
+
* consults changeVersion.
|
|
274
|
+
*/
|
|
275
|
+
drainChanged(q) {
|
|
276
|
+
const flavor = this.#changedFlavors.get(q);
|
|
277
|
+
if (flavor === undefined)
|
|
278
|
+
return EMPTY_U32;
|
|
279
|
+
let count = 0;
|
|
280
|
+
const current = q.current;
|
|
281
|
+
// Size the dedup bitset to the current matching high-water (entity indices).
|
|
282
|
+
const need = this.#maxIndexOf(current) + 1;
|
|
283
|
+
if (need > flavor.dedup.length)
|
|
284
|
+
flavor.dedup = new Uint8Array(need);
|
|
285
|
+
flavor.dedup.fill(0);
|
|
286
|
+
const emit = (index) => {
|
|
287
|
+
if (count >= flavor.out.length) {
|
|
288
|
+
const grown = new Uint32Array(flavor.out.length * 2);
|
|
289
|
+
grown.set(flavor.out);
|
|
290
|
+
flavor.out = grown;
|
|
291
|
+
}
|
|
292
|
+
flavor.out[count++] = index;
|
|
293
|
+
};
|
|
294
|
+
this.#writeLog.consume(flavor.ptr, (source, base) => {
|
|
295
|
+
if (source.length === 1 && source[0] === OVERFLOW_SENTINEL) {
|
|
296
|
+
// Treat every current match as changed.
|
|
297
|
+
for (const index of current) {
|
|
298
|
+
if (index < flavor.dedup.length && flavor.dedup[index] === 1)
|
|
299
|
+
continue;
|
|
300
|
+
if (index < flavor.dedup.length)
|
|
301
|
+
flavor.dedup[index] = 1;
|
|
302
|
+
emit(index);
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const { index, componentId } = this.#unpackWrite(source, base);
|
|
307
|
+
if (flavor.componentIds.size > 0 && !flavor.componentIds.has(componentId))
|
|
308
|
+
return;
|
|
309
|
+
if (!current.has(index))
|
|
310
|
+
return;
|
|
311
|
+
if (index < flavor.dedup.length && flavor.dedup[index] === 1)
|
|
312
|
+
return;
|
|
313
|
+
if (index < flavor.dedup.length)
|
|
314
|
+
flavor.dedup[index] = 1;
|
|
315
|
+
emit(index);
|
|
316
|
+
});
|
|
317
|
+
return flavor.out.subarray(0, count);
|
|
318
|
+
}
|
|
319
|
+
#maxIndexOf(set) {
|
|
320
|
+
let max = 0;
|
|
321
|
+
for (const i of set)
|
|
322
|
+
if (i > max)
|
|
323
|
+
max = i;
|
|
324
|
+
return max;
|
|
325
|
+
}
|
|
326
|
+
// --- lifecycle -------------------------------
|
|
327
|
+
/**: start of frame — advance the world tick, snapshot peak, recycle the rings. */
|
|
328
|
+
frameReset() {
|
|
329
|
+
this.#deps.advanceTick();
|
|
330
|
+
if (this.#deps.tick() === 0xffffffff) {
|
|
331
|
+
this.#changeVersion.resetAll(); //
|
|
332
|
+
this.#structuralJournal.resetAll();
|
|
333
|
+
}
|
|
334
|
+
this.#spilledThisFrame = false;
|
|
335
|
+
this.#writeLog.frameReset(this.#minWriteCursor());
|
|
336
|
+
this.#shapeLog.frameReset(this.#minShapeCursor());
|
|
337
|
+
// When the ring recycled to slot 0 (all consumers caught up), rewind every caught-up
|
|
338
|
+
// consumer's cursor to 0 too, so it scans the new frame's entries from the head. A still-lagging
|
|
339
|
+
// consumer (cursor below the now-zero head is impossible) keeps its cursor.
|
|
340
|
+
this.#rewindCaughtUp(this.#writeLog.header[0], [this.#observerWritePtr, ...this.#changedPointers]);
|
|
341
|
+
this.#rewindCaughtUp(this.#shapeLog.header[0], [this.#observerShapePtr, this.#maintainShapePtr]);
|
|
342
|
+
}
|
|
343
|
+
#rewindCaughtUp(head, pointers) {
|
|
344
|
+
if (head !== 0)
|
|
345
|
+
return; // ring was not recycled (a lagging consumer pinned it)
|
|
346
|
+
for (const ptr of pointers) {
|
|
347
|
+
ptr.cursor = 0;
|
|
348
|
+
ptr.spillCursor = 0;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/**: merge per-worker write corrals into the shared ring (deterministic). No-op single-thread. */
|
|
352
|
+
mergeCorrals() {
|
|
353
|
+
const c = this.#corral;
|
|
354
|
+
for (let i = 0; i < c.count; i++) {
|
|
355
|
+
this.#writeLog.pushWord(c.data[i]);
|
|
356
|
+
}
|
|
357
|
+
c.reset();
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* /+: merge ONE worker's staged value writes into the shared write log. `pairs` is a
|
|
361
|
+
* flat `[index, componentId, index, componentId, …]` buffer (the worker's raw corral payload); the
|
|
362
|
+
* caller drives this in ASCENDING worker-index order so the merged stream is deterministic. We
|
|
363
|
+
* (re)pack each pair through the module's own packWrite so single/wide layout stays the single
|
|
364
|
+
* source of truth — the worker never duplicates the packing scheme. Writes flow into the SAME ring
|
|
365
|
+
* the main thread appends to, so `.changed` filters and onChange observers fire for worker writes
|
|
366
|
+
* exactly as for single-thread writes.: when changeVersion is enabled we also
|
|
367
|
+
* stamp each row here (the worker hot path stays atomic-free; the stamp lands at the serial merge).
|
|
368
|
+
*/
|
|
369
|
+
mergeWorkerWrites(pairs, count) {
|
|
370
|
+
for (let i = 0; i < count; i++) {
|
|
371
|
+
const index = pairs[i * 2] >>> 0;
|
|
372
|
+
const componentId = pairs[i * 2 + 1] >>> 0;
|
|
373
|
+
for (const w of this.#packWriteEntry(index, componentId))
|
|
374
|
+
this.#writeLog.pushWord(w);
|
|
375
|
+
if (this.#changeVersion.enabled) {
|
|
376
|
+
this.#changeVersion.stamp(index, this.#deps.tick());
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* _STRUCTURAL: drain the shape log, re-testing each affected entity against the queries
|
|
382
|
+
* referencing the changed component. In single-thread mode already maintains `current`
|
|
383
|
+
* synchronously at the commit point, so this re-runs the same idempotent re-test off the log (the
|
|
384
|
+
* drain is the spec's serial mechanism; the synchronous path is the optimization that agrees with
|
|
385
|
+
* it). Add/remove coalesce within the frame because the drain happens once.
|
|
386
|
+
*/
|
|
387
|
+
maintainStructural() {
|
|
388
|
+
const hook = this.#maintainHook;
|
|
389
|
+
if (hook === null) {
|
|
390
|
+
this.#maintainShapePtr.cursor = this.#shapeLogHead();
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
this.#shapeLog.consume(this.#maintainShapePtr, (source, base) => {
|
|
394
|
+
if (source.length === 1 && source[0] === OVERFLOW_SENTINEL)
|
|
395
|
+
return;
|
|
396
|
+
const { index, componentId, kind } = this.#unpackShape(source, base);
|
|
397
|
+
if (kind === ShapeKind.Add || kind === ShapeKind.Remove)
|
|
398
|
+
hook(index, componentId);
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
/** _DRAIN: fire deferred observers from the saved shape/write pointers. */
|
|
402
|
+
observerDrain() {
|
|
403
|
+
if (!this.#observers.hasObservers) {
|
|
404
|
+
this.#observerShapePtr.cursor = this.#shapeLogHead();
|
|
405
|
+
this.#observerWritePtr.cursor = this.#writeLogHead();
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
this.#observers.resetChangeDedup();
|
|
409
|
+
// Capture BOTH log heads at drain entry. A structural (add/remove) handler may
|
|
410
|
+
// call entity.write(C), which appends to the write log; bounding the change consume to this snapshot
|
|
411
|
+
// defers that observer-issued write to the NEXT drain — no intra-drain write-cascade (review #2).
|
|
412
|
+
const writeHeadSnapshot = this.#writeLogHead();
|
|
413
|
+
// Structural observers (add/remove) off the shape log.
|
|
414
|
+
this.#shapeLog.consume(this.#observerShapePtr, (source, base) => {
|
|
415
|
+
if (source.length === 1 && source[0] === OVERFLOW_SENTINEL)
|
|
416
|
+
return;
|
|
417
|
+
const { index, componentId, kind } = this.#unpackShape(source, base);
|
|
418
|
+
const okind = kind === ShapeKind.Add || kind === ShapeKind.AddPair
|
|
419
|
+
? 'add'
|
|
420
|
+
: kind === ShapeKind.Remove || kind === ShapeKind.RemovePair || kind === ShapeKind.Destroy
|
|
421
|
+
? 'remove'
|
|
422
|
+
: null;
|
|
423
|
+
if (okind === null)
|
|
424
|
+
return; // CREATE has no per-component observer
|
|
425
|
+
this.#observers.dispatchStructural(okind, index, componentId);
|
|
426
|
+
});
|
|
427
|
+
// Change observers off the write log.
|
|
428
|
+
this.#writeLog.consume(this.#observerWritePtr, (source, base) => {
|
|
429
|
+
if (source.length === 1 && source[0] === OVERFLOW_SENTINEL) {
|
|
430
|
+
if (this.#currentMembers !== null)
|
|
431
|
+
this.#observers.fireAllChangeConservatively(this.#currentMembers());
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
const { index, componentId } = this.#unpackWrite(source, base);
|
|
435
|
+
this.#observers.dispatchChange(index, componentId);
|
|
436
|
+
}, writeHeadSnapshot);
|
|
437
|
+
}
|
|
438
|
+
/** _LOGS: drain/merge spill (consumers already drained it), schedule next-frame resize. */
|
|
439
|
+
flushLogs() {
|
|
440
|
+
if (this.#writeLog.spill.length > 0 || this.#shapeLog.spill.length > 0)
|
|
441
|
+
this.#spilledThisFrame = true;
|
|
442
|
+
this.#writeLog.observePeak();
|
|
443
|
+
this.#shapeLog.observePeak();
|
|
444
|
+
if (this.#deps.dev && this.#spilledThisFrame && typeof console !== 'undefined') {
|
|
445
|
+
console.warn(`[ecsia] reactivity log overflowed its ring this frame; entries spilled to the main-thread ` +
|
|
446
|
+
`array and the ring will grow next frame. Set createWorld({ reactivity: { maxWritesPerFrame / ` +
|
|
447
|
+
`maxShapeChangesPerFrame } }) to pre-size.`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
// --- internals -------------------------------------------------------------
|
|
451
|
+
#shapeLogHead() {
|
|
452
|
+
return this.#shapeLog.header[0];
|
|
453
|
+
}
|
|
454
|
+
#writeLogHead() {
|
|
455
|
+
return this.#writeLog.header[0];
|
|
456
|
+
}
|
|
457
|
+
#minWriteCursor() {
|
|
458
|
+
let min = this.#writeLog.header[0];
|
|
459
|
+
if (this.#observerWritePtr.cursor < min)
|
|
460
|
+
min = this.#observerWritePtr.cursor;
|
|
461
|
+
// changed-flavor pointers are drained lazily; they pin the ring until read so the recycle never
|
|
462
|
+
// overruns an unread consumer ("ring is not recycled past a lagging pointer"). In the common
|
|
463
|
+
// case every system reads its filter within the frame, so they equal head and the ring recycles.
|
|
464
|
+
for (const ptr of this.#changedPointers)
|
|
465
|
+
if (ptr.cursor < min)
|
|
466
|
+
min = ptr.cursor;
|
|
467
|
+
return min;
|
|
468
|
+
}
|
|
469
|
+
#minShapeCursor() {
|
|
470
|
+
let min = this.#shapeLog.header[0];
|
|
471
|
+
if (this.#observerShapePtr.cursor < min)
|
|
472
|
+
min = this.#observerShapePtr.cursor;
|
|
473
|
+
if (this.#maintainShapePtr.cursor < min)
|
|
474
|
+
min = this.#maintainShapePtr.cursor;
|
|
475
|
+
return min;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
const EMPTY_U32 = new Uint32Array(0);
|
|
479
|
+
//# sourceMappingURL=reactivity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactivity.js","sourceRoot":"","sources":["../../src/reactivity/reactivity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ShapeKind } from './log.js';
|
|
2
|
+
export interface StructuralRecord {
|
|
3
|
+
readonly tick: number;
|
|
4
|
+
readonly kind: ShapeKind;
|
|
5
|
+
/** The FULL (generational) subject/entity handle, resolved at commit time (portable across boundary). */
|
|
6
|
+
readonly handle: number;
|
|
7
|
+
/** User/synthetic component id (Add/Remove) or synthetic pair id (AddPair/RemovePair). 0 for Create/Destroy. */
|
|
8
|
+
readonly componentId: number;
|
|
9
|
+
/** The FULL pair-target handle (AddPair/RemovePair/SetPayload), resolved at commit time; else 0. */
|
|
10
|
+
readonly target: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class StructuralJournal {
|
|
13
|
+
#private;
|
|
14
|
+
/** False ⇒ zero record cost (no delta serializer attached). Mirrors ChangeVersionStore.enabled. */
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
constructor(initialCapacityRecords?: number);
|
|
17
|
+
/** Append one structural op at `tick`. O(1); drops the oldest record once the ring is full. */
|
|
18
|
+
record(tick: number, kind: ShapeKind, handle: number, componentId: number, target: number): void;
|
|
19
|
+
/**
|
|
20
|
+
* Records with tick > since, in commit (append) order. Returns `gap: true` if `since` predates the
|
|
21
|
+
* oldest resident record (the live window evicted it — the caller must resync from a snapshot).
|
|
22
|
+
*/
|
|
23
|
+
drainSince(since: number): {
|
|
24
|
+
records: StructuralRecord[];
|
|
25
|
+
gap: boolean;
|
|
26
|
+
};
|
|
27
|
+
/**: clear the journal at a serial flush (alongside changeVersion.resetAll). */
|
|
28
|
+
resetAll(): void;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=structural-journal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structural-journal.d.ts","sourceRoot":"","sources":["../../src/reactivity/structural-journal.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,yGAAyG;IACzG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,gHAAgH;IAChH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,oGAAoG;IACpG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAID,qBAAa,iBAAiB;;IAC5B,mGAAmG;IACnG,OAAO,UAAQ;gBASH,sBAAsB,SAAO;IAKzC,+FAA+F;IAC/F,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAgBhG;;;OAGG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAE;IAoBxE,+EAA+E;IAC/E,QAAQ,IAAI,IAAI;CAIjB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// The persistent, bounded, tick-keyed STRUCTURAL JOURNAL — the since-T structural source the
|
|
2
|
+
// delta serializer consumes. The per-frame shape log (log.ts) is RECYCLED at every frame
|
|
3
|
+
// boundary, so a "since tick T" serializer cannot pin that ring across frames. Exactly as
|
|
4
|
+
// `changeVersion` is the persistent
|
|
5
|
+
// since-T source for VALUE changes, this journal is the persistent since-T source for STRUCTURAL
|
|
6
|
+
// changes (Create/Destroy/ComponentAdd/ComponentRemove/AddPair/RemovePair/SetPayload).
|
|
7
|
+
//
|
|
8
|
+
// It is appended SYNCHRONOUSLY at the structural commit point (from trackShape/trackShapePair), so the
|
|
9
|
+
// dying entity's FULL handle is still resolvable (Destroy is emitted BEFORE identity
|
|
10
|
+
// invalidation). Each record is keyed by the current frame tick; drainSince(T) returns the ops
|
|
11
|
+
// with tick > T in commit order. The journal is a bounded ring (drop-oldest); when a requested T has
|
|
12
|
+
// been evicted, the caller must resync from a fresh snapshot (the delta-gap rule).
|
|
13
|
+
// LAZILY enabled: zero memory/zero record cost until a delta serializer attaches.
|
|
14
|
+
const FIELDS_PER_RECORD = 5;
|
|
15
|
+
export class StructuralJournal {
|
|
16
|
+
/** False ⇒ zero record cost (no delta serializer attached). Mirrors ChangeVersionStore.enabled. */
|
|
17
|
+
enabled = false;
|
|
18
|
+
/** A flat ring: [tick, kind, handle, componentId, target] × capacity. Drop-oldest on overflow. */
|
|
19
|
+
#ring;
|
|
20
|
+
#capacity;
|
|
21
|
+
/** Total records ever appended (monotonic). The live window is [count-capacity, count). */
|
|
22
|
+
#count = 0;
|
|
23
|
+
/** The oldest tick still resident; a drainSince(T) with T < this floor signals an evicted gap. */
|
|
24
|
+
#oldestResidentTick = 0;
|
|
25
|
+
constructor(initialCapacityRecords = 1024) {
|
|
26
|
+
this.#capacity = Math.max(16, initialCapacityRecords);
|
|
27
|
+
this.#ring = new Uint32Array(this.#capacity * FIELDS_PER_RECORD);
|
|
28
|
+
}
|
|
29
|
+
/** Append one structural op at `tick`. O(1); drops the oldest record once the ring is full. */
|
|
30
|
+
record(tick, kind, handle, componentId, target) {
|
|
31
|
+
if (!this.enabled)
|
|
32
|
+
return;
|
|
33
|
+
const slot = (this.#count % this.#capacity) * FIELDS_PER_RECORD;
|
|
34
|
+
if (this.#count >= this.#capacity) {
|
|
35
|
+
// About to overwrite the oldest live record — advance the resident-floor to its successor's tick.
|
|
36
|
+
const nextOldest = ((this.#count + 1) % this.#capacity) * FIELDS_PER_RECORD;
|
|
37
|
+
this.#oldestResidentTick = this.#ring[nextOldest];
|
|
38
|
+
}
|
|
39
|
+
this.#ring[slot] = tick >>> 0;
|
|
40
|
+
this.#ring[slot + 1] = kind >>> 0;
|
|
41
|
+
this.#ring[slot + 2] = handle >>> 0;
|
|
42
|
+
this.#ring[slot + 3] = componentId >>> 0;
|
|
43
|
+
this.#ring[slot + 4] = target >>> 0;
|
|
44
|
+
this.#count += 1;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Records with tick > since, in commit (append) order. Returns `gap: true` if `since` predates the
|
|
48
|
+
* oldest resident record (the live window evicted it — the caller must resync from a snapshot).
|
|
49
|
+
*/
|
|
50
|
+
drainSince(since) {
|
|
51
|
+
const out = [];
|
|
52
|
+
if (!this.enabled)
|
|
53
|
+
return { records: out, gap: false };
|
|
54
|
+
const gap = this.#count > this.#capacity && since < this.#oldestResidentTick;
|
|
55
|
+
const start = this.#count > this.#capacity ? this.#count - this.#capacity : 0;
|
|
56
|
+
for (let i = start; i < this.#count; i++) {
|
|
57
|
+
const slot = (i % this.#capacity) * FIELDS_PER_RECORD;
|
|
58
|
+
const tick = this.#ring[slot];
|
|
59
|
+
if (tick <= since)
|
|
60
|
+
continue;
|
|
61
|
+
out.push({
|
|
62
|
+
tick,
|
|
63
|
+
kind: this.#ring[slot + 1],
|
|
64
|
+
handle: this.#ring[slot + 2],
|
|
65
|
+
componentId: this.#ring[slot + 3],
|
|
66
|
+
target: this.#ring[slot + 4],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return { records: out, gap };
|
|
70
|
+
}
|
|
71
|
+
/**: clear the journal at a serial flush (alongside changeVersion.resetAll). */
|
|
72
|
+
resetAll() {
|
|
73
|
+
this.#count = 0;
|
|
74
|
+
this.#oldestResidentTick = 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=structural-journal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structural-journal.js","sourceRoot":"","sources":["../../src/reactivity/structural-journal.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,yFAAyF;AACzF,0FAA0F;AAC1F,oCAAoC;AACpC,iGAAiG;AACjG,uFAAuF;AACvF,EAAE;AACF,uGAAuG;AACvG,qFAAqF;AACrF,+FAA+F;AAC/F,qGAAqG;AACrG,mFAAmF;AACnF,kFAAkF;AAelF,MAAM,iBAAiB,GAAG,CAAC,CAAA;AAE3B,MAAM,OAAO,iBAAiB;IAC5B,mGAAmG;IACnG,OAAO,GAAG,KAAK,CAAA;IACf,kGAAkG;IAClG,KAAK,CAAa;IACT,SAAS,CAAQ;IAC1B,2FAA2F;IAC3F,MAAM,GAAG,CAAC,CAAA;IACV,kGAAkG;IAClG,mBAAmB,GAAG,CAAC,CAAA;IAEvB,YAAY,sBAAsB,GAAG,IAAI;QACvC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,sBAAsB,CAAC,CAAA;QACrD,IAAI,CAAC,KAAK,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC,CAAA;IAClE,CAAC;IAED,+FAA+F;IAC/F,MAAM,CAAC,IAAY,EAAE,IAAe,EAAE,MAAc,EAAE,WAAmB,EAAE,MAAc;QACvF,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAAA;QAC/D,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClC,kGAAkG;YAClG,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAAA;YAC3E,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAW,CAAA;QAC7D,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC,CAAA;QAC7B,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,CAAA;QACjC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,KAAK,CAAC,CAAA;QACnC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,KAAK,CAAC,CAAA;QACxC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,KAAK,CAAC,CAAA;QACnC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAA;IAClB,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,KAAa;QACtB,MAAM,GAAG,GAAuB,EAAE,CAAA;QAClC,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAA;QACtD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAA;QAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7E,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,iBAAiB,CAAA;YACrD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAW,CAAA;YACvC,IAAI,IAAI,IAAI,KAAK;gBAAE,SAAQ;YAC3B,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI;gBACJ,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAc;gBACvC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAW;gBACtC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAW;gBAC3C,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAW;aACvC,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;IAC9B,CAAC;IAED,+EAA+E;IAC/E,QAAQ;QACN,IAAI,CAAC,MAAM,GAAG,CAAC,CAAA;QACf,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAA;IAC9B,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ComponentDef, ComponentId, Schema } from '@ecsia/schema';
|
|
2
|
+
import type { ComponentRuntime } from './component/index.js';
|
|
3
|
+
export declare class ComponentRegistry {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(..._legacy: readonly unknown[]);
|
|
6
|
+
register(components: readonly ComponentDef<Schema>[]): void;
|
|
7
|
+
/**
|
|
8
|
+
* Mint the next dense ComponentId WITHOUT binding a def (allocSyntheticComponentId).
|
|
9
|
+
* Pair/presence/overflow ids draw from the SAME dense space as ordinary
|
|
10
|
+
* components so storage, queries, and the bitmask treat them identically. Serial / main-thread.
|
|
11
|
+
*/
|
|
12
|
+
allocSyntheticId(): ComponentId;
|
|
13
|
+
/**
|
|
14
|
+
* Intern a synthetic ComponentDef (a relation presence/overflow def, or a per-pair def) at an id
|
|
15
|
+
* already minted by `allocSyntheticId`, so `defOf`/`idOf` resolve it and storage can build its
|
|
16
|
+
* ColumnSet. Serial / main-thread; relations is the only caller (the acyclic boundary holds —
|
|
17
|
+
* the world exposes this through a seam, core never imports relations).
|
|
18
|
+
*/
|
|
19
|
+
registerSynthetic(def: ComponentDef<Schema>, id: ComponentId): void;
|
|
20
|
+
idOf(def: ComponentDef<Schema>): ComponentId | undefined;
|
|
21
|
+
defOf(id: ComponentId): ComponentDef<Schema> | undefined;
|
|
22
|
+
/**: seeds the bitmask/sigWords fixed stride = ceil(nextComponentId/32) ( C4). */
|
|
23
|
+
get nextComponentId(): number;
|
|
24
|
+
}
|
|
25
|
+
export type { ComponentRuntime };
|
|
26
|
+
//# sourceMappingURL=registry.d.ts.map
|