kiru 0.54.3 → 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 +36 -50
- 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 +29 -63
- 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 +45 -58
- 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 -41
- 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,9 +55,7 @@ type ElementMap = {
|
|
|
58
55
|
SignalableAriaProps &
|
|
59
56
|
Kiru.EventAttributes<HTMLTagToElement<Tag>> &
|
|
60
57
|
JSX.ElementAttributes & {
|
|
61
|
-
ref?:
|
|
62
|
-
| Kiru.Ref<HTMLTagToElement<Tag>>
|
|
63
|
-
| SignalClass<HTMLTagToElement<Tag> | null>
|
|
58
|
+
ref?: Kiru.Ref<Element | null> | SignalClass<Element | null> | null
|
|
64
59
|
}
|
|
65
60
|
} & {
|
|
66
61
|
[Tag in keyof SvgElementAttributes]: SignalableSvgElementAttributes<Tag> &
|
|
@@ -69,9 +64,7 @@ type ElementMap = {
|
|
|
69
64
|
SignalableAriaProps &
|
|
70
65
|
Kiru.EventAttributes<SVGTagToElement<Tag>> &
|
|
71
66
|
JSX.ElementAttributes & {
|
|
72
|
-
ref?:
|
|
73
|
-
| Kiru.Ref<SVGTagToElement<Tag>>
|
|
74
|
-
| SignalClass<SVGTagToElement<Tag> | null>
|
|
67
|
+
ref?: Kiru.Ref<Element | null> | SignalClass<Element | null> | null
|
|
75
68
|
}
|
|
76
69
|
} & {
|
|
77
70
|
[Tag in `${string}-${string}`]: Record<string, any>
|
|
@@ -106,6 +99,7 @@ declare global {
|
|
|
106
99
|
| Kiru.Element
|
|
107
100
|
| PrimitiveChild
|
|
108
101
|
| Kiru.Signal<PrimitiveChild>
|
|
102
|
+
| Kiru.FC<any>
|
|
109
103
|
|
|
110
104
|
interface ElementAttributes {
|
|
111
105
|
key?: JSX.ElementKey
|
|
@@ -119,42 +113,25 @@ declare global {
|
|
|
119
113
|
namespace Kiru {
|
|
120
114
|
interface CustomEvents {}
|
|
121
115
|
|
|
122
|
-
interface
|
|
116
|
+
interface ContextProps<T> {
|
|
123
117
|
value: T
|
|
124
|
-
children?: JSX.Children
|
|
118
|
+
children?: JSX.Children
|
|
125
119
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
displayName?: string
|
|
130
|
-
}
|
|
131
|
-
default: () => T
|
|
132
|
-
/** Used to display the name of the context in devtools */
|
|
133
|
-
displayName?: string
|
|
120
|
+
|
|
121
|
+
interface Context<T> extends Kiru.FC<ContextProps<T>> {
|
|
122
|
+
[$CONTEXT]: () => T
|
|
134
123
|
}
|
|
135
124
|
|
|
136
|
-
interface FC<T = {}> {
|
|
137
|
-
(props:
|
|
125
|
+
export interface FC<T = {}> {
|
|
126
|
+
(props: T):
|
|
127
|
+
| Exclude<JSX.Element, Kiru.FC<any>>
|
|
128
|
+
| ((props: T) => JSX.Element)
|
|
138
129
|
/** Used to display the name of the component in devtools */
|
|
139
130
|
displayName?: string
|
|
140
131
|
}
|
|
141
132
|
|
|
142
|
-
type FCProps<T = {}> = T & { children?: JSX.Children }
|
|
143
133
|
type InferProps<T> = T extends Kiru.FC<infer P> ? P : never
|
|
144
134
|
|
|
145
|
-
interface HookDevtoolsProvisions<T extends Record<string, any>> {
|
|
146
|
-
get: () => T
|
|
147
|
-
set?: (value: T) => void
|
|
148
|
-
}
|
|
149
|
-
type Hook<T> = T & {
|
|
150
|
-
cleanup?: () => void
|
|
151
|
-
name?: string
|
|
152
|
-
dev?: {
|
|
153
|
-
/** Used to perform invalidation during HMR when the hook's arguments have changed */
|
|
154
|
-
initialArgs?: any
|
|
155
|
-
devtools?: HookDevtoolsProvisions<any>
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
135
|
interface RefObject<T> {
|
|
159
136
|
current: T
|
|
160
137
|
}
|
|
@@ -171,7 +148,7 @@ declare global {
|
|
|
171
148
|
error?: Error
|
|
172
149
|
}
|
|
173
150
|
|
|
174
|
-
interface
|
|
151
|
+
interface StatefulPromiseBase<T> extends Promise<T>, PromiseState<T> {}
|
|
175
152
|
|
|
176
153
|
type RenderMode = "dom" | "hydrate" | "string" | "stream"
|
|
177
154
|
|
|
@@ -181,7 +158,7 @@ declare global {
|
|
|
181
158
|
|
|
182
159
|
type ExoticSymbol =
|
|
183
160
|
| typeof $FRAGMENT
|
|
184
|
-
| typeof $
|
|
161
|
+
| typeof $CONTEXT
|
|
185
162
|
| typeof $ERROR_BOUNDARY
|
|
186
163
|
|
|
187
164
|
interface Element {
|
|
@@ -190,12 +167,14 @@ declare global {
|
|
|
190
167
|
props: {
|
|
191
168
|
[key: string]: any
|
|
192
169
|
children?: unknown
|
|
193
|
-
ref?: Kiru.Ref<unknown>
|
|
170
|
+
ref?: Kiru.Ref<unknown> | null
|
|
194
171
|
}
|
|
195
172
|
}
|
|
196
173
|
|
|
174
|
+
type LifecycleHookCallback = () => (() => void) | void
|
|
175
|
+
|
|
197
176
|
interface VNode extends Element {
|
|
198
|
-
app?:
|
|
177
|
+
app?: AppHandle
|
|
199
178
|
dom?: SomeDom
|
|
200
179
|
index: number
|
|
201
180
|
depth: number
|
|
@@ -205,22 +184,30 @@ declare global {
|
|
|
205
184
|
sibling: VNode | null
|
|
206
185
|
prev: VNodeSnapshot | null
|
|
207
186
|
deletions: VNode[] | null
|
|
208
|
-
hooks?: Hook<unknown>[]
|
|
209
187
|
subs?: Set<Function>
|
|
210
188
|
cleanups?: Record<string, Function>
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
189
|
+
|
|
190
|
+
hooks?: {
|
|
191
|
+
pre: LifecycleHookCallback[]
|
|
192
|
+
preCleanups: (() => void)[]
|
|
193
|
+
post: LifecycleHookCallback[]
|
|
194
|
+
postCleanups: (() => void)[]
|
|
195
|
+
}
|
|
196
|
+
render?: (props: VNode["props"]) => unknown
|
|
215
197
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
198
|
+
interface VNodeSnapshot {
|
|
199
|
+
props: Kiru.VNode["props"]
|
|
200
|
+
key: Kiru.VNode["key"]
|
|
201
|
+
index: number
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
type ContainerElement = HTMLElement | ShadowRoot
|
|
221
205
|
}
|
|
222
206
|
|
|
223
207
|
interface Element {
|
|
224
208
|
__kiruNode?: Kiru.VNode
|
|
225
209
|
}
|
|
210
|
+
interface ShadowRoot {
|
|
211
|
+
__kiruNode?: Kiru.VNode
|
|
212
|
+
}
|
|
226
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
|
+
}
|