sygnal 5.3.7 → 6.0.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 (438) hide show
  1. package/CHANGELOG.md +646 -0
  2. package/README.md +77 -47
  3. package/dist/astro/client.cjs.js +33 -8114
  4. package/dist/astro/client.cjs.js.map +1 -0
  5. package/dist/astro/client.mjs +33 -8114
  6. package/dist/astro/client.mjs.map +1 -0
  7. package/dist/astro/index.cjs.js +1039 -9
  8. package/dist/astro/index.cjs.js.map +1 -0
  9. package/dist/astro/index.mjs +1038 -9
  10. package/dist/astro/index.mjs.map +1 -0
  11. package/dist/astro/server.cjs.js +3400 -166
  12. package/dist/astro/server.cjs.js.map +1 -0
  13. package/dist/astro/server.mjs +3400 -166
  14. package/dist/astro/server.mjs.map +1 -0
  15. package/dist/devtools.cjs.js +1431 -0
  16. package/dist/devtools.cjs.js.map +1 -0
  17. package/dist/devtools.esm.js +1419 -0
  18. package/dist/devtools.esm.js.map +1 -0
  19. package/dist/diagnostics.cjs.js +4033 -0
  20. package/dist/diagnostics.cjs.js.map +1 -0
  21. package/dist/diagnostics.esm.js +4003 -0
  22. package/dist/diagnostics.esm.js.map +1 -0
  23. package/dist/element.cjs.js +230 -0
  24. package/dist/element.cjs.js.map +1 -0
  25. package/dist/element.esm.js +228 -0
  26. package/dist/element.esm.js.map +1 -0
  27. package/dist/guide/accessibility.md +257 -0
  28. package/dist/guide/adapters.md +221 -0
  29. package/dist/guide/behaviors.md +312 -0
  30. package/dist/guide/browser-sources.md +203 -0
  31. package/dist/guide/drag-and-drop.md +342 -0
  32. package/dist/guide/element-commands.md +306 -0
  33. package/dist/guide/error-boundaries.md +169 -0
  34. package/dist/guide/forms-reference.md +381 -0
  35. package/dist/guide/forms.md +250 -0
  36. package/dist/guide/http.md +299 -0
  37. package/dist/guide/inputs.md +173 -0
  38. package/dist/guide/persistence.md +245 -0
  39. package/dist/guide/recipes/carousel.md +155 -0
  40. package/dist/guide/recipes/charts.md +177 -0
  41. package/dist/guide/recipes/code-editor.md +135 -0
  42. package/dist/guide/recipes/data-grid.md +155 -0
  43. package/dist/guide/recipes/data-table.md +196 -0
  44. package/dist/guide/recipes/i18n.md +222 -0
  45. package/dist/guide/recipes/icons.md +115 -0
  46. package/dist/guide/recipes/overview.md +33 -0
  47. package/dist/guide/recipes/rich-text.md +154 -0
  48. package/dist/guide/resources.md +471 -0
  49. package/dist/guide/ssr.md +255 -0
  50. package/dist/guide/timers.md +178 -0
  51. package/dist/guide/ui/accordion.md +93 -0
  52. package/dist/guide/ui/combobox.md +144 -0
  53. package/dist/guide/ui/dialog.md +124 -0
  54. package/dist/guide/ui/disclosure.md +60 -0
  55. package/dist/guide/ui/menu.md +125 -0
  56. package/dist/guide/ui/overview.md +166 -0
  57. package/dist/guide/ui/popover.md +101 -0
  58. package/dist/guide/ui/select.md +114 -0
  59. package/dist/guide/ui/tabs.md +161 -0
  60. package/dist/guide/ui/toaster.md +152 -0
  61. package/dist/guide/ui/tooltip.md +103 -0
  62. package/dist/guide/undo.md +178 -0
  63. package/dist/guide/virtual-collections.md +183 -0
  64. package/dist/guide/web-components.md +179 -0
  65. package/dist/guide/widgets.md +217 -0
  66. package/dist/index.cjs.js +15283 -6279
  67. package/dist/index.cjs.js.map +1 -0
  68. package/dist/index.d.ts +3739 -370
  69. package/dist/index.esm.js +15230 -6274
  70. package/dist/index.esm.js.map +1 -0
  71. package/dist/jsx-dev-runtime.cjs.js +27 -329
  72. package/dist/jsx-dev-runtime.cjs.js.map +1 -0
  73. package/dist/jsx-dev-runtime.esm.js +20 -322
  74. package/dist/jsx-dev-runtime.esm.js.map +1 -0
  75. package/dist/jsx-runtime.cjs.js +27 -329
  76. package/dist/jsx-runtime.cjs.js.map +1 -0
  77. package/dist/jsx-runtime.esm.js +20 -322
  78. package/dist/jsx-runtime.esm.js.map +1 -0
  79. package/dist/jsx.cjs.js +11 -309
  80. package/dist/jsx.cjs.js.map +1 -0
  81. package/dist/jsx.esm.js +9 -310
  82. package/dist/jsx.esm.js.map +1 -0
  83. package/dist/react.cjs.js +117 -0
  84. package/dist/react.cjs.js.map +1 -0
  85. package/dist/react.esm.js +115 -0
  86. package/dist/react.esm.js.map +1 -0
  87. package/dist/shims/globalthis.cjs +20 -0
  88. package/dist/sygnal.min.js +2 -1
  89. package/dist/sygnal.min.js.map +1 -0
  90. package/dist/ui-combobox.cjs.js +169 -0
  91. package/dist/ui-combobox.cjs.js.map +1 -0
  92. package/dist/ui-combobox.esm.js +148 -0
  93. package/dist/ui-combobox.esm.js.map +1 -0
  94. package/dist/ui-menu.cjs.js +87 -0
  95. package/dist/ui-menu.cjs.js.map +1 -0
  96. package/dist/ui-menu.esm.js +66 -0
  97. package/dist/ui-menu.esm.js.map +1 -0
  98. package/dist/ui-select.cjs.js +104 -0
  99. package/dist/ui-select.cjs.js.map +1 -0
  100. package/dist/ui-select.esm.js +83 -0
  101. package/dist/ui-select.esm.js.map +1 -0
  102. package/dist/ui.cjs.js +738 -0
  103. package/dist/ui.cjs.js.map +1 -0
  104. package/dist/ui.esm.js +727 -0
  105. package/dist/ui.esm.js.map +1 -0
  106. package/dist/vike/ClientOnly.cjs.js +5 -14
  107. package/dist/vike/ClientOnly.cjs.js.map +1 -0
  108. package/dist/vike/ClientOnly.mjs +5 -14
  109. package/dist/vike/ClientOnly.mjs.map +1 -0
  110. package/dist/vike/{+config.js → config/+config.js} +10 -1
  111. package/dist/vike/config/+config.js.map +1 -0
  112. package/dist/vike/config/package.json +6 -0
  113. package/dist/vike/onRenderClient.cjs.js +166 -95
  114. package/dist/vike/onRenderClient.cjs.js.map +1 -0
  115. package/dist/vike/onRenderClient.mjs +166 -95
  116. package/dist/vike/onRenderClient.mjs.map +1 -0
  117. package/dist/vike/onRenderHtml.cjs.js +60 -24
  118. package/dist/vike/onRenderHtml.cjs.js.map +1 -0
  119. package/dist/vike/onRenderHtml.mjs +61 -25
  120. package/dist/vike/onRenderHtml.mjs.map +1 -0
  121. package/dist/vite/plugin.cjs.js +926 -65
  122. package/dist/vite/plugin.cjs.js.map +1 -0
  123. package/dist/vite/plugin.mjs +925 -65
  124. package/dist/vite/plugin.mjs.map +1 -0
  125. package/dist/zag.cjs.js +408 -0
  126. package/dist/zag.cjs.js.map +1 -0
  127. package/dist/zag.esm.js +405 -0
  128. package/dist/zag.esm.js.map +1 -0
  129. package/llms.txt +313 -0
  130. package/package.json +109 -16
  131. package/src/astro/client.ts +40 -18
  132. package/src/astro/index.d.ts +48 -1
  133. package/src/astro/index.ts +106 -9
  134. package/src/astro/server.ts +11 -3
  135. package/src/collection.ts +6 -90
  136. package/src/core/actions.ts +134 -0
  137. package/src/core/cell.ts +202 -0
  138. package/src/core/debug.ts +23 -0
  139. package/src/core/define.ts +242 -0
  140. package/src/core/hooks.ts +314 -0
  141. package/src/core/hosts/collection.ts +325 -0
  142. package/src/core/hosts/switchable.ts +146 -0
  143. package/src/core/instance.ts +592 -0
  144. package/src/core/markers/clientonly.ts +13 -0
  145. package/src/core/markers/lazy.ts +40 -0
  146. package/src/core/markers/portal.ts +96 -0
  147. package/src/core/markers/suspense.ts +41 -0
  148. package/src/core/markers/transition.ts +70 -0
  149. package/src/core/registry.ts +25 -0
  150. package/src/core/runtime.ts +573 -0
  151. package/src/core/statics.ts +104 -0
  152. package/src/core/teardown.ts +60 -0
  153. package/src/core/view.ts +37 -0
  154. package/src/cycle/dom/DocumentDOMSource.ts +13 -8
  155. package/src/cycle/dom/ElementFinder.ts +7 -9
  156. package/src/cycle/dom/EventDelegator.ts +174 -223
  157. package/src/cycle/dom/IsolateModule.ts +65 -35
  158. package/src/cycle/dom/MainDOMSource.ts +13 -2
  159. package/src/cycle/dom/PriorityQueue.ts +4 -2
  160. package/src/cycle/dom/SymbolTree.ts +18 -47
  161. package/src/cycle/dom/classNameModule.ts +76 -0
  162. package/src/cycle/dom/controlledInputModule.ts +50 -0
  163. package/src/cycle/dom/enrichEventStream.ts +29 -45
  164. package/src/cycle/dom/fragment.ts +7 -0
  165. package/src/cycle/dom/isolate.ts +30 -27
  166. package/src/cycle/dom/makeDOMDriver.ts +115 -57
  167. package/src/cycle/dom/mockDOMSource.ts +83 -9
  168. package/src/cycle/dom/modules.ts +21 -4
  169. package/src/cycle/dom/propsModule.ts +65 -0
  170. package/src/cycle/dom/selectModule.ts +22 -17
  171. package/src/cycle/dom/snabbdom.ts +1 -6
  172. package/src/cycle/dom/thunk.ts +3 -0
  173. package/src/cycle/dom/utils.ts +98 -0
  174. package/src/cycle/dom/viewTransition.ts +43 -0
  175. package/src/cycle/state/StateSource.ts +20 -4
  176. package/src/cycle/state/objIsEqual.ts +50 -0
  177. package/src/cycle/state/types.ts +0 -10
  178. package/src/defineComponent.ts +34 -0
  179. package/src/devtools.d.ts +151 -0
  180. package/src/devtools.ts +34 -0
  181. package/src/element.d.ts +59 -0
  182. package/src/element.ts +235 -0
  183. package/src/extra/backoff.ts +9 -0
  184. package/src/extra/behaviors.ts +169 -0
  185. package/src/extra/browserSignals.ts +23 -0
  186. package/src/extra/browserSources.ts +326 -0
  187. package/src/extra/command.ts +3 -3
  188. package/src/extra/controls.ts +47 -0
  189. package/src/extra/copyAsTest.ts +286 -0
  190. package/src/extra/devtools.ts +109 -31
  191. package/src/extra/devtoolsActions.ts +379 -0
  192. package/src/extra/devtoolsHook.ts +9 -0
  193. package/src/extra/devtoolsNext.ts +83 -0
  194. package/src/extra/diagnostics/checks/actionLog.ts +108 -0
  195. package/src/extra/diagnostics/checks/behaviors.ts +49 -0
  196. package/src/extra/diagnostics/checks/browserSources.ts +96 -0
  197. package/src/extra/diagnostics/checks/collections.ts +67 -0
  198. package/src/extra/diagnostics/checks/controls.ts +148 -0
  199. package/src/extra/diagnostics/checks/dataset.ts +57 -0
  200. package/src/extra/diagnostics/checks/dom.ts +250 -0
  201. package/src/extra/diagnostics/checks/elementCommands.ts +175 -0
  202. package/src/extra/diagnostics/checks/events.ts +83 -0
  203. package/src/extra/diagnostics/checks/fetch.ts +135 -0
  204. package/src/extra/diagnostics/checks/forms.ts +163 -0
  205. package/src/extra/diagnostics/checks/index.ts +202 -0
  206. package/src/extra/diagnostics/checks/inspect.ts +427 -0
  207. package/src/extra/diagnostics/checks/next.ts +417 -0
  208. package/src/extra/diagnostics/checks/persist.ts +54 -0
  209. package/src/extra/diagnostics/checks/props.ts +56 -0
  210. package/src/extra/diagnostics/checks/public.d.ts +302 -0
  211. package/src/extra/diagnostics/checks/replies.ts +128 -0
  212. package/src/extra/diagnostics/checks/router.ts +100 -0
  213. package/src/extra/diagnostics/checks/rxjsHints.ts +88 -0
  214. package/src/extra/diagnostics/checks/shared.ts +203 -0
  215. package/src/extra/diagnostics/checks/shorthand.ts +115 -0
  216. package/src/extra/diagnostics/checks/sortable.ts +129 -0
  217. package/src/extra/diagnostics/checks/state.ts +148 -0
  218. package/src/extra/diagnostics/checks/statics.ts +48 -0
  219. package/src/extra/diagnostics/checks/strict.ts +55 -0
  220. package/src/extra/diagnostics/checks/timers.ts +80 -0
  221. package/src/extra/diagnostics/checks/viewTransitions.ts +47 -0
  222. package/src/extra/diagnostics/checks/virtual.ts +73 -0
  223. package/src/extra/diagnostics/checks/widgets.ts +109 -0
  224. package/src/extra/diagnostics/checks/wiring.ts +121 -0
  225. package/src/extra/diagnostics/codes.ts +477 -0
  226. package/src/extra/diagnostics/index.ts +353 -0
  227. package/src/extra/diagnostics/legacy.ts +76 -0
  228. package/src/extra/driverFactories.ts +172 -60
  229. package/src/extra/elementCommands.ts +53 -0
  230. package/src/extra/eventDriver.ts +4 -0
  231. package/src/extra/fetchDriver.ts +519 -0
  232. package/src/extra/flatten.ts +75 -0
  233. package/src/extra/focusWithin.ts +27 -0
  234. package/src/extra/form.ts +268 -0
  235. package/src/extra/formHelpers.ts +139 -0
  236. package/src/extra/head.ts +106 -0
  237. package/src/extra/hmr.ts +2 -3
  238. package/src/extra/owned.ts +24 -0
  239. package/src/extra/pager.ts +50 -0
  240. package/src/extra/persist.ts +133 -0
  241. package/src/extra/pwa.ts +1 -1
  242. package/src/extra/queryCache.ts +107 -0
  243. package/src/extra/reducers.ts +13 -6
  244. package/src/extra/reduxDevtools.ts +92 -0
  245. package/src/extra/replies.ts +54 -0
  246. package/src/extra/router.ts +323 -0
  247. package/src/extra/run.ts +94 -210
  248. package/src/extra/selection.ts +76 -0
  249. package/src/extra/socketDriver.ts +265 -0
  250. package/src/extra/sortable.ts +377 -0
  251. package/src/extra/ssr.ts +427 -160
  252. package/src/extra/standardSchema.ts +27 -0
  253. package/src/extra/testing.ts +3158 -190
  254. package/src/extra/timers.ts +95 -0
  255. package/src/extra/undo.ts +261 -0
  256. package/src/extra/viewTransitions.ts +38 -0
  257. package/src/extra/virtual.ts +513 -0
  258. package/src/extra/widget.ts +201 -0
  259. package/src/extra/xstreamExtras.ts +269 -0
  260. package/src/index.d.ts +3012 -87
  261. package/src/index.ts +32 -10
  262. package/src/jsx-runtime.ts +15 -1
  263. package/src/jsx.ts +2 -1
  264. package/src/lazy.ts +50 -7
  265. package/src/portal.ts +3 -1
  266. package/src/pragma/index.ts +262 -134
  267. package/src/react-peers.d.ts +5 -0
  268. package/src/react.d.ts +43 -0
  269. package/src/react.ts +110 -0
  270. package/src/shared.ts +48 -0
  271. package/src/slot.ts +1 -1
  272. package/src/suspense.ts +3 -1
  273. package/src/switchable.ts +6 -119
  274. package/src/transition.ts +3 -1
  275. package/src/ui/accordion.ts +64 -0
  276. package/src/ui/dialog.ts +129 -0
  277. package/src/ui/disclosure.ts +35 -0
  278. package/src/ui/popover.ts +45 -0
  279. package/src/ui/shared.ts +94 -0
  280. package/src/ui/tabs.ts +82 -0
  281. package/src/ui/toaster.ts +198 -0
  282. package/src/ui/tooltip.ts +70 -0
  283. package/src/ui/zag/combobox.ts +115 -0
  284. package/src/ui/zag/menu.ts +40 -0
  285. package/src/ui/zag/select.ts +54 -0
  286. package/src/ui/zag/shared.ts +43 -0
  287. package/src/ui-combobox.d.ts +20 -0
  288. package/src/ui-combobox.ts +6 -0
  289. package/src/ui-menu.d.ts +30 -0
  290. package/src/ui-menu.ts +6 -0
  291. package/src/ui-select.d.ts +17 -0
  292. package/src/ui-select.ts +6 -0
  293. package/src/ui-zag-types.d.ts +42 -0
  294. package/src/ui.d.ts +208 -0
  295. package/src/ui.ts +15 -0
  296. package/src/vike/+config.ts +9 -1
  297. package/src/vike/ClientOnly.ts +1 -1
  298. package/src/vike/onRenderClient.ts +144 -96
  299. package/src/vike/onRenderHtml.ts +69 -26
  300. package/src/vike/types.ts +27 -4
  301. package/src/vite/globalthis-shim.ts +18 -0
  302. package/src/vite/globalthis.ts +56 -0
  303. package/src/vite/plugin.d.ts +114 -2
  304. package/src/vite/plugin.ts +920 -56
  305. package/src/zag.d.ts +64 -0
  306. package/src/zag.ts +238 -0
  307. package/dist/astro/astro/client.d.ts +0 -5
  308. package/dist/astro/astro/index.d.ts +0 -16
  309. package/dist/astro/astro/server.d.ts +0 -12
  310. package/dist/astro/client.d.ts +0 -5
  311. package/dist/astro/client.esm.js +0 -4665
  312. package/dist/astro/collection.d.ts +0 -12
  313. package/dist/astro/component.d.ts +0 -22
  314. package/dist/astro/cycle/dom/BodyDOMSource.d.ts +0 -10
  315. package/dist/astro/cycle/dom/DOMSource.d.ts +0 -11
  316. package/dist/astro/cycle/dom/DocumentDOMSource.d.ts +0 -12
  317. package/dist/astro/cycle/dom/ElementFinder.d.ts +0 -8
  318. package/dist/astro/cycle/dom/EventDelegator.d.ts +0 -34
  319. package/dist/astro/cycle/dom/IsolateModule.d.ts +0 -23
  320. package/dist/astro/cycle/dom/MainDOMSource.d.ts +0 -32
  321. package/dist/astro/cycle/dom/PriorityQueue.d.ts +0 -7
  322. package/dist/astro/cycle/dom/ScopeChecker.d.ts +0 -9
  323. package/dist/astro/cycle/dom/SymbolTree.d.ts +0 -9
  324. package/dist/astro/cycle/dom/VNodeWrapper.d.ts +0 -8
  325. package/dist/astro/cycle/dom/enrichEventStream.d.ts +0 -24
  326. package/dist/astro/cycle/dom/fromEvent.d.ts +0 -6
  327. package/dist/astro/cycle/dom/index.d.ts +0 -8
  328. package/dist/astro/cycle/dom/isolate.d.ts +0 -9
  329. package/dist/astro/cycle/dom/makeDOMDriver.d.ts +0 -11
  330. package/dist/astro/cycle/dom/mockDOMSource.d.ts +0 -17
  331. package/dist/astro/cycle/dom/modules.d.ts +0 -5
  332. package/dist/astro/cycle/dom/snabbdom.d.ts +0 -22
  333. package/dist/astro/cycle/dom/styleModule.d.ts +0 -13
  334. package/dist/astro/cycle/dom/thunk.d.ts +0 -11
  335. package/dist/astro/cycle/dom/utils.d.ts +0 -8
  336. package/dist/astro/cycle/isolate/index.d.ts +0 -42
  337. package/dist/astro/cycle/run/adapt.d.ts +0 -6
  338. package/dist/astro/cycle/run/index.d.ts +0 -36
  339. package/dist/astro/cycle/run/internals.d.ts +0 -8
  340. package/dist/astro/cycle/run/types.d.ts +0 -49
  341. package/dist/astro/cycle/state/Collection.d.ts +0 -29
  342. package/dist/astro/cycle/state/StateSource.d.ts +0 -20
  343. package/dist/astro/cycle/state/index.d.ts +0 -5
  344. package/dist/astro/cycle/state/pickCombine.d.ts +0 -3
  345. package/dist/astro/cycle/state/pickMerge.d.ts +0 -3
  346. package/dist/astro/cycle/state/types.d.ts +0 -18
  347. package/dist/astro/cycle/state/withState.d.ts +0 -17
  348. package/dist/astro/extra/classes.d.ts +0 -7
  349. package/dist/astro/extra/devtools.d.ts +0 -78
  350. package/dist/astro/extra/dragDriver.d.ts +0 -20
  351. package/dist/astro/extra/driverFactories.d.ts +0 -12
  352. package/dist/astro/extra/eventDriver.d.ts +0 -9
  353. package/dist/astro/extra/exactState.d.ts +0 -1
  354. package/dist/astro/extra/hmr.d.ts +0 -17
  355. package/dist/astro/extra/logDriver.d.ts +0 -2
  356. package/dist/astro/extra/processDrag.d.ts +0 -19
  357. package/dist/astro/extra/processForm.d.ts +0 -15
  358. package/dist/astro/extra/run.d.ts +0 -13
  359. package/dist/astro/extra/xstreamCompat.d.ts +0 -5
  360. package/dist/astro/index.d.ts +0 -19
  361. package/dist/astro/index.esm.js +0 -27
  362. package/dist/astro/jsx-dev-runtime.d.ts +0 -1
  363. package/dist/astro/jsx-runtime.d.ts +0 -4
  364. package/dist/astro/jsx.d.ts +0 -2
  365. package/dist/astro/pragma/fn.d.ts +0 -7
  366. package/dist/astro/pragma/index.d.ts +0 -7
  367. package/dist/astro/pragma/is.d.ts +0 -10
  368. package/dist/astro/server.d.ts +0 -12
  369. package/dist/astro/server.esm.js +0 -25
  370. package/dist/astro/switchable.d.ts +0 -7
  371. package/dist/collection.d.ts +0 -12
  372. package/dist/component.d.ts +0 -22
  373. package/dist/cycle/dom/BodyDOMSource.d.ts +0 -10
  374. package/dist/cycle/dom/DOMSource.d.ts +0 -11
  375. package/dist/cycle/dom/DocumentDOMSource.d.ts +0 -12
  376. package/dist/cycle/dom/ElementFinder.d.ts +0 -8
  377. package/dist/cycle/dom/EventDelegator.d.ts +0 -34
  378. package/dist/cycle/dom/IsolateModule.d.ts +0 -23
  379. package/dist/cycle/dom/MainDOMSource.d.ts +0 -32
  380. package/dist/cycle/dom/PriorityQueue.d.ts +0 -7
  381. package/dist/cycle/dom/ScopeChecker.d.ts +0 -9
  382. package/dist/cycle/dom/SymbolTree.d.ts +0 -9
  383. package/dist/cycle/dom/VNodeWrapper.d.ts +0 -8
  384. package/dist/cycle/dom/enrichEventStream.d.ts +0 -24
  385. package/dist/cycle/dom/fromEvent.d.ts +0 -6
  386. package/dist/cycle/dom/index.d.ts +0 -8
  387. package/dist/cycle/dom/isolate.d.ts +0 -9
  388. package/dist/cycle/dom/makeDOMDriver.d.ts +0 -11
  389. package/dist/cycle/dom/mockDOMSource.d.ts +0 -17
  390. package/dist/cycle/dom/modules.d.ts +0 -5
  391. package/dist/cycle/dom/snabbdom.d.ts +0 -22
  392. package/dist/cycle/dom/styleModule.d.ts +0 -13
  393. package/dist/cycle/dom/thunk.d.ts +0 -11
  394. package/dist/cycle/dom/utils.d.ts +0 -8
  395. package/dist/cycle/isolate/index.d.ts +0 -42
  396. package/dist/cycle/run/adapt.d.ts +0 -6
  397. package/dist/cycle/run/index.d.ts +0 -36
  398. package/dist/cycle/run/internals.d.ts +0 -8
  399. package/dist/cycle/run/types.d.ts +0 -49
  400. package/dist/cycle/state/Collection.d.ts +0 -29
  401. package/dist/cycle/state/StateSource.d.ts +0 -20
  402. package/dist/cycle/state/index.d.ts +0 -5
  403. package/dist/cycle/state/pickCombine.d.ts +0 -3
  404. package/dist/cycle/state/pickMerge.d.ts +0 -3
  405. package/dist/cycle/state/types.d.ts +0 -18
  406. package/dist/cycle/state/withState.d.ts +0 -17
  407. package/dist/extra/classes.d.ts +0 -7
  408. package/dist/extra/devtools.d.ts +0 -78
  409. package/dist/extra/dragDriver.d.ts +0 -20
  410. package/dist/extra/driverFactories.d.ts +0 -12
  411. package/dist/extra/eventDriver.d.ts +0 -9
  412. package/dist/extra/exactState.d.ts +0 -1
  413. package/dist/extra/hmr.d.ts +0 -17
  414. package/dist/extra/logDriver.d.ts +0 -2
  415. package/dist/extra/processDrag.d.ts +0 -19
  416. package/dist/extra/processForm.d.ts +0 -15
  417. package/dist/extra/run.d.ts +0 -13
  418. package/dist/extra/xstreamCompat.d.ts +0 -5
  419. package/dist/jsx-dev-runtime.d.ts +0 -1
  420. package/dist/jsx-dev-runtime.js +0 -224
  421. package/dist/jsx-runtime.d.ts +0 -4
  422. package/dist/jsx-runtime.js +0 -224
  423. package/dist/jsx.d.ts +0 -2
  424. package/dist/pragma/fn.d.ts +0 -7
  425. package/dist/pragma/index.d.ts +0 -7
  426. package/dist/pragma/is.d.ts +0 -10
  427. package/dist/switchable.d.ts +0 -7
  428. package/dist/vike/+config.cjs.js +0 -65
  429. package/src/component.ts +0 -2256
  430. package/src/cycle/isolate/index.ts +0 -196
  431. package/src/cycle/run/index.ts +0 -151
  432. package/src/cycle/run/internals.ts +0 -143
  433. package/src/cycle/state/Collection.ts +0 -174
  434. package/src/cycle/state/index.ts +0 -5
  435. package/src/cycle/state/pickCombine.ts +0 -167
  436. package/src/cycle/state/pickMerge.ts +0 -122
  437. package/src/cycle/state/withState.ts +0 -47
  438. package/src/pragma/fn.ts +0 -55
@@ -0,0 +1,573 @@
1
+ /**
2
+ * PLAN-4.6 core: the app runtime, one per run() (03-proposal §3, 04 §2.4: the flush contract).
3
+ *
4
+ * - dispatch(): one FIFO queue, run to completion. An action dispatched while the queue drains
5
+ * (a driver answering synchronously during sink delivery, an EFFECT, a PARENT, a hook) is
6
+ * appended, never run nested; one dispatched while the flush renders is drained in that flush.
7
+ * - commit(): a state write schedules one flush (a microtask).
8
+ * - flush(): repeat { STATE streams, render top-down (dirty-checked), statics (R3's hook point),
9
+ * drain the queue } until nothing changed; then ONE vnode to the DOM driver (one patch), then
10
+ * the disposed instances' streams are stopped, and BOOTSTRAP goes to the instances created in
11
+ * it a microtask later (D165). No startup timers, gates or holds.
12
+ * - loop guard (G-260 / G-283 / G-284): at most 100 passes per flush; a flush caused by the one
13
+ * before it (a commit while it ran or emitted: a loop that never settles) is chained, and past
14
+ * 100 chained flushes, or 1,000 flushes of any kind without a macrotask, the next one waits for
15
+ * a MessageChannel message. No setTimeout anywhere.
16
+ * - teardown (D165 / Q18): while an instance unsubscribes, Stream.prototype._remove queues the
17
+ * streams it leaves without listeners instead of arming xstream's stop timer, and the queue is
18
+ * stopped at the first macrotask after the drain / flush (G-302). The swap is scoped to dispose().
19
+ */
20
+ import xs from '../extra/xstreamCompat'
21
+ import {makeDOMDriver} from '../cycle/dom/index'
22
+ import eventBusDriver from '../extra/eventDriver'
23
+ import logDriver from '../extra/logDriver'
24
+ import {NOT_SINK, isAbort} from '../shared'
25
+ import {error as logError, callHook} from '../extra/diagnostics/legacy'
26
+ import type {ComponentFn, DefSource, Hooks, RuntimeAPI, ActionCause} from './hooks'
27
+ import {CoreDef, defOf, rootDef} from './define'
28
+ import {rootCell} from './cell'
29
+ import {Inst} from './instance'
30
+ import {viewOf} from './view'
31
+ import {stopQueued, INST, SET, SEED} from './teardown'
32
+ import {scanSources} from './statics'
33
+ // the public ClientOnly is a separate bundle (sygnal/vike/ClientOnly) with no core of its own, so
34
+ // its marker handler registers with the core (the other markers register from their modules)
35
+ import './markers/clientonly'
36
+
37
+ const LOOP = 100, HARD = 1000
38
+ // the macrotask, captured at load (a test's fake timers don't hold the ping): Node drains a
39
+ // MessagePort's messages back to back (timers starve), so its setImmediate is the macrotask
40
+ // there; browsers have no setImmediate and get a MessageChannel
41
+ const G: any = globalThis
42
+ const SI: ((f: () => void) => void) | undefined = typeof G.setImmediate == 'function' ? G.setImmediate.bind(G) : undefined
43
+ const MC: any = typeof G.MessageChannel == 'function' ? G.MessageChannel : undefined
44
+ const ERR_FIX = 'See the attached error'
45
+
46
+ export interface StartOptions {
47
+ mountPoint?: string | Element
48
+ /** no effect (3-Q: the DOM driver flattens fragments) */
49
+ fragments?: boolean
50
+ useDefaultDrivers?: boolean
51
+ onError?: (error: any, info: any) => void
52
+ uid?: string
53
+ /** internal: this app's hooks (testing, devtools, diagnostics) */
54
+ __hooks?: Hooks
55
+ /** internal: the root's state at start (an HMR swap) */
56
+ __state?: any
57
+ /** internal: an HMR swap: the instances its first flush makes get no BOOTSTRAP (as today's `__hmr`) */
58
+ __swap?: boolean
59
+ /** internal: renderComponent's root (test intent, initial state, name) */
60
+ __override?: Partial<DefSource> & {name?: string; testActions?: string[]}
61
+ }
62
+
63
+ export class App {
64
+ state: any = undefined
65
+ queue: any[] = []
66
+ draining = false
67
+ rendering = false
68
+ flushing = false
69
+ scheduled = false
70
+ dirty = false
71
+ /** in a flush's emission (a commit there chains the next flush) */
72
+ tail = false
73
+ chained = false
74
+ chain = 0
75
+ flushes = 0
76
+ /** bumped on every state write (context memo) */
77
+ ver = 0
78
+ /** render epoch: bumped when a render threw (G-311: every instance injects its kids again once) */
79
+ ep = 0
80
+ root!: Inst
81
+ last: any
82
+ /** P46-P: a view ran but kept its last vnode (the flush still emits, as when it changed) */
83
+ ran = false
84
+ vdomL: any
85
+ vdom$: any
86
+ sources: Record<string, any> = {}
87
+ proxies: Record<string, any> = {}
88
+ bus: Record<string, any> = {}
89
+ busL: Record<string, any> = {}
90
+ /** G-296: before the first flush emitted, the sink values sent, per sink */
91
+ early = true
92
+ log: Record<string, any[]> = {}
93
+ ex: Record<string, any> = {}
94
+ exL: Record<string, any> = {}
95
+ hooks: Hooks
96
+ /** run()'s hooks, then each addHooks() layer (G-297) */
97
+ layers: Hooks[]
98
+ born: Inst[] = []
99
+ watchers = new Set<Inst>()
100
+ /** streams the disposed instances left without listeners, stopped when the drain / flush ends */
101
+ dq: any[] = []
102
+ stopping = false
103
+ disposed = false
104
+ initState: any
105
+ /** D168 hook point (onContextSkip): a view context tracking skipped, with the context before and after */
106
+ ctxSkip: ((inst: Inst, prev: any, next: any) => void) | null = null
107
+ /** the statics step, recomputed after each render pass (statics.ts; set when a driver takes a static) */
108
+ afterRender: (() => void) | null = null
109
+ /** [sink, static] of the drivers that take a static; the reply-capable sources (statics.ts) */
110
+ stat: Array<[string, string]> = []
111
+ rep: string[] = []
112
+ /** a definition's [sink, static] pairs (this app's drivers) */
113
+ stc = new WeakMap<CoreDef, Array<[string, string]> | null>()
114
+ /** the live instances that declare a static */
115
+ statics = new Set<Inst>()
116
+ defs = new WeakMap<ComponentFn, CoreDef>()
117
+ waiters: Array<() => void> = []
118
+ scopeN = 0
119
+ mc: any
120
+ hops: Array<() => void> = []
121
+ ping = false
122
+ desc: any[] = []
123
+
124
+ constructor(public opts: StartOptions = {}) {
125
+ this.hooks = {...opts.__hooks}
126
+ this.layers = [opts.__hooks || {}]
127
+ this.initState = opts.__state
128
+ this.compose()
129
+ // the dev entries' hooks ('sygnal/diagnostics', 'sygnal/devtools'), one layer each (04 §2.2:
130
+ // what the bridge holds becomes hooks, read once per app); none without a dev entry
131
+ const L = G.__SYGNAL_DIAGNOSTICS__?.layers
132
+ // G-330: a throwing layer factory (a dev-entry bug) is reported and skipped; the app starts
133
+ if (L) for (const f of L) {
134
+ let h
135
+ try { h = f(this.api()) } catch (e) { logError('SYG900', 'run', 'A dev-tools hook layer threw while the app started; it is skipped', 'Report this as a Sygnal bug', e); continue }
136
+ this.addHooks(h)
137
+ }
138
+ }
139
+
140
+ def(view: ComponentFn, override?: StartOptions['__override']) {
141
+ return defOf(view, this.hooks.transformDef, this.defs, override)
142
+ }
143
+ /** a child's isolation scope (one for every channel of the instance, as isolate() gave) */
144
+ scope() { return 's' + ++this.scopeN }
145
+
146
+ // ---------------------------------------------------------------- queue
147
+ /** `src`: for a reply, the source that delivered it (the action log's replySink) */
148
+ dispatch(inst: Inst, type: any, data: any, cause: ActionCause = 'intent', src?: string) {
149
+ if (this.disposed) return
150
+ this.queue.push(inst, type, data, cause, src)
151
+ if (!this.draining && !this.rendering) this.drain()
152
+ }
153
+ drain() {
154
+ this.draining = true
155
+ const q = this.queue
156
+ try {
157
+ for (let i = 0; i < q.length; i += 5) {
158
+ const inst: Inst = q[i]
159
+ if (inst.disposed) continue
160
+ // G-331: one item that throws (a setState function from devtools / Vike / sygnal/element,
161
+ // a hook) is reported; the rest of the queue still runs
162
+ try {
163
+ if (q[i + 1] === SET) {
164
+ const f = q[i + 2], c = inst.cell
165
+ const v = typeof f == 'function' ? f(c.get()) : f
166
+ // (ABORT: no change, as from a reducer)
167
+ if (v !== c.get() && !isAbort(v)) c.set(v)
168
+ } else if (q[i + 1] === SEED) {
169
+ // G-309: decided when it is applied: a parent write queued before it keeps the slice (D174)
170
+ const d = q[i + 2], b = d.b
171
+ if (d.r || !(b.has ? b.has() : b.get() !== undefined)) inst.cell.set(d.v)
172
+ else this.hooks.onStateSeed?.(viewOf(inst), b.get(), d.v)
173
+ }
174
+ else inst.handle(q[i + 1], q[i + 2], q[i + 3], q[i + 4])
175
+ } catch (e) {
176
+ this.caught(inst, 'SYG216', `${typeof q[i + 1] == 'string' ? `Action '${q[i + 1]}'` : 'A state update'} threw; the actions queued after it still run`, e, 'reducer', typeof q[i + 1] == 'string' ? q[i + 1] : undefined)
177
+ }
178
+ if (this.watchers.size) this.notify()
179
+ }
180
+ } finally {
181
+ q.length = 0
182
+ this.draining = false
183
+ if (!this.flushing && this.dq.length) this.stopLater()
184
+ }
185
+ }
186
+ /** STATE.stream: the instances whose state changed emit it */
187
+ notify() {
188
+ for (const i of this.watchers) i.notify()
189
+ }
190
+
191
+ // ---------------------------------------------------------------- flush
192
+ commit() {
193
+ this.ver++
194
+ if (this.flushing) { this.dirty = true; return }
195
+ if (this.tail) this.chained = true
196
+ if (this.scheduled || this.disposed) return
197
+ this.scheduled = true
198
+ const chained = this.chained
199
+ this.chained = false
200
+ this.chain = chained ? this.chain + 1 : 0
201
+ // the first flush since the last macrotask pings one, which resets the count
202
+ if (!this.flushes++) this.macro()
203
+ if (this.chain > LOOP || this.flushes > HARD) this.macro(() => { this.chain = 0; this.flush() })
204
+ else queueMicrotask(() => this.flush())
205
+ }
206
+ /**
207
+ * A macrotask without a timer: one MessageChannel per app, at most one message in flight (it
208
+ * resets the flush count, then runs the hops waiting for it)
209
+ */
210
+ macro(f?: () => void) {
211
+ if (f) this.hops.push(f)
212
+ if (this.ping) return
213
+ this.ping = true
214
+ if (SI) return void SI(() => this.pong())
215
+ if (!MC) return void setTimeout(() => this.pong())
216
+ if (!this.mc) {
217
+ this.mc = new MC()
218
+ this.mc.port1.onmessage = () => this.pong()
219
+ this.mc.port1.unref?.()
220
+ }
221
+ this.mc.port2.postMessage(0)
222
+ }
223
+ /**
224
+ * G-302: the streams disposed instances left without listeners stop at the first macrotask, as
225
+ * xstream's own deferred stop does (a shared stream unmounted in one flush and mounted again in
226
+ * the next keeps running), but through macro(): no setTimeout per stream
227
+ */
228
+ stopLater() {
229
+ if (this.stopping) return
230
+ this.stopping = true
231
+ this.macro(() => { this.stopping = false; stopQueued(this.dq, this.stopErr) })
232
+ }
233
+ pong() {
234
+ this.ping = false
235
+ this.flushes = 0
236
+ for (const g of this.hops.splice(0)) g()
237
+ }
238
+ flush() {
239
+ this.scheduled = false
240
+ if (this.disposed) return this.release()
241
+ try { this.flushOnce() } finally { this.release() }
242
+ }
243
+ /** G-301: flushed() resolves once nothing is scheduled, after a throwing flush, or on dispose */
244
+ release() {
245
+ if (this.waiters.length && (!this.scheduled || this.disposed)) for (const w of this.waiters.splice(0)) w()
246
+ }
247
+ flushOnce() {
248
+ this.flushing = true
249
+ let v: any, n = 0
250
+ try {
251
+ do {
252
+ this.dirty = false
253
+ if (this.watchers.size) this.notify()
254
+ this.rendering = true
255
+ try { v = this.root.render() } catch (e) {
256
+ // G-298: an error that escaped every boundary (a hook, a host): reported; the DOM keeps
257
+ // its last render and the flush still ends (BOOTSTRAP, teardown, waiters)
258
+ this.rendering = false
259
+ this.caught(this.root, 'SYG406', 'Render threw; the page keeps its last render', e, 'view')
260
+ v = this.last
261
+ // G-311: the instances that rendered before the throw are injected at the next render
262
+ this.ep++
263
+ // G-320: the statics still follow the state (a throwing render doesn't freeze them)
264
+ try { this.afterRender?.() } catch (_) { /* reported by the statics step */ }
265
+ break
266
+ }
267
+ this.afterRender?.()
268
+ this.rendering = false
269
+ if (this.queue.length) this.drain()
270
+ } while (this.dirty && ++n < LOOP)
271
+ } finally {
272
+ this.rendering = false
273
+ this.flushing = false
274
+ }
275
+ this.tail = true
276
+ try {
277
+ // G-311 (c): what the throwing pass queued (a new child's INITIALIZE / seed) is still applied
278
+ if (this.queue.length) this.drain()
279
+ if (v !== this.last || this.ran) {
280
+ this.ran = false
281
+ this.last = v
282
+ this.hooks.onPatch?.(v)
283
+ this.vdomL?.next(v)
284
+ }
285
+ if (this.dq.length) this.stopLater()
286
+ } finally {
287
+ // G-313: a throwing patch / onPatch still ends the startup log and dispatches BOOTSTRAP
288
+ this.tail = false
289
+ // an HMR swap: what the start rendered was already bootstrapped in the old app
290
+ if (this.opts.__swap) { this.opts.__swap = false; this.born.length = 0 }
291
+ if (this.born.length) {
292
+ const b = this.born.splice(0)
293
+ queueMicrotask(() => { for (const i of b) if (!i.disposed) this.dispatch(i, 'BOOTSTRAP', undefined, 'built-in') })
294
+ }
295
+ if (this.dirty) { this.chained = true; this.dirty = false; this.commit() }
296
+ if (this.early) { this.early = false; this.log = {} }
297
+ }
298
+ }
299
+
300
+ // ---------------------------------------------------------------- sinks
301
+ /** the app's stream for one sink (every instance's values; drivers get them synchronously) */
302
+ sink(n: string) {
303
+ return this.bus[n] ||= xs.create({start: (l: any) => { this.busL[n] = l }, stop: () => { delete this.busL[n] }})
304
+ }
305
+ out(n: string, v: any) {
306
+ // G-296: until the first flush has emitted, a sink's values are kept for a listener added
307
+ // right after run() / renderComponent (sinks[n], as Cycle's run buffered its sinks)
308
+ if (this.early) (this.log[n] ||= []).push(v)
309
+ const l = this.busL[n]
310
+ if (!l) return
311
+ try { l.next(v) } catch (e) {
312
+ // GS-11: a driver that throws handling a sink value goes to the app's onError ('driver'),
313
+ // and to the hooks' onError (G-303)
314
+ const info: any = {phase: 'driver', driver: n}
315
+ callHook(this.opts.onError, e, info)
316
+ callHook(this.hooks.onError, e, info)
317
+ queueMicrotask(() => { throw e })
318
+ }
319
+ }
320
+ /** run()'s sinks[n]: the bus, with the values sent before the first flush replayed to its first listener (G-296) */
321
+ exposed(n: string) {
322
+ return this.ex[n] ||= xs.create({
323
+ start: (l: any) => {
324
+ const early = this.early ? this.log[n] : undefined
325
+ if (early) for (const v of early.slice()) l.next(v)
326
+ this.sink(n).addListener(this.exL[n] = {next: (v: any) => l.next(v), error: (e: any) => l.error(e), complete: () => l.complete()})
327
+ },
328
+ stop: () => { this.sink(n).removeListener(this.exL[n]) },
329
+ })
330
+ }
331
+ /**
332
+ * The value-level fallback (a source without isolateValue): one stream per instance and key
333
+ * through `build` (isolateSink at each level), delivered to `to` synchronously.
334
+ */
335
+ pipe(inst: Inst, key: string, v: any, build: (s$: any) => any, to: (x: any) => void) {
336
+ const fb = inst.fb ||= {}
337
+ let p = fb[key]
338
+ if (!p) {
339
+ const in$ = xs.create()
340
+ p = fb[key] = in$
341
+ inst.subs.push(build(in$).subscribe({next: to}))
342
+ }
343
+ p.shamefullySendNext(v)
344
+ }
345
+ /** an instance's vnode, scoped by its parent's DOM source (isolateValue, else a pipe) */
346
+ scopeValue(parent: Inst, _: string, v: any, inst: Inst) {
347
+ const d = parent.dom
348
+ if (!d || inst.scope === undefined) return v
349
+ if (typeof d.isolateValue == 'function') return d.isolateValue(v, inst.scope)
350
+ let r: any
351
+ this.pipe(inst, '\u0000DOM', v, (s$) => d.isolateSink(s$, inst.scope), (x) => { r = x })
352
+ return r
353
+ }
354
+
355
+ // ---------------------------------------------------------------- errors
356
+ /** G-342/G-267: a stream's stop() threw while an instance's streams were torn down */
357
+ stopErr = (e: any, inst: any) => {
358
+ console.error(`[Sygnal] ${inst ? inst.def.name + ': ' : ''}a stream's stop() threw while it was torn down; the other streams stopped`, e)
359
+ inst ? this.appError(inst, e, 'dispose') : callHook(this.opts.onError, e, {phase: 'dispose'})
360
+ }
361
+ appError(inst: Inst, e: any, phase: string, action?: string) {
362
+ const info: any = {componentName: inst.def.name, action, phase}
363
+ callHook(this.opts.onError, e, info)
364
+ // 3-W G-546: a hook layer's onError that throws is logged (as the app's is)
365
+ callHook(this.hooks.onError, e, info)
366
+ }
367
+ /** an error caught at a call site that keeps running (as legacy caught(): a fail()'s own code) */
368
+ caught(inst: Inst, code: string, message: string, err: any, phase: string, action?: string) {
369
+ const s = err && err.sygnal
370
+ s ? logError(err.code, s[0], `${s[1]} (${message})`, s[2], err) : logError(code, inst, message, ERR_FIX, err)
371
+ this.appError(inst, err, phase, action)
372
+ }
373
+
374
+ // ---------------------------------------------------------------- intent sources
375
+ /** the getters of an instance's intent sources (one descriptor map per app and kind) */
376
+ srcDesc(child: boolean) {
377
+ const k = +child
378
+ if (this.desc[k]) return this.desc[k]
379
+ const d: any = {}
380
+ const get = (f: (i: Inst) => any) => ({get(this: any) { return f(this[INST]) }, enumerable: true, configurable: true})
381
+ for (const n in this.sources) if (n !== 'DOM') d[n] = get(i => i.src(n))
382
+ d.DOM = get(i => i.dom && (i.wd ||= wrapDOM(i.dom)))
383
+ d.STATE = get(i => i.stateSource())
384
+ d.CHILD = get(i => i.childSource())
385
+ d.dispose$ = get(i => i.dispose$())
386
+ if (child) {
387
+ d.props$ = get(i => i.props$ || seeded(i, 'props$', i.props))
388
+ d.children$ = get(i => i.children$ || seeded(i, 'children$', i.children))
389
+ // a Command passed as a prop (createCommand): its messages, as today's `commands$`
390
+ d.commands$ = get(i => i.commands())
391
+ }
392
+ return (this.desc[k] = d)
393
+ }
394
+
395
+ // ---------------------------------------------------------------- the runtime API (04 §2.3)
396
+ api(): RuntimeAPI {
397
+ const app = this
398
+ const find = (t: any): Inst | undefined => t === 'root' ? app.root : typeof t == 'number' ? byId(app.root, t) : t && byId(app.root, t.id)
399
+ return {
400
+ get root() { return viewOf(app.root) },
401
+ get: (id) => { const i = byId(app.root, id); return i && viewOf(i) },
402
+ getState: () => app.state,
403
+ setState: (t, s) => { const i = find(t); if (i) app.dispatch(i, SET, s, 'setState') },
404
+ dispatch: (t, type, data, cause = 'simulateAction') => { const i = find(t); if (i) app.dispatch(i, type, data, cause) },
405
+ addHooks: (h) => app.addHooks(h),
406
+ setDebug: (t, on) => { const i = find(t); if (i) i.debug = on },
407
+ flushed: () => new Promise<void>(r => (app.scheduled || app.flushing ? app.waiters.push(r) : r())),
408
+ }
409
+ }
410
+ /**
411
+ * A layer of hooks on top of run()'s own (devtools connecting late, a dev entry). G-297: the
412
+ * remover drops only its own layer; the hooks are composed again from the layers left.
413
+ */
414
+ addHooks(h: Hooks) {
415
+ this.layers.push(h)
416
+ this.compose()
417
+ return () => {
418
+ const i = this.layers.indexOf(h)
419
+ if (i >= 0) { this.layers.splice(i, 1); this.compose() }
420
+ }
421
+ }
422
+ compose() {
423
+ const H: any = this.hooks
424
+ for (const k in H) delete H[k]
425
+ this.ctxSkip = null
426
+ for (const layer of this.layers) {
427
+ const added: any = layer
428
+ for (const k in added) {
429
+ const a = added[k], b = H[k]
430
+ if (!a) continue
431
+ // G-312: a wrapping layer that returns nothing keeps what the layers below gave
432
+ H[k] = !b ? a
433
+ : k == 'wrapHandler' ? (i: any, t: any, s: any, f: any) => { const x = b(i, t, s, f) || f; return a(i, t, s, x) || x }
434
+ : k == 'wrapSources' ? (i: any, s: any) => { const x = b(i, s) || s; return a(i, x) || x }
435
+ : k == 'transformDef' ? (src: any, v: any) => { const x = b(src, v) || src; return a(x, v) || x }
436
+ // onElementCommand: false (not run) from either layer
437
+ : k == 'onElementCommand' ? (i: any, c: any) => { const x = b(i, c); return a(i, c) === false || x === false ? false : undefined }
438
+ : (...args: any[]) => { b(...args); a(...args) }
439
+ }
440
+ }
441
+ // D168's safety net (R4): a view context tracking skipped, offered for a re-run check
442
+ const cs = H.onContextSkip
443
+ if (cs) this.ctxSkip = (i, a, b) => cs(viewOf(i), (c: any) => i.def.view({...i.props, state: i.cell.get(), children: i.children, slots: i.slots, context: c, uid: i.uid}), a, b, [...(i.keys || [])])
444
+ }
445
+
446
+ dispose() {
447
+ if (this.disposed) return
448
+ try { this.root?.dispose() } finally {
449
+ stopQueued(this.dq, this.stopErr)
450
+ this.disposed = true
451
+ for (const n in this.sources) try { this.sources[n]?.dispose?.() } catch (_) {}
452
+ for (const n in this.proxies) try { this.proxies[n]._c() } catch (_) {}
453
+ this.mc?.port1.close()
454
+ this.release()
455
+ }
456
+ }
457
+ }
458
+
459
+ function wrapDOM(dom: any) {
460
+ return new Proxy(dom, {get: (t, p, r) => (typeof p == 'symbol' || p in t ? Reflect.get(t, p, r) : (sel: any) => t.select(sel).events(p))})
461
+ }
462
+ /** props$ / children$: a memory stream with the current value, fed by setProps */
463
+ function seeded(i: any, k: string, v: any) {
464
+ const s = xs.createWithMemory()
465
+ s.shamefullySendNext(v)
466
+ return (i[k] = s)
467
+ }
468
+ function byId(i: Inst, id: number): Inst | undefined {
469
+ if (i.id === id) return i
470
+ for (const k of i.kids.values()) {
471
+ if (k instanceof Inst) { const f = byId(k, id); if (f) return f }
472
+ else if (k.insts) for (const j of k.insts()) { const f = byId(j, id); if (f) return f }
473
+ }
474
+ }
475
+
476
+ /**
477
+ * The root shim a root setup (persist, GS-5: `Root.persist.setup(component)`, root only as today)
478
+ * runs on before the root exists (04 §3.2, §4 #1): the instance fields it reads and writes today.
479
+ * It may restore into `initialState` and rewrite `model` (both read back into the root's Def);
480
+ * `sources.STATE.stream`, `_dispose$` and `vdom$` are the root's, linked once it exists (the
481
+ * returned function); `action$.shamefullySendNext` dispatches to the root (RESTORE).
482
+ */
483
+ function rootShim(app: App, Root: ComponentFn, src: DefSource): [any, () => void] {
484
+ const st$ = xs.create(), dsp$ = xs.create()
485
+ const shim = {
486
+ name: (Root as any).componentName || Root.name || 'FUNCTION_COMPONENT', view: Root,
487
+ model: src.model, initialState: src.initialState, calculated: src.calculated, stateSourceName: 'STATE',
488
+ sources: {...app.sources, STATE: {stream: st$}},
489
+ vdom$: app.vdom$, _dispose$: dsp$,
490
+ action$: {shamefullySendNext: (a: any) => { if (app.root) app.dispatch(app.root, a.type, a.data, 'built-in') }},
491
+ }
492
+ return [shim, () => {
493
+ const r = app.root
494
+ r.stateSource().stream.addListener({next: (v: any) => st$.shamefullySendNext(v), error: () => {}})
495
+ r.dispose$().addListener({next: (v: any) => dsp$.shamefullySendNext(v), error: () => {}})
496
+ }]
497
+ }
498
+
499
+ export interface Started {
500
+ app: App
501
+ sources: Record<string, any>
502
+ sinks: Record<string, any>
503
+ dispose: () => void
504
+ api: RuntimeAPI
505
+ }
506
+
507
+ /**
508
+ * Start an app: the drivers (run()'s defaults unless useDefaultDrivers is
509
+ * false), the root instance, the first flush. Returns run()'s shape (sources with the root's
510
+ * STATE, sinks: one stream per driver sink, DOM and the root's PARENT) plus the runtime API.
511
+ */
512
+ export function start(Root: ComponentFn, drivers: Record<string, any> = {}, opts: StartOptions = {}): Started {
513
+ const app = new App(opts)
514
+ const {mountPoint = '#root', useDefaultDrivers = true} = opts
515
+ // G-537 (D223): a DOM patch that throws goes to onError (phase 'patch') and the hooks' onError;
516
+ // it is logged only without an onError. G-545: given to any DOM driver (one passed in drivers,
517
+ // makeViewTransitionDOMDriver) through its source's isolate module
518
+ const patchErr = (e: any, i: any = {phase: 'patch'}) => {
519
+ opts.onError ? callHook(opts.onError, e, i) : console.error(e)
520
+ callHook(app.hooks.onError, e, i)
521
+ }
522
+ const all: Record<string, any> = {
523
+ ...(useDefaultDrivers && {EVENTS: eventBusDriver, DOM: makeDOMDriver(mountPoint as any), LOG: logDriver, __m: () => mountPoint}),
524
+ ...drivers,
525
+ }
526
+ // the Cycle run loop, reduced: a proxy sink per driver, the driver's source, then the app's
527
+ // streams imitated (values reach a driver synchronously; the DOM gets one vnode per flush)
528
+ for (const n in all) {
529
+ const p = app.proxies[n] = xs.create()
530
+ const src = app.sources[n] = all[n](p, n)
531
+ if (src && typeof src == 'object') try { src._isCycleSource = n } catch (_) {}
532
+ if (src?._isolateModule) src._isolateModule.rep = patchErr
533
+ }
534
+ scanSources(app)
535
+ app.vdom$ = xs.create({start: (l: any) => { app.vdomL = l; if (app.last) l.next(app.last) }, stop: () => { app.vdomL = null }})
536
+ for (const n in all) {
537
+ if (n == 'DOM') app.proxies.DOM.imitate(app.vdom$)
538
+ // a PARENT driver (sygnal/element) gets the root's PARENT values, as under Cycle's run
539
+ else if (!NOT_SINK.test(n) || n == 'PARENT') app.proxies[n].imitate(app.sink(n))
540
+ }
541
+ const was = app.draining
542
+ app.draining = true
543
+ let link: (() => void) | undefined
544
+ try {
545
+ const setup = (Root as any).persist?.setup
546
+ const def = rootDef(Root, app.hooks.transformDef, opts.__override, typeof setup == 'function' ? (src) => {
547
+ const [shim, l] = rootShim(app, Root, src)
548
+ link = l
549
+ setup(shim)
550
+ return {...src, model: shim.model, initialState: shim.initialState}
551
+ } : undefined)
552
+ app.root = new Inst(app, def, null, rootCell(app), app.sources.DOM, {}, [], undefined,
553
+ opts.uid ? opts.uid.replace(/[^\w-]+/g, '_') : 'u', 'root')
554
+ link?.()
555
+ } catch (e) {
556
+ app.draining = was
557
+ app.dispose()
558
+ throw e
559
+ }
560
+ app.draining = was
561
+ if (app.queue.length) app.drain()
562
+ app.commit()
563
+ let dom$: any
564
+ const sinks: Record<string, any> = {__dispose: () => app.dispose()}
565
+ for (const n of new Set([...Object.keys(all), 'PARENT'])) {
566
+ if (n == 'DOM') Object.defineProperty(sinks, n, {get: () => dom$ ||= app.vdom$.remember(), enumerable: true})
567
+ else if (!NOT_SINK.test(n) || n == 'PARENT') Object.defineProperty(sinks, n, {get: () => app.exposed(n), enumerable: true})
568
+ }
569
+ const sources: Record<string, any> = {...app.sources}
570
+ Object.defineProperty(sources, 'STATE', {get: () => app.root.stateSource(), enumerable: true})
571
+ return {app, sources, sinks, dispose: () => app.dispose(), api: app.api()}
572
+ }
573
+
@@ -0,0 +1,104 @@
1
+ /**
2
+ * PLAN-4.6 core: declaration statics and reply actions (04-hooks-contract §2.1 "statics",
3
+ * §3.7; spike 0-S proto/statics.ts). The core names no static: a driver source marked
4
+ * `__sygnalStatic: 'timers'` (makeTimerDriver; 'resources' makeFetchDriver, 'connections'
5
+ * makeSocketDriver, 'route' the router, 'head' makeHeadDriver, a testing fake) takes that static
6
+ * of every component that declares it.
7
+ *
8
+ * - A declaring instance's value of `view[static]` (a function of the calculated state, an object
9
+ * of such functions, or a constant such as a `route` string) is recomputed when its state or its
10
+ * shown flag changed: in the flush (after each render pass, so a new instance and a parent's
11
+ * write are covered) and synchronously after each of its own actions (G-158: before that
12
+ * action's own values on any driver sink; D170/Q21).
13
+ * - Sent as `{ [static]: value }`, without deep-equal repeats (objIsEqual); while the instance is
14
+ * on a hidden Switchable page, an object value keeps only its `background: true` entries.
15
+ * Stamped and scoped like any sink value (actions.ts send()). A throwing declaration is SYG216
16
+ * ('declaration'; nothing sent).
17
+ * - Reply actions: an instance listens to `replies(id)` of each reply-capable source
18
+ * (`__sygnalReplies: true`) it sends to or declares a static to, from its creation; a reply is
19
+ * dispatched to it with cause 'reply'. Disposing completes them at once, so the driver stops the
20
+ * instance's timers / aborts its requests (G-144), after DISPOSE and dispose$ ran.
21
+ */
22
+ import type {Inst} from './instance'
23
+ import type {App} from './runtime'
24
+ import type {CoreDef} from './define'
25
+ import {objIsEqual} from '../cycle/state/objIsEqual'
26
+ import {send} from './actions'
27
+ import {viewOf} from './view'
28
+
29
+ /** the drivers' statics and reply-capable sources (once per app, at start) */
30
+ export function scanSources(app: App) {
31
+ for (const n in app.sources) {
32
+ const s = app.sources[n]
33
+ if (!s || typeof s != 'object') continue
34
+ if (typeof s.__sygnalStatic == 'string') app.stat.push([n, s.__sygnalStatic])
35
+ if (s.__sygnalReplies === true && typeof s.replies == 'function') app.rep.push(n)
36
+ }
37
+ if (app.stat.length) app.afterRender = () => { for (const i of app.statics) checkStatics(i) }
38
+ }
39
+
40
+ /** the [sink, static] pairs this definition declares (null: none), cached per app */
41
+ export function staticsOf(app: App, def: CoreDef): Array<[string, string]> | null {
42
+ let s = app.stc.get(def)
43
+ if (s === undefined) {
44
+ const v = def.view, l = app.stat.filter(([, k]) => v[k] != null)
45
+ app.stc.set(def, (s = l.length ? l : null))
46
+ }
47
+ return s
48
+ }
49
+
50
+ /** at creation (before the intent): the statics it declares and the replies it listens to */
51
+ export function attach(inst: Inst) {
52
+ const app = inst.app, def = inst.def
53
+ const st = inst.st = app.stat.length ? staticsOf(app, def) : null
54
+ // (made in a flush's render: that pass's statics step computes it, G-323; else a flush does)
55
+ if (st) { inst.sv = {}; app.statics.add(inst); if (!app.flushing) app.commit() }
56
+ for (const n of app.rep) {
57
+ if (!def.sinks.has(n) && !st?.some(s => s[0] == n)) continue
58
+ const src = inst.src(n), r$ = (typeof src?.replies == 'function' ? src : app.sources[n]).replies(inst.id)
59
+ ;(inst.rep ||= []).push(r$)
60
+ r$.subscribe({next: (a: any) => a && app.dispatch(inst, a.type, a.data, 'reply', n)})
61
+ }
62
+ }
63
+
64
+ /** on dispose: no more declarations; the replies end now (the drivers drop the instance) */
65
+ export function detach(inst: Inst) {
66
+ if (inst.st) inst.app.statics.delete(inst)
67
+ const r = inst.rep
68
+ if (r) { inst.rep = null; for (const r$ of r) try { r$.shamefullySendComplete() } catch (_) {} }
69
+ }
70
+
71
+ const shownOf = (inst: Inst) => {
72
+ for (let i: Inst | null = inst; i; i = i.parent) if (!i.shown) return false
73
+ return true
74
+ }
75
+
76
+ /** recompute the instance's declarations when its state or shown flag changed; send the changed ones */
77
+ export function checkStatics(inst: Inst) {
78
+ if (inst.disposed) return
79
+ const s = inst.cell.get(), shown = shownOf(inst)
80
+ // no state yet: nothing declared (as the state stream, which skips undefined)
81
+ if (s === undefined || (s === inst.sS && shown === inst.sH)) return
82
+ inst.sS = s; inst.sH = shown
83
+ const view = inst.def.view, sv = inst.sv!
84
+ for (const [n, k] of inst.st!) {
85
+ const f = view[k]
86
+ let v: any = f
87
+ try {
88
+ if (typeof f == 'function') v = f(s)
89
+ else if (f && typeof f == 'object') { v = {}; for (const r in f) v[r] = f[r](s) }
90
+ } catch (e) {
91
+ // as today: nothing sent; the next value is sent even when equal to the last one
92
+ inst.app.caught(inst, 'SYG216', `${k} threw; nothing sent`, e, 'declaration')
93
+ sv[n] = undefined
94
+ continue
95
+ }
96
+ // D85: a hidden page keeps only its background entries (an object value)
97
+ if (!shown && v && typeof v == 'object') { const w = v; v = {}; for (const r in w) if (w[r]?.background) v[r] = w[r] }
98
+ const out = {[k]: v}
99
+ if (n in sv && objIsEqual(out, sv[n])) continue
100
+ sv[n] = out
101
+ inst.app.hooks.onSink?.(viewOf(inst), null, n, out)
102
+ send(inst, n, out)
103
+ }
104
+ }