@rezi-ui/core 0.1.0-alpha.60 → 0.1.0-alpha.63
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/app/createApp/breadcrumbs.d.ts +38 -0
- package/dist/app/createApp/breadcrumbs.d.ts.map +1 -0
- package/dist/app/createApp/breadcrumbs.js +65 -0
- package/dist/app/createApp/breadcrumbs.js.map +1 -0
- package/dist/app/createApp/config.d.ts +25 -0
- package/dist/app/createApp/config.d.ts.map +1 -0
- package/dist/app/createApp/config.js +130 -0
- package/dist/app/createApp/config.js.map +1 -0
- package/dist/app/createApp/eventLoop.d.ts +95 -0
- package/dist/app/createApp/eventLoop.d.ts.map +1 -0
- package/dist/app/createApp/eventLoop.js +384 -0
- package/dist/app/createApp/eventLoop.js.map +1 -0
- package/dist/app/createApp/guards.d.ts +21 -0
- package/dist/app/createApp/guards.d.ts.map +1 -0
- package/dist/app/createApp/guards.js +54 -0
- package/dist/app/createApp/guards.js.map +1 -0
- package/dist/app/createApp/keybindings.d.ts +28 -0
- package/dist/app/createApp/keybindings.d.ts.map +1 -0
- package/dist/app/createApp/keybindings.js +113 -0
- package/dist/app/createApp/keybindings.js.map +1 -0
- package/dist/app/createApp/renderLoop.d.ts +64 -0
- package/dist/app/createApp/renderLoop.d.ts.map +1 -0
- package/dist/app/createApp/renderLoop.js +305 -0
- package/dist/app/createApp/renderLoop.js.map +1 -0
- package/dist/app/createApp.d.ts +3 -39
- package/dist/app/createApp.d.ts.map +1 -1
- package/dist/app/createApp.js +403 -1205
- package/dist/app/createApp.js.map +1 -1
- package/dist/app/widgetRenderer/constraintState.d.ts +98 -0
- package/dist/app/widgetRenderer/constraintState.d.ts.map +1 -0
- package/dist/app/widgetRenderer/constraintState.js +563 -0
- package/dist/app/widgetRenderer/constraintState.js.map +1 -0
- package/dist/app/widgetRenderer/fileNodeCache.d.ts +2 -0
- package/dist/app/widgetRenderer/fileNodeCache.d.ts.map +1 -1
- package/dist/app/widgetRenderer/fileNodeCache.js +31 -0
- package/dist/app/widgetRenderer/fileNodeCache.js.map +1 -1
- package/dist/app/widgetRenderer/filePickerRouting.d.ts +12 -1
- package/dist/app/widgetRenderer/filePickerRouting.d.ts.map +1 -1
- package/dist/app/widgetRenderer/filePickerRouting.js +63 -14
- package/dist/app/widgetRenderer/filePickerRouting.js.map +1 -1
- package/dist/app/widgetRenderer/focusState.d.ts +46 -0
- package/dist/app/widgetRenderer/focusState.d.ts.map +1 -0
- package/dist/app/widgetRenderer/focusState.js +122 -0
- package/dist/app/widgetRenderer/focusState.js.map +1 -0
- package/dist/app/widgetRenderer/keyboardRouting.d.ts.map +1 -1
- package/dist/app/widgetRenderer/keyboardRouting.js.map +1 -1
- package/dist/app/widgetRenderer/mouseRouting.d.ts +5 -0
- package/dist/app/widgetRenderer/mouseRouting.d.ts.map +1 -1
- package/dist/app/widgetRenderer/mouseRouting.js +78 -8
- package/dist/app/widgetRenderer/mouseRouting.js.map +1 -1
- package/dist/app/widgetRenderer/overlayShortcuts.d.ts.map +1 -1
- package/dist/app/widgetRenderer/overlayShortcuts.js +14 -4
- package/dist/app/widgetRenderer/overlayShortcuts.js.map +1 -1
- package/dist/app/widgetRenderer/overlayState.d.ts +198 -0
- package/dist/app/widgetRenderer/overlayState.d.ts.map +1 -0
- package/dist/app/widgetRenderer/overlayState.js +590 -0
- package/dist/app/widgetRenderer/overlayState.js.map +1 -0
- package/dist/app/widgetRenderer/routeEngineEvent.d.ts +189 -0
- package/dist/app/widgetRenderer/routeEngineEvent.d.ts.map +1 -0
- package/dist/app/widgetRenderer/routeEngineEvent.js +527 -0
- package/dist/app/widgetRenderer/routeEngineEvent.js.map +1 -0
- package/dist/app/widgetRenderer.d.ts +2 -1
- package/dist/app/widgetRenderer.d.ts.map +1 -1
- package/dist/app/widgetRenderer.js +334 -1707
- package/dist/app/widgetRenderer.js.map +1 -1
- package/dist/forms/internal/arrayState.d.ts +35 -0
- package/dist/forms/internal/arrayState.d.ts.map +1 -0
- package/dist/forms/internal/arrayState.js +238 -0
- package/dist/forms/internal/arrayState.js.map +1 -0
- package/dist/forms/internal/bindings.d.ts +46 -0
- package/dist/forms/internal/bindings.d.ts.map +1 -0
- package/dist/forms/internal/bindings.js +161 -0
- package/dist/forms/internal/bindings.js.map +1 -0
- package/dist/forms/internal/dev.d.ts +4 -0
- package/dist/forms/internal/dev.d.ts.map +1 -0
- package/dist/forms/internal/dev.js +21 -0
- package/dist/forms/internal/dev.js.map +1 -0
- package/dist/forms/internal/state.d.ts +52 -0
- package/dist/forms/internal/state.d.ts.map +1 -0
- package/dist/forms/internal/state.js +240 -0
- package/dist/forms/internal/state.js.map +1 -0
- package/dist/forms/internal/submit.d.ts +43 -0
- package/dist/forms/internal/submit.d.ts.map +1 -0
- package/dist/forms/internal/submit.js +165 -0
- package/dist/forms/internal/submit.js.map +1 -0
- package/dist/forms/internal/wizard.d.ts +53 -0
- package/dist/forms/internal/wizard.d.ts.map +1 -0
- package/dist/forms/internal/wizard.js +311 -0
- package/dist/forms/internal/wizard.js.map +1 -0
- package/dist/forms/useForm.d.ts.map +1 -1
- package/dist/forms/useForm.js +90 -1117
- package/dist/forms/useForm.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keybindings/manager.d.ts.map +1 -1
- package/dist/keybindings/manager.js.map +1 -1
- package/dist/keybindings/parser.d.ts.map +1 -1
- package/dist/keybindings/parser.js +10 -5
- package/dist/keybindings/parser.js.map +1 -1
- package/dist/layout/dropdownGeometry.d.ts +8 -0
- package/dist/layout/dropdownGeometry.d.ts.map +1 -1
- package/dist/layout/dropdownGeometry.js +40 -0
- package/dist/layout/dropdownGeometry.js.map +1 -1
- package/dist/layout/engine/layoutEngine.js +1 -1
- package/dist/layout/engine/layoutEngine.js.map +1 -1
- package/dist/layout/kinds/overlays.d.ts.map +1 -1
- package/dist/layout/kinds/stack.d.ts +1 -3
- package/dist/layout/kinds/stack.d.ts.map +1 -1
- package/dist/layout/kinds/stack.js +11 -1523
- package/dist/layout/kinds/stack.js.map +1 -1
- package/dist/layout/kinds/stackParts/axis.d.ts +32 -0
- package/dist/layout/kinds/stackParts/axis.d.ts.map +1 -0
- package/dist/layout/kinds/stackParts/axis.js +61 -0
- package/dist/layout/kinds/stackParts/axis.js.map +1 -0
- package/dist/layout/kinds/stackParts/constraintPlan.d.ts +18 -0
- package/dist/layout/kinds/stackParts/constraintPlan.d.ts.map +1 -0
- package/dist/layout/kinds/stackParts/constraintPlan.js +434 -0
- package/dist/layout/kinds/stackParts/constraintPlan.js.map +1 -0
- package/dist/layout/kinds/stackParts/layout.d.ts +6 -0
- package/dist/layout/kinds/stackParts/layout.d.ts.map +1 -0
- package/dist/layout/kinds/stackParts/layout.js +376 -0
- package/dist/layout/kinds/stackParts/layout.js.map +1 -0
- package/dist/layout/kinds/stackParts/measure.d.ts +6 -0
- package/dist/layout/kinds/stackParts/measure.d.ts.map +1 -0
- package/dist/layout/kinds/stackParts/measure.js +212 -0
- package/dist/layout/kinds/stackParts/measure.js.map +1 -0
- package/dist/layout/kinds/stackParts/shared.d.ts +31 -0
- package/dist/layout/kinds/stackParts/shared.d.ts.map +1 -0
- package/dist/layout/kinds/stackParts/shared.js +94 -0
- package/dist/layout/kinds/stackParts/shared.js.map +1 -0
- package/dist/layout/kinds/stackParts/wrap.d.ts +26 -0
- package/dist/layout/kinds/stackParts/wrap.d.ts.map +1 -0
- package/dist/layout/kinds/stackParts/wrap.js +374 -0
- package/dist/layout/kinds/stackParts/wrap.js.map +1 -0
- package/dist/layout/validate/interactive.d.ts +106 -0
- package/dist/layout/validate/interactive.d.ts.map +1 -0
- package/dist/layout/validate/interactive.js +430 -0
- package/dist/layout/validate/interactive.js.map +1 -0
- package/dist/layout/validate/layoutConstraints.d.ts +51 -0
- package/dist/layout/validate/layoutConstraints.d.ts.map +1 -0
- package/dist/layout/validate/layoutConstraints.js +100 -0
- package/dist/layout/validate/layoutConstraints.js.map +1 -0
- package/dist/layout/validate/primitives.d.ts +31 -0
- package/dist/layout/validate/primitives.d.ts.map +1 -0
- package/dist/layout/validate/primitives.js +299 -0
- package/dist/layout/validate/primitives.js.map +1 -0
- package/dist/layout/validate/shared.d.ts +23 -0
- package/dist/layout/validate/shared.d.ts.map +1 -0
- package/dist/layout/validate/shared.js +32 -0
- package/dist/layout/validate/shared.js.map +1 -0
- package/dist/layout/validate/spacing.d.ts +21 -0
- package/dist/layout/validate/spacing.d.ts.map +1 -0
- package/dist/layout/validate/spacing.js +33 -0
- package/dist/layout/validate/spacing.js.map +1 -0
- package/dist/layout/validateProps.d.ts +5 -159
- package/dist/layout/validateProps.d.ts.map +1 -1
- package/dist/layout/validateProps.js +1 -832
- package/dist/layout/validateProps.js.map +1 -1
- package/dist/pipeline.js +1 -1
- package/dist/pipeline.js.map +1 -1
- package/dist/renderer/renderToDrawlist/renderTree.d.ts +1 -1
- package/dist/renderer/renderToDrawlist/renderTree.d.ts.map +1 -1
- package/dist/renderer/renderToDrawlist/renderTree.js +3 -3
- package/dist/renderer/renderToDrawlist/renderTree.js.map +1 -1
- package/dist/renderer/renderToDrawlist/types.d.ts +2 -0
- package/dist/renderer/renderToDrawlist/types.d.ts.map +1 -1
- package/dist/renderer/renderToDrawlist/widgets/containers.d.ts.map +1 -1
- package/dist/renderer/renderToDrawlist/widgets/containers.js +1 -1
- package/dist/renderer/renderToDrawlist/widgets/containers.js.map +1 -1
- package/dist/renderer/renderToDrawlist/widgets/files.d.ts +2 -1
- package/dist/renderer/renderToDrawlist/widgets/files.d.ts.map +1 -1
- package/dist/renderer/renderToDrawlist/widgets/files.js +30 -3
- package/dist/renderer/renderToDrawlist/widgets/files.js.map +1 -1
- package/dist/renderer/renderToDrawlist/widgets/overlays.d.ts +1 -1
- package/dist/renderer/renderToDrawlist/widgets/overlays.d.ts.map +1 -1
- package/dist/renderer/renderToDrawlist/widgets/overlays.js +26 -6
- package/dist/renderer/renderToDrawlist/widgets/overlays.js.map +1 -1
- package/dist/renderer/renderToDrawlist/widgets/renderFormWidgets.d.ts.map +1 -1
- package/dist/renderer/renderToDrawlist/widgets/renderFormWidgets.js +52 -18
- package/dist/renderer/renderToDrawlist/widgets/renderFormWidgets.js.map +1 -1
- package/dist/renderer/renderToDrawlist.d.ts +0 -8
- package/dist/renderer/renderToDrawlist.d.ts.map +1 -1
- package/dist/renderer/renderToDrawlist.js +1 -9
- package/dist/renderer/renderToDrawlist.js.map +1 -1
- package/dist/runtime/commit/composite.d.ts +11 -0
- package/dist/runtime/commit/composite.d.ts.map +1 -0
- package/dist/runtime/commit/composite.js +238 -0
- package/dist/runtime/commit/composite.js.map +1 -0
- package/dist/runtime/commit/container.d.ts +7 -0
- package/dist/runtime/commit/container.d.ts.map +1 -0
- package/dist/runtime/commit/container.js +350 -0
- package/dist/runtime/commit/container.js.map +1 -0
- package/dist/runtime/commit/equality.d.ts +20 -0
- package/dist/runtime/commit/equality.d.ts.map +1 -0
- package/dist/runtime/commit/equality.js +436 -0
- package/dist/runtime/commit/equality.js.map +1 -0
- package/dist/runtime/commit/errorBoundary.d.ts +7 -0
- package/dist/runtime/commit/errorBoundary.d.ts.map +1 -0
- package/dist/runtime/commit/errorBoundary.js +53 -0
- package/dist/runtime/commit/errorBoundary.js.map +1 -0
- package/dist/runtime/commit/shared.d.ts +138 -0
- package/dist/runtime/commit/shared.d.ts.map +1 -0
- package/dist/runtime/commit/shared.js +11 -0
- package/dist/runtime/commit/shared.js.map +1 -0
- package/dist/runtime/commit/transitions.d.ts +9 -0
- package/dist/runtime/commit/transitions.d.ts.map +1 -0
- package/dist/runtime/commit/transitions.js +93 -0
- package/dist/runtime/commit/transitions.js.map +1 -0
- package/dist/runtime/commit/validation.d.ts +16 -0
- package/dist/runtime/commit/validation.d.ts.map +1 -0
- package/dist/runtime/commit/validation.js +157 -0
- package/dist/runtime/commit/validation.js.map +1 -0
- package/dist/runtime/commit.d.ts +7 -117
- package/dist/runtime/commit.d.ts.map +1 -1
- package/dist/runtime/commit.js +13 -1394
- package/dist/runtime/commit.js.map +1 -1
- package/dist/runtime/localState.d.ts +4 -0
- package/dist/runtime/localState.d.ts.map +1 -1
- package/dist/runtime/localState.js.map +1 -1
- package/dist/runtime/widgetMeta/collector.d.ts +77 -0
- package/dist/runtime/widgetMeta/collector.d.ts.map +1 -0
- package/dist/runtime/widgetMeta/collector.js +293 -0
- package/dist/runtime/widgetMeta/collector.js.map +1 -0
- package/dist/runtime/widgetMeta/focusContainers.d.ts +44 -0
- package/dist/runtime/widgetMeta/focusContainers.d.ts.map +1 -0
- package/dist/runtime/widgetMeta/focusContainers.js +190 -0
- package/dist/runtime/widgetMeta/focusContainers.js.map +1 -0
- package/dist/runtime/widgetMeta/focusInfo.d.ts +19 -0
- package/dist/runtime/widgetMeta/focusInfo.d.ts.map +1 -0
- package/dist/runtime/widgetMeta/focusInfo.js +172 -0
- package/dist/runtime/widgetMeta/focusInfo.js.map +1 -0
- package/dist/runtime/widgetMeta/helpers.d.ts +47 -0
- package/dist/runtime/widgetMeta/helpers.d.ts.map +1 -0
- package/dist/runtime/widgetMeta/helpers.js +182 -0
- package/dist/runtime/widgetMeta/helpers.js.map +1 -0
- package/dist/runtime/widgetMeta.d.ts +12 -175
- package/dist/runtime/widgetMeta.d.ts.map +1 -1
- package/dist/runtime/widgetMeta.js +6 -847
- package/dist/runtime/widgetMeta.js.map +1 -1
- package/dist/ui/capabilities.d.ts.map +1 -1
- package/dist/ui/designTokens.d.ts.map +1 -1
- package/dist/widgets/accordion.d.ts.map +1 -1
- package/dist/widgets/accordion.js +8 -13
- package/dist/widgets/accordion.js.map +1 -1
- package/dist/widgets/factories/advanced.d.ts +20 -0
- package/dist/widgets/factories/advanced.d.ts.map +1 -0
- package/dist/widgets/factories/advanced.js +75 -0
- package/dist/widgets/factories/advanced.js.map +1 -0
- package/dist/widgets/factories/basic.d.ts +14 -0
- package/dist/widgets/factories/basic.d.ts.map +1 -0
- package/dist/widgets/factories/basic.js +44 -0
- package/dist/widgets/factories/basic.js.map +1 -0
- package/dist/widgets/factories/feedback.d.ts +20 -0
- package/dist/widgets/factories/feedback.d.ts.map +1 -0
- package/dist/widgets/factories/feedback.js +102 -0
- package/dist/widgets/factories/feedback.js.map +1 -0
- package/dist/widgets/factories/helpers.d.ts +41 -0
- package/dist/widgets/factories/helpers.d.ts.map +1 -0
- package/dist/widgets/factories/helpers.js +72 -0
- package/dist/widgets/factories/helpers.js.map +1 -0
- package/dist/widgets/factories/interactive.d.ts +15 -0
- package/dist/widgets/factories/interactive.d.ts.map +1 -0
- package/dist/widgets/factories/interactive.js +46 -0
- package/dist/widgets/factories/interactive.js.map +1 -0
- package/dist/widgets/factories/layoutShell.d.ts +22 -0
- package/dist/widgets/factories/layoutShell.d.ts.map +1 -0
- package/dist/widgets/factories/layoutShell.js +190 -0
- package/dist/widgets/factories/layoutShell.js.map +1 -0
- package/dist/widgets/factories/media.d.ts +14 -0
- package/dist/widgets/factories/media.d.ts.map +1 -0
- package/dist/widgets/factories/media.js +25 -0
- package/dist/widgets/factories/media.js.map +1 -0
- package/dist/widgets/factories/navigation.d.ts +10 -0
- package/dist/widgets/factories/navigation.d.ts.map +1 -0
- package/dist/widgets/factories/navigation.js +24 -0
- package/dist/widgets/factories/navigation.js.map +1 -0
- package/dist/widgets/field.d.ts +6 -1
- package/dist/widgets/field.d.ts.map +1 -1
- package/dist/widgets/field.js +8 -2
- package/dist/widgets/field.js.map +1 -1
- package/dist/widgets/filePicker.d.ts +5 -0
- package/dist/widgets/filePicker.d.ts.map +1 -0
- package/dist/widgets/filePicker.js +136 -0
- package/dist/widgets/filePicker.js.map +1 -0
- package/dist/widgets/protocol.d.ts +0 -6
- package/dist/widgets/protocol.d.ts.map +1 -1
- package/dist/widgets/protocol.js +0 -6
- package/dist/widgets/protocol.js.map +1 -1
- package/dist/widgets/select.js +1 -1
- package/dist/widgets/select.js.map +1 -1
- package/dist/widgets/splitPane.d.ts.map +1 -1
- package/dist/widgets/splitPane.js.map +1 -1
- package/dist/widgets/table.d.ts.map +1 -1
- package/dist/widgets/table.js +43 -1
- package/dist/widgets/table.js.map +1 -1
- package/dist/widgets/tree.d.ts.map +1 -1
- package/dist/widgets/types/advanced.d.ts +611 -0
- package/dist/widgets/types/advanced.d.ts.map +1 -0
- package/dist/widgets/types/advanced.js +2 -0
- package/dist/widgets/types/advanced.js.map +1 -0
- package/dist/widgets/types/base.d.ts +933 -0
- package/dist/widgets/types/base.d.ts.map +1 -0
- package/dist/widgets/types/base.js +2 -0
- package/dist/widgets/types/base.js.map +1 -0
- package/dist/widgets/types/forms.d.ts +136 -0
- package/dist/widgets/types/forms.d.ts.map +1 -0
- package/dist/widgets/types/forms.js +2 -0
- package/dist/widgets/types/forms.js.map +1 -0
- package/dist/widgets/types/navigation.d.ts +83 -0
- package/dist/widgets/types/navigation.d.ts.map +1 -0
- package/dist/widgets/types/navigation.js +2 -0
- package/dist/widgets/types/navigation.js.map +1 -0
- package/dist/widgets/types/overlaysShell.d.ts +223 -0
- package/dist/widgets/types/overlaysShell.d.ts.map +1 -0
- package/dist/widgets/types/overlaysShell.js +2 -0
- package/dist/widgets/types/overlaysShell.js.map +1 -0
- package/dist/widgets/types/table.d.ts +104 -0
- package/dist/widgets/types/table.d.ts.map +1 -0
- package/dist/widgets/types/table.js +2 -0
- package/dist/widgets/types/table.js.map +1 -0
- package/dist/widgets/types/tree.d.ts +64 -0
- package/dist/widgets/types/tree.d.ts.map +1 -0
- package/dist/widgets/types/tree.js +2 -0
- package/dist/widgets/types/tree.js.map +1 -0
- package/dist/widgets/types.d.ts +14 -2123
- package/dist/widgets/types.d.ts.map +1 -1
- package/dist/widgets/ui.d.ts +37 -843
- package/dist/widgets/ui.d.ts.map +1 -1
- package/dist/widgets/ui.js +37 -1262
- package/dist/widgets/ui.js.map +1 -1
- package/package.json +2 -2
- package/dist/constraints/aggregation.d.ts +0 -17
- package/dist/constraints/aggregation.d.ts.map +0 -1
- package/dist/constraints/aggregation.js +0 -59
- package/dist/constraints/aggregation.js.map +0 -1
- package/dist/renderer/renderToDrawlist/overflowCulling.d.ts +0 -3
- package/dist/renderer/renderToDrawlist/overflowCulling.d.ts.map +0 -1
- package/dist/renderer/renderToDrawlist/overflowCulling.js +0 -81
- package/dist/renderer/renderToDrawlist/overflowCulling.js.map +0 -1
- package/dist/widgets/tests/protocol.test.d.ts +0 -2
- package/dist/widgets/tests/protocol.test.d.ts.map +0 -1
- package/dist/widgets/tests/protocol.test.js +0 -120
- package/dist/widgets/tests/protocol.test.js.map +0 -1
package/dist/runtime/commit.js
CHANGED
|
@@ -15,1379 +15,16 @@
|
|
|
15
15
|
*
|
|
16
16
|
* @see docs/guide/runtime-and-layout.md
|
|
17
17
|
*/
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
18
|
+
import { getCompositeMeta } from "../widgets/composition.js";
|
|
19
|
+
import { executeCompositeRender } from "./commit/composite.js";
|
|
20
|
+
import { commitContainer } from "./commit/container.js";
|
|
21
|
+
import { __commitDiag, leafVNodeEqual } from "./commit/equality.js";
|
|
22
|
+
import { captureErrorBoundaryState, commitErrorBoundaryFallback } from "./commit/errorBoundary.js";
|
|
23
|
+
import { DEV_MODE, EMPTY_CHILDREN, LAYOUT_DEPTH_PATH_TRACK_START, LAYOUT_DEPTH_WARN_THRESHOLD, MAX_LAYOUT_NESTING_DEPTH, } from "./commit/shared.js";
|
|
24
|
+
import { collectSubtreeInstanceIds, deleteLocalStateForSubtree, tryScheduleExitAnimation, } from "./commit/transitions.js";
|
|
25
|
+
import { ensureFocusContainerId, ensureInteractiveId, formatWidgetPath, isContainerVNode, isVNode, warnDev, widgetPathEntry, } from "./commit/validation.js";
|
|
26
26
|
import { reconcileChildren } from "./reconcile.js";
|
|
27
|
-
|
|
28
|
-
const EMPTY_CHILDREN = Object.freeze([]);
|
|
29
|
-
/** Global commit diagnostics buffer. */
|
|
30
|
-
export const __commitDiag = {
|
|
31
|
-
enabled: false,
|
|
32
|
-
entries: [],
|
|
33
|
-
reset() {
|
|
34
|
-
this.entries.length = 0;
|
|
35
|
-
},
|
|
36
|
-
push(e) {
|
|
37
|
-
this.entries.push(e);
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
/** Fast equality for packed color values. */
|
|
41
|
-
function colorEqual(a, b) {
|
|
42
|
-
return a === b;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Fast shallow equality for text style objects.
|
|
46
|
-
* Returns true if both styles produce identical render output.
|
|
47
|
-
*/
|
|
48
|
-
function textStyleEqual(a, b) {
|
|
49
|
-
if (a === b)
|
|
50
|
-
return true;
|
|
51
|
-
if (!a || !b)
|
|
52
|
-
return false;
|
|
53
|
-
return (a.bold === b.bold &&
|
|
54
|
-
a.dim === b.dim &&
|
|
55
|
-
a.italic === b.italic &&
|
|
56
|
-
a.underline === b.underline &&
|
|
57
|
-
a.inverse === b.inverse &&
|
|
58
|
-
a.strikethrough === b.strikethrough &&
|
|
59
|
-
a.overline === b.overline &&
|
|
60
|
-
a.blink === b.blink &&
|
|
61
|
-
colorEqual(a.fg, b.fg) &&
|
|
62
|
-
colorEqual(a.bg, b.bg));
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Check if two leaf VNodes are semantically equal (same render output).
|
|
66
|
-
* Used to skip allocating new RuntimeInstance objects for unchanged leaves.
|
|
67
|
-
* Only covers common leaf kinds; returns false for unknown kinds (safe fallback).
|
|
68
|
-
*/
|
|
69
|
-
function leafVNodeEqual(a, b) {
|
|
70
|
-
switch (a.kind) {
|
|
71
|
-
case "text": {
|
|
72
|
-
if (b.kind !== "text")
|
|
73
|
-
return false;
|
|
74
|
-
if (a.text !== b.text)
|
|
75
|
-
return false;
|
|
76
|
-
if (a.props === b.props)
|
|
77
|
-
return true;
|
|
78
|
-
const ap = a.props;
|
|
79
|
-
const bp = b.props;
|
|
80
|
-
// Even when render output is identical, `id` changes must re-commit so downstream
|
|
81
|
-
// id-based lookups (layout rect indexing, anchors, etc) don't observe stale ids.
|
|
82
|
-
if (ap.id !== bp.id)
|
|
83
|
-
return false;
|
|
84
|
-
if (ap.textOverflow !== bp.textOverflow)
|
|
85
|
-
return false;
|
|
86
|
-
if (ap.variant !== bp.variant)
|
|
87
|
-
return false;
|
|
88
|
-
if (ap.maxWidth !== bp.maxWidth)
|
|
89
|
-
return false;
|
|
90
|
-
return textStyleEqual(ap.style, bp.style);
|
|
91
|
-
}
|
|
92
|
-
case "spacer": {
|
|
93
|
-
if (b.kind !== "spacer")
|
|
94
|
-
return false;
|
|
95
|
-
const ap = a.props;
|
|
96
|
-
const bp = b.props;
|
|
97
|
-
return ap.size === bp.size && ap.flex === bp.flex;
|
|
98
|
-
}
|
|
99
|
-
case "divider": {
|
|
100
|
-
if (b.kind !== "divider")
|
|
101
|
-
return false;
|
|
102
|
-
const ap = a.props;
|
|
103
|
-
const bp = b.props;
|
|
104
|
-
return (ap.direction === bp.direction &&
|
|
105
|
-
ap.char === bp.char &&
|
|
106
|
-
ap.label === bp.label &&
|
|
107
|
-
ap.color === bp.color);
|
|
108
|
-
}
|
|
109
|
-
case "richText": {
|
|
110
|
-
if (b.kind !== "richText")
|
|
111
|
-
return false;
|
|
112
|
-
const ap = a.props;
|
|
113
|
-
const bp = b.props;
|
|
114
|
-
const as = ap.spans;
|
|
115
|
-
const bs = bp.spans;
|
|
116
|
-
if (as === bs)
|
|
117
|
-
return true;
|
|
118
|
-
if (!as || !bs || as.length !== bs.length)
|
|
119
|
-
return false;
|
|
120
|
-
for (let i = 0; i < as.length; i++) {
|
|
121
|
-
const sa = as[i];
|
|
122
|
-
const sb = bs[i];
|
|
123
|
-
if (!sa || !sb)
|
|
124
|
-
return false;
|
|
125
|
-
if (sa.text !== sb.text)
|
|
126
|
-
return false;
|
|
127
|
-
if (!textStyleEqual(sa.style, sb.style))
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
default:
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
function boxShadowEqual(a, b) {
|
|
137
|
-
if (a === b)
|
|
138
|
-
return true;
|
|
139
|
-
if (a === undefined || b === undefined)
|
|
140
|
-
return false;
|
|
141
|
-
if (typeof a === "boolean" || typeof b === "boolean")
|
|
142
|
-
return a === b;
|
|
143
|
-
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null)
|
|
144
|
-
return false;
|
|
145
|
-
const ao = a;
|
|
146
|
-
const bo = b;
|
|
147
|
-
return ao.offsetX === bo.offsetX && ao.offsetY === bo.offsetY && ao.density === bo.density;
|
|
148
|
-
}
|
|
149
|
-
function transitionPropertiesEqual(a, b) {
|
|
150
|
-
if (a === b)
|
|
151
|
-
return true;
|
|
152
|
-
if (a === undefined || b === undefined)
|
|
153
|
-
return false;
|
|
154
|
-
if (a === "all" || b === "all")
|
|
155
|
-
return a === b;
|
|
156
|
-
if (!Array.isArray(a) || !Array.isArray(b))
|
|
157
|
-
return false;
|
|
158
|
-
if (a.length !== b.length)
|
|
159
|
-
return false;
|
|
160
|
-
for (let i = 0; i < a.length; i++) {
|
|
161
|
-
if (a[i] !== b[i])
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
function transitionSpecEqual(a, b) {
|
|
167
|
-
if (a === b)
|
|
168
|
-
return true;
|
|
169
|
-
if (a === undefined || b === undefined)
|
|
170
|
-
return false;
|
|
171
|
-
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null)
|
|
172
|
-
return false;
|
|
173
|
-
const ao = a;
|
|
174
|
-
const bo = b;
|
|
175
|
-
return (ao.duration === bo.duration &&
|
|
176
|
-
ao.easing === bo.easing &&
|
|
177
|
-
transitionPropertiesEqual(ao.properties, bo.properties));
|
|
178
|
-
}
|
|
179
|
-
function layoutConstraintsEqual(a, b) {
|
|
180
|
-
if (a === b)
|
|
181
|
-
return true;
|
|
182
|
-
const ao = (a ?? {});
|
|
183
|
-
const bo = (b ?? {});
|
|
184
|
-
return (ao.width === bo.width &&
|
|
185
|
-
ao.height === bo.height &&
|
|
186
|
-
ao.minWidth === bo.minWidth &&
|
|
187
|
-
ao.maxWidth === bo.maxWidth &&
|
|
188
|
-
ao.minHeight === bo.minHeight &&
|
|
189
|
-
ao.maxHeight === bo.maxHeight &&
|
|
190
|
-
ao.flex === bo.flex &&
|
|
191
|
-
ao.aspectRatio === bo.aspectRatio);
|
|
192
|
-
}
|
|
193
|
-
function shallowRecordEqual(a, b) {
|
|
194
|
-
const aKeys = Object.keys(a);
|
|
195
|
-
const bKeys = Object.keys(b);
|
|
196
|
-
if (aKeys.length !== bKeys.length)
|
|
197
|
-
return false;
|
|
198
|
-
for (const key of aKeys) {
|
|
199
|
-
if (!(key in b))
|
|
200
|
-
return false;
|
|
201
|
-
if (!Object.is(a[key], b[key]))
|
|
202
|
-
return false;
|
|
203
|
-
}
|
|
204
|
-
return true;
|
|
205
|
-
}
|
|
206
|
-
function compositePropsEqual(prev, next) {
|
|
207
|
-
if (Object.is(prev, next))
|
|
208
|
-
return true;
|
|
209
|
-
if (typeof prev !== "object" || prev === null)
|
|
210
|
-
return false;
|
|
211
|
-
if (typeof next !== "object" || next === null)
|
|
212
|
-
return false;
|
|
213
|
-
return shallowRecordEqual(prev, next);
|
|
214
|
-
}
|
|
215
|
-
function evaluateAppStateSelections(selections, appState) {
|
|
216
|
-
for (const selection of selections) {
|
|
217
|
-
try {
|
|
218
|
-
const nextValue = selection.selector(appState);
|
|
219
|
-
if (!Object.is(nextValue, selection.value)) {
|
|
220
|
-
return { changed: true, threw: null };
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
catch (e) {
|
|
224
|
-
return { changed: true, threw: e };
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return { changed: false, threw: null };
|
|
228
|
-
}
|
|
229
|
-
function spacingPropsEqual(a, b) {
|
|
230
|
-
if (a === b)
|
|
231
|
-
return true;
|
|
232
|
-
const ao = (a ?? {});
|
|
233
|
-
const bo = (b ?? {});
|
|
234
|
-
return (ao.p === bo.p &&
|
|
235
|
-
ao.px === bo.px &&
|
|
236
|
-
ao.py === bo.py &&
|
|
237
|
-
ao.pt === bo.pt &&
|
|
238
|
-
ao.pb === bo.pb &&
|
|
239
|
-
ao.pl === bo.pl &&
|
|
240
|
-
ao.pr === bo.pr &&
|
|
241
|
-
ao.m === bo.m &&
|
|
242
|
-
ao.mx === bo.mx &&
|
|
243
|
-
ao.my === bo.my &&
|
|
244
|
-
ao.mt === bo.mt &&
|
|
245
|
-
ao.mr === bo.mr &&
|
|
246
|
-
ao.mb === bo.mb &&
|
|
247
|
-
ao.ml === bo.ml);
|
|
248
|
-
}
|
|
249
|
-
function boxPropsEqual(a, b) {
|
|
250
|
-
if (a === b)
|
|
251
|
-
return true;
|
|
252
|
-
const ao = (a ?? {});
|
|
253
|
-
const bo = (b ?? {});
|
|
254
|
-
return (ao.title === bo.title &&
|
|
255
|
-
ao.titleAlign === bo.titleAlign &&
|
|
256
|
-
ao.pad === bo.pad &&
|
|
257
|
-
ao.border === bo.border &&
|
|
258
|
-
ao.borderTop === bo.borderTop &&
|
|
259
|
-
ao.borderRight === bo.borderRight &&
|
|
260
|
-
ao.borderBottom === bo.borderBottom &&
|
|
261
|
-
ao.borderLeft === bo.borderLeft &&
|
|
262
|
-
boxShadowEqual(ao.shadow, bo.shadow) &&
|
|
263
|
-
textStyleEqual(ao.style, bo.style) &&
|
|
264
|
-
textStyleEqual(ao.inheritStyle, bo.inheritStyle) &&
|
|
265
|
-
ao.opacity === bo.opacity &&
|
|
266
|
-
transitionSpecEqual(ao.transition, bo.transition) &&
|
|
267
|
-
transitionSpecEqual(ao.exitTransition, bo.exitTransition) &&
|
|
268
|
-
spacingPropsEqual(ao, bo) &&
|
|
269
|
-
layoutConstraintsEqual(ao, bo));
|
|
270
|
-
}
|
|
271
|
-
function stackPropsEqual(a, b) {
|
|
272
|
-
if (a === b)
|
|
273
|
-
return true;
|
|
274
|
-
const ao = (a ?? {});
|
|
275
|
-
const bo = (b ?? {});
|
|
276
|
-
return (ao.pad === bo.pad &&
|
|
277
|
-
ao.gap === bo.gap &&
|
|
278
|
-
ao.align === bo.align &&
|
|
279
|
-
ao.justify === bo.justify &&
|
|
280
|
-
ao.items === bo.items &&
|
|
281
|
-
textStyleEqual(ao.style, bo.style) &&
|
|
282
|
-
textStyleEqual(ao.inheritStyle, bo.inheritStyle) &&
|
|
283
|
-
transitionSpecEqual(ao.transition, bo.transition) &&
|
|
284
|
-
transitionSpecEqual(ao.exitTransition, bo.exitTransition) &&
|
|
285
|
-
spacingPropsEqual(ao, bo) &&
|
|
286
|
-
layoutConstraintsEqual(ao, bo));
|
|
287
|
-
}
|
|
288
|
-
function focusZonePropsEqual(a, b) {
|
|
289
|
-
if (a === b)
|
|
290
|
-
return true;
|
|
291
|
-
const ao = (a ?? {});
|
|
292
|
-
const bo = (b ?? {});
|
|
293
|
-
return (ao.id === bo.id &&
|
|
294
|
-
ao.tabIndex === bo.tabIndex &&
|
|
295
|
-
ao.navigation === bo.navigation &&
|
|
296
|
-
ao.columns === bo.columns &&
|
|
297
|
-
ao.wrapAround === bo.wrapAround &&
|
|
298
|
-
ao.onEnter === bo.onEnter &&
|
|
299
|
-
ao.onExit === bo.onExit);
|
|
300
|
-
}
|
|
301
|
-
function focusTrapPropsEqual(a, b) {
|
|
302
|
-
if (a === b)
|
|
303
|
-
return true;
|
|
304
|
-
const ao = (a ?? {});
|
|
305
|
-
const bo = (b ?? {});
|
|
306
|
-
return (ao.id === bo.id &&
|
|
307
|
-
ao.active === bo.active &&
|
|
308
|
-
ao.returnFocusTo === bo.returnFocusTo &&
|
|
309
|
-
ao.initialFocus === bo.initialFocus);
|
|
310
|
-
}
|
|
311
|
-
function deepEqualUnknown(a, b) {
|
|
312
|
-
if (a === b)
|
|
313
|
-
return true;
|
|
314
|
-
if (typeof a !== typeof b)
|
|
315
|
-
return false;
|
|
316
|
-
if (typeof a !== "object" || a === null || b === null)
|
|
317
|
-
return false;
|
|
318
|
-
if (Array.isArray(a) || Array.isArray(b)) {
|
|
319
|
-
if (!Array.isArray(a) || !Array.isArray(b))
|
|
320
|
-
return false;
|
|
321
|
-
if (a.length !== b.length)
|
|
322
|
-
return false;
|
|
323
|
-
for (let i = 0; i < a.length; i++) {
|
|
324
|
-
if (!deepEqualUnknown(a[i], b[i]))
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
327
|
-
return true;
|
|
328
|
-
}
|
|
329
|
-
const aRecord = a;
|
|
330
|
-
const bRecord = b;
|
|
331
|
-
const aKeys = Object.keys(aRecord);
|
|
332
|
-
const bKeys = Object.keys(bRecord);
|
|
333
|
-
if (aKeys.length !== bKeys.length)
|
|
334
|
-
return false;
|
|
335
|
-
for (const key of aKeys) {
|
|
336
|
-
if (!Object.prototype.hasOwnProperty.call(bRecord, key))
|
|
337
|
-
return false;
|
|
338
|
-
if (!deepEqualUnknown(aRecord[key], bRecord[key]))
|
|
339
|
-
return false;
|
|
340
|
-
}
|
|
341
|
-
return true;
|
|
342
|
-
}
|
|
343
|
-
function themedPropsEqual(a, b) {
|
|
344
|
-
if (a === b)
|
|
345
|
-
return true;
|
|
346
|
-
const ao = (a ?? {});
|
|
347
|
-
const bo = (b ?? {});
|
|
348
|
-
return deepEqualUnknown(ao.theme, bo.theme);
|
|
349
|
-
}
|
|
350
|
-
function fragmentPropsEqual(a, b) {
|
|
351
|
-
if (a === b)
|
|
352
|
-
return true;
|
|
353
|
-
const ao = (a ?? {});
|
|
354
|
-
const bo = (b ?? {});
|
|
355
|
-
return ao.key === bo.key;
|
|
356
|
-
}
|
|
357
|
-
function canFastReuseContainerSelf(prev, next) {
|
|
358
|
-
if (prev.kind !== next.kind)
|
|
359
|
-
return false;
|
|
360
|
-
switch (prev.kind) {
|
|
361
|
-
case "fragment":
|
|
362
|
-
return fragmentPropsEqual(prev.props, next.props);
|
|
363
|
-
case "box":
|
|
364
|
-
return boxPropsEqual(prev.props, next.props);
|
|
365
|
-
case "row":
|
|
366
|
-
case "column":
|
|
367
|
-
return stackPropsEqual(prev.props, next.props);
|
|
368
|
-
case "focusZone":
|
|
369
|
-
return focusZonePropsEqual(prev.props, next.props);
|
|
370
|
-
case "focusTrap":
|
|
371
|
-
return focusTrapPropsEqual(prev.props, next.props);
|
|
372
|
-
case "themed":
|
|
373
|
-
return themedPropsEqual(prev.props, next.props);
|
|
374
|
-
default:
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Diagnostic: identify which specific prop fails for container reuse.
|
|
380
|
-
* Only called when __commitDiag.enabled is true.
|
|
381
|
-
*/
|
|
382
|
-
function diagWhichPropFails(prev, next) {
|
|
383
|
-
if (prev.kind !== next.kind)
|
|
384
|
-
return "kind";
|
|
385
|
-
const ap = (prev.props ?? {});
|
|
386
|
-
const bp = (next.props ?? {});
|
|
387
|
-
if (prev.kind === "fragment" && ap.key !== bp.key) {
|
|
388
|
-
return "key";
|
|
389
|
-
}
|
|
390
|
-
if (prev.kind === "row" || prev.kind === "column") {
|
|
391
|
-
for (const k of ["pad", "gap", "align", "justify", "items"]) {
|
|
392
|
-
if (ap[k] !== bp[k])
|
|
393
|
-
return k;
|
|
394
|
-
}
|
|
395
|
-
if (!textStyleEqual(ap.style, bp.style))
|
|
396
|
-
return "style";
|
|
397
|
-
if (!textStyleEqual(ap.inheritStyle, bp.inheritStyle))
|
|
398
|
-
return "inheritStyle";
|
|
399
|
-
// layout constraints
|
|
400
|
-
for (const k of [
|
|
401
|
-
"width",
|
|
402
|
-
"height",
|
|
403
|
-
"minWidth",
|
|
404
|
-
"maxWidth",
|
|
405
|
-
"minHeight",
|
|
406
|
-
"maxHeight",
|
|
407
|
-
"flex",
|
|
408
|
-
"aspectRatio",
|
|
409
|
-
]) {
|
|
410
|
-
if (ap[k] !== bp[k])
|
|
411
|
-
return k;
|
|
412
|
-
}
|
|
413
|
-
// spacing
|
|
414
|
-
for (const k of [
|
|
415
|
-
"p",
|
|
416
|
-
"px",
|
|
417
|
-
"py",
|
|
418
|
-
"pt",
|
|
419
|
-
"pb",
|
|
420
|
-
"pl",
|
|
421
|
-
"pr",
|
|
422
|
-
"m",
|
|
423
|
-
"mx",
|
|
424
|
-
"my",
|
|
425
|
-
"mt",
|
|
426
|
-
"mr",
|
|
427
|
-
"mb",
|
|
428
|
-
"ml",
|
|
429
|
-
]) {
|
|
430
|
-
if (ap[k] !== bp[k])
|
|
431
|
-
return k;
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
if (prev.kind === "box") {
|
|
435
|
-
for (const k of [
|
|
436
|
-
"title",
|
|
437
|
-
"titleAlign",
|
|
438
|
-
"pad",
|
|
439
|
-
"border",
|
|
440
|
-
"borderTop",
|
|
441
|
-
"borderRight",
|
|
442
|
-
"borderBottom",
|
|
443
|
-
"borderLeft",
|
|
444
|
-
"opacity",
|
|
445
|
-
]) {
|
|
446
|
-
if (ap[k] !== bp[k])
|
|
447
|
-
return k;
|
|
448
|
-
}
|
|
449
|
-
if (!textStyleEqual(ap.style, bp.style))
|
|
450
|
-
return "style";
|
|
451
|
-
for (const k of [
|
|
452
|
-
"width",
|
|
453
|
-
"height",
|
|
454
|
-
"minWidth",
|
|
455
|
-
"maxWidth",
|
|
456
|
-
"minHeight",
|
|
457
|
-
"maxHeight",
|
|
458
|
-
"flex",
|
|
459
|
-
"aspectRatio",
|
|
460
|
-
]) {
|
|
461
|
-
if (ap[k] !== bp[k])
|
|
462
|
-
return k;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
return "unknown";
|
|
466
|
-
}
|
|
467
|
-
function runtimeChildrenChanged(prevChildren, nextChildren) {
|
|
468
|
-
if (prevChildren.length !== nextChildren.length)
|
|
469
|
-
return true;
|
|
470
|
-
for (let i = 0; i < prevChildren.length; i++) {
|
|
471
|
-
if (prevChildren[i] !== nextChildren[i])
|
|
472
|
-
return true;
|
|
473
|
-
}
|
|
474
|
-
return false;
|
|
475
|
-
}
|
|
476
|
-
function hasDirtyChild(children) {
|
|
477
|
-
for (const child of children) {
|
|
478
|
-
if (child.dirty)
|
|
479
|
-
return true;
|
|
480
|
-
}
|
|
481
|
-
return false;
|
|
482
|
-
}
|
|
483
|
-
const NODE_ENV = globalThis.process?.env?.NODE_ENV ??
|
|
484
|
-
"development";
|
|
485
|
-
const DEV_MODE = NODE_ENV !== "production";
|
|
486
|
-
const LAYOUT_DEPTH_WARN_THRESHOLD = 200;
|
|
487
|
-
const MAX_LAYOUT_NESTING_DEPTH = 500;
|
|
488
|
-
const MAX_LAYOUT_DEPTH_PATH_SEGMENTS = 32;
|
|
489
|
-
const MAX_INTERACTIVE_ID_LENGTH = 256;
|
|
490
|
-
const DEFAULT_EXIT_TRANSITION_DURATION_MS = 180;
|
|
491
|
-
const LAYOUT_DEPTH_PATH_TRACK_START = Math.max(1, LAYOUT_DEPTH_WARN_THRESHOLD - MAX_LAYOUT_DEPTH_PATH_SEGMENTS + 2);
|
|
492
|
-
function warnDev(message) {
|
|
493
|
-
const c = globalThis.console;
|
|
494
|
-
c?.warn?.(message);
|
|
495
|
-
}
|
|
496
|
-
function widgetPathEntry(vnode) {
|
|
497
|
-
const props = vnode.props;
|
|
498
|
-
const id = typeof props?.id === "string" && props.id.length > 0 ? `#${props.id}` : "";
|
|
499
|
-
const key = typeof props?.key === "string" || typeof props?.key === "number"
|
|
500
|
-
? `[key=${String(props.key)}]`
|
|
501
|
-
: "";
|
|
502
|
-
return `${vnode.kind}${id}${key}`;
|
|
503
|
-
}
|
|
504
|
-
function formatWidgetPath(depth, tailPath) {
|
|
505
|
-
if (tailPath.length === 0)
|
|
506
|
-
return "(root)";
|
|
507
|
-
const path = tailPath.join(" -> ");
|
|
508
|
-
return depth > tailPath.length ? `... -> ${path}` : path;
|
|
509
|
-
}
|
|
510
|
-
function isInteractiveVNode(v) {
|
|
511
|
-
const proto = getWidgetProtocol(v.kind);
|
|
512
|
-
return proto.requiresId || proto.focusable || proto.pressable;
|
|
513
|
-
}
|
|
514
|
-
function ensureInteractiveId(seen, instanceId, vnode) {
|
|
515
|
-
if (!isInteractiveVNode(vnode))
|
|
516
|
-
return null;
|
|
517
|
-
// Runtime validation (even though most interactive widgets are typed with required ids).
|
|
518
|
-
const id = vnode.props.id;
|
|
519
|
-
if (typeof id !== "string" || id.length === 0) {
|
|
520
|
-
if (!kindRequiresId(vnode.kind))
|
|
521
|
-
return null;
|
|
522
|
-
return {
|
|
523
|
-
code: "ZRUI_INVALID_PROPS",
|
|
524
|
-
detail: `interactive node missing required id (kind=${vnode.kind}, instanceId=${String(instanceId)})`,
|
|
525
|
-
};
|
|
526
|
-
}
|
|
527
|
-
if (id.trim().length === 0) {
|
|
528
|
-
return {
|
|
529
|
-
code: "ZRUI_INVALID_PROPS",
|
|
530
|
-
detail: `interactive node id must contain non-whitespace characters (kind=${vnode.kind}, instanceId=${String(instanceId)})`,
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
const existing = seen.get(id);
|
|
534
|
-
if (existing !== undefined) {
|
|
535
|
-
return {
|
|
536
|
-
code: "ZRUI_DUPLICATE_ID",
|
|
537
|
-
detail: `Duplicate interactive widget id "${id}". First: <${existing}>, second: <${vnode.kind}>. Hint: Use ctx.id() inside defineWidget to generate unique IDs for list items.`,
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
if (DEV_MODE && id.length > MAX_INTERACTIVE_ID_LENGTH) {
|
|
541
|
-
warnDev(`[rezi][commit] interactive widget id exceeds ${String(MAX_INTERACTIVE_ID_LENGTH)} chars (kind=${vnode.kind}, id length=${String(id.length)}). Consider using shorter IDs.`);
|
|
542
|
-
}
|
|
543
|
-
seen.set(id, vnode.kind);
|
|
544
|
-
return null;
|
|
545
|
-
}
|
|
546
|
-
function isFocusContainerVNode(vnode) {
|
|
547
|
-
return vnode.kind === "focusZone" || vnode.kind === "focusTrap" || vnode.kind === "modal";
|
|
548
|
-
}
|
|
549
|
-
function ensureFocusContainerId(seen, instanceId, vnode) {
|
|
550
|
-
if (!isFocusContainerVNode(vnode))
|
|
551
|
-
return null;
|
|
552
|
-
const id = vnode.props.id;
|
|
553
|
-
if (typeof id !== "string" || id.length === 0) {
|
|
554
|
-
return {
|
|
555
|
-
code: "ZRUI_INVALID_PROPS",
|
|
556
|
-
detail: `focus container missing required id (kind=${vnode.kind}, instanceId=${String(instanceId)})`,
|
|
557
|
-
};
|
|
558
|
-
}
|
|
559
|
-
if (id.trim().length === 0) {
|
|
560
|
-
return {
|
|
561
|
-
code: "ZRUI_INVALID_PROPS",
|
|
562
|
-
detail: `focus container id must contain non-whitespace characters (kind=${vnode.kind}, instanceId=${String(instanceId)})`,
|
|
563
|
-
};
|
|
564
|
-
}
|
|
565
|
-
const existing = seen.get(id);
|
|
566
|
-
if (existing !== undefined) {
|
|
567
|
-
return {
|
|
568
|
-
code: "ZRUI_DUPLICATE_ID",
|
|
569
|
-
detail: `Duplicate focus container id "${id}". First: <${existing}>, second: <${vnode.kind}>. Hint: focusZone, focusTrap, and modal ids must be unique across the tree.`,
|
|
570
|
-
};
|
|
571
|
-
}
|
|
572
|
-
seen.set(id, vnode.kind);
|
|
573
|
-
return null;
|
|
574
|
-
}
|
|
575
|
-
function isVNode(v) {
|
|
576
|
-
return typeof v === "object" && v !== null && "kind" in v;
|
|
577
|
-
}
|
|
578
|
-
function commitChildrenForVNode(vnode) {
|
|
579
|
-
if (vnode.kind === "fragment" ||
|
|
580
|
-
vnode.kind === "box" ||
|
|
581
|
-
vnode.kind === "row" ||
|
|
582
|
-
vnode.kind === "column" ||
|
|
583
|
-
vnode.kind === "themed" ||
|
|
584
|
-
vnode.kind === "grid" ||
|
|
585
|
-
vnode.kind === "focusZone" ||
|
|
586
|
-
vnode.kind === "focusTrap" ||
|
|
587
|
-
vnode.kind === "layers" ||
|
|
588
|
-
vnode.kind === "tabs" ||
|
|
589
|
-
vnode.kind === "accordion" ||
|
|
590
|
-
vnode.kind === "breadcrumb" ||
|
|
591
|
-
vnode.kind === "pagination" ||
|
|
592
|
-
// Advanced container widgets (GitHub issue #136)
|
|
593
|
-
vnode.kind === "splitPane" ||
|
|
594
|
-
vnode.kind === "panelGroup") {
|
|
595
|
-
return vnode.children;
|
|
596
|
-
}
|
|
597
|
-
if (vnode.kind === "field" || vnode.kind === "resizablePanel") {
|
|
598
|
-
const child = vnode.children[0];
|
|
599
|
-
return child ? [child] : [];
|
|
600
|
-
}
|
|
601
|
-
if (vnode.kind === "layer") {
|
|
602
|
-
const content = vnode.props.content;
|
|
603
|
-
return isVNode(content) ? [content] : [];
|
|
604
|
-
}
|
|
605
|
-
if (vnode.kind === "modal") {
|
|
606
|
-
const props = vnode.props;
|
|
607
|
-
const content = isVNode(props.content) ? props.content : null;
|
|
608
|
-
const actionsRaw = Array.isArray(props.actions) ? props.actions : [];
|
|
609
|
-
const actions = [];
|
|
610
|
-
for (const a of actionsRaw) {
|
|
611
|
-
if (isVNode(a))
|
|
612
|
-
actions.push(a);
|
|
613
|
-
}
|
|
614
|
-
const children = [];
|
|
615
|
-
if (content)
|
|
616
|
-
children.push(content);
|
|
617
|
-
children.push(...actions);
|
|
618
|
-
return children;
|
|
619
|
-
}
|
|
620
|
-
return [];
|
|
621
|
-
}
|
|
622
|
-
function collectSubtreeInstanceIds(node, out) {
|
|
623
|
-
out.push(node.instanceId);
|
|
624
|
-
for (const c of node.children)
|
|
625
|
-
collectSubtreeInstanceIds(c, out);
|
|
626
|
-
}
|
|
627
|
-
function deleteLocalStateForSubtree(store, node) {
|
|
628
|
-
if (!store)
|
|
629
|
-
return;
|
|
630
|
-
const stack = [node];
|
|
631
|
-
while (stack.length > 0) {
|
|
632
|
-
const cur = stack.pop();
|
|
633
|
-
if (!cur)
|
|
634
|
-
continue;
|
|
635
|
-
store.delete(cur.instanceId);
|
|
636
|
-
for (const c of cur.children)
|
|
637
|
-
stack.push(c);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
function commitNowMs() {
|
|
641
|
-
const perf = globalThis.performance;
|
|
642
|
-
const perfNow = perf?.now;
|
|
643
|
-
if (typeof perfNow === "function")
|
|
644
|
-
return perfNow.call(perf);
|
|
645
|
-
return Date.now();
|
|
646
|
-
}
|
|
647
|
-
function readVNodeKey(vnode) {
|
|
648
|
-
const props = vnode.props;
|
|
649
|
-
const key = props?.key;
|
|
650
|
-
return typeof key === "string" ? key : undefined;
|
|
651
|
-
}
|
|
652
|
-
function readExitTransition(vnode) {
|
|
653
|
-
if (vnode.kind !== "box" &&
|
|
654
|
-
vnode.kind !== "row" &&
|
|
655
|
-
vnode.kind !== "column" &&
|
|
656
|
-
vnode.kind !== "grid") {
|
|
657
|
-
return null;
|
|
658
|
-
}
|
|
659
|
-
const props = vnode.props;
|
|
660
|
-
return props?.exitTransition ?? null;
|
|
661
|
-
}
|
|
662
|
-
function resolveExitAnimationState(instanceId, transition) {
|
|
663
|
-
const durationMs = normalizeDurationMs(transition.duration, DEFAULT_EXIT_TRANSITION_DURATION_MS);
|
|
664
|
-
if (durationMs <= 0)
|
|
665
|
-
return null;
|
|
666
|
-
return Object.freeze({
|
|
667
|
-
instanceId,
|
|
668
|
-
startMs: commitNowMs(),
|
|
669
|
-
durationMs,
|
|
670
|
-
easing: resolveEasing(transition.easing),
|
|
671
|
-
properties: transition.properties ?? "all",
|
|
672
|
-
});
|
|
673
|
-
}
|
|
674
|
-
function createDeferredLocalStateCleanup(localState, node) {
|
|
675
|
-
let cleaned = false;
|
|
676
|
-
return () => {
|
|
677
|
-
if (cleaned)
|
|
678
|
-
return;
|
|
679
|
-
cleaned = true;
|
|
680
|
-
deleteLocalStateForSubtree(localState, node);
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
function tryScheduleExitAnimation(ctx, node, parentInstanceId) {
|
|
684
|
-
const exitTransition = readExitTransition(node.vnode);
|
|
685
|
-
if (!exitTransition)
|
|
686
|
-
return false;
|
|
687
|
-
const exit = resolveExitAnimationState(node.instanceId, exitTransition);
|
|
688
|
-
if (!exit)
|
|
689
|
-
return false;
|
|
690
|
-
const subtreeInstanceIds = [];
|
|
691
|
-
collectSubtreeInstanceIds(node, subtreeInstanceIds);
|
|
692
|
-
ctx.pendingExitAnimations.push(Object.freeze({
|
|
693
|
-
instanceId: node.instanceId,
|
|
694
|
-
parentInstanceId,
|
|
695
|
-
runtimeRoot: node,
|
|
696
|
-
vnodeKind: node.vnode.kind,
|
|
697
|
-
key: readVNodeKey(node.vnode),
|
|
698
|
-
exit,
|
|
699
|
-
subtreeInstanceIds: Object.freeze(subtreeInstanceIds),
|
|
700
|
-
runDeferredLocalStateCleanup: createDeferredLocalStateCleanup(ctx.localState, node),
|
|
701
|
-
}));
|
|
702
|
-
return true;
|
|
703
|
-
}
|
|
704
|
-
function markCompositeSubtreeStale(registry, node) {
|
|
705
|
-
const stack = [node];
|
|
706
|
-
while (stack.length > 0) {
|
|
707
|
-
const cur = stack.pop();
|
|
708
|
-
if (!cur)
|
|
709
|
-
continue;
|
|
710
|
-
registry.incrementGeneration(cur.instanceId);
|
|
711
|
-
for (const c of cur.children)
|
|
712
|
-
stack.push(c);
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
function currentCompositeTheme(ctx) {
|
|
716
|
-
if (ctx.compositeThemeStack.length === 0)
|
|
717
|
-
return null;
|
|
718
|
-
return ctx.compositeThemeStack[ctx.compositeThemeStack.length - 1] ?? null;
|
|
719
|
-
}
|
|
720
|
-
function resolveCompositeChildTheme(parentTheme, vnode) {
|
|
721
|
-
if (vnode.kind === "themed") {
|
|
722
|
-
const props = vnode.props;
|
|
723
|
-
return mergeThemeOverride(parentTheme, props.theme);
|
|
724
|
-
}
|
|
725
|
-
if (vnode.kind === "row" ||
|
|
726
|
-
vnode.kind === "column" ||
|
|
727
|
-
vnode.kind === "grid" ||
|
|
728
|
-
vnode.kind === "box") {
|
|
729
|
-
const props = vnode.props;
|
|
730
|
-
return mergeThemeOverride(parentTheme, props.theme);
|
|
731
|
-
}
|
|
732
|
-
return parentTheme;
|
|
733
|
-
}
|
|
734
|
-
function readCompositeColorTokens(ctx) {
|
|
735
|
-
const composite = ctx.composite;
|
|
736
|
-
if (!composite)
|
|
737
|
-
return defaultTheme.definition.colors;
|
|
738
|
-
const theme = currentCompositeTheme(ctx);
|
|
739
|
-
if (theme !== null) {
|
|
740
|
-
if (!composite.getColorTokens)
|
|
741
|
-
return theme.definition.colors;
|
|
742
|
-
return composite.getColorTokens(theme) ?? theme.definition.colors;
|
|
743
|
-
}
|
|
744
|
-
return composite.colorTokens ?? defaultTheme.definition.colors;
|
|
745
|
-
}
|
|
746
|
-
const MAX_COMPOSITE_RENDER_DEPTH = 100;
|
|
747
|
-
const DEFAULT_VIEWPORT_SNAPSHOT = Object.freeze({
|
|
748
|
-
width: 0,
|
|
749
|
-
height: 0,
|
|
750
|
-
breakpoint: "sm",
|
|
751
|
-
});
|
|
752
|
-
function captureErrorBoundaryState(detail) {
|
|
753
|
-
return Object.freeze({
|
|
754
|
-
code: "ZRUI_USER_CODE_THROW",
|
|
755
|
-
detail,
|
|
756
|
-
message: detail,
|
|
757
|
-
});
|
|
758
|
-
}
|
|
759
|
-
function commitErrorBoundaryFallback(prev, instanceId, boundaryPath, fallbackPath, props, state, ctx) {
|
|
760
|
-
const fallback = props.fallback;
|
|
761
|
-
if (typeof fallback !== "function") {
|
|
762
|
-
return {
|
|
763
|
-
ok: false,
|
|
764
|
-
fatal: {
|
|
765
|
-
code: "ZRUI_INVALID_PROPS",
|
|
766
|
-
detail: "errorBoundary fallback must be a function",
|
|
767
|
-
},
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
let fallbackVNode;
|
|
771
|
-
try {
|
|
772
|
-
fallbackVNode = fallback(Object.freeze({
|
|
773
|
-
code: state.code,
|
|
774
|
-
message: state.message,
|
|
775
|
-
detail: state.detail,
|
|
776
|
-
...(state.stack ? { stack: state.stack } : {}),
|
|
777
|
-
retry: () => {
|
|
778
|
-
ctx.errorBoundary?.requestRetry(boundaryPath);
|
|
779
|
-
},
|
|
780
|
-
}));
|
|
781
|
-
}
|
|
782
|
-
catch (e) {
|
|
783
|
-
return {
|
|
784
|
-
ok: false,
|
|
785
|
-
fatal: {
|
|
786
|
-
code: "ZRUI_USER_CODE_THROW",
|
|
787
|
-
detail: describeThrown(e),
|
|
788
|
-
},
|
|
789
|
-
};
|
|
790
|
-
}
|
|
791
|
-
if (!isVNode(fallbackVNode)) {
|
|
792
|
-
return {
|
|
793
|
-
ok: false,
|
|
794
|
-
fatal: {
|
|
795
|
-
code: "ZRUI_INVALID_PROPS",
|
|
796
|
-
detail: "errorBoundary fallback must return a VNode",
|
|
797
|
-
},
|
|
798
|
-
};
|
|
799
|
-
}
|
|
800
|
-
return commitNode(prev, instanceId, fallbackVNode, ctx, fallbackPath);
|
|
801
|
-
}
|
|
802
|
-
function appendNodePath(nodePath, segment) {
|
|
803
|
-
return [...nodePath, segment];
|
|
804
|
-
}
|
|
805
|
-
function formatNodePath(nodePath) {
|
|
806
|
-
return nodePath.join("/");
|
|
807
|
-
}
|
|
808
|
-
function isContainerVNode(vnode) {
|
|
809
|
-
return (vnode.kind === "fragment" ||
|
|
810
|
-
vnode.kind === "box" ||
|
|
811
|
-
vnode.kind === "row" ||
|
|
812
|
-
vnode.kind === "column" ||
|
|
813
|
-
vnode.kind === "themed" ||
|
|
814
|
-
vnode.kind === "grid" ||
|
|
815
|
-
vnode.kind === "focusZone" ||
|
|
816
|
-
vnode.kind === "focusTrap" ||
|
|
817
|
-
vnode.kind === "layers" ||
|
|
818
|
-
vnode.kind === "field" ||
|
|
819
|
-
vnode.kind === "tabs" ||
|
|
820
|
-
vnode.kind === "accordion" ||
|
|
821
|
-
vnode.kind === "breadcrumb" ||
|
|
822
|
-
vnode.kind === "pagination" ||
|
|
823
|
-
// Advanced container widgets (GitHub issue #136)
|
|
824
|
-
vnode.kind === "splitPane" ||
|
|
825
|
-
vnode.kind === "panelGroup" ||
|
|
826
|
-
vnode.kind === "resizablePanel" ||
|
|
827
|
-
vnode.kind === "modal" ||
|
|
828
|
-
vnode.kind === "layer");
|
|
829
|
-
}
|
|
830
|
-
function rewriteCommittedVNode(next, committedChildren) {
|
|
831
|
-
if (next.kind === "modal") {
|
|
832
|
-
const props = next.props;
|
|
833
|
-
const contentPresent = isVNode(props.content);
|
|
834
|
-
const nextContent = contentPresent ? (committedChildren[0] ?? props.content) : props.content;
|
|
835
|
-
const actionsStart = contentPresent ? 1 : 0;
|
|
836
|
-
const actions = committedChildren.slice(actionsStart);
|
|
837
|
-
return {
|
|
838
|
-
...next,
|
|
839
|
-
props: {
|
|
840
|
-
...next.props,
|
|
841
|
-
...(isVNode(nextContent) ? { content: nextContent } : {}),
|
|
842
|
-
actions: actions.length > 0 ? actions : undefined,
|
|
843
|
-
},
|
|
844
|
-
};
|
|
845
|
-
}
|
|
846
|
-
if (next.kind === "layer") {
|
|
847
|
-
const props = next.props;
|
|
848
|
-
const nextContent = committedChildren[0] ?? props.content;
|
|
849
|
-
return {
|
|
850
|
-
...next,
|
|
851
|
-
props: {
|
|
852
|
-
...next.props,
|
|
853
|
-
...(isVNode(nextContent) ? { content: nextContent } : {}),
|
|
854
|
-
},
|
|
855
|
-
};
|
|
856
|
-
}
|
|
857
|
-
if (next.kind === "fragment" ||
|
|
858
|
-
next.kind === "box" ||
|
|
859
|
-
next.kind === "row" ||
|
|
860
|
-
next.kind === "column" ||
|
|
861
|
-
next.kind === "themed" ||
|
|
862
|
-
next.kind === "grid" ||
|
|
863
|
-
next.kind === "focusZone" ||
|
|
864
|
-
next.kind === "focusTrap" ||
|
|
865
|
-
next.kind === "layers" ||
|
|
866
|
-
next.kind === "field" ||
|
|
867
|
-
next.kind === "tabs" ||
|
|
868
|
-
next.kind === "accordion" ||
|
|
869
|
-
next.kind === "breadcrumb" ||
|
|
870
|
-
next.kind === "pagination" ||
|
|
871
|
-
// Advanced container widgets (GitHub issue #136)
|
|
872
|
-
next.kind === "splitPane" ||
|
|
873
|
-
next.kind === "panelGroup" ||
|
|
874
|
-
next.kind === "resizablePanel") {
|
|
875
|
-
return {
|
|
876
|
-
...next,
|
|
877
|
-
children: committedChildren,
|
|
878
|
-
};
|
|
879
|
-
}
|
|
880
|
-
return next;
|
|
881
|
-
}
|
|
882
|
-
function commitContainer(instanceId, vnode, prev, ctx, nodePath, depth) {
|
|
883
|
-
void depth;
|
|
884
|
-
const parentProps = vnode.props;
|
|
885
|
-
const parentId = typeof parentProps?.id === "string" && parentProps.id.length > 0 ? parentProps.id : undefined;
|
|
886
|
-
const prevChildren = prev ? prev.children : [];
|
|
887
|
-
const compositeWrapperChildren = ctx.containerChildOverrides.get(instanceId) ?? null;
|
|
888
|
-
const res = reconcileChildren(instanceId, prevChildren, compositeWrapperChildren ? compositeWrapperChildren : commitChildrenForVNode(vnode), ctx.allocator, {
|
|
889
|
-
kind: vnode.kind,
|
|
890
|
-
...(parentId === undefined ? {} : { id: parentId }),
|
|
891
|
-
});
|
|
892
|
-
if (!res.ok)
|
|
893
|
-
return { ok: false, fatal: res.fatal };
|
|
894
|
-
const byPrevIndex = prevChildren;
|
|
895
|
-
let byPrevInstanceId = null;
|
|
896
|
-
if (res.value.unmountedInstanceIds.length > 0) {
|
|
897
|
-
byPrevInstanceId = new Map();
|
|
898
|
-
for (const c of prevChildren)
|
|
899
|
-
byPrevInstanceId.set(c.instanceId, c);
|
|
900
|
-
}
|
|
901
|
-
const parentCompositeTheme = currentCompositeTheme(ctx);
|
|
902
|
-
let pushedCompositeTheme = false;
|
|
903
|
-
if (parentCompositeTheme !== null) {
|
|
904
|
-
const nextCompositeTheme = resolveCompositeChildTheme(parentCompositeTheme, vnode);
|
|
905
|
-
if (nextCompositeTheme !== parentCompositeTheme) {
|
|
906
|
-
ctx.compositeThemeStack.push(nextCompositeTheme);
|
|
907
|
-
pushedCompositeTheme = true;
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
try {
|
|
911
|
-
// Container fast path: when reconciliation reuses all children with no
|
|
912
|
-
// additions/removals, commit each child and check if all return the exact
|
|
913
|
-
// same RuntimeInstance reference. If so, reuse the parent's RuntimeInstance,
|
|
914
|
-
// avoiding new arrays, VNode spreads, and RuntimeInstance allocation.
|
|
915
|
-
const canTryFastReuse = prev !== null &&
|
|
916
|
-
res.value.newInstanceIds.length === 0 &&
|
|
917
|
-
res.value.unmountedInstanceIds.length === 0 &&
|
|
918
|
-
res.value.nextChildren.length === prevChildren.length;
|
|
919
|
-
let childOrderStable = true;
|
|
920
|
-
if (canTryFastReuse) {
|
|
921
|
-
for (let i = 0; i < res.value.nextChildren.length; i++) {
|
|
922
|
-
const child = res.value.nextChildren[i];
|
|
923
|
-
if (!child || child.prevIndex !== i) {
|
|
924
|
-
childOrderStable = false;
|
|
925
|
-
break;
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
// Avoid allocating nextChildren/committedChildVNodes for the common case where
|
|
930
|
-
// everything is reused (e.g., list updates where only a couple rows change).
|
|
931
|
-
let nextChildren = null;
|
|
932
|
-
let committedChildVNodes = null;
|
|
933
|
-
if (canTryFastReuse) {
|
|
934
|
-
let allChildrenSame = true;
|
|
935
|
-
for (let i = 0; i < res.value.nextChildren.length; i++) {
|
|
936
|
-
const child = res.value.nextChildren[i];
|
|
937
|
-
if (!child)
|
|
938
|
-
continue;
|
|
939
|
-
const prevChild = child.prevIndex !== null ? byPrevIndex[child.prevIndex] : null;
|
|
940
|
-
const committed = commitNode(prevChild ?? null, child.instanceId, child.vnode, ctx, formatNodePath(appendNodePath(nodePath, child.slotId)));
|
|
941
|
-
if (!committed.ok)
|
|
942
|
-
return committed;
|
|
943
|
-
if (allChildrenSame && committed.value.root !== prevChild) {
|
|
944
|
-
allChildrenSame = false;
|
|
945
|
-
// First mismatch: allocate arrays and backfill prior entries with the prevChild refs
|
|
946
|
-
// we already proved were identical in earlier iterations.
|
|
947
|
-
const len = res.value.nextChildren.length;
|
|
948
|
-
const nextChildrenArr = new Array(len);
|
|
949
|
-
const committedChildVNodesArr = new Array(len);
|
|
950
|
-
nextChildren = nextChildrenArr;
|
|
951
|
-
committedChildVNodes = committedChildVNodesArr;
|
|
952
|
-
for (let j = 0; j < i; j++) {
|
|
953
|
-
const plan = res.value.nextChildren[j];
|
|
954
|
-
if (!plan)
|
|
955
|
-
continue;
|
|
956
|
-
const pc = plan.prevIndex !== null ? byPrevIndex[plan.prevIndex] : null;
|
|
957
|
-
if (!pc)
|
|
958
|
-
continue;
|
|
959
|
-
nextChildrenArr[j] = pc;
|
|
960
|
-
committedChildVNodesArr[j] = pc.vnode;
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
if (!allChildrenSame) {
|
|
964
|
-
// Arrays are allocated after the first mismatch.
|
|
965
|
-
if (!nextChildren || !committedChildVNodes) {
|
|
966
|
-
return {
|
|
967
|
-
ok: false,
|
|
968
|
-
fatal: {
|
|
969
|
-
code: "ZRUI_INVALID_PROPS",
|
|
970
|
-
detail: "commitNode: internal fast-reuse invariant",
|
|
971
|
-
},
|
|
972
|
-
};
|
|
973
|
-
}
|
|
974
|
-
nextChildren[i] = committed.value.root;
|
|
975
|
-
committedChildVNodes[i] = committed.value.root.vnode;
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
if (allChildrenSame &&
|
|
979
|
-
prev !== null &&
|
|
980
|
-
childOrderStable &&
|
|
981
|
-
canFastReuseContainerSelf(prev.vnode, vnode)) {
|
|
982
|
-
// Even when child RuntimeInstance references are stable, child VNodes may have
|
|
983
|
-
// been updated via in-place child commits. Keep the parent VNode's committed
|
|
984
|
-
// child wiring in sync so layout traverses the same tree shape as runtime.
|
|
985
|
-
const fastReuseCommittedChildren = prev.children.map((child) => child.vnode);
|
|
986
|
-
prev.vnode = rewriteCommittedVNode(vnode, fastReuseCommittedChildren);
|
|
987
|
-
// All children are identical references → reuse parent entirely.
|
|
988
|
-
// Propagate dirty from children: a child may have been mutated in-place
|
|
989
|
-
// with dirty=true even though it returned the same reference.
|
|
990
|
-
if (__commitDiag.enabled) {
|
|
991
|
-
const wasDirty = prev.selfDirty;
|
|
992
|
-
__commitDiag.push({
|
|
993
|
-
id: instanceId,
|
|
994
|
-
kind: vnode.kind,
|
|
995
|
-
reason: "fast-reuse",
|
|
996
|
-
detail: wasDirty ? "was-dirty" : undefined,
|
|
997
|
-
});
|
|
998
|
-
}
|
|
999
|
-
prev.selfDirty = false;
|
|
1000
|
-
prev.dirty = hasDirtyChild(prev.children);
|
|
1001
|
-
return { ok: true, value: { root: prev } };
|
|
1002
|
-
}
|
|
1003
|
-
// Fast-path in-place mutation: children changed but props are identical.
|
|
1004
|
-
// Mutate the existing RuntimeInstance to preserve reference identity and
|
|
1005
|
-
// prevent parent containers from cascading new-instance creation.
|
|
1006
|
-
if (!allChildrenSame &&
|
|
1007
|
-
prev !== null &&
|
|
1008
|
-
nextChildren !== null &&
|
|
1009
|
-
committedChildVNodes !== null &&
|
|
1010
|
-
canFastReuseContainerSelf(prev.vnode, vnode)) {
|
|
1011
|
-
if (__commitDiag.enabled) {
|
|
1012
|
-
let childDiffs = 0;
|
|
1013
|
-
for (let ci = 0; ci < prevChildren.length; ci++) {
|
|
1014
|
-
if (prevChildren[ci] !== nextChildren[ci])
|
|
1015
|
-
childDiffs++;
|
|
1016
|
-
}
|
|
1017
|
-
__commitDiag.push({
|
|
1018
|
-
id: instanceId,
|
|
1019
|
-
kind: vnode.kind,
|
|
1020
|
-
reason: "fast-reuse",
|
|
1021
|
-
detail: "children-changed",
|
|
1022
|
-
childDiffs,
|
|
1023
|
-
prevChildren: prevChildren.length,
|
|
1024
|
-
nextChildren: nextChildren.length,
|
|
1025
|
-
});
|
|
1026
|
-
}
|
|
1027
|
-
prev.children = nextChildren;
|
|
1028
|
-
prev.vnode = rewriteCommittedVNode(vnode, committedChildVNodes);
|
|
1029
|
-
prev.selfDirty = true;
|
|
1030
|
-
prev.dirty = true;
|
|
1031
|
-
return { ok: true, value: { root: prev } };
|
|
1032
|
-
}
|
|
1033
|
-
// Diagnostic: fast-reuse check failed at container level
|
|
1034
|
-
if (__commitDiag.enabled && prev !== null && canTryFastReuse) {
|
|
1035
|
-
if (!allChildrenSame) {
|
|
1036
|
-
// children are different — but WHY? count how many differ
|
|
1037
|
-
let childDiffs = 0;
|
|
1038
|
-
for (let ci = 0; ci < prevChildren.length; ci++) {
|
|
1039
|
-
if (nextChildren &&
|
|
1040
|
-
prevChildren[ci] !== nextChildren[ci])
|
|
1041
|
-
childDiffs++;
|
|
1042
|
-
}
|
|
1043
|
-
// also check if props would have passed
|
|
1044
|
-
const propsOk = canFastReuseContainerSelf(prev.vnode, vnode);
|
|
1045
|
-
__commitDiag.push({
|
|
1046
|
-
id: instanceId,
|
|
1047
|
-
kind: vnode.kind,
|
|
1048
|
-
reason: "new-instance",
|
|
1049
|
-
detail: propsOk ? "children-changed" : "props+children",
|
|
1050
|
-
failingProp: propsOk ? undefined : diagWhichPropFails(prev.vnode, vnode),
|
|
1051
|
-
childDiffs,
|
|
1052
|
-
prevChildren: prevChildren.length,
|
|
1053
|
-
nextChildren: nextChildren
|
|
1054
|
-
? nextChildren.length
|
|
1055
|
-
: res.value.nextChildren.length,
|
|
1056
|
-
});
|
|
1057
|
-
}
|
|
1058
|
-
else if (!childOrderStable) {
|
|
1059
|
-
__commitDiag.push({
|
|
1060
|
-
id: instanceId,
|
|
1061
|
-
kind: vnode.kind,
|
|
1062
|
-
reason: "new-instance",
|
|
1063
|
-
detail: "children-changed",
|
|
1064
|
-
});
|
|
1065
|
-
}
|
|
1066
|
-
else {
|
|
1067
|
-
// allChildrenSame && childOrderStable but canFastReuseContainerSelf failed
|
|
1068
|
-
__commitDiag.push({
|
|
1069
|
-
id: instanceId,
|
|
1070
|
-
kind: vnode.kind,
|
|
1071
|
-
reason: "new-instance",
|
|
1072
|
-
detail: "props-changed",
|
|
1073
|
-
failingProp: diagWhichPropFails(prev.vnode, vnode),
|
|
1074
|
-
});
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
}
|
|
1078
|
-
else {
|
|
1079
|
-
// General path: commit children and build next arrays.
|
|
1080
|
-
const nextChildrenArr = [];
|
|
1081
|
-
const committedChildVNodesArr = [];
|
|
1082
|
-
for (const child of res.value.nextChildren) {
|
|
1083
|
-
const prevChild = child.prevIndex !== null ? byPrevIndex[child.prevIndex] : null;
|
|
1084
|
-
const committed = commitNode(prevChild ?? null, child.instanceId, child.vnode, ctx, formatNodePath(appendNodePath(nodePath, child.slotId)));
|
|
1085
|
-
if (!committed.ok)
|
|
1086
|
-
return committed;
|
|
1087
|
-
nextChildrenArr.push(committed.value.root);
|
|
1088
|
-
committedChildVNodesArr.push(committed.value.root.vnode);
|
|
1089
|
-
}
|
|
1090
|
-
nextChildren = nextChildrenArr;
|
|
1091
|
-
committedChildVNodes = committedChildVNodesArr;
|
|
1092
|
-
}
|
|
1093
|
-
for (const unmountedId of res.value.unmountedInstanceIds) {
|
|
1094
|
-
const prevNode = byPrevInstanceId?.get(unmountedId);
|
|
1095
|
-
if (!prevNode)
|
|
1096
|
-
continue;
|
|
1097
|
-
if (tryScheduleExitAnimation(ctx, prevNode, instanceId)) {
|
|
1098
|
-
continue;
|
|
1099
|
-
}
|
|
1100
|
-
if (ctx.composite) {
|
|
1101
|
-
markCompositeSubtreeStale(ctx.composite.registry, prevNode);
|
|
1102
|
-
}
|
|
1103
|
-
deleteLocalStateForSubtree(ctx.localState, prevNode);
|
|
1104
|
-
collectSubtreeInstanceIds(prevNode, ctx.lists.unmounted);
|
|
1105
|
-
}
|
|
1106
|
-
if (!nextChildren || !committedChildVNodes) {
|
|
1107
|
-
// All committed children matched existing instances, but we still need to
|
|
1108
|
-
// materialize the next order (e.g., keyed reorders) when parent reuse is disallowed.
|
|
1109
|
-
const reorderedChildren = [];
|
|
1110
|
-
const reorderedVNodes = [];
|
|
1111
|
-
for (const child of res.value.nextChildren) {
|
|
1112
|
-
const reused = child.prevIndex !== null ? byPrevIndex[child.prevIndex] : null;
|
|
1113
|
-
if (!reused)
|
|
1114
|
-
continue;
|
|
1115
|
-
reorderedChildren.push(reused);
|
|
1116
|
-
reorderedVNodes.push(reused.vnode);
|
|
1117
|
-
}
|
|
1118
|
-
nextChildren = reorderedChildren;
|
|
1119
|
-
committedChildVNodes = reorderedVNodes;
|
|
1120
|
-
}
|
|
1121
|
-
if (!committedChildVNodes) {
|
|
1122
|
-
return {
|
|
1123
|
-
ok: false,
|
|
1124
|
-
fatal: {
|
|
1125
|
-
code: "ZRUI_INVALID_PROPS",
|
|
1126
|
-
detail: "commit invariant violated: missing committed child VNodes",
|
|
1127
|
-
},
|
|
1128
|
-
};
|
|
1129
|
-
}
|
|
1130
|
-
const propsChanged = prev === null || !canFastReuseContainerSelf(prev.vnode, vnode);
|
|
1131
|
-
const childrenChanged = prev === null || runtimeChildrenChanged(prevChildren, nextChildren);
|
|
1132
|
-
const selfDirty = propsChanged || childrenChanged;
|
|
1133
|
-
// Diagnostic: general-path new-instance (only if not already logged by fast-reuse diagnostic)
|
|
1134
|
-
if (__commitDiag.enabled && !canTryFastReuse && prev !== null) {
|
|
1135
|
-
let cDiffs = 0;
|
|
1136
|
-
const minLen = Math.min(prevChildren.length, nextChildren.length);
|
|
1137
|
-
for (let ci = 0; ci < minLen; ci++) {
|
|
1138
|
-
if (prevChildren[ci] !== nextChildren[ci])
|
|
1139
|
-
cDiffs++;
|
|
1140
|
-
}
|
|
1141
|
-
cDiffs += Math.abs(prevChildren.length - nextChildren.length);
|
|
1142
|
-
__commitDiag.push({
|
|
1143
|
-
id: instanceId,
|
|
1144
|
-
kind: vnode.kind,
|
|
1145
|
-
reason: "new-instance",
|
|
1146
|
-
detail: propsChanged && childrenChanged
|
|
1147
|
-
? "props+children"
|
|
1148
|
-
: propsChanged
|
|
1149
|
-
? "props-changed"
|
|
1150
|
-
: childrenChanged
|
|
1151
|
-
? "children-changed"
|
|
1152
|
-
: "general-path",
|
|
1153
|
-
failingProp: propsChanged ? diagWhichPropFails(prev.vnode, vnode) : undefined,
|
|
1154
|
-
childDiffs: cDiffs,
|
|
1155
|
-
prevChildren: prevChildren.length,
|
|
1156
|
-
nextChildren: nextChildren.length,
|
|
1157
|
-
});
|
|
1158
|
-
}
|
|
1159
|
-
else if (__commitDiag.enabled && prev === null) {
|
|
1160
|
-
__commitDiag.push({
|
|
1161
|
-
id: instanceId,
|
|
1162
|
-
kind: vnode.kind,
|
|
1163
|
-
reason: "new-instance",
|
|
1164
|
-
detail: "no-prev",
|
|
1165
|
-
});
|
|
1166
|
-
}
|
|
1167
|
-
// In-place mutation: when props are unchanged and only children references
|
|
1168
|
-
// changed, mutate the existing RuntimeInstance to preserve reference identity.
|
|
1169
|
-
// This prevents parent containers from cascading new-instance creation.
|
|
1170
|
-
if (prev !== null && !propsChanged && childrenChanged) {
|
|
1171
|
-
prev.children = nextChildren;
|
|
1172
|
-
prev.vnode = rewriteCommittedVNode(vnode, committedChildVNodes);
|
|
1173
|
-
prev.selfDirty = true;
|
|
1174
|
-
prev.dirty = true;
|
|
1175
|
-
return { ok: true, value: { root: prev } };
|
|
1176
|
-
}
|
|
1177
|
-
return {
|
|
1178
|
-
ok: true,
|
|
1179
|
-
value: {
|
|
1180
|
-
root: {
|
|
1181
|
-
instanceId,
|
|
1182
|
-
vnode: rewriteCommittedVNode(vnode, committedChildVNodes),
|
|
1183
|
-
children: nextChildren,
|
|
1184
|
-
dirty: selfDirty || childrenChanged || hasDirtyChild(nextChildren),
|
|
1185
|
-
selfDirty,
|
|
1186
|
-
renderPacketKey: prev?.renderPacketKey ?? 0,
|
|
1187
|
-
renderPacket: prev?.renderPacket ?? null,
|
|
1188
|
-
},
|
|
1189
|
-
},
|
|
1190
|
-
};
|
|
1191
|
-
}
|
|
1192
|
-
finally {
|
|
1193
|
-
if (pushedCompositeTheme) {
|
|
1194
|
-
ctx.compositeThemeStack.pop();
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
function executeCompositeRender(instanceId, vnode, compositeMeta, ctx, nodePath, depth) {
|
|
1199
|
-
const prev = ctx.prevNodeStack.length > 0 ? (ctx.prevNodeStack[ctx.prevNodeStack.length - 1] ?? null) : null;
|
|
1200
|
-
const compositeRuntime = ctx.composite;
|
|
1201
|
-
let compositeChild = null;
|
|
1202
|
-
let popCompositeStack = false;
|
|
1203
|
-
try {
|
|
1204
|
-
const activeCompositeMeta = compositeMeta;
|
|
1205
|
-
const registry = compositeRuntime.registry;
|
|
1206
|
-
const existing = registry.get(instanceId);
|
|
1207
|
-
if (existing && existing.widgetKey !== compositeMeta.widgetKey) {
|
|
1208
|
-
// Same instanceId but different widget type: invalidate stale closures and remount hooks.
|
|
1209
|
-
registry.incrementGeneration(instanceId);
|
|
1210
|
-
registry.delete(instanceId);
|
|
1211
|
-
}
|
|
1212
|
-
if (!registry.get(instanceId)) {
|
|
1213
|
-
try {
|
|
1214
|
-
registry.create(instanceId, compositeMeta.widgetKey);
|
|
1215
|
-
}
|
|
1216
|
-
catch (e) {
|
|
1217
|
-
return {
|
|
1218
|
-
ok: false,
|
|
1219
|
-
fatal: {
|
|
1220
|
-
code: "ZRUI_USER_CODE_THROW",
|
|
1221
|
-
detail: describeThrown(e),
|
|
1222
|
-
},
|
|
1223
|
-
};
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
const state = registry.get(instanceId);
|
|
1227
|
-
if (!state) {
|
|
1228
|
-
return {
|
|
1229
|
-
ok: false,
|
|
1230
|
-
fatal: {
|
|
1231
|
-
code: "ZRUI_INVALID_PROPS",
|
|
1232
|
-
detail: `composite state missing for instanceId=${String(instanceId)}`,
|
|
1233
|
-
},
|
|
1234
|
-
};
|
|
1235
|
-
}
|
|
1236
|
-
const invalidateInstance = () => {
|
|
1237
|
-
registry.invalidate(instanceId);
|
|
1238
|
-
ctx.composite?.onInvalidate(instanceId);
|
|
1239
|
-
};
|
|
1240
|
-
const prevMeta = prev ? getCompositeMeta(prev.vnode) : null;
|
|
1241
|
-
const prevChild = prev?.children[0] ?? null;
|
|
1242
|
-
const previousSelections = registry.getAppStateSelections(instanceId);
|
|
1243
|
-
const skipRenderEligible = !state.needsRender &&
|
|
1244
|
-
previousSelections.length > 0 &&
|
|
1245
|
-
prevMeta !== null &&
|
|
1246
|
-
prevChild !== null &&
|
|
1247
|
-
prevMeta.widgetKey === activeCompositeMeta.widgetKey &&
|
|
1248
|
-
compositePropsEqual(prevMeta.props, activeCompositeMeta.props);
|
|
1249
|
-
let canSkipCompositeRender = false;
|
|
1250
|
-
if (skipRenderEligible) {
|
|
1251
|
-
const evalRes = evaluateAppStateSelections(previousSelections, compositeRuntime.appState);
|
|
1252
|
-
if (evalRes.threw !== null) {
|
|
1253
|
-
return {
|
|
1254
|
-
ok: false,
|
|
1255
|
-
fatal: {
|
|
1256
|
-
code: "ZRUI_USER_CODE_THROW",
|
|
1257
|
-
detail: describeThrown(evalRes.threw),
|
|
1258
|
-
},
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
|
-
canSkipCompositeRender = !evalRes.changed;
|
|
1262
|
-
}
|
|
1263
|
-
if (canSkipCompositeRender && prevChild !== null) {
|
|
1264
|
-
compositeChild = prevChild.vnode;
|
|
1265
|
-
}
|
|
1266
|
-
else {
|
|
1267
|
-
let colorTokens;
|
|
1268
|
-
try {
|
|
1269
|
-
colorTokens = readCompositeColorTokens(ctx);
|
|
1270
|
-
}
|
|
1271
|
-
catch (e) {
|
|
1272
|
-
return {
|
|
1273
|
-
ok: false,
|
|
1274
|
-
fatal: {
|
|
1275
|
-
code: "ZRUI_USER_CODE_THROW",
|
|
1276
|
-
detail: describeThrown(e),
|
|
1277
|
-
},
|
|
1278
|
-
};
|
|
1279
|
-
}
|
|
1280
|
-
const compositeDepth = ctx.compositeRenderStack.length + 1;
|
|
1281
|
-
if (compositeDepth > MAX_COMPOSITE_RENDER_DEPTH) {
|
|
1282
|
-
const chain = ctx.compositeRenderStack
|
|
1283
|
-
.map((entry) => entry.widgetKey)
|
|
1284
|
-
.concat(activeCompositeMeta.widgetKey)
|
|
1285
|
-
.join(" -> ");
|
|
1286
|
-
return {
|
|
1287
|
-
ok: false,
|
|
1288
|
-
fatal: {
|
|
1289
|
-
code: "ZRUI_INVALID_PROPS",
|
|
1290
|
-
detail: `ZRUI_MAX_DEPTH: composite render depth ${String(compositeDepth)} exceeds max ${String(MAX_COMPOSITE_RENDER_DEPTH)}. Chain: ${chain}`,
|
|
1291
|
-
},
|
|
1292
|
-
};
|
|
1293
|
-
}
|
|
1294
|
-
registry.beginRender(instanceId);
|
|
1295
|
-
const hookCtx = createHookContext(state, invalidateInstance);
|
|
1296
|
-
const nextSelections = [];
|
|
1297
|
-
const widgetCtx = Object.freeze({
|
|
1298
|
-
id: (suffix) => scopedId(activeCompositeMeta.widgetKey, instanceId, suffix),
|
|
1299
|
-
useState: hookCtx.useState,
|
|
1300
|
-
useReducer: hookCtx.useReducer,
|
|
1301
|
-
useRef: hookCtx.useRef,
|
|
1302
|
-
useEffect: hookCtx.useEffect,
|
|
1303
|
-
useMemo: hookCtx.useMemo,
|
|
1304
|
-
useCallback: hookCtx.useCallback,
|
|
1305
|
-
useAppState: (selector) => {
|
|
1306
|
-
const selected = selector(compositeRuntime.appState);
|
|
1307
|
-
nextSelections.push({
|
|
1308
|
-
selector: selector,
|
|
1309
|
-
value: selected,
|
|
1310
|
-
});
|
|
1311
|
-
return selected;
|
|
1312
|
-
},
|
|
1313
|
-
useTheme: () => colorTokens,
|
|
1314
|
-
useViewport: () => {
|
|
1315
|
-
compositeRuntime.onUseViewport?.();
|
|
1316
|
-
return compositeRuntime.viewport ?? DEFAULT_VIEWPORT_SNAPSHOT;
|
|
1317
|
-
},
|
|
1318
|
-
invalidate: invalidateInstance,
|
|
1319
|
-
});
|
|
1320
|
-
ctx.compositeRenderStack.push({
|
|
1321
|
-
widgetKey: activeCompositeMeta.widgetKey,
|
|
1322
|
-
instanceId,
|
|
1323
|
-
});
|
|
1324
|
-
popCompositeStack = true;
|
|
1325
|
-
try {
|
|
1326
|
-
compositeChild = activeCompositeMeta.render(widgetCtx);
|
|
1327
|
-
}
|
|
1328
|
-
catch (e) {
|
|
1329
|
-
return {
|
|
1330
|
-
ok: false,
|
|
1331
|
-
fatal: {
|
|
1332
|
-
code: "ZRUI_USER_CODE_THROW",
|
|
1333
|
-
detail: describeThrown(e),
|
|
1334
|
-
},
|
|
1335
|
-
};
|
|
1336
|
-
}
|
|
1337
|
-
try {
|
|
1338
|
-
const pending = registry.endRender(instanceId);
|
|
1339
|
-
const pendingCleanups = registry.getPendingCleanups(instanceId);
|
|
1340
|
-
for (const cleanup of pendingCleanups)
|
|
1341
|
-
ctx.pendingCleanups.push(cleanup);
|
|
1342
|
-
for (const eff of pending)
|
|
1343
|
-
ctx.pendingEffects.push(eff);
|
|
1344
|
-
registry.setAppStateSelections(instanceId, nextSelections);
|
|
1345
|
-
}
|
|
1346
|
-
catch (e) {
|
|
1347
|
-
return {
|
|
1348
|
-
ok: false,
|
|
1349
|
-
fatal: {
|
|
1350
|
-
code: "ZRUI_USER_CODE_THROW",
|
|
1351
|
-
detail: describeThrown(e),
|
|
1352
|
-
},
|
|
1353
|
-
};
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
if (isContainerVNode(vnode)) {
|
|
1357
|
-
const childOverride = compositeChild ? [compositeChild] : null;
|
|
1358
|
-
if (childOverride) {
|
|
1359
|
-
ctx.containerChildOverrides.set(instanceId, childOverride);
|
|
1360
|
-
}
|
|
1361
|
-
try {
|
|
1362
|
-
return commitContainer(instanceId, vnode, prev, ctx, nodePath, depth);
|
|
1363
|
-
}
|
|
1364
|
-
finally {
|
|
1365
|
-
if (childOverride) {
|
|
1366
|
-
ctx.containerChildOverrides.delete(instanceId);
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
return {
|
|
1371
|
-
ok: true,
|
|
1372
|
-
value: {
|
|
1373
|
-
root: {
|
|
1374
|
-
instanceId,
|
|
1375
|
-
vnode,
|
|
1376
|
-
children: EMPTY_CHILDREN,
|
|
1377
|
-
dirty: true,
|
|
1378
|
-
selfDirty: true,
|
|
1379
|
-
renderPacketKey: 0,
|
|
1380
|
-
renderPacket: null,
|
|
1381
|
-
},
|
|
1382
|
-
},
|
|
1383
|
-
};
|
|
1384
|
-
}
|
|
1385
|
-
finally {
|
|
1386
|
-
if (popCompositeStack) {
|
|
1387
|
-
ctx.compositeRenderStack.pop();
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
27
|
+
export { __commitDiag } from "./commit/equality.js";
|
|
1391
28
|
function commitNode(prev, instanceId, vnode, ctx, nodePath) {
|
|
1392
29
|
ctx.layoutDepthRef.value += 1;
|
|
1393
30
|
const layoutDepth = ctx.layoutDepthRef.value;
|
|
@@ -1411,7 +48,6 @@ function commitNode(prev, instanceId, vnode, ctx, nodePath) {
|
|
|
1411
48
|
},
|
|
1412
49
|
};
|
|
1413
50
|
}
|
|
1414
|
-
// Temporary debug: trace commit matching (remove after investigation)
|
|
1415
51
|
const commitDebug = globalThis;
|
|
1416
52
|
if (commitDebug.__commitDebug) {
|
|
1417
53
|
const debugLog = commitDebug.__commitDebugLog;
|
|
@@ -1419,9 +55,6 @@ function commitNode(prev, instanceId, vnode, ctx, nodePath) {
|
|
|
1419
55
|
debugLog.push(`commitNode(${String(instanceId)}, ${vnode.kind}, prev=${prev ? `${prev.vnode.kind}:${String(prev.instanceId)}` : "null"})`);
|
|
1420
56
|
}
|
|
1421
57
|
}
|
|
1422
|
-
// Leaf nodes — fast path: reuse previous RuntimeInstance when content is unchanged.
|
|
1423
|
-
// Do this before any bookkeeping so unchanged leaf-heavy subtrees (lists, tables)
|
|
1424
|
-
// don't pay per-node validation overhead.
|
|
1425
58
|
if (prev && prev.vnode.kind === vnode.kind && leafVNodeEqual(prev.vnode, vnode)) {
|
|
1426
59
|
if (__commitDiag.enabled) {
|
|
1427
60
|
const wasDirty = prev.selfDirty;
|
|
@@ -1438,7 +71,6 @@ function commitNode(prev, instanceId, vnode, ctx, nodePath) {
|
|
|
1438
71
|
prev.selfDirty = false;
|
|
1439
72
|
return { ok: true, value: { root: prev } };
|
|
1440
73
|
}
|
|
1441
|
-
// Diagnostic: leaf not reused
|
|
1442
74
|
if (__commitDiag.enabled && prev && !isContainerVNode(vnode)) {
|
|
1443
75
|
if (prev.vnode.kind !== vnode.kind) {
|
|
1444
76
|
__commitDiag.push({
|
|
@@ -1475,7 +107,7 @@ function commitNode(prev, instanceId, vnode, ctx, nodePath) {
|
|
|
1475
107
|
const retryRequested = ctx.errorBoundary?.retryRequestedPaths.delete(nodePath) === true;
|
|
1476
108
|
const existingState = ctx.errorBoundary?.errorsByPath.get(nodePath);
|
|
1477
109
|
if (existingState && !retryRequested) {
|
|
1478
|
-
return commitErrorBoundaryFallback(prev, instanceId, nodePath, fallbackPath, props, existingState, ctx);
|
|
110
|
+
return commitErrorBoundaryFallback(prev, instanceId, nodePath, fallbackPath, props, existingState, ctx, commitNode);
|
|
1479
111
|
}
|
|
1480
112
|
const committedProtected = commitNode(prev, instanceId, protectedChild, ctx, protectedPath);
|
|
1481
113
|
if (committedProtected.ok) {
|
|
@@ -1487,7 +119,7 @@ function commitNode(prev, instanceId, vnode, ctx, nodePath) {
|
|
|
1487
119
|
}
|
|
1488
120
|
const trappedState = captureErrorBoundaryState(committedProtected.fatal.detail);
|
|
1489
121
|
ctx.errorBoundary?.errorsByPath.set(nodePath, trappedState);
|
|
1490
|
-
return commitErrorBoundaryFallback(prev, instanceId, nodePath, fallbackPath, props, trappedState, ctx);
|
|
122
|
+
return commitErrorBoundaryFallback(prev, instanceId, nodePath, fallbackPath, props, trappedState, ctx, commitNode);
|
|
1491
123
|
}
|
|
1492
124
|
const idFatal = ensureInteractiveId(ctx.seenInteractiveIds, instanceId, vnode);
|
|
1493
125
|
if (idFatal)
|
|
@@ -1507,15 +139,12 @@ function commitNode(prev, instanceId, vnode, ctx, nodePath) {
|
|
|
1507
139
|
if (ctx.composite) {
|
|
1508
140
|
const compositeMeta = getCompositeMeta(vnode);
|
|
1509
141
|
if (compositeMeta) {
|
|
1510
|
-
return executeCompositeRender(instanceId, vnode, compositeMeta, ctx, [nodePath], layoutDepth);
|
|
142
|
+
return executeCompositeRender(instanceId, vnode, compositeMeta, ctx, [nodePath], layoutDepth, (nextInstanceId, nextVnode, nextPrev, nextCtx, nextNodePath, nextDepth) => commitContainer(nextInstanceId, nextVnode, nextPrev, nextCtx, nextNodePath, nextDepth, commitNode));
|
|
1511
143
|
}
|
|
1512
144
|
}
|
|
1513
145
|
if (isContainerVNode(vnode)) {
|
|
1514
|
-
return commitContainer(instanceId, vnode, prev, ctx, [nodePath], layoutDepth);
|
|
146
|
+
return commitContainer(instanceId, vnode, prev, ctx, [nodePath], layoutDepth, commitNode);
|
|
1515
147
|
}
|
|
1516
|
-
// Leaf node: when prev exists and kind matches, mutate in-place to preserve
|
|
1517
|
-
// reference identity. This prevents parent containers from cascading new-instance
|
|
1518
|
-
// creation when only leaf content changed.
|
|
1519
148
|
if (prev !== null && prev.vnode.kind === vnode.kind) {
|
|
1520
149
|
prev.vnode = vnode;
|
|
1521
150
|
prev.selfDirty = true;
|
|
@@ -1544,14 +173,6 @@ function commitNode(prev, instanceId, vnode, ctx, nodePath) {
|
|
|
1544
173
|
ctx.layoutDepthRef.value -= 1;
|
|
1545
174
|
}
|
|
1546
175
|
}
|
|
1547
|
-
/**
|
|
1548
|
-
* Deterministically commit a VNode tree into a runtime instance tree, applying
|
|
1549
|
-
* locked reconciliation rules (docs/10) and enforcing interactive id uniqueness.
|
|
1550
|
-
*
|
|
1551
|
-
* Notes:
|
|
1552
|
-
* - Uses an implicit root parent instanceId=0 for reconciliation of the returned root VNode.
|
|
1553
|
-
* - Does not perform layout, focus, routing, or drawlist building.
|
|
1554
|
-
*/
|
|
1555
176
|
export function commitVNodeTree(prevRoot, nextRootVNode, opts) {
|
|
1556
177
|
const collectLifecycleInstanceIds = opts.collectLifecycleInstanceIds !== false;
|
|
1557
178
|
const interactiveIdIndex = opts.interactiveIdIndex ?? new Map();
|
|
@@ -1590,8 +211,6 @@ export function commitVNodeTree(prevRoot, nextRootVNode, opts) {
|
|
|
1590
211
|
};
|
|
1591
212
|
}
|
|
1592
213
|
if (prevRoot && rootPlan.prevIndex === null) {
|
|
1593
|
-
// Root was replaced; unmount the entire previous tree before committing the new one so
|
|
1594
|
-
// the returned lists include the unmount lifecycle deterministically.
|
|
1595
214
|
if (!tryScheduleExitAnimation(ctx, prevRoot, 0)) {
|
|
1596
215
|
deleteLocalStateForSubtree(opts.localState, prevRoot);
|
|
1597
216
|
collectSubtreeInstanceIds(prevRoot, ctx.lists.unmounted);
|