@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,7 +1,56 @@
1
- import { logger } from "../dev/logger.js";
1
+ import { isDevelopmentEnvironment } from "../common/env.js";
2
+ import { logger } from "../common/logger.js";
3
+ import { createBoundaryReset, reportBoundaryError } from "../runtime/error-boundary.js";
4
+ import "../runtime/index.js";
2
5
  import { getRendererDOMHost } from "./dom-host.js";
3
- import { createBoundaryReset, reportBoundaryError, resolveErrorBoundaryFallback } from "../components/error-boundary.js";
4
6
  //#region src/renderer/error-boundary-dom.ts
7
+ function getBoundaryMessage(error) {
8
+ if (error instanceof Error) return error.message || error.name || "Unknown error";
9
+ if (typeof error === "string") return error;
10
+ try {
11
+ return JSON.stringify(error);
12
+ } catch {
13
+ return String(error);
14
+ }
15
+ }
16
+ function createDefaultFallbackNode(error, reset) {
17
+ const message = getBoundaryMessage(error);
18
+ const wrapper = document.createElement("div");
19
+ wrapper.setAttribute("role", "alert");
20
+ wrapper.setAttribute("data-askr-error-boundary", "true");
21
+ wrapper.style.boxSizing = "border-box";
22
+ wrapper.style.padding = "1rem";
23
+ wrapper.style.border = "1px solid currentColor";
24
+ wrapper.style.borderRadius = "0.75rem";
25
+ wrapper.style.display = "grid";
26
+ wrapper.style.gap = "0.75rem";
27
+ wrapper.style.maxWidth = "100%";
28
+ const title = document.createElement("strong");
29
+ title.textContent = "Something went wrong while rendering this view.";
30
+ const summary = document.createElement("p");
31
+ summary.textContent = "The app recovered into a visible fallback so the error is not hidden in the console.";
32
+ summary.style.margin = "0";
33
+ const details = document.createElement("details");
34
+ details.open = isDevelopmentEnvironment();
35
+ const detailsSummary = document.createElement("summary");
36
+ detailsSummary.textContent = "Error details";
37
+ const pre = document.createElement("pre");
38
+ pre.textContent = message;
39
+ pre.style.margin = "0";
40
+ pre.style.whiteSpace = "pre-wrap";
41
+ pre.style.wordBreak = "break-word";
42
+ const button = document.createElement("button");
43
+ button.type = "button";
44
+ button.textContent = "Try again";
45
+ button.addEventListener("click", () => reset());
46
+ details.append(detailsSummary, pre);
47
+ wrapper.append(title, summary, details, button);
48
+ return wrapper;
49
+ }
50
+ function resolveErrorBoundaryFallback(fallback, error, reset) {
51
+ if (typeof fallback === "function") return fallback(error, reset);
52
+ return fallback ?? createDefaultFallbackNode(error, reset);
53
+ }
5
54
  function createErrorBoundaryElement(node, props, parentNamespace) {
6
55
  const boundaryState = node.__instance?.errorBoundaryState ?? null;
7
56
  const reset = node.__instance ? createBoundaryReset(node.__instance) : () => {};
@@ -1 +1 @@
1
- {"version":3,"file":"error-boundary-dom.js","names":[],"sources":["../../src/renderer/error-boundary-dom.ts"],"sourcesContent":["import { logger } from '../dev/logger';\nimport {\n createBoundaryReset,\n reportBoundaryError,\n resolveErrorBoundaryFallback,\n type ErrorBoundaryProps,\n} from '../components/error-boundary';\nimport type { ComponentInstance } from '../runtime/component-contracts';\nimport { getRendererDOMHost } from './dom-host';\nimport type { DOMElement } from './types';\n\nexport type ErrorBoundaryVNode = DOMElement & {\n __instance?: ComponentInstance;\n};\n\nexport function createErrorBoundaryElement(\n node: ErrorBoundaryVNode,\n props: Record<string, unknown>,\n parentNamespace?: string\n): Node {\n const boundaryState = node.__instance?.errorBoundaryState ?? null;\n const reset = node.__instance\n ? createBoundaryReset(node.__instance)\n : () => {};\n const fallback = props.fallback as ErrorBoundaryProps['fallback'];\n const children = props.children as ErrorBoundaryProps['children'];\n const domHost = getRendererDOMHost();\n\n if (boundaryState?.error != null) {\n const fallbackValue = resolveErrorBoundaryFallback(\n fallback,\n boundaryState.error,\n reset\n );\n if (fallbackValue instanceof Node) {\n return fallbackValue;\n }\n const fallbackDom = domHost.createDOMNode(fallbackValue, parentNamespace);\n return fallbackDom ?? document.createComment('');\n }\n\n try {\n const dom = domHost.createDOMNode(children, parentNamespace);\n return dom ?? document.createComment('');\n } catch (error) {\n if (node.__instance) {\n reportBoundaryError(\n node.__instance,\n error,\n props.onError as ((next: unknown) => void) | undefined\n );\n } else {\n logger.error('[Askr] ErrorBoundary caught render error:', error);\n }\n\n const fallbackValue = resolveErrorBoundaryFallback(fallback, error, reset);\n if (fallbackValue instanceof Node) {\n return fallbackValue;\n }\n const fallbackDom = domHost.createDOMNode(fallbackValue, parentNamespace);\n return fallbackDom ?? document.createComment('');\n }\n}\n"],"mappings":";;;;AAeA,SAAgB,2BACd,MACA,OACA,iBACM;CACN,MAAM,gBAAgB,KAAK,YAAY,sBAAsB;CAC7D,MAAM,QAAQ,KAAK,aACf,oBAAoB,KAAK,UAAU,UAC7B,CAAC;CACX,MAAM,WAAW,MAAM;CACvB,MAAM,WAAW,MAAM;CACvB,MAAM,UAAU,mBAAmB;CAEnC,IAAI,eAAe,SAAS,MAAM;EAChC,MAAM,gBAAgB,6BACpB,UACA,cAAc,OACd,KACF;EACA,IAAI,yBAAyB,MAC3B,OAAO;EAGT,OADoB,QAAQ,cAAc,eAAe,eAClD,KAAe,SAAS,cAAc,EAAE;CACjD;CAEA,IAAI;EAEF,OADY,QAAQ,cAAc,UAAU,eACrC,KAAO,SAAS,cAAc,EAAE;CACzC,SAAS,OAAO;EACd,IAAI,KAAK,YACP,oBACE,KAAK,YACL,OACA,MAAM,OACR;OAEA,OAAO,MAAM,6CAA6C,KAAK;EAGjE,MAAM,gBAAgB,6BAA6B,UAAU,OAAO,KAAK;EACzE,IAAI,yBAAyB,MAC3B,OAAO;EAGT,OADoB,QAAQ,cAAc,eAAe,eAClD,KAAe,SAAS,cAAc,EAAE;CACjD;AACF"}
1
+ {"version":3,"file":"error-boundary-dom.js","names":[],"sources":["../../src/renderer/error-boundary-dom.ts"],"sourcesContent":["import {\n type ErrorBoundaryFallbackValue,\n type ErrorBoundaryProps,\n} from '../common/error-boundary';\nimport { isDevelopmentEnvironment } from '../common/env';\nimport { logger } from '../common/logger';\nimport { createBoundaryReset, reportBoundaryError } from '../runtime';\nimport type { ComponentInstance } from '../runtime';\nimport { getRendererDOMHost } from './dom-host';\nimport type { DOMElement } from './types';\n\nexport type ErrorBoundaryVNode = DOMElement & {\n __instance?: ComponentInstance;\n};\n\nfunction getBoundaryMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message || error.name || 'Unknown error';\n }\n\n if (typeof error === 'string') {\n return error;\n }\n\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n}\n\nfunction createDefaultFallbackNode(error: unknown, reset: () => void): Node {\n const message = getBoundaryMessage(error);\n const wrapper = document.createElement('div');\n wrapper.setAttribute('role', 'alert');\n wrapper.setAttribute('data-askr-error-boundary', 'true');\n wrapper.style.boxSizing = 'border-box';\n wrapper.style.padding = '1rem';\n wrapper.style.border = '1px solid currentColor';\n wrapper.style.borderRadius = '0.75rem';\n wrapper.style.display = 'grid';\n wrapper.style.gap = '0.75rem';\n wrapper.style.maxWidth = '100%';\n\n const title = document.createElement('strong');\n title.textContent = 'Something went wrong while rendering this view.';\n\n const summary = document.createElement('p');\n summary.textContent =\n 'The app recovered into a visible fallback so the error is not hidden in the console.';\n summary.style.margin = '0';\n\n const details = document.createElement('details');\n details.open = isDevelopmentEnvironment();\n\n const detailsSummary = document.createElement('summary');\n detailsSummary.textContent = 'Error details';\n\n const pre = document.createElement('pre');\n pre.textContent = message;\n pre.style.margin = '0';\n pre.style.whiteSpace = 'pre-wrap';\n pre.style.wordBreak = 'break-word';\n\n const button = document.createElement('button');\n button.type = 'button';\n button.textContent = 'Try again';\n button.addEventListener('click', () => reset());\n\n details.append(detailsSummary, pre);\n wrapper.append(title, summary, details, button);\n return wrapper;\n}\n\nfunction resolveErrorBoundaryFallback(\n fallback: ErrorBoundaryProps['fallback'],\n error: unknown,\n reset: () => void\n): ErrorBoundaryFallbackValue {\n if (typeof fallback === 'function') {\n return fallback(error, reset);\n }\n\n return fallback ?? createDefaultFallbackNode(error, reset);\n}\n\nexport function createErrorBoundaryElement(\n node: ErrorBoundaryVNode,\n props: Record<string, unknown>,\n parentNamespace?: string\n): Node {\n const boundaryState = node.__instance?.errorBoundaryState ?? null;\n const reset = node.__instance\n ? createBoundaryReset(node.__instance)\n : () => {};\n const fallback = props.fallback as ErrorBoundaryProps['fallback'];\n const children = props.children as ErrorBoundaryProps['children'];\n const domHost = getRendererDOMHost();\n\n if (boundaryState?.error != null) {\n const fallbackValue = resolveErrorBoundaryFallback(\n fallback,\n boundaryState.error,\n reset\n );\n if (fallbackValue instanceof Node) {\n return fallbackValue;\n }\n const fallbackDom = domHost.createDOMNode(fallbackValue, parentNamespace);\n return fallbackDom ?? document.createComment('');\n }\n\n try {\n const dom = domHost.createDOMNode(children, parentNamespace);\n return dom ?? document.createComment('');\n } catch (error) {\n if (node.__instance) {\n reportBoundaryError(\n node.__instance,\n error,\n props.onError as ((next: unknown) => void) | undefined\n );\n } else {\n logger.error('[Askr] ErrorBoundary caught render error:', error);\n }\n\n const fallbackValue = resolveErrorBoundaryFallback(fallback, error, reset);\n if (fallbackValue instanceof Node) {\n return fallbackValue;\n }\n const fallbackDom = domHost.createDOMNode(fallbackValue, parentNamespace);\n return fallbackDom ?? document.createComment('');\n }\n}\n"],"mappings":";;;;;;AAeA,SAAS,mBAAmB,OAAwB;CAClD,IAAI,iBAAiB,OACnB,OAAO,MAAM,WAAW,MAAM,QAAQ;CAGxC,IAAI,OAAO,UAAU,UACnB,OAAO;CAGT,IAAI;EACF,OAAO,KAAK,UAAU,KAAK;CAC7B,QAAQ;EACN,OAAO,OAAO,KAAK;CACrB;AACF;AAEA,SAAS,0BAA0B,OAAgB,OAAyB;CAC1E,MAAM,UAAU,mBAAmB,KAAK;CACxC,MAAM,UAAU,SAAS,cAAc,KAAK;CAC5C,QAAQ,aAAa,QAAQ,OAAO;CACpC,QAAQ,aAAa,4BAA4B,MAAM;CACvD,QAAQ,MAAM,YAAY;CAC1B,QAAQ,MAAM,UAAU;CACxB,QAAQ,MAAM,SAAS;CACvB,QAAQ,MAAM,eAAe;CAC7B,QAAQ,MAAM,UAAU;CACxB,QAAQ,MAAM,MAAM;CACpB,QAAQ,MAAM,WAAW;CAEzB,MAAM,QAAQ,SAAS,cAAc,QAAQ;CAC7C,MAAM,cAAc;CAEpB,MAAM,UAAU,SAAS,cAAc,GAAG;CAC1C,QAAQ,cACN;CACF,QAAQ,MAAM,SAAS;CAEvB,MAAM,UAAU,SAAS,cAAc,SAAS;CAChD,QAAQ,OAAO,yBAAyB;CAExC,MAAM,iBAAiB,SAAS,cAAc,SAAS;CACvD,eAAe,cAAc;CAE7B,MAAM,MAAM,SAAS,cAAc,KAAK;CACxC,IAAI,cAAc;CAClB,IAAI,MAAM,SAAS;CACnB,IAAI,MAAM,aAAa;CACvB,IAAI,MAAM,YAAY;CAEtB,MAAM,SAAS,SAAS,cAAc,QAAQ;CAC9C,OAAO,OAAO;CACd,OAAO,cAAc;CACrB,OAAO,iBAAiB,eAAe,MAAM,CAAC;CAE9C,QAAQ,OAAO,gBAAgB,GAAG;CAClC,QAAQ,OAAO,OAAO,SAAS,SAAS,MAAM;CAC9C,OAAO;AACT;AAEA,SAAS,6BACP,UACA,OACA,OAC4B;CAC5B,IAAI,OAAO,aAAa,YACtB,OAAO,SAAS,OAAO,KAAK;CAG9B,OAAO,YAAY,0BAA0B,OAAO,KAAK;AAC3D;AAEA,SAAgB,2BACd,MACA,OACA,iBACM;CACN,MAAM,gBAAgB,KAAK,YAAY,sBAAsB;CAC7D,MAAM,QAAQ,KAAK,aACf,oBAAoB,KAAK,UAAU,UAC7B,CAAC;CACX,MAAM,WAAW,MAAM;CACvB,MAAM,WAAW,MAAM;CACvB,MAAM,UAAU,mBAAmB;CAEnC,IAAI,eAAe,SAAS,MAAM;EAChC,MAAM,gBAAgB,6BACpB,UACA,cAAc,OACd,KACF;EACA,IAAI,yBAAyB,MAC3B,OAAO;EAGT,OADoB,QAAQ,cAAc,eAAe,eAClD,KAAe,SAAS,cAAc,EAAE;CACjD;CAEA,IAAI;EAEF,OADY,QAAQ,cAAc,UAAU,eACrC,KAAO,SAAS,cAAc,EAAE;CACzC,SAAS,OAAO;EACd,IAAI,KAAK,YACP,oBACE,KAAK,YACL,OACA,MAAM,OACR;OAEA,OAAO,MAAM,6CAA6C,KAAK;EAGjE,MAAM,gBAAgB,6BAA6B,UAAU,OAAO,KAAK;EACzE,IAAI,yBAAyB,MAC3B,OAAO;EAGT,OADoB,QAAQ,cAAc,eAAe,eAClD,KAAe,SAAS,cAAc,EAAE;CACjD;AACF"}
@@ -1,19 +1,20 @@
1
1
  import { __FOR_BOUNDARY__, _isDOMElement } from "../common/vnode.js";
2
2
  import "./types.js";
3
3
  import { getRuntimeEnv } from "../common/env.js";
4
- import { logger } from "../dev/logger.js";
4
+ import { logger } from "../common/logger.js";
5
5
  import { Fragment } from "../common/jsx.js";
6
6
  import { incDevCounter, setDevValue } from "../runtime/dev-namespace.js";
7
+ import { evaluateCaseState, evaluateShowState } from "../runtime/control.js";
8
+ import { evaluateForState } from "../runtime/for-internal.js";
9
+ import "../runtime/index.js";
7
10
  import { elementListeners } from "./cleanup.js";
8
11
  import "./env.js";
9
12
  import { createWrappedHandler, extractKey, getEventListenerKey, getEventListenerOptions, parseEventProp, setRenderedAttribute, tagNamesEqualIgnoreCase as tagNamesEqualIgnoreCase$1, writeElementClassName } from "./utils.js";
10
13
  import { keyedElements } from "./keyed.js";
11
- import { evaluateForState } from "../runtime/for-internal.js";
12
- import "../runtime/for.js";
13
- import { evaluateCaseState, evaluateShowState } from "../runtime/control.js";
14
14
  import { createElementForNamespace, getParentNamespace } from "./namespaces.js";
15
15
  import { commitForBoundaryChildren } from "./boundaries.js";
16
- import { isBulkTextFastPathEligible, performBulkPositionalKeyedTextUpdate, performBulkTextReplace } from "./children.js";
16
+ import { performBulkPositionalKeyedTextUpdate } from "./children-fastpath.js";
17
+ import { isBulkTextFastPathEligible, performBulkTextReplace } from "./children.js";
17
18
  import { getRendererDOMHost } from "./dom-host.js";
18
19
  import { reconcileKeyedChildren } from "./reconcile.js";
19
20
  import { updateUnkeyedChildren } from "./element-children.js";
@@ -1 +1 @@
1
- {"version":3,"file":"evaluate-reconcile.js","names":["sharedTagNamesEqualIgnoreCase"],"sources":["../../src/renderer/evaluate-reconcile.ts"],"sourcesContent":["import { logger } from '../dev/logger';\nimport { getRuntimeEnv } from './env';\nimport type { Props } from '../common/props';\nimport type { ComponentInstance } from '../runtime/component-contracts';\nimport { elementListeners } from './cleanup';\nimport { keyedElements } from './keyed';\nimport { createElementForNamespace, getParentNamespace } from './namespaces';\nimport { reconcileKeyedChildren } from './reconcile';\nimport { _isDOMElement, type DOMElement, type VNode } from './types';\nimport { __FOR_BOUNDARY__ } from '../common/vnode';\nimport { evaluateForState } from '../runtime/for';\nimport {\n evaluateCaseState,\n evaluateShowState,\n type ControlBoundaryState,\n} from '../runtime/control';\nimport { commitForBoundaryChildren } from './boundaries';\nimport {\n isBulkTextFastPathEligible,\n performBulkPositionalKeyedTextUpdate,\n performBulkTextReplace,\n} from './children';\nimport { getRendererDOMHost } from './dom-host';\nimport { updateUnkeyedChildren } from './element-children';\nimport { setDevValue, incDevCounter } from '../runtime/dev-namespace';\nimport { Fragment } from '../common/jsx';\nimport {\n createWrappedHandler,\n extractKey,\n getEventListenerKey,\n getEventListenerOptions,\n parseEventProp,\n setRenderedAttribute,\n tagNamesEqualIgnoreCase as sharedTagNamesEqualIgnoreCase,\n writeElementClassName,\n} from './utils';\nimport { runRetainedElementUpdate } from './retained-element-rollback';\n\ntype ComponentHostElement = Element & {\n __ASKR_INSTANCE?: ComponentInstance;\n __ASKR_INSTANCES?: ComponentInstance[];\n};\n\nexport function getRetainedHostOwnerChain(\n host: ComponentHostElement,\n owner: ComponentInstance\n): ComponentInstance[] {\n const instances = host.__ASKR_INSTANCES ?? [];\n const ownerIndex = instances.indexOf(owner);\n\n return ownerIndex >= 0 ? instances.slice(ownerIndex) : [owner];\n}\n\nexport function retainHostOwnerChain(\n host: Element,\n owner: ComponentInstance,\n retainedInstances: ComponentInstance[]\n): void {\n const componentHost = host as ComponentHostElement;\n const existing = componentHost.__ASKR_INSTANCES ?? [];\n const nextInstances = [...existing];\n\n for (const instance of retainedInstances) {\n if (!nextInstances.includes(instance)) {\n nextInstances.push(instance);\n }\n }\n\n componentHost.__ASKR_INSTANCES = nextInstances;\n componentHost.__ASKR_INSTANCE = owner;\n}\n\ninterface SimpleTextResult {\n isSimple: true;\n text: string;\n}\n\ninterface NotSimpleTextResult {\n isSimple: false;\n text?: undefined;\n}\n\ntype TextCheckResult = SimpleTextResult | NotSimpleTextResult;\n\nexport function tagNamesEqualIgnoreCase(a: string, b: string): boolean {\n return sharedTagNamesEqualIgnoreCase(a, b);\n}\n\nfunction checkSimpleText(vnodeChildren: unknown): TextCheckResult {\n if (!Array.isArray(vnodeChildren)) {\n if (\n typeof vnodeChildren === 'string' ||\n typeof vnodeChildren === 'number'\n ) {\n return { isSimple: true, text: String(vnodeChildren) };\n }\n } else if (vnodeChildren.length === 1) {\n const child = vnodeChildren[0];\n if (typeof child === 'string' || typeof child === 'number') {\n return { isSimple: true, text: String(child) };\n }\n }\n return { isSimple: false };\n}\n\nfunction tryUpdateTextInPlace(element: Element, text: string): boolean {\n if (element.childNodes.length === 1 && element.firstChild?.nodeType === 3) {\n (element.firstChild as Text).data = text;\n return true;\n }\n return false;\n}\n\nfunction buildKeyMapFromDOM(parent: Element): Map<string | number, Element> {\n const keyMap = new Map<string | number, Element>();\n for (\n let child = parent.firstElementChild;\n child;\n child = child.nextElementSibling\n ) {\n const k = child.getAttribute('data-key');\n if (k !== null) {\n keyMap.set(k, child);\n const n = Number(k);\n if (!Number.isNaN(n)) keyMap.set(n, child);\n }\n }\n return keyMap;\n}\n\nfunction getOrBuildKeyMap(\n parent: Element\n): Map<string | number, Element> | undefined {\n let keyMap = keyedElements.get(parent);\n if (!keyMap) {\n keyMap = buildKeyMapFromDOM(parent);\n if (keyMap.size > 0) {\n keyedElements.set(parent, keyMap);\n }\n }\n return keyMap.size > 0 ? keyMap : undefined;\n}\n\nfunction hasKeyedChildren(children: unknown[]): boolean {\n for (let i = 0; i < children.length; i++) {\n if (extractKey(children[i]) !== undefined) return true;\n }\n return false;\n}\n\nfunction trackBulkTextStats(\n stats: ReturnType<typeof performBulkTextReplace>\n): void {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n try {\n setDevValue('__LAST_BULK_TEXT_FASTPATH_STATS', stats);\n incDevCounter('bulkTextHits');\n } catch {\n // ignore\n }\n }\n}\n\nfunction trackBulkTextMiss(): void {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n try {\n incDevCounter('bulkTextMisses');\n } catch {\n // ignore\n }\n }\n}\n\nfunction reconcileKeyed(\n parent: Element,\n children: VNode[],\n oldKeyMap: Map<string | number, Element> | undefined\n): void {\n if (getRuntimeEnv().ASKR_FORCE_BULK_POSREUSE === '1') {\n const result = tryForcedBulkKeyedPath(parent, children);\n if (result) return;\n }\n\n const newKeyMap = reconcileKeyedChildren(parent, children, oldKeyMap);\n keyedElements.set(parent, newKeyMap);\n}\n\nfunction tryForcedBulkKeyedPath(parent: Element, children: VNode[]): boolean {\n try {\n const keyedVnodes: Array<{ key: string | number; vnode: VNode }> = [];\n for (const child of children) {\n const key = extractKey(child);\n if (_isDOMElement(child) && key !== undefined) {\n keyedVnodes.push({\n key,\n vnode: child,\n });\n }\n }\n\n if (keyedVnodes.length === 0 || keyedVnodes.length !== children.length) {\n return false;\n }\n\n const fastPathEnv = getRuntimeEnv();\n if (\n fastPathEnv.ASKR_FASTPATH_DEBUG === '1' ||\n fastPathEnv.ASKR_FASTPATH_DEBUG === 'true'\n ) {\n logger.warn(\n '[Askr][FASTPATH] forced positional bulk keyed reuse (evaluate-level)'\n );\n }\n\n const stats = performBulkPositionalKeyedTextUpdate(parent, keyedVnodes);\n\n const statsEnv = getRuntimeEnv();\n if (\n statsEnv.NODE_ENV !== 'production' ||\n statsEnv.ASKR_FASTPATH_DEBUG === '1'\n ) {\n try {\n setDevValue('__LAST_FASTPATH_STATS', stats);\n setDevValue('__LAST_FASTPATH_COMMIT_COUNT', 1);\n incDevCounter('bulkKeyedPositionalForced');\n } catch {\n // ignore\n }\n }\n\n const newMap = buildKeyMapFromDOM(parent);\n keyedElements.set(parent, newMap);\n return true;\n } catch (err) {\n const fallbackEnv = getRuntimeEnv();\n if (\n fallbackEnv.ASKR_FASTPATH_DEBUG === '1' ||\n fallbackEnv.ASKR_FASTPATH_DEBUG === 'true'\n ) {\n logger.warn(\n '[Askr][FASTPATH] forced bulk path failed, falling back',\n err\n );\n }\n return false;\n }\n}\n\nfunction reconcileUnkeyed(parent: Element, children: VNode[]): void {\n if (isBulkTextFastPathEligible(parent, children)) {\n const stats = performBulkTextReplace(parent, children);\n trackBulkTextStats(stats);\n } else {\n trackBulkTextMiss();\n updateUnkeyedChildren(parent, children);\n }\n keyedElements.delete(parent);\n}\n\nexport function updateForBoundaryChildren(\n element: Element,\n forVnode: DOMElement\n): void {\n const controlState =\n forVnode._controlState ??\n (forVnode._forState as ControlBoundaryState | undefined);\n if (!controlState) return;\n\n const childrenVNodes =\n controlState.kind === 'for'\n ? evaluateForState(controlState)\n : controlState.kind === 'show'\n ? evaluateShowState(controlState)\n : evaluateCaseState(controlState);\n commitForBoundaryChildren(element, controlState, childrenVNodes);\n}\n\nexport function updateElementChildren(\n element: Element,\n vnodeChildren: unknown,\n cleanupRangeNode: (node: Node) => void\n): void {\n const domHost = getRendererDOMHost();\n\n if (vnodeChildren === null || vnodeChildren === undefined) {\n for (let n = element.firstChild; n; ) {\n const next = n.nextSibling;\n cleanupRangeNode(n);\n n = next;\n }\n element.textContent = '';\n keyedElements.delete(element);\n return;\n }\n\n if (\n !Array.isArray(vnodeChildren) &&\n _isDOMElement(vnodeChildren) &&\n (vnodeChildren as DOMElement).type === __FOR_BOUNDARY__\n ) {\n updateForBoundaryChildren(element, vnodeChildren as DOMElement);\n return;\n }\n\n if (!Array.isArray(vnodeChildren) && isFragment(vnodeChildren)) {\n updateElementChildren(\n element,\n getFragmentChildren(vnodeChildren),\n cleanupRangeNode\n );\n return;\n }\n\n if (!Array.isArray(vnodeChildren)) {\n for (let n = element.firstChild; n; ) {\n const next = n.nextSibling;\n cleanupRangeNode(n);\n n = next;\n }\n element.textContent = '';\n const dom = domHost.createDOMNode(vnodeChildren);\n if (dom) element.appendChild(dom);\n keyedElements.delete(element);\n return;\n }\n\n if (\n vnodeChildren.length === 1 &&\n _isDOMElement(vnodeChildren[0]) &&\n (vnodeChildren[0] as DOMElement).type === __FOR_BOUNDARY__\n ) {\n updateForBoundaryChildren(element, vnodeChildren[0] as DOMElement);\n return;\n }\n\n if (hasKeyedChildren(vnodeChildren)) {\n const oldKeyMap = getOrBuildKeyMap(element);\n try {\n reconcileKeyed(element, vnodeChildren, oldKeyMap);\n } catch {\n const newKeyMap = reconcileKeyedChildren(\n element,\n vnodeChildren,\n oldKeyMap\n );\n keyedElements.set(element, newKeyMap);\n }\n } else {\n reconcileUnkeyed(element, vnodeChildren);\n }\n}\n\nexport function smartUpdateElement(\n element: Element,\n vnode: DOMElement,\n cleanupRangeNode: (node: Node) => void\n): void {\n const hadVNodeKey = Object.prototype.hasOwnProperty.call(vnode, 'key');\n const previousVNodeKey = vnode.key;\n\n runRetainedElementUpdate(\n element,\n cleanupRangeNode,\n () => applySmartUpdateElement(element, vnode, cleanupRangeNode),\n () => {\n if (hadVNodeKey) vnode.key = previousVNodeKey;\n else delete vnode.key;\n }\n );\n}\n\nfunction applySmartUpdateElement(\n element: Element,\n vnode: DOMElement,\n cleanupRangeNode: (node: Node) => void\n): void {\n const domHost = getRendererDOMHost();\n\n if (vnode.key == null && element.hasAttribute('data-key')) {\n const existingKey = element.getAttribute('data-key');\n if (existingKey !== null) {\n const numericKey = Number(existingKey);\n vnode.key = Number.isNaN(numericKey) ? existingKey : numericKey;\n }\n }\n\n let vnodeChildren = vnode.props?.children ?? vnode.children;\n\n if (\n vnodeChildren &&\n _isDOMElement(vnodeChildren) &&\n (vnodeChildren as DOMElement).type === __FOR_BOUNDARY__\n ) {\n updateElementChildren(element, vnodeChildren, cleanupRangeNode);\n domHost.updateElementFromVnode(element, vnode, false);\n return;\n }\n\n if (vnodeChildren && !Array.isArray(vnodeChildren)) {\n vnodeChildren = [vnodeChildren];\n }\n\n const textCheck = checkSimpleText(vnodeChildren);\n\n if (textCheck.isSimple && tryUpdateTextInPlace(element, textCheck.text)) {\n // Text updated in place.\n } else {\n updateElementChildren(element, vnodeChildren, cleanupRangeNode);\n }\n\n domHost.updateElementFromVnode(element, vnode, false);\n}\n\nexport function processFragmentChildren(\n target: Element,\n childArray: unknown[],\n cleanupRangeNode: (node: Node) => void\n): void {\n updateElementChildren(target, childArray, cleanupRangeNode);\n}\n\nfunction applyPropsToElement(el: Element, props: Props): void {\n for (const [key, value] of Object.entries(props)) {\n if (key === 'children' || key === 'key') continue;\n if (value === undefined || value === null || value === false) continue;\n\n if (key === 'ref') {\n applyRef(el, value);\n continue;\n }\n\n const eventProp = parseEventProp(key);\n if (eventProp) {\n const { eventName, capture } = eventProp;\n const wrappedHandler = createWrappedHandler(value as EventListener, true);\n const options = getEventListenerOptions(eventName, capture);\n const listenerKey = getEventListenerKey(eventName, capture);\n\n if (options !== undefined)\n el.addEventListener(eventName, wrappedHandler, options);\n else el.addEventListener(eventName, wrappedHandler);\n\n if (!elementListeners.has(el)) elementListeners.set(el, new Map());\n elementListeners.get(el)!.set(listenerKey, {\n handler: wrappedHandler,\n original: value as EventListener,\n eventName,\n options,\n });\n continue;\n }\n\n if (key === 'class' || key === 'className') {\n writeElementClassName(el, String(value));\n } else if (key === 'value' || key === 'checked') {\n (el as HTMLElement & Props)[key] = value;\n } else {\n setRenderedAttribute(el, key, String(value));\n }\n }\n}\n\ntype Ref<T> =\n | ((value: T | null) => void)\n | { current: T | null }\n | null\n | undefined;\n\nfunction applyRef<T>(el: T, ref: unknown): void {\n const r = ref as Ref<T>;\n if (!r) return;\n if (typeof r === 'function') {\n r(el);\n return;\n }\n try {\n (r as { current: T | null }).current = el;\n } catch {\n // Ignore write failures.\n }\n}\n\nexport function tryFirstRenderKeyedChildren(\n target: Element,\n vnode: DOMElement\n): boolean {\n const children = vnode.children;\n if (!Array.isArray(children) || !hasKeyedChildren(children)) {\n return false;\n }\n\n const el = createElementForNamespace(\n vnode.type as string,\n getParentNamespace(target)\n );\n target.appendChild(el);\n\n applyPropsToElement(el, vnode.props || {});\n\n const newKeyMap = reconcileKeyedChildren(el, children, undefined);\n keyedElements.set(el, newKeyMap);\n return true;\n}\n\nexport function isFragment(vnode: unknown): vnode is DOMElement {\n return (\n _isDOMElement(vnode) &&\n typeof (vnode as DOMElement).type === 'symbol' &&\n ((vnode as DOMElement).type === Fragment ||\n String((vnode as DOMElement).type) === 'Symbol(askr.fragment)')\n );\n}\n\nexport function getFragmentChildren(vnode: DOMElement): unknown[] {\n const fragmentChildren = vnode.props?.children ?? vnode.children ?? [];\n return Array.isArray(fragmentChildren)\n ? fragmentChildren\n : [fragmentChildren];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"evaluate-reconcile.js","names":["sharedTagNamesEqualIgnoreCase"],"sources":["../../src/renderer/evaluate-reconcile.ts"],"sourcesContent":["import { logger } from '../common/logger';\nimport { getRuntimeEnv } from './env';\nimport type { Props } from '../common/props';\nimport type { ComponentInstance } from '../runtime';\nimport { elementListeners } from './cleanup';\nimport { keyedElements } from './keyed';\nimport { createElementForNamespace, getParentNamespace } from './namespaces';\nimport { reconcileKeyedChildren } from './reconcile';\nimport { _isDOMElement, type DOMElement, type VNode } from './types';\nimport { __FOR_BOUNDARY__ } from '../common/vnode';\nimport { evaluateForState } from '../runtime';\nimport {\n evaluateCaseState,\n evaluateShowState,\n type ControlBoundaryState,\n} from '../runtime';\nimport { commitForBoundaryChildren } from './boundaries';\nimport {\n isBulkTextFastPathEligible,\n performBulkPositionalKeyedTextUpdate,\n performBulkTextReplace,\n} from './children';\nimport { getRendererDOMHost } from './dom-host';\nimport { updateUnkeyedChildren } from './element-children';\nimport { setDevValue, incDevCounter } from '../runtime';\nimport { Fragment } from '../common/jsx';\nimport {\n createWrappedHandler,\n extractKey,\n getEventListenerKey,\n getEventListenerOptions,\n parseEventProp,\n setRenderedAttribute,\n tagNamesEqualIgnoreCase as sharedTagNamesEqualIgnoreCase,\n writeElementClassName,\n} from './utils';\nimport { runRetainedElementUpdate } from './retained-element-rollback';\n\ntype ComponentHostElement = Element & {\n __ASKR_INSTANCE?: ComponentInstance;\n __ASKR_INSTANCES?: ComponentInstance[];\n};\n\nexport function getRetainedHostOwnerChain(\n host: ComponentHostElement,\n owner: ComponentInstance\n): ComponentInstance[] {\n const instances = host.__ASKR_INSTANCES ?? [];\n const ownerIndex = instances.indexOf(owner);\n\n return ownerIndex >= 0 ? instances.slice(ownerIndex) : [owner];\n}\n\nexport function retainHostOwnerChain(\n host: Element,\n owner: ComponentInstance,\n retainedInstances: ComponentInstance[]\n): void {\n const componentHost = host as ComponentHostElement;\n const existing = componentHost.__ASKR_INSTANCES ?? [];\n const nextInstances = [...existing];\n\n for (const instance of retainedInstances) {\n if (!nextInstances.includes(instance)) {\n nextInstances.push(instance);\n }\n }\n\n componentHost.__ASKR_INSTANCES = nextInstances;\n componentHost.__ASKR_INSTANCE = owner;\n}\n\ninterface SimpleTextResult {\n isSimple: true;\n text: string;\n}\n\ninterface NotSimpleTextResult {\n isSimple: false;\n text?: undefined;\n}\n\ntype TextCheckResult = SimpleTextResult | NotSimpleTextResult;\n\nexport function tagNamesEqualIgnoreCase(a: string, b: string): boolean {\n return sharedTagNamesEqualIgnoreCase(a, b);\n}\n\nfunction checkSimpleText(vnodeChildren: unknown): TextCheckResult {\n if (!Array.isArray(vnodeChildren)) {\n if (\n typeof vnodeChildren === 'string' ||\n typeof vnodeChildren === 'number'\n ) {\n return { isSimple: true, text: String(vnodeChildren) };\n }\n } else if (vnodeChildren.length === 1) {\n const child = vnodeChildren[0];\n if (typeof child === 'string' || typeof child === 'number') {\n return { isSimple: true, text: String(child) };\n }\n }\n return { isSimple: false };\n}\n\nfunction tryUpdateTextInPlace(element: Element, text: string): boolean {\n if (element.childNodes.length === 1 && element.firstChild?.nodeType === 3) {\n (element.firstChild as Text).data = text;\n return true;\n }\n return false;\n}\n\nfunction buildKeyMapFromDOM(parent: Element): Map<string | number, Element> {\n const keyMap = new Map<string | number, Element>();\n for (\n let child = parent.firstElementChild;\n child;\n child = child.nextElementSibling\n ) {\n const k = child.getAttribute('data-key');\n if (k !== null) {\n keyMap.set(k, child);\n const n = Number(k);\n if (!Number.isNaN(n)) keyMap.set(n, child);\n }\n }\n return keyMap;\n}\n\nfunction getOrBuildKeyMap(\n parent: Element\n): Map<string | number, Element> | undefined {\n let keyMap = keyedElements.get(parent);\n if (!keyMap) {\n keyMap = buildKeyMapFromDOM(parent);\n if (keyMap.size > 0) {\n keyedElements.set(parent, keyMap);\n }\n }\n return keyMap.size > 0 ? keyMap : undefined;\n}\n\nfunction hasKeyedChildren(children: unknown[]): boolean {\n for (let i = 0; i < children.length; i++) {\n if (extractKey(children[i]) !== undefined) return true;\n }\n return false;\n}\n\nfunction trackBulkTextStats(\n stats: ReturnType<typeof performBulkTextReplace>\n): void {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n try {\n setDevValue('__LAST_BULK_TEXT_FASTPATH_STATS', stats);\n incDevCounter('bulkTextHits');\n } catch {\n // ignore\n }\n }\n}\n\nfunction trackBulkTextMiss(): void {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n try {\n incDevCounter('bulkTextMisses');\n } catch {\n // ignore\n }\n }\n}\n\nfunction reconcileKeyed(\n parent: Element,\n children: VNode[],\n oldKeyMap: Map<string | number, Element> | undefined\n): void {\n if (getRuntimeEnv().ASKR_FORCE_BULK_POSREUSE === '1') {\n const result = tryForcedBulkKeyedPath(parent, children);\n if (result) return;\n }\n\n const newKeyMap = reconcileKeyedChildren(parent, children, oldKeyMap);\n keyedElements.set(parent, newKeyMap);\n}\n\nfunction tryForcedBulkKeyedPath(parent: Element, children: VNode[]): boolean {\n try {\n const keyedVnodes: Array<{ key: string | number; vnode: VNode }> = [];\n for (const child of children) {\n const key = extractKey(child);\n if (_isDOMElement(child) && key !== undefined) {\n keyedVnodes.push({\n key,\n vnode: child,\n });\n }\n }\n\n if (keyedVnodes.length === 0 || keyedVnodes.length !== children.length) {\n return false;\n }\n\n const fastPathEnv = getRuntimeEnv();\n if (\n fastPathEnv.ASKR_FASTPATH_DEBUG === '1' ||\n fastPathEnv.ASKR_FASTPATH_DEBUG === 'true'\n ) {\n logger.warn(\n '[Askr][FASTPATH] forced positional bulk keyed reuse (evaluate-level)'\n );\n }\n\n const stats = performBulkPositionalKeyedTextUpdate(parent, keyedVnodes);\n\n const statsEnv = getRuntimeEnv();\n if (\n statsEnv.NODE_ENV !== 'production' ||\n statsEnv.ASKR_FASTPATH_DEBUG === '1'\n ) {\n try {\n setDevValue('__LAST_FASTPATH_STATS', stats);\n setDevValue('__LAST_FASTPATH_COMMIT_COUNT', 1);\n incDevCounter('bulkKeyedPositionalForced');\n } catch {\n // ignore\n }\n }\n\n const newMap = buildKeyMapFromDOM(parent);\n keyedElements.set(parent, newMap);\n return true;\n } catch (err) {\n const fallbackEnv = getRuntimeEnv();\n if (\n fallbackEnv.ASKR_FASTPATH_DEBUG === '1' ||\n fallbackEnv.ASKR_FASTPATH_DEBUG === 'true'\n ) {\n logger.warn(\n '[Askr][FASTPATH] forced bulk path failed, falling back',\n err\n );\n }\n return false;\n }\n}\n\nfunction reconcileUnkeyed(parent: Element, children: VNode[]): void {\n if (isBulkTextFastPathEligible(parent, children)) {\n const stats = performBulkTextReplace(parent, children);\n trackBulkTextStats(stats);\n } else {\n trackBulkTextMiss();\n updateUnkeyedChildren(parent, children);\n }\n keyedElements.delete(parent);\n}\n\nexport function updateForBoundaryChildren(\n element: Element,\n forVnode: DOMElement\n): void {\n const controlState =\n forVnode._controlState ??\n (forVnode._forState as ControlBoundaryState | undefined);\n if (!controlState) return;\n\n const childrenVNodes =\n controlState.kind === 'for'\n ? evaluateForState(controlState)\n : controlState.kind === 'show'\n ? evaluateShowState(controlState)\n : evaluateCaseState(controlState);\n commitForBoundaryChildren(element, controlState, childrenVNodes);\n}\n\nexport function updateElementChildren(\n element: Element,\n vnodeChildren: unknown,\n cleanupRangeNode: (node: Node) => void\n): void {\n const domHost = getRendererDOMHost();\n\n if (vnodeChildren === null || vnodeChildren === undefined) {\n for (let n = element.firstChild; n; ) {\n const next = n.nextSibling;\n cleanupRangeNode(n);\n n = next;\n }\n element.textContent = '';\n keyedElements.delete(element);\n return;\n }\n\n if (\n !Array.isArray(vnodeChildren) &&\n _isDOMElement(vnodeChildren) &&\n (vnodeChildren as DOMElement).type === __FOR_BOUNDARY__\n ) {\n updateForBoundaryChildren(element, vnodeChildren as DOMElement);\n return;\n }\n\n if (!Array.isArray(vnodeChildren) && isFragment(vnodeChildren)) {\n updateElementChildren(\n element,\n getFragmentChildren(vnodeChildren),\n cleanupRangeNode\n );\n return;\n }\n\n if (!Array.isArray(vnodeChildren)) {\n for (let n = element.firstChild; n; ) {\n const next = n.nextSibling;\n cleanupRangeNode(n);\n n = next;\n }\n element.textContent = '';\n const dom = domHost.createDOMNode(vnodeChildren);\n if (dom) element.appendChild(dom);\n keyedElements.delete(element);\n return;\n }\n\n if (\n vnodeChildren.length === 1 &&\n _isDOMElement(vnodeChildren[0]) &&\n (vnodeChildren[0] as DOMElement).type === __FOR_BOUNDARY__\n ) {\n updateForBoundaryChildren(element, vnodeChildren[0] as DOMElement);\n return;\n }\n\n if (hasKeyedChildren(vnodeChildren)) {\n const oldKeyMap = getOrBuildKeyMap(element);\n try {\n reconcileKeyed(element, vnodeChildren, oldKeyMap);\n } catch {\n const newKeyMap = reconcileKeyedChildren(\n element,\n vnodeChildren,\n oldKeyMap\n );\n keyedElements.set(element, newKeyMap);\n }\n } else {\n reconcileUnkeyed(element, vnodeChildren);\n }\n}\n\nexport function smartUpdateElement(\n element: Element,\n vnode: DOMElement,\n cleanupRangeNode: (node: Node) => void\n): void {\n const hadVNodeKey = Object.prototype.hasOwnProperty.call(vnode, 'key');\n const previousVNodeKey = vnode.key;\n\n runRetainedElementUpdate(\n element,\n cleanupRangeNode,\n () => applySmartUpdateElement(element, vnode, cleanupRangeNode),\n () => {\n if (hadVNodeKey) vnode.key = previousVNodeKey;\n else delete vnode.key;\n }\n );\n}\n\nfunction applySmartUpdateElement(\n element: Element,\n vnode: DOMElement,\n cleanupRangeNode: (node: Node) => void\n): void {\n const domHost = getRendererDOMHost();\n\n if (vnode.key == null && element.hasAttribute('data-key')) {\n const existingKey = element.getAttribute('data-key');\n if (existingKey !== null) {\n const numericKey = Number(existingKey);\n vnode.key = Number.isNaN(numericKey) ? existingKey : numericKey;\n }\n }\n\n let vnodeChildren = vnode.props?.children ?? vnode.children;\n\n if (\n vnodeChildren &&\n _isDOMElement(vnodeChildren) &&\n (vnodeChildren as DOMElement).type === __FOR_BOUNDARY__\n ) {\n updateElementChildren(element, vnodeChildren, cleanupRangeNode);\n domHost.updateElementFromVnode(element, vnode, false);\n return;\n }\n\n if (vnodeChildren && !Array.isArray(vnodeChildren)) {\n vnodeChildren = [vnodeChildren];\n }\n\n const textCheck = checkSimpleText(vnodeChildren);\n\n if (textCheck.isSimple && tryUpdateTextInPlace(element, textCheck.text)) {\n // Text updated in place.\n } else {\n updateElementChildren(element, vnodeChildren, cleanupRangeNode);\n }\n\n domHost.updateElementFromVnode(element, vnode, false);\n}\n\nexport function processFragmentChildren(\n target: Element,\n childArray: unknown[],\n cleanupRangeNode: (node: Node) => void\n): void {\n updateElementChildren(target, childArray, cleanupRangeNode);\n}\n\nfunction applyPropsToElement(el: Element, props: Props): void {\n for (const [key, value] of Object.entries(props)) {\n if (key === 'children' || key === 'key') continue;\n if (value === undefined || value === null || value === false) continue;\n\n if (key === 'ref') {\n applyRef(el, value);\n continue;\n }\n\n const eventProp = parseEventProp(key);\n if (eventProp) {\n const { eventName, capture } = eventProp;\n const wrappedHandler = createWrappedHandler(value as EventListener, true);\n const options = getEventListenerOptions(eventName, capture);\n const listenerKey = getEventListenerKey(eventName, capture);\n\n if (options !== undefined)\n el.addEventListener(eventName, wrappedHandler, options);\n else el.addEventListener(eventName, wrappedHandler);\n\n if (!elementListeners.has(el)) elementListeners.set(el, new Map());\n elementListeners.get(el)!.set(listenerKey, {\n handler: wrappedHandler,\n original: value as EventListener,\n eventName,\n options,\n });\n continue;\n }\n\n if (key === 'class' || key === 'className') {\n writeElementClassName(el, String(value));\n } else if (key === 'value' || key === 'checked') {\n (el as HTMLElement & Props)[key] = value;\n } else {\n setRenderedAttribute(el, key, String(value));\n }\n }\n}\n\ntype Ref<T> =\n | ((value: T | null) => void)\n | { current: T | null }\n | null\n | undefined;\n\nfunction applyRef<T>(el: T, ref: unknown): void {\n const r = ref as Ref<T>;\n if (!r) return;\n if (typeof r === 'function') {\n r(el);\n return;\n }\n try {\n (r as { current: T | null }).current = el;\n } catch {\n // Ignore write failures.\n }\n}\n\nexport function tryFirstRenderKeyedChildren(\n target: Element,\n vnode: DOMElement\n): boolean {\n const children = vnode.children;\n if (!Array.isArray(children) || !hasKeyedChildren(children)) {\n return false;\n }\n\n const el = createElementForNamespace(\n vnode.type as string,\n getParentNamespace(target)\n );\n target.appendChild(el);\n\n applyPropsToElement(el, vnode.props || {});\n\n const newKeyMap = reconcileKeyedChildren(el, children, undefined);\n keyedElements.set(el, newKeyMap);\n return true;\n}\n\nexport function isFragment(vnode: unknown): vnode is DOMElement {\n return (\n _isDOMElement(vnode) &&\n typeof (vnode as DOMElement).type === 'symbol' &&\n ((vnode as DOMElement).type === Fragment ||\n String((vnode as DOMElement).type) === 'Symbol(askr.fragment)')\n );\n}\n\nexport function getFragmentChildren(vnode: DOMElement): unknown[] {\n const fragmentChildren = vnode.props?.children ?? vnode.children ?? [];\n return Array.isArray(fragmentChildren)\n ? fragmentChildren\n : [fragmentChildren];\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"evaluate.js","names":[],"sources":["../../src/renderer/evaluate.ts"],"sourcesContent":["import { getRuntimeEnv } from './env';\nimport type {\n ComponentFunction,\n ComponentInstance,\n} from '../runtime/component-contracts';\nimport { removeAllListeners } from './cleanup';\nimport { createDOMNode, syncComponentElement } from './dom';\nimport type { ElementWithContext } from './dom-host';\nimport {\n cleanupRangeNode,\n createDOMRange,\n hasDOMRange,\n updateDOMRangeForContext,\n} from './evaluate-dom-range';\nimport {\n getFragmentChildren,\n getRetainedHostOwnerChain,\n isFragment,\n processFragmentChildren,\n retainHostOwnerChain,\n smartUpdateElement,\n tagNamesEqualIgnoreCase,\n tryFirstRenderKeyedChildren,\n updateElementChildren,\n updateForBoundaryChildren,\n} from './evaluate-reconcile';\nimport { _isDOMElement, type DOMElement } from './types';\nimport { __FOR_BOUNDARY__ } from '../common/vnode';\n\nexport { clearDOMRange } from './evaluate-dom-range';\n\nexport const IS_DOM_AVAILABLE = typeof document !== 'undefined';\n\nexport function evaluate(\n node: unknown,\n target: Element | null,\n context?: object,\n retainedOwner?: ComponentInstance\n): void {\n if (!target) return;\n if (typeof document === 'undefined') {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n try {\n console.warn('[Askr] evaluate() called in non-DOM environment; no-op.');\n } catch (e) {\n void e;\n }\n }\n return;\n }\n\n if (context && hasDOMRange(context)) {\n const normalizedChildren =\n node === null || node === undefined || node === false\n ? []\n : isFragment(node)\n ? getFragmentChildren(node as DOMElement)\n : Array.isArray(node)\n ? node\n : [node];\n\n updateDOMRangeForContext(target, context, normalizedChildren);\n } else if (context) {\n createDOMRange(target, context, node);\n } else {\n let vnode = node;\n\n if (isFragment(vnode)) {\n const childArray = getFragmentChildren(vnode as DOMElement);\n if (\n childArray.length === 1 &&\n _isDOMElement(childArray[0]) &&\n typeof (childArray[0] as DOMElement).type === 'string'\n ) {\n vnode = childArray[0];\n } else {\n processFragmentChildren(target, childArray, cleanupRangeNode);\n return;\n }\n }\n\n if (\n _isDOMElement(vnode) &&\n (vnode as DOMElement).type === __FOR_BOUNDARY__\n ) {\n updateForBoundaryChildren(target, vnode as DOMElement);\n return;\n }\n\n if (Array.isArray(vnode)) {\n updateElementChildren(target, vnode, cleanupRangeNode);\n return;\n }\n\n const targetWithInstance = target as Element & {\n __ASKR_INSTANCE?: ComponentInstance;\n };\n const targetInstance =\n retainedOwner?.target === target\n ? retainedOwner\n : targetWithInstance.__ASKR_INSTANCE;\n if (targetInstance && targetInstance.target === target) {\n const retainedHostInstances = getRetainedHostOwnerChain(\n targetWithInstance,\n targetInstance\n );\n\n if (_isDOMElement(vnode) && typeof vnode.type === 'function') {\n const syncedDom = syncComponentElement(\n target,\n vnode as unknown as ElementWithContext,\n vnode.type as ComponentFunction,\n (((vnode as DOMElement).props ?? {}) as Record<string, unknown>) ||\n {},\n undefined,\n false,\n retainedHostInstances\n );\n\n if (syncedDom instanceof Element) {\n retainHostOwnerChain(\n syncedDom,\n targetInstance,\n retainedHostInstances\n );\n targetInstance.target = syncedDom;\n return;\n }\n }\n\n if (\n _isDOMElement(vnode) &&\n typeof vnode.type === 'string' &&\n tagNamesEqualIgnoreCase(target.tagName, vnode.type)\n ) {\n smartUpdateElement(target, vnode as DOMElement, cleanupRangeNode);\n return;\n }\n\n const newDom = createDOMNode(vnode);\n if (newDom && target.parentNode) {\n if (newDom instanceof Element) {\n (\n newDom as Element & { __ASKR_INSTANCE?: ComponentInstance }\n ).__ASKR_INSTANCE = targetInstance;\n targetInstance.target = newDom as Element;\n }\n removeAllListeners(target);\n target.parentNode.replaceChild(newDom, target);\n return;\n }\n }\n\n const firstChild = target.children[0] as Element | undefined;\n\n if (\n firstChild &&\n _isDOMElement(vnode) &&\n typeof vnode.type === 'string' &&\n tagNamesEqualIgnoreCase(firstChild.tagName, vnode.type)\n ) {\n smartUpdateElement(firstChild, vnode as DOMElement, cleanupRangeNode);\n } else {\n for (let node = target.firstChild; node; ) {\n const next = node.nextSibling;\n cleanupRangeNode(node);\n node = next;\n }\n target.textContent = '';\n\n if (\n _isDOMElement(vnode) &&\n typeof vnode.type === 'string' &&\n tryFirstRenderKeyedChildren(target, vnode as DOMElement)\n ) {\n return;\n }\n\n const dom = createDOMNode(vnode);\n if (dom) {\n target.appendChild(dom);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAiCA,SAAgB,SACd,MACA,QACA,SACA,eACM;CACN,IAAI,CAAC,QAAQ;CACb,IAAI,OAAO,aAAa,aAAa;EACnC,IAAI,cAAc,CAAC,CAAC,aAAa,cAC/B,IAAI;GACF,QAAQ,KAAK,yDAAyD;EACxE,SAAS,GAAG,CAEZ;EAEF;CACF;CAEA,IAAI,WAAW,YAAY,OAAO,GAUhC,yBAAyB,QAAQ,SAR/B,SAAS,QAAQ,SAAS,UAAa,SAAS,QAC5C,CAAC,IACD,WAAW,IAAI,IACb,oBAAoB,IAAkB,IACtC,MAAM,QAAQ,IAAI,IAChB,OACA,CAAC,IAAI,CAE6C;MACvD,IAAI,SACT,eAAe,QAAQ,SAAS,IAAI;MAC/B;EACL,IAAI,QAAQ;EAEZ,IAAI,WAAW,KAAK,GAAG;GACrB,MAAM,aAAa,oBAAoB,KAAmB;GAC1D,IACE,WAAW,WAAW,KACtB,cAAc,WAAW,EAAE,KAC3B,OAAQ,WAAW,EAAE,CAAgB,SAAS,UAE9C,QAAQ,WAAW;QACd;IACL,wBAAwB,QAAQ,YAAY,gBAAgB;IAC5D;GACF;EACF;EAEA,IACE,cAAc,KAAK,KAClB,MAAqB,SAAS,kBAC/B;GACA,0BAA0B,QAAQ,KAAmB;GACrD;EACF;EAEA,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,sBAAsB,QAAQ,OAAO,gBAAgB;GACrD;EACF;EAEA,MAAM,qBAAqB;EAG3B,MAAM,iBACJ,eAAe,WAAW,SACtB,gBACA,mBAAmB;EACzB,IAAI,kBAAkB,eAAe,WAAW,QAAQ;GACtD,MAAM,wBAAwB,0BAC5B,oBACA,cACF;GAEA,IAAI,cAAc,KAAK,KAAK,OAAO,MAAM,SAAS,YAAY;IAC5D,MAAM,YAAY,qBAChB,QACA,OACA,MAAM,OACH,MAAqB,SAAS,CAAC,MAChC,CAAC,GACH,QACA,OACA,qBACF;IAEA,IAAI,qBAAqB,SAAS;KAChC,qBACE,WACA,gBACA,qBACF;KACA,eAAe,SAAS;KACxB;IACF;GACF;GAEA,IACE,cAAc,KAAK,KACnB,OAAO,MAAM,SAAS,YACtB,wBAAwB,OAAO,SAAS,MAAM,IAAI,GAClD;IACA,mBAAmB,QAAQ,OAAqB,gBAAgB;IAChE;GACF;GAEA,MAAM,SAAS,cAAc,KAAK;GAClC,IAAI,UAAU,OAAO,YAAY;IAC/B,IAAI,kBAAkB,SAAS;KAC7B,OAEE,kBAAkB;KACpB,eAAe,SAAS;IAC1B;IACA,mBAAmB,MAAM;IACzB,OAAO,WAAW,aAAa,QAAQ,MAAM;IAC7C;GACF;EACF;EAEA,MAAM,aAAa,OAAO,SAAS;EAEnC,IACE,cACA,cAAc,KAAK,KACnB,OAAO,MAAM,SAAS,YACtB,wBAAwB,WAAW,SAAS,MAAM,IAAI,GAEtD,mBAAmB,YAAY,OAAqB,gBAAgB;OAC/D;GACL,KAAK,IAAI,OAAO,OAAO,YAAY,OAAQ;IACzC,MAAM,OAAO,KAAK;IAClB,iBAAiB,IAAI;IACrB,OAAO;GACT;GACA,OAAO,cAAc;GAErB,IACE,cAAc,KAAK,KACnB,OAAO,MAAM,SAAS,YACtB,4BAA4B,QAAQ,KAAmB,GAEvD;GAGF,MAAM,MAAM,cAAc,KAAK;GAC/B,IAAI,KACF,OAAO,YAAY,GAAG;EAE1B;CACF;AACF"}
1
+ {"version":3,"file":"evaluate.js","names":[],"sources":["../../src/renderer/evaluate.ts"],"sourcesContent":["import { getRuntimeEnv } from './env';\nimport type { ComponentFunction, ComponentInstance } from '../runtime';\nimport { removeAllListeners } from './cleanup';\nimport { createDOMNode, syncComponentElement } from './dom';\nimport type { ElementWithContext } from './dom-host';\nimport {\n cleanupRangeNode,\n createDOMRange,\n hasDOMRange,\n updateDOMRangeForContext,\n} from './evaluate-dom-range';\nimport {\n getFragmentChildren,\n getRetainedHostOwnerChain,\n isFragment,\n processFragmentChildren,\n retainHostOwnerChain,\n smartUpdateElement,\n tagNamesEqualIgnoreCase,\n tryFirstRenderKeyedChildren,\n updateElementChildren,\n updateForBoundaryChildren,\n} from './evaluate-reconcile';\nimport { _isDOMElement, type DOMElement } from './types';\nimport { __FOR_BOUNDARY__ } from '../common/vnode';\n\nexport { clearDOMRange } from './evaluate-dom-range';\n\nexport const IS_DOM_AVAILABLE = typeof document !== 'undefined';\n\nexport function evaluate(\n node: unknown,\n target: Element | null,\n context?: object,\n retainedOwner?: ComponentInstance\n): void {\n if (!target) return;\n if (typeof document === 'undefined') {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n try {\n console.warn('[Askr] evaluate() called in non-DOM environment; no-op.');\n } catch (e) {\n void e;\n }\n }\n return;\n }\n\n if (context && hasDOMRange(context)) {\n const normalizedChildren =\n node === null || node === undefined || node === false\n ? []\n : isFragment(node)\n ? getFragmentChildren(node as DOMElement)\n : Array.isArray(node)\n ? node\n : [node];\n\n updateDOMRangeForContext(target, context, normalizedChildren);\n } else if (context) {\n createDOMRange(target, context, node);\n } else {\n let vnode = node;\n\n if (isFragment(vnode)) {\n const childArray = getFragmentChildren(vnode as DOMElement);\n if (\n childArray.length === 1 &&\n _isDOMElement(childArray[0]) &&\n typeof (childArray[0] as DOMElement).type === 'string'\n ) {\n vnode = childArray[0];\n } else {\n processFragmentChildren(target, childArray, cleanupRangeNode);\n return;\n }\n }\n\n if (\n _isDOMElement(vnode) &&\n (vnode as DOMElement).type === __FOR_BOUNDARY__\n ) {\n updateForBoundaryChildren(target, vnode as DOMElement);\n return;\n }\n\n if (Array.isArray(vnode)) {\n updateElementChildren(target, vnode, cleanupRangeNode);\n return;\n }\n\n const targetWithInstance = target as Element & {\n __ASKR_INSTANCE?: ComponentInstance;\n };\n const targetInstance =\n retainedOwner?.target === target\n ? retainedOwner\n : targetWithInstance.__ASKR_INSTANCE;\n if (targetInstance && targetInstance.target === target) {\n const retainedHostInstances = getRetainedHostOwnerChain(\n targetWithInstance,\n targetInstance\n );\n\n if (_isDOMElement(vnode) && typeof vnode.type === 'function') {\n const syncedDom = syncComponentElement(\n target,\n vnode as unknown as ElementWithContext,\n vnode.type as ComponentFunction,\n (((vnode as DOMElement).props ?? {}) as Record<string, unknown>) ||\n {},\n undefined,\n false,\n retainedHostInstances\n );\n\n if (syncedDom instanceof Element) {\n retainHostOwnerChain(\n syncedDom,\n targetInstance,\n retainedHostInstances\n );\n targetInstance.target = syncedDom;\n return;\n }\n }\n\n if (\n _isDOMElement(vnode) &&\n typeof vnode.type === 'string' &&\n tagNamesEqualIgnoreCase(target.tagName, vnode.type)\n ) {\n smartUpdateElement(target, vnode as DOMElement, cleanupRangeNode);\n return;\n }\n\n const newDom = createDOMNode(vnode);\n if (newDom && target.parentNode) {\n if (newDom instanceof Element) {\n (\n newDom as Element & { __ASKR_INSTANCE?: ComponentInstance }\n ).__ASKR_INSTANCE = targetInstance;\n targetInstance.target = newDom as Element;\n }\n removeAllListeners(target);\n target.parentNode.replaceChild(newDom, target);\n return;\n }\n }\n\n const firstChild = target.children[0] as Element | undefined;\n\n if (\n firstChild &&\n _isDOMElement(vnode) &&\n typeof vnode.type === 'string' &&\n tagNamesEqualIgnoreCase(firstChild.tagName, vnode.type)\n ) {\n smartUpdateElement(firstChild, vnode as DOMElement, cleanupRangeNode);\n } else {\n for (let node = target.firstChild; node; ) {\n const next = node.nextSibling;\n cleanupRangeNode(node);\n node = next;\n }\n target.textContent = '';\n\n if (\n _isDOMElement(vnode) &&\n typeof vnode.type === 'string' &&\n tryFirstRenderKeyedChildren(target, vnode as DOMElement)\n ) {\n return;\n }\n\n const dom = createDOMNode(vnode);\n if (dom) {\n target.appendChild(dom);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;AA8BA,SAAgB,SACd,MACA,QACA,SACA,eACM;CACN,IAAI,CAAC,QAAQ;CACb,IAAI,OAAO,aAAa,aAAa;EACnC,IAAI,cAAc,CAAC,CAAC,aAAa,cAC/B,IAAI;GACF,QAAQ,KAAK,yDAAyD;EACxE,SAAS,GAAG,CAEZ;EAEF;CACF;CAEA,IAAI,WAAW,YAAY,OAAO,GAUhC,yBAAyB,QAAQ,SAR/B,SAAS,QAAQ,SAAS,UAAa,SAAS,QAC5C,CAAC,IACD,WAAW,IAAI,IACb,oBAAoB,IAAkB,IACtC,MAAM,QAAQ,IAAI,IAChB,OACA,CAAC,IAAI,CAE6C;MACvD,IAAI,SACT,eAAe,QAAQ,SAAS,IAAI;MAC/B;EACL,IAAI,QAAQ;EAEZ,IAAI,WAAW,KAAK,GAAG;GACrB,MAAM,aAAa,oBAAoB,KAAmB;GAC1D,IACE,WAAW,WAAW,KACtB,cAAc,WAAW,EAAE,KAC3B,OAAQ,WAAW,EAAE,CAAgB,SAAS,UAE9C,QAAQ,WAAW;QACd;IACL,wBAAwB,QAAQ,YAAY,gBAAgB;IAC5D;GACF;EACF;EAEA,IACE,cAAc,KAAK,KAClB,MAAqB,SAAS,kBAC/B;GACA,0BAA0B,QAAQ,KAAmB;GACrD;EACF;EAEA,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,sBAAsB,QAAQ,OAAO,gBAAgB;GACrD;EACF;EAEA,MAAM,qBAAqB;EAG3B,MAAM,iBACJ,eAAe,WAAW,SACtB,gBACA,mBAAmB;EACzB,IAAI,kBAAkB,eAAe,WAAW,QAAQ;GACtD,MAAM,wBAAwB,0BAC5B,oBACA,cACF;GAEA,IAAI,cAAc,KAAK,KAAK,OAAO,MAAM,SAAS,YAAY;IAC5D,MAAM,YAAY,qBAChB,QACA,OACA,MAAM,OACH,MAAqB,SAAS,CAAC,MAChC,CAAC,GACH,QACA,OACA,qBACF;IAEA,IAAI,qBAAqB,SAAS;KAChC,qBACE,WACA,gBACA,qBACF;KACA,eAAe,SAAS;KACxB;IACF;GACF;GAEA,IACE,cAAc,KAAK,KACnB,OAAO,MAAM,SAAS,YACtB,wBAAwB,OAAO,SAAS,MAAM,IAAI,GAClD;IACA,mBAAmB,QAAQ,OAAqB,gBAAgB;IAChE;GACF;GAEA,MAAM,SAAS,cAAc,KAAK;GAClC,IAAI,UAAU,OAAO,YAAY;IAC/B,IAAI,kBAAkB,SAAS;KAC7B,OAEE,kBAAkB;KACpB,eAAe,SAAS;IAC1B;IACA,mBAAmB,MAAM;IACzB,OAAO,WAAW,aAAa,QAAQ,MAAM;IAC7C;GACF;EACF;EAEA,MAAM,aAAa,OAAO,SAAS;EAEnC,IACE,cACA,cAAc,KAAK,KACnB,OAAO,MAAM,SAAS,YACtB,wBAAwB,WAAW,SAAS,MAAM,IAAI,GAEtD,mBAAmB,YAAY,OAAqB,gBAAgB;OAC/D;GACL,KAAK,IAAI,OAAO,OAAO,YAAY,OAAQ;IACzC,MAAM,OAAO,KAAK;IAClB,iBAAiB,IAAI;IACrB,OAAO;GACT;GACA,OAAO,cAAc;GAErB,IACE,cAAc,KAAK,KACnB,OAAO,MAAM,SAAS,YACtB,4BAA4B,QAAQ,KAAmB,GAEvD;GAGF,MAAM,MAAM,cAAc,KAAK;GAC/B,IAAI,KACF,OAAO,YAAY,GAAG;EAE1B;CACF;AACF"}
@@ -1,13 +1,14 @@
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 { isRuntimeSchedulerExecuting } from "../runtime/access.js";
4
4
  import { incDevCounter, setDevValue } from "../runtime/dev-namespace.js";
5
5
  import { isBulkCommitActive, markFastPathApplied } from "../runtime/fastlane.js";
6
+ import { recordBenchCounter, recordBenchEvent } from "../runtime/for-bench.js";
7
+ import "../runtime/index.js";
6
8
  import { cleanupInstanceIfPresent, removeAllListeners } from "./cleanup.js";
7
9
  import "./env.js";
8
10
  import { canUseDirectReplaceChildrenSpread } from "./utils.js";
9
11
  import { _reconcilerRecordedParents } from "./keyed.js";
10
- import { recordBenchCounter, recordBenchEvent } from "../runtime/for-bench.js";
11
12
  import { createDOMNode, updateElementFromVnode } from "./dom-internal.js";
12
13
  import "./dom.js";
13
14
  function applyRendererFastPath(parent, keyedVnodes, oldKeyMap) {
@@ -1 +1 @@
1
- {"version":3,"file":"fastpath.js","names":[],"sources":["../../src/renderer/fastpath.ts"],"sourcesContent":["import { createDOMNode, updateElementFromVnode } from './dom';\nimport { _reconcilerRecordedParents } from './keyed';\nimport { logger } from '../dev/logger';\nimport { getRuntimeEnv } from './env';\nimport { cleanupInstanceIfPresent, removeAllListeners } from './cleanup';\nimport { recordBenchCounter, recordBenchEvent } from '../runtime/for-bench';\nimport { setDevValue, incDevCounter } from '../runtime/dev-namespace';\nimport { isRuntimeSchedulerExecuting } from '../runtime/access';\nimport { isBulkCommitActive, markFastPathApplied } from '../runtime/fastlane';\nimport { canUseDirectReplaceChildrenSpread } from './utils';\nimport type { KeyedVnode } from './keyed-children';\n\nexport const IS_DOM_AVAILABLE = typeof document !== 'undefined';\n\n// Apply the \"renderer\" fast-path: build final node list reusing existing\n// elements by key when possible, then perform a single atomic replaceChildren\n// commit. Returns a new key map when the fast-path is applied, otherwise\n// returns null to indicate the caller should continue with fallback paths.\nexport function applyRendererFastPath(\n parent: Element,\n keyedVnodes: KeyedVnode[],\n oldKeyMap?: Map<string | number, Element>\n): Map<string | number, Element> | null {\n // SSR guard: fast-path is DOM-specific\n if (typeof document === 'undefined') return null;\n\n const totalKeyed = keyedVnodes.length;\n if (totalKeyed === 0) return null;\n\n // Dev invariant: ensure we are executing inside the scheduler/commit flush\n if (!isRuntimeSchedulerExecuting()) {\n logger.warn(\n '[Askr][FASTPATH][DEV] Fast-path reconciliation invoked outside scheduler execution'\n );\n }\n\n // Choose lookup strategy depending on size (linear scan for small lists)\n let parentChildrenArr: Element[] | undefined;\n let localOldKeyMap: Map<string | number, Element> | undefined;\n\n if (totalKeyed <= 20) {\n // Small lists: use array scan (faster than Map overhead for ≤20 items)\n try {\n parentChildrenArr = Array.from(\n parent.children,\n (child) => child as Element\n );\n } catch (e) {\n parentChildrenArr = undefined;\n void e;\n }\n } else if (!oldKeyMap || oldKeyMap.size === 0) {\n // Medium/large lists without existing key map: build from DOM\n localOldKeyMap = new Map<string | number, Element>();\n try {\n for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {\n const k = ch.getAttribute('data-key');\n if (k !== null) {\n localOldKeyMap.set(k, ch);\n const n = Number(k);\n if (!Number.isNaN(n)) localOldKeyMap.set(n, ch);\n }\n }\n } catch (e) {\n localOldKeyMap = undefined;\n void e;\n }\n }\n // else: reuse oldKeyMap directly (most common case for repeat renders)\n\n const finalNodes: Node[] = [];\n let mapLookups = 0;\n let createdNodes = 0;\n let reusedCount = 0;\n\n for (let i = 0; i < keyedVnodes.length; i++) {\n const { key, vnode } = keyedVnodes[i];\n mapLookups++;\n\n let el: Element | undefined;\n if (totalKeyed <= 20 && parentChildrenArr) {\n const ks = String(key);\n for (let j = 0; j < parentChildrenArr.length; j++) {\n const ch = parentChildrenArr[j];\n const k = ch.getAttribute('data-key');\n if (k !== null && (k === ks || Number(k) === (key as number))) {\n el = ch;\n break;\n }\n }\n if (!el) el = oldKeyMap?.get(key);\n } else {\n el = localOldKeyMap?.get(key as string | number) ?? oldKeyMap?.get(key);\n }\n\n if (el) {\n updateElementFromVnode(el, vnode);\n finalNodes.push(el);\n reusedCount++;\n } else {\n const newEl = createDOMNode(vnode);\n if (newEl) {\n finalNodes.push(newEl);\n createdNodes++;\n }\n }\n }\n\n // Atomic commit\n try {\n const tCommitStart = Date.now();\n const fragmentAppendCount = finalNodes.length;\n const useDirectReplace = canUseDirectReplaceChildrenSpread(\n finalNodes.length\n );\n const finalNodeSet = useDirectReplace ? new Set<Node>(finalNodes) : null;\n const fragment = useDirectReplace\n ? null\n : parent.ownerDocument.createDocumentFragment();\n\n if (fragment) {\n for (let i = 0; i < finalNodes.length; i++) {\n fragment.appendChild(finalNodes[i]);\n }\n }\n\n // Pre-cleanup: remove component instances that will be removed by replaceChildren\n try {\n // Keep reused nodes alive, but clean up anything still attached to the\n // parent that will be removed by replaceChildren.\n for (let n = parent.firstChild; n; ) {\n const next = n.nextSibling;\n if (finalNodeSet?.has(n)) {\n n = next;\n continue;\n }\n if (n instanceof Element) removeAllListeners(n);\n cleanupInstanceIfPresent(n);\n n = next;\n }\n } catch (e) {\n void e;\n }\n\n try {\n incDevCounter('__DOM_REPLACE_COUNT');\n setDevValue('__LAST_DOM_REPLACE_STACK_FASTPATH', new Error().stack);\n } catch (e) {\n void e;\n }\n\n if (useDirectReplace) {\n // Move-only reorder commits already have the final node set, so small\n // lists can write it directly without a fragment round-trip.\n parent.replaceChildren(...finalNodes);\n } else {\n parent.replaceChildren(fragment!);\n }\n recordBenchEvent('domMove', reusedCount);\n recordBenchEvent('domInsert', createdNodes);\n recordBenchCounter('replaceChildrenCommits');\n\n // Record that we performed exactly one DOM commit.\n try {\n setDevValue('__LAST_FASTPATH_COMMIT_COUNT', 1);\n } catch (e) {\n void e;\n }\n\n // If a runtime bulk commit is active, mark this parent as fast-path applied.\n try {\n if (isBulkCommitActive()) markFastPathApplied(parent);\n } catch (e) {\n void e;\n }\n\n // Phase: bookkeeping - populate newKeyMap\n const newKeyMap = new Map<string | number, Element>();\n for (let i = 0; i < keyedVnodes.length; i++) {\n const key = keyedVnodes[i].key;\n const node = finalNodes[i];\n if (node instanceof Element) newKeyMap.set(key, node as Element);\n }\n\n // Dev tracing\n try {\n const stats = {\n n: totalKeyed,\n moves: 0,\n lisLen: 0,\n t_lookup: 0,\n t_fragment: Date.now() - tCommitStart,\n t_commit: 0,\n t_bookkeeping: 0,\n fragmentAppendCount,\n mapLookups,\n createdNodes,\n reusedCount,\n } as const;\n if (typeof globalThis !== 'undefined') {\n setDevValue('__LAST_FASTPATH_STATS', stats);\n setDevValue('__LAST_FASTPATH_REUSED', reusedCount > 0);\n incDevCounter('fastpathHistoryPush');\n }\n const env = getRuntimeEnv();\n if (\n env.ASKR_FASTPATH_DEBUG === '1' ||\n env.ASKR_FASTPATH_DEBUG === 'true'\n ) {\n logger.warn(\n '[Askr][FASTPATH]',\n JSON.stringify({ n: totalKeyed, createdNodes, reusedCount })\n );\n }\n } catch (e) {\n void e;\n }\n\n // Record that reconciler recorded stats for this parent in this pass\n try {\n _reconcilerRecordedParents.add(parent);\n } catch (e) {\n void e;\n }\n\n return newKeyMap;\n } catch (e) {\n void e;\n return null;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fastpath.js","names":[],"sources":["../../src/renderer/fastpath.ts"],"sourcesContent":["import { createDOMNode, updateElementFromVnode } from './dom';\nimport { _reconcilerRecordedParents } from './keyed';\nimport { logger } from '../common/logger';\nimport { getRuntimeEnv } from './env';\nimport { cleanupInstanceIfPresent, removeAllListeners } from './cleanup';\nimport { recordBenchCounter, recordBenchEvent } from '../runtime';\nimport { setDevValue, incDevCounter } from '../runtime';\nimport { isRuntimeSchedulerExecuting } from '../runtime';\nimport { isBulkCommitActive, markFastPathApplied } from '../runtime';\nimport { canUseDirectReplaceChildrenSpread } from './utils';\nimport type { KeyedVnode } from './keyed-children';\n\nexport const IS_DOM_AVAILABLE = typeof document !== 'undefined';\n\n// Apply the \"renderer\" fast-path: build final node list reusing existing\n// elements by key when possible, then perform a single atomic replaceChildren\n// commit. Returns a new key map when the fast-path is applied, otherwise\n// returns null to indicate the caller should continue with fallback paths.\nexport function applyRendererFastPath(\n parent: Element,\n keyedVnodes: KeyedVnode[],\n oldKeyMap?: Map<string | number, Element>\n): Map<string | number, Element> | null {\n // SSR guard: fast-path is DOM-specific\n if (typeof document === 'undefined') return null;\n\n const totalKeyed = keyedVnodes.length;\n if (totalKeyed === 0) return null;\n\n // Dev invariant: ensure we are executing inside the scheduler/commit flush\n if (!isRuntimeSchedulerExecuting()) {\n logger.warn(\n '[Askr][FASTPATH][DEV] Fast-path reconciliation invoked outside scheduler execution'\n );\n }\n\n // Choose lookup strategy depending on size (linear scan for small lists)\n let parentChildrenArr: Element[] | undefined;\n let localOldKeyMap: Map<string | number, Element> | undefined;\n\n if (totalKeyed <= 20) {\n // Small lists: use array scan (faster than Map overhead for ≤20 items)\n try {\n parentChildrenArr = Array.from(\n parent.children,\n (child) => child as Element\n );\n } catch (e) {\n parentChildrenArr = undefined;\n void e;\n }\n } else if (!oldKeyMap || oldKeyMap.size === 0) {\n // Medium/large lists without existing key map: build from DOM\n localOldKeyMap = new Map<string | number, Element>();\n try {\n for (let ch = parent.firstElementChild; ch; ch = ch.nextElementSibling) {\n const k = ch.getAttribute('data-key');\n if (k !== null) {\n localOldKeyMap.set(k, ch);\n const n = Number(k);\n if (!Number.isNaN(n)) localOldKeyMap.set(n, ch);\n }\n }\n } catch (e) {\n localOldKeyMap = undefined;\n void e;\n }\n }\n // else: reuse oldKeyMap directly (most common case for repeat renders)\n\n const finalNodes: Node[] = [];\n let mapLookups = 0;\n let createdNodes = 0;\n let reusedCount = 0;\n\n for (let i = 0; i < keyedVnodes.length; i++) {\n const { key, vnode } = keyedVnodes[i];\n mapLookups++;\n\n let el: Element | undefined;\n if (totalKeyed <= 20 && parentChildrenArr) {\n const ks = String(key);\n for (let j = 0; j < parentChildrenArr.length; j++) {\n const ch = parentChildrenArr[j];\n const k = ch.getAttribute('data-key');\n if (k !== null && (k === ks || Number(k) === (key as number))) {\n el = ch;\n break;\n }\n }\n if (!el) el = oldKeyMap?.get(key);\n } else {\n el = localOldKeyMap?.get(key as string | number) ?? oldKeyMap?.get(key);\n }\n\n if (el) {\n updateElementFromVnode(el, vnode);\n finalNodes.push(el);\n reusedCount++;\n } else {\n const newEl = createDOMNode(vnode);\n if (newEl) {\n finalNodes.push(newEl);\n createdNodes++;\n }\n }\n }\n\n // Atomic commit\n try {\n const tCommitStart = Date.now();\n const fragmentAppendCount = finalNodes.length;\n const useDirectReplace = canUseDirectReplaceChildrenSpread(\n finalNodes.length\n );\n const finalNodeSet = useDirectReplace ? new Set<Node>(finalNodes) : null;\n const fragment = useDirectReplace\n ? null\n : parent.ownerDocument.createDocumentFragment();\n\n if (fragment) {\n for (let i = 0; i < finalNodes.length; i++) {\n fragment.appendChild(finalNodes[i]);\n }\n }\n\n // Pre-cleanup: remove component instances that will be removed by replaceChildren\n try {\n // Keep reused nodes alive, but clean up anything still attached to the\n // parent that will be removed by replaceChildren.\n for (let n = parent.firstChild; n; ) {\n const next = n.nextSibling;\n if (finalNodeSet?.has(n)) {\n n = next;\n continue;\n }\n if (n instanceof Element) removeAllListeners(n);\n cleanupInstanceIfPresent(n);\n n = next;\n }\n } catch (e) {\n void e;\n }\n\n try {\n incDevCounter('__DOM_REPLACE_COUNT');\n setDevValue('__LAST_DOM_REPLACE_STACK_FASTPATH', new Error().stack);\n } catch (e) {\n void e;\n }\n\n if (useDirectReplace) {\n // Move-only reorder commits already have the final node set, so small\n // lists can write it directly without a fragment round-trip.\n parent.replaceChildren(...finalNodes);\n } else {\n parent.replaceChildren(fragment!);\n }\n recordBenchEvent('domMove', reusedCount);\n recordBenchEvent('domInsert', createdNodes);\n recordBenchCounter('replaceChildrenCommits');\n\n // Record that we performed exactly one DOM commit.\n try {\n setDevValue('__LAST_FASTPATH_COMMIT_COUNT', 1);\n } catch (e) {\n void e;\n }\n\n // If a runtime bulk commit is active, mark this parent as fast-path applied.\n try {\n if (isBulkCommitActive()) markFastPathApplied(parent);\n } catch (e) {\n void e;\n }\n\n // Phase: bookkeeping - populate newKeyMap\n const newKeyMap = new Map<string | number, Element>();\n for (let i = 0; i < keyedVnodes.length; i++) {\n const key = keyedVnodes[i].key;\n const node = finalNodes[i];\n if (node instanceof Element) newKeyMap.set(key, node as Element);\n }\n\n // Dev tracing\n try {\n const stats = {\n n: totalKeyed,\n moves: 0,\n lisLen: 0,\n t_lookup: 0,\n t_fragment: Date.now() - tCommitStart,\n t_commit: 0,\n t_bookkeeping: 0,\n fragmentAppendCount,\n mapLookups,\n createdNodes,\n reusedCount,\n } as const;\n if (typeof globalThis !== 'undefined') {\n setDevValue('__LAST_FASTPATH_STATS', stats);\n setDevValue('__LAST_FASTPATH_REUSED', reusedCount > 0);\n incDevCounter('fastpathHistoryPush');\n }\n const env = getRuntimeEnv();\n if (\n env.ASKR_FASTPATH_DEBUG === '1' ||\n env.ASKR_FASTPATH_DEBUG === 'true'\n ) {\n logger.warn(\n '[Askr][FASTPATH]',\n JSON.stringify({ n: totalKeyed, createdNodes, reusedCount })\n );\n }\n } catch (e) {\n void e;\n }\n\n // Record that reconciler recorded stats for this parent in this pass\n try {\n _reconcilerRecordedParents.add(parent);\n } catch (e) {\n void e;\n }\n\n return newKeyMap;\n } catch (e) {\n void e;\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAkBA,SAAgB,sBACd,QACA,aACA,WACsC;CAEtC,IAAI,OAAO,aAAa,aAAa,OAAO;CAE5C,MAAM,aAAa,YAAY;CAC/B,IAAI,eAAe,GAAG,OAAO;CAG7B,IAAI,CAAC,4BAA4B,GAC/B,OAAO,KACL,oFACF;CAIF,IAAI;CACJ,IAAI;CAEJ,IAAI,cAAc,IAEhB,IAAI;EACF,oBAAoB,MAAM,KACxB,OAAO,WACN,UAAU,KACb;CACF,SAAS,GAAG;EACV,oBAAoB;CAEtB;MACK,IAAI,CAAC,aAAa,UAAU,SAAS,GAAG;EAE7C,iCAAiB,IAAI,IAA8B;EACnD,IAAI;GACF,KAAK,IAAI,KAAK,OAAO,mBAAmB,IAAI,KAAK,GAAG,oBAAoB;IACtE,MAAM,IAAI,GAAG,aAAa,UAAU;IACpC,IAAI,MAAM,MAAM;KACd,eAAe,IAAI,GAAG,EAAE;KACxB,MAAM,IAAI,OAAO,CAAC;KAClB,IAAI,CAAC,OAAO,MAAM,CAAC,GAAG,eAAe,IAAI,GAAG,EAAE;IAChD;GACF;EACF,SAAS,GAAG;GACV,iBAAiB;EAEnB;CACF;CAGA,MAAM,aAAqB,CAAC;CAC5B,IAAI,aAAa;CACjB,IAAI,eAAe;CACnB,IAAI,cAAc;CAElB,KAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;EAC3C,MAAM,EAAE,KAAK,UAAU,YAAY;EACnC;EAEA,IAAI;EACJ,IAAI,cAAc,MAAM,mBAAmB;GACzC,MAAM,KAAK,OAAO,GAAG;GACrB,KAAK,IAAI,IAAI,GAAG,IAAI,kBAAkB,QAAQ,KAAK;IACjD,MAAM,KAAK,kBAAkB;IAC7B,MAAM,IAAI,GAAG,aAAa,UAAU;IACpC,IAAI,MAAM,SAAS,MAAM,MAAM,OAAO,CAAC,MAAO,MAAiB;KAC7D,KAAK;KACL;IACF;GACF;GACA,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,GAAG;EAClC,OACE,KAAK,gBAAgB,IAAI,GAAsB,KAAK,WAAW,IAAI,GAAG;EAGxE,IAAI,IAAI;GACN,uBAAuB,IAAI,KAAK;GAChC,WAAW,KAAK,EAAE;GAClB;EACF,OAAO;GACL,MAAM,QAAQ,cAAc,KAAK;GACjC,IAAI,OAAO;IACT,WAAW,KAAK,KAAK;IACrB;GACF;EACF;CACF;CAGA,IAAI;EACF,MAAM,eAAe,KAAK,IAAI;EAC9B,MAAM,sBAAsB,WAAW;EACvC,MAAM,mBAAmB,kCACvB,WAAW,MACb;EACA,MAAM,eAAe,mBAAmB,IAAI,IAAU,UAAU,IAAI;EACpE,MAAM,WAAW,mBACb,OACA,OAAO,cAAc,uBAAuB;EAEhD,IAAI,UACF,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KACrC,SAAS,YAAY,WAAW,EAAE;EAKtC,IAAI;GAGF,KAAK,IAAI,IAAI,OAAO,YAAY,IAAK;IACnC,MAAM,OAAO,EAAE;IACf,IAAI,cAAc,IAAI,CAAC,GAAG;KACxB,IAAI;KACJ;IACF;IACA,IAAI,aAAa,SAAS,mBAAmB,CAAC;IAC9C,yBAAyB,CAAC;IAC1B,IAAI;GACN;EACF,SAAS,GAAG,CAEZ;EAEA,IAAI;GACF,cAAc,qBAAqB;GACnC,YAAY,sDAAqC,IAAI,MAAM,EAAC,CAAC,KAAK;EACpE,SAAS,GAAG,CAEZ;EAEA,IAAI,kBAGF,OAAO,gBAAgB,GAAG,UAAU;OAEpC,OAAO,gBAAgB,QAAS;EAElC,iBAAiB,WAAW,WAAW;EACvC,iBAAiB,aAAa,YAAY;EAC1C,mBAAmB,wBAAwB;EAG3C,IAAI;GACF,YAAY,gCAAgC,CAAC;EAC/C,SAAS,GAAG,CAEZ;EAGA,IAAI;GACF,IAAI,mBAAmB,GAAG,oBAAoB,MAAM;EACtD,SAAS,GAAG,CAEZ;EAGA,MAAM,4BAAY,IAAI,IAA8B;EACpD,KAAK,IAAI,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;GAC3C,MAAM,MAAM,YAAY,EAAE,CAAC;GAC3B,MAAM,OAAO,WAAW;GACxB,IAAI,gBAAgB,SAAS,UAAU,IAAI,KAAK,IAAe;EACjE;EAGA,IAAI;GACF,MAAM,QAAQ;IACZ,GAAG;IACH,OAAO;IACP,QAAQ;IACR,UAAU;IACV,YAAY,KAAK,IAAI,IAAI;IACzB,UAAU;IACV,eAAe;IACf;IACA;IACA;IACA;GACF;GACA,IAAI,OAAO,eAAe,aAAa;IACrC,YAAY,yBAAyB,KAAK;IAC1C,YAAY,0BAA0B,cAAc,CAAC;IACrD,cAAc,qBAAqB;GACrC;GACA,MAAM,MAAM,cAAc;GAC1B,IACE,IAAI,wBAAwB,OAC5B,IAAI,wBAAwB,QAE5B,OAAO,KACL,oBACA,KAAK,UAAU;IAAE,GAAG;IAAY;IAAc;GAAY,CAAC,CAC7D;EAEJ,SAAS,GAAG,CAEZ;EAGA,IAAI;GACF,2BAA2B,IAAI,MAAM;EACvC,SAAS,GAAG,CAEZ;EAEA,OAAO;CACT,SAAS,GAAG;EAEV,OAAO;CACT;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"for-commit-dom-map.js","names":[],"sources":["../../src/renderer/for-commit-dom-map.ts"],"sourcesContent":["import type { ForCommitStrategy, ForState } from '../runtime/for';\nimport { keyedElements } from './keyed';\n\nexport function getOrBuildDomKeyMap(\n parent: Element\n): Map<string | number, Element> | undefined {\n let keyMap = keyedElements.get(parent);\n if (!keyMap) {\n keyMap = new Map<string | number, Element>();\n for (\n let child = parent.firstElementChild;\n child;\n child = child.nextElementSibling\n ) {\n const key = child.getAttribute('data-key');\n if (key !== null) {\n keyMap.set(key, child);\n const numericKey = Number(key);\n if (!Number.isNaN(numericKey)) {\n keyMap.set(numericKey, child);\n }\n }\n }\n if (keyMap.size > 0) {\n keyedElements.set(parent, keyMap);\n }\n }\n return keyMap.size > 0 ? keyMap : undefined;\n}\n\nexport function hydrateExistingForDomInOrder(\n parent: Element,\n forState: ForState<unknown>\n): boolean {\n if (parent.children.length !== forState.orderedKeys.length) {\n return false;\n }\n\n for (let i = 0; i < forState.orderedKeys.length; i += 1) {\n const itemKey = forState.orderedKeys[i];\n const itemInstance = forState.items.get(itemKey);\n const currentDom = parent.children[i];\n\n if (\n !itemInstance ||\n currentDom.getAttribute('data-key') !== String(itemKey)\n ) {\n return false;\n }\n\n itemInstance.scope.dom = currentDom;\n itemInstance.scope.needsDomUpdate = true;\n }\n\n return true;\n}\n\nexport function syncKeyedMapFromForState(\n parent: Element,\n forState: ForState<unknown>,\n strategy: ForCommitStrategy,\n removedNodes: Node[]\n): void {\n const existing = keyedElements.get(parent);\n const ensureMapEntry = (\n map: Map<string | number, Element>,\n key: string | number,\n element: Element\n ): void => {\n map.set(key, element);\n const keyString = String(key);\n map.set(keyString, element);\n const keyNumber = Number(keyString);\n if (!Number.isNaN(keyNumber)) {\n map.set(keyNumber, element);\n }\n };\n\n if (strategy === 'SWAP') {\n if (existing) {\n return;\n }\n }\n\n if (strategy === 'FULL_KEYED' && existing && removedNodes.length === 0) {\n return;\n }\n\n if (strategy === 'NO_REORDER') {\n if (existing && removedNodes.length === 0) {\n return;\n }\n\n if (existing) {\n for (const [mapKey, element] of existing) {\n if (element.parentNode !== parent) {\n existing.delete(mapKey);\n }\n }\n\n if (existing.size > 0) {\n keyedElements.set(parent, existing);\n } else {\n keyedElements.delete(parent);\n }\n return;\n }\n }\n\n if (strategy === 'TRUNCATE' && forState.orderedKeys.length === 0) {\n if (existing) {\n existing.clear();\n }\n keyedElements.delete(parent);\n return;\n }\n\n if (strategy === 'APPEND' && existing) {\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const key = forState.orderedKeys[i];\n if (key === null || existing.has(key)) continue;\n const itemInstance = forState.items.get(key);\n if (itemInstance?.scope.dom instanceof Element) {\n ensureMapEntry(existing, key, itemInstance.scope.dom);\n }\n }\n\n if (existing.size > 0) {\n keyedElements.set(parent, existing);\n } else {\n keyedElements.delete(parent);\n }\n return;\n }\n\n const nextMap = existing ?? new Map<string | number, Element>();\n nextMap.clear();\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const key = forState.orderedKeys[i];\n if (key === null) continue;\n const itemInstance = forState.items.get(key);\n if (itemInstance?.scope.dom instanceof Element) {\n ensureMapEntry(nextMap, key, itemInstance.scope.dom);\n }\n }\n\n if (nextMap.size > 0) {\n keyedElements.set(parent, nextMap);\n } else {\n keyedElements.delete(parent);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"for-commit-dom-map.js","names":[],"sources":["../../src/renderer/for-commit-dom-map.ts"],"sourcesContent":["import type { ForCommitStrategy, ForState } from '../runtime';\nimport { keyedElements } from './keyed';\n\nexport function getOrBuildDomKeyMap(\n parent: Element\n): Map<string | number, Element> | undefined {\n let keyMap = keyedElements.get(parent);\n if (!keyMap) {\n keyMap = new Map<string | number, Element>();\n for (\n let child = parent.firstElementChild;\n child;\n child = child.nextElementSibling\n ) {\n const key = child.getAttribute('data-key');\n if (key !== null) {\n keyMap.set(key, child);\n const numericKey = Number(key);\n if (!Number.isNaN(numericKey)) {\n keyMap.set(numericKey, child);\n }\n }\n }\n if (keyMap.size > 0) {\n keyedElements.set(parent, keyMap);\n }\n }\n return keyMap.size > 0 ? keyMap : undefined;\n}\n\nexport function hydrateExistingForDomInOrder(\n parent: Element,\n forState: ForState<unknown>\n): boolean {\n if (parent.children.length !== forState.orderedKeys.length) {\n return false;\n }\n\n for (let i = 0; i < forState.orderedKeys.length; i += 1) {\n const itemKey = forState.orderedKeys[i];\n const itemInstance = forState.items.get(itemKey);\n const currentDom = parent.children[i];\n\n if (\n !itemInstance ||\n currentDom.getAttribute('data-key') !== String(itemKey)\n ) {\n return false;\n }\n\n itemInstance.scope.dom = currentDom;\n itemInstance.scope.needsDomUpdate = true;\n }\n\n return true;\n}\n\nexport function syncKeyedMapFromForState(\n parent: Element,\n forState: ForState<unknown>,\n strategy: ForCommitStrategy,\n removedNodes: Node[]\n): void {\n const existing = keyedElements.get(parent);\n const ensureMapEntry = (\n map: Map<string | number, Element>,\n key: string | number,\n element: Element\n ): void => {\n map.set(key, element);\n const keyString = String(key);\n map.set(keyString, element);\n const keyNumber = Number(keyString);\n if (!Number.isNaN(keyNumber)) {\n map.set(keyNumber, element);\n }\n };\n\n if (strategy === 'SWAP') {\n if (existing) {\n return;\n }\n }\n\n if (strategy === 'FULL_KEYED' && existing && removedNodes.length === 0) {\n return;\n }\n\n if (strategy === 'NO_REORDER') {\n if (existing && removedNodes.length === 0) {\n return;\n }\n\n if (existing) {\n for (const [mapKey, element] of existing) {\n if (element.parentNode !== parent) {\n existing.delete(mapKey);\n }\n }\n\n if (existing.size > 0) {\n keyedElements.set(parent, existing);\n } else {\n keyedElements.delete(parent);\n }\n return;\n }\n }\n\n if (strategy === 'TRUNCATE' && forState.orderedKeys.length === 0) {\n if (existing) {\n existing.clear();\n }\n keyedElements.delete(parent);\n return;\n }\n\n if (strategy === 'APPEND' && existing) {\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const key = forState.orderedKeys[i];\n if (key === null || existing.has(key)) continue;\n const itemInstance = forState.items.get(key);\n if (itemInstance?.scope.dom instanceof Element) {\n ensureMapEntry(existing, key, itemInstance.scope.dom);\n }\n }\n\n if (existing.size > 0) {\n keyedElements.set(parent, existing);\n } else {\n keyedElements.delete(parent);\n }\n return;\n }\n\n const nextMap = existing ?? new Map<string | number, Element>();\n nextMap.clear();\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const key = forState.orderedKeys[i];\n if (key === null) continue;\n const itemInstance = forState.items.get(key);\n if (itemInstance?.scope.dom instanceof Element) {\n ensureMapEntry(nextMap, key, itemInstance.scope.dom);\n }\n }\n\n if (nextMap.size > 0) {\n keyedElements.set(parent, nextMap);\n } else {\n keyedElements.delete(parent);\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { teardownNodeSubtree } from "./cleanup.js";
2
1
  import { recordBenchCounter, recordBenchEvent, withBenchMetricScope } from "../runtime/for-bench.js";
3
- import "../runtime/for.js";
2
+ import "../runtime/index.js";
3
+ import { teardownNodeSubtree } from "./cleanup.js";
4
4
  //#region src/renderer/for-commit-removal.ts
5
5
  function removeForBoundaryNodes(parent, removedNodes) {
6
6
  if (removedNodes.length > 0 && removedNodes.length === parent.childNodes.length) {
@@ -1 +1 @@
1
- {"version":3,"file":"for-commit-removal.js","names":[],"sources":["../../src/renderer/for-commit-removal.ts"],"sourcesContent":["import {\n recordBenchCounter,\n recordBenchEvent,\n withBenchMetricScope,\n} from '../runtime/for';\nimport { teardownNodeSubtree } from './cleanup';\n\nexport function removeForBoundaryNodes(\n parent: Element,\n removedNodes: Node[]\n): void {\n if (\n removedNodes.length > 0 &&\n removedNodes.length === parent.childNodes.length\n ) {\n let canBulkClear = true;\n for (let i = 0; i < removedNodes.length; i++) {\n if (removedNodes[i].parentNode !== parent) {\n canBulkClear = false;\n break;\n }\n }\n\n if (canBulkClear) {\n for (let i = 0; i < removedNodes.length; i++) {\n recordBenchEvent('domRemove');\n teardownNodeSubtree(removedNodes[i]);\n }\n withBenchMetricScope('fullClear', () => {\n recordBenchCounter('bulkClearCommits');\n parent.textContent = '';\n });\n return;\n }\n }\n\n for (let i = 0; i < removedNodes.length; i++) {\n const node = removedNodes[i];\n if (node.parentNode === parent) {\n recordBenchEvent('domRemove');\n teardownNodeSubtree(node);\n parent.removeChild(node);\n }\n }\n}\n"],"mappings":";;;;AAOA,SAAgB,uBACd,QACA,cACM;CACN,IACE,aAAa,SAAS,KACtB,aAAa,WAAW,OAAO,WAAW,QAC1C;EACA,IAAI,eAAe;EACnB,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACvC,IAAI,aAAa,EAAE,CAAC,eAAe,QAAQ;GACzC,eAAe;GACf;EACF;EAGF,IAAI,cAAc;GAChB,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;IAC5C,iBAAiB,WAAW;IAC5B,oBAAoB,aAAa,EAAE;GACrC;GACA,qBAAqB,mBAAmB;IACtC,mBAAmB,kBAAkB;IACrC,OAAO,cAAc;GACvB,CAAC;GACD;EACF;CACF;CAEA,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;EAC5C,MAAM,OAAO,aAAa;EAC1B,IAAI,KAAK,eAAe,QAAQ;GAC9B,iBAAiB,WAAW;GAC5B,oBAAoB,IAAI;GACxB,OAAO,YAAY,IAAI;EACzB;CACF;AACF"}
1
+ {"version":3,"file":"for-commit-removal.js","names":[],"sources":["../../src/renderer/for-commit-removal.ts"],"sourcesContent":["import {\n recordBenchCounter,\n recordBenchEvent,\n withBenchMetricScope,\n} from '../runtime';\nimport { teardownNodeSubtree } from './cleanup';\n\nexport function removeForBoundaryNodes(\n parent: Element,\n removedNodes: Node[]\n): void {\n if (\n removedNodes.length > 0 &&\n removedNodes.length === parent.childNodes.length\n ) {\n let canBulkClear = true;\n for (let i = 0; i < removedNodes.length; i++) {\n if (removedNodes[i].parentNode !== parent) {\n canBulkClear = false;\n break;\n }\n }\n\n if (canBulkClear) {\n for (let i = 0; i < removedNodes.length; i++) {\n recordBenchEvent('domRemove');\n teardownNodeSubtree(removedNodes[i]);\n }\n withBenchMetricScope('fullClear', () => {\n recordBenchCounter('bulkClearCommits');\n parent.textContent = '';\n });\n return;\n }\n }\n\n for (let i = 0; i < removedNodes.length; i++) {\n const node = removedNodes[i];\n if (node.parentNode === parent) {\n recordBenchEvent('domRemove');\n teardownNodeSubtree(node);\n parent.removeChild(node);\n }\n }\n}\n"],"mappings":";;;;AAOA,SAAgB,uBACd,QACA,cACM;CACN,IACE,aAAa,SAAS,KACtB,aAAa,WAAW,OAAO,WAAW,QAC1C;EACA,IAAI,eAAe;EACnB,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KACvC,IAAI,aAAa,EAAE,CAAC,eAAe,QAAQ;GACzC,eAAe;GACf;EACF;EAGF,IAAI,cAAc;GAChB,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;IAC5C,iBAAiB,WAAW;IAC5B,oBAAoB,aAAa,EAAE;GACrC;GACA,qBAAqB,mBAAmB;IACtC,mBAAmB,kBAAkB;IACrC,OAAO,cAAc;GACvB,CAAC;GACD;EACF;CACF;CAEA,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;EAC5C,MAAM,OAAO,aAAa;EAC1B,IAAI,KAAK,eAAe,QAAQ;GAC9B,iBAAiB,WAAW;GAC5B,oBAAoB,IAAI;GACxB,OAAO,YAAY,IAAI;EACzB;CACF;AACF"}
@@ -1,6 +1,6 @@
1
- import { canUseDirectReplaceChildrenSpread } from "./utils.js";
2
1
  import { recordBenchCounter, recordBenchEvent } from "../runtime/for-bench.js";
3
- import "../runtime/for.js";
2
+ import "../runtime/index.js";
3
+ import { canUseDirectReplaceChildrenSpread } from "./utils.js";
4
4
  //#region src/renderer/for-commit-reorder.ts
5
5
  const DENSE_MOVE_MINIMUM = 64;
6
6
  const DENSE_MOVE_RATIO = .75;
@@ -1 +1 @@
1
- {"version":3,"file":"for-commit-reorder.js","names":[],"sources":["../../src/renderer/for-commit-reorder.ts"],"sourcesContent":["import { recordBenchCounter, recordBenchEvent } from '../runtime/for';\nimport { canUseDirectReplaceChildrenSpread } from './utils';\n\nconst DENSE_MOVE_MINIMUM = 64;\nconst DENSE_MOVE_RATIO = 0.75;\n\nexport function replaceChildrenInOrder(\n parent: Element,\n nodes: Node[],\n allowDirectSpread: boolean\n): void {\n if (allowDirectSpread && canUseDirectReplaceChildrenSpread(nodes.length)) {\n parent.replaceChildren(...nodes);\n return;\n }\n\n const fragment = parent.ownerDocument.createDocumentFragment();\n for (let i = 0; i < nodes.length; i++) {\n fragment.appendChild(nodes[i]);\n }\n parent.replaceChildren(fragment);\n}\n\nfunction getLISIndices(sequence: number[]): number[] {\n if (sequence.length === 0) {\n return [];\n }\n\n const predecessors = sequence.slice();\n const lisIndices: number[] = [0];\n\n for (let i = 1; i < sequence.length; i += 1) {\n const current = sequence[i];\n const lastLisIndex = lisIndices[lisIndices.length - 1];\n\n if (sequence[lastLisIndex] < current) {\n predecessors[i] = lastLisIndex;\n lisIndices.push(i);\n continue;\n }\n\n let lo = 0;\n let hi = lisIndices.length - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (sequence[lisIndices[mid]] < current) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n if (current < sequence[lisIndices[lo]]) {\n if (lo > 0) {\n predecessors[i] = lisIndices[lo - 1];\n }\n lisIndices[lo] = i;\n }\n }\n\n let cursor = lisIndices.length - 1;\n let index = lisIndices[cursor];\n while (cursor >= 0) {\n lisIndices[cursor] = index;\n index = predecessors[index];\n cursor -= 1;\n }\n\n return lisIndices;\n}\n\nexport function commitMoveOnlyReorder(parent: Element, nodes: Node[]): boolean {\n const currentNodes = Array.from(parent.childNodes);\n if (currentNodes.length !== nodes.length) {\n return false;\n }\n\n const currentIndexByNode = new Map<Node, number>();\n for (let i = 0; i < currentNodes.length; i += 1) {\n currentIndexByNode.set(currentNodes[i], i);\n }\n\n const positions = Array.from({ length: nodes.length }, () => 0);\n for (let i = 0; i < nodes.length; i += 1) {\n const position = currentIndexByNode.get(nodes[i]);\n if (position === undefined) {\n return false;\n }\n positions[i] = position;\n }\n\n const lisIndices = getLISIndices(positions);\n if (lisIndices.length === nodes.length) {\n return true;\n }\n\n const moveCount = nodes.length - lisIndices.length;\n const denseMoveThreshold = Math.max(\n DENSE_MOVE_MINIMUM,\n Math.floor(nodes.length * DENSE_MOVE_RATIO)\n );\n\n if (moveCount >= denseMoveThreshold) {\n recordBenchEvent('domMove', moveCount);\n recordBenchCounter('replaceChildrenCommits');\n replaceChildrenInOrder(parent, nodes, false);\n return true;\n }\n\n let lisCursor = lisIndices.length - 1;\n let anchor: Node | null = null;\n\n for (let i = nodes.length - 1; i >= 0; i -= 1) {\n const node = nodes[i];\n if (lisCursor >= 0 && i === lisIndices[lisCursor]) {\n anchor = node;\n lisCursor -= 1;\n continue;\n }\n\n if (node.nextSibling !== anchor) {\n recordBenchEvent('domMove');\n parent.insertBefore(node, anchor);\n }\n\n anchor = node;\n }\n\n return true;\n}\n"],"mappings":";;;;AAGA,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AAEzB,SAAgB,uBACd,QACA,OACA,mBACM;CACN,IAAI,qBAAqB,kCAAkC,MAAM,MAAM,GAAG;EACxE,OAAO,gBAAgB,GAAG,KAAK;EAC/B;CACF;CAEA,MAAM,WAAW,OAAO,cAAc,uBAAuB;CAC7D,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAChC,SAAS,YAAY,MAAM,EAAE;CAE/B,OAAO,gBAAgB,QAAQ;AACjC;AAEA,SAAS,cAAc,UAA8B;CACnD,IAAI,SAAS,WAAW,GACtB,OAAO,CAAC;CAGV,MAAM,eAAe,SAAS,MAAM;CACpC,MAAM,aAAuB,CAAC,CAAC;CAE/B,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,GAAG;EAC3C,MAAM,UAAU,SAAS;EACzB,MAAM,eAAe,WAAW,WAAW,SAAS;EAEpD,IAAI,SAAS,gBAAgB,SAAS;GACpC,aAAa,KAAK;GAClB,WAAW,KAAK,CAAC;GACjB;EACF;EAEA,IAAI,KAAK;EACT,IAAI,KAAK,WAAW,SAAS;EAC7B,OAAO,KAAK,IAAI;GACd,MAAM,MAAO,KAAK,MAAO;GACzB,IAAI,SAAS,WAAW,QAAQ,SAC9B,KAAK,MAAM;QAEX,KAAK;EAET;EAEA,IAAI,UAAU,SAAS,WAAW,MAAM;GACtC,IAAI,KAAK,GACP,aAAa,KAAK,WAAW,KAAK;GAEpC,WAAW,MAAM;EACnB;CACF;CAEA,IAAI,SAAS,WAAW,SAAS;CACjC,IAAI,QAAQ,WAAW;CACvB,OAAO,UAAU,GAAG;EAClB,WAAW,UAAU;EACrB,QAAQ,aAAa;EACrB,UAAU;CACZ;CAEA,OAAO;AACT;AAEA,SAAgB,sBAAsB,QAAiB,OAAwB;CAC7E,MAAM,eAAe,MAAM,KAAK,OAAO,UAAU;CACjD,IAAI,aAAa,WAAW,MAAM,QAChC,OAAO;CAGT,MAAM,qCAAqB,IAAI,IAAkB;CACjD,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,GAC5C,mBAAmB,IAAI,aAAa,IAAI,CAAC;CAG3C,MAAM,YAAY,MAAM,KAAK,EAAE,QAAQ,MAAM,OAAO,SAAS,CAAC;CAC9D,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxC,MAAM,WAAW,mBAAmB,IAAI,MAAM,EAAE;EAChD,IAAI,aAAa,QACf,OAAO;EAET,UAAU,KAAK;CACjB;CAEA,MAAM,aAAa,cAAc,SAAS;CAC1C,IAAI,WAAW,WAAW,MAAM,QAC9B,OAAO;CAGT,MAAM,YAAY,MAAM,SAAS,WAAW;CAM5C,IAAI,aALuB,KAAK,IAC9B,oBACA,KAAK,MAAM,MAAM,SAAS,gBAAgB,CAG3B,GAAoB;EACnC,iBAAiB,WAAW,SAAS;EACrC,mBAAmB,wBAAwB;EAC3C,uBAAuB,QAAQ,OAAO,KAAK;EAC3C,OAAO;CACT;CAEA,IAAI,YAAY,WAAW,SAAS;CACpC,IAAI,SAAsB;CAE1B,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;EAC7C,MAAM,OAAO,MAAM;EACnB,IAAI,aAAa,KAAK,MAAM,WAAW,YAAY;GACjD,SAAS;GACT,aAAa;GACb;EACF;EAEA,IAAI,KAAK,gBAAgB,QAAQ;GAC/B,iBAAiB,SAAS;GAC1B,OAAO,aAAa,MAAM,MAAM;EAClC;EAEA,SAAS;CACX;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"for-commit-reorder.js","names":[],"sources":["../../src/renderer/for-commit-reorder.ts"],"sourcesContent":["import { recordBenchCounter, recordBenchEvent } from '../runtime';\nimport { canUseDirectReplaceChildrenSpread } from './utils';\n\nconst DENSE_MOVE_MINIMUM = 64;\nconst DENSE_MOVE_RATIO = 0.75;\n\nexport function replaceChildrenInOrder(\n parent: Element,\n nodes: Node[],\n allowDirectSpread: boolean\n): void {\n if (allowDirectSpread && canUseDirectReplaceChildrenSpread(nodes.length)) {\n parent.replaceChildren(...nodes);\n return;\n }\n\n const fragment = parent.ownerDocument.createDocumentFragment();\n for (let i = 0; i < nodes.length; i++) {\n fragment.appendChild(nodes[i]);\n }\n parent.replaceChildren(fragment);\n}\n\nfunction getLISIndices(sequence: number[]): number[] {\n if (sequence.length === 0) {\n return [];\n }\n\n const predecessors = sequence.slice();\n const lisIndices: number[] = [0];\n\n for (let i = 1; i < sequence.length; i += 1) {\n const current = sequence[i];\n const lastLisIndex = lisIndices[lisIndices.length - 1];\n\n if (sequence[lastLisIndex] < current) {\n predecessors[i] = lastLisIndex;\n lisIndices.push(i);\n continue;\n }\n\n let lo = 0;\n let hi = lisIndices.length - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (sequence[lisIndices[mid]] < current) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n\n if (current < sequence[lisIndices[lo]]) {\n if (lo > 0) {\n predecessors[i] = lisIndices[lo - 1];\n }\n lisIndices[lo] = i;\n }\n }\n\n let cursor = lisIndices.length - 1;\n let index = lisIndices[cursor];\n while (cursor >= 0) {\n lisIndices[cursor] = index;\n index = predecessors[index];\n cursor -= 1;\n }\n\n return lisIndices;\n}\n\nexport function commitMoveOnlyReorder(parent: Element, nodes: Node[]): boolean {\n const currentNodes = Array.from(parent.childNodes);\n if (currentNodes.length !== nodes.length) {\n return false;\n }\n\n const currentIndexByNode = new Map<Node, number>();\n for (let i = 0; i < currentNodes.length; i += 1) {\n currentIndexByNode.set(currentNodes[i], i);\n }\n\n const positions = Array.from({ length: nodes.length }, () => 0);\n for (let i = 0; i < nodes.length; i += 1) {\n const position = currentIndexByNode.get(nodes[i]);\n if (position === undefined) {\n return false;\n }\n positions[i] = position;\n }\n\n const lisIndices = getLISIndices(positions);\n if (lisIndices.length === nodes.length) {\n return true;\n }\n\n const moveCount = nodes.length - lisIndices.length;\n const denseMoveThreshold = Math.max(\n DENSE_MOVE_MINIMUM,\n Math.floor(nodes.length * DENSE_MOVE_RATIO)\n );\n\n if (moveCount >= denseMoveThreshold) {\n recordBenchEvent('domMove', moveCount);\n recordBenchCounter('replaceChildrenCommits');\n replaceChildrenInOrder(parent, nodes, false);\n return true;\n }\n\n let lisCursor = lisIndices.length - 1;\n let anchor: Node | null = null;\n\n for (let i = nodes.length - 1; i >= 0; i -= 1) {\n const node = nodes[i];\n if (lisCursor >= 0 && i === lisIndices[lisCursor]) {\n anchor = node;\n lisCursor -= 1;\n continue;\n }\n\n if (node.nextSibling !== anchor) {\n recordBenchEvent('domMove');\n parent.insertBefore(node, anchor);\n }\n\n anchor = node;\n }\n\n return true;\n}\n"],"mappings":";;;;AAGA,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AAEzB,SAAgB,uBACd,QACA,OACA,mBACM;CACN,IAAI,qBAAqB,kCAAkC,MAAM,MAAM,GAAG;EACxE,OAAO,gBAAgB,GAAG,KAAK;EAC/B;CACF;CAEA,MAAM,WAAW,OAAO,cAAc,uBAAuB;CAC7D,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAChC,SAAS,YAAY,MAAM,EAAE;CAE/B,OAAO,gBAAgB,QAAQ;AACjC;AAEA,SAAS,cAAc,UAA8B;CACnD,IAAI,SAAS,WAAW,GACtB,OAAO,CAAC;CAGV,MAAM,eAAe,SAAS,MAAM;CACpC,MAAM,aAAuB,CAAC,CAAC;CAE/B,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,GAAG;EAC3C,MAAM,UAAU,SAAS;EACzB,MAAM,eAAe,WAAW,WAAW,SAAS;EAEpD,IAAI,SAAS,gBAAgB,SAAS;GACpC,aAAa,KAAK;GAClB,WAAW,KAAK,CAAC;GACjB;EACF;EAEA,IAAI,KAAK;EACT,IAAI,KAAK,WAAW,SAAS;EAC7B,OAAO,KAAK,IAAI;GACd,MAAM,MAAO,KAAK,MAAO;GACzB,IAAI,SAAS,WAAW,QAAQ,SAC9B,KAAK,MAAM;QAEX,KAAK;EAET;EAEA,IAAI,UAAU,SAAS,WAAW,MAAM;GACtC,IAAI,KAAK,GACP,aAAa,KAAK,WAAW,KAAK;GAEpC,WAAW,MAAM;EACnB;CACF;CAEA,IAAI,SAAS,WAAW,SAAS;CACjC,IAAI,QAAQ,WAAW;CACvB,OAAO,UAAU,GAAG;EAClB,WAAW,UAAU;EACrB,QAAQ,aAAa;EACrB,UAAU;CACZ;CAEA,OAAO;AACT;AAEA,SAAgB,sBAAsB,QAAiB,OAAwB;CAC7E,MAAM,eAAe,MAAM,KAAK,OAAO,UAAU;CACjD,IAAI,aAAa,WAAW,MAAM,QAChC,OAAO;CAGT,MAAM,qCAAqB,IAAI,IAAkB;CACjD,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,GAC5C,mBAAmB,IAAI,aAAa,IAAI,CAAC;CAG3C,MAAM,YAAY,MAAM,KAAK,EAAE,QAAQ,MAAM,OAAO,SAAS,CAAC;CAC9D,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxC,MAAM,WAAW,mBAAmB,IAAI,MAAM,EAAE;EAChD,IAAI,aAAa,QACf,OAAO;EAET,UAAU,KAAK;CACjB;CAEA,MAAM,aAAa,cAAc,SAAS;CAC1C,IAAI,WAAW,WAAW,MAAM,QAC9B,OAAO;CAGT,MAAM,YAAY,MAAM,SAAS,WAAW;CAM5C,IAAI,aALuB,KAAK,IAC9B,oBACA,KAAK,MAAM,MAAM,SAAS,gBAAgB,CAG3B,GAAoB;EACnC,iBAAiB,WAAW,SAAS;EACrC,mBAAmB,wBAAwB;EAC3C,uBAAuB,QAAQ,OAAO,KAAK;EAC3C,OAAO;CACT;CAEA,IAAI,YAAY,WAAW,SAAS;CACpC,IAAI,SAAsB;CAE1B,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;EAC7C,MAAM,OAAO,MAAM;EACnB,IAAI,aAAa,KAAK,MAAM,WAAW,YAAY;GACjD,SAAS;GACT,aAAa;GACb;EACF;EAEA,IAAI,KAAK,gBAAgB,QAAQ;GAC/B,iBAAiB,SAAS;GAC1B,OAAO,aAAa,MAAM,MAAM;EAClC;EAEA,SAAS;CACX;CAEA,OAAO;AACT"}
@@ -1,9 +1,9 @@
1
+ import { recordBenchCounter, recordBenchEvent, recordBenchTiming, withBenchMetricScope } from "../runtime/for-bench.js";
2
+ import { clearForDomUpdateState } from "../runtime/for-internal.js";
3
+ import "../runtime/index.js";
1
4
  import { teardownNodeSubtree } from "./cleanup.js";
2
5
  import { canUseDirectReplaceChildrenSpread } from "./utils.js";
3
6
  import { keyedElements } from "./keyed.js";
4
- import { recordBenchCounter, recordBenchEvent, recordBenchTiming, withBenchMetricScope } from "../runtime/for-bench.js";
5
- import { clearForDomUpdateState } from "../runtime/for-internal.js";
6
- import "../runtime/for.js";
7
7
  import { getOrBuildDomKeyMap, hydrateExistingForDomInOrder, syncKeyedMapFromForState } from "./for-commit-dom-map.js";
8
8
  import { commitMoveOnlyReorder, replaceChildrenInOrder } from "./for-commit-reorder.js";
9
9
  import { removeForBoundaryNodes } from "./for-commit-removal.js";
@@ -1 +1 @@
1
- {"version":3,"file":"for-commit.js","names":[],"sources":["../../src/renderer/for-commit.ts"],"sourcesContent":["import type { ChildScope } from '../runtime/child-scope';\nimport {\n clearForDomUpdateState,\n recordBenchCounter,\n recordBenchEvent,\n recordBenchTiming,\n type ForState,\n withBenchMetricScope,\n} from '../runtime/for';\nimport { teardownNodeSubtree } from './cleanup';\nimport { keyedElements } from './keyed';\nimport type { VNode } from './types';\nimport { canUseDirectReplaceChildrenSpread } from './utils';\nimport {\n getOrBuildDomKeyMap,\n hydrateExistingForDomInOrder,\n syncKeyedMapFromForState,\n} from './for-commit-dom-map';\nimport {\n commitMoveOnlyReorder,\n replaceChildrenInOrder,\n} from './for-commit-reorder';\nimport { removeForBoundaryNodes } from './for-commit-removal';\n\nexport interface ForCommitRuntime {\n isProduction(): boolean;\n syncForItemDom(parent: Element, scope: ChildScope, vnode: VNode): Node | null;\n tryPatchStableForDirtyItem(scope: ChildScope): boolean;\n}\n\nexport function commitForStateBoundaryChildren(\n parent: Element,\n forState: ForState<unknown>,\n childrenVNodes: VNode[],\n runtime: ForCommitRuntime\n): void {\n const domCommitStart = performance.now();\n\n const hydrateExistingForDom = (): void => {\n if (hydrateExistingForDomInOrder(parent, forState)) {\n return;\n }\n\n const domKeyMap = getOrBuildDomKeyMap(parent);\n if (!domKeyMap) {\n return;\n }\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemKey = forState.orderedKeys[i];\n const itemInstance = forState.items.get(itemKey);\n if (!itemInstance || itemInstance.scope.dom) {\n continue;\n }\n\n const existingDom = domKeyMap.get(itemKey);\n if (!existingDom) {\n continue;\n }\n\n itemInstance.scope.dom = existingDom;\n itemInstance.scope.needsDomUpdate = true;\n }\n };\n\n if (forState.orderedKeys.length === 0) {\n removeForBoundaryNodes(parent, forState.lastRemovedNodes);\n\n const fallbackScope = forState.fallbackScope;\n const fallbackVNode = childrenVNodes[0];\n const nextDom =\n fallbackScope && fallbackVNode !== undefined\n ? runtime.syncForItemDom(parent, fallbackScope, fallbackVNode)\n : null;\n\n if (nextDom) {\n if (\n parent.childNodes.length !== 1 ||\n parent.firstChild !== nextDom ||\n forState.lastRemovedNodes.length > 0\n ) {\n parent.replaceChildren(nextDom);\n }\n } else if (parent.firstChild) {\n parent.textContent = '';\n }\n\n keyedElements.delete(parent);\n forState._hasResolvedItemDom = false;\n recordBenchTiming('domCommit', performance.now() - domCommitStart);\n clearForDomUpdateState(forState);\n return;\n }\n\n if (!forState._hasResolvedItemDom && parent.childNodes.length > 0) {\n hydrateExistingForDom();\n }\n\n const getDirtyForIndices = (): number[] => {\n const pendingDirtyIndices = forState.pendingDirtyIndices;\n if (pendingDirtyIndices && pendingDirtyIndices.length > 0) {\n return pendingDirtyIndices;\n }\n\n const dirtyIndices: number[] = [];\n for (let index = 0; index < forState.orderedKeys.length; index += 1) {\n const itemInstance = forState.orderedItems[index];\n if (itemInstance?.scope.needsDomUpdate) {\n dirtyIndices.push(index);\n }\n }\n\n return dirtyIndices;\n };\n\n let dirtyIndicesCache: number[] | null = null;\n const ensureDirtyIndices = (): number[] => {\n if (dirtyIndicesCache) {\n return dirtyIndicesCache;\n }\n\n dirtyIndicesCache = getDirtyForIndices();\n return dirtyIndicesCache;\n };\n\n const dirtyIndices =\n forState.lastCommitStrategy === 'NO_REORDER' ? ensureDirtyIndices() : [];\n let boundaryChildrenExact = false;\n\n const commitDirtyNoReorder = (dirtyIndices: number[]): void => {\n if (dirtyIndices.length === 0) {\n boundaryChildrenExact = true;\n return;\n }\n\n const orderedItems = forState.orderedItems;\n const childNodes = parent.childNodes;\n\n for (let dirtyIndex = 0; dirtyIndex < dirtyIndices.length; dirtyIndex++) {\n const i = dirtyIndices[dirtyIndex];\n const itemInstance = orderedItems[i];\n if (!itemInstance) {\n continue;\n }\n\n if (runtime.tryPatchStableForDirtyItem(itemInstance.scope)) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n const anchor = childNodes[i] ?? null;\n if (dom.parentNode !== parent || dom !== anchor) {\n recordBenchEvent('domInsert');\n parent.insertBefore(dom, anchor);\n }\n }\n\n boundaryChildrenExact = true;\n };\n\n const commitPositional = (): void => {\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemInstance = forState.orderedItems[i];\n if (!itemInstance) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n if (dom.parentNode !== parent) {\n const anchor = parent.childNodes[i] ?? null;\n recordBenchEvent('domInsert');\n parent.insertBefore(dom, anchor);\n }\n }\n\n boundaryChildrenExact = true;\n };\n\n const commitAppend = (): void => {\n const canHydrateInPlace =\n !forState._hasResolvedItemDom &&\n forState.lastRemovedNodes.length === 0 &&\n parent.childNodes.length === forState.orderedKeys.length;\n if (canHydrateInPlace) {\n let exactOrder = true;\n let currentNode = parent.firstChild;\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemInstance = forState.orderedItems[i];\n if (!itemInstance) {\n exactOrder = false;\n currentNode = currentNode?.nextSibling ?? null;\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom || dom.parentNode !== parent || dom !== currentNode) {\n exactOrder = false;\n }\n\n currentNode = currentNode?.nextSibling ?? null;\n }\n\n if (exactOrder) {\n boundaryChildrenExact = true;\n return;\n }\n }\n\n withBenchMetricScope('coldCreate', () => {\n const fragment = parent.ownerDocument.createDocumentFragment();\n let hasPendingAppend = false;\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemInstance = forState.orderedItems[i];\n if (!itemInstance) {\n continue;\n }\n\n if (\n itemInstance.scope.dom?.parentNode === parent &&\n !itemInstance.scope.needsDomUpdate\n ) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n if (dom.parentNode !== parent) {\n recordBenchEvent('domInsert');\n fragment.appendChild(dom);\n hasPendingAppend = true;\n }\n }\n\n if (hasPendingAppend) {\n parent.appendChild(fragment);\n }\n });\n\n boundaryChildrenExact = true;\n };\n\n const commitSwap = (): void => {\n const swapIndices = forState.pendingSwapIndices;\n if (!swapIndices) {\n return;\n }\n\n let [firstIndex, secondIndex] = swapIndices;\n if (firstIndex === secondIndex) {\n return;\n }\n\n if (firstIndex > secondIndex) {\n [firstIndex, secondIndex] = [secondIndex, firstIndex];\n }\n\n const firstKey = forState.orderedKeys[firstIndex];\n const secondKey = forState.orderedKeys[secondIndex];\n const firstItem = forState.items.get(firstKey);\n const secondItem = forState.items.get(secondKey);\n\n if (!firstItem || !secondItem) {\n commitReorder();\n return;\n }\n\n const firstDom = runtime.syncForItemDom(\n parent,\n firstItem.scope,\n childrenVNodes[firstIndex]\n );\n const secondDom = runtime.syncForItemDom(\n parent,\n secondItem.scope,\n childrenVNodes[secondIndex]\n );\n\n if (!firstDom || !secondDom) {\n commitReorder();\n return;\n }\n\n if (firstDom.parentNode !== parent || secondDom.parentNode !== parent) {\n commitReorder();\n return;\n }\n\n const firstBeforeSecond =\n (firstDom.compareDocumentPosition(secondDom) &\n Node.DOCUMENT_POSITION_FOLLOWING) !==\n 0;\n if (firstBeforeSecond) {\n boundaryChildrenExact = true;\n return;\n }\n\n const firstNextSibling = firstDom.nextSibling;\n recordBenchEvent('domMove');\n parent.insertBefore(firstDom, secondDom);\n recordBenchEvent('domMove');\n parent.insertBefore(secondDom, firstNextSibling);\n\n boundaryChildrenExact = true;\n };\n\n const commitReorder = (): void => {\n const items = forState.orderedItems;\n const count = items.length;\n\n if (forState.pendingMoveOnly && forState.lastRemovedNodes.length === 0) {\n const nodes = Array<Node>(count);\n let movedCount = 0;\n let insertedCount = 0;\n\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (!itemInstance) {\n return;\n }\n\n const scope = itemInstance.scope;\n const dom =\n scope.dom && !scope.needsDomUpdate\n ? scope.dom\n : runtime.syncForItemDom(parent, scope, childrenVNodes[i]);\n\n if (!dom) {\n return;\n }\n\n if (dom.parentNode === parent) {\n movedCount++;\n } else {\n insertedCount++;\n }\n nodes[i] = dom;\n }\n\n if (!canUseDirectReplaceChildrenSpread(count)) {\n if (movedCount > 0) {\n recordBenchEvent('domMove', movedCount);\n }\n if (insertedCount > 0) {\n recordBenchEvent('domInsert', insertedCount);\n }\n replaceChildrenInOrder(parent, nodes, false);\n boundaryChildrenExact = true;\n return;\n }\n\n if (insertedCount > 0) {\n if (movedCount > 0) {\n recordBenchEvent('domMove', movedCount);\n }\n recordBenchEvent('domInsert', insertedCount);\n replaceChildrenInOrder(parent, nodes, true);\n boundaryChildrenExact = true;\n return;\n }\n\n if (count > 1 && commitMoveOnlyReorder(parent, nodes)) {\n boundaryChildrenExact = true;\n return;\n }\n\n if (movedCount > 0) {\n recordBenchEvent('domMove', movedCount);\n }\n if (insertedCount > 0) {\n recordBenchEvent('domInsert', insertedCount);\n }\n\n replaceChildrenInOrder(parent, nodes, true);\n boundaryChildrenExact = true;\n return;\n }\n\n let hasExistingChild = false;\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (itemInstance?.scope.dom?.parentNode === parent) {\n hasExistingChild = true;\n break;\n }\n }\n\n if (!hasExistingChild) {\n withBenchMetricScope('coldCreate', () => {\n const nodes: Node[] = [];\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (!itemInstance) continue;\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (dom) {\n recordBenchEvent('domInsert');\n nodes.push(dom);\n }\n }\n recordBenchCounter('replaceChildrenCommits');\n replaceChildrenInOrder(parent, nodes, false);\n });\n\n boundaryChildrenExact = true;\n return;\n }\n\n if (forState.lastRemovedNodes.length === 0) {\n const nodes: Node[] = [];\n\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (!itemInstance) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n recordBenchEvent(dom.parentNode === parent ? 'domMove' : 'domInsert');\n nodes.push(dom);\n }\n\n replaceChildrenInOrder(parent, nodes, false);\n boundaryChildrenExact = true;\n return;\n }\n\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (!itemInstance) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n const anchor = parent.childNodes[i] ?? null;\n if (dom !== anchor) {\n recordBenchEvent('domMove');\n parent.insertBefore(dom, anchor);\n }\n }\n\n boundaryChildrenExact = true;\n };\n\n const isLocalOnlyDirtyCommit =\n forState.lastCommitStrategy === 'NO_REORDER' &&\n dirtyIndices.length > 0 &&\n forState.pendingDirtyIndices === null &&\n forState.pendingSwapIndices === null &&\n !forState.pendingMoveOnly &&\n forState.lastRemovedNodes.length === 0 &&\n parent.childNodes.length === forState.orderedKeys.length;\n\n if (isLocalOnlyDirtyCommit) {\n commitDirtyNoReorder(dirtyIndices);\n syncKeyedMapFromForState(parent, forState, 'NO_REORDER', []);\n\n recordBenchTiming('domCommit', performance.now() - domCommitStart);\n clearForDomUpdateState(forState);\n return;\n }\n\n switch (forState.lastCommitStrategy) {\n case 'NO_REORDER':\n commitDirtyNoReorder(dirtyIndices);\n break;\n case 'TRUNCATE':\n commitPositional();\n break;\n case 'APPEND':\n commitAppend();\n break;\n case 'SWAP':\n commitSwap();\n break;\n case 'FULL_KEYED':\n default:\n commitReorder();\n break;\n }\n\n removeForBoundaryNodes(parent, forState.lastRemovedNodes);\n if (forState.lastRemovedNodes.length > 0) {\n boundaryChildrenExact = false;\n }\n syncKeyedMapFromForState(\n parent,\n forState,\n forState.lastCommitStrategy,\n forState.lastRemovedNodes\n );\n\n const syncExactForBoundaryChildren = (): void => {\n const expectedNodes: Node[] = [];\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemInstance = forState.orderedItems[i];\n if (!itemInstance) {\n continue;\n }\n\n const dom =\n itemInstance.scope.dom && !itemInstance.scope.needsDomUpdate\n ? itemInstance.scope.dom\n : runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (dom) {\n expectedNodes.push(dom);\n }\n }\n\n const currentNodes = Array.from(parent.childNodes);\n if (\n currentNodes.length === expectedNodes.length &&\n currentNodes.every((node, index) => node === expectedNodes[index])\n ) {\n return;\n }\n\n const expectedNodeSet = new Set(expectedNodes);\n for (const currentNode of currentNodes) {\n if (expectedNodeSet.has(currentNode)) {\n continue;\n }\n\n teardownNodeSubtree(currentNode);\n\n if (currentNode.parentNode === parent) {\n recordBenchEvent('domRemove');\n currentNode.remove();\n }\n }\n\n replaceChildrenInOrder(parent, expectedNodes, true);\n };\n\n if (!boundaryChildrenExact) {\n syncExactForBoundaryChildren();\n }\n forState._hasResolvedItemDom = true;\n recordBenchTiming('domCommit', performance.now() - domCommitStart);\n clearForDomUpdateState(forState);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"for-commit.js","names":[],"sources":["../../src/renderer/for-commit.ts"],"sourcesContent":["import type { ChildScope } from '../runtime';\nimport {\n clearForDomUpdateState,\n recordBenchCounter,\n recordBenchEvent,\n recordBenchTiming,\n type ForState,\n withBenchMetricScope,\n} from '../runtime';\nimport { teardownNodeSubtree } from './cleanup';\nimport { keyedElements } from './keyed';\nimport type { VNode } from './types';\nimport { canUseDirectReplaceChildrenSpread } from './utils';\nimport {\n getOrBuildDomKeyMap,\n hydrateExistingForDomInOrder,\n syncKeyedMapFromForState,\n} from './for-commit-dom-map';\nimport {\n commitMoveOnlyReorder,\n replaceChildrenInOrder,\n} from './for-commit-reorder';\nimport { removeForBoundaryNodes } from './for-commit-removal';\n\nexport interface ForCommitRuntime {\n isProduction(): boolean;\n syncForItemDom(parent: Element, scope: ChildScope, vnode: VNode): Node | null;\n tryPatchStableForDirtyItem(scope: ChildScope): boolean;\n}\n\nexport function commitForStateBoundaryChildren(\n parent: Element,\n forState: ForState<unknown>,\n childrenVNodes: VNode[],\n runtime: ForCommitRuntime\n): void {\n const domCommitStart = performance.now();\n\n const hydrateExistingForDom = (): void => {\n if (hydrateExistingForDomInOrder(parent, forState)) {\n return;\n }\n\n const domKeyMap = getOrBuildDomKeyMap(parent);\n if (!domKeyMap) {\n return;\n }\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemKey = forState.orderedKeys[i];\n const itemInstance = forState.items.get(itemKey);\n if (!itemInstance || itemInstance.scope.dom) {\n continue;\n }\n\n const existingDom = domKeyMap.get(itemKey);\n if (!existingDom) {\n continue;\n }\n\n itemInstance.scope.dom = existingDom;\n itemInstance.scope.needsDomUpdate = true;\n }\n };\n\n if (forState.orderedKeys.length === 0) {\n removeForBoundaryNodes(parent, forState.lastRemovedNodes);\n\n const fallbackScope = forState.fallbackScope;\n const fallbackVNode = childrenVNodes[0];\n const nextDom =\n fallbackScope && fallbackVNode !== undefined\n ? runtime.syncForItemDom(parent, fallbackScope, fallbackVNode)\n : null;\n\n if (nextDom) {\n if (\n parent.childNodes.length !== 1 ||\n parent.firstChild !== nextDom ||\n forState.lastRemovedNodes.length > 0\n ) {\n parent.replaceChildren(nextDom);\n }\n } else if (parent.firstChild) {\n parent.textContent = '';\n }\n\n keyedElements.delete(parent);\n forState._hasResolvedItemDom = false;\n recordBenchTiming('domCommit', performance.now() - domCommitStart);\n clearForDomUpdateState(forState);\n return;\n }\n\n if (!forState._hasResolvedItemDom && parent.childNodes.length > 0) {\n hydrateExistingForDom();\n }\n\n const getDirtyForIndices = (): number[] => {\n const pendingDirtyIndices = forState.pendingDirtyIndices;\n if (pendingDirtyIndices && pendingDirtyIndices.length > 0) {\n return pendingDirtyIndices;\n }\n\n const dirtyIndices: number[] = [];\n for (let index = 0; index < forState.orderedKeys.length; index += 1) {\n const itemInstance = forState.orderedItems[index];\n if (itemInstance?.scope.needsDomUpdate) {\n dirtyIndices.push(index);\n }\n }\n\n return dirtyIndices;\n };\n\n let dirtyIndicesCache: number[] | null = null;\n const ensureDirtyIndices = (): number[] => {\n if (dirtyIndicesCache) {\n return dirtyIndicesCache;\n }\n\n dirtyIndicesCache = getDirtyForIndices();\n return dirtyIndicesCache;\n };\n\n const dirtyIndices =\n forState.lastCommitStrategy === 'NO_REORDER' ? ensureDirtyIndices() : [];\n let boundaryChildrenExact = false;\n\n const commitDirtyNoReorder = (dirtyIndices: number[]): void => {\n if (dirtyIndices.length === 0) {\n boundaryChildrenExact = true;\n return;\n }\n\n const orderedItems = forState.orderedItems;\n const childNodes = parent.childNodes;\n\n for (let dirtyIndex = 0; dirtyIndex < dirtyIndices.length; dirtyIndex++) {\n const i = dirtyIndices[dirtyIndex];\n const itemInstance = orderedItems[i];\n if (!itemInstance) {\n continue;\n }\n\n if (runtime.tryPatchStableForDirtyItem(itemInstance.scope)) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n const anchor = childNodes[i] ?? null;\n if (dom.parentNode !== parent || dom !== anchor) {\n recordBenchEvent('domInsert');\n parent.insertBefore(dom, anchor);\n }\n }\n\n boundaryChildrenExact = true;\n };\n\n const commitPositional = (): void => {\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemInstance = forState.orderedItems[i];\n if (!itemInstance) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n if (dom.parentNode !== parent) {\n const anchor = parent.childNodes[i] ?? null;\n recordBenchEvent('domInsert');\n parent.insertBefore(dom, anchor);\n }\n }\n\n boundaryChildrenExact = true;\n };\n\n const commitAppend = (): void => {\n const canHydrateInPlace =\n !forState._hasResolvedItemDom &&\n forState.lastRemovedNodes.length === 0 &&\n parent.childNodes.length === forState.orderedKeys.length;\n if (canHydrateInPlace) {\n let exactOrder = true;\n let currentNode = parent.firstChild;\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemInstance = forState.orderedItems[i];\n if (!itemInstance) {\n exactOrder = false;\n currentNode = currentNode?.nextSibling ?? null;\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom || dom.parentNode !== parent || dom !== currentNode) {\n exactOrder = false;\n }\n\n currentNode = currentNode?.nextSibling ?? null;\n }\n\n if (exactOrder) {\n boundaryChildrenExact = true;\n return;\n }\n }\n\n withBenchMetricScope('coldCreate', () => {\n const fragment = parent.ownerDocument.createDocumentFragment();\n let hasPendingAppend = false;\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemInstance = forState.orderedItems[i];\n if (!itemInstance) {\n continue;\n }\n\n if (\n itemInstance.scope.dom?.parentNode === parent &&\n !itemInstance.scope.needsDomUpdate\n ) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n if (dom.parentNode !== parent) {\n recordBenchEvent('domInsert');\n fragment.appendChild(dom);\n hasPendingAppend = true;\n }\n }\n\n if (hasPendingAppend) {\n parent.appendChild(fragment);\n }\n });\n\n boundaryChildrenExact = true;\n };\n\n const commitSwap = (): void => {\n const swapIndices = forState.pendingSwapIndices;\n if (!swapIndices) {\n return;\n }\n\n let [firstIndex, secondIndex] = swapIndices;\n if (firstIndex === secondIndex) {\n return;\n }\n\n if (firstIndex > secondIndex) {\n [firstIndex, secondIndex] = [secondIndex, firstIndex];\n }\n\n const firstKey = forState.orderedKeys[firstIndex];\n const secondKey = forState.orderedKeys[secondIndex];\n const firstItem = forState.items.get(firstKey);\n const secondItem = forState.items.get(secondKey);\n\n if (!firstItem || !secondItem) {\n commitReorder();\n return;\n }\n\n const firstDom = runtime.syncForItemDom(\n parent,\n firstItem.scope,\n childrenVNodes[firstIndex]\n );\n const secondDom = runtime.syncForItemDom(\n parent,\n secondItem.scope,\n childrenVNodes[secondIndex]\n );\n\n if (!firstDom || !secondDom) {\n commitReorder();\n return;\n }\n\n if (firstDom.parentNode !== parent || secondDom.parentNode !== parent) {\n commitReorder();\n return;\n }\n\n const firstBeforeSecond =\n (firstDom.compareDocumentPosition(secondDom) &\n Node.DOCUMENT_POSITION_FOLLOWING) !==\n 0;\n if (firstBeforeSecond) {\n boundaryChildrenExact = true;\n return;\n }\n\n const firstNextSibling = firstDom.nextSibling;\n recordBenchEvent('domMove');\n parent.insertBefore(firstDom, secondDom);\n recordBenchEvent('domMove');\n parent.insertBefore(secondDom, firstNextSibling);\n\n boundaryChildrenExact = true;\n };\n\n const commitReorder = (): void => {\n const items = forState.orderedItems;\n const count = items.length;\n\n if (forState.pendingMoveOnly && forState.lastRemovedNodes.length === 0) {\n const nodes = Array<Node>(count);\n let movedCount = 0;\n let insertedCount = 0;\n\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (!itemInstance) {\n return;\n }\n\n const scope = itemInstance.scope;\n const dom =\n scope.dom && !scope.needsDomUpdate\n ? scope.dom\n : runtime.syncForItemDom(parent, scope, childrenVNodes[i]);\n\n if (!dom) {\n return;\n }\n\n if (dom.parentNode === parent) {\n movedCount++;\n } else {\n insertedCount++;\n }\n nodes[i] = dom;\n }\n\n if (!canUseDirectReplaceChildrenSpread(count)) {\n if (movedCount > 0) {\n recordBenchEvent('domMove', movedCount);\n }\n if (insertedCount > 0) {\n recordBenchEvent('domInsert', insertedCount);\n }\n replaceChildrenInOrder(parent, nodes, false);\n boundaryChildrenExact = true;\n return;\n }\n\n if (insertedCount > 0) {\n if (movedCount > 0) {\n recordBenchEvent('domMove', movedCount);\n }\n recordBenchEvent('domInsert', insertedCount);\n replaceChildrenInOrder(parent, nodes, true);\n boundaryChildrenExact = true;\n return;\n }\n\n if (count > 1 && commitMoveOnlyReorder(parent, nodes)) {\n boundaryChildrenExact = true;\n return;\n }\n\n if (movedCount > 0) {\n recordBenchEvent('domMove', movedCount);\n }\n if (insertedCount > 0) {\n recordBenchEvent('domInsert', insertedCount);\n }\n\n replaceChildrenInOrder(parent, nodes, true);\n boundaryChildrenExact = true;\n return;\n }\n\n let hasExistingChild = false;\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (itemInstance?.scope.dom?.parentNode === parent) {\n hasExistingChild = true;\n break;\n }\n }\n\n if (!hasExistingChild) {\n withBenchMetricScope('coldCreate', () => {\n const nodes: Node[] = [];\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (!itemInstance) continue;\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (dom) {\n recordBenchEvent('domInsert');\n nodes.push(dom);\n }\n }\n recordBenchCounter('replaceChildrenCommits');\n replaceChildrenInOrder(parent, nodes, false);\n });\n\n boundaryChildrenExact = true;\n return;\n }\n\n if (forState.lastRemovedNodes.length === 0) {\n const nodes: Node[] = [];\n\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (!itemInstance) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n recordBenchEvent(dom.parentNode === parent ? 'domMove' : 'domInsert');\n nodes.push(dom);\n }\n\n replaceChildrenInOrder(parent, nodes, false);\n boundaryChildrenExact = true;\n return;\n }\n\n for (let i = 0; i < count; i++) {\n const itemInstance = items[i];\n if (!itemInstance) {\n continue;\n }\n\n const dom = runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (!dom) {\n continue;\n }\n\n const anchor = parent.childNodes[i] ?? null;\n if (dom !== anchor) {\n recordBenchEvent('domMove');\n parent.insertBefore(dom, anchor);\n }\n }\n\n boundaryChildrenExact = true;\n };\n\n const isLocalOnlyDirtyCommit =\n forState.lastCommitStrategy === 'NO_REORDER' &&\n dirtyIndices.length > 0 &&\n forState.pendingDirtyIndices === null &&\n forState.pendingSwapIndices === null &&\n !forState.pendingMoveOnly &&\n forState.lastRemovedNodes.length === 0 &&\n parent.childNodes.length === forState.orderedKeys.length;\n\n if (isLocalOnlyDirtyCommit) {\n commitDirtyNoReorder(dirtyIndices);\n syncKeyedMapFromForState(parent, forState, 'NO_REORDER', []);\n\n recordBenchTiming('domCommit', performance.now() - domCommitStart);\n clearForDomUpdateState(forState);\n return;\n }\n\n switch (forState.lastCommitStrategy) {\n case 'NO_REORDER':\n commitDirtyNoReorder(dirtyIndices);\n break;\n case 'TRUNCATE':\n commitPositional();\n break;\n case 'APPEND':\n commitAppend();\n break;\n case 'SWAP':\n commitSwap();\n break;\n case 'FULL_KEYED':\n default:\n commitReorder();\n break;\n }\n\n removeForBoundaryNodes(parent, forState.lastRemovedNodes);\n if (forState.lastRemovedNodes.length > 0) {\n boundaryChildrenExact = false;\n }\n syncKeyedMapFromForState(\n parent,\n forState,\n forState.lastCommitStrategy,\n forState.lastRemovedNodes\n );\n\n const syncExactForBoundaryChildren = (): void => {\n const expectedNodes: Node[] = [];\n\n for (let i = 0; i < forState.orderedKeys.length; i++) {\n const itemInstance = forState.orderedItems[i];\n if (!itemInstance) {\n continue;\n }\n\n const dom =\n itemInstance.scope.dom && !itemInstance.scope.needsDomUpdate\n ? itemInstance.scope.dom\n : runtime.syncForItemDom(\n parent,\n itemInstance.scope,\n childrenVNodes[i]\n );\n if (dom) {\n expectedNodes.push(dom);\n }\n }\n\n const currentNodes = Array.from(parent.childNodes);\n if (\n currentNodes.length === expectedNodes.length &&\n currentNodes.every((node, index) => node === expectedNodes[index])\n ) {\n return;\n }\n\n const expectedNodeSet = new Set(expectedNodes);\n for (const currentNode of currentNodes) {\n if (expectedNodeSet.has(currentNode)) {\n continue;\n }\n\n teardownNodeSubtree(currentNode);\n\n if (currentNode.parentNode === parent) {\n recordBenchEvent('domRemove');\n currentNode.remove();\n }\n }\n\n replaceChildrenInOrder(parent, expectedNodes, true);\n };\n\n if (!boundaryChildrenExact) {\n syncExactForBoundaryChildren();\n }\n forState._hasResolvedItemDom = true;\n recordBenchTiming('domCommit', performance.now() - domCommitStart);\n clearForDomUpdateState(forState);\n}\n"],"mappings":"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"}
@@ -2,10 +2,12 @@ import { _isDOMElement } from "../common/vnode.js";
2
2
  import "./types.js";
3
3
  import { configureRuntimeRenderer } from "../runtime/runtime.js";
4
4
  import { getDefaultRuntimeInstance } from "../runtime/access.js";
5
+ import "../runtime/index.js";
5
6
  import { REACTIVE_CHILDREN_KEY, cleanupInstanceIfPresent, cleanupInstancesUnder, elementListeners, elementReactivePropsCleanup, elementRefs, removeAllListeners, removeElementListeners, removeElementReactiveProps, removeElementRef, teardownNodeSubtree, updateElementRef } from "./cleanup.js";
6
7
  import { getKeyMapForElement, isKeyedReorderFastPathEligible, populateKeyMapForElement } from "./keyed.js";
7
8
  import "./boundaries.js";
8
- import { isBulkTextFastPathEligible, performBulkPositionalKeyedTextUpdate, performBulkTextReplace } from "./children.js";
9
+ import { performBulkPositionalKeyedTextUpdate } from "./children-fastpath.js";
10
+ import { isBulkTextFastPathEligible, performBulkTextReplace } from "./children.js";
9
11
  import { syncComponentElement } from "./component-host.js";
10
12
  import { setStaticChildSlotsCacheEnabled } from "./static-reuse.js";
11
13
  import { updateElementChildren, updateUnkeyedChildren } from "./element-children.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_evaluate","_markReactivePropsDirtySource"],"sources":["../../src/renderer/index.ts"],"sourcesContent":["// Renderer barrel entrypoint.\n// Keep this file small: re-export the public surface and provide the runtime\n// renderer host used by browser composition.\n\nexport * from './types';\nexport * from './cleanup';\nexport {\n keyedElements,\n getKeyMapForElement,\n populateKeyMapForElement,\n _reconcilerRecordedParents,\n isKeyedReorderFastPathEligible,\n} from './keyed';\nexport * from './dom';\nexport { evaluate, clearDOMRange } from './evaluate';\n\nimport { evaluate as _evaluate } from './evaluate';\nimport { cleanupInstancesUnder, teardownNodeSubtree } from './cleanup';\nimport { isKeyedReorderFastPathEligible, getKeyMapForElement } from './keyed';\nimport { populateKeyMapForElement } from './keyed';\nimport { markReactivePropsDirtySource as _markReactivePropsDirtySource } from './dom';\nimport { getDefaultRuntimeInstance } from '../runtime/access';\nimport {\n configureRuntimeRenderer,\n type AskrRuntime,\n type RuntimeRendererHost,\n} from '../runtime/runtime';\n\nexport function createRendererHost(): RuntimeRendererHost {\n return {\n evaluate: _evaluate,\n cleanupInstancesUnder,\n teardownNodeSubtree,\n populateKeyMapForElement,\n getKeyMapForElement,\n isKeyedReorderFastPathEligible,\n markReactivePropsDirtySource: _markReactivePropsDirtySource,\n };\n}\n\nexport function installRendererBridge(\n runtime: AskrRuntime = getDefaultRuntimeInstance()\n): true {\n configureRuntimeRenderer(createRendererHost(), runtime);\n return true;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA4BA,SAAgB,qBAA0C;CACxD,OAAO;EACKA;EACV;EACA;EACA;EACA;EACA;EAC8BC;CAChC;AACF;AAEA,SAAgB,sBACd,UAAuB,0BAA0B,GAC3C;CACN,yBAAyB,mBAAmB,GAAG,OAAO;CACtD,OAAO;AACT"}
1
+ {"version":3,"file":"index.js","names":["_evaluate","_markReactivePropsDirtySource"],"sources":["../../src/renderer/index.ts"],"sourcesContent":["// Renderer barrel entrypoint.\n// Keep this file small: re-export the public surface and provide the runtime\n// renderer host used by browser composition.\n\nexport * from './types';\nexport * from './cleanup';\nexport {\n keyedElements,\n getKeyMapForElement,\n populateKeyMapForElement,\n _reconcilerRecordedParents,\n isKeyedReorderFastPathEligible,\n} from './keyed';\nexport * from './dom';\nexport { evaluate, clearDOMRange } from './evaluate';\n\nimport { evaluate as _evaluate } from './evaluate';\nimport { cleanupInstancesUnder, teardownNodeSubtree } from './cleanup';\nimport { isKeyedReorderFastPathEligible, getKeyMapForElement } from './keyed';\nimport { populateKeyMapForElement } from './keyed';\nimport { markReactivePropsDirtySource as _markReactivePropsDirtySource } from './dom';\nimport { getDefaultRuntimeInstance } from '../runtime';\nimport {\n configureRuntimeRenderer,\n type AskrRuntime,\n type RuntimeRendererHost,\n} from '../runtime';\n\nexport function createRendererHost(): RuntimeRendererHost {\n return {\n evaluate: _evaluate,\n cleanupInstancesUnder,\n teardownNodeSubtree,\n populateKeyMapForElement,\n getKeyMapForElement,\n isKeyedReorderFastPathEligible,\n markReactivePropsDirtySource: _markReactivePropsDirtySource,\n };\n}\n\nexport function installRendererBridge(\n runtime: AskrRuntime = getDefaultRuntimeInstance()\n): true {\n configureRuntimeRenderer(createRendererHost(), runtime);\n return true;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,qBAA0C;CACxD,OAAO;EACKA;EACV;EACA;EACA;EACA;EACA;EAC8BC;CAChC;AACF;AAEA,SAAgB,sBACd,UAAuB,0BAA0B,GAC3C;CACN,yBAAyB,mBAAmB,GAAG,OAAO;CACtD,OAAO;AACT"}