@askrjs/askr 0.0.50 → 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.
- package/dist/bench/components/benchmark-table.js.map +1 -1
- package/dist/benchmark.js +5 -4
- package/dist/benchmark.js.map +1 -1
- package/dist/bin/askr-ssg.d.ts.map +1 -1
- package/dist/bin/askr-ssg.js.map +1 -1
- package/dist/boot/hydration.js.map +1 -1
- package/dist/boot/index.js +2 -1
- package/dist/boot/index.js.map +1 -1
- package/dist/boot/root-lifecycle.d.ts.map +1 -1
- package/dist/boot/root-lifecycle.js +4 -4
- package/dist/boot/root-lifecycle.js.map +1 -1
- package/dist/boot/route-startup.js.map +1 -1
- package/dist/common/error-boundary.d.ts +16 -0
- package/dist/common/error-boundary.d.ts.map +1 -0
- package/dist/common/invariant.js +17 -0
- package/dist/common/invariant.js.map +1 -0
- package/dist/{dev → common}/logger.js +5 -6
- package/dist/common/logger.js.map +1 -0
- package/dist/common/vnode.js.map +1 -1
- package/dist/components/error-boundary.d.ts +2 -15
- package/dist/components/error-boundary.d.ts.map +1 -1
- package/dist/components/error-boundary.js +2 -74
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/index.d.ts +2 -1
- package/dist/components/link.js +2 -0
- package/dist/components/link.js.map +1 -1
- package/dist/control/case.d.ts.map +1 -1
- package/dist/control/case.js +1 -0
- package/dist/control/case.js.map +1 -1
- package/dist/control/for.d.ts +3 -3
- package/dist/control/for.d.ts.map +1 -1
- package/dist/control/for.js +2 -2
- package/dist/control/for.js.map +1 -1
- package/dist/control/show.js +1 -0
- package/dist/control/show.js.map +1 -1
- package/dist/data/data-runtime.js.map +1 -1
- package/dist/data/invalidation.js +2 -2
- package/dist/data/invalidation.js.map +1 -1
- package/dist/data/mutation-cell.d.ts.map +1 -1
- package/dist/data/mutation-cell.js +1 -1
- package/dist/data/mutation-cell.js.map +1 -1
- package/dist/data/query-cell.js +2 -2
- package/dist/data/query-cell.js.map +1 -1
- package/dist/data/shared.js +1 -0
- package/dist/data/shared.js.map +1 -1
- package/dist/data/testing.js +2 -0
- package/dist/foundations/index.d.ts +1 -1
- package/dist/foundations/index.js +1 -1
- package/dist/foundations/state/controllable.d.ts +0 -1
- package/dist/foundations/state/controllable.d.ts.map +1 -1
- package/dist/foundations/state/controllable.js +1 -0
- package/dist/foundations/state/controllable.js.map +1 -1
- package/dist/foundations/structures/index.d.ts +1 -1
- package/dist/foundations/structures/index.js +2 -1
- package/dist/foundations/structures/portal.d.ts +2 -24
- package/dist/foundations/structures/portal.js +3 -187
- package/dist/fx/fx.js +2 -2
- package/dist/fx/fx.js.map +1 -1
- package/dist/fx/index.js +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/jsx/types.d.ts.map +1 -1
- package/dist/jsx-dev-runtime.js +1 -0
- package/dist/jsx-dev-runtime.js.map +1 -1
- package/dist/jsx-runtime.js +1 -0
- package/dist/jsx-runtime.js.map +1 -1
- package/dist/renderer/attributes.js +1 -0
- package/dist/renderer/attributes.js.map +1 -1
- package/dist/renderer/boundaries.js +5 -5
- package/dist/renderer/boundaries.js.map +1 -1
- package/dist/renderer/child-shape.js +2 -2
- package/dist/renderer/child-shape.js.map +1 -1
- package/dist/renderer/children-fastpath.js +149 -0
- package/dist/renderer/children-fastpath.js.map +1 -0
- package/dist/renderer/children.js +3 -138
- package/dist/renderer/children.js.map +1 -1
- package/dist/renderer/cleanup.js +2 -2
- package/dist/renderer/cleanup.js.map +1 -1
- package/dist/renderer/component-host-cleanup.js +1 -1
- package/dist/renderer/component-host-cleanup.js.map +1 -1
- package/dist/renderer/component-host-instances.js +1 -1
- package/dist/renderer/component-host-instances.js.map +1 -1
- package/dist/renderer/component-host.js +1 -1
- package/dist/renderer/component-host.js.map +1 -1
- package/dist/renderer/dom-host.js.map +1 -1
- package/dist/renderer/dom-internal.js +5 -4
- package/dist/renderer/dom-internal.js.map +1 -1
- package/dist/renderer/dom.js +2 -1
- package/dist/renderer/element-children.js.map +1 -1
- package/dist/renderer/error-boundary-dom.js +51 -2
- package/dist/renderer/error-boundary-dom.js.map +1 -1
- package/dist/renderer/evaluate-reconcile.js +6 -5
- package/dist/renderer/evaluate-reconcile.js.map +1 -1
- package/dist/renderer/evaluate.js.map +1 -1
- package/dist/renderer/fastpath.js +3 -2
- package/dist/renderer/fastpath.js.map +1 -1
- package/dist/renderer/for-commit-dom-map.js.map +1 -1
- package/dist/renderer/for-commit-removal.js +2 -2
- package/dist/renderer/for-commit-removal.js.map +1 -1
- package/dist/renderer/for-commit-reorder.js +2 -2
- package/dist/renderer/for-commit-reorder.js.map +1 -1
- package/dist/renderer/for-commit.js +3 -3
- package/dist/renderer/for-commit.js.map +1 -1
- package/dist/renderer/index.js +3 -1
- package/dist/renderer/index.js.map +1 -1
- package/dist/renderer/prop-bindings.js +4 -4
- package/dist/renderer/prop-bindings.js.map +1 -1
- package/dist/renderer/reactive-child-dom.js.map +1 -1
- package/dist/renderer/reactive-children.js +4 -4
- package/dist/renderer/reactive-children.js.map +1 -1
- package/dist/renderer/reconcile-fastpaths.js +2 -1
- package/dist/renderer/reconcile-fastpaths.js.map +1 -1
- package/dist/renderer/reconcile-resolution.js +3 -3
- package/dist/renderer/reconcile-resolution.js.map +1 -1
- package/dist/renderer/retained-element-rollback.js +2 -1
- package/dist/renderer/retained-element-rollback.js.map +1 -1
- package/dist/renderer/stable-patch.js +2 -3
- package/dist/renderer/stable-patch.js.map +1 -1
- package/dist/renderer/utils.js +2 -1
- package/dist/renderer/utils.js.map +1 -1
- package/dist/resources/index.js +1 -2
- package/dist/router/activity.d.ts.map +1 -1
- package/dist/router/activity.js +20 -22
- package/dist/router/activity.js.map +1 -1
- package/dist/router/authoring.js +1 -1
- package/dist/router/authoring.js.map +1 -1
- package/dist/router/index.d.ts +1 -1
- package/dist/router/navigate.js +1 -1
- package/dist/router/navigate.js.map +1 -1
- package/dist/router/navigation-registry.js +1 -1
- package/dist/router/navigation-registry.js.map +1 -1
- package/dist/router/navigation-targets.d.ts.map +1 -1
- package/dist/router/navigation-targets.js +7 -5
- package/dist/router/navigation-targets.js.map +1 -1
- package/dist/router/rendering.js +1 -0
- package/dist/router/rendering.js.map +1 -1
- package/dist/router/resolution.d.ts +1 -14
- package/dist/router/resolution.d.ts.map +1 -1
- package/dist/router/resolution.js +6 -173
- package/dist/router/resolution.js.map +1 -1
- package/dist/router/route-matching.d.ts +20 -0
- package/dist/router/route-matching.d.ts.map +1 -0
- package/dist/router/route-matching.js +175 -0
- package/dist/router/route-matching.js.map +1 -0
- package/dist/router/route.js +4 -2
- package/dist/router/testing.js +4 -0
- package/dist/runtime/access.d.ts +20 -0
- package/dist/runtime/access.d.ts.map +1 -0
- package/dist/runtime/component-cleanup.js +1 -1
- package/dist/runtime/component-cleanup.js.map +1 -1
- package/dist/runtime/component-commit.js +1 -1
- package/dist/runtime/component-commit.js.map +1 -1
- package/dist/runtime/component-internal.d.ts +1 -1
- package/dist/runtime/component-internal.js +1 -1
- package/dist/runtime/component-internal.js.map +1 -1
- package/dist/runtime/component-lifecycle.d.ts +1 -1
- package/dist/runtime/component-lifecycle.js +1 -1
- package/dist/runtime/component-lifecycle.js.map +1 -1
- package/dist/runtime/component-scope.d.ts +1 -1
- package/dist/runtime/dev-namespace.d.ts +31 -0
- package/dist/runtime/dev-namespace.d.ts.map +1 -0
- package/dist/runtime/error-boundary.d.ts +5 -0
- package/dist/runtime/error-boundary.d.ts.map +1 -0
- package/dist/runtime/error-boundary.js +31 -0
- package/dist/runtime/error-boundary.js.map +1 -0
- package/dist/runtime/events.d.ts +58 -0
- package/dist/runtime/events.d.ts.map +1 -0
- package/dist/runtime/events.js +1 -1
- package/dist/runtime/events.js.map +1 -1
- package/dist/runtime/execution-model.d.ts +7 -0
- package/dist/runtime/execution-model.d.ts.map +1 -0
- package/dist/runtime/fastlane.d.ts +34 -0
- package/dist/runtime/fastlane.d.ts.map +1 -0
- package/dist/runtime/for-internal.d.ts +5 -5
- package/dist/runtime/for-internal.d.ts.map +1 -1
- package/dist/runtime/for-internal.js.map +1 -1
- package/dist/runtime/for-signals.d.ts +1 -1
- package/dist/runtime/for-signals.d.ts.map +1 -1
- package/dist/runtime/for-signals.js +1 -1
- package/dist/runtime/for-signals.js.map +1 -1
- package/dist/runtime/for-types.d.ts +9 -0
- package/dist/runtime/for-types.d.ts.map +1 -0
- package/dist/runtime/index.d.ts +24 -0
- package/dist/runtime/index.js +31 -0
- package/dist/runtime/perf-metrics.d.ts +26 -0
- package/dist/runtime/perf-metrics.d.ts.map +1 -0
- package/dist/runtime/portal.d.ts +22 -0
- package/dist/runtime/portal.d.ts.map +1 -0
- package/dist/runtime/portal.js +213 -0
- package/dist/runtime/portal.js.map +1 -0
- package/dist/runtime/resource-cell.js +1 -1
- package/dist/runtime/resource-cell.js.map +1 -1
- package/dist/runtime/resource-operation.js +1 -1
- package/dist/runtime/runtime.d.ts +1 -1
- package/dist/runtime/scheduler.js +2 -2
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/selector-store.js +24 -0
- package/dist/runtime/selector-store.js.map +1 -0
- package/dist/runtime/selector.d.ts.map +1 -1
- package/dist/runtime/selector.js +3 -18
- package/dist/runtime/selector.js.map +1 -1
- package/dist/ssg/create-static-gen.js +1 -0
- package/dist/ssg/create-static-gen.js.map +1 -1
- package/dist/ssg/static-routes.js +1 -0
- package/dist/ssg/static-routes.js.map +1 -1
- package/dist/ssr/boundaries.js +2 -2
- package/dist/ssr/boundaries.js.map +1 -1
- package/dist/ssr/component-runtime.js +3 -3
- package/dist/ssr/component-runtime.js.map +1 -1
- package/dist/ssr/render-resolved.js +1 -1
- package/dist/ssr/render-sync.js +1 -1
- package/dist/ssr/render-sync.js.map +1 -1
- package/dist/ssr/route-policy-resolution.js +2 -1
- package/dist/ssr/route-policy-resolution.js.map +1 -1
- package/dist/ssr/route-render.js +2 -1
- package/dist/ssr/route-render.js.map +1 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +3 -2
- package/dist/testing/index.js.map +1 -1
- package/package.json +4 -4
- package/dist/dev/invariant.js +0 -29
- package/dist/dev/invariant.js.map +0 -1
- package/dist/dev/logger.js.map +0 -1
- package/dist/foundations/structures/portal.d.ts.map +0 -1
- package/dist/foundations/structures/portal.js.map +0 -1
- package/dist/runtime/component-contracts.js +0 -5
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { getRuntimeEnv } from "../common/env.js";
|
|
2
|
-
import { logger } from "../
|
|
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":"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"}
|
|
@@ -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
|
|
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/
|
|
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
|
|
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/
|
|
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
|
|
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":";;;;;;;;;;AA8BA,SAAgB,+BACd,QACA,UACA,gBACA,SACM;CACN,MAAM,iBAAiB,YAAY,IAAI;CAEvC,MAAM,8BAAoC;EACxC,IAAI,6BAA6B,QAAQ,QAAQ,GAC/C;EAGF,MAAM,YAAY,oBAAoB,MAAM;EAC5C,IAAI,CAAC,WACH;EAGF,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,YAAY,QAAQ,KAAK;GACpD,MAAM,UAAU,SAAS,YAAY;GACrC,MAAM,eAAe,SAAS,MAAM,IAAI,OAAO;GAC/C,IAAI,CAAC,gBAAgB,aAAa,MAAM,KACtC;GAGF,MAAM,cAAc,UAAU,IAAI,OAAO;GACzC,IAAI,CAAC,aACH;GAGF,aAAa,MAAM,MAAM;GACzB,aAAa,MAAM,iBAAiB;EACtC;CACF;CAEA,IAAI,SAAS,YAAY,WAAW,GAAG;EACrC,uBAAuB,QAAQ,SAAS,gBAAgB;EAExD,MAAM,gBAAgB,SAAS;EAC/B,MAAM,gBAAgB,eAAe;EACrC,MAAM,UACJ,iBAAiB,kBAAkB,SAC/B,QAAQ,eAAe,QAAQ,eAAe,aAAa,IAC3D;EAEN,IAAI,SACF;OACE,OAAO,WAAW,WAAW,KAC7B,OAAO,eAAe,WACtB,SAAS,iBAAiB,SAAS,GAEnC,OAAO,gBAAgB,OAAO;EAChC,OACK,IAAI,OAAO,YAChB,OAAO,cAAc;EAGvB,cAAc,OAAO,MAAM;EAC3B,SAAS,sBAAsB;EAC/B,kBAAkB,aAAa,YAAY,IAAI,IAAI,cAAc;EACjE,uBAAuB,QAAQ;EAC/B;CACF;CAEA,IAAI,CAAC,SAAS,uBAAuB,OAAO,WAAW,SAAS,GAC9D,sBAAsB;CAGxB,MAAM,2BAAqC;EACzC,MAAM,sBAAsB,SAAS;EACrC,IAAI,uBAAuB,oBAAoB,SAAS,GACtD,OAAO;EAGT,MAAM,eAAyB,CAAC;EAChC,KAAK,IAAI,QAAQ,GAAG,QAAQ,SAAS,YAAY,QAAQ,SAAS,GAEhE,IADqB,SAAS,aAAa,MACvC,EAAc,MAAM,gBACtB,aAAa,KAAK,KAAK;EAI3B,OAAO;CACT;CAEA,IAAI,oBAAqC;CACzC,MAAM,2BAAqC;EACzC,IAAI,mBACF,OAAO;EAGT,oBAAoB,mBAAmB;EACvC,OAAO;CACT;CAEA,MAAM,eACJ,SAAS,uBAAuB,eAAe,mBAAmB,IAAI,CAAC;CACzE,IAAI,wBAAwB;CAE5B,MAAM,wBAAwB,iBAAiC;EAC7D,IAAI,aAAa,WAAW,GAAG;GAC7B,wBAAwB;GACxB;EACF;EAEA,MAAM,eAAe,SAAS;EAC9B,MAAM,aAAa,OAAO;EAE1B,KAAK,IAAI,aAAa,GAAG,aAAa,aAAa,QAAQ,cAAc;GACvE,MAAM,IAAI,aAAa;GACvB,MAAM,eAAe,aAAa;GAClC,IAAI,CAAC,cACH;GAGF,IAAI,QAAQ,2BAA2B,aAAa,KAAK,GACvD;GAGF,MAAM,MAAM,QAAQ,eAClB,QACA,aAAa,OACb,eAAe,EACjB;GACA,IAAI,CAAC,KACH;GAGF,MAAM,SAAS,WAAW,MAAM;GAChC,IAAI,IAAI,eAAe,UAAU,QAAQ,QAAQ;IAC/C,iBAAiB,WAAW;IAC5B,OAAO,aAAa,KAAK,MAAM;GACjC;EACF;EAEA,wBAAwB;CAC1B;CAEA,MAAM,yBAA+B;EACnC,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,YAAY,QAAQ,KAAK;GACpD,MAAM,eAAe,SAAS,aAAa;GAC3C,IAAI,CAAC,cACH;GAGF,MAAM,MAAM,QAAQ,eAClB,QACA,aAAa,OACb,eAAe,EACjB;GACA,IAAI,CAAC,KACH;GAGF,IAAI,IAAI,eAAe,QAAQ;IAC7B,MAAM,SAAS,OAAO,WAAW,MAAM;IACvC,iBAAiB,WAAW;IAC5B,OAAO,aAAa,KAAK,MAAM;GACjC;EACF;EAEA,wBAAwB;CAC1B;CAEA,MAAM,qBAA2B;EAK/B,IAHE,CAAC,SAAS,uBACV,SAAS,iBAAiB,WAAW,KACrC,OAAO,WAAW,WAAW,SAAS,YAAY,QAC7B;GACrB,IAAI,aAAa;GACjB,IAAI,cAAc,OAAO;GAEzB,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,YAAY,QAAQ,KAAK;IACpD,MAAM,eAAe,SAAS,aAAa;IAC3C,IAAI,CAAC,cAAc;KACjB,aAAa;KACb,cAAc,aAAa,eAAe;KAC1C;IACF;IAEA,MAAM,MAAM,QAAQ,eAClB,QACA,aAAa,OACb,eAAe,EACjB;IACA,IAAI,CAAC,OAAO,IAAI,eAAe,UAAU,QAAQ,aAC/C,aAAa;IAGf,cAAc,aAAa,eAAe;GAC5C;GAEA,IAAI,YAAY;IACd,wBAAwB;IACxB;GACF;EACF;EAEA,qBAAqB,oBAAoB;GACvC,MAAM,WAAW,OAAO,cAAc,uBAAuB;GAC7D,IAAI,mBAAmB;GAEvB,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,YAAY,QAAQ,KAAK;IACpD,MAAM,eAAe,SAAS,aAAa;IAC3C,IAAI,CAAC,cACH;IAGF,IACE,aAAa,MAAM,KAAK,eAAe,UACvC,CAAC,aAAa,MAAM,gBAEpB;IAGF,MAAM,MAAM,QAAQ,eAClB,QACA,aAAa,OACb,eAAe,EACjB;IACA,IAAI,CAAC,KACH;IAGF,IAAI,IAAI,eAAe,QAAQ;KAC7B,iBAAiB,WAAW;KAC5B,SAAS,YAAY,GAAG;KACxB,mBAAmB;IACrB;GACF;GAEA,IAAI,kBACF,OAAO,YAAY,QAAQ;EAE/B,CAAC;EAED,wBAAwB;CAC1B;CAEA,MAAM,mBAAyB;EAC7B,MAAM,cAAc,SAAS;EAC7B,IAAI,CAAC,aACH;EAGF,IAAI,CAAC,YAAY,eAAe;EAChC,IAAI,eAAe,aACjB;EAGF,IAAI,aAAa,aACf,CAAC,YAAY,eAAe,CAAC,aAAa,UAAU;EAGtD,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,YAAY,SAAS,YAAY;EACvC,MAAM,YAAY,SAAS,MAAM,IAAI,QAAQ;EAC7C,MAAM,aAAa,SAAS,MAAM,IAAI,SAAS;EAE/C,IAAI,CAAC,aAAa,CAAC,YAAY;GAC7B,cAAc;GACd;EACF;EAEA,MAAM,WAAW,QAAQ,eACvB,QACA,UAAU,OACV,eAAe,WACjB;EACA,MAAM,YAAY,QAAQ,eACxB,QACA,WAAW,OACX,eAAe,YACjB;EAEA,IAAI,CAAC,YAAY,CAAC,WAAW;GAC3B,cAAc;GACd;EACF;EAEA,IAAI,SAAS,eAAe,UAAU,UAAU,eAAe,QAAQ;GACrE,cAAc;GACd;EACF;EAMA,KAHG,SAAS,wBAAwB,SAAS,IACzC,KAAK,iCACP,GACqB;GACrB,wBAAwB;GACxB;EACF;EAEA,MAAM,mBAAmB,SAAS;EAClC,iBAAiB,SAAS;EAC1B,OAAO,aAAa,UAAU,SAAS;EACvC,iBAAiB,SAAS;EAC1B,OAAO,aAAa,WAAW,gBAAgB;EAE/C,wBAAwB;CAC1B;CAEA,MAAM,sBAA4B;EAChC,MAAM,QAAQ,SAAS;EACvB,MAAM,QAAQ,MAAM;EAEpB,IAAI,SAAS,mBAAmB,SAAS,iBAAiB,WAAW,GAAG;GACtE,MAAM,QAAQ,MAAY,KAAK;GAC/B,IAAI,aAAa;GACjB,IAAI,gBAAgB;GAEpB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;IAC9B,MAAM,eAAe,MAAM;IAC3B,IAAI,CAAC,cACH;IAGF,MAAM,QAAQ,aAAa;IAC3B,MAAM,MACJ,MAAM,OAAO,CAAC,MAAM,iBAChB,MAAM,MACN,QAAQ,eAAe,QAAQ,OAAO,eAAe,EAAE;IAE7D,IAAI,CAAC,KACH;IAGF,IAAI,IAAI,eAAe,QACrB;SAEA;IAEF,MAAM,KAAK;GACb;GAEA,IAAI,CAAC,kCAAkC,KAAK,GAAG;IAC7C,IAAI,aAAa,GACf,iBAAiB,WAAW,UAAU;IAExC,IAAI,gBAAgB,GAClB,iBAAiB,aAAa,aAAa;IAE7C,uBAAuB,QAAQ,OAAO,KAAK;IAC3C,wBAAwB;IACxB;GACF;GAEA,IAAI,gBAAgB,GAAG;IACrB,IAAI,aAAa,GACf,iBAAiB,WAAW,UAAU;IAExC,iBAAiB,aAAa,aAAa;IAC3C,uBAAuB,QAAQ,OAAO,IAAI;IAC1C,wBAAwB;IACxB;GACF;GAEA,IAAI,QAAQ,KAAK,sBAAsB,QAAQ,KAAK,GAAG;IACrD,wBAAwB;IACxB;GACF;GAEA,IAAI,aAAa,GACf,iBAAiB,WAAW,UAAU;GAExC,IAAI,gBAAgB,GAClB,iBAAiB,aAAa,aAAa;GAG7C,uBAAuB,QAAQ,OAAO,IAAI;GAC1C,wBAAwB;GACxB;EACF;EAEA,IAAI,mBAAmB;EACvB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAEzB,IADqB,MAAM,EACvB,EAAc,MAAM,KAAK,eAAe,QAAQ;GAClD,mBAAmB;GACnB;EACF;EAGF,IAAI,CAAC,kBAAkB;GACrB,qBAAqB,oBAAoB;IACvC,MAAM,QAAgB,CAAC;IACvB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;KAC9B,MAAM,eAAe,MAAM;KAC3B,IAAI,CAAC,cAAc;KACnB,MAAM,MAAM,QAAQ,eAClB,QACA,aAAa,OACb,eAAe,EACjB;KACA,IAAI,KAAK;MACP,iBAAiB,WAAW;MAC5B,MAAM,KAAK,GAAG;KAChB;IACF;IACA,mBAAmB,wBAAwB;IAC3C,uBAAuB,QAAQ,OAAO,KAAK;GAC7C,CAAC;GAED,wBAAwB;GACxB;EACF;EAEA,IAAI,SAAS,iBAAiB,WAAW,GAAG;GAC1C,MAAM,QAAgB,CAAC;GAEvB,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;IAC9B,MAAM,eAAe,MAAM;IAC3B,IAAI,CAAC,cACH;IAGF,MAAM,MAAM,QAAQ,eAClB,QACA,aAAa,OACb,eAAe,EACjB;IACA,IAAI,CAAC,KACH;IAGF,iBAAiB,IAAI,eAAe,SAAS,YAAY,WAAW;IACpE,MAAM,KAAK,GAAG;GAChB;GAEA,uBAAuB,QAAQ,OAAO,KAAK;GAC3C,wBAAwB;GACxB;EACF;EAEA,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK;GAC9B,MAAM,eAAe,MAAM;GAC3B,IAAI,CAAC,cACH;GAGF,MAAM,MAAM,QAAQ,eAClB,QACA,aAAa,OACb,eAAe,EACjB;GACA,IAAI,CAAC,KACH;GAGF,MAAM,SAAS,OAAO,WAAW,MAAM;GACvC,IAAI,QAAQ,QAAQ;IAClB,iBAAiB,SAAS;IAC1B,OAAO,aAAa,KAAK,MAAM;GACjC;EACF;EAEA,wBAAwB;CAC1B;CAWA,IARE,SAAS,uBAAuB,gBAChC,aAAa,SAAS,KACtB,SAAS,wBAAwB,QACjC,SAAS,uBAAuB,QAChC,CAAC,SAAS,mBACV,SAAS,iBAAiB,WAAW,KACrC,OAAO,WAAW,WAAW,SAAS,YAAY,QAExB;EAC1B,qBAAqB,YAAY;EACjC,yBAAyB,QAAQ,UAAU,cAAc,CAAC,CAAC;EAE3D,kBAAkB,aAAa,YAAY,IAAI,IAAI,cAAc;EACjE,uBAAuB,QAAQ;EAC/B;CACF;CAEA,QAAQ,SAAS,oBAAjB;EACE,KAAK;GACH,qBAAqB,YAAY;GACjC;EACF,KAAK;GACH,iBAAiB;GACjB;EACF,KAAK;GACH,aAAa;GACb;EACF,KAAK;GACH,WAAW;GACX;EAEF;GACE,cAAc;GACd;CACJ;CAEA,uBAAuB,QAAQ,SAAS,gBAAgB;CACxD,IAAI,SAAS,iBAAiB,SAAS,GACrC,wBAAwB;CAE1B,yBACE,QACA,UACA,SAAS,oBACT,SAAS,gBACX;CAEA,MAAM,qCAA2C;EAC/C,MAAM,gBAAwB,CAAC;EAE/B,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,YAAY,QAAQ,KAAK;GACpD,MAAM,eAAe,SAAS,aAAa;GAC3C,IAAI,CAAC,cACH;GAGF,MAAM,MACJ,aAAa,MAAM,OAAO,CAAC,aAAa,MAAM,iBAC1C,aAAa,MAAM,MACnB,QAAQ,eACN,QACA,aAAa,OACb,eAAe,EACjB;GACN,IAAI,KACF,cAAc,KAAK,GAAG;EAE1B;EAEA,MAAM,eAAe,MAAM,KAAK,OAAO,UAAU;EACjD,IACE,aAAa,WAAW,cAAc,UACtC,aAAa,OAAO,MAAM,UAAU,SAAS,cAAc,MAAM,GAEjE;EAGF,MAAM,kBAAkB,IAAI,IAAI,aAAa;EAC7C,KAAK,MAAM,eAAe,cAAc;GACtC,IAAI,gBAAgB,IAAI,WAAW,GACjC;GAGF,oBAAoB,WAAW;GAE/B,IAAI,YAAY,eAAe,QAAQ;IACrC,iBAAiB,WAAW;IAC5B,YAAY,OAAO;GACrB;EACF;EAEA,uBAAuB,QAAQ,eAAe,IAAI;CACpD;CAEA,IAAI,CAAC,uBACH,6BAA6B;CAE/B,SAAS,sBAAsB;CAC/B,kBAAkB,aAAa,YAAY,IAAI,IAAI,cAAc;CACjE,uBAAuB,QAAQ;AACjC"}
|
|
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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"}
|
package/dist/renderer/index.js
CHANGED
|
@@ -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 {
|
|
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
|
|
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"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { getRuntimeEnv } from "../common/env.js";
|
|
2
|
-
import { logger } from "../
|
|
2
|
+
import { logger } from "../common/logger.js";
|
|
3
3
|
import { incrementPerfMetric } from "../runtime/perf-metrics.js";
|
|
4
4
|
import { incDevCounter } from "../runtime/dev-namespace.js";
|
|
5
|
+
import { createFineGrainedEffect, markFineGrainedEffectsDirtySource } from "../runtime/effect.js";
|
|
5
6
|
import { addDelegatedListener, getDelegatedHandlerForElement, getDelegatedHandlersForElement, isDelegatedEvent, isEventDelegationEnabled, removeDelegatedListener, updateDelegatedListener } from "../runtime/events.js";
|
|
7
|
+
import { isBenchMetricScopeActive, recordBenchCounter } from "../runtime/for-bench.js";
|
|
8
|
+
import "../runtime/index.js";
|
|
6
9
|
import { REACTIVE_CHILDREN_KEY, elementListeners, elementReactivePropsCleanup, updateElementRef } from "./cleanup.js";
|
|
7
10
|
import "./env.js";
|
|
8
11
|
import { createMutableWrappedHandler, getEventListenerKey, getEventListenerOptions, isSkippedProp, parseEventProp } from "./utils.js";
|
|
9
|
-
import { isBenchMetricScopeActive, recordBenchCounter } from "../runtime/for-bench.js";
|
|
10
|
-
import "../runtime/for.js";
|
|
11
12
|
import { applyScalarPropValue, removeStaleAttributes } from "./attributes.js";
|
|
12
|
-
import { createFineGrainedEffect, markFineGrainedEffectsDirtySource } from "../runtime/effect.js";
|
|
13
13
|
//#region src/renderer/prop-bindings.ts
|
|
14
14
|
const reactivePropRegistry = /* @__PURE__ */ new Set();
|
|
15
15
|
function addTrackedListener(el, eventName, handler, capture = false) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prop-bindings.js","names":[],"sources":["../../src/renderer/prop-bindings.ts"],"sourcesContent":["import { logger } from '../dev/logger';\nimport { incDevCounter } from '../runtime/dev-namespace';\nimport {\n createFineGrainedEffect,\n markFineGrainedEffectsDirtySource,\n type FineGrainedEffectHandle,\n} from '../runtime/effect';\nimport { isBenchMetricScopeActive, recordBenchCounter } from '../runtime/for';\nimport { incrementPerfMetric } from '../runtime/perf-metrics';\nimport type { ReadableSource } from '../runtime/readable';\nimport {\n isEventDelegationEnabled,\n addDelegatedListener,\n getDelegatedHandlerForElement,\n getDelegatedHandlersForElement,\n updateDelegatedListener,\n removeDelegatedListener,\n isDelegatedEvent,\n} from '../runtime/events';\nimport { applyScalarPropValue, removeStaleAttributes } from './attributes';\nimport {\n elementListeners,\n elementReactivePropsCleanup,\n REACTIVE_CHILDREN_KEY,\n type ReactivePropCleanupEntry,\n updateElementRef,\n} from './cleanup';\nimport { getRuntimeEnv } from './env';\nimport type { DOMElement } from './types';\nimport {\n createMutableWrappedHandler,\n getEventListenerKey,\n getEventListenerOptions,\n isSkippedProp,\n parseEventProp,\n} from './utils';\n\ninterface ReactivePropDescriptor {\n el: Element;\n propName: string;\n propFn: () => unknown;\n tagName: string;\n lastClassTokens: string[] | null;\n}\n\nconst reactivePropRegistry = new Set<ReactivePropDescriptor>();\n\nfunction addTrackedListener(\n el: Element,\n eventName: string,\n handler: EventListener,\n capture = false\n): void {\n const useDelegation =\n !capture && isEventDelegationEnabled() && isDelegatedEvent(eventName);\n const listenerKey = getEventListenerKey(eventName, capture);\n\n if (useDelegation) {\n addDelegatedListener(el, eventName, handler, handler, undefined);\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('listenerBindings');\n }\n return;\n }\n\n const options = getEventListenerOptions(eventName, capture);\n const mutableHandler = createMutableWrappedHandler(handler, true);\n const trackedHandler = mutableHandler.handler;\n\n if (options !== undefined) {\n el.addEventListener(eventName, trackedHandler, options);\n } else {\n el.addEventListener(eventName, trackedHandler);\n }\n incDevCounter('listenerAdds');\n\n if (!elementListeners.has(el)) {\n elementListeners.set(el, new Map());\n }\n elementListeners.get(el)!.set(listenerKey, {\n handler: trackedHandler,\n original: handler,\n eventName,\n options,\n isDelegated: false,\n updateHandler: mutableHandler?.updateHandler,\n });\n\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('listenerBindings');\n }\n}\n\nexport function markReactivePropsDirtySource(\n source: ReadableSource<unknown>\n): void {\n markFineGrainedEffectsDirtySource(source);\n}\n\nfunction setupReactiveProp(\n el: Element,\n propName: string,\n propFn: () => unknown,\n tagName: string\n): { cleanup: () => void; updateFn: (nextFn: () => unknown) => void } {\n const descriptor: ReactivePropDescriptor = {\n el,\n propName,\n propFn,\n tagName,\n lastClassTokens: null,\n };\n\n let effectHandle: FineGrainedEffectHandle<unknown> | null = null;\n\n reactivePropRegistry.add(descriptor);\n effectHandle = createFineGrainedEffect({\n lane: 'reactive',\n compute: () => descriptor.propFn(),\n commit: (value, previousValue) => {\n incrementPerfMetric('reactivePropReevaluations');\n applyScalarPropValue(\n el,\n propName,\n value,\n tagName,\n previousValue,\n descriptor\n );\n },\n equals: (previousValue, nextValue) => {\n if (Object.is(previousValue, nextValue)) {\n incrementPerfMetric('skippedDomPropWrites');\n return true;\n }\n return false;\n },\n onError: (err) => {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive prop update failed:', err);\n }\n },\n });\n\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('reactivePropsMounted');\n }\n\n const cleanup = () => {\n reactivePropRegistry.delete(descriptor);\n effectHandle?.cleanup();\n effectHandle = null;\n };\n\n const updateFn = (nextFn: () => unknown): void => {\n if (!effectHandle) {\n return;\n }\n\n descriptor.propFn = nextFn;\n\n try {\n effectHandle.updateCompute(nextFn);\n } catch (err) {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive prop update failed:', err);\n }\n }\n };\n\n return {\n cleanup,\n updateFn,\n };\n}\n\nfunction getOrCreateReactivePropsCleanupMap(\n el: Element\n): Map<string, ReactivePropCleanupEntry> {\n let cleanupMap = elementReactivePropsCleanup.get(el);\n if (!cleanupMap) {\n cleanupMap = new Map();\n elementReactivePropsCleanup.set(el, cleanupMap);\n }\n return cleanupMap;\n}\n\nfunction createReactivePropCleanupEntry(\n el: Element,\n propName: string,\n propFn: () => unknown,\n tagName: string\n): ReactivePropCleanupEntry {\n const reactive = setupReactiveProp(el, propName, propFn, tagName);\n\n return {\n cleanup: reactive.cleanup,\n updateFn: (nextValue) => {\n reactive.updateFn(nextValue as () => unknown);\n },\n restoreFn: (nextValue) =>\n createReactivePropCleanupEntry(\n el,\n propName,\n nextValue as () => unknown,\n tagName\n ),\n fnRef: propFn,\n };\n}\n\nexport function hasTrackedElementPropBindings(el: Element): boolean {\n const existingListeners = elementListeners.get(el);\n const existingReactiveProps = elementReactivePropsCleanup.get(el);\n return (\n (existingListeners !== undefined && existingListeners.size > 0) ||\n (existingReactiveProps !== undefined && existingReactiveProps.size > 0)\n );\n}\n\nexport function applyPropsToElement(\n el: Element,\n props: Record<string, unknown>,\n tagName: string,\n isHydrationSkipped: (el: Element) => boolean\n): void {\n if (isHydrationSkipped(el)) {\n return;\n }\n\n for (const key in props) {\n const value = props[key];\n if (key === 'ref') {\n updateElementRef(el, value);\n continue;\n }\n if (isSkippedProp(key)) continue;\n if (value === undefined || value === null || value === false) continue;\n\n const eventProp = parseEventProp(key);\n if (eventProp) {\n addTrackedListener(\n el,\n eventProp.eventName,\n value as EventListener,\n eventProp.capture\n );\n continue;\n }\n\n if (typeof value === 'function' && key !== 'ref') {\n getOrCreateReactivePropsCleanupMap(el).set(\n key,\n createReactivePropCleanupEntry(el, key, value as () => unknown, tagName)\n );\n continue;\n }\n\n applyScalarPropValue(el, key, value, tagName);\n }\n}\n\nexport function syncElementPropBindings(\n el: Element,\n domVNode: DOMElement,\n props: Record<string, unknown>,\n usesReactiveChildren: boolean\n): void {\n const existingListeners = elementListeners.get(el);\n const existingReactiveProps = elementReactivePropsCleanup.get(el);\n\n let desiredListenerKeys: Set<string> | null = null;\n let desiredDelegatedEventNames: Set<string> | null = null;\n let desiredReactivePropNames: Set<string> | null = null;\n\n if (usesReactiveChildren) {\n (desiredReactivePropNames ??= new Set()).add(REACTIVE_CHILDREN_KEY);\n }\n\n for (const key in props) {\n const value = props[key];\n if (key === 'ref') continue;\n if (isSkippedProp(key)) continue;\n\n const eventProp = parseEventProp(key);\n const eventName = eventProp?.eventName;\n const eventCapture = eventProp?.capture ?? false;\n const listenerKey =\n eventName === undefined\n ? null\n : getEventListenerKey(eventName, eventCapture);\n\n if (value === undefined || value === null || value === false) {\n if (listenerKey && existingListeners?.has(listenerKey)) {\n const entry = existingListeners.get(listenerKey)!;\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n existingListeners.delete(listenerKey);\n } else {\n const entry = existingReactiveProps?.get(key);\n if (entry) {\n entry.cleanup();\n existingReactiveProps?.delete(key);\n } else {\n applyScalarPropValue(el, key, value, domVNode.type as string);\n }\n }\n continue;\n }\n\n if (typeof value === 'function' && !eventProp && key !== 'ref') {\n const existingEntry = existingReactiveProps?.get(key);\n if (existingReactiveProps && existingReactiveProps.size > 0) {\n (desiredReactivePropNames ??= new Set()).add(key);\n }\n\n if (existingEntry && existingEntry.fnRef === value) {\n continue;\n }\n\n if (existingEntry?.updateFn) {\n existingEntry.updateFn(value as () => unknown);\n existingEntry.fnRef = value as () => unknown;\n continue;\n }\n\n if (existingEntry) {\n existingEntry.cleanup();\n }\n\n getOrCreateReactivePropsCleanupMap(el).set(\n key,\n createReactivePropCleanupEntry(\n el,\n key,\n value as () => unknown,\n domVNode.type as string\n )\n );\n continue;\n }\n\n const existingReactiveEntry = existingReactiveProps?.get(key);\n if (existingReactiveEntry) {\n existingReactiveEntry.cleanup();\n existingReactiveProps?.delete(key);\n }\n\n if (eventProp && listenerKey) {\n const eventName = eventProp.eventName;\n const eventCapture = eventProp.capture;\n const useDelegation =\n !eventCapture &&\n isEventDelegationEnabled() &&\n isDelegatedEvent(eventName);\n if (useDelegation) {\n (desiredDelegatedEventNames ??= new Set()).add(eventName);\n }\n\n if (useDelegation) {\n const existingDelegated = getDelegatedHandlerForElement(el, eventName);\n if (existingDelegated?.original === value) {\n continue;\n }\n\n if (\n existingDelegated &&\n updateDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n )\n ) {\n continue;\n }\n\n addDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n );\n continue;\n }\n\n (desiredListenerKeys ??= new Set()).add(listenerKey);\n\n const existing = existingListeners?.get(listenerKey);\n\n if (existing && existing.original === value) {\n continue;\n }\n\n if (existing) {\n if (\n useDelegation &&\n existing.isDelegated &&\n updateDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n )\n ) {\n existing.handler = value as EventListener;\n existing.original = value as EventListener;\n existing.options = undefined;\n continue;\n }\n\n if (!useDelegation && !existing.isDelegated && existing.updateHandler) {\n existing.updateHandler(value as EventListener);\n existing.original = value as EventListener;\n continue;\n }\n\n if (existing.isDelegated) {\n removeDelegatedListener(el, existing.eventName);\n } else {\n if (existing.options !== undefined) {\n el.removeEventListener(\n existing.eventName,\n existing.handler,\n existing.options\n );\n } else {\n el.removeEventListener(existing.eventName, existing.handler);\n }\n }\n }\n\n const options = getEventListenerOptions(eventName, eventCapture);\n const mutableHandler = createMutableWrappedHandler(\n value as EventListener,\n true\n );\n const trackedHandler = mutableHandler.handler;\n\n if (options !== undefined) {\n el.addEventListener(eventName, trackedHandler, options);\n } else {\n el.addEventListener(eventName, trackedHandler);\n }\n incDevCounter('listenerAdds');\n\n const listenerEntry = {\n handler: trackedHandler,\n original: value as EventListener,\n eventName,\n options,\n isDelegated: false,\n updateHandler: mutableHandler?.updateHandler,\n };\n if (!elementListeners.has(el)) {\n elementListeners.set(el, new Map());\n }\n elementListeners.get(el)!.set(listenerKey, listenerEntry);\n } else {\n applyScalarPropValue(el, key, value, domVNode.type as string);\n }\n }\n\n removeStaleAttributes(el, domVNode, props);\n\n if (existingListeners && existingListeners.size > 0) {\n if (desiredListenerKeys === null) {\n existingListeners.forEach((entry) => {\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n });\n elementListeners.delete(el);\n } else {\n existingListeners.forEach((entry, listenerKey) => {\n if (!desiredListenerKeys.has(listenerKey)) {\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n existingListeners.delete(listenerKey);\n }\n });\n if (existingListeners.size === 0) elementListeners.delete(el);\n }\n }\n\n const delegatedHandlers = getDelegatedHandlersForElement(el);\n if (delegatedHandlers && delegatedHandlers.size > 0) {\n if (desiredDelegatedEventNames === null) {\n for (const eventName of delegatedHandlers.keys()) {\n removeDelegatedListener(el, eventName);\n }\n } else {\n for (const eventName of delegatedHandlers.keys()) {\n if (!desiredDelegatedEventNames.has(eventName)) {\n removeDelegatedListener(el, eventName);\n }\n }\n }\n }\n\n if (existingReactiveProps && existingReactiveProps.size > 0) {\n if (desiredReactivePropNames === null) {\n existingReactiveProps.forEach((entry) => {\n entry.cleanup();\n });\n elementReactivePropsCleanup.delete(el);\n } else {\n existingReactiveProps.forEach((entry, key) => {\n if (!desiredReactivePropNames.has(key)) {\n entry.cleanup();\n existingReactiveProps.delete(key);\n }\n });\n if (existingReactiveProps.size === 0) {\n elementReactivePropsCleanup.delete(el);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;AA6CA,MAAM,uCAAuB,IAAI,IAA4B;AAE7D,SAAS,mBACP,IACA,WACA,SACA,UAAU,OACJ;CACN,MAAM,gBACJ,CAAC,WAAW,yBAAyB,KAAK,iBAAiB,SAAS;CACtE,MAAM,cAAc,oBAAoB,WAAW,OAAO;CAE1D,IAAI,eAAe;EACjB,qBAAqB,IAAI,WAAW,SAAS,SAAS,MAAS;EAC/D,IAAI,yBAAyB,YAAY,GACvC,mBAAmB,kBAAkB;EAEvC;CACF;CAEA,MAAM,UAAU,wBAAwB,WAAW,OAAO;CAC1D,MAAM,iBAAiB,4BAA4B,SAAS,IAAI;CAChE,MAAM,iBAAiB,eAAe;CAEtC,IAAI,YAAY,QACd,GAAG,iBAAiB,WAAW,gBAAgB,OAAO;MAEtD,GAAG,iBAAiB,WAAW,cAAc;CAE/C,cAAc,cAAc;CAE5B,IAAI,CAAC,iBAAiB,IAAI,EAAE,GAC1B,iBAAiB,IAAI,oBAAI,IAAI,IAAI,CAAC;CAEpC,iBAAiB,IAAI,EAAE,CAAC,CAAE,IAAI,aAAa;EACzC,SAAS;EACT,UAAU;EACV;EACA;EACA,aAAa;EACb,eAAe,gBAAgB;CACjC,CAAC;CAED,IAAI,yBAAyB,YAAY,GACvC,mBAAmB,kBAAkB;AAEzC;AAEA,SAAgB,6BACd,QACM;CACN,kCAAkC,MAAM;AAC1C;AAEA,SAAS,kBACP,IACA,UACA,QACA,SACoE;CACpE,MAAM,aAAqC;EACzC;EACA;EACA;EACA;EACA,iBAAiB;CACnB;CAEA,IAAI,eAAwD;CAE5D,qBAAqB,IAAI,UAAU;CACnC,eAAe,wBAAwB;EACrC,MAAM;EACN,eAAe,WAAW,OAAO;EACjC,SAAS,OAAO,kBAAkB;GAChC,oBAAoB,2BAA2B;GAC/C,qBACE,IACA,UACA,OACA,SACA,eACA,UACF;EACF;EACA,SAAS,eAAe,cAAc;GACpC,IAAI,OAAO,GAAG,eAAe,SAAS,GAAG;IACvC,oBAAoB,sBAAsB;IAC1C,OAAO;GACT;GACA,OAAO;EACT;EACA,UAAU,QAAQ;GAChB,IAAI,cAAc,CAAC,CAAC,aAAa,cAC/B,OAAO,KAAK,uCAAuC,GAAG;EAE1D;CACF,CAAC;CAED,IAAI,yBAAyB,YAAY,GACvC,mBAAmB,sBAAsB;CAG3C,MAAM,gBAAgB;EACpB,qBAAqB,OAAO,UAAU;EACtC,cAAc,QAAQ;EACtB,eAAe;CACjB;CAEA,MAAM,YAAY,WAAgC;EAChD,IAAI,CAAC,cACH;EAGF,WAAW,SAAS;EAEpB,IAAI;GACF,aAAa,cAAc,MAAM;EACnC,SAAS,KAAK;GACZ,IAAI,cAAc,CAAC,CAAC,aAAa,cAC/B,OAAO,KAAK,uCAAuC,GAAG;EAE1D;CACF;CAEA,OAAO;EACL;EACA;CACF;AACF;AAEA,SAAS,mCACP,IACuC;CACvC,IAAI,aAAa,4BAA4B,IAAI,EAAE;CACnD,IAAI,CAAC,YAAY;EACf,6BAAa,IAAI,IAAI;EACrB,4BAA4B,IAAI,IAAI,UAAU;CAChD;CACA,OAAO;AACT;AAEA,SAAS,+BACP,IACA,UACA,QACA,SAC0B;CAC1B,MAAM,WAAW,kBAAkB,IAAI,UAAU,QAAQ,OAAO;CAEhE,OAAO;EACL,SAAS,SAAS;EAClB,WAAW,cAAc;GACvB,SAAS,SAAS,SAA0B;EAC9C;EACA,YAAY,cACV,+BACE,IACA,UACA,WACA,OACF;EACF,OAAO;CACT;AACF;AAEA,SAAgB,8BAA8B,IAAsB;CAClE,MAAM,oBAAoB,iBAAiB,IAAI,EAAE;CACjD,MAAM,wBAAwB,4BAA4B,IAAI,EAAE;CAChE,OACG,sBAAsB,UAAa,kBAAkB,OAAO,KAC5D,0BAA0B,UAAa,sBAAsB,OAAO;AAEzE;AAEA,SAAgB,oBACd,IACA,OACA,SACA,oBACM;CACN,IAAI,mBAAmB,EAAE,GACvB;CAGF,KAAK,MAAM,OAAO,OAAO;EACvB,MAAM,QAAQ,MAAM;EACpB,IAAI,QAAQ,OAAO;GACjB,iBAAiB,IAAI,KAAK;GAC1B;EACF;EACA,IAAI,cAAc,GAAG,GAAG;EACxB,IAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,OAAO;EAE9D,MAAM,YAAY,eAAe,GAAG;EACpC,IAAI,WAAW;GACb,mBACE,IACA,UAAU,WACV,OACA,UAAU,OACZ;GACA;EACF;EAEA,IAAI,OAAO,UAAU,cAAc,QAAQ,OAAO;GAChD,mCAAmC,EAAE,CAAC,CAAC,IACrC,KACA,+BAA+B,IAAI,KAAK,OAAwB,OAAO,CACzE;GACA;EACF;EAEA,qBAAqB,IAAI,KAAK,OAAO,OAAO;CAC9C;AACF;AAEA,SAAgB,wBACd,IACA,UACA,OACA,sBACM;CACN,MAAM,oBAAoB,iBAAiB,IAAI,EAAE;CACjD,MAAM,wBAAwB,4BAA4B,IAAI,EAAE;CAEhE,IAAI,sBAA0C;CAC9C,IAAI,6BAAiD;CACrD,IAAI,2BAA+C;CAEnD,IAAI,sBACF,CAAC,6CAA6B,IAAI,IAAI,EAAA,CAAG,IAAI,qBAAqB;CAGpE,KAAK,MAAM,OAAO,OAAO;EACvB,MAAM,QAAQ,MAAM;EACpB,IAAI,QAAQ,OAAO;EACnB,IAAI,cAAc,GAAG,GAAG;EAExB,MAAM,YAAY,eAAe,GAAG;EACpC,MAAM,YAAY,WAAW;EAC7B,MAAM,eAAe,WAAW,WAAW;EAC3C,MAAM,cACJ,cAAc,SACV,OACA,oBAAoB,WAAW,YAAY;EAEjD,IAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,OAAO;GAC5D,IAAI,eAAe,mBAAmB,IAAI,WAAW,GAAG;IACtD,MAAM,QAAQ,kBAAkB,IAAI,WAAW;IAC/C,cAAc,iBAAiB;IAC/B,IAAI,MAAM,aACR,wBAAwB,IAAI,MAAM,SAAS;SAE3C,IAAI,MAAM,YAAY,QACpB,GAAG,oBACD,MAAM,WACN,MAAM,SACN,MAAM,OACR;SAEA,GAAG,oBAAoB,MAAM,WAAW,MAAM,OAAO;IAGzD,kBAAkB,OAAO,WAAW;GACtC,OAAO;IACL,MAAM,QAAQ,uBAAuB,IAAI,GAAG;IAC5C,IAAI,OAAO;KACT,MAAM,QAAQ;KACd,uBAAuB,OAAO,GAAG;IACnC,OACE,qBAAqB,IAAI,KAAK,OAAO,SAAS,IAAc;GAEhE;GACA;EACF;EAEA,IAAI,OAAO,UAAU,cAAc,CAAC,aAAa,QAAQ,OAAO;GAC9D,MAAM,gBAAgB,uBAAuB,IAAI,GAAG;GACpD,IAAI,yBAAyB,sBAAsB,OAAO,GACxD,CAAC,6CAA6B,IAAI,IAAI,EAAA,CAAG,IAAI,GAAG;GAGlD,IAAI,iBAAiB,cAAc,UAAU,OAC3C;GAGF,IAAI,eAAe,UAAU;IAC3B,cAAc,SAAS,KAAsB;IAC7C,cAAc,QAAQ;IACtB;GACF;GAEA,IAAI,eACF,cAAc,QAAQ;GAGxB,mCAAmC,EAAE,CAAC,CAAC,IACrC,KACA,+BACE,IACA,KACA,OACA,SAAS,IACX,CACF;GACA;EACF;EAEA,MAAM,wBAAwB,uBAAuB,IAAI,GAAG;EAC5D,IAAI,uBAAuB;GACzB,sBAAsB,QAAQ;GAC9B,uBAAuB,OAAO,GAAG;EACnC;EAEA,IAAI,aAAa,aAAa;GAC5B,MAAM,YAAY,UAAU;GAC5B,MAAM,eAAe,UAAU;GAC/B,MAAM,gBACJ,CAAC,gBACD,yBAAyB,KACzB,iBAAiB,SAAS;GAC5B,IAAI,eACF,CAAC,+CAA+B,IAAI,IAAI,EAAA,CAAG,IAAI,SAAS;GAG1D,IAAI,eAAe;IACjB,MAAM,oBAAoB,8BAA8B,IAAI,SAAS;IACrE,IAAI,mBAAmB,aAAa,OAClC;IAGF,IACE,qBACA,wBACE,IACA,WACA,OACA,OACA,MACF,GAEA;IAGF,qBACE,IACA,WACA,OACA,OACA,MACF;IACA;GACF;GAEA,CAAC,wCAAwB,IAAI,IAAI,EAAA,CAAG,IAAI,WAAW;GAEnD,MAAM,WAAW,mBAAmB,IAAI,WAAW;GAEnD,IAAI,YAAY,SAAS,aAAa,OACpC;GAGF,IAAI,UAAU;IACZ,IACE,iBACA,SAAS,eACT,wBACE,IACA,WACA,OACA,OACA,MACF,GACA;KACA,SAAS,UAAU;KACnB,SAAS,WAAW;KACpB,SAAS,UAAU;KACnB;IACF;IAEA,IAAI,CAAC,iBAAiB,CAAC,SAAS,eAAe,SAAS,eAAe;KACrE,SAAS,cAAc,KAAsB;KAC7C,SAAS,WAAW;KACpB;IACF;IAEA,IAAI,SAAS,aACX,wBAAwB,IAAI,SAAS,SAAS;SAE9C,IAAI,SAAS,YAAY,QACvB,GAAG,oBACD,SAAS,WACT,SAAS,SACT,SAAS,OACX;SAEA,GAAG,oBAAoB,SAAS,WAAW,SAAS,OAAO;GAGjE;GAEA,MAAM,UAAU,wBAAwB,WAAW,YAAY;GAC/D,MAAM,iBAAiB,4BACrB,OACA,IACF;GACA,MAAM,iBAAiB,eAAe;GAEtC,IAAI,YAAY,QACd,GAAG,iBAAiB,WAAW,gBAAgB,OAAO;QAEtD,GAAG,iBAAiB,WAAW,cAAc;GAE/C,cAAc,cAAc;GAE5B,MAAM,gBAAgB;IACpB,SAAS;IACT,UAAU;IACV;IACA;IACA,aAAa;IACb,eAAe,gBAAgB;GACjC;GACA,IAAI,CAAC,iBAAiB,IAAI,EAAE,GAC1B,iBAAiB,IAAI,oBAAI,IAAI,IAAI,CAAC;GAEpC,iBAAiB,IAAI,EAAE,CAAC,CAAE,IAAI,aAAa,aAAa;EAC1D,OACE,qBAAqB,IAAI,KAAK,OAAO,SAAS,IAAc;CAEhE;CAEA,sBAAsB,IAAI,UAAU,KAAK;CAEzC,IAAI,qBAAqB,kBAAkB,OAAO,GAChD,IAAI,wBAAwB,MAAM;EAChC,kBAAkB,SAAS,UAAU;GACnC,cAAc,iBAAiB;GAC/B,IAAI,MAAM,aACR,wBAAwB,IAAI,MAAM,SAAS;QAE3C,IAAI,MAAM,YAAY,QACpB,GAAG,oBACD,MAAM,WACN,MAAM,SACN,MAAM,OACR;QAEA,GAAG,oBAAoB,MAAM,WAAW,MAAM,OAAO;EAG3D,CAAC;EACD,iBAAiB,OAAO,EAAE;CAC5B,OAAO;EACL,kBAAkB,SAAS,OAAO,gBAAgB;GAChD,IAAI,CAAC,oBAAoB,IAAI,WAAW,GAAG;IACzC,cAAc,iBAAiB;IAC/B,IAAI,MAAM,aACR,wBAAwB,IAAI,MAAM,SAAS;SAE3C,IAAI,MAAM,YAAY,QACpB,GAAG,oBACD,MAAM,WACN,MAAM,SACN,MAAM,OACR;SAEA,GAAG,oBAAoB,MAAM,WAAW,MAAM,OAAO;IAGzD,kBAAkB,OAAO,WAAW;GACtC;EACF,CAAC;EACD,IAAI,kBAAkB,SAAS,GAAG,iBAAiB,OAAO,EAAE;CAC9D;CAGF,MAAM,oBAAoB,+BAA+B,EAAE;CAC3D,IAAI,qBAAqB,kBAAkB,OAAO,GAChD;MAAI,+BAA+B,MACjC,KAAK,MAAM,aAAa,kBAAkB,KAAK,GAC7C,wBAAwB,IAAI,SAAS;OAGvC,KAAK,MAAM,aAAa,kBAAkB,KAAK,GAC7C,IAAI,CAAC,2BAA2B,IAAI,SAAS,GAC3C,wBAAwB,IAAI,SAAS;CAG3C;CAGF,IAAI,yBAAyB,sBAAsB,OAAO,GACxD,IAAI,6BAA6B,MAAM;EACrC,sBAAsB,SAAS,UAAU;GACvC,MAAM,QAAQ;EAChB,CAAC;EACD,4BAA4B,OAAO,EAAE;CACvC,OAAO;EACL,sBAAsB,SAAS,OAAO,QAAQ;GAC5C,IAAI,CAAC,yBAAyB,IAAI,GAAG,GAAG;IACtC,MAAM,QAAQ;IACd,sBAAsB,OAAO,GAAG;GAClC;EACF,CAAC;EACD,IAAI,sBAAsB,SAAS,GACjC,4BAA4B,OAAO,EAAE;CAEzC;AAEJ"}
|
|
1
|
+
{"version":3,"file":"prop-bindings.js","names":[],"sources":["../../src/renderer/prop-bindings.ts"],"sourcesContent":["import { logger } from '../common/logger';\nimport { incDevCounter } from '../runtime';\nimport {\n createFineGrainedEffect,\n markFineGrainedEffectsDirtySource,\n type FineGrainedEffectHandle,\n} from '../runtime';\nimport { isBenchMetricScopeActive, recordBenchCounter } from '../runtime';\nimport { incrementPerfMetric } from '../runtime';\nimport type { ReadableSource } from '../runtime';\nimport {\n isEventDelegationEnabled,\n addDelegatedListener,\n getDelegatedHandlerForElement,\n getDelegatedHandlersForElement,\n updateDelegatedListener,\n removeDelegatedListener,\n isDelegatedEvent,\n} from '../runtime';\nimport { applyScalarPropValue, removeStaleAttributes } from './attributes';\nimport {\n elementListeners,\n elementReactivePropsCleanup,\n REACTIVE_CHILDREN_KEY,\n type ReactivePropCleanupEntry,\n updateElementRef,\n} from './cleanup';\nimport { getRuntimeEnv } from './env';\nimport type { DOMElement } from './types';\nimport {\n createMutableWrappedHandler,\n getEventListenerKey,\n getEventListenerOptions,\n isSkippedProp,\n parseEventProp,\n} from './utils';\n\ninterface ReactivePropDescriptor {\n el: Element;\n propName: string;\n propFn: () => unknown;\n tagName: string;\n lastClassTokens: string[] | null;\n}\n\nconst reactivePropRegistry = new Set<ReactivePropDescriptor>();\n\nfunction addTrackedListener(\n el: Element,\n eventName: string,\n handler: EventListener,\n capture = false\n): void {\n const useDelegation =\n !capture && isEventDelegationEnabled() && isDelegatedEvent(eventName);\n const listenerKey = getEventListenerKey(eventName, capture);\n\n if (useDelegation) {\n addDelegatedListener(el, eventName, handler, handler, undefined);\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('listenerBindings');\n }\n return;\n }\n\n const options = getEventListenerOptions(eventName, capture);\n const mutableHandler = createMutableWrappedHandler(handler, true);\n const trackedHandler = mutableHandler.handler;\n\n if (options !== undefined) {\n el.addEventListener(eventName, trackedHandler, options);\n } else {\n el.addEventListener(eventName, trackedHandler);\n }\n incDevCounter('listenerAdds');\n\n if (!elementListeners.has(el)) {\n elementListeners.set(el, new Map());\n }\n elementListeners.get(el)!.set(listenerKey, {\n handler: trackedHandler,\n original: handler,\n eventName,\n options,\n isDelegated: false,\n updateHandler: mutableHandler?.updateHandler,\n });\n\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('listenerBindings');\n }\n}\n\nexport function markReactivePropsDirtySource(\n source: ReadableSource<unknown>\n): void {\n markFineGrainedEffectsDirtySource(source);\n}\n\nfunction setupReactiveProp(\n el: Element,\n propName: string,\n propFn: () => unknown,\n tagName: string\n): { cleanup: () => void; updateFn: (nextFn: () => unknown) => void } {\n const descriptor: ReactivePropDescriptor = {\n el,\n propName,\n propFn,\n tagName,\n lastClassTokens: null,\n };\n\n let effectHandle: FineGrainedEffectHandle<unknown> | null = null;\n\n reactivePropRegistry.add(descriptor);\n effectHandle = createFineGrainedEffect({\n lane: 'reactive',\n compute: () => descriptor.propFn(),\n commit: (value, previousValue) => {\n incrementPerfMetric('reactivePropReevaluations');\n applyScalarPropValue(\n el,\n propName,\n value,\n tagName,\n previousValue,\n descriptor\n );\n },\n equals: (previousValue, nextValue) => {\n if (Object.is(previousValue, nextValue)) {\n incrementPerfMetric('skippedDomPropWrites');\n return true;\n }\n return false;\n },\n onError: (err) => {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive prop update failed:', err);\n }\n },\n });\n\n if (isBenchMetricScopeActive('coldCreate')) {\n recordBenchCounter('reactivePropsMounted');\n }\n\n const cleanup = () => {\n reactivePropRegistry.delete(descriptor);\n effectHandle?.cleanup();\n effectHandle = null;\n };\n\n const updateFn = (nextFn: () => unknown): void => {\n if (!effectHandle) {\n return;\n }\n\n descriptor.propFn = nextFn;\n\n try {\n effectHandle.updateCompute(nextFn);\n } catch (err) {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Reactive prop update failed:', err);\n }\n }\n };\n\n return {\n cleanup,\n updateFn,\n };\n}\n\nfunction getOrCreateReactivePropsCleanupMap(\n el: Element\n): Map<string, ReactivePropCleanupEntry> {\n let cleanupMap = elementReactivePropsCleanup.get(el);\n if (!cleanupMap) {\n cleanupMap = new Map();\n elementReactivePropsCleanup.set(el, cleanupMap);\n }\n return cleanupMap;\n}\n\nfunction createReactivePropCleanupEntry(\n el: Element,\n propName: string,\n propFn: () => unknown,\n tagName: string\n): ReactivePropCleanupEntry {\n const reactive = setupReactiveProp(el, propName, propFn, tagName);\n\n return {\n cleanup: reactive.cleanup,\n updateFn: (nextValue) => {\n reactive.updateFn(nextValue as () => unknown);\n },\n restoreFn: (nextValue) =>\n createReactivePropCleanupEntry(\n el,\n propName,\n nextValue as () => unknown,\n tagName\n ),\n fnRef: propFn,\n };\n}\n\nexport function hasTrackedElementPropBindings(el: Element): boolean {\n const existingListeners = elementListeners.get(el);\n const existingReactiveProps = elementReactivePropsCleanup.get(el);\n return (\n (existingListeners !== undefined && existingListeners.size > 0) ||\n (existingReactiveProps !== undefined && existingReactiveProps.size > 0)\n );\n}\n\nexport function applyPropsToElement(\n el: Element,\n props: Record<string, unknown>,\n tagName: string,\n isHydrationSkipped: (el: Element) => boolean\n): void {\n if (isHydrationSkipped(el)) {\n return;\n }\n\n for (const key in props) {\n const value = props[key];\n if (key === 'ref') {\n updateElementRef(el, value);\n continue;\n }\n if (isSkippedProp(key)) continue;\n if (value === undefined || value === null || value === false) continue;\n\n const eventProp = parseEventProp(key);\n if (eventProp) {\n addTrackedListener(\n el,\n eventProp.eventName,\n value as EventListener,\n eventProp.capture\n );\n continue;\n }\n\n if (typeof value === 'function' && key !== 'ref') {\n getOrCreateReactivePropsCleanupMap(el).set(\n key,\n createReactivePropCleanupEntry(el, key, value as () => unknown, tagName)\n );\n continue;\n }\n\n applyScalarPropValue(el, key, value, tagName);\n }\n}\n\nexport function syncElementPropBindings(\n el: Element,\n domVNode: DOMElement,\n props: Record<string, unknown>,\n usesReactiveChildren: boolean\n): void {\n const existingListeners = elementListeners.get(el);\n const existingReactiveProps = elementReactivePropsCleanup.get(el);\n\n let desiredListenerKeys: Set<string> | null = null;\n let desiredDelegatedEventNames: Set<string> | null = null;\n let desiredReactivePropNames: Set<string> | null = null;\n\n if (usesReactiveChildren) {\n (desiredReactivePropNames ??= new Set()).add(REACTIVE_CHILDREN_KEY);\n }\n\n for (const key in props) {\n const value = props[key];\n if (key === 'ref') continue;\n if (isSkippedProp(key)) continue;\n\n const eventProp = parseEventProp(key);\n const eventName = eventProp?.eventName;\n const eventCapture = eventProp?.capture ?? false;\n const listenerKey =\n eventName === undefined\n ? null\n : getEventListenerKey(eventName, eventCapture);\n\n if (value === undefined || value === null || value === false) {\n if (listenerKey && existingListeners?.has(listenerKey)) {\n const entry = existingListeners.get(listenerKey)!;\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n existingListeners.delete(listenerKey);\n } else {\n const entry = existingReactiveProps?.get(key);\n if (entry) {\n entry.cleanup();\n existingReactiveProps?.delete(key);\n } else {\n applyScalarPropValue(el, key, value, domVNode.type as string);\n }\n }\n continue;\n }\n\n if (typeof value === 'function' && !eventProp && key !== 'ref') {\n const existingEntry = existingReactiveProps?.get(key);\n if (existingReactiveProps && existingReactiveProps.size > 0) {\n (desiredReactivePropNames ??= new Set()).add(key);\n }\n\n if (existingEntry && existingEntry.fnRef === value) {\n continue;\n }\n\n if (existingEntry?.updateFn) {\n existingEntry.updateFn(value as () => unknown);\n existingEntry.fnRef = value as () => unknown;\n continue;\n }\n\n if (existingEntry) {\n existingEntry.cleanup();\n }\n\n getOrCreateReactivePropsCleanupMap(el).set(\n key,\n createReactivePropCleanupEntry(\n el,\n key,\n value as () => unknown,\n domVNode.type as string\n )\n );\n continue;\n }\n\n const existingReactiveEntry = existingReactiveProps?.get(key);\n if (existingReactiveEntry) {\n existingReactiveEntry.cleanup();\n existingReactiveProps?.delete(key);\n }\n\n if (eventProp && listenerKey) {\n const eventName = eventProp.eventName;\n const eventCapture = eventProp.capture;\n const useDelegation =\n !eventCapture &&\n isEventDelegationEnabled() &&\n isDelegatedEvent(eventName);\n if (useDelegation) {\n (desiredDelegatedEventNames ??= new Set()).add(eventName);\n }\n\n if (useDelegation) {\n const existingDelegated = getDelegatedHandlerForElement(el, eventName);\n if (existingDelegated?.original === value) {\n continue;\n }\n\n if (\n existingDelegated &&\n updateDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n )\n ) {\n continue;\n }\n\n addDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n );\n continue;\n }\n\n (desiredListenerKeys ??= new Set()).add(listenerKey);\n\n const existing = existingListeners?.get(listenerKey);\n\n if (existing && existing.original === value) {\n continue;\n }\n\n if (existing) {\n if (\n useDelegation &&\n existing.isDelegated &&\n updateDelegatedListener(\n el,\n eventName,\n value as EventListener,\n value as EventListener,\n undefined\n )\n ) {\n existing.handler = value as EventListener;\n existing.original = value as EventListener;\n existing.options = undefined;\n continue;\n }\n\n if (!useDelegation && !existing.isDelegated && existing.updateHandler) {\n existing.updateHandler(value as EventListener);\n existing.original = value as EventListener;\n continue;\n }\n\n if (existing.isDelegated) {\n removeDelegatedListener(el, existing.eventName);\n } else {\n if (existing.options !== undefined) {\n el.removeEventListener(\n existing.eventName,\n existing.handler,\n existing.options\n );\n } else {\n el.removeEventListener(existing.eventName, existing.handler);\n }\n }\n }\n\n const options = getEventListenerOptions(eventName, eventCapture);\n const mutableHandler = createMutableWrappedHandler(\n value as EventListener,\n true\n );\n const trackedHandler = mutableHandler.handler;\n\n if (options !== undefined) {\n el.addEventListener(eventName, trackedHandler, options);\n } else {\n el.addEventListener(eventName, trackedHandler);\n }\n incDevCounter('listenerAdds');\n\n const listenerEntry = {\n handler: trackedHandler,\n original: value as EventListener,\n eventName,\n options,\n isDelegated: false,\n updateHandler: mutableHandler?.updateHandler,\n };\n if (!elementListeners.has(el)) {\n elementListeners.set(el, new Map());\n }\n elementListeners.get(el)!.set(listenerKey, listenerEntry);\n } else {\n applyScalarPropValue(el, key, value, domVNode.type as string);\n }\n }\n\n removeStaleAttributes(el, domVNode, props);\n\n if (existingListeners && existingListeners.size > 0) {\n if (desiredListenerKeys === null) {\n existingListeners.forEach((entry) => {\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n });\n elementListeners.delete(el);\n } else {\n existingListeners.forEach((entry, listenerKey) => {\n if (!desiredListenerKeys.has(listenerKey)) {\n incDevCounter('listenerRemoves');\n if (entry.isDelegated) {\n removeDelegatedListener(el, entry.eventName);\n } else {\n if (entry.options !== undefined) {\n el.removeEventListener(\n entry.eventName,\n entry.handler,\n entry.options\n );\n } else {\n el.removeEventListener(entry.eventName, entry.handler);\n }\n }\n existingListeners.delete(listenerKey);\n }\n });\n if (existingListeners.size === 0) elementListeners.delete(el);\n }\n }\n\n const delegatedHandlers = getDelegatedHandlersForElement(el);\n if (delegatedHandlers && delegatedHandlers.size > 0) {\n if (desiredDelegatedEventNames === null) {\n for (const eventName of delegatedHandlers.keys()) {\n removeDelegatedListener(el, eventName);\n }\n } else {\n for (const eventName of delegatedHandlers.keys()) {\n if (!desiredDelegatedEventNames.has(eventName)) {\n removeDelegatedListener(el, eventName);\n }\n }\n }\n }\n\n if (existingReactiveProps && existingReactiveProps.size > 0) {\n if (desiredReactivePropNames === null) {\n existingReactiveProps.forEach((entry) => {\n entry.cleanup();\n });\n elementReactivePropsCleanup.delete(el);\n } else {\n existingReactiveProps.forEach((entry, key) => {\n if (!desiredReactivePropNames.has(key)) {\n entry.cleanup();\n existingReactiveProps.delete(key);\n }\n });\n if (existingReactiveProps.size === 0) {\n elementReactivePropsCleanup.delete(el);\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactive-child-dom.js","names":[],"sources":["../../src/renderer/reactive-child-dom.ts"],"sourcesContent":["import type { ChildScope } from '../runtime
|
|
1
|
+
{"version":3,"file":"reactive-child-dom.js","names":[],"sources":["../../src/renderer/reactive-child-dom.ts"],"sourcesContent":["import type { ChildScope } from '../runtime';\nimport { syncControlBoundaryScopeDom } from './boundaries';\nimport { teardownNodeSubtree } from './cleanup';\nimport {\n createElementForNamespace,\n getParentNamespace,\n SVG_NAMESPACE,\n} from './namespaces';\nimport {\n collectReactiveChildBoundaryVNodes,\n isSingleRootReactiveChildBoundaryValue,\n} from './reactive-child-sources';\nimport type { VNode } from './types';\n\nexport interface ReactiveChildDOMHost {\n createDOMNode(node: unknown, parentNamespace?: string): Node | null;\n updateElementChildren(\n el: Element,\n children: VNode | VNode[] | undefined,\n forceUpdate?: boolean\n ): void;\n}\n\nexport type ReactiveChildBoundarySequenceEntry =\n | { kind: 'static'; nodes: Node[] }\n | { kind: 'dynamic'; scope: ChildScope; nodes: Node[] };\n\nexport function materializeReactiveChildBoundaryNodes(\n value: unknown,\n parentNamespace: string | undefined,\n host: ReactiveChildDOMHost\n): Node[] {\n const nodes: Node[] = [];\n const dom = host.createDOMNode(value, parentNamespace);\n if (!dom) {\n return nodes;\n }\n\n if (dom instanceof DocumentFragment) {\n for (let child = dom.firstChild; child; child = dom.firstChild) {\n nodes.push(child);\n dom.removeChild(child);\n }\n return nodes;\n }\n\n nodes.push(dom);\n return nodes;\n}\n\nexport function createReactiveChildBoundaryHost(el: Element): Element {\n const ownerDocument = el.ownerDocument;\n const parentNamespace = getParentNamespace(el);\n return parentNamespace === SVG_NAMESPACE\n ? createElementForNamespace('g', parentNamespace, ownerDocument)\n : createElementForNamespace('div', parentNamespace, ownerDocument);\n}\n\nexport function disposeReactiveChildBoundaryNodes(nodes: Node[]): void {\n for (const node of nodes) {\n if (node.parentNode) {\n node.parentNode.removeChild(node);\n }\n\n teardownNodeSubtree(node);\n }\n}\n\nexport function syncReactiveChildExpectedNodes(\n el: Element,\n expectedNodes: Node[]\n): void {\n const expectedNodeSet = new Set(expectedNodes);\n\n for (let node = el.firstChild; node; ) {\n const next = node.nextSibling;\n if (!expectedNodeSet.has(node)) {\n teardownNodeSubtree(node);\n el.removeChild(node);\n }\n node = next;\n }\n\n let anchor = el.firstChild;\n for (const node of expectedNodes) {\n if (node === anchor) {\n anchor = anchor.nextSibling;\n continue;\n }\n\n el.insertBefore(node, anchor);\n anchor = node.nextSibling;\n }\n}\n\nexport function commitReactiveChildBoundaryEntryNodes(\n el: Element,\n entry: { scope: ChildScope; nodes: Node[] },\n host: ReactiveChildDOMHost\n): Node[] {\n if (!entry.scope.needsDomUpdate) {\n return entry.nodes;\n }\n\n if (\n entry.scope.vnode === null ||\n entry.scope.vnode === undefined ||\n entry.scope.vnode === false\n ) {\n if (entry.nodes.length > 0) {\n disposeReactiveChildBoundaryNodes(entry.nodes);\n entry.nodes = [];\n }\n\n const dom = entry.scope.dom;\n if (dom?.parentNode === el) {\n teardownNodeSubtree(dom);\n el.removeChild(dom);\n }\n\n entry.scope.dom = undefined;\n entry.scope.needsDomUpdate = false;\n return entry.nodes;\n }\n\n if (!isSingleRootReactiveChildBoundaryValue(entry.scope.vnode)) {\n const nextChildren: VNode[] = [];\n collectReactiveChildBoundaryVNodes(entry.scope.vnode, nextChildren);\n\n const boundaryHost = createReactiveChildBoundaryHost(el);\n for (const node of entry.nodes) {\n boundaryHost.appendChild(node);\n }\n\n host.updateElementChildren(boundaryHost, nextChildren);\n\n const nextNodes = Array.from(boundaryHost.childNodes);\n\n entry.scope.dom = undefined;\n entry.scope.needsDomUpdate = false;\n entry.nodes = nextNodes;\n return nextNodes;\n }\n\n if (entry.nodes.length > 1) {\n disposeReactiveChildBoundaryNodes(entry.nodes);\n entry.nodes = [];\n entry.scope.dom = undefined;\n }\n\n const nextDom = syncControlBoundaryScopeDom(\n el,\n entry.scope,\n entry.scope.vnode ?? null\n );\n if (!nextDom) {\n entry.nodes = [];\n entry.scope.needsDomUpdate = false;\n return entry.nodes;\n }\n\n entry.nodes = [nextDom];\n entry.scope.needsDomUpdate = false;\n return entry.nodes;\n}\n\nexport function syncReactiveChildSequenceNodes(\n el: Element,\n entries: ReactiveChildBoundarySequenceEntry[],\n host: ReactiveChildDOMHost\n): void {\n const expectedNodes: Node[] = [];\n\n for (const entry of entries) {\n if (entry.kind === 'static') {\n expectedNodes.push(...entry.nodes);\n continue;\n }\n\n expectedNodes.push(\n ...commitReactiveChildBoundaryEntryNodes(el, entry, host)\n );\n }\n\n syncReactiveChildExpectedNodes(el, expectedNodes);\n}\n\nexport function syncReactiveScalarTextNodes(\n el: Element,\n slotValues: unknown[],\n values: string[],\n host: ReactiveChildDOMHost\n): void {\n const childNodes = el.childNodes;\n const canPatchInPlace = childNodes.length === values.length;\n\n if (canPatchInPlace) {\n let allText = true;\n for (let index = 0; index < childNodes.length; index += 1) {\n if (childNodes[index]?.nodeType !== Node.TEXT_NODE) {\n allText = false;\n break;\n }\n }\n\n if (allText) {\n for (let index = 0; index < values.length; index += 1) {\n const textNode = childNodes[index] as Text;\n if (textNode.data !== values[index]) {\n textNode.data = values[index];\n }\n }\n return;\n }\n }\n\n const boundaryHost = createReactiveChildBoundaryHost(el);\n for (let node = el.firstChild; node; ) {\n const next = node.nextSibling;\n boundaryHost.appendChild(node);\n node = next;\n }\n\n host.updateElementChildren(boundaryHost, slotValues as VNode[]);\n syncReactiveChildExpectedNodes(el, Array.from(boundaryHost.childNodes));\n}\n"],"mappings":"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"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { getRuntimeEnv } from "../common/env.js";
|
|
2
|
-
import { logger } from "../
|
|
2
|
+
import { logger } from "../common/logger.js";
|
|
3
3
|
import { incDevCounter } from "../runtime/dev-namespace.js";
|
|
4
4
|
import { getCurrentInstance } from "../runtime/component-scope.js";
|
|
5
|
-
import "../runtime/
|
|
5
|
+
import { createChildScope, disposeChildScope, rerenderChildScope } from "../runtime/child-scope.js";
|
|
6
|
+
import { createFineGrainedEffect } from "../runtime/effect.js";
|
|
7
|
+
import "../runtime/index.js";
|
|
6
8
|
import { REACTIVE_CHILDREN_KEY, elementReactivePropsCleanup, teardownNodeSubtree } from "./cleanup.js";
|
|
7
9
|
import "./env.js";
|
|
8
|
-
import { createChildScope, disposeChildScope, rerenderChildScope } from "../runtime/child-scope.js";
|
|
9
10
|
import { getParentNamespace } from "./namespaces.js";
|
|
10
|
-
import { createFineGrainedEffect } from "../runtime/effect.js";
|
|
11
11
|
import { areReactiveChildBoundarySequenceSourcesEqual, areReactiveScalarChildSourcesEqual, canUpdateReactiveChildBoundarySequenceSource, collectReactiveChildValuesAsVNodes, getReactiveChildBoundarySequenceSource, getReactiveScalarChildSource, getSingleReactiveChildBoundarySource, normalizeOwnedReactiveTextValue, normalizeReactiveChildBoundaryVNode, normalizeReactiveScalarSequenceValues } from "./reactive-child-sources.js";
|
|
12
12
|
import { commitReactiveChildBoundaryEntryNodes, createReactiveChildBoundaryHost, disposeReactiveChildBoundaryNodes, materializeReactiveChildBoundaryNodes, syncReactiveChildExpectedNodes, syncReactiveChildSequenceNodes, syncReactiveScalarTextNodes } from "./reactive-child-dom.js";
|
|
13
13
|
//#region src/renderer/reactive-children.ts
|