@playfast/reform 1.2.1 → 1.4.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 (416) hide show
  1. package/README.md +15 -6
  2. package/dist/boundary/boundary.d.ts +64 -0
  3. package/dist/boundary/boundary.d.ts.map +1 -0
  4. package/dist/boundary/boundary.js +102 -0
  5. package/dist/boundary/boundary.js.map +1 -0
  6. package/dist/calc/asyncCalc.d.ts +23 -0
  7. package/dist/calc/asyncCalc.d.ts.map +1 -0
  8. package/dist/calc/asyncCalc.js +100 -0
  9. package/dist/calc/asyncCalc.js.map +1 -0
  10. package/dist/calc/asyncCalcTypes.d.ts +80 -0
  11. package/dist/calc/asyncCalcTypes.d.ts.map +1 -0
  12. package/dist/calc/asyncCalcTypes.js +2 -0
  13. package/dist/calc/asyncCalcTypes.js.map +1 -0
  14. package/dist/calc/asyncData.d.ts +29 -0
  15. package/dist/calc/asyncData.d.ts.map +1 -0
  16. package/dist/calc/asyncData.js +21 -0
  17. package/dist/calc/asyncData.js.map +1 -0
  18. package/dist/calc/calc.d.ts +39 -0
  19. package/dist/calc/calc.d.ts.map +1 -0
  20. package/dist/calc/calc.js +48 -0
  21. package/dist/calc/calc.js.map +1 -0
  22. package/dist/calc/calcFamily.d.ts +40 -0
  23. package/dist/calc/calcFamily.d.ts.map +1 -0
  24. package/dist/calc/calcFamily.js +156 -0
  25. package/dist/calc/calcFamily.js.map +1 -0
  26. package/dist/calc/compose.d.ts +5 -0
  27. package/dist/calc/compose.d.ts.map +1 -0
  28. package/dist/calc/compose.js +5 -0
  29. package/dist/calc/compose.js.map +1 -0
  30. package/dist/calc/queryState.d.ts +14 -0
  31. package/dist/calc/queryState.d.ts.map +1 -0
  32. package/dist/calc/queryState.js +39 -0
  33. package/dist/calc/queryState.js.map +1 -0
  34. package/dist/channel/channel.d.ts +51 -0
  35. package/dist/channel/channel.d.ts.map +1 -0
  36. package/dist/channel/channel.js +91 -0
  37. package/dist/channel/channel.js.map +1 -0
  38. package/dist/channel/procedures.d.ts +24 -0
  39. package/dist/channel/procedures.d.ts.map +1 -0
  40. package/dist/channel/procedures.js +82 -0
  41. package/dist/channel/procedures.js.map +1 -0
  42. package/dist/compose/composition.d.ts +12 -0
  43. package/dist/compose/composition.d.ts.map +1 -0
  44. package/dist/compose/composition.js +62 -0
  45. package/dist/compose/composition.js.map +1 -0
  46. package/dist/compose/compositionTypes.d.ts +127 -0
  47. package/dist/compose/compositionTypes.d.ts.map +1 -0
  48. package/dist/compose/compositionTypes.js +2 -0
  49. package/dist/compose/compositionTypes.js.map +1 -0
  50. package/dist/compose/host.d.ts +6 -0
  51. package/dist/compose/host.d.ts.map +1 -0
  52. package/dist/compose/host.js +2 -0
  53. package/dist/compose/host.js.map +1 -0
  54. package/dist/compose/props.d.ts +10 -0
  55. package/dist/compose/props.d.ts.map +1 -0
  56. package/dist/compose/props.js +6 -0
  57. package/dist/compose/props.js.map +1 -0
  58. package/dist/compose/provide.d.ts +18 -0
  59. package/dist/compose/provide.d.ts.map +1 -0
  60. package/dist/compose/provide.js +49 -0
  61. package/dist/compose/provide.js.map +1 -0
  62. package/dist/compose/slot.d.ts +70 -0
  63. package/dist/compose/slot.d.ts.map +1 -0
  64. package/dist/compose/slot.js +26 -0
  65. package/dist/compose/slot.js.map +1 -0
  66. package/dist/compose/structure.d.ts +51 -0
  67. package/dist/compose/structure.d.ts.map +1 -0
  68. package/dist/compose/structure.js +117 -0
  69. package/dist/compose/structure.js.map +1 -0
  70. package/dist/compose/ui.d.ts +112 -0
  71. package/dist/compose/ui.d.ts.map +1 -0
  72. package/dist/compose/ui.js +58 -0
  73. package/dist/compose/ui.js.map +1 -0
  74. package/dist/definition/definition.d.ts +11 -0
  75. package/dist/definition/definition.d.ts.map +1 -0
  76. package/dist/definition/definition.js +35 -0
  77. package/dist/definition/definition.js.map +1 -0
  78. package/dist/event/event.d.ts +52 -0
  79. package/dist/event/event.d.ts.map +1 -0
  80. package/dist/event/event.js +88 -0
  81. package/dist/event/event.js.map +1 -0
  82. package/dist/event/eventGroup.d.ts +8 -0
  83. package/dist/event/eventGroup.d.ts.map +1 -0
  84. package/dist/event/eventGroup.js +3 -0
  85. package/dist/event/eventGroup.js.map +1 -0
  86. package/dist/feature/feature.d.ts +27 -0
  87. package/dist/feature/feature.d.ts.map +1 -0
  88. package/dist/feature/feature.js +20 -0
  89. package/dist/feature/feature.js.map +1 -0
  90. package/dist/feature/featureBinding.d.ts +85 -0
  91. package/dist/feature/featureBinding.d.ts.map +1 -0
  92. package/dist/feature/featureBinding.js +10 -0
  93. package/dist/feature/featureBinding.js.map +1 -0
  94. package/dist/feature/featureClass.d.ts +10 -0
  95. package/dist/feature/featureClass.d.ts.map +1 -0
  96. package/dist/feature/featureClass.js +2 -0
  97. package/dist/feature/featureClass.js.map +1 -0
  98. package/dist/feature/featureConfig.d.ts +86 -0
  99. package/dist/feature/featureConfig.d.ts.map +1 -0
  100. package/dist/feature/featureConfig.js +13 -0
  101. package/dist/feature/featureConfig.js.map +1 -0
  102. package/dist/feature/featureFactory.d.ts +15 -0
  103. package/dist/feature/featureFactory.d.ts.map +1 -0
  104. package/dist/feature/featureFactory.js +59 -0
  105. package/dist/feature/featureFactory.js.map +1 -0
  106. package/dist/feature/featureModule.d.ts +28 -0
  107. package/dist/feature/featureModule.d.ts.map +1 -0
  108. package/dist/feature/featureModule.js +33 -0
  109. package/dist/feature/featureModule.js.map +1 -0
  110. package/dist/feature/featureNativeTree.d.ts +26 -0
  111. package/dist/feature/featureNativeTree.d.ts.map +1 -0
  112. package/dist/feature/featureNativeTree.js +2 -0
  113. package/dist/feature/featureNativeTree.js.map +1 -0
  114. package/dist/feature/featureRequirement.d.ts +43 -0
  115. package/dist/feature/featureRequirement.d.ts.map +1 -0
  116. package/dist/feature/featureRequirement.js +6 -0
  117. package/dist/feature/featureRequirement.js.map +1 -0
  118. package/dist/feature/featureVariants.d.ts +9 -0
  119. package/dist/feature/featureVariants.d.ts.map +1 -0
  120. package/dist/feature/featureVariants.js +59 -0
  121. package/dist/feature/featureVariants.js.map +1 -0
  122. package/dist/feature/mountFeature.d.ts +10 -0
  123. package/dist/feature/mountFeature.d.ts.map +1 -0
  124. package/dist/feature/mountFeature.js +14 -0
  125. package/dist/feature/mountFeature.js.map +1 -0
  126. package/dist/graph/closure.d.ts +77 -0
  127. package/dist/graph/closure.d.ts.map +1 -0
  128. package/dist/graph/closure.js +4 -0
  129. package/dist/graph/closure.js.map +1 -0
  130. package/dist/graph/services.d.ts +30 -0
  131. package/dist/graph/services.d.ts.map +1 -0
  132. package/dist/graph/services.js +2 -0
  133. package/dist/graph/services.js.map +1 -0
  134. package/dist/graph/summary.d.ts +60 -0
  135. package/dist/graph/summary.d.ts.map +1 -0
  136. package/dist/graph/summary.js +7 -0
  137. package/dist/graph/summary.js.map +1 -0
  138. package/dist/index.d.ts +51 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +34 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/internal/bucketCache.d.ts +19 -0
  143. package/dist/internal/bucketCache.d.ts.map +1 -0
  144. package/dist/internal/bucketCache.js +20 -0
  145. package/dist/internal/bucketCache.js.map +1 -0
  146. package/dist/internal/capture.d.ts +17 -0
  147. package/dist/internal/capture.d.ts.map +1 -0
  148. package/dist/internal/capture.js +5 -0
  149. package/dist/internal/capture.js.map +1 -0
  150. package/dist/internal/env.d.ts +2 -0
  151. package/dist/internal/env.d.ts.map +1 -0
  152. package/dist/internal/env.js +5 -0
  153. package/dist/internal/env.js.map +1 -0
  154. package/dist/internal/errors.d.ts +48 -0
  155. package/dist/internal/errors.d.ts.map +1 -0
  156. package/dist/internal/errors.js +69 -0
  157. package/dist/internal/errors.js.map +1 -0
  158. package/dist/internal/familyKeys.d.ts +16 -0
  159. package/dist/internal/familyKeys.d.ts.map +1 -0
  160. package/dist/internal/familyKeys.js +35 -0
  161. package/dist/internal/familyKeys.js.map +1 -0
  162. package/dist/internal/inspect.d.ts +5 -0
  163. package/dist/internal/inspect.d.ts.map +1 -0
  164. package/dist/internal/inspect.js +20 -0
  165. package/dist/internal/inspect.js.map +1 -0
  166. package/dist/internal/platform.d.ts +43 -0
  167. package/dist/internal/platform.d.ts.map +1 -0
  168. package/dist/internal/platform.js +68 -0
  169. package/dist/internal/platform.js.map +1 -0
  170. package/dist/internal/queryDriver.d.ts +7 -0
  171. package/dist/internal/queryDriver.d.ts.map +1 -0
  172. package/dist/internal/queryDriver.js +222 -0
  173. package/dist/internal/queryDriver.js.map +1 -0
  174. package/dist/internal/queryDriverConsume.d.ts +9 -0
  175. package/dist/internal/queryDriverConsume.d.ts.map +1 -0
  176. package/dist/internal/queryDriverConsume.js +16 -0
  177. package/dist/internal/queryDriverConsume.js.map +1 -0
  178. package/dist/internal/queryDriverHydrate.d.ts +17 -0
  179. package/dist/internal/queryDriverHydrate.d.ts.map +1 -0
  180. package/dist/internal/queryDriverHydrate.js +25 -0
  181. package/dist/internal/queryDriverHydrate.js.map +1 -0
  182. package/dist/internal/queryDriverPersist.d.ts +16 -0
  183. package/dist/internal/queryDriverPersist.d.ts.map +1 -0
  184. package/dist/internal/queryDriverPersist.js +15 -0
  185. package/dist/internal/queryDriverPersist.js.map +1 -0
  186. package/dist/internal/queryDriverPersistWarn.d.ts +12 -0
  187. package/dist/internal/queryDriverPersistWarn.d.ts.map +1 -0
  188. package/dist/internal/queryDriverPersistWarn.js +31 -0
  189. package/dist/internal/queryDriverPersistWarn.js.map +1 -0
  190. package/dist/internal/queryDriverSettle.d.ts +23 -0
  191. package/dist/internal/queryDriverSettle.d.ts.map +1 -0
  192. package/dist/internal/queryDriverSettle.js +52 -0
  193. package/dist/internal/queryDriverSettle.js.map +1 -0
  194. package/dist/internal/queryDriverStore.d.ts +28 -0
  195. package/dist/internal/queryDriverStore.d.ts.map +1 -0
  196. package/dist/internal/queryDriverStore.js +53 -0
  197. package/dist/internal/queryDriverStore.js.map +1 -0
  198. package/dist/internal/queryDriverTypes.d.ts +44 -0
  199. package/dist/internal/queryDriverTypes.d.ts.map +1 -0
  200. package/dist/internal/queryDriverTypes.js +9 -0
  201. package/dist/internal/queryDriverTypes.js.map +1 -0
  202. package/dist/internal/queryEvents.d.ts +12 -0
  203. package/dist/internal/queryEvents.d.ts.map +1 -0
  204. package/dist/internal/queryEvents.js +11 -0
  205. package/dist/internal/queryEvents.js.map +1 -0
  206. package/dist/internal/queryStore.d.ts +13 -0
  207. package/dist/internal/queryStore.d.ts.map +1 -0
  208. package/dist/internal/queryStore.js +11 -0
  209. package/dist/internal/queryStore.js.map +1 -0
  210. package/dist/internal/reuse.d.ts +2 -0
  211. package/dist/internal/reuse.d.ts.map +1 -0
  212. package/dist/internal/reuse.js +55 -0
  213. package/dist/internal/reuse.js.map +1 -0
  214. package/dist/internal/scheduler.d.ts +14 -0
  215. package/dist/internal/scheduler.d.ts.map +1 -0
  216. package/dist/internal/scheduler.js +101 -0
  217. package/dist/internal/scheduler.js.map +1 -0
  218. package/dist/internal/seeds.d.ts +3 -0
  219. package/dist/internal/seeds.d.ts.map +1 -0
  220. package/dist/internal/seeds.js +3 -0
  221. package/dist/internal/seeds.js.map +1 -0
  222. package/dist/internal/sources.d.ts +20 -0
  223. package/dist/internal/sources.d.ts.map +1 -0
  224. package/dist/internal/sources.js +39 -0
  225. package/dist/internal/sources.js.map +1 -0
  226. package/dist/internal/stateRegistry.d.ts +2 -0
  227. package/dist/internal/stateRegistry.d.ts.map +1 -0
  228. package/dist/internal/stateRegistry.js +15 -0
  229. package/dist/internal/stateRegistry.js.map +1 -0
  230. package/dist/internal/store.d.ts +15 -0
  231. package/dist/internal/store.d.ts.map +1 -0
  232. package/dist/internal/store.js +61 -0
  233. package/dist/internal/store.js.map +1 -0
  234. package/dist/internal/track.d.ts +15 -0
  235. package/dist/internal/track.d.ts.map +1 -0
  236. package/dist/internal/track.js +11 -0
  237. package/dist/internal/track.js.map +1 -0
  238. package/dist/internal/variance.d.ts +4 -0
  239. package/dist/internal/variance.d.ts.map +1 -0
  240. package/dist/internal/variance.js +2 -0
  241. package/dist/internal/variance.js.map +1 -0
  242. package/dist/internal.d.ts +43 -0
  243. package/dist/internal.d.ts.map +1 -0
  244. package/dist/internal.js +59 -0
  245. package/dist/internal.js.map +1 -0
  246. package/dist/namespace/namespace.d.ts +24 -0
  247. package/dist/namespace/namespace.d.ts.map +1 -0
  248. package/dist/namespace/namespace.js +20 -0
  249. package/dist/namespace/namespace.js.map +1 -0
  250. package/dist/procedure/procedure.d.ts +32 -0
  251. package/dist/procedure/procedure.d.ts.map +1 -0
  252. package/dist/procedure/procedure.js +34 -0
  253. package/dist/procedure/procedure.js.map +1 -0
  254. package/dist/reducer/reducer.d.ts +35 -0
  255. package/dist/reducer/reducer.d.ts.map +1 -0
  256. package/dist/reducer/reducer.js +73 -0
  257. package/dist/reducer/reducer.js.map +1 -0
  258. package/dist/remote/pendingQueue.d.ts +22 -0
  259. package/dist/remote/pendingQueue.d.ts.map +1 -0
  260. package/dist/remote/pendingQueue.js +129 -0
  261. package/dist/remote/pendingQueue.js.map +1 -0
  262. package/dist/remote/remoteState.d.ts +13 -0
  263. package/dist/remote/remoteState.d.ts.map +1 -0
  264. package/dist/remote/remoteState.js +189 -0
  265. package/dist/remote/remoteState.js.map +1 -0
  266. package/dist/remote/remoteStateMake.d.ts +8 -0
  267. package/dist/remote/remoteStateMake.d.ts.map +1 -0
  268. package/dist/remote/remoteStateMake.js +46 -0
  269. package/dist/remote/remoteStateMake.js.map +1 -0
  270. package/dist/remote/remoteStateSend.d.ts +43 -0
  271. package/dist/remote/remoteStateSend.d.ts.map +1 -0
  272. package/dist/remote/remoteStateSend.js +83 -0
  273. package/dist/remote/remoteStateSend.js.map +1 -0
  274. package/dist/remote/remoteStateTypes.d.ts +106 -0
  275. package/dist/remote/remoteStateTypes.d.ts.map +1 -0
  276. package/dist/remote/remoteStateTypes.js +4 -0
  277. package/dist/remote/remoteStateTypes.js.map +1 -0
  278. package/dist/runtime/appRuntime.d.ts +10 -0
  279. package/dist/runtime/appRuntime.d.ts.map +1 -0
  280. package/dist/runtime/appRuntime.js +6 -0
  281. package/dist/runtime/appRuntime.js.map +1 -0
  282. package/dist/runtime/bus.d.ts +22 -0
  283. package/dist/runtime/bus.d.ts.map +1 -0
  284. package/dist/runtime/bus.js +12 -0
  285. package/dist/runtime/bus.js.map +1 -0
  286. package/dist/runtime/capturedAppRuntime.d.ts +7 -0
  287. package/dist/runtime/capturedAppRuntime.d.ts.map +1 -0
  288. package/dist/runtime/capturedAppRuntime.js +137 -0
  289. package/dist/runtime/capturedAppRuntime.js.map +1 -0
  290. package/dist/runtime/eventBudget.d.ts +32 -0
  291. package/dist/runtime/eventBudget.d.ts.map +1 -0
  292. package/dist/runtime/eventBudget.js +68 -0
  293. package/dist/runtime/eventBudget.js.map +1 -0
  294. package/dist/runtime/featureMount.d.ts +48 -0
  295. package/dist/runtime/featureMount.d.ts.map +1 -0
  296. package/dist/runtime/featureMount.js +118 -0
  297. package/dist/runtime/featureMount.js.map +1 -0
  298. package/dist/runtime/instrumentation.d.ts +18 -0
  299. package/dist/runtime/instrumentation.d.ts.map +1 -0
  300. package/dist/runtime/instrumentation.js +16 -0
  301. package/dist/runtime/instrumentation.js.map +1 -0
  302. package/dist/runtime/loop.d.ts +44 -0
  303. package/dist/runtime/loop.d.ts.map +1 -0
  304. package/dist/runtime/loop.js +131 -0
  305. package/dist/runtime/loop.js.map +1 -0
  306. package/dist/runtime/queries.d.ts +20 -0
  307. package/dist/runtime/queries.d.ts.map +1 -0
  308. package/dist/runtime/queries.js +21 -0
  309. package/dist/runtime/queries.js.map +1 -0
  310. package/dist/runtime/runtimeHandle.d.ts +56 -0
  311. package/dist/runtime/runtimeHandle.d.ts.map +1 -0
  312. package/dist/runtime/runtimeHandle.js +2 -0
  313. package/dist/runtime/runtimeHandle.js.map +1 -0
  314. package/dist/scene/scene.d.ts +55 -0
  315. package/dist/scene/scene.d.ts.map +1 -0
  316. package/dist/scene/scene.js +74 -0
  317. package/dist/scene/scene.js.map +1 -0
  318. package/dist/state/state.d.ts +54 -0
  319. package/dist/state/state.d.ts.map +1 -0
  320. package/dist/state/state.js +41 -0
  321. package/dist/state/state.js.map +1 -0
  322. package/dist/state/stateFamily.d.ts +59 -0
  323. package/dist/state/stateFamily.d.ts.map +1 -0
  324. package/dist/state/stateFamily.js +139 -0
  325. package/dist/state/stateFamily.js.map +1 -0
  326. package/dist/state/stateGroup.d.ts +36 -0
  327. package/dist/state/stateGroup.d.ts.map +1 -0
  328. package/dist/state/stateGroup.js +33 -0
  329. package/dist/state/stateGroup.js.map +1 -0
  330. package/dist/state/token.d.ts +35 -0
  331. package/dist/state/token.d.ts.map +1 -0
  332. package/dist/state/token.js +18 -0
  333. package/dist/state/token.js.map +1 -0
  334. package/dist/synced/syncedStore.d.ts +44 -0
  335. package/dist/synced/syncedStore.d.ts.map +1 -0
  336. package/dist/synced/syncedStore.js +32 -0
  337. package/dist/synced/syncedStore.js.map +1 -0
  338. package/dist/testkit/flight.testkit.d.ts +18 -0
  339. package/dist/testkit/flight.testkit.d.ts.map +1 -0
  340. package/dist/testkit/flight.testkit.js +46 -0
  341. package/dist/testkit/flight.testkit.js.map +1 -0
  342. package/dist/ui/node.d.ts +3 -0
  343. package/dist/ui/node.d.ts.map +1 -0
  344. package/dist/ui/node.js +2 -0
  345. package/dist/ui/node.js.map +1 -0
  346. package/dist/ui/trigger.d.ts +2 -0
  347. package/dist/ui/trigger.d.ts.map +1 -0
  348. package/dist/ui/trigger.js +2 -0
  349. package/dist/ui/trigger.js.map +1 -0
  350. package/dist/wire/tree.d.ts +32 -0
  351. package/dist/wire/tree.d.ts.map +1 -0
  352. package/dist/wire/tree.js +64 -0
  353. package/dist/wire/tree.js.map +1 -0
  354. package/dist/wire/triggers.d.ts +25 -0
  355. package/dist/wire/triggers.d.ts.map +1 -0
  356. package/dist/wire/triggers.js +31 -0
  357. package/dist/wire/triggers.js.map +1 -0
  358. package/package.json +17 -5
  359. package/src/calc/asyncCalc-key-attribution.test.ts +182 -0
  360. package/src/calc/asyncCalc-registry-name.test.ts +82 -0
  361. package/src/calc/asyncCalc.superseded-commit.test.ts +162 -0
  362. package/src/calc/asyncCalc.test.ts +35 -7
  363. package/src/calc/asyncCalc.ts +33 -10
  364. package/src/calc/asyncCalcTypes.test.ts +64 -0
  365. package/src/calc/asyncCalcTypes.ts +8 -10
  366. package/src/calc/calcFamily.ts +81 -34
  367. package/src/calc/family-identity.test.ts +231 -0
  368. package/src/calc/queryState.ts +36 -5
  369. package/src/channel/channel-throttle-frames.test.ts +163 -0
  370. package/src/channel/channel.ts +5 -0
  371. package/src/compose/compose-identity.test.ts +175 -0
  372. package/src/compose/composition.ts +8 -4
  373. package/src/compose/structure.ts +45 -13
  374. package/src/compose/ui.ts +22 -5
  375. package/src/event/event.ts +31 -2
  376. package/src/event/syncTrigger.test.ts +66 -0
  377. package/src/internal/familyKeys.ts +41 -0
  378. package/src/internal/platform.test.ts +55 -0
  379. package/src/internal/platform.ts +72 -0
  380. package/src/internal/queryDriver-defect-attribution.test.ts +107 -0
  381. package/src/internal/queryDriver-persist-key.test.ts +118 -0
  382. package/src/internal/queryDriver.persistence-staleness.test.ts +209 -0
  383. package/src/internal/queryDriver.ts +92 -80
  384. package/src/internal/queryDriverConsume.ts +42 -0
  385. package/src/internal/queryDriverHydrate.ts +9 -3
  386. package/src/internal/queryDriverPersist.ts +42 -0
  387. package/src/internal/queryDriverPersistWarn.ts +61 -0
  388. package/src/internal/queryDriverSettle.ts +85 -0
  389. package/src/internal/queryDriverStore.ts +9 -74
  390. package/src/internal/queryDriverTypes.ts +10 -0
  391. package/src/internal/queryState-and-scheduler-audit.test.ts +170 -0
  392. package/src/internal/scheduler-multi-source-wake.test.ts +111 -0
  393. package/src/internal/scheduler.ts +80 -6
  394. package/src/internal.ts +1 -0
  395. package/src/reducer/reducer.ts +3 -3
  396. package/src/remote/pendingQueue.ts +35 -5
  397. package/src/remote/remoteState.intent-key-stamp.test.ts +207 -0
  398. package/src/remote/remoteState.key-attribution.test.ts +174 -0
  399. package/src/remote/remoteState.ts +27 -15
  400. package/src/remote/remoteStateSend.ts +29 -8
  401. package/src/remote/remoteStateTypes.ts +7 -0
  402. package/src/runtime/bus.ts +6 -1
  403. package/src/runtime/capturedAppRuntime.ts +134 -110
  404. package/src/runtime/eventBudget.ts +2 -1
  405. package/src/runtime/feature-mount-ownership.test.ts +539 -0
  406. package/src/runtime/featureMount.ts +110 -3
  407. package/src/runtime/loop.ts +29 -6
  408. package/src/runtime/mount-inflight-ownership.test.ts +361 -0
  409. package/src/runtime/mount-scope-hardening.test.ts +440 -0
  410. package/src/runtime/runtime.schema-identity.test.ts +188 -0
  411. package/src/state/state.ts +8 -4
  412. package/src/state/stateFamily.ts +86 -36
  413. package/src/state/stateGroup.ts +24 -6
  414. package/src/testkit/flight.testkit.ts +2 -1
  415. package/src/wire/tree-key-presence.test.ts +46 -0
  416. package/src/wire/tree.ts +9 -1
@@ -1,7 +1,26 @@
1
- import { Context, Effect, Exit, Fiber, Layer, ManagedRuntime, Option, Scope } from 'effect'
2
- import type { CompositionActivation, CompositionId, RequiredSlotIdentities } from '../compose/composition'
1
+ import {
2
+ Context,
3
+ Effect,
4
+ ExecutionStrategy,
5
+ Exit,
6
+ Layer,
7
+ ManagedRuntime,
8
+ Option,
9
+ Scope,
10
+ } from 'effect'
11
+ import type {
12
+ CompositionActivation,
13
+ CompositionId,
14
+ RequiredSlotIdentities,
15
+ } from '../compose/composition'
3
16
  import type { UiContract } from '../compose/ui'
4
- import { type AnyFeatureBinding, type CapturedFeatureBinding, type FeatureBinding, FeatureInput, type FeatureRequirement } from '../feature/feature'
17
+ import {
18
+ type AnyFeatureBinding,
19
+ type CapturedFeatureBinding,
20
+ type FeatureBinding,
21
+ FeatureInput,
22
+ type FeatureRequirement,
23
+ } from '../feature/feature'
5
24
  import type {
6
25
  AnyFeatureGraphSummary,
7
26
  FeatureSummaryCompositionIdentity,
@@ -17,7 +36,16 @@ import { type Node } from '../ui/node'
17
36
  import { type CapturedScene, sceneInstrumentation } from '../scene/scene'
18
37
  import { Bus, publish, type Priority, type Tagged } from './bus'
19
38
  import { CurrentEventBudget, type ReformOptions, resolveEventBudget } from './eventBudget'
20
- import { featureMountFailure, forkFeatureMount, hasFeatureRequirements } from './featureMount'
39
+ import {
40
+ invalidMountProps,
41
+ missingHostServices,
42
+ type FeatureMountHost,
43
+ forkFeatureMount,
44
+ hasFeatureRequirements,
45
+ mountActivation,
46
+ startMount,
47
+ withInstrumentation,
48
+ } from './featureMount'
21
49
  import type {
22
50
  AnyFeatureMountHandlers,
23
51
  AppRuntime,
@@ -52,8 +80,15 @@ export const makeCapturedAppRuntime = <
52
80
  // Hosts can still render tearing-down trees after the managed runtime is disposed.
53
81
  const status = { disposed: false, booted: false }
54
82
  const activationDisposers = new Set<() => void>()
55
- const mountHost = {
56
- runFork: (effect: Effect.Effect<void, never, never>) => runtime.runFork(effect),
83
+ // Everything this runtime mounts is forked from here, so `dispose()` closes it all
84
+ // without having to be handed each mount's disposer. A forked scope deregisters
85
+ // itself from its owner when it closes first, so churn does not accumulate.
86
+ // Parallel: the root's finalizers are one independent mount each, so a teardown that
87
+ // takes a turn must not withhold its siblings'.
88
+ const rootScope = Effect.runSync(Scope.make(ExecutionStrategy.parallel))
89
+ const instrumented = withInstrumentation(instrumentation)
90
+ const mountHost: FeatureMountHost = {
91
+ runFork: <A>(effect: Effect.Effect<A, never, never>) => runtime.runFork(effect),
57
92
  isDisposed: () => status.disposed,
58
93
  }
59
94
 
@@ -68,33 +103,22 @@ export const makeCapturedAppRuntime = <
68
103
  runtime.runFork(publish(priority, event).pipe(Effect.provideService(Bus, rootBus.value)))
69
104
  }
70
105
 
71
- const mountScoped = (activation: CompositionActivation): (() => void) => {
72
- if (status.disposed) {
73
- return () => {}
74
- }
75
- const scope = Effect.runSync(Scope.make())
76
- const liveness = { active: true }
77
- const fiber = runtime.runFork(
78
- Layer.build(activation).pipe(Effect.provideService(Scope.Scope, scope)),
106
+ const mountScopedOnto = (
107
+ ownerScope: Scope.Scope,
108
+ activation: CompositionActivation,
109
+ ): (() => void) =>
110
+ mountActivation(
111
+ mountHost,
112
+ activationDisposers,
113
+ instrumented(Layer.build(activation)),
114
+ ownerScope,
79
115
  )
80
- const dispose = (): void => {
81
- if (!liveness.active) {
82
- return
83
- }
84
- liveness.active = false
85
- fiber.unsafeInterruptAsFork(fiber.id())
86
- const close = Fiber.await(fiber).pipe(
87
- Effect.zipRight(Scope.close(scope, Exit.succeed(undefined))),
88
- Effect.ensuring(Effect.sync(() => activationDisposers.delete(dispose))),
89
- )
90
- Effect.runFork(close)
91
- }
92
- activationDisposers.add(dispose)
93
- return dispose
94
- }
95
116
 
117
+ // A feature's handle mounts into the feature's own scope: whatever it mounts must
118
+ // not outlive the context it was built against.
96
119
  const makeChildRuntime = <ChildServices>(
97
120
  context: Context.Context<ChildServices>,
121
+ ownerScope: Scope.Scope,
98
122
  ): RuntimeHandle<ChildServices> => ({
99
123
  read: <Identifier extends ChildServices, Service>(
100
124
  tag: Context.Tag<Identifier, Service>,
@@ -104,11 +128,12 @@ export const makeCapturedAppRuntime = <
104
128
  ): Option.Option<Service> => Context.getOption(context, tag),
105
129
  runRender,
106
130
  dispatch,
107
- mountScoped,
108
- mountFeature: (binding, handlers) => mountFeatureOnto(context, binding, handlers),
131
+ mountScoped: (activation) => mountScopedOnto(ownerScope, activation),
132
+ mountFeature: (binding, handlers) => mountFeatureOnto(context, ownerScope, binding, handlers),
109
133
  mountCapturedFeature: (binding, handlers) =>
110
- mountCapturedFeatureOnto(context, binding, handlers),
111
- mountAnyFeature: (binding, handlers) => mountAnyFeatureOnto(context, binding, handlers),
134
+ mountCapturedFeatureOnto(context, ownerScope, binding, handlers),
135
+ mountAnyFeature: (binding, handlers) =>
136
+ mountAnyFeatureOnto(context, ownerScope, binding, handlers),
112
137
  instrumentation,
113
138
  })
114
139
 
@@ -119,6 +144,7 @@ export const makeCapturedAppRuntime = <
119
144
  const DirectRequires extends ReadonlyArray<FeatureRequirement>,
120
145
  >(
121
146
  hostContext: Context.Context<HostServices>,
147
+ ownerScope: Scope.Scope,
122
148
  binding: FeatureBinding<Summary, ROut, DirectRequires>,
123
149
  handlers: FeatureMountHandlers<
124
150
  FeatureSummaryUsesInput<Summary>,
@@ -126,37 +152,35 @@ export const makeCapturedAppRuntime = <
126
152
  HostServices | ROut
127
153
  >,
128
154
  ): (() => void) => {
129
- if (status.disposed) {
130
- return () => {}
131
- }
132
- const scope = Effect.runSync(Scope.make())
133
- const mount = Effect.flatMap(binding.load, (loaded) => {
134
- if (
135
- !hasFeatureRequirements<HostServices, FeatureSummaryOpenServices<Summary>, DirectRequires>(
136
- hostContext,
137
- loaded.requires,
138
- )
139
- ) {
140
- return Effect.fail(
141
- featureMountFailure(
142
- `Feature ${binding.manifest.name} requires services missing from the host runtime`,
143
- ),
144
- )
145
- }
146
- return Effect.gen(function* () {
147
- const bus = Context.get(hostContext, Bus)
148
- const featureContext = Context.add(hostContext, FeatureInput, handlers.props)
149
- const context = yield* Layer.build(
150
- Layer.provide(loaded.layer, Layer.succeedContext(featureContext)),
151
- )
152
- yield* Effect.forEach(binding.boot, (event) => publish('High', event), {
153
- discard: true,
154
- }).pipe(Effect.provideService(Bus, bus))
155
- const merged = Context.merge(hostContext, context)
156
- yield* Effect.sync(() => handlers.onLive(makeChildRuntime<HostServices | ROut>(merged)))
155
+ const mountInto = (scope: Scope.CloseableScope) =>
156
+ Effect.flatMap(binding.load, (loaded) => {
157
+ if (
158
+ !hasFeatureRequirements<
159
+ HostServices,
160
+ FeatureSummaryOpenServices<Summary>,
161
+ DirectRequires
162
+ >(hostContext, loaded.requires)
163
+ ) {
164
+ return missingHostServices(binding.manifest.name)
165
+ }
166
+ return Effect.gen(function* () {
167
+ const bus = Context.get(hostContext, Bus)
168
+ const featureContext = Context.add(hostContext, FeatureInput, handlers.props)
169
+ const context = yield* Layer.build(
170
+ Layer.provide(loaded.layer, Layer.succeedContext(featureContext)),
171
+ )
172
+ yield* Effect.forEach(binding.boot, (event) => publish('High', event), {
173
+ discard: true,
174
+ }).pipe(Effect.provideService(Bus, bus))
175
+ const merged = Context.merge(hostContext, context)
176
+ yield* Effect.sync(() =>
177
+ handlers.onLive(makeChildRuntime<HostServices | ROut>(merged, scope)),
178
+ )
179
+ })
157
180
  })
158
- })
159
- return forkFeatureMount(mountHost, scope, mount, handlers.onFailed)
181
+ return startMount(mountHost, ownerScope, (scope) =>
182
+ forkFeatureMount(mountHost, scope, instrumented(mountInto(scope)), handlers.onFailed),
183
+ )
160
184
  }
161
185
 
162
186
  const mountCapturedFeatureOnto = <
@@ -166,6 +190,7 @@ export const makeCapturedAppRuntime = <
166
190
  const DirectRequires extends ReadonlyArray<FeatureRequirement>,
167
191
  >(
168
192
  hostContext: Context.Context<HostServices>,
193
+ ownerScope: Scope.Scope,
169
194
  binding: CapturedFeatureBinding<Summary, ROut, DirectRequires>,
170
195
  handlers: CapturedFeatureMountHandlers<
171
196
  FeatureSummaryMountProps<Summary>,
@@ -176,58 +201,52 @@ export const makeCapturedAppRuntime = <
176
201
  FeatureSummaryCompositionIdentity<Summary>
177
202
  >,
178
203
  ): (() => void) => {
179
- if (status.disposed) {
180
- return () => {}
181
- }
182
- const scope = Effect.runSync(Scope.make())
183
- const mount = Effect.flatMap(binding.load, (loaded) => {
184
- if (
185
- !hasFeatureRequirements<HostServices, FeatureSummaryOpenServices<Summary>, DirectRequires>(
186
- hostContext,
187
- loaded.requires,
188
- )
189
- ) {
190
- return Effect.fail(
191
- featureMountFailure(
192
- `Feature ${binding.manifest.name} requires services missing from the host runtime`,
193
- ),
194
- )
195
- }
196
- const input = loaded.usesInput ? binding.parseInput(handlers.props) : Option.some(undefined)
197
- return Option.match(input, {
198
- onNone: () =>
199
- Effect.fail(
200
- featureMountFailure(`Feature ${binding.manifest.name} received invalid props`),
201
- ),
202
- onSome: (props) =>
203
- Effect.gen(function* () {
204
- const bus = Context.get(hostContext, Bus)
205
- const featureContext = Context.add(hostContext, FeatureInput, props)
206
- const context = yield* Layer.build(
207
- Layer.provide(loaded.layer, Layer.succeedContext(featureContext)),
208
- )
209
- yield* Effect.forEach(binding.boot, (event) => publish('High', event), {
210
- discard: true,
211
- }).pipe(Effect.provideService(Bus, bus))
212
- const merged = Context.merge(hostContext, context)
213
- const compositionService = Option.getOrThrow(
214
- Context.getOption(merged, binding.composition.tag),
215
- )
216
- const rooted = Context.add(merged, binding.composition.tag, compositionService)
217
- yield* Effect.sync(() => handlers.onLive(makeChildRuntime(rooted)))
218
- }),
204
+ const mountInto = (scope: Scope.CloseableScope) =>
205
+ Effect.flatMap(binding.load, (loaded) => {
206
+ if (
207
+ !hasFeatureRequirements<
208
+ HostServices,
209
+ FeatureSummaryOpenServices<Summary>,
210
+ DirectRequires
211
+ >(hostContext, loaded.requires)
212
+ ) {
213
+ return missingHostServices(binding.manifest.name)
214
+ }
215
+ const input = loaded.usesInput ? binding.parseInput(handlers.props) : Option.some(undefined)
216
+ return Option.match(input, {
217
+ onNone: () => invalidMountProps(binding.manifest.name),
218
+ onSome: (props) =>
219
+ Effect.gen(function* () {
220
+ const bus = Context.get(hostContext, Bus)
221
+ const featureContext = Context.add(hostContext, FeatureInput, props)
222
+ const context = yield* Layer.build(
223
+ Layer.provide(loaded.layer, Layer.succeedContext(featureContext)),
224
+ )
225
+ yield* Effect.forEach(binding.boot, (event) => publish('High', event), {
226
+ discard: true,
227
+ }).pipe(Effect.provideService(Bus, bus))
228
+ const merged = Context.merge(hostContext, context)
229
+ const compositionService = Option.getOrThrow(
230
+ Context.getOption(merged, binding.composition.tag),
231
+ )
232
+ const rooted = Context.add(merged, binding.composition.tag, compositionService)
233
+ yield* Effect.sync(() => handlers.onLive(makeChildRuntime(rooted, scope)))
234
+ }),
235
+ })
219
236
  })
220
- })
221
- return forkFeatureMount(mountHost, scope, mount, handlers.onFailed)
237
+ return startMount(mountHost, ownerScope, (scope) =>
238
+ forkFeatureMount(mountHost, scope, instrumented(mountInto(scope)), handlers.onFailed),
239
+ )
222
240
  }
223
241
 
224
242
  const mountAnyFeatureOnto = <HostServices>(
225
243
  hostContext: Context.Context<HostServices>,
244
+ ownerScope: Scope.Scope,
226
245
  binding: AnyFeatureBinding,
227
246
  handlers: AnyFeatureMountHandlers,
228
247
  ): (() => void) =>
229
248
  binding.capture((exactBinding) =>
230
- mountCapturedFeatureOnto(hostContext, exactBinding, {
249
+ mountCapturedFeatureOnto(hostContext, ownerScope, exactBinding, {
231
250
  props: handlers.props,
232
251
  onLive: (childRuntime) => handlers.onLive(childRuntime),
233
252
  onFailed: handlers.onFailed,
@@ -245,11 +264,13 @@ export const makeCapturedAppRuntime = <
245
264
  ): Option.Option<Service> => Context.getOption(rootContext, tag),
246
265
  runRender,
247
266
  dispatch,
248
- mountScoped,
249
- mountFeature: (binding, handlers) => mountFeatureOnto(rootContext, binding, handlers),
267
+ mountScoped: (activation) => mountScopedOnto(rootScope, activation),
268
+ mountFeature: (binding, handlers) =>
269
+ mountFeatureOnto(rootContext, rootScope, binding, handlers),
250
270
  mountCapturedFeature: (binding, handlers) =>
251
- mountCapturedFeatureOnto(rootContext, binding, handlers),
252
- mountAnyFeature: (binding, handlers) => mountAnyFeatureOnto(rootContext, binding, handlers),
271
+ mountCapturedFeatureOnto(rootContext, rootScope, binding, handlers),
272
+ mountAnyFeature: (binding, handlers) =>
273
+ mountAnyFeatureOnto(rootContext, rootScope, binding, handlers),
253
274
  boot: () => {
254
275
  if (status.disposed || status.booted) {
255
276
  return
@@ -265,6 +286,9 @@ export const makeCapturedAppRuntime = <
265
286
  }
266
287
  status.disposed = true
267
288
  activationDisposers.forEach((dispose) => dispose())
289
+ // On the default runtime: the managed runtime is going away underneath us and
290
+ // must not interrupt the finalizers of what it mounted.
291
+ Effect.runFork(Scope.close(rootScope, Exit.succeed(undefined)))
268
292
  void runtime.dispose()
269
293
  },
270
294
  isDisposed: () => status.disposed,
@@ -1,6 +1,7 @@
1
1
  import { Boolean as Bool, Effect, FiberRef, GlobalValue, MutableRef, Option } from 'effect'
2
2
  import { isDev } from '../internal/env'
3
3
  import { EventLoopOverflow } from '../internal/errors'
4
+ import { microtask } from '../internal/platform'
4
5
 
5
6
  interface EventLimitFields {
6
7
  readonly errorAt: number
@@ -20,7 +21,7 @@ export interface EventBudget {
20
21
  }
21
22
 
22
23
  const rethrowOverflow = (error: EventLoopOverflow): void =>
23
- queueMicrotask(() => {
24
+ microtask(() => {
24
25
  // oxlint-disable-next-line reform-rules/no-throw -- only way to surface the halt to the host's global error handler
25
26
  throw error
26
27
  })