kiru 0.54.4 → 1.0.1
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/{appContext.d.ts → appHandle.d.ts} +4 -4
- package/dist/appHandle.d.ts.map +1 -0
- package/dist/{appContext.js → appHandle.js} +12 -9
- package/dist/appHandle.js.map +1 -0
- package/dist/components/derive.d.ts +10 -8
- package/dist/components/derive.d.ts.map +1 -1
- package/dist/components/derive.js +50 -47
- package/dist/components/derive.js.map +1 -1
- package/dist/components/index.d.ts +0 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +0 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/lazy.d.ts.map +1 -1
- package/dist/components/lazy.js +5 -4
- package/dist/components/lazy.js.map +1 -1
- package/dist/components/portal.d.ts.map +1 -1
- package/dist/components/portal.js +2 -3
- package/dist/components/portal.js.map +1 -1
- package/dist/components/transition.d.ts +3 -2
- package/dist/components/transition.d.ts.map +1 -1
- package/dist/components/transition.js +29 -26
- package/dist/components/transition.js.map +1 -1
- package/dist/constants.d.ts +1 -5
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -5
- package/dist/constants.js.map +1 -1
- package/dist/context.d.ts +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +25 -19
- package/dist/context.js.map +1 -1
- package/dist/devtools.d.ts +7 -0
- package/dist/devtools.d.ts.map +1 -0
- package/dist/devtools.js +15 -0
- package/dist/devtools.js.map +1 -0
- package/dist/dom.d.ts.map +1 -1
- package/dist/dom.js +25 -58
- package/dist/dom.js.map +1 -1
- package/dist/globalContext.d.ts +15 -16
- package/dist/globalContext.d.ts.map +1 -1
- package/dist/globalContext.js +36 -46
- package/dist/globalContext.js.map +1 -1
- package/dist/globals.d.ts +1 -4
- package/dist/globals.d.ts.map +1 -1
- package/dist/globals.js +1 -4
- package/dist/globals.js.map +1 -1
- package/dist/headlessRender.d.ts +6 -0
- package/dist/headlessRender.d.ts.map +1 -0
- package/dist/{recursiveRender.js → headlessRender.js} +17 -16
- package/dist/headlessRender.js.map +1 -0
- package/dist/hmr.d.ts +5 -7
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +27 -32
- package/dist/hmr.js.map +1 -1
- package/dist/hooks/index.d.ts +3 -14
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +3 -14
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/onBeforeMount.d.ts +9 -0
- package/dist/hooks/onBeforeMount.d.ts.map +1 -0
- package/dist/hooks/onBeforeMount.js +12 -0
- package/dist/hooks/onBeforeMount.js.map +1 -0
- package/dist/hooks/onCleanup.d.ts +8 -0
- package/dist/hooks/onCleanup.d.ts.map +1 -0
- package/dist/hooks/onCleanup.js +15 -0
- package/dist/hooks/onCleanup.js.map +1 -0
- package/dist/hooks/onMount.d.ts +9 -0
- package/dist/hooks/onMount.d.ts.map +1 -0
- package/dist/hooks/onMount.js +12 -0
- package/dist/hooks/onMount.js.map +1 -0
- package/dist/hooks/utils.d.ts +2 -62
- package/dist/hooks/utils.d.ts.map +1 -1
- package/dist/hooks/utils.js +22 -144
- package/dist/hooks/utils.js.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/dist/profiling.d.ts +15 -14
- package/dist/profiling.d.ts.map +1 -1
- package/dist/profiling.js +9 -4
- package/dist/profiling.js.map +1 -1
- package/dist/reconciler.d.ts.map +1 -1
- package/dist/reconciler.js +12 -25
- package/dist/reconciler.js.map +1 -1
- package/dist/ref.d.ts +4 -0
- package/dist/ref.d.ts.map +1 -0
- package/dist/ref.js +4 -0
- package/dist/ref.js.map +1 -0
- package/dist/renderToString.js +1 -1
- package/dist/renderToString.js.map +1 -1
- package/dist/router/context.d.ts.map +1 -1
- package/dist/router/context.js +1 -2
- package/dist/router/context.js.map +1 -1
- package/dist/router/fileRouter.d.ts +1 -1
- package/dist/router/fileRouter.d.ts.map +1 -1
- package/dist/router/fileRouter.js +17 -11
- package/dist/router/fileRouter.js.map +1 -1
- package/dist/router/fileRouterController.d.ts.map +1 -1
- package/dist/router/fileRouterController.js +68 -55
- package/dist/router/fileRouterController.js.map +1 -1
- package/dist/router/link.d.ts.map +1 -1
- package/dist/router/link.js +19 -23
- package/dist/router/link.js.map +1 -1
- package/dist/router/server/index.d.ts.map +1 -1
- package/dist/router/server/index.js +14 -11
- package/dist/router/server/index.js.map +1 -1
- package/dist/router/types.d.ts +11 -6
- package/dist/router/types.d.ts.map +1 -1
- package/dist/scheduler.d.ts +1 -0
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +65 -52
- package/dist/scheduler.js.map +1 -1
- package/dist/signals/base.d.ts +0 -1
- package/dist/signals/base.d.ts.map +1 -1
- package/dist/signals/base.js +13 -36
- package/dist/signals/base.js.map +1 -1
- package/dist/signals/computed.d.ts +0 -2
- package/dist/signals/computed.d.ts.map +1 -1
- package/dist/signals/computed.js +1 -40
- package/dist/signals/computed.js.map +1 -1
- package/dist/signals/effect.d.ts +15 -14
- package/dist/signals/effect.d.ts.map +1 -1
- package/dist/signals/effect.js +65 -37
- package/dist/signals/effect.js.map +1 -1
- package/dist/signals/globals.d.ts +0 -5
- package/dist/signals/globals.d.ts.map +1 -1
- package/dist/signals/globals.js +0 -6
- package/dist/signals/globals.js.map +1 -1
- package/dist/signals/index.d.ts +4 -4
- package/dist/signals/index.d.ts.map +1 -1
- package/dist/signals/index.js +4 -4
- package/dist/signals/index.js.map +1 -1
- package/dist/signals/{for.d.ts → jsx.d.ts} +8 -1
- package/dist/signals/jsx.d.ts.map +1 -0
- package/dist/signals/{for.js → jsx.js} +4 -1
- package/dist/signals/jsx.js.map +1 -0
- package/dist/signals/tracking.d.ts +23 -0
- package/dist/signals/tracking.d.ts.map +1 -0
- package/dist/signals/tracking.js +51 -0
- package/dist/signals/tracking.js.map +1 -0
- package/dist/signals/types.d.ts +1 -1
- package/dist/signals/types.d.ts.map +1 -1
- package/dist/signals/utils.d.ts +2 -1
- package/dist/signals/utils.d.ts.map +1 -1
- package/dist/signals/utils.js +9 -2
- package/dist/signals/utils.js.map +1 -1
- package/dist/ssr/client.d.ts +3 -3
- package/dist/ssr/client.d.ts.map +1 -1
- package/dist/ssr/client.js.map +1 -1
- package/dist/ssr/server.js +1 -1
- package/dist/ssr/server.js.map +1 -1
- package/dist/statefulPromise.d.ts +22 -0
- package/dist/statefulPromise.d.ts.map +1 -0
- package/dist/statefulPromise.js +94 -0
- package/dist/statefulPromise.js.map +1 -0
- package/dist/types.d.ts +35 -49
- package/dist/types.d.ts.map +1 -1
- package/dist/types.dom.d.ts +4 -7
- package/dist/types.dom.d.ts.map +1 -1
- package/dist/types.utils.d.ts +3 -4
- package/dist/types.utils.d.ts.map +1 -1
- package/dist/utils/vdom.d.ts +8 -6
- package/dist/utils/vdom.d.ts.map +1 -1
- package/dist/utils/vdom.js +32 -9
- package/dist/utils/vdom.js.map +1 -1
- package/dist/viewTransitions.d.ts +7 -0
- package/dist/viewTransitions.d.ts.map +1 -0
- package/dist/viewTransitions.js +71 -0
- package/dist/viewTransitions.js.map +1 -0
- package/package.json +1 -1
- package/src/{appContext.ts → appHandle.ts} +21 -16
- package/src/components/derive.ts +74 -69
- package/src/components/index.ts +0 -1
- package/src/components/lazy.ts +5 -4
- package/src/components/portal.ts +2 -3
- package/src/components/transition.ts +33 -35
- package/src/constants.ts +0 -8
- package/src/context.ts +30 -23
- package/src/devtools.ts +16 -0
- package/src/dom.ts +31 -65
- package/src/globalContext.ts +57 -74
- package/src/globals.ts +1 -5
- package/src/{recursiveRender.ts → headlessRender.ts} +18 -18
- package/src/hmr.ts +29 -38
- package/src/hooks/index.ts +3 -14
- package/src/hooks/onBeforeMount.ts +12 -0
- package/src/hooks/onCleanup.ts +15 -0
- package/src/hooks/onMount.ts +12 -0
- package/src/hooks/utils.ts +28 -238
- package/src/index.ts +14 -6
- package/src/profiling.ts +22 -20
- package/src/reconciler.ts +18 -30
- package/src/ref.ts +6 -0
- package/src/renderToString.ts +1 -1
- package/src/router/context.ts +1 -2
- package/src/router/fileRouter.ts +23 -13
- package/src/router/fileRouterController.ts +72 -64
- package/src/router/link.ts +11 -25
- package/src/router/server/index.ts +24 -13
- package/src/router/types.ts +15 -8
- package/src/scheduler.ts +74 -71
- package/src/signals/base.ts +12 -41
- package/src/signals/computed.ts +1 -62
- package/src/signals/effect.ts +95 -48
- package/src/signals/globals.ts +0 -7
- package/src/signals/index.ts +4 -4
- package/src/signals/{for.ts → jsx.ts} +10 -0
- package/src/signals/tracking.ts +69 -0
- package/src/signals/types.ts +1 -1
- package/src/signals/utils.ts +9 -1
- package/src/ssr/client.ts +4 -4
- package/src/ssr/server.ts +2 -2
- package/src/statefulPromise.ts +136 -0
- package/src/types.dom.ts +4 -8
- package/src/types.ts +44 -59
- package/src/types.utils.ts +3 -4
- package/src/utils/vdom.ts +44 -15
- package/src/viewTransitions.ts +88 -0
- package/dist/appContext.d.ts.map +0 -1
- package/dist/appContext.js.map +0 -1
- package/dist/components/memo.d.ts +0 -10
- package/dist/components/memo.d.ts.map +0 -1
- package/dist/components/memo.js +0 -23
- package/dist/components/memo.js.map +0 -1
- package/dist/form/index.d.ts +0 -4
- package/dist/form/index.d.ts.map +0 -1
- package/dist/form/index.js +0 -518
- package/dist/form/index.js.map +0 -1
- package/dist/form/types.d.ts +0 -122
- package/dist/form/types.d.ts.map +0 -1
- package/dist/form/types.js +0 -2
- package/dist/form/types.js.map +0 -1
- package/dist/form/utils.d.ts +0 -3
- package/dist/form/utils.d.ts.map +0 -1
- package/dist/form/utils.js +0 -16
- package/dist/form/utils.js.map +0 -1
- package/dist/hooks/useAsync.d.ts +0 -18
- package/dist/hooks/useAsync.d.ts.map +0 -1
- package/dist/hooks/useAsync.js +0 -96
- package/dist/hooks/useAsync.js.map +0 -1
- package/dist/hooks/useCallback.d.ts +0 -7
- package/dist/hooks/useCallback.d.ts.map +0 -1
- package/dist/hooks/useCallback.js +0 -30
- package/dist/hooks/useCallback.js.map +0 -1
- package/dist/hooks/useContext.d.ts +0 -7
- package/dist/hooks/useContext.d.ts.map +0 -1
- package/dist/hooks/useContext.js +0 -59
- package/dist/hooks/useContext.js.map +0 -1
- package/dist/hooks/useEffect.d.ts +0 -8
- package/dist/hooks/useEffect.d.ts.map +0 -1
- package/dist/hooks/useEffect.js +0 -34
- package/dist/hooks/useEffect.js.map +0 -1
- package/dist/hooks/useEffectEvent.d.ts +0 -8
- package/dist/hooks/useEffectEvent.d.ts.map +0 -1
- package/dist/hooks/useEffectEvent.js +0 -23
- package/dist/hooks/useEffectEvent.js.map +0 -1
- package/dist/hooks/useId.d.ts +0 -8
- package/dist/hooks/useId.d.ts.map +0 -1
- package/dist/hooks/useId.js +0 -35
- package/dist/hooks/useId.js.map +0 -1
- package/dist/hooks/useLayoutEffect.d.ts +0 -8
- package/dist/hooks/useLayoutEffect.d.ts.map +0 -1
- package/dist/hooks/useLayoutEffect.js +0 -34
- package/dist/hooks/useLayoutEffect.js.map +0 -1
- package/dist/hooks/useMemo.d.ts +0 -8
- package/dist/hooks/useMemo.d.ts.map +0 -1
- package/dist/hooks/useMemo.js +0 -31
- package/dist/hooks/useMemo.js.map +0 -1
- package/dist/hooks/usePromise.d.ts +0 -8
- package/dist/hooks/usePromise.d.ts.map +0 -1
- package/dist/hooks/usePromise.js +0 -90
- package/dist/hooks/usePromise.js.map +0 -1
- package/dist/hooks/useReducer.d.ts +0 -7
- package/dist/hooks/useReducer.d.ts.map +0 -1
- package/dist/hooks/useReducer.js +0 -44
- package/dist/hooks/useReducer.js.map +0 -1
- package/dist/hooks/useRef.d.ts +0 -10
- package/dist/hooks/useRef.d.ts.map +0 -1
- package/dist/hooks/useRef.js +0 -29
- package/dist/hooks/useRef.js.map +0 -1
- package/dist/hooks/useState.d.ts +0 -7
- package/dist/hooks/useState.d.ts.map +0 -1
- package/dist/hooks/useState.js +0 -54
- package/dist/hooks/useState.js.map +0 -1
- package/dist/hooks/useSyncExternalStore.d.ts +0 -8
- package/dist/hooks/useSyncExternalStore.d.ts.map +0 -1
- package/dist/hooks/useSyncExternalStore.js +0 -50
- package/dist/hooks/useSyncExternalStore.js.map +0 -1
- package/dist/hooks/useViewTransition.d.ts +0 -10
- package/dist/hooks/useViewTransition.d.ts.map +0 -1
- package/dist/hooks/useViewTransition.js +0 -27
- package/dist/hooks/useViewTransition.js.map +0 -1
- package/dist/recursiveRender.d.ts +0 -7
- package/dist/recursiveRender.d.ts.map +0 -1
- package/dist/recursiveRender.js.map +0 -1
- package/dist/signals/for.d.ts.map +0 -1
- package/dist/signals/for.js.map +0 -1
- package/dist/signals/watch.d.ts +0 -21
- package/dist/signals/watch.d.ts.map +0 -1
- package/dist/signals/watch.js +0 -86
- package/dist/signals/watch.js.map +0 -1
- package/dist/store.d.ts +0 -28
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -166
- package/dist/store.js.map +0 -1
- package/dist/swr.d.ts +0 -63
- package/dist/swr.d.ts.map +0 -1
- package/dist/swr.js +0 -236
- package/dist/swr.js.map +0 -1
- package/dist/utils/promise.d.ts +0 -16
- package/dist/utils/promise.d.ts.map +0 -1
- package/dist/utils/promise.js +0 -14
- package/dist/utils/promise.js.map +0 -1
- package/src/components/memo.ts +0 -39
- package/src/form/index.ts +0 -676
- package/src/form/types.ts +0 -262
- package/src/form/utils.ts +0 -19
- package/src/hooks/useAsync.ts +0 -121
- package/src/hooks/useCallback.ts +0 -32
- package/src/hooks/useContext.ts +0 -79
- package/src/hooks/useEffect.ts +0 -40
- package/src/hooks/useEffectEvent.ts +0 -24
- package/src/hooks/useId.ts +0 -42
- package/src/hooks/useLayoutEffect.ts +0 -43
- package/src/hooks/useMemo.ts +0 -34
- package/src/hooks/usePromise.ts +0 -126
- package/src/hooks/useReducer.ts +0 -50
- package/src/hooks/useRef.ts +0 -40
- package/src/hooks/useState.ts +0 -62
- package/src/hooks/useSyncExternalStore.ts +0 -59
- package/src/hooks/useViewTransition.ts +0 -25
- package/src/signals/watch.ts +0 -139
- package/src/store.ts +0 -245
- package/src/swr.ts +0 -351
- package/src/utils/promise.ts +0 -26
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { node } from "../globals.js"
|
|
2
|
+
import { sideEffectsEnabled } from "../utils/index.js"
|
|
3
|
+
import { effectQueue } from "./globals.js"
|
|
4
|
+
import { tick } from "./utils.js"
|
|
5
|
+
import type { Signal } from "./base.js"
|
|
6
|
+
import type { SignalValues } from "./types.js"
|
|
7
|
+
|
|
8
|
+
export const tracking = {
|
|
9
|
+
enabled: true,
|
|
10
|
+
stack: new Array<Map<string, Signal<unknown>>>(),
|
|
11
|
+
current: function (): Map<string, Signal<unknown>> | undefined {
|
|
12
|
+
return this.stack[this.stack.length - 1]
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type TrackedExecutionContext<T, Deps extends readonly Signal<unknown>[]> = {
|
|
17
|
+
id: string
|
|
18
|
+
subs: Map<string, Function>
|
|
19
|
+
fn: (...values: SignalValues<Deps>) => T
|
|
20
|
+
deps?: Deps
|
|
21
|
+
onDepChanged: () => void
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Executes an effect function with dependency tracking enabled, and manages
|
|
26
|
+
* the effect's subscriptions.
|
|
27
|
+
* @param ctx - The execution context
|
|
28
|
+
* @returns The result of the effect function
|
|
29
|
+
*/
|
|
30
|
+
export function executeWithTracking<T, Deps extends readonly Signal<unknown>[]>(
|
|
31
|
+
ctx: TrackedExecutionContext<T, Deps>
|
|
32
|
+
): T {
|
|
33
|
+
const { id, subs, fn, deps = [], onDepChanged } = ctx
|
|
34
|
+
let observations: Map<string, Signal<unknown>> | undefined
|
|
35
|
+
|
|
36
|
+
effectQueue.delete(id)
|
|
37
|
+
const isServer = !!node.current && !sideEffectsEnabled()
|
|
38
|
+
|
|
39
|
+
if (!isServer) {
|
|
40
|
+
observations = new Map<string, Signal<unknown>>()
|
|
41
|
+
tracking.stack.push(observations)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const result = fn(...(deps.map((s) => s.value) as SignalValues<Deps>))
|
|
45
|
+
|
|
46
|
+
if (!isServer) {
|
|
47
|
+
for (const [id, unsub] of subs) {
|
|
48
|
+
if (observations!.has(id)) continue
|
|
49
|
+
unsub()
|
|
50
|
+
subs.delete(id)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const effect = () => {
|
|
54
|
+
if (!effectQueue.size) {
|
|
55
|
+
queueMicrotask(tick)
|
|
56
|
+
}
|
|
57
|
+
effectQueue.set(id, onDepChanged)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
for (const [id, sig] of observations!) {
|
|
61
|
+
if (subs.has(id)) continue
|
|
62
|
+
const unsub = sig.subscribe(effect)
|
|
63
|
+
subs.set(id, unsub)
|
|
64
|
+
}
|
|
65
|
+
tracking.stack.pop()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return result
|
|
69
|
+
}
|
package/src/signals/types.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type SignalSubscriber<T = unknown> = (value: T, prevValue?: T) => void
|
|
|
7
7
|
|
|
8
8
|
export type SignalValues<T extends readonly Signal<unknown>[]> = {
|
|
9
9
|
[I in keyof T]: T[I] extends Signal<infer V>
|
|
10
|
-
? V extends Kiru.
|
|
10
|
+
? V extends Kiru.StatefulPromiseBase<infer P>
|
|
11
11
|
? P
|
|
12
12
|
: V
|
|
13
13
|
: never
|
package/src/signals/utils.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import { call } from "../utils/index.js"
|
|
2
2
|
import { Signal } from "./base.js"
|
|
3
3
|
import { effectQueue } from "./globals.js"
|
|
4
|
+
import { tracking } from "./tracking.js"
|
|
4
5
|
|
|
5
6
|
export function unwrap<T>(value: T | Signal<T>, reactive = false): T {
|
|
6
7
|
if (!Signal.isSignal(value)) return value
|
|
7
8
|
return reactive ? value.value : value.peek()
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
export
|
|
11
|
+
export function tick() {
|
|
11
12
|
effectQueue.forEach(call)
|
|
12
13
|
effectQueue.clear()
|
|
13
14
|
}
|
|
15
|
+
|
|
16
|
+
export function untrack<T>(fn: () => T) {
|
|
17
|
+
tracking.enabled = false
|
|
18
|
+
const result = fn()
|
|
19
|
+
tracking.enabled = true
|
|
20
|
+
return result
|
|
21
|
+
}
|
package/src/ssr/client.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AppHandle, AppHandleOptions } from "../appHandle"
|
|
2
2
|
import { hydrationStack } from "../hydration.js"
|
|
3
3
|
import { hydrationMode, renderMode } from "../globals.js"
|
|
4
4
|
import { mount } from "../index.js"
|
|
5
5
|
|
|
6
|
-
interface
|
|
6
|
+
interface AppHandleHydrationOptions extends AppHandleOptions {
|
|
7
7
|
/**
|
|
8
8
|
* Configures the hydration mode
|
|
9
9
|
* - "static": SSG
|
|
@@ -16,8 +16,8 @@ interface HydrationAppContextOptions extends AppContextOptions {
|
|
|
16
16
|
export function hydrate(
|
|
17
17
|
children: JSX.Element,
|
|
18
18
|
container: HTMLElement,
|
|
19
|
-
options?:
|
|
20
|
-
):
|
|
19
|
+
options?: AppHandleHydrationOptions
|
|
20
|
+
): AppHandle {
|
|
21
21
|
hydrationStack.clear()
|
|
22
22
|
|
|
23
23
|
const prevRenderMode = renderMode.current
|
package/src/ssr/server.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Readable } from "node:stream"
|
|
|
2
2
|
import { Fragment } from "../element.js"
|
|
3
3
|
import { renderMode } from "../globals.js"
|
|
4
4
|
import { STREAMED_DATA_EVENT } from "../constants.js"
|
|
5
|
-
import { headlessRender, HeadlessRenderContext } from "../
|
|
5
|
+
import { headlessRender, HeadlessRenderContext } from "../headlessRender.js"
|
|
6
6
|
|
|
7
7
|
const STREAMED_DATA_SETUP = `
|
|
8
8
|
<script type="text/javascript">
|
|
@@ -26,7 +26,7 @@ export function renderToReadableStream(element: JSX.Element): {
|
|
|
26
26
|
} {
|
|
27
27
|
const stream = new Readable({ read() {} })
|
|
28
28
|
const rootNode = Fragment({ children: element })
|
|
29
|
-
const streamPromises = new Set<Kiru.
|
|
29
|
+
const streamPromises = new Set<Kiru.StatefulPromiseBase<unknown>>()
|
|
30
30
|
const pendingWritePromises: Promise<void>[] = []
|
|
31
31
|
|
|
32
32
|
let immediate = ""
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { $STREAM_DATA, STREAMED_DATA_EVENT } from "./constants.js"
|
|
2
|
+
import { hydrationMode, node, renderMode } from "./globals.js"
|
|
3
|
+
import { Signal, signal } from "./signals/base.js"
|
|
4
|
+
import { getVNodeId } from "./utils/vdom.js"
|
|
5
|
+
import { onCleanup } from "./hooks/onCleanup.js"
|
|
6
|
+
|
|
7
|
+
export interface StreamDataThrowValue {
|
|
8
|
+
[$STREAM_DATA]: {
|
|
9
|
+
fallback?: JSX.Element
|
|
10
|
+
data: Kiru.StatefulPromiseBase<unknown>[]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if the value is a {@link StreamDataThrowValue}
|
|
16
|
+
*/
|
|
17
|
+
export function isStreamDataThrowValue(
|
|
18
|
+
value: unknown
|
|
19
|
+
): value is StreamDataThrowValue {
|
|
20
|
+
return typeof value === "object" && !!value && $STREAM_DATA in value
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Returns true if the value is a {@link Kiru.StatefulPromiseBase}
|
|
25
|
+
*/
|
|
26
|
+
export function isStatefulPromise(
|
|
27
|
+
thing: unknown
|
|
28
|
+
): thing is Kiru.StatefulPromiseBase<unknown> {
|
|
29
|
+
return thing instanceof Promise && "id" in thing && "state" in thing
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const nodeToPromiseIndex = new WeakMap<Kiru.VNode, number>()
|
|
33
|
+
|
|
34
|
+
type StatefulPromise<T> = Kiru.StatefulPromiseBase<T> & {
|
|
35
|
+
isPending: Signal<boolean>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function statefulPromise<T>(
|
|
39
|
+
callback: (signal: AbortSignal) => Promise<T>
|
|
40
|
+
): StatefulPromise<T> {
|
|
41
|
+
const vNode = node.current!
|
|
42
|
+
if (!vNode) {
|
|
43
|
+
throw new Error("statefulPromise must be called inside a Kiru component")
|
|
44
|
+
}
|
|
45
|
+
const id = getVNodeId(vNode)
|
|
46
|
+
const isPending = signal(true)
|
|
47
|
+
|
|
48
|
+
isPending.value = true
|
|
49
|
+
|
|
50
|
+
const controller = new AbortController()
|
|
51
|
+
onCleanup(() => controller.abort())
|
|
52
|
+
|
|
53
|
+
const index = nodeToPromiseIndex.get(vNode) ?? 0
|
|
54
|
+
nodeToPromiseIndex.set(vNode, index + 1)
|
|
55
|
+
|
|
56
|
+
const promiseId = `${id}:data:${index}`
|
|
57
|
+
|
|
58
|
+
let promise: Promise<T>
|
|
59
|
+
if (renderMode.current === "string") {
|
|
60
|
+
// if we're rendering to a string, there's no need to fire the callback
|
|
61
|
+
promise = Promise.resolve() as Promise<T>
|
|
62
|
+
} else if (
|
|
63
|
+
renderMode.current === "hydrate" &&
|
|
64
|
+
hydrationMode.current === "dynamic"
|
|
65
|
+
) {
|
|
66
|
+
// if we're hydrating and the hydration mode is not static,
|
|
67
|
+
// we need to resolve the promise from cache/event
|
|
68
|
+
promise = resolveDeferredPromise<T>(promiseId, controller.signal)
|
|
69
|
+
} else {
|
|
70
|
+
// dom / stream / (hydrate + static)
|
|
71
|
+
promise = callback(controller.signal)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const state: Kiru.PromiseState<T> = {
|
|
75
|
+
id: promiseId,
|
|
76
|
+
state: "pending",
|
|
77
|
+
}
|
|
78
|
+
const statefulPromise: Kiru.StatefulPromiseBase<T> = Object.assign(
|
|
79
|
+
promise,
|
|
80
|
+
state
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
statefulPromise
|
|
84
|
+
.then((value) => {
|
|
85
|
+
statefulPromise.state = "fulfilled"
|
|
86
|
+
statefulPromise.value = value
|
|
87
|
+
isPending.value = false
|
|
88
|
+
})
|
|
89
|
+
.catch((error) => {
|
|
90
|
+
statefulPromise.state = "rejected"
|
|
91
|
+
statefulPromise.error = error instanceof Error ? error : new Error(error)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
return Object.assign(statefulPromise, { isPending })
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface DeferredPromiseEventDetail<T> {
|
|
98
|
+
id: string
|
|
99
|
+
data?: T
|
|
100
|
+
error?: string
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function resolveDeferredPromise<T>(
|
|
104
|
+
id: string,
|
|
105
|
+
signal: AbortSignal
|
|
106
|
+
): Promise<T> {
|
|
107
|
+
return new Promise<T>((resolve, reject) => {
|
|
108
|
+
const deferralCache: Map<string, { data?: T; error?: string }> = // @ts-ignore
|
|
109
|
+
(window[STREAMED_DATA_EVENT] ??= new Map())
|
|
110
|
+
|
|
111
|
+
const existing = deferralCache.get(id)
|
|
112
|
+
if (existing) {
|
|
113
|
+
const { data, error } = existing
|
|
114
|
+
deferralCache.delete(id)
|
|
115
|
+
if (error) return reject(error)
|
|
116
|
+
return resolve(data!)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const onDataEvent = (event: Event) => {
|
|
120
|
+
const { detail } = event as CustomEvent<DeferredPromiseEventDetail<T>>
|
|
121
|
+
if (detail.id === id) {
|
|
122
|
+
deferralCache.delete(id)
|
|
123
|
+
window.removeEventListener(STREAMED_DATA_EVENT, onDataEvent)
|
|
124
|
+
const { data, error } = detail
|
|
125
|
+
if (error) return reject(error)
|
|
126
|
+
resolve(data!)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
window.addEventListener(STREAMED_DATA_EVENT, onDataEvent)
|
|
131
|
+
signal.addEventListener("abort", () => {
|
|
132
|
+
window.removeEventListener(STREAMED_DATA_EVENT, onDataEvent)
|
|
133
|
+
reject()
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
}
|
package/src/types.dom.ts
CHANGED
|
@@ -598,17 +598,13 @@ interface PopoverControlAttributes {
|
|
|
598
598
|
popoverTargetAction?: "show" | "hide" | "toggle"
|
|
599
599
|
}
|
|
600
600
|
|
|
601
|
-
declare class DoNotUseBindWithPlainError extends Error {
|
|
602
|
-
$brand: "DoNotUseBindWithPlainError"
|
|
603
|
-
}
|
|
604
|
-
|
|
605
601
|
type BindableProp<K extends string, V> =
|
|
606
602
|
| ({
|
|
607
|
-
[k in K]?: Signalable<V>
|
|
608
|
-
} & { [k in `bind:${K}`]?:
|
|
603
|
+
[k in K]?: Signalable<V | undefined>
|
|
604
|
+
} & { [k in `bind:${K}`]?: never })
|
|
609
605
|
| ({
|
|
610
|
-
[k in `bind:${K}`]?: Signal<V>
|
|
611
|
-
} & { [k in K]?:
|
|
606
|
+
[k in `bind:${K}`]?: Signal<V | undefined>
|
|
607
|
+
} & { [k in K]?: never })
|
|
612
608
|
|
|
613
609
|
type MediaElementBindableProps = BindableProp<"volume", number> &
|
|
614
610
|
BindableProp<"playbackRate", number> &
|
package/src/types.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import type { ReadonlySignal, Signal as SignalClass } from "./signals"
|
|
2
|
-
import type {
|
|
3
|
-
$CONTEXT,
|
|
4
|
-
$CONTEXT_PROVIDER,
|
|
5
|
-
$ERROR_BOUNDARY,
|
|
6
|
-
$FRAGMENT,
|
|
7
|
-
} from "./constants"
|
|
2
|
+
import type { $CONTEXT, $ERROR_BOUNDARY, $FRAGMENT } from "./constants"
|
|
8
3
|
import type { KiruGlobalContext } from "./globalContext"
|
|
9
4
|
import type {
|
|
10
5
|
GlobalAttributes,
|
|
@@ -22,7 +17,7 @@ import type {
|
|
|
22
17
|
Signalable,
|
|
23
18
|
SomeDom,
|
|
24
19
|
} from "./types.utils"
|
|
25
|
-
import type {
|
|
20
|
+
import type { AppHandle } from "./appHandle"
|
|
26
21
|
|
|
27
22
|
export type { AsyncTaskState, ElementProps, Prettify, Signalable, StyleObject }
|
|
28
23
|
|
|
@@ -32,24 +27,26 @@ type ElementProps<T extends keyof JSX.IntrinsicElements> =
|
|
|
32
27
|
type SignalableHtmlElementAttributes<Tag extends keyof HtmlElementAttributes> =
|
|
33
28
|
{
|
|
34
29
|
[K in keyof HtmlElementAttributes[Tag]]: Signalable<
|
|
35
|
-
HtmlElementAttributes[Tag][K]
|
|
30
|
+
HtmlElementAttributes[Tag][K] | undefined
|
|
36
31
|
>
|
|
37
32
|
} & (Tag extends keyof HtmlElementBindableProps
|
|
38
33
|
? HtmlElementBindableProps[Tag]
|
|
39
34
|
: {})
|
|
40
35
|
type SignalableSvgElementAttributes<Tag extends keyof SvgElementAttributes> = {
|
|
41
36
|
[K in keyof SvgElementAttributes[Tag]]: Signalable<
|
|
42
|
-
SvgElementAttributes[Tag][K]
|
|
37
|
+
SvgElementAttributes[Tag][K] | undefined
|
|
43
38
|
>
|
|
44
39
|
}
|
|
45
40
|
type SignalableAriaProps = {
|
|
46
|
-
[K in keyof ARIAMixin]?: Signalable<ARIAMixin[K]>
|
|
41
|
+
[K in keyof ARIAMixin]?: Signalable<ARIAMixin[K] | undefined>
|
|
47
42
|
}
|
|
48
43
|
type SignalableGlobalAttributes = {
|
|
49
|
-
[K in keyof GlobalAttributes]: Signalable<GlobalAttributes[K]>
|
|
44
|
+
[K in keyof GlobalAttributes]: Signalable<GlobalAttributes[K] | undefined>
|
|
50
45
|
}
|
|
51
46
|
type SignalableSvgGlobalAttributes = {
|
|
52
|
-
[K in keyof SvgGlobalAttributes]: Signalable<
|
|
47
|
+
[K in keyof SvgGlobalAttributes]: Signalable<
|
|
48
|
+
SvgGlobalAttributes[K] | undefined
|
|
49
|
+
>
|
|
53
50
|
}
|
|
54
51
|
|
|
55
52
|
type ElementMap = {
|
|
@@ -58,10 +55,7 @@ type ElementMap = {
|
|
|
58
55
|
SignalableAriaProps &
|
|
59
56
|
Kiru.EventAttributes<HTMLTagToElement<Tag>> &
|
|
60
57
|
JSX.ElementAttributes & {
|
|
61
|
-
ref?:
|
|
62
|
-
| Kiru.Ref<HTMLTagToElement<Tag> | null>
|
|
63
|
-
| SignalClass<HTMLTagToElement<Tag> | null>
|
|
64
|
-
| null
|
|
58
|
+
ref?: Kiru.Ref<Element | null> | SignalClass<Element | null> | null
|
|
65
59
|
}
|
|
66
60
|
} & {
|
|
67
61
|
[Tag in keyof SvgElementAttributes]: SignalableSvgElementAttributes<Tag> &
|
|
@@ -70,10 +64,7 @@ type ElementMap = {
|
|
|
70
64
|
SignalableAriaProps &
|
|
71
65
|
Kiru.EventAttributes<SVGTagToElement<Tag>> &
|
|
72
66
|
JSX.ElementAttributes & {
|
|
73
|
-
ref?:
|
|
74
|
-
| Kiru.Ref<SVGTagToElement<Tag> | null>
|
|
75
|
-
| SignalClass<SVGTagToElement<Tag> | null>
|
|
76
|
-
| null
|
|
67
|
+
ref?: Kiru.Ref<Element | null> | SignalClass<Element | null> | null
|
|
77
68
|
}
|
|
78
69
|
} & {
|
|
79
70
|
[Tag in `${string}-${string}`]: Record<string, any>
|
|
@@ -108,6 +99,7 @@ declare global {
|
|
|
108
99
|
| Kiru.Element
|
|
109
100
|
| PrimitiveChild
|
|
110
101
|
| Kiru.Signal<PrimitiveChild>
|
|
102
|
+
| Kiru.FC<any>
|
|
111
103
|
|
|
112
104
|
interface ElementAttributes {
|
|
113
105
|
key?: JSX.ElementKey
|
|
@@ -121,42 +113,25 @@ declare global {
|
|
|
121
113
|
namespace Kiru {
|
|
122
114
|
interface CustomEvents {}
|
|
123
115
|
|
|
124
|
-
interface
|
|
116
|
+
interface ContextProps<T> {
|
|
125
117
|
value: T
|
|
126
|
-
children?: JSX.Children
|
|
118
|
+
children?: JSX.Children
|
|
127
119
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
displayName?: string
|
|
132
|
-
}
|
|
133
|
-
default: () => T
|
|
134
|
-
/** Used to display the name of the context in devtools */
|
|
135
|
-
displayName?: string
|
|
120
|
+
|
|
121
|
+
interface Context<T> extends Kiru.FC<ContextProps<T>> {
|
|
122
|
+
[$CONTEXT]: () => T
|
|
136
123
|
}
|
|
137
124
|
|
|
138
|
-
interface FC<T = {}> {
|
|
139
|
-
(props:
|
|
125
|
+
export interface FC<T = {}> {
|
|
126
|
+
(props: T):
|
|
127
|
+
| Exclude<JSX.Element, Kiru.FC<any>>
|
|
128
|
+
| ((props: T) => JSX.Element)
|
|
140
129
|
/** Used to display the name of the component in devtools */
|
|
141
130
|
displayName?: string
|
|
142
131
|
}
|
|
143
132
|
|
|
144
|
-
type FCProps<T = {}> = T & { children?: JSX.Children }
|
|
145
133
|
type InferProps<T> = T extends Kiru.FC<infer P> ? P : never
|
|
146
134
|
|
|
147
|
-
interface HookDevtoolsProvisions<T extends Record<string, any>> {
|
|
148
|
-
get: () => T
|
|
149
|
-
set?: (value: T) => void
|
|
150
|
-
}
|
|
151
|
-
type Hook<T> = T & {
|
|
152
|
-
cleanup?: () => void
|
|
153
|
-
name?: string
|
|
154
|
-
dev?: {
|
|
155
|
-
/** Used to perform invalidation during HMR when the hook's arguments have changed */
|
|
156
|
-
initialArgs?: any
|
|
157
|
-
devtools?: HookDevtoolsProvisions<any>
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
135
|
interface RefObject<T> {
|
|
161
136
|
current: T
|
|
162
137
|
}
|
|
@@ -173,7 +148,7 @@ declare global {
|
|
|
173
148
|
error?: Error
|
|
174
149
|
}
|
|
175
150
|
|
|
176
|
-
interface
|
|
151
|
+
interface StatefulPromiseBase<T> extends Promise<T>, PromiseState<T> {}
|
|
177
152
|
|
|
178
153
|
type RenderMode = "dom" | "hydrate" | "string" | "stream"
|
|
179
154
|
|
|
@@ -183,7 +158,7 @@ declare global {
|
|
|
183
158
|
|
|
184
159
|
type ExoticSymbol =
|
|
185
160
|
| typeof $FRAGMENT
|
|
186
|
-
| typeof $
|
|
161
|
+
| typeof $CONTEXT
|
|
187
162
|
| typeof $ERROR_BOUNDARY
|
|
188
163
|
|
|
189
164
|
interface Element {
|
|
@@ -196,8 +171,10 @@ declare global {
|
|
|
196
171
|
}
|
|
197
172
|
}
|
|
198
173
|
|
|
174
|
+
type LifecycleHookCallback = () => (() => void) | void
|
|
175
|
+
|
|
199
176
|
interface VNode extends Element {
|
|
200
|
-
app?:
|
|
177
|
+
app?: AppHandle
|
|
201
178
|
dom?: SomeDom
|
|
202
179
|
index: number
|
|
203
180
|
depth: number
|
|
@@ -207,22 +184,30 @@ declare global {
|
|
|
207
184
|
sibling: VNode | null
|
|
208
185
|
prev: VNodeSnapshot | null
|
|
209
186
|
deletions: VNode[] | null
|
|
210
|
-
hooks?: Hook<unknown>[]
|
|
211
187
|
subs?: Set<Function>
|
|
212
188
|
cleanups?: Record<string, Function>
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
189
|
+
|
|
190
|
+
hooks?: {
|
|
191
|
+
pre: LifecycleHookCallback[]
|
|
192
|
+
preCleanups: (() => void)[]
|
|
193
|
+
post: LifecycleHookCallback[]
|
|
194
|
+
postCleanups: (() => void)[]
|
|
195
|
+
}
|
|
196
|
+
render?: (props: VNode["props"]) => unknown
|
|
217
197
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
198
|
+
interface VNodeSnapshot {
|
|
199
|
+
props: Kiru.VNode["props"]
|
|
200
|
+
key: Kiru.VNode["key"]
|
|
201
|
+
index: number
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
type ContainerElement = HTMLElement | ShadowRoot
|
|
223
205
|
}
|
|
224
206
|
|
|
225
207
|
interface Element {
|
|
226
208
|
__kiruNode?: Kiru.VNode
|
|
227
209
|
}
|
|
210
|
+
interface ShadowRoot {
|
|
211
|
+
__kiruNode?: Kiru.VNode
|
|
212
|
+
}
|
|
228
213
|
}
|
package/src/types.utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { $
|
|
1
|
+
import type { $CONTEXT, $ERROR_BOUNDARY, $FRAGMENT } from "./constants"
|
|
2
2
|
import type { Signal } from "./signals"
|
|
3
3
|
import type { ErrorBoundaryProps } from "./components/errorBoundary"
|
|
4
4
|
|
|
@@ -20,12 +20,11 @@ export interface DomVNode extends Kiru.VNode {
|
|
|
20
20
|
type: "#text" | (string & {})
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export interface
|
|
24
|
-
type: typeof $
|
|
23
|
+
export interface ContextNode<T> extends Kiru.VNode {
|
|
24
|
+
type: typeof $CONTEXT
|
|
25
25
|
props: Kiru.VNode["props"] & {
|
|
26
26
|
value: T
|
|
27
27
|
ctx: Kiru.Context<T>
|
|
28
|
-
dependents: Set<Kiru.VNode>
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
30
|
|
package/src/utils/vdom.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FLAG_DELETION,
|
|
3
3
|
$FRAGMENT,
|
|
4
|
-
$CONTEXT_PROVIDER,
|
|
5
4
|
FLAG_PLACEMENT,
|
|
6
5
|
FLAG_UPDATE,
|
|
7
6
|
$ERROR_BOUNDARY,
|
|
7
|
+
$CONTEXT,
|
|
8
8
|
} from "../constants.js"
|
|
9
9
|
import { createElement } from "../index.js"
|
|
10
10
|
import { KiruError } from "../error.js"
|
|
11
11
|
import { node } from "../globals.js"
|
|
12
|
-
import type {
|
|
12
|
+
import type { AppHandle } from "../appHandle.js"
|
|
13
13
|
import type { ErrorBoundaryNode } from "../types.utils.js"
|
|
14
|
-
import { isMemoFn } from "../components/memo.js"
|
|
15
14
|
|
|
16
15
|
export {
|
|
17
16
|
cloneElement,
|
|
@@ -22,17 +21,19 @@ export {
|
|
|
22
21
|
isExoticType,
|
|
23
22
|
isFragment,
|
|
24
23
|
isLazy,
|
|
25
|
-
isMemo,
|
|
26
24
|
isContextProvider,
|
|
27
25
|
vNodeContains,
|
|
28
26
|
getCurrentVNode,
|
|
29
|
-
|
|
27
|
+
getVNodeApp,
|
|
30
28
|
commitSnapshot,
|
|
31
29
|
traverseApply,
|
|
32
30
|
findParent,
|
|
33
31
|
findParentErrorBoundary,
|
|
34
32
|
assertValidElementProps,
|
|
35
33
|
normalizeElementKey,
|
|
34
|
+
getVNodeId,
|
|
35
|
+
registerVNodeCleanup,
|
|
36
|
+
propsChanged,
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
function cloneElement(vNode: Kiru.VNode): Kiru.Element {
|
|
@@ -68,9 +69,7 @@ function isValidTextChild(thing: unknown): thing is string | number | bigint {
|
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
function isExoticType(type: Kiru.VNode["type"]): type is Kiru.ExoticSymbol {
|
|
71
|
-
return
|
|
72
|
-
type === $FRAGMENT || type === $CONTEXT_PROVIDER || type === $ERROR_BOUNDARY
|
|
73
|
-
)
|
|
72
|
+
return type === $FRAGMENT || type === $CONTEXT || type === $ERROR_BOUNDARY
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
function isFragment(
|
|
@@ -87,21 +86,17 @@ function isLazy(vNode: Kiru.VNode): boolean {
|
|
|
87
86
|
)
|
|
88
87
|
}
|
|
89
88
|
|
|
90
|
-
function isMemo(vNode: Kiru.VNode): boolean {
|
|
91
|
-
return typeof vNode.type === "function" && isMemoFn(vNode.type)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
89
|
function isContextProvider(
|
|
95
90
|
thing: unknown
|
|
96
|
-
): thing is Kiru.VNode & { type: typeof $
|
|
97
|
-
return isVNode(thing) && thing.type === $
|
|
91
|
+
): thing is Kiru.VNode & { type: typeof $CONTEXT } {
|
|
92
|
+
return isVNode(thing) && thing.type === $CONTEXT
|
|
98
93
|
}
|
|
99
94
|
|
|
100
95
|
function getCurrentVNode(): Kiru.VNode | null {
|
|
101
96
|
return node.current
|
|
102
97
|
}
|
|
103
98
|
|
|
104
|
-
function
|
|
99
|
+
function getVNodeApp(vNode: Kiru.VNode): AppHandle | null {
|
|
105
100
|
let n: Kiru.VNode | null = vNode
|
|
106
101
|
while (n) {
|
|
107
102
|
if (n.app) {
|
|
@@ -190,3 +185,37 @@ function normalizeElementKey(thing: unknown): JSX.ElementKey | null {
|
|
|
190
185
|
}
|
|
191
186
|
return null
|
|
192
187
|
}
|
|
188
|
+
|
|
189
|
+
function getVNodeId(vNode: Kiru.VNode): string {
|
|
190
|
+
const accumulator: number[] = []
|
|
191
|
+
let n: Kiru.VNode | null = vNode
|
|
192
|
+
while (n) {
|
|
193
|
+
accumulator.push(n.index)
|
|
194
|
+
accumulator.push(n.depth)
|
|
195
|
+
n = n.parent
|
|
196
|
+
}
|
|
197
|
+
return `k:${BigInt(accumulator.join("")).toString(36)}`
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function registerVNodeCleanup(
|
|
201
|
+
vNode: Kiru.VNode,
|
|
202
|
+
id: string,
|
|
203
|
+
callback: () => void
|
|
204
|
+
) {
|
|
205
|
+
;(vNode.cleanups ??= {})[id] = callback
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function propsChanged(
|
|
209
|
+
oldProps: Kiru.VNode["props"],
|
|
210
|
+
newProps: Kiru.VNode["props"],
|
|
211
|
+
keysToSkip?: string[]
|
|
212
|
+
) {
|
|
213
|
+
const aKeys = Object.keys(oldProps)
|
|
214
|
+
const bKeys = Object.keys(newProps)
|
|
215
|
+
if (aKeys.length !== bKeys.length) return true
|
|
216
|
+
for (let key of aKeys) {
|
|
217
|
+
if (keysToSkip?.includes(key)) continue
|
|
218
|
+
if (oldProps[key] !== newProps[key]) return true
|
|
219
|
+
}
|
|
220
|
+
return false
|
|
221
|
+
}
|