@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,187 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
//#region src/foundations/structures/portal.tsx
|
|
5
|
-
/**
|
|
6
|
-
* Portal / Host primitive.
|
|
7
|
-
*
|
|
8
|
-
* Foundations remain runtime-agnostic: a portal is an explicit read/write slot.
|
|
9
|
-
* Scheduling and attachment are owned by the runtime when `createPortalSlot`
|
|
10
|
-
* exists; otherwise this falls back to a local slot (deterministic, but does
|
|
11
|
-
* not schedule updates).
|
|
12
|
-
*
|
|
13
|
-
* POLICY DECISIONS (LOCKED):
|
|
14
|
-
*
|
|
15
|
-
* 1. Local Mutable State
|
|
16
|
-
* Foundations may use local mutable state ONLY to model deterministic slots,
|
|
17
|
-
* never to coordinate timing, effects, or ordering. The fallback mode uses
|
|
18
|
-
* closure-local `mounted` and `value` variables which are non-escaping and
|
|
19
|
-
* deterministic.
|
|
20
|
-
*
|
|
21
|
-
* 2. Return Type Philosophy
|
|
22
|
-
* Portal call signatures return `unknown` (intentionally opaque). The runtime
|
|
23
|
-
* owns the concrete type. This prevents foundations from assuming JSX.Element
|
|
24
|
-
* or DOM node types, maintaining runtime-agnostic portability.
|
|
25
|
-
*/
|
|
26
|
-
function createPortalSlot() {
|
|
27
|
-
let currentValue;
|
|
28
|
-
const source = (() => {
|
|
29
|
-
recordReadableRead(source);
|
|
30
|
-
return currentValue;
|
|
31
|
-
});
|
|
32
|
-
return {
|
|
33
|
-
read() {
|
|
34
|
-
return source();
|
|
35
|
-
},
|
|
36
|
-
write(value) {
|
|
37
|
-
if (Object.is(currentValue, value)) return;
|
|
38
|
-
currentValue = value;
|
|
39
|
-
markReadableDerivedSubscribersDirty(source);
|
|
40
|
-
markReactivePropsDirtySource(source);
|
|
41
|
-
notifyReadableReaders(source);
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function definePortal() {
|
|
46
|
-
if (typeof createPortalSlot === "function") {
|
|
47
|
-
const slot = createPortalSlot();
|
|
48
|
-
function PortalHost() {
|
|
49
|
-
return slot.read();
|
|
50
|
-
}
|
|
51
|
-
PortalHost.render = function PortalRender(props) {
|
|
52
|
-
slot.write(props.children);
|
|
53
|
-
return null;
|
|
54
|
-
};
|
|
55
|
-
return PortalHost;
|
|
56
|
-
}
|
|
57
|
-
let mounted = false;
|
|
58
|
-
let value;
|
|
59
|
-
function PortalHostFallback() {
|
|
60
|
-
mounted = true;
|
|
61
|
-
return value;
|
|
62
|
-
}
|
|
63
|
-
PortalHostFallback.render = function PortalRenderFallback(props) {
|
|
64
|
-
if (!mounted) return null;
|
|
65
|
-
value = props.children;
|
|
66
|
-
return null;
|
|
67
|
-
};
|
|
68
|
-
return PortalHostFallback;
|
|
69
|
-
}
|
|
70
|
-
let _defaultPortalStates = /* @__PURE__ */ new Map();
|
|
71
|
-
let _hasPendingDefaultPortalValue = false;
|
|
72
|
-
let _pendingDefaultPortalValue = void 0;
|
|
73
|
-
function disposeDefaultPortalScope(scope) {
|
|
74
|
-
if (!scope) return;
|
|
75
|
-
const state = _defaultPortalStates.get(scope);
|
|
76
|
-
if (state) state.portal.render({ children: void 0 });
|
|
77
|
-
_defaultPortalStates.delete(scope);
|
|
78
|
-
}
|
|
79
|
-
function isComponentPortalScope(scope) {
|
|
80
|
-
return Array.isArray(scope.cleanupFns);
|
|
81
|
-
}
|
|
82
|
-
function isStaleDefaultPortalScope(scope) {
|
|
83
|
-
if (!isComponentPortalScope(scope)) return false;
|
|
84
|
-
if (scope.target && scope.target.isConnected === false) return true;
|
|
85
|
-
return scope.mounted === false;
|
|
86
|
-
}
|
|
87
|
-
function pruneStaleDefaultPortalScopes() {
|
|
88
|
-
if (_defaultPortalStates.size === 0) return;
|
|
89
|
-
for (const scope of Array.from(_defaultPortalStates.keys())) if (isStaleDefaultPortalScope(scope)) disposeDefaultPortalScope(scope);
|
|
90
|
-
}
|
|
91
|
-
function getSingleDefaultPortalScope() {
|
|
92
|
-
pruneStaleDefaultPortalScopes();
|
|
93
|
-
if (_defaultPortalStates.size !== 1) return null;
|
|
94
|
-
return _defaultPortalStates.keys().next().value ?? null;
|
|
95
|
-
}
|
|
96
|
-
function getDefaultPortalState(scope) {
|
|
97
|
-
let state = _defaultPortalStates.get(scope);
|
|
98
|
-
if (!state) {
|
|
99
|
-
state = {
|
|
100
|
-
portal: definePortal(),
|
|
101
|
-
owner: null,
|
|
102
|
-
cleanupOwners: /* @__PURE__ */ new WeakSet()
|
|
103
|
-
};
|
|
104
|
-
_defaultPortalStates.set(scope, state);
|
|
105
|
-
}
|
|
106
|
-
return state;
|
|
107
|
-
}
|
|
108
|
-
function resolveDefaultPortalScope(owner) {
|
|
109
|
-
return owner?.portalScope ?? getCurrentPortalScope() ?? getSingleDefaultPortalScope();
|
|
110
|
-
}
|
|
111
|
-
function writeDefaultPortal(props, owner) {
|
|
112
|
-
const scope = resolveDefaultPortalScope(owner);
|
|
113
|
-
if (!scope) {
|
|
114
|
-
if (_defaultPortalStates.size !== 0) return;
|
|
115
|
-
_hasPendingDefaultPortalValue = true;
|
|
116
|
-
_pendingDefaultPortalValue = props.children;
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const state = getDefaultPortalState(scope);
|
|
120
|
-
_hasPendingDefaultPortalValue = false;
|
|
121
|
-
_pendingDefaultPortalValue = void 0;
|
|
122
|
-
state.portal.render(props);
|
|
123
|
-
state.owner = owner;
|
|
124
|
-
}
|
|
125
|
-
function applyPendingDefaultPortalValue(scope) {
|
|
126
|
-
if (!_hasPendingDefaultPortalValue) return;
|
|
127
|
-
const state = getDefaultPortalState(scope);
|
|
128
|
-
state.portal.render({ children: _pendingDefaultPortalValue });
|
|
129
|
-
state.owner = null;
|
|
130
|
-
_hasPendingDefaultPortalValue = false;
|
|
131
|
-
_pendingDefaultPortalValue = void 0;
|
|
132
|
-
}
|
|
133
|
-
function registerDefaultPortalOwner(owner) {
|
|
134
|
-
const scope = resolveDefaultPortalScope(owner);
|
|
135
|
-
if (!scope) return;
|
|
136
|
-
const state = getDefaultPortalState(scope);
|
|
137
|
-
if (state.cleanupOwners.has(owner)) return;
|
|
138
|
-
state.cleanupOwners.add(owner);
|
|
139
|
-
owner.cleanupFns.push(() => {
|
|
140
|
-
const currentState = _defaultPortalStates.get(scope);
|
|
141
|
-
if (!currentState) return;
|
|
142
|
-
if (currentState.owner === owner) {
|
|
143
|
-
currentState.portal.render({ children: void 0 });
|
|
144
|
-
currentState.owner = null;
|
|
145
|
-
}
|
|
146
|
-
currentState.cleanupOwners.delete(owner);
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
function clearDefaultPortalForInstance(instance) {
|
|
150
|
-
const scope = instance.portalScope;
|
|
151
|
-
if (!scope) return;
|
|
152
|
-
const state = _defaultPortalStates.get(scope);
|
|
153
|
-
if (!state) return;
|
|
154
|
-
_hasPendingDefaultPortalValue = false;
|
|
155
|
-
_pendingDefaultPortalValue = void 0;
|
|
156
|
-
state.portal.render({ children: void 0 });
|
|
157
|
-
state.owner = null;
|
|
158
|
-
}
|
|
159
|
-
const DefaultPortal = (() => {
|
|
160
|
-
function Host() {
|
|
161
|
-
const scope = resolveDefaultPortalScope(getCurrentComponentInstance());
|
|
162
|
-
if (!scope) return null;
|
|
163
|
-
applyPendingDefaultPortalValue(scope);
|
|
164
|
-
const v = getDefaultPortalState(scope).portal();
|
|
165
|
-
return v === void 0 ? null : v;
|
|
166
|
-
}
|
|
167
|
-
Host.render = function Render(props) {
|
|
168
|
-
writeDefaultPortal(props, getCurrentComponentInstance());
|
|
169
|
-
return null;
|
|
170
|
-
};
|
|
171
|
-
return Host;
|
|
172
|
-
})();
|
|
173
|
-
function Portal(props) {
|
|
174
|
-
const owner = getCurrentComponentInstance();
|
|
175
|
-
if (owner) registerDefaultPortalOwner(owner);
|
|
176
|
-
writeDefaultPortal(props, owner);
|
|
177
|
-
return null;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* NOTE:
|
|
181
|
-
* createPortalSlot is a runtime primitive.
|
|
182
|
-
* It owns scheduling, consistency, and SSR behavior.
|
|
183
|
-
*/
|
|
184
|
-
//#endregion
|
|
185
|
-
export { DefaultPortal, Portal, clearDefaultPortalForInstance, definePortal, disposeDefaultPortalScope };
|
|
186
|
-
|
|
187
|
-
//# sourceMappingURL=portal.js.map
|
|
1
|
+
import { DefaultPortal, Portal, definePortal } from "../../runtime/portal.js";
|
|
2
|
+
import "../../runtime/index.js";
|
|
3
|
+
export { DefaultPortal, Portal, definePortal };
|
package/dist/fx/fx.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { logger } from "../
|
|
1
|
+
import { logger } from "../common/logger.js";
|
|
2
2
|
import { enqueueRuntimeTask } from "../runtime/access.js";
|
|
3
3
|
import { getCurrentComponentInstance } from "../runtime/component-scope.js";
|
|
4
|
-
import "../runtime/
|
|
4
|
+
import "../runtime/index.js";
|
|
5
5
|
import { noopEventListener, noopEventListenerWithFlush } from "./noop.js";
|
|
6
6
|
//#region src/fx/fx.ts
|
|
7
7
|
function throwIfDuringRender() {
|
package/dist/fx/fx.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fx.js","names":[],"sources":["../../src/fx/fx.ts"],"sourcesContent":["import { enqueueRuntimeTask } from '../runtime/access';\nimport { getCurrentComponentInstance } from '../runtime/component';\nimport { logger } from '../dev/logger';\nimport { noopEventListener, noopEventListenerWithFlush } from './noop';\n\nexport type CancelFn = () => void;\n\n// Platform-specific timer handle types\ntype TimeoutHandle = ReturnType<typeof setTimeout> | null;\n// rAF may fall back to setTimeout in some environments/tests, include both\ntype RafHandle =\n | ReturnType<typeof requestAnimationFrame>\n | ReturnType<typeof setTimeout>\n | null;\n// requestIdleCallback may be unavailable; allow setTimeout fallback handle\ntype IdleHandle =\n | ReturnType<typeof requestIdleCallback>\n | ReturnType<typeof setTimeout>\n | null;\n\nfunction throwIfDuringRender(): void {\n const inst = getCurrentComponentInstance();\n if (inst !== null) {\n throw new Error(\n '[Askr] calling FX handler during render is not allowed. Move calls to event handlers or effects.'\n );\n }\n}\n\n/**\n * Helper: schedule a user callback through the global scheduler\n */\nfunction enqueueUserCallback(fn: () => void) {\n enqueueRuntimeTask(() => {\n try {\n fn();\n } catch (err) {\n // Keep behavior consistent with other scheduler-queued work\n logger.error('[Askr] FX handler error:', err);\n }\n });\n}\n\n// ---------- Event handlers ----------\n\nexport function debounceEvent(\n ms: number,\n handler: EventListener,\n options?: { leading?: boolean; trailing?: boolean }\n): EventListener & { cancel(): void; flush(): void } {\n const { leading = false, trailing = true } = options || {};\n\n const inst = getCurrentComponentInstance();\n // On SSR, event handlers are inert\n if (inst && inst.ssr) {\n return noopEventListenerWithFlush;\n }\n\n let timeoutId: TimeoutHandle = null;\n let lastEvent: Event | null = null;\n let lastCallTime = 0;\n\n const debounced = function (this: unknown, ev: Event) {\n // Disallow using returned handler during render\n throwIfDuringRender();\n\n const now = Date.now();\n lastEvent = ev;\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (leading && now - lastCallTime >= ms) {\n enqueueUserCallback(() => handler.call(null, ev));\n lastCallTime = now;\n }\n\n if (trailing) {\n timeoutId = setTimeout(() => {\n // Schedule through scheduler\n if (lastEvent) {\n enqueueUserCallback(() => handler.call(null, lastEvent!));\n }\n timeoutId = null;\n lastCallTime = Date.now();\n }, ms);\n }\n } as EventListener & { cancel(): void; flush(): void };\n\n debounced.cancel = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n lastEvent = null;\n };\n\n debounced.flush = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n const ev = lastEvent;\n lastEvent = null;\n timeoutId = null;\n if (ev) enqueueUserCallback(() => handler.call(null, ev));\n }\n };\n\n // Auto-cleanup on component unmount\n if (inst) {\n (inst.cleanupFns ??= []).push(() => {\n debounced.cancel();\n });\n }\n\n return debounced;\n}\n\nexport function throttleEvent(\n ms: number,\n handler: EventListener,\n options?: { leading?: boolean; trailing?: boolean }\n): EventListener & { cancel(): void } {\n const { leading = true, trailing = true } = options || {};\n\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) {\n return noopEventListener;\n }\n\n let lastCallTime = 0;\n let timeoutId: TimeoutHandle = null;\n let lastEvent: Event | null = null;\n\n const throttled = function (this: unknown, ev: Event) {\n throwIfDuringRender();\n\n const now = Date.now();\n lastEvent = ev;\n\n if (leading && now - lastCallTime >= ms) {\n enqueueUserCallback(() => handler.call(null, ev));\n lastCallTime = now;\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n } else if (!leading && lastCallTime === 0) {\n lastCallTime = now;\n }\n\n if (trailing && timeoutId === null) {\n const wait = ms - (now - lastCallTime);\n timeoutId = setTimeout(\n () => {\n if (lastEvent)\n enqueueUserCallback(() => handler.call(null, lastEvent!));\n lastCallTime = Date.now();\n timeoutId = null;\n },\n Math.max(0, wait)\n );\n }\n } as EventListener & { cancel(): void };\n\n throttled.cancel = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n lastEvent = null;\n };\n\n if (inst) {\n (inst.cleanupFns ??= []).push(() => throttled.cancel());\n }\n\n return throttled;\n}\n\nexport function rafEvent(\n handler: EventListener\n): EventListener & { cancel(): void } {\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) {\n return noopEventListener;\n }\n\n let frameId: RafHandle = null;\n let lastEvent: Event | null = null;\n\n const scheduleFrame = () => {\n const rAF =\n typeof requestAnimationFrame !== 'undefined'\n ? requestAnimationFrame\n : (cb: FrameRequestCallback) => setTimeout(() => cb(Date.now()), 16);\n\n frameId = rAF(() => {\n frameId = null;\n if (lastEvent) {\n const ev = lastEvent;\n lastEvent = null;\n enqueueUserCallback(() => handler.call(null, ev));\n }\n });\n };\n\n const fn = function (this: unknown, ev: Event) {\n throwIfDuringRender();\n lastEvent = ev;\n if (frameId === null) scheduleFrame();\n } as EventListener & { cancel(): void };\n\n fn.cancel = () => {\n if (frameId !== null) {\n // If frameId is numeric and cancelAnimationFrame is available, use it;\n // otherwise fall back to clearTimeout for the setTimeout fallback.\n if (\n typeof cancelAnimationFrame !== 'undefined' &&\n typeof frameId === 'number'\n ) {\n cancelAnimationFrame(frameId);\n } else {\n clearTimeout(frameId as ReturnType<typeof setTimeout>);\n }\n frameId = null;\n }\n lastEvent = null;\n };\n\n if (inst) (inst.cleanupFns ??= []).push(() => fn.cancel());\n\n return fn;\n}\n\n// ---------- Scheduled work ----------\n\nexport function scheduleTimeout(ms: number, fn: () => void): CancelFn {\n throwIfDuringRender();\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) {\n return () => {};\n }\n\n let id: TimeoutHandle = setTimeout(() => {\n id = null;\n enqueueUserCallback(fn);\n }, ms);\n\n const cancel = () => {\n if (id !== null) {\n clearTimeout(id);\n id = null;\n }\n };\n\n if (inst) (inst.cleanupFns ??= []).push(cancel);\n return cancel;\n}\n\nexport function scheduleIdle(\n fn: () => void,\n options?: { timeout?: number }\n): CancelFn {\n throwIfDuringRender();\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) return () => {};\n\n let id: IdleHandle = null;\n let usingRIC = false;\n\n if (typeof requestIdleCallback !== 'undefined') {\n usingRIC = true;\n id = requestIdleCallback(() => {\n id = null;\n enqueueUserCallback(fn);\n }, options);\n } else {\n // Fallback: schedule on next macrotask\n id = setTimeout(() => {\n id = null;\n enqueueUserCallback(fn);\n }, 0);\n }\n\n const cancel = () => {\n if (id !== null) {\n // If using requestIdleCallback and available, call cancelIdleCallback for numeric ids.\n if (\n usingRIC &&\n typeof cancelIdleCallback !== 'undefined' &&\n typeof id === 'number'\n ) {\n cancelIdleCallback(id);\n } else {\n clearTimeout(id as ReturnType<typeof setTimeout>);\n }\n id = null;\n }\n };\n\n if (inst) (inst.cleanupFns ??= []).push(cancel);\n return cancel;\n}\n\nexport interface RetryOptions {\n maxAttempts?: number;\n delayMs?: number;\n backoff?: (attemptIndex: number) => number;\n}\n\nexport function scheduleRetry<T>(\n fn: () => Promise<T>,\n options?: RetryOptions\n): { cancel(): void } {\n throwIfDuringRender();\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) return { cancel: () => {} };\n\n const {\n maxAttempts = 3,\n delayMs = 100,\n backoff = (i: number) => delayMs * Math.pow(2, i),\n } = options || {};\n\n let cancelled = false;\n\n const attempt = (index: number) => {\n if (cancelled) return;\n // Run user fn inside scheduler\n enqueueRuntimeTask(() => {\n if (cancelled) return;\n // Call fn (it may be async)\n const p = fn();\n p.then(\n () => {\n // Completed successfully\n },\n () => {\n if (cancelled) return;\n if (index + 1 < maxAttempts) {\n const delay = backoff(index);\n // Schedule next attempt via setTimeout so it gets enqueued through scheduleTimeout\n setTimeout(() => {\n attempt(index + 1);\n }, delay);\n }\n }\n ).catch((e) => {\n logger.error('[Askr] scheduleRetry error:', e);\n });\n });\n };\n\n // Start first attempt\n attempt(0);\n\n const cancel = () => {\n cancelled = true;\n };\n\n if (inst) (inst.cleanupFns ??= []).push(cancel);\n return { cancel };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fx.js","names":[],"sources":["../../src/fx/fx.ts"],"sourcesContent":["import { enqueueRuntimeTask } from '../runtime';\nimport { getCurrentComponentInstance } from '../runtime';\nimport { logger } from '../common/logger';\nimport { noopEventListener, noopEventListenerWithFlush } from './noop';\n\nexport type CancelFn = () => void;\n\n// Platform-specific timer handle types\ntype TimeoutHandle = ReturnType<typeof setTimeout> | null;\n// rAF may fall back to setTimeout in some environments/tests, include both\ntype RafHandle =\n | ReturnType<typeof requestAnimationFrame>\n | ReturnType<typeof setTimeout>\n | null;\n// requestIdleCallback may be unavailable; allow setTimeout fallback handle\ntype IdleHandle =\n | ReturnType<typeof requestIdleCallback>\n | ReturnType<typeof setTimeout>\n | null;\n\nfunction throwIfDuringRender(): void {\n const inst = getCurrentComponentInstance();\n if (inst !== null) {\n throw new Error(\n '[Askr] calling FX handler during render is not allowed. Move calls to event handlers or effects.'\n );\n }\n}\n\n/**\n * Helper: schedule a user callback through the global scheduler\n */\nfunction enqueueUserCallback(fn: () => void) {\n enqueueRuntimeTask(() => {\n try {\n fn();\n } catch (err) {\n // Keep behavior consistent with other scheduler-queued work\n logger.error('[Askr] FX handler error:', err);\n }\n });\n}\n\n// ---------- Event handlers ----------\n\nexport function debounceEvent(\n ms: number,\n handler: EventListener,\n options?: { leading?: boolean; trailing?: boolean }\n): EventListener & { cancel(): void; flush(): void } {\n const { leading = false, trailing = true } = options || {};\n\n const inst = getCurrentComponentInstance();\n // On SSR, event handlers are inert\n if (inst && inst.ssr) {\n return noopEventListenerWithFlush;\n }\n\n let timeoutId: TimeoutHandle = null;\n let lastEvent: Event | null = null;\n let lastCallTime = 0;\n\n const debounced = function (this: unknown, ev: Event) {\n // Disallow using returned handler during render\n throwIfDuringRender();\n\n const now = Date.now();\n lastEvent = ev;\n\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n if (leading && now - lastCallTime >= ms) {\n enqueueUserCallback(() => handler.call(null, ev));\n lastCallTime = now;\n }\n\n if (trailing) {\n timeoutId = setTimeout(() => {\n // Schedule through scheduler\n if (lastEvent) {\n enqueueUserCallback(() => handler.call(null, lastEvent!));\n }\n timeoutId = null;\n lastCallTime = Date.now();\n }, ms);\n }\n } as EventListener & { cancel(): void; flush(): void };\n\n debounced.cancel = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n lastEvent = null;\n };\n\n debounced.flush = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n const ev = lastEvent;\n lastEvent = null;\n timeoutId = null;\n if (ev) enqueueUserCallback(() => handler.call(null, ev));\n }\n };\n\n // Auto-cleanup on component unmount\n if (inst) {\n (inst.cleanupFns ??= []).push(() => {\n debounced.cancel();\n });\n }\n\n return debounced;\n}\n\nexport function throttleEvent(\n ms: number,\n handler: EventListener,\n options?: { leading?: boolean; trailing?: boolean }\n): EventListener & { cancel(): void } {\n const { leading = true, trailing = true } = options || {};\n\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) {\n return noopEventListener;\n }\n\n let lastCallTime = 0;\n let timeoutId: TimeoutHandle = null;\n let lastEvent: Event | null = null;\n\n const throttled = function (this: unknown, ev: Event) {\n throwIfDuringRender();\n\n const now = Date.now();\n lastEvent = ev;\n\n if (leading && now - lastCallTime >= ms) {\n enqueueUserCallback(() => handler.call(null, ev));\n lastCallTime = now;\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n } else if (!leading && lastCallTime === 0) {\n lastCallTime = now;\n }\n\n if (trailing && timeoutId === null) {\n const wait = ms - (now - lastCallTime);\n timeoutId = setTimeout(\n () => {\n if (lastEvent)\n enqueueUserCallback(() => handler.call(null, lastEvent!));\n lastCallTime = Date.now();\n timeoutId = null;\n },\n Math.max(0, wait)\n );\n }\n } as EventListener & { cancel(): void };\n\n throttled.cancel = () => {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n lastEvent = null;\n };\n\n if (inst) {\n (inst.cleanupFns ??= []).push(() => throttled.cancel());\n }\n\n return throttled;\n}\n\nexport function rafEvent(\n handler: EventListener\n): EventListener & { cancel(): void } {\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) {\n return noopEventListener;\n }\n\n let frameId: RafHandle = null;\n let lastEvent: Event | null = null;\n\n const scheduleFrame = () => {\n const rAF =\n typeof requestAnimationFrame !== 'undefined'\n ? requestAnimationFrame\n : (cb: FrameRequestCallback) => setTimeout(() => cb(Date.now()), 16);\n\n frameId = rAF(() => {\n frameId = null;\n if (lastEvent) {\n const ev = lastEvent;\n lastEvent = null;\n enqueueUserCallback(() => handler.call(null, ev));\n }\n });\n };\n\n const fn = function (this: unknown, ev: Event) {\n throwIfDuringRender();\n lastEvent = ev;\n if (frameId === null) scheduleFrame();\n } as EventListener & { cancel(): void };\n\n fn.cancel = () => {\n if (frameId !== null) {\n // If frameId is numeric and cancelAnimationFrame is available, use it;\n // otherwise fall back to clearTimeout for the setTimeout fallback.\n if (\n typeof cancelAnimationFrame !== 'undefined' &&\n typeof frameId === 'number'\n ) {\n cancelAnimationFrame(frameId);\n } else {\n clearTimeout(frameId as ReturnType<typeof setTimeout>);\n }\n frameId = null;\n }\n lastEvent = null;\n };\n\n if (inst) (inst.cleanupFns ??= []).push(() => fn.cancel());\n\n return fn;\n}\n\n// ---------- Scheduled work ----------\n\nexport function scheduleTimeout(ms: number, fn: () => void): CancelFn {\n throwIfDuringRender();\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) {\n return () => {};\n }\n\n let id: TimeoutHandle = setTimeout(() => {\n id = null;\n enqueueUserCallback(fn);\n }, ms);\n\n const cancel = () => {\n if (id !== null) {\n clearTimeout(id);\n id = null;\n }\n };\n\n if (inst) (inst.cleanupFns ??= []).push(cancel);\n return cancel;\n}\n\nexport function scheduleIdle(\n fn: () => void,\n options?: { timeout?: number }\n): CancelFn {\n throwIfDuringRender();\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) return () => {};\n\n let id: IdleHandle = null;\n let usingRIC = false;\n\n if (typeof requestIdleCallback !== 'undefined') {\n usingRIC = true;\n id = requestIdleCallback(() => {\n id = null;\n enqueueUserCallback(fn);\n }, options);\n } else {\n // Fallback: schedule on next macrotask\n id = setTimeout(() => {\n id = null;\n enqueueUserCallback(fn);\n }, 0);\n }\n\n const cancel = () => {\n if (id !== null) {\n // If using requestIdleCallback and available, call cancelIdleCallback for numeric ids.\n if (\n usingRIC &&\n typeof cancelIdleCallback !== 'undefined' &&\n typeof id === 'number'\n ) {\n cancelIdleCallback(id);\n } else {\n clearTimeout(id as ReturnType<typeof setTimeout>);\n }\n id = null;\n }\n };\n\n if (inst) (inst.cleanupFns ??= []).push(cancel);\n return cancel;\n}\n\nexport interface RetryOptions {\n maxAttempts?: number;\n delayMs?: number;\n backoff?: (attemptIndex: number) => number;\n}\n\nexport function scheduleRetry<T>(\n fn: () => Promise<T>,\n options?: RetryOptions\n): { cancel(): void } {\n throwIfDuringRender();\n const inst = getCurrentComponentInstance();\n if (inst && inst.ssr) return { cancel: () => {} };\n\n const {\n maxAttempts = 3,\n delayMs = 100,\n backoff = (i: number) => delayMs * Math.pow(2, i),\n } = options || {};\n\n let cancelled = false;\n\n const attempt = (index: number) => {\n if (cancelled) return;\n // Run user fn inside scheduler\n enqueueRuntimeTask(() => {\n if (cancelled) return;\n // Call fn (it may be async)\n const p = fn();\n p.then(\n () => {\n // Completed successfully\n },\n () => {\n if (cancelled) return;\n if (index + 1 < maxAttempts) {\n const delay = backoff(index);\n // Schedule next attempt via setTimeout so it gets enqueued through scheduleTimeout\n setTimeout(() => {\n attempt(index + 1);\n }, delay);\n }\n }\n ).catch((e) => {\n logger.error('[Askr] scheduleRetry error:', e);\n });\n });\n };\n\n // Start first attempt\n attempt(0);\n\n const cancel = () => {\n cancelled = true;\n };\n\n if (inst) (inst.cleanupFns ??= []).push(cancel);\n return { cancel };\n}\n"],"mappings":";;;;;;AAoBA,SAAS,sBAA4B;CAEnC,IADa,4BACT,MAAS,MACX,MAAM,IAAI,MACR,kGACF;AAEJ;;;;AAKA,SAAS,oBAAoB,IAAgB;CAC3C,yBAAyB;EACvB,IAAI;GACF,GAAG;EACL,SAAS,KAAK;GAEZ,OAAO,MAAM,4BAA4B,GAAG;EAC9C;CACF,CAAC;AACH;AAIA,SAAgB,cACd,IACA,SACA,SACmD;CACnD,MAAM,EAAE,UAAU,OAAO,WAAW,SAAS,WAAW,CAAC;CAEzD,MAAM,OAAO,4BAA4B;CAEzC,IAAI,QAAQ,KAAK,KACf,OAAO;CAGT,IAAI,YAA2B;CAC/B,IAAI,YAA0B;CAC9B,IAAI,eAAe;CAEnB,MAAM,YAAY,SAAyB,IAAW;EAEpD,oBAAoB;EAEpB,MAAM,MAAM,KAAK,IAAI;EACrB,YAAY;EAEZ,IAAI,cAAc,MAAM;GACtB,aAAa,SAAS;GACtB,YAAY;EACd;EAEA,IAAI,WAAW,MAAM,gBAAgB,IAAI;GACvC,0BAA0B,QAAQ,KAAK,MAAM,EAAE,CAAC;GAChD,eAAe;EACjB;EAEA,IAAI,UACF,YAAY,iBAAiB;GAE3B,IAAI,WACF,0BAA0B,QAAQ,KAAK,MAAM,SAAU,CAAC;GAE1D,YAAY;GACZ,eAAe,KAAK,IAAI;EAC1B,GAAG,EAAE;CAET;CAEA,UAAU,eAAe;EACvB,IAAI,cAAc,MAAM;GACtB,aAAa,SAAS;GACtB,YAAY;EACd;EACA,YAAY;CACd;CAEA,UAAU,cAAc;EACtB,IAAI,cAAc,MAAM;GACtB,aAAa,SAAS;GACtB,MAAM,KAAK;GACX,YAAY;GACZ,YAAY;GACZ,IAAI,IAAI,0BAA0B,QAAQ,KAAK,MAAM,EAAE,CAAC;EAC1D;CACF;CAGA,IAAI,MACF,CAAC,KAAK,eAAe,CAAC,EAAA,CAAG,WAAW;EAClC,UAAU,OAAO;CACnB,CAAC;CAGH,OAAO;AACT;AAEA,SAAgB,cACd,IACA,SACA,SACoC;CACpC,MAAM,EAAE,UAAU,MAAM,WAAW,SAAS,WAAW,CAAC;CAExD,MAAM,OAAO,4BAA4B;CACzC,IAAI,QAAQ,KAAK,KACf,OAAO;CAGT,IAAI,eAAe;CACnB,IAAI,YAA2B;CAC/B,IAAI,YAA0B;CAE9B,MAAM,YAAY,SAAyB,IAAW;EACpD,oBAAoB;EAEpB,MAAM,MAAM,KAAK,IAAI;EACrB,YAAY;EAEZ,IAAI,WAAW,MAAM,gBAAgB,IAAI;GACvC,0BAA0B,QAAQ,KAAK,MAAM,EAAE,CAAC;GAChD,eAAe;GACf,IAAI,cAAc,MAAM;IACtB,aAAa,SAAS;IACtB,YAAY;GACd;EACF,OAAO,IAAI,CAAC,WAAW,iBAAiB,GACtC,eAAe;EAGjB,IAAI,YAAY,cAAc,MAAM;GAClC,MAAM,OAAO,MAAM,MAAM;GACzB,YAAY,iBACJ;IACJ,IAAI,WACF,0BAA0B,QAAQ,KAAK,MAAM,SAAU,CAAC;IAC1D,eAAe,KAAK,IAAI;IACxB,YAAY;GACd,GACA,KAAK,IAAI,GAAG,IAAI,CAClB;EACF;CACF;CAEA,UAAU,eAAe;EACvB,IAAI,cAAc,MAAM;GACtB,aAAa,SAAS;GACtB,YAAY;EACd;EACA,YAAY;CACd;CAEA,IAAI,MACF,CAAC,KAAK,eAAe,CAAC,EAAA,CAAG,WAAW,UAAU,OAAO,CAAC;CAGxD,OAAO;AACT;AAEA,SAAgB,SACd,SACoC;CACpC,MAAM,OAAO,4BAA4B;CACzC,IAAI,QAAQ,KAAK,KACf,OAAO;CAGT,IAAI,UAAqB;CACzB,IAAI,YAA0B;CAE9B,MAAM,sBAAsB;EAM1B,WAJE,OAAO,0BAA0B,cAC7B,yBACC,OAA6B,iBAAiB,GAAG,KAAK,IAAI,CAAC,GAAG,EAAE,EAE7D,OAAU;GAClB,UAAU;GACV,IAAI,WAAW;IACb,MAAM,KAAK;IACX,YAAY;IACZ,0BAA0B,QAAQ,KAAK,MAAM,EAAE,CAAC;GAClD;EACF,CAAC;CACH;CAEA,MAAM,KAAK,SAAyB,IAAW;EAC7C,oBAAoB;EACpB,YAAY;EACZ,IAAI,YAAY,MAAM,cAAc;CACtC;CAEA,GAAG,eAAe;EAChB,IAAI,YAAY,MAAM;GAGpB,IACE,OAAO,yBAAyB,eAChC,OAAO,YAAY,UAEnB,qBAAqB,OAAO;QAE5B,aAAa,OAAwC;GAEvD,UAAU;EACZ;EACA,YAAY;CACd;CAEA,IAAI,MAAM,CAAC,KAAK,eAAe,CAAC,EAAA,CAAG,WAAW,GAAG,OAAO,CAAC;CAEzD,OAAO;AACT;AAIA,SAAgB,gBAAgB,IAAY,IAA0B;CACpE,oBAAoB;CACpB,MAAM,OAAO,4BAA4B;CACzC,IAAI,QAAQ,KAAK,KACf,aAAa,CAAC;CAGhB,IAAI,KAAoB,iBAAiB;EACvC,KAAK;EACL,oBAAoB,EAAE;CACxB,GAAG,EAAE;CAEL,MAAM,eAAe;EACnB,IAAI,OAAO,MAAM;GACf,aAAa,EAAE;GACf,KAAK;EACP;CACF;CAEA,IAAI,MAAM,CAAC,KAAK,eAAe,CAAC,EAAA,CAAG,KAAK,MAAM;CAC9C,OAAO;AACT;AAEA,SAAgB,aACd,IACA,SACU;CACV,oBAAoB;CACpB,MAAM,OAAO,4BAA4B;CACzC,IAAI,QAAQ,KAAK,KAAK,aAAa,CAAC;CAEpC,IAAI,KAAiB;CACrB,IAAI,WAAW;CAEf,IAAI,OAAO,wBAAwB,aAAa;EAC9C,WAAW;EACX,KAAK,0BAA0B;GAC7B,KAAK;GACL,oBAAoB,EAAE;EACxB,GAAG,OAAO;CACZ,OAEE,KAAK,iBAAiB;EACpB,KAAK;EACL,oBAAoB,EAAE;CACxB,GAAG,CAAC;CAGN,MAAM,eAAe;EACnB,IAAI,OAAO,MAAM;GAEf,IACE,YACA,OAAO,uBAAuB,eAC9B,OAAO,OAAO,UAEd,mBAAmB,EAAE;QAErB,aAAa,EAAmC;GAElD,KAAK;EACP;CACF;CAEA,IAAI,MAAM,CAAC,KAAK,eAAe,CAAC,EAAA,CAAG,KAAK,MAAM;CAC9C,OAAO;AACT;AAQA,SAAgB,cACd,IACA,SACoB;CACpB,oBAAoB;CACpB,MAAM,OAAO,4BAA4B;CACzC,IAAI,QAAQ,KAAK,KAAK,OAAO,EAAE,cAAc,CAAC,EAAE;CAEhD,MAAM,EACJ,cAAc,GACd,UAAU,KACV,WAAW,MAAc,UAAU,KAAK,IAAI,GAAG,CAAC,MAC9C,WAAW,CAAC;CAEhB,IAAI,YAAY;CAEhB,MAAM,WAAW,UAAkB;EACjC,IAAI,WAAW;EAEf,yBAAyB;GACvB,IAAI,WAAW;GAGf,AADU,GACV,CAAA,CAAE,WACM,CAEN,SACM;IACJ,IAAI,WAAW;IACf,IAAI,QAAQ,IAAI,aAAa;KAC3B,MAAM,QAAQ,QAAQ,KAAK;KAE3B,iBAAiB;MACf,QAAQ,QAAQ,CAAC;KACnB,GAAG,KAAK;IACV;GACF,CACF,CAAC,CAAC,OAAO,MAAM;IACb,OAAO,MAAM,+BAA+B,CAAC;GAC/C,CAAC;EACH,CAAC;CACH;CAGA,QAAQ,CAAC;CAET,MAAM,eAAe;EACnB,YAAY;CACd;CAEA,IAAI,MAAM,CAAC,KAAK,eAAe,CAAC,EAAA,CAAG,KAAK,MAAM;CAC9C,OAAO,EAAE,OAAO;AAClB"}
|
package/dist/fx/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { scheduleEventHandler } from "../runtime/scheduler.js";
|
|
2
|
+
import "../runtime/index.js";
|
|
2
3
|
import { debounce, defer, idle, once, raf, retry, throttle, timeout } from "./timing.js";
|
|
3
4
|
import { debounceEvent, rafEvent, scheduleIdle, scheduleRetry, scheduleTimeout, throttleEvent } from "./fx.js";
|
|
4
5
|
export { debounce, debounceEvent, defer, idle, once, raf, rafEvent, retry, scheduleEventHandler, scheduleIdle, scheduleRetry, scheduleTimeout, throttle, throttleEvent, timeout };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,11 +3,11 @@ import { Fragment } from "./common/jsx.js";
|
|
|
3
3
|
import { State, StateSetter, StateTuple, state } from "./runtime/state.js";
|
|
4
4
|
import { Context, defineContext, readContext } from "./runtime/context.js";
|
|
5
5
|
import { getSignal } from "./runtime/component-scope.js";
|
|
6
|
-
import { For, ForProps } from "./control/for.js";
|
|
7
|
-
import { Show, ShowProps } from "./control/show.js";
|
|
8
|
-
import { Case, CaseProps, Match, MatchProps } from "./control/case.js";
|
|
9
6
|
import { AskrRuntime, AskrRuntimeOptions, RuntimeKeyedReorderDecision, RuntimeRendererHost, createRuntime, getDefaultRuntime } from "./runtime/runtime.js";
|
|
10
7
|
import { Derived, derive } from "./runtime/derive.js";
|
|
11
8
|
import { Selector, selector } from "./runtime/selector.js";
|
|
9
|
+
import { For, ForProps } from "./control/for.js";
|
|
10
|
+
import { Show, ShowProps } from "./control/show.js";
|
|
11
|
+
import { Case, CaseProps, Match, MatchProps } from "./control/case.js";
|
|
12
12
|
import { jsx, jsxs } from "./jsx-runtime.js";
|
|
13
13
|
export { AskrRuntime, type AskrRuntimeOptions, Case, type CaseProps, type Context, type Derived, For, type ForProps, Fragment, Match, type MatchProps, type Props, type RuntimeKeyedReorderDecision, type RuntimeRendererHost, type Selector, Show, type ShowProps, type State, type StateSetter, type StateTuple, createRuntime, defineContext, derive, getDefaultRuntime, getSignal, jsx, jsxs, readContext, selector, state };
|
package/dist/index.js
CHANGED
|
@@ -2,12 +2,12 @@ import { AskrRuntime, createRuntime, getDefaultRuntime } from "./runtime/runtime
|
|
|
2
2
|
import { Fragment } from "./common/jsx.js";
|
|
3
3
|
import { defineContext, readContext } from "./runtime/context.js";
|
|
4
4
|
import { getSignal } from "./runtime/component-scope.js";
|
|
5
|
-
import "./runtime/component.js";
|
|
6
|
-
import { jsx, jsxs } from "./jsx-runtime.js";
|
|
7
|
-
import { installRendererBridge } from "./renderer/index.js";
|
|
8
|
-
import { state } from "./runtime/state.js";
|
|
9
5
|
import { derive } from "./runtime/derive.js";
|
|
6
|
+
import { state } from "./runtime/state.js";
|
|
10
7
|
import { selector } from "./runtime/selector.js";
|
|
8
|
+
import "./runtime/index.js";
|
|
9
|
+
import { jsx, jsxs } from "./jsx-runtime.js";
|
|
10
|
+
import { installRendererBridge } from "./renderer/index.js";
|
|
11
11
|
import { For } from "./control/for.js";
|
|
12
12
|
import { Show } from "./control/show.js";
|
|
13
13
|
import { Case, Match } from "./control/case.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Askr: Actor-backed deterministic UI framework\n *\n * Public API surface — only users should import from here\n */\n\nimport { installRendererBridge } from './renderer';\n\ninstallRendererBridge();\n\nexport { createRuntime, getDefaultRuntime } from './runtime
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Askr: Actor-backed deterministic UI framework\n *\n * Public API surface — only users should import from here\n */\n\nimport { installRendererBridge } from './renderer';\n\ninstallRendererBridge();\n\nexport { createRuntime, getDefaultRuntime } from './runtime';\nexport type {\n AskrRuntimeOptions,\n RuntimeRendererHost,\n RuntimeKeyedReorderDecision,\n} from './runtime';\nexport { AskrRuntime } from './runtime';\n\n// Runtime primitives\nexport { derive, getSignal, selector, state } from './runtime';\nexport type {\n Derived,\n Selector,\n State,\n StateSetter,\n StateTuple,\n} from './runtime';\n\n// Control flow\nexport { Case, For, Match, Show } from './control';\nexport type { CaseProps, ForProps, MatchProps, ShowProps } from './control';\n\n// Context\nexport { defineContext, readContext } from './runtime';\nexport type { Context } from './runtime';\n\n// Re-export JSX runtime for tsconfig jsxImportSource\nexport { jsx, jsxs, Fragment } from './jsx-runtime';\n\n// Public types\nexport type { Props } from './common/props';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAQA,sBAAsB"}
|
package/dist/jsx/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/jsx/types.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/jsx/types.ts"],"mappings":";;;;QAoBQ,MAAA;EAAA,UAEI,GAAA;IAAA,UAEE,OAAA,SAAgB,UAAA;MAAA,SACf,qBAAA;IAAA;IAAA,UAGD,iBAAA,SAA0B,0BAAA;MAAA,CACjC,IAAA,WACG,sBAAA,GACA,0BAAA,OAAiC,0BAAA;IAAA;IAAA,UAG7B,yBAAA;MACR,KAAA,EAAO,KAAA;IAAA;IAAA,UAGC,wBAAA;MACR,QAAA;IAAA;EAAA;AAAA"}
|
package/dist/jsx-dev-runtime.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isEagerControlPrimitive } from "./common/control.js";
|
|
2
2
|
import { ELEMENT_TYPE, Fragment, STATIC_CHILDREN } from "./common/jsx.js";
|
|
3
3
|
import { markReadableUsage } from "./runtime/readable.js";
|
|
4
|
+
import "./runtime/index.js";
|
|
4
5
|
import "./jsx/types.js";
|
|
5
6
|
//#region src/jsx/jsx-dev-runtime.ts
|
|
6
7
|
function annotatePropsUsage(props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-dev-runtime.js","names":[],"sources":["../src/jsx/jsx-dev-runtime.ts"],"sourcesContent":["/**\n * JSX dev runtime factory\n * Same element shape as production runtime, with room for dev warnings.\n */\nimport type {\n IntrinsicFallbackProps,\n KnownIntrinsicElementProps,\n Props,\n} from '../common/props';\nimport {\n isEagerControlPrimitive,\n type EagerControlPrimitive,\n} from '../common/control';\nimport {\n ELEMENT_TYPE,\n Fragment,\n STATIC_CHILDREN,\n type JSXElementType,\n type JSXElement,\n} from './types';\nimport { markReadableUsage } from '../runtime
|
|
1
|
+
{"version":3,"file":"jsx-dev-runtime.js","names":[],"sources":["../src/jsx/jsx-dev-runtime.ts"],"sourcesContent":["/**\n * JSX dev runtime factory\n * Same element shape as production runtime, with room for dev warnings.\n */\nimport type {\n IntrinsicFallbackProps,\n KnownIntrinsicElementProps,\n Props,\n} from '../common/props';\nimport {\n isEagerControlPrimitive,\n type EagerControlPrimitive,\n} from '../common/control';\nimport {\n ELEMENT_TYPE,\n Fragment,\n STATIC_CHILDREN,\n type JSXElementType,\n type JSXElement,\n} from './types';\nimport { markReadableUsage } from '../runtime';\n\nfunction annotatePropsUsage(props: Record<string, unknown> | null): Props {\n const normalizedProps = (props ?? {}) as Props;\n\n for (const value of Object.values(normalizedProps)) {\n markReadableUsage(value);\n }\n\n return normalizedProps;\n}\n\nfunction markStaticChildren(props: Props): Props {\n if (Array.isArray(props.children)) {\n Object.defineProperty(props.children, STATIC_CHILDREN, {\n value: true,\n configurable: true,\n });\n }\n\n return props;\n}\n\nexport function jsxDEV(\n type: EagerControlPrimitive,\n props: Props | null,\n key?: string | number,\n isStaticChildren?: boolean\n): unknown;\nexport function jsxDEV<TTag extends keyof KnownIntrinsicElementProps>(\n type: TTag,\n props: KnownIntrinsicElementProps[TTag] | null,\n key?: string | number,\n isStaticChildren?: boolean\n): JSXElement;\nexport function jsxDEV<TTag extends string>(\n type: Exclude<TTag, keyof KnownIntrinsicElementProps>,\n props: IntrinsicFallbackProps | null,\n key?: string | number,\n isStaticChildren?: boolean\n): JSXElement;\nexport function jsxDEV<TProps extends object>(\n type: (props: TProps) => unknown,\n props: TProps | null,\n key?: string | number,\n isStaticChildren?: boolean\n): JSXElement;\nexport function jsxDEV(\n type: symbol,\n props: Props | null,\n key?: string | number,\n isStaticChildren?: boolean\n): JSXElement;\nexport function jsxDEV(\n type: unknown,\n props: Record<string, unknown> | null,\n key?: string | number,\n isStaticChildren = false\n): JSXElement | unknown {\n const normalizedProps = annotatePropsUsage(props);\n const preparedProps = isStaticChildren\n ? markStaticChildren(normalizedProps)\n : normalizedProps;\n\n if (isEagerControlPrimitive(type)) {\n return type(preparedProps);\n }\n\n return {\n $$typeof: ELEMENT_TYPE,\n type: type as JSXElementType,\n props: preparedProps,\n key: key ?? null,\n };\n}\n\n// Re-export Fragment for JSX\nexport { Fragment };\nexport type { JSXComponent, JSXElement, JSXElementType } from './types';\n"],"mappings":";;;;;;AAsBA,SAAS,mBAAmB,OAA8C;CACxE,MAAM,kBAAmB,SAAS,CAAC;CAEnC,KAAK,MAAM,SAAS,OAAO,OAAO,eAAe,GAC/C,kBAAkB,KAAK;CAGzB,OAAO;AACT;AAEA,SAAS,mBAAmB,OAAqB;CAC/C,IAAI,MAAM,QAAQ,MAAM,QAAQ,GAC9B,OAAO,eAAe,MAAM,UAAU,iBAAiB;EACrD,OAAO;EACP,cAAc;CAChB,CAAC;CAGH,OAAO;AACT;AAgCA,SAAgB,OACd,MACA,OACA,KACA,mBAAmB,OACG;CACtB,MAAM,kBAAkB,mBAAmB,KAAK;CAChD,MAAM,gBAAgB,mBAClB,mBAAmB,eAAe,IAClC;CAEJ,IAAI,wBAAwB,IAAI,GAC9B,OAAO,KAAK,aAAa;CAG3B,OAAO;EACL,UAAU;EACJ;EACN,OAAO;EACP,KAAK,OAAO;CACd;AACF"}
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isEagerControlPrimitive } from "./common/control.js";
|
|
2
2
|
import { ELEMENT_TYPE, Fragment, STATIC_CHILDREN } from "./common/jsx.js";
|
|
3
3
|
import { markReadableUsage } from "./runtime/readable.js";
|
|
4
|
+
import "./runtime/index.js";
|
|
4
5
|
import "./jsx/types.js";
|
|
5
6
|
//#region src/jsx/jsx-runtime.ts
|
|
6
7
|
function annotatePropsUsage(props) {
|
package/dist/jsx-runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-runtime.js","names":[],"sources":["../src/jsx/jsx-runtime.ts"],"sourcesContent":["/**\n * JSX runtime factory\n * Same element shape as production runtime.\n */\n\nimport type {\n IntrinsicFallbackProps,\n KnownIntrinsicElementProps,\n Props,\n} from '../common/props';\nimport {\n isEagerControlPrimitive,\n type EagerControlPrimitive,\n} from '../common/control';\nimport {\n ELEMENT_TYPE,\n Fragment,\n STATIC_CHILDREN,\n type JSXElementType,\n type JSXElement,\n} from './types';\nimport { markReadableUsage } from '../runtime
|
|
1
|
+
{"version":3,"file":"jsx-runtime.js","names":[],"sources":["../src/jsx/jsx-runtime.ts"],"sourcesContent":["/**\n * JSX runtime factory\n * Same element shape as production runtime.\n */\n\nimport type {\n IntrinsicFallbackProps,\n KnownIntrinsicElementProps,\n Props,\n} from '../common/props';\nimport {\n isEagerControlPrimitive,\n type EagerControlPrimitive,\n} from '../common/control';\nimport {\n ELEMENT_TYPE,\n Fragment,\n STATIC_CHILDREN,\n type JSXElementType,\n type JSXElement,\n} from './types';\nimport { markReadableUsage } from '../runtime';\n\nfunction annotatePropsUsage(props: Record<string, unknown> | null): Props {\n const normalizedProps = (props ?? {}) as Props;\n\n for (const value of Object.values(normalizedProps)) {\n markReadableUsage(value);\n }\n\n return normalizedProps;\n}\n\nfunction markStaticChildren(props: Props): Props {\n if (Array.isArray(props.children)) {\n Object.defineProperty(props.children, STATIC_CHILDREN, {\n value: true,\n configurable: true,\n });\n }\n\n return props;\n}\n\nexport function jsxDEV(\n type: EagerControlPrimitive,\n props: Props | null,\n key?: string | number,\n isStaticChildren?: boolean\n): unknown;\nexport function jsxDEV<TTag extends keyof KnownIntrinsicElementProps>(\n type: TTag,\n props: KnownIntrinsicElementProps[TTag] | null,\n key?: string | number,\n isStaticChildren?: boolean\n): JSXElement;\nexport function jsxDEV<TTag extends string>(\n type: Exclude<TTag, keyof KnownIntrinsicElementProps>,\n props: IntrinsicFallbackProps | null,\n key?: string | number,\n isStaticChildren?: boolean\n): JSXElement;\nexport function jsxDEV<TProps extends object>(\n type: (props: TProps) => unknown,\n props: TProps | null,\n key?: string | number,\n isStaticChildren?: boolean\n): JSXElement;\nexport function jsxDEV(\n type: symbol,\n props: Props | null,\n key?: string | number,\n isStaticChildren?: boolean\n): JSXElement;\nexport function jsxDEV(\n type: unknown,\n props: Record<string, unknown> | null,\n key?: string | number,\n isStaticChildren = false\n): JSXElement | unknown {\n const normalizedProps = annotatePropsUsage(props);\n const preparedProps = isStaticChildren\n ? markStaticChildren(normalizedProps)\n : normalizedProps;\n\n if (isEagerControlPrimitive(type)) {\n return type(preparedProps);\n }\n\n return {\n $$typeof: ELEMENT_TYPE,\n type: type as JSXElementType,\n props: preparedProps,\n key: key ?? null,\n };\n}\n\n// Production-style helpers: alias to the DEV factory for now\nexport function jsx(\n type: EagerControlPrimitive,\n props: Props | null,\n key?: string | number\n): unknown;\nexport function jsx<TTag extends keyof KnownIntrinsicElementProps>(\n type: TTag,\n props: KnownIntrinsicElementProps[TTag] | null,\n key?: string | number\n): JSXElement;\nexport function jsx<TTag extends string>(\n type: Exclude<TTag, keyof KnownIntrinsicElementProps>,\n props: IntrinsicFallbackProps | null,\n key?: string | number\n): JSXElement;\nexport function jsx<TProps extends object>(\n type: (props: TProps) => unknown,\n props: TProps | null,\n key?: string | number\n): JSXElement;\nexport function jsx(\n type: symbol,\n props: Props | null,\n key?: string | number\n): JSXElement;\nexport function jsx(\n type: unknown,\n props: Record<string, unknown> | null,\n key?: string | number\n) {\n return jsxDEV(type as never, props, key);\n}\n\nexport function jsxs(\n type: EagerControlPrimitive,\n props: Props | null,\n key?: string | number\n): unknown;\nexport function jsxs<TTag extends keyof KnownIntrinsicElementProps>(\n type: TTag,\n props: KnownIntrinsicElementProps[TTag] | null,\n key?: string | number\n): JSXElement;\nexport function jsxs<TTag extends string>(\n type: Exclude<TTag, keyof KnownIntrinsicElementProps>,\n props: IntrinsicFallbackProps | null,\n key?: string | number\n): JSXElement;\nexport function jsxs<TProps extends object>(\n type: (props: TProps) => unknown,\n props: TProps | null,\n key?: string | number\n): JSXElement;\nexport function jsxs(\n type: symbol,\n props: Props | null,\n key?: string | number\n): JSXElement;\nexport function jsxs(\n type: unknown,\n props: Record<string, unknown> | null,\n key?: string | number\n) {\n const normalizedProps = markStaticChildren(annotatePropsUsage(props));\n\n if (isEagerControlPrimitive(type)) {\n return type(normalizedProps);\n }\n\n return {\n $$typeof: ELEMENT_TYPE,\n type: type as JSXElementType,\n props: normalizedProps,\n key: key ?? null,\n } as JSXElement;\n}\n\n// Re-export Fragment for JSX.\nexport { Fragment };\nexport type { JSXComponent, JSXElement, JSXElementType } from './types';\n"],"mappings":";;;;;;AAuBA,SAAS,mBAAmB,OAA8C;CACxE,MAAM,kBAAmB,SAAS,CAAC;CAEnC,KAAK,MAAM,SAAS,OAAO,OAAO,eAAe,GAC/C,kBAAkB,KAAK;CAGzB,OAAO;AACT;AAEA,SAAS,mBAAmB,OAAqB;CAC/C,IAAI,MAAM,QAAQ,MAAM,QAAQ,GAC9B,OAAO,eAAe,MAAM,UAAU,iBAAiB;EACrD,OAAO;EACP,cAAc;CAChB,CAAC;CAGH,OAAO;AACT;AAgCA,SAAgB,OACd,MACA,OACA,KACA,mBAAmB,OACG;CACtB,MAAM,kBAAkB,mBAAmB,KAAK;CAChD,MAAM,gBAAgB,mBAClB,mBAAmB,eAAe,IAClC;CAEJ,IAAI,wBAAwB,IAAI,GAC9B,OAAO,KAAK,aAAa;CAG3B,OAAO;EACL,UAAU;EACJ;EACN,OAAO;EACP,KAAK,OAAO;CACd;AACF;AA4BA,SAAgB,IACd,MACA,OACA,KACA;CACA,OAAO,OAAO,MAAe,OAAO,GAAG;AACzC;AA2BA,SAAgB,KACd,MACA,OACA,KACA;CACA,MAAM,kBAAkB,mBAAmB,mBAAmB,KAAK,CAAC;CAEpE,IAAI,wBAAwB,IAAI,GAC9B,OAAO,KAAK,eAAe;CAG7B,OAAO;EACL,UAAU;EACJ;EACN,OAAO;EACP,KAAK,OAAO;CACd;AACF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { incrementPerfMetric } from "../runtime/perf-metrics.js";
|
|
2
|
+
import "../runtime/index.js";
|
|
2
3
|
import { extractKey, getRenderedAttributeName, isSkippedProp, parseEventName, readElementClassName, removeRenderedAttribute, setRenderedAttribute, tagNamesEqualIgnoreCase, writeElementClassName } from "./utils.js";
|
|
3
4
|
function applyFormControlProp(el, key, value, tagName) {
|
|
4
5
|
if (key === "value") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attributes.js","names":[],"sources":["../../src/renderer/attributes.ts"],"sourcesContent":["import type { Props } from '../common/props';\nimport { incrementPerfMetric } from '../runtime/perf-metrics';\nimport {\n extractKey,\n getRenderedAttributeName,\n isSkippedProp,\n parseEventName,\n readElementClassName,\n removeRenderedAttribute,\n setRenderedAttribute,\n tagNamesEqualIgnoreCase,\n writeElementClassName,\n} from './utils';\n\ntype ClassTokenDescriptor = {\n lastClassTokens: string[] | null;\n};\n\ntype StyleEntries = Map<string, string>;\n\ntype Ref<T> =\n | ((value: T | null) => void)\n | { current: T | null }\n | null\n | undefined;\n\nexport function applyRef<T>(el: T, ref: unknown): void {\n const resolvedRef = ref as Ref<T>;\n if (!resolvedRef) return;\n if (typeof resolvedRef === 'function') {\n resolvedRef(el);\n return;\n }\n\n if (Object.isExtensible(resolvedRef)) {\n (resolvedRef as { current: T | null }).current = el;\n }\n}\n\nexport function applyFormControlProp(\n el: Element,\n key: string,\n value: unknown,\n tagName: string\n): void {\n if (key === 'value') {\n if (\n tagNamesEqualIgnoreCase(tagName, 'input') ||\n tagNamesEqualIgnoreCase(tagName, 'textarea') ||\n tagNamesEqualIgnoreCase(tagName, 'select')\n ) {\n (el as HTMLInputElement & Props).value = String(value);\n el.setAttribute('value', String(value));\n } else {\n el.setAttribute('value', String(value));\n }\n return;\n }\n\n if (key === 'checked') {\n if (tagNamesEqualIgnoreCase(tagName, 'input')) {\n const checked = Boolean(value);\n (el as HTMLInputElement & Props).checked = checked;\n if (checked) {\n el.setAttribute('checked', '');\n } else {\n el.removeAttribute('checked');\n }\n } else if (value) {\n el.setAttribute('checked', '');\n } else {\n el.removeAttribute('checked');\n }\n }\n}\n\nfunction normalizeStylePropertyName(propertyName: string): string {\n if (propertyName.startsWith('--')) {\n return propertyName;\n }\n\n return propertyName.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);\n}\n\nfunction collectCurrentStyleEntries(el: Element): StyleEntries {\n const entries: StyleEntries = new Map();\n const style = (el as HTMLElement | SVGElement).style;\n\n if (!style) {\n return entries;\n }\n\n for (let index = 0; index < style.length; index += 1) {\n const propertyName = style.item(index);\n entries.set(propertyName, style.getPropertyValue(propertyName));\n }\n\n return entries;\n}\n\nfunction normalizeStyleEntries(value: unknown): StyleEntries | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return null;\n }\n\n const entries: StyleEntries = new Map();\n for (const [key, entryValue] of Object.entries(\n value as Record<string, unknown>\n )) {\n if (\n entryValue === undefined ||\n entryValue === null ||\n entryValue === false\n ) {\n continue;\n }\n\n entries.set(normalizeStylePropertyName(key), String(entryValue));\n }\n\n return entries;\n}\n\nexport function applyStylePropValue(el: Element, value: unknown): void {\n const style = (el as HTMLElement | SVGElement).style;\n if (!style) {\n if (value === null || value === undefined || value === false) {\n el.removeAttribute('style');\n return;\n }\n\n el.setAttribute('style', String(value));\n return;\n }\n\n if (value === null || value === undefined || value === false) {\n if (!el.getAttribute('style')) {\n incrementPerfMetric('skippedDomPropWrites');\n return;\n }\n\n style.cssText = '';\n el.removeAttribute('style');\n return;\n }\n\n if (typeof value === 'string') {\n if ((el.getAttribute('style') ?? '') === value) {\n incrementPerfMetric('skippedDomPropWrites');\n return;\n }\n\n style.cssText = value;\n return;\n }\n\n const nextEntries = normalizeStyleEntries(value);\n if (!nextEntries) {\n const nextText = String(value);\n if ((el.getAttribute('style') ?? '') === nextText) {\n incrementPerfMetric('skippedDomPropWrites');\n return;\n }\n\n style.cssText = nextText;\n return;\n }\n\n const previousEntries = collectCurrentStyleEntries(el);\n let didWrite = false;\n\n for (const [propertyName] of previousEntries) {\n if (nextEntries.has(propertyName)) {\n continue;\n }\n\n style.removeProperty(propertyName);\n didWrite = true;\n }\n\n for (const [propertyName, propertyValue] of nextEntries) {\n if (previousEntries.get(propertyName) === propertyValue) {\n continue;\n }\n\n style.setProperty(propertyName, propertyValue);\n didWrite = true;\n }\n\n if (!didWrite) {\n incrementPerfMetric('skippedDomPropWrites');\n }\n}\n\nexport function applyStaticScalarPropsToElement(\n el: Element,\n props: Record<string, unknown>,\n tagName: string\n): void {\n for (const key in props) {\n if (isSkippedProp(key)) {\n continue;\n }\n\n const value = props[key];\n if (value === undefined || value === null || value === false) {\n continue;\n }\n\n if (key === 'class' || key === 'className') {\n writeElementClassName(el, String(value));\n } else if (key === 'style') {\n applyStylePropValue(el, value);\n } else if (key === 'value' || key === 'checked') {\n applyFormControlProp(el, key, value, tagName);\n } else {\n setRenderedAttribute(el, key, String(value));\n }\n }\n}\n\nfunction tokenizeClassValue(value: unknown): string[] | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n return [];\n }\n\n return trimmed.split(/\\s+/);\n}\n\nfunction patchClassList(\n el: Element,\n previousTokens: string[],\n nextTokens: string[]\n): void {\n if (previousTokens.length === nextTokens.length) {\n let identical = true;\n for (let index = 0; index < previousTokens.length; index += 1) {\n if (previousTokens[index] !== nextTokens[index]) {\n identical = false;\n break;\n }\n }\n if (identical) {\n return;\n }\n }\n\n if (previousTokens.length === 0) {\n if (nextTokens.length === 0) {\n return;\n }\n el.classList.add(...nextTokens);\n incrementPerfMetric('classListPatchOps');\n return;\n }\n\n if (nextTokens.length === 0) {\n el.classList.remove(...previousTokens);\n incrementPerfMetric('classListPatchOps');\n return;\n }\n\n if (previousTokens.length === 1 && nextTokens.length === 1) {\n el.classList.remove(previousTokens[0]);\n el.classList.add(nextTokens[0]);\n incrementPerfMetric('classListPatchOps');\n return;\n }\n\n const nextSet = new Set(nextTokens);\n const previousSet = new Set(previousTokens);\n\n for (const token of previousTokens) {\n if (!nextSet.has(token)) {\n el.classList.remove(token);\n }\n }\n\n for (const token of nextTokens) {\n if (!previousSet.has(token)) {\n el.classList.add(token);\n }\n }\n\n incrementPerfMetric('classListPatchOps');\n}\n\nexport function applyClassPropValue(\n el: Element,\n value: unknown,\n previousValue: unknown,\n descriptor?: ClassTokenDescriptor\n): void {\n const nextString = String(value);\n const nextTokens = tokenizeClassValue(nextString);\n const previousTokens =\n descriptor?.lastClassTokens ?? tokenizeClassValue(previousValue);\n\n if (nextTokens && previousTokens) {\n patchClassList(el, previousTokens, nextTokens);\n if (descriptor) {\n descriptor.lastClassTokens = nextTokens;\n }\n return;\n }\n\n writeElementClassName(el, nextString);\n if (descriptor) {\n descriptor.lastClassTokens = nextTokens;\n }\n}\n\nexport function applyScalarPropValue(\n el: Element,\n key: string,\n value: unknown,\n tagName: string,\n previousValue?: unknown,\n descriptor?: ClassTokenDescriptor\n): void {\n if (value === undefined || value === null || value === false) {\n if (key === 'class' || key === 'className') {\n const previousTokens = descriptor?.lastClassTokens;\n if (previousTokens && previousTokens.length > 0) {\n el.classList.remove(...previousTokens);\n incrementPerfMetric('classListPatchOps');\n } else {\n writeElementClassName(el, '');\n }\n if (descriptor) {\n descriptor.lastClassTokens = [];\n }\n } else if (key === 'value') {\n applyFormControlProp(el, key, '', tagName);\n } else if (key === 'checked') {\n applyFormControlProp(el, key, false, tagName);\n } else if (key === 'style') {\n applyStylePropValue(el, null);\n } else {\n removeRenderedAttribute(el, key);\n }\n return;\n }\n\n if (key === 'class' || key === 'className') {\n applyClassPropValue(el, value, previousValue, descriptor);\n } else if (key === 'style') {\n applyStylePropValue(el, value);\n } else if (key === 'value' || key === 'checked') {\n applyFormControlProp(el, key, value, tagName);\n } else {\n setRenderedAttribute(el, key, String(value));\n }\n}\n\nexport function removeStaleAttributes(\n el: Element,\n vnode: unknown,\n props: Record<string, unknown>\n): void {\n const desiredAttributes = new Set<string>();\n const key = extractKey(vnode);\n\n if (key !== undefined) {\n desiredAttributes.add('data-key');\n }\n\n for (const propName in props) {\n if (isSkippedProp(propName)) continue;\n if (parseEventName(propName)) continue;\n\n const value = props[propName];\n if (value === undefined || value === null || value === false) continue;\n\n desiredAttributes.add(getRenderedAttributeName(el, propName));\n }\n\n for (const attribute of Array.from(el.attributes)) {\n if (!desiredAttributes.has(getRenderedAttributeName(el, attribute.name))) {\n removeRenderedAttribute(el, attribute.name);\n }\n }\n}\n\nexport function materializeKey(\n el: Element,\n vnode: { key?: unknown },\n props: Record<string, unknown>\n): void {\n const rawKey = vnode.key ?? props.key;\n const vnodeKey =\n rawKey === null || rawKey === undefined\n ? undefined\n : typeof rawKey === 'symbol'\n ? String(rawKey)\n : (rawKey as string | number);\n if (vnodeKey !== undefined) {\n const nextKey = String(vnodeKey);\n if (el.getAttribute('data-key') !== nextKey) {\n el.setAttribute('data-key', nextKey);\n }\n }\n}\n\nexport function hasMatchingStaticProps(\n el: Element,\n props: Record<string, unknown>,\n vnodeType: string\n): boolean {\n let staticPropCount = 0;\n\n for (const key in props) {\n if (isSkippedProp(key)) continue;\n\n const value = props[key];\n if (value === undefined || value === null || value === false) {\n return false;\n }\n\n const eventName = parseEventName(key);\n if (eventName || typeof value === 'function') {\n return false;\n }\n\n if (key === 'class' || key === 'className') {\n if (readElementClassName(el) !== String(value)) {\n return false;\n }\n staticPropCount += 1;\n continue;\n }\n\n if (key === 'style') {\n const styleValue =\n typeof value === 'string' ? value.trim().replace(/;$/, '') : null;\n const domStyle = el.getAttribute('style')?.trim().replace(/;$/, '') ?? '';\n if (styleValue === null || domStyle !== styleValue) {\n return false;\n }\n staticPropCount += 1;\n continue;\n }\n\n if (key === 'value' || key === 'checked') {\n if ((el as HTMLElement & Record<string, unknown>)[key] !== value) {\n return false;\n }\n staticPropCount += 1;\n continue;\n }\n\n if (key === 'selected' && vnodeType === 'option') {\n if ((el as HTMLOptionElement).selected !== Boolean(value)) {\n return false;\n }\n staticPropCount += 1;\n continue;\n }\n\n if (el.getAttribute(getRenderedAttributeName(el, key)) !== String(value)) {\n return false;\n }\n\n staticPropCount += 1;\n }\n\n return el.attributes.length === staticPropCount;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"attributes.js","names":[],"sources":["../../src/renderer/attributes.ts"],"sourcesContent":["import type { Props } from '../common/props';\nimport { incrementPerfMetric } from '../runtime';\nimport {\n extractKey,\n getRenderedAttributeName,\n isSkippedProp,\n parseEventName,\n readElementClassName,\n removeRenderedAttribute,\n setRenderedAttribute,\n tagNamesEqualIgnoreCase,\n writeElementClassName,\n} from './utils';\n\ntype ClassTokenDescriptor = {\n lastClassTokens: string[] | null;\n};\n\ntype StyleEntries = Map<string, string>;\n\ntype Ref<T> =\n | ((value: T | null) => void)\n | { current: T | null }\n | null\n | undefined;\n\nexport function applyRef<T>(el: T, ref: unknown): void {\n const resolvedRef = ref as Ref<T>;\n if (!resolvedRef) return;\n if (typeof resolvedRef === 'function') {\n resolvedRef(el);\n return;\n }\n\n if (Object.isExtensible(resolvedRef)) {\n (resolvedRef as { current: T | null }).current = el;\n }\n}\n\nexport function applyFormControlProp(\n el: Element,\n key: string,\n value: unknown,\n tagName: string\n): void {\n if (key === 'value') {\n if (\n tagNamesEqualIgnoreCase(tagName, 'input') ||\n tagNamesEqualIgnoreCase(tagName, 'textarea') ||\n tagNamesEqualIgnoreCase(tagName, 'select')\n ) {\n (el as HTMLInputElement & Props).value = String(value);\n el.setAttribute('value', String(value));\n } else {\n el.setAttribute('value', String(value));\n }\n return;\n }\n\n if (key === 'checked') {\n if (tagNamesEqualIgnoreCase(tagName, 'input')) {\n const checked = Boolean(value);\n (el as HTMLInputElement & Props).checked = checked;\n if (checked) {\n el.setAttribute('checked', '');\n } else {\n el.removeAttribute('checked');\n }\n } else if (value) {\n el.setAttribute('checked', '');\n } else {\n el.removeAttribute('checked');\n }\n }\n}\n\nfunction normalizeStylePropertyName(propertyName: string): string {\n if (propertyName.startsWith('--')) {\n return propertyName;\n }\n\n return propertyName.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);\n}\n\nfunction collectCurrentStyleEntries(el: Element): StyleEntries {\n const entries: StyleEntries = new Map();\n const style = (el as HTMLElement | SVGElement).style;\n\n if (!style) {\n return entries;\n }\n\n for (let index = 0; index < style.length; index += 1) {\n const propertyName = style.item(index);\n entries.set(propertyName, style.getPropertyValue(propertyName));\n }\n\n return entries;\n}\n\nfunction normalizeStyleEntries(value: unknown): StyleEntries | null {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return null;\n }\n\n const entries: StyleEntries = new Map();\n for (const [key, entryValue] of Object.entries(\n value as Record<string, unknown>\n )) {\n if (\n entryValue === undefined ||\n entryValue === null ||\n entryValue === false\n ) {\n continue;\n }\n\n entries.set(normalizeStylePropertyName(key), String(entryValue));\n }\n\n return entries;\n}\n\nexport function applyStylePropValue(el: Element, value: unknown): void {\n const style = (el as HTMLElement | SVGElement).style;\n if (!style) {\n if (value === null || value === undefined || value === false) {\n el.removeAttribute('style');\n return;\n }\n\n el.setAttribute('style', String(value));\n return;\n }\n\n if (value === null || value === undefined || value === false) {\n if (!el.getAttribute('style')) {\n incrementPerfMetric('skippedDomPropWrites');\n return;\n }\n\n style.cssText = '';\n el.removeAttribute('style');\n return;\n }\n\n if (typeof value === 'string') {\n if ((el.getAttribute('style') ?? '') === value) {\n incrementPerfMetric('skippedDomPropWrites');\n return;\n }\n\n style.cssText = value;\n return;\n }\n\n const nextEntries = normalizeStyleEntries(value);\n if (!nextEntries) {\n const nextText = String(value);\n if ((el.getAttribute('style') ?? '') === nextText) {\n incrementPerfMetric('skippedDomPropWrites');\n return;\n }\n\n style.cssText = nextText;\n return;\n }\n\n const previousEntries = collectCurrentStyleEntries(el);\n let didWrite = false;\n\n for (const [propertyName] of previousEntries) {\n if (nextEntries.has(propertyName)) {\n continue;\n }\n\n style.removeProperty(propertyName);\n didWrite = true;\n }\n\n for (const [propertyName, propertyValue] of nextEntries) {\n if (previousEntries.get(propertyName) === propertyValue) {\n continue;\n }\n\n style.setProperty(propertyName, propertyValue);\n didWrite = true;\n }\n\n if (!didWrite) {\n incrementPerfMetric('skippedDomPropWrites');\n }\n}\n\nexport function applyStaticScalarPropsToElement(\n el: Element,\n props: Record<string, unknown>,\n tagName: string\n): void {\n for (const key in props) {\n if (isSkippedProp(key)) {\n continue;\n }\n\n const value = props[key];\n if (value === undefined || value === null || value === false) {\n continue;\n }\n\n if (key === 'class' || key === 'className') {\n writeElementClassName(el, String(value));\n } else if (key === 'style') {\n applyStylePropValue(el, value);\n } else if (key === 'value' || key === 'checked') {\n applyFormControlProp(el, key, value, tagName);\n } else {\n setRenderedAttribute(el, key, String(value));\n }\n }\n}\n\nfunction tokenizeClassValue(value: unknown): string[] | null {\n if (typeof value !== 'string') {\n return null;\n }\n\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n return [];\n }\n\n return trimmed.split(/\\s+/);\n}\n\nfunction patchClassList(\n el: Element,\n previousTokens: string[],\n nextTokens: string[]\n): void {\n if (previousTokens.length === nextTokens.length) {\n let identical = true;\n for (let index = 0; index < previousTokens.length; index += 1) {\n if (previousTokens[index] !== nextTokens[index]) {\n identical = false;\n break;\n }\n }\n if (identical) {\n return;\n }\n }\n\n if (previousTokens.length === 0) {\n if (nextTokens.length === 0) {\n return;\n }\n el.classList.add(...nextTokens);\n incrementPerfMetric('classListPatchOps');\n return;\n }\n\n if (nextTokens.length === 0) {\n el.classList.remove(...previousTokens);\n incrementPerfMetric('classListPatchOps');\n return;\n }\n\n if (previousTokens.length === 1 && nextTokens.length === 1) {\n el.classList.remove(previousTokens[0]);\n el.classList.add(nextTokens[0]);\n incrementPerfMetric('classListPatchOps');\n return;\n }\n\n const nextSet = new Set(nextTokens);\n const previousSet = new Set(previousTokens);\n\n for (const token of previousTokens) {\n if (!nextSet.has(token)) {\n el.classList.remove(token);\n }\n }\n\n for (const token of nextTokens) {\n if (!previousSet.has(token)) {\n el.classList.add(token);\n }\n }\n\n incrementPerfMetric('classListPatchOps');\n}\n\nexport function applyClassPropValue(\n el: Element,\n value: unknown,\n previousValue: unknown,\n descriptor?: ClassTokenDescriptor\n): void {\n const nextString = String(value);\n const nextTokens = tokenizeClassValue(nextString);\n const previousTokens =\n descriptor?.lastClassTokens ?? tokenizeClassValue(previousValue);\n\n if (nextTokens && previousTokens) {\n patchClassList(el, previousTokens, nextTokens);\n if (descriptor) {\n descriptor.lastClassTokens = nextTokens;\n }\n return;\n }\n\n writeElementClassName(el, nextString);\n if (descriptor) {\n descriptor.lastClassTokens = nextTokens;\n }\n}\n\nexport function applyScalarPropValue(\n el: Element,\n key: string,\n value: unknown,\n tagName: string,\n previousValue?: unknown,\n descriptor?: ClassTokenDescriptor\n): void {\n if (value === undefined || value === null || value === false) {\n if (key === 'class' || key === 'className') {\n const previousTokens = descriptor?.lastClassTokens;\n if (previousTokens && previousTokens.length > 0) {\n el.classList.remove(...previousTokens);\n incrementPerfMetric('classListPatchOps');\n } else {\n writeElementClassName(el, '');\n }\n if (descriptor) {\n descriptor.lastClassTokens = [];\n }\n } else if (key === 'value') {\n applyFormControlProp(el, key, '', tagName);\n } else if (key === 'checked') {\n applyFormControlProp(el, key, false, tagName);\n } else if (key === 'style') {\n applyStylePropValue(el, null);\n } else {\n removeRenderedAttribute(el, key);\n }\n return;\n }\n\n if (key === 'class' || key === 'className') {\n applyClassPropValue(el, value, previousValue, descriptor);\n } else if (key === 'style') {\n applyStylePropValue(el, value);\n } else if (key === 'value' || key === 'checked') {\n applyFormControlProp(el, key, value, tagName);\n } else {\n setRenderedAttribute(el, key, String(value));\n }\n}\n\nexport function removeStaleAttributes(\n el: Element,\n vnode: unknown,\n props: Record<string, unknown>\n): void {\n const desiredAttributes = new Set<string>();\n const key = extractKey(vnode);\n\n if (key !== undefined) {\n desiredAttributes.add('data-key');\n }\n\n for (const propName in props) {\n if (isSkippedProp(propName)) continue;\n if (parseEventName(propName)) continue;\n\n const value = props[propName];\n if (value === undefined || value === null || value === false) continue;\n\n desiredAttributes.add(getRenderedAttributeName(el, propName));\n }\n\n for (const attribute of Array.from(el.attributes)) {\n if (!desiredAttributes.has(getRenderedAttributeName(el, attribute.name))) {\n removeRenderedAttribute(el, attribute.name);\n }\n }\n}\n\nexport function materializeKey(\n el: Element,\n vnode: { key?: unknown },\n props: Record<string, unknown>\n): void {\n const rawKey = vnode.key ?? props.key;\n const vnodeKey =\n rawKey === null || rawKey === undefined\n ? undefined\n : typeof rawKey === 'symbol'\n ? String(rawKey)\n : (rawKey as string | number);\n if (vnodeKey !== undefined) {\n const nextKey = String(vnodeKey);\n if (el.getAttribute('data-key') !== nextKey) {\n el.setAttribute('data-key', nextKey);\n }\n }\n}\n\nexport function hasMatchingStaticProps(\n el: Element,\n props: Record<string, unknown>,\n vnodeType: string\n): boolean {\n let staticPropCount = 0;\n\n for (const key in props) {\n if (isSkippedProp(key)) continue;\n\n const value = props[key];\n if (value === undefined || value === null || value === false) {\n return false;\n }\n\n const eventName = parseEventName(key);\n if (eventName || typeof value === 'function') {\n return false;\n }\n\n if (key === 'class' || key === 'className') {\n if (readElementClassName(el) !== String(value)) {\n return false;\n }\n staticPropCount += 1;\n continue;\n }\n\n if (key === 'style') {\n const styleValue =\n typeof value === 'string' ? value.trim().replace(/;$/, '') : null;\n const domStyle = el.getAttribute('style')?.trim().replace(/;$/, '') ?? '';\n if (styleValue === null || domStyle !== styleValue) {\n return false;\n }\n staticPropCount += 1;\n continue;\n }\n\n if (key === 'value' || key === 'checked') {\n if ((el as HTMLElement & Record<string, unknown>)[key] !== value) {\n return false;\n }\n staticPropCount += 1;\n continue;\n }\n\n if (key === 'selected' && vnodeType === 'option') {\n if ((el as HTMLOptionElement).selected !== Boolean(value)) {\n return false;\n }\n staticPropCount += 1;\n continue;\n }\n\n if (el.getAttribute(getRenderedAttributeName(el, key)) !== String(value)) {\n return false;\n }\n\n staticPropCount += 1;\n }\n\n return el.attributes.length === staticPropCount;\n}\n"],"mappings":"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"}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { __FOR_BOUNDARY__, _isDOMElement } from "../common/vnode.js";
|
|
2
2
|
import "./types.js";
|
|
3
3
|
import { getRuntimeEnv } from "../common/env.js";
|
|
4
|
-
import { logger } from "../
|
|
4
|
+
import { logger } from "../common/logger.js";
|
|
5
5
|
import { enqueueRuntimeTask } from "../runtime/access.js";
|
|
6
|
+
import { clearCaseDomUpdateState, clearShowDomUpdateState, evaluateCaseState, evaluateShowState } from "../runtime/control.js";
|
|
7
|
+
import { recordBenchEvent } from "../runtime/for-bench.js";
|
|
8
|
+
import { clearForDomUpdateState, evaluateForState } from "../runtime/for-internal.js";
|
|
9
|
+
import "../runtime/index.js";
|
|
6
10
|
import { teardownNodeSubtree } from "./cleanup.js";
|
|
7
11
|
import "./env.js";
|
|
8
12
|
import { tagNamesEqualIgnoreCase } from "./utils.js";
|
|
9
13
|
import { keyedElements } from "./keyed.js";
|
|
10
|
-
import { recordBenchEvent } from "../runtime/for-bench.js";
|
|
11
|
-
import { clearForDomUpdateState, evaluateForState } from "../runtime/for-internal.js";
|
|
12
|
-
import "../runtime/for.js";
|
|
13
|
-
import { clearCaseDomUpdateState, clearShowDomUpdateState, evaluateCaseState, evaluateShowState } from "../runtime/control.js";
|
|
14
14
|
import { commitForStateBoundaryChildren } from "./for-commit.js";
|
|
15
15
|
import { getParentNamespace } from "./namespaces.js";
|
|
16
16
|
//#region src/renderer/boundaries.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundaries.js","names":[],"sources":["../../src/renderer/boundaries.ts"],"sourcesContent":["import { __FOR_BOUNDARY__ } from '../common/vnode';\nimport { logger } from '../dev/logger';\nimport { enqueueRuntimeTask } from '../runtime/access';\nimport type { ChildScope } from '../runtime/child-scope';\nimport type {\n ComponentFunction,\n ComponentInstance,\n} from '../runtime/component-contracts';\nimport {\n clearCaseDomUpdateState,\n clearShowDomUpdateState,\n evaluateCaseState,\n evaluateShowState,\n type ControlBoundaryState,\n} from '../runtime/control';\nimport {\n clearForDomUpdateState,\n evaluateForState,\n recordBenchEvent,\n} from '../runtime/for';\nimport { teardownNodeSubtree } from './cleanup';\nimport { getRuntimeEnv } from './env';\nimport { commitForStateBoundaryChildren } from './for-commit';\nimport { keyedElements } from './keyed';\nimport { getParentNamespace } from './namespaces';\nimport { _isDOMElement, type DOMElement, type VNode } from './types';\nimport { tagNamesEqualIgnoreCase } from './utils';\n\ntype ElementWithContext = DOMElement & {\n __instance?: ComponentInstance;\n};\n\ntype BoundaryCommitOwnerState = ControlBoundaryState & {\n _commitOwner?: Element | null;\n};\n\nexport interface BoundaryDOMHost {\n createDOMNode(vnode: unknown, parentNamespace?: string): Node | null;\n syncComponentElement(\n currentDom: Node | null,\n node: ElementWithContext,\n type: ComponentFunction,\n props: Record<string, unknown>,\n parentNamespace?: string,\n forceChildrenUpdate?: boolean,\n retainedHostInstances?: Iterable<ComponentInstance>\n ): Node | null;\n updateElementFromVnode(\n el: Element,\n vnode: VNode,\n updateChildren?: boolean,\n forceChildrenUpdate?: boolean\n ): void;\n tryPatchStableForDirtyItem(scope: { dom?: Node; vnode?: VNode }): boolean;\n}\n\nlet boundaryDOMHost: BoundaryDOMHost | null = null;\nconst controlBoundaryOwners = new WeakMap<Element, ControlBoundaryState>();\n\nexport function configureBoundaryDOMHost(host: BoundaryDOMHost): void {\n boundaryDOMHost = host;\n}\n\nfunction getBoundaryDOMHost(): BoundaryDOMHost {\n if (!boundaryDOMHost) {\n throw new Error('[askr] Control boundary DOM host is not configured.');\n }\n return boundaryDOMHost;\n}\n\nfunction checkVNodeShapeChanged(dom: Node, vnode: VNode): boolean {\n if (!_isDOMElement(vnode)) return true;\n if (!(dom instanceof Element)) return true;\n const vnodeType = (vnode as DOMElement).type;\n if (typeof vnodeType !== 'string') return true;\n return dom.tagName.toLowerCase() !== vnodeType.toLowerCase();\n}\n\nfunction materializeChildScopeDom(\n vnode: VNode,\n parentNamespace?: string\n): Node | null {\n if (vnode === null || vnode === undefined || vnode === false) {\n return document.createComment('');\n }\n\n const dom = getBoundaryDOMHost().createDOMNode(vnode, parentNamespace);\n if (!(dom instanceof DocumentFragment)) {\n return dom;\n }\n\n const firstChild = dom.firstChild;\n const secondChild = firstChild?.nextSibling ?? null;\n if (!firstChild) {\n return document.createComment('');\n }\n if (secondChild) {\n throw new Error('[askr] Child scopes must render a single DOM root node.');\n }\n return firstChild;\n}\n\nexport function evaluateControlBoundaryState(\n controlState: ControlBoundaryState\n): VNode[] {\n if (controlState.kind === 'for') {\n return evaluateForState(controlState);\n }\n if (controlState.kind === 'show') {\n return evaluateShowState(controlState);\n }\n return evaluateCaseState(controlState);\n}\n\nfunction clearControlBoundaryDomUpdateState(\n controlState: ControlBoundaryState\n): void {\n if (controlState.kind === 'for') {\n clearForDomUpdateState(controlState);\n return;\n }\n if (controlState.kind === 'show') {\n clearShowDomUpdateState(controlState);\n return;\n }\n clearCaseDomUpdateState(controlState);\n}\n\nexport function getControlBoundaryState(\n node: DOMElement\n): ControlBoundaryState | null {\n return (\n node._controlState ??\n (node._forState as ControlBoundaryState | undefined) ??\n null\n );\n}\n\nexport function getDirectControlBoundaryVNode(\n children: unknown\n): DOMElement | null {\n if (\n !Array.isArray(children) &&\n _isDOMElement(children) &&\n (children as DOMElement).type === __FOR_BOUNDARY__\n ) {\n return children as DOMElement;\n }\n\n if (\n Array.isArray(children) &&\n children.length === 1 &&\n _isDOMElement(children[0]) &&\n (children[0] as DOMElement).type === __FOR_BOUNDARY__\n ) {\n return children[0] as DOMElement;\n }\n\n return null;\n}\n\nfunction getControlBoundaryCommitChildren(\n controlState: ControlBoundaryState\n): VNode[] {\n if (controlState.kind === 'for' && controlState._needsSourceReconcile) {\n return evaluateForState(controlState);\n }\n\n if (controlState.kind !== 'for') {\n const activeVNode = controlState.activeScope?.vnode;\n return activeVNode == null || activeVNode === false ? [] : [activeVNode];\n }\n\n if (controlState.orderedKeys.length === 0) {\n const fallbackVNode = controlState.fallbackScope?.vnode;\n return fallbackVNode == null || fallbackVNode === false\n ? []\n : [fallbackVNode];\n }\n\n const childrenVNodes: VNode[] = [];\n for (let index = 0; index < controlState.orderedKeys.length; index += 1) {\n const itemKey = controlState.orderedKeys[index];\n const itemInstance = controlState.items.get(itemKey);\n childrenVNodes.push((itemInstance?.scope.vnode ?? null) as VNode);\n }\n\n return childrenVNodes;\n}\n\nexport function clearControlBoundaryCommitOwner(parent: Element): void {\n const owner = controlBoundaryOwners.get(parent) as\n | BoundaryCommitOwnerState\n | undefined;\n if (owner) {\n owner._enqueueBoundaryCommit = null;\n owner._hasPendingBoundaryCommit = false;\n if (owner._commitOwner === parent) {\n owner._commitOwner = null;\n }\n }\n\n controlBoundaryOwners.delete(parent);\n}\n\nexport function registerControlBoundaryCommitOwner(\n parent: Element,\n controlState: ControlBoundaryState\n): void {\n const ownerState = controlState as BoundaryCommitOwnerState;\n const previousParent = ownerState._commitOwner;\n if (\n previousParent &&\n previousParent !== parent &&\n controlBoundaryOwners.get(previousParent) === controlState\n ) {\n controlBoundaryOwners.delete(previousParent);\n }\n\n const previousOwner = controlBoundaryOwners.get(parent) as\n | BoundaryCommitOwnerState\n | undefined;\n if (previousOwner && previousOwner !== controlState) {\n previousOwner._enqueueBoundaryCommit = null;\n previousOwner._hasPendingBoundaryCommit = false;\n if (previousOwner._commitOwner === parent) {\n previousOwner._commitOwner = null;\n }\n }\n\n controlBoundaryOwners.set(parent, controlState);\n ownerState._commitOwner = parent;\n controlState._enqueueBoundaryCommit = () => {\n if (controlState._hasPendingBoundaryCommit) {\n return;\n }\n\n controlState._hasPendingBoundaryCommit = true;\n enqueueRuntimeTask(() => {\n controlState._hasPendingBoundaryCommit = false;\n\n if (controlBoundaryOwners.get(parent) !== controlState) {\n return;\n }\n\n const childrenVNodes = getControlBoundaryCommitChildren(controlState);\n commitForBoundaryChildren(parent, controlState, childrenVNodes);\n });\n };\n}\n\n/**\n * Create DOM from For/Show/Case control boundaries.\n *\n * DOM order is reconstructed from the current vnode list on every render.\n * Reusing DOM nodes never implies preserving their position; appending an\n * existing node to the fragment expresses reordering per the DOM spec.\n */\nexport function createForBoundary(\n node: DOMElement,\n props: Record<string, unknown>,\n parentNamespace?: string\n): DocumentFragment {\n void props;\n const controlState = getControlBoundaryState(node);\n\n if (!controlState) {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Control boundary missing state');\n }\n return document.createDocumentFragment();\n }\n\n const childrenVNodes = evaluateControlBoundaryState(controlState);\n const fragment = document.createDocumentFragment();\n\n if (controlState.kind !== 'for') {\n const activeScope = controlState.activeScope;\n const vnode = childrenVNodes[0];\n if (activeScope && vnode !== undefined) {\n const dom = materializeChildScopeDom(vnode, parentNamespace);\n activeScope.dom = dom ?? undefined;\n if (dom) {\n fragment.appendChild(dom);\n }\n }\n clearControlBoundaryDomUpdateState(controlState);\n return fragment;\n }\n\n const forState = controlState;\n if (forState.orderedKeys.length === 0) {\n const fallbackScope = forState.fallbackScope;\n const fallbackVNode = childrenVNodes[0];\n if (fallbackScope && fallbackVNode !== undefined) {\n const dom = materializeChildScopeDom(fallbackVNode, parentNamespace);\n fallbackScope.dom = dom ?? undefined;\n if (dom) {\n fragment.appendChild(dom);\n }\n }\n clearControlBoundaryDomUpdateState(controlState);\n return fragment;\n }\n\n for (let i = 0; i < childrenVNodes.length; i++) {\n const childVNode = childrenVNodes[i];\n const itemKey = forState.orderedKeys[i];\n const itemInstance = itemKey != null ? forState.items.get(itemKey) : null;\n\n let dom: Node | null = null;\n\n if (itemInstance && itemInstance.scope.dom) {\n const cachedDom = itemInstance.scope.dom;\n if (!checkVNodeShapeChanged(cachedDom, childVNode)) {\n dom = cachedDom;\n }\n }\n\n if (!dom) {\n dom = materializeChildScopeDom(childVNode, parentNamespace);\n if (itemInstance) {\n itemInstance.scope.dom = dom ?? undefined;\n }\n }\n\n if (dom) {\n fragment.appendChild(dom);\n }\n }\n\n clearControlBoundaryDomUpdateState(controlState);\n return fragment;\n}\n\nexport function syncControlBoundaryScopeDom(\n parent: Element,\n scope: ChildScope,\n vnode: VNode\n): Node | null {\n let dom = scope.dom ?? null;\n const parentNamespace = getParentNamespace(parent);\n const host = getBoundaryDOMHost();\n\n if (_isDOMElement(vnode) && typeof vnode.type === 'function') {\n const syncedComponentDom = host.syncComponentElement(\n dom,\n vnode as ElementWithContext,\n vnode.type as ComponentFunction,\n ((vnode as DOMElement).props ?? {}) as Record<string, unknown>,\n parentNamespace\n );\n if (syncedComponentDom) {\n scope.dom = syncedComponentDom ?? undefined;\n return syncedComponentDom;\n }\n }\n\n if (!dom) {\n dom = materializeChildScopeDom(vnode, parentNamespace);\n scope.dom = dom ?? undefined;\n return dom;\n }\n\n if (\n dom.nodeType === 3 &&\n (typeof vnode === 'string' || typeof vnode === 'number')\n ) {\n (dom as Text).data = String(vnode);\n return dom;\n }\n\n if (\n dom.nodeType === 8 &&\n (vnode === null || vnode === undefined || vnode === false)\n ) {\n return dom;\n }\n\n if (\n dom instanceof Element &&\n _isDOMElement(vnode) &&\n typeof vnode.type === 'string' &&\n tagNamesEqualIgnoreCase(dom.tagName, vnode.type)\n ) {\n host.updateElementFromVnode(dom, vnode, true);\n return dom;\n }\n\n const nextDom = materializeChildScopeDom(vnode, parentNamespace);\n if (!nextDom) {\n if (dom.parentNode === parent) {\n teardownNodeSubtree(dom);\n dom.parentNode.removeChild(dom);\n }\n scope.dom = undefined;\n return null;\n }\n\n if (dom.parentNode === parent) {\n parent.replaceChild(nextDom, dom);\n }\n\n teardownNodeSubtree(dom);\n\n scope.dom = nextDom;\n return nextDom;\n}\n\nexport function commitForBoundaryChildren(\n parent: Element,\n controlState: ControlBoundaryState,\n childrenVNodes: VNode[]\n): void {\n if (controlState.kind !== 'for') {\n const activeScope = controlState.activeScope;\n const activeVNode = childrenVNodes[0];\n const nextDom =\n activeScope && activeVNode !== undefined\n ? syncControlBoundaryScopeDom(parent, activeScope, activeVNode)\n : null;\n\n for (let i = 0; i < controlState.lastRemovedNodes.length; i++) {\n const removedNode = controlState.lastRemovedNodes[i];\n if (removedNode instanceof Element) {\n teardownNodeSubtree(removedNode);\n }\n if (removedNode.parentNode === parent) {\n recordBenchEvent('domRemove');\n parent.removeChild(removedNode);\n }\n }\n\n if (nextDom) {\n if (\n parent.childNodes.length !== 1 ||\n parent.firstChild !== nextDom ||\n controlState.lastRemovedNodes.length > 0\n ) {\n parent.replaceChildren(nextDom);\n }\n } else if (parent.firstChild) {\n parent.textContent = '';\n }\n\n keyedElements.delete(parent);\n clearControlBoundaryDomUpdateState(controlState);\n return;\n }\n\n commitForStateBoundaryChildren(parent, controlState, childrenVNodes, {\n isProduction: () => getRuntimeEnv().NODE_ENV === 'production',\n syncForItemDom: syncControlBoundaryScopeDom,\n tryPatchStableForDirtyItem: (scope) =>\n getBoundaryDOMHost().tryPatchStableForDirtyItem(scope),\n });\n}\n\nexport function trySyncControlBoundaryChild(\n parent: Element,\n currentNode: Node | null,\n next: DOMElement\n): boolean {\n if (next.type !== __FOR_BOUNDARY__) {\n return false;\n }\n\n const controlState = getControlBoundaryState(next);\n if (!controlState || controlState.kind === 'for') {\n return false;\n }\n\n const childrenVNodes = evaluateControlBoundaryState(controlState);\n const activeScope = controlState.activeScope;\n const activeVNode = childrenVNodes[0];\n const nextDom =\n activeScope && activeVNode !== undefined\n ? syncControlBoundaryScopeDom(parent, activeScope, activeVNode)\n : null;\n\n for (let i = 0; i < controlState.lastRemovedNodes.length; i++) {\n const removedNode = controlState.lastRemovedNodes[i];\n if (removedNode.parentNode !== parent) {\n continue;\n }\n\n teardownNodeSubtree(removedNode);\n if (nextDom && nextDom !== removedNode && !nextDom.parentNode) {\n parent.replaceChild(nextDom, removedNode);\n } else {\n parent.removeChild(removedNode);\n }\n }\n\n if (nextDom && !nextDom.parentNode) {\n if (currentNode?.parentNode === parent) {\n teardownNodeSubtree(currentNode);\n parent.replaceChild(nextDom, currentNode);\n } else {\n parent.appendChild(nextDom);\n }\n } else if (!nextDom && currentNode?.parentNode === parent) {\n teardownNodeSubtree(currentNode);\n parent.removeChild(currentNode);\n }\n\n clearControlBoundaryDomUpdateState(controlState);\n return true;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"boundaries.js","names":[],"sources":["../../src/renderer/boundaries.ts"],"sourcesContent":["import { __FOR_BOUNDARY__ } from '../common/vnode';\nimport { logger } from '../common/logger';\nimport { enqueueRuntimeTask } from '../runtime';\nimport type { ChildScope } from '../runtime';\nimport type { ComponentFunction, ComponentInstance } from '../runtime';\nimport {\n clearCaseDomUpdateState,\n clearShowDomUpdateState,\n evaluateCaseState,\n evaluateShowState,\n type ControlBoundaryState,\n} from '../runtime';\nimport {\n clearForDomUpdateState,\n evaluateForState,\n recordBenchEvent,\n} from '../runtime';\nimport { teardownNodeSubtree } from './cleanup';\nimport { getRuntimeEnv } from './env';\nimport { commitForStateBoundaryChildren } from './for-commit';\nimport { keyedElements } from './keyed';\nimport { getParentNamespace } from './namespaces';\nimport { _isDOMElement, type DOMElement, type VNode } from './types';\nimport { tagNamesEqualIgnoreCase } from './utils';\n\ntype ElementWithContext = DOMElement & {\n __instance?: ComponentInstance;\n};\n\ntype BoundaryCommitOwnerState = ControlBoundaryState & {\n _commitOwner?: Element | null;\n};\n\nexport interface BoundaryDOMHost {\n createDOMNode(vnode: unknown, parentNamespace?: string): Node | null;\n syncComponentElement(\n currentDom: Node | null,\n node: ElementWithContext,\n type: ComponentFunction,\n props: Record<string, unknown>,\n parentNamespace?: string,\n forceChildrenUpdate?: boolean,\n retainedHostInstances?: Iterable<ComponentInstance>\n ): Node | null;\n updateElementFromVnode(\n el: Element,\n vnode: VNode,\n updateChildren?: boolean,\n forceChildrenUpdate?: boolean\n ): void;\n tryPatchStableForDirtyItem(scope: { dom?: Node; vnode?: VNode }): boolean;\n}\n\nlet boundaryDOMHost: BoundaryDOMHost | null = null;\nconst controlBoundaryOwners = new WeakMap<Element, ControlBoundaryState>();\n\nexport function configureBoundaryDOMHost(host: BoundaryDOMHost): void {\n boundaryDOMHost = host;\n}\n\nfunction getBoundaryDOMHost(): BoundaryDOMHost {\n if (!boundaryDOMHost) {\n throw new Error('[askr] Control boundary DOM host is not configured.');\n }\n return boundaryDOMHost;\n}\n\nfunction checkVNodeShapeChanged(dom: Node, vnode: VNode): boolean {\n if (!_isDOMElement(vnode)) return true;\n if (!(dom instanceof Element)) return true;\n const vnodeType = (vnode as DOMElement).type;\n if (typeof vnodeType !== 'string') return true;\n return dom.tagName.toLowerCase() !== vnodeType.toLowerCase();\n}\n\nfunction materializeChildScopeDom(\n vnode: VNode,\n parentNamespace?: string\n): Node | null {\n if (vnode === null || vnode === undefined || vnode === false) {\n return document.createComment('');\n }\n\n const dom = getBoundaryDOMHost().createDOMNode(vnode, parentNamespace);\n if (!(dom instanceof DocumentFragment)) {\n return dom;\n }\n\n const firstChild = dom.firstChild;\n const secondChild = firstChild?.nextSibling ?? null;\n if (!firstChild) {\n return document.createComment('');\n }\n if (secondChild) {\n throw new Error('[askr] Child scopes must render a single DOM root node.');\n }\n return firstChild;\n}\n\nexport function evaluateControlBoundaryState(\n controlState: ControlBoundaryState\n): VNode[] {\n if (controlState.kind === 'for') {\n return evaluateForState(controlState);\n }\n if (controlState.kind === 'show') {\n return evaluateShowState(controlState);\n }\n return evaluateCaseState(controlState);\n}\n\nfunction clearControlBoundaryDomUpdateState(\n controlState: ControlBoundaryState\n): void {\n if (controlState.kind === 'for') {\n clearForDomUpdateState(controlState);\n return;\n }\n if (controlState.kind === 'show') {\n clearShowDomUpdateState(controlState);\n return;\n }\n clearCaseDomUpdateState(controlState);\n}\n\nexport function getControlBoundaryState(\n node: DOMElement\n): ControlBoundaryState | null {\n return (\n node._controlState ??\n (node._forState as ControlBoundaryState | undefined) ??\n null\n );\n}\n\nexport function getDirectControlBoundaryVNode(\n children: unknown\n): DOMElement | null {\n if (\n !Array.isArray(children) &&\n _isDOMElement(children) &&\n (children as DOMElement).type === __FOR_BOUNDARY__\n ) {\n return children as DOMElement;\n }\n\n if (\n Array.isArray(children) &&\n children.length === 1 &&\n _isDOMElement(children[0]) &&\n (children[0] as DOMElement).type === __FOR_BOUNDARY__\n ) {\n return children[0] as DOMElement;\n }\n\n return null;\n}\n\nfunction getControlBoundaryCommitChildren(\n controlState: ControlBoundaryState\n): VNode[] {\n if (controlState.kind === 'for' && controlState._needsSourceReconcile) {\n return evaluateForState(controlState);\n }\n\n if (controlState.kind !== 'for') {\n const activeVNode = controlState.activeScope?.vnode;\n return activeVNode == null || activeVNode === false ? [] : [activeVNode];\n }\n\n if (controlState.orderedKeys.length === 0) {\n const fallbackVNode = controlState.fallbackScope?.vnode;\n return fallbackVNode == null || fallbackVNode === false\n ? []\n : [fallbackVNode];\n }\n\n const childrenVNodes: VNode[] = [];\n for (let index = 0; index < controlState.orderedKeys.length; index += 1) {\n const itemKey = controlState.orderedKeys[index];\n const itemInstance = controlState.items.get(itemKey);\n childrenVNodes.push((itemInstance?.scope.vnode ?? null) as VNode);\n }\n\n return childrenVNodes;\n}\n\nexport function clearControlBoundaryCommitOwner(parent: Element): void {\n const owner = controlBoundaryOwners.get(parent) as\n | BoundaryCommitOwnerState\n | undefined;\n if (owner) {\n owner._enqueueBoundaryCommit = null;\n owner._hasPendingBoundaryCommit = false;\n if (owner._commitOwner === parent) {\n owner._commitOwner = null;\n }\n }\n\n controlBoundaryOwners.delete(parent);\n}\n\nexport function registerControlBoundaryCommitOwner(\n parent: Element,\n controlState: ControlBoundaryState\n): void {\n const ownerState = controlState as BoundaryCommitOwnerState;\n const previousParent = ownerState._commitOwner;\n if (\n previousParent &&\n previousParent !== parent &&\n controlBoundaryOwners.get(previousParent) === controlState\n ) {\n controlBoundaryOwners.delete(previousParent);\n }\n\n const previousOwner = controlBoundaryOwners.get(parent) as\n | BoundaryCommitOwnerState\n | undefined;\n if (previousOwner && previousOwner !== controlState) {\n previousOwner._enqueueBoundaryCommit = null;\n previousOwner._hasPendingBoundaryCommit = false;\n if (previousOwner._commitOwner === parent) {\n previousOwner._commitOwner = null;\n }\n }\n\n controlBoundaryOwners.set(parent, controlState);\n ownerState._commitOwner = parent;\n controlState._enqueueBoundaryCommit = () => {\n if (controlState._hasPendingBoundaryCommit) {\n return;\n }\n\n controlState._hasPendingBoundaryCommit = true;\n enqueueRuntimeTask(() => {\n controlState._hasPendingBoundaryCommit = false;\n\n if (controlBoundaryOwners.get(parent) !== controlState) {\n return;\n }\n\n const childrenVNodes = getControlBoundaryCommitChildren(controlState);\n commitForBoundaryChildren(parent, controlState, childrenVNodes);\n });\n };\n}\n\n/**\n * Create DOM from For/Show/Case control boundaries.\n *\n * DOM order is reconstructed from the current vnode list on every render.\n * Reusing DOM nodes never implies preserving their position; appending an\n * existing node to the fragment expresses reordering per the DOM spec.\n */\nexport function createForBoundary(\n node: DOMElement,\n props: Record<string, unknown>,\n parentNamespace?: string\n): DocumentFragment {\n void props;\n const controlState = getControlBoundaryState(node);\n\n if (!controlState) {\n if (getRuntimeEnv().NODE_ENV !== 'production') {\n logger.warn('[Askr] Control boundary missing state');\n }\n return document.createDocumentFragment();\n }\n\n const childrenVNodes = evaluateControlBoundaryState(controlState);\n const fragment = document.createDocumentFragment();\n\n if (controlState.kind !== 'for') {\n const activeScope = controlState.activeScope;\n const vnode = childrenVNodes[0];\n if (activeScope && vnode !== undefined) {\n const dom = materializeChildScopeDom(vnode, parentNamespace);\n activeScope.dom = dom ?? undefined;\n if (dom) {\n fragment.appendChild(dom);\n }\n }\n clearControlBoundaryDomUpdateState(controlState);\n return fragment;\n }\n\n const forState = controlState;\n if (forState.orderedKeys.length === 0) {\n const fallbackScope = forState.fallbackScope;\n const fallbackVNode = childrenVNodes[0];\n if (fallbackScope && fallbackVNode !== undefined) {\n const dom = materializeChildScopeDom(fallbackVNode, parentNamespace);\n fallbackScope.dom = dom ?? undefined;\n if (dom) {\n fragment.appendChild(dom);\n }\n }\n clearControlBoundaryDomUpdateState(controlState);\n return fragment;\n }\n\n for (let i = 0; i < childrenVNodes.length; i++) {\n const childVNode = childrenVNodes[i];\n const itemKey = forState.orderedKeys[i];\n const itemInstance = itemKey != null ? forState.items.get(itemKey) : null;\n\n let dom: Node | null = null;\n\n if (itemInstance && itemInstance.scope.dom) {\n const cachedDom = itemInstance.scope.dom;\n if (!checkVNodeShapeChanged(cachedDom, childVNode)) {\n dom = cachedDom;\n }\n }\n\n if (!dom) {\n dom = materializeChildScopeDom(childVNode, parentNamespace);\n if (itemInstance) {\n itemInstance.scope.dom = dom ?? undefined;\n }\n }\n\n if (dom) {\n fragment.appendChild(dom);\n }\n }\n\n clearControlBoundaryDomUpdateState(controlState);\n return fragment;\n}\n\nexport function syncControlBoundaryScopeDom(\n parent: Element,\n scope: ChildScope,\n vnode: VNode\n): Node | null {\n let dom = scope.dom ?? null;\n const parentNamespace = getParentNamespace(parent);\n const host = getBoundaryDOMHost();\n\n if (_isDOMElement(vnode) && typeof vnode.type === 'function') {\n const syncedComponentDom = host.syncComponentElement(\n dom,\n vnode as ElementWithContext,\n vnode.type as ComponentFunction,\n ((vnode as DOMElement).props ?? {}) as Record<string, unknown>,\n parentNamespace\n );\n if (syncedComponentDom) {\n scope.dom = syncedComponentDom ?? undefined;\n return syncedComponentDom;\n }\n }\n\n if (!dom) {\n dom = materializeChildScopeDom(vnode, parentNamespace);\n scope.dom = dom ?? undefined;\n return dom;\n }\n\n if (\n dom.nodeType === 3 &&\n (typeof vnode === 'string' || typeof vnode === 'number')\n ) {\n (dom as Text).data = String(vnode);\n return dom;\n }\n\n if (\n dom.nodeType === 8 &&\n (vnode === null || vnode === undefined || vnode === false)\n ) {\n return dom;\n }\n\n if (\n dom instanceof Element &&\n _isDOMElement(vnode) &&\n typeof vnode.type === 'string' &&\n tagNamesEqualIgnoreCase(dom.tagName, vnode.type)\n ) {\n host.updateElementFromVnode(dom, vnode, true);\n return dom;\n }\n\n const nextDom = materializeChildScopeDom(vnode, parentNamespace);\n if (!nextDom) {\n if (dom.parentNode === parent) {\n teardownNodeSubtree(dom);\n dom.parentNode.removeChild(dom);\n }\n scope.dom = undefined;\n return null;\n }\n\n if (dom.parentNode === parent) {\n parent.replaceChild(nextDom, dom);\n }\n\n teardownNodeSubtree(dom);\n\n scope.dom = nextDom;\n return nextDom;\n}\n\nexport function commitForBoundaryChildren(\n parent: Element,\n controlState: ControlBoundaryState,\n childrenVNodes: VNode[]\n): void {\n if (controlState.kind !== 'for') {\n const activeScope = controlState.activeScope;\n const activeVNode = childrenVNodes[0];\n const nextDom =\n activeScope && activeVNode !== undefined\n ? syncControlBoundaryScopeDom(parent, activeScope, activeVNode)\n : null;\n\n for (let i = 0; i < controlState.lastRemovedNodes.length; i++) {\n const removedNode = controlState.lastRemovedNodes[i];\n if (removedNode instanceof Element) {\n teardownNodeSubtree(removedNode);\n }\n if (removedNode.parentNode === parent) {\n recordBenchEvent('domRemove');\n parent.removeChild(removedNode);\n }\n }\n\n if (nextDom) {\n if (\n parent.childNodes.length !== 1 ||\n parent.firstChild !== nextDom ||\n controlState.lastRemovedNodes.length > 0\n ) {\n parent.replaceChildren(nextDom);\n }\n } else if (parent.firstChild) {\n parent.textContent = '';\n }\n\n keyedElements.delete(parent);\n clearControlBoundaryDomUpdateState(controlState);\n return;\n }\n\n commitForStateBoundaryChildren(parent, controlState, childrenVNodes, {\n isProduction: () => getRuntimeEnv().NODE_ENV === 'production',\n syncForItemDom: syncControlBoundaryScopeDom,\n tryPatchStableForDirtyItem: (scope) =>\n getBoundaryDOMHost().tryPatchStableForDirtyItem(scope),\n });\n}\n\nexport function trySyncControlBoundaryChild(\n parent: Element,\n currentNode: Node | null,\n next: DOMElement\n): boolean {\n if (next.type !== __FOR_BOUNDARY__) {\n return false;\n }\n\n const controlState = getControlBoundaryState(next);\n if (!controlState || controlState.kind === 'for') {\n return false;\n }\n\n const childrenVNodes = evaluateControlBoundaryState(controlState);\n const activeScope = controlState.activeScope;\n const activeVNode = childrenVNodes[0];\n const nextDom =\n activeScope && activeVNode !== undefined\n ? syncControlBoundaryScopeDom(parent, activeScope, activeVNode)\n : null;\n\n for (let i = 0; i < controlState.lastRemovedNodes.length; i++) {\n const removedNode = controlState.lastRemovedNodes[i];\n if (removedNode.parentNode !== parent) {\n continue;\n }\n\n teardownNodeSubtree(removedNode);\n if (nextDom && nextDom !== removedNode && !nextDom.parentNode) {\n parent.replaceChild(nextDom, removedNode);\n } else {\n parent.removeChild(removedNode);\n }\n }\n\n if (nextDom && !nextDom.parentNode) {\n if (currentNode?.parentNode === parent) {\n teardownNodeSubtree(currentNode);\n parent.replaceChild(nextDom, currentNode);\n } else {\n parent.appendChild(nextDom);\n }\n } else if (!nextDom && currentNode?.parentNode === parent) {\n teardownNodeSubtree(currentNode);\n parent.removeChild(currentNode);\n }\n\n clearControlBoundaryDomUpdateState(controlState);\n return true;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAqDA,IAAI,kBAA0C;AAC9C,MAAM,wCAAwB,IAAI,QAAuC;AAEzE,SAAgB,yBAAyB,MAA6B;CACpE,kBAAkB;AACpB;AAEA,SAAS,qBAAsC;CAC7C,IAAI,CAAC,iBACH,MAAM,IAAI,MAAM,qDAAqD;CAEvE,OAAO;AACT;AAEA,SAAS,uBAAuB,KAAW,OAAuB;CAChE,IAAI,CAAC,cAAc,KAAK,GAAG,OAAO;CAClC,IAAI,EAAE,eAAe,UAAU,OAAO;CACtC,MAAM,YAAa,MAAqB;CACxC,IAAI,OAAO,cAAc,UAAU,OAAO;CAC1C,OAAO,IAAI,QAAQ,YAAY,MAAM,UAAU,YAAY;AAC7D;AAEA,SAAS,yBACP,OACA,iBACa;CACb,IAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,OACrD,OAAO,SAAS,cAAc,EAAE;CAGlC,MAAM,MAAM,mBAAmB,CAAC,CAAC,cAAc,OAAO,eAAe;CACrE,IAAI,EAAE,eAAe,mBACnB,OAAO;CAGT,MAAM,aAAa,IAAI;CACvB,MAAM,cAAc,YAAY,eAAe;CAC/C,IAAI,CAAC,YACH,OAAO,SAAS,cAAc,EAAE;CAElC,IAAI,aACF,MAAM,IAAI,MAAM,yDAAyD;CAE3E,OAAO;AACT;AAEA,SAAgB,6BACd,cACS;CACT,IAAI,aAAa,SAAS,OACxB,OAAO,iBAAiB,YAAY;CAEtC,IAAI,aAAa,SAAS,QACxB,OAAO,kBAAkB,YAAY;CAEvC,OAAO,kBAAkB,YAAY;AACvC;AAEA,SAAS,mCACP,cACM;CACN,IAAI,aAAa,SAAS,OAAO;EAC/B,uBAAuB,YAAY;EACnC;CACF;CACA,IAAI,aAAa,SAAS,QAAQ;EAChC,wBAAwB,YAAY;EACpC;CACF;CACA,wBAAwB,YAAY;AACtC;AAEA,SAAgB,wBACd,MAC6B;CAC7B,OACE,KAAK,iBACJ,KAAK,aACN;AAEJ;AAEA,SAAgB,8BACd,UACmB;CACnB,IACE,CAAC,MAAM,QAAQ,QAAQ,KACvB,cAAc,QAAQ,KACrB,SAAwB,SAAS,kBAElC,OAAO;CAGT,IACE,MAAM,QAAQ,QAAQ,KACtB,SAAS,WAAW,KACpB,cAAc,SAAS,EAAE,KACxB,SAAS,EAAE,CAAgB,SAAS,kBAErC,OAAO,SAAS;CAGlB,OAAO;AACT;AAEA,SAAS,iCACP,cACS;CACT,IAAI,aAAa,SAAS,SAAS,aAAa,uBAC9C,OAAO,iBAAiB,YAAY;CAGtC,IAAI,aAAa,SAAS,OAAO;EAC/B,MAAM,cAAc,aAAa,aAAa;EAC9C,OAAO,eAAe,QAAQ,gBAAgB,QAAQ,CAAC,IAAI,CAAC,WAAW;CACzE;CAEA,IAAI,aAAa,YAAY,WAAW,GAAG;EACzC,MAAM,gBAAgB,aAAa,eAAe;EAClD,OAAO,iBAAiB,QAAQ,kBAAkB,QAC9C,CAAC,IACD,CAAC,aAAa;CACpB;CAEA,MAAM,iBAA0B,CAAC;CACjC,KAAK,IAAI,QAAQ,GAAG,QAAQ,aAAa,YAAY,QAAQ,SAAS,GAAG;EACvE,MAAM,UAAU,aAAa,YAAY;EACzC,MAAM,eAAe,aAAa,MAAM,IAAI,OAAO;EACnD,eAAe,KAAM,cAAc,MAAM,SAAS,IAAc;CAClE;CAEA,OAAO;AACT;AAEA,SAAgB,gCAAgC,QAAuB;CACrE,MAAM,QAAQ,sBAAsB,IAAI,MAAM;CAG9C,IAAI,OAAO;EACT,MAAM,yBAAyB;EAC/B,MAAM,4BAA4B;EAClC,IAAI,MAAM,iBAAiB,QACzB,MAAM,eAAe;CAEzB;CAEA,sBAAsB,OAAO,MAAM;AACrC;AAEA,SAAgB,mCACd,QACA,cACM;CACN,MAAM,aAAa;CACnB,MAAM,iBAAiB,WAAW;CAClC,IACE,kBACA,mBAAmB,UACnB,sBAAsB,IAAI,cAAc,MAAM,cAE9C,sBAAsB,OAAO,cAAc;CAG7C,MAAM,gBAAgB,sBAAsB,IAAI,MAAM;CAGtD,IAAI,iBAAiB,kBAAkB,cAAc;EACnD,cAAc,yBAAyB;EACvC,cAAc,4BAA4B;EAC1C,IAAI,cAAc,iBAAiB,QACjC,cAAc,eAAe;CAEjC;CAEA,sBAAsB,IAAI,QAAQ,YAAY;CAC9C,WAAW,eAAe;CAC1B,aAAa,+BAA+B;EAC1C,IAAI,aAAa,2BACf;EAGF,aAAa,4BAA4B;EACzC,yBAAyB;GACvB,aAAa,4BAA4B;GAEzC,IAAI,sBAAsB,IAAI,MAAM,MAAM,cACxC;GAIF,0BAA0B,QAAQ,cADX,iCAAiC,YACR,CAAc;EAChE,CAAC;CACH;AACF;;;;;;;;AASA,SAAgB,kBACd,MACA,OACA,iBACkB;CAElB,MAAM,eAAe,wBAAwB,IAAI;CAEjD,IAAI,CAAC,cAAc;EACjB,IAAI,cAAc,CAAC,CAAC,aAAa,cAC/B,OAAO,KAAK,uCAAuC;EAErD,OAAO,SAAS,uBAAuB;CACzC;CAEA,MAAM,iBAAiB,6BAA6B,YAAY;CAChE,MAAM,WAAW,SAAS,uBAAuB;CAEjD,IAAI,aAAa,SAAS,OAAO;EAC/B,MAAM,cAAc,aAAa;EACjC,MAAM,QAAQ,eAAe;EAC7B,IAAI,eAAe,UAAU,QAAW;GACtC,MAAM,MAAM,yBAAyB,OAAO,eAAe;GAC3D,YAAY,MAAM,OAAO;GACzB,IAAI,KACF,SAAS,YAAY,GAAG;EAE5B;EACA,mCAAmC,YAAY;EAC/C,OAAO;CACT;CAEA,MAAM,WAAW;CACjB,IAAI,SAAS,YAAY,WAAW,GAAG;EACrC,MAAM,gBAAgB,SAAS;EAC/B,MAAM,gBAAgB,eAAe;EACrC,IAAI,iBAAiB,kBAAkB,QAAW;GAChD,MAAM,MAAM,yBAAyB,eAAe,eAAe;GACnE,cAAc,MAAM,OAAO;GAC3B,IAAI,KACF,SAAS,YAAY,GAAG;EAE5B;EACA,mCAAmC,YAAY;EAC/C,OAAO;CACT;CAEA,KAAK,IAAI,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;EAC9C,MAAM,aAAa,eAAe;EAClC,MAAM,UAAU,SAAS,YAAY;EACrC,MAAM,eAAe,WAAW,OAAO,SAAS,MAAM,IAAI,OAAO,IAAI;EAErE,IAAI,MAAmB;EAEvB,IAAI,gBAAgB,aAAa,MAAM,KAAK;GAC1C,MAAM,YAAY,aAAa,MAAM;GACrC,IAAI,CAAC,uBAAuB,WAAW,UAAU,GAC/C,MAAM;EAEV;EAEA,IAAI,CAAC,KAAK;GACR,MAAM,yBAAyB,YAAY,eAAe;GAC1D,IAAI,cACF,aAAa,MAAM,MAAM,OAAO;EAEpC;EAEA,IAAI,KACF,SAAS,YAAY,GAAG;CAE5B;CAEA,mCAAmC,YAAY;CAC/C,OAAO;AACT;AAEA,SAAgB,4BACd,QACA,OACA,OACa;CACb,IAAI,MAAM,MAAM,OAAO;CACvB,MAAM,kBAAkB,mBAAmB,MAAM;CACjD,MAAM,OAAO,mBAAmB;CAEhC,IAAI,cAAc,KAAK,KAAK,OAAO,MAAM,SAAS,YAAY;EAC5D,MAAM,qBAAqB,KAAK,qBAC9B,KACA,OACA,MAAM,MACJ,MAAqB,SAAS,CAAC,GACjC,eACF;EACA,IAAI,oBAAoB;GACtB,MAAM,MAAM,sBAAsB;GAClC,OAAO;EACT;CACF;CAEA,IAAI,CAAC,KAAK;EACR,MAAM,yBAAyB,OAAO,eAAe;EACrD,MAAM,MAAM,OAAO;EACnB,OAAO;CACT;CAEA,IACE,IAAI,aAAa,MAChB,OAAO,UAAU,YAAY,OAAO,UAAU,WAC/C;EACA,IAAc,OAAO,OAAO,KAAK;EACjC,OAAO;CACT;CAEA,IACE,IAAI,aAAa,MAChB,UAAU,QAAQ,UAAU,UAAa,UAAU,QAEpD,OAAO;CAGT,IACE,eAAe,WACf,cAAc,KAAK,KACnB,OAAO,MAAM,SAAS,YACtB,wBAAwB,IAAI,SAAS,MAAM,IAAI,GAC/C;EACA,KAAK,uBAAuB,KAAK,OAAO,IAAI;EAC5C,OAAO;CACT;CAEA,MAAM,UAAU,yBAAyB,OAAO,eAAe;CAC/D,IAAI,CAAC,SAAS;EACZ,IAAI,IAAI,eAAe,QAAQ;GAC7B,oBAAoB,GAAG;GACvB,IAAI,WAAW,YAAY,GAAG;EAChC;EACA,MAAM,MAAM;EACZ,OAAO;CACT;CAEA,IAAI,IAAI,eAAe,QACrB,OAAO,aAAa,SAAS,GAAG;CAGlC,oBAAoB,GAAG;CAEvB,MAAM,MAAM;CACZ,OAAO;AACT;AAEA,SAAgB,0BACd,QACA,cACA,gBACM;CACN,IAAI,aAAa,SAAS,OAAO;EAC/B,MAAM,cAAc,aAAa;EACjC,MAAM,cAAc,eAAe;EACnC,MAAM,UACJ,eAAe,gBAAgB,SAC3B,4BAA4B,QAAQ,aAAa,WAAW,IAC5D;EAEN,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,iBAAiB,QAAQ,KAAK;GAC7D,MAAM,cAAc,aAAa,iBAAiB;GAClD,IAAI,uBAAuB,SACzB,oBAAoB,WAAW;GAEjC,IAAI,YAAY,eAAe,QAAQ;IACrC,iBAAiB,WAAW;IAC5B,OAAO,YAAY,WAAW;GAChC;EACF;EAEA,IAAI,SACF;OACE,OAAO,WAAW,WAAW,KAC7B,OAAO,eAAe,WACtB,aAAa,iBAAiB,SAAS,GAEvC,OAAO,gBAAgB,OAAO;EAChC,OACK,IAAI,OAAO,YAChB,OAAO,cAAc;EAGvB,cAAc,OAAO,MAAM;EAC3B,mCAAmC,YAAY;EAC/C;CACF;CAEA,+BAA+B,QAAQ,cAAc,gBAAgB;EACnE,oBAAoB,cAAc,CAAC,CAAC,aAAa;EACjD,gBAAgB;EAChB,6BAA6B,UAC3B,mBAAmB,CAAC,CAAC,2BAA2B,KAAK;CACzD,CAAC;AACH;AAEA,SAAgB,4BACd,QACA,aACA,MACS;CACT,IAAI,KAAK,SAAS,kBAChB,OAAO;CAGT,MAAM,eAAe,wBAAwB,IAAI;CACjD,IAAI,CAAC,gBAAgB,aAAa,SAAS,OACzC,OAAO;CAGT,MAAM,iBAAiB,6BAA6B,YAAY;CAChE,MAAM,cAAc,aAAa;CACjC,MAAM,cAAc,eAAe;CACnC,MAAM,UACJ,eAAe,gBAAgB,SAC3B,4BAA4B,QAAQ,aAAa,WAAW,IAC5D;CAEN,KAAK,IAAI,IAAI,GAAG,IAAI,aAAa,iBAAiB,QAAQ,KAAK;EAC7D,MAAM,cAAc,aAAa,iBAAiB;EAClD,IAAI,YAAY,eAAe,QAC7B;EAGF,oBAAoB,WAAW;EAC/B,IAAI,WAAW,YAAY,eAAe,CAAC,QAAQ,YACjD,OAAO,aAAa,SAAS,WAAW;OAExC,OAAO,YAAY,WAAW;CAElC;CAEA,IAAI,WAAW,CAAC,QAAQ,YACtB,IAAI,aAAa,eAAe,QAAQ;EACtC,oBAAoB,WAAW;EAC/B,OAAO,aAAa,SAAS,WAAW;CAC1C,OACE,OAAO,YAAY,OAAO;MAEvB,IAAI,CAAC,WAAW,aAAa,eAAe,QAAQ;EACzD,oBAAoB,WAAW;EAC/B,OAAO,YAAY,WAAW;CAChC;CAEA,mCAAmC,YAAY;CAC/C,OAAO;AACT"}
|