@torpor/view 0.1.11 → 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 (807) hide show
  1. package/.oxlintrc.json +3 -0
  2. package/CHANGELOG.md +37 -0
  3. package/README.md +28 -27
  4. package/dist/Component-d19HOoEw.d.ts +11 -0
  5. package/dist/Component-d19HOoEw.d.ts.map +1 -0
  6. package/dist/ServerSlotRender-BiG4xB8e.d.ts +41 -0
  7. package/dist/ServerSlotRender-BiG4xB8e.d.ts.map +1 -0
  8. package/dist/compile.d.ts +202 -148
  9. package/dist/compile.d.ts.map +1 -0
  10. package/dist/compile.js +3380 -3747
  11. package/dist/compile.js.map +1 -1
  12. package/dist/formatText-B0FXBdFT.js +410 -0
  13. package/dist/formatText-B0FXBdFT.js.map +1 -0
  14. package/dist/index.d.ts +373 -170
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +826 -760
  17. package/dist/index.js.map +1 -1
  18. package/dist/ssr.d.ts +13 -8
  19. package/dist/ssr.d.ts.map +1 -0
  20. package/dist/ssr.js +18 -27
  21. package/dist/ssr.js.map +1 -1
  22. package/package.json +18 -22
  23. package/scripts/buildTestOutput.ts +1 -1
  24. package/scripts/copyToRepl.ts +9 -7
  25. package/src/ambient.d.ts +1 -0
  26. package/src/compile/build/client/BuildStatus.ts +6 -4
  27. package/src/compile/build/client/addMappedText.ts +25 -0
  28. package/src/compile/build/client/buildAddFragment.ts +26 -4
  29. package/src/compile/build/client/buildAwaitNode.ts +86 -54
  30. package/src/compile/build/client/buildCode.ts +91 -57
  31. package/src/compile/build/client/buildComponentNode.ts +23 -43
  32. package/src/compile/build/client/buildControlNode.ts +5 -4
  33. package/src/compile/build/client/buildElementNode.ts +70 -78
  34. package/src/compile/build/client/buildForNode.ts +24 -12
  35. package/src/compile/build/client/buildFragment.ts +29 -43
  36. package/src/compile/build/client/buildFragmentText.ts +27 -20
  37. package/src/compile/build/client/buildHtmlNode.ts +5 -3
  38. package/src/compile/build/client/buildIfNode.ts +44 -29
  39. package/src/compile/build/client/buildMount.ts +1 -1
  40. package/src/compile/build/client/buildNode.ts +8 -7
  41. package/src/compile/build/client/buildReplaceNode.ts +5 -3
  42. package/src/compile/build/client/buildRootNode.ts +2 -2
  43. package/src/compile/build/client/buildRun.ts +1 -1
  44. package/src/compile/build/client/buildScriptNode.ts +5 -3
  45. package/src/compile/build/client/buildSlotNode.ts +7 -23
  46. package/src/compile/build/client/buildSpecialNode.ts +10 -14
  47. package/src/compile/build/client/buildStyles.ts +53 -18
  48. package/src/compile/build/client/buildSwitchNode.ts +53 -32
  49. package/src/compile/build/client/buildTextNode.ts +31 -28
  50. package/src/compile/build/client/replaceForVarNames.ts +1 -1
  51. package/src/compile/build/client/stashRun.ts +22 -0
  52. package/src/compile/build/client/stashRunWithOffsets.ts +32 -0
  53. package/src/compile/build/server/BuildServerStatus.ts +3 -3
  54. package/src/compile/build/server/buildServerAwaitNode.ts +5 -5
  55. package/src/compile/build/server/buildServerCode.ts +60 -39
  56. package/src/compile/build/server/buildServerComponentNode.ts +21 -41
  57. package/src/compile/build/server/buildServerControlNode.ts +7 -4
  58. package/src/compile/build/server/buildServerElementNode.ts +18 -29
  59. package/src/compile/build/server/buildServerForNode.ts +5 -5
  60. package/src/compile/build/server/buildServerHtmlNode.ts +3 -3
  61. package/src/compile/build/server/buildServerIfNode.ts +5 -5
  62. package/src/compile/build/server/buildServerNode.ts +7 -6
  63. package/src/compile/build/server/buildServerReplaceNode.ts +5 -5
  64. package/src/compile/build/server/buildServerRootNode.ts +2 -2
  65. package/src/compile/build/server/buildServerScriptNode.ts +1 -1
  66. package/src/compile/build/server/buildServerSlotNode.ts +14 -26
  67. package/src/compile/build/server/buildServerSpecialNode.ts +10 -13
  68. package/src/compile/build/server/buildServerSwitchNode.ts +5 -5
  69. package/src/compile/build/server/buildServerTextNode.ts +9 -23
  70. package/src/compile/build/utils/nextVarName.ts +2 -2
  71. package/src/compile/build.ts +9 -4
  72. package/src/compile/buildType.ts +2 -2
  73. package/src/compile/parse/ParseComponentStatus.ts +24 -0
  74. package/src/compile/parse/ParseStatus.ts +6 -26
  75. package/src/compile/parse/addSpaceElement.ts +6 -5
  76. package/src/compile/parse/parseCode.ts +116 -60
  77. package/src/compile/parse/parseControl.ts +34 -32
  78. package/src/compile/parse/parseElement.ts +56 -121
  79. package/src/compile/parse/parseImports.ts +1 -1
  80. package/src/compile/parse/parseInlineScript.ts +12 -26
  81. package/src/compile/parse/parseMarkup.ts +9 -3
  82. package/src/compile/parse/parseStyles.ts +4 -4
  83. package/src/compile/parse/parseTag.ts +50 -8
  84. package/src/compile/parse/parseText.ts +96 -0
  85. package/src/compile/parse/scopeStyles.ts +9 -8
  86. package/src/compile/parse/slottifyChildNodes.ts +8 -7
  87. package/src/compile/parse/utils/accept.ts +1 -1
  88. package/src/compile/parse/utils/addError.ts +24 -6
  89. package/src/compile/parse/utils/consumeAlphaNumeric.ts +1 -1
  90. package/src/compile/parse/utils/consumeNonSpace.ts +1 -1
  91. package/src/compile/parse/utils/consumeSpace.ts +1 -1
  92. package/src/compile/parse/utils/consumeUntil.ts +1 -1
  93. package/src/compile/parse/utils/expect.ts +1 -1
  94. package/src/compile/parse.ts +1 -1
  95. package/src/compile/types/BuildResult.ts +5 -2
  96. package/src/compile/types/CompileError.ts +8 -5
  97. package/src/compile/types/Import.ts +2 -2
  98. package/src/compile/types/ParseResult.ts +4 -4
  99. package/src/compile/types/ScriptChunk.ts +6 -0
  100. package/src/compile/types/SourceMapping.ts +7 -0
  101. package/src/compile/types/SourceRange.ts +4 -0
  102. package/src/compile/types/nodes/Attribute.ts +7 -2
  103. package/src/compile/types/nodes/ControlNode.ts +8 -6
  104. package/src/compile/types/nodes/ElementNode.ts +11 -6
  105. package/src/compile/types/nodes/Fragment.ts +10 -2
  106. package/src/compile/types/nodes/NodeType.ts +3 -1
  107. package/src/compile/types/nodes/OperationType.ts +3 -1
  108. package/src/compile/types/nodes/ParentNode.ts +4 -4
  109. package/src/compile/types/nodes/RootNode.ts +5 -5
  110. package/src/compile/types/nodes/TemplateNode.ts +3 -3
  111. package/src/compile/types/nodes/TextNode.ts +5 -3
  112. package/src/compile/types/styles/Attribute.ts +2 -2
  113. package/src/compile/types/styles/Style.ts +3 -3
  114. package/src/compile/types/styles/StyleBlock.ts +3 -3
  115. package/src/compile/utils/Builder.ts +25 -11
  116. package/src/compile/utils/endOfString.ts +8 -0
  117. package/src/compile/utils/endOfTemplateString.ts +14 -0
  118. package/src/compile/{types/nodes → utils}/isComponentNode.ts +2 -2
  119. package/src/compile/utils/isControlNode.ts +6 -0
  120. package/src/compile/utils/isElementNode.ts +6 -0
  121. package/src/compile/utils/isParentNode.ts +6 -0
  122. package/src/compile/{types/nodes → utils}/isSpaceNode.ts +3 -3
  123. package/src/compile/utils/isSpecialNode.ts +6 -0
  124. package/src/compile/utils/isTextNode.ts +6 -0
  125. package/src/compile.ts +2 -2
  126. package/src/debug/printNode.ts +12 -8
  127. package/src/debug/printRanges.ts +74 -0
  128. package/src/debug/printSignalDiagram.ts +139 -0
  129. package/src/debug/printSimpleDiagram.ts +88 -0
  130. package/src/index.ts +15 -8
  131. package/src/render/$batch.ts +22 -0
  132. package/src/render/$cache.ts +34 -0
  133. package/src/render/$mount.ts +1 -1
  134. package/src/render/$peek.ts +14 -0
  135. package/src/render/$run.ts +16 -13
  136. package/src/render/$serverBatch.ts +3 -0
  137. package/src/render/$serverCache.ts +3 -0
  138. package/src/render/$serverMount.ts +1 -1
  139. package/src/render/$serverPeek.ts +3 -0
  140. package/src/render/$serverRun.ts +1 -1
  141. package/src/render/$unwrap.ts +3 -1
  142. package/src/render/$watch.ts +12 -13
  143. package/src/render/addAnimation.ts +1 -1
  144. package/src/render/addFragment.ts +16 -24
  145. package/src/render/applyProps.ts +1 -1
  146. package/src/render/buildClasses.ts +31 -0
  147. package/src/render/buildStyles.ts +19 -0
  148. package/src/render/clearLayoutSlot.ts +1 -1
  149. package/src/render/clearRange.ts +43 -50
  150. package/src/render/context.ts +19 -48
  151. package/src/render/fillLayoutSlot.ts +3 -3
  152. package/src/render/getFragment.ts +1 -1
  153. package/src/render/hydrate.ts +9 -2
  154. package/src/render/hydrateRoot.ts +2 -2
  155. package/src/render/isCommentNode.ts +3 -0
  156. package/src/render/isFragmentNode.ts +3 -0
  157. package/src/render/isTextNode.ts +3 -0
  158. package/src/render/mount.ts +12 -4
  159. package/src/render/moveRange.ts +5 -3
  160. package/src/render/newListItem.ts +4 -4
  161. package/src/render/newRange.ts +6 -5
  162. package/src/render/nodeAnchor.ts +6 -6
  163. package/src/render/nodeCheckHydrationBreak.ts +3 -3
  164. package/src/render/nodeChild.ts +2 -2
  165. package/src/render/nodeNext.ts +2 -2
  166. package/src/render/nodeRoot.ts +18 -4
  167. package/src/render/popRange.ts +2 -2
  168. package/src/render/pushRange.ts +12 -4
  169. package/src/render/runControl.ts +1 -5
  170. package/src/render/runControlBranch.ts +10 -24
  171. package/src/render/runList.ts +6 -5
  172. package/src/render/runListItems.ts +39 -39
  173. package/src/render/setAttribute.ts +1 -1
  174. package/src/render/setDynamicElement.ts +2 -2
  175. package/src/ssr.ts +7 -4
  176. package/src/types/Animation.ts +1 -1
  177. package/src/types/BuildOptions.ts +6 -2
  178. package/src/types/Cleanup.ts +3 -1
  179. package/src/types/Component.ts +4 -2
  180. package/src/types/Computed.ts +62 -0
  181. package/src/types/Context.ts +99 -0
  182. package/src/types/Effect.ts +45 -9
  183. package/src/types/ListItem.ts +3 -3
  184. package/src/types/ProxyData.ts +6 -4
  185. package/src/types/ProxySignal.ts +28 -0
  186. package/src/types/Range.ts +10 -16
  187. package/src/types/ServerComponent.ts +5 -3
  188. package/src/types/ServerSlotRender.ts +3 -1
  189. package/src/types/SlotRender.ts +4 -2
  190. package/src/types/Subscription.ts +57 -0
  191. package/src/types/Template.ts +6 -5
  192. package/src/types/TemplateComponent.ts +7 -5
  193. package/src/types/WatchOptions.ts +8 -2
  194. package/src/types/constants.ts +14 -0
  195. package/src/watch/batchEnd.ts +17 -0
  196. package/src/watch/batchStart.ts +5 -0
  197. package/src/watch/checkComputed.ts +46 -0
  198. package/src/watch/checkEffect.ts +30 -0
  199. package/src/watch/checkSources.ts +63 -0
  200. package/src/watch/clearSources.ts +39 -0
  201. package/src/watch/clearTargets.ts +28 -0
  202. package/src/watch/deactivateSources.ts +19 -0
  203. package/src/watch/proxyGet.ts +106 -51
  204. package/src/watch/proxySet.ts +17 -13
  205. package/src/watch/runCleanups.ts +40 -0
  206. package/src/watch/runComputed.ts +36 -0
  207. package/src/watch/runEffect.ts +38 -13
  208. package/src/watch/symbols.ts +3 -1
  209. package/src/watch/trackEffect.ts +63 -15
  210. package/src/watch/trackProxyEffect.ts +21 -0
  211. package/src/watch/transferEffects.ts +66 -62
  212. package/src/watch/triggerEffects.ts +55 -18
  213. package/src/watch/updateSignal.ts +102 -0
  214. package/src/wrappers/ReactiveDate.ts +68 -0
  215. package/test/attributes/attributes.test.ts +2 -2
  216. package/test/attributes/components/output/Attributes-client.ts +8 -20
  217. package/test/attributes/components/output/Attributes-server.ts +9 -11
  218. package/test/attributes/components/temp/{Attributes-client-4620a40099e57a7fdaab895b204d85881f6dbfb7.ts → Attributes-client-9b2935d7824ba501776fdc6c48861422c15b6a12.ts} +8 -20
  219. package/test/attributes/components/temp/Attributes-server-716db6e335e5a372a34dd931e5f358ee6d1869e5.ts +16 -0
  220. package/test/attributes/disappearing.test.ts +2 -2
  221. package/test/attributes/parse.test.ts +161 -248
  222. package/test/await/await.test.ts +2 -2
  223. package/test/await/components/Await.torp +11 -13
  224. package/test/await/components/output/Await-client.ts +31 -46
  225. package/test/await/components/output/Await-server.ts +13 -14
  226. package/test/await/components/temp/{Await-client-9c30564ea39457e614e60c0cc0a71c431e8a1e76.ts → Await-client-e969f4bd0712acf259ddfaa5a3b3448307201fd2.ts} +31 -46
  227. package/test/await/components/temp/{Await-server-f02f39af3bb3344ca6b18a1d64d60b21913fba31.ts → Await-server-614014fab69e234b8271088b10397cf0452d9a76.ts} +13 -14
  228. package/test/bench/components/Bench.torp +4 -4
  229. package/test/bench/components/output/Bench-client.ts +43 -46
  230. package/test/bench/components/output/Bench-server.ts +16 -17
  231. package/test/bench/components/temp/Bench-client-7f31596dafc8077370d8d90b1bb9b6e0208154e7.ts +205 -0
  232. package/test/bench/components/temp/{Bench-server-00cefa588803c01ca4f2741c595e4f045cdd101e.ts → Bench-server-341b20073668f4f2160cd2ba37847c7db15e1e0f.ts} +16 -17
  233. package/test/bind/bind.test.ts +2 -2
  234. package/test/bind/component.test.ts +2 -2
  235. package/test/bind/components/BindComponent.torp +3 -18
  236. package/test/bind/components/BindText.torp +8 -10
  237. package/test/bind/components/output/BindComponent-client.ts +26 -47
  238. package/test/bind/components/output/BindComponent-server.ts +25 -36
  239. package/test/bind/components/output/BindText-client.ts +9 -16
  240. package/test/bind/components/output/BindText-server.ts +10 -11
  241. package/test/bind/components/temp/BindComponent-client-22eccb5354a2b0267841e015f3a2a0baf534bf89.ts +72 -0
  242. package/test/bind/components/temp/BindComponent-server-0da6ba90a409468fd1f7358f8198e96b7595ff80.ts +41 -0
  243. package/test/bind/components/temp/{BindText-client-134676d616abbad6b8a7ec48df0a2e38cbfe3b87.ts → BindText-client-7692ae1570533cc17e2186e9c7d4768529e4a2fe.ts} +9 -16
  244. package/test/bind/components/temp/BindText-server-6801c5f8e66a65405b45061bc037a011620c0591.ts +20 -0
  245. package/test/build-server/build-server.test.ts +2 -1
  246. package/test/build-server/components/IfNested.torp +11 -13
  247. package/test/{if/components/temp/IfNested-client-f3045daba052e459add6e7f84e8d21ba7b0d81e4.ts → build-server/components/output/IfNested-client.ts} +23 -27
  248. package/test/build-server/components/output/IfNested-server.ts +29 -0
  249. package/test/build-server/components/temp/IfNested-client-eefdd449fa700b2e7326bc72df8b32ddcadf9d21.ts +88 -0
  250. package/test/build-server/components/temp/IfNested-server-7a53e4969b5dfe5073f05edbcb1b986f718bb939.ts +29 -0
  251. package/test/buildHtml.ts +3 -2
  252. package/test/buildOutputFiles.ts +7 -7
  253. package/test/child-component/child-component.test.ts +2 -2
  254. package/test/child-component/components/ParentChild.torp +1 -3
  255. package/test/child-component/components/output/ParentChild-client.ts +13 -24
  256. package/test/child-component/components/output/ParentChild-server.ts +20 -22
  257. package/test/child-component/components/temp/{ParentChild-client-50ca7e499599209c9d674f2561413ca14a282c22.ts → ParentChild-client-2dfd600f7d409630d429a1d2d18c038bd08b08da.ts} +13 -24
  258. package/test/child-component/components/temp/ParentChild-server-448d57c3229189c1d297d01dfb0f33646d280e90.ts +37 -0
  259. package/test/class/class.test.ts +2 -2
  260. package/test/class/components/Class.torp +22 -24
  261. package/test/class/components/output/Class-client.ts +17 -37
  262. package/test/class/components/output/Class-server.ts +25 -25
  263. package/test/class/components/temp/{Class-client-de2491c550647203bea08727fa8c88f30654db0a.ts → Class-client-5af6a50cd454ae019b2aa79457ba7ead83b8c056.ts} +17 -37
  264. package/test/class/components/temp/Class-server-eb70ff01fbc7d6d53e16c3593ba021a6bf0317f9.ts +40 -0
  265. package/test/comments/html-comments.test.ts +16 -24
  266. package/test/comments/js-block-comments.test.ts +16 -25
  267. package/test/comments/js-line-comments.test.ts +16 -25
  268. package/test/component/component.test.ts +2 -2
  269. package/test/component/components/Component.torp +1 -1
  270. package/test/component/components/output/Component-client.ts +5 -10
  271. package/test/component/components/output/Component-server.ts +13 -13
  272. package/test/component/components/output/Header-client.ts +6 -12
  273. package/test/component/components/output/Header-server.ts +9 -11
  274. package/test/component/components/temp/{Component-client-350d20784712c710929cc3ab34c6828b0ea338d8.ts → Component-client-fdc327499be0a01f987d0f2897baf022a247c77c.ts} +5 -10
  275. package/test/component/components/temp/Component-server-f53221ac7b1c922ef10de2d1fe8fb534d0169fe7.ts +24 -0
  276. package/test/component/components/temp/{Header-client-903877003b220272b0cb5bfd62d7d748ad46c477.ts → Header-client-6beb5770e68e6b19595e53e20bc906765fc6c260.ts} +6 -12
  277. package/test/component/components/temp/Header-server-940b0984f9b6c11f310db9200c9075ded385eda5.ts +16 -0
  278. package/test/console/components/output/Console-client.ts +5 -10
  279. package/test/console/components/output/Console-server.ts +9 -11
  280. package/test/console/components/temp/{Console-client-4fa3b3679cee88bf6151185438e36d14010944b7.ts → Console-client-2b58290ac407ebbe89a0613d64eb9cd141b99887.ts} +5 -10
  281. package/test/console/components/temp/Console-server-bde0121ce434f767435b1841fc4c24402becdba2.ts +15 -0
  282. package/test/console/console.test.ts +2 -2
  283. package/test/const/components/Const.torp +4 -6
  284. package/test/const/components/output/Const-client.ts +8 -13
  285. package/test/const/components/output/Const-server.ts +10 -12
  286. package/test/const/components/temp/{Const-client-7dff2758c14bfbd208e301a702ae1781e6daba1b.ts → Const-client-d1037557e7ef75a8fe06f56816e65883047e9421.ts} +8 -13
  287. package/test/const/components/temp/Const-server-32ddc3617afe2324f17a4cff6c0f086df6694778.ts +18 -0
  288. package/test/const/const.test.ts +2 -2
  289. package/test/context/components/ChildA.torp +10 -0
  290. package/test/context/components/ChildB.torp +8 -0
  291. package/test/context/components/Parent.torp +11 -0
  292. package/test/context/components/output/ChildA-client.ts +38 -0
  293. package/test/context/components/output/ChildA-server.ts +19 -0
  294. package/test/{party/components/temp/CssStyle-client-37465dd48d1479db1bae513eb0b92c4e9a15e9ea.ts → context/components/output/ChildB-client.ts} +10 -12
  295. package/test/context/components/output/ChildB-server.ts +18 -0
  296. package/test/context/components/output/Parent-server.ts +31 -0
  297. package/test/context/components/temp/ChildA-client-9dea3e29ffcb82ca1779f6ff671e19b1c106fc4a.ts +38 -0
  298. package/test/context/components/temp/ChildA-server-54024d23c8241c3f475068f4fe3a3a14fd1c5870.ts +19 -0
  299. package/test/{special-head/components/temp/Head-client-18616689a7d6f83ca076c9d825606b049de9d3ef.ts → context/components/temp/ChildB-client-4b801099936c8aa013a1220f291375f67eba1acb.ts} +10 -21
  300. package/test/context/components/temp/ChildB-server-f9b71341863bf869248bd406dbe8c7726a30ff90.ts +18 -0
  301. package/test/context/components/temp/Parent-client-9898b2e521527c86d69905053b6727ea8fd28166.ts +41 -0
  302. package/test/context/components/temp/Parent-server-b592ff0f516f4592e56d3a0bcb1f271ed28e812c.ts +31 -0
  303. package/test/context/context.test.ts +37 -0
  304. package/test/effects/components/For.torp +3 -5
  305. package/test/effects/components/If.torp +5 -7
  306. package/test/effects/components/NestedIf.torp +6 -8
  307. package/test/effects/components/output/For-client.ts +23 -25
  308. package/test/effects/components/output/For-server.ts +10 -12
  309. package/test/effects/components/output/If-client.ts +19 -25
  310. package/test/effects/components/output/If-server.ts +11 -13
  311. package/test/effects/components/output/NestedIf-client.ts +26 -31
  312. package/test/effects/components/output/NestedIf-server.ts +13 -15
  313. package/test/effects/components/temp/{For-client-35bf9bea43f53d6c0cf807f9e31500765fa0b455.ts → For-client-7c7d7c0dba2547f816b9bd9c6a95d6873ec00ffd.ts} +23 -25
  314. package/test/effects/components/temp/For-server-9e2de4efaff38ecf6c8a169c629d83c385489ca1.ts +20 -0
  315. package/test/effects/components/temp/{If-client-efb994796596d9d08f59a0ab5ffdacc74bd04545.ts → If-client-f0480a98f80b32612d12765c6838ff6db5982e82.ts} +19 -25
  316. package/test/effects/components/temp/If-server-ab409671b5d4c918047394a37b6e96b0e17063ca.ts +22 -0
  317. package/test/effects/components/temp/{NestedIf-client-845b3789b8a938439bff758bc9b3731d769c8ff6.ts → NestedIf-client-702deffd158f219c5da4199b563a62cd54385a7f.ts} +26 -31
  318. package/test/effects/components/temp/NestedIf-server-40f6bfd99a7e75fb4f9f874adab77e5eed97c629.ts +26 -0
  319. package/test/effects/for-effect.test.ts +15 -15
  320. package/test/effects/if-effect.test.ts +7 -7
  321. package/test/effects/nested-if-effect.test.ts +11 -11
  322. package/test/events/components/Increment.torp +10 -12
  323. package/test/events/components/output/Increment-client.ts +10 -15
  324. package/test/events/components/output/Increment-server.ts +11 -12
  325. package/test/events/components/temp/{Increment-client-1b5f9e231c5c4fc059d77ca0da632719283e5ac4.ts → Increment-client-84c09711baf098c82ee226598ba7a36913616b75.ts} +10 -15
  326. package/test/events/components/temp/Increment-server-e77c6b207023ac60e033ca542ee82473ef017f74.ts +23 -0
  327. package/test/events/events.test.ts +9 -15
  328. package/test/for/components/output/For-client.ts +19 -19
  329. package/test/for/components/output/For-server.ts +11 -13
  330. package/test/for/components/output/ForEscape-client.ts +23 -37
  331. package/test/for/components/output/ForEscape-server.ts +12 -13
  332. package/test/for/components/output/ForIn-client.ts +19 -20
  333. package/test/for/components/output/ForIn-server.ts +11 -13
  334. package/test/for/components/output/ForOf-client.ts +19 -20
  335. package/test/for/components/output/ForOf-server.ts +11 -13
  336. package/test/for/components/temp/{For-client-8ecb11a2f34c81f837bffdb88598da06d8c19158.ts → For-client-2f6b4b81670b0ba31b01176b4f61ebf321e945bb.ts} +19 -19
  337. package/test/for/components/temp/For-server-5144615e53d23da5062b7169e847e0777d068738.ts +20 -0
  338. package/test/for/components/temp/{ForEscape-client-14e7648415d967cdc57bf03d176eb6b6dddf0fb2.ts → ForEscape-client-8d0fcc940851e687173b6a9129c3d83e0fc771ef.ts} +23 -37
  339. package/test/for/components/temp/ForEscape-server-b359d8d3e12bac290855a1b27387ddd963562c08.ts +23 -0
  340. package/test/for/components/temp/{ForIn-client-25cd67f246a50fc6d926a8c66aa5e106f19578a8.ts → ForIn-client-fa0614a1c7b8aa6e8819ed91a518479fd80453ae.ts} +19 -20
  341. package/test/for/components/temp/ForIn-server-5fd472a7a5a5c00b384791780025a0c3bdc9c41b.ts +20 -0
  342. package/test/for/components/temp/{ForOf-client-8f6598ccd9dc7b79aff6167b90ccea94f3029c84.ts → ForOf-client-11006c4239d9018363e582dc5b54b50477d652e7.ts} +19 -20
  343. package/test/for/components/temp/ForOf-server-197b29abcb60412c6c8670b2d4a2e644b650faa3.ts +20 -0
  344. package/test/for/for-escape.test.ts +2 -2
  345. package/test/for/for-in.test.ts +4 -4
  346. package/test/for/for-of.test.ts +4 -4
  347. package/test/for/for-with-key.test.ts +28 -36
  348. package/test/for/for.test.ts +2 -2
  349. package/test/function/components/Function.torp +7 -10
  350. package/test/function/components/output/Function-client.ts +9 -15
  351. package/test/function/components/output/Function-server.ts +11 -13
  352. package/test/function/components/temp/{Function-client-4e2168306756eb927d5ed4b673334b357eecaa74.ts → Function-client-ec5fe7d599d6099bdfab78c2a0c8edf77a23cd9b.ts} +9 -15
  353. package/test/function/components/temp/Function-server-fee2402b0ef4ad4c3d2779afb190ce46dbedf737.ts +25 -0
  354. package/test/function/function.test.ts +7 -13
  355. package/test/helpers.ts +44 -9
  356. package/test/html/components/output/Html-client.ts +6 -12
  357. package/test/html/components/output/Html-server.ts +9 -11
  358. package/test/html/components/temp/{Html-client-93b0d666142c64cd651dc37f14f12884b2f30612.ts → Html-client-82ff34dcdcbdf4be1112bcb1baac8027cdc32de7.ts} +6 -12
  359. package/test/html/components/temp/Html-server-14fa484fc2a617bc0f24432a2e37e7a756f87a0f.ts +15 -0
  360. package/test/html/html.test.ts +2 -2
  361. package/test/hydrateComponent.ts +4 -5
  362. package/test/if/components/output/IfAfterIf-client.ts +21 -23
  363. package/test/if/components/output/IfAfterIf-server.ts +12 -14
  364. package/test/if/components/output/IfElse-client.ts +14 -18
  365. package/test/if/components/output/IfElse-server.ts +11 -13
  366. package/test/if/components/output/IfElseIf-client.ts +16 -22
  367. package/test/if/components/output/IfElseIf-server.ts +12 -14
  368. package/test/if/components/output/IfFalse-client.ts +13 -16
  369. package/test/if/components/output/IfFalse-server.ts +10 -12
  370. package/test/if/components/output/IfNested-client.ts +23 -27
  371. package/test/if/components/output/IfNested-server.ts +14 -16
  372. package/test/if/components/temp/{IfAfterIf-client-6b4833209a01cdad18d453839e9c8b5dad2a8510.ts → IfAfterIf-client-c1cfd21a6ace4945703ba8f46aada923a60265d9.ts} +21 -23
  373. package/test/if/components/temp/IfAfterIf-server-26c9a638e3933a53208bfe66f8f37067511a28aa.ts +23 -0
  374. package/test/if/components/temp/{IfElse-client-f7eb8e5fe5e62975a2442c4b0ff3344fa44cef69.ts → IfElse-client-06dfcacd3a5225dcb0947587bcd4fae9ec3d3c1e.ts} +14 -18
  375. package/test/if/components/temp/IfElse-server-146b3779f85ea02a281c6042dddefa5372945fb0.ts +22 -0
  376. package/test/if/components/temp/{IfElseIf-client-734f1b2d9133294573770c1ffc2b589273498532.ts → IfElseIf-client-26df9a728c9cb712d5ac0235b4c99885f25545b8.ts} +16 -22
  377. package/test/if/components/temp/IfElseIf-server-f094cdb45bc0fcd3144ca493346994b2445d2ff0.ts +25 -0
  378. package/test/if/components/temp/{IfFalse-client-8a388cb48b4a5879d491f57d1f2551834de1e72e.ts → IfFalse-client-de6fc8e9eb222153608490e6d172e9aae9000aa1.ts} +13 -16
  379. package/test/if/components/temp/IfFalse-server-b6d3446fd7d4219d5cb3c1009dec76870e73fa30.ts +19 -0
  380. package/test/if/components/temp/IfNested-client-eefdd449fa700b2e7326bc72df8b32ddcadf9d21.ts +88 -0
  381. package/test/if/components/temp/IfNested-server-7a53e4969b5dfe5073f05edbcb1b986f718bb939.ts +29 -0
  382. package/test/if/else-if-true.test.ts +4 -4
  383. package/test/if/else-true.test.ts +4 -4
  384. package/test/if/if-after-if.test.ts +4 -4
  385. package/test/if/if-else-false.test.ts +4 -4
  386. package/test/if/if-else-true.test.ts +4 -4
  387. package/test/if/if-false.test.ts +4 -4
  388. package/test/if/if-nested.test.ts +4 -4
  389. package/test/imports/commented-imports.ts +1 -1
  390. package/test/imports/imports.ts +1 -1
  391. package/test/imports/multiple-imports.ts +1 -1
  392. package/test/mount/components/Mount.torp +1 -1
  393. package/test/mount/components/output/Mount-client.ts +6 -11
  394. package/test/mount/components/output/Mount-server.ts +11 -13
  395. package/test/mount/components/temp/{Mount-client-efa5c34fbfc7646e114a1a58f0814b6dff33e566.ts → Mount-client-29896228d7d0ef3692a9d13065c1bbfbe3198cdc.ts} +6 -11
  396. package/test/mount/components/temp/Mount-server-1c5aef88b8cc25b8e02851c0aa7fedffea987224.ts +22 -0
  397. package/test/mount/mount.test.ts +4 -4
  398. package/test/mountComponent.ts +1 -1
  399. package/test/on-mount/components/OnMount.torp +1 -1
  400. package/test/on-mount/components/output/OnMount-client.ts +5 -10
  401. package/test/on-mount/components/output/OnMount-server.ts +9 -11
  402. package/test/on-mount/components/temp/{OnMount-client-4bb62e8bf1fcd67798598fe03bf5455a57f0a6be.ts → OnMount-client-038f8c6bbcf0278406909d6ba5394f311924fda9.ts} +5 -10
  403. package/test/on-mount/components/temp/OnMount-server-ff4afcd976fd907c539e763d7887b38c61737be7.ts +15 -0
  404. package/test/on-mount/on-mount.test.ts +6 -6
  405. package/test/party/1-declare-state.test.ts +2 -2
  406. package/test/party/10-on-mount.test.ts +2 -2
  407. package/test/party/12-props.test.ts +2 -2
  408. package/test/party/13-emit-to-parent.test.ts +2 -2
  409. package/test/party/14-slot.test.ts +2 -2
  410. package/test/party/15-slot-fallback.test.ts +2 -2
  411. package/test/party/16-context.test.ts +2 -2
  412. package/test/party/17-input-text.test.ts +2 -2
  413. package/test/party/18-input-checkbox.test.ts +2 -2
  414. package/test/party/19-input-radio.test.ts +2 -2
  415. package/test/party/2-update-state.test.ts +2 -2
  416. package/test/party/20-input-select.test.ts +2 -2
  417. package/test/party/3-computed-state.test.ts +2 -2
  418. package/test/party/4-minimal-template.test.ts +2 -2
  419. package/test/party/5-styling.test.ts +2 -2
  420. package/test/party/6-loop.test.ts +2 -2
  421. package/test/party/7-event-click.test.ts +2 -2
  422. package/test/party/8-dom-ref.test.ts +4 -4
  423. package/test/party/9-conditional.test.ts +2 -2
  424. package/test/party/components/AnswerButton.torp +2 -5
  425. package/test/party/components/AnswerButtonApp.torp +3 -5
  426. package/test/party/components/ColorSelect.torp +8 -10
  427. package/test/party/components/Counter.torp +2 -4
  428. package/test/party/components/CssStyle.torp +2 -4
  429. package/test/party/components/FunnyButton.torp +2 -2
  430. package/test/party/components/FunnyButtonApp.torp +2 -4
  431. package/test/party/components/InputFocused.torp +1 -1
  432. package/test/party/components/InputHello.torp +2 -4
  433. package/test/party/components/IsAvailable.torp +3 -5
  434. package/test/party/components/PickPill.torp +5 -7
  435. package/test/party/components/TrafficLight.torp +12 -14
  436. package/test/party/components/UserProfile.torp +4 -6
  437. package/test/party/components/UserProfileApp.torp +1 -1
  438. package/test/party/components/UserProfileContext.torp +6 -8
  439. package/test/party/components/UserProfileContextApp.torp +3 -5
  440. package/test/party/components/output/AnswerButton-client.ts +7 -14
  441. package/test/party/components/output/AnswerButton-server.ts +8 -10
  442. package/test/party/components/output/AnswerButtonApp-client.ts +10 -16
  443. package/test/party/components/output/AnswerButtonApp-server.ts +14 -13
  444. package/test/party/components/output/ColorSelect-client.ts +26 -30
  445. package/test/party/components/output/ColorSelect-server.ts +12 -13
  446. package/test/party/components/output/Colors-client.ts +19 -20
  447. package/test/party/components/output/Colors-server.ts +12 -13
  448. package/test/party/components/output/Counter-client.ts +11 -16
  449. package/test/party/components/output/Counter-server.ts +10 -11
  450. package/test/party/components/output/CssStyle-client.ts +7 -12
  451. package/test/party/components/output/CssStyle-server.ts +12 -11
  452. package/test/party/components/output/DoubleCount-client.ts +6 -11
  453. package/test/party/components/output/DoubleCount-server.ts +10 -11
  454. package/test/party/components/output/FunnyButton-client.ts +4 -10
  455. package/test/party/components/output/FunnyButton-server.ts +11 -12
  456. package/test/party/components/output/FunnyButtonApp-client.ts +12 -22
  457. package/test/party/components/output/FunnyButtonApp-server.ts +21 -20
  458. package/test/party/components/output/HelloWorld-client.ts +5 -10
  459. package/test/party/components/output/HelloWorld-server.ts +9 -11
  460. package/test/party/components/output/InputFocused-client.ts +6 -11
  461. package/test/party/components/output/InputFocused-server.ts +11 -13
  462. package/test/party/components/output/InputHello-client.ts +12 -17
  463. package/test/party/components/output/InputHello-server.ts +10 -11
  464. package/test/party/components/output/IsAvailable-client.ts +12 -17
  465. package/test/party/components/output/IsAvailable-server.ts +10 -11
  466. package/test/party/components/output/Name-client.ts +6 -11
  467. package/test/party/components/output/Name-server.ts +10 -11
  468. package/test/party/components/output/NameUpdate-client.ts +6 -11
  469. package/test/party/components/output/NameUpdate-server.ts +10 -11
  470. package/test/party/components/output/PageTitle-client.ts +6 -11
  471. package/test/party/components/output/PageTitle-server.ts +10 -11
  472. package/test/party/components/output/PickPill-client.ts +12 -17
  473. package/test/party/components/output/PickPill-server.ts +10 -11
  474. package/test/party/components/output/Time-client.ts +6 -11
  475. package/test/party/components/output/Time-server.ts +10 -11
  476. package/test/party/components/output/TrafficLight-client.ts +21 -29
  477. package/test/party/components/output/TrafficLight-server.ts +14 -15
  478. package/test/party/components/output/UserProfile-client.ts +12 -24
  479. package/test/party/components/output/UserProfile-server.ts +8 -10
  480. package/test/party/components/output/UserProfileApp-client.ts +6 -11
  481. package/test/party/components/output/UserProfileApp-server.ts +14 -14
  482. package/test/party/components/output/UserProfileContext-client.ts +12 -18
  483. package/test/party/components/output/UserProfileContext-server.ts +10 -10
  484. package/test/party/components/output/UserProfileContextApp-client.ts +12 -18
  485. package/test/party/components/output/UserProfileContextApp-server.ts +15 -14
  486. package/test/party/components/temp/{AnswerButton-client-ad8f8db36b7aaa68d8de5898a324bacfbe9f20df.ts → AnswerButton-client-df895c3e7a88fd7ede9f951fc9de2ed75c27a5cb.ts} +7 -14
  487. package/test/party/components/temp/AnswerButton-server-fa0e78b504a78d0e2dcd33a9a589f62e5b99c675.ts +15 -0
  488. package/test/party/components/temp/{AnswerButtonApp-client-5661f07868550612bcdeee268b82c473af6a2613.ts → AnswerButtonApp-client-4c05ef36b1c0e93370fb463643419928717fa701.ts} +10 -16
  489. package/test/party/components/temp/AnswerButtonApp-server-062042691dabfa1a20d4088030c0b5bee1cd0be2.ts +39 -0
  490. package/test/party/components/temp/{ColorSelect-client-70bf59d6399d63c0eed421b9d370a1e5c97a89ca.ts → ColorSelect-client-5db8d1b0924361fdb5efb867c14491402ec9668c.ts} +26 -30
  491. package/test/party/components/temp/ColorSelect-server-8722b440cb7266a18a71b35c166be6dd6566fcec.ts +33 -0
  492. package/test/party/components/temp/{Colors-client-806316cc5e01e8235c0b025cad34b1068addf5a5.ts → Colors-client-6d3ac693e85bdda50b8742282915997063a32769.ts} +19 -20
  493. package/test/party/components/temp/Colors-server-16572e26a55214c26683ce560b058b55d8c92685.ts +22 -0
  494. package/test/party/components/temp/{Counter-client-3b876c148f2b14da1766eff77eb6c494f7be6414.ts → Counter-client-0c604a107c5b84cdbf725f307dfe29d34f8a2cc8.ts} +11 -16
  495. package/test/party/components/temp/Counter-server-db18f030a6e02ab17708d6a17eb3e590965090e5.ts +25 -0
  496. package/test/party/components/temp/CssStyle-client-2a642d115ad52539f97c051c34687b8d6d12b324.ts +24 -0
  497. package/test/party/components/temp/CssStyle-server-0477c5497707dd9071105e5ec9045a3a7d1dd62d.ts +18 -0
  498. package/test/party/components/temp/{DoubleCount-client-6d4cf1e54368e3c6082e37c1e04f9ecde90624f2.ts → DoubleCount-client-8c85c3af12c471ea23bb702bbf5a3e240420f3ec.ts} +6 -11
  499. package/test/party/components/temp/DoubleCount-server-5b04bb31269f9c8de6c25be427f57ab6e3d4dc19.ts +24 -0
  500. package/test/party/components/temp/{FunnyButton-client-6d5662018a5a5529fd52ee82f7c88975b5c3355a.ts → FunnyButton-client-850dd3da0fa803c1bce5c53e88fcd2d48d279eb8.ts} +4 -10
  501. package/test/party/components/temp/{FunnyButton-server-e0adab2be2d283acb8a8b580479ade999dc918e9.ts → FunnyButton-server-3df0067ec21476e7525d1c3de7099431c976f73b.ts} +11 -12
  502. package/test/party/components/temp/{FunnyButtonApp-client-daa929c6d64f67e4a1a387b884317a4bb615b5d4.ts → FunnyButtonApp-client-00300846d11a3d0a5a620c2ade87b935b7f0ebf8.ts} +12 -22
  503. package/test/party/components/temp/FunnyButtonApp-server-4cd83d2c71615fe4c905920e5ea836df4ed66c5e.ts +37 -0
  504. package/test/party/components/temp/{HelloWorld-client-7344e400b4adb975fa8263d3081a06de0a793e57.ts → HelloWorld-client-890b311ad9a3919379acdc1d52807ea36cc9f489.ts} +5 -10
  505. package/test/party/components/temp/HelloWorld-server-e2c800d7f5cd3e772a9e5bbd7af58b00611b79d5.ts +15 -0
  506. package/test/party/components/temp/{InputFocused-client-20d755aea7dfaf1fd5e42dcade8fb7867f59ef28.ts → InputFocused-client-03527f9ceb52f66ac53887dbc884a0aa83bb7a23.ts} +6 -11
  507. package/test/party/components/temp/InputFocused-server-544a76ea64852474a3c7bf450b6fac36cbaf21c6.ts +23 -0
  508. package/test/party/components/temp/{InputHello-client-2a4cbd980534fde14b9d3e8a2f8e4f59a4f15d64.ts → InputHello-client-f65a477624975b68b7aaa3614fbf198d4476480f.ts} +12 -17
  509. package/test/party/components/temp/InputHello-server-102d293d6c0fff7feda50d64bbd607df7d09393a.ts +22 -0
  510. package/test/party/components/temp/{IsAvailable-client-3949f85aea0e935c3b59ab1389baee836eff1866.ts → IsAvailable-client-8767437fd92cf79713de5b00828e1502e38d79e3.ts} +12 -17
  511. package/test/party/components/temp/IsAvailable-server-2cf1e0d72df4bc194b5e00a1b415ba99f488525f.ts +21 -0
  512. package/test/party/components/temp/{Name-client-62f0dab96aff130e81882099d7c0a111ba99cebd.ts → Name-client-08903a8df8bdff5288170d3c89658192956587a9.ts} +6 -11
  513. package/test/party/components/temp/Name-server-7d95226078ef4cd13b0ac6c5365ccbe4b8b9c0a2.ts +21 -0
  514. package/test/party/components/temp/{NameUpdate-client-6ceb440637c99142bafcf8512eabf831c113b8c7.ts → NameUpdate-client-d65b2476c3721d2efddf9385a61433e2a2dd0d72.ts} +6 -11
  515. package/test/party/components/temp/NameUpdate-server-9c901f861eddfde14440c2591dfafb2b1fb1993d.ts +22 -0
  516. package/test/party/components/temp/{PageTitle-client-75fea3a37fb1213bc13f56160bb6779486b2e6e9.ts → PageTitle-client-c006df9a3e662488a1db089de53fd485c6b923e4.ts} +6 -11
  517. package/test/party/components/temp/PageTitle-server-f4676ec6feccaa03b89d52835c6635536eb885ef.ts +26 -0
  518. package/test/party/components/temp/{PickPill-client-0f13aa652cb1bd45f57d5a249f8364e80204441a.ts → PickPill-client-af8357daf3f6633c7f451d0bddd72fefe786d5c3.ts} +12 -17
  519. package/test/party/components/temp/PickPill-server-d8fb383bc25f7d26bb0153088a2ee19c765fc66b.ts +22 -0
  520. package/test/party/components/temp/{Time-client-2013f274e90b45be3138727f2298305e1951131f.ts → Time-client-94380d45de7275a5cec98e5f58c15b74b13e9c3e.ts} +6 -11
  521. package/test/party/components/temp/{Time-server-8e0278a4b16925903f3c4ceedbf1332cde4921fa.ts → Time-server-3f71a83b6fd357b57e85344281454ee793024e7b.ts} +10 -11
  522. package/test/party/components/temp/{TrafficLight-client-4a90675ca6157ed7701aefa0d9141575960a1d47.ts → TrafficLight-client-12b20962b4146ef08fe0c37597441533c7699408.ts} +21 -29
  523. package/test/party/components/temp/TrafficLight-server-625a774075633be88822f4d345e1421a77aba98a.ts +39 -0
  524. package/test/party/components/temp/{UserProfile-client-11c2a928de5a5ed4cab45186f08ca09f6161afb5.ts → UserProfile-client-e5330b2c96bd8b225cb6291bc8b1d9f35c93307e.ts} +12 -24
  525. package/test/party/components/temp/UserProfile-server-6e89fd7f8ade8e8d64630e5da8361d7a1fa2ff5a.ts +21 -0
  526. package/test/party/components/temp/{UserProfileApp-client-e0bfaa4ffed336c8be4b23dd81800501980c9938.ts → UserProfileApp-client-4c86e4f9a0d042f4f4811868f0146e872b17353c.ts} +6 -11
  527. package/test/party/components/temp/UserProfileApp-server-754d269451abf8fd04e519b8edde33d25c73ce28.ts +27 -0
  528. package/test/party/components/temp/{UserProfileContext-client-c97c077254210061b3c9ba561f681c0cf4f6167f.ts → UserProfileContext-client-424131db3cc89ae4babe127b9108ffc5696c9e1d.ts} +12 -18
  529. package/test/party/components/temp/UserProfileContext-server-e72e8ccee2703cce216f2368a1555d64acc2654c.ts +20 -0
  530. package/test/party/components/temp/{UserProfileContextApp-client-05ce216919de6ffde56d1c2c39299173d9b611b3.ts → UserProfileContextApp-client-5f94a7ccf3e4542ea40d8046ad75eeb21005c55f.ts} +12 -18
  531. package/test/party/components/temp/UserProfileContextApp-server-267ac147e0e59e53aeb6741a8cd0f3ef1216051f.ts +34 -0
  532. package/test/preact.test.ts +2560 -0
  533. package/test/props/components/Reactive.torp +2 -4
  534. package/test/props/components/output/Reactive-client.ts +12 -22
  535. package/test/props/components/output/Reactive-server.ts +20 -20
  536. package/test/props/components/temp/{Reactive-client-cf6e602b2f74fce8e9451b6c41c6f8ff8eab63a3.ts → Reactive-client-9bc3643675fc563f96efb00bc3c4b843ba4b7f2e.ts} +12 -22
  537. package/test/props/components/temp/Reactive-server-8a84d0fc1f375d91438d840ca9753e32d86366ac.ts +40 -0
  538. package/test/props/reactive.test.ts +2 -2
  539. package/test/replace/components/Replace.torp +3 -5
  540. package/test/replace/components/output/Replace-client.ts +10 -19
  541. package/test/replace/components/output/Replace-server.ts +11 -12
  542. package/test/replace/components/temp/{Replace-client-2a9ee3430708b469fa31bbc6989eed5b2f22984d.ts → Replace-client-6f21ff3eb303bd5488d211087dc35fcf998d4e2a.ts} +10 -19
  543. package/test/replace/components/temp/Replace-server-b536cf6d792ae73aaa7f5ea04cda6858a07479f9.ts +21 -0
  544. package/test/replace/replace.test.ts +2 -2
  545. package/test/script/script-with-comments.test.ts +14 -19
  546. package/test/script/script-with-strings.test.ts +14 -19
  547. package/test/script/script.test.ts +14 -19
  548. package/test/slots/basic-slot.test.ts +2 -2
  549. package/test/slots/components/Article.torp +3 -3
  550. package/test/slots/components/Basic.torp +1 -1
  551. package/test/slots/components/Header.torp +2 -2
  552. package/test/slots/components/Let.torp +3 -3
  553. package/test/slots/components/List.torp +1 -1
  554. package/test/slots/components/Named.torp +3 -3
  555. package/test/slots/components/Unused.torp +1 -1
  556. package/test/slots/components/output/Article-client.ts +4 -8
  557. package/test/slots/components/output/Article-server.ts +14 -15
  558. package/test/slots/components/output/Basic-client.ts +7 -14
  559. package/test/slots/components/output/Basic-server.ts +17 -18
  560. package/test/slots/components/output/Header-client.ts +4 -9
  561. package/test/slots/components/output/Header-server.ts +11 -12
  562. package/test/slots/components/output/Let-client.ts +7 -14
  563. package/test/slots/components/output/Let-server.ts +16 -17
  564. package/test/slots/components/output/List-client.ts +17 -16
  565. package/test/slots/components/output/List-server.ts +12 -13
  566. package/test/slots/components/output/Named-client.ts +9 -19
  567. package/test/slots/components/output/Named-server.ts +21 -23
  568. package/test/slots/components/output/Unused-client.ts +5 -10
  569. package/test/slots/components/output/Unused-server.ts +13 -13
  570. package/test/slots/components/temp/{Article-client-3f2da4b399f94ae8c329489e1ba0ba98196df9c5.ts → Article-client-0b674ee98ae7f85021bfb8b912f28e3c4b35e877.ts} +4 -8
  571. package/test/slots/components/temp/Article-server-3db1718b70b86b456514b54ae17a597d07cc0ca9.ts +27 -0
  572. package/test/slots/components/temp/{Basic-client-a2c4bf685d4b75d0395da427b7754c2a58374dd7.ts → Basic-client-196f7f0244dca0baeffb547eec55c089a108283d.ts} +7 -14
  573. package/test/slots/components/temp/Basic-server-a22e6ec236b84e09d4d59c7abc4f0b22bf60f22c.ts +32 -0
  574. package/test/slots/components/temp/{Header-client-d7418b71df5db36d58a73e909233863a6c03678b.ts → Header-client-e5c784d60469523803898ee4d8b85fb82a7b7c0b.ts} +4 -9
  575. package/test/slots/components/temp/Header-server-3182d735443d9cf6a0cc7891919cc2c08df2aa8f.ts +21 -0
  576. package/test/slots/components/temp/{Let-client-913f9dede92b68a3f4a13d1f56f99b3e08e01efe.ts → Let-client-645271fcd63cd500001c75740b22b1b387330657.ts} +7 -14
  577. package/test/slots/components/temp/Let-server-b6d6e2012155c7533a0eb4ee0aaf00157a7d4493.ts +35 -0
  578. package/test/slots/components/temp/{List-client-6bc2d267a8b2028a14b12b2c70feb7c6a47d6d64.ts → List-client-ee6047ac396dc0b6fce5e38af51c38093fae83a2.ts} +17 -16
  579. package/test/slots/components/temp/List-server-1ee246e864cdb31bb8f52cf4424b6ef0e9b41cf1.ts +25 -0
  580. package/test/slots/components/temp/{Named-client-f6e7a984759ce8f50bc52dcf56f6f06cab925a80.ts → Named-client-559988562c5de1ae6017d2ad6de063f4363064b6.ts} +9 -19
  581. package/test/slots/components/temp/Named-server-f2ce3d301e916ea38901a92185c25512b11d42d4.ts +41 -0
  582. package/test/slots/components/temp/{Unused-client-ea0a096aa7a1c958f3bf807f35340b96f8a025ee.ts → Unused-client-52d1828bd28ebf7046a2e948a369563c0ea83b98.ts} +5 -10
  583. package/test/slots/components/temp/Unused-server-f5248f5cd4616c65eaf27c67385f13ed671accad.ts +22 -0
  584. package/test/slots/let-slot.test.ts +4 -4
  585. package/test/slots/named-slot.test.ts +2 -2
  586. package/test/slots/unused-slot.test.ts +2 -2
  587. package/test/source-maps/components/Source.torp +19 -0
  588. package/test/source-maps/components/output/Source-client.ts +63 -0
  589. package/test/source-maps/components/output/Source-server.ts +26 -0
  590. package/test/source-maps/components/temp/Source-client-ae8c4811ff658c13ee8c9b9e0e53fff1b83b178b.ts +63 -0
  591. package/test/source-maps/components/temp/Source-server-70b20214c52b8820f450324943e8a1ffb0a72d5e.ts +26 -0
  592. package/test/source-maps/parse.test.ts +62 -0
  593. package/test/special-component/components/BigTitle.torp +1 -1
  594. package/test/special-component/components/Component.torp +2 -2
  595. package/test/special-component/components/SmallTitle.torp +1 -1
  596. package/test/special-component/components/output/BigTitle-client.ts +4 -8
  597. package/test/special-component/components/output/BigTitle-server.ts +10 -11
  598. package/test/special-component/components/output/Component-client.ts +7 -15
  599. package/test/special-component/components/output/Component-server.ts +19 -19
  600. package/test/special-component/components/output/SmallTitle-client.ts +4 -8
  601. package/test/special-component/components/output/SmallTitle-server.ts +10 -11
  602. package/test/special-component/components/temp/{BigTitle-client-c4bd66406d55ce83ab4491c4114d563055e1c275.ts → BigTitle-client-cb3055f809aaf17bd1fa82748d039ac3730a8d44.ts} +4 -8
  603. package/test/special-component/components/temp/BigTitle-server-fef9d1e1deacfde2be4469c2e63a801b2e518dff.ts +19 -0
  604. package/test/special-component/components/temp/{Component-client-c39c66cf5274445bb863fd759e0ef223613a9f3a.ts → Component-client-0eb9553b52acce2dfa564242295a4c57a38bd540.ts} +7 -15
  605. package/test/special-component/components/temp/Component-server-9d0fddeff790bfb2b6cfbcd2edf677837f5b8120.ts +43 -0
  606. package/test/special-component/components/temp/{SmallTitle-client-e4b3e51243ca4f1efca21ac0f957b81e8bc93167.ts → SmallTitle-client-5a65b233be29395e9650f57d9708a33de1279af3.ts} +4 -8
  607. package/test/special-component/components/temp/SmallTitle-server-11f8b6b3c613716d6a5371883a9b55434bb43ad5.ts +19 -0
  608. package/test/special-component/special-component.test.ts +2 -2
  609. package/test/special-element/components/Element.torp +2 -2
  610. package/test/special-element/components/output/Element-client.ts +5 -11
  611. package/test/special-element/components/output/Element-server.ts +9 -11
  612. package/test/special-element/components/temp/{Element-client-c5701ed44faa4ec8ae558505063684a84cada3f2.ts → Element-client-745e610fbd5c652d327c8ac349d49d5ee4c8d9ea.ts} +5 -11
  613. package/test/special-element/components/temp/Element-server-7aef6d0ed7369aa2418183519c8320e0409a5641.ts +15 -0
  614. package/test/special-element/special-element.test.ts +2 -2
  615. package/test/special-head/components/Head.torp +2 -6
  616. package/test/special-head/components/output/Head-client.ts +8 -27
  617. package/test/special-head/components/output/Head-server.ts +8 -13
  618. package/test/special-head/components/temp/Head-client-bbbb5e712247ee41ca65a7ffd457987de5e99b3e.ts +19 -0
  619. package/test/special-head/components/temp/Head-server-c3de2e6b56aabc095380370d8bf93ae3bc7c10d9.ts +12 -0
  620. package/test/special-head/special-head.test.ts +2 -2
  621. package/test/special-self/components/Self.torp +4 -6
  622. package/test/special-self/components/output/Self-client.ts +18 -23
  623. package/test/special-self/components/output/Self-server.ts +14 -14
  624. package/test/special-self/components/temp/{Self-client-43a0a90fac58867c88bf32221883e8da342a0295.ts → Self-client-dfe57df69e3677e94f7b5f3657c82602054ef19e.ts} +18 -23
  625. package/test/special-self/components/temp/Self-server-5d135dab2b6fd4ba7fe3f56768f0725607d36bd9.ts +27 -0
  626. package/test/special-self/special-self.test.ts +2 -2
  627. package/test/style/components/Style.torp +1 -1
  628. package/test/style/components/output/Style-client.ts +7 -13
  629. package/test/style/components/output/Style-server.ts +10 -12
  630. package/test/style/components/temp/{Style-client-bc13f8dbb5f754e4eebb2473fc63a139ebf1ba92.ts → Style-client-9491a5aff97f118df542f976d7f7a21e7cc88c62.ts} +7 -13
  631. package/test/style/components/temp/Style-server-8b8cbe1868cab30d9e34dda52921652768ada1db.ts +16 -0
  632. package/test/style/parse.test.ts +507 -193
  633. package/test/style/style.test.ts +2 -2
  634. package/test/svg/components/Shape.torp +1 -1
  635. package/test/svg/components/output/Shape-client.ts +23 -23
  636. package/test/svg/components/output/Shape-server.ts +12 -13
  637. package/test/svg/components/temp/{Shape-client-052ea7838de07222602834de58968a3f89e6ea56.ts → Shape-client-4cc148d8b70d3750d2982360aad76b74d194b60e.ts} +23 -23
  638. package/test/svg/components/temp/Shape-server-76aaef570e067031ff39635ffe37626364c2200a.ts +23 -0
  639. package/test/svg/svg.test.ts +4 -4
  640. package/test/switch/components/Switch.torp +16 -18
  641. package/test/switch/components/output/Switch-client.ts +22 -30
  642. package/test/switch/components/output/Switch-server.ts +12 -14
  643. package/test/switch/components/temp/{Switch-client-30113fadf131c72e7c24160fa62068b651716896.ts → Switch-client-5fc00f4d41300dc7587b113d8e53a102beca7558.ts} +22 -30
  644. package/test/switch/components/temp/Switch-server-440f7e852145b79656c0023ddc776e4d1d077d2a.ts +36 -0
  645. package/test/switch/switch-values.test.ts +4 -4
  646. package/test/template/basic-file.test.ts +61 -88
  647. package/test/template/empty-file.test.ts +7 -12
  648. package/test/template/errors.test.ts +64 -34
  649. package/test/text/components/Text.torp +5 -7
  650. package/test/text/components/output/Text-client.ts +9 -17
  651. package/test/text/components/output/Text-server.ts +8 -10
  652. package/test/text/components/temp/{Text-client-e335aae6d8aef389dfdbb5bee14e3dd3d41e86bd.ts → Text-client-6c3be8a1a31a13eff86ce8b5330829cd15b07fab.ts} +9 -17
  653. package/test/text/components/temp/Text-server-ac34d47e755aa39b2d89cb44f854450c3db1ddff.ts +22 -0
  654. package/test/text/text.test.ts +4 -4
  655. package/test/watch-array/ArrayState.ts +2 -2
  656. package/test/watch-array/array-all-functions-unkeyed.test.ts +16 -14
  657. package/test/watch-array/array-all-functions.test.ts +16 -14
  658. package/test/watch-array/array-empty.test.ts +8 -6
  659. package/test/watch-array/array-entries.test.ts +11 -9
  660. package/test/watch-array/array-indexes.test.ts +11 -9
  661. package/test/watch-array/array-pop.test.ts +10 -8
  662. package/test/watch-array/array-push.test.ts +10 -8
  663. package/test/watch-array/array-reassign.test.ts +11 -9
  664. package/test/watch-array/array-reverse.test.ts +10 -8
  665. package/test/watch-array/array-set-object.test.ts +10 -8
  666. package/test/watch-array/array-set-property.test.ts +10 -8
  667. package/test/watch-array/array-shift.test.ts +10 -8
  668. package/test/watch-array/array-sort.test.ts +11 -9
  669. package/test/watch-array/array-splice-add.test.ts +10 -8
  670. package/test/watch-array/array-splice-delete-all.test.ts +10 -8
  671. package/test/watch-array/array-splice-delete-and-add.test.ts +10 -8
  672. package/test/watch-array/array-splice-delete-end.test.ts +10 -8
  673. package/test/watch-array/array-splice-delete.test.ts +10 -8
  674. package/test/watch-array/array-swap.test.ts +10 -8
  675. package/test/watch-array/array-unshift.test.ts +10 -8
  676. package/test/watch-array/array-update-assignment.test.ts +10 -8
  677. package/test/watch-array/components/output/Array-client.ts +19 -21
  678. package/test/watch-array/components/output/Array-server.ts +11 -13
  679. package/test/watch-array/components/output/ArrayEntries-client.ts +21 -23
  680. package/test/watch-array/components/output/ArrayEntries-server.ts +11 -13
  681. package/test/watch-array/components/output/ArrayIndexes-client.ts +19 -21
  682. package/test/watch-array/components/output/ArrayIndexes-server.ts +11 -13
  683. package/test/watch-array/components/output/ArrayUnkeyed-client.ts +19 -20
  684. package/test/watch-array/components/output/ArrayUnkeyed-server.ts +11 -13
  685. package/test/watch-array/components/temp/{Array-client-d048f5c224a3f2e2729878dbb069ce15ca913e12.ts → Array-client-552f81452d33fe6dc715c9f6bb7986f06475d761.ts} +19 -21
  686. package/test/watch-array/components/temp/Array-server-16921ef3289ecba5881fcd59e3353fbfad60d4d3.ts +20 -0
  687. package/test/watch-array/components/temp/{ArrayEntries-client-741607b276718f5deb520e3b657dbf6abbb8081c.ts → ArrayEntries-client-736755fba2492e74812ff9c905202810de54e15a.ts} +21 -23
  688. package/test/watch-array/components/temp/ArrayEntries-server-ac150fc9fd18c1d9dab9b329f7703e190f5c2725.ts +20 -0
  689. package/test/watch-array/components/temp/{ArrayIndexes-client-8ab14b254ef67dafad5228c9ec1906eb3b3babef.ts → ArrayIndexes-client-a496328fa92ffca676ab8893013a0cfec1734ad1.ts} +19 -21
  690. package/test/watch-array/components/temp/ArrayIndexes-server-e8fc511c0d27796dc1733f8cc63377f7a4511f76.ts +20 -0
  691. package/test/watch-array/components/temp/{ArrayUnkeyed-client-9684aba82757748815b94c04bf3f8d1f98332535.ts → ArrayUnkeyed-client-5a2c5cb1fecba52653f7f35cfd07627682930c15.ts} +19 -20
  692. package/test/watch-array/components/temp/ArrayUnkeyed-server-916a5cdb7c36d95946cafdc69dca782291af24e4.ts +20 -0
  693. package/test/watch-object/components/Watched.torp +5 -7
  694. package/test/watch-object/components/output/Watched-client.ts +7 -13
  695. package/test/watch-object/components/output/Watched-server.ts +8 -10
  696. package/test/watch-object/components/temp/{Watched-client-d26e846bbeb8271ec5dc2a1ceb75b362af44d3bd.ts → Watched-client-1f0409aa6e2c425d0319a23caec7d10ad313d579.ts} +7 -13
  697. package/test/watch-object/components/temp/Watched-server-156afd257b562162d86417f2bbf5afe1bf57de06.ts +16 -0
  698. package/test/watch-object/watch-object.test.ts +11 -9
  699. package/{tsup.config.ts → tsdown.config.ts} +2 -4
  700. package/dist/Component-CysAnHpO.d.cts +0 -8
  701. package/dist/Component-CysAnHpO.d.ts +0 -8
  702. package/dist/ServerSlotRender-t1sOutne.d.cts +0 -15
  703. package/dist/ServerSlotRender-t1sOutne.d.ts +0 -15
  704. package/dist/chunk-EGRHWZRV.js +0 -1
  705. package/dist/chunk-EGRHWZRV.js.map +0 -1
  706. package/dist/chunk-T6JGCJ5T.js +0 -45
  707. package/dist/chunk-T6JGCJ5T.js.map +0 -1
  708. package/dist/compile.cjs +0 -4074
  709. package/dist/compile.cjs.map +0 -1
  710. package/dist/compile.d.cts +0 -156
  711. package/dist/index.cjs +0 -895
  712. package/dist/index.cjs.map +0 -1
  713. package/dist/index.d.cts +0 -208
  714. package/dist/metafile-cjs.json +0 -1
  715. package/dist/metafile-esm.json +0 -1
  716. package/dist/ssr.cjs +0 -106
  717. package/dist/ssr.cjs.map +0 -1
  718. package/dist/ssr.d.cts +0 -14
  719. package/src/compile/build/client/buildHeadNode.ts +0 -17
  720. package/src/compile/build/utils/isReactiveAttribute.ts +0 -16
  721. package/src/compile/types/nodes/isControlNode.ts +0 -6
  722. package/src/compile/types/nodes/isElementNode.ts +0 -6
  723. package/src/compile/types/nodes/isParentNode.ts +0 -6
  724. package/src/compile/types/nodes/isSpecialNode.ts +0 -6
  725. package/src/compile/types/nodes/isTextNode.ts +0 -6
  726. package/src/debug/printHtml.ts +0 -25
  727. package/src/render/getClasses.ts +0 -24
  728. package/src/render/getStyles.ts +0 -7
  729. package/src/render/isComment.ts +0 -3
  730. package/src/render/isText.ts +0 -3
  731. package/src/types/ProxyPropData.ts +0 -11
  732. package/src/watch/removeEffect.ts +0 -34
  733. package/test/attributes/components/temp/Attributes-server-80f9f58fd6cb30df11867386d4f0b15b44401ebe.ts +0 -18
  734. package/test/bench/components/temp/Bench-client-fca94b485c6263778751927240ab3ca4048d7a10.ts +0 -208
  735. package/test/bind/components/temp/BindComponent-client-6f650efb818a185ef33e1b071cfd77415a803dd3.ts +0 -93
  736. package/test/bind/components/temp/BindComponent-server-2e6caf0cbbb2831eb4bfbd7dcd6cf4d5c422d047.ts +0 -52
  737. package/test/bind/components/temp/BindText-server-807a1ddcb68410b30429cb088d2e204ed6f585b2.ts +0 -21
  738. package/test/child-component/components/temp/ParentChild-server-5e4a7fa5f4cd1c7dbe6866819025d2c03bfc62cb.ts +0 -39
  739. package/test/class/components/temp/Class-server-c24c01d0d3a98169172aba453c183c4152705be9.ts +0 -40
  740. package/test/component/components/temp/Component-server-57f59c74599572da6322a67cb97848cfbfcf6968.ts +0 -24
  741. package/test/component/components/temp/Header-server-6969d20782edd8f99d4b5c5b7b5563ce26e6dc2d.ts +0 -18
  742. package/test/console/components/temp/Console-server-cfb2208b130d5f15403df19ae8341aaa1c9ad33a.ts +0 -17
  743. package/test/const/components/temp/Const-server-1cf6ed84f72d3b15b318b80937b8de1f2c0f188c.ts +0 -20
  744. package/test/effects/components/temp/For-server-efe60939d185315f4c9b567b6867c6d5af14d9aa.ts +0 -22
  745. package/test/effects/components/temp/If-server-2424b7b812d350d7eb8ff9afb1146807217320cd.ts +0 -24
  746. package/test/effects/components/temp/NestedIf-server-ab260586490cb5afed31377d2226bb5a1fc30e2d.ts +0 -28
  747. package/test/events/components/temp/Increment-server-b084f43082e2ec31dbe5f9edc1cb6e37e4c8df9d.ts +0 -24
  748. package/test/for/components/temp/For-server-3b6ead39728c79206203c519a215390d07d80f7e.ts +0 -22
  749. package/test/for/components/temp/ForEscape-server-ed906c8cd593a0b467073ada415734de31dc38d9.ts +0 -24
  750. package/test/for/components/temp/ForIn-server-c8f13304a2ba235e091685256909fbfa50bdd5fd.ts +0 -22
  751. package/test/for/components/temp/ForOf-server-8c2c33ca6595bf0a5e952ca9971e595e18446623.ts +0 -22
  752. package/test/function/components/temp/Function-server-2b19d0cd881c31dc67132107c6e322a18701c318.ts +0 -27
  753. package/test/html/components/temp/Html-server-d159b0ef04b1f65ae4f9e05a7b44b21e7aa14cf9.ts +0 -17
  754. package/test/if/components/temp/IfAfterIf-server-a5005147e7902d1a5a048c9fe07feb9804eb6560.ts +0 -25
  755. package/test/if/components/temp/IfElse-server-80d93e5fc4ceba7a645f7081fa11b177dbe730d0.ts +0 -24
  756. package/test/if/components/temp/IfElseIf-server-ddc7348705d51b02538301e0aa704130748992cf.ts +0 -27
  757. package/test/if/components/temp/IfFalse-server-e8385013cfdde584b43cc0d71311cbb417859116.ts +0 -21
  758. package/test/if/components/temp/IfNested-server-285a5d8e0e0fcc8ccf421df152fdc00811782835.ts +0 -31
  759. package/test/mount/components/temp/Mount-server-62f94f276c2d6c9048765a77b575cb21146917f1.ts +0 -24
  760. package/test/on-mount/components/temp/OnMount-server-c531f718eb68754ea6c3001d5db9c07c511e434c.ts +0 -17
  761. package/test/party/components/temp/AnswerButton-server-928b5d447afa865fa09e0142c79bb1f2c1b86875.ts +0 -17
  762. package/test/party/components/temp/AnswerButtonApp-server-e4ea88e0f4d65508950594437e5e34424bd28897.ts +0 -38
  763. package/test/party/components/temp/ColorSelect-server-90f83722bd85155ebb2b8ccdaf053cd28d3152be.ts +0 -34
  764. package/test/party/components/temp/Colors-server-e13d49ba57f7b0dc6fb10a333ec872f5207e1ff0.ts +0 -23
  765. package/test/party/components/temp/Counter-server-7adf9376b38d97f1fd4b9c14108e6814e81f14ea.ts +0 -26
  766. package/test/party/components/temp/CssStyle-server-90a950501a20bfa5feac84ca6d97898c25bce2ed.ts +0 -17
  767. package/test/party/components/temp/DoubleCount-server-62c94483ebe9661e5ecc4f489787e32448ddcafa.ts +0 -25
  768. package/test/party/components/temp/FunnyButtonApp-server-80d85ede7da558154a5aa17cd602d6724bf1c9cb.ts +0 -36
  769. package/test/party/components/temp/HelloWorld-server-e0ed80e7531f303952a4af30d646263ff2e4ead6.ts +0 -17
  770. package/test/party/components/temp/InputFocused-server-ee70758a515227c04788be0e298a79c277994ccd.ts +0 -25
  771. package/test/party/components/temp/InputHello-server-1b9dd5442ded022abe92a9075ca5a4bb90486cbe.ts +0 -23
  772. package/test/party/components/temp/IsAvailable-server-123daa1ae56b77defe6666faddb44ba4252dd0fb.ts +0 -22
  773. package/test/party/components/temp/Name-server-a402418f1ca2d8a0e6403596ec03ec47b5ff40ec.ts +0 -22
  774. package/test/party/components/temp/NameUpdate-server-b7dcc875e894a5606544fcd78bda575ea07632ca.ts +0 -23
  775. package/test/party/components/temp/PageTitle-server-12dcb4e437aaef227c704a2ee8bbdee55ca323dc.ts +0 -27
  776. package/test/party/components/temp/PickPill-server-f10dae4708e36775a5e1a5ad10c6c0c309335009.ts +0 -23
  777. package/test/party/components/temp/TrafficLight-server-04bb3b2f11322ccc97a9a8a8fbb26c3c99843042.ts +0 -40
  778. package/test/party/components/temp/UserProfile-server-a0576b8d9dd15b3fab6c11758984c686ddfe2f66.ts +0 -23
  779. package/test/party/components/temp/UserProfileApp-server-86c204098fd0ffbeded50372354488768b255156.ts +0 -27
  780. package/test/party/components/temp/UserProfileContext-server-2d32476b00448bdec6c1c45aac5087a5152c2471.ts +0 -20
  781. package/test/party/components/temp/UserProfileContextApp-server-c970abaa8326db9a5efc3a5c64741743ae0dd1ca.ts +0 -33
  782. package/test/props/components/temp/Reactive-server-206bcc8984bad12c5712661b77d000216cdfe66d.ts +0 -40
  783. package/test/replace/components/temp/Replace-server-9519943d193b681e1d7894a0d7952affdfb0660c.ts +0 -22
  784. package/test/slots/components/temp/Article-server-b84141b05064f5ea1e4b535faafe459df0d875fb.ts +0 -28
  785. package/test/slots/components/temp/Basic-server-6b37594c9bf74e0c86a05b20213f69651e2cc937.ts +0 -33
  786. package/test/slots/components/temp/Header-server-d8e8ccb129d84478f0c4f8dc8ad1d2091188cc7b.ts +0 -22
  787. package/test/slots/components/temp/Let-server-8cad3b1199bec801bc3a1f2f3dbc20f2ef1e9741.ts +0 -36
  788. package/test/slots/components/temp/List-server-f4f63df4d19e15311da347284935a1bb530a8df4.ts +0 -26
  789. package/test/slots/components/temp/Named-server-2aac48bb8c7300d1a8858917fe81edc17c6372fa.ts +0 -43
  790. package/test/slots/components/temp/Unused-server-6e832928d7db6c43c556e7bda8af34ac37c0d4c1.ts +0 -22
  791. package/test/special-component/components/temp/BigTitle-server-d8919a4c975e022c936584bd668917cb89aa8e20.ts +0 -20
  792. package/test/special-component/components/temp/Component-server-14cd9beb57d6e833f75ab8c6624eb9841444ef63.ts +0 -43
  793. package/test/special-component/components/temp/SmallTitle-server-0a9b5098e4dda96f8c1da30294d71b39997dd118.ts +0 -20
  794. package/test/special-element/components/temp/Element-server-166d672256ef4635168de0090e490e48b569c7d6.ts +0 -17
  795. package/test/special-head/components/temp/Head-server-c0956653b544ff632e36da15d5f7623fa285953a.ts +0 -17
  796. package/test/special-self/components/temp/Self-server-b857c30c279a16dd81ad29567fb8abb9b2a0c239.ts +0 -27
  797. package/test/style/components/temp/Style-server-85720cb43e20ab000f98bc632c29454a51ae92d9.ts +0 -18
  798. package/test/svg/components/temp/Shape-server-9951ff1dcc7aa0827f28d3f8d970813767115ae3.ts +0 -24
  799. package/test/switch/components/temp/Switch-server-c1b5e1c657438ee3d8afdbf2166c5295cafc5604.ts +0 -38
  800. package/test/text/components/temp/Text-server-e37d33aa182f36461927d8ce36040bfd05e2f227.ts +0 -24
  801. package/test/watch-array/components/temp/Array-server-c907209008ac6177f614b62931a2bb1f1c3a04e1.ts +0 -22
  802. package/test/watch-array/components/temp/ArrayEntries-server-57c1ab0045fa4a02de95f69a65de6f54efe9850c.ts +0 -22
  803. package/test/watch-array/components/temp/ArrayIndexes-server-f093878b94a37617e2e697a786caa680f75630a7.ts +0 -22
  804. package/test/watch-array/components/temp/ArrayUnkeyed-server-c893fa024be07e5e7fce608c3ae456bdf2279dbe.ts +0 -22
  805. package/test/watch-object/components/temp/Watched-server-312fca1e769d7594fc5bb6295ccf55b544dd2f4d.ts +0 -18
  806. /package/src/compile/{build/utils → utils}/isFullyReactive.ts +0 -0
  807. /package/src/compile/{build/utils → utils}/isReactive.ts +0 -0
@@ -0,0 +1,2560 @@
1
+ // eslint-disable no-unused-expressions
2
+ import { afterEach, describe, expect, it, vi } from "vitest";
3
+ import $batch from "../src/render/$batch";
4
+ import $cache from "../src/render/$cache";
5
+ import $peek from "../src/render/$peek";
6
+ import $run from "../src/render/$run";
7
+ import $watch from "../src/render/$watch";
8
+ import context from "../src/render/context";
9
+
10
+ //import checkState from "./checkState";
11
+ //import printDiagram from "./printDiagram";
12
+ //import printSimpleDiagram from "./printSimpleDiagram";
13
+
14
+ /*
15
+ let si = 1;
16
+ dev.subName = () => `S${si++}`;
17
+ dev.effectName = (fn: Function) => {
18
+ let name = String(fn);
19
+ if (name.startsWith("function ")) {
20
+ name = name.substring(9);
21
+ }
22
+ name = name.substring(0, name.indexOf("() {"));
23
+ return name;
24
+ };
25
+ dev.propName = (key: PropertyKey) => String(key);
26
+ */
27
+ afterEach(() => {
28
+ //expect(context.activeTarget).toBe(null);
29
+ expect(context.batch, "POST TEST BATCH").toBe(0);
30
+ });
31
+
32
+ describe("signal", () => {
33
+ it("should return value", () => {
34
+ const v = [1, 2];
35
+ let $state = $watch({ s: v });
36
+ expect($state.s).toEqual(v);
37
+ });
38
+
39
+ // it("should inherit from Signal", () => {
40
+ // expect(signal(0)).to.be.instanceOf(Signal);
41
+ // });
42
+ //
43
+ // it("should support .toString()", () => {
44
+ // let $state = $watch({ s: 123 });
45
+ // expect(s.toString()).equal("123");
46
+ // });
47
+ //
48
+ // it("should support .toJSON()", () => {
49
+ // let $state = $watch({ s: 123 });
50
+ // expect(s.toJSON()).equal(123);
51
+ // });
52
+ //
53
+ // it("should support JSON.Stringify()", () => {
54
+ // let $state = $watch({ s: 123 });
55
+ // expect(JSON.stringify({ s })).equal(JSON.stringify({ s: 123 }));
56
+ // });
57
+ //
58
+ // it("should support .valueOf()", () => {
59
+ // let $state = $watch({ s: 123 });
60
+ // expect(s).to.have.property("valueOf");
61
+ // expect(s.valueOf).to.be.a("function");
62
+ // expect(s.valueOf()).equal(123);
63
+ // expect(+s).equal(123);
64
+ //
65
+ // let $state = $watch({ a: 1 });
66
+ // let $state = $watch({ b: 2 });
67
+ // // @ts-ignore-next-line
68
+ // expect(a + b).toEqual(3);
69
+ // });
70
+ //
71
+ // it("should notify other listeners of changes after one listener is disposed", () => {
72
+ // let $state = $watch({ s: 0 });
73
+ // let spy1 = vi.fn(() => {
74
+ // $state.s;
75
+ // });
76
+ // let spy2 = vi.fn(() => {
77
+ // $state.s;
78
+ // });
79
+ // let spy3 = vi.fn(() => {
80
+ // $state.s;
81
+ // });
82
+ //
83
+ // $run(spy1);
84
+ // const dispose = $run(spy2);
85
+ // $run(spy3);
86
+ //
87
+ // expect(spy1).toHaveBeenCalledOnce();
88
+ // expect(spy2).toHaveBeenCalledOnce();
89
+ // expect(spy3).toHaveBeenCalledOnce();
90
+ //
91
+ // dispose();
92
+ //
93
+ // $state.s = 1;
94
+ // expect(spy1).toHaveBeenCalledTimes(2);
95
+ // expect(spy2).toHaveBeenCalledOnce();
96
+ // expect(spy3).toHaveBeenCalledTimes(2);
97
+ // });
98
+
99
+ describe("$peek()", () => {
100
+ it("should get value", () => {
101
+ let $state = $watch({ s: 1 });
102
+ expect($peek(() => $state.s)).toEqual(1);
103
+ });
104
+
105
+ it("should get the updated value after a value change", () => {
106
+ let $state = $watch({ s: 1 });
107
+ $state.s = 2;
108
+ expect($peek(() => $state.s)).toEqual(2);
109
+ });
110
+
111
+ it("should not make surrounding effect depend on the signal", () => {
112
+ let $state = $watch({ s: 1 });
113
+ let spy = vi.fn(() => {
114
+ $peek(() => $state.s);
115
+ });
116
+
117
+ $run(spy);
118
+ expect(spy).toHaveBeenCalledOnce();
119
+ expect(spy).toHaveBeenCalledOnce();
120
+
121
+ $state.s = 2;
122
+ expect(spy).toHaveBeenCalledOnce();
123
+ });
124
+
125
+ it("should not make surrounding computed depend on the signal", () => {
126
+ let spy = vi.fn(() => {
127
+ $peek(() => $state.s);
128
+ });
129
+ let $state = $watch({
130
+ s: 1,
131
+ get d() {
132
+ return $cache(spy);
133
+ },
134
+ });
135
+
136
+ $state.d;
137
+ expect(spy).toHaveBeenCalledOnce();
138
+
139
+ $state.s = 2;
140
+ $state.d;
141
+ expect(spy).toHaveBeenCalledOnce();
142
+ });
143
+ });
144
+
145
+ describe("subscribe", () => {
146
+ it("should subscribe to a signal", () => {
147
+ let spy = vi.fn();
148
+ let $state = $watch({ a: 1 });
149
+
150
+ $run(() => {
151
+ spy($state.a);
152
+ });
153
+
154
+ expect(spy).toBeCalledWith(1);
155
+ });
156
+
157
+ it("should run the callback when the signal value changes", () => {
158
+ let spy = vi.fn();
159
+ let $state = $watch({ a: 1 });
160
+
161
+ $run(() => {
162
+ spy($state.a);
163
+ });
164
+
165
+ $state.a = 2;
166
+ expect(spy).toBeCalledWith(2);
167
+ });
168
+
169
+ // it("should unsubscribe from a signal", () => {
170
+ // let spy = vi.fn();
171
+ // let $state = $watch({ a: 1 });
172
+ //
173
+ // const dispose = a.subscribe(spy);
174
+ // dispose();
175
+ // spy.mockReset();
176
+ //
177
+ // $state.a = 2;
178
+ // expect(spy).not.toHaveBeenCalled();
179
+ // });
180
+
181
+ // it("should not start triggering on when a signal accessed in the callback changes", () => {
182
+ // let spy = vi.fn();
183
+ // let $state = $watch({ a: 0 });
184
+ // let $state = $watch({ b: 0 });
185
+ //
186
+ // a.subscribe(() => {
187
+ // $state.b;
188
+ // spy();
189
+ // });
190
+ // expect(spy).toHaveBeenCalledOnce();
191
+ // spy.mockReset();
192
+ //
193
+ // $state.b++;
194
+ // expect(spy).not.toHaveBeenCalled();
195
+ // });
196
+
197
+ it("should not cause surrounding effect to subscribe to changes to a signal accessed in the callback", () => {
198
+ let spy = vi.fn();
199
+ let $state = $watch({ a: 0, b: 0 });
200
+
201
+ $run(() => {
202
+ $state.a;
203
+ $run(() => {
204
+ $state.b;
205
+ });
206
+ spy();
207
+ });
208
+ expect(spy).toHaveBeenCalledOnce();
209
+ spy.mockReset();
210
+
211
+ $state.b++;
212
+ expect(spy).not.toHaveBeenCalled();
213
+ });
214
+ });
215
+
216
+ // describe(".(un)watched()", () => {
217
+ // it("should call watched when first subscription occurs", () => {
218
+ // const watched = vi.fn();
219
+ // const unwatched = vi.fn();
220
+ // let $state = $watch({ s: 1, { watched, unwatched } });
221
+ // expect(watched).not.toHaveBeenCalled();
222
+ // const unsubscribe = s.subscribe(() => {});
223
+ // expect(watched).toHaveBeenCalledOnce();
224
+ // const unsubscribe2 = s.subscribe(() => {});
225
+ // expect(watched).toHaveBeenCalledOnce();
226
+ // unsubscribe();
227
+ // unsubscribe2();
228
+ // expect(unwatched).toHaveBeenCalledOnce();
229
+ // });
230
+ //
231
+ // it("should allow updating the signal from watched", async () => {
232
+ // const calls: number[] = [];
233
+ // const watched = vi.fn(() => {
234
+ // setTimeout(() => {
235
+ // $state.s = 2;
236
+ // });
237
+ // });
238
+ // const unwatched = vi.fn();
239
+ // let $state = $watch({ s: 1, { watched, unwatched } });
240
+ // expect(watched).not.toHaveBeenCalled();
241
+ // const unsubscribe = s.subscribe(() => {
242
+ // calls.push(s.value);
243
+ // });
244
+ // expect(watched).toHaveBeenCalledOnce();
245
+ // const unsubscribe2 = s.subscribe(() => {});
246
+ // expect(watched).toHaveBeenCalledOnce();
247
+ // await new Promise((resolve) => setTimeout(resolve));
248
+ // unsubscribe();
249
+ // unsubscribe2();
250
+ // expect(unwatched).toHaveBeenCalledOnce();
251
+ // expect(calls).to.deep.equal([1, 2]);
252
+ // });
253
+ // });
254
+
255
+ // it("signals should be identified with a symbol", () => {
256
+ // let $state = $watch({ a: 0 });
257
+ // expect(a.brand).toEqual(Symbol.for("preact-signals"));
258
+ // });
259
+ //
260
+ // it("should be identified with a symbol", () => {
261
+ // const a = $derive(() => {});
262
+ // expect(a.brand).toEqual(Symbol.for("preact-signals"));
263
+ // });
264
+ });
265
+
266
+ describe("$run()", () => {
267
+ it("should run the callback immediately", () => {
268
+ let $state = $watch({ s: 123 });
269
+ let spy = vi.fn(() => {
270
+ $state.s;
271
+ });
272
+ $run(spy);
273
+ expect(spy).toHaveBeenCalled();
274
+ });
275
+
276
+ it("should subscribe to signals", () => {
277
+ let $state = $watch({ s: 123 });
278
+ let spy = vi.fn(() => {
279
+ $state.s;
280
+ });
281
+ $run(spy);
282
+ spy.mockReset();
283
+ $state.s = 42;
284
+ expect(spy).toHaveBeenCalled();
285
+ });
286
+
287
+ it("should subscribe to multiple signals", () => {
288
+ let $state = $watch({ a: "a", b: "b" });
289
+ let spy = vi.fn(() => {
290
+ $state.a;
291
+ $state.b;
292
+ });
293
+ $run(spy);
294
+ spy.mockReset();
295
+
296
+ $state.a = "aa";
297
+ $state.b = "bb";
298
+ expect(spy).toHaveBeenCalledTimes(2);
299
+ });
300
+
301
+ // it("should dispose of subscriptions", () => {
302
+ // let $state = $watch({ a: "a" });
303
+ // let $state = $watch({ b: "b" });
304
+ // let spy = vi.fn(() => {
305
+ // $state.a + " " + $state.b;
306
+ // });
307
+ // const dispose = $run(spy);
308
+ // spy.mockReset();
309
+ //
310
+ // dispose();
311
+ // expect(spy).not.toHaveBeenCalled();
312
+ //
313
+ // $state.a = "aa";
314
+ // $state.b = "bb";
315
+ // expect(spy).not.toHaveBeenCalled();
316
+ // });
317
+ //
318
+ // it("should dispose of subscriptions", () => {
319
+ // let $state = $watch({ a: "a" });
320
+ // let $state = $watch({ b: "b" });
321
+ // let spy = vi.fn(() => {
322
+ // $state.a + " " + $state.b;
323
+ // });
324
+ // $run(function () {
325
+ // spy();
326
+ // if ($state.a === "aa") {
327
+ // this.dispose();
328
+ // }
329
+ // });
330
+ //
331
+ // expect(spy).toHaveBeenCalled();
332
+ //
333
+ // $state.a = "aa";
334
+ // expect(spy).toHaveBeenCalledTimes(2);
335
+ //
336
+ // $state.a = "aaa";
337
+ // expect(spy).toHaveBeenCalledTimes(2);
338
+ // });
339
+ //
340
+ // it("should dispose of subscriptions immediately", () => {
341
+ // let $state = $watch({ a: "a" });
342
+ // let $state = $watch({ b: "b" });
343
+ // let spy = vi.fn(() => {
344
+ // $state.a + " " + $state.b;
345
+ // });
346
+ // $run(function () {
347
+ // spy();
348
+ // this.dispose();
349
+ // });
350
+ //
351
+ // expect(spy).toHaveBeenCalledOnce();
352
+ //
353
+ // $state.a = "aa";
354
+ // expect(spy).toHaveBeenCalledOnce();
355
+ //
356
+ // $state.a = "aaa";
357
+ // expect(spy).toHaveBeenCalledOnce();
358
+ // });
359
+ //
360
+ // it("should dispose of subscriptions when called twice", () => {
361
+ // let $state = $watch({ a: "a" });
362
+ // let $state = $watch({ b: "b" });
363
+ // let spy = vi.fn(() => {
364
+ // $state.a + " " + $state.b;
365
+ // });
366
+ // const dispose = $run(function () {
367
+ // spy();
368
+ // if ($state.a === "aa") {
369
+ // this.dispose();
370
+ // }
371
+ // });
372
+ //
373
+ // expect(spy).toHaveBeenCalled();
374
+ //
375
+ // $state.a = "aa";
376
+ // expect(spy).toHaveBeenCalledTimes(2);
377
+ // dispose();
378
+ //
379
+ // $state.a = "aaa";
380
+ // expect(spy).toHaveBeenCalledTimes(2);
381
+ // });
382
+ //
383
+ // it("should dispose of subscriptions immediately and signals are read after disposing", () => {
384
+ // let $state = $watch({ a: "a" });
385
+ // let $state = $watch({ b: "b" });
386
+ // let spy = vi.fn(() => {
387
+ // $state.a + " " + $state.b;
388
+ // });
389
+ // $run(function () {
390
+ // this.dispose();
391
+ // spy();
392
+ // });
393
+ //
394
+ // expect(spy).toHaveBeenCalledOnce();
395
+ //
396
+ // $state.a = "aa";
397
+ // expect(spy).toHaveBeenCalledOnce();
398
+ //
399
+ // $state.a = "aaa";
400
+ // expect(spy).toHaveBeenCalledOnce();
401
+ // });
402
+ //
403
+ // it("should dispose of subscriptions immediately when called twice (deferred)", () => {
404
+ // let $state = $watch({ a: "a" });
405
+ // let $state = $watch({ b: "b" });
406
+ // let spy = vi.fn(() => {
407
+ // $state.a + " " + $state.b;
408
+ // });
409
+ // const dispose = $run(function () {
410
+ // spy();
411
+ // this.dispose();
412
+ // });
413
+ //
414
+ // expect(spy).toHaveBeenCalledOnce();
415
+ //
416
+ // $state.a = "aa";
417
+ // expect(spy).toHaveBeenCalledOnce();
418
+ // dispose();
419
+ //
420
+ // $state.a = "aaa";
421
+ // expect(spy).toHaveBeenCalledOnce();
422
+ // });
423
+ //
424
+ // it("should unsubscribe from signal", () => {
425
+ // let $state = $watch({ s: 123 });
426
+ // let spy = vi.fn(() => {
427
+ // $state.s;
428
+ // });
429
+ // const unsub = $run(spy);
430
+ // spy.mockReset();
431
+ //
432
+ // unsub();
433
+ // $state.s = 42;
434
+ // expect(spy).not.toHaveBeenCalled();
435
+ // });
436
+
437
+ it("should conditionally unsubscribe from signals", () => {
438
+ let $state = $watch({ a: "a", b: "b", cond: true });
439
+
440
+ let spy = vi.fn(() => {
441
+ $state.cond ? $state.a : $state.b;
442
+ });
443
+
444
+ $run(spy);
445
+ expect(spy).toHaveBeenCalledOnce();
446
+
447
+ $state.b = "bb";
448
+ expect(spy).toHaveBeenCalledOnce();
449
+
450
+ $state.cond = false;
451
+ expect(spy).toHaveBeenCalledTimes(2);
452
+
453
+ spy.mockReset();
454
+
455
+ $state.a = "aaa";
456
+ expect(spy).not.toHaveBeenCalled();
457
+ });
458
+
459
+ it("should batch writes", () => {
460
+ let $state = $watch({ a: "a" });
461
+ let spy = vi.fn(() => {
462
+ $state.a;
463
+ });
464
+ $run(spy);
465
+ spy.mockReset();
466
+
467
+ $run(() => {
468
+ $state.a = "aa";
469
+ $state.a = "aaa";
470
+ });
471
+
472
+ expect(spy).toHaveBeenCalledOnce();
473
+ });
474
+
475
+ it("should call the cleanup callback before the next run", () => {
476
+ let $state = $watch({ a: 0 });
477
+ let spy = vi.fn();
478
+
479
+ $run(() => {
480
+ $state.a;
481
+ return spy;
482
+ });
483
+ expect(spy).not.toHaveBeenCalled();
484
+ $state.a = 1;
485
+ expect(spy).toHaveBeenCalledOnce();
486
+ $state.a = 2;
487
+ expect(spy).toHaveBeenCalledTimes(2);
488
+ });
489
+
490
+ it("should call only the callback from the previous run", () => {
491
+ let spy1 = vi.fn();
492
+ let spy2 = vi.fn();
493
+ let spy3 = vi.fn();
494
+ let $state = $watch({ a: spy1 });
495
+
496
+ $run(() => {
497
+ return $state.a;
498
+ });
499
+
500
+ expect(spy1).not.toHaveBeenCalled();
501
+ expect(spy2).not.toHaveBeenCalled();
502
+ expect(spy3).not.toHaveBeenCalled();
503
+
504
+ $state.a = spy2;
505
+ expect(spy1).toHaveBeenCalledOnce();
506
+ expect(spy2).not.toHaveBeenCalled();
507
+ expect(spy3).not.toHaveBeenCalled();
508
+
509
+ $state.a = spy3;
510
+ expect(spy1).toHaveBeenCalledOnce();
511
+ expect(spy2).toHaveBeenCalledOnce();
512
+ expect(spy3).not.toHaveBeenCalled();
513
+ });
514
+
515
+ // it("should call the cleanup callback function when disposed", () => {
516
+ // let spy = vi.fn();
517
+ //
518
+ // const dispose = $run(() => {
519
+ // return spy;
520
+ // });
521
+ // expect(spy).not.toHaveBeenCalled();
522
+ // dispose();
523
+ // expect(spy).toHaveBeenCalledOnce();
524
+ // });
525
+
526
+ it("should not recompute if the effect has been notified about changes, but no direct dependency has actually changed", () => {
527
+ let $state = $watch({
528
+ s: 0,
529
+ get c() {
530
+ return $cache(() => {
531
+ $state.s;
532
+ return 0;
533
+ });
534
+ },
535
+ });
536
+ let spy = vi.fn(() => {
537
+ $state.c;
538
+ });
539
+ $run(spy);
540
+ expect(spy).toHaveBeenCalledOnce();
541
+ spy.mockReset();
542
+
543
+ $state.s = 1;
544
+ expect(spy).not.toHaveBeenCalled();
545
+ });
546
+
547
+ it("should not recompute dependencies unnecessarily", () => {
548
+ let spy = vi.fn();
549
+ let $state = $watch({
550
+ a: 0,
551
+ b: 0,
552
+ get c() {
553
+ return $cache(() => {
554
+ spy();
555
+ return $state.b;
556
+ });
557
+ },
558
+ });
559
+ $run(() => {
560
+ if ($state.a === 0) {
561
+ $state.c;
562
+ }
563
+ });
564
+ expect(spy).toHaveBeenCalledOnce();
565
+
566
+ $batch(() => {
567
+ $state.b = 1;
568
+ $state.a = 1;
569
+ });
570
+ expect(spy).toHaveBeenCalledOnce();
571
+ });
572
+
573
+ it("should not recompute dependencies out of order", () => {
574
+ let spy = vi.fn();
575
+ let $state = $watch({
576
+ a: 1,
577
+ b: 1,
578
+ c: 1,
579
+ get d() {
580
+ return $cache(() => {
581
+ spy();
582
+ return $state.c;
583
+ });
584
+ },
585
+ });
586
+
587
+ $run(() => {
588
+ if ($state.a > 0) {
589
+ $state.b;
590
+ $state.d;
591
+ } else {
592
+ $state.b;
593
+ }
594
+ });
595
+ spy.mockReset();
596
+
597
+ $batch(() => {
598
+ $state.a = 2;
599
+ $state.b = 2;
600
+ $state.c = 2;
601
+ });
602
+ expect(spy).toHaveBeenCalledOnce();
603
+ spy.mockReset();
604
+
605
+ $batch(() => {
606
+ $state.a = -1;
607
+ $state.b = -1;
608
+ $state.c = -1;
609
+ });
610
+ expect(spy).not.toHaveBeenCalled();
611
+ spy.mockReset();
612
+ });
613
+
614
+ it("should recompute if a dependency changes during computation after becoming a dependency", () => {
615
+ let $state = $watch({ a: 0 });
616
+ let spy = vi.fn(() => {
617
+ if ($state.a === 0) {
618
+ $state.a++;
619
+ }
620
+ });
621
+ $run(spy);
622
+ expect(spy).toHaveBeenCalledTimes(2);
623
+ });
624
+
625
+ it("should run the cleanup in an implicit batch", () => {
626
+ let $state = $watch({ a: 0, b: "a", c: "b" });
627
+ let spy = vi.fn();
628
+
629
+ $run(() => {
630
+ $state.b;
631
+ $state.c;
632
+ spy($state.b + $state.c);
633
+ });
634
+
635
+ $run(() => {
636
+ $state.a;
637
+ return () => {
638
+ $state.b = "x";
639
+ $state.c = "y";
640
+ };
641
+ });
642
+
643
+ expect(spy).toHaveBeenCalledOnce();
644
+ spy.mockReset();
645
+
646
+ $state.a = 1;
647
+ expect(spy).toHaveBeenCalledOnce();
648
+ expect(spy).toBeCalledWith("xy");
649
+ });
650
+
651
+ it("should not retrigger the effect if the cleanup modifies one of the dependencies", () => {
652
+ let $state = $watch({ a: 0 });
653
+ let spy = vi.fn();
654
+
655
+ $run(() => {
656
+ spy($state.a);
657
+ return () => {
658
+ $state.a = 2;
659
+ };
660
+ });
661
+ expect(spy).toHaveBeenCalledOnce();
662
+ spy.mockReset();
663
+
664
+ $state.a = 1;
665
+ expect(spy).toHaveBeenCalledOnce();
666
+ expect(spy).toBeCalledWith(2);
667
+ });
668
+
669
+ // it("should run the cleanup if the effect disposes itself", () => {
670
+ // let $state = $watch({ a: 0 });
671
+ // let spy = vi.fn();
672
+ //
673
+ // const dispose = $run(() => {
674
+ // if ($state.a > 0) {
675
+ // dispose();
676
+ // return spy;
677
+ // }
678
+ // });
679
+ // expect(spy).not.toHaveBeenCalled();
680
+ // $state.a = 1;
681
+ // expect(spy).toHaveBeenCalledOnce();
682
+ // $state.a = 2;
683
+ // expect(spy).toHaveBeenCalledOnce();
684
+ // });
685
+ //
686
+ // it("should not run the effect if the cleanup function disposes it", () => {
687
+ // let $state = $watch({ a: 0 });
688
+ // let spy = vi.fn();
689
+ //
690
+ // const dispose = $run(() => {
691
+ // $state.a;
692
+ // spy();
693
+ // return () => {
694
+ // dispose();
695
+ // };
696
+ // });
697
+ // expect(spy).toHaveBeenCalledOnce();
698
+ // $state.a = 1;
699
+ // expect(spy).toHaveBeenCalledOnce();
700
+ // });
701
+
702
+ it("should not subscribe to anything if first run throws", () => {
703
+ let $state = $watch({ s: 0 });
704
+ let spy = vi.fn(() => {
705
+ $state.s;
706
+ throw new Error("test");
707
+ });
708
+ expect(() => $run(spy)).toThrow("test");
709
+ expect(spy).toHaveBeenCalledOnce();
710
+
711
+ $state.s++;
712
+ expect(spy).toHaveBeenCalledOnce();
713
+ });
714
+
715
+ it("should reset the cleanup if the effect throws", () => {
716
+ let $state = $watch({ a: 0 });
717
+ let spy = vi.fn();
718
+
719
+ $run(() => {
720
+ if ($state.a === 0) {
721
+ return spy;
722
+ } else {
723
+ throw new Error("hello");
724
+ }
725
+ });
726
+ expect(spy).not.toHaveBeenCalled();
727
+ expect(() => ($state.a = 1)).toThrow("hello");
728
+ expect(spy).toHaveBeenCalledOnce();
729
+ $state.a = 0;
730
+ expect(spy).toHaveBeenCalledOnce();
731
+ });
732
+
733
+ it("should dispose the effect if the cleanup callback throws", () => {
734
+ let $state = $watch({ a: 0 });
735
+ let spy = vi.fn();
736
+
737
+ $run(() => {
738
+ if ($state.a === 0) {
739
+ return () => {
740
+ throw new Error("hello");
741
+ };
742
+ } else {
743
+ spy();
744
+ }
745
+ });
746
+ expect(spy).not.toHaveBeenCalled();
747
+ expect(() => $state.a++).toThrow("hello");
748
+ expect(spy).not.toHaveBeenCalled();
749
+ $state.a++;
750
+ expect(spy).not.toHaveBeenCalled();
751
+ });
752
+
753
+ it("should run cleanups outside any evaluation context", () => {
754
+ let spy = vi.fn();
755
+ let $state = $watch({
756
+ a: 0,
757
+ b: 0,
758
+ get c() {
759
+ return $cache(() => {
760
+ if ($state.a === 0) {
761
+ $run(() => {
762
+ return () => {
763
+ $state.b;
764
+ };
765
+ });
766
+ }
767
+ return $state.a;
768
+ });
769
+ },
770
+ });
771
+
772
+ $run(() => {
773
+ spy();
774
+ $state.c;
775
+ });
776
+ expect(spy).toHaveBeenCalledOnce();
777
+ spy.mockReset();
778
+
779
+ $state.a = 1;
780
+ expect(spy).toHaveBeenCalledOnce();
781
+ spy.mockReset();
782
+
783
+ $state.b = 1;
784
+ expect(spy).not.toHaveBeenCalled();
785
+ });
786
+
787
+ // NOTE: I don't think we can cycle in effects, because we don't add already
788
+ // running effects to the batch
789
+
790
+ it.skip("should throw on cycles", () => {
791
+ let $state = $watch({ a: 0 });
792
+ let i = 0;
793
+
794
+ const fn = () =>
795
+ $run(() => {
796
+ // Prevent test suite from spinning if limit is not hit
797
+ if (i++ > 200) {
798
+ throw new Error("test failed");
799
+ }
800
+ $state.a;
801
+ $state.a = NaN;
802
+ });
803
+
804
+ expect(fn).toThrow("Cycle detected");
805
+ });
806
+
807
+ it.skip("should throw on indirect cycles", () => {
808
+ let $state = $watch({
809
+ a: 0,
810
+ get c() {
811
+ return $cache(() => {
812
+ $state.a;
813
+ $state.a = NaN;
814
+ return NaN;
815
+ });
816
+ },
817
+ });
818
+
819
+ let i = 0;
820
+ const fn = () =>
821
+ $run(() => {
822
+ // Prevent test suite from spinning if limit is not hit
823
+ if (i++ > 200) {
824
+ throw new Error("test failed");
825
+ }
826
+ $state.c;
827
+ });
828
+
829
+ expect(fn).toThrow("Cycle detected");
830
+ });
831
+
832
+ // it("should allow disposing the effect multiple times", () => {
833
+ // const dispose = $run(() => undefined);
834
+ // dispose();
835
+ // expect(() => dispose()).not.toThrow();
836
+ // });
837
+ //
838
+ // it("should support resource management disposal", () => {
839
+ // //let $state = $watch({ a: 0 });
840
+ // //let spy = vi.fn();
841
+ // //{
842
+ // // // @ts-expect-error This is a test for the dispose API
843
+ // // using _dispose = $run(() => {
844
+ // // $state.a;
845
+ // // return spy;
846
+ // // });
847
+ // //}
848
+ // //expect(spy).toHaveBeenCalledOnce();
849
+ // });
850
+ //
851
+ // it("should allow disposing a running effect", () => {
852
+ // let $state = $watch({ a: 0 });
853
+ // let spy = vi.fn();
854
+ // const dispose = $run(() => {
855
+ // if ($state.a === 1) {
856
+ // dispose();
857
+ // spy();
858
+ // }
859
+ // });
860
+ // expect(spy).not.toHaveBeenCalled();
861
+ // $state.a = 1;
862
+ // expect(spy).toHaveBeenCalledOnce();
863
+ // $state.a = 2;
864
+ // expect(spy).toHaveBeenCalledOnce();
865
+ // });
866
+ //
867
+ // it("should not run if it's first been triggered and then disposed in a batch", () => {
868
+ // let $state = $watch({ a: 0 });
869
+ // let spy = vi.fn(() => {
870
+ // $state.a;
871
+ // });
872
+ // const dispose = $run(spy);
873
+ // spy.mockReset();
874
+ //
875
+ // $batch(() => {
876
+ // $state.a = 1;
877
+ // dispose();
878
+ // });
879
+ //
880
+ // expect(spy).not.toHaveBeenCalled();
881
+ // });
882
+ //
883
+ // it("should not run if it's been triggered, disposed and then triggered again in a batch", () => {
884
+ // let $state = $watch({ a: 0 });
885
+ // let spy = vi.fn(() => {
886
+ // $state.a;
887
+ // });
888
+ // const dispose = $run(spy);
889
+ // spy.mockReset();
890
+ //
891
+ // $batch(() => {
892
+ // $state.a = 1;
893
+ // dispose();
894
+ // $state.a = 2;
895
+ // });
896
+ //
897
+ // expect(spy).not.toHaveBeenCalled();
898
+ // });
899
+
900
+ it("should not rerun parent effect if a nested child effect's signal's value changes", () => {
901
+ let $state = $watch({
902
+ parentSignal: 0,
903
+ childSignal: 0,
904
+ independentSignal: 0,
905
+ });
906
+
907
+ const parent$run = vi.fn(() => {
908
+ $state.parentSignal;
909
+ });
910
+ const child$run = vi.fn(() => {
911
+ $state.childSignal;
912
+ //return () => console.log("CLEANUP CHILD");
913
+ });
914
+ const independent$run = vi.fn(() => {
915
+ $state.independentSignal;
916
+ //return () => console.log("CLEANUP INDEPENDENT");
917
+ });
918
+
919
+ $run(
920
+ () => {
921
+ parent$run();
922
+ $run(child$run /*, { name: "CHILD $run" }*/);
923
+ $run(independent$run /*, { name: "INDEPENDENT $run" }*/);
924
+ //return () => console.log("CLEANUP PARENT");
925
+ } /*,
926
+ { name: "PARENT $run" },*/,
927
+ );
928
+
929
+ expect(parent$run).toHaveBeenCalledOnce();
930
+ expect(child$run).toHaveBeenCalledOnce();
931
+ expect(independent$run).toHaveBeenCalledOnce();
932
+
933
+ //console.log("===\nSETTING CHILD SIGNAL");
934
+ $state.childSignal = 1;
935
+
936
+ expect(parent$run).toHaveBeenCalledOnce();
937
+ expect(child$run).toHaveBeenCalledTimes(2);
938
+ expect(independent$run).toHaveBeenCalledOnce();
939
+
940
+ //console.log("===\nSETTING PARENT SIGNAL");
941
+ $state.parentSignal = 1;
942
+
943
+ expect(parent$run).toHaveBeenCalledTimes(2);
944
+ expect(child$run).toHaveBeenCalledTimes(3);
945
+ expect(independent$run).toHaveBeenCalledTimes(2);
946
+ });
947
+
948
+ // // Test internal behavior depended on by Preact & React integrations
949
+ // describe("internals", () => {
950
+ // it("should pass in the effect instance in callback's `this`", () => {
951
+ // let e: any;
952
+ // $run(function (this: any) {
953
+ // e = this;
954
+ // });
955
+ // expect(typeof e._start).toEqual("function");
956
+ // expect(typeof e._dispose).toEqual("function");
957
+ // });
958
+ //
959
+ // it("should allow setting _callback that replaces the default functionality", () => {
960
+ // let $state = $watch({ a: 0 });
961
+ // const oldSpy = vi.fn();
962
+ // const newSpy = vi.fn();
963
+ //
964
+ // let e: any;
965
+ // $run(function (this: any) {
966
+ // e = this;
967
+ // $state.a;
968
+ // oldSpy();
969
+ // });
970
+ // oldSpy.mockReset();
971
+ //
972
+ // e._callback = newSpy;
973
+ // $state.a = 1;
974
+ //
975
+ // expect(oldSpy).not.toHaveBeenCalled();
976
+ // expect(newSpy).toHaveBeenCalled();
977
+ // });
978
+ //
979
+ // it("should return a function for closing the effect scope from _start", () => {
980
+ // let $state = $watch({ s: 0 });
981
+ //
982
+ // let e: any;
983
+ // $run(function (this: any) {
984
+ // e = this;
985
+ // });
986
+ //
987
+ // let spy = vi.fn();
988
+ // e._callback = spy;
989
+ //
990
+ // const done1 = e._start();
991
+ // $state.s;
992
+ // done1();
993
+ // expect(spy).not.toHaveBeenCalled();
994
+ //
995
+ // $state.s = 2;
996
+ // expect(spy).toHaveBeenCalled();
997
+ // spy.mockReset();
998
+ //
999
+ // const done2 = e._start();
1000
+ // done2();
1001
+ //
1002
+ // $state.s = 3;
1003
+ // expect(spy).not.toHaveBeenCalled();
1004
+ // });
1005
+ //
1006
+ // it("should throw on out-of-order start1-start2-end1 sequences", () => {
1007
+ // let e1: any;
1008
+ // $run(function (this: any) {
1009
+ // e1 = this;
1010
+ // });
1011
+ //
1012
+ // let e2: any;
1013
+ // $run(function (this: any) {
1014
+ // e2 = this;
1015
+ // });
1016
+ //
1017
+ // const done1 = e1._start();
1018
+ // const done2 = e2._start();
1019
+ // try {
1020
+ // expect(() => done1()).toThrow(/Out-of-order/);
1021
+ // } finally {
1022
+ // done2();
1023
+ // done1();
1024
+ // }
1025
+ // });
1026
+ //
1027
+ // it("should throw a cycle detection error when _start is called while the effect is running", () => {
1028
+ // let e: any;
1029
+ // $run(function (this: any) {
1030
+ // e = this;
1031
+ // });
1032
+ //
1033
+ // const done = e._start();
1034
+ // try {
1035
+ // expect(() => e._start()).toThrow("Cycle detected");
1036
+ // } finally {
1037
+ // done();
1038
+ // }
1039
+ // });
1040
+ //
1041
+ // it("should dispose the effect on _dispose", () => {
1042
+ // let $state = $watch({ s: 0 });
1043
+ //
1044
+ // let e: any;
1045
+ // $run(function (this: any) {
1046
+ // e = this;
1047
+ // });
1048
+ //
1049
+ // let spy = vi.fn();
1050
+ // e._callback = spy;
1051
+ //
1052
+ // const done = e._start();
1053
+ // try {
1054
+ // $state.s;
1055
+ // } finally {
1056
+ // done();
1057
+ // }
1058
+ // expect(spy).not.toHaveBeenCalled();
1059
+ //
1060
+ // $state.s = 2;
1061
+ // expect(spy).toHaveBeenCalled();
1062
+ // spy.mockReset();
1063
+ //
1064
+ // e._dispose();
1065
+ // $state.s = 3;
1066
+ // expect(spy).not.toHaveBeenCalled();
1067
+ // });
1068
+ //
1069
+ // it("should allow reusing the effect after disposing it", () => {
1070
+ // let $state = $watch({ s: 0 });
1071
+ //
1072
+ // let e: any;
1073
+ // $run(function (this: any) {
1074
+ // e = this;
1075
+ // });
1076
+ //
1077
+ // let spy = vi.fn();
1078
+ // e._callback = spy;
1079
+ // e._dispose();
1080
+ //
1081
+ // const done = e._start();
1082
+ // try {
1083
+ // $state.s;
1084
+ // } finally {
1085
+ // done();
1086
+ // }
1087
+ // $state.s = 2;
1088
+ // expect(spy).toHaveBeenCalled();
1089
+ // });
1090
+ //
1091
+ // it("should have property _sources that is undefined when and only when the effect has no sources", () => {
1092
+ // let $state = $watch({ s: 0 });
1093
+ //
1094
+ // let e: any;
1095
+ // $run(function (this: any) {
1096
+ // e = this;
1097
+ // });
1098
+ // expect(e._sources).toBeUndefined();
1099
+ //
1100
+ // const done1 = e._start();
1101
+ // try {
1102
+ // $state.s;
1103
+ // } finally {
1104
+ // done1();
1105
+ // }
1106
+ // expect(e._sources).not.toBeUndefined();
1107
+ //
1108
+ // const done2 = e._start();
1109
+ // done2();
1110
+ // expect(e._sources).toBeUndefined();
1111
+ //
1112
+ // const done3 = e._start();
1113
+ // try {
1114
+ // $state.s;
1115
+ // } finally {
1116
+ // done3();
1117
+ // }
1118
+ // expect(e._sources).not.toBeUndefined();
1119
+ //
1120
+ // e._dispose();
1121
+ // expect(e._sources).toBeUndefined();
1122
+ // });
1123
+ // });
1124
+ });
1125
+
1126
+ describe("$derive()", () => {
1127
+ it("should return value", () => {
1128
+ let $state = $watch({
1129
+ a: "a",
1130
+ b: "b",
1131
+ get c() {
1132
+ return $cache(() => $state.a + $state.b);
1133
+ },
1134
+ });
1135
+
1136
+ expect($state.c).toEqual("ab");
1137
+ });
1138
+
1139
+ // it("should inherit from Signal", () => {
1140
+ // expect($derive(() => 0)).to.be.instanceOf(Signal);
1141
+ // });
1142
+
1143
+ it("should return updated value", () => {
1144
+ let $state = $watch({
1145
+ a: "a",
1146
+ b: "b",
1147
+ get c() {
1148
+ return $cache(() => $state.a + $state.b);
1149
+ },
1150
+ });
1151
+ expect($state.c).toEqual("ab");
1152
+
1153
+ $state.a = "aa";
1154
+ expect($state.c).toEqual("aab");
1155
+ });
1156
+
1157
+ it("should be lazily computed on demand", () => {
1158
+ let spy = vi.fn(() => $state.a + $state.b);
1159
+ let $state = $watch({
1160
+ a: "a",
1161
+ b: "b",
1162
+ get c() {
1163
+ return $cache(spy);
1164
+ },
1165
+ });
1166
+ expect(spy).not.toHaveBeenCalled();
1167
+ $state.c;
1168
+ expect(spy).toHaveBeenCalledOnce();
1169
+ $state.a = "x";
1170
+ $state.b = "y";
1171
+ expect(spy).toHaveBeenCalledOnce();
1172
+ $state.c;
1173
+ expect(spy).toHaveBeenCalledTimes(2);
1174
+ });
1175
+
1176
+ it("should be computed only when a dependency has changed at some point", () => {
1177
+ let spy = vi.fn(() => {
1178
+ return $state.a;
1179
+ });
1180
+ let $state = $watch({
1181
+ a: "a",
1182
+ get c() {
1183
+ return $cache(spy);
1184
+ },
1185
+ });
1186
+ $state.c;
1187
+ expect(spy).toHaveBeenCalledOnce();
1188
+ $state.a = "a";
1189
+ $state.c;
1190
+ expect(spy).toHaveBeenCalledOnce();
1191
+ });
1192
+
1193
+ it("should recompute if a dependency changes during computation after becoming a dependency", () => {
1194
+ let spy = vi.fn(() => {
1195
+ $state.a++;
1196
+ });
1197
+ let $state = $watch({
1198
+ a: 0,
1199
+ get c() {
1200
+ return $cache(spy);
1201
+ },
1202
+ });
1203
+ $state.c;
1204
+ expect(spy).toHaveBeenCalledOnce();
1205
+ $state.c;
1206
+ expect(spy).toHaveBeenCalledTimes(2);
1207
+ });
1208
+
1209
+ it("should detect simple dependency cycles", () => {
1210
+ const $state = $watch({
1211
+ get a(): any {
1212
+ return $cache(() => $state.a);
1213
+ },
1214
+ });
1215
+ expect(() => $state.a).toThrow("Cycle detected");
1216
+ });
1217
+
1218
+ it("should detect deep dependency cycles", () => {
1219
+ const $state = $watch({
1220
+ get a(): any {
1221
+ return $cache(() => $state.b);
1222
+ },
1223
+ get b() {
1224
+ return $cache(() => $state.c);
1225
+ },
1226
+ get c() {
1227
+ return $cache(() => $state.d);
1228
+ },
1229
+ get d() {
1230
+ return $cache(() => $state.a);
1231
+ },
1232
+ });
1233
+ expect(() => $state.a).toThrow("Cycle detected");
1234
+ });
1235
+
1236
+ // it("should not allow a computed signal to become a direct dependency of itself", () => {
1237
+ // let spy = vi.fn(() => {
1238
+ // try {
1239
+ // $state.a;
1240
+ // } catch {
1241
+ // // pass
1242
+ // }
1243
+ // });
1244
+ // const a = $derive(spy);
1245
+ // $state.a;
1246
+ // expect(() => $run(() => $state.a)).to.not.throw();
1247
+ // });
1248
+
1249
+ it("should store thrown errors and recompute only after a dependency changes", () => {
1250
+ let spy = vi.fn(() => {
1251
+ $state.a;
1252
+ throw new Error();
1253
+ });
1254
+ let $state = $watch({
1255
+ a: 0,
1256
+ get c() {
1257
+ return $cache(spy);
1258
+ },
1259
+ });
1260
+ expect(() => $state.c).toThrow();
1261
+ expect(() => $state.c).toThrow();
1262
+ expect(spy).toHaveBeenCalledOnce();
1263
+ $state.a = 1;
1264
+ expect(() => $state.c).toThrow();
1265
+ expect(spy).toHaveBeenCalledTimes(2);
1266
+ });
1267
+
1268
+ it("should store thrown non-errors and recompute only after a dependency changes", () => {
1269
+ let spy = vi.fn();
1270
+ let $state = $watch({
1271
+ a: 0,
1272
+ get c() {
1273
+ return $cache(() => {
1274
+ $state.a;
1275
+ spy();
1276
+ throw undefined;
1277
+ });
1278
+ },
1279
+ });
1280
+ try {
1281
+ $state.c;
1282
+ expect.fail();
1283
+ } catch (err) {
1284
+ expect(err).toBeUndefined();
1285
+ }
1286
+ try {
1287
+ $state.c;
1288
+ expect.fail();
1289
+ } catch (err) {
1290
+ expect(err).toBeUndefined();
1291
+ }
1292
+ expect(spy).toHaveBeenCalledOnce();
1293
+
1294
+ $state.a = 1;
1295
+ try {
1296
+ $state.c;
1297
+ expect.fail();
1298
+ } catch (err) {
1299
+ expect(err).toBeUndefined();
1300
+ }
1301
+ expect(spy).toHaveBeenCalledTimes(2);
1302
+ });
1303
+
1304
+ it("should conditionally unsubscribe from signals", () => {
1305
+ let spy = vi.fn(() => {
1306
+ return $state.cond ? $state.a : $state.b;
1307
+ });
1308
+
1309
+ let $state = $watch({
1310
+ a: "a",
1311
+ b: "b",
1312
+ cond: true,
1313
+ get c() {
1314
+ return $cache(spy);
1315
+ },
1316
+ });
1317
+
1318
+ expect($state.c).toEqual("a");
1319
+ expect(spy).toHaveBeenCalledOnce();
1320
+
1321
+ $state.b = "bb";
1322
+ expect($state.c).toEqual("a");
1323
+ expect(spy).toHaveBeenCalledOnce();
1324
+
1325
+ $state.cond = false;
1326
+ expect($state.c).toEqual("bb");
1327
+ expect(spy).toHaveBeenCalledTimes(2);
1328
+
1329
+ spy.mockReset();
1330
+
1331
+ $state.a = "aaa";
1332
+ expect($state.c).toEqual("bb");
1333
+ expect(spy).not.toHaveBeenCalled();
1334
+ });
1335
+
1336
+ // describe(".(un)watched()", () => {
1337
+ // it("should call watched when first subscription occurs", () => {
1338
+ // const watched = vi.fn();
1339
+ // const unwatched = vi.fn();
1340
+ // const s = $derive(() => 1, { watched, unwatched });
1341
+ // expect(watched).not.toHaveBeenCalled();
1342
+ // const unsubscribe = s.subscribe(() => {});
1343
+ // expect(watched).toHaveBeenCalledOnce();
1344
+ // const unsubscribe2 = s.subscribe(() => {});
1345
+ // expect(watched).toHaveBeenCalledOnce();
1346
+ // unsubscribe();
1347
+ // unsubscribe2();
1348
+ // expect(unwatched).toHaveBeenCalledOnce();
1349
+ // });
1350
+ //
1351
+ // it("should call watched when first subscription occurs w/ nested signal", () => {
1352
+ // const watched = vi.fn();
1353
+ // const unwatched = vi.fn();
1354
+ // let $state = $watch({ s: 1, { watched, unwatched } });
1355
+ // const c = $derive(() => s.value + 1, { watched, unwatched });
1356
+ // expect(watched).not.toHaveBeenCalled();
1357
+ // const unsubscribe = c.subscribe(() => {});
1358
+ // expect(watched).toHaveBeenCalledTimes(2);
1359
+ // const unsubscribe2 = s.subscribe(() => {});
1360
+ // expect(watched).toHaveBeenCalledTimes(2);
1361
+ // unsubscribe2();
1362
+ // unsubscribe();
1363
+ // expect(unwatched).toHaveBeenCalledTimes(2);
1364
+ // });
1365
+ // });
1366
+
1367
+ it("should consider undefined value separate from uninitialized value", () => {
1368
+ let spy = vi.fn(() => undefined);
1369
+ let $state = $watch({
1370
+ a: 0,
1371
+ get c() {
1372
+ return $cache(spy);
1373
+ },
1374
+ });
1375
+
1376
+ expect($state.c).toBeUndefined();
1377
+ $state.a = 1;
1378
+ expect($state.c).toBeUndefined();
1379
+ expect(spy).toHaveBeenCalledOnce();
1380
+ });
1381
+
1382
+ it("should not leak errors raised by dependencies", () => {
1383
+ let $state = $watch({
1384
+ a: 0,
1385
+ get b() {
1386
+ return $cache(() => {
1387
+ $state.a;
1388
+ throw new Error("error");
1389
+ });
1390
+ },
1391
+ get c() {
1392
+ return $cache(() => {
1393
+ try {
1394
+ return $state.b;
1395
+ } catch {
1396
+ return "ok";
1397
+ }
1398
+ });
1399
+ },
1400
+ });
1401
+ expect($state.c).toEqual("ok");
1402
+ $state.a = 1;
1403
+ expect($state.c).toEqual("ok");
1404
+ });
1405
+
1406
+ it("should propagate notifications even right after first subscription", () => {
1407
+ let $state = $watch({
1408
+ a: 0,
1409
+ get b() {
1410
+ return $cache(() => $state.a);
1411
+ },
1412
+ get c() {
1413
+ return $cache(() => $state.b);
1414
+ },
1415
+ });
1416
+ $state.c;
1417
+
1418
+ let spy = vi.fn(() => {
1419
+ $state.c;
1420
+ });
1421
+
1422
+ $run(spy);
1423
+ expect(spy).toHaveBeenCalledOnce();
1424
+ spy.mockReset();
1425
+
1426
+ $state.a = 1;
1427
+ expect(spy).toHaveBeenCalledOnce();
1428
+ });
1429
+
1430
+ it("should get marked as outdated right after first subscription", () => {
1431
+ let $state = $watch({
1432
+ s: 0,
1433
+ get c() {
1434
+ return $cache(() => $state.s);
1435
+ },
1436
+ });
1437
+ $state.c;
1438
+
1439
+ $state.s = 1;
1440
+ $run(() => {
1441
+ $state.c;
1442
+ });
1443
+ expect($state.c).toEqual(1);
1444
+ });
1445
+
1446
+ // it("should propagate notification to other listeners after one listener is disposed", () => {
1447
+ // let $state = $watch({ s: 0 });
1448
+ // const c = $derive(() => s.value);
1449
+ //
1450
+ // let spy1 = vi.fn(() => {
1451
+ // $state.c;
1452
+ // });
1453
+ // let spy2 = vi.fn(() => {
1454
+ // $state.c;
1455
+ // });
1456
+ // let spy3 = vi.fn(() => {
1457
+ // $state.c;
1458
+ // });
1459
+ //
1460
+ // $run(spy1);
1461
+ // const dispose = $run(spy2);
1462
+ // $run(spy3);
1463
+ //
1464
+ // expect(spy1).toHaveBeenCalledOnce();
1465
+ // expect(spy2).toHaveBeenCalledOnce();
1466
+ // expect(spy3).toHaveBeenCalledOnce();
1467
+ //
1468
+ // dispose();
1469
+ //
1470
+ // $state.s = 1;
1471
+ // expect(spy1).toHaveBeenCalledTimes(2);
1472
+ // expect(spy2).toHaveBeenCalledOnce();
1473
+ // expect(spy3).toHaveBeenCalledTimes(2);
1474
+ // });
1475
+
1476
+ it("should not recompute dependencies out of order", () => {
1477
+ let spy = vi.fn(() => $state.c);
1478
+ let $state = $watch({
1479
+ a: 1,
1480
+ b: 1,
1481
+ c: 1,
1482
+ get d() {
1483
+ return $cache(spy);
1484
+ },
1485
+ get e() {
1486
+ return $cache(() => {
1487
+ if ($state.a > 0) {
1488
+ $state.b;
1489
+ $state.d;
1490
+ } else {
1491
+ $state.b;
1492
+ }
1493
+ return true;
1494
+ });
1495
+ },
1496
+ });
1497
+
1498
+ $state.e;
1499
+ spy.mockReset();
1500
+
1501
+ $state.a = 2;
1502
+ $state.b = 2;
1503
+ $state.c = 2;
1504
+ $state.e;
1505
+ expect(spy).toHaveBeenCalledOnce();
1506
+ spy.mockReset();
1507
+
1508
+ $state.a = -1;
1509
+ $state.b = -1;
1510
+ $state.c = -1;
1511
+ $state.e;
1512
+ expect(spy).not.toHaveBeenCalled();
1513
+ spy.mockReset();
1514
+ });
1515
+
1516
+ it("should not recompute dependencies unnecessarily", () => {
1517
+ let spy = vi.fn();
1518
+ let $state = $watch({
1519
+ a: 0,
1520
+ b: 0,
1521
+ get c() {
1522
+ return $cache(() => {
1523
+ $state.b;
1524
+ return spy();
1525
+ });
1526
+ },
1527
+ get d() {
1528
+ return $cache(() => {
1529
+ if ($state.a === 0) {
1530
+ return $state.c;
1531
+ }
1532
+ });
1533
+ },
1534
+ });
1535
+
1536
+ $state.d;
1537
+ expect(spy).toHaveBeenCalledOnce();
1538
+
1539
+ $batch(() => {
1540
+ $state.b = 1;
1541
+ $state.a = 1;
1542
+ });
1543
+ $state.d;
1544
+ expect(spy).toHaveBeenCalledOnce();
1545
+ });
1546
+
1547
+ describe("$peek()", () => {
1548
+ it("should get value", () => {
1549
+ let $state = $watch({
1550
+ s: 1,
1551
+ get c() {
1552
+ return $cache(() => $state.s);
1553
+ },
1554
+ });
1555
+ expect($peek(() => $state.c)).equal(1);
1556
+ });
1557
+
1558
+ it("should throw when evaluation throws", () => {
1559
+ let $state = $watch({
1560
+ get c() {
1561
+ return $cache(() => {
1562
+ throw Error("test");
1563
+ });
1564
+ },
1565
+ });
1566
+ expect(() => $peek(() => $state.c)).toThrow("test");
1567
+ });
1568
+
1569
+ it("should throw when previous evaluation threw and dependencies haven't changed", () => {
1570
+ let $state = $watch({
1571
+ get c() {
1572
+ return $cache(() => {
1573
+ throw Error("test");
1574
+ });
1575
+ },
1576
+ });
1577
+ expect(() => $state.c).toThrow("test");
1578
+ expect(() => $peek(() => $state.c)).toThrow("test");
1579
+ });
1580
+
1581
+ it("should refresh value if stale", () => {
1582
+ let $state = $watch({
1583
+ a: 1,
1584
+ get b() {
1585
+ return $cache(() => $state.a);
1586
+ },
1587
+ });
1588
+ expect($peek(() => $state.b)).toEqual(1);
1589
+
1590
+ $state.a = 2;
1591
+ expect($peek(() => $state.b)).toEqual(2);
1592
+ });
1593
+
1594
+ it("should detect simple dependency cycles", () => {
1595
+ const $state = $watch({
1596
+ get a(): any {
1597
+ return $cache(() => $peek(() => $state.a));
1598
+ },
1599
+ });
1600
+ expect(() => $peek(() => $state.a)).toThrow("Cycle detected");
1601
+ });
1602
+
1603
+ it("should detect deep dependency cycles", () => {
1604
+ const $state = $watch({
1605
+ get a(): any {
1606
+ return $cache(() => $state.b);
1607
+ },
1608
+ get b() {
1609
+ return $cache(() => $state.c);
1610
+ },
1611
+ get c() {
1612
+ return $cache(() => $state.d);
1613
+ },
1614
+ get d() {
1615
+ return $cache(() => $peek(() => $state.a));
1616
+ },
1617
+ });
1618
+ expect(() => $peek(() => $state.a)).toThrow("Cycle detected");
1619
+ });
1620
+
1621
+ it("should not make surrounding effect depend on the computed", () => {
1622
+ let $state = $watch({
1623
+ s: 1,
1624
+ get c() {
1625
+ return $cache(() => $state.s);
1626
+ },
1627
+ });
1628
+ let spy = vi.fn(() => {
1629
+ $peek(() => $state.c);
1630
+ });
1631
+
1632
+ $run(spy);
1633
+ expect(spy).toHaveBeenCalledOnce();
1634
+
1635
+ $state.s = 2;
1636
+ expect(spy).toHaveBeenCalledOnce();
1637
+ });
1638
+
1639
+ it("should not make surrounding computed depend on the $derive", () => {
1640
+ let spy = vi.fn(() => {
1641
+ $peek(() => $state.c);
1642
+ });
1643
+
1644
+ let $state = $watch({
1645
+ s: 1,
1646
+ get c() {
1647
+ return $cache(() => $state.s);
1648
+ },
1649
+ get d() {
1650
+ return $cache(spy);
1651
+ },
1652
+ });
1653
+ $state.d;
1654
+ expect(spy).toHaveBeenCalledOnce();
1655
+
1656
+ $state.s = 2;
1657
+ $state.d;
1658
+ expect(spy).toHaveBeenCalledOnce();
1659
+ });
1660
+
1661
+ it("should not make surrounding effect depend on the peeked computed's dependencies", () => {
1662
+ let $state = $watch({
1663
+ a: 1,
1664
+ get b() {
1665
+ return $cache(() => $state.a);
1666
+ },
1667
+ });
1668
+
1669
+ let spy = vi.fn();
1670
+ $run(() => {
1671
+ spy();
1672
+ $peek(() => $state.b);
1673
+ });
1674
+ expect(spy).toHaveBeenCalledOnce();
1675
+ spy.mockReset();
1676
+
1677
+ $state.a = 1;
1678
+ expect(spy).not.toHaveBeenCalled();
1679
+ });
1680
+
1681
+ it("should not make surrounding computed depend on peeked $derive's dependencies", () => {
1682
+ let spy = vi.fn();
1683
+ let $state = $watch({
1684
+ a: 1,
1685
+ get b() {
1686
+ return $cache(() => $state.a);
1687
+ },
1688
+ get d() {
1689
+ spy();
1690
+ return $cache(() => $peek(() => $state.b));
1691
+ },
1692
+ });
1693
+ $state.d;
1694
+ expect(spy).toHaveBeenCalledOnce();
1695
+ spy.mockReset();
1696
+
1697
+ $state.a = 1;
1698
+ $state.d;
1699
+ expect(spy).not.toHaveBeenCalled();
1700
+ });
1701
+ });
1702
+
1703
+ // describe("garbage collection", function () {
1704
+ // // Skip GC tests if window.gc/global.gc is not defined.
1705
+ // before(function () {
1706
+ // if (typeof gc === "undefined") {
1707
+ // this.skip();
1708
+ // }
1709
+ // });
1710
+ //
1711
+ // it("should be garbage collectable if nothing is listening to its changes", async () => {
1712
+ // let $state = $watch({ s: 0 });
1713
+ // const ref = new WeakRef($derive(() => s.value));
1714
+ //
1715
+ // (gc as () => void)();
1716
+ // await new Promise((resolve) => setTimeout(resolve, 0));
1717
+ // (gc as () => void)();
1718
+ // expect(ref.deref()).toBeUndefined();
1719
+ // });
1720
+ //
1721
+ // it("should be garbage collectable after it has lost all of its listeners", async () => {
1722
+ // let $state = $watch({ s: 0 });
1723
+ //
1724
+ // let ref: WeakRef<ReadonlySignal>;
1725
+ // let dispose: () => void;
1726
+ // (function () {
1727
+ // const c = $derive(() => s.value);
1728
+ // ref = new WeakRef(c);
1729
+ // dispose = $run(() => {
1730
+ // $state.c;
1731
+ // });
1732
+ // })();
1733
+ //
1734
+ // dispose();
1735
+ // (gc as () => void)();
1736
+ // await new Promise((resolve) => setTimeout(resolve, 0));
1737
+ // (gc as () => void)();
1738
+ // expect(ref.deref()).toBeUndefined();
1739
+ // });
1740
+ // });
1741
+
1742
+ describe("graph updates", () => {
1743
+ it("should run computeds once for multiple dep changes", async () => {
1744
+ const compute = vi.fn(() => {
1745
+ // debugger;
1746
+ return $state.a + $state.b;
1747
+ });
1748
+ let $state = $watch({
1749
+ a: "a",
1750
+ b: "b",
1751
+ get c() {
1752
+ return $cache(() => compute());
1753
+ },
1754
+ });
1755
+
1756
+ expect($state.c).toEqual("ab");
1757
+ expect(compute).toHaveBeenCalledOnce();
1758
+ compute.mockReset();
1759
+
1760
+ $state.a = "aa";
1761
+ $state.b = "bb";
1762
+ $state.c;
1763
+ expect(compute).toHaveBeenCalledOnce();
1764
+ });
1765
+
1766
+ it("should drop A->B->A updates", async () => {
1767
+ const compute = vi.fn(() => "d: " + $state.c);
1768
+
1769
+ // A
1770
+ // / |
1771
+ // B | <- Looks like a flag doesn't it? :D
1772
+ // \ |
1773
+ // C
1774
+ // |
1775
+ // D
1776
+ let $state = $watch({
1777
+ a: 2,
1778
+ get b() {
1779
+ return $cache(() => $state.a - 1);
1780
+ },
1781
+ get c() {
1782
+ return $cache(() => $state.a + $state.b);
1783
+ },
1784
+ get d() {
1785
+ return $cache(() => compute());
1786
+ },
1787
+ });
1788
+
1789
+ // Trigger read
1790
+ expect($state.d).toEqual("d: 3");
1791
+ expect(compute).toHaveBeenCalledOnce();
1792
+ compute.mockReset();
1793
+
1794
+ $state.a = 4;
1795
+ $state.d;
1796
+ expect(compute).toHaveBeenCalledOnce();
1797
+ });
1798
+
1799
+ it("should only update every signal once (diamond graph)", () => {
1800
+ let spy = vi.fn(() => $state.b + " " + $state.c);
1801
+
1802
+ // In this scenario "D" should only update once when "A" receives
1803
+ // an update. This is sometimes referred to as the "diamond" scenario.
1804
+ // A
1805
+ // / \
1806
+ // B C
1807
+ // \ /
1808
+ // D
1809
+ let $state = $watch({
1810
+ a: "a",
1811
+ get b() {
1812
+ return $cache(() => $state.a);
1813
+ },
1814
+ get c() {
1815
+ return $cache(() => $state.a);
1816
+ },
1817
+ get d() {
1818
+ return $cache(spy);
1819
+ },
1820
+ });
1821
+
1822
+ expect($state.d).toEqual("a a");
1823
+ expect(spy).toHaveBeenCalledOnce();
1824
+
1825
+ $state.a = "aa";
1826
+ expect($state.d).toEqual("aa aa");
1827
+ expect(spy).toHaveBeenCalledTimes(2);
1828
+ });
1829
+
1830
+ it("should only update every signal once (diamond graph + tail)", () => {
1831
+ let spy = vi.fn(() => $state.d);
1832
+
1833
+ // "E" will be likely updated twice if our mark+sweep logic is buggy.
1834
+ // A
1835
+ // / \
1836
+ // B C
1837
+ // \ /
1838
+ // D
1839
+ // |
1840
+ // E
1841
+ let $state = $watch({
1842
+ a: "a",
1843
+ get b() {
1844
+ return $cache(() => $state.a);
1845
+ },
1846
+ get c() {
1847
+ return $cache(() => $state.a);
1848
+ },
1849
+ get d() {
1850
+ return $cache(() => $state.b + " " + $state.c);
1851
+ },
1852
+ get e() {
1853
+ return $cache(spy);
1854
+ },
1855
+ });
1856
+
1857
+ expect($state.e).toEqual("a a");
1858
+ expect(spy).toHaveBeenCalledOnce();
1859
+
1860
+ $state.a = "aa";
1861
+ expect($state.e).toEqual("aa aa");
1862
+ expect(spy).toHaveBeenCalledTimes(2);
1863
+ });
1864
+
1865
+ it("should bail out if result is the same", () => {
1866
+ let spy = vi.fn(() => $state.b);
1867
+
1868
+ // Bail out if value of "B" never changes
1869
+ // A->B->C
1870
+ let $state = $watch({
1871
+ a: "a",
1872
+ get b() {
1873
+ return $cache(() => {
1874
+ $state.a;
1875
+ return "foo";
1876
+ });
1877
+ },
1878
+ get c() {
1879
+ return $cache(spy);
1880
+ },
1881
+ });
1882
+
1883
+ expect($state.c).toEqual("foo");
1884
+ expect(spy).toHaveBeenCalledOnce();
1885
+
1886
+ $state.a = "aa";
1887
+ expect($state.c).toEqual("foo");
1888
+ expect(spy).toHaveBeenCalledOnce();
1889
+ });
1890
+
1891
+ it("should only update every signal once (jagged diamond graph + tails)", () => {
1892
+ const eSpy = vi.fn();
1893
+ const fSpy = vi.fn();
1894
+ const gSpy = vi.fn();
1895
+
1896
+ // "F" and "G" will be likely updated twice if our mark+sweep logic is buggy.
1897
+ // A
1898
+ // / \
1899
+ // B C
1900
+ // | |
1901
+ // | D
1902
+ // \ /
1903
+ // E
1904
+ // / \
1905
+ // F G
1906
+ let $state = $watch({
1907
+ a: "a",
1908
+ get b() {
1909
+ return $cache(() => $state.a);
1910
+ },
1911
+ get c() {
1912
+ return $cache(() => $state.a);
1913
+ },
1914
+ get d() {
1915
+ return $cache(() => $state.c);
1916
+ },
1917
+ get e() {
1918
+ return $cache(() => {
1919
+ eSpy();
1920
+ return $state.b + " " + $state.d;
1921
+ });
1922
+ },
1923
+ get f() {
1924
+ return $cache(() => {
1925
+ fSpy();
1926
+ return $state.e;
1927
+ });
1928
+ },
1929
+ get g() {
1930
+ return $cache(() => {
1931
+ gSpy();
1932
+ return $state.e;
1933
+ });
1934
+ },
1935
+ });
1936
+
1937
+ expect($state.f).toEqual("a a");
1938
+ expect(fSpy).toHaveBeenCalledOnce();
1939
+
1940
+ expect($state.g).toEqual("a a");
1941
+ expect(gSpy).toHaveBeenCalledOnce();
1942
+
1943
+ eSpy.mockReset();
1944
+ fSpy.mockReset();
1945
+ gSpy.mockReset();
1946
+
1947
+ $state.a = "b";
1948
+
1949
+ expect($state.e).toEqual("b b");
1950
+ expect(eSpy).toHaveBeenCalledOnce();
1951
+
1952
+ expect($state.f).toEqual("b b");
1953
+ expect(fSpy).toHaveBeenCalledOnce();
1954
+
1955
+ expect($state.g).toEqual("b b");
1956
+ expect(gSpy).toHaveBeenCalledOnce();
1957
+
1958
+ eSpy.mockReset();
1959
+ fSpy.mockReset();
1960
+ gSpy.mockReset();
1961
+
1962
+ $state.a = "c";
1963
+
1964
+ expect($state.e).toEqual("c c");
1965
+ expect(eSpy).toHaveBeenCalledOnce();
1966
+
1967
+ expect($state.f).toEqual("c c");
1968
+ expect(fSpy).toHaveBeenCalledOnce();
1969
+
1970
+ expect($state.g).toEqual("c c");
1971
+ expect(gSpy).toHaveBeenCalledOnce();
1972
+
1973
+ // top to bottom
1974
+ expect(eSpy).toHaveBeenCalledBefore(fSpy);
1975
+ // left to right
1976
+ expect(fSpy).toHaveBeenCalledBefore(gSpy);
1977
+ });
1978
+
1979
+ it("should only subscribe to signals listened to", () => {
1980
+ let spy = vi.fn(() => $state.a);
1981
+
1982
+ // *A
1983
+ // / \
1984
+ // *B C <- we don't listen to C
1985
+ let $state = $watch({
1986
+ a: "a",
1987
+ get b() {
1988
+ return $cache(() => $state.a);
1989
+ },
1990
+ get c() {
1991
+ return $cache(spy);
1992
+ },
1993
+ });
1994
+
1995
+ expect($state.b).toEqual("a");
1996
+ expect(spy).not.toHaveBeenCalled();
1997
+
1998
+ $state.a = "aa";
1999
+ expect($state.b).toEqual("aa");
2000
+ expect(spy).not.toHaveBeenCalled();
2001
+ });
2002
+
2003
+ // it("should only subscribe to signals listened to", () => {
2004
+ // // Here both "B" and "C" are active in the beginning, but
2005
+ // // "B" becomes inactive later. At that point it should
2006
+ // // not receive any updates anymore.
2007
+ // // *A
2008
+ // // / \
2009
+ // // *B D <- we don't listen to C
2010
+ // // |
2011
+ // // *C
2012
+ // let $state = $watch({ a: "a" });
2013
+ // let spyB = vi.fn(() => $state.a);
2014
+ // const b = $derive(spyB);
2015
+ //
2016
+ // let spyC = vi.fn(() => $state.b);
2017
+ // const c = $derive(spyC);
2018
+ //
2019
+ // const d = $derive(() => $state.a);
2020
+ //
2021
+ // let result = "";
2022
+ // const unsub = $run(() => {
2023
+ // result = $state.c;
2024
+ // });
2025
+ //
2026
+ // expect(result).toEqual("a");
2027
+ // expect($state.d).toEqual("a");
2028
+ //
2029
+ // spyB.mockReset();
2030
+ // spyC.mockReset();
2031
+ // unsub();
2032
+ //
2033
+ // $state.a = "aa";
2034
+ //
2035
+ // expect(spyB).not.toHaveBeenCalled();
2036
+ // expect(spyC).not.toHaveBeenCalled();
2037
+ // expect($state.d).toEqual("aa");
2038
+ // });
2039
+
2040
+ it("should ensure subs update even if one dep unmarks it", () => {
2041
+ let spy = vi.fn(() => $state.b + " " + $state.c);
2042
+
2043
+ // In this scenario "C" always returns the same value. When "A"
2044
+ // changes, "B" will update, then "C" at which point its update
2045
+ // to "D" will be unmarked. But "D" must still update because
2046
+ // "B" marked it. If "D" isn't updated, then we have a bug.
2047
+ // A
2048
+ // / \
2049
+ // B *C <- returns same value every time
2050
+ // \ /
2051
+ // D
2052
+ let $state = $watch({
2053
+ a: "a",
2054
+ get b() {
2055
+ return $cache(() => $state.a);
2056
+ },
2057
+ get c() {
2058
+ return $cache(() => {
2059
+ $state.a;
2060
+ return "c";
2061
+ });
2062
+ },
2063
+ get d() {
2064
+ return $cache(spy);
2065
+ },
2066
+ });
2067
+
2068
+ expect($state.d).toEqual("a c");
2069
+ spy.mockReset();
2070
+
2071
+ $state.a = "aa";
2072
+ $state.d;
2073
+ expect(spy).toHaveLastReturnedWith("aa c");
2074
+ });
2075
+
2076
+ it("should ensure subs update even if two deps unmark it", () => {
2077
+ let spy = vi.fn(() => $state.b + " " + $state.c + " " + $state.d);
2078
+
2079
+ // In this scenario both "C" and "D" always return the same
2080
+ // value. But "E" must still update because "A" marked it.
2081
+ // If "E" isn't updated, then we have a bug.
2082
+ // A
2083
+ // / | \
2084
+ // B *C *D
2085
+ // \ | /
2086
+ // E
2087
+ let $state = $watch({
2088
+ a: "a",
2089
+ get b() {
2090
+ return $cache(() => $state.a);
2091
+ },
2092
+ get c() {
2093
+ return $cache(() => {
2094
+ $state.a;
2095
+ return "c";
2096
+ });
2097
+ },
2098
+ get d() {
2099
+ return $cache(() => {
2100
+ $state.a;
2101
+ return "d";
2102
+ });
2103
+ },
2104
+ get e() {
2105
+ return $cache(spy);
2106
+ },
2107
+ });
2108
+ expect($state.e).toEqual("a c d");
2109
+ spy.mockReset();
2110
+
2111
+ $state.a = "aa";
2112
+ $state.e;
2113
+ expect(spy).toHaveLastReturnedWith("aa c d");
2114
+ });
2115
+ });
2116
+
2117
+ describe("error handling", () => {
2118
+ // it("should throw when writing to computeds", () => {
2119
+ // let $state = $watch({ a: "a" });
2120
+ // const b = $derive(() => $state.a);
2121
+ // const fn = () => ((b as $state.Signal) = "aa");
2122
+ // expect(fn).toThrow(/Cannot set property value/);
2123
+ // });
2124
+
2125
+ it("should keep graph consistent on errors during activation", () => {
2126
+ let $state = $watch({
2127
+ a: 0,
2128
+ get b() {
2129
+ return $cache(() => {
2130
+ throw new Error("fail");
2131
+ });
2132
+ },
2133
+ get c() {
2134
+ return $cache(() => $state.a);
2135
+ },
2136
+ });
2137
+ expect(() => $state.b).toThrow("fail");
2138
+
2139
+ $state.a = 1;
2140
+ expect($state.c).toEqual(1);
2141
+ });
2142
+
2143
+ it("should keep graph consistent on errors in computeds", () => {
2144
+ let $state = $watch({
2145
+ a: 0,
2146
+ get b() {
2147
+ return $cache(() => {
2148
+ if ($state.a === 1) throw new Error("fail");
2149
+ return $state.a;
2150
+ });
2151
+ },
2152
+ get c() {
2153
+ return $cache(() => $state.b);
2154
+ },
2155
+ });
2156
+ expect($state.c).toEqual(0);
2157
+
2158
+ $state.a = 1;
2159
+ expect(() => $state.b).toThrow("fail");
2160
+
2161
+ $state.a = 2;
2162
+ expect($state.c).toEqual(2);
2163
+ });
2164
+
2165
+ it("should support lazy branches", () => {
2166
+ let $state = $watch({
2167
+ a: 0,
2168
+ get b() {
2169
+ return $cache(() => $state.a);
2170
+ },
2171
+ get c() {
2172
+ return $cache(() => ($state.a > 0 ? $state.a : $state.b));
2173
+ },
2174
+ });
2175
+
2176
+ expect($state.c).toEqual(0);
2177
+ $state.a = 1;
2178
+ expect($state.c).toEqual(1);
2179
+
2180
+ $state.a = 0;
2181
+ expect($state.c).toEqual(0);
2182
+ });
2183
+
2184
+ it("should not update a sub if all deps unmark it", () => {
2185
+ let spy = vi.fn(() => $state.b + " " + $state.c);
2186
+
2187
+ // In this scenario "B" and "C" always return the same value. When "A"
2188
+ // changes, "D" should not update.
2189
+ // A
2190
+ // / \
2191
+ // *B *C
2192
+ // \ /
2193
+ // D
2194
+ let $state = $watch({
2195
+ a: "a",
2196
+ get b() {
2197
+ return $cache(() => {
2198
+ $state.a;
2199
+ return "b";
2200
+ });
2201
+ },
2202
+ get c() {
2203
+ return $cache(() => {
2204
+ $state.a;
2205
+ return "c";
2206
+ });
2207
+ },
2208
+ get d() {
2209
+ return $cache(spy);
2210
+ },
2211
+ });
2212
+
2213
+ expect($state.d).toEqual("b c");
2214
+ spy.mockReset();
2215
+
2216
+ $state.a = "aa";
2217
+ expect(spy).not.toHaveBeenCalled();
2218
+ });
2219
+ });
2220
+ });
2221
+
2222
+ describe("$batch()", () => {
2223
+ // it("should return the value from the callback", () => {
2224
+ // expect($batch(() => 1)).toEqual(1);
2225
+ // });
2226
+ //
2227
+ // it("should throw errors thrown from the callback", () => {
2228
+ // expect(() =>
2229
+ // $batch(() => {
2230
+ // throw Error("hello");
2231
+ // }),
2232
+ // ).toThrow("hello");
2233
+ // });
2234
+ //
2235
+ // it("should throw non-errors thrown from the callback", () => {
2236
+ // try {
2237
+ // $batch(() => {
2238
+ // throw undefined;
2239
+ // });
2240
+ // expect.fail();
2241
+ // } catch (err) {
2242
+ // expect(err).toBeUndefined();
2243
+ // }
2244
+ // });
2245
+
2246
+ it("should delay writes", () => {
2247
+ let $state = $watch({ a: "a", b: "b" });
2248
+ let spy = vi.fn(() => {
2249
+ $state.a + " " + $state.b;
2250
+ });
2251
+ $run(spy);
2252
+ spy.mockReset();
2253
+
2254
+ $batch(() => {
2255
+ $state.a = "aa";
2256
+ $state.b = "bb";
2257
+ });
2258
+
2259
+ expect(spy).toHaveBeenCalledOnce();
2260
+ });
2261
+
2262
+ it("should delay writes until outermost batch is complete", () => {
2263
+ let $state = $watch({ a: "a", b: "b" });
2264
+ let spy = vi.fn(() => {
2265
+ $state.a + ", " + $state.b;
2266
+ });
2267
+ $run(spy);
2268
+ spy.mockReset();
2269
+
2270
+ $batch(() => {
2271
+ $batch(() => {
2272
+ $state.a += " inner";
2273
+ $state.b += " inner";
2274
+ });
2275
+ $state.a += " outer";
2276
+ $state.b += " outer";
2277
+ });
2278
+
2279
+ // If the inner $batch() would have flushed the update
2280
+ // this spy would've been called twice.
2281
+ expect(spy).toHaveBeenCalledOnce();
2282
+ });
2283
+
2284
+ it("should read signals written to", () => {
2285
+ let $state = $watch({ a: "a" });
2286
+
2287
+ let result = "";
2288
+ $batch(() => {
2289
+ $state.a = "aa";
2290
+ result = $state.a;
2291
+ });
2292
+
2293
+ expect(result).toEqual("aa");
2294
+ });
2295
+
2296
+ it("should read computed signals with updated source signals", () => {
2297
+ let spyC = vi.fn(() => $state.b);
2298
+ let spyD = vi.fn(() => $state.c);
2299
+ let spyE = vi.fn(() => $state.d);
2300
+
2301
+ // A->B->C->D->E
2302
+ let $state = $watch({
2303
+ a: "a",
2304
+ get b() {
2305
+ return $cache(() => $state.a);
2306
+ },
2307
+ get c() {
2308
+ return $cache(() => spyC());
2309
+ },
2310
+ get d() {
2311
+ return $cache(() => spyD());
2312
+ },
2313
+ get e() {
2314
+ return $cache(() => spyE());
2315
+ },
2316
+ });
2317
+
2318
+ spyC.mockReset();
2319
+ spyD.mockReset();
2320
+ spyE.mockReset();
2321
+
2322
+ let result = "";
2323
+ $batch(() => {
2324
+ $state.a = "aa";
2325
+ result = $state.c;
2326
+
2327
+ // Since "D" isn't accessed during batching, we should not
2328
+ // update it, only after batching has completed
2329
+ expect(spyD).not.toHaveBeenCalled();
2330
+ });
2331
+
2332
+ expect(result).toEqual("aa");
2333
+ expect($state.d).toEqual("aa");
2334
+ expect($state.e).toEqual("aa");
2335
+ expect(spyC).toHaveBeenCalledOnce();
2336
+ expect(spyD).toHaveBeenCalledOnce();
2337
+ expect(spyE).toHaveBeenCalledOnce();
2338
+ });
2339
+
2340
+ it("should not block writes after batching completed", () => {
2341
+ // If no further writes after $batch() are possible, than we
2342
+ // didn't restore state properly. Most likely "pending" still
2343
+ // holds elements that are already processed.
2344
+ let $state = $watch({
2345
+ a: "a",
2346
+ b: "b",
2347
+ c: "c",
2348
+ get d() {
2349
+ return $cache(() => $state.a + " " + $state.b + " " + $state.c);
2350
+ },
2351
+ });
2352
+
2353
+ let result;
2354
+ $run(() => {
2355
+ result = $state.d;
2356
+ });
2357
+
2358
+ $batch(() => {
2359
+ $state.a = "aa";
2360
+ $state.b = "bb";
2361
+ });
2362
+
2363
+ $state.c = "cc";
2364
+ expect(result).toEqual("aa bb cc");
2365
+ });
2366
+
2367
+ it("should not lead to stale signals with .value in batch", () => {
2368
+ const invokes: number[][] = [];
2369
+ let $state = $watch({
2370
+ counter: 0,
2371
+ get double() {
2372
+ return $cache(() => this.counter * 2);
2373
+ },
2374
+ get triple() {
2375
+ return $cache(() => this.counter * 3);
2376
+ },
2377
+ });
2378
+
2379
+ $run(() => {
2380
+ invokes.push([$state.double, $state.triple]);
2381
+ });
2382
+
2383
+ expect(invokes).to.deep.equal([[0, 0]]);
2384
+
2385
+ $batch(() => {
2386
+ $state.counter = 1;
2387
+ expect($state.double).toEqual(2);
2388
+ });
2389
+
2390
+ expect(invokes[1]).to.deep.equal([2, 3]);
2391
+ });
2392
+
2393
+ it("should not lead to stale signals with peek() in batch", () => {
2394
+ const invokes: number[][] = [];
2395
+ let $state = $watch({
2396
+ counter: 0,
2397
+ get double() {
2398
+ return $cache(() => this.counter * 2);
2399
+ },
2400
+ get triple() {
2401
+ return $cache(() => this.counter * 3);
2402
+ },
2403
+ });
2404
+
2405
+ $run(() => {
2406
+ invokes.push([$state.double, $state.triple]);
2407
+ });
2408
+
2409
+ expect(invokes).to.deep.equal([[0, 0]]);
2410
+
2411
+ $batch(() => {
2412
+ $state.counter = 1;
2413
+ expect($peek(() => $state.double)).toEqual(2);
2414
+ });
2415
+
2416
+ expect(invokes[1]).to.deep.equal([2, 3]);
2417
+ });
2418
+
2419
+ it("should run pending effects even if the callback throws", () => {
2420
+ let $state = $watch({ a: 0, b: 1 });
2421
+ let spy1 = vi.fn(() => {
2422
+ $state.a;
2423
+ });
2424
+ let spy2 = vi.fn(() => {
2425
+ $state.b;
2426
+ });
2427
+ $run(spy1);
2428
+ $run(spy2);
2429
+ spy1.mockReset();
2430
+ spy2.mockReset();
2431
+
2432
+ expect(() =>
2433
+ $batch(() => {
2434
+ $state.a++;
2435
+ $state.b++;
2436
+ throw Error("hello");
2437
+ }),
2438
+ ).toThrow("hello");
2439
+
2440
+ expect(spy1).toHaveBeenCalledOnce();
2441
+ expect(spy2).toHaveBeenCalledOnce();
2442
+ });
2443
+
2444
+ it("should run pending effects even if some effects throw", () => {
2445
+ let $state = $watch({ a: 0 });
2446
+ let spy1 = vi.fn(() => {
2447
+ $state.a;
2448
+ });
2449
+ let spy2 = vi.fn(() => {
2450
+ $state.a;
2451
+ });
2452
+ $run(() => {
2453
+ if ($state.a === 1) {
2454
+ throw new Error("hello");
2455
+ }
2456
+ });
2457
+ $run(spy1);
2458
+ $run(() => {
2459
+ if ($state.a === 1) {
2460
+ throw new Error("hello");
2461
+ }
2462
+ });
2463
+ $run(spy2);
2464
+ $run(() => {
2465
+ if ($state.a === 1) {
2466
+ throw new Error("hello");
2467
+ }
2468
+ });
2469
+ spy1.mockReset();
2470
+ spy2.mockReset();
2471
+
2472
+ expect(() =>
2473
+ $batch(() => {
2474
+ $state.a++;
2475
+ }),
2476
+ ).toThrow("hello");
2477
+
2478
+ expect(spy1).toHaveBeenCalledOnce();
2479
+ expect(spy2).toHaveBeenCalledOnce();
2480
+ });
2481
+
2482
+ it("should run effect's first run immediately even inside a batch", () => {
2483
+ //let callCount = 0;
2484
+ let spy = vi.fn();
2485
+ $batch(() => {
2486
+ $run(spy);
2487
+ //callCount = spy.callCount;
2488
+ expect(spy).toHaveBeenCalledOnce();
2489
+ });
2490
+ //expect(callCount).toBe(1);
2491
+ });
2492
+ });
2493
+
2494
+ describe("untracked ($peek)", () => {
2495
+ it("should block tracking inside effects", () => {
2496
+ let $state = $watch({ a: 1, b: 2 });
2497
+ let spy = vi.fn(() => {
2498
+ $state.a + $state.b;
2499
+ });
2500
+ $run(() => $peek(spy));
2501
+ expect(spy).toHaveBeenCalledOnce();
2502
+
2503
+ $state.a = 10;
2504
+ $state.b = 20;
2505
+ expect(spy).toHaveBeenCalledOnce();
2506
+ });
2507
+
2508
+ it("should block tracking even when run inside effect run inside untracked", () => {
2509
+ let $state = $watch({ s: 1 });
2510
+ let spy = vi.fn(() => $state.s);
2511
+
2512
+ $peek(() =>
2513
+ $run(() => {
2514
+ $peek(spy);
2515
+ }),
2516
+ );
2517
+ expect(spy).toHaveBeenCalledOnce();
2518
+
2519
+ $state.s = 2;
2520
+ expect(spy).toHaveBeenCalledOnce();
2521
+ });
2522
+
2523
+ it("should not cause signal assignments throw", () => {
2524
+ let $state = $watch({ a: 1, aChangedTime: 0 });
2525
+
2526
+ /*const dispose =*/ $run(() => {
2527
+ //dev.log("RUNNING");
2528
+ $state.a;
2529
+ $peek(() => {
2530
+ $state.aChangedTime = $state.aChangedTime + 1;
2531
+ });
2532
+ });
2533
+ expect(() => ($state.a = 2)).not.toThrow();
2534
+ expect($state.aChangedTime).toEqual(2);
2535
+ $state.a = 3;
2536
+ expect($state.aChangedTime).toEqual(3);
2537
+
2538
+ //dispose();
2539
+ });
2540
+
2541
+ it("should block tracking inside computed signals", () => {
2542
+ let spy = vi.fn(() => $state.a + $state.b);
2543
+ let $state = $watch({
2544
+ a: 1,
2545
+ b: 2,
2546
+ get c() {
2547
+ return $cache(() => $peek(spy));
2548
+ },
2549
+ });
2550
+
2551
+ expect(spy).not.toHaveBeenCalled();
2552
+ expect($state.c).toEqual(3);
2553
+ $state.a = 10;
2554
+ $state.c;
2555
+ $state.b = 20;
2556
+ $state.c;
2557
+ expect(spy).toHaveBeenCalledOnce();
2558
+ expect($state.c).toEqual(3);
2559
+ });
2560
+ });