@vworlds/vecs 1.0.15 → 1.0.17

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 (181) hide show
  1. package/README.md +249 -119
  2. package/dist/component.d.ts +52 -76
  3. package/dist/component.js +60 -45
  4. package/dist/component.js.map +1 -1
  5. package/dist/component_meta.d.ts +98 -0
  6. package/dist/component_meta.js +65 -0
  7. package/dist/component_meta.js.map +1 -0
  8. package/dist/dsl.d.ts +46 -34
  9. package/dist/dsl.js +459 -61
  10. package/dist/dsl.js.map +1 -1
  11. package/dist/entity/entity.base.d.ts +57 -0
  12. package/dist/entity/entity.base.js +81 -0
  13. package/dist/entity/entity.base.js.map +1 -0
  14. package/dist/entity/entity.components.d.ts +117 -0
  15. package/dist/entity/entity.components.js +244 -0
  16. package/dist/entity/entity.components.js.map +1 -0
  17. package/dist/entity/entity.d.ts +35 -0
  18. package/dist/entity/entity.identity.d.ts +8 -0
  19. package/dist/entity/entity.identity.js +15 -0
  20. package/dist/entity/entity.identity.js.map +1 -0
  21. package/dist/entity/entity.js +33 -0
  22. package/dist/entity/entity.js.map +1 -0
  23. package/dist/entity/entity.lifecycle.d.ts +12 -0
  24. package/dist/entity/entity.lifecycle.js +111 -0
  25. package/dist/entity/entity.lifecycle.js.map +1 -0
  26. package/dist/entity/entity.queries.d.ts +3 -0
  27. package/dist/entity/entity.queries.js +33 -0
  28. package/dist/entity/entity.queries.js.map +1 -0
  29. package/dist/entity/entity.relationships.d.ts +9 -0
  30. package/dist/entity/entity.relationships.js +74 -0
  31. package/dist/entity/entity.relationships.js.map +1 -0
  32. package/dist/entity/index.d.ts +2 -0
  33. package/dist/entity/index.js +3 -0
  34. package/dist/entity/index.js.map +1 -0
  35. package/dist/filter.d.ts +27 -8
  36. package/dist/filter.js +33 -18
  37. package/dist/filter.js.map +1 -1
  38. package/dist/index.d.ts +13 -5
  39. package/dist/index.js +13 -2
  40. package/dist/index.js.map +1 -1
  41. package/dist/inject.d.ts +80 -0
  42. package/dist/inject.js +270 -0
  43. package/dist/inject.js.map +1 -0
  44. package/dist/module.d.ts +23 -0
  45. package/dist/module.js +17 -0
  46. package/dist/module.js.map +1 -0
  47. package/dist/modules/identity.d.ts +15 -0
  48. package/dist/modules/identity.js +41 -0
  49. package/dist/modules/identity.js.map +1 -0
  50. package/dist/modules/singleton.d.ts +26 -0
  51. package/dist/modules/singleton.js +41 -0
  52. package/dist/modules/singleton.js.map +1 -0
  53. package/dist/package.json +12 -1
  54. package/dist/phase.d.ts +2 -2
  55. package/dist/query/index.d.ts +6 -0
  56. package/dist/query/index.js +5 -0
  57. package/dist/query/index.js.map +1 -0
  58. package/dist/query/query.00.base.d.ts +23 -0
  59. package/dist/query/query.00.base.js +77 -0
  60. package/dist/query/query.00.base.js.map +1 -0
  61. package/dist/query/query.01.reactive.d.ts +7 -0
  62. package/dist/query/query.01.reactive.js +58 -0
  63. package/dist/query/query.01.reactive.js.map +1 -0
  64. package/dist/query/query.02.lifecycle.d.ts +6 -0
  65. package/dist/query/query.02.lifecycle.js +63 -0
  66. package/dist/query/query.02.lifecycle.js.map +1 -0
  67. package/dist/query/query.03.tracking.d.ts +15 -0
  68. package/dist/query/query.03.tracking.js +31 -0
  69. package/dist/query/query.03.tracking.js.map +1 -0
  70. package/dist/query/query.04.callbacks.d.ts +14 -0
  71. package/dist/query/query.04.callbacks.js +65 -0
  72. package/dist/query/query.04.callbacks.js.map +1 -0
  73. package/dist/query/query.05.updates.d.ts +14 -0
  74. package/dist/query/query.05.updates.js +81 -0
  75. package/dist/query/query.05.updates.js.map +1 -0
  76. package/dist/query/query.06.predicate.d.ts +13 -0
  77. package/dist/query/query.06.predicate.js +40 -0
  78. package/dist/query/query.06.predicate.js.map +1 -0
  79. package/dist/query/query.07.groups.d.ts +41 -0
  80. package/dist/query/query.07.groups.js +110 -0
  81. package/dist/query/query.07.groups.js.map +1 -0
  82. package/dist/query/query.d.ts +53 -0
  83. package/dist/query/query.js +138 -0
  84. package/dist/query/query.js.map +1 -0
  85. package/dist/relationship.d.ts +19 -0
  86. package/dist/relationship.js +18 -0
  87. package/dist/relationship.js.map +1 -0
  88. package/dist/system.d.ts +37 -23
  89. package/dist/system.js +80 -64
  90. package/dist/system.js.map +1 -1
  91. package/dist/terms/all_term.d.ts +32 -0
  92. package/dist/terms/all_term.js +41 -0
  93. package/dist/terms/all_term.js.map +1 -0
  94. package/dist/terms/any_term.d.ts +33 -0
  95. package/dist/terms/any_term.js +42 -0
  96. package/dist/terms/any_term.js.map +1 -0
  97. package/dist/terms/build.d.ts +62 -0
  98. package/dist/terms/build.js +382 -0
  99. package/dist/terms/build.js.map +1 -0
  100. package/dist/terms/component_term.d.ts +37 -0
  101. package/dist/terms/component_term.js +49 -0
  102. package/dist/terms/component_term.js.map +1 -0
  103. package/dist/terms/empty_term.d.ts +6 -0
  104. package/dist/terms/empty_term.js +12 -0
  105. package/dist/terms/empty_term.js.map +1 -0
  106. package/dist/terms/index.d.ts +11 -0
  107. package/dist/terms/index.js +12 -0
  108. package/dist/terms/index.js.map +1 -0
  109. package/dist/terms/not_term.d.ts +35 -0
  110. package/dist/terms/not_term.js +47 -0
  111. package/dist/terms/not_term.js.map +1 -0
  112. package/dist/terms/only_term.d.ts +47 -0
  113. package/dist/terms/only_term.js +79 -0
  114. package/dist/terms/only_term.js.map +1 -0
  115. package/dist/terms/predicate_term.d.ts +80 -0
  116. package/dist/terms/predicate_term.js +109 -0
  117. package/dist/terms/predicate_term.js.map +1 -0
  118. package/dist/terms/target_term.d.ts +43 -0
  119. package/dist/terms/target_term.js +87 -0
  120. package/dist/terms/target_term.js.map +1 -0
  121. package/dist/terms/term.d.ts +94 -0
  122. package/dist/terms/term.js +202 -0
  123. package/dist/terms/term.js.map +1 -0
  124. package/dist/terms/world_term.d.ts +68 -0
  125. package/dist/terms/world_term.js +99 -0
  126. package/dist/terms/world_term.js.map +1 -0
  127. package/dist/timer.js +2 -2
  128. package/dist/timer.js.map +1 -1
  129. package/dist/util/array_map.js +12 -0
  130. package/dist/util/array_map.js.map +1 -1
  131. package/dist/util/bitset.js +107 -22
  132. package/dist/util/bitset.js.map +1 -1
  133. package/dist/util/dense_set.d.ts +1 -0
  134. package/dist/util/dense_set.js +90 -0
  135. package/dist/util/dense_set.js.map +1 -0
  136. package/dist/util/id_pool.d.ts +30 -0
  137. package/dist/util/id_pool.js +222 -0
  138. package/dist/util/id_pool.js.map +1 -0
  139. package/dist/world/index.d.ts +3 -0
  140. package/dist/world/index.js +3 -0
  141. package/dist/world/index.js.map +1 -0
  142. package/dist/world/world.base.d.ts +6 -0
  143. package/dist/world/world.base.js +21 -0
  144. package/dist/world/world.base.js.map +1 -0
  145. package/dist/world/world.components.d.ts +67 -0
  146. package/dist/world/world.components.js +93 -0
  147. package/dist/world/world.components.js.map +1 -0
  148. package/dist/world/world.d.ts +29 -0
  149. package/dist/world/world.deferred.d.ts +13 -0
  150. package/dist/world/world.deferred.js +93 -0
  151. package/dist/world/world.deferred.js.map +1 -0
  152. package/dist/world/world.entities.d.ts +18 -0
  153. package/dist/world/world.entities.js +97 -0
  154. package/dist/world/world.entities.js.map +1 -0
  155. package/dist/world/world.js +39 -0
  156. package/dist/world/world.js.map +1 -0
  157. package/dist/world/world.modules.d.ts +12 -0
  158. package/dist/world/world.modules.js +21 -0
  159. package/dist/world/world.modules.js.map +1 -0
  160. package/dist/world/world.pipeline.d.ts +21 -0
  161. package/dist/world/world.pipeline.js +106 -0
  162. package/dist/world/world.pipeline.js.map +1 -0
  163. package/dist/world/world.pools.d.ts +9 -0
  164. package/dist/world/world.pools.js +63 -0
  165. package/dist/world/world.pools.js.map +1 -0
  166. package/dist/world/world.queries.d.ts +18 -0
  167. package/dist/world/world.queries.js +101 -0
  168. package/dist/world/world.queries.js.map +1 -0
  169. package/dist/world/world.storage.d.ts +7 -0
  170. package/dist/world/world.storage.js +26 -0
  171. package/dist/world/world.storage.js.map +1 -0
  172. package/package.json +12 -1
  173. package/dist/entity.d.ts +0 -215
  174. package/dist/entity.js +0 -457
  175. package/dist/entity.js.map +0 -1
  176. package/dist/query.d.ts +0 -251
  177. package/dist/query.js +0 -353
  178. package/dist/query.js.map +0 -1
  179. package/dist/world.d.ts +0 -389
  180. package/dist/world.js +0 -631
  181. package/dist/world.js.map +0 -1
@@ -0,0 +1,87 @@
1
+ import { Term } from "./term.js";
2
+ /**
3
+ * Composite term that matches entities whose relationship target satisfies a
4
+ * given inner predicate.
5
+ *
6
+ * An entity `e` matches when it carries the relationship component
7
+ * `_relationshipEid` **and** the target entity stored in that component
8
+ * satisfies `_innerTerm`.
9
+ *
10
+ * Children: `[relationshipTerm, innerTerm]`.
11
+ * - `children[0]` (`relationshipTerm`): the `ComponentTerm` for the
12
+ * relationship eid — fires when the relationship is added/removed from `e`.
13
+ * - `children[1]` (`innerTerm`): the term for the inner DSL — fires when the
14
+ * target entity transitions in or out.
15
+ *
16
+ * ## Non-standard event routing
17
+ *
18
+ * `TargetTerm` overrides `_onChildEvent` and `_onChildRefresh` to implement
19
+ * a **fan-out** strategy: when the inner term changes (the target enters or
20
+ * exits), all *sources* that point at that target via the relationship must be
21
+ * re-evaluated. This reverses the normal bottom-up signal direction. The
22
+ * fan-out is why `TargetTerm` subtrees are excluded from diamond collapsing —
23
+ * a plain compiled predicate cannot replicate this per-source walk.
24
+ */
25
+ export class TargetTerm extends Term {
26
+ constructor(world, key, _relationshipEid, relationshipTerm, _innerTerm, onDestroy) {
27
+ super(world, key, "target", false, onDestroy);
28
+ this._relationshipEid = _relationshipEid;
29
+ this._innerTerm = _innerTerm;
30
+ this._setChildren([relationshipTerm, _innerTerm]);
31
+ this._initializeFromWorld();
32
+ }
33
+ /**
34
+ * Build a `TargetTerm` for the given relationship eid and inner DSL.
35
+ *
36
+ * @param world - Owning world.
37
+ * @param relationshipEid - Numeric eid of the relationship component type.
38
+ * @param innerDSL - DSL expression the relationship target must satisfy.
39
+ * @param key - Canonical cache key.
40
+ * @param getTerm - Term canonicalizer / cache accessor.
41
+ * @param onDestroy - Called when the last consumer unsubscribes.
42
+ */
43
+ static build(world, relationshipEid, innerDSL, key, getTerm, onDestroy) {
44
+ const relationshipTerm = getTerm(world, relationshipEid);
45
+ const innerTerm = getTerm(world, innerDSL);
46
+ return new TargetTerm(world, key, relationshipEid, relationshipTerm, innerTerm, onDestroy);
47
+ }
48
+ /**
49
+ * @internal Fan-out child membership event handler.
50
+ *
51
+ * When the relationship component is added/removed from `entity`
52
+ * (`child === children[0]`), re-evaluate that entity directly. When the
53
+ * inner term changes for some target entity (`child === children[1]`), walk
54
+ * every source entity that points at that target via the relationship and
55
+ * re-evaluate each one.
56
+ */
57
+ _onChildEvent(_kind, entity, child) {
58
+ if (child === this._children[0]) {
59
+ this._sync(entity);
60
+ return;
61
+ }
62
+ entity.children(this._relationshipEid).forEach((source) => this._sync(source));
63
+ }
64
+ /**
65
+ * @internal Fan-out child refresh handler.
66
+ *
67
+ * Mirrors `_onChildEvent`: a data/shape change on the relationship component
68
+ * or the inner term may alter whether a source entity matches, so the same
69
+ * fan-out logic applies.
70
+ */
71
+ _onChildRefresh(entity, child) {
72
+ if (child === this._children[0]) {
73
+ this._sync(entity);
74
+ return;
75
+ }
76
+ entity.children(this._relationshipEid).forEach((source) => this._sync(source));
77
+ }
78
+ /** @internal */
79
+ _matches(entity) {
80
+ if (entity._destroyed) {
81
+ return false;
82
+ }
83
+ const target = entity._get(this._relationshipEid)?.target;
84
+ return target !== undefined && this._innerTerm.has(target);
85
+ }
86
+ }
87
+ //# sourceMappingURL=target_term.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"target_term.js","sourceRoot":"","sources":["../../src/terms/target_term.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAiB,MAAM,WAAW,CAAC;AAGhD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,UAAW,SAAQ,IAAI;IAClC,YACE,KAAY,EACZ,GAAW,EACM,gBAAwB,EACzC,gBAAsB,EACL,UAAgB,EACjC,SAA+B;QAE/B,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QAL7B,qBAAgB,GAAhB,gBAAgB,CAAQ;QAExB,eAAU,GAAV,UAAU,CAAM;QAIjC,IAAI,CAAC,YAAY,CAAC,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;;;;;OASG;IACI,MAAM,CAAC,KAAK,CACjB,KAAY,EACZ,eAAuB,EACvB,QAAkB,EAClB,GAAW,EACX,OAAyB,EACzB,SAA+B;QAE/B,MAAM,gBAAgB,GAAG,OAAO,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;QACzD,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC3C,OAAO,IAAI,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC7F,CAAC;IAED;;;;;;;;OAQG;IACgB,aAAa,CAAC,KAAoB,EAAE,MAAc,EAAE,KAAW;QAChF,IAAI,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACjF,CAAC;IAED;;;;;;OAMG;IACgB,eAAe,CAAC,MAAc,EAAE,KAAW;QAC5D,IAAI,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACjF,CAAC;IAED,gBAAgB;IACN,QAAQ,CAAC,MAAc;QAC/B,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,MAAM,GAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAA8B,EAAE,MAAM,CAAC;QACxF,OAAO,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7D,CAAC;CACF"}
@@ -0,0 +1,94 @@
1
+ import type { Entity } from "../entity/index.js";
2
+ import type { World } from "../world/index.js";
3
+ export declare const enum TermEventKind {
4
+ Enter = 0,
5
+ Exit = 1
6
+ }
7
+ /**
8
+ * Observer interface for a `Term` node.
9
+ *
10
+ * ## Two-signal contract
11
+ *
12
+ * Consumers receive two independent channels:
13
+ *
14
+ * - **`onTermEvent`** — the ordered **membership stream**. Only real
15
+ * enter/exit flips are emitted here (no spurious duplicates). Every
16
+ * consumer — including `Query`, `System`, and composite parent terms —
17
+ * implements this method. It is the sole authoritative source of "who is
18
+ * in the set".
19
+ *
20
+ * - **`onTermRefresh`** — an *optional* **invalidation hint**. It signals
21
+ * that an entity's data or shape changed but membership *may* not have.
22
+ * Only composite terms that need to pull-recompute on data changes
23
+ * (e.g. `PredicateTerm`, `OnlyTerm`) implement this; membership-only
24
+ * consumers such as `Query` omit it and are never woken by pure data
25
+ * updates. The `?` makes the method optional so implementors that do not
26
+ * care about data refreshes pay zero overhead.
27
+ */
28
+ export interface TermConsumer {
29
+ /** Ordered membership stream. Only real enter/exit flips are emitted here. */
30
+ onTermEvent(kind: TermEventKind, entity: Entity): void;
31
+ }
32
+ export type TermKind = "world" | "component" | "empty" | "all" | "any" | "not" | "only" | "predicate" | "target" | "merged";
33
+ /**
34
+ * Base class for all reactive entity-set nodes in the term graph.
35
+ *
36
+ * A `Term` maintains a live `Set<Entity>` of every entity currently satisfying
37
+ * its sub-predicate. It subscribes to its children via the two-signal contract
38
+ * defined on {@link TermConsumer} and propagates enter/exit events upward to
39
+ * its own consumers.
40
+ *
41
+ * Subclasses implement `_matches` (the membership test) and may override
42
+ * `_onChildEvent`, `_onChildRefresh`, or `onTermRefresh` to customize how
43
+ * signals from children are interpreted.
44
+ */
45
+ export declare abstract class Term implements TermConsumer {
46
+ readonly world: World;
47
+ readonly key: string;
48
+ readonly kind: TermKind;
49
+ private readonly _pinned;
50
+ private readonly _onDestroy;
51
+ private _destroyed;
52
+ private readonly _childUnsubscribes;
53
+ protected constructor(world: World, key: string, kind: TermKind, _pinned: boolean, _onDestroy: (term: Term) => void);
54
+ get count(): number;
55
+ [Symbol.iterator](): IterableIterator<Entity>;
56
+ children(): readonly Term[];
57
+ has(entity: Entity): boolean;
58
+ /**
59
+ * Default membership-event handler: re-run `_matches` and add/remove
60
+ * accordingly. Composite terms typically let this default run; leaf terms
61
+ * use explicit `_add`/`_delete` calls instead and never receive child events.
62
+ */
63
+ onTermEvent(_kind: TermEventKind, entity: Entity): void;
64
+ /**
65
+ * Default invalidation-hint handler: re-run `_matches` via `_sync`.
66
+ *
67
+ * Terms that should *not* re-evaluate on a data/shape refresh (e.g.
68
+ * `NotTerm`) override this with a no-op. Terms that need the shape channel
69
+ * but want to override the full handler (e.g. `OnlyTerm`) override with a
70
+ * call to `_sync` as well — this default is already correct for most cases.
71
+ */
72
+ onTermRefresh(entity: Entity): void;
73
+ /**
74
+ * Add `consumer` to the set of active consumers and return an unsubscribe
75
+ * function.
76
+ *
77
+ * Consumer count drives term lifetime: when the count falls to zero on a
78
+ * non-pinned term the term destroys itself and cascades destruction to
79
+ * children. Calling the unsubscribe function more than once is safe (idempotent).
80
+ *
81
+ * @throws If the term has already been destroyed.
82
+ */
83
+ subscribe(consumer: TermConsumer): () => void;
84
+ /**
85
+ * Permanently destroy this term.
86
+ *
87
+ * Clears all consumers, unsubscribes from all children (cascading
88
+ * destruction when their consumer counts reach zero), clears the entity
89
+ * set, and calls `_onDestroy` to remove the term from the world cache.
90
+ * Pinned terms (`WorldTerm`, `ComponentTerm`, `EmptyTerm`) ignore this call.
91
+ */
92
+ destroy(): void;
93
+ private _emit;
94
+ }
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Base class for all reactive entity-set nodes in the term graph.
3
+ *
4
+ * A `Term` maintains a live `Set<Entity>` of every entity currently satisfying
5
+ * its sub-predicate. It subscribes to its children via the two-signal contract
6
+ * defined on {@link TermConsumer} and propagates enter/exit events upward to
7
+ * its own consumers.
8
+ *
9
+ * Subclasses implement `_matches` (the membership test) and may override
10
+ * `_onChildEvent`, `_onChildRefresh`, or `onTermRefresh` to customize how
11
+ * signals from children are interpreted.
12
+ */
13
+ export class Term {
14
+ constructor(world, key, kind, _pinned, _onDestroy) {
15
+ this.world = world;
16
+ this.key = key;
17
+ this.kind = kind;
18
+ this._pinned = _pinned;
19
+ this._onDestroy = _onDestroy;
20
+ /** @internal */
21
+ this._children = [];
22
+ /** @internal */
23
+ this._consumers = new Set();
24
+ /** @internal */
25
+ this._entities = new Set();
26
+ this._destroyed = false;
27
+ this._childUnsubscribes = [];
28
+ }
29
+ get count() {
30
+ return this._entities.size;
31
+ }
32
+ [Symbol.iterator]() {
33
+ return this._entities[Symbol.iterator]();
34
+ }
35
+ children() {
36
+ return this._children;
37
+ }
38
+ has(entity) {
39
+ return this._entities.has(entity);
40
+ }
41
+ /**
42
+ * Default membership-event handler: re-run `_matches` and add/remove
43
+ * accordingly. Composite terms typically let this default run; leaf terms
44
+ * use explicit `_add`/`_delete` calls instead and never receive child events.
45
+ */
46
+ onTermEvent(_kind, entity) {
47
+ this._sync(entity);
48
+ }
49
+ /**
50
+ * Default invalidation-hint handler: re-run `_matches` via `_sync`.
51
+ *
52
+ * Terms that should *not* re-evaluate on a data/shape refresh (e.g.
53
+ * `NotTerm`) override this with a no-op. Terms that need the shape channel
54
+ * but want to override the full handler (e.g. `OnlyTerm`) override with a
55
+ * call to `_sync` as well — this default is already correct for most cases.
56
+ */
57
+ onTermRefresh(entity) {
58
+ this._sync(entity);
59
+ }
60
+ /**
61
+ * Add `consumer` to the set of active consumers and return an unsubscribe
62
+ * function.
63
+ *
64
+ * Consumer count drives term lifetime: when the count falls to zero on a
65
+ * non-pinned term the term destroys itself and cascades destruction to
66
+ * children. Calling the unsubscribe function more than once is safe (idempotent).
67
+ *
68
+ * @throws If the term has already been destroyed.
69
+ */
70
+ subscribe(consumer) {
71
+ if (this._destroyed) {
72
+ throw new Error(`Cannot subscribe to destroyed ${this.kind} term`);
73
+ }
74
+ this._consumers.add(consumer);
75
+ let active = true;
76
+ return () => {
77
+ if (!active) {
78
+ return;
79
+ }
80
+ active = false;
81
+ this._consumers.delete(consumer);
82
+ if (!this._pinned && this._consumers.size === 0) {
83
+ this.destroy();
84
+ }
85
+ };
86
+ }
87
+ /**
88
+ * Permanently destroy this term.
89
+ *
90
+ * Clears all consumers, unsubscribes from all children (cascading
91
+ * destruction when their consumer counts reach zero), clears the entity
92
+ * set, and calls `_onDestroy` to remove the term from the world cache.
93
+ * Pinned terms (`WorldTerm`, `ComponentTerm`, `EmptyTerm`) ignore this call.
94
+ */
95
+ destroy() {
96
+ if (this._destroyed || this._pinned) {
97
+ return;
98
+ }
99
+ this._destroyed = true;
100
+ this._consumers.clear();
101
+ while (this._childUnsubscribes.length > 0) {
102
+ this._childUnsubscribes.pop()();
103
+ }
104
+ this._entities.clear();
105
+ this._onDestroy(this);
106
+ }
107
+ /** @internal Emit an enter event and add entity; no-op if already present. */
108
+ _add(entity) {
109
+ if (this._entities.has(entity)) {
110
+ return;
111
+ }
112
+ this._entities.add(entity);
113
+ this._emit(0 /* TermEventKind.Enter */, entity);
114
+ }
115
+ /** @internal Emit an exit event and remove entity; no-op if not present. */
116
+ _delete(entity) {
117
+ if (!this._entities.delete(entity)) {
118
+ return;
119
+ }
120
+ this._emit(1 /* TermEventKind.Exit */, entity);
121
+ }
122
+ /** @internal Propagate a refresh hint to all consumers (both channels). */
123
+ _emitRefresh(entity) {
124
+ this._consumers.forEach((consumer) => consumer.onTermRefresh?.(entity));
125
+ }
126
+ /** @internal Register an additional cleanup callback run during `destroy`. */
127
+ _addChildCleanup(cleanup) {
128
+ this._childUnsubscribes.push(cleanup);
129
+ }
130
+ /**
131
+ * @internal Seed the entity set from the current world state without
132
+ * emitting events.
133
+ *
134
+ * Called once at the end of construction so the term starts up-to-date
135
+ * before any consumers subscribe.
136
+ */
137
+ _initializeFromWorld() {
138
+ this.world.entities.forEach((entity) => {
139
+ if (this._matches(entity)) {
140
+ this._entities.add(entity);
141
+ }
142
+ });
143
+ }
144
+ /**
145
+ * @internal Register `children` as this term's child nodes.
146
+ *
147
+ * For each child, subscribes **both** channels via an anonymous
148
+ * `TermConsumer` that routes to `_onChildEvent` and `_onChildRefresh`.
149
+ * Registering both channels here (rather than in subclass constructors)
150
+ * ensures that every composite term receives refresh hints without
151
+ * boilerplate — subclasses then filter in `_onChildRefresh` to decide
152
+ * whether to act.
153
+ */
154
+ _setChildren(children) {
155
+ this._children.push(...children);
156
+ children.forEach((child) => {
157
+ this._childUnsubscribes.push(child.subscribe({
158
+ onTermEvent: (kind, entity) => this._onChildEvent(kind, entity, child),
159
+ onTermRefresh: (entity) => this._onChildRefresh(entity, child),
160
+ }));
161
+ });
162
+ }
163
+ /**
164
+ * @internal Default child membership-event handler: forward to
165
+ * `onTermEvent`. Composite terms (e.g. `TargetTerm`) override this to
166
+ * implement non-trivial fan-out logic.
167
+ */
168
+ _onChildEvent(kind, entity, _child) {
169
+ this.onTermEvent(kind, entity);
170
+ }
171
+ /**
172
+ * @internal Default child refresh handler: forward to `onTermRefresh`.
173
+ *
174
+ * Most composites delegate to `onTermRefresh` which defaults to `_sync`.
175
+ * Subclasses that only want to react to *specific* child kinds (e.g.
176
+ * `PredicateTerm` reacting only to component-kind children) override this
177
+ * to filter before calling `_sync`.
178
+ */
179
+ _onChildRefresh(entity, _child) {
180
+ this.onTermRefresh(entity);
181
+ }
182
+ /**
183
+ * @internal Pull-recompute membership for `entity`.
184
+ *
185
+ * Re-evaluates `_matches` and calls `_add` or `_delete`. Because `_add` and
186
+ * `_delete` are idempotent, `_sync` is safe to call redundantly — it emits
187
+ * an event only on a real flip, which is the core of the glitch-free
188
+ * propagation guarantee.
189
+ */
190
+ _sync(entity) {
191
+ if (this._matches(entity)) {
192
+ this._add(entity);
193
+ }
194
+ else {
195
+ this._delete(entity);
196
+ }
197
+ }
198
+ _emit(kind, entity) {
199
+ this._consumers.forEach((consumer) => consumer.onTermEvent(kind, entity));
200
+ }
201
+ }
202
+ //# sourceMappingURL=term.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"term.js","sourceRoot":"","sources":["../../src/terms/term.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import type { Entity } from "../entity/index.js";
2
+ import type { World } from "../world/index.js";
3
+ import { Term, type TermConsumer } from "./term.js";
4
+ /**
5
+ * World-pinned leaf term that matches every live entity.
6
+ *
7
+ * `WorldTerm` is the "universe" node: it holds all entities that are not
8
+ * destroyed. Component-definition entities are first-class members too (they
9
+ * are ordinary entities), so world-rooted queries can enumerate them — this is
10
+ * what makes schema reflection possible. Every other term that needs
11
+ * world-lifecycle awareness (e.g. `NotTerm`, `PredicateTerm`) subscribes to
12
+ * this leaf via the standard membership channel so they see entity creation
13
+ * and destruction.
14
+ *
15
+ * ## Shape channel
16
+ *
17
+ * `WorldTerm` also maintains a separate **shape channel** via
18
+ * {@link subscribeShape} / {@link entityShapeChanged}. When a component is
19
+ * added to or removed from an entity, `build.ts` calls
20
+ * `entityShapeChanged`; the world term then fans that notification out to all
21
+ * registered shape consumers as an `onTermRefresh` call. Only terms that are
22
+ * sensitive to the *set* of components on an entity (currently `OnlyTerm` and
23
+ * merged `PredicateTerm` nodes that contain an `only(...)` sub-expression)
24
+ * register on this channel, keeping it zero-cost for the common case.
25
+ */
26
+ export declare class WorldTerm extends Term {
27
+ constructor(world: World, key: string, onDestroy: (term: Term) => void);
28
+ /**
29
+ * Called by `build.ts` when a new entity is created.
30
+ *
31
+ * Adds the entity if it matches (i.e. it is live), which propagates an enter
32
+ * event to all consumers.
33
+ */
34
+ entityCreated(entity: Entity): void;
35
+ /**
36
+ * Called by `build.ts` when an entity is destroyed.
37
+ *
38
+ * Unconditionally removes the entity, propagating an exit event.
39
+ */
40
+ entityDestroyed(entity: Entity): void;
41
+ /**
42
+ * Called by `build.ts` when a component is added to or removed from an
43
+ * entity (a shape change).
44
+ *
45
+ * Notifies all {@link _shapeConsumers} via `onTermRefresh` so terms like
46
+ * `OnlyTerm` can re-evaluate whether the entity's component set still
47
+ * satisfies their exact-match predicate.
48
+ *
49
+ * Only fires for entities already in this term's set (i.e. live entities) —
50
+ * there is no point notifying about shape changes on entities that the world
51
+ * term itself does not track.
52
+ */
53
+ entityShapeChanged(entity: Entity): void;
54
+ /**
55
+ * Register `consumer` on the shape channel and return an unsubscribe
56
+ * function.
57
+ *
58
+ * The shape channel is separate from the standard membership channel so
59
+ * that component-add/remove events can be distinguished from
60
+ * entity-create/destroy events. Consumers on this channel receive
61
+ * `onTermRefresh` calls (not `onTermEvent`) because the shape change does
62
+ * not itself imply a membership change in the world term.
63
+ *
64
+ * @param consumer - The term or callback object to notify.
65
+ * @returns Cleanup function; safe to call multiple times.
66
+ */
67
+ subscribeShape(consumer: TermConsumer): () => void;
68
+ }
@@ -0,0 +1,99 @@
1
+ import { Term } from "./term.js";
2
+ /**
3
+ * World-pinned leaf term that matches every live entity.
4
+ *
5
+ * `WorldTerm` is the "universe" node: it holds all entities that are not
6
+ * destroyed. Component-definition entities are first-class members too (they
7
+ * are ordinary entities), so world-rooted queries can enumerate them — this is
8
+ * what makes schema reflection possible. Every other term that needs
9
+ * world-lifecycle awareness (e.g. `NotTerm`, `PredicateTerm`) subscribes to
10
+ * this leaf via the standard membership channel so they see entity creation
11
+ * and destruction.
12
+ *
13
+ * ## Shape channel
14
+ *
15
+ * `WorldTerm` also maintains a separate **shape channel** via
16
+ * {@link subscribeShape} / {@link entityShapeChanged}. When a component is
17
+ * added to or removed from an entity, `build.ts` calls
18
+ * `entityShapeChanged`; the world term then fans that notification out to all
19
+ * registered shape consumers as an `onTermRefresh` call. Only terms that are
20
+ * sensitive to the *set* of components on an entity (currently `OnlyTerm` and
21
+ * merged `PredicateTerm` nodes that contain an `only(...)` sub-expression)
22
+ * register on this channel, keeping it zero-cost for the common case.
23
+ */
24
+ export class WorldTerm extends Term {
25
+ constructor(world, key, onDestroy) {
26
+ super(world, key, "world", true, onDestroy);
27
+ /**
28
+ * @internal Consumers registered via {@link subscribeShape} that want
29
+ * notification when any entity's component set changes.
30
+ */
31
+ this._shapeConsumers = new Set();
32
+ this._initializeFromWorld();
33
+ }
34
+ /**
35
+ * Called by `build.ts` when a new entity is created.
36
+ *
37
+ * Adds the entity if it matches (i.e. it is live), which propagates an enter
38
+ * event to all consumers.
39
+ */
40
+ entityCreated(entity) {
41
+ if (this._matches(entity)) {
42
+ this._add(entity);
43
+ }
44
+ }
45
+ /**
46
+ * Called by `build.ts` when an entity is destroyed.
47
+ *
48
+ * Unconditionally removes the entity, propagating an exit event.
49
+ */
50
+ entityDestroyed(entity) {
51
+ this._delete(entity);
52
+ }
53
+ /**
54
+ * Called by `build.ts` when a component is added to or removed from an
55
+ * entity (a shape change).
56
+ *
57
+ * Notifies all {@link _shapeConsumers} via `onTermRefresh` so terms like
58
+ * `OnlyTerm` can re-evaluate whether the entity's component set still
59
+ * satisfies their exact-match predicate.
60
+ *
61
+ * Only fires for entities already in this term's set (i.e. live entities) —
62
+ * there is no point notifying about shape changes on entities that the world
63
+ * term itself does not track.
64
+ */
65
+ entityShapeChanged(entity) {
66
+ if (this.has(entity)) {
67
+ this._shapeConsumers.forEach((consumer) => consumer.onTermRefresh?.(entity));
68
+ }
69
+ }
70
+ /**
71
+ * Register `consumer` on the shape channel and return an unsubscribe
72
+ * function.
73
+ *
74
+ * The shape channel is separate from the standard membership channel so
75
+ * that component-add/remove events can be distinguished from
76
+ * entity-create/destroy events. Consumers on this channel receive
77
+ * `onTermRefresh` calls (not `onTermEvent`) because the shape change does
78
+ * not itself imply a membership change in the world term.
79
+ *
80
+ * @param consumer - The term or callback object to notify.
81
+ * @returns Cleanup function; safe to call multiple times.
82
+ */
83
+ subscribeShape(consumer) {
84
+ this._shapeConsumers.add(consumer);
85
+ let active = true;
86
+ return () => {
87
+ if (!active) {
88
+ return;
89
+ }
90
+ active = false;
91
+ this._shapeConsumers.delete(consumer);
92
+ };
93
+ }
94
+ /** @internal */
95
+ _matches(entity) {
96
+ return !entity._destroyed;
97
+ }
98
+ }
99
+ //# sourceMappingURL=world_term.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"world_term.js","sourceRoot":"","sources":["../../src/terms/world_term.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAqB,MAAM,WAAW,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,SAAU,SAAQ,IAAI;IAOjC,YAAmB,KAAY,EAAE,GAAW,EAAE,SAA+B;QAC3E,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAP9C;;;WAGG;QACc,oBAAe,GAAG,IAAI,GAAG,EAAgB,CAAC;QAIzD,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;OAKG;IACI,aAAa,CAAC,MAAc;QACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,eAAe,CAAC,MAAc;QACnC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED;;;;;;;;;;;OAWG;IACI,kBAAkB,CAAC,MAAc;QACtC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,cAAc,CAAC,QAAsB;QAC1C,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,MAAM,GAAG,KAAK,CAAC;YACf,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxC,CAAC,CAAC;IACJ,CAAC;IAED,gBAAgB;IACN,QAAQ,CAAC,MAAc;QAC/B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC;IAC5B,CAAC;CACF"}
package/dist/timer.js CHANGED
@@ -49,7 +49,7 @@ export class IntervalTickSource extends BaseTickSource {
49
49
  super();
50
50
  this._accumulator = 0;
51
51
  if (intervalSeconds <= 0) {
52
- throw "interval seconds must be greater than 0";
52
+ throw new Error("interval seconds must be greater than 0");
53
53
  }
54
54
  this._intervalMs = intervalSeconds * 1000;
55
55
  }
@@ -93,7 +93,7 @@ export class RateTickSource extends BaseTickSource {
93
93
  super();
94
94
  this._counter = 0;
95
95
  if (!Number.isInteger(rate) || rate <= 0) {
96
- throw "rate must be a positive integer";
96
+ throw new Error("rate must be a positive integer");
97
97
  }
98
98
  this._rate = rate;
99
99
  this._source = source;
package/dist/timer.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"timer.js","sourceRoot":"","sources":["../src/timer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"timer.js","sourceRoot":"","sources":["../src/timer.ts"],"names":[],"mappings":"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"}
@@ -77,6 +77,18 @@ export class ArrayMap {
77
77
  }
78
78
  }
79
79
  }
80
+ /** Return every present value in ascending key order. */
81
+ values() {
82
+ const out = [];
83
+ const backend = this._backend;
84
+ for (let i = 0; i < backend.length; i++) {
85
+ const value = backend[i];
86
+ if (value !== undefined) {
87
+ out.push(value);
88
+ }
89
+ }
90
+ return out;
91
+ }
80
92
  /** Remove all entries and reset {@link size} to zero. */
81
93
  clear() {
82
94
  this._backend.length = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"array_map.js","sourceRoot":"","sources":["../../src/util/array_map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,QAAQ;IAArB;QACU,aAAQ,GAAsB,EAAE,CAAC;QACjC,UAAK,GAAW,CAAC,CAAC;IAwE5B,CAAC;IAtEC,kDAAkD;IAClD,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;;;OAKG;IACI,GAAG,CAAC,GAAW,EAAE,KAAQ;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACI,GAAG,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACI,GAAG,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,GAAW;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;YACzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,OAAO,CAAC,QAA2D;QACxE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,yDAAyD;IAClD,KAAK;QACV,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"array_map.js","sourceRoot":"","sources":["../../src/util/array_map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,QAAQ;IAArB;QACU,aAAQ,GAAsB,EAAE,CAAC;QACjC,UAAK,GAAW,CAAC,CAAC;IAqF5B,CAAC;IAnFC,kDAAkD;IAClD,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED;;;;;OAKG;IACI,GAAG,CAAC,GAAW,EAAE,KAAQ;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACvB,CAAC;IAED;;;;OAIG;IACI,GAAG,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED;;;;OAIG;IACI,GAAG,CAAC,GAAW;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,GAAW;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;YACzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,OAAO,CAAC,QAA2D;QACxE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,yDAAyD;IAClD,MAAM;QACX,MAAM,GAAG,GAAQ,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,yDAAyD;IAClD,KAAK;QACV,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACjB,CAAC;CACF"}