@ecsia/core 0.3.0 → 0.5.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/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -2
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/query/compile.d.ts +7 -0
- package/dist/query/compile.d.ts.map +1 -1
- package/dist/query/compile.js +41 -2
- package/dist/query/compile.js.map +1 -1
- package/dist/reactivity/observer-commands.d.ts +1 -0
- package/dist/reactivity/observer-commands.d.ts.map +1 -1
- package/dist/reactivity/observer-commands.js +12 -0
- package/dist/reactivity/observer-commands.js.map +1 -1
- package/dist/topics/codec.d.ts +23 -0
- package/dist/topics/codec.d.ts.map +1 -0
- package/dist/topics/codec.js +113 -0
- package/dist/topics/codec.js.map +1 -0
- package/dist/topics/define.d.ts +44 -0
- package/dist/topics/define.d.ts.map +1 -0
- package/dist/topics/define.js +61 -0
- package/dist/topics/define.js.map +1 -0
- package/dist/topics/index.d.ts +7 -0
- package/dist/topics/index.d.ts.map +1 -0
- package/dist/topics/index.js +4 -0
- package/dist/topics/index.js.map +1 -0
- package/dist/topics/store.d.ts +83 -0
- package/dist/topics/store.d.ts.map +1 -0
- package/dist/topics/store.js +416 -0
- package/dist/topics/store.js.map +1 -0
- package/dist/world.d.ts +56 -0
- package/dist/world.d.ts.map +1 -1
- package/dist/world.js +119 -9
- package/dist/world.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// `defineTopic` — module-scope definition of a typed event queue, mirroring `defineComponent`:
|
|
2
|
+
// a pure descriptor with no world attached, interned (id minted) when a world first sees it.
|
|
3
|
+
// Topic payloads are schema'd rows: the same field-token set as components, MINUS the non-shareable
|
|
4
|
+
// tokens (`object<T>`, `'string'`) — an event row must be encodable to plain u32 words so it can
|
|
5
|
+
// live in the SAB-backed canonical ring and cross the worker boundary byte-deterministically.
|
|
6
|
+
import { resolveDescriptor, UNREGISTERED } from '../component/index.js';
|
|
7
|
+
const IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
8
|
+
function isFieldSpec(token) {
|
|
9
|
+
return typeof token === 'object' && token !== null && token.__fieldSpec === true;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Define a typed event queue. `schema` uses the component field tokens (`'f32'`, `'eid'`, `vec`,
|
|
13
|
+
* `staticString`, ...); `object<T>` and `'string'` fields are rejected — event rows are fixed-width
|
|
14
|
+
* u32 words so the stream is shareable, byte-deterministic, and serializable.
|
|
15
|
+
*
|
|
16
|
+
* `eid` payload fields carry the full generational handle with NO liveness validation on delivery:
|
|
17
|
+
* an event is a fact about the past, and the referenced entity may legitimately be dead by the time
|
|
18
|
+
* a consumer reads it (especially on next-frame delivery). Check `world.isAlive(ev.target)` if the
|
|
19
|
+
* consumer needs the entity.
|
|
20
|
+
*
|
|
21
|
+
* Like a `defineComponent` def, a topic def binds to ONE world: registration writes the minted id
|
|
22
|
+
* into the def, so a second world (another test, an HMR cycle) must call `defineTopic` afresh
|
|
23
|
+
* rather than reuse the module-scope def — reuse throws "already registered with another world".
|
|
24
|
+
*/
|
|
25
|
+
export function defineTopic(name, schema) {
|
|
26
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
27
|
+
throw new Error('defineTopic: a non-empty topic name is required');
|
|
28
|
+
}
|
|
29
|
+
if (typeof schema !== 'object' || schema === null || Array.isArray(schema)) {
|
|
30
|
+
throw new Error(`defineTopic('${name}'): schema must be a plain object`);
|
|
31
|
+
}
|
|
32
|
+
const fields = [];
|
|
33
|
+
for (const fieldName of Object.keys(schema)) {
|
|
34
|
+
if (!IDENT.test(fieldName) || fieldName.startsWith('__')) {
|
|
35
|
+
throw new Error(`defineTopic('${name}'): invalid field name '${fieldName}' (reserved __ prefix or non-identifier)`);
|
|
36
|
+
}
|
|
37
|
+
const raw = schema[fieldName];
|
|
38
|
+
const token = isFieldSpec(raw) ? raw.token : raw;
|
|
39
|
+
if (typeof token === 'object' && token !== null && token.kind === 'object') {
|
|
40
|
+
throw new Error(`defineTopic('${name}'): field '${fieldName}' is an object<T> field — object fields cannot live in a topic ring or cross the worker boundary (v1)`);
|
|
41
|
+
}
|
|
42
|
+
if (token === 'string') {
|
|
43
|
+
throw new Error(`defineTopic('${name}'): field '${fieldName}' is a free-form 'string' field — rich fields are sidecar-backed and cannot live in a topic ring (v1); use staticString(...) for enumerated strings`);
|
|
44
|
+
}
|
|
45
|
+
const descriptor = isFieldSpec(raw)
|
|
46
|
+
? resolveDescriptor(fieldName, raw.token, raw.default)
|
|
47
|
+
: resolveDescriptor(fieldName, raw);
|
|
48
|
+
fields.push(descriptor);
|
|
49
|
+
}
|
|
50
|
+
const def = {
|
|
51
|
+
name,
|
|
52
|
+
schema,
|
|
53
|
+
fields: Object.freeze(fields),
|
|
54
|
+
__ecsiaTopic: true,
|
|
55
|
+
};
|
|
56
|
+
// `id` is the registry's single commit point (mirrors ComponentRuntime): mutable so a world (or a
|
|
57
|
+
// worker aligning ids from the boot manifest) can intern the def after construction.
|
|
58
|
+
Object.defineProperty(def, 'id', { value: UNREGISTERED, enumerable: true, writable: true, configurable: true });
|
|
59
|
+
return Object.preventExtensions(def);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=define.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/topics/define.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,6FAA6F;AAC7F,oGAAoG;AACpG,iGAAiG;AACjG,8FAA8F;AAa9F,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAoCvE,MAAM,KAAK,GAAG,4BAA4B,CAAA;AAE1C,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAK,KAAmC,CAAC,WAAW,KAAK,IAAI,CAAA;AACjH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,WAAW,CAAiD,IAAO,EAAE,MAAS;IAC5F,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;IACpE,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,mCAAmC,CAAC,CAAA;IAC1E,CAAC;IACD,MAAM,MAAM,GAAsB,EAAE,CAAA;IACpC,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,2BAA2B,SAAS,0CAA0C,CAAC,CAAA;QACrH,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAe,CAAA;QAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAA;QAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAK,KAA2B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAClG,MAAM,IAAI,KAAK,CACb,gBAAgB,IAAI,cAAc,SAAS,uGAAuG,CACnJ,CAAA;QACH,CAAC;QACD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,gBAAgB,IAAI,cAAc,SAAS,qJAAqJ,CACjM,CAAA;QACH,CAAC;QACD,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC;YACjC,CAAC,CAAC,iBAAiB,CAAC,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;YACtD,CAAC,CAAC,iBAAiB,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;QACrC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IACzB,CAAC;IACD,MAAM,GAAG,GAAG;QACV,IAAI;QACJ,MAAM;QACN,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;QAC7B,YAAY,EAAE,IAAa;KACV,CAAA;IACnB,kGAAkG;IAClG,qFAAqF;IACrF,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/G,OAAO,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAA;AACtC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { defineTopic } from './define.js';
|
|
2
|
+
export type { TopicDef, TopicEvent, TopicEventInit, TopicFieldValue } from './define.js';
|
|
3
|
+
export { buildTopicCodec } from './codec.js';
|
|
4
|
+
export type { TopicCodec, TopicFieldCodec } from './codec.js';
|
|
5
|
+
export { Topics, TOPIC_HEADER_WORDS } from './store.js';
|
|
6
|
+
export type { TopicsConfig } from './store.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/topics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AACxF,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC7D,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/topics/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Schema } from '@ecsia/schema';
|
|
2
|
+
import type { Buffers } from '../memory/index.js';
|
|
3
|
+
import type { TopicDef } from './define.js';
|
|
4
|
+
/** Reserved-zero metadata words per event row (future: tick + publishing system; payload-only v1). */
|
|
5
|
+
export declare const TOPIC_HEADER_WORDS = 2;
|
|
6
|
+
export interface TopicsConfig {
|
|
7
|
+
readonly buffers: Buffers;
|
|
8
|
+
/** Mint the next dense ComponentId (the topic's virtual id; same space as relations' synthetics). */
|
|
9
|
+
readonly allocId: () => number;
|
|
10
|
+
readonly phase: () => 'serial' | 'wave';
|
|
11
|
+
readonly dev: boolean;
|
|
12
|
+
readonly warn: (message: string) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare class Topics {
|
|
15
|
+
#private;
|
|
16
|
+
constructor(cfg: TopicsConfig);
|
|
17
|
+
/** Number of topics registered with this world. Zero ⇒ every per-frame hook is a no-op. */
|
|
18
|
+
get count(): number;
|
|
19
|
+
/** Intern a topic with this world (idempotent): mints its virtual ComponentId + canonical ring. */
|
|
20
|
+
register(def: TopicDef<Schema>): void;
|
|
21
|
+
/** The topic's virtual ComponentId, or -1 if not registered. */
|
|
22
|
+
idOf(def: TopicDef<Schema>): number;
|
|
23
|
+
/** `(name, id)` pairs for worker id alignment (the boot manifest). */
|
|
24
|
+
manifest(): readonly {
|
|
25
|
+
name: string;
|
|
26
|
+
id: number;
|
|
27
|
+
}[];
|
|
28
|
+
/** Scheduler frame hooks: world.publish is illegal while an update is in progress. */
|
|
29
|
+
beginUpdate(): void;
|
|
30
|
+
endUpdate(): void;
|
|
31
|
+
/**
|
|
32
|
+
* `world.publish` — the outside-systems path (input/network handlers, between frames). Appends
|
|
33
|
+
* directly to the canonical stream in call order, ahead of wave 0 of the next frame. Registers
|
|
34
|
+
* the topic on first use. Serial phase only; inside a system body use `ctx.publish` instead
|
|
35
|
+
* (direct appends mid-update would bypass the SystemId canonicalization).
|
|
36
|
+
*/
|
|
37
|
+
publishOutside(def: TopicDef<Schema>, init: Record<string, unknown> | undefined): void;
|
|
38
|
+
/** `ctx.publish` (main-thread system) — encode now, stage to the system's segment. */
|
|
39
|
+
stageValues(def: TopicDef<Schema>, systemId: number, init: Record<string, unknown> | undefined): void;
|
|
40
|
+
/** OP_PUBLISH apply (worker publishes replayed at the command flush) — stage raw field words. */
|
|
41
|
+
stageWords(topicId: number, systemId: number, words: ArrayLike<number>, at: number, fieldWords: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* The wave's serial-slot merge: for every topic with staged events, sort the staging segments by
|
|
44
|
+
* publishing SystemId ascending and append each segment FIFO to the canonical stream. Runs once
|
|
45
|
+
* per wave, after the wave's command flush — the single canonicalization point for every
|
|
46
|
+
* execution mode.
|
|
47
|
+
*/
|
|
48
|
+
mergeStaged(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Eagerly position a reader's cursor at plan time. Before the first update has ever run
|
|
51
|
+
* (the FIRST plan), the cursor starts at the oldest retained event so `world.publish` calls made
|
|
52
|
+
* before `createScheduler` are still delivered; once any update has run, a newly-added reader
|
|
53
|
+
* (a late re-plan join) starts at the current head — no replay of stale retained events.
|
|
54
|
+
*/
|
|
55
|
+
initCursor(def: TopicDef<Schema>, readerKey: string): void;
|
|
56
|
+
/**
|
|
57
|
+
* Iterate the reader's unseen events up to the current visible head and advance its cursor —
|
|
58
|
+
* exactly-once per (reader, topic), independent cursors per reader (no drain stealing). The
|
|
59
|
+
* yielded view is pooled: read fields inside the loop, never store the view itself.
|
|
60
|
+
*
|
|
61
|
+
* A reader with no cursor starts at the oldest retained event (the manual-consumption default);
|
|
62
|
+
* scheduler consumers are positioned eagerly via `initCursor` at plan time — at the oldest
|
|
63
|
+
* retained event for the first plan (pre-plan `world.publish` events are delivered), at the
|
|
64
|
+
* current head for a re-plan join (no replay).
|
|
65
|
+
*/
|
|
66
|
+
consume(def: TopicDef<Schema>, readerKey: string): IterableIterator<Record<string, unknown>>;
|
|
67
|
+
/**
|
|
68
|
+
* Frame reset (serial, quiescent): drop events two frames old, fold any spill back into the ring
|
|
69
|
+
* (regrowing it to 2x the observed peak), and compact retained rows to the ring front.
|
|
70
|
+
*/
|
|
71
|
+
frameReset(): void;
|
|
72
|
+
/** Oldest retained / next sequence numbers for `def`. */
|
|
73
|
+
bounds(def: TopicDef<Schema>): {
|
|
74
|
+
tail: number;
|
|
75
|
+
head: number;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* A copy of the retained canonical stream `[tail, head)` in sequence order — the byte-identity
|
|
79
|
+
* surface the serial-equivalence suite compares across worker counts and transports.
|
|
80
|
+
*/
|
|
81
|
+
streamWords(def: TopicDef<Schema>): Uint32Array;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/topics/store.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,oBAAoB,CAAA;AAKpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,sGAAsG;AACtG,eAAO,MAAM,kBAAkB,IAAI,CAAA;AAoDnC,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,qGAAqG;IACrG,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAA;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,QAAQ,GAAG,MAAM,CAAA;IACvC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACzC;AAED,qBAAa,MAAM;;gBAoBL,GAAG,EAAE,YAAY;IAQ7B,2FAA2F;IAC3F,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,mGAAmG;IACnG,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI;IAsErC,gEAAgE;IAChE,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM;IAInC,sEAAsE;IACtE,QAAQ,IAAI,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE;IAInD,sFAAsF;IACtF,WAAW,IAAI,IAAI;IAQnB,SAAS,IAAI,IAAI;IAMjB;;;;;OAKG;IACH,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI;IAYtF,sFAAsF;IACtF,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI;IAMrG,iGAAiG;IACjG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAyB7G;;;;;OAKG;IACH,WAAW,IAAI,IAAI;IA8CnB;;;;;OAKG;IACH,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAK1D;;;;;;;;;OASG;IACF,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IA4B7F;;;OAGG;IACH,UAAU,IAAI,IAAI;IAqFlB,yDAAyD;IACzD,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAK7D;;;OAGG;IACH,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,WAAW;CAYhD"}
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
// The world-owned topic store: one canonical event stream per topic plus the per-system staging
|
|
2
|
+
// segments and per-(reader, topic) consume cursors.
|
|
3
|
+
//
|
|
4
|
+
// THE DETERMINISM CONTRACT (the reason this module exists): the total order of events within a
|
|
5
|
+
// topic is `(frame, wave, publishing SystemId ascending, per-system FIFO append order)`.
|
|
6
|
+
// `publish()` therefore NEVER appends to the canonical stream directly — it appends to a
|
|
7
|
+
// per-(topic, system) staging segment, and the wave's serial slot performs ONE segment sort by
|
|
8
|
+
// SystemId (`mergeStaged`). Worker publishes arrive in the same staging via OP_PUBLISH records
|
|
9
|
+
// replayed at the command flush; main-thread publishes stage directly. One code path, every
|
|
10
|
+
// execution mode, byte-identical stream — direct append would expose round/worker order, which
|
|
11
|
+
// varies with workerCount and greedy round packing.
|
|
12
|
+
//
|
|
13
|
+
// The canonical stream is mutated ONLY while world.phase === 'serial' (asserted): the merge runs in
|
|
14
|
+
// the wave's serial slot, so a system mid-wave reads a frozen stream with plain loads.
|
|
15
|
+
//
|
|
16
|
+
// Retention is double-buffered by frame (Bevy's model): at the frame reset entering frame N, every
|
|
17
|
+
// event belonging to frame N-2 or earlier is dropped, so every event is visible for at least one
|
|
18
|
+
// complete frame after the frame it was published in. `world.publish` calls between updates are
|
|
19
|
+
// stamped for the UPCOMING frame. Overflow inside one frame spills to a main-thread array and the
|
|
20
|
+
// ring is regrown to 2x the observed peak at the next frame reset — never a hard throw.
|
|
21
|
+
import { isSharedBacking } from '../memory/buffers.js';
|
|
22
|
+
import { UNREGISTERED } from '../component/index.js';
|
|
23
|
+
import { buildTopicCodec } from './codec.js';
|
|
24
|
+
/** Reserved-zero metadata words per event row (future: tick + publishing system; payload-only v1). */
|
|
25
|
+
export const TOPIC_HEADER_WORDS = 2;
|
|
26
|
+
const INITIAL_CAPACITY_ROWS = 256;
|
|
27
|
+
const NO_SPILL = Number.MAX_SAFE_INTEGER;
|
|
28
|
+
function nextPow2(n) {
|
|
29
|
+
let p = 1;
|
|
30
|
+
while (p < n)
|
|
31
|
+
p *= 2;
|
|
32
|
+
return p;
|
|
33
|
+
}
|
|
34
|
+
export class Topics {
|
|
35
|
+
#buffers;
|
|
36
|
+
#allocId;
|
|
37
|
+
#phase;
|
|
38
|
+
#dev;
|
|
39
|
+
#warn;
|
|
40
|
+
#byDef = new Map();
|
|
41
|
+
#byId = new Map();
|
|
42
|
+
#byName = new Map();
|
|
43
|
+
/** Topics with >= 1 staged segment this cycle — the O(1) merge-skip gate, not an event count. */
|
|
44
|
+
#stagedTopics = 0;
|
|
45
|
+
#inUpdate = false;
|
|
46
|
+
/**
|
|
47
|
+
* Has any update (or manual merge) ever run? Discriminates the FIRST plan from a late re-plan:
|
|
48
|
+
* a consumer in the first plan must see `world.publish` events appended before the plan existed
|
|
49
|
+
* (the input-event contract — "every system sees it next update"), while a consumer added by a
|
|
50
|
+
* re-plan after frames have run starts at the head (no replay of stale retained events).
|
|
51
|
+
*/
|
|
52
|
+
#everUpdated = false;
|
|
53
|
+
constructor(cfg) {
|
|
54
|
+
this.#buffers = cfg.buffers;
|
|
55
|
+
this.#allocId = cfg.allocId;
|
|
56
|
+
this.#phase = cfg.phase;
|
|
57
|
+
this.#dev = cfg.dev;
|
|
58
|
+
this.#warn = cfg.warn;
|
|
59
|
+
}
|
|
60
|
+
/** Number of topics registered with this world. Zero ⇒ every per-frame hook is a no-op. */
|
|
61
|
+
get count() {
|
|
62
|
+
return this.#byDef.size;
|
|
63
|
+
}
|
|
64
|
+
/** Intern a topic with this world (idempotent): mints its virtual ComponentId + canonical ring. */
|
|
65
|
+
register(def) {
|
|
66
|
+
if (this.#byDef.has(def))
|
|
67
|
+
return;
|
|
68
|
+
if (def.id !== UNREGISTERED) {
|
|
69
|
+
throw new Error(`topic '${def.name}' is already registered with another world`);
|
|
70
|
+
}
|
|
71
|
+
const collision = this.#byName.get(def.name);
|
|
72
|
+
if (collision !== undefined) {
|
|
73
|
+
throw new Error(`a different topic named '${def.name}' is already registered with this world — topic names must be unique per world`);
|
|
74
|
+
}
|
|
75
|
+
const id = this.#allocId();
|
|
76
|
+
def.id = id;
|
|
77
|
+
const codec = buildTopicCodec(def.fields);
|
|
78
|
+
const rowWords = TOPIC_HEADER_WORDS + codec.fieldWords;
|
|
79
|
+
const capacityWords = INITIAL_CAPACITY_ROWS * rowWords;
|
|
80
|
+
const region = this.#buffers.region(`topic.${def.name}.ring`, 'u32', capacityWords, {
|
|
81
|
+
maxLength: capacityWords * 16,
|
|
82
|
+
});
|
|
83
|
+
const view = {};
|
|
84
|
+
let curWords = region.view;
|
|
85
|
+
let curBase = 0;
|
|
86
|
+
for (const f of codec.fields) {
|
|
87
|
+
Object.defineProperty(view, f.name, {
|
|
88
|
+
enumerable: true,
|
|
89
|
+
get: () => f.decode(curWords, curBase + f.offset),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
const rt = {
|
|
93
|
+
def,
|
|
94
|
+
id,
|
|
95
|
+
name: def.name,
|
|
96
|
+
codec,
|
|
97
|
+
rowWords,
|
|
98
|
+
region,
|
|
99
|
+
ring: region.view,
|
|
100
|
+
baseSeq: 0,
|
|
101
|
+
tail: 0,
|
|
102
|
+
head: 0,
|
|
103
|
+
spill: [],
|
|
104
|
+
spillStartSeq: NO_SPILL,
|
|
105
|
+
prevFrameStart: 0,
|
|
106
|
+
frameEndHead: -1,
|
|
107
|
+
peakRows: 0,
|
|
108
|
+
staged: new Map(),
|
|
109
|
+
stagedEvents: 0,
|
|
110
|
+
cursors: new Map(),
|
|
111
|
+
view,
|
|
112
|
+
bind(words, base) {
|
|
113
|
+
curWords = words;
|
|
114
|
+
curBase = base;
|
|
115
|
+
},
|
|
116
|
+
scratchRow: new Uint32Array(Math.max(codec.fieldWords, 1)),
|
|
117
|
+
overflowWarned: false,
|
|
118
|
+
};
|
|
119
|
+
this.#byDef.set(def, rt);
|
|
120
|
+
this.#byId.set(id, rt);
|
|
121
|
+
this.#byName.set(def.name, rt);
|
|
122
|
+
}
|
|
123
|
+
#runtimeOf(def) {
|
|
124
|
+
const rt = this.#byDef.get(def);
|
|
125
|
+
if (rt === undefined) {
|
|
126
|
+
throw new Error(`topic '${def.name}' is not registered with this world — declare it in a system's publish/consume or publish it once via world.publish`);
|
|
127
|
+
}
|
|
128
|
+
return rt;
|
|
129
|
+
}
|
|
130
|
+
/** The topic's virtual ComponentId, or -1 if not registered. */
|
|
131
|
+
idOf(def) {
|
|
132
|
+
return this.#byDef.get(def)?.id ?? -1;
|
|
133
|
+
}
|
|
134
|
+
/** `(name, id)` pairs for worker id alignment (the boot manifest). */
|
|
135
|
+
manifest() {
|
|
136
|
+
return [...this.#byId.values()].map((rt) => ({ name: rt.name, id: rt.id }));
|
|
137
|
+
}
|
|
138
|
+
/** Scheduler frame hooks: world.publish is illegal while an update is in progress. */
|
|
139
|
+
beginUpdate() {
|
|
140
|
+
if (this.#inUpdate) {
|
|
141
|
+
throw new Error('topics: beginUpdate re-entered — a world update is already in progress (nested scheduler.update?)');
|
|
142
|
+
}
|
|
143
|
+
this.#inUpdate = true;
|
|
144
|
+
this.#everUpdated = true;
|
|
145
|
+
}
|
|
146
|
+
endUpdate() {
|
|
147
|
+
this.#inUpdate = false;
|
|
148
|
+
if (this.#byDef.size === 0)
|
|
149
|
+
return;
|
|
150
|
+
for (const rt of this.#byId.values())
|
|
151
|
+
rt.frameEndHead = rt.head;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* `world.publish` — the outside-systems path (input/network handlers, between frames). Appends
|
|
155
|
+
* directly to the canonical stream in call order, ahead of wave 0 of the next frame. Registers
|
|
156
|
+
* the topic on first use. Serial phase only; inside a system body use `ctx.publish` instead
|
|
157
|
+
* (direct appends mid-update would bypass the SystemId canonicalization).
|
|
158
|
+
*/
|
|
159
|
+
publishOutside(def, init) {
|
|
160
|
+
if (this.#inUpdate) {
|
|
161
|
+
throw new Error(`world.publish('${def.name}') called during world update — world.publish is for code outside systems; use the system's ctx.publish so the event enters the canonical (frame, wave, SystemId, FIFO) order`);
|
|
162
|
+
}
|
|
163
|
+
if (!this.#byDef.has(def))
|
|
164
|
+
this.register(def);
|
|
165
|
+
const rt = this.#runtimeOf(def);
|
|
166
|
+
rt.codec.encode(init, rt.scratchRow, 0);
|
|
167
|
+
this.#appendRow(rt, rt.scratchRow, 0);
|
|
168
|
+
}
|
|
169
|
+
/** `ctx.publish` (main-thread system) — encode now, stage to the system's segment. */
|
|
170
|
+
stageValues(def, systemId, init) {
|
|
171
|
+
const rt = this.#runtimeOf(def);
|
|
172
|
+
rt.codec.encode(init, rt.scratchRow, 0);
|
|
173
|
+
this.#stage(rt, systemId, rt.scratchRow, 0);
|
|
174
|
+
}
|
|
175
|
+
/** OP_PUBLISH apply (worker publishes replayed at the command flush) — stage raw field words. */
|
|
176
|
+
stageWords(topicId, systemId, words, at, fieldWords) {
|
|
177
|
+
const rt = this.#byId.get(topicId);
|
|
178
|
+
if (rt === undefined) {
|
|
179
|
+
this.#warn(`OP_PUBLISH names unknown topic id ${topicId}; record dropped`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (fieldWords !== rt.codec.fieldWords) {
|
|
183
|
+
this.#warn(`OP_PUBLISH for topic '${rt.name}' carries ${fieldWords} field words, expected ${rt.codec.fieldWords}; record dropped`);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
this.#stage(rt, systemId, words, at);
|
|
187
|
+
}
|
|
188
|
+
#stage(rt, systemId, words, at) {
|
|
189
|
+
let segment = rt.staged.get(systemId);
|
|
190
|
+
if (segment === undefined) {
|
|
191
|
+
segment = { words: [], events: 0 };
|
|
192
|
+
rt.staged.set(systemId, segment);
|
|
193
|
+
if (rt.staged.size === 1)
|
|
194
|
+
this.#stagedTopics += 1;
|
|
195
|
+
}
|
|
196
|
+
for (let i = 0; i < rt.codec.fieldWords; i++)
|
|
197
|
+
segment.words.push(words[at + i] >>> 0);
|
|
198
|
+
segment.events += 1;
|
|
199
|
+
rt.stagedEvents += 1;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* The wave's serial-slot merge: for every topic with staged events, sort the staging segments by
|
|
203
|
+
* publishing SystemId ascending and append each segment FIFO to the canonical stream. Runs once
|
|
204
|
+
* per wave, after the wave's command flush — the single canonicalization point for every
|
|
205
|
+
* execution mode.
|
|
206
|
+
*/
|
|
207
|
+
mergeStaged() {
|
|
208
|
+
this.#everUpdated = true;
|
|
209
|
+
if (this.#stagedTopics === 0)
|
|
210
|
+
return;
|
|
211
|
+
if (this.#phase() !== 'serial') {
|
|
212
|
+
throw new Error('topics: canonical stream merge attempted outside the serial phase');
|
|
213
|
+
}
|
|
214
|
+
for (const rt of this.#byId.values()) {
|
|
215
|
+
if (rt.stagedEvents === 0)
|
|
216
|
+
continue;
|
|
217
|
+
const systemIds = [...rt.staged.keys()].sort((a, b) => a - b);
|
|
218
|
+
const f = rt.codec.fieldWords;
|
|
219
|
+
for (const sid of systemIds) {
|
|
220
|
+
const segment = rt.staged.get(sid);
|
|
221
|
+
for (let e = 0; e < segment.events; e++)
|
|
222
|
+
this.#appendRow(rt, segment.words, e * f);
|
|
223
|
+
}
|
|
224
|
+
rt.staged.clear();
|
|
225
|
+
rt.stagedEvents = 0;
|
|
226
|
+
}
|
|
227
|
+
this.#stagedTopics = 0;
|
|
228
|
+
}
|
|
229
|
+
#appendRow(rt, words, at) {
|
|
230
|
+
if (this.#phase() !== 'serial') {
|
|
231
|
+
throw new Error(`topics: canonical stream for '${rt.name}' mutated outside the serial phase`);
|
|
232
|
+
}
|
|
233
|
+
const seq = rt.head;
|
|
234
|
+
const f = rt.codec.fieldWords;
|
|
235
|
+
if (rt.spillStartSeq === NO_SPILL && (seq - rt.baseSeq + 1) * rt.rowWords <= rt.ring.length) {
|
|
236
|
+
const base = (seq - rt.baseSeq) * rt.rowWords;
|
|
237
|
+
for (let i = 0; i < TOPIC_HEADER_WORDS; i++)
|
|
238
|
+
rt.ring[base + i] = 0;
|
|
239
|
+
for (let i = 0; i < f; i++)
|
|
240
|
+
rt.ring[base + TOPIC_HEADER_WORDS + i] = words[at + i] >>> 0;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
if (rt.spillStartSeq === NO_SPILL)
|
|
244
|
+
rt.spillStartSeq = seq;
|
|
245
|
+
for (let i = 0; i < TOPIC_HEADER_WORDS; i++)
|
|
246
|
+
rt.spill.push(0);
|
|
247
|
+
for (let i = 0; i < f; i++)
|
|
248
|
+
rt.spill.push(words[at + i] >>> 0);
|
|
249
|
+
if (this.#dev && !rt.overflowWarned) {
|
|
250
|
+
rt.overflowWarned = true;
|
|
251
|
+
this.#warn(`topic '${rt.name}' ring overflowed (${Math.floor(rt.ring.length / rt.rowWords)} rows); spilling — the ring grows to 2x peak at the next frame reset`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
rt.head = seq + 1;
|
|
255
|
+
const retained = rt.head - rt.tail;
|
|
256
|
+
if (retained > rt.peakRows)
|
|
257
|
+
rt.peakRows = retained;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Eagerly position a reader's cursor at plan time. Before the first update has ever run
|
|
261
|
+
* (the FIRST plan), the cursor starts at the oldest retained event so `world.publish` calls made
|
|
262
|
+
* before `createScheduler` are still delivered; once any update has run, a newly-added reader
|
|
263
|
+
* (a late re-plan join) starts at the current head — no replay of stale retained events.
|
|
264
|
+
*/
|
|
265
|
+
initCursor(def, readerKey) {
|
|
266
|
+
const rt = this.#runtimeOf(def);
|
|
267
|
+
if (!rt.cursors.has(readerKey))
|
|
268
|
+
rt.cursors.set(readerKey, this.#everUpdated ? rt.head : rt.tail);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Iterate the reader's unseen events up to the current visible head and advance its cursor —
|
|
272
|
+
* exactly-once per (reader, topic), independent cursors per reader (no drain stealing). The
|
|
273
|
+
* yielded view is pooled: read fields inside the loop, never store the view itself.
|
|
274
|
+
*
|
|
275
|
+
* A reader with no cursor starts at the oldest retained event (the manual-consumption default);
|
|
276
|
+
* scheduler consumers are positioned eagerly via `initCursor` at plan time — at the oldest
|
|
277
|
+
* retained event for the first plan (pre-plan `world.publish` events are delivered), at the
|
|
278
|
+
* current head for a re-plan join (no replay).
|
|
279
|
+
*/
|
|
280
|
+
*consume(def, readerKey) {
|
|
281
|
+
const rt = this.#runtimeOf(def);
|
|
282
|
+
let cursor = rt.cursors.get(readerKey) ?? rt.tail;
|
|
283
|
+
if (cursor < rt.tail) {
|
|
284
|
+
if (this.#dev) {
|
|
285
|
+
this.#warn(`topic '${rt.name}': reader '${readerKey}' missed ${rt.tail - cursor} event(s) dropped by retention; cursor snapped to the oldest retained event`);
|
|
286
|
+
}
|
|
287
|
+
cursor = rt.tail;
|
|
288
|
+
}
|
|
289
|
+
// The visible head is frozen for the duration of this iteration: merges happen only at serial
|
|
290
|
+
// slots, never while a system body runs, so `end` is the head as of the consumer's wave start.
|
|
291
|
+
const end = rt.head;
|
|
292
|
+
rt.cursors.set(readerKey, cursor);
|
|
293
|
+
for (let seq = cursor; seq < end; seq++) {
|
|
294
|
+
// Advance BEFORE the yield: a consumer that breaks out of the loop has still observed the
|
|
295
|
+
// yielded event, and exactly-once means it must not be redelivered next consume.
|
|
296
|
+
rt.cursors.set(readerKey, seq + 1);
|
|
297
|
+
if (seq >= rt.spillStartSeq) {
|
|
298
|
+
rt.bind(rt.spill, (seq - rt.spillStartSeq) * rt.rowWords + TOPIC_HEADER_WORDS);
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
rt.bind(rt.ring, (seq - rt.baseSeq) * rt.rowWords + TOPIC_HEADER_WORDS);
|
|
302
|
+
}
|
|
303
|
+
yield rt.view;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Frame reset (serial, quiescent): drop events two frames old, fold any spill back into the ring
|
|
308
|
+
* (regrowing it to 2x the observed peak), and compact retained rows to the ring front.
|
|
309
|
+
*/
|
|
310
|
+
frameReset() {
|
|
311
|
+
if (this.#byDef.size === 0)
|
|
312
|
+
return;
|
|
313
|
+
for (const rt of this.#byId.values()) {
|
|
314
|
+
// Frame boundary: events appended after the last update ended belong to the UPCOMING frame
|
|
315
|
+
// (the world.publish input-event path). Without a scheduler (no endUpdate), everything
|
|
316
|
+
// appended so far belongs to the frame now ending.
|
|
317
|
+
const boundary = rt.frameEndHead >= 0 ? rt.frameEndHead : rt.head;
|
|
318
|
+
const newTail = Math.max(rt.tail, rt.prevFrameStart);
|
|
319
|
+
rt.prevFrameStart = boundary;
|
|
320
|
+
rt.frameEndHead = -1;
|
|
321
|
+
this.#compact(rt, newTail);
|
|
322
|
+
rt.peakRows = rt.head - rt.tail;
|
|
323
|
+
rt.overflowWarned = false;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
#compact(rt, newTail) {
|
|
327
|
+
const retained = rt.head - newTail;
|
|
328
|
+
const needWords = retained * rt.rowWords;
|
|
329
|
+
const hadSpill = rt.spillStartSeq !== NO_SPILL;
|
|
330
|
+
if (hadSpill || needWords > rt.ring.length) {
|
|
331
|
+
// Regrow to 2x the frame's peak (never below what must be retained right now), then re-place
|
|
332
|
+
// every retained row contiguously from the front.
|
|
333
|
+
const targetRows = Math.max(retained, nextPow2(rt.peakRows * 2));
|
|
334
|
+
const rows = [];
|
|
335
|
+
for (let seq = newTail; seq < rt.head; seq++) {
|
|
336
|
+
const src = seq >= rt.spillStartSeq ? rt.spill : rt.ring;
|
|
337
|
+
const base = seq >= rt.spillStartSeq
|
|
338
|
+
? (seq - rt.spillStartSeq) * rt.rowWords
|
|
339
|
+
: (seq - rt.baseSeq) * rt.rowWords;
|
|
340
|
+
const row = [];
|
|
341
|
+
for (let i = 0; i < rt.rowWords; i++)
|
|
342
|
+
row.push(src[base + i]);
|
|
343
|
+
rows.push(row);
|
|
344
|
+
}
|
|
345
|
+
this.#growRing(rt, targetRows * rt.rowWords);
|
|
346
|
+
for (let r = 0; r < rows.length; r++) {
|
|
347
|
+
const base = r * rt.rowWords;
|
|
348
|
+
for (let i = 0; i < rt.rowWords; i++)
|
|
349
|
+
rt.ring[base + i] = rows[r][i];
|
|
350
|
+
}
|
|
351
|
+
rt.spill = [];
|
|
352
|
+
rt.spillStartSeq = NO_SPILL;
|
|
353
|
+
}
|
|
354
|
+
else if (newTail > rt.baseSeq) {
|
|
355
|
+
// Reclaim the dropped prefix in place so appends keep landing inside the ring.
|
|
356
|
+
rt.ring.copyWithin(0, (newTail - rt.baseSeq) * rt.rowWords, (rt.head - rt.baseSeq) * rt.rowWords);
|
|
357
|
+
}
|
|
358
|
+
rt.baseSeq = newTail;
|
|
359
|
+
rt.tail = newTail;
|
|
360
|
+
}
|
|
361
|
+
#growRing(rt, requiredWords) {
|
|
362
|
+
const region = rt.region;
|
|
363
|
+
const requiredBytes = requiredWords * 4;
|
|
364
|
+
if (requiredBytes <= region.backing.byteLength) {
|
|
365
|
+
rt.ring = region.view;
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
// The reactivity-ring growth protocol: in-place resizable grow when the reservation allows,
|
|
369
|
+
// else allocate-copy re-back (serial quiescent point; main thread is the only ring reader in
|
|
370
|
+
// v1 — worker-side consume, and with it the TopicRingGrown re-wrap notice, is the deferred leg).
|
|
371
|
+
const growable = region.backing;
|
|
372
|
+
const resizeFn = growable.grow ?? growable.resize;
|
|
373
|
+
const max = growable.maxByteLength;
|
|
374
|
+
if (typeof resizeFn === 'function' && typeof max === 'number' && requiredBytes <= max) {
|
|
375
|
+
try {
|
|
376
|
+
resizeFn.call(growable, requiredBytes);
|
|
377
|
+
region.view = new Uint32Array(region.backing);
|
|
378
|
+
rt.ring = region.view;
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
// fall through to re-back
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
const shared = isSharedBacking(region.backing);
|
|
386
|
+
const fresh = shared ? new SharedArrayBuffer(requiredBytes) : new ArrayBuffer(requiredBytes);
|
|
387
|
+
const freshView = new Uint32Array(fresh);
|
|
388
|
+
freshView.set(region.view);
|
|
389
|
+
region.backing = fresh;
|
|
390
|
+
region.view = freshView;
|
|
391
|
+
rt.ring = freshView;
|
|
392
|
+
}
|
|
393
|
+
// ---- introspection (tests, diagnostics) ------------------------------------------------------
|
|
394
|
+
/** Oldest retained / next sequence numbers for `def`. */
|
|
395
|
+
bounds(def) {
|
|
396
|
+
const rt = this.#runtimeOf(def);
|
|
397
|
+
return { tail: rt.tail, head: rt.head };
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* A copy of the retained canonical stream `[tail, head)` in sequence order — the byte-identity
|
|
401
|
+
* surface the serial-equivalence suite compares across worker counts and transports.
|
|
402
|
+
*/
|
|
403
|
+
streamWords(def) {
|
|
404
|
+
const rt = this.#runtimeOf(def);
|
|
405
|
+
const out = new Uint32Array((rt.head - rt.tail) * rt.rowWords);
|
|
406
|
+
let w = 0;
|
|
407
|
+
for (let seq = rt.tail; seq < rt.head; seq++) {
|
|
408
|
+
const src = seq >= rt.spillStartSeq ? rt.spill : rt.ring;
|
|
409
|
+
const base = seq >= rt.spillStartSeq ? (seq - rt.spillStartSeq) * rt.rowWords : (seq - rt.baseSeq) * rt.rowWords;
|
|
410
|
+
for (let i = 0; i < rt.rowWords; i++)
|
|
411
|
+
out[w++] = src[base + i];
|
|
412
|
+
}
|
|
413
|
+
return out;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/topics/store.ts"],"names":[],"mappings":"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"}
|