@askrjs/askr 0.0.47 → 0.0.49

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 (394) hide show
  1. package/dist/benchmark.js +6 -6
  2. package/dist/benchmark.js.map +1 -1
  3. package/dist/boot/hydration.js +140 -0
  4. package/dist/boot/hydration.js.map +1 -0
  5. package/dist/boot/index.d.ts +3 -56
  6. package/dist/boot/index.d.ts.map +1 -1
  7. package/dist/boot/index.js +62 -410
  8. package/dist/boot/index.js.map +1 -1
  9. package/dist/boot/root-lifecycle.d.ts +15 -0
  10. package/dist/boot/root-lifecycle.d.ts.map +1 -0
  11. package/dist/boot/root-lifecycle.js +205 -0
  12. package/dist/boot/root-lifecycle.js.map +1 -0
  13. package/dist/boot/route-startup.js +45 -0
  14. package/dist/boot/route-startup.js.map +1 -0
  15. package/dist/boot/types.d.ts +62 -0
  16. package/dist/boot/types.d.ts.map +1 -0
  17. package/dist/common/component.d.ts +3 -1
  18. package/dist/common/component.d.ts.map +1 -1
  19. package/dist/common/jsx.d.ts +1 -1
  20. package/dist/common/jsx.d.ts.map +1 -1
  21. package/dist/common/jsx.js.map +1 -1
  22. package/dist/common/props.d.ts +1 -1
  23. package/dist/common/render-context.js +55 -0
  24. package/dist/common/render-context.js.map +1 -0
  25. package/dist/common/router.d.ts +5 -1
  26. package/dist/common/router.d.ts.map +1 -1
  27. package/dist/common/ssr.d.ts +1 -1
  28. package/dist/common/ssr.js.map +1 -1
  29. package/dist/common/vnode.d.ts +5 -4
  30. package/dist/common/vnode.d.ts.map +1 -1
  31. package/dist/common/vnode.js.map +1 -1
  32. package/dist/components/error-boundary.d.ts +1 -1
  33. package/dist/components/error-boundary.js +2 -1
  34. package/dist/components/error-boundary.js.map +1 -1
  35. package/dist/components/link.js.map +1 -1
  36. package/dist/control/for.js +2 -1
  37. package/dist/control/for.js.map +1 -1
  38. package/dist/data/data-runtime.d.ts +28 -0
  39. package/dist/data/data-runtime.d.ts.map +1 -0
  40. package/dist/data/data-runtime.js +114 -0
  41. package/dist/data/data-runtime.js.map +1 -0
  42. package/dist/data/index.d.ts +6 -142
  43. package/dist/data/index.js +5 -539
  44. package/dist/data/invalidation.d.ts +9 -0
  45. package/dist/data/invalidation.d.ts.map +1 -0
  46. package/dist/data/invalidation.js +27 -0
  47. package/dist/data/invalidation.js.map +1 -0
  48. package/dist/data/mutation-cell.d.ts +28 -0
  49. package/dist/data/mutation-cell.d.ts.map +1 -0
  50. package/dist/data/mutation-cell.js +132 -0
  51. package/dist/data/mutation-cell.js.map +1 -0
  52. package/dist/data/query-cell.d.ts +46 -0
  53. package/dist/data/query-cell.d.ts.map +1 -0
  54. package/dist/data/query-cell.js +290 -0
  55. package/dist/data/query-cell.js.map +1 -0
  56. package/dist/data/query-key.js +42 -0
  57. package/dist/data/query-key.js.map +1 -0
  58. package/dist/data/shared.js +20 -0
  59. package/dist/data/shared.js.map +1 -0
  60. package/dist/data/types.d.ts +161 -0
  61. package/dist/data/types.d.ts.map +1 -0
  62. package/dist/foundations/icon/icon.d.ts.map +1 -1
  63. package/dist/foundations/icon/icon.js.map +1 -1
  64. package/dist/foundations/structures/portal.d.ts +1 -1
  65. package/dist/foundations/structures/portal.d.ts.map +1 -1
  66. package/dist/foundations/structures/portal.js +2 -1
  67. package/dist/foundations/structures/portal.js.map +1 -1
  68. package/dist/fx/fx.d.ts +1 -1
  69. package/dist/fx/fx.js +5 -4
  70. package/dist/fx/fx.js.map +1 -1
  71. package/dist/fx/timing.d.ts.map +1 -1
  72. package/dist/fx/timing.js +10 -6
  73. package/dist/fx/timing.js.map +1 -1
  74. package/dist/index.d.ts +3 -2
  75. package/dist/index.js +4 -2
  76. package/dist/index.js.map +1 -1
  77. package/dist/jsx/index.d.ts +2 -1
  78. package/dist/jsx/index.js +3 -2
  79. package/dist/jsx/types.d.ts +2 -0
  80. package/dist/jsx/types.js +2 -1
  81. package/dist/jsx-runtime2.d.ts +2 -1
  82. package/dist/jsx-runtime2.js +3 -2
  83. package/dist/renderer/attributes.js +231 -0
  84. package/dist/renderer/attributes.js.map +1 -0
  85. package/dist/renderer/boundaries.js +266 -0
  86. package/dist/renderer/boundaries.js.map +1 -0
  87. package/dist/renderer/child-shape.js +85 -0
  88. package/dist/renderer/child-shape.js.map +1 -0
  89. package/dist/renderer/children.js +3 -2
  90. package/dist/renderer/children.js.map +1 -1
  91. package/dist/renderer/cleanup.js +2 -1
  92. package/dist/renderer/cleanup.js.map +1 -1
  93. package/dist/renderer/component-host-cleanup.js +68 -0
  94. package/dist/renderer/component-host-cleanup.js.map +1 -0
  95. package/dist/renderer/component-host-instances.js +65 -0
  96. package/dist/renderer/component-host-instances.js.map +1 -0
  97. package/dist/renderer/component-host.js +247 -0
  98. package/dist/renderer/component-host.js.map +1 -0
  99. package/dist/renderer/dom-host.js +13 -0
  100. package/dist/renderer/dom-host.js.map +1 -0
  101. package/dist/renderer/dom-internal.js +185 -0
  102. package/dist/renderer/dom-internal.js.map +1 -0
  103. package/dist/renderer/dom.js +9 -2356
  104. package/dist/renderer/element-children.js +279 -0
  105. package/dist/renderer/element-children.js.map +1 -0
  106. package/dist/renderer/env.js +2 -1
  107. package/dist/renderer/error-boundary-dom.js +29 -0
  108. package/dist/renderer/error-boundary-dom.js.map +1 -0
  109. package/dist/renderer/evaluate-dom-range.js +85 -0
  110. package/dist/renderer/evaluate-dom-range.js.map +1 -0
  111. package/dist/renderer/evaluate-reconcile.js +281 -0
  112. package/dist/renderer/evaluate-reconcile.js.map +1 -0
  113. package/dist/renderer/evaluate.js +13 -399
  114. package/dist/renderer/evaluate.js.map +1 -1
  115. package/dist/renderer/fastpath.js +6 -5
  116. package/dist/renderer/fastpath.js.map +1 -1
  117. package/dist/renderer/for-commit-dom-map.js +83 -0
  118. package/dist/renderer/for-commit-dom-map.js.map +1 -0
  119. package/dist/renderer/for-commit-removal.js +36 -0
  120. package/dist/renderer/for-commit-removal.js.map +1 -0
  121. package/dist/renderer/for-commit-reorder.js +89 -0
  122. package/dist/renderer/for-commit-reorder.js.map +1 -0
  123. package/dist/renderer/for-commit.js +6 -188
  124. package/dist/renderer/for-commit.js.map +1 -1
  125. package/dist/renderer/index.js +28 -16
  126. package/dist/renderer/index.js.map +1 -1
  127. package/dist/renderer/keyed-children.js +32 -0
  128. package/dist/renderer/keyed-children.js.map +1 -0
  129. package/dist/renderer/keyed.js +2 -15
  130. package/dist/renderer/keyed.js.map +1 -1
  131. package/dist/renderer/namespaces.js +23 -0
  132. package/dist/renderer/namespaces.js.map +1 -0
  133. package/dist/renderer/prop-bindings.js +280 -0
  134. package/dist/renderer/prop-bindings.js.map +1 -0
  135. package/dist/renderer/reactive-child-dom.js +133 -0
  136. package/dist/renderer/reactive-child-dom.js.map +1 -0
  137. package/dist/renderer/reactive-child-sources.js +184 -0
  138. package/dist/renderer/reactive-child-sources.js.map +1 -0
  139. package/dist/renderer/reactive-children.js +294 -0
  140. package/dist/renderer/reactive-children.js.map +1 -0
  141. package/dist/renderer/reconcile-commit.js +38 -0
  142. package/dist/renderer/reconcile-commit.js.map +1 -0
  143. package/dist/renderer/reconcile-fastpaths.js +106 -0
  144. package/dist/renderer/reconcile-fastpaths.js.map +1 -0
  145. package/dist/renderer/reconcile-resolution.js +187 -0
  146. package/dist/renderer/reconcile-resolution.js.map +1 -0
  147. package/dist/renderer/reconcile.js +9 -371
  148. package/dist/renderer/reconcile.js.map +1 -1
  149. package/dist/renderer/retained-element-rollback.js +276 -0
  150. package/dist/renderer/retained-element-rollback.js.map +1 -0
  151. package/dist/renderer/stable-patch.js +82 -0
  152. package/dist/renderer/stable-patch.js.map +1 -0
  153. package/dist/renderer/static-reuse.js +96 -0
  154. package/dist/renderer/static-reuse.js.map +1 -0
  155. package/dist/renderer/types.js +2 -1
  156. package/dist/renderer/utils.js +4 -4
  157. package/dist/renderer/utils.js.map +1 -1
  158. package/dist/resources/index.d.ts +3 -2
  159. package/dist/resources/index.js +5 -2
  160. package/dist/router/access.js +36 -0
  161. package/dist/router/access.js.map +1 -0
  162. package/dist/router/activity.d.ts +10 -0
  163. package/dist/router/activity.d.ts.map +1 -0
  164. package/dist/router/activity.js +89 -0
  165. package/dist/router/activity.js.map +1 -0
  166. package/dist/router/authoring.d.ts +22 -0
  167. package/dist/router/authoring.d.ts.map +1 -0
  168. package/dist/router/authoring.js +198 -0
  169. package/dist/router/authoring.js.map +1 -0
  170. package/dist/router/index.d.ts +12 -4
  171. package/dist/router/index.js +9 -2
  172. package/dist/router/internal-types.d.ts +31 -0
  173. package/dist/router/internal-types.d.ts.map +1 -0
  174. package/dist/router/lazy.d.ts +19 -0
  175. package/dist/router/lazy.d.ts.map +1 -0
  176. package/dist/router/lazy.js +52 -0
  177. package/dist/router/lazy.js.map +1 -0
  178. package/dist/router/manifest.d.ts +10 -0
  179. package/dist/router/manifest.d.ts.map +1 -0
  180. package/dist/router/manifest.js +49 -0
  181. package/dist/router/manifest.js.map +1 -0
  182. package/dist/router/navigate.d.ts +4 -33
  183. package/dist/router/navigate.d.ts.map +1 -1
  184. package/dist/router/navigate.js +17 -414
  185. package/dist/router/navigate.js.map +1 -1
  186. package/dist/router/navigation-registry.d.ts +32 -0
  187. package/dist/router/navigation-registry.d.ts.map +1 -0
  188. package/dist/router/navigation-registry.js +105 -0
  189. package/dist/router/navigation-registry.js.map +1 -0
  190. package/dist/router/navigation-scroll.d.ts +14 -0
  191. package/dist/router/navigation-scroll.d.ts.map +1 -0
  192. package/dist/router/navigation-scroll.js +93 -0
  193. package/dist/router/navigation-scroll.js.map +1 -0
  194. package/dist/router/navigation-targets.d.ts +31 -0
  195. package/dist/router/navigation-targets.d.ts.map +1 -0
  196. package/dist/router/navigation-targets.js +253 -0
  197. package/dist/router/navigation-targets.js.map +1 -0
  198. package/dist/router/policy.d.ts +7 -1
  199. package/dist/router/policy.d.ts.map +1 -1
  200. package/dist/router/policy.js +27 -9
  201. package/dist/router/policy.js.map +1 -1
  202. package/dist/router/rendering.d.ts +10 -0
  203. package/dist/router/rendering.d.ts.map +1 -0
  204. package/dist/router/rendering.js +45 -0
  205. package/dist/router/rendering.js.map +1 -0
  206. package/dist/router/resolution.d.ts +17 -0
  207. package/dist/router/resolution.d.ts.map +1 -0
  208. package/dist/router/resolution.js +253 -0
  209. package/dist/router/resolution.js.map +1 -0
  210. package/dist/router/route-query.d.ts +17 -0
  211. package/dist/router/route-query.d.ts.map +1 -0
  212. package/dist/router/route-query.js +47 -0
  213. package/dist/router/route-query.js.map +1 -0
  214. package/dist/router/route.d.ts +8 -149
  215. package/dist/router/route.js +8 -854
  216. package/dist/router/store.d.ts +50 -0
  217. package/dist/router/store.d.ts.map +1 -0
  218. package/dist/router/store.js +171 -0
  219. package/dist/router/store.js.map +1 -0
  220. package/dist/runtime/access.js +45 -0
  221. package/dist/runtime/access.js.map +1 -0
  222. package/dist/runtime/child-scope.d.ts +1 -1
  223. package/dist/runtime/child-scope.js +4 -1
  224. package/dist/runtime/child-scope.js.map +1 -1
  225. package/dist/runtime/component-cleanup.d.ts +16 -0
  226. package/dist/runtime/component-cleanup.d.ts.map +1 -0
  227. package/dist/runtime/component-cleanup.js +70 -0
  228. package/dist/runtime/component-cleanup.js.map +1 -0
  229. package/dist/runtime/component-commit.js +165 -0
  230. package/dist/runtime/component-commit.js.map +1 -0
  231. package/dist/runtime/component-contracts.js +5 -0
  232. package/dist/runtime/component-facade.d.ts +5 -0
  233. package/dist/runtime/component-facade.js +4 -0
  234. package/dist/runtime/component-internal.d.ts +100 -0
  235. package/dist/runtime/component-internal.d.ts.map +1 -0
  236. package/dist/runtime/component-internal.js +219 -0
  237. package/dist/runtime/component-internal.js.map +1 -0
  238. package/dist/runtime/component-lifecycle.d.ts +49 -0
  239. package/dist/runtime/component-lifecycle.d.ts.map +1 -0
  240. package/dist/runtime/component-lifecycle.js +176 -0
  241. package/dist/runtime/component-lifecycle.js.map +1 -0
  242. package/dist/runtime/component-scope.d.ts +55 -0
  243. package/dist/runtime/component-scope.d.ts.map +1 -0
  244. package/dist/runtime/component-scope.js +154 -0
  245. package/dist/runtime/component-scope.js.map +1 -0
  246. package/dist/runtime/component.d.ts +4 -152
  247. package/dist/runtime/component.js +4 -692
  248. package/dist/runtime/context.d.ts +1 -1
  249. package/dist/runtime/context.js +6 -4
  250. package/dist/runtime/context.js.map +1 -1
  251. package/dist/runtime/control.d.ts +3 -3
  252. package/dist/runtime/control.js +2 -1
  253. package/dist/runtime/control.js.map +1 -1
  254. package/dist/runtime/derive.d.ts.map +1 -1
  255. package/dist/runtime/derive.js +6 -5
  256. package/dist/runtime/derive.js.map +1 -1
  257. package/dist/runtime/effect.d.ts +1 -1
  258. package/dist/runtime/effect.d.ts.map +1 -1
  259. package/dist/runtime/effect.js +2 -2
  260. package/dist/runtime/effect.js.map +1 -1
  261. package/dist/runtime/events.js +3 -3
  262. package/dist/runtime/events.js.map +1 -1
  263. package/dist/runtime/fastlane.js +13 -27
  264. package/dist/runtime/fastlane.js.map +1 -1
  265. package/dist/runtime/for-bench.d.ts +1 -1
  266. package/dist/runtime/for-bench.js +1 -4
  267. package/dist/runtime/for-bench.js.map +1 -1
  268. package/dist/runtime/for-internal.d.ts +43 -0
  269. package/dist/runtime/for-internal.d.ts.map +1 -0
  270. package/dist/runtime/for-internal.js +98 -0
  271. package/dist/runtime/for-internal.js.map +1 -0
  272. package/dist/runtime/for-reconcile.d.ts +8 -0
  273. package/dist/runtime/for-reconcile.d.ts.map +1 -0
  274. package/dist/runtime/for-reconcile.js +389 -0
  275. package/dist/runtime/for-reconcile.js.map +1 -0
  276. package/dist/runtime/for-scopes.d.ts +26 -0
  277. package/dist/runtime/for-scopes.d.ts.map +1 -0
  278. package/dist/runtime/for-scopes.js +160 -0
  279. package/dist/runtime/for-scopes.js.map +1 -0
  280. package/dist/runtime/for-signals.d.ts +30 -0
  281. package/dist/runtime/for-signals.d.ts.map +1 -0
  282. package/dist/runtime/for-signals.js +139 -0
  283. package/dist/runtime/for-signals.js.map +1 -0
  284. package/dist/runtime/for.d.ts +4 -66
  285. package/dist/runtime/for.js +5 -773
  286. package/dist/runtime/lifecycle-operations.d.ts +31 -0
  287. package/dist/runtime/lifecycle-operations.d.ts.map +1 -0
  288. package/dist/runtime/lifecycle-operations.js +195 -0
  289. package/dist/runtime/lifecycle-operations.js.map +1 -0
  290. package/dist/runtime/operations.d.ts +3 -40
  291. package/dist/runtime/operations.js +2 -357
  292. package/dist/runtime/readable.d.ts +2 -3
  293. package/dist/runtime/readable.d.ts.map +1 -1
  294. package/dist/runtime/readable.js +6 -5
  295. package/dist/runtime/readable.js.map +1 -1
  296. package/dist/runtime/resource-cell.js +2 -2
  297. package/dist/runtime/resource-cell.js.map +1 -1
  298. package/dist/runtime/resource-operation.d.ts +13 -0
  299. package/dist/runtime/resource-operation.d.ts.map +1 -0
  300. package/dist/runtime/resource-operation.js +170 -0
  301. package/dist/runtime/resource-operation.js.map +1 -0
  302. package/dist/runtime/runtime.d.ts +42 -0
  303. package/dist/runtime/runtime.d.ts.map +1 -0
  304. package/dist/runtime/runtime.js +59 -0
  305. package/dist/runtime/runtime.js.map +1 -0
  306. package/dist/runtime/scheduler.d.ts +5 -1
  307. package/dist/runtime/scheduler.d.ts.map +1 -1
  308. package/dist/runtime/scheduler.js +17 -17
  309. package/dist/runtime/scheduler.js.map +1 -1
  310. package/dist/runtime/selector.js +4 -3
  311. package/dist/runtime/selector.js.map +1 -1
  312. package/dist/runtime/snapshot-source.d.ts +1 -1
  313. package/dist/runtime/snapshot-source.js +1 -1
  314. package/dist/runtime/state.js +2 -1
  315. package/dist/runtime/state.js.map +1 -1
  316. package/dist/ssg/batch-render.js +2 -1
  317. package/dist/ssg/batch-render.js.map +1 -1
  318. package/dist/ssg/create-static-gen.d.ts +9 -3
  319. package/dist/ssg/create-static-gen.d.ts.map +1 -1
  320. package/dist/ssg/create-static-gen.js +12 -99
  321. package/dist/ssg/create-static-gen.js.map +1 -1
  322. package/dist/ssg/generation-plan.js +70 -0
  323. package/dist/ssg/generation-plan.js.map +1 -0
  324. package/dist/ssg/incremental-manifest.js +1 -1
  325. package/dist/ssg/static-routes.js +101 -0
  326. package/dist/ssg/static-routes.js.map +1 -0
  327. package/dist/ssg/types.d.ts +15 -7
  328. package/dist/ssg/types.d.ts.map +1 -1
  329. package/dist/ssr/boundaries.js +113 -0
  330. package/dist/ssr/boundaries.js.map +1 -0
  331. package/dist/ssr/component-runtime.js +111 -0
  332. package/dist/ssr/component-runtime.js.map +1 -0
  333. package/dist/ssr/context.d.ts +3 -1
  334. package/dist/ssr/context.d.ts.map +1 -1
  335. package/dist/ssr/context.js +9 -2
  336. package/dist/ssr/context.js.map +1 -1
  337. package/dist/ssr/errors.d.ts +2 -0
  338. package/dist/ssr/errors.js +11 -1
  339. package/dist/ssr/errors.js.map +1 -1
  340. package/dist/ssr/escape.js +3 -3
  341. package/dist/ssr/escape.js.map +1 -1
  342. package/dist/ssr/hydration-data.js +10 -0
  343. package/dist/ssr/hydration-data.js.map +1 -0
  344. package/dist/ssr/hydration-verify.d.ts +12 -0
  345. package/dist/ssr/hydration-verify.d.ts.map +1 -0
  346. package/dist/ssr/hydration-verify.js +144 -0
  347. package/dist/ssr/hydration-verify.js.map +1 -0
  348. package/dist/ssr/index-internal.d.ts +15 -0
  349. package/dist/ssr/index-internal.d.ts.map +1 -0
  350. package/dist/ssr/index-internal.js +19 -0
  351. package/dist/ssr/index-internal.js.map +1 -0
  352. package/dist/ssr/index.d.ts +5 -57
  353. package/dist/ssr/index.js +3 -738
  354. package/dist/ssr/render-keys.js +9 -32
  355. package/dist/ssr/render-keys.js.map +1 -1
  356. package/dist/ssr/render-resolved.d.ts +1 -1
  357. package/dist/ssr/render-resolved.d.ts.map +1 -1
  358. package/dist/ssr/render-resolved.js +4 -2
  359. package/dist/ssr/render-resolved.js.map +1 -1
  360. package/dist/ssr/render-sync.d.ts +21 -0
  361. package/dist/ssr/render-sync.d.ts.map +1 -0
  362. package/dist/ssr/render-sync.js +275 -0
  363. package/dist/ssr/render-sync.js.map +1 -0
  364. package/dist/ssr/route-policy-resolution.js +77 -0
  365. package/dist/ssr/route-policy-resolution.js.map +1 -0
  366. package/dist/ssr/route-render.d.ts +77 -0
  367. package/dist/ssr/route-render.d.ts.map +1 -0
  368. package/dist/ssr/route-render.js +119 -0
  369. package/dist/ssr/route-render.js.map +1 -0
  370. package/dist/ssr/sink.d.ts +26 -0
  371. package/dist/ssr/sink.d.ts.map +1 -0
  372. package/dist/ssr/types.d.ts +1 -0
  373. package/dist/ssr/types.d.ts.map +1 -1
  374. package/dist/ssr/verify-hydration.js.map +1 -1
  375. package/dist/testing/index.d.ts +1 -2
  376. package/dist/testing/index.d.ts.map +1 -1
  377. package/dist/testing/index.js +2 -1
  378. package/dist/testing/index.js.map +1 -1
  379. package/package.json +4 -3
  380. package/dist/data/index.d.ts.map +0 -1
  381. package/dist/data/index.js.map +0 -1
  382. package/dist/renderer/dom.js.map +0 -1
  383. package/dist/router/route.d.ts.map +0 -1
  384. package/dist/router/route.js.map +0 -1
  385. package/dist/runtime/component.d.ts.map +0 -1
  386. package/dist/runtime/component.js.map +0 -1
  387. package/dist/runtime/for.d.ts.map +0 -1
  388. package/dist/runtime/for.js.map +0 -1
  389. package/dist/runtime/operations.d.ts.map +0 -1
  390. package/dist/runtime/operations.js.map +0 -1
  391. package/dist/runtime/ssr-bridge.js +0 -24
  392. package/dist/runtime/ssr-bridge.js.map +0 -1
  393. package/dist/ssr/index.d.ts.map +0 -1
  394. package/dist/ssr/index.js.map +0 -1
@@ -1,2356 +1,9 @@
1
- import { __ERROR_BOUNDARY__, __FOR_BOUNDARY__, _isDOMElement } from "../common/vnode.js";
2
- import "./types.js";
3
- import { getRuntimeEnv } from "../common/env.js";
4
- import { logger } from "../dev/logger.js";
5
- import { incrementPerfMetric } from "../runtime/perf-metrics.js";
6
- import { globalScheduler } from "../runtime/scheduler.js";
7
- import { Fragment, STATIC_CHILDREN } from "../common/jsx.js";
8
- import { getCurrentContextFrame, getVNodeContextFrame, markVNodeTreeWithContextFrame, withContext } from "../runtime/context.js";
9
- import { getDevValue, incDevCounter } from "../runtime/dev-namespace.js";
10
- import { isPromiseLike } from "../common/promise.js";
11
- import "./env.js";
12
- import { createMutableWrappedHandler, extractKey, getEventListenerKey, getEventListenerOptions, getRenderedAttributeName, isSkippedProp, parseEventName, parseEventProp, readElementClassName, removeRenderedAttribute, setRenderedAttribute, tagNamesEqualIgnoreCase, writeElementClassName } from "./utils.js";
13
- import { keyedElements } from "./keyed.js";
14
- import { captureInlineRenderSnapshot, cleanupComponent, createComponentInstance, getCurrentInstance, mountInstanceInline, renderComponentInline, warnUnusedStateReads } from "../runtime/component.js";
15
- import { addDelegatedListener, getDelegatedHandlerForElement, getDelegatedHandlersForElement, isDelegatedEvent, isEventDelegationEnabled, removeDelegatedListener, updateDelegatedListener } from "../runtime/events.js";
16
- import { REACTIVE_CHILDREN_KEY, elementListeners, elementReactivePropsCleanup, removeAllListeners, removeElementListeners, removeElementReactiveProps, teardownNodeSubtree, updateElementRef } from "./cleanup.js";
17
- import { ROUTE_ROOT_COMPONENT } from "../common/router-internal.js";
18
- import "../jsx-runtime.js";
19
- import { createChildScope, disposeChildScope, rerenderChildScope } from "../runtime/child-scope.js";
20
- import { isBenchMetricScopeActive, recordBenchCounter, recordBenchEvent } from "../runtime/for-bench.js";
21
- import { clearForDomUpdateState, evaluateForState } from "../runtime/for.js";
22
- import { clearCaseDomUpdateState, clearShowDomUpdateState, evaluateCaseState, evaluateShowState } from "../runtime/control.js";
23
- import { commitForStateBoundaryChildren } from "./for-commit.js";
24
- import { reconcileKeyedChildren } from "./reconcile.js";
25
- import { isBulkTextFastPathEligible, performBulkTextReplace } from "./children.js";
26
- import { createFineGrainedEffect, markFineGrainedEffectsDirtySource } from "../runtime/effect.js";
27
- import { createBoundaryReset, reportBoundaryError, resolveErrorBoundaryFallback } from "../components/error-boundary.js";
28
- //#region src/renderer/dom.ts
29
- const reactivePropRegistry = /* @__PURE__ */ new Set();
30
- const controlBoundaryOwners = /* @__PURE__ */ new WeakMap();
31
- function isRouteRootComponentVNode(node) {
32
- return typeof node === "object" && node !== null && node[ROUTE_ROOT_COMPONENT] === true;
33
- }
34
- function inheritComponentCleanupStrict(instance) {
35
- const owner = getCurrentInstance();
36
- if (owner) instance.cleanupStrict = owner.cleanupStrict;
37
- }
38
- let reactiveChildScopeId = 0;
39
- function collectReactiveScalarSequenceValue(value, normalized) {
40
- if (isFragmentVNode(value)) return collectReactiveScalarSequenceValue(value.props?.children ?? value.children, normalized);
41
- if (Array.isArray(value)) {
42
- for (const child of value) if (!collectReactiveScalarSequenceValue(child, normalized)) return false;
43
- return true;
44
- }
45
- if (value === null || value === void 0 || value === false) return true;
46
- if (typeof value === "string" || typeof value === "number") {
47
- normalized.push(String(value));
48
- return true;
49
- }
50
- return false;
51
- }
52
- function collectReactiveScalarChildSource(children, slots, state) {
53
- if (isFragmentVNode(children)) return collectReactiveScalarChildSource(children.props?.children ?? children.children, slots, state);
54
- if (Array.isArray(children)) {
55
- for (const child of children) if (!collectReactiveScalarChildSource(child, slots, state)) return false;
56
- return true;
57
- }
58
- if (children === null || children === void 0 || children === false) return true;
59
- if (typeof children === "function") {
60
- slots.push({
61
- kind: "dynamic",
62
- compute: children
63
- });
64
- state.hasDynamic = true;
65
- return true;
66
- }
67
- if (typeof children === "string" || typeof children === "number") {
68
- slots.push({
69
- kind: "static",
70
- value: String(children)
71
- });
72
- return true;
73
- }
74
- return false;
75
- }
76
- function getReactiveScalarChildSource(children) {
77
- const slots = [];
78
- const state = { hasDynamic: false };
79
- if (!collectReactiveScalarChildSource(children, slots, state)) return null;
80
- return state.hasDynamic ? slots : null;
81
- }
82
- function getSingleReactiveChildBoundarySource(children) {
83
- if (isFragmentVNode(children)) return getSingleReactiveChildBoundarySource(children.props?.children ?? children.children);
84
- if (Array.isArray(children)) {
85
- if (children.length !== 1) return null;
86
- return getSingleReactiveChildBoundarySource(children[0]);
87
- }
88
- if (typeof children === "function") return children;
89
- return null;
90
- }
91
- function collectReactiveChildBoundarySequenceSource(children, slots, state) {
92
- if (isFragmentVNode(children)) return collectReactiveChildBoundarySequenceSource(children.props?.children ?? children.children, slots, state);
93
- if (Array.isArray(children)) {
94
- for (const child of children) if (!collectReactiveChildBoundarySequenceSource(child, slots, state)) return false;
95
- return true;
96
- }
97
- if (children === null || children === void 0 || children === false) return true;
98
- if (typeof children === "function") {
99
- slots.push({
100
- kind: "dynamic",
101
- compute: children
102
- });
103
- state.dynamicCount += 1;
104
- return true;
105
- }
106
- if (typeof children === "string" || typeof children === "number") {
107
- slots.push({
108
- kind: "static-text",
109
- value: String(children)
110
- });
111
- return true;
112
- }
113
- if (_isDOMElement(children)) {
114
- slots.push({
115
- kind: "static-node",
116
- value: children
117
- });
118
- return true;
119
- }
120
- return false;
121
- }
122
- function getReactiveChildBoundarySequenceSource(children) {
123
- const slots = [];
124
- const state = { dynamicCount: 0 };
125
- if (!collectReactiveChildBoundarySequenceSource(children, slots, state)) return null;
126
- return state.dynamicCount >= 1 && slots.length > 1 ? slots : null;
127
- }
128
- function areReactiveChildBoundarySequenceSourcesEqual(previousSource, nextSource) {
129
- if (!Array.isArray(previousSource) || previousSource.length !== nextSource.length) return false;
130
- for (let index = 0; index < nextSource.length; index += 1) {
131
- const previousSlot = previousSource[index];
132
- const nextSlot = nextSource[index];
133
- if (!previousSlot || previousSlot.kind !== nextSlot.kind) return false;
134
- if (nextSlot.kind === "static-text") {
135
- if (previousSlot.kind !== "static-text" || previousSlot.value !== nextSlot.value) return false;
136
- continue;
137
- }
138
- if (nextSlot.kind === "static-node") {
139
- if (previousSlot.kind !== "static-node" || previousSlot.value !== nextSlot.value) return false;
140
- continue;
141
- }
142
- if (previousSlot.kind !== "dynamic" || previousSlot.compute !== nextSlot.compute) return false;
143
- }
144
- return true;
145
- }
146
- function cleanupDetachedComponentHost(host, retainedInstance) {
147
- removeElementListeners(host);
148
- removeElementReactiveProps(host);
149
- const hostInstances = host.__ASKR_INSTANCES;
150
- if (hostInstances && hostInstances.length > 0) for (const instance of hostInstances) {
151
- if (instance === retainedInstance) continue;
152
- cleanupComponent(instance);
153
- }
154
- else if (host.__ASKR_INSTANCE && host.__ASKR_INSTANCE !== retainedInstance) cleanupComponent(host.__ASKR_INSTANCE);
155
- const descendants = host.querySelectorAll("*");
156
- for (let index = 0; index < descendants.length; index += 1) {
157
- const descendant = descendants[index];
158
- removeElementListeners(descendant);
159
- removeElementReactiveProps(descendant);
160
- if (descendant.__ASKR_INSTANCES?.length) {
161
- for (const instance of descendant.__ASKR_INSTANCES) {
162
- if (instance === retainedInstance) continue;
163
- cleanupComponent(instance);
164
- }
165
- try {
166
- delete descendant.__ASKR_INSTANCES;
167
- } catch {}
168
- } else if (descendant.__ASKR_INSTANCE && descendant.__ASKR_INSTANCE !== retainedInstance) {
169
- cleanupComponent(descendant.__ASKR_INSTANCE);
170
- try {
171
- delete descendant.__ASKR_INSTANCE;
172
- } catch {}
173
- }
174
- }
175
- try {
176
- delete host.__ASKR_INSTANCE;
177
- delete host.__ASKR_INSTANCES;
178
- delete host.__ASKR_WRAPPER_HOST;
179
- } catch {}
180
- }
181
- function pruneComponentHostInstances(host, retainedInstances) {
182
- const retained = new Set(retainedInstances);
183
- const nextInstances = [];
184
- const staleInstances = /* @__PURE__ */ new Set();
185
- const retainOrMarkStale = (instance) => {
186
- if (!instance) return;
187
- if (retained.has(instance)) {
188
- if (!nextInstances.includes(instance)) nextInstances.push(instance);
189
- return;
190
- }
191
- staleInstances.add(instance);
192
- };
193
- for (const instance of host.__ASKR_INSTANCES ?? []) retainOrMarkStale(instance);
194
- retainOrMarkStale(host.__ASKR_INSTANCE);
195
- for (const instance of staleInstances) cleanupComponent(instance);
196
- try {
197
- if (nextInstances.length > 0) {
198
- host.__ASKR_INSTANCES = nextInstances;
199
- host.__ASKR_INSTANCE = nextInstances[0];
200
- } else {
201
- delete host.__ASKR_INSTANCES;
202
- delete host.__ASKR_INSTANCE;
203
- }
204
- } catch {}
205
- }
206
- function canUpdateReactiveChildBoundarySequenceSource(previousSource, nextSource) {
207
- if (!Array.isArray(previousSource) || previousSource.length !== nextSource.length) return false;
208
- for (let index = 0; index < nextSource.length; index += 1) {
209
- const previousSlot = previousSource[index];
210
- const nextSlot = nextSource[index];
211
- if (!previousSlot || previousSlot.kind !== nextSlot.kind) return false;
212
- if (nextSlot.kind === "static-text") {
213
- if (previousSlot.kind !== "static-text" || previousSlot.value !== nextSlot.value) return false;
214
- continue;
215
- }
216
- if (nextSlot.kind === "static-node") {
217
- if (previousSlot.kind !== "static-node" || previousSlot.value !== nextSlot.value) return false;
218
- }
219
- }
220
- return true;
221
- }
222
- function areReactiveScalarChildSourcesEqual(previousSource, nextSource) {
223
- if (!Array.isArray(previousSource) || previousSource.length !== nextSource.length) return false;
224
- for (let index = 0; index < nextSource.length; index += 1) {
225
- const previousSlot = previousSource[index];
226
- const nextSlot = nextSource[index];
227
- if (!previousSlot || previousSlot.kind !== nextSlot.kind) return false;
228
- if (nextSlot.kind === "static") {
229
- if (previousSlot.kind !== "static" || previousSlot.value !== nextSlot.value) return false;
230
- continue;
231
- }
232
- if (previousSlot.kind !== "dynamic" || previousSlot.compute !== nextSlot.compute) return false;
233
- }
234
- return true;
235
- }
236
- function getOrCreateElementReactiveCleanupMap(el) {
237
- let cleanupMap = elementReactivePropsCleanup.get(el);
238
- if (!cleanupMap) {
239
- cleanupMap = /* @__PURE__ */ new Map();
240
- elementReactivePropsCleanup.set(el, cleanupMap);
241
- }
242
- return cleanupMap;
243
- }
244
- function normalizeReactiveScalarSequenceValues(values) {
245
- const normalized = [];
246
- for (const value of values) if (!collectReactiveScalarSequenceValue(value, normalized)) return null;
247
- return normalized;
248
- }
249
- function normalizeOwnedReactiveTextValue(value) {
250
- if (typeof value === "string" || typeof value === "number") return String(value);
251
- return null;
252
- }
253
- function collectReactiveChildValuesAsVNodes(values, children) {
254
- for (const value of values) collectReactiveChildBoundaryVNodes(value, children);
255
- }
256
- function materializeReactiveChildBoundaryNodes(value, parentNamespace) {
257
- const nodes = [];
258
- const dom = createDOMNode(value, parentNamespace);
259
- if (!dom) return nodes;
260
- if (dom instanceof DocumentFragment) {
261
- for (let child = dom.firstChild; child; child = dom.firstChild) {
262
- nodes.push(child);
263
- dom.removeChild(child);
264
- }
265
- return nodes;
266
- }
267
- nodes.push(dom);
268
- return nodes;
269
- }
270
- function syncReactiveScalarTextNodes(el, slotValues, values) {
271
- const childNodes = el.childNodes;
272
- if (childNodes.length === values.length) {
273
- let allText = true;
274
- for (let index = 0; index < childNodes.length; index += 1) if (childNodes[index]?.nodeType !== Node.TEXT_NODE) {
275
- allText = false;
276
- break;
277
- }
278
- if (allText) {
279
- for (let index = 0; index < values.length; index += 1) {
280
- const textNode = childNodes[index];
281
- if (textNode.data !== values[index]) textNode.data = values[index];
282
- }
283
- return;
284
- }
285
- }
286
- const host = createReactiveChildBoundaryHost(el);
287
- for (let node = el.firstChild; node;) {
288
- const next = node.nextSibling;
289
- host.appendChild(node);
290
- node = next;
291
- }
292
- updateElementChildren(host, slotValues);
293
- syncReactiveChildExpectedNodes(el, Array.from(host.childNodes));
294
- }
295
- function trySyncScalarChildSequenceInPlace(el, children) {
296
- const normalized = normalizeReactiveScalarSequenceValues(children);
297
- if (!normalized) return false;
298
- if (el.childNodes.length !== normalized.length) return false;
299
- for (let index = 0; index < el.childNodes.length; index += 1) if (el.childNodes[index]?.nodeType !== Node.TEXT_NODE) return false;
300
- syncReactiveScalarTextNodes(el, children, normalized);
301
- return true;
302
- }
303
- function normalizeReactiveChildBoundaryVNode(value) {
304
- if (!isFragmentVNode(value)) return value;
305
- const children = normalizeComponentChildren(value);
306
- if (children.length !== 1) return value;
307
- return normalizeReactiveChildBoundaryVNode(children[0]);
308
- }
309
- function isSingleRootReactiveChildBoundaryValue(value) {
310
- if (value === null || value === void 0 || value === false) return true;
311
- if (Array.isArray(value)) return value.length === 1 && isSingleRootReactiveChildBoundaryValue(value[0]);
312
- if (isFragmentVNode(value)) {
313
- const children = normalizeComponentChildren(value);
314
- return children.length === 1 && isSingleRootReactiveChildBoundaryValue(children[0]);
315
- }
316
- return true;
317
- }
318
- function collectReactiveChildBoundaryVNodes(value, children) {
319
- if (value === null || value === void 0 || value === false) return;
320
- if (Array.isArray(value)) {
321
- for (const child of value) collectReactiveChildBoundaryVNodes(child, children);
322
- return;
323
- }
324
- if (isFragmentVNode(value)) {
325
- collectReactiveChildBoundaryVNodes(value.props?.children ?? value.children, children);
326
- return;
327
- }
328
- children.push(value);
329
- }
330
- function createReactiveChildBoundaryHost(el) {
331
- const ownerDocument = el.ownerDocument;
332
- return el.namespaceURI === SVG_NAMESPACE ? ownerDocument.createElementNS(SVG_NAMESPACE, "g") : ownerDocument.createElement("div");
333
- }
334
- function disposeReactiveChildBoundaryNodes(nodes) {
335
- for (const node of nodes) {
336
- if (node.parentNode) node.parentNode.removeChild(node);
337
- teardownNodeSubtree(node);
338
- }
339
- }
340
- function syncReactiveChildExpectedNodes(el, expectedNodes) {
341
- const expectedNodeSet = new Set(expectedNodes);
342
- for (let node = el.firstChild; node;) {
343
- const next = node.nextSibling;
344
- if (!expectedNodeSet.has(node)) {
345
- teardownNodeSubtree(node);
346
- el.removeChild(node);
347
- }
348
- node = next;
349
- }
350
- let anchor = el.firstChild;
351
- for (const node of expectedNodes) {
352
- if (node === anchor) {
353
- anchor = anchor.nextSibling;
354
- continue;
355
- }
356
- el.insertBefore(node, anchor);
357
- anchor = node.nextSibling;
358
- }
359
- }
360
- function commitReactiveChildBoundaryEntryNodes(el, entry) {
361
- if (!entry.scope.needsDomUpdate) return entry.nodes;
362
- if (entry.scope.vnode === null || entry.scope.vnode === void 0 || entry.scope.vnode === false) {
363
- if (entry.nodes.length > 0) {
364
- disposeReactiveChildBoundaryNodes(entry.nodes);
365
- entry.nodes = [];
366
- }
367
- const dom = entry.scope.dom;
368
- if (dom?.parentNode === el) {
369
- teardownNodeSubtree(dom);
370
- el.removeChild(dom);
371
- }
372
- entry.scope.dom = void 0;
373
- entry.scope.needsDomUpdate = false;
374
- return entry.nodes;
375
- }
376
- if (!isSingleRootReactiveChildBoundaryValue(entry.scope.vnode)) {
377
- const nextChildren = [];
378
- collectReactiveChildBoundaryVNodes(entry.scope.vnode, nextChildren);
379
- const host = createReactiveChildBoundaryHost(el);
380
- for (const node of entry.nodes) host.appendChild(node);
381
- updateElementChildren(host, nextChildren);
382
- const nextNodes = Array.from(host.childNodes);
383
- entry.scope.dom = void 0;
384
- entry.scope.needsDomUpdate = false;
385
- entry.nodes = nextNodes;
386
- return nextNodes;
387
- }
388
- if (entry.nodes.length > 1) {
389
- disposeReactiveChildBoundaryNodes(entry.nodes);
390
- entry.nodes = [];
391
- entry.scope.dom = void 0;
392
- }
393
- const nextDom = syncForItemDom(el, entry.scope, entry.scope.vnode ?? null);
394
- if (!nextDom) {
395
- entry.nodes = [];
396
- entry.scope.needsDomUpdate = false;
397
- return entry.nodes;
398
- }
399
- entry.nodes = [nextDom];
400
- entry.scope.needsDomUpdate = false;
401
- return entry.nodes;
402
- }
403
- function syncReactiveChildSequenceNodes(el, entries) {
404
- const expectedNodes = [];
405
- for (const entry of entries) {
406
- if (entry.kind === "static") {
407
- expectedNodes.push(...entry.nodes);
408
- continue;
409
- }
410
- expectedNodes.push(...commitReactiveChildBoundaryEntryNodes(el, entry));
411
- }
412
- syncReactiveChildExpectedNodes(el, expectedNodes);
413
- }
414
- function setupReactiveScalarChild(el, source) {
415
- let currentSource = source;
416
- if (source.length === 1 && source[0]?.kind === "dynamic") {
417
- let ownedTextNode = el.childNodes.length === 1 && el.firstChild?.nodeType === Node.TEXT_NODE ? el.firstChild : null;
418
- let effectHandle = createFineGrainedEffect({
419
- lane: "reactive",
420
- compute: () => {
421
- const currentSlot = currentSource[0];
422
- if (!currentSlot || currentSlot.kind !== "dynamic") throw new Error("[Askr] Direct reactive text bindings require a single dynamic slot.");
423
- const rawValue = currentSlot.compute();
424
- return normalizeOwnedReactiveTextValue(rawValue) ?? rawValue;
425
- },
426
- commit: (value) => {
427
- const normalized = normalizeOwnedReactiveTextValue(value);
428
- if (normalized === null) {
429
- ownedTextNode = null;
430
- updateElementChildren(el, value);
431
- return;
432
- }
433
- if (!ownedTextNode || el.childNodes.length !== 1 || el.firstChild !== ownedTextNode) {
434
- updateElementChildren(el, normalized);
435
- ownedTextNode = el.childNodes.length === 1 && el.firstChild?.nodeType === Node.TEXT_NODE ? el.firstChild : null;
436
- }
437
- if (!ownedTextNode) return;
438
- if (ownedTextNode.data !== normalized) {
439
- ownedTextNode.data = normalized;
440
- incDevCounter("textNodeWrites");
441
- }
442
- },
443
- onError: (err) => {
444
- if (getRuntimeEnv().NODE_ENV !== "production") logger.warn("[Askr] Reactive child update failed:", err);
445
- }
446
- });
447
- return {
448
- cleanup: () => {
449
- effectHandle?.cleanup();
450
- effectHandle = null;
451
- },
452
- updateFn: (nextSource) => {
453
- if (!effectHandle) return;
454
- currentSource = nextSource;
455
- effectHandle.updateCompute(() => {
456
- const currentSlot = currentSource[0];
457
- if (!currentSlot || currentSlot.kind !== "dynamic") throw new Error("[Askr] Direct reactive text bindings require a single dynamic slot.");
458
- const rawValue = currentSlot.compute();
459
- return normalizeOwnedReactiveTextValue(rawValue) ?? rawValue;
460
- });
461
- }
462
- };
463
- }
464
- let effectHandle = createFineGrainedEffect({
465
- lane: "reactive",
466
- compute: () => currentSource.map((slot) => slot.kind === "static" ? slot.value : slot.compute()),
467
- commit: (values) => {
468
- if (!Array.isArray(values)) throw new Error("[Askr] Reactive scalar children must evaluate to a slot array.");
469
- const normalized = normalizeReactiveScalarSequenceValues(values);
470
- if (normalized) {
471
- syncReactiveScalarTextNodes(el, values, normalized);
472
- return;
473
- }
474
- const nextChildren = [];
475
- collectReactiveChildValuesAsVNodes(values, nextChildren);
476
- const host = createReactiveChildBoundaryHost(el);
477
- for (let node = el.firstChild; node;) {
478
- const next = node.nextSibling;
479
- host.appendChild(node);
480
- node = next;
481
- }
482
- updateElementChildren(host, nextChildren);
483
- syncReactiveChildExpectedNodes(el, Array.from(host.childNodes));
484
- },
485
- equals: (previousValue, nextValue) => {
486
- if (!Array.isArray(previousValue) || !Array.isArray(nextValue)) return false;
487
- const previousNormalized = normalizeReactiveScalarSequenceValues(previousValue);
488
- const nextNormalized = normalizeReactiveScalarSequenceValues(nextValue);
489
- if (!previousNormalized || !nextNormalized) return false;
490
- if (previousNormalized.length !== nextNormalized.length) return false;
491
- for (let index = 0; index < previousNormalized.length; index += 1) if (previousNormalized[index] !== nextNormalized[index]) return false;
492
- return true;
493
- },
494
- onError: (err) => {
495
- if (getRuntimeEnv().NODE_ENV !== "production") logger.warn("[Askr] Reactive child update failed:", err);
496
- }
497
- });
498
- return {
499
- cleanup: () => {
500
- effectHandle?.cleanup();
501
- effectHandle = null;
502
- },
503
- updateFn: (nextSource) => {
504
- if (!effectHandle) return;
505
- currentSource = nextSource;
506
- effectHandle.updateCompute(() => currentSource.map((slot) => slot.kind === "static" ? slot.value : slot.compute()));
507
- }
508
- };
509
- }
510
- function setupReactiveChildBoundary(el, childFn) {
511
- let currentChildFn = childFn;
512
- const entry = {
513
- scope: createChildScope(getCurrentInstance(), `__reactive-child__:${reactiveChildScopeId += 1}`, () => {
514
- syncReactiveChildExpectedNodes(el, commitReactiveChildBoundaryEntryNodes(el, entry));
515
- }),
516
- nodes: []
517
- };
518
- entry.scope.render(() => normalizeReactiveChildBoundaryVNode(currentChildFn()));
519
- syncReactiveChildExpectedNodes(el, commitReactiveChildBoundaryEntryNodes(el, entry));
520
- return {
521
- cleanup: () => {
522
- const dom = entry.scope.dom;
523
- const nodes = entry.nodes;
524
- disposeChildScope(entry.scope);
525
- entry.nodes = [];
526
- if (nodes.length > 0) {
527
- disposeReactiveChildBoundaryNodes(nodes);
528
- return;
529
- }
530
- if (dom?.parentNode === el) {
531
- teardownNodeSubtree(dom);
532
- el.removeChild(dom);
533
- }
534
- },
535
- updateFn: (nextValue) => {
536
- currentChildFn = nextValue;
537
- rerenderChildScope(entry.scope);
538
- syncReactiveChildExpectedNodes(el, commitReactiveChildBoundaryEntryNodes(el, entry));
539
- }
540
- };
541
- }
542
- function setupReactiveChildBoundarySequence(el, source) {
543
- let currentSource = source;
544
- const parentInstance = getCurrentInstance();
545
- const entries = [];
546
- const dynamicEntries = [];
547
- if (!currentSource.some((slot) => slot.kind === "dynamic")) throw new Error("[Askr] Reactive child boundary sequence requires at least one dynamic slot.");
548
- const syncSequence = () => {
549
- syncReactiveChildSequenceNodes(el, entries);
550
- };
551
- const parentNamespace = el.namespaceURI === SVG_NAMESPACE ? SVG_NAMESPACE : void 0;
552
- for (let index = 0; index < currentSource.length; index += 1) {
553
- const slot = currentSource[index];
554
- if (!slot) continue;
555
- if (slot.kind === "static-text") {
556
- entries.push({
557
- kind: "static",
558
- nodes: [document.createTextNode(slot.value)]
559
- });
560
- continue;
561
- }
562
- if (slot.kind === "static-node") {
563
- entries.push({
564
- kind: "static",
565
- nodes: materializeReactiveChildBoundaryNodes(slot.value, parentNamespace)
566
- });
567
- continue;
568
- }
569
- const dynamicEntry = {
570
- kind: "dynamic",
571
- scope: createChildScope(parentInstance, `__reactive-child-seq__:${reactiveChildScopeId += 1}`, syncSequence),
572
- nodes: []
573
- };
574
- entries.push(dynamicEntry);
575
- dynamicEntries.push({
576
- index,
577
- entry: dynamicEntry
578
- });
579
- }
580
- for (const dynamicEntry of dynamicEntries) dynamicEntry.entry.scope.render(() => normalizeReactiveChildBoundaryVNode(currentSource[dynamicEntry.index].compute()));
581
- syncSequence();
582
- return {
583
- cleanup: () => {
584
- for (const dynamicEntry of dynamicEntries) {
585
- const dom = dynamicEntry.entry.scope.dom;
586
- const nodes = dynamicEntry.entry.nodes;
587
- disposeChildScope(dynamicEntry.entry.scope);
588
- if (nodes.length > 0) {
589
- disposeReactiveChildBoundaryNodes(nodes);
590
- continue;
591
- }
592
- if (dom?.parentNode === el) {
593
- teardownNodeSubtree(dom);
594
- el.removeChild(dom);
595
- }
596
- }
597
- for (const entry of entries) if (entry.kind === "static") disposeReactiveChildBoundaryNodes(entry.nodes);
598
- },
599
- updateFn: (nextValue) => {
600
- currentSource = nextValue;
601
- for (const dynamicEntry of dynamicEntries) rerenderChildScope(dynamicEntry.entry.scope);
602
- syncSequence();
603
- }
604
- };
605
- }
606
- function syncReactiveScalarChild(el, children) {
607
- const reactiveChildSource = getReactiveScalarChildSource(children);
608
- const reactiveChildBoundary = getSingleReactiveChildBoundarySource(children);
609
- const reactiveChildBoundarySequence = getReactiveChildBoundarySequenceSource(children);
610
- const existingReactiveEntry = elementReactivePropsCleanup.get(el)?.get(REACTIVE_CHILDREN_KEY);
611
- if (!reactiveChildSource && !reactiveChildBoundary && !reactiveChildBoundarySequence) {
612
- if (existingReactiveEntry) {
613
- existingReactiveEntry.cleanup();
614
- const cleanupMap = elementReactivePropsCleanup.get(el);
615
- cleanupMap?.delete(REACTIVE_CHILDREN_KEY);
616
- if (cleanupMap && cleanupMap.size === 0) elementReactivePropsCleanup.delete(el);
617
- }
618
- return false;
619
- }
620
- if (reactiveChildSource && !reactiveChildBoundarySequence) {
621
- if (existingReactiveEntry && Array.isArray(existingReactiveEntry.fnRef) && areReactiveScalarChildSourcesEqual(existingReactiveEntry.fnRef, reactiveChildSource)) return true;
622
- if (existingReactiveEntry?.updateFn && Array.isArray(existingReactiveEntry.fnRef)) {
623
- existingReactiveEntry.updateFn(reactiveChildSource);
624
- existingReactiveEntry.fnRef = reactiveChildSource;
625
- return true;
626
- }
627
- existingReactiveEntry?.cleanup();
628
- try {
629
- const reactive = setupReactiveScalarChild(el, reactiveChildSource);
630
- getOrCreateElementReactiveCleanupMap(el).set(REACTIVE_CHILDREN_KEY, {
631
- cleanup: reactive.cleanup,
632
- updateFn: (nextValue) => {
633
- reactive.updateFn(nextValue);
634
- },
635
- fnRef: reactiveChildSource
636
- });
637
- return true;
638
- } catch (error) {
639
- if (!reactiveChildBoundary && !reactiveChildBoundarySequence) throw error;
640
- }
641
- }
642
- if (reactiveChildBoundarySequence) {
643
- if (existingReactiveEntry && Array.isArray(existingReactiveEntry.fnRef) && areReactiveChildBoundarySequenceSourcesEqual(existingReactiveEntry.fnRef, reactiveChildBoundarySequence)) return true;
644
- if (existingReactiveEntry?.updateFn && Array.isArray(existingReactiveEntry.fnRef) && canUpdateReactiveChildBoundarySequenceSource(existingReactiveEntry.fnRef, reactiveChildBoundarySequence)) {
645
- existingReactiveEntry.updateFn(reactiveChildBoundarySequence);
646
- existingReactiveEntry.fnRef = reactiveChildBoundarySequence;
647
- return true;
648
- }
649
- existingReactiveEntry?.cleanup();
650
- const reactive = setupReactiveChildBoundarySequence(el, reactiveChildBoundarySequence);
651
- getOrCreateElementReactiveCleanupMap(el).set(REACTIVE_CHILDREN_KEY, {
652
- cleanup: reactive.cleanup,
653
- updateFn: reactive.updateFn,
654
- fnRef: reactiveChildBoundarySequence
655
- });
656
- return true;
657
- }
658
- if (existingReactiveEntry?.fnRef === reactiveChildBoundary) return true;
659
- if (existingReactiveEntry?.updateFn && !Array.isArray(existingReactiveEntry.fnRef)) {
660
- existingReactiveEntry.updateFn(reactiveChildBoundary);
661
- existingReactiveEntry.fnRef = reactiveChildBoundary;
662
- return true;
663
- }
664
- existingReactiveEntry?.cleanup();
665
- if (!reactiveChildBoundary) return false;
666
- const reactive = setupReactiveChildBoundary(el, reactiveChildBoundary);
667
- getOrCreateElementReactiveCleanupMap(el).set(REACTIVE_CHILDREN_KEY, {
668
- cleanup: reactive.cleanup,
669
- updateFn: reactive.updateFn,
670
- fnRef: reactiveChildBoundary
671
- });
672
- return true;
673
- }
674
- const vnodeComponentInstances = /* @__PURE__ */ new WeakMap();
675
- function getVNodeComponentInstance(node) {
676
- if (typeof node !== "object" || node === null) return;
677
- return vnodeComponentInstances.get(node) ?? node.__instance;
678
- }
679
- function setVNodeComponentInstance(node, instance) {
680
- if (typeof node !== "object" || node === null) return;
681
- const objectNode = node;
682
- if (Object.prototype.hasOwnProperty.call(objectNode, "__instance")) try {
683
- objectNode.__instance = instance;
684
- return;
685
- } catch {}
686
- if (Object.isExtensible(objectNode)) try {
687
- objectNode.__instance = instance;
688
- return;
689
- } catch {}
690
- vnodeComponentInstances.set(objectNode, instance);
691
- }
692
- const IS_DOM_AVAILABLE = typeof document !== "undefined";
693
- const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
694
- function resolveChildNamespace(type, parentNamespace) {
695
- if (type === "svg") return SVG_NAMESPACE;
696
- if (parentNamespace === SVG_NAMESPACE && type !== "foreignObject") return SVG_NAMESPACE;
697
- }
698
- function createElementForNamespace(type, parentNamespace) {
699
- const namespace = resolveChildNamespace(type, parentNamespace);
700
- return namespace ? document.createElementNS(namespace, type) : document.createElement(type);
701
- }
702
- function getHydrationSkipBoundary(el) {
703
- return el.closest("[data-skip-hydrate=\"true\"]");
704
- }
705
- function isHydrationSkipped(el) {
706
- return getHydrationSkipBoundary(el) !== null;
707
- }
708
- function clearHydrationDeferredSubtree(el) {
709
- const boundary = getHydrationSkipBoundary(el);
710
- if (!boundary) return;
711
- if (boundary === el) {
712
- removeAllListeners(el);
713
- removeElementReactiveProps(el);
714
- }
715
- }
716
- let fallbackComponentInstanceId = 0;
717
- function nextComponentInstanceId() {
718
- const key = "__COMPONENT_INSTANCE_ID";
719
- try {
720
- incDevCounter(key);
721
- const n = getDevValue(key);
722
- if (typeof n === "number" && Number.isFinite(n)) return `comp-${n}`;
723
- } catch {}
724
- fallbackComponentInstanceId++;
725
- return `comp-${fallbackComponentInstanceId}`;
726
- }
727
- /**
728
- * Add an event listener to an element with tracking
729
- * Uses event delegation when enabled (opt-out model)
730
- */
731
- function addTrackedListener(el, eventName, handler, capture = false) {
732
- const useDelegation = !capture && isEventDelegationEnabled() && isDelegatedEvent(eventName);
733
- const listenerKey = getEventListenerKey(eventName, capture);
734
- if (useDelegation) {
735
- addDelegatedListener(el, eventName, handler, handler, void 0);
736
- if (isBenchMetricScopeActive("coldCreate")) recordBenchCounter("listenerBindings");
737
- return;
738
- }
739
- const options = getEventListenerOptions(eventName, capture);
740
- const mutableHandler = createMutableWrappedHandler(handler, true);
741
- const trackedHandler = mutableHandler.handler;
742
- if (options !== void 0) el.addEventListener(eventName, trackedHandler, options);
743
- else el.addEventListener(eventName, trackedHandler);
744
- incDevCounter("listenerAdds");
745
- if (!elementListeners.has(el)) elementListeners.set(el, /* @__PURE__ */ new Map());
746
- elementListeners.get(el).set(listenerKey, {
747
- handler: trackedHandler,
748
- original: handler,
749
- eventName,
750
- options,
751
- isDelegated: false,
752
- updateHandler: mutableHandler?.updateHandler
753
- });
754
- if (isBenchMetricScopeActive("coldCreate")) recordBenchCounter("listenerBindings");
755
- }
756
- function markReactivePropsDirtySource(source) {
757
- markFineGrainedEffectsDirtySource(source);
758
- }
759
- /**
760
- * Set up a reactive prop that re-evaluates when its dependencies change
761
- * Returns a cleanup function to unsubscribe
762
- */
763
- function setupReactiveProp(el, propName, propFn, tagName) {
764
- const descriptor = {
765
- el,
766
- propName,
767
- propFn,
768
- tagName,
769
- lastClassTokens: null
770
- };
771
- let effectHandle = null;
772
- reactivePropRegistry.add(descriptor);
773
- effectHandle = createFineGrainedEffect({
774
- lane: "reactive",
775
- compute: () => descriptor.propFn(),
776
- commit: (value, previousValue) => {
777
- incrementPerfMetric("reactivePropReevaluations");
778
- applyPropValue(el, propName, value, tagName, previousValue, descriptor);
779
- },
780
- equals: (previousValue, nextValue) => {
781
- if (Object.is(previousValue, nextValue)) {
782
- incrementPerfMetric("skippedDomPropWrites");
783
- return true;
784
- }
785
- return false;
786
- },
787
- onError: (err) => {
788
- if (getRuntimeEnv().NODE_ENV !== "production") logger.warn("[Askr] Reactive prop update failed:", err);
789
- }
790
- });
791
- if (isBenchMetricScopeActive("coldCreate")) recordBenchCounter("reactivePropsMounted");
792
- const cleanup = () => {
793
- reactivePropRegistry.delete(descriptor);
794
- effectHandle?.cleanup();
795
- effectHandle = null;
796
- };
797
- const updateFn = (nextFn) => {
798
- if (!effectHandle) return;
799
- descriptor.propFn = nextFn;
800
- try {
801
- effectHandle.updateCompute(nextFn);
802
- } catch (err) {
803
- if (getRuntimeEnv().NODE_ENV !== "production") logger.warn("[Askr] Reactive prop update failed:", err);
804
- }
805
- };
806
- return {
807
- cleanup,
808
- updateFn
809
- };
810
- }
811
- /**
812
- * Apply a prop value to an element (helper for reactive props)
813
- */
814
- function applyPropValue(el, key, value, tagName, previousValue, descriptor) {
815
- if (value === void 0 || value === null || value === false) {
816
- if (key === "class" || key === "className") {
817
- const previousTokens = descriptor?.lastClassTokens;
818
- if (previousTokens && previousTokens.length > 0) {
819
- el.classList.remove(...previousTokens);
820
- incrementPerfMetric("classListPatchOps");
821
- } else writeElementClassName(el, "");
822
- if (descriptor) descriptor.lastClassTokens = [];
823
- } else if (key === "value") applyFormControlProp(el, key, "", tagName);
824
- else if (key === "checked") applyFormControlProp(el, key, false, tagName);
825
- else if (key === "style") applyStylePropValue(el, null);
826
- else removeRenderedAttribute(el, key);
827
- return;
828
- }
829
- if (key === "class" || key === "className") applyClassPropValue(el, value, previousValue, descriptor);
830
- else if (key === "style") applyStylePropValue(el, value);
831
- else if (key === "value" || key === "checked") applyFormControlProp(el, key, value, tagName);
832
- else setRenderedAttribute(el, key, String(value));
833
- }
834
- function normalizeStylePropertyName(propertyName) {
835
- if (propertyName.startsWith("--")) return propertyName;
836
- return propertyName.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
837
- }
838
- function collectCurrentStyleEntries(el) {
839
- const entries = /* @__PURE__ */ new Map();
840
- const style = el.style;
841
- if (!style) return entries;
842
- for (let index = 0; index < style.length; index += 1) {
843
- const propertyName = style.item(index);
844
- entries.set(propertyName, style.getPropertyValue(propertyName));
845
- }
846
- return entries;
847
- }
848
- function normalizeStyleEntries(value) {
849
- if (!value || typeof value !== "object" || Array.isArray(value)) return null;
850
- const entries = /* @__PURE__ */ new Map();
851
- for (const [key, entryValue] of Object.entries(value)) {
852
- if (entryValue === void 0 || entryValue === null || entryValue === false) continue;
853
- entries.set(normalizeStylePropertyName(key), String(entryValue));
854
- }
855
- return entries;
856
- }
857
- function applyStylePropValue(el, value) {
858
- const style = el.style;
859
- if (!style) {
860
- if (value === null || value === void 0 || value === false) {
861
- el.removeAttribute("style");
862
- return;
863
- }
864
- el.setAttribute("style", String(value));
865
- return;
866
- }
867
- if (value === null || value === void 0 || value === false) {
868
- if (!el.getAttribute("style")) {
869
- incrementPerfMetric("skippedDomPropWrites");
870
- return;
871
- }
872
- style.cssText = "";
873
- el.removeAttribute("style");
874
- return;
875
- }
876
- if (typeof value === "string") {
877
- if ((el.getAttribute("style") ?? "") === value) {
878
- incrementPerfMetric("skippedDomPropWrites");
879
- return;
880
- }
881
- style.cssText = value;
882
- return;
883
- }
884
- const nextEntries = normalizeStyleEntries(value);
885
- if (!nextEntries) {
886
- const nextText = String(value);
887
- if ((el.getAttribute("style") ?? "") === nextText) {
888
- incrementPerfMetric("skippedDomPropWrites");
889
- return;
890
- }
891
- style.cssText = nextText;
892
- return;
893
- }
894
- const previousEntries = collectCurrentStyleEntries(el);
895
- let didWrite = false;
896
- for (const [propertyName] of previousEntries) {
897
- if (nextEntries.has(propertyName)) continue;
898
- style.removeProperty(propertyName);
899
- didWrite = true;
900
- }
901
- for (const [propertyName, propertyValue] of nextEntries) {
902
- if (previousEntries.get(propertyName) === propertyValue) continue;
903
- style.setProperty(propertyName, propertyValue);
904
- didWrite = true;
905
- }
906
- if (!didWrite) incrementPerfMetric("skippedDomPropWrites");
907
- }
908
- function tokenizeClassValue(value) {
909
- if (typeof value !== "string") return null;
910
- const trimmed = value.trim();
911
- if (trimmed.length === 0) return [];
912
- return trimmed.split(/\s+/);
913
- }
914
- function patchClassList(el, previousTokens, nextTokens) {
915
- if (previousTokens.length === nextTokens.length) {
916
- let identical = true;
917
- for (let index = 0; index < previousTokens.length; index += 1) if (previousTokens[index] !== nextTokens[index]) {
918
- identical = false;
919
- break;
920
- }
921
- if (identical) return;
922
- }
923
- if (previousTokens.length === 0) {
924
- if (nextTokens.length === 0) return;
925
- el.classList.add(...nextTokens);
926
- incrementPerfMetric("classListPatchOps");
927
- return;
928
- }
929
- if (nextTokens.length === 0) {
930
- el.classList.remove(...previousTokens);
931
- incrementPerfMetric("classListPatchOps");
932
- return;
933
- }
934
- if (previousTokens.length === 1 && nextTokens.length === 1) {
935
- el.classList.remove(previousTokens[0]);
936
- el.classList.add(nextTokens[0]);
937
- incrementPerfMetric("classListPatchOps");
938
- return;
939
- }
940
- const nextSet = new Set(nextTokens);
941
- const previousSet = new Set(previousTokens);
942
- for (const token of previousTokens) if (!nextSet.has(token)) el.classList.remove(token);
943
- for (const token of nextTokens) if (!previousSet.has(token)) el.classList.add(token);
944
- incrementPerfMetric("classListPatchOps");
945
- }
946
- function applyClassPropValue(el, value, previousValue, descriptor) {
947
- const nextString = String(value);
948
- const nextTokens = tokenizeClassValue(nextString);
949
- const previousTokens = descriptor?.lastClassTokens ?? tokenizeClassValue(previousValue);
950
- if (nextTokens && previousTokens) {
951
- patchClassList(el, previousTokens, nextTokens);
952
- if (descriptor) descriptor.lastClassTokens = nextTokens;
953
- return;
954
- }
955
- writeElementClassName(el, nextString);
956
- if (descriptor) descriptor.lastClassTokens = nextTokens;
957
- }
958
- /**
959
- * Apply attributes and event listeners to an element from props
960
- */
961
- function applyPropsToElement(el, props, tagName) {
962
- if (isHydrationSkipped(el)) return;
963
- for (const key in props) {
964
- const value = props[key];
965
- if (key === "ref") {
966
- updateElementRef(el, value);
967
- continue;
968
- }
969
- if (isSkippedProp(key)) continue;
970
- if (value === void 0 || value === null || value === false) continue;
971
- const eventProp = parseEventProp(key);
972
- if (eventProp) {
973
- addTrackedListener(el, eventProp.eventName, value, eventProp.capture);
974
- continue;
975
- }
976
- if (typeof value === "function" && key !== "ref") {
977
- const reactive = setupReactiveProp(el, key, value, tagName);
978
- if (!elementReactivePropsCleanup.has(el)) elementReactivePropsCleanup.set(el, /* @__PURE__ */ new Map());
979
- elementReactivePropsCleanup.get(el).set(key, {
980
- cleanup: reactive.cleanup,
981
- updateFn: (nextValue) => {
982
- reactive.updateFn(nextValue);
983
- },
984
- fnRef: value
985
- });
986
- continue;
987
- }
988
- if (key === "class" || key === "className") writeElementClassName(el, String(value));
989
- else if (key === "style") applyStylePropValue(el, value);
990
- else if (key === "value" || key === "checked") applyFormControlProp(el, key, value, tagName);
991
- else setRenderedAttribute(el, key, String(value));
992
- }
993
- }
994
- function removeStaleAttributes(el, vnode, props) {
995
- const desiredAttributes = /* @__PURE__ */ new Set();
996
- if (extractKey(vnode) !== void 0) desiredAttributes.add("data-key");
997
- for (const propName in props) {
998
- if (isSkippedProp(propName)) continue;
999
- if (parseEventName(propName)) continue;
1000
- const value = props[propName];
1001
- if (value === void 0 || value === null || value === false) continue;
1002
- desiredAttributes.add(getRenderedAttributeName(el, propName));
1003
- }
1004
- for (const attribute of Array.from(el.attributes)) if (!desiredAttributes.has(getRenderedAttributeName(el, attribute.name))) el.removeAttribute(attribute.name);
1005
- }
1006
- /**
1007
- * Apply value/checked props to form controls
1008
- */
1009
- function applyFormControlProp(el, key, value, tagName) {
1010
- if (key === "value") if (tagNamesEqualIgnoreCase(tagName, "input") || tagNamesEqualIgnoreCase(tagName, "textarea") || tagNamesEqualIgnoreCase(tagName, "select")) {
1011
- el.value = String(value);
1012
- el.setAttribute("value", String(value));
1013
- } else el.setAttribute("value", String(value));
1014
- else if (key === "checked") if (tagNamesEqualIgnoreCase(tagName, "input")) {
1015
- const checked = Boolean(value);
1016
- el.checked = checked;
1017
- if (checked) el.setAttribute("checked", "");
1018
- else el.removeAttribute("checked");
1019
- } else if (value) el.setAttribute("checked", "");
1020
- else el.removeAttribute("checked");
1021
- }
1022
- /**
1023
- * Materialize vnode key as data-key attribute
1024
- */
1025
- function materializeKey(el, vnode, props) {
1026
- const rawKey = vnode.key ?? props?.key;
1027
- const vnodeKey = rawKey === null || rawKey === void 0 ? void 0 : typeof rawKey === "symbol" ? String(rawKey) : rawKey;
1028
- if (vnodeKey !== void 0) {
1029
- const nextKey = String(vnodeKey);
1030
- if (el.getAttribute("data-key") !== nextKey) el.setAttribute("data-key", nextKey);
1031
- }
1032
- }
1033
- function inheritComponentKey(target, source) {
1034
- const inheritedKey = extractKey(source);
1035
- if (inheritedKey === void 0 || extractKey(target) !== void 0) return target;
1036
- target.key = inheritedKey;
1037
- if (typeof target.type === "string") {
1038
- if (!target.props) target.props = {};
1039
- const props = target.props;
1040
- if (props["data-key"] === void 0) props["data-key"] = String(inheritedKey);
1041
- }
1042
- return target;
1043
- }
1044
- /**
1045
- * Warn about missing keys on dynamic lists (dev only)
1046
- */
1047
- function warnMissingKeys(children) {
1048
- if (getRuntimeEnv().NODE_ENV === "production") return;
1049
- let hasElements = false;
1050
- let hasKeys = false;
1051
- for (const item of children) if (typeof item === "object" && item !== null && "type" in item) {
1052
- if (item.type === __FOR_BOUNDARY__) continue;
1053
- hasElements = true;
1054
- if ((item.key ?? item.props?.key) !== void 0) {
1055
- hasKeys = true;
1056
- break;
1057
- }
1058
- }
1059
- if (hasElements && !hasKeys) {
1060
- const inst = getCurrentInstance();
1061
- const warnings = inst ? inst.devWarningsEmitted ??= /* @__PURE__ */ new Set() : null;
1062
- if (warnings?.has("missing-keys")) return;
1063
- warnings?.add("missing-keys");
1064
- try {
1065
- const name = inst?.fn?.name || "<anonymous>";
1066
- logger.warn(`Missing keys on dynamic lists in ${name}. Each child in a list should have a unique "key" prop.`);
1067
- } catch {
1068
- logger.warn("Missing keys on dynamic lists. Each child in a list should have a unique \"key\" prop.");
1069
- }
1070
- }
1071
- }
1072
- function hasStaticChildrenMarker(children) {
1073
- return children[STATIC_CHILDREN] === true;
1074
- }
1075
- function maybeWarnMissingKeys(children) {
1076
- if (!hasStaticChildrenMarker(children)) warnMissingKeys(children);
1077
- }
1078
- /**
1079
- * Create a DOM node from a VNode
1080
- */
1081
- function createDOMNode(node, parentNamespace) {
1082
- if (!IS_DOM_AVAILABLE) {
1083
- if (getRuntimeEnv().NODE_ENV !== "production") try {
1084
- logger.warn("[Askr] createDOMNode called in non-DOM environment");
1085
- } catch {}
1086
- return null;
1087
- }
1088
- if (typeof node === "string") {
1089
- if (isBenchMetricScopeActive("coldCreate")) recordBenchCounter("domNodesCreated");
1090
- return document.createTextNode(node);
1091
- }
1092
- if (typeof node === "number") {
1093
- if (isBenchMetricScopeActive("coldCreate")) recordBenchCounter("domNodesCreated");
1094
- return document.createTextNode(String(node));
1095
- }
1096
- if (!node) return null;
1097
- if (Array.isArray(node)) {
1098
- maybeWarnMissingKeys(node);
1099
- const fragment = document.createDocumentFragment();
1100
- for (const child of node) {
1101
- const dom = createDOMNode(child, parentNamespace);
1102
- if (dom) fragment.appendChild(dom);
1103
- }
1104
- return fragment;
1105
- }
1106
- if (typeof node === "object" && node !== null && "type" in node) {
1107
- const type = node.type;
1108
- const props = node.props || {};
1109
- if (typeof type === "string") return createIntrinsicElement(node, type, props, parentNamespace);
1110
- if (typeof type === "function") return createComponentElement(node, type, props, parentNamespace);
1111
- if (type === __FOR_BOUNDARY__) return createForBoundary(node, props, parentNamespace);
1112
- if (type === __ERROR_BOUNDARY__) return createErrorBoundaryElement(node, props, parentNamespace);
1113
- if (typeof type === "symbol" && (type === Fragment || String(type) === "Symbol(Fragment)")) return createFragmentElement(node, props, parentNamespace);
1114
- }
1115
- return null;
1116
- }
1117
- function tryGetStaticCreateChildShape(children) {
1118
- if (children === null || children === void 0 || children === false) return { textContent: null };
1119
- if (typeof children === "string" || typeof children === "number") return { textContent: String(children) };
1120
- if (Array.isArray(children) && children.length === 1) {
1121
- const child = children[0];
1122
- if (child === null || child === void 0 || child === false) return { textContent: null };
1123
- if (typeof child === "string" || typeof child === "number") return { textContent: String(child) };
1124
- }
1125
- return null;
1126
- }
1127
- function isStaticCreateScalarValue(value) {
1128
- const valueType = typeof value;
1129
- return valueType === "string" || valueType === "number" || valueType === "boolean";
1130
- }
1131
- function tryGetStaticCreateFastPathShape(props, children) {
1132
- const childShape = tryGetStaticCreateChildShape(children);
1133
- if (!childShape) return null;
1134
- for (const key in props) {
1135
- if (key === "ref") return null;
1136
- if (isSkippedProp(key)) continue;
1137
- const value = props[key];
1138
- if (value === void 0 || value === null || value === false) continue;
1139
- if (parseEventName(key) || !isStaticCreateScalarValue(value)) return null;
1140
- }
1141
- return childShape;
1142
- }
1143
- function applyStaticScalarPropsToElement(el, props) {
1144
- for (const key in props) {
1145
- if (isSkippedProp(key)) continue;
1146
- const value = props[key];
1147
- if (value === void 0 || value === null || value === false) continue;
1148
- if (key === "class" || key === "className") writeElementClassName(el, String(value));
1149
- else if (key === "style") applyStylePropValue(el, value);
1150
- else if (key === "value" || key === "checked") el[key] = value;
1151
- else setRenderedAttribute(el, key, String(value));
1152
- }
1153
- }
1154
- /**
1155
- * Create an intrinsic DOM element (div, span, etc.)
1156
- */
1157
- function createIntrinsicElement(node, type, props, parentNamespace) {
1158
- const children = props.children ?? node.children;
1159
- const elementNamespace = resolveChildNamespace(type, parentNamespace);
1160
- const el = createElementForNamespace(type, parentNamespace);
1161
- if (isBenchMetricScopeActive("coldCreate")) recordBenchCounter("domNodesCreated");
1162
- materializeKey(el, node, props);
1163
- const staticCreateFastPath = tryGetStaticCreateFastPathShape(props, children);
1164
- if (staticCreateFastPath) {
1165
- applyStaticScalarPropsToElement(el, props);
1166
- if (staticCreateFastPath.textContent !== null) {
1167
- el.textContent = staticCreateFastPath.textContent;
1168
- if (isBenchMetricScopeActive("coldCreate")) recordBenchCounter("domNodesCreated");
1169
- }
1170
- return el;
1171
- }
1172
- applyPropsToElement(el, props, type);
1173
- if (children !== null && children !== void 0) {
1174
- const controlBoundaryVNode = getDirectControlBoundaryVNode(children);
1175
- if (controlBoundaryVNode) {
1176
- const controlState = getControlBoundaryState(controlBoundaryVNode);
1177
- if (!controlState) throw new Error("[createIntrinsicElement] Control boundary missing internal state");
1178
- registerControlBoundaryCommitOwner(el, controlState);
1179
- }
1180
- if (syncReactiveScalarChild(el, children)) return el;
1181
- if (Array.isArray(children)) {
1182
- maybeWarnMissingKeys(children);
1183
- if (children.length > 1) {
1184
- const childFrag = document.createDocumentFragment();
1185
- for (const child of children) {
1186
- const dom = createDOMNode(child, elementNamespace);
1187
- if (dom) childFrag.appendChild(dom);
1188
- }
1189
- el.appendChild(childFrag);
1190
- } else if (children.length === 1) {
1191
- const dom = createDOMNode(children[0], elementNamespace);
1192
- if (dom) el.appendChild(dom);
1193
- }
1194
- } else {
1195
- const dom = createDOMNode(children, elementNamespace);
1196
- if (dom) el.appendChild(dom);
1197
- }
1198
- }
1199
- return el;
1200
- }
1201
- function findHostInstanceByType(host, type) {
1202
- const instances = host.__ASKR_INSTANCES;
1203
- if (instances && instances.length > 0) for (let index = instances.length - 1; index >= 0; index -= 1) {
1204
- const instance = instances[index];
1205
- if (instance.fn === type) return instance;
1206
- }
1207
- return host.__ASKR_INSTANCE?.fn === type ? host.__ASKR_INSTANCE : null;
1208
- }
1209
- function materializeComponentResultNode(childInstance, result, parentNamespace) {
1210
- const dom = createDOMNode(result, parentNamespace);
1211
- if (dom instanceof Element) {
1212
- mountInstanceInline(childInstance, dom);
1213
- return dom;
1214
- }
1215
- if (!dom) {
1216
- const placeholder = document.createComment("");
1217
- try {
1218
- placeholder.__ASKR_INSTANCE = childInstance;
1219
- } catch {}
1220
- childInstance._placeholder = placeholder;
1221
- mountInstanceInline(childInstance, null);
1222
- return placeholder;
1223
- }
1224
- const host = document.createElement("div");
1225
- host.appendChild(dom);
1226
- host.__ASKR_WRAPPER_HOST = true;
1227
- mountInstanceInline(childInstance, host);
1228
- return host;
1229
- }
1230
- function resolveNestedComponentResult(result, snapshot, parentInstance) {
1231
- let currentResult = result;
1232
- let activeSnapshot = snapshot;
1233
- let depth = 0;
1234
- while (_isDOMElement(currentResult) && typeof currentResult.type === "function" && depth < 16) {
1235
- const nestedSnapshot = getVNodeContextFrame(currentResult) ?? activeSnapshot;
1236
- const nestedInstance = createComponentInstance(nextComponentInstanceId(), currentResult.type, currentResult.props ?? {}, null);
1237
- nestedInstance.isRoot = isRouteRootComponentVNode(currentResult);
1238
- nestedInstance.parentInstance = parentInstance;
1239
- nestedInstance.portalScope = parentInstance?.portalScope ?? nestedInstance.portalScope;
1240
- inheritComponentCleanupStrict(nestedInstance);
1241
- if (nestedSnapshot) nestedInstance.ownerFrame = nestedSnapshot;
1242
- const nextResult = withContext(nestedSnapshot ?? null, () => renderComponentInline(nestedInstance));
1243
- cleanupComponent(nestedInstance);
1244
- if (isPromiseLike(nextResult)) throw new Error("Async components are not supported. Components must return synchronously.");
1245
- activeSnapshot = nestedSnapshot ?? null;
1246
- currentResult = nextResult;
1247
- depth += 1;
1248
- }
1249
- return currentResult;
1250
- }
1251
- function resolveHostNestedComponentResult(host, retainedInstance, result, snapshot, retainedHostInstances) {
1252
- let currentResult = result;
1253
- let activeSnapshot = snapshot;
1254
- let depth = 0;
1255
- const retainedInstances = new Set([retainedInstance]);
1256
- if (retainedHostInstances) for (const instance of retainedHostInstances) retainedInstances.add(instance);
1257
- const createdInstances = [];
1258
- while (_isDOMElement(currentResult) && typeof currentResult.type === "function" && depth < 16) {
1259
- const nestedSnapshot = getVNodeContextFrame(currentResult) ?? activeSnapshot;
1260
- let nestedInstance = findHostInstanceByType(host, currentResult.type);
1261
- const hadNestedInstance = !!nestedInstance;
1262
- if (!nestedInstance) {
1263
- nestedInstance = createComponentInstance(nextComponentInstanceId(), currentResult.type, currentResult.props ?? {}, null);
1264
- createdInstances.push(nestedInstance);
1265
- }
1266
- if (hadNestedInstance) captureInlineRenderSnapshot(nestedInstance);
1267
- setVNodeComponentInstance(currentResult, nestedInstance);
1268
- nestedInstance.isRoot = isRouteRootComponentVNode(currentResult);
1269
- nestedInstance.parentInstance = retainedInstance;
1270
- nestedInstance.portalScope = retainedInstance.portalScope ?? nestedInstance.portalScope;
1271
- inheritComponentCleanupStrict(nestedInstance);
1272
- nestedInstance.props = (currentResult.props ?? {}) || {};
1273
- if (nestedSnapshot) nestedInstance.ownerFrame = nestedSnapshot;
1274
- const nextResult = withContext(nestedSnapshot ?? null, () => renderComponentInline(nestedInstance));
1275
- if (isPromiseLike(nextResult)) throw new Error("Async components are not supported. Components must return synchronously.");
1276
- retainedInstances.add(nestedInstance);
1277
- warnUnusedStateReads(nestedInstance);
1278
- activeSnapshot = nestedSnapshot ?? null;
1279
- currentResult = markVNodeTreeWithContextFrame(nextResult, activeSnapshot);
1280
- depth += 1;
1281
- }
1282
- const previousInstances = host.__ASKR_INSTANCES ?? [];
1283
- for (const instance of previousInstances) if (!retainedInstances.has(instance)) cleanupComponent(instance);
1284
- const nextHostInstances = previousInstances.filter((instance) => retainedInstances.has(instance));
1285
- for (const instance of retainedInstances) if (instance.target === host && !nextHostInstances.includes(instance)) nextHostInstances.push(instance);
1286
- host.__ASKR_INSTANCES = nextHostInstances;
1287
- host.__ASKR_INSTANCE = host.__ASKR_INSTANCES[0] ?? retainedInstance;
1288
- for (const instance of createdInstances) mountInstanceInline(instance, host);
1289
- return currentResult;
1290
- }
1291
- function resolveWrapperHostResult(host, result, snapshot) {
1292
- let currentResult = result;
1293
- let activeSnapshot = snapshot;
1294
- let depth = 0;
1295
- while (_isDOMElement(currentResult) && typeof currentResult.type === "function" && depth < 16) {
1296
- const nestedSnapshot = getVNodeContextFrame(currentResult) ?? activeSnapshot;
1297
- const nestedInstance = findHostInstanceByType(host, currentResult.type);
1298
- if (!nestedInstance) break;
1299
- captureInlineRenderSnapshot(nestedInstance);
1300
- nestedInstance.props = (currentResult.props ?? {}) || {};
1301
- nestedInstance.parentInstance = getCurrentInstance();
1302
- nestedInstance.isRoot = isRouteRootComponentVNode(currentResult);
1303
- nestedInstance.portalScope = getCurrentInstance()?.portalScope ?? nestedInstance.portalScope;
1304
- inheritComponentCleanupStrict(nestedInstance);
1305
- if (nestedSnapshot) nestedInstance.ownerFrame = nestedSnapshot;
1306
- const nextResult = withContext(nestedSnapshot ?? null, () => renderComponentInline(nestedInstance));
1307
- if (isPromiseLike(nextResult)) throw new Error("Async components are not supported. Components must return synchronously.");
1308
- warnUnusedStateReads(nestedInstance);
1309
- activeSnapshot = nestedSnapshot ?? null;
1310
- currentResult = nextResult;
1311
- depth += 1;
1312
- }
1313
- return markVNodeTreeWithContextFrame(currentResult, activeSnapshot);
1314
- }
1315
- function isFragmentVNode(node) {
1316
- return _isDOMElement(node) && typeof node.type === "symbol" && (node.type === Fragment || String(node.type) === "Symbol(askr.fragment)");
1317
- }
1318
- function normalizeComponentChildren(result) {
1319
- if (result === null || result === void 0 || result === false) return [];
1320
- if (Array.isArray(result)) {
1321
- const children = [];
1322
- for (const child of result) children.push(...normalizeComponentChildren(child));
1323
- return children;
1324
- }
1325
- if (isFragmentVNode(result)) return normalizeComponentChildren(result.props?.children ?? result.children ?? []);
1326
- return [result];
1327
- }
1328
- function syncComponentElement(currentDom, node, type, props, parentNamespace, forceChildrenUpdate = false, retainedHostInstances) {
1329
- const existingHost = currentDom instanceof Element ? currentDom : null;
1330
- const existingInstance = existingHost ? findHostInstanceByType(existingHost, type) : null;
1331
- if (!existingHost) return null;
1332
- if (!existingInstance || existingInstance.fn !== type) {
1333
- const snapshot = getVNodeContextFrame(node) || getCurrentContextFrame() || null;
1334
- const hydrationInstance = createComponentInstance(nextComponentInstanceId(), type, props || {}, existingHost);
1335
- hydrationInstance.isRoot = isRouteRootComponentVNode(node);
1336
- hydrationInstance.portalScope = getCurrentInstance()?.portalScope ?? hydrationInstance.portalScope;
1337
- inheritComponentCleanupStrict(hydrationInstance);
1338
- setVNodeComponentInstance(node, hydrationInstance);
1339
- if (snapshot) hydrationInstance.ownerFrame = snapshot;
1340
- const result = withContext(snapshot, () => renderComponentInline(hydrationInstance));
1341
- if (isPromiseLike(result)) throw new Error("Async components are not supported. Components must return synchronously.");
1342
- const scopedResult = markVNodeTreeWithContextFrame(result, snapshot ?? null);
1343
- if (scopedResult && typeof scopedResult === "object" && "type" in scopedResult && typeof scopedResult.type === "string" && tagNamesEqualIgnoreCase(existingHost.tagName, scopedResult.type)) {
1344
- pruneComponentHostInstances(existingHost, retainedHostInstances ? [hydrationInstance, ...retainedHostInstances] : [hydrationInstance]);
1345
- withContext(snapshot, () => {
1346
- updateElementFromVnode(existingHost, inheritComponentKey(scopedResult, node), true, forceChildrenUpdate || hydrationInstance.mounted === false);
1347
- materializeKey(existingHost, node, props);
1348
- });
1349
- mountInstanceInline(hydrationInstance, existingHost);
1350
- itemInstanceHydrationComplete(existingHost);
1351
- warnUnusedStateReads(hydrationInstance);
1352
- return existingHost;
1353
- }
1354
- const resolvedResult = resolveHostNestedComponentResult(existingHost, hydrationInstance, scopedResult, snapshot ?? null, retainedHostInstances);
1355
- if (_isDOMElement(resolvedResult) && typeof resolvedResult.type === "string" && tagNamesEqualIgnoreCase(existingHost.tagName, resolvedResult.type)) {
1356
- withContext(snapshot, () => {
1357
- updateElementFromVnode(existingHost, inheritComponentKey(resolvedResult, node), true, forceChildrenUpdate || hydrationInstance.mounted === false);
1358
- materializeKey(existingHost, node, props);
1359
- });
1360
- mountInstanceInline(hydrationInstance, existingHost);
1361
- itemInstanceHydrationComplete(existingHost);
1362
- warnUnusedStateReads(hydrationInstance);
1363
- return existingHost;
1364
- }
1365
- const nextDom = materializeComponentResultNode(hydrationInstance, scopedResult, parentNamespace);
1366
- if (nextDom instanceof Element) materializeKey(nextDom, node, props);
1367
- if (nextDom !== existingHost && existingHost.parentNode) {
1368
- existingHost.parentNode.replaceChild(nextDom, existingHost);
1369
- cleanupDetachedComponentHost(existingHost, hydrationInstance);
1370
- }
1371
- warnUnusedStateReads(hydrationInstance);
1372
- return nextDom;
1373
- }
1374
- const snapshot = getVNodeContextFrame(node) || getCurrentContextFrame() || existingInstance.ownerFrame || null;
1375
- captureInlineRenderSnapshot(existingInstance);
1376
- existingInstance.props = props || {};
1377
- existingInstance.isRoot = isRouteRootComponentVNode(node);
1378
- existingInstance.portalScope = getCurrentInstance()?.portalScope ?? existingInstance.portalScope;
1379
- inheritComponentCleanupStrict(existingInstance);
1380
- if (snapshot) existingInstance.ownerFrame = snapshot;
1381
- const result = withContext(snapshot, () => renderComponentInline(existingInstance));
1382
- if (isPromiseLike(result)) throw new Error("Async components are not supported. Components must return synchronously.");
1383
- const scopedResult = markVNodeTreeWithContextFrame(result, snapshot ?? null);
1384
- if (existingHost.__ASKR_WRAPPER_HOST) {
1385
- updateElementChildren(existingHost, normalizeComponentChildren(resolveWrapperHostResult(existingHost, scopedResult, snapshot ?? null)));
1386
- warnUnusedStateReads(existingInstance);
1387
- return existingHost;
1388
- }
1389
- if (scopedResult && typeof scopedResult === "object" && "type" in scopedResult && typeof scopedResult.type === "string" && tagNamesEqualIgnoreCase(existingHost.tagName, scopedResult.type)) {
1390
- pruneComponentHostInstances(existingHost, retainedHostInstances ? [existingInstance, ...retainedHostInstances] : [existingInstance]);
1391
- withContext(snapshot, () => {
1392
- updateElementFromVnode(existingHost, inheritComponentKey(scopedResult, node), true, forceChildrenUpdate || existingInstance.mounted === false);
1393
- materializeKey(existingHost, node, props);
1394
- });
1395
- warnUnusedStateReads(existingInstance);
1396
- return existingHost;
1397
- }
1398
- const resolvedResult = resolveHostNestedComponentResult(existingHost, existingInstance, scopedResult, snapshot ?? null, retainedHostInstances);
1399
- if (_isDOMElement(resolvedResult) && typeof resolvedResult.type === "string" && tagNamesEqualIgnoreCase(existingHost.tagName, resolvedResult.type)) {
1400
- withContext(snapshot, () => {
1401
- updateElementFromVnode(existingHost, inheritComponentKey(resolvedResult, node), true, forceChildrenUpdate || existingInstance.mounted === false);
1402
- materializeKey(existingHost, node, props);
1403
- });
1404
- warnUnusedStateReads(existingInstance);
1405
- return existingHost;
1406
- }
1407
- const nextDom = materializeComponentResultNode(existingInstance, scopedResult, parentNamespace);
1408
- if (nextDom instanceof Element) materializeKey(nextDom, node, props);
1409
- if (nextDom !== existingHost && existingHost.parentNode) {
1410
- existingHost.parentNode.replaceChild(nextDom, existingHost);
1411
- cleanupDetachedComponentHost(existingHost, existingInstance);
1412
- }
1413
- warnUnusedStateReads(existingInstance);
1414
- return nextDom;
1415
- }
1416
- function itemInstanceHydrationComplete(host) {
1417
- const instance = host.__ASKR_INSTANCE;
1418
- if (instance) {
1419
- const scope = instance.scope;
1420
- if (scope) scope.hydrationPending = false;
1421
- }
1422
- }
1423
- function createComponentElement(node, type, props, parentNamespace) {
1424
- const snapshot = getVNodeContextFrame(node) || getCurrentContextFrame();
1425
- const componentFn = type;
1426
- if (componentFn.constructor.name === "AsyncFunction") throw new Error("Async components are not supported. Use resource() for async work.");
1427
- let childInstance = getVNodeComponentInstance(node);
1428
- const hadChildInstance = !!childInstance;
1429
- if (!childInstance) {
1430
- childInstance = createComponentInstance(nextComponentInstanceId(), componentFn, props || {}, null);
1431
- setVNodeComponentInstance(node, childInstance);
1432
- }
1433
- if (hadChildInstance) captureInlineRenderSnapshot(childInstance);
1434
- childInstance.portalScope = getCurrentInstance()?.portalScope ?? childInstance.portalScope;
1435
- childInstance.parentInstance = getCurrentInstance();
1436
- childInstance.props = props || {};
1437
- childInstance.isRoot = isRouteRootComponentVNode(node);
1438
- inheritComponentCleanupStrict(childInstance);
1439
- if (snapshot) childInstance.ownerFrame = snapshot;
1440
- const result = withContext(snapshot, () => renderComponentInline(childInstance));
1441
- if (isPromiseLike(result)) throw new Error("Async components are not supported. Components must return synchronously.");
1442
- const scopedResult = markVNodeTreeWithContextFrame(result, snapshot ?? null);
1443
- const dom = withContext(snapshot, () => materializeComponentResultNode(childInstance, scopedResult, parentNamespace));
1444
- warnUnusedStateReads(childInstance);
1445
- if (dom instanceof Element) materializeKey(dom, node, props);
1446
- return dom;
1447
- }
1448
- /**
1449
- * Create a document fragment from Fragment vnode
1450
- */
1451
- function createFragmentElement(node, props, parentNamespace) {
1452
- const fragment = document.createDocumentFragment();
1453
- const children = props.children ?? node.children;
1454
- if (children) if (Array.isArray(children)) {
1455
- maybeWarnMissingKeys(children);
1456
- for (const child of children) {
1457
- const dom = createDOMNode(child, parentNamespace);
1458
- if (dom) fragment.appendChild(dom);
1459
- }
1460
- } else {
1461
- const dom = createDOMNode(children, parentNamespace);
1462
- if (dom) fragment.appendChild(dom);
1463
- }
1464
- return fragment;
1465
- }
1466
- /**
1467
- * Check if a cached DOM node can be reused for a given vnode.
1468
- *
1469
- * Returns true if shape has changed (i.e., DOM cannot be reused).
1470
- * Structural check: compares DOM tagName with vnode type.
1471
- * Do NOT rely on vnode identity (===) — vnodes are mutable.
1472
- */
1473
- function checkVNodeShapeChanged(dom, vnode) {
1474
- if (!_isDOMElement(vnode)) return true;
1475
- if (!(dom instanceof Element)) return true;
1476
- const vnodeType = vnode.type;
1477
- if (typeof vnodeType !== "string") return true;
1478
- return dom.tagName.toLowerCase() !== vnodeType.toLowerCase();
1479
- }
1480
- function materializeChildScopeDom(vnode, parentNamespace) {
1481
- if (vnode === null || vnode === void 0 || vnode === false) return document.createComment("");
1482
- const dom = createDOMNode(vnode, parentNamespace);
1483
- if (!(dom instanceof DocumentFragment)) return dom;
1484
- const firstChild = dom.firstChild;
1485
- const secondChild = firstChild?.nextSibling ?? null;
1486
- if (!firstChild) return document.createComment("");
1487
- if (secondChild) throw new Error("[askr] Child scopes must render a single DOM root node.");
1488
- return firstChild;
1489
- }
1490
- function evaluateControlBoundaryState(controlState) {
1491
- if (controlState.kind === "for") return evaluateForState(controlState);
1492
- if (controlState.kind === "show") return evaluateShowState(controlState);
1493
- return evaluateCaseState(controlState);
1494
- }
1495
- function clearControlBoundaryDomUpdateState(controlState) {
1496
- if (controlState.kind === "for") {
1497
- clearForDomUpdateState(controlState);
1498
- return;
1499
- }
1500
- if (controlState.kind === "show") {
1501
- clearShowDomUpdateState(controlState);
1502
- return;
1503
- }
1504
- clearCaseDomUpdateState(controlState);
1505
- }
1506
- function getControlBoundaryState(node) {
1507
- return node._controlState ?? node._forState ?? null;
1508
- }
1509
- function getDirectControlBoundaryVNode(children) {
1510
- if (!Array.isArray(children) && _isDOMElement(children) && children.type === __FOR_BOUNDARY__) return children;
1511
- if (Array.isArray(children) && children.length === 1 && _isDOMElement(children[0]) && children[0].type === __FOR_BOUNDARY__) return children[0];
1512
- return null;
1513
- }
1514
- function getControlBoundaryCommitChildren(controlState) {
1515
- if (controlState.kind === "for" && controlState._needsSourceReconcile) return evaluateForState(controlState);
1516
- if (controlState.kind !== "for") {
1517
- const activeVNode = controlState.activeScope?.vnode;
1518
- return activeVNode == null || activeVNode === false ? [] : [activeVNode];
1519
- }
1520
- if (controlState.orderedKeys.length === 0) {
1521
- const fallbackVNode = controlState.fallbackScope?.vnode;
1522
- return fallbackVNode == null || fallbackVNode === false ? [] : [fallbackVNode];
1523
- }
1524
- const childrenVNodes = [];
1525
- for (let index = 0; index < controlState.orderedKeys.length; index += 1) {
1526
- const itemKey = controlState.orderedKeys[index];
1527
- const itemInstance = controlState.items.get(itemKey);
1528
- childrenVNodes.push(itemInstance?.scope.vnode ?? null);
1529
- }
1530
- return childrenVNodes;
1531
- }
1532
- function clearControlBoundaryCommitOwner(parent) {
1533
- const owner = controlBoundaryOwners.get(parent);
1534
- if (owner) {
1535
- owner._enqueueBoundaryCommit = null;
1536
- owner._hasPendingBoundaryCommit = false;
1537
- if (owner._commitOwner === parent) owner._commitOwner = null;
1538
- }
1539
- controlBoundaryOwners.delete(parent);
1540
- }
1541
- function registerControlBoundaryCommitOwner(parent, controlState) {
1542
- const ownerState = controlState;
1543
- const previousParent = ownerState._commitOwner;
1544
- if (previousParent && previousParent !== parent && controlBoundaryOwners.get(previousParent) === controlState) controlBoundaryOwners.delete(previousParent);
1545
- const previousOwner = controlBoundaryOwners.get(parent);
1546
- if (previousOwner && previousOwner !== controlState) {
1547
- previousOwner._enqueueBoundaryCommit = null;
1548
- previousOwner._hasPendingBoundaryCommit = false;
1549
- if (previousOwner._commitOwner === parent) previousOwner._commitOwner = null;
1550
- }
1551
- controlBoundaryOwners.set(parent, controlState);
1552
- ownerState._commitOwner = parent;
1553
- controlState._enqueueBoundaryCommit = () => {
1554
- if (controlState._hasPendingBoundaryCommit) return;
1555
- controlState._hasPendingBoundaryCommit = true;
1556
- globalScheduler.enqueue(() => {
1557
- controlState._hasPendingBoundaryCommit = false;
1558
- if (controlBoundaryOwners.get(parent) !== controlState) return;
1559
- commitForBoundaryChildren(parent, controlState, getControlBoundaryCommitChildren(controlState));
1560
- });
1561
- };
1562
- }
1563
- /**
1564
- * Create DOM from For boundary - evaluates list and renders items
1565
- *
1566
- * CRITICAL INVARIANT:
1567
- * DOM order MUST be reconstructed from the current vnode list on every render.
1568
- * Reusing DOM nodes never implies preserving their position.
1569
- *
1570
- * This function ALWAYS returns a fragment whose child order exactly matches
1571
- * the evaluated vnode list, even when all DOM nodes are reused.
1572
- * Appending an existing node to the fragment is how we express reordering
1573
- * (per DOM spec, appendChild moves already-attached nodes).
1574
- *
1575
- * Do NOT:
1576
- * - Skip appending based on parentElement or existing attachment
1577
- * - Rely on vnode identity (===) to decide DOM reuse (vnodes are mutable)
1578
- * - Introduce fast-paths that might skip DOM reconstruction
1579
- */
1580
- function createForBoundary(node, props, parentNamespace) {
1581
- const controlState = getControlBoundaryState(node);
1582
- if (!controlState) {
1583
- if (getRuntimeEnv().NODE_ENV !== "production") logger.warn("[Askr] Control boundary missing state");
1584
- return document.createDocumentFragment();
1585
- }
1586
- const childrenVNodes = evaluateControlBoundaryState(controlState);
1587
- const fragment = document.createDocumentFragment();
1588
- if (controlState.kind !== "for") {
1589
- const activeScope = controlState.activeScope;
1590
- const vnode = childrenVNodes[0];
1591
- if (activeScope && vnode !== void 0) {
1592
- const dom = materializeChildScopeDom(vnode, parentNamespace);
1593
- activeScope.dom = dom ?? void 0;
1594
- if (dom) fragment.appendChild(dom);
1595
- }
1596
- clearControlBoundaryDomUpdateState(controlState);
1597
- return fragment;
1598
- }
1599
- const forState = controlState;
1600
- if (forState.orderedKeys.length === 0) {
1601
- const fallbackScope = forState.fallbackScope;
1602
- const fallbackVNode = childrenVNodes[0];
1603
- if (fallbackScope && fallbackVNode !== void 0) {
1604
- const dom = materializeChildScopeDom(fallbackVNode, parentNamespace);
1605
- fallbackScope.dom = dom ?? void 0;
1606
- if (dom) fragment.appendChild(dom);
1607
- }
1608
- clearControlBoundaryDomUpdateState(controlState);
1609
- return fragment;
1610
- }
1611
- for (let i = 0; i < childrenVNodes.length; i++) {
1612
- const childVNode = childrenVNodes[i];
1613
- const itemKey = forState.orderedKeys[i];
1614
- const itemInstance = itemKey != null ? forState.items.get(itemKey) : null;
1615
- let dom = null;
1616
- if (itemInstance && itemInstance.scope.dom) {
1617
- const cachedDom = itemInstance.scope.dom;
1618
- if (!checkVNodeShapeChanged(cachedDom, childVNode)) dom = cachedDom;
1619
- }
1620
- if (!dom) {
1621
- dom = materializeChildScopeDom(childVNode, parentNamespace);
1622
- if (itemInstance) itemInstance.scope.dom = dom ?? void 0;
1623
- }
1624
- if (dom) fragment.appendChild(dom);
1625
- }
1626
- clearControlBoundaryDomUpdateState(controlState);
1627
- return fragment;
1628
- }
1629
- function createErrorBoundaryElement(node, props, parentNamespace) {
1630
- const boundaryState = node.__instance?.errorBoundaryState ?? null;
1631
- const reset = node.__instance ? createBoundaryReset(node.__instance) : () => {};
1632
- const fallback = props.fallback;
1633
- const children = props.children;
1634
- if (boundaryState?.error != null) {
1635
- const fallbackValue = resolveErrorBoundaryFallback(fallback, boundaryState.error, reset);
1636
- if (fallbackValue instanceof Node) return fallbackValue;
1637
- return createDOMNode(fallbackValue, parentNamespace) ?? document.createComment("");
1638
- }
1639
- try {
1640
- return createDOMNode(children, parentNamespace) ?? document.createComment("");
1641
- } catch (error) {
1642
- if (node.__instance) reportBoundaryError(node.__instance, error, props.onError);
1643
- else logger.error("[Askr] ErrorBoundary caught render error:", error);
1644
- const fallbackValue = resolveErrorBoundaryFallback(fallback, error, reset);
1645
- if (fallbackValue instanceof Node) return fallbackValue;
1646
- return createDOMNode(fallbackValue, parentNamespace) ?? document.createComment("");
1647
- }
1648
- }
1649
- function syncForItemDom(parent, scope, vnode) {
1650
- let dom = scope.dom ?? null;
1651
- const parentNamespace = parent.namespaceURI === SVG_NAMESPACE ? SVG_NAMESPACE : void 0;
1652
- if (_isDOMElement(vnode) && typeof vnode.type === "function") {
1653
- const syncedComponentDom = syncComponentElement(dom, vnode, vnode.type, vnode.props ?? {}, parentNamespace);
1654
- if (syncedComponentDom) {
1655
- scope.dom = syncedComponentDom ?? void 0;
1656
- return syncedComponentDom;
1657
- }
1658
- }
1659
- if (!dom) {
1660
- dom = materializeChildScopeDom(vnode, parentNamespace);
1661
- scope.dom = dom ?? void 0;
1662
- return dom;
1663
- }
1664
- if (dom.nodeType === 3 && (typeof vnode === "string" || typeof vnode === "number")) {
1665
- dom.data = String(vnode);
1666
- return dom;
1667
- }
1668
- if (dom.nodeType === 8 && (vnode === null || vnode === void 0 || vnode === false)) return dom;
1669
- if (dom instanceof Element && _isDOMElement(vnode) && typeof vnode.type === "string" && tagNamesEqualIgnoreCase(dom.tagName, vnode.type)) {
1670
- updateElementFromVnode(dom, vnode, true);
1671
- return dom;
1672
- }
1673
- const nextDom = materializeChildScopeDom(vnode, parentNamespace);
1674
- if (!nextDom) {
1675
- if (dom.parentNode === parent) {
1676
- teardownNodeSubtree(dom);
1677
- dom.parentNode.removeChild(dom);
1678
- }
1679
- scope.dom = void 0;
1680
- return null;
1681
- }
1682
- if (dom.parentNode === parent) parent.replaceChild(nextDom, dom);
1683
- teardownNodeSubtree(dom);
1684
- scope.dom = nextDom;
1685
- return nextDom;
1686
- }
1687
- function normalizeStableIntrinsicChildren(children) {
1688
- if (children === null || children === void 0 || children === false) return [];
1689
- return Array.isArray(children) ? children : [children];
1690
- }
1691
- function getStableIntrinsicChildren(vnode) {
1692
- return normalizeStableIntrinsicChildren(vnode.props?.children ?? vnode.children);
1693
- }
1694
- function patchStableIntrinsicText(domNode, nextVNode) {
1695
- if (domNode.nodeType !== 3 || typeof nextVNode !== "string" && typeof nextVNode !== "number") return false;
1696
- const nextText = String(nextVNode);
1697
- const textNode = domNode;
1698
- if (textNode.data !== nextText) {
1699
- recordBenchEvent("domTextSet");
1700
- textNode.data = nextText;
1701
- }
1702
- return true;
1703
- }
1704
- function patchStableIntrinsicElement(dom, nextVNode) {
1705
- if (typeof nextVNode.type !== "string" || !tagNamesEqualIgnoreCase(dom.tagName, nextVNode.type)) return false;
1706
- updateElementFromVnode(dom, nextVNode, false);
1707
- const nextChildren = getStableIntrinsicChildren(nextVNode);
1708
- if (dom.childNodes.length !== nextChildren.length) return false;
1709
- for (let index = 0; index < nextChildren.length; index += 1) {
1710
- const nextChild = nextChildren[index];
1711
- const currentChildNode = dom.childNodes[index];
1712
- if (!currentChildNode) return false;
1713
- if (patchStableIntrinsicText(currentChildNode, nextChild)) continue;
1714
- if (currentChildNode instanceof Element && _isDOMElement(nextChild) && typeof nextChild.type === "string" && patchStableIntrinsicElement(currentChildNode, nextChild)) continue;
1715
- return false;
1716
- }
1717
- return true;
1718
- }
1719
- function resolveStableIntrinsicPatchVNode(dom, vnode) {
1720
- if (!_isDOMElement(vnode)) return null;
1721
- if (typeof vnode.type === "string") return tagNamesEqualIgnoreCase(dom.tagName, vnode.type) ? vnode : null;
1722
- if (typeof vnode.type !== "function") return null;
1723
- const host = dom;
1724
- const existingInstance = findHostInstanceByType(host, vnode.type);
1725
- if (!existingInstance || existingInstance.fn !== vnode.type || host.__ASKR_WRAPPER_HOST) return null;
1726
- const snapshot = getVNodeContextFrame(vnode) || getCurrentContextFrame() || existingInstance.ownerFrame || null;
1727
- captureInlineRenderSnapshot(existingInstance);
1728
- existingInstance.props = (vnode.props ?? {}) || {};
1729
- existingInstance.isRoot = isRouteRootComponentVNode(vnode);
1730
- existingInstance.portalScope = getCurrentInstance()?.portalScope ?? existingInstance.portalScope;
1731
- inheritComponentCleanupStrict(existingInstance);
1732
- if (snapshot) existingInstance.ownerFrame = snapshot;
1733
- const result = withContext(snapshot, () => renderComponentInline(existingInstance));
1734
- if (isPromiseLike(result)) throw new Error("Async components are not supported. Components must return synchronously.");
1735
- const resolvedResult = resolveNestedComponentResult(result, snapshot ?? null, existingInstance);
1736
- if (_isDOMElement(resolvedResult) && typeof resolvedResult.type === "string" && tagNamesEqualIgnoreCase(dom.tagName, resolvedResult.type)) return inheritComponentKey(resolvedResult, vnode);
1737
- return null;
1738
- }
1739
- function tryPatchStableForDirtyItem(scope) {
1740
- incDevCounter("stableForPatchAttempt");
1741
- if (!(scope.dom instanceof Element) || scope.vnode === void 0) return false;
1742
- const nextIntrinsic = resolveStableIntrinsicPatchVNode(scope.dom, scope.vnode);
1743
- if (!nextIntrinsic) return false;
1744
- const didPatch = patchStableIntrinsicElement(scope.dom, nextIntrinsic);
1745
- const existingInstance = scope.dom.__ASKR_INSTANCE;
1746
- if (didPatch && existingInstance) warnUnusedStateReads(existingInstance);
1747
- if (didPatch) incDevCounter("stableForPatchHit");
1748
- return didPatch;
1749
- }
1750
- function commitForBoundaryChildren(parent, controlState, childrenVNodes) {
1751
- if (controlState.kind !== "for") {
1752
- const activeScope = controlState.activeScope;
1753
- const activeVNode = childrenVNodes[0];
1754
- const nextDom = activeScope && activeVNode !== void 0 ? syncForItemDom(parent, activeScope, activeVNode) : null;
1755
- for (let i = 0; i < controlState.lastRemovedNodes.length; i++) {
1756
- const removedNode = controlState.lastRemovedNodes[i];
1757
- if (removedNode instanceof Element) teardownNodeSubtree(removedNode);
1758
- if (removedNode.parentNode === parent) {
1759
- recordBenchEvent("domRemove");
1760
- parent.removeChild(removedNode);
1761
- }
1762
- }
1763
- if (nextDom) {
1764
- if (parent.childNodes.length !== 1 || parent.firstChild !== nextDom || controlState.lastRemovedNodes.length > 0) parent.replaceChildren(nextDom);
1765
- } else if (parent.firstChild) parent.textContent = "";
1766
- keyedElements.delete(parent);
1767
- clearControlBoundaryDomUpdateState(controlState);
1768
- return;
1769
- }
1770
- commitForStateBoundaryChildren(parent, controlState, childrenVNodes, {
1771
- isProduction: () => getRuntimeEnv().NODE_ENV === "production",
1772
- syncForItemDom,
1773
- tryPatchStableForDirtyItem
1774
- });
1775
- }
1776
- /**
1777
- * Update an existing element's attributes and children from vnode
1778
- */
1779
- function updateElementFromVnode(el, vnode, updateChildren = true, forceChildrenUpdate = false) {
1780
- if (!_isDOMElement(vnode)) return;
1781
- const props = vnode.props || {};
1782
- const domVNode = vnode;
1783
- if (isHydrationSkipped(el)) {
1784
- clearHydrationDeferredSubtree(el);
1785
- return;
1786
- }
1787
- materializeKey(el, vnode, props);
1788
- updateElementRef(el, props.ref);
1789
- const existingListeners = elementListeners.get(el);
1790
- const existingReactiveProps = elementReactivePropsCleanup.get(el);
1791
- if ((!existingListeners || existingListeners.size === 0) && (!existingReactiveProps || existingReactiveProps.size === 0)) {
1792
- if (!forceChildrenUpdate && hasMatchingStaticProps(el, props, vnode.type)) {
1793
- if (updateChildren) {
1794
- const children = props.children ?? vnode.children;
1795
- if (!forceChildrenUpdate && canReuseStaticSubtree(el, domVNode)) return;
1796
- updateElementChildren(el, children, forceChildrenUpdate);
1797
- }
1798
- return;
1799
- }
1800
- }
1801
- let desiredListenerKeys = null;
1802
- let desiredDelegatedEventNames = null;
1803
- let desiredReactivePropNames = null;
1804
- const usesReactiveChildren = syncReactiveScalarChild(el, props.children ?? domVNode.children);
1805
- if (usesReactiveChildren) (desiredReactivePropNames ??= /* @__PURE__ */ new Set()).add(REACTIVE_CHILDREN_KEY);
1806
- for (const key in props) {
1807
- const value = props[key];
1808
- if (key === "ref") continue;
1809
- if (isSkippedProp(key)) continue;
1810
- const eventProp = parseEventProp(key);
1811
- const eventName = eventProp?.eventName;
1812
- const eventCapture = eventProp?.capture ?? false;
1813
- const listenerKey = eventName === void 0 ? null : getEventListenerKey(eventName, eventCapture);
1814
- if (value === void 0 || value === null || value === false) {
1815
- if (key === "class" || key === "className") writeElementClassName(el, "");
1816
- else if (key === "value") applyFormControlProp(el, key, "", vnode.type);
1817
- else if (key === "checked") applyFormControlProp(el, key, false, vnode.type);
1818
- else if (listenerKey && existingListeners?.has(listenerKey)) {
1819
- const entry = existingListeners.get(listenerKey);
1820
- incDevCounter("listenerRemoves");
1821
- if (entry.isDelegated) removeDelegatedListener(el, entry.eventName);
1822
- else if (entry.options !== void 0) el.removeEventListener(entry.eventName, entry.handler, entry.options);
1823
- else el.removeEventListener(entry.eventName, entry.handler);
1824
- existingListeners.delete(listenerKey);
1825
- } else {
1826
- const entry = existingReactiveProps?.get(key);
1827
- if (entry) {
1828
- entry.cleanup();
1829
- existingReactiveProps?.delete(key);
1830
- } else removeRenderedAttribute(el, key);
1831
- }
1832
- continue;
1833
- }
1834
- if (typeof value === "function" && !eventProp && key !== "ref") {
1835
- const existingEntry = existingReactiveProps?.get(key);
1836
- if (existingReactiveProps && existingReactiveProps.size > 0) (desiredReactivePropNames ??= /* @__PURE__ */ new Set()).add(key);
1837
- if (existingEntry && existingEntry.fnRef === value) continue;
1838
- if (existingEntry?.updateFn) {
1839
- existingEntry.updateFn(value);
1840
- existingEntry.fnRef = value;
1841
- continue;
1842
- }
1843
- if (existingEntry) existingEntry.cleanup();
1844
- const reactive = setupReactiveProp(el, key, value, vnode.type);
1845
- if (!elementReactivePropsCleanup.has(el)) elementReactivePropsCleanup.set(el, /* @__PURE__ */ new Map());
1846
- elementReactivePropsCleanup.get(el).set(key, {
1847
- cleanup: reactive.cleanup,
1848
- updateFn: (nextValue) => {
1849
- reactive.updateFn(nextValue);
1850
- },
1851
- fnRef: value
1852
- });
1853
- continue;
1854
- }
1855
- const existingReactiveEntry = existingReactiveProps?.get(key);
1856
- if (existingReactiveEntry) {
1857
- existingReactiveEntry.cleanup();
1858
- existingReactiveProps?.delete(key);
1859
- }
1860
- if (key === "class" || key === "className") writeElementClassName(el, String(value));
1861
- else if (key === "style") applyStylePropValue(el, value);
1862
- else if (key === "value" || key === "checked") applyFormControlProp(el, key, value, vnode.type);
1863
- else if (eventProp && listenerKey) {
1864
- const eventName = eventProp.eventName;
1865
- const eventCapture = eventProp.capture;
1866
- const useDelegation = !eventCapture && isEventDelegationEnabled() && isDelegatedEvent(eventName);
1867
- if (useDelegation) (desiredDelegatedEventNames ??= /* @__PURE__ */ new Set()).add(eventName);
1868
- if (useDelegation) {
1869
- const existingDelegated = getDelegatedHandlerForElement(el, eventName);
1870
- if (existingDelegated?.original === value) continue;
1871
- if (existingDelegated && updateDelegatedListener(el, eventName, value, value, void 0)) continue;
1872
- addDelegatedListener(el, eventName, value, value, void 0);
1873
- continue;
1874
- }
1875
- (desiredListenerKeys ??= /* @__PURE__ */ new Set()).add(listenerKey);
1876
- const existing = existingListeners?.get(listenerKey);
1877
- if (existing && existing.original === value) continue;
1878
- if (existing) {
1879
- if (useDelegation && existing.isDelegated && updateDelegatedListener(el, eventName, value, value, void 0)) {
1880
- existing.handler = value;
1881
- existing.original = value;
1882
- existing.options = void 0;
1883
- continue;
1884
- }
1885
- if (!useDelegation && !existing.isDelegated && existing.updateHandler) {
1886
- existing.updateHandler(value);
1887
- existing.original = value;
1888
- continue;
1889
- }
1890
- if (existing.isDelegated) removeDelegatedListener(el, existing.eventName);
1891
- else if (existing.options !== void 0) el.removeEventListener(existing.eventName, existing.handler, existing.options);
1892
- else el.removeEventListener(existing.eventName, existing.handler);
1893
- }
1894
- const options = getEventListenerOptions(eventName, eventCapture);
1895
- const mutableHandler = createMutableWrappedHandler(value, true);
1896
- const trackedHandler = mutableHandler.handler;
1897
- if (options !== void 0) el.addEventListener(eventName, trackedHandler, options);
1898
- else el.addEventListener(eventName, trackedHandler);
1899
- incDevCounter("listenerAdds");
1900
- const listenerEntry = {
1901
- handler: trackedHandler,
1902
- original: value,
1903
- eventName,
1904
- options,
1905
- isDelegated: false,
1906
- updateHandler: mutableHandler?.updateHandler
1907
- };
1908
- if (!elementListeners.has(el)) elementListeners.set(el, /* @__PURE__ */ new Map());
1909
- elementListeners.get(el).set(listenerKey, listenerEntry);
1910
- } else setRenderedAttribute(el, key, String(value));
1911
- }
1912
- removeStaleAttributes(el, domVNode, props);
1913
- if (existingListeners && existingListeners.size > 0) if (desiredListenerKeys === null) {
1914
- existingListeners.forEach((entry) => {
1915
- incDevCounter("listenerRemoves");
1916
- if (entry.isDelegated) removeDelegatedListener(el, entry.eventName);
1917
- else if (entry.options !== void 0) el.removeEventListener(entry.eventName, entry.handler, entry.options);
1918
- else el.removeEventListener(entry.eventName, entry.handler);
1919
- });
1920
- elementListeners.delete(el);
1921
- } else {
1922
- existingListeners.forEach((entry, listenerKey) => {
1923
- if (!desiredListenerKeys.has(listenerKey)) {
1924
- incDevCounter("listenerRemoves");
1925
- if (entry.isDelegated) removeDelegatedListener(el, entry.eventName);
1926
- else if (entry.options !== void 0) el.removeEventListener(entry.eventName, entry.handler, entry.options);
1927
- else el.removeEventListener(entry.eventName, entry.handler);
1928
- existingListeners.delete(listenerKey);
1929
- }
1930
- });
1931
- if (existingListeners.size === 0) elementListeners.delete(el);
1932
- }
1933
- const delegatedHandlers = getDelegatedHandlersForElement(el);
1934
- if (delegatedHandlers && delegatedHandlers.size > 0) {
1935
- if (desiredDelegatedEventNames === null) for (const eventName of delegatedHandlers.keys()) removeDelegatedListener(el, eventName);
1936
- else for (const eventName of delegatedHandlers.keys()) if (!desiredDelegatedEventNames.has(eventName)) removeDelegatedListener(el, eventName);
1937
- }
1938
- if (existingReactiveProps && existingReactiveProps.size > 0) if (desiredReactivePropNames === null) {
1939
- existingReactiveProps.forEach((entry) => {
1940
- entry.cleanup();
1941
- });
1942
- elementReactivePropsCleanup.delete(el);
1943
- } else {
1944
- existingReactiveProps.forEach((entry, key) => {
1945
- if (!desiredReactivePropNames.has(key)) {
1946
- entry.cleanup();
1947
- existingReactiveProps.delete(key);
1948
- }
1949
- });
1950
- if (existingReactiveProps.size === 0) elementReactivePropsCleanup.delete(el);
1951
- }
1952
- if (updateChildren) {
1953
- const children = props.children ?? vnode.children;
1954
- if (usesReactiveChildren) return;
1955
- updateElementChildren(el, children, forceChildrenUpdate);
1956
- }
1957
- }
1958
- function updateElementChildren(el, children, forceUpdate = false) {
1959
- const directControlBoundary = getDirectControlBoundaryVNode(children);
1960
- if (directControlBoundary) {
1961
- const controlState = getControlBoundaryState(directControlBoundary);
1962
- if (!controlState) throw new Error("[updateElementChildren] Control boundary missing internal state");
1963
- registerControlBoundaryCommitOwner(el, controlState);
1964
- commitForBoundaryChildren(el, controlState, evaluateControlBoundaryState(controlState));
1965
- return;
1966
- }
1967
- clearControlBoundaryCommitOwner(el);
1968
- if (children === null || children === void 0) {
1969
- for (let n = el.firstChild; n;) {
1970
- const next = n.nextSibling;
1971
- teardownNodeSubtree(n);
1972
- n = next;
1973
- }
1974
- el.textContent = "";
1975
- return;
1976
- }
1977
- if (!Array.isArray(children) && isFragmentVNode(children)) {
1978
- updateUnkeyedChildren(el, normalizeComponentChildren(children), forceUpdate);
1979
- return;
1980
- }
1981
- if (!Array.isArray(children) && (typeof children === "string" || typeof children === "number")) {
1982
- if (el.childNodes.length === 1 && el.firstChild?.nodeType === 3) {
1983
- const s = String(children);
1984
- const t = el.firstChild;
1985
- if (t.data !== s) t.data = s;
1986
- } else {
1987
- for (let n = el.firstChild; n;) {
1988
- const next = n.nextSibling;
1989
- teardownNodeSubtree(n);
1990
- n = next;
1991
- }
1992
- el.textContent = String(children);
1993
- }
1994
- return;
1995
- }
1996
- if (Array.isArray(children)) {
1997
- const normalizedChildren = normalizeComponentChildren(children);
1998
- if (trySyncScalarChildSequenceInPlace(el, normalizedChildren)) {
1999
- keyedElements.delete(el);
2000
- return;
2001
- }
2002
- if (hasKeyedVNodeChildren(normalizedChildren)) {
2003
- const newKeyMap = reconcileKeyedChildren(el, normalizedChildren, getOrBuildDomKeyMap(el));
2004
- keyedElements.set(el, newKeyMap);
2005
- return;
2006
- }
2007
- if (isBulkTextFastPathEligible(el, normalizedChildren)) {
2008
- performBulkTextReplace(el, normalizedChildren);
2009
- keyedElements.delete(el);
2010
- return;
2011
- }
2012
- updateUnkeyedChildren(el, normalizedChildren, forceUpdate);
2013
- return;
2014
- }
2015
- if (_isDOMElement(children)) {
2016
- updateUnkeyedChildren(el, [children], forceUpdate);
2017
- return;
2018
- }
2019
- for (let n = el.firstChild; n;) {
2020
- const next = n.nextSibling;
2021
- teardownNodeSubtree(n);
2022
- n = next;
2023
- }
2024
- el.textContent = "";
2025
- const dom = createDOMNode(children);
2026
- if (dom) el.appendChild(dom);
2027
- }
2028
- function hasKeyedVNodeChildren(children) {
2029
- for (let i = 0; i < children.length; i++) if (extractKey(children[i]) !== void 0) return true;
2030
- return false;
2031
- }
2032
- function isEmptyChild(child) {
2033
- return child === null || child === void 0 || child === false;
2034
- }
2035
- function getOrBuildDomKeyMap(parent) {
2036
- let keyMap = keyedElements.get(parent);
2037
- if (!keyMap) {
2038
- keyMap = /* @__PURE__ */ new Map();
2039
- for (let child = parent.firstElementChild; child; child = child.nextElementSibling) {
2040
- const key = child.getAttribute("data-key");
2041
- if (key !== null) {
2042
- keyMap.set(key, child);
2043
- const numericKey = Number(key);
2044
- if (!Number.isNaN(numericKey)) keyMap.set(numericKey, child);
2045
- }
2046
- }
2047
- if (keyMap.size > 0) keyedElements.set(parent, keyMap);
2048
- }
2049
- return keyMap.size > 0 ? keyMap : void 0;
2050
- }
2051
- function upperCommonTagName(tag) {
2052
- switch (tag) {
2053
- case "div": return "DIV";
2054
- case "span": return "SPAN";
2055
- case "p": return "P";
2056
- case "a": return "A";
2057
- case "button": return "BUTTON";
2058
- case "input": return "INPUT";
2059
- case "ul": return "UL";
2060
- case "ol": return "OL";
2061
- case "li": return "LI";
2062
- default: return null;
2063
- }
2064
- }
2065
- function tagsEqualIgnoreCase(elementTagName, vnodeType) {
2066
- const upperCommon = upperCommonTagName(vnodeType);
2067
- if (upperCommon !== null && elementTagName === upperCommon) return true;
2068
- return tagNamesEqualIgnoreCase(elementTagName, vnodeType);
2069
- }
2070
- const STATIC_CHILD_SLOTS_CACHE = Symbol.for("__askrStaticChildSlots");
2071
- let staticChildSlotsCacheEnabled = true;
2072
- function setStaticChildSlotsCacheEnabled(enabled) {
2073
- staticChildSlotsCacheEnabled = enabled;
2074
- }
2075
- function collectStaticChildSlots(children, slots) {
2076
- if (isFragmentVNode(children)) return collectStaticChildSlots(children.props?.children ?? children.children, slots);
2077
- if (Array.isArray(children)) {
2078
- for (const child of children) if (!collectStaticChildSlots(child, slots)) return false;
2079
- return true;
2080
- }
2081
- if (children === null || children === void 0 || children === false) return true;
2082
- if (typeof children === "string" || typeof children === "number") {
2083
- slots.push({
2084
- kind: "text",
2085
- value: String(children)
2086
- });
2087
- return true;
2088
- }
2089
- if (_isDOMElement(children) && typeof children.type === "string") {
2090
- slots.push({
2091
- kind: "element",
2092
- value: children
2093
- });
2094
- return true;
2095
- }
2096
- return false;
2097
- }
2098
- function getStaticChildSlots(vnode) {
2099
- if (staticChildSlotsCacheEnabled) {
2100
- const cached = vnode[STATIC_CHILD_SLOTS_CACHE];
2101
- if (cached !== void 0) return cached;
2102
- }
2103
- const slots = [];
2104
- const staticSlots = collectStaticChildSlots(vnode.props?.children ?? vnode.children, slots) ? slots : null;
2105
- if (staticChildSlotsCacheEnabled) {
2106
- const cacheNode = vnode;
2107
- if (Object.isExtensible(vnode)) cacheNode[STATIC_CHILD_SLOTS_CACHE] = staticSlots;
2108
- }
2109
- return staticSlots;
2110
- }
2111
- function hasMatchingStaticProps(el, props, vnodeType) {
2112
- let staticPropCount = 0;
2113
- for (const key in props) {
2114
- if (isSkippedProp(key)) continue;
2115
- const value = props[key];
2116
- if (value === void 0 || value === null || value === false) return false;
2117
- if (parseEventName(key) || typeof value === "function") return false;
2118
- if (key === "class" || key === "className") {
2119
- if (readElementClassName(el) !== String(value)) return false;
2120
- staticPropCount += 1;
2121
- continue;
2122
- }
2123
- if (key === "style") {
2124
- const styleValue = typeof value === "string" ? value.trim().replace(/;$/, "") : null;
2125
- const domStyle = el.getAttribute("style")?.trim().replace(/;$/, "") ?? "";
2126
- if (styleValue === null || domStyle !== styleValue) return false;
2127
- staticPropCount += 1;
2128
- continue;
2129
- }
2130
- if (key === "value" || key === "checked") {
2131
- if (el[key] !== value) return false;
2132
- staticPropCount += 1;
2133
- continue;
2134
- }
2135
- if (key === "selected" && vnodeType === "option") {
2136
- if (el.selected !== Boolean(value)) return false;
2137
- staticPropCount += 1;
2138
- continue;
2139
- }
2140
- if (el.getAttribute(getRenderedAttributeName(el, key)) !== String(value)) return false;
2141
- staticPropCount += 1;
2142
- }
2143
- return el.attributes.length === staticPropCount;
2144
- }
2145
- function canReuseStaticSubtree(el, vnode) {
2146
- if (typeof vnode.type !== "string" || !tagsEqualIgnoreCase(el.tagName, vnode.type)) return false;
2147
- if (!hasMatchingStaticProps(el, vnode.props || {}, vnode.type)) return false;
2148
- const slots = getStaticChildSlots(vnode);
2149
- if (!slots) return false;
2150
- if (el.childNodes.length !== slots.length) return false;
2151
- for (let index = 0; index < slots.length; index += 1) {
2152
- const slot = slots[index];
2153
- const current = el.childNodes[index];
2154
- if (!current) return false;
2155
- if (slot.kind === "text") {
2156
- if (current.nodeType !== 3 || current.data !== slot.value) return false;
2157
- continue;
2158
- }
2159
- if (!(current instanceof Element)) return false;
2160
- if (!canReuseStaticSubtree(current, slot.value)) return false;
2161
- }
2162
- return true;
2163
- }
2164
- function updateUnkeyedChildren(parent, newChildren, forceUpdate = false) {
2165
- const parentNamespace = parent.namespaceURI === SVG_NAMESPACE ? SVG_NAMESPACE : void 0;
2166
- const trySyncComponentChild = (currentDom, next) => {
2167
- if (typeof next.type !== "function") return null;
2168
- return syncComponentElement(currentDom, next, next.type, (next.props ?? {}) || {}, parentNamespace, forceUpdate);
2169
- };
2170
- const trySyncControlBoundaryChild = (parent, currentNode, next) => {
2171
- if (next.type !== __FOR_BOUNDARY__) return false;
2172
- const controlState = getControlBoundaryState(next);
2173
- if (!controlState || controlState.kind === "for") return false;
2174
- const childrenVNodes = evaluateControlBoundaryState(controlState);
2175
- const activeScope = controlState.activeScope;
2176
- const activeVNode = childrenVNodes[0];
2177
- const nextDom = activeScope && activeVNode !== void 0 ? syncForItemDom(parent, activeScope, activeVNode) : null;
2178
- for (let i = 0; i < controlState.lastRemovedNodes.length; i++) {
2179
- const removedNode = controlState.lastRemovedNodes[i];
2180
- if (removedNode.parentNode !== parent) continue;
2181
- teardownNodeSubtree(removedNode);
2182
- if (nextDom && nextDom !== removedNode && !nextDom.parentNode) parent.replaceChild(nextDom, removedNode);
2183
- else parent.removeChild(removedNode);
2184
- }
2185
- if (nextDom && !nextDom.parentNode) if (currentNode?.parentNode === parent) {
2186
- teardownNodeSubtree(currentNode);
2187
- parent.replaceChild(nextDom, currentNode);
2188
- } else parent.appendChild(nextDom);
2189
- else if (!nextDom && currentNode?.parentNode === parent) {
2190
- teardownNodeSubtree(currentNode);
2191
- parent.removeChild(currentNode);
2192
- }
2193
- clearControlBoundaryDomUpdateState(controlState);
2194
- return true;
2195
- };
2196
- const hasText = newChildren.some((c) => typeof c === "string" || typeof c === "number");
2197
- const hasElements = newChildren.some((c) => _isDOMElement(c));
2198
- const hasEmptyChildren = newChildren.some(isEmptyChild);
2199
- const hasComponentChildren = newChildren.some((c) => _isDOMElement(c) && typeof c.type === "function");
2200
- const hasNonElementDomChildren = parent.childNodes.length !== parent.children.length;
2201
- if (!hasEmptyChildren && !hasText && !hasComponentChildren && !hasNonElementDomChildren && hasElements && parent.children.length === newChildren.length) {
2202
- const c = parent.children;
2203
- for (let i = 0; i < newChildren.length; i++) {
2204
- const next = newChildren[i];
2205
- const current = c[i];
2206
- if (!current || next === void 0) continue;
2207
- if (_isDOMElement(next) && typeof next.type === "string") if (tagsEqualIgnoreCase(current.tagName, next.type)) updateElementFromVnode(current, next, true, forceUpdate);
2208
- else {
2209
- const dom = createDOMNode(next, parentNamespace);
2210
- if (dom) {
2211
- teardownNodeSubtree(current);
2212
- parent.replaceChild(dom, current);
2213
- }
2214
- }
2215
- else if (_isDOMElement(next)) {
2216
- if (trySyncControlBoundaryChild(parent, current, next)) continue;
2217
- const synced = trySyncComponentChild(current, next);
2218
- if (synced && synced !== current) teardownNodeSubtree(current);
2219
- else if (!synced) {
2220
- const dom = createDOMNode(next, parentNamespace);
2221
- if (dom) {
2222
- teardownNodeSubtree(current);
2223
- parent.replaceChild(dom, current);
2224
- }
2225
- }
2226
- } else {
2227
- const dom = createDOMNode(next, parentNamespace);
2228
- if (dom) {
2229
- teardownNodeSubtree(current);
2230
- parent.replaceChild(dom, current);
2231
- }
2232
- }
2233
- }
2234
- return;
2235
- }
2236
- const existing = Array.from(parent.children);
2237
- if (hasText || hasComponentChildren || hasEmptyChildren || hasNonElementDomChildren) {
2238
- const allNodes = Array.from(parent.childNodes);
2239
- const max = Math.max(allNodes.length, newChildren.length);
2240
- for (let i = 0; i < max; i++) {
2241
- const currentNode = allNodes[i];
2242
- const next = newChildren[i];
2243
- const nextIsEmpty = isEmptyChild(next);
2244
- if (nextIsEmpty && currentNode) {
2245
- teardownNodeSubtree(currentNode);
2246
- currentNode.remove();
2247
- continue;
2248
- }
2249
- if (!currentNode && !nextIsEmpty) {
2250
- const dom = createDOMNode(next, parentNamespace);
2251
- if (dom) parent.appendChild(dom);
2252
- continue;
2253
- }
2254
- if (!currentNode || nextIsEmpty) continue;
2255
- if (typeof next === "string" || typeof next === "number") if (currentNode.nodeType === 3) currentNode.data = String(next);
2256
- else {
2257
- const textNode = document.createTextNode(String(next));
2258
- parent.replaceChild(textNode, currentNode);
2259
- }
2260
- else if (_isDOMElement(next)) if (currentNode.nodeType === 1) {
2261
- const currentEl = currentNode;
2262
- if (typeof next.type === "string") if (tagsEqualIgnoreCase(currentEl.tagName, next.type)) updateElementFromVnode(currentEl, next, true, forceUpdate);
2263
- else {
2264
- const dom = createDOMNode(next, parentNamespace);
2265
- if (dom) {
2266
- teardownNodeSubtree(currentEl);
2267
- parent.replaceChild(dom, currentNode);
2268
- }
2269
- }
2270
- else {
2271
- if (trySyncControlBoundaryChild(parent, currentNode, next)) continue;
2272
- const synced = trySyncComponentChild(currentEl, next);
2273
- if (synced && synced !== currentNode) teardownNodeSubtree(currentEl);
2274
- else if (!synced) {
2275
- const dom = createDOMNode(next, parentNamespace);
2276
- if (dom) {
2277
- teardownNodeSubtree(currentEl);
2278
- parent.replaceChild(dom, currentNode);
2279
- }
2280
- }
2281
- }
2282
- } else {
2283
- const dom = createDOMNode(next, parentNamespace);
2284
- if (dom) parent.replaceChild(dom, currentNode);
2285
- }
2286
- }
2287
- return;
2288
- }
2289
- if (newChildren.length === 1 && existing.length === 0 && parent.childNodes.length === 1) {
2290
- const firstNewChild = newChildren[0];
2291
- const firstExisting = parent.firstChild;
2292
- if ((typeof firstNewChild === "string" || typeof firstNewChild === "number") && firstExisting?.nodeType === 3) {
2293
- firstExisting.data = String(firstNewChild);
2294
- return;
2295
- }
2296
- }
2297
- if (existing.length === 0 && parent.childNodes.length > 0) {
2298
- for (let n = parent.firstChild; n;) {
2299
- const next = n.nextSibling;
2300
- teardownNodeSubtree(n);
2301
- n = next;
2302
- }
2303
- parent.textContent = "";
2304
- }
2305
- const max = Math.max(existing.length, newChildren.length);
2306
- for (let i = 0; i < max; i++) {
2307
- const current = existing[i];
2308
- const next = newChildren[i];
2309
- const nextIsEmpty = isEmptyChild(next);
2310
- if (nextIsEmpty && current) {
2311
- teardownNodeSubtree(current);
2312
- current.remove();
2313
- continue;
2314
- }
2315
- if (!current && !nextIsEmpty) {
2316
- const dom = createDOMNode(next, parentNamespace);
2317
- if (dom) parent.appendChild(dom);
2318
- continue;
2319
- }
2320
- if (!current || nextIsEmpty) continue;
2321
- if (typeof next === "string" || typeof next === "number") {
2322
- const textNode = document.createTextNode(String(next));
2323
- teardownNodeSubtree(current);
2324
- parent.replaceChild(textNode, current);
2325
- } else if (_isDOMElement(next)) if (typeof next.type === "string") if (tagsEqualIgnoreCase(current.tagName, next.type)) updateElementFromVnode(current, next, true, forceUpdate);
2326
- else {
2327
- const dom = createDOMNode(next, parentNamespace);
2328
- if (dom) {
2329
- teardownNodeSubtree(current);
2330
- parent.replaceChild(dom, current);
2331
- }
2332
- }
2333
- else {
2334
- const synced = trySyncComponentChild(current, next);
2335
- if (synced && synced !== current) teardownNodeSubtree(current);
2336
- else if (!synced) {
2337
- const dom = createDOMNode(next, parentNamespace);
2338
- if (dom) {
2339
- teardownNodeSubtree(current);
2340
- parent.replaceChild(dom, current);
2341
- }
2342
- }
2343
- }
2344
- else {
2345
- const dom = createDOMNode(next);
2346
- if (dom) {
2347
- teardownNodeSubtree(current);
2348
- parent.replaceChild(dom, current);
2349
- }
2350
- }
2351
- }
2352
- }
2353
- //#endregion
2354
- export { IS_DOM_AVAILABLE, commitForBoundaryChildren, createDOMNode, createForBoundary, markReactivePropsDirtySource, setStaticChildSlotsCacheEnabled, syncComponentElement, tryPatchStableForDirtyItem, updateElementChildren, updateElementFromVnode, updateUnkeyedChildren };
2355
-
2356
- //# sourceMappingURL=dom.js.map
1
+ import "./boundaries.js";
2
+ import { isBulkTextFastPathEligible, performBulkPositionalKeyedTextUpdate, performBulkTextReplace } from "./children.js";
3
+ import { syncComponentElement } from "./component-host.js";
4
+ import { setStaticChildSlotsCacheEnabled } from "./static-reuse.js";
5
+ import { updateElementChildren, updateUnkeyedChildren } from "./element-children.js";
6
+ import { markReactivePropsDirtySource } from "./prop-bindings.js";
7
+ import { tryPatchStableForDirtyItem } from "./stable-patch.js";
8
+ import { IS_DOM_AVAILABLE, createDOMNode, updateElementFromVnode } from "./dom-internal.js";
9
+ export { IS_DOM_AVAILABLE, createDOMNode, isBulkTextFastPathEligible, markReactivePropsDirtySource, performBulkPositionalKeyedTextUpdate, performBulkTextReplace, setStaticChildSlotsCacheEnabled, syncComponentElement, tryPatchStableForDirtyItem, updateElementChildren, updateElementFromVnode, updateUnkeyedChildren };