@adobe/ecs 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/dist/implementation/compiler/augmentations.js +8 -1
  2. package/dist/implementation/compiler/augmentations.js.map +1 -1
  3. package/dist/implementation/compiler/body-access.d.ts +18 -1
  4. package/dist/implementation/compiler/body-access.js +104 -15
  5. package/dist/implementation/compiler/body-access.js.map +1 -1
  6. package/dist/implementation/compiler/estree.d.ts +5 -2
  7. package/dist/implementation/compiler/estree.js +8 -5
  8. package/dist/implementation/compiler/estree.js.map +1 -1
  9. package/dist/implementation/compiler/inferred.js +5 -2
  10. package/dist/implementation/compiler/inferred.js.map +1 -1
  11. package/dist/implementation/compiler/transform.js +5 -4
  12. package/dist/implementation/compiler/transform.js.map +1 -1
  13. package/dist/implementation/compiler/type-schemas.d.ts +1 -0
  14. package/dist/implementation/compiler/type-schemas.js +35 -2
  15. package/dist/implementation/compiler/type-schemas.js.map +1 -1
  16. package/dist/implementation/world/activate.d.ts +14 -3
  17. package/dist/implementation/world/activate.js +28 -10
  18. package/dist/implementation/world/activate.js.map +1 -1
  19. package/dist/implementation/world/buffer.d.ts +7 -0
  20. package/dist/implementation/world/buffer.js +7 -0
  21. package/dist/implementation/world/buffer.js.map +1 -1
  22. package/dist/implementation/world/cascade.d.ts +10 -3
  23. package/dist/implementation/world/cascade.js +48 -23
  24. package/dist/implementation/world/cascade.js.map +1 -1
  25. package/dist/implementation/world/commands.js +41 -5
  26. package/dist/implementation/world/commands.js.map +1 -1
  27. package/dist/implementation/world/create.js +57 -6
  28. package/dist/implementation/world/create.js.map +1 -1
  29. package/dist/implementation/world/execute.d.ts +4 -4
  30. package/dist/implementation/world/execute.js +228 -93
  31. package/dist/implementation/world/execute.js.map +1 -1
  32. package/dist/implementation/world/finalizers.d.ts +10 -0
  33. package/dist/implementation/world/finalizers.js +60 -10
  34. package/dist/implementation/world/finalizers.js.map +1 -1
  35. package/dist/implementation/world/join.js +12 -2
  36. package/dist/implementation/world/join.js.map +1 -1
  37. package/dist/implementation/world/program.js +5 -1
  38. package/dist/implementation/world/program.js.map +1 -1
  39. package/dist/implementation/world/resource-changes.d.ts +18 -0
  40. package/dist/implementation/world/resource-changes.js +66 -0
  41. package/dist/implementation/world/resource-changes.js.map +1 -0
  42. package/dist/implementation/world/rows.js +21 -16
  43. package/dist/implementation/world/rows.js.map +1 -1
  44. package/dist/implementation/world/run-changes.d.ts +38 -0
  45. package/dist/implementation/world/run-changes.js +138 -0
  46. package/dist/implementation/world/run-changes.js.map +1 -0
  47. package/dist/implementation/world/runner.js +16 -12
  48. package/dist/implementation/world/runner.js.map +1 -1
  49. package/dist/implementation/world/state.d.ts +15 -0
  50. package/dist/implementation/world/state.js +22 -1
  51. package/dist/implementation/world/state.js.map +1 -1
  52. package/dist/implementation/world/synchronize.js +81 -24
  53. package/dist/implementation/world/synchronize.js.map +1 -1
  54. package/dist/implementation/world/tables-read.d.ts +5 -3
  55. package/dist/implementation/world/tables-read.js +16 -4
  56. package/dist/implementation/world/tables-read.js.map +1 -1
  57. package/dist/implementation/world/tables.d.ts +4 -2
  58. package/dist/implementation/world/tables.js +137 -38
  59. package/dist/implementation/world/tables.js.map +1 -1
  60. package/dist/implementation/world/thread-observer.js +1 -1
  61. package/dist/implementation/world/thread-observer.js.map +1 -1
  62. package/dist/implementation/world/thread-systems.js +10 -6
  63. package/dist/implementation/world/thread-systems.js.map +1 -1
  64. package/dist/implementation/world/up.js +7 -1
  65. package/dist/implementation/world/up.js.map +1 -1
  66. package/dist/implementation/world/where.d.ts +8 -0
  67. package/dist/implementation/world/where.js +40 -11
  68. package/dist/implementation/world/where.js.map +1 -1
  69. package/dist/interface/finalizer/body.d.ts +40 -4
  70. package/dist/interface/finalizer/create.d.ts +8 -6
  71. package/dist/interface/finalizer/create.js +45 -10
  72. package/dist/interface/finalizer/create.js.map +1 -1
  73. package/dist/interface/finalizer/declaration.d.ts +26 -4
  74. package/dist/interface/indexes/declaration-of.d.ts +17 -0
  75. package/dist/interface/indexes/declaration-of.js +20 -0
  76. package/dist/interface/indexes/declaration-of.js.map +1 -0
  77. package/dist/interface/indexes/index.d.ts +1 -0
  78. package/dist/interface/indexes/index.js +1 -0
  79. package/dist/interface/indexes/index.js.map +1 -1
  80. package/dist/interface/registry/index.d.ts +1 -1
  81. package/dist/interface/registry/index.js +1 -1
  82. package/dist/interface/registry/index.js.map +1 -1
  83. package/dist/interface/registry/names.d.ts +4 -0
  84. package/dist/interface/registry/names.js +20 -0
  85. package/dist/interface/registry/names.js.map +1 -1
  86. package/dist/interface/registry/schedule.d.ts +29 -1
  87. package/dist/interface/registry/schedule.js +261 -25
  88. package/dist/interface/registry/schedule.js.map +1 -1
  89. package/dist/interface/system/access.d.ts +15 -0
  90. package/dist/interface/system/check.d.ts +7 -0
  91. package/dist/interface/system/check.js +21 -3
  92. package/dist/interface/system/check.js.map +1 -1
  93. package/dist/interface/system/commands.d.ts +31 -5
  94. package/dist/interface/system/create-resolved.js +2 -1
  95. package/dist/interface/system/create-resolved.js.map +1 -1
  96. package/dist/interface/system/create.d.ts +10 -6
  97. package/dist/interface/system/create.js +5 -4
  98. package/dist/interface/system/create.js.map +1 -1
  99. package/dist/interface/system/declaration.d.ts +11 -4
  100. package/dist/interface/system/describe.d.ts +120 -0
  101. package/dist/interface/system/describe.js +116 -0
  102. package/dist/interface/system/describe.js.map +1 -0
  103. package/dist/interface/system/index.d.ts +1 -0
  104. package/dist/interface/system/index.js +1 -0
  105. package/dist/interface/system/index.js.map +1 -1
  106. package/dist/interface/system/leaf.d.ts +7 -0
  107. package/dist/interface/system/render.js +2 -1
  108. package/dist/interface/system/render.js.map +1 -1
  109. package/dist/interface/system/resolve.d.ts +14 -1
  110. package/dist/interface/system/resolve.js +50 -1
  111. package/dist/interface/system/resolve.js.map +1 -1
  112. package/dist/interface/system/shared-only.d.ts +7 -0
  113. package/dist/interface/system/shared-only.js +2 -0
  114. package/dist/interface/system/shared-only.js.map +1 -0
  115. package/dist/interface/system/tables.d.ts +9 -1
  116. package/dist/interface/world/table/index.d.ts +3 -2
  117. package/dist/interface/world/world.d.ts +15 -0
  118. package/package.json +11 -2
  119. package/src/guide/01-resources.md +4 -3
  120. package/src/guide/03-systems.out +1 -1
  121. package/src/guide/05-scheduling.md +12 -6
  122. package/src/guide/05-scheduling.out +1 -0
  123. package/src/guide/05-scheduling.ts +17 -0
  124. package/src/guide/06-sync-points.md +20 -8
  125. package/src/guide/06-sync-points.out +3 -2
  126. package/src/guide/06-sync-points.ts +24 -5
  127. package/src/guide/10-finalizers.md +5 -0
  128. package/src/guide/18-identity.out +1 -1
  129. package/src/guide/guide.test.ts +6 -153
  130. package/src/implementation/compiler/augmentations.test.ts +28 -1
  131. package/src/implementation/compiler/augmentations.ts +5 -1
  132. package/src/implementation/compiler/body-access.ts +102 -12
  133. package/src/implementation/compiler/estree.ts +9 -6
  134. package/src/implementation/compiler/inferred.test.ts +1 -1
  135. package/src/implementation/compiler/inferred.ts +5 -2
  136. package/src/implementation/compiler/transform.test.ts +41 -21
  137. package/src/implementation/compiler/transform.ts +5 -3
  138. package/src/implementation/compiler/type-schemas.ts +28 -2
  139. package/src/implementation/world/activate.ts +32 -10
  140. package/src/implementation/world/batches.test.ts +3 -3
  141. package/src/implementation/world/buffer.ts +7 -0
  142. package/src/implementation/world/cascade.ts +46 -22
  143. package/src/implementation/world/commands.ts +37 -5
  144. package/src/implementation/world/create.test.ts +8 -8
  145. package/src/implementation/world/create.ts +61 -6
  146. package/src/implementation/world/defaults.test.ts +24 -1
  147. package/src/implementation/world/despawn-where.test.ts +310 -0
  148. package/src/implementation/world/execute.ts +222 -86
  149. package/src/implementation/world/finalizers.ts +63 -11
  150. package/src/implementation/world/ids.test.ts +1 -1
  151. package/src/implementation/world/indexes.test.ts +2 -1
  152. package/src/implementation/world/join.test.ts +19 -0
  153. package/src/implementation/world/join.ts +16 -2
  154. package/src/implementation/world/lifetime.test-helper.ts +1 -1
  155. package/src/implementation/world/names.test.ts +1 -2
  156. package/src/implementation/world/passes.test.ts +61 -0
  157. package/src/implementation/world/perf.md +12 -1
  158. package/src/implementation/world/program.ts +4 -1
  159. package/src/implementation/world/resource-changes.test.ts +61 -0
  160. package/src/implementation/world/resource-changes.ts +67 -0
  161. package/src/implementation/world/rows.ts +21 -14
  162. package/src/implementation/world/rules.test.ts +37 -0
  163. package/src/implementation/world/run-changes.test.ts +88 -0
  164. package/src/implementation/world/run-changes.ts +160 -0
  165. package/src/implementation/world/run-results.test.ts +17 -0
  166. package/src/implementation/world/runner.ts +17 -13
  167. package/src/implementation/world/schedule.test.ts +42 -1
  168. package/src/implementation/world/shared.test.ts +2 -2
  169. package/src/implementation/world/state.ts +27 -0
  170. package/src/implementation/world/sync-points.test.ts +147 -0
  171. package/src/implementation/world/synchronize.ts +73 -20
  172. package/src/implementation/world/tables-read.ts +16 -5
  173. package/src/implementation/world/tables.test.ts +139 -4
  174. package/src/implementation/world/tables.ts +118 -35
  175. package/src/implementation/world/thread-observer.ts +1 -1
  176. package/src/implementation/world/thread-systems.ts +10 -6
  177. package/src/implementation/world/up.test.ts +13 -1
  178. package/src/implementation/world/up.ts +6 -1
  179. package/src/implementation/world/watch-traits-late.test-helper.ts +14 -0
  180. package/src/implementation/world/watch-traits.test-helper.ts +10 -0
  181. package/src/implementation/world/watch-traits.test.ts +62 -0
  182. package/src/implementation/world/where.ts +38 -10
  183. package/src/interface/finalizer/body.ts +33 -4
  184. package/src/interface/finalizer/create.test.ts +6 -1
  185. package/src/interface/finalizer/create.ts +45 -12
  186. package/src/interface/finalizer/declaration.ts +31 -4
  187. package/src/interface/indexes/create.test.ts +10 -0
  188. package/src/interface/indexes/declaration-of.ts +34 -0
  189. package/src/interface/indexes/index.ts +1 -0
  190. package/src/interface/registry/index.ts +1 -1
  191. package/src/interface/registry/names.ts +19 -0
  192. package/src/interface/registry/schedule.ts +275 -29
  193. package/src/interface/rule/rule.type-test.ts +23 -1
  194. package/src/interface/system/access.ts +16 -0
  195. package/src/interface/system/check.ts +17 -2
  196. package/src/interface/system/commands.ts +28 -4
  197. package/src/interface/system/commands.type-test.ts +31 -0
  198. package/src/interface/system/create-resolved.ts +2 -1
  199. package/src/interface/system/create.test.ts +10 -2
  200. package/src/interface/system/create.ts +9 -5
  201. package/src/interface/system/declaration.ts +10 -4
  202. package/src/interface/system/describe.test.ts +98 -0
  203. package/src/interface/system/describe.ts +122 -0
  204. package/src/interface/system/index.ts +1 -0
  205. package/src/interface/system/leaf.ts +7 -0
  206. package/src/interface/system/render.ts +2 -1
  207. package/src/interface/system/resolve.test.ts +17 -1
  208. package/src/interface/system/resolve.ts +60 -2
  209. package/src/interface/system/shared-only.ts +5 -0
  210. package/src/interface/system/system.type-test.ts +6 -0
  211. package/src/interface/system/tables.ts +7 -1
  212. package/src/interface/world/run.type-test.ts +11 -1
  213. package/src/interface/world/table/index.ts +3 -2
  214. package/src/interface/world/world.ts +13 -0
  215. package/src/perftest/benchmarks.ts +20 -0
  216. package/src/perftest/chained.ts +108 -0
  217. package/src/perftest/structural.ts +20 -0
  218. package/src/perftest/tables.ts +107 -0
@@ -2,6 +2,7 @@ import type { Component } from '../component/component.js';
2
2
  import type { Entity } from '../entity/entity.js';
3
3
  import type { Essential, Shared } from '../component/value.js';
4
4
  import type { Table } from '../world/table/table.js';
5
+ import type { SharedOnly } from './shared-only.js';
5
6
  import type { ValuesOf } from './values-of.js';
6
7
  /** The value an `add` of one component takes: none for a tag. */
7
8
  type ValueArgument<K extends Essential> = Component<K> extends true ? [value?: true] : [value: Component<K>];
@@ -65,6 +66,20 @@ export type Commands = {
65
66
  */
66
67
  spawn<const C extends readonly Essential[], const P extends Preset<C> = {}>(components: Spawned<C, P>, ...constant: RequiresPreset<C> extends true ? [constant?: P & SharedPreset<C> & Named<C, P>] : [constant?: P & Named<C, P>]): (...values: SpawnValues<C, P>) => Entity;
67
68
  despawn(entity: Entity): void;
69
+ /**
70
+ * Despawns, as a `despawn` of each would, every entity alive before its sync point that has each component of
71
+ * `with` and none of `not` once the commands issued before it apply, as a row system over the same query despawning
72
+ * each of its rows would; never one the sync point spawns, whenever spawned. Derived components may be named. `where` keeps it to the archetypes holding these values of shared components,
73
+ * each one required as `with` requires it, as a system's `where` of values does. Never the resource entity. Only on
74
+ * the world's thread: a joined thread's throws.
75
+ */
76
+ despawnWhere<const W extends object = {}>(query: {
77
+ readonly with: readonly [Component.Key, ...Component.Key[]];
78
+ readonly not?: readonly Component.Key[];
79
+ readonly where?: W & SharedOnly<NoInfer<W>> & {
80
+ readonly [K in Shared]?: Component<K>;
81
+ };
82
+ }): void;
68
83
  /** Adds or replaces one component's value, marking it changed. */
69
84
  add<K extends Essential>(entity: Entity, component: K, ...value: ValueArgument<K>): void;
70
85
  /** Adds or replaces the values of `components`, marking them changed. */
@@ -79,12 +94,23 @@ export type Commands = {
79
94
  * outside them isn't spawned, nor anything it owns, through owner references, as despawning its owner would; a
80
95
  * weak reference to one is left out of its row, which is spawned without it; any other value naming one is
81
96
  * `Entity.none`. Returns, at once, each table's new entities, alive at the sync point. A column's stride must be its
82
- * component's in this world, and its length its table's count. `resources` sets each resource it names, by key, at
83
- * the sync point, as commands apply, each value checked against its resource's schema; not one only the world
84
- * writes, nor one living on another thread. On the world's thread only.
97
+ * component's in this world, and its length its table's count. On the world's thread only.
98
+ * - `existing` maps entities to ones already alive in this world, which stand for them: a row whose entity it maps
99
+ * isn't spawned, its entry in the result is the entity it maps to, and every value naming one it maps names that
100
+ * entity, whether or not it's in the tables. Fails for one that isn't alive.
101
+ * - `update` writes each row `existing` maps onto the entity standing for it, as `commands.add` of its table's
102
+ * components would: adding those the entity lacks, replacing and marking changed those it has, and leaving its
103
+ * other components as they are. Its entity values are rewritten as a spawned row's are, but a reference naming an
104
+ * entity that isn't there, weak or owner, is left out, so the entity's own stands.
105
+ * - `resources` sets each resource it names, by key, at the sync point, as commands apply, each value checked
106
+ * against its resource's schema; not one only the world writes, nor one living on another thread.
85
107
  */
86
- spawnTables(tables: readonly Table[], resources?: {
87
- readonly [key: symbol]: unknown;
108
+ spawnTables(tables: readonly Table[], options?: {
109
+ readonly resources?: {
110
+ readonly [key: symbol]: unknown;
111
+ };
112
+ readonly existing?: ReadonlyMap<Entity, Entity>;
113
+ readonly update?: boolean;
88
114
  }): Table.Spawned;
89
115
  };
90
116
  export {};
@@ -2,6 +2,7 @@
2
2
  import { nameOf } from '../registry/items.js';
3
3
  import { claimSystem } from '../registry/program.js';
4
4
  import { checkLeaf, inputSchemaOf } from './check.js';
5
+ import { noCommands } from './resolve.js';
5
6
  /**
6
7
  * Makes a system of a declaration as the world takes it, with what its body reads and writes already listed: for the
7
8
  * implementation's own systems, such as those standing for a joined thread's, whose bodies no build reads. Checks it
@@ -10,7 +11,7 @@ import { checkLeaf, inputSchemaOf } from './check.js';
10
11
  export const createResolved = (declaration, body, input) => {
11
12
  const name = nameOf(declaration, undefined, "system");
12
13
  const schema = inputSchemaOf(name, body, declaration.components === undefined ? 1 : 2, input);
13
- const system = { kind: "system", name, declaration, input: schema, body };
14
+ const system = { kind: "system", name, declaration, input: schema, body, commands: noCommands };
14
15
  checkLeaf(system);
15
16
  claimSystem(system, undefined);
16
17
  return system;
@@ -1 +1 @@
1
- {"version":3,"file":"create-resolved.js","sourceRoot":"","sources":["../../../src/interface/system/create-resolved.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKtD;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,WAAqB,EAAE,IAAkB,EAAE,KAAe,EAAmB,EAAE;IAC1G,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9F,MAAM,MAAM,GAA2B,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAClG,SAAS,CAAC,MAAM,CAAC,CAAC;IAClB,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC"}
1
+ {"version":3,"file":"create-resolved.js","sourceRoot":"","sources":["../../../src/interface/system/create-resolved.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI1C;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,WAAqB,EAAE,IAAkB,EAAE,KAAe,EAAmB,EAAE;IAC1G,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9F,MAAM,MAAM,GAA2B,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;IACxH,SAAS,CAAC,MAAM,CAAC,CAAC;IAClB,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC/B,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC"}
@@ -9,7 +9,7 @@ import type { Listed, Property } from './property.js';
9
9
  import type { System } from './system.js';
10
10
  import type { OneThread, ThreadedBy, ThreadsOf } from './threads.js';
11
11
  import type { HeldBy } from './values.js';
12
- import type { Shared } from '../component/value.js';
12
+ import type { SharedOnly } from './shared-only.js';
13
13
  type Lookups<D> = Property<D, "lookup">;
14
14
  /** A lookup's `changed` names what it requires: a lookup by entity's `with`, an index lookup's what its index holds. */
15
15
  type LookupChanges<D> = {
@@ -86,11 +86,7 @@ type Where<D> = D extends {
86
86
  };
87
87
  } ? {
88
88
  readonly components?: {
89
- readonly where?: {
90
- readonly [K in Exclude<keyof W, Shared>]: {
91
- readonly "error: where names only shared components, which each archetype holds one value of": K;
92
- };
93
- };
89
+ readonly where?: SharedOnly<W>;
94
90
  };
95
91
  } & (D extends {
96
92
  readonly up: object;
@@ -139,6 +135,14 @@ type Validate<D extends Declaration> = LookupChanges<D> & Where<D> & Conditions<
139
135
  } : {}) & (D extends {
140
136
  readonly readonly: true;
141
137
  } ? Readonly : {}) & (D extends {
138
+ readonly tables: {
139
+ readonly where: infer W;
140
+ };
141
+ } ? {
142
+ readonly tables?: {
143
+ readonly where?: SharedOnly<W>;
144
+ };
145
+ } : {}) & (D extends {
142
146
  readonly tables: object;
143
147
  } ? (D extends {
144
148
  readonly readonly: true;
@@ -2,7 +2,7 @@ import { takeIdOfDeclaration } from '../registry/ids.js';
2
2
  import { nameOf } from '../registry/items.js';
3
3
  import { claimSystem } from '../registry/program.js';
4
4
  import { checkComposite, checkLeaf, inputSchemaOf } from './check.js';
5
- import { accessOf, compact, componentLists, lookupsLists, resourceUses, upReads, whereReadsOf } from './resolve.js';
5
+ import { accessOf, commandListsOf, compact, componentLists, lookupsLists, resourceUses, upReads, whereReadsOf } from './resolve.js';
6
6
  // The plugin passes the schema of the body's input as a third argument.
7
7
  export function create(first, second, input) {
8
8
  // The plugin gives its id to the call's first argument: the declaration, the members, or the body made into a
@@ -17,9 +17,10 @@ export function create(first, second, input) {
17
17
  if (body === undefined)
18
18
  throw new Error("A system needs a body, and a composite its systems.");
19
19
  const name = nameOf(first, id, "system");
20
- const declaration = resolve(`System "${name}"`, declared, accessOf(`System "${name}"`, first));
20
+ const access = accessOf(`System "${name}"`, first);
21
+ const declaration = resolve(`System "${name}"`, declared, access);
21
22
  const schema = inputSchemaOf(name, body, declaration.components === undefined ? 1 : 2, input);
22
- const system = { kind: "system", name, declaration, input: schema, body };
23
+ const system = { kind: "system", name, declaration, input: schema, body, commands: commandListsOf(`System "${name}"`, access) };
23
24
  checkLeaf(system);
24
25
  claimSystem(system, id);
25
26
  return system;
@@ -37,7 +38,7 @@ const resolve = (what, declared, access) => {
37
38
  uses.read.push(key);
38
39
  const resolved = {
39
40
  ...rest,
40
- ...components === undefined ? {} : { components: componentLists(components, access.components, reading, whereReads) },
41
+ ...components === undefined ? {} : { components: componentLists(components, components.whole === true ? null : access.components, reading, whereReads) },
41
42
  ...lookup === undefined ? {} : { lookup: lookupsLists(lookup, access) },
42
43
  ...up === undefined ? {} : { up: { through: up.through, read: upReads(what, access) } },
43
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/interface/system/create.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/interface/system/create.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { Index } from '../indexes/index-type.js';
2
+ import type { Resource } from '../resource/resource.js';
2
3
  import type { ComponentAccess, ComponentLists, ResourceAccess, ResourceLists, SystemLookup, SystemLookupLists, Up, UpLists } from './access.js';
3
4
  import type { Shader } from './render.js';
4
5
  import type { System } from './system.js';
@@ -53,10 +54,16 @@ export type Declaration = {
53
54
  readonly target?: string;
54
55
  /** Makes this a render system (see `render`): its body records GPU work over the GPU copy of the components it names. */
55
56
  readonly shader?: Shader;
56
- /** Hard constraint. */
57
- readonly before?: readonly System<unknown>[];
58
- /** Hard constraint. */
59
- readonly after?: readonly System<unknown>[];
57
+ /**
58
+ * Hard constraint: runs before each system listed, and, for a resource listed, before every other system of the
59
+ * composite that uses it, but those its constraints already order before it and those listing it in `before` too.
60
+ */
61
+ readonly before?: readonly (System<unknown> | Resource.Key)[];
62
+ /**
63
+ * Hard constraint: runs after each system listed, and, for a resource listed, after every other system of the
64
+ * composite that uses it, but those its constraints already order after it and those listing it in `after` too.
65
+ */
66
+ readonly after?: readonly (System<unknown> | Resource.Key)[];
60
67
  /** Runs inside the span of the systems listed: after what they follow and before what follows them. */
61
68
  readonly during?: readonly System<unknown>[];
62
69
  /**
@@ -0,0 +1,120 @@
1
+ import type { System } from './system.js';
2
+ /**
3
+ * Describes how a system or composite runs: its tiers in run order, systems in one tier having no ordering path between
4
+ * them, each with the sync point after it, if any, and its readonly systems apart, which run after its last sync
5
+ * point. For each system, what the build inferred it reads, writes, looks up and commands, whether it takes its row
6
+ * whole, and the systems it follows directly, with what ordered it after each. `text` gives it all to read; the rest
7
+ * is data to assert on.
8
+ */
9
+ export declare const describe: <I, R>(system: System<I, R>) => {
10
+ tiers: {
11
+ systems: {
12
+ /** The system, the value its constructor returned. */
13
+ system: System<unknown, unknown>;
14
+ name: string;
15
+ components: {
16
+ read: symbol[];
17
+ write: readonly symbol[];
18
+ /** What it requires without reading: `with` members it doesn't use, `added` and `changed` filters' among them. */
19
+ has: readonly symbol[];
20
+ optional: readonly symbol[];
21
+ not: readonly symbol[];
22
+ added: readonly symbol[];
23
+ changed: readonly symbol[];
24
+ /** What it reads of each row's parent, through `up`. */
25
+ parent: readonly symbol[];
26
+ };
27
+ resources: {
28
+ read: readonly symbol[];
29
+ write: readonly symbol[];
30
+ reduce: readonly symbol[];
31
+ changed: readonly symbol[];
32
+ is: readonly symbol[];
33
+ not: readonly symbol[];
34
+ };
35
+ lookups: {
36
+ name: string;
37
+ /** The label of the index it looks up through, or null for a lookup by entity. */
38
+ index: string | null;
39
+ read: readonly symbol[];
40
+ }[];
41
+ /** The label of the sorted index ordering its rows, or null. */
42
+ order: string | null;
43
+ /** What its commands name by kind, and whether it despawns; null where the build couldn't follow them. */
44
+ commands: {
45
+ spawn: readonly symbol[];
46
+ add: readonly symbol[];
47
+ remove: readonly symbol[];
48
+ despawn: boolean;
49
+ } | null;
50
+ /** Whether it takes its row whole (`components: { whole: true }`), every member written. */
51
+ whole: boolean;
52
+ /** The systems it follows directly, with what ordered it after each and the keys that need that order. */
53
+ after: {
54
+ system: System<unknown, unknown>;
55
+ name: string;
56
+ because: "before" | "after" | "during" | "reduction";
57
+ conflicts: readonly symbol[];
58
+ }[];
59
+ }[];
60
+ /**
61
+ * Why a sync point follows the tier, applying the commands so far: each system whose commands may change what a
62
+ * later one that follows it uses, through `keys`, none listed where it despawns or a cascade could; null for none.
63
+ */
64
+ sync: {
65
+ from: System<unknown, unknown>;
66
+ to: System<unknown, unknown>;
67
+ keys: readonly symbol[];
68
+ }[] | null;
69
+ }[];
70
+ readonly: {
71
+ /** The system, the value its constructor returned. */
72
+ system: System<unknown, unknown>;
73
+ name: string;
74
+ components: {
75
+ read: symbol[];
76
+ write: readonly symbol[];
77
+ /** What it requires without reading: `with` members it doesn't use, `added` and `changed` filters' among them. */
78
+ has: readonly symbol[];
79
+ optional: readonly symbol[];
80
+ not: readonly symbol[];
81
+ added: readonly symbol[];
82
+ changed: readonly symbol[];
83
+ /** What it reads of each row's parent, through `up`. */
84
+ parent: readonly symbol[];
85
+ };
86
+ resources: {
87
+ read: readonly symbol[];
88
+ write: readonly symbol[];
89
+ reduce: readonly symbol[];
90
+ changed: readonly symbol[];
91
+ is: readonly symbol[];
92
+ not: readonly symbol[];
93
+ };
94
+ lookups: {
95
+ name: string;
96
+ /** The label of the index it looks up through, or null for a lookup by entity. */
97
+ index: string | null;
98
+ read: readonly symbol[];
99
+ }[];
100
+ /** The label of the sorted index ordering its rows, or null. */
101
+ order: string | null;
102
+ /** What its commands name by kind, and whether it despawns; null where the build couldn't follow them. */
103
+ commands: {
104
+ spawn: readonly symbol[];
105
+ add: readonly symbol[];
106
+ remove: readonly symbol[];
107
+ despawn: boolean;
108
+ } | null;
109
+ /** Whether it takes its row whole (`components: { whole: true }`), every member written. */
110
+ whole: boolean;
111
+ /** The systems it follows directly, with what ordered it after each and the keys that need that order. */
112
+ after: {
113
+ system: System<unknown, unknown>;
114
+ name: string;
115
+ because: "before" | "after" | "during" | "reduction";
116
+ conflicts: readonly symbol[];
117
+ }[];
118
+ }[];
119
+ text: string;
120
+ };
@@ -0,0 +1,116 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { indexDefinitionOf } from '../registry/indexes.js';
3
+ import { labelOf } from '../registry/names.js';
4
+ import { requireDefinition } from '../registry/program.js';
5
+ import { isLeaf, placementsOf, scheduleOf } from '../registry/schedule.js';
6
+ const none = [];
7
+ /** A leaf as the system value it is. */
8
+ const asSystem = (leaf) => leaf;
9
+ /** What the build inferred one system uses, and what placed it, as plain data. */
10
+ const describeLeaf = (leaf, placements) => {
11
+ const { components, resources, lookup, up, order } = leaf.declaration;
12
+ const commands = leaf.commands();
13
+ return {
14
+ /** The system, the value its constructor returned. */
15
+ system: asSystem(leaf),
16
+ name: leaf.name,
17
+ components: {
18
+ read: [...components?.read ?? none, ...up === undefined ? none : [up.through]],
19
+ write: components?.write ?? none,
20
+ /** What it requires without reading: `with` members it doesn't use, `added` and `changed` filters' among them. */
21
+ has: components?.has ?? none,
22
+ optional: components?.optional ?? none,
23
+ not: components?.not ?? none,
24
+ added: components?.added ?? none,
25
+ changed: components?.changed ?? none,
26
+ /** What it reads of each row's parent, through `up`. */
27
+ parent: up?.read ?? none,
28
+ },
29
+ resources: {
30
+ read: resources?.read ?? none,
31
+ write: resources?.write ?? none,
32
+ reduce: resources?.reduce ?? none,
33
+ changed: resources?.changed ?? none,
34
+ is: resources?.is ?? none,
35
+ not: resources?.not ?? none,
36
+ },
37
+ lookups: Object.entries(lookup ?? {}).map(([name, used]) => ({
38
+ name,
39
+ /** The label of the index it looks up through, or null for a lookup by entity. */
40
+ index: "index" in used && used.index !== undefined ? indexDefinitionOf(used.index)?.name ?? null : null,
41
+ read: used.read ?? none,
42
+ })),
43
+ /** The label of the sorted index ordering its rows, or null. */
44
+ order: indexDefinitionOf(order)?.name ?? null,
45
+ /** What its commands name by kind, and whether it despawns; null where the build couldn't follow them. */
46
+ commands: commands === null ? null : {
47
+ spawn: commands?.spawn ?? none,
48
+ add: commands?.add ?? none,
49
+ remove: commands?.remove ?? none,
50
+ despawn: commands?.despawn === true,
51
+ },
52
+ /** Whether it takes its row whole (`components: { whole: true }`), every member written. */
53
+ whole: components?.whole === true,
54
+ /** The systems it follows directly, with what ordered it after each and the keys that need that order. */
55
+ after: placements.map(placement => ({ system: asSystem(placement.leaf), name: placement.leaf.name, because: placement.because, conflicts: placement.conflicts })),
56
+ };
57
+ };
58
+ const keys = (list) => list.map(labelOf).join(" ");
59
+ /** A system's lines of text, after its name in a column of `width`. */
60
+ const linesOf = (system, width) => {
61
+ const lines = [];
62
+ const add = (label, text) => { if (text !== "")
63
+ lines.push(`${label.padEnd(10)}${text}`); };
64
+ const { components, resources, commands } = system;
65
+ add("reads", keys(components.read));
66
+ add("writes", `${keys(components.write)}${system.whole ? " (its whole row)" : ""}`);
67
+ add("requires", [keys(components.has), components.not.length === 0 ? "" : `not ${keys(components.not)}`, components.optional.length === 0 ? "" : `optional ${keys(components.optional)}`].filter(text => text !== "").join(", "));
68
+ add("filters", [...components.added.map(key => `added ${labelOf(key)}`), ...components.changed.map(key => `changed ${labelOf(key)}`), ...resources.changed.map(key => `changed ${labelOf(key)}`)].join(", "));
69
+ add("parent", keys(components.parent));
70
+ add("resources", [resources.read.length === 0 ? "" : `reads ${keys(resources.read)}`, resources.write.length === 0 ? "" : `writes ${keys(resources.write)}`,
71
+ resources.reduce.length === 0 ? "" : `reduces ${keys(resources.reduce)}`, resources.is.length === 0 ? "" : `while ${keys(resources.is)}`,
72
+ resources.not.length === 0 ? "" : `unless ${keys(resources.not)}`].filter(text => text !== "").join(", "));
73
+ for (const lookup of system.lookups)
74
+ add("looks up", `${lookup.name}${lookup.index === null ? "" : ` through ${lookup.index}`}${lookup.read.length === 0 ? "" : `: ${keys(lookup.read)}`}`);
75
+ if (system.order !== null)
76
+ add("ordered", `by ${system.order}`);
77
+ if (commands === null)
78
+ add("commands", "unknown: the build couldn't follow them");
79
+ else
80
+ add("commands", [commands.spawn.length === 0 ? "" : `spawn ${keys(commands.spawn)}`, commands.add.length === 0 ? "" : `add ${keys(commands.add)}`,
81
+ commands.remove.length === 0 ? "" : `remove ${keys(commands.remove)}`, commands.despawn ? "despawn" : ""].filter(text => text !== "").join(", "));
82
+ add("after", system.after.map(placement => `${placement.name} (${placement.because}${placement.conflicts.length === 0 ? "" : `: ${keys(placement.conflicts)}`})`).join(", "));
83
+ const indent = " ".repeat(width);
84
+ return lines.length === 0 ? [system.name] : lines.map((line, i) => `${i === 0 ? system.name.padEnd(width) : indent}${line}`);
85
+ };
86
+ /**
87
+ * Describes how a system or composite runs: its tiers in run order, systems in one tier having no ordering path between
88
+ * them, each with the sync point after it, if any, and its readonly systems apart, which run after its last sync
89
+ * point. For each system, what the build inferred it reads, writes, looks up and commands, whether it takes its row
90
+ * whole, and the systems it follows directly, with what ordered it after each. `text` gives it all to read; the rest
91
+ * is data to assert on.
92
+ */
93
+ export const describe = (system) => {
94
+ const definition = requireDefinition(system);
95
+ const schedule = scheduleOf(definition);
96
+ const placements = placementsOf(definition);
97
+ const tiers = schedule.tiers.map((tier, t) => ({
98
+ systems: tier.map(leaf => describeLeaf(leaf, placements.get(leaf) ?? none)),
99
+ /**
100
+ * Why a sync point follows the tier, applying the commands so far: each system whose commands may change what a
101
+ * later one that follows it uses, through `keys`, none listed where it despawns or a cascade could; null for none.
102
+ */
103
+ sync: schedule.syncs[t]?.map(reason => ({ from: asSystem(reason.from), to: asSystem(reason.to), keys: reason.keys })) ?? null,
104
+ }));
105
+ const readonly = schedule.observer.flatMap(member => isLeaf(member) ? [describeLeaf(member, none)] : []);
106
+ const width = Math.max(0, ...[...tiers.flatMap(tier => tier.systems), ...readonly].map(described => described.name.length)) + 2;
107
+ const text = [
108
+ ...tiers.flatMap((tier, t) => [
109
+ ...tier.systems.flatMap((described, i) => linesOf(described, width).map((line, l) => `${(i === 0 && l === 0 ? `tier ${t}` : "").padEnd(8)}${line}`)),
110
+ ...(tier.sync ?? none).map((reason, r) => `${(r === 0 ? "sync" : "").padEnd(8)}${reason.from.name}'s commands${reason.keys.length === 0 ? "" : ` of ${keys(reason.keys)}`}, for ${reason.to.name}`),
111
+ ]),
112
+ ...readonly.length === 0 ? none : ["readonly", ...readonly.flatMap(described => linesOf(described, width).map(line => `${"".padEnd(8)}${line}`))],
113
+ ].map(line => line.trimEnd()).join("\n");
114
+ return { tiers, readonly, text };
115
+ };
116
+ //# sourceMappingURL=describe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe.js","sourceRoot":"","sources":["../../../src/interface/system/describe.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
1
  export type { Commands } from './commands.js';
2
2
  export * from './create.js';
3
+ export { describe } from './describe.js';
3
4
  export { render, type RenderContext, type RenderTable } from './render.js';
@@ -1,3 +1,4 @@
1
1
  export * from './create.js';
2
+ export { describe } from './describe.js';
2
3
  export { render } from './render.js';
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/interface/system/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAwC,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/interface/system/index.ts"],"names":[],"mappings":"AAEA,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,EAAwC,MAAM,aAAa,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { Schema } from '../schema/schema.js';
2
+ import type { CommandLists } from './access.js';
2
3
  import type { Resolved } from './declaration.js';
3
4
  import type { Name } from './name.js';
4
5
  /** The schema of a body's input: an object of named fields. */
@@ -16,4 +17,10 @@ export type Leaf = {
16
17
  readonly declaration: Resolved;
17
18
  readonly input: InputSchema | undefined;
18
19
  readonly body: (...parameters: never[]) => void;
20
+ /**
21
+ * What its body's commands name, as the build inferred them, read at first need: null where it couldn't follow
22
+ * them, undefined for none. Apart from its declaration, so a module evaluated again with other commands declares the
23
+ * same system.
24
+ */
25
+ readonly commands: () => CommandLists | null | undefined;
19
26
  };
@@ -4,7 +4,7 @@ import { claimSystem } from '../registry/program.js';
4
4
  import { gpuDevice } from '../resources/gpu-device.js';
5
5
  import { accessorsOf } from '../gpu/accessors.js';
6
6
  import { checkLeaf } from './check.js';
7
- import { accessOf, compact, resourceUses } from './resolve.js';
7
+ import { accessOf, compact, noCommands, resourceUses } from './resolve.js';
8
8
  /**
9
9
  * Declares a render system: it runs once per run on `gpuDevice`'s thread, in schedule order, and records GPU work over
10
10
  * the GPU copy of the components its accessors name, which the world uploads first as needed. It runs only while the
@@ -33,6 +33,7 @@ export const render = (declaration, body) => {
33
33
  },
34
34
  input: undefined,
35
35
  body,
36
+ commands: noCommands,
36
37
  };
37
38
  if (uses.write.length > 0 || uses.reduce.length > 0)
38
39
  throw new Error(`${what} writes or reduces into resources; a render system only reads.`);
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/interface/system/render.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAsD/D;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAClB,WAAuG,EACvG,IAA6B,EACvB,EAAE;IACR,MAAM,EAAE,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,WAAW,IAAI,GAAG,CAAC;IAChC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,WAAW,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACjF,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;IACjE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,WAAW,CAAC;IACvD,MAAM,MAAM,GAAkB;QAC1B,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,WAAW,EAAE;YACT,GAAG,IAAI;YACP,UAAU,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;YACrH,SAAS,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;SACnE;QACD,KAAK,EAAE,SAAS;QAChB,IAAI;KACP,CAAC;IACF,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,gEAAgE,CAAC,CAAC;IAC9I,SAAS,CAAC,MAAM,CAAC,CAAC;IAClB,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,OAAO,SAAS,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,mBAAmB,SAAS,GAAG,CAAC,CAAC;IACnG,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC"}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/interface/system/render.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAGrD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAsD3E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAClB,WAAuG,EACvG,IAA6B,EACvB,EAAE;IACR,MAAM,EAAE,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,WAAW,IAAI,GAAG,CAAC;IAChC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,WAAW,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACjF,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,CAAC;IACjE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,WAAW,CAAC;IACvD,MAAM,MAAM,GAAkB;QAC1B,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,WAAW,EAAE;YACT,GAAG,IAAI;YACP,UAAU,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;YACrH,SAAS,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;SACnE;QACD,KAAK,EAAE,SAAS;QAChB,IAAI;QACJ,QAAQ,EAAE,UAAU;KACvB,CAAC;IACF,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,gEAAgE,CAAC,CAAC;IAC9I,SAAS,CAAC,MAAM,CAAC,CAAC;IAClB,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,OAAO,SAAS,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,mBAAmB,SAAS,GAAG,CAAC,CAAC;IACnG,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACxB,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { ComponentAccess, ComponentLists, Lookup, SystemLookup, SystemLookupLists } from './access.js';
1
+ import type { CommandLists, ComponentAccess, ComponentLists, Lookup, SystemLookup, SystemLookupLists } from './access.js';
2
2
  type Key = symbol;
3
3
  /** What a body reads and writes of a group of keys, and those it changes inside their values, read as well. */
4
4
  type Used = {
@@ -23,6 +23,11 @@ export type Access = {
23
23
  readonly up: readonly Key[] | null;
24
24
  /** The resources the predicates of its declaration's `where` read; absent without predicates. */
25
25
  readonly where?: readonly Key[] | null;
26
+ /**
27
+ * What its commands name, keys or lists of them, by kind, and whether it despawns, or a function giving that; absent
28
+ * where no build said.
29
+ */
30
+ readonly commands?: unknown;
26
31
  readonly at: string;
27
32
  };
28
33
  /**
@@ -63,6 +68,14 @@ export declare const resourceUses: (what: string, access: Access, is: readonly K
63
68
  * them, since the world couldn't tell when to evaluate them again.
64
69
  */
65
70
  export declare const whereReadsOf: (what: string, components: ComponentAccess | undefined, access: Access) => readonly Key[];
71
+ /**
72
+ * What a body's commands name, as the world takes it, read at the first call and kept: null where the build couldn't
73
+ * follow them, nothing for none. The build gives them as a function, so a list declared below the system is read once
74
+ * its module has loaded; one still uninitialized then, as an import cycle leaves it, throws naming it.
75
+ */
76
+ export declare const commandListsOf: (what: string, access: Access) => (() => CommandLists | null | undefined);
77
+ /** The command lists of a system whose body issues none. */
78
+ export declare const noCommands: () => undefined;
66
79
  /** What a body reads of its parent's values. */
67
80
  export declare const upReads: (what: string, access: Access) => readonly Key[];
68
81
  export {};
@@ -4,6 +4,11 @@ import { indexDefinitionOf } from '../registry/indexes.js';
4
4
  import { declarationOf, labelOf } from '../registry/names.js';
5
5
  import { isString, isStruct } from '../registry/schemas.js';
6
6
  const isKeys = (value) => Array.isArray(value) && value.every(key => typeof key === "symbol");
7
+ const isNamed = (value) => Array.isArray(value) && value.every(item => typeof item === "symbol" || isKeys(item));
8
+ /** A binding a command named that holds neither a key nor a list of them isn't followed. */
9
+ const isCommanded = (value) => typeof value === "object" && value !== null
10
+ && isNamed(Reflect.get(value, "spawn")) && isNamed(Reflect.get(value, "add")) && isNamed(Reflect.get(value, "remove"))
11
+ && typeof Reflect.get(value, "despawn") === "boolean";
7
12
  const isUsed = (value) => typeof value === "object" && value !== null
8
13
  && isKeys(Reflect.get(value, "read")) && isKeys(Reflect.get(value, "write"))
9
14
  && (Reflect.get(value, "mutate") === undefined || isKeys(Reflect.get(value, "mutate")));
@@ -79,7 +84,7 @@ export const componentLists = (components, used, reading, whereReads = []) => {
79
84
  : used.write;
80
85
  const read = used === null ? without(held, write) : without(used.read, write);
81
86
  const has = [...without(members, read, write), ...without(filtered, read, write)];
82
- return compact({ read, write, has, optional, not: components.not, added: components.added, changed: components.changed, where, whereReads });
87
+ return compact({ read, write, has, optional, not: components.not, added: components.added, changed: components.changed, where, whereReads, whole: components.whole });
83
88
  };
84
89
  /**
85
90
  * A lookup's lists: what the body reads of its rows, the rest of its `with` only required. Without the body's uses,
@@ -133,6 +138,50 @@ export const whereReadsOf = (what, components, access) => {
133
138
  throw new Error(`${what}'s where predicates (${access.at}) read resources in a way the build can't follow, so it can't tell when to evaluate them again: index them by key directly, or destructure them by key, in a predicate written in place in a module built with Compiler.plugin().`);
134
139
  return reads;
135
140
  };
141
+ /**
142
+ * What a body's commands name, as the world takes it, read at the first call and kept: null where the build couldn't
143
+ * follow them, nothing for none. The build gives them as a function, so a list declared below the system is read once
144
+ * its module has loaded; one still uninitialized then, as an import cycle leaves it, throws naming it.
145
+ */
146
+ export const commandListsOf = (what, access) => {
147
+ let read = false;
148
+ let lists;
149
+ return () => {
150
+ if (!read) {
151
+ lists = listsOf(what, access.commands);
152
+ read = true;
153
+ }
154
+ return lists;
155
+ };
156
+ };
157
+ /** The command lists of a system whose body issues none. */
158
+ export const noCommands = () => undefined;
159
+ const listsOf = (what, given) => {
160
+ const commands = typeof given === "function" ? evaluated(what, () => Reflect.apply(given, undefined, [])) : given;
161
+ if (commands === undefined)
162
+ return undefined;
163
+ if (!isCommanded(commands))
164
+ return null;
165
+ if (!commands.despawn && commands.spawn.length + commands.add.length + commands.remove.length === 0)
166
+ return undefined;
167
+ const flat = (named) => [...new Set(named.flat())];
168
+ const lists = compact({ spawn: flat(commands.spawn), add: flat(commands.add), remove: flat(commands.remove), despawn: commands.despawn ? true : undefined });
169
+ return Object.keys(lists).length === 0 ? undefined : lists;
170
+ };
171
+ /** What the build's function of a body's commands gives. */
172
+ const evaluated = (what, commands) => {
173
+ try {
174
+ return commands();
175
+ }
176
+ catch (error) {
177
+ if (!(error instanceof ReferenceError))
178
+ throw error;
179
+ // Engines quote the binding in the message: "Cannot access 'standard' before initialization", or "can't access
180
+ // lexical declaration 'standard' before initialization".
181
+ const binding = /'([A-Za-z_$][\w$]*)'/.exec(error.message)?.[1];
182
+ throw new Error(`${what} names ${binding === undefined ? "a declaration" : `"${binding}"`} in its commands before it's initialized: declare it above the system.`, { cause: error });
183
+ }
184
+ };
136
185
  /** What a body reads of its parent's values. */
137
186
  export const upReads = (what, access) => followed(what, access.up, "its parent's values", access);
138
187
  //# sourceMappingURL=resolve.js.map