@askrjs/askr 0.0.49 → 0.0.51

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 (238) hide show
  1. package/dist/bench/components/benchmark-table.js.map +1 -1
  2. package/dist/benchmark.js +5 -4
  3. package/dist/benchmark.js.map +1 -1
  4. package/dist/bin/askr-ssg.d.ts.map +1 -1
  5. package/dist/bin/askr-ssg.js.map +1 -1
  6. package/dist/boot/hydration.js.map +1 -1
  7. package/dist/boot/index.js +2 -1
  8. package/dist/boot/index.js.map +1 -1
  9. package/dist/boot/root-lifecycle.d.ts.map +1 -1
  10. package/dist/boot/root-lifecycle.js +4 -4
  11. package/dist/boot/root-lifecycle.js.map +1 -1
  12. package/dist/boot/route-startup.js.map +1 -1
  13. package/dist/common/error-boundary.d.ts +16 -0
  14. package/dist/common/error-boundary.d.ts.map +1 -0
  15. package/dist/common/invariant.js +17 -0
  16. package/dist/common/invariant.js.map +1 -0
  17. package/dist/common/jsx.d.ts +6 -2
  18. package/dist/common/jsx.d.ts.map +1 -1
  19. package/dist/common/jsx.js.map +1 -1
  20. package/dist/{dev → common}/logger.js +5 -6
  21. package/dist/common/logger.js.map +1 -0
  22. package/dist/common/vnode.d.ts +2 -2
  23. package/dist/common/vnode.d.ts.map +1 -1
  24. package/dist/common/vnode.js.map +1 -1
  25. package/dist/components/error-boundary.d.ts +2 -15
  26. package/dist/components/error-boundary.d.ts.map +1 -1
  27. package/dist/components/error-boundary.js +2 -74
  28. package/dist/components/error-boundary.js.map +1 -1
  29. package/dist/components/index.d.ts +2 -1
  30. package/dist/components/link.js +2 -0
  31. package/dist/components/link.js.map +1 -1
  32. package/dist/control/case.d.ts.map +1 -1
  33. package/dist/control/case.js +1 -0
  34. package/dist/control/case.js.map +1 -1
  35. package/dist/control/for.d.ts +3 -3
  36. package/dist/control/for.d.ts.map +1 -1
  37. package/dist/control/for.js +2 -2
  38. package/dist/control/for.js.map +1 -1
  39. package/dist/control/show.js +1 -0
  40. package/dist/control/show.js.map +1 -1
  41. package/dist/data/data-runtime.js.map +1 -1
  42. package/dist/data/invalidation.js +2 -2
  43. package/dist/data/invalidation.js.map +1 -1
  44. package/dist/data/mutation-cell.d.ts.map +1 -1
  45. package/dist/data/mutation-cell.js +1 -1
  46. package/dist/data/mutation-cell.js.map +1 -1
  47. package/dist/data/query-cell.js +2 -2
  48. package/dist/data/query-cell.js.map +1 -1
  49. package/dist/data/shared.js +1 -0
  50. package/dist/data/shared.js.map +1 -1
  51. package/dist/data/testing.js +2 -0
  52. package/dist/foundations/index.d.ts +1 -1
  53. package/dist/foundations/index.js +1 -1
  54. package/dist/foundations/state/controllable.d.ts +0 -1
  55. package/dist/foundations/state/controllable.d.ts.map +1 -1
  56. package/dist/foundations/state/controllable.js +1 -0
  57. package/dist/foundations/state/controllable.js.map +1 -1
  58. package/dist/foundations/structures/index.d.ts +1 -1
  59. package/dist/foundations/structures/index.js +2 -1
  60. package/dist/foundations/structures/portal.d.ts +2 -24
  61. package/dist/foundations/structures/portal.js +3 -187
  62. package/dist/fx/fx.js +2 -2
  63. package/dist/fx/fx.js.map +1 -1
  64. package/dist/fx/index.js +1 -0
  65. package/dist/index.d.ts +3 -3
  66. package/dist/index.js +4 -4
  67. package/dist/index.js.map +1 -1
  68. package/dist/jsx/index.d.ts +1 -1
  69. package/dist/jsx/types.d.ts +2 -2
  70. package/dist/jsx-dev-runtime.d.ts +2 -2
  71. package/dist/jsx-dev-runtime.d.ts.map +1 -1
  72. package/dist/jsx-dev-runtime.js +1 -0
  73. package/dist/jsx-dev-runtime.js.map +1 -1
  74. package/dist/jsx-runtime.d.ts +2 -2
  75. package/dist/jsx-runtime.d.ts.map +1 -1
  76. package/dist/jsx-runtime.js +1 -0
  77. package/dist/jsx-runtime.js.map +1 -1
  78. package/dist/jsx-runtime2.d.ts +1 -1
  79. package/dist/renderer/attributes.js +1 -0
  80. package/dist/renderer/attributes.js.map +1 -1
  81. package/dist/renderer/boundaries.js +5 -5
  82. package/dist/renderer/boundaries.js.map +1 -1
  83. package/dist/renderer/child-shape.js +2 -2
  84. package/dist/renderer/child-shape.js.map +1 -1
  85. package/dist/renderer/children-fastpath.js +149 -0
  86. package/dist/renderer/children-fastpath.js.map +1 -0
  87. package/dist/renderer/children.js +3 -138
  88. package/dist/renderer/children.js.map +1 -1
  89. package/dist/renderer/cleanup.js +2 -2
  90. package/dist/renderer/cleanup.js.map +1 -1
  91. package/dist/renderer/component-host-cleanup.js +1 -1
  92. package/dist/renderer/component-host-cleanup.js.map +1 -1
  93. package/dist/renderer/component-host-instances.js +1 -1
  94. package/dist/renderer/component-host-instances.js.map +1 -1
  95. package/dist/renderer/component-host.js +1 -1
  96. package/dist/renderer/component-host.js.map +1 -1
  97. package/dist/renderer/dom-host.js.map +1 -1
  98. package/dist/renderer/dom-internal.js +5 -4
  99. package/dist/renderer/dom-internal.js.map +1 -1
  100. package/dist/renderer/dom.js +2 -1
  101. package/dist/renderer/element-children.js.map +1 -1
  102. package/dist/renderer/error-boundary-dom.js +51 -2
  103. package/dist/renderer/error-boundary-dom.js.map +1 -1
  104. package/dist/renderer/evaluate-reconcile.js +6 -5
  105. package/dist/renderer/evaluate-reconcile.js.map +1 -1
  106. package/dist/renderer/evaluate.js.map +1 -1
  107. package/dist/renderer/fastpath.js +3 -2
  108. package/dist/renderer/fastpath.js.map +1 -1
  109. package/dist/renderer/for-commit-dom-map.js.map +1 -1
  110. package/dist/renderer/for-commit-removal.js +2 -2
  111. package/dist/renderer/for-commit-removal.js.map +1 -1
  112. package/dist/renderer/for-commit-reorder.js +2 -2
  113. package/dist/renderer/for-commit-reorder.js.map +1 -1
  114. package/dist/renderer/for-commit.js +3 -3
  115. package/dist/renderer/for-commit.js.map +1 -1
  116. package/dist/renderer/index.js +3 -1
  117. package/dist/renderer/index.js.map +1 -1
  118. package/dist/renderer/prop-bindings.js +4 -4
  119. package/dist/renderer/prop-bindings.js.map +1 -1
  120. package/dist/renderer/reactive-child-dom.js.map +1 -1
  121. package/dist/renderer/reactive-children.js +4 -4
  122. package/dist/renderer/reactive-children.js.map +1 -1
  123. package/dist/renderer/reconcile-fastpaths.js +2 -1
  124. package/dist/renderer/reconcile-fastpaths.js.map +1 -1
  125. package/dist/renderer/reconcile-resolution.js +3 -3
  126. package/dist/renderer/reconcile-resolution.js.map +1 -1
  127. package/dist/renderer/retained-element-rollback.js +2 -1
  128. package/dist/renderer/retained-element-rollback.js.map +1 -1
  129. package/dist/renderer/stable-patch.js +2 -3
  130. package/dist/renderer/stable-patch.js.map +1 -1
  131. package/dist/renderer/utils.js +2 -1
  132. package/dist/renderer/utils.js.map +1 -1
  133. package/dist/resources/index.js +1 -2
  134. package/dist/router/activity.d.ts.map +1 -1
  135. package/dist/router/activity.js +20 -22
  136. package/dist/router/activity.js.map +1 -1
  137. package/dist/router/authoring.js +1 -1
  138. package/dist/router/authoring.js.map +1 -1
  139. package/dist/router/index.d.ts +1 -1
  140. package/dist/router/navigate.js +1 -1
  141. package/dist/router/navigate.js.map +1 -1
  142. package/dist/router/navigation-registry.js +1 -1
  143. package/dist/router/navigation-registry.js.map +1 -1
  144. package/dist/router/navigation-targets.d.ts.map +1 -1
  145. package/dist/router/navigation-targets.js +7 -5
  146. package/dist/router/navigation-targets.js.map +1 -1
  147. package/dist/router/rendering.js +1 -0
  148. package/dist/router/rendering.js.map +1 -1
  149. package/dist/router/resolution.d.ts +1 -14
  150. package/dist/router/resolution.d.ts.map +1 -1
  151. package/dist/router/resolution.js +6 -173
  152. package/dist/router/resolution.js.map +1 -1
  153. package/dist/router/route-matching.d.ts +20 -0
  154. package/dist/router/route-matching.d.ts.map +1 -0
  155. package/dist/router/route-matching.js +175 -0
  156. package/dist/router/route-matching.js.map +1 -0
  157. package/dist/router/route.js +4 -2
  158. package/dist/router/testing.js +4 -0
  159. package/dist/runtime/access.d.ts +20 -0
  160. package/dist/runtime/access.d.ts.map +1 -0
  161. package/dist/runtime/component-cleanup.js +1 -1
  162. package/dist/runtime/component-cleanup.js.map +1 -1
  163. package/dist/runtime/component-commit.js +1 -1
  164. package/dist/runtime/component-commit.js.map +1 -1
  165. package/dist/runtime/component-internal.d.ts +1 -1
  166. package/dist/runtime/component-internal.js +1 -1
  167. package/dist/runtime/component-internal.js.map +1 -1
  168. package/dist/runtime/component-lifecycle.d.ts +1 -1
  169. package/dist/runtime/component-lifecycle.js +1 -1
  170. package/dist/runtime/component-lifecycle.js.map +1 -1
  171. package/dist/runtime/component-scope.d.ts +1 -1
  172. package/dist/runtime/dev-namespace.d.ts +31 -0
  173. package/dist/runtime/dev-namespace.d.ts.map +1 -0
  174. package/dist/runtime/error-boundary.d.ts +5 -0
  175. package/dist/runtime/error-boundary.d.ts.map +1 -0
  176. package/dist/runtime/error-boundary.js +31 -0
  177. package/dist/runtime/error-boundary.js.map +1 -0
  178. package/dist/runtime/events.d.ts +58 -0
  179. package/dist/runtime/events.d.ts.map +1 -0
  180. package/dist/runtime/events.js +1 -1
  181. package/dist/runtime/events.js.map +1 -1
  182. package/dist/runtime/execution-model.d.ts +7 -0
  183. package/dist/runtime/execution-model.d.ts.map +1 -0
  184. package/dist/runtime/fastlane.d.ts +34 -0
  185. package/dist/runtime/fastlane.d.ts.map +1 -0
  186. package/dist/runtime/for-internal.d.ts +5 -5
  187. package/dist/runtime/for-internal.d.ts.map +1 -1
  188. package/dist/runtime/for-internal.js.map +1 -1
  189. package/dist/runtime/for-signals.d.ts +1 -1
  190. package/dist/runtime/for-signals.d.ts.map +1 -1
  191. package/dist/runtime/for-signals.js +1 -1
  192. package/dist/runtime/for-signals.js.map +1 -1
  193. package/dist/runtime/for-types.d.ts +9 -0
  194. package/dist/runtime/for-types.d.ts.map +1 -0
  195. package/dist/runtime/index.d.ts +24 -0
  196. package/dist/runtime/index.js +31 -0
  197. package/dist/runtime/perf-metrics.d.ts +26 -0
  198. package/dist/runtime/perf-metrics.d.ts.map +1 -0
  199. package/dist/runtime/portal.d.ts +22 -0
  200. package/dist/runtime/portal.d.ts.map +1 -0
  201. package/dist/runtime/portal.js +213 -0
  202. package/dist/runtime/portal.js.map +1 -0
  203. package/dist/runtime/resource-cell.js +1 -1
  204. package/dist/runtime/resource-cell.js.map +1 -1
  205. package/dist/runtime/resource-operation.js +1 -1
  206. package/dist/runtime/runtime.d.ts +1 -1
  207. package/dist/runtime/scheduler.js +2 -2
  208. package/dist/runtime/scheduler.js.map +1 -1
  209. package/dist/runtime/selector-store.js +24 -0
  210. package/dist/runtime/selector-store.js.map +1 -0
  211. package/dist/runtime/selector.d.ts.map +1 -1
  212. package/dist/runtime/selector.js +3 -18
  213. package/dist/runtime/selector.js.map +1 -1
  214. package/dist/ssg/create-static-gen.js +1 -0
  215. package/dist/ssg/create-static-gen.js.map +1 -1
  216. package/dist/ssg/static-routes.js +1 -0
  217. package/dist/ssg/static-routes.js.map +1 -1
  218. package/dist/ssr/boundaries.js +2 -2
  219. package/dist/ssr/boundaries.js.map +1 -1
  220. package/dist/ssr/component-runtime.js +3 -3
  221. package/dist/ssr/component-runtime.js.map +1 -1
  222. package/dist/ssr/render-resolved.js +1 -1
  223. package/dist/ssr/render-sync.js +1 -1
  224. package/dist/ssr/render-sync.js.map +1 -1
  225. package/dist/ssr/route-policy-resolution.js +2 -1
  226. package/dist/ssr/route-policy-resolution.js.map +1 -1
  227. package/dist/ssr/route-render.js +2 -1
  228. package/dist/ssr/route-render.js.map +1 -1
  229. package/dist/testing/index.d.ts.map +1 -1
  230. package/dist/testing/index.js +3 -2
  231. package/dist/testing/index.js.map +1 -1
  232. package/package.json +4 -4
  233. package/dist/dev/invariant.js +0 -29
  234. package/dist/dev/invariant.js.map +0 -1
  235. package/dist/dev/logger.js.map +0 -1
  236. package/dist/foundations/structures/portal.d.ts.map +0 -1
  237. package/dist/foundations/structures/portal.js.map +0 -1
  238. package/dist/runtime/component-contracts.js +0 -5
@@ -1,15 +1,15 @@
1
1
  import { getRuntimeEnv } from "../common/env.js";
2
- import { logger } from "../dev/logger.js";
2
+ import { logger } from "../common/logger.js";
3
3
  import { incrementPerfMetric } from "../runtime/perf-metrics.js";
4
4
  import { incDevCounter } from "../runtime/dev-namespace.js";
5
+ import { createFineGrainedEffect, markFineGrainedEffectsDirtySource } from "../runtime/effect.js";
5
6
  import { addDelegatedListener, getDelegatedHandlerForElement, getDelegatedHandlersForElement, isDelegatedEvent, isEventDelegationEnabled, removeDelegatedListener, updateDelegatedListener } from "../runtime/events.js";
7
+ import { isBenchMetricScopeActive, recordBenchCounter } from "../runtime/for-bench.js";
8
+ import "../runtime/index.js";
6
9
  import { REACTIVE_CHILDREN_KEY, elementListeners, elementReactivePropsCleanup, updateElementRef } from "./cleanup.js";
7
10
  import "./env.js";
8
11
  import { createMutableWrappedHandler, getEventListenerKey, getEventListenerOptions, isSkippedProp, parseEventProp } from "./utils.js";
9
- import { isBenchMetricScopeActive, recordBenchCounter } from "../runtime/for-bench.js";
10
- import "../runtime/for.js";
11
12
  import { applyScalarPropValue, removeStaleAttributes } from "./attributes.js";
12
- import { createFineGrainedEffect, markFineGrainedEffectsDirtySource } from "../runtime/effect.js";
13
13
  //#region src/renderer/prop-bindings.ts
14
14
  const reactivePropRegistry = /* @__PURE__ */ new Set();
15
15
  function addTrackedListener(el, eventName, handler, capture = false) {
@@ -1 +1 @@
1
- {"version":3,"file":"prop-bindings.js","names":[],"sources":["../../src/renderer/prop-bindings.ts"],"sourcesContent":["import { logger } from '../dev/logger';\nimport { incDevCounter } from '../runtime/dev-namespace';\nimport {\n createFineGrainedEffect,\n markFineGrainedEffectsDirtySource,\n type FineGrainedEffectHandle,\n} from '../runtime/effect';\nimport { isBenchMetricScopeActive, recordBenchCounter } from '../runtime/for';\nimport { incrementPerfMetric } from '../runtime/perf-metrics';\nimport type { ReadableSource } from '../runtime/readable';\nimport {\n isEventDelegationEnabled,\n addDelegatedListener,\n getDelegatedHandlerForElement,\n getDelegatedHandlersForElement,\n updateDelegatedListener,\n removeDelegatedListener,\n isDelegatedEvent,\n} from '../runtime/events';\nimport { applyScalarPropValue, removeStaleAttributes } from './attributes';\nimport {\n elementListeners,\n elementReactivePropsCleanup,\n REACTIVE_CHILDREN_KEY,\n type ReactivePropCleanupEntry,\n updateElementRef,\n} from './cleanup';\nimport { getRuntimeEnv } from './env';\nimport type { DOMElement } from './types';\nimport {\n createMutableWrappedHandler,\n getEventListenerKey,\n getEventListenerOptions,\n isSkippedProp,\n parseEventProp,\n} from './utils';\n\ninterface ReactivePropDescriptor {\n el: Element;\n propName: string;\n propFn: () => unknown;\n tagName: string;\n lastClassTokens: string[] | null;\n}\n\nconst reactivePropRegistry = new Set<ReactivePropDescriptor>();\n\nfunction addTrackedListener(\n el: Element,\n eventName: string,\n handler: EventListener,\n capture = false\n): void {\n const useDelegation =\n !capture && isEventDelegationEnabled() && isDelegatedEvent(eventName);\n const listenerKey = getEventListenerKey(eventName, capture);\n\n if (useDelegation) {\n addDelegatedListener(el, eventName, handler, handler, undefined);\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('listenerBindings');\n }\n return;\n }\n\n const options = getEventListenerOptions(eventName, capture);\n const mutableHandler = createMutableWrappedHandler(handler, true);\n const trackedHandler = mutableHandler.handler;\n\n if (options !== undefined) {\n el.addEventListener(eventName, trackedHandler, options);\n } else {\n el.addEventListener(eventName, trackedHandler);\n }\n incDevCounter('listenerAdds');\n\n if (!elementListeners.has(el)) {\n elementListeners.set(el, new Map());\n }\n elementListeners.get(el)!.set(listenerKey, {\n handler: trackedHandler,\n original: handler,\n eventName,\n options,\n isDelegated: false,\n updateHandler: mutableHandler?.updateHandler,\n });\n\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('listenerBindings');\n }\n}\n\nexport function markReactivePropsDirtySource(\n source: ReadableSource<unknown>\n): void {\n markFineGrainedEffectsDirtySource(source);\n}\n\nfunction setupReactiveProp(\n el: Element,\n propName: string,\n propFn: () => unknown,\n tagName: string\n): { cleanup: () => void; updateFn: (nextFn: () => unknown) => void } {\n const descriptor: ReactivePropDescriptor = {\n el,\n propName,\n propFn,\n tagName,\n lastClassTokens: null,\n };\n\n let effectHandle: FineGrainedEffectHandle<unknown> | null = null;\n\n reactivePropRegistry.add(descriptor);\n effectHandle = createFineGrainedEffect({\n lane: 'reactive',\n compute: () => descriptor.propFn(),\n commit: (value, previousValue) => {\n incrementPerfMetric('reactivePropReevaluations');\n applyScalarPropValue(\n el,\n propName,\n value,\n tagName,\n previousValue,\n descriptor\n );\n },\n equals: (previousValue, nextValue) => {\n if (Object.is(previousValue, nextValue)) {\n incrementPerfMetric('skippedDomPropWrites');\n return true;\n }\n return false;\n },\n onError: (err) => {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive prop update failed:', err);\n }\n },\n });\n\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('reactivePropsMounted');\n }\n\n const cleanup = () => {\n reactivePropRegistry.delete(descriptor);\n effectHandle?.cleanup();\n effectHandle = null;\n };\n\n const updateFn = (nextFn: () => unknown): void => {\n if (!effectHandle) {\n return;\n }\n\n descriptor.propFn = nextFn;\n\n try {\n effectHandle.updateCompute(nextFn);\n } catch (err) {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive prop update failed:', err);\n }\n }\n };\n\n return {\n cleanup,\n updateFn,\n };\n}\n\nfunction getOrCreateReactivePropsCleanupMap(\n el: Element\n): Map<string, ReactivePropCleanupEntry> {\n let cleanupMap = elementReactivePropsCleanup.get(el);\n if (!cleanupMap) {\n cleanupMap = new Map();\n elementReactivePropsCleanup.set(el, cleanupMap);\n }\n return cleanupMap;\n}\n\nfunction createReactivePropCleanupEntry(\n el: Element,\n propName: string,\n propFn: () => unknown,\n tagName: string\n): ReactivePropCleanupEntry {\n const reactive = setupReactiveProp(el, propName, propFn, tagName);\n\n return {\n cleanup: reactive.cleanup,\n updateFn: (nextValue) => {\n reactive.updateFn(nextValue as () => unknown);\n },\n restoreFn: (nextValue) =>\n createReactivePropCleanupEntry(\n el,\n propName,\n nextValue as () => unknown,\n tagName\n ),\n fnRef: propFn,\n };\n}\n\nexport function hasTrackedElementPropBindings(el: Element): boolean {\n const existingListeners = elementListeners.get(el);\n const existingReactiveProps = elementReactivePropsCleanup.get(el);\n return (\n (existingListeners !== undefined && existingListeners.size > 0) ||\n (existingReactiveProps !== undefined && existingReactiveProps.size > 0)\n );\n}\n\nexport function applyPropsToElement(\n el: Element,\n props: Record<string, unknown>,\n tagName: string,\n isHydrationSkipped: (el: Element) => boolean\n): void {\n if (isHydrationSkipped(el)) {\n return;\n }\n\n for (const key in props) {\n const value = props[key];\n if (key === 'ref') {\n updateElementRef(el, value);\n continue;\n }\n if (isSkippedProp(key)) continue;\n if (value === undefined || value === null || value === false) continue;\n\n const eventProp = parseEventProp(key);\n if (eventProp) {\n addTrackedListener(\n el,\n eventProp.eventName,\n value as EventListener,\n eventProp.capture\n );\n continue;\n }\n\n if (typeof value === 'function' && key !== 'ref') {\n getOrCreateReactivePropsCleanupMap(el).set(\n key,\n createReactivePropCleanupEntry(el, key, value as () => unknown, tagName)\n );\n continue;\n }\n\n applyScalarPropValue(el, key, value, tagName);\n }\n}\n\nexport function syncElementPropBindings(\n el: Element,\n domVNode: DOMElement,\n props: Record<string, unknown>,\n usesReactiveChildren: boolean\n): void {\n const existingListeners = elementListeners.get(el);\n const existingReactiveProps = elementReactivePropsCleanup.get(el);\n\n let desiredListenerKeys: Set<string> | null = null;\n let desiredDelegatedEventNames: Set<string> | null = null;\n let desiredReactivePropNames: Set<string> | null = null;\n\n if (usesReactiveChildren) {\n (desiredReactivePropNames ??= new Set()).add(REACTIVE_CHILDREN_KEY);\n }\n\n for (const key in props) {\n const value = props[key];\n if (key === 'ref') continue;\n if (isSkippedProp(key)) continue;\n\n const eventProp = parseEventProp(key);\n const eventName = eventProp?.eventName;\n const eventCapture = eventProp?.capture ?? false;\n const listenerKey =\n eventName === undefined\n ? null\n : getEventListenerKey(eventName, eventCapture);\n\n if (value === undefined || value === null || value === false) {\n if (listenerKey && existingListeners?.has(listenerKey)) {\n const entry = existingListeners.get(listenerKey)!;\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n existingListeners.delete(listenerKey);\n } else {\n const entry = existingReactiveProps?.get(key);\n if (entry) {\n entry.cleanup();\n existingReactiveProps?.delete(key);\n } else {\n applyScalarPropValue(el, key, value, domVNode.type as string);\n }\n }\n continue;\n }\n\n if (typeof value === 'function' && !eventProp && key !== 'ref') {\n const existingEntry = existingReactiveProps?.get(key);\n if (existingReactiveProps && existingReactiveProps.size > 0) {\n (desiredReactivePropNames ??= new Set()).add(key);\n }\n\n if (existingEntry && existingEntry.fnRef === value) {\n continue;\n }\n\n if (existingEntry?.updateFn) {\n existingEntry.updateFn(value as () => unknown);\n existingEntry.fnRef = value as () => unknown;\n continue;\n }\n\n if (existingEntry) {\n existingEntry.cleanup();\n }\n\n getOrCreateReactivePropsCleanupMap(el).set(\n key,\n createReactivePropCleanupEntry(\n el,\n key,\n value as () => unknown,\n domVNode.type as string\n )\n );\n continue;\n }\n\n const existingReactiveEntry = existingReactiveProps?.get(key);\n if (existingReactiveEntry) {\n existingReactiveEntry.cleanup();\n existingReactiveProps?.delete(key);\n }\n\n if (eventProp && listenerKey) {\n const eventName = eventProp.eventName;\n const eventCapture = eventProp.capture;\n const useDelegation =\n !eventCapture &&\n isEventDelegationEnabled() &&\n isDelegatedEvent(eventName);\n if (useDelegation) {\n (desiredDelegatedEventNames ??= new Set()).add(eventName);\n }\n\n if (useDelegation) {\n const existingDelegated = getDelegatedHandlerForElement(el, eventName);\n if (existingDelegated?.original === value) {\n continue;\n }\n\n if (\n existingDelegated &&\n updateDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n )\n ) {\n continue;\n }\n\n addDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n );\n continue;\n }\n\n (desiredListenerKeys ??= new Set()).add(listenerKey);\n\n const existing = existingListeners?.get(listenerKey);\n\n if (existing && existing.original === value) {\n continue;\n }\n\n if (existing) {\n if (\n useDelegation &&\n existing.isDelegated &&\n updateDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n )\n ) {\n existing.handler = value as EventListener;\n existing.original = value as EventListener;\n existing.options = undefined;\n continue;\n }\n\n if (!useDelegation && !existing.isDelegated && existing.updateHandler) {\n existing.updateHandler(value as EventListener);\n existing.original = value as EventListener;\n continue;\n }\n\n if (existing.isDelegated) {\n removeDelegatedListener(el, existing.eventName);\n } else {\n if (existing.options !== undefined) {\n el.removeEventListener(\n existing.eventName,\n existing.handler,\n existing.options\n );\n } else {\n el.removeEventListener(existing.eventName, existing.handler);\n }\n }\n }\n\n const options = getEventListenerOptions(eventName, eventCapture);\n const mutableHandler = createMutableWrappedHandler(\n value as EventListener,\n true\n );\n const trackedHandler = mutableHandler.handler;\n\n if (options !== undefined) {\n el.addEventListener(eventName, trackedHandler, options);\n } else {\n el.addEventListener(eventName, trackedHandler);\n }\n incDevCounter('listenerAdds');\n\n const listenerEntry = {\n handler: trackedHandler,\n original: value as EventListener,\n eventName,\n options,\n isDelegated: false,\n updateHandler: mutableHandler?.updateHandler,\n };\n if (!elementListeners.has(el)) {\n elementListeners.set(el, new Map());\n }\n elementListeners.get(el)!.set(listenerKey, listenerEntry);\n } else {\n applyScalarPropValue(el, key, value, domVNode.type as string);\n }\n }\n\n removeStaleAttributes(el, domVNode, props);\n\n if (existingListeners && existingListeners.size > 0) {\n if (desiredListenerKeys === null) {\n existingListeners.forEach((entry) => {\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n });\n elementListeners.delete(el);\n } else {\n existingListeners.forEach((entry, listenerKey) => {\n if (!desiredListenerKeys.has(listenerKey)) {\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n existingListeners.delete(listenerKey);\n }\n });\n if (existingListeners.size === 0) elementListeners.delete(el);\n }\n }\n\n const delegatedHandlers = getDelegatedHandlersForElement(el);\n if (delegatedHandlers && delegatedHandlers.size > 0) {\n if (desiredDelegatedEventNames === null) {\n for (const eventName of delegatedHandlers.keys()) {\n removeDelegatedListener(el, eventName);\n }\n } else {\n for (const eventName of delegatedHandlers.keys()) {\n if (!desiredDelegatedEventNames.has(eventName)) {\n removeDelegatedListener(el, eventName);\n }\n }\n }\n }\n\n if (existingReactiveProps && existingReactiveProps.size > 0) {\n if (desiredReactivePropNames === null) {\n existingReactiveProps.forEach((entry) => {\n entry.cleanup();\n });\n elementReactivePropsCleanup.delete(el);\n } else {\n existingReactiveProps.forEach((entry, key) => {\n if (!desiredReactivePropNames.has(key)) {\n entry.cleanup();\n existingReactiveProps.delete(key);\n }\n });\n if (existingReactiveProps.size === 0) {\n elementReactivePropsCleanup.delete(el);\n }\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"prop-bindings.js","names":[],"sources":["../../src/renderer/prop-bindings.ts"],"sourcesContent":["import { logger } from '../common/logger';\nimport { incDevCounter } from '../runtime';\nimport {\n createFineGrainedEffect,\n markFineGrainedEffectsDirtySource,\n type FineGrainedEffectHandle,\n} from '../runtime';\nimport { isBenchMetricScopeActive, recordBenchCounter } from '../runtime';\nimport { incrementPerfMetric } from '../runtime';\nimport type { ReadableSource } from '../runtime';\nimport {\n isEventDelegationEnabled,\n addDelegatedListener,\n getDelegatedHandlerForElement,\n getDelegatedHandlersForElement,\n updateDelegatedListener,\n removeDelegatedListener,\n isDelegatedEvent,\n} from '../runtime';\nimport { applyScalarPropValue, removeStaleAttributes } from './attributes';\nimport {\n elementListeners,\n elementReactivePropsCleanup,\n REACTIVE_CHILDREN_KEY,\n type ReactivePropCleanupEntry,\n updateElementRef,\n} from './cleanup';\nimport { getRuntimeEnv } from './env';\nimport type { DOMElement } from './types';\nimport {\n createMutableWrappedHandler,\n getEventListenerKey,\n getEventListenerOptions,\n isSkippedProp,\n parseEventProp,\n} from './utils';\n\ninterface ReactivePropDescriptor {\n el: Element;\n propName: string;\n propFn: () => unknown;\n tagName: string;\n lastClassTokens: string[] | null;\n}\n\nconst reactivePropRegistry = new Set<ReactivePropDescriptor>();\n\nfunction addTrackedListener(\n el: Element,\n eventName: string,\n handler: EventListener,\n capture = false\n): void {\n const useDelegation =\n !capture && isEventDelegationEnabled() && isDelegatedEvent(eventName);\n const listenerKey = getEventListenerKey(eventName, capture);\n\n if (useDelegation) {\n addDelegatedListener(el, eventName, handler, handler, undefined);\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('listenerBindings');\n }\n return;\n }\n\n const options = getEventListenerOptions(eventName, capture);\n const mutableHandler = createMutableWrappedHandler(handler, true);\n const trackedHandler = mutableHandler.handler;\n\n if (options !== undefined) {\n el.addEventListener(eventName, trackedHandler, options);\n } else {\n el.addEventListener(eventName, trackedHandler);\n }\n incDevCounter('listenerAdds');\n\n if (!elementListeners.has(el)) {\n elementListeners.set(el, new Map());\n }\n elementListeners.get(el)!.set(listenerKey, {\n handler: trackedHandler,\n original: handler,\n eventName,\n options,\n isDelegated: false,\n updateHandler: mutableHandler?.updateHandler,\n });\n\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('listenerBindings');\n }\n}\n\nexport function markReactivePropsDirtySource(\n source: ReadableSource<unknown>\n): void {\n markFineGrainedEffectsDirtySource(source);\n}\n\nfunction setupReactiveProp(\n el: Element,\n propName: string,\n propFn: () => unknown,\n tagName: string\n): { cleanup: () => void; updateFn: (nextFn: () => unknown) => void } {\n const descriptor: ReactivePropDescriptor = {\n el,\n propName,\n propFn,\n tagName,\n lastClassTokens: null,\n };\n\n let effectHandle: FineGrainedEffectHandle<unknown> | null = null;\n\n reactivePropRegistry.add(descriptor);\n effectHandle = createFineGrainedEffect({\n lane: 'reactive',\n compute: () => descriptor.propFn(),\n commit: (value, previousValue) => {\n incrementPerfMetric('reactivePropReevaluations');\n applyScalarPropValue(\n el,\n propName,\n value,\n tagName,\n previousValue,\n descriptor\n );\n },\n equals: (previousValue, nextValue) => {\n if (Object.is(previousValue, nextValue)) {\n incrementPerfMetric('skippedDomPropWrites');\n return true;\n }\n return false;\n },\n onError: (err) => {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive prop update failed:', err);\n }\n },\n });\n\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('reactivePropsMounted');\n }\n\n const cleanup = () => {\n reactivePropRegistry.delete(descriptor);\n effectHandle?.cleanup();\n effectHandle = null;\n };\n\n const updateFn = (nextFn: () => unknown): void => {\n if (!effectHandle) {\n return;\n }\n\n descriptor.propFn = nextFn;\n\n try {\n effectHandle.updateCompute(nextFn);\n } catch (err) {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive prop update failed:', err);\n }\n }\n };\n\n return {\n cleanup,\n updateFn,\n };\n}\n\nfunction getOrCreateReactivePropsCleanupMap(\n el: Element\n): Map<string, ReactivePropCleanupEntry> {\n let cleanupMap = elementReactivePropsCleanup.get(el);\n if (!cleanupMap) {\n cleanupMap = new Map();\n elementReactivePropsCleanup.set(el, cleanupMap);\n }\n return cleanupMap;\n}\n\nfunction createReactivePropCleanupEntry(\n el: Element,\n propName: string,\n propFn: () => unknown,\n tagName: string\n): ReactivePropCleanupEntry {\n const reactive = setupReactiveProp(el, propName, propFn, tagName);\n\n return {\n cleanup: reactive.cleanup,\n updateFn: (nextValue) => {\n reactive.updateFn(nextValue as () => unknown);\n },\n restoreFn: (nextValue) =>\n createReactivePropCleanupEntry(\n el,\n propName,\n nextValue as () => unknown,\n tagName\n ),\n fnRef: propFn,\n };\n}\n\nexport function hasTrackedElementPropBindings(el: Element): boolean {\n const existingListeners = elementListeners.get(el);\n const existingReactiveProps = elementReactivePropsCleanup.get(el);\n return (\n (existingListeners !== undefined && existingListeners.size > 0) ||\n (existingReactiveProps !== undefined && existingReactiveProps.size > 0)\n );\n}\n\nexport function applyPropsToElement(\n el: Element,\n props: Record<string, unknown>,\n tagName: string,\n isHydrationSkipped: (el: Element) => boolean\n): void {\n if (isHydrationSkipped(el)) {\n return;\n }\n\n for (const key in props) {\n const value = props[key];\n if (key === 'ref') {\n updateElementRef(el, value);\n continue;\n }\n if (isSkippedProp(key)) continue;\n if (value === undefined || value === null || value === false) continue;\n\n const eventProp = parseEventProp(key);\n if (eventProp) {\n addTrackedListener(\n el,\n eventProp.eventName,\n value as EventListener,\n eventProp.capture\n );\n continue;\n }\n\n if (typeof value === 'function' && key !== 'ref') {\n getOrCreateReactivePropsCleanupMap(el).set(\n key,\n createReactivePropCleanupEntry(el, key, value as () => unknown, tagName)\n );\n continue;\n }\n\n applyScalarPropValue(el, key, value, tagName);\n }\n}\n\nexport function syncElementPropBindings(\n el: Element,\n domVNode: DOMElement,\n props: Record<string, unknown>,\n usesReactiveChildren: boolean\n): void {\n const existingListeners = elementListeners.get(el);\n const existingReactiveProps = elementReactivePropsCleanup.get(el);\n\n let desiredListenerKeys: Set<string> | null = null;\n let desiredDelegatedEventNames: Set<string> | null = null;\n let desiredReactivePropNames: Set<string> | null = null;\n\n if (usesReactiveChildren) {\n (desiredReactivePropNames ??= new Set()).add(REACTIVE_CHILDREN_KEY);\n }\n\n for (const key in props) {\n const value = props[key];\n if (key === 'ref') continue;\n if (isSkippedProp(key)) continue;\n\n const eventProp = parseEventProp(key);\n const eventName = eventProp?.eventName;\n const eventCapture = eventProp?.capture ?? false;\n const listenerKey =\n eventName === undefined\n ? null\n : getEventListenerKey(eventName, eventCapture);\n\n if (value === undefined || value === null || value === false) {\n if (listenerKey && existingListeners?.has(listenerKey)) {\n const entry = existingListeners.get(listenerKey)!;\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n existingListeners.delete(listenerKey);\n } else {\n const entry = existingReactiveProps?.get(key);\n if (entry) {\n entry.cleanup();\n existingReactiveProps?.delete(key);\n } else {\n applyScalarPropValue(el, key, value, domVNode.type as string);\n }\n }\n continue;\n }\n\n if (typeof value === 'function' && !eventProp && key !== 'ref') {\n const existingEntry = existingReactiveProps?.get(key);\n if (existingReactiveProps && existingReactiveProps.size > 0) {\n (desiredReactivePropNames ??= new Set()).add(key);\n }\n\n if (existingEntry && existingEntry.fnRef === value) {\n continue;\n }\n\n if (existingEntry?.updateFn) {\n existingEntry.updateFn(value as () => unknown);\n existingEntry.fnRef = value as () => unknown;\n continue;\n }\n\n if (existingEntry) {\n existingEntry.cleanup();\n }\n\n getOrCreateReactivePropsCleanupMap(el).set(\n key,\n createReactivePropCleanupEntry(\n el,\n key,\n value as () => unknown,\n domVNode.type as string\n )\n );\n continue;\n }\n\n const existingReactiveEntry = existingReactiveProps?.get(key);\n if (existingReactiveEntry) {\n existingReactiveEntry.cleanup();\n existingReactiveProps?.delete(key);\n }\n\n if (eventProp && listenerKey) {\n const eventName = eventProp.eventName;\n const eventCapture = eventProp.capture;\n const useDelegation =\n !eventCapture &&\n isEventDelegationEnabled() &&\n isDelegatedEvent(eventName);\n if (useDelegation) {\n (desiredDelegatedEventNames ??= new Set()).add(eventName);\n }\n\n if (useDelegation) {\n const existingDelegated = getDelegatedHandlerForElement(el, eventName);\n if (existingDelegated?.original === value) {\n continue;\n }\n\n if (\n existingDelegated &&\n updateDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n )\n ) {\n continue;\n }\n\n addDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n );\n continue;\n }\n\n (desiredListenerKeys ??= new Set()).add(listenerKey);\n\n const existing = existingListeners?.get(listenerKey);\n\n if (existing && existing.original === value) {\n continue;\n }\n\n if (existing) {\n if (\n useDelegation &&\n existing.isDelegated &&\n updateDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n )\n ) {\n existing.handler = value as EventListener;\n existing.original = value as EventListener;\n existing.options = undefined;\n continue;\n }\n\n if (!useDelegation && !existing.isDelegated && existing.updateHandler) {\n existing.updateHandler(value as EventListener);\n existing.original = value as EventListener;\n continue;\n }\n\n if (existing.isDelegated) {\n removeDelegatedListener(el, existing.eventName);\n } else {\n if (existing.options !== undefined) {\n el.removeEventListener(\n existing.eventName,\n existing.handler,\n existing.options\n );\n } else {\n el.removeEventListener(existing.eventName, existing.handler);\n }\n }\n }\n\n const options = getEventListenerOptions(eventName, eventCapture);\n const mutableHandler = createMutableWrappedHandler(\n value as EventListener,\n true\n );\n const trackedHandler = mutableHandler.handler;\n\n if (options !== undefined) {\n el.addEventListener(eventName, trackedHandler, options);\n } else {\n el.addEventListener(eventName, trackedHandler);\n }\n incDevCounter('listenerAdds');\n\n const listenerEntry = {\n handler: trackedHandler,\n original: value as EventListener,\n eventName,\n options,\n isDelegated: false,\n updateHandler: mutableHandler?.updateHandler,\n };\n if (!elementListeners.has(el)) {\n elementListeners.set(el, new Map());\n }\n elementListeners.get(el)!.set(listenerKey, listenerEntry);\n } else {\n applyScalarPropValue(el, key, value, domVNode.type as string);\n }\n }\n\n removeStaleAttributes(el, domVNode, props);\n\n if (existingListeners && existingListeners.size > 0) {\n if (desiredListenerKeys === null) {\n existingListeners.forEach((entry) => {\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n });\n elementListeners.delete(el);\n } else {\n existingListeners.forEach((entry, listenerKey) => {\n if (!desiredListenerKeys.has(listenerKey)) {\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n existingListeners.delete(listenerKey);\n }\n });\n if (existingListeners.size === 0) elementListeners.delete(el);\n }\n }\n\n const delegatedHandlers = getDelegatedHandlersForElement(el);\n if (delegatedHandlers && delegatedHandlers.size > 0) {\n if (desiredDelegatedEventNames === null) {\n for (const eventName of delegatedHandlers.keys()) {\n removeDelegatedListener(el, eventName);\n }\n } else {\n for (const eventName of delegatedHandlers.keys()) {\n if (!desiredDelegatedEventNames.has(eventName)) {\n removeDelegatedListener(el, eventName);\n }\n }\n }\n }\n\n if (existingReactiveProps && existingReactiveProps.size > 0) {\n if (desiredReactivePropNames === null) {\n existingReactiveProps.forEach((entry) => {\n entry.cleanup();\n });\n elementReactivePropsCleanup.delete(el);\n } else {\n existingReactiveProps.forEach((entry, key) => {\n if (!desiredReactivePropNames.has(key)) {\n entry.cleanup();\n existingReactiveProps.delete(key);\n }\n });\n if (existingReactiveProps.size === 0) {\n elementReactivePropsCleanup.delete(el);\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"reactive-child-dom.js","names":[],"sources":["../../src/renderer/reactive-child-dom.ts"],"sourcesContent":["import type { ChildScope } from '../runtime/child-scope';\nimport { syncControlBoundaryScopeDom } from './boundaries';\nimport { teardownNodeSubtree } from './cleanup';\nimport {\n createElementForNamespace,\n getParentNamespace,\n SVG_NAMESPACE,\n} from './namespaces';\nimport {\n collectReactiveChildBoundaryVNodes,\n isSingleRootReactiveChildBoundaryValue,\n} from './reactive-child-sources';\nimport type { VNode } from './types';\n\nexport interface ReactiveChildDOMHost {\n createDOMNode(node: unknown, parentNamespace?: string): Node | null;\n updateElementChildren(\n el: Element,\n children: VNode | VNode[] | undefined,\n forceUpdate?: boolean\n ): void;\n}\n\nexport type ReactiveChildBoundarySequenceEntry =\n | { kind: 'static'; nodes: Node[] }\n | { kind: 'dynamic'; scope: ChildScope; nodes: Node[] };\n\nexport function materializeReactiveChildBoundaryNodes(\n value: unknown,\n parentNamespace: string | undefined,\n host: ReactiveChildDOMHost\n): Node[] {\n const nodes: Node[] = [];\n const dom = host.createDOMNode(value, parentNamespace);\n if (!dom) {\n return nodes;\n }\n\n if (dom instanceof DocumentFragment) {\n for (let child = dom.firstChild; child; child = dom.firstChild) {\n nodes.push(child);\n dom.removeChild(child);\n }\n return nodes;\n }\n\n nodes.push(dom);\n return nodes;\n}\n\nexport function createReactiveChildBoundaryHost(el: Element): Element {\n const ownerDocument = el.ownerDocument;\n const parentNamespace = getParentNamespace(el);\n return parentNamespace === SVG_NAMESPACE\n ? createElementForNamespace('g', parentNamespace, ownerDocument)\n : createElementForNamespace('div', parentNamespace, ownerDocument);\n}\n\nexport function disposeReactiveChildBoundaryNodes(nodes: Node[]): void {\n for (const node of nodes) {\n if (node.parentNode) {\n node.parentNode.removeChild(node);\n }\n\n teardownNodeSubtree(node);\n }\n}\n\nexport function syncReactiveChildExpectedNodes(\n el: Element,\n expectedNodes: Node[]\n): void {\n const expectedNodeSet = new Set(expectedNodes);\n\n for (let node = el.firstChild; node; ) {\n const next = node.nextSibling;\n if (!expectedNodeSet.has(node)) {\n teardownNodeSubtree(node);\n el.removeChild(node);\n }\n node = next;\n }\n\n let anchor = el.firstChild;\n for (const node of expectedNodes) {\n if (node === anchor) {\n anchor = anchor.nextSibling;\n continue;\n }\n\n el.insertBefore(node, anchor);\n anchor = node.nextSibling;\n }\n}\n\nexport function commitReactiveChildBoundaryEntryNodes(\n el: Element,\n entry: { scope: ChildScope; nodes: Node[] },\n host: ReactiveChildDOMHost\n): Node[] {\n if (!entry.scope.needsDomUpdate) {\n return entry.nodes;\n }\n\n if (\n entry.scope.vnode === null ||\n entry.scope.vnode === undefined ||\n entry.scope.vnode === false\n ) {\n if (entry.nodes.length > 0) {\n disposeReactiveChildBoundaryNodes(entry.nodes);\n entry.nodes = [];\n }\n\n const dom = entry.scope.dom;\n if (dom?.parentNode === el) {\n teardownNodeSubtree(dom);\n el.removeChild(dom);\n }\n\n entry.scope.dom = undefined;\n entry.scope.needsDomUpdate = false;\n return entry.nodes;\n }\n\n if (!isSingleRootReactiveChildBoundaryValue(entry.scope.vnode)) {\n const nextChildren: VNode[] = [];\n collectReactiveChildBoundaryVNodes(entry.scope.vnode, nextChildren);\n\n const boundaryHost = createReactiveChildBoundaryHost(el);\n for (const node of entry.nodes) {\n boundaryHost.appendChild(node);\n }\n\n host.updateElementChildren(boundaryHost, nextChildren);\n\n const nextNodes = Array.from(boundaryHost.childNodes);\n\n entry.scope.dom = undefined;\n entry.scope.needsDomUpdate = false;\n entry.nodes = nextNodes;\n return nextNodes;\n }\n\n if (entry.nodes.length > 1) {\n disposeReactiveChildBoundaryNodes(entry.nodes);\n entry.nodes = [];\n entry.scope.dom = undefined;\n }\n\n const nextDom = syncControlBoundaryScopeDom(\n el,\n entry.scope,\n entry.scope.vnode ?? null\n );\n if (!nextDom) {\n entry.nodes = [];\n entry.scope.needsDomUpdate = false;\n return entry.nodes;\n }\n\n entry.nodes = [nextDom];\n entry.scope.needsDomUpdate = false;\n return entry.nodes;\n}\n\nexport function syncReactiveChildSequenceNodes(\n el: Element,\n entries: ReactiveChildBoundarySequenceEntry[],\n host: ReactiveChildDOMHost\n): void {\n const expectedNodes: Node[] = [];\n\n for (const entry of entries) {\n if (entry.kind === 'static') {\n expectedNodes.push(...entry.nodes);\n continue;\n }\n\n expectedNodes.push(\n ...commitReactiveChildBoundaryEntryNodes(el, entry, host)\n );\n }\n\n syncReactiveChildExpectedNodes(el, expectedNodes);\n}\n\nexport function syncReactiveScalarTextNodes(\n el: Element,\n slotValues: unknown[],\n values: string[],\n host: ReactiveChildDOMHost\n): void {\n const childNodes = el.childNodes;\n const canPatchInPlace = childNodes.length === values.length;\n\n if (canPatchInPlace) {\n let allText = true;\n for (let index = 0; index < childNodes.length; index += 1) {\n if (childNodes[index]?.nodeType !== Node.TEXT_NODE) {\n allText = false;\n break;\n }\n }\n\n if (allText) {\n for (let index = 0; index < values.length; index += 1) {\n const textNode = childNodes[index] as Text;\n if (textNode.data !== values[index]) {\n textNode.data = values[index];\n }\n }\n return;\n }\n }\n\n const boundaryHost = createReactiveChildBoundaryHost(el);\n for (let node = el.firstChild; node; ) {\n const next = node.nextSibling;\n boundaryHost.appendChild(node);\n node = next;\n }\n\n host.updateElementChildren(boundaryHost, slotValues as VNode[]);\n syncReactiveChildExpectedNodes(el, Array.from(boundaryHost.childNodes));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"reactive-child-dom.js","names":[],"sources":["../../src/renderer/reactive-child-dom.ts"],"sourcesContent":["import type { ChildScope } from '../runtime';\nimport { syncControlBoundaryScopeDom } from './boundaries';\nimport { teardownNodeSubtree } from './cleanup';\nimport {\n createElementForNamespace,\n getParentNamespace,\n SVG_NAMESPACE,\n} from './namespaces';\nimport {\n collectReactiveChildBoundaryVNodes,\n isSingleRootReactiveChildBoundaryValue,\n} from './reactive-child-sources';\nimport type { VNode } from './types';\n\nexport interface ReactiveChildDOMHost {\n createDOMNode(node: unknown, parentNamespace?: string): Node | null;\n updateElementChildren(\n el: Element,\n children: VNode | VNode[] | undefined,\n forceUpdate?: boolean\n ): void;\n}\n\nexport type ReactiveChildBoundarySequenceEntry =\n | { kind: 'static'; nodes: Node[] }\n | { kind: 'dynamic'; scope: ChildScope; nodes: Node[] };\n\nexport function materializeReactiveChildBoundaryNodes(\n value: unknown,\n parentNamespace: string | undefined,\n host: ReactiveChildDOMHost\n): Node[] {\n const nodes: Node[] = [];\n const dom = host.createDOMNode(value, parentNamespace);\n if (!dom) {\n return nodes;\n }\n\n if (dom instanceof DocumentFragment) {\n for (let child = dom.firstChild; child; child = dom.firstChild) {\n nodes.push(child);\n dom.removeChild(child);\n }\n return nodes;\n }\n\n nodes.push(dom);\n return nodes;\n}\n\nexport function createReactiveChildBoundaryHost(el: Element): Element {\n const ownerDocument = el.ownerDocument;\n const parentNamespace = getParentNamespace(el);\n return parentNamespace === SVG_NAMESPACE\n ? createElementForNamespace('g', parentNamespace, ownerDocument)\n : createElementForNamespace('div', parentNamespace, ownerDocument);\n}\n\nexport function disposeReactiveChildBoundaryNodes(nodes: Node[]): void {\n for (const node of nodes) {\n if (node.parentNode) {\n node.parentNode.removeChild(node);\n }\n\n teardownNodeSubtree(node);\n }\n}\n\nexport function syncReactiveChildExpectedNodes(\n el: Element,\n expectedNodes: Node[]\n): void {\n const expectedNodeSet = new Set(expectedNodes);\n\n for (let node = el.firstChild; node; ) {\n const next = node.nextSibling;\n if (!expectedNodeSet.has(node)) {\n teardownNodeSubtree(node);\n el.removeChild(node);\n }\n node = next;\n }\n\n let anchor = el.firstChild;\n for (const node of expectedNodes) {\n if (node === anchor) {\n anchor = anchor.nextSibling;\n continue;\n }\n\n el.insertBefore(node, anchor);\n anchor = node.nextSibling;\n }\n}\n\nexport function commitReactiveChildBoundaryEntryNodes(\n el: Element,\n entry: { scope: ChildScope; nodes: Node[] },\n host: ReactiveChildDOMHost\n): Node[] {\n if (!entry.scope.needsDomUpdate) {\n return entry.nodes;\n }\n\n if (\n entry.scope.vnode === null ||\n entry.scope.vnode === undefined ||\n entry.scope.vnode === false\n ) {\n if (entry.nodes.length > 0) {\n disposeReactiveChildBoundaryNodes(entry.nodes);\n entry.nodes = [];\n }\n\n const dom = entry.scope.dom;\n if (dom?.parentNode === el) {\n teardownNodeSubtree(dom);\n el.removeChild(dom);\n }\n\n entry.scope.dom = undefined;\n entry.scope.needsDomUpdate = false;\n return entry.nodes;\n }\n\n if (!isSingleRootReactiveChildBoundaryValue(entry.scope.vnode)) {\n const nextChildren: VNode[] = [];\n collectReactiveChildBoundaryVNodes(entry.scope.vnode, nextChildren);\n\n const boundaryHost = createReactiveChildBoundaryHost(el);\n for (const node of entry.nodes) {\n boundaryHost.appendChild(node);\n }\n\n host.updateElementChildren(boundaryHost, nextChildren);\n\n const nextNodes = Array.from(boundaryHost.childNodes);\n\n entry.scope.dom = undefined;\n entry.scope.needsDomUpdate = false;\n entry.nodes = nextNodes;\n return nextNodes;\n }\n\n if (entry.nodes.length > 1) {\n disposeReactiveChildBoundaryNodes(entry.nodes);\n entry.nodes = [];\n entry.scope.dom = undefined;\n }\n\n const nextDom = syncControlBoundaryScopeDom(\n el,\n entry.scope,\n entry.scope.vnode ?? null\n );\n if (!nextDom) {\n entry.nodes = [];\n entry.scope.needsDomUpdate = false;\n return entry.nodes;\n }\n\n entry.nodes = [nextDom];\n entry.scope.needsDomUpdate = false;\n return entry.nodes;\n}\n\nexport function syncReactiveChildSequenceNodes(\n el: Element,\n entries: ReactiveChildBoundarySequenceEntry[],\n host: ReactiveChildDOMHost\n): void {\n const expectedNodes: Node[] = [];\n\n for (const entry of entries) {\n if (entry.kind === 'static') {\n expectedNodes.push(...entry.nodes);\n continue;\n }\n\n expectedNodes.push(\n ...commitReactiveChildBoundaryEntryNodes(el, entry, host)\n );\n }\n\n syncReactiveChildExpectedNodes(el, expectedNodes);\n}\n\nexport function syncReactiveScalarTextNodes(\n el: Element,\n slotValues: unknown[],\n values: string[],\n host: ReactiveChildDOMHost\n): void {\n const childNodes = el.childNodes;\n const canPatchInPlace = childNodes.length === values.length;\n\n if (canPatchInPlace) {\n let allText = true;\n for (let index = 0; index < childNodes.length; index += 1) {\n if (childNodes[index]?.nodeType !== Node.TEXT_NODE) {\n allText = false;\n break;\n }\n }\n\n if (allText) {\n for (let index = 0; index < values.length; index += 1) {\n const textNode = childNodes[index] as Text;\n if (textNode.data !== values[index]) {\n textNode.data = values[index];\n }\n }\n return;\n }\n }\n\n const boundaryHost = createReactiveChildBoundaryHost(el);\n for (let node = el.firstChild; node; ) {\n const next = node.nextSibling;\n boundaryHost.appendChild(node);\n node = next;\n }\n\n host.updateElementChildren(boundaryHost, slotValues as VNode[]);\n syncReactiveChildExpectedNodes(el, Array.from(boundaryHost.childNodes));\n}\n"],"mappings":"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"}
@@ -1,13 +1,13 @@
1
1
  import { getRuntimeEnv } from "../common/env.js";
2
- import { logger } from "../dev/logger.js";
2
+ import { logger } from "../common/logger.js";
3
3
  import { incDevCounter } from "../runtime/dev-namespace.js";
4
4
  import { getCurrentInstance } from "../runtime/component-scope.js";
5
- import "../runtime/component-contracts.js";
5
+ import { createChildScope, disposeChildScope, rerenderChildScope } from "../runtime/child-scope.js";
6
+ import { createFineGrainedEffect } from "../runtime/effect.js";
7
+ import "../runtime/index.js";
6
8
  import { REACTIVE_CHILDREN_KEY, elementReactivePropsCleanup, teardownNodeSubtree } from "./cleanup.js";
7
9
  import "./env.js";
8
- import { createChildScope, disposeChildScope, rerenderChildScope } from "../runtime/child-scope.js";
9
10
  import { getParentNamespace } from "./namespaces.js";
10
- import { createFineGrainedEffect } from "../runtime/effect.js";
11
11
  import { areReactiveChildBoundarySequenceSourcesEqual, areReactiveScalarChildSourcesEqual, canUpdateReactiveChildBoundarySequenceSource, collectReactiveChildValuesAsVNodes, getReactiveChildBoundarySequenceSource, getReactiveScalarChildSource, getSingleReactiveChildBoundarySource, normalizeOwnedReactiveTextValue, normalizeReactiveChildBoundaryVNode, normalizeReactiveScalarSequenceValues } from "./reactive-child-sources.js";
12
12
  import { commitReactiveChildBoundaryEntryNodes, createReactiveChildBoundaryHost, disposeReactiveChildBoundaryNodes, materializeReactiveChildBoundaryNodes, syncReactiveChildExpectedNodes, syncReactiveChildSequenceNodes, syncReactiveScalarTextNodes } from "./reactive-child-dom.js";
13
13
  //#region src/renderer/reactive-children.ts
@@ -1 +1 @@
1
- {"version":3,"file":"reactive-children.js","names":[],"sources":["../../src/renderer/reactive-children.ts"],"sourcesContent":["import { logger } from '../dev/logger';\nimport {\n createChildScope,\n disposeChildScope,\n rerenderChildScope,\n type ChildScope,\n} from '../runtime/child-scope';\nimport { getCurrentInstance } from '../runtime/component-contracts';\nimport { incDevCounter } from '../runtime/dev-namespace';\nimport {\n createFineGrainedEffect,\n type FineGrainedEffectHandle,\n} from '../runtime/effect';\nimport {\n elementReactivePropsCleanup,\n REACTIVE_CHILDREN_KEY,\n teardownNodeSubtree,\n type ReactivePropCleanupEntry,\n} from './cleanup';\nimport { getRuntimeEnv } from './env';\nimport { getParentNamespace } from './namespaces';\nimport type { VNode } from './types';\nimport {\n commitReactiveChildBoundaryEntryNodes,\n createReactiveChildBoundaryHost,\n disposeReactiveChildBoundaryNodes,\n materializeReactiveChildBoundaryNodes,\n syncReactiveChildExpectedNodes,\n syncReactiveChildSequenceNodes,\n syncReactiveScalarTextNodes,\n type ReactiveChildBoundarySequenceEntry,\n type ReactiveChildDOMHost,\n} from './reactive-child-dom';\nimport {\n areReactiveChildBoundarySequenceSourcesEqual,\n areReactiveScalarChildSourcesEqual,\n canUpdateReactiveChildBoundarySequenceSource,\n collectReactiveChildValuesAsVNodes,\n getReactiveChildBoundarySequenceSource,\n getReactiveScalarChildSource,\n getSingleReactiveChildBoundarySource,\n normalizeOwnedReactiveTextValue,\n normalizeReactiveChildBoundaryVNode,\n normalizeReactiveScalarSequenceValues,\n type ReactiveChildBoundarySequenceSource,\n type ReactiveScalarChildSource,\n} from './reactive-child-sources';\n\nexport type { ReactiveChildDOMHost } from './reactive-child-dom';\n\nlet reactiveChildScopeId = 0;\n\nfunction getOrCreateElementReactiveCleanupMap(\n el: Element\n): Map<string, ReactivePropCleanupEntry> {\n let cleanupMap = elementReactivePropsCleanup.get(el);\n if (!cleanupMap) {\n cleanupMap = new Map();\n elementReactivePropsCleanup.set(el, cleanupMap);\n }\n\n return cleanupMap;\n}\n\nexport function trySyncScalarChildSequenceInPlace(\n el: Element,\n children: unknown[],\n host: ReactiveChildDOMHost\n): boolean {\n const normalized = normalizeReactiveScalarSequenceValues(children);\n if (!normalized) {\n return false;\n }\n\n if (el.childNodes.length !== normalized.length) {\n return false;\n }\n\n for (let index = 0; index < el.childNodes.length; index += 1) {\n if (el.childNodes[index]?.nodeType !== Node.TEXT_NODE) {\n return false;\n }\n }\n\n syncReactiveScalarTextNodes(el, children, normalized, host);\n return true;\n}\n\nfunction setupReactiveScalarChild(\n el: Element,\n source: ReactiveScalarChildSource,\n host: ReactiveChildDOMHost\n): {\n cleanup: () => void;\n updateFn: (nextSource: ReactiveScalarChildSource) => void;\n} {\n let currentSource = source;\n\n if (source.length === 1 && source[0]?.kind === 'dynamic') {\n let ownedTextNode =\n el.childNodes.length === 1 && el.firstChild?.nodeType === Node.TEXT_NODE\n ? (el.firstChild as Text)\n : null;\n\n let effectHandle: FineGrainedEffectHandle<string> | null =\n createFineGrainedEffect({\n lane: 'reactive',\n compute: () => {\n const currentSlot = currentSource[0];\n if (!currentSlot || currentSlot.kind !== 'dynamic') {\n throw new Error(\n '[Askr] Direct reactive text bindings require a single dynamic slot.'\n );\n }\n\n const rawValue = currentSlot.compute();\n const normalized = normalizeOwnedReactiveTextValue(rawValue);\n return normalized ?? (rawValue as string);\n },\n commit: (value) => {\n const normalized = normalizeOwnedReactiveTextValue(value);\n\n if (normalized === null) {\n ownedTextNode = null;\n host.updateElementChildren(\n el,\n value as unknown as VNode | VNode[] | undefined\n );\n return;\n }\n\n if (\n !ownedTextNode ||\n el.childNodes.length !== 1 ||\n el.firstChild !== ownedTextNode\n ) {\n host.updateElementChildren(el, normalized);\n ownedTextNode =\n el.childNodes.length === 1 &&\n el.firstChild?.nodeType === Node.TEXT_NODE\n ? (el.firstChild as Text)\n : null;\n }\n\n if (!ownedTextNode) {\n return;\n }\n\n if (ownedTextNode.data !== normalized) {\n ownedTextNode.data = normalized;\n incDevCounter('textNodeWrites');\n }\n },\n onError: (err) => {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive child update failed:', err);\n }\n },\n });\n\n return {\n cleanup: () => {\n effectHandle?.cleanup();\n effectHandle = null;\n },\n updateFn: (nextSource: ReactiveScalarChildSource) => {\n if (!effectHandle) {\n return;\n }\n\n currentSource = nextSource;\n effectHandle.updateCompute(() => {\n const currentSlot = currentSource[0];\n if (!currentSlot || currentSlot.kind !== 'dynamic') {\n throw new Error(\n '[Askr] Direct reactive text bindings require a single dynamic slot.'\n );\n }\n\n const rawValue = currentSlot.compute();\n const normalized = normalizeOwnedReactiveTextValue(rawValue);\n return normalized ?? (rawValue as string);\n });\n },\n };\n }\n\n let effectHandle: FineGrainedEffectHandle<unknown> | null =\n createFineGrainedEffect({\n lane: 'reactive',\n compute: () =>\n currentSource.map((slot) =>\n slot.kind === 'static' ? slot.value : slot.compute()\n ),\n commit: (values) => {\n if (!Array.isArray(values)) {\n throw new Error(\n '[Askr] Reactive scalar children must evaluate to a slot array.'\n );\n }\n\n const normalized = normalizeReactiveScalarSequenceValues(values);\n if (normalized) {\n syncReactiveScalarTextNodes(el, values, normalized, host);\n return;\n }\n\n const nextChildren: VNode[] = [];\n collectReactiveChildValuesAsVNodes(values, nextChildren);\n\n const boundaryHost = createReactiveChildBoundaryHost(el);\n for (let node = el.firstChild; node; ) {\n const next = node.nextSibling;\n boundaryHost.appendChild(node);\n node = next;\n }\n\n host.updateElementChildren(boundaryHost, nextChildren);\n syncReactiveChildExpectedNodes(el, Array.from(boundaryHost.childNodes));\n },\n equals: (previousValue, nextValue) => {\n if (!Array.isArray(previousValue) || !Array.isArray(nextValue)) {\n return false;\n }\n\n const previousNormalized =\n normalizeReactiveScalarSequenceValues(previousValue);\n const nextNormalized = normalizeReactiveScalarSequenceValues(nextValue);\n\n if (!previousNormalized || !nextNormalized) {\n return false;\n }\n\n if (previousNormalized.length !== nextNormalized.length) {\n return false;\n }\n\n for (let index = 0; index < previousNormalized.length; index += 1) {\n if (previousNormalized[index] !== nextNormalized[index]) {\n return false;\n }\n }\n\n return true;\n },\n onError: (err) => {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive child update failed:', err);\n }\n },\n });\n\n return {\n cleanup: () => {\n effectHandle?.cleanup();\n effectHandle = null;\n },\n updateFn: (nextSource: ReactiveScalarChildSource) => {\n if (!effectHandle) {\n return;\n }\n\n currentSource = nextSource;\n effectHandle.updateCompute(() =>\n currentSource.map((slot) =>\n slot.kind === 'static' ? slot.value : slot.compute()\n )\n );\n },\n };\n}\n\nfunction setupReactiveChildBoundary(\n el: Element,\n childFn: () => VNode,\n host: ReactiveChildDOMHost\n): { cleanup: () => void; updateFn: (nextValue: unknown) => void } {\n let currentChildFn = childFn;\n const parentInstance = getCurrentInstance();\n const entry: { scope: ChildScope; nodes: Node[] } = {\n scope: createChildScope(\n parentInstance,\n `__reactive-child__:${(reactiveChildScopeId += 1)}`,\n () => {\n const expectedNodes = commitReactiveChildBoundaryEntryNodes(\n el,\n entry,\n host\n );\n syncReactiveChildExpectedNodes(el, expectedNodes);\n }\n ),\n nodes: [],\n };\n\n entry.scope.render(() =>\n normalizeReactiveChildBoundaryVNode(currentChildFn())\n );\n syncReactiveChildExpectedNodes(\n el,\n commitReactiveChildBoundaryEntryNodes(el, entry, host)\n );\n\n return {\n cleanup: () => {\n const dom = entry.scope.dom;\n const nodes = entry.nodes;\n disposeChildScope(entry.scope);\n entry.nodes = [];\n\n if (nodes.length > 0) {\n disposeReactiveChildBoundaryNodes(nodes);\n return;\n }\n\n if (dom?.parentNode === el) {\n teardownNodeSubtree(dom);\n el.removeChild(dom);\n }\n },\n updateFn: (nextValue: unknown) => {\n currentChildFn = nextValue as () => VNode;\n rerenderChildScope(entry.scope);\n const expectedNodes = commitReactiveChildBoundaryEntryNodes(\n el,\n entry,\n host\n );\n syncReactiveChildExpectedNodes(el, expectedNodes);\n },\n };\n}\n\nfunction setupReactiveChildBoundarySequence(\n el: Element,\n source: ReactiveChildBoundarySequenceSource,\n host: ReactiveChildDOMHost\n): { cleanup: () => void; updateFn: (nextValue: unknown) => void } {\n let currentSource = source;\n const parentInstance = getCurrentInstance();\n const entries: ReactiveChildBoundarySequenceEntry[] = [];\n const dynamicEntries: Array<{\n index: number;\n entry: Extract<ReactiveChildBoundarySequenceEntry, { kind: 'dynamic' }>;\n }> = [];\n\n if (!currentSource.some((slot) => slot.kind === 'dynamic')) {\n throw new Error(\n '[Askr] Reactive child boundary sequence requires at least one dynamic slot.'\n );\n }\n\n const syncSequence = () => {\n syncReactiveChildSequenceNodes(el, entries, host);\n };\n\n const parentNamespace = getParentNamespace(el);\n\n for (let index = 0; index < currentSource.length; index += 1) {\n const slot = currentSource[index];\n if (!slot) {\n continue;\n }\n\n if (slot.kind === 'static-text') {\n entries.push({\n kind: 'static',\n nodes: [document.createTextNode(slot.value)],\n });\n continue;\n }\n\n if (slot.kind === 'static-node') {\n entries.push({\n kind: 'static',\n nodes: materializeReactiveChildBoundaryNodes(\n slot.value,\n parentNamespace,\n host\n ),\n });\n continue;\n }\n\n const scope = createChildScope(\n parentInstance,\n `__reactive-child-seq__:${(reactiveChildScopeId += 1)}`,\n syncSequence\n );\n\n const dynamicEntry: Extract<\n ReactiveChildBoundarySequenceEntry,\n { kind: 'dynamic' }\n > = {\n kind: 'dynamic',\n scope,\n nodes: [],\n };\n entries.push(dynamicEntry);\n dynamicEntries.push({ index, entry: dynamicEntry });\n }\n\n for (const dynamicEntry of dynamicEntries) {\n dynamicEntry.entry.scope.render(() =>\n normalizeReactiveChildBoundaryVNode(\n (\n currentSource[dynamicEntry.index] as {\n kind: 'dynamic';\n compute: () => VNode;\n }\n ).compute()\n )\n );\n }\n\n syncSequence();\n\n return {\n cleanup: () => {\n for (const dynamicEntry of dynamicEntries) {\n const dom = dynamicEntry.entry.scope.dom;\n const nodes = dynamicEntry.entry.nodes;\n disposeChildScope(dynamicEntry.entry.scope);\n\n if (nodes.length > 0) {\n disposeReactiveChildBoundaryNodes(nodes);\n continue;\n }\n\n if (dom?.parentNode === el) {\n teardownNodeSubtree(dom);\n el.removeChild(dom);\n }\n }\n\n for (const entry of entries) {\n if (entry.kind === 'static') {\n disposeReactiveChildBoundaryNodes(entry.nodes);\n }\n }\n },\n updateFn: (nextValue: unknown) => {\n currentSource = nextValue as ReactiveChildBoundarySequenceSource;\n for (const dynamicEntry of dynamicEntries) {\n rerenderChildScope(dynamicEntry.entry.scope);\n }\n syncSequence();\n },\n };\n}\n\nexport function syncReactiveScalarChild(\n el: Element,\n children: unknown,\n host: ReactiveChildDOMHost\n): boolean {\n const reactiveChildSource = getReactiveScalarChildSource(children);\n const reactiveChildBoundary = getSingleReactiveChildBoundarySource(children);\n const reactiveChildBoundarySequence =\n getReactiveChildBoundarySequenceSource(children);\n const existingReactiveEntry = elementReactivePropsCleanup\n .get(el)\n ?.get(REACTIVE_CHILDREN_KEY);\n\n if (\n !reactiveChildSource &&\n !reactiveChildBoundary &&\n !reactiveChildBoundarySequence\n ) {\n if (existingReactiveEntry) {\n existingReactiveEntry.cleanup();\n const cleanupMap = elementReactivePropsCleanup.get(el);\n cleanupMap?.delete(REACTIVE_CHILDREN_KEY);\n if (cleanupMap && cleanupMap.size === 0) {\n elementReactivePropsCleanup.delete(el);\n }\n }\n\n return false;\n }\n\n if (reactiveChildSource && !reactiveChildBoundarySequence) {\n if (\n existingReactiveEntry &&\n Array.isArray(existingReactiveEntry.fnRef) &&\n areReactiveScalarChildSourcesEqual(\n existingReactiveEntry.fnRef,\n reactiveChildSource\n )\n ) {\n return true;\n }\n\n if (\n existingReactiveEntry?.updateFn &&\n Array.isArray(existingReactiveEntry.fnRef)\n ) {\n existingReactiveEntry.updateFn(reactiveChildSource);\n existingReactiveEntry.fnRef = reactiveChildSource;\n return true;\n }\n\n existingReactiveEntry?.cleanup();\n\n try {\n const reactive = setupReactiveScalarChild(el, reactiveChildSource, host);\n getOrCreateElementReactiveCleanupMap(el).set(REACTIVE_CHILDREN_KEY, {\n cleanup: reactive.cleanup,\n updateFn: (nextValue) => {\n reactive.updateFn(nextValue as ReactiveScalarChildSource);\n },\n fnRef: reactiveChildSource,\n });\n return true;\n } catch (error) {\n if (!reactiveChildBoundary && !reactiveChildBoundarySequence) {\n throw error;\n }\n }\n }\n\n if (reactiveChildBoundarySequence) {\n if (\n existingReactiveEntry &&\n Array.isArray(existingReactiveEntry.fnRef) &&\n areReactiveChildBoundarySequenceSourcesEqual(\n existingReactiveEntry.fnRef,\n reactiveChildBoundarySequence\n )\n ) {\n return true;\n }\n\n if (\n existingReactiveEntry?.updateFn &&\n Array.isArray(existingReactiveEntry.fnRef) &&\n canUpdateReactiveChildBoundarySequenceSource(\n existingReactiveEntry.fnRef,\n reactiveChildBoundarySequence\n )\n ) {\n existingReactiveEntry.updateFn(reactiveChildBoundarySequence);\n existingReactiveEntry.fnRef = reactiveChildBoundarySequence;\n return true;\n }\n\n existingReactiveEntry?.cleanup();\n\n const reactive = setupReactiveChildBoundarySequence(\n el,\n reactiveChildBoundarySequence,\n host\n );\n getOrCreateElementReactiveCleanupMap(el).set(REACTIVE_CHILDREN_KEY, {\n cleanup: reactive.cleanup,\n updateFn: reactive.updateFn,\n fnRef: reactiveChildBoundarySequence,\n });\n return true;\n }\n\n if (existingReactiveEntry?.fnRef === reactiveChildBoundary) {\n return true;\n }\n\n if (\n existingReactiveEntry?.updateFn &&\n !Array.isArray(existingReactiveEntry.fnRef)\n ) {\n existingReactiveEntry.updateFn(reactiveChildBoundary);\n existingReactiveEntry.fnRef = reactiveChildBoundary;\n return true;\n }\n\n existingReactiveEntry?.cleanup();\n\n if (!reactiveChildBoundary) {\n return false;\n }\n\n const reactive = setupReactiveChildBoundary(el, reactiveChildBoundary, host);\n getOrCreateElementReactiveCleanupMap(el).set(REACTIVE_CHILDREN_KEY, {\n cleanup: reactive.cleanup,\n updateFn: reactive.updateFn,\n fnRef: reactiveChildBoundary,\n });\n return true;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"reactive-children.js","names":[],"sources":["../../src/renderer/reactive-children.ts"],"sourcesContent":["import { logger } from '../common/logger';\nimport {\n createChildScope,\n disposeChildScope,\n rerenderChildScope,\n type ChildScope,\n} from '../runtime';\nimport { getCurrentInstance } from '../runtime';\nimport { incDevCounter } from '../runtime';\nimport {\n createFineGrainedEffect,\n type FineGrainedEffectHandle,\n} from '../runtime';\nimport {\n elementReactivePropsCleanup,\n REACTIVE_CHILDREN_KEY,\n teardownNodeSubtree,\n type ReactivePropCleanupEntry,\n} from './cleanup';\nimport { getRuntimeEnv } from './env';\nimport { getParentNamespace } from './namespaces';\nimport type { VNode } from './types';\nimport {\n commitReactiveChildBoundaryEntryNodes,\n createReactiveChildBoundaryHost,\n disposeReactiveChildBoundaryNodes,\n materializeReactiveChildBoundaryNodes,\n syncReactiveChildExpectedNodes,\n syncReactiveChildSequenceNodes,\n syncReactiveScalarTextNodes,\n type ReactiveChildBoundarySequenceEntry,\n type ReactiveChildDOMHost,\n} from './reactive-child-dom';\nimport {\n areReactiveChildBoundarySequenceSourcesEqual,\n areReactiveScalarChildSourcesEqual,\n canUpdateReactiveChildBoundarySequenceSource,\n collectReactiveChildValuesAsVNodes,\n getReactiveChildBoundarySequenceSource,\n getReactiveScalarChildSource,\n getSingleReactiveChildBoundarySource,\n normalizeOwnedReactiveTextValue,\n normalizeReactiveChildBoundaryVNode,\n normalizeReactiveScalarSequenceValues,\n type ReactiveChildBoundarySequenceSource,\n type ReactiveScalarChildSource,\n} from './reactive-child-sources';\n\nexport type { ReactiveChildDOMHost } from './reactive-child-dom';\n\nlet reactiveChildScopeId = 0;\n\nfunction getOrCreateElementReactiveCleanupMap(\n el: Element\n): Map<string, ReactivePropCleanupEntry> {\n let cleanupMap = elementReactivePropsCleanup.get(el);\n if (!cleanupMap) {\n cleanupMap = new Map();\n elementReactivePropsCleanup.set(el, cleanupMap);\n }\n\n return cleanupMap;\n}\n\nexport function trySyncScalarChildSequenceInPlace(\n el: Element,\n children: unknown[],\n host: ReactiveChildDOMHost\n): boolean {\n const normalized = normalizeReactiveScalarSequenceValues(children);\n if (!normalized) {\n return false;\n }\n\n if (el.childNodes.length !== normalized.length) {\n return false;\n }\n\n for (let index = 0; index < el.childNodes.length; index += 1) {\n if (el.childNodes[index]?.nodeType !== Node.TEXT_NODE) {\n return false;\n }\n }\n\n syncReactiveScalarTextNodes(el, children, normalized, host);\n return true;\n}\n\nfunction setupReactiveScalarChild(\n el: Element,\n source: ReactiveScalarChildSource,\n host: ReactiveChildDOMHost\n): {\n cleanup: () => void;\n updateFn: (nextSource: ReactiveScalarChildSource) => void;\n} {\n let currentSource = source;\n\n if (source.length === 1 && source[0]?.kind === 'dynamic') {\n let ownedTextNode =\n el.childNodes.length === 1 && el.firstChild?.nodeType === Node.TEXT_NODE\n ? (el.firstChild as Text)\n : null;\n\n let effectHandle: FineGrainedEffectHandle<string> | null =\n createFineGrainedEffect({\n lane: 'reactive',\n compute: () => {\n const currentSlot = currentSource[0];\n if (!currentSlot || currentSlot.kind !== 'dynamic') {\n throw new Error(\n '[Askr] Direct reactive text bindings require a single dynamic slot.'\n );\n }\n\n const rawValue = currentSlot.compute();\n const normalized = normalizeOwnedReactiveTextValue(rawValue);\n return normalized ?? (rawValue as string);\n },\n commit: (value) => {\n const normalized = normalizeOwnedReactiveTextValue(value);\n\n if (normalized === null) {\n ownedTextNode = null;\n host.updateElementChildren(\n el,\n value as unknown as VNode | VNode[] | undefined\n );\n return;\n }\n\n if (\n !ownedTextNode ||\n el.childNodes.length !== 1 ||\n el.firstChild !== ownedTextNode\n ) {\n host.updateElementChildren(el, normalized);\n ownedTextNode =\n el.childNodes.length === 1 &&\n el.firstChild?.nodeType === Node.TEXT_NODE\n ? (el.firstChild as Text)\n : null;\n }\n\n if (!ownedTextNode) {\n return;\n }\n\n if (ownedTextNode.data !== normalized) {\n ownedTextNode.data = normalized;\n incDevCounter('textNodeWrites');\n }\n },\n onError: (err) => {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive child update failed:', err);\n }\n },\n });\n\n return {\n cleanup: () => {\n effectHandle?.cleanup();\n effectHandle = null;\n },\n updateFn: (nextSource: ReactiveScalarChildSource) => {\n if (!effectHandle) {\n return;\n }\n\n currentSource = nextSource;\n effectHandle.updateCompute(() => {\n const currentSlot = currentSource[0];\n if (!currentSlot || currentSlot.kind !== 'dynamic') {\n throw new Error(\n '[Askr] Direct reactive text bindings require a single dynamic slot.'\n );\n }\n\n const rawValue = currentSlot.compute();\n const normalized = normalizeOwnedReactiveTextValue(rawValue);\n return normalized ?? (rawValue as string);\n });\n },\n };\n }\n\n let effectHandle: FineGrainedEffectHandle<unknown> | null =\n createFineGrainedEffect({\n lane: 'reactive',\n compute: () =>\n currentSource.map((slot) =>\n slot.kind === 'static' ? slot.value : slot.compute()\n ),\n commit: (values) => {\n if (!Array.isArray(values)) {\n throw new Error(\n '[Askr] Reactive scalar children must evaluate to a slot array.'\n );\n }\n\n const normalized = normalizeReactiveScalarSequenceValues(values);\n if (normalized) {\n syncReactiveScalarTextNodes(el, values, normalized, host);\n return;\n }\n\n const nextChildren: VNode[] = [];\n collectReactiveChildValuesAsVNodes(values, nextChildren);\n\n const boundaryHost = createReactiveChildBoundaryHost(el);\n for (let node = el.firstChild; node; ) {\n const next = node.nextSibling;\n boundaryHost.appendChild(node);\n node = next;\n }\n\n host.updateElementChildren(boundaryHost, nextChildren);\n syncReactiveChildExpectedNodes(el, Array.from(boundaryHost.childNodes));\n },\n equals: (previousValue, nextValue) => {\n if (!Array.isArray(previousValue) || !Array.isArray(nextValue)) {\n return false;\n }\n\n const previousNormalized =\n normalizeReactiveScalarSequenceValues(previousValue);\n const nextNormalized = normalizeReactiveScalarSequenceValues(nextValue);\n\n if (!previousNormalized || !nextNormalized) {\n return false;\n }\n\n if (previousNormalized.length !== nextNormalized.length) {\n return false;\n }\n\n for (let index = 0; index < previousNormalized.length; index += 1) {\n if (previousNormalized[index] !== nextNormalized[index]) {\n return false;\n }\n }\n\n return true;\n },\n onError: (err) => {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive child update failed:', err);\n }\n },\n });\n\n return {\n cleanup: () => {\n effectHandle?.cleanup();\n effectHandle = null;\n },\n updateFn: (nextSource: ReactiveScalarChildSource) => {\n if (!effectHandle) {\n return;\n }\n\n currentSource = nextSource;\n effectHandle.updateCompute(() =>\n currentSource.map((slot) =>\n slot.kind === 'static' ? slot.value : slot.compute()\n )\n );\n },\n };\n}\n\nfunction setupReactiveChildBoundary(\n el: Element,\n childFn: () => VNode,\n host: ReactiveChildDOMHost\n): { cleanup: () => void; updateFn: (nextValue: unknown) => void } {\n let currentChildFn = childFn;\n const parentInstance = getCurrentInstance();\n const entry: { scope: ChildScope; nodes: Node[] } = {\n scope: createChildScope(\n parentInstance,\n `__reactive-child__:${(reactiveChildScopeId += 1)}`,\n () => {\n const expectedNodes = commitReactiveChildBoundaryEntryNodes(\n el,\n entry,\n host\n );\n syncReactiveChildExpectedNodes(el, expectedNodes);\n }\n ),\n nodes: [],\n };\n\n entry.scope.render(() =>\n normalizeReactiveChildBoundaryVNode(currentChildFn())\n );\n syncReactiveChildExpectedNodes(\n el,\n commitReactiveChildBoundaryEntryNodes(el, entry, host)\n );\n\n return {\n cleanup: () => {\n const dom = entry.scope.dom;\n const nodes = entry.nodes;\n disposeChildScope(entry.scope);\n entry.nodes = [];\n\n if (nodes.length > 0) {\n disposeReactiveChildBoundaryNodes(nodes);\n return;\n }\n\n if (dom?.parentNode === el) {\n teardownNodeSubtree(dom);\n el.removeChild(dom);\n }\n },\n updateFn: (nextValue: unknown) => {\n currentChildFn = nextValue as () => VNode;\n rerenderChildScope(entry.scope);\n const expectedNodes = commitReactiveChildBoundaryEntryNodes(\n el,\n entry,\n host\n );\n syncReactiveChildExpectedNodes(el, expectedNodes);\n },\n };\n}\n\nfunction setupReactiveChildBoundarySequence(\n el: Element,\n source: ReactiveChildBoundarySequenceSource,\n host: ReactiveChildDOMHost\n): { cleanup: () => void; updateFn: (nextValue: unknown) => void } {\n let currentSource = source;\n const parentInstance = getCurrentInstance();\n const entries: ReactiveChildBoundarySequenceEntry[] = [];\n const dynamicEntries: Array<{\n index: number;\n entry: Extract<ReactiveChildBoundarySequenceEntry, { kind: 'dynamic' }>;\n }> = [];\n\n if (!currentSource.some((slot) => slot.kind === 'dynamic')) {\n throw new Error(\n '[Askr] Reactive child boundary sequence requires at least one dynamic slot.'\n );\n }\n\n const syncSequence = () => {\n syncReactiveChildSequenceNodes(el, entries, host);\n };\n\n const parentNamespace = getParentNamespace(el);\n\n for (let index = 0; index < currentSource.length; index += 1) {\n const slot = currentSource[index];\n if (!slot) {\n continue;\n }\n\n if (slot.kind === 'static-text') {\n entries.push({\n kind: 'static',\n nodes: [document.createTextNode(slot.value)],\n });\n continue;\n }\n\n if (slot.kind === 'static-node') {\n entries.push({\n kind: 'static',\n nodes: materializeReactiveChildBoundaryNodes(\n slot.value,\n parentNamespace,\n host\n ),\n });\n continue;\n }\n\n const scope = createChildScope(\n parentInstance,\n `__reactive-child-seq__:${(reactiveChildScopeId += 1)}`,\n syncSequence\n );\n\n const dynamicEntry: Extract<\n ReactiveChildBoundarySequenceEntry,\n { kind: 'dynamic' }\n > = {\n kind: 'dynamic',\n scope,\n nodes: [],\n };\n entries.push(dynamicEntry);\n dynamicEntries.push({ index, entry: dynamicEntry });\n }\n\n for (const dynamicEntry of dynamicEntries) {\n dynamicEntry.entry.scope.render(() =>\n normalizeReactiveChildBoundaryVNode(\n (\n currentSource[dynamicEntry.index] as {\n kind: 'dynamic';\n compute: () => VNode;\n }\n ).compute()\n )\n );\n }\n\n syncSequence();\n\n return {\n cleanup: () => {\n for (const dynamicEntry of dynamicEntries) {\n const dom = dynamicEntry.entry.scope.dom;\n const nodes = dynamicEntry.entry.nodes;\n disposeChildScope(dynamicEntry.entry.scope);\n\n if (nodes.length > 0) {\n disposeReactiveChildBoundaryNodes(nodes);\n continue;\n }\n\n if (dom?.parentNode === el) {\n teardownNodeSubtree(dom);\n el.removeChild(dom);\n }\n }\n\n for (const entry of entries) {\n if (entry.kind === 'static') {\n disposeReactiveChildBoundaryNodes(entry.nodes);\n }\n }\n },\n updateFn: (nextValue: unknown) => {\n currentSource = nextValue as ReactiveChildBoundarySequenceSource;\n for (const dynamicEntry of dynamicEntries) {\n rerenderChildScope(dynamicEntry.entry.scope);\n }\n syncSequence();\n },\n };\n}\n\nexport function syncReactiveScalarChild(\n el: Element,\n children: unknown,\n host: ReactiveChildDOMHost\n): boolean {\n const reactiveChildSource = getReactiveScalarChildSource(children);\n const reactiveChildBoundary = getSingleReactiveChildBoundarySource(children);\n const reactiveChildBoundarySequence =\n getReactiveChildBoundarySequenceSource(children);\n const existingReactiveEntry = elementReactivePropsCleanup\n .get(el)\n ?.get(REACTIVE_CHILDREN_KEY);\n\n if (\n !reactiveChildSource &&\n !reactiveChildBoundary &&\n !reactiveChildBoundarySequence\n ) {\n if (existingReactiveEntry) {\n existingReactiveEntry.cleanup();\n const cleanupMap = elementReactivePropsCleanup.get(el);\n cleanupMap?.delete(REACTIVE_CHILDREN_KEY);\n if (cleanupMap && cleanupMap.size === 0) {\n elementReactivePropsCleanup.delete(el);\n }\n }\n\n return false;\n }\n\n if (reactiveChildSource && !reactiveChildBoundarySequence) {\n if (\n existingReactiveEntry &&\n Array.isArray(existingReactiveEntry.fnRef) &&\n areReactiveScalarChildSourcesEqual(\n existingReactiveEntry.fnRef,\n reactiveChildSource\n )\n ) {\n return true;\n }\n\n if (\n existingReactiveEntry?.updateFn &&\n Array.isArray(existingReactiveEntry.fnRef)\n ) {\n existingReactiveEntry.updateFn(reactiveChildSource);\n existingReactiveEntry.fnRef = reactiveChildSource;\n return true;\n }\n\n existingReactiveEntry?.cleanup();\n\n try {\n const reactive = setupReactiveScalarChild(el, reactiveChildSource, host);\n getOrCreateElementReactiveCleanupMap(el).set(REACTIVE_CHILDREN_KEY, {\n cleanup: reactive.cleanup,\n updateFn: (nextValue) => {\n reactive.updateFn(nextValue as ReactiveScalarChildSource);\n },\n fnRef: reactiveChildSource,\n });\n return true;\n } catch (error) {\n if (!reactiveChildBoundary && !reactiveChildBoundarySequence) {\n throw error;\n }\n }\n }\n\n if (reactiveChildBoundarySequence) {\n if (\n existingReactiveEntry &&\n Array.isArray(existingReactiveEntry.fnRef) &&\n areReactiveChildBoundarySequenceSourcesEqual(\n existingReactiveEntry.fnRef,\n reactiveChildBoundarySequence\n )\n ) {\n return true;\n }\n\n if (\n existingReactiveEntry?.updateFn &&\n Array.isArray(existingReactiveEntry.fnRef) &&\n canUpdateReactiveChildBoundarySequenceSource(\n existingReactiveEntry.fnRef,\n reactiveChildBoundarySequence\n )\n ) {\n existingReactiveEntry.updateFn(reactiveChildBoundarySequence);\n existingReactiveEntry.fnRef = reactiveChildBoundarySequence;\n return true;\n }\n\n existingReactiveEntry?.cleanup();\n\n const reactive = setupReactiveChildBoundarySequence(\n el,\n reactiveChildBoundarySequence,\n host\n );\n getOrCreateElementReactiveCleanupMap(el).set(REACTIVE_CHILDREN_KEY, {\n cleanup: reactive.cleanup,\n updateFn: reactive.updateFn,\n fnRef: reactiveChildBoundarySequence,\n });\n return true;\n }\n\n if (existingReactiveEntry?.fnRef === reactiveChildBoundary) {\n return true;\n }\n\n if (\n existingReactiveEntry?.updateFn &&\n !Array.isArray(existingReactiveEntry.fnRef)\n ) {\n existingReactiveEntry.updateFn(reactiveChildBoundary);\n existingReactiveEntry.fnRef = reactiveChildBoundary;\n return true;\n }\n\n existingReactiveEntry?.cleanup();\n\n if (!reactiveChildBoundary) {\n return false;\n }\n\n const reactive = setupReactiveChildBoundary(el, reactiveChildBoundary, host);\n getOrCreateElementReactiveCleanupMap(el).set(REACTIVE_CHILDREN_KEY, {\n cleanup: reactive.cleanup,\n updateFn: reactive.updateFn,\n fnRef: reactiveChildBoundary,\n });\n return true;\n}\n"],"mappings":"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"}
@@ -3,7 +3,8 @@ import "./env.js";
3
3
  import { checkPropChanges, recordFastPathStats } from "./utils.js";
4
4
  import { keyedElements, planKeyedReorderFastPath } from "./keyed.js";
5
5
  import { canReuseIntrinsicElementInNamespace, getParentNamespace } from "./namespaces.js";
6
- import { performBulkPositionalKeyedTextUpdate } from "./children.js";
6
+ import { performBulkPositionalKeyedTextUpdate } from "./children-fastpath.js";
7
+ import "./children.js";
7
8
  import { applyRendererFastPath } from "./fastpath.js";
8
9
  //#region src/renderer/reconcile-fastpaths.ts
9
10
  function tryFastPaths(parent, newChildren, keyedVnodes, oldKeyMap) {
@@ -1 +1 @@
1
- {"version":3,"file":"reconcile-fastpaths.js","names":[],"sources":["../../src/renderer/reconcile-fastpaths.ts"],"sourcesContent":["import type { VNode } from './types';\nimport { performBulkPositionalKeyedTextUpdate } from './children';\nimport { getRuntimeEnv } from './env';\nimport { applyRendererFastPath } from './fastpath';\nimport { keyedElements, planKeyedReorderFastPath } from './keyed';\nimport type { KeyedVnode } from './keyed-children';\nimport {\n canReuseIntrinsicElementInNamespace,\n getParentNamespace,\n} from './namespaces';\nimport { checkPropChanges, recordFastPathStats } from './utils';\n\ntype VnodeObj = VNode & { type?: unknown; props?: Record<string, unknown> };\n\nexport function tryFastPaths(\n parent: Element,\n newChildren: VNode[],\n keyedVnodes: KeyedVnode[],\n oldKeyMap: Map<string | number, Element> | undefined\n): Map<string | number, Element> | null {\n try {\n const forcedResult = tryForcedPositionalBulkUpdate(\n parent,\n newChildren,\n keyedVnodes\n );\n if (forcedResult) {\n return forcedResult;\n }\n\n const rendererResult = tryRendererFastPath(\n parent,\n keyedVnodes,\n newChildren.length,\n oldKeyMap\n );\n if (rendererResult) {\n return rendererResult;\n }\n\n const positionalResult = tryPositionalBulkUpdate(parent, keyedVnodes);\n if (positionalResult) {\n return positionalResult;\n }\n } catch {\n // Fall through to full reconciliation.\n }\n\n return null;\n}\n\nfunction tryRendererFastPath(\n parent: Element,\n keyedVnodes: KeyedVnode[],\n totalChildren: number,\n oldKeyMap: Map<string | number, Element> | undefined\n): Map<string | number, Element> | null {\n const decision = planKeyedReorderFastPath(\n parent,\n keyedVnodes,\n totalChildren,\n oldKeyMap\n );\n\n if (decision.useFastPath) {\n try {\n const map = applyRendererFastPath(parent, keyedVnodes, oldKeyMap);\n if (map) {\n keyedElements.set(parent, map);\n return map;\n }\n } catch {\n // Fall through.\n }\n }\n\n return null;\n}\n\nfunction tryForcedPositionalBulkUpdate(\n parent: Element,\n newChildren: VNode[],\n keyedVnodes: KeyedVnode[]\n): Map<string | number, Element> | null {\n if (getRuntimeEnv().ASKR_FORCE_BULK_POSREUSE !== '1') return null;\n if (keyedVnodes.length === 0 || keyedVnodes.length !== newChildren.length) {\n return null;\n }\n\n try {\n const stats = performBulkPositionalKeyedTextUpdate(parent, keyedVnodes);\n recordFastPathStats(stats, 'bulkKeyedPositionalForced');\n\n rebuildKeyedMap(parent);\n return keyedElements.get(parent) as Map<string | number, Element>;\n } catch {\n return null;\n }\n}\n\nfunction tryPositionalBulkUpdate(\n parent: Element,\n keyedVnodes: KeyedVnode[]\n): Map<string | number, Element> | null {\n const total = keyedVnodes.length;\n if (total < 10) return null;\n\n if (parent.children.length !== total) {\n return null;\n }\n\n const parentNamespace = getParentNamespace(parent);\n const matchCount = countPositionalMatches(\n parent,\n keyedVnodes,\n parentNamespace\n );\n const matchFraction = matchCount / total;\n\n if (keyedVnodes.length > 0) {\n if (matchCount !== total && matchFraction >= 0.1) {\n return null;\n }\n } else if (matchFraction < 0.9) {\n return null;\n }\n\n if (hasPositionalPropChanges(parent, keyedVnodes)) {\n return null;\n }\n\n try {\n const stats = performBulkPositionalKeyedTextUpdate(parent, keyedVnodes);\n recordFastPathStats(stats, 'bulkKeyedPositionalHits');\n\n rebuildKeyedMap(parent);\n return keyedElements.get(parent) as Map<string | number, Element>;\n } catch {\n return null;\n }\n}\n\nfunction countPositionalMatches(\n parent: Element,\n keyedVnodes: KeyedVnode[],\n parentNamespace: string | undefined\n): number {\n let matchCount = 0;\n\n try {\n for (let i = 0; i < keyedVnodes.length; i++) {\n const vnode = keyedVnodes[i].vnode as VnodeObj;\n const expectedKey = keyedVnodes[i].key;\n\n if (!vnode || typeof vnode !== 'object' || typeof vnode.type !== 'string')\n continue;\n\n const el = parent.children[i] as Element | undefined;\n if (!el) continue;\n\n if (\n canReuseIntrinsicElementInNamespace(el, vnode.type, parentNamespace)\n ) {\n const actualKey = el.getAttribute('data-key');\n const keyMatches =\n actualKey === String(expectedKey) ||\n (actualKey !== null &&\n !Number.isNaN(Number(actualKey)) &&\n Number(actualKey) === expectedKey);\n\n if (keyMatches) {\n matchCount++;\n }\n }\n }\n } catch {\n // Ignore.\n }\n\n return matchCount;\n}\n\nfunction hasPositionalPropChanges(\n parent: Element,\n keyedVnodes: KeyedVnode[]\n): boolean {\n try {\n for (let i = 0; i < keyedVnodes.length; i++) {\n const vnode = keyedVnodes[i].vnode as VnodeObj;\n const el = parent.children[i] as Element | undefined;\n if (!el || !vnode || typeof vnode !== 'object') continue;\n\n if (checkPropChanges(el, vnode.props || {})) {\n return true;\n }\n }\n } catch {\n return true;\n }\n\n return false;\n}\n\nfunction rebuildKeyedMap(parent: Element): void {\n try {\n const map = new Map<string | number, Element>();\n for (let el = parent.firstElementChild; el; el = el.nextElementSibling) {\n const k = el.getAttribute('data-key');\n if (k !== null) {\n map.set(k, el);\n const n = Number(k);\n if (!Number.isNaN(n)) map.set(n, el);\n }\n }\n keyedElements.set(parent, map);\n } catch {\n // Ignore.\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"reconcile-fastpaths.js","names":[],"sources":["../../src/renderer/reconcile-fastpaths.ts"],"sourcesContent":["import type { VNode } from './types';\nimport { performBulkPositionalKeyedTextUpdate } from './children';\nimport { getRuntimeEnv } from './env';\nimport { applyRendererFastPath } from './fastpath';\nimport { keyedElements, planKeyedReorderFastPath } from './keyed';\nimport type { KeyedVnode } from './keyed-children';\nimport {\n canReuseIntrinsicElementInNamespace,\n getParentNamespace,\n} from './namespaces';\nimport { checkPropChanges, recordFastPathStats } from './utils';\n\ntype VnodeObj = VNode & { type?: unknown; props?: Record<string, unknown> };\n\nexport function tryFastPaths(\n parent: Element,\n newChildren: VNode[],\n keyedVnodes: KeyedVnode[],\n oldKeyMap: Map<string | number, Element> | undefined\n): Map<string | number, Element> | null {\n try {\n const forcedResult = tryForcedPositionalBulkUpdate(\n parent,\n newChildren,\n keyedVnodes\n );\n if (forcedResult) {\n return forcedResult;\n }\n\n const rendererResult = tryRendererFastPath(\n parent,\n keyedVnodes,\n newChildren.length,\n oldKeyMap\n );\n if (rendererResult) {\n return rendererResult;\n }\n\n const positionalResult = tryPositionalBulkUpdate(parent, keyedVnodes);\n if (positionalResult) {\n return positionalResult;\n }\n } catch {\n // Fall through to full reconciliation.\n }\n\n return null;\n}\n\nfunction tryRendererFastPath(\n parent: Element,\n keyedVnodes: KeyedVnode[],\n totalChildren: number,\n oldKeyMap: Map<string | number, Element> | undefined\n): Map<string | number, Element> | null {\n const decision = planKeyedReorderFastPath(\n parent,\n keyedVnodes,\n totalChildren,\n oldKeyMap\n );\n\n if (decision.useFastPath) {\n try {\n const map = applyRendererFastPath(parent, keyedVnodes, oldKeyMap);\n if (map) {\n keyedElements.set(parent, map);\n return map;\n }\n } catch {\n // Fall through.\n }\n }\n\n return null;\n}\n\nfunction tryForcedPositionalBulkUpdate(\n parent: Element,\n newChildren: VNode[],\n keyedVnodes: KeyedVnode[]\n): Map<string | number, Element> | null {\n if (getRuntimeEnv().ASKR_FORCE_BULK_POSREUSE !== '1') return null;\n if (keyedVnodes.length === 0 || keyedVnodes.length !== newChildren.length) {\n return null;\n }\n\n try {\n const stats = performBulkPositionalKeyedTextUpdate(parent, keyedVnodes);\n recordFastPathStats(stats, 'bulkKeyedPositionalForced');\n\n rebuildKeyedMap(parent);\n return keyedElements.get(parent) as Map<string | number, Element>;\n } catch {\n return null;\n }\n}\n\nfunction tryPositionalBulkUpdate(\n parent: Element,\n keyedVnodes: KeyedVnode[]\n): Map<string | number, Element> | null {\n const total = keyedVnodes.length;\n if (total < 10) return null;\n\n if (parent.children.length !== total) {\n return null;\n }\n\n const parentNamespace = getParentNamespace(parent);\n const matchCount = countPositionalMatches(\n parent,\n keyedVnodes,\n parentNamespace\n );\n const matchFraction = matchCount / total;\n\n if (keyedVnodes.length > 0) {\n if (matchCount !== total && matchFraction >= 0.1) {\n return null;\n }\n } else if (matchFraction < 0.9) {\n return null;\n }\n\n if (hasPositionalPropChanges(parent, keyedVnodes)) {\n return null;\n }\n\n try {\n const stats = performBulkPositionalKeyedTextUpdate(parent, keyedVnodes);\n recordFastPathStats(stats, 'bulkKeyedPositionalHits');\n\n rebuildKeyedMap(parent);\n return keyedElements.get(parent) as Map<string | number, Element>;\n } catch {\n return null;\n }\n}\n\nfunction countPositionalMatches(\n parent: Element,\n keyedVnodes: KeyedVnode[],\n parentNamespace: string | undefined\n): number {\n let matchCount = 0;\n\n try {\n for (let i = 0; i < keyedVnodes.length; i++) {\n const vnode = keyedVnodes[i].vnode as VnodeObj;\n const expectedKey = keyedVnodes[i].key;\n\n if (!vnode || typeof vnode !== 'object' || typeof vnode.type !== 'string')\n continue;\n\n const el = parent.children[i] as Element | undefined;\n if (!el) continue;\n\n if (\n canReuseIntrinsicElementInNamespace(el, vnode.type, parentNamespace)\n ) {\n const actualKey = el.getAttribute('data-key');\n const keyMatches =\n actualKey === String(expectedKey) ||\n (actualKey !== null &&\n !Number.isNaN(Number(actualKey)) &&\n Number(actualKey) === expectedKey);\n\n if (keyMatches) {\n matchCount++;\n }\n }\n }\n } catch {\n // Ignore.\n }\n\n return matchCount;\n}\n\nfunction hasPositionalPropChanges(\n parent: Element,\n keyedVnodes: KeyedVnode[]\n): boolean {\n try {\n for (let i = 0; i < keyedVnodes.length; i++) {\n const vnode = keyedVnodes[i].vnode as VnodeObj;\n const el = parent.children[i] as Element | undefined;\n if (!el || !vnode || typeof vnode !== 'object') continue;\n\n if (checkPropChanges(el, vnode.props || {})) {\n return true;\n }\n }\n } catch {\n return true;\n }\n\n return false;\n}\n\nfunction rebuildKeyedMap(parent: Element): void {\n try {\n const map = new Map<string | number, Element>();\n for (let el = parent.firstElementChild; el; el = el.nextElementSibling) {\n const k = el.getAttribute('data-key');\n if (k !== null) {\n map.set(k, el);\n const n = Number(k);\n if (!Number.isNaN(n)) map.set(n, el);\n }\n }\n keyedElements.set(parent, map);\n } catch {\n // Ignore.\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { __FOR_BOUNDARY__ } from "../common/vnode.js";
2
- import { extractKey } from "./utils.js";
3
- import { evaluateForState } from "../runtime/for-internal.js";
4
- import "../runtime/for.js";
5
2
  import { evaluateCaseState, evaluateShowState } from "../runtime/control.js";
3
+ import { evaluateForState } from "../runtime/for-internal.js";
4
+ import "../runtime/index.js";
5
+ import { extractKey } from "./utils.js";
6
6
  import { canReuseIntrinsicElementInNamespace, getParentNamespace } from "./namespaces.js";
7
7
  import { getRendererDOMHost } from "./dom-host.js";
8
8
  //#region src/renderer/reconcile-resolution.ts
@@ -1 +1 @@
1
- {"version":3,"file":"reconcile-resolution.js","names":[],"sources":["../../src/renderer/reconcile-resolution.ts"],"sourcesContent":["import { __FOR_BOUNDARY__ } from '../common/vnode';\nimport type { Props } from '../common/props';\nimport type { ComponentFunction } from '../runtime/component-contracts';\nimport {\n evaluateCaseState,\n evaluateShowState,\n type ControlBoundaryState,\n} from '../runtime/control';\nimport { evaluateForState } from '../runtime/for';\nimport { getRendererDOMHost, type ElementWithContext } from './dom-host';\nimport {\n canReuseIntrinsicElementInNamespace,\n getParentNamespace,\n} from './namespaces';\nimport type { DOMElement, VNode } from './types';\nimport { extractKey } from './utils';\n\ntype VnodeObj = VNode & { type?: unknown; props?: Record<string, unknown> };\ntype ComponentVNode = DOMElement & { type: ComponentFunction };\n\nexport function createOldElResolver(\n parent: Element,\n oldKeyMap: Map<string | number, Element> | undefined,\n usedOldEls: WeakSet<Node>\n): (k: string | number) => Element | undefined {\n return (k: string | number) => {\n if (!oldKeyMap) return undefined;\n\n const direct = oldKeyMap.get(k);\n if (direct && !usedOldEls.has(direct)) {\n usedOldEls.add(direct);\n return direct;\n }\n\n const s = String(k);\n const byString = oldKeyMap.get(s);\n if (byString && !usedOldEls.has(byString)) {\n usedOldEls.add(byString);\n return byString;\n }\n\n const n = Number(s);\n if (!Number.isNaN(n)) {\n const byNum = oldKeyMap.get(n);\n if (byNum && !usedOldEls.has(byNum)) {\n usedOldEls.add(byNum);\n return byNum;\n }\n }\n\n return scanForElementByKey(parent, k, s, usedOldEls);\n };\n}\n\nfunction scanForElementByKey(\n parent: Element,\n k: string | number,\n keyStr: string,\n usedOldEls: WeakSet<Node>\n): Element | undefined {\n try {\n for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {\n if (usedOldEls.has(ch)) continue;\n const attr = ch.getAttribute('data-key');\n if (attr === keyStr) {\n usedOldEls.add(ch);\n return ch;\n }\n if (attr !== null) {\n const numAttr = Number(attr);\n if (!Number.isNaN(numAttr) && numAttr === (k as number)) {\n usedOldEls.add(ch);\n return ch;\n }\n }\n }\n } catch {\n // Ignore.\n }\n return undefined;\n}\n\nexport function reconcileSingleChild(\n child: VNode,\n index: number,\n parent: Element,\n resolveOldElOnce: (k: string | number) => Element | undefined,\n resolveUnkeyedOnce: () => Element | undefined,\n usedOldEls: WeakSet<Node>,\n newKeyMap: Map<string | number, Element>\n): Node | null {\n const resolvedControlBoundary = prepareControlBoundaryResolution(child);\n if (resolvedControlBoundary !== null) {\n if (resolvedControlBoundary.remount) {\n return getRendererDOMHost().createDOMNode(\n resolvedControlBoundary.vnode,\n getParentNamespace(parent)\n );\n }\n\n return reconcileSingleChild(\n resolvedControlBoundary.vnode,\n index,\n parent,\n resolveOldElOnce,\n resolveUnkeyedOnce,\n usedOldEls,\n newKeyMap\n );\n }\n\n const key = extractKey(child);\n\n if (key !== undefined) {\n return reconcileKeyedChild(child, key, parent, resolveOldElOnce, newKeyMap);\n }\n\n return reconcileUnkeyedChild(\n child,\n index,\n parent,\n resolveUnkeyedOnce,\n usedOldEls\n );\n}\n\nfunction reconcileKeyedChild(\n child: VNode,\n key: string | number,\n parent: Element,\n resolveOldElOnce: (k: string | number) => Element | undefined,\n newKeyMap: Map<string | number, Element>\n): Node | null {\n const el = resolveOldElOnce(key);\n const parentNamespace = getParentNamespace(parent);\n const domHost = getRendererDOMHost();\n\n if (el && el.parentElement === parent) {\n try {\n const childObj = child as VnodeObj;\n if (\n childObj &&\n typeof childObj === 'object' &&\n typeof childObj.type === 'string'\n ) {\n if (\n canReuseIntrinsicElementInNamespace(\n el,\n childObj.type,\n parentNamespace\n )\n ) {\n domHost.updateElementFromVnode(el, child);\n newKeyMap.set(key, el);\n return el;\n }\n }\n if (isComponentVNode(child)) {\n const synced = domHost.syncComponentElement(\n el,\n child as unknown as ElementWithContext,\n child.type,\n ((child.props ?? {}) as Props) || {},\n parentNamespace\n );\n if (synced) {\n if (synced instanceof Element) newKeyMap.set(key, synced);\n return synced;\n }\n }\n } catch {\n // Fall through to replacement.\n }\n }\n\n const dom = domHost.createDOMNode(child, parentNamespace);\n if (dom) {\n if (dom instanceof Element) newKeyMap.set(key, dom);\n return dom;\n }\n\n return null;\n}\n\nfunction reconcileUnkeyedChild(\n child: VNode,\n index: number,\n parent: Element,\n resolveUnkeyedOnce: () => Element | undefined,\n usedOldEls: WeakSet<Node>\n): Node | null {\n const parentNamespace = getParentNamespace(parent);\n const domHost = getRendererDOMHost();\n\n try {\n const existing = parent.childNodes[index] as Node | undefined;\n\n if (typeof child === 'string' || typeof child === 'number') {\n if (existing && existing.nodeType === 3) {\n (existing as Text).data = String(child);\n usedOldEls.add(existing);\n return existing;\n }\n return domHost.createDOMNode(child, parentNamespace);\n }\n\n if (existing instanceof Element) {\n const synced = trySyncComponentChild(\n existing,\n child,\n usedOldEls,\n parentNamespace\n );\n if (synced) return synced;\n }\n\n if (\n existing instanceof Element &&\n canReuseElement(existing, child, parentNamespace)\n ) {\n domHost.updateElementFromVnode(existing, child);\n usedOldEls.add(existing);\n return existing;\n }\n\n const avail = resolveUnkeyedOnce();\n if (avail) {\n const reuseResult = tryReuseElement(\n avail,\n child,\n usedOldEls,\n parentNamespace\n );\n if (reuseResult) return reuseResult;\n }\n } catch {\n // Fall through to create new.\n }\n\n return domHost.createDOMNode(child, parentNamespace);\n}\n\nfunction isComponentVNode(child: VNode): child is ComponentVNode {\n return (\n typeof child === 'object' &&\n child !== null &&\n 'type' in child &&\n typeof (child as VnodeObj).type === 'function'\n );\n}\n\nfunction isControlBoundaryVNode(child: VNode): child is DOMElement {\n return (\n typeof child === 'object' &&\n child !== null &&\n 'type' in child &&\n (child as VnodeObj).type === __FOR_BOUNDARY__\n );\n}\n\nfunction prepareControlBoundaryResolution(child: VNode): {\n remount: boolean;\n vnode: VNode | null;\n} | null {\n if (!isControlBoundaryVNode(child)) {\n return null;\n }\n\n const controlState = child._controlState ?? child._forState;\n if (!controlState) {\n return null;\n }\n if (controlState.kind === 'for') {\n const childrenVNodes = evaluateControlBoundaryChildren(controlState);\n return childrenVNodes.length === 1\n ? { remount: false, vnode: childrenVNodes[0] ?? null }\n : null;\n }\n\n const previousActiveKey = controlState.activeKey;\n const childrenVNodes = evaluateControlBoundaryChildren(controlState);\n\n return {\n remount:\n previousActiveKey !== null &&\n controlState.activeKey !== previousActiveKey,\n vnode: childrenVNodes[0] ?? null,\n };\n}\n\nfunction evaluateControlBoundaryChildren(\n controlState: ControlBoundaryState\n): VNode[] {\n if (controlState.kind === 'for') {\n return evaluateForState(controlState);\n }\n\n if (controlState.kind === 'show') {\n return evaluateShowState(controlState);\n }\n\n return evaluateCaseState(controlState);\n}\n\nfunction trySyncComponentChild(\n existing: Element,\n child: VNode,\n usedOldEls: WeakSet<Node>,\n parentNamespace: string | undefined\n): Node | null {\n if (!isComponentVNode(child)) return null;\n\n const synced = getRendererDOMHost().syncComponentElement(\n existing,\n child as unknown as ElementWithContext,\n child.type,\n ((child.props ?? {}) as Props) || {},\n parentNamespace\n );\n if (!synced) return null;\n\n usedOldEls.add(existing);\n usedOldEls.add(synced);\n return synced;\n}\n\nfunction canReuseElement(\n existing: Element | undefined,\n child: VNode,\n parentNamespace: string | undefined\n): boolean {\n if (!existing) return false;\n if (typeof child !== 'object' || child === null || !('type' in child))\n return false;\n\n const childObj = child as VnodeObj;\n const existingKey = existing.getAttribute('data-key');\n const hasNoKey = existingKey === null || existingKey === undefined;\n\n return (\n hasNoKey &&\n typeof childObj.type === 'string' &&\n canReuseIntrinsicElementInNamespace(\n existing,\n childObj.type,\n parentNamespace\n )\n );\n}\n\nexport function collectUnkeyedElements(parent: Element): Element[] {\n const elements: Element[] = [];\n for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {\n if (ch.getAttribute('data-key') === null) elements.push(ch);\n }\n return elements;\n}\n\nfunction tryReuseElement(\n avail: Element,\n child: VNode,\n usedOldEls: WeakSet<Node>,\n parentNamespace: string | undefined\n): Node | null {\n if (typeof child === 'string' || typeof child === 'number') {\n return null;\n }\n\n const synced = trySyncComponentChild(\n avail,\n child,\n usedOldEls,\n parentNamespace\n );\n if (synced) {\n return synced;\n }\n\n if (typeof child === 'object' && child !== null && 'type' in child) {\n const childObj = child as VnodeObj;\n if (\n typeof childObj.type === 'string' &&\n canReuseIntrinsicElementInNamespace(avail, childObj.type, parentNamespace)\n ) {\n getRendererDOMHost().updateElementFromVnode(avail, child);\n usedOldEls.add(avail);\n return avail;\n }\n }\n\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"reconcile-resolution.js","names":[],"sources":["../../src/renderer/reconcile-resolution.ts"],"sourcesContent":["import { __FOR_BOUNDARY__ } from '../common/vnode';\nimport type { Props } from '../common/props';\nimport type { ComponentFunction } from '../runtime';\nimport {\n evaluateCaseState,\n evaluateShowState,\n type ControlBoundaryState,\n} from '../runtime';\nimport { evaluateForState } from '../runtime';\nimport { getRendererDOMHost, type ElementWithContext } from './dom-host';\nimport {\n canReuseIntrinsicElementInNamespace,\n getParentNamespace,\n} from './namespaces';\nimport type { DOMElement, VNode } from './types';\nimport { extractKey } from './utils';\n\ntype VnodeObj = VNode & { type?: unknown; props?: Record<string, unknown> };\ntype ComponentVNode = DOMElement & { type: ComponentFunction };\n\nexport function createOldElResolver(\n parent: Element,\n oldKeyMap: Map<string | number, Element> | undefined,\n usedOldEls: WeakSet<Node>\n): (k: string | number) => Element | undefined {\n return (k: string | number) => {\n if (!oldKeyMap) return undefined;\n\n const direct = oldKeyMap.get(k);\n if (direct && !usedOldEls.has(direct)) {\n usedOldEls.add(direct);\n return direct;\n }\n\n const s = String(k);\n const byString = oldKeyMap.get(s);\n if (byString && !usedOldEls.has(byString)) {\n usedOldEls.add(byString);\n return byString;\n }\n\n const n = Number(s);\n if (!Number.isNaN(n)) {\n const byNum = oldKeyMap.get(n);\n if (byNum && !usedOldEls.has(byNum)) {\n usedOldEls.add(byNum);\n return byNum;\n }\n }\n\n return scanForElementByKey(parent, k, s, usedOldEls);\n };\n}\n\nfunction scanForElementByKey(\n parent: Element,\n k: string | number,\n keyStr: string,\n usedOldEls: WeakSet<Node>\n): Element | undefined {\n try {\n for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {\n if (usedOldEls.has(ch)) continue;\n const attr = ch.getAttribute('data-key');\n if (attr === keyStr) {\n usedOldEls.add(ch);\n return ch;\n }\n if (attr !== null) {\n const numAttr = Number(attr);\n if (!Number.isNaN(numAttr) && numAttr === (k as number)) {\n usedOldEls.add(ch);\n return ch;\n }\n }\n }\n } catch {\n // Ignore.\n }\n return undefined;\n}\n\nexport function reconcileSingleChild(\n child: VNode,\n index: number,\n parent: Element,\n resolveOldElOnce: (k: string | number) => Element | undefined,\n resolveUnkeyedOnce: () => Element | undefined,\n usedOldEls: WeakSet<Node>,\n newKeyMap: Map<string | number, Element>\n): Node | null {\n const resolvedControlBoundary = prepareControlBoundaryResolution(child);\n if (resolvedControlBoundary !== null) {\n if (resolvedControlBoundary.remount) {\n return getRendererDOMHost().createDOMNode(\n resolvedControlBoundary.vnode,\n getParentNamespace(parent)\n );\n }\n\n return reconcileSingleChild(\n resolvedControlBoundary.vnode,\n index,\n parent,\n resolveOldElOnce,\n resolveUnkeyedOnce,\n usedOldEls,\n newKeyMap\n );\n }\n\n const key = extractKey(child);\n\n if (key !== undefined) {\n return reconcileKeyedChild(child, key, parent, resolveOldElOnce, newKeyMap);\n }\n\n return reconcileUnkeyedChild(\n child,\n index,\n parent,\n resolveUnkeyedOnce,\n usedOldEls\n );\n}\n\nfunction reconcileKeyedChild(\n child: VNode,\n key: string | number,\n parent: Element,\n resolveOldElOnce: (k: string | number) => Element | undefined,\n newKeyMap: Map<string | number, Element>\n): Node | null {\n const el = resolveOldElOnce(key);\n const parentNamespace = getParentNamespace(parent);\n const domHost = getRendererDOMHost();\n\n if (el && el.parentElement === parent) {\n try {\n const childObj = child as VnodeObj;\n if (\n childObj &&\n typeof childObj === 'object' &&\n typeof childObj.type === 'string'\n ) {\n if (\n canReuseIntrinsicElementInNamespace(\n el,\n childObj.type,\n parentNamespace\n )\n ) {\n domHost.updateElementFromVnode(el, child);\n newKeyMap.set(key, el);\n return el;\n }\n }\n if (isComponentVNode(child)) {\n const synced = domHost.syncComponentElement(\n el,\n child as unknown as ElementWithContext,\n child.type,\n ((child.props ?? {}) as Props) || {},\n parentNamespace\n );\n if (synced) {\n if (synced instanceof Element) newKeyMap.set(key, synced);\n return synced;\n }\n }\n } catch {\n // Fall through to replacement.\n }\n }\n\n const dom = domHost.createDOMNode(child, parentNamespace);\n if (dom) {\n if (dom instanceof Element) newKeyMap.set(key, dom);\n return dom;\n }\n\n return null;\n}\n\nfunction reconcileUnkeyedChild(\n child: VNode,\n index: number,\n parent: Element,\n resolveUnkeyedOnce: () => Element | undefined,\n usedOldEls: WeakSet<Node>\n): Node | null {\n const parentNamespace = getParentNamespace(parent);\n const domHost = getRendererDOMHost();\n\n try {\n const existing = parent.childNodes[index] as Node | undefined;\n\n if (typeof child === 'string' || typeof child === 'number') {\n if (existing && existing.nodeType === 3) {\n (existing as Text).data = String(child);\n usedOldEls.add(existing);\n return existing;\n }\n return domHost.createDOMNode(child, parentNamespace);\n }\n\n if (existing instanceof Element) {\n const synced = trySyncComponentChild(\n existing,\n child,\n usedOldEls,\n parentNamespace\n );\n if (synced) return synced;\n }\n\n if (\n existing instanceof Element &&\n canReuseElement(existing, child, parentNamespace)\n ) {\n domHost.updateElementFromVnode(existing, child);\n usedOldEls.add(existing);\n return existing;\n }\n\n const avail = resolveUnkeyedOnce();\n if (avail) {\n const reuseResult = tryReuseElement(\n avail,\n child,\n usedOldEls,\n parentNamespace\n );\n if (reuseResult) return reuseResult;\n }\n } catch {\n // Fall through to create new.\n }\n\n return domHost.createDOMNode(child, parentNamespace);\n}\n\nfunction isComponentVNode(child: VNode): child is ComponentVNode {\n return (\n typeof child === 'object' &&\n child !== null &&\n 'type' in child &&\n typeof (child as VnodeObj).type === 'function'\n );\n}\n\nfunction isControlBoundaryVNode(child: VNode): child is DOMElement {\n return (\n typeof child === 'object' &&\n child !== null &&\n 'type' in child &&\n (child as VnodeObj).type === __FOR_BOUNDARY__\n );\n}\n\nfunction prepareControlBoundaryResolution(child: VNode): {\n remount: boolean;\n vnode: VNode | null;\n} | null {\n if (!isControlBoundaryVNode(child)) {\n return null;\n }\n\n const controlState = child._controlState ?? child._forState;\n if (!controlState) {\n return null;\n }\n if (controlState.kind === 'for') {\n const childrenVNodes = evaluateControlBoundaryChildren(controlState);\n return childrenVNodes.length === 1\n ? { remount: false, vnode: childrenVNodes[0] ?? null }\n : null;\n }\n\n const previousActiveKey = controlState.activeKey;\n const childrenVNodes = evaluateControlBoundaryChildren(controlState);\n\n return {\n remount:\n previousActiveKey !== null &&\n controlState.activeKey !== previousActiveKey,\n vnode: childrenVNodes[0] ?? null,\n };\n}\n\nfunction evaluateControlBoundaryChildren(\n controlState: ControlBoundaryState\n): VNode[] {\n if (controlState.kind === 'for') {\n return evaluateForState(controlState);\n }\n\n if (controlState.kind === 'show') {\n return evaluateShowState(controlState);\n }\n\n return evaluateCaseState(controlState);\n}\n\nfunction trySyncComponentChild(\n existing: Element,\n child: VNode,\n usedOldEls: WeakSet<Node>,\n parentNamespace: string | undefined\n): Node | null {\n if (!isComponentVNode(child)) return null;\n\n const synced = getRendererDOMHost().syncComponentElement(\n existing,\n child as unknown as ElementWithContext,\n child.type,\n ((child.props ?? {}) as Props) || {},\n parentNamespace\n );\n if (!synced) return null;\n\n usedOldEls.add(existing);\n usedOldEls.add(synced);\n return synced;\n}\n\nfunction canReuseElement(\n existing: Element | undefined,\n child: VNode,\n parentNamespace: string | undefined\n): boolean {\n if (!existing) return false;\n if (typeof child !== 'object' || child === null || !('type' in child))\n return false;\n\n const childObj = child as VnodeObj;\n const existingKey = existing.getAttribute('data-key');\n const hasNoKey = existingKey === null || existingKey === undefined;\n\n return (\n hasNoKey &&\n typeof childObj.type === 'string' &&\n canReuseIntrinsicElementInNamespace(\n existing,\n childObj.type,\n parentNamespace\n )\n );\n}\n\nexport function collectUnkeyedElements(parent: Element): Element[] {\n const elements: Element[] = [];\n for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {\n if (ch.getAttribute('data-key') === null) elements.push(ch);\n }\n return elements;\n}\n\nfunction tryReuseElement(\n avail: Element,\n child: VNode,\n usedOldEls: WeakSet<Node>,\n parentNamespace: string | undefined\n): Node | null {\n if (typeof child === 'string' || typeof child === 'number') {\n return null;\n }\n\n const synced = trySyncComponentChild(\n avail,\n child,\n usedOldEls,\n parentNamespace\n );\n if (synced) {\n return synced;\n }\n\n if (typeof child === 'object' && child !== null && 'type' in child) {\n const childObj = child as VnodeObj;\n if (\n typeof childObj.type === 'string' &&\n canReuseIntrinsicElementInNamespace(avail, childObj.type, parentNamespace)\n ) {\n getRendererDOMHost().updateElementFromVnode(avail, child);\n usedOldEls.add(avail);\n return avail;\n }\n }\n\n return null;\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import { logger } from "../dev/logger.js";
1
+ import { logger } from "../common/logger.js";
2
2
  import { addDelegatedListener, getDelegatedHandlersForElement, removeDelegatedListener, updateDelegatedListener } from "../runtime/events.js";
3
+ import "../runtime/index.js";
3
4
  import { elementListeners, elementReactivePropsCleanup, elementRefs } from "./cleanup.js";
4
5
  import { keyedElements } from "./keyed.js";
5
6
  //#region src/renderer/retained-element-rollback.ts
@@ -1 +1 @@
1
- {"version":3,"file":"retained-element-rollback.js","names":[],"sources":["../../src/renderer/retained-element-rollback.ts"],"sourcesContent":["import { logger } from '../dev/logger';\nimport {\n addDelegatedListener,\n getDelegatedHandlersForElement,\n removeDelegatedListener,\n updateDelegatedListener,\n} from '../runtime/events';\nimport {\n elementListeners,\n elementReactivePropsCleanup,\n elementRefs,\n type ListenerMapEntry,\n type ReactivePropCleanupEntry,\n} from './cleanup';\nimport { keyedElements } from './keyed';\n\ninterface AttributeSnapshot {\n element: Element;\n attributes: Array<[string, string]>;\n}\n\ninterface ChildNodesSnapshot {\n element: Element;\n childNodes: Node[];\n}\n\ninterface FormControlSnapshot {\n element: Element;\n value?: string;\n checked?: boolean;\n}\n\ninterface DelegatedListenerEntrySnapshot {\n eventName: string;\n handler: EventListener;\n original: EventListener;\n options?: AddEventListenerOptions;\n}\n\ninterface DelegatedListenerSnapshot {\n element: Element;\n entries: DelegatedListenerEntrySnapshot[];\n}\n\ninterface ListenerEntrySnapshot {\n listenerKey: string;\n entry: ListenerMapEntry;\n}\n\ninterface ListenerSnapshot {\n element: Element;\n entries: ListenerEntrySnapshot[];\n}\n\ninterface RefSnapshot {\n element: Element;\n ref: unknown;\n}\n\ninterface ReactivePropEntrySnapshot {\n propName: string;\n entry: ReactivePropCleanupEntry;\n}\n\ninterface ReactivePropsSnapshot {\n element: Element;\n entries: ReactivePropEntrySnapshot[];\n}\n\ninterface TextSnapshot {\n node: Text;\n data: string;\n}\n\nexport interface RetainedElementSnapshot {\n attributes: AttributeSnapshot[];\n childNodes: ChildNodesSnapshot[];\n delegatedListeners: DelegatedListenerSnapshot[];\n formControls: FormControlSnapshot[];\n keyedMap: Map<string | number, Element> | undefined;\n listeners: ListenerSnapshot[];\n reactiveProps: ReactivePropsSnapshot[];\n refs: RefSnapshot[];\n textNodes: TextSnapshot[];\n}\n\nfunction collectElementSubtree(root: Element): Element[] {\n const elements = [root];\n const descendants = root.querySelectorAll('*');\n for (let index = 0; index < descendants.length; index += 1) {\n elements.push(descendants[index]);\n }\n return elements;\n}\n\nfunction collectTextSnapshots(root: Element): TextSnapshot[] {\n const snapshots: TextSnapshot[] = [];\n const stack = Array.from(root.childNodes).reverse();\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n if (node.nodeType === 3) {\n snapshots.push({ node: node as Text, data: (node as Text).data });\n continue;\n }\n\n for (let child = node.lastChild; child; child = child.previousSibling) {\n stack.push(child);\n }\n }\n\n return snapshots;\n}\n\nfunction getFormControlSnapshot(element: Element): FormControlSnapshot | null {\n const control = element as Element & {\n value?: unknown;\n checked?: unknown;\n };\n const snapshot: FormControlSnapshot = { element };\n\n if ('value' in control) {\n snapshot.value = String(control.value ?? '');\n }\n\n if ('checked' in control) {\n snapshot.checked = Boolean(control.checked);\n }\n\n return snapshot.value !== undefined || snapshot.checked !== undefined\n ? snapshot\n : null;\n}\n\nfunction cloneListenerEntry(entry: ListenerMapEntry): ListenerMapEntry {\n return {\n handler: entry.handler,\n original: entry.original,\n eventName: entry.eventName,\n options: entry.options,\n isDelegated: entry.isDelegated,\n updateHandler: entry.updateHandler,\n };\n}\n\nfunction cloneReactivePropEntry(\n entry: ReactivePropCleanupEntry\n): ReactivePropCleanupEntry {\n return {\n cleanup: entry.cleanup,\n fnRef: entry.fnRef,\n restoreFn: entry.restoreFn,\n updateFn: entry.updateFn,\n };\n}\n\nexport function snapshotRetainedElement(\n element: Element\n): RetainedElementSnapshot {\n const elements = collectElementSubtree(element);\n const attributes: AttributeSnapshot[] = [];\n const childNodes: ChildNodesSnapshot[] = [];\n const delegatedListeners: DelegatedListenerSnapshot[] = [];\n const formControls: FormControlSnapshot[] = [];\n const listeners: ListenerSnapshot[] = [];\n const reactiveProps: ReactivePropsSnapshot[] = [];\n const refs: RefSnapshot[] = [];\n\n for (const currentElement of elements) {\n attributes.push({\n element: currentElement,\n attributes: Array.from(currentElement.attributes, (attribute) => [\n attribute.name,\n attribute.value,\n ]),\n });\n childNodes.push({\n element: currentElement,\n childNodes: Array.from(currentElement.childNodes),\n });\n\n const formControl = getFormControlSnapshot(currentElement);\n if (formControl) {\n formControls.push(formControl);\n }\n\n const listenerMap = elementListeners.get(currentElement);\n listeners.push({\n element: currentElement,\n entries: listenerMap\n ? Array.from(listenerMap, ([listenerKey, entry]) => ({\n listenerKey,\n entry: cloneListenerEntry(entry),\n }))\n : [],\n });\n\n const delegatedHandlerMap = getDelegatedHandlersForElement(currentElement);\n delegatedListeners.push({\n element: currentElement,\n entries: delegatedHandlerMap\n ? Array.from(delegatedHandlerMap, ([eventName, entry]) => ({\n eventName,\n handler: entry.handler,\n original: entry.original,\n options: entry.options,\n }))\n : [],\n });\n\n const reactivePropMap = elementReactivePropsCleanup.get(currentElement);\n reactiveProps.push({\n element: currentElement,\n entries: reactivePropMap\n ? Array.from(reactivePropMap, ([propName, entry]) => ({\n propName,\n entry: cloneReactivePropEntry(entry),\n }))\n : [],\n });\n\n refs.push({\n element: currentElement,\n ref: elementRefs.get(currentElement),\n });\n }\n\n const keyedMap = keyedElements.get(element);\n\n return {\n attributes,\n childNodes,\n delegatedListeners,\n formControls,\n keyedMap: keyedMap ? new Map(keyedMap) : undefined,\n listeners,\n reactiveProps,\n refs,\n textNodes: collectTextSnapshots(element),\n };\n}\n\nfunction sameChildOrder(element: Element, childNodes: Node[]): boolean {\n if (element.childNodes.length !== childNodes.length) {\n return false;\n }\n\n for (let index = 0; index < childNodes.length; index += 1) {\n if (element.childNodes[index] !== childNodes[index]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction restoreAttributes(snapshot: RetainedElementSnapshot): void {\n for (const { element, attributes } of snapshot.attributes) {\n const expectedNames = new Set(attributes.map(([name]) => name));\n\n for (const attribute of Array.from(element.attributes)) {\n if (!expectedNames.has(attribute.name)) {\n element.removeAttribute(attribute.name);\n }\n }\n\n for (const [name, value] of attributes) {\n if (element.getAttribute(name) !== value) {\n element.setAttribute(name, value);\n }\n }\n }\n}\n\nfunction restoreFormControls(snapshot: RetainedElementSnapshot): void {\n for (const { element, value, checked } of snapshot.formControls) {\n const control = element as Element & {\n value?: string;\n checked?: boolean;\n };\n\n if (value !== undefined && 'value' in control) {\n control.value = value;\n }\n\n if (checked !== undefined && 'checked' in control) {\n control.checked = checked;\n }\n }\n}\n\nfunction applyRefValue<T>(ref: unknown, value: T | null): void {\n if (!ref) {\n return;\n }\n\n try {\n if (typeof ref === 'function') {\n (ref as (value: T | null) => void)(value);\n return;\n }\n\n if (Object.isExtensible(ref)) {\n (ref as { current: T | null }).current = value;\n }\n } catch {\n // Rollback must preserve the original render error.\n }\n}\n\nfunction restoreRefs(snapshot: RetainedElementSnapshot): void {\n for (const { element, ref } of snapshot.refs) {\n const currentRef = elementRefs.get(element);\n\n if (currentRef !== ref) {\n applyRefValue(currentRef, null);\n }\n\n if (ref) {\n applyRefValue(ref, element);\n elementRefs.set(element, ref);\n } else {\n elementRefs.delete(element);\n }\n }\n}\n\nfunction removeDirectListener(element: Element, entry: ListenerMapEntry): void {\n if (entry.isDelegated) {\n return;\n }\n\n if (entry.options !== undefined) {\n element.removeEventListener(entry.eventName, entry.handler, entry.options);\n } else {\n element.removeEventListener(entry.eventName, entry.handler);\n }\n}\n\nfunction addDirectListener(element: Element, entry: ListenerMapEntry): void {\n if (entry.isDelegated) {\n return;\n }\n\n if (entry.options !== undefined) {\n element.addEventListener(entry.eventName, entry.handler, entry.options);\n } else {\n element.addEventListener(entry.eventName, entry.handler);\n }\n}\n\nfunction restoreListeners(snapshot: RetainedElementSnapshot): void {\n for (const { element, entries } of snapshot.listeners) {\n const expectedKeys = new Set(entries.map(({ listenerKey }) => listenerKey));\n let currentMap = elementListeners.get(element);\n\n if (currentMap) {\n for (const [listenerKey, entry] of Array.from(currentMap)) {\n if (!expectedKeys.has(listenerKey)) {\n removeDirectListener(element, entry);\n currentMap.delete(listenerKey);\n }\n }\n }\n\n if (entries.length === 0) {\n if (currentMap?.size === 0) {\n elementListeners.delete(element);\n }\n continue;\n }\n\n if (!currentMap) {\n currentMap = new Map();\n elementListeners.set(element, currentMap);\n }\n\n for (const { listenerKey, entry } of entries) {\n const currentEntry = currentMap.get(listenerKey);\n\n entry.updateHandler?.(entry.original);\n\n if (currentEntry && currentEntry.handler !== entry.handler) {\n removeDirectListener(element, currentEntry);\n }\n\n if (!currentEntry || currentEntry.handler !== entry.handler) {\n addDirectListener(element, entry);\n } else {\n currentEntry.updateHandler?.(entry.original);\n }\n\n currentMap.set(listenerKey, cloneListenerEntry(entry));\n }\n }\n}\n\nfunction restoreDelegatedListeners(snapshot: RetainedElementSnapshot): void {\n for (const { element, entries } of snapshot.delegatedListeners) {\n const expectedEventNames = new Set(\n entries.map(({ eventName }) => eventName)\n );\n const currentMap = getDelegatedHandlersForElement(element);\n\n if (currentMap) {\n for (const eventName of currentMap.keys()) {\n if (!expectedEventNames.has(eventName)) {\n removeDelegatedListener(element, eventName);\n }\n }\n }\n\n for (const { eventName, handler, original, options } of entries) {\n if (\n !updateDelegatedListener(element, eventName, handler, original, options)\n ) {\n addDelegatedListener(element, eventName, handler, original, options);\n }\n }\n }\n}\n\nfunction restoreReactiveProps(snapshot: RetainedElementSnapshot): void {\n for (const { element, entries } of snapshot.reactiveProps) {\n const expectedPropNames = new Set(entries.map(({ propName }) => propName));\n let currentMap = elementReactivePropsCleanup.get(element);\n\n if (currentMap) {\n for (const [propName, entry] of Array.from(currentMap)) {\n if (!expectedPropNames.has(propName)) {\n entry.cleanup();\n currentMap.delete(propName);\n }\n }\n }\n\n if (entries.length === 0) {\n if (currentMap?.size === 0) {\n elementReactivePropsCleanup.delete(element);\n }\n continue;\n }\n\n if (!currentMap) {\n currentMap = new Map();\n elementReactivePropsCleanup.set(element, currentMap);\n }\n\n for (const { propName, entry } of entries) {\n const currentEntry = currentMap.get(propName);\n\n if (currentEntry) {\n currentEntry.updateFn?.(entry.fnRef);\n currentEntry.fnRef = entry.fnRef;\n currentMap.set(propName, currentEntry);\n continue;\n }\n\n currentMap.set(\n propName,\n entry.restoreFn?.(entry.fnRef) ?? cloneReactivePropEntry(entry)\n );\n }\n }\n}\n\nfunction restoreChildNodes(\n snapshot: RetainedElementSnapshot,\n cleanupRangeNode: (node: Node) => void\n): void {\n for (const { element, childNodes } of snapshot.childNodes) {\n const expectedChildren = new Set(childNodes);\n\n for (const child of Array.from(element.childNodes)) {\n if (!expectedChildren.has(child)) {\n cleanupRangeNode(child);\n }\n }\n }\n\n for (const { element, childNodes } of snapshot.childNodes) {\n if (!sameChildOrder(element, childNodes)) {\n element.replaceChildren(...childNodes);\n }\n }\n}\n\nfunction restoreTextNodes(snapshot: RetainedElementSnapshot): void {\n for (const { node, data } of snapshot.textNodes) {\n if (node.data !== data) {\n node.data = data;\n }\n }\n}\n\nfunction restoreKeyedMap(\n element: Element,\n snapshot: RetainedElementSnapshot\n): void {\n if (snapshot.keyedMap) {\n keyedElements.set(element, new Map(snapshot.keyedMap));\n } else {\n keyedElements.delete(element);\n }\n}\n\nexport function restoreRetainedElement(\n element: Element,\n snapshot: RetainedElementSnapshot,\n cleanupRangeNode: (node: Node) => void\n): void {\n restoreChildNodes(snapshot, cleanupRangeNode);\n restoreReactiveProps(snapshot);\n restoreAttributes(snapshot);\n restoreTextNodes(snapshot);\n restoreFormControls(snapshot);\n restoreRefs(snapshot);\n restoreListeners(snapshot);\n restoreDelegatedListeners(snapshot);\n restoreKeyedMap(element, snapshot);\n}\n\nexport function runRetainedElementUpdate(\n element: Element,\n cleanupRangeNode: (node: Node) => void,\n update: () => void,\n onError?: () => void\n): void {\n const snapshot = snapshotRetainedElement(element);\n\n try {\n update();\n } catch (err) {\n onError?.();\n\n try {\n restoreRetainedElement(element, snapshot, cleanupRangeNode);\n } catch (rollbackError) {\n logger.warn('[Askr] retained element rollback failed:', rollbackError);\n }\n\n throw err;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"retained-element-rollback.js","names":[],"sources":["../../src/renderer/retained-element-rollback.ts"],"sourcesContent":["import { logger } from '../common/logger';\nimport {\n addDelegatedListener,\n getDelegatedHandlersForElement,\n removeDelegatedListener,\n updateDelegatedListener,\n} from '../runtime';\nimport {\n elementListeners,\n elementReactivePropsCleanup,\n elementRefs,\n type ListenerMapEntry,\n type ReactivePropCleanupEntry,\n} from './cleanup';\nimport { keyedElements } from './keyed';\n\ninterface AttributeSnapshot {\n element: Element;\n attributes: Array<[string, string]>;\n}\n\ninterface ChildNodesSnapshot {\n element: Element;\n childNodes: Node[];\n}\n\ninterface FormControlSnapshot {\n element: Element;\n value?: string;\n checked?: boolean;\n}\n\ninterface DelegatedListenerEntrySnapshot {\n eventName: string;\n handler: EventListener;\n original: EventListener;\n options?: AddEventListenerOptions;\n}\n\ninterface DelegatedListenerSnapshot {\n element: Element;\n entries: DelegatedListenerEntrySnapshot[];\n}\n\ninterface ListenerEntrySnapshot {\n listenerKey: string;\n entry: ListenerMapEntry;\n}\n\ninterface ListenerSnapshot {\n element: Element;\n entries: ListenerEntrySnapshot[];\n}\n\ninterface RefSnapshot {\n element: Element;\n ref: unknown;\n}\n\ninterface ReactivePropEntrySnapshot {\n propName: string;\n entry: ReactivePropCleanupEntry;\n}\n\ninterface ReactivePropsSnapshot {\n element: Element;\n entries: ReactivePropEntrySnapshot[];\n}\n\ninterface TextSnapshot {\n node: Text;\n data: string;\n}\n\nexport interface RetainedElementSnapshot {\n attributes: AttributeSnapshot[];\n childNodes: ChildNodesSnapshot[];\n delegatedListeners: DelegatedListenerSnapshot[];\n formControls: FormControlSnapshot[];\n keyedMap: Map<string | number, Element> | undefined;\n listeners: ListenerSnapshot[];\n reactiveProps: ReactivePropsSnapshot[];\n refs: RefSnapshot[];\n textNodes: TextSnapshot[];\n}\n\nfunction collectElementSubtree(root: Element): Element[] {\n const elements = [root];\n const descendants = root.querySelectorAll('*');\n for (let index = 0; index < descendants.length; index += 1) {\n elements.push(descendants[index]);\n }\n return elements;\n}\n\nfunction collectTextSnapshots(root: Element): TextSnapshot[] {\n const snapshots: TextSnapshot[] = [];\n const stack = Array.from(root.childNodes).reverse();\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n if (node.nodeType === 3) {\n snapshots.push({ node: node as Text, data: (node as Text).data });\n continue;\n }\n\n for (let child = node.lastChild; child; child = child.previousSibling) {\n stack.push(child);\n }\n }\n\n return snapshots;\n}\n\nfunction getFormControlSnapshot(element: Element): FormControlSnapshot | null {\n const control = element as Element & {\n value?: unknown;\n checked?: unknown;\n };\n const snapshot: FormControlSnapshot = { element };\n\n if ('value' in control) {\n snapshot.value = String(control.value ?? '');\n }\n\n if ('checked' in control) {\n snapshot.checked = Boolean(control.checked);\n }\n\n return snapshot.value !== undefined || snapshot.checked !== undefined\n ? snapshot\n : null;\n}\n\nfunction cloneListenerEntry(entry: ListenerMapEntry): ListenerMapEntry {\n return {\n handler: entry.handler,\n original: entry.original,\n eventName: entry.eventName,\n options: entry.options,\n isDelegated: entry.isDelegated,\n updateHandler: entry.updateHandler,\n };\n}\n\nfunction cloneReactivePropEntry(\n entry: ReactivePropCleanupEntry\n): ReactivePropCleanupEntry {\n return {\n cleanup: entry.cleanup,\n fnRef: entry.fnRef,\n restoreFn: entry.restoreFn,\n updateFn: entry.updateFn,\n };\n}\n\nexport function snapshotRetainedElement(\n element: Element\n): RetainedElementSnapshot {\n const elements = collectElementSubtree(element);\n const attributes: AttributeSnapshot[] = [];\n const childNodes: ChildNodesSnapshot[] = [];\n const delegatedListeners: DelegatedListenerSnapshot[] = [];\n const formControls: FormControlSnapshot[] = [];\n const listeners: ListenerSnapshot[] = [];\n const reactiveProps: ReactivePropsSnapshot[] = [];\n const refs: RefSnapshot[] = [];\n\n for (const currentElement of elements) {\n attributes.push({\n element: currentElement,\n attributes: Array.from(currentElement.attributes, (attribute) => [\n attribute.name,\n attribute.value,\n ]),\n });\n childNodes.push({\n element: currentElement,\n childNodes: Array.from(currentElement.childNodes),\n });\n\n const formControl = getFormControlSnapshot(currentElement);\n if (formControl) {\n formControls.push(formControl);\n }\n\n const listenerMap = elementListeners.get(currentElement);\n listeners.push({\n element: currentElement,\n entries: listenerMap\n ? Array.from(listenerMap, ([listenerKey, entry]) => ({\n listenerKey,\n entry: cloneListenerEntry(entry),\n }))\n : [],\n });\n\n const delegatedHandlerMap = getDelegatedHandlersForElement(currentElement);\n delegatedListeners.push({\n element: currentElement,\n entries: delegatedHandlerMap\n ? Array.from(delegatedHandlerMap, ([eventName, entry]) => ({\n eventName,\n handler: entry.handler,\n original: entry.original,\n options: entry.options,\n }))\n : [],\n });\n\n const reactivePropMap = elementReactivePropsCleanup.get(currentElement);\n reactiveProps.push({\n element: currentElement,\n entries: reactivePropMap\n ? Array.from(reactivePropMap, ([propName, entry]) => ({\n propName,\n entry: cloneReactivePropEntry(entry),\n }))\n : [],\n });\n\n refs.push({\n element: currentElement,\n ref: elementRefs.get(currentElement),\n });\n }\n\n const keyedMap = keyedElements.get(element);\n\n return {\n attributes,\n childNodes,\n delegatedListeners,\n formControls,\n keyedMap: keyedMap ? new Map(keyedMap) : undefined,\n listeners,\n reactiveProps,\n refs,\n textNodes: collectTextSnapshots(element),\n };\n}\n\nfunction sameChildOrder(element: Element, childNodes: Node[]): boolean {\n if (element.childNodes.length !== childNodes.length) {\n return false;\n }\n\n for (let index = 0; index < childNodes.length; index += 1) {\n if (element.childNodes[index] !== childNodes[index]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction restoreAttributes(snapshot: RetainedElementSnapshot): void {\n for (const { element, attributes } of snapshot.attributes) {\n const expectedNames = new Set(attributes.map(([name]) => name));\n\n for (const attribute of Array.from(element.attributes)) {\n if (!expectedNames.has(attribute.name)) {\n element.removeAttribute(attribute.name);\n }\n }\n\n for (const [name, value] of attributes) {\n if (element.getAttribute(name) !== value) {\n element.setAttribute(name, value);\n }\n }\n }\n}\n\nfunction restoreFormControls(snapshot: RetainedElementSnapshot): void {\n for (const { element, value, checked } of snapshot.formControls) {\n const control = element as Element & {\n value?: string;\n checked?: boolean;\n };\n\n if (value !== undefined && 'value' in control) {\n control.value = value;\n }\n\n if (checked !== undefined && 'checked' in control) {\n control.checked = checked;\n }\n }\n}\n\nfunction applyRefValue<T>(ref: unknown, value: T | null): void {\n if (!ref) {\n return;\n }\n\n try {\n if (typeof ref === 'function') {\n (ref as (value: T | null) => void)(value);\n return;\n }\n\n if (Object.isExtensible(ref)) {\n (ref as { current: T | null }).current = value;\n }\n } catch {\n // Rollback must preserve the original render error.\n }\n}\n\nfunction restoreRefs(snapshot: RetainedElementSnapshot): void {\n for (const { element, ref } of snapshot.refs) {\n const currentRef = elementRefs.get(element);\n\n if (currentRef !== ref) {\n applyRefValue(currentRef, null);\n }\n\n if (ref) {\n applyRefValue(ref, element);\n elementRefs.set(element, ref);\n } else {\n elementRefs.delete(element);\n }\n }\n}\n\nfunction removeDirectListener(element: Element, entry: ListenerMapEntry): void {\n if (entry.isDelegated) {\n return;\n }\n\n if (entry.options !== undefined) {\n element.removeEventListener(entry.eventName, entry.handler, entry.options);\n } else {\n element.removeEventListener(entry.eventName, entry.handler);\n }\n}\n\nfunction addDirectListener(element: Element, entry: ListenerMapEntry): void {\n if (entry.isDelegated) {\n return;\n }\n\n if (entry.options !== undefined) {\n element.addEventListener(entry.eventName, entry.handler, entry.options);\n } else {\n element.addEventListener(entry.eventName, entry.handler);\n }\n}\n\nfunction restoreListeners(snapshot: RetainedElementSnapshot): void {\n for (const { element, entries } of snapshot.listeners) {\n const expectedKeys = new Set(entries.map(({ listenerKey }) => listenerKey));\n let currentMap = elementListeners.get(element);\n\n if (currentMap) {\n for (const [listenerKey, entry] of Array.from(currentMap)) {\n if (!expectedKeys.has(listenerKey)) {\n removeDirectListener(element, entry);\n currentMap.delete(listenerKey);\n }\n }\n }\n\n if (entries.length === 0) {\n if (currentMap?.size === 0) {\n elementListeners.delete(element);\n }\n continue;\n }\n\n if (!currentMap) {\n currentMap = new Map();\n elementListeners.set(element, currentMap);\n }\n\n for (const { listenerKey, entry } of entries) {\n const currentEntry = currentMap.get(listenerKey);\n\n entry.updateHandler?.(entry.original);\n\n if (currentEntry && currentEntry.handler !== entry.handler) {\n removeDirectListener(element, currentEntry);\n }\n\n if (!currentEntry || currentEntry.handler !== entry.handler) {\n addDirectListener(element, entry);\n } else {\n currentEntry.updateHandler?.(entry.original);\n }\n\n currentMap.set(listenerKey, cloneListenerEntry(entry));\n }\n }\n}\n\nfunction restoreDelegatedListeners(snapshot: RetainedElementSnapshot): void {\n for (const { element, entries } of snapshot.delegatedListeners) {\n const expectedEventNames = new Set(\n entries.map(({ eventName }) => eventName)\n );\n const currentMap = getDelegatedHandlersForElement(element);\n\n if (currentMap) {\n for (const eventName of currentMap.keys()) {\n if (!expectedEventNames.has(eventName)) {\n removeDelegatedListener(element, eventName);\n }\n }\n }\n\n for (const { eventName, handler, original, options } of entries) {\n if (\n !updateDelegatedListener(element, eventName, handler, original, options)\n ) {\n addDelegatedListener(element, eventName, handler, original, options);\n }\n }\n }\n}\n\nfunction restoreReactiveProps(snapshot: RetainedElementSnapshot): void {\n for (const { element, entries } of snapshot.reactiveProps) {\n const expectedPropNames = new Set(entries.map(({ propName }) => propName));\n let currentMap = elementReactivePropsCleanup.get(element);\n\n if (currentMap) {\n for (const [propName, entry] of Array.from(currentMap)) {\n if (!expectedPropNames.has(propName)) {\n entry.cleanup();\n currentMap.delete(propName);\n }\n }\n }\n\n if (entries.length === 0) {\n if (currentMap?.size === 0) {\n elementReactivePropsCleanup.delete(element);\n }\n continue;\n }\n\n if (!currentMap) {\n currentMap = new Map();\n elementReactivePropsCleanup.set(element, currentMap);\n }\n\n for (const { propName, entry } of entries) {\n const currentEntry = currentMap.get(propName);\n\n if (currentEntry) {\n currentEntry.updateFn?.(entry.fnRef);\n currentEntry.fnRef = entry.fnRef;\n currentMap.set(propName, currentEntry);\n continue;\n }\n\n currentMap.set(\n propName,\n entry.restoreFn?.(entry.fnRef) ?? cloneReactivePropEntry(entry)\n );\n }\n }\n}\n\nfunction restoreChildNodes(\n snapshot: RetainedElementSnapshot,\n cleanupRangeNode: (node: Node) => void\n): void {\n for (const { element, childNodes } of snapshot.childNodes) {\n const expectedChildren = new Set(childNodes);\n\n for (const child of Array.from(element.childNodes)) {\n if (!expectedChildren.has(child)) {\n cleanupRangeNode(child);\n }\n }\n }\n\n for (const { element, childNodes } of snapshot.childNodes) {\n if (!sameChildOrder(element, childNodes)) {\n element.replaceChildren(...childNodes);\n }\n }\n}\n\nfunction restoreTextNodes(snapshot: RetainedElementSnapshot): void {\n for (const { node, data } of snapshot.textNodes) {\n if (node.data !== data) {\n node.data = data;\n }\n }\n}\n\nfunction restoreKeyedMap(\n element: Element,\n snapshot: RetainedElementSnapshot\n): void {\n if (snapshot.keyedMap) {\n keyedElements.set(element, new Map(snapshot.keyedMap));\n } else {\n keyedElements.delete(element);\n }\n}\n\nexport function restoreRetainedElement(\n element: Element,\n snapshot: RetainedElementSnapshot,\n cleanupRangeNode: (node: Node) => void\n): void {\n restoreChildNodes(snapshot, cleanupRangeNode);\n restoreReactiveProps(snapshot);\n restoreAttributes(snapshot);\n restoreTextNodes(snapshot);\n restoreFormControls(snapshot);\n restoreRefs(snapshot);\n restoreListeners(snapshot);\n restoreDelegatedListeners(snapshot);\n restoreKeyedMap(element, snapshot);\n}\n\nexport function runRetainedElementUpdate(\n element: Element,\n cleanupRangeNode: (node: Node) => void,\n update: () => void,\n onError?: () => void\n): void {\n const snapshot = snapshotRetainedElement(element);\n\n try {\n update();\n } catch (err) {\n onError?.();\n\n try {\n restoreRetainedElement(element, snapshot, cleanupRangeNode);\n } catch (rollbackError) {\n logger.warn('[Askr] retained element rollback failed:', rollbackError);\n }\n\n throw err;\n }\n}\n"],"mappings":"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"}
@@ -5,10 +5,9 @@ import { incDevCounter } from "../runtime/dev-namespace.js";
5
5
  import { getCurrentInstance } from "../runtime/component-scope.js";
6
6
  import { isPromiseLike } from "../common/promise.js";
7
7
  import { captureInlineRenderSnapshot, renderComponentInline, warnUnusedStateReads } from "../runtime/component-internal.js";
8
- import "../runtime/component-contracts.js";
9
- import { tagNamesEqualIgnoreCase } from "./utils.js";
10
8
  import { recordBenchEvent } from "../runtime/for-bench.js";
11
- import "../runtime/for.js";
9
+ import "../runtime/index.js";
10
+ import { tagNamesEqualIgnoreCase } from "./utils.js";
12
11
  import { getRendererDOMHost } from "./dom-host.js";
13
12
  import { findHostInstanceByType, inheritComponentCleanupStrict, inheritComponentKey, isRouteRootComponentVNode } from "./component-host-instances.js";
14
13
  import { resolveNestedComponentResult } from "./component-host.js";