kiru 0.54.4 → 1.1.0
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} +13 -10
- 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 +7 -6
- 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 -30
- 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 +19 -0
- package/dist/devtools.js.map +1 -0
- package/dist/dom/commit.d.ts +5 -0
- package/dist/dom/commit.d.ts.map +1 -0
- package/dist/dom/commit.js +94 -0
- package/dist/dom/commit.js.map +1 -0
- package/dist/dom/focus.d.ts +4 -0
- package/dist/dom/focus.d.ts.map +1 -0
- package/dist/dom/focus.js +32 -0
- package/dist/dom/focus.js.map +1 -0
- package/dist/dom/index.d.ts +4 -0
- package/dist/dom/index.d.ts.map +1 -0
- package/dist/dom/index.js +4 -0
- package/dist/dom/index.js.map +1 -0
- package/dist/dom/nodes.d.ts +12 -0
- package/dist/dom/nodes.d.ts.map +1 -0
- package/dist/dom/nodes.js +165 -0
- package/dist/dom/nodes.js.map +1 -0
- package/dist/dom/props.d.ts +8 -0
- package/dist/dom/props.d.ts.map +1 -0
- package/dist/dom/props.js +675 -0
- package/dist/dom/props.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +2 -0
- package/dist/env.js.map +1 -1
- package/dist/globalContext.d.ts +17 -23
- package/dist/globalContext.d.ts.map +1 -1
- package/dist/globalContext.js +31 -53
- package/dist/globalContext.js.map +1 -1
- package/dist/globals.d.ts +21 -4
- package/dist/globals.d.ts.map +1 -1
- package/dist/globals.js +22 -5
- 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 +21 -8
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +58 -37
- package/dist/hmr.js.map +1 -1
- package/dist/hooks/index.d.ts +4 -14
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +4 -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 +19 -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 +18 -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 +19 -0
- package/dist/hooks/onMount.js.map +1 -0
- package/dist/hooks/setup.d.ts +13 -0
- package/dist/hooks/setup.d.ts.map +1 -0
- package/dist/hooks/setup.js +54 -0
- package/dist/hooks/setup.js.map +1 -0
- package/dist/hooks/utils.d.ts +2 -63
- package/dist/hooks/utils.d.ts.map +1 -1
- package/dist/hooks/utils.js +17 -144
- package/dist/hooks/utils.js.map +1 -1
- package/dist/index.d.ts +9 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -8
- 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 +15 -28
- 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/head.js +2 -2
- package/dist/router/head.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/pageConfig.js +2 -2
- package/dist/router/pageConfig.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 +91 -73
- 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 +14 -37
- 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 +24 -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 +40 -50
- package/dist/types.d.ts.map +1 -1
- package/dist/types.dom.d.ts +5 -8
- 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/format.d.ts.map +1 -1
- package/dist/utils/format.js +4 -1
- package/dist/utils/format.js.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 +72 -0
- package/dist/viewTransitions.js.map +1 -0
- package/package.json +1 -1
- package/src/{appContext.ts → appHandle.ts} +22 -17
- package/src/components/derive.ts +74 -69
- package/src/components/index.ts +0 -1
- package/src/components/lazy.ts +10 -10
- package/src/components/portal.ts +2 -3
- package/src/components/transition.ts +33 -39
- package/src/constants.ts +0 -8
- package/src/context.ts +30 -23
- package/src/devtools.ts +18 -0
- package/src/dom/commit.ts +133 -0
- package/src/dom/focus.ts +34 -0
- package/src/dom/index.ts +3 -0
- package/src/dom/nodes.ts +204 -0
- package/src/dom/props.ts +818 -0
- package/src/env.ts +3 -0
- package/src/globalContext.ts +51 -85
- package/src/globals.ts +25 -6
- package/src/{recursiveRender.ts → headlessRender.ts} +18 -18
- package/src/hmr.ts +60 -42
- package/src/hooks/index.ts +4 -14
- package/src/hooks/onBeforeMount.ts +18 -0
- package/src/hooks/onCleanup.ts +21 -0
- package/src/hooks/onMount.ts +18 -0
- package/src/hooks/setup.ts +70 -0
- package/src/hooks/utils.ts +24 -239
- package/src/index.ts +17 -7
- package/src/profiling.ts +22 -20
- package/src/reconciler.ts +21 -33
- 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/head.ts +2 -2
- package/src/router/link.ts +11 -25
- package/src/router/pageConfig.ts +2 -2
- package/src/router/server/index.ts +24 -13
- package/src/router/types.ts +15 -8
- package/src/scheduler.ts +116 -98
- package/src/signals/base.ts +13 -42
- package/src/signals/computed.ts +1 -62
- package/src/signals/effect.ts +93 -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 +70 -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 +6 -10
- package/src/types.ts +51 -60
- package/src/types.utils.ts +3 -4
- package/src/utils/format.ts +3 -1
- package/src/utils/vdom.ts +44 -15
- package/src/viewTransitions.ts +89 -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/dom.d.ts +0 -10
- package/dist/dom.d.ts.map +0 -1
- package/dist/dom.js +0 -634
- package/dist/dom.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/dom.ts +0 -809
- 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
package/src/scheduler.ts
CHANGED
|
@@ -1,48 +1,39 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ContextProviderNode,
|
|
3
|
-
DomVNode,
|
|
4
|
-
ErrorBoundaryNode,
|
|
5
|
-
FunctionVNode,
|
|
6
|
-
} from "./types.utils"
|
|
1
|
+
import type { DomVNode, ErrorBoundaryNode, FunctionVNode } from "./types.utils"
|
|
7
2
|
import {
|
|
8
|
-
$CONTEXT_PROVIDER,
|
|
9
3
|
$ERROR_BOUNDARY,
|
|
10
|
-
$MEMO,
|
|
11
4
|
CONSECUTIVE_DIRTY_LIMIT,
|
|
12
5
|
FLAG_DELETION,
|
|
13
6
|
FLAG_DIRTY,
|
|
14
|
-
FLAG_MEMO,
|
|
15
|
-
FLAG_NOOP,
|
|
16
7
|
} from "./constants.js"
|
|
17
8
|
import {
|
|
9
|
+
captureFocus,
|
|
18
10
|
commitDeletion,
|
|
19
11
|
commitWork,
|
|
20
12
|
createDom,
|
|
21
13
|
hydrateDom,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} from "./dom.js"
|
|
25
|
-
import { __DEV__ } from "./env.js"
|
|
26
|
-
import { KiruError } from "./error.js"
|
|
27
|
-
import { hookIndex, node, renderMode } from "./globals.js"
|
|
28
|
-
import { hydrationStack } from "./hydration.js"
|
|
29
|
-
import { reconcileChildren } from "./reconciler.js"
|
|
14
|
+
reinstateFocus,
|
|
15
|
+
} from "./dom/index.js"
|
|
30
16
|
import {
|
|
31
17
|
assertValidElementProps,
|
|
32
18
|
latest,
|
|
33
19
|
traverseApply,
|
|
34
20
|
isExoticType,
|
|
35
|
-
|
|
21
|
+
getVNodeApp,
|
|
36
22
|
findParentErrorBoundary,
|
|
37
23
|
call,
|
|
24
|
+
propsChanged,
|
|
38
25
|
} from "./utils/index.js"
|
|
39
|
-
import
|
|
40
|
-
import
|
|
26
|
+
import { __DEV__ } from "./env.js"
|
|
27
|
+
import { KiruError } from "./error.js"
|
|
28
|
+
import { node, postEffectCleanups, renderMode, setups } from "./globals.js"
|
|
29
|
+
import { hydrationStack } from "./hydration.js"
|
|
30
|
+
import { reconcileChildren } from "./reconciler.js"
|
|
41
31
|
import { isHmrUpdate } from "./hmr.js"
|
|
32
|
+
import type { AppHandle } from "./appHandle"
|
|
42
33
|
|
|
43
34
|
type VNode = Kiru.VNode
|
|
44
35
|
|
|
45
|
-
let
|
|
36
|
+
let app: AppHandle | null
|
|
46
37
|
let treesInProgress: VNode[] = []
|
|
47
38
|
let isRunningOrQueued = false
|
|
48
39
|
let nextIdleEffects: (() => void)[] = []
|
|
@@ -51,8 +42,8 @@ let isImmediateEffectsMode = false
|
|
|
51
42
|
let immediateEffectDirtiedRender = false
|
|
52
43
|
let isRenderDirtied = false
|
|
53
44
|
let consecutiveDirtyCount = 0
|
|
54
|
-
let preEffects:
|
|
55
|
-
let postEffects:
|
|
45
|
+
let preEffects: Kiru.LifecycleHookCallback[] = []
|
|
46
|
+
let postEffects: Kiru.LifecycleHookCallback[] = []
|
|
56
47
|
let animationFrameHandle = -1
|
|
57
48
|
|
|
58
49
|
/**
|
|
@@ -94,21 +85,16 @@ export function requestUpdate(vNode: VNode): void {
|
|
|
94
85
|
queueUpdate(vNode)
|
|
95
86
|
}
|
|
96
87
|
|
|
97
|
-
function
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function onWorkFinished(): void {
|
|
104
|
-
isRunningOrQueued = false
|
|
105
|
-
while (nextIdleEffects.length) {
|
|
106
|
-
nextIdleEffects.shift()!()
|
|
88
|
+
export function useRequestUpdate(): () => void {
|
|
89
|
+
const n = node.current
|
|
90
|
+
if (!n) {
|
|
91
|
+
throw new Error("useRequestUpdate must be called inside a Kiru component")
|
|
107
92
|
}
|
|
93
|
+
return () => requestUpdate(n)
|
|
108
94
|
}
|
|
109
95
|
|
|
110
96
|
function queueUpdate(vNode: VNode): void {
|
|
111
|
-
// In immediate effect mode (
|
|
97
|
+
// In immediate effect mode (onBeforeMount), immediately mark the render as dirty
|
|
112
98
|
if (isImmediateEffectsMode) {
|
|
113
99
|
immediateEffectDirtiedRender = true
|
|
114
100
|
}
|
|
@@ -116,7 +102,7 @@ function queueUpdate(vNode: VNode): void {
|
|
|
116
102
|
// If this node is currently being rendered, just mark it dirty
|
|
117
103
|
if (node.current === vNode) {
|
|
118
104
|
if (__DEV__) {
|
|
119
|
-
window.__kiru.profilingContext?.emit("updateDirtied",
|
|
105
|
+
window.__kiru.profilingContext?.emit("updateDirtied", app!)
|
|
120
106
|
}
|
|
121
107
|
isRenderDirtied = true
|
|
122
108
|
return
|
|
@@ -127,7 +113,12 @@ function queueUpdate(vNode: VNode): void {
|
|
|
127
113
|
|
|
128
114
|
if (!treesInProgress.length) {
|
|
129
115
|
treesInProgress.push(vNode)
|
|
130
|
-
|
|
116
|
+
|
|
117
|
+
if (!isRunningOrQueued) {
|
|
118
|
+
isRunningOrQueued = true
|
|
119
|
+
animationFrameHandle = window.requestAnimationFrame(doWork)
|
|
120
|
+
}
|
|
121
|
+
return
|
|
131
122
|
}
|
|
132
123
|
|
|
133
124
|
treesInProgress.push(vNode)
|
|
@@ -146,16 +137,16 @@ function doWork(): void {
|
|
|
146
137
|
if (__DEV__) {
|
|
147
138
|
const n = deletions[0] ?? treesInProgress[0]
|
|
148
139
|
if (n) {
|
|
149
|
-
|
|
150
|
-
window.__kiru.profilingContext?.beginTick(
|
|
140
|
+
app = getVNodeApp(n)!
|
|
141
|
+
window.__kiru.profilingContext?.beginTick(app)
|
|
151
142
|
} else {
|
|
152
|
-
|
|
143
|
+
app = null
|
|
153
144
|
}
|
|
154
145
|
}
|
|
155
146
|
|
|
156
147
|
let len = 1
|
|
157
148
|
|
|
158
|
-
|
|
149
|
+
captureFocus()
|
|
159
150
|
while (treesInProgress.length) {
|
|
160
151
|
if (treesInProgress.length > len) {
|
|
161
152
|
treesInProgress.sort(depthSort)
|
|
@@ -178,7 +169,7 @@ function doWork(): void {
|
|
|
178
169
|
currentWorkRoot.flags &= ~FLAG_DIRTY
|
|
179
170
|
}
|
|
180
171
|
}
|
|
181
|
-
|
|
172
|
+
reinstateFocus()
|
|
182
173
|
|
|
183
174
|
isImmediateEffectsMode = true
|
|
184
175
|
flushEffects(preEffects)
|
|
@@ -190,19 +181,25 @@ function doWork(): void {
|
|
|
190
181
|
immediateEffectDirtiedRender = false
|
|
191
182
|
consecutiveDirtyCount++
|
|
192
183
|
if (__DEV__) {
|
|
193
|
-
window.__kiru.profilingContext?.endTick(
|
|
194
|
-
window.__kiru.profilingContext?.emit("updateDirtied",
|
|
184
|
+
window.__kiru.profilingContext?.endTick(app!)
|
|
185
|
+
window.__kiru.profilingContext?.emit("updateDirtied", app!)
|
|
195
186
|
}
|
|
196
187
|
return flushSync()
|
|
197
188
|
}
|
|
198
189
|
consecutiveDirtyCount = 0
|
|
199
190
|
|
|
200
|
-
|
|
201
|
-
|
|
191
|
+
isRunningOrQueued = false
|
|
192
|
+
while (nextIdleEffects.length) {
|
|
193
|
+
nextIdleEffects.shift()!()
|
|
194
|
+
}
|
|
195
|
+
queueMicrotask(() => {
|
|
196
|
+
flushEffects(postEffectCleanups)
|
|
197
|
+
flushEffects(postEffects)
|
|
198
|
+
})
|
|
202
199
|
if (__DEV__) {
|
|
203
|
-
window.__kiru.emit("update",
|
|
204
|
-
window.__kiru.profilingContext?.emit("update",
|
|
205
|
-
window.__kiru.profilingContext?.endTick(
|
|
200
|
+
window.__kiru.emit("update", app!)
|
|
201
|
+
window.__kiru.profilingContext?.emit("update", app!)
|
|
202
|
+
window.__kiru.profilingContext?.endTick(app!)
|
|
206
203
|
}
|
|
207
204
|
}
|
|
208
205
|
|
|
@@ -221,13 +218,12 @@ function performUnitOfWork(vNode: VNode): VNode | null {
|
|
|
221
218
|
let nextNode: VNode | null = vNode
|
|
222
219
|
while (nextNode) {
|
|
223
220
|
// queue effects upon ascent
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
nextNode.effects = undefined
|
|
221
|
+
const { hooks } = nextNode
|
|
222
|
+
if (hooks) {
|
|
223
|
+
preEffects.push(...hooks.pre)
|
|
224
|
+
postEffects.push(...hooks.post)
|
|
225
|
+
hooks.pre.length = 0
|
|
226
|
+
hooks.post.length = 0
|
|
231
227
|
}
|
|
232
228
|
|
|
233
229
|
if (nextNode === currentWorkRoot) return null
|
|
@@ -246,8 +242,13 @@ function performUnitOfWork(vNode: VNode): VNode | null {
|
|
|
246
242
|
|
|
247
243
|
function updateVNode(vNode: VNode): VNode | null {
|
|
248
244
|
const { type, props, prev, flags } = vNode
|
|
245
|
+
|
|
249
246
|
if (__DEV__ && isHmrUpdate()) {
|
|
250
|
-
} else if (
|
|
247
|
+
} else if (
|
|
248
|
+
prev &&
|
|
249
|
+
(flags & FLAG_DIRTY) === 0 &&
|
|
250
|
+
(prev.props === props || !propsChanged(prev.props, props))
|
|
251
|
+
) {
|
|
251
252
|
return null
|
|
252
253
|
}
|
|
253
254
|
try {
|
|
@@ -262,7 +263,7 @@ function updateVNode(vNode: VNode): VNode | null {
|
|
|
262
263
|
if (__DEV__) {
|
|
263
264
|
window.__kiru.emit(
|
|
264
265
|
"error",
|
|
265
|
-
|
|
266
|
+
app!,
|
|
266
267
|
error instanceof Error ? error : new Error(String(error))
|
|
267
268
|
)
|
|
268
269
|
}
|
|
@@ -302,16 +303,7 @@ function updateExoticComponent(vNode: VNode): VNode | null {
|
|
|
302
303
|
const { props, type } = vNode
|
|
303
304
|
let children = props.children
|
|
304
305
|
|
|
305
|
-
if (type === $
|
|
306
|
-
const {
|
|
307
|
-
props: { dependents, value },
|
|
308
|
-
prev,
|
|
309
|
-
} = vNode as ContextProviderNode<unknown>
|
|
310
|
-
|
|
311
|
-
if (dependents.size && prev && prev.props.value !== value) {
|
|
312
|
-
dependents.forEach(queueUpdate)
|
|
313
|
-
}
|
|
314
|
-
} else if (type === $ERROR_BOUNDARY) {
|
|
306
|
+
if (type === $ERROR_BOUNDARY) {
|
|
315
307
|
const n = vNode as ErrorBoundaryNode
|
|
316
308
|
const { error } = n
|
|
317
309
|
if (error) {
|
|
@@ -328,18 +320,11 @@ function updateExoticComponent(vNode: VNode): VNode | null {
|
|
|
328
320
|
}
|
|
329
321
|
|
|
330
322
|
function updateFunctionComponent(vNode: FunctionVNode): VNode | null {
|
|
331
|
-
const { type, props, subs
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
!(__DEV__ && isHmrUpdate())
|
|
337
|
-
) {
|
|
338
|
-
vNode.flags |= FLAG_NOOP
|
|
339
|
-
return null
|
|
340
|
-
}
|
|
341
|
-
vNode.flags &= ~FLAG_NOOP
|
|
342
|
-
}
|
|
323
|
+
const { type, props, subs } = vNode
|
|
324
|
+
|
|
325
|
+
/** Only sync prop-derived signals when update came from parent (new props), not from internal subscription (e.g. signal). */
|
|
326
|
+
const shouldSyncProps = (vNode.flags & FLAG_DIRTY) === 0
|
|
327
|
+
|
|
343
328
|
try {
|
|
344
329
|
node.current = vNode
|
|
345
330
|
let newChild
|
|
@@ -347,7 +332,6 @@ function updateFunctionComponent(vNode: FunctionVNode): VNode | null {
|
|
|
347
332
|
do {
|
|
348
333
|
vNode.flags &= ~FLAG_DIRTY
|
|
349
334
|
isRenderDirtied = false
|
|
350
|
-
hookIndex.current = 0
|
|
351
335
|
|
|
352
336
|
/**
|
|
353
337
|
* remove previous signal subscriptions (if any) every render.
|
|
@@ -363,23 +347,26 @@ function updateFunctionComponent(vNode: FunctionVNode): VNode | null {
|
|
|
363
347
|
subs.clear()
|
|
364
348
|
}
|
|
365
349
|
|
|
366
|
-
if (__DEV__) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
vNode.hooks.length = hookIndex.current
|
|
378
|
-
vNode.hookSig.length = hookIndex.current
|
|
379
|
-
}
|
|
350
|
+
if (__DEV__ && isHmrUpdate()) {
|
|
351
|
+
const { hooks, cleanups } = vNode
|
|
352
|
+
if (cleanups) {
|
|
353
|
+
Object.values(cleanups).forEach(call)
|
|
354
|
+
delete vNode.cleanups
|
|
355
|
+
}
|
|
356
|
+
if (hooks) {
|
|
357
|
+
const { preCleanups, postCleanups } = hooks
|
|
358
|
+
preCleanups.forEach(call)
|
|
359
|
+
postCleanups.forEach(call)
|
|
360
|
+
preCleanups.length = postCleanups.length = 0
|
|
380
361
|
}
|
|
362
|
+
delete vNode.propSyncs
|
|
363
|
+
delete vNode.render
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
newChild = renderFunctionComponent(vNode, type, props, shouldSyncProps)
|
|
381
367
|
|
|
382
|
-
|
|
368
|
+
if (++renderTryCount > CONSECUTIVE_DIRTY_LIMIT) {
|
|
369
|
+
if (__DEV__) {
|
|
383
370
|
throw new KiruError({
|
|
384
371
|
message:
|
|
385
372
|
"Too many re-renders. Kiru limits the number of renders to prevent an infinite loop.",
|
|
@@ -387,9 +374,8 @@ function updateFunctionComponent(vNode: FunctionVNode): VNode | null {
|
|
|
387
374
|
vNode,
|
|
388
375
|
})
|
|
389
376
|
}
|
|
390
|
-
|
|
377
|
+
break
|
|
391
378
|
}
|
|
392
|
-
newChild = type(props)
|
|
393
379
|
} while (isRenderDirtied)
|
|
394
380
|
|
|
395
381
|
return (vNode.child = reconcileChildren(vNode, newChild))
|
|
@@ -398,6 +384,38 @@ function updateFunctionComponent(vNode: FunctionVNode): VNode | null {
|
|
|
398
384
|
}
|
|
399
385
|
}
|
|
400
386
|
|
|
387
|
+
function renderFunctionComponent(
|
|
388
|
+
vNode: FunctionVNode,
|
|
389
|
+
type: Function,
|
|
390
|
+
props: Record<string, unknown>,
|
|
391
|
+
shouldSyncProps: boolean
|
|
392
|
+
): unknown {
|
|
393
|
+
const { render, propSyncs } = vNode
|
|
394
|
+
|
|
395
|
+
if (render) {
|
|
396
|
+
if (shouldSyncProps) {
|
|
397
|
+
const p = { ...props }
|
|
398
|
+
propSyncs?.forEach((sync) => sync(p))
|
|
399
|
+
}
|
|
400
|
+
return render(props)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
let newChild = latest(type)(props)
|
|
404
|
+
if (typeof newChild === "function") {
|
|
405
|
+
vNode.subs?.forEach(call) // unsub from signals observered during setup
|
|
406
|
+
vNode.render = newChild
|
|
407
|
+
if (shouldSyncProps) {
|
|
408
|
+
const p = { ...props }
|
|
409
|
+
propSyncs?.forEach((sync) => sync(p))
|
|
410
|
+
}
|
|
411
|
+
newChild = newChild(props)
|
|
412
|
+
} else if (__DEV__ && setups.has(vNode)) {
|
|
413
|
+
throw new Error("setup() must not be called inside a render function")
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return newChild
|
|
417
|
+
}
|
|
418
|
+
|
|
401
419
|
function updateHostComponent(vNode: DomVNode): VNode | null {
|
|
402
420
|
const { props, type } = vNode
|
|
403
421
|
if (__DEV__) {
|
package/src/signals/base.ts
CHANGED
|
@@ -3,13 +3,14 @@ import {
|
|
|
3
3
|
safeStringify,
|
|
4
4
|
sideEffectsEnabled,
|
|
5
5
|
generateRandomID,
|
|
6
|
+
registerVNodeCleanup,
|
|
6
7
|
} from "../utils/index.js"
|
|
7
8
|
import { $HMR_ACCEPT, $SIGNAL } from "../constants.js"
|
|
8
|
-
import { __DEV__ } from "../env.js"
|
|
9
|
+
import { __DEV__, isBrowser } from "../env.js"
|
|
9
10
|
import { node } from "../globals.js"
|
|
10
|
-
import { useHook } from "../hooks/utils.js"
|
|
11
11
|
import { requestUpdate } from "../scheduler.js"
|
|
12
|
-
import {
|
|
12
|
+
import { signalSubsMap } from "./globals.js"
|
|
13
|
+
import { tracking } from "./tracking.js"
|
|
13
14
|
import type { SignalSubscriber, ReadonlySignal } from "./types.js"
|
|
14
15
|
import type { HMRAccept } from "../hmr.js"
|
|
15
16
|
|
|
@@ -38,6 +39,7 @@ export class Signal<T> {
|
|
|
38
39
|
return this as Signal<any>
|
|
39
40
|
},
|
|
40
41
|
inject: (prev) => {
|
|
42
|
+
if (isBrowser) window.__kiru.devtools?.untrack(prev)
|
|
41
43
|
signalSubsMap.get(this.$id)?.clear?.()
|
|
42
44
|
signalSubsMap.delete(this.$id)
|
|
43
45
|
this.$id = prev.$id
|
|
@@ -56,6 +58,11 @@ export class Signal<T> {
|
|
|
56
58
|
} else {
|
|
57
59
|
this.$subs = new Set()
|
|
58
60
|
}
|
|
61
|
+
|
|
62
|
+
const n = node.current
|
|
63
|
+
if (n) {
|
|
64
|
+
registerVNodeCleanup(n, this.$id, Signal.dispose.bind(null, this))
|
|
65
|
+
}
|
|
59
66
|
}
|
|
60
67
|
|
|
61
68
|
get value() {
|
|
@@ -175,6 +182,8 @@ export class Signal<T> {
|
|
|
175
182
|
}
|
|
176
183
|
|
|
177
184
|
static entangle<T>(signal: Signal<T>) {
|
|
185
|
+
if (tracking.enabled === false) return
|
|
186
|
+
|
|
178
187
|
const vNode = node.current
|
|
179
188
|
const trackedSignalObservations = tracking.current()
|
|
180
189
|
if (trackedSignalObservations) {
|
|
@@ -192,6 +201,7 @@ export class Signal<T> {
|
|
|
192
201
|
signal.$isDisposed = true
|
|
193
202
|
if (__DEV__) {
|
|
194
203
|
signalSubsMap.delete(signal.$id)
|
|
204
|
+
if (isBrowser) window.__kiru.devtools?.untrack(signal)
|
|
195
205
|
return
|
|
196
206
|
}
|
|
197
207
|
signal.$subs!.clear()
|
|
@@ -201,42 +211,3 @@ export class Signal<T> {
|
|
|
201
211
|
export const signal = <T>(initial: T, displayName?: string) => {
|
|
202
212
|
return new Signal(initial, displayName)
|
|
203
213
|
}
|
|
204
|
-
|
|
205
|
-
export const useSignal = <T>(initial: T, displayName?: string) => {
|
|
206
|
-
return useHook(
|
|
207
|
-
"useSignal",
|
|
208
|
-
{ signal: null! as Signal<T> },
|
|
209
|
-
({ hook, isInit, isHMR }) => {
|
|
210
|
-
if (__DEV__) {
|
|
211
|
-
if (isInit) {
|
|
212
|
-
hook.dev = {
|
|
213
|
-
devtools: {
|
|
214
|
-
get: () => ({
|
|
215
|
-
displayName: hook.signal.displayName,
|
|
216
|
-
value: hook.signal.peek(),
|
|
217
|
-
}),
|
|
218
|
-
set: ({ value }) => {
|
|
219
|
-
hook.signal.value = value
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
initialArgs: [initial, displayName],
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
if (isHMR) {
|
|
226
|
-
const [v, name] = hook.dev!.initialArgs
|
|
227
|
-
if (v !== initial || name !== displayName) {
|
|
228
|
-
hook.cleanup?.()
|
|
229
|
-
isInit = true
|
|
230
|
-
hook.dev!.initialArgs = [initial, displayName]
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (isInit) {
|
|
236
|
-
hook.cleanup = () => Signal.dispose(hook.signal)
|
|
237
|
-
hook.signal = new Signal(initial, displayName)
|
|
238
|
-
}
|
|
239
|
-
return hook.signal
|
|
240
|
-
}
|
|
241
|
-
)
|
|
242
|
-
}
|
package/src/signals/computed.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { __DEV__ } from "../env.js"
|
|
2
2
|
import { $HMR_ACCEPT } from "../constants.js"
|
|
3
|
-
import { depsRequireChange, useHook } from "../hooks/utils.js"
|
|
4
3
|
import { call, latest } from "../utils/index.js"
|
|
5
4
|
import { effectQueue, signalSubsMap } from "./globals.js"
|
|
6
|
-
import { executeWithTracking } from "./
|
|
5
|
+
import { executeWithTracking } from "./tracking.js"
|
|
7
6
|
import { Signal } from "./base.js"
|
|
8
7
|
import type { HMRAccept } from "../hmr.js"
|
|
9
8
|
|
|
@@ -131,63 +130,3 @@ export function computed<T>(
|
|
|
131
130
|
): ComputedSignal<T> {
|
|
132
131
|
return new ComputedSignal(getter, displayName)
|
|
133
132
|
}
|
|
134
|
-
|
|
135
|
-
export function useComputed<T>(
|
|
136
|
-
getter: (prev?: T) => T,
|
|
137
|
-
displayName?: string
|
|
138
|
-
): ComputedSignal<T>
|
|
139
|
-
|
|
140
|
-
export function useComputed<T>(
|
|
141
|
-
getter: (prev?: T) => T,
|
|
142
|
-
deps?: unknown[],
|
|
143
|
-
displayName?: string
|
|
144
|
-
): ComputedSignal<T>
|
|
145
|
-
|
|
146
|
-
export function useComputed<T>(
|
|
147
|
-
getter: (prev?: T) => T,
|
|
148
|
-
depsOrDisplayName?: string | unknown[],
|
|
149
|
-
displayName?: string
|
|
150
|
-
) {
|
|
151
|
-
return useHook(
|
|
152
|
-
"useComputedSignal",
|
|
153
|
-
{
|
|
154
|
-
signal: null! as ComputedSignal<T>,
|
|
155
|
-
deps: void 0 as unknown[] | undefined,
|
|
156
|
-
},
|
|
157
|
-
({ hook, isInit, isHMR }) => {
|
|
158
|
-
if (__DEV__) {
|
|
159
|
-
hook.dev = {
|
|
160
|
-
devtools: {
|
|
161
|
-
get: () => ({
|
|
162
|
-
displayName: hook.signal.displayName,
|
|
163
|
-
value: hook.signal.peek(),
|
|
164
|
-
}),
|
|
165
|
-
},
|
|
166
|
-
}
|
|
167
|
-
if (isHMR) {
|
|
168
|
-
// useComputed is always considered side-effecty, so we need to re-run
|
|
169
|
-
hook.cleanup?.()
|
|
170
|
-
isInit = true
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (isInit) {
|
|
174
|
-
if (typeof depsOrDisplayName === "string") {
|
|
175
|
-
displayName = depsOrDisplayName
|
|
176
|
-
depsOrDisplayName = void 0
|
|
177
|
-
}
|
|
178
|
-
hook.deps = depsOrDisplayName
|
|
179
|
-
hook.cleanup = () => ComputedSignal.dispose(hook.signal)
|
|
180
|
-
hook.signal = computed(getter, displayName)
|
|
181
|
-
} else if (
|
|
182
|
-
hook.deps &&
|
|
183
|
-
typeof depsOrDisplayName !== "string" &&
|
|
184
|
-
depsRequireChange(hook.deps, depsOrDisplayName)
|
|
185
|
-
) {
|
|
186
|
-
hook.deps = depsOrDisplayName
|
|
187
|
-
ComputedSignal.updateGetter(hook.signal, getter)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return hook.signal
|
|
191
|
-
}
|
|
192
|
-
)
|
|
193
|
-
}
|
package/src/signals/effect.ts
CHANGED
|
@@ -1,61 +1,106 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { __DEV__, isBrowser } from "../env.js"
|
|
2
|
+
import { effectQueue } from "./globals.js"
|
|
3
|
+
import { executeWithTracking } from "./tracking.js"
|
|
4
|
+
import {
|
|
5
|
+
latest,
|
|
6
|
+
generateRandomID,
|
|
7
|
+
call,
|
|
8
|
+
registerVNodeCleanup,
|
|
9
|
+
sideEffectsEnabled,
|
|
10
|
+
} from "../utils/index.js"
|
|
5
11
|
import type { Signal } from "./base.js"
|
|
6
12
|
import type { SignalValues } from "./types.js"
|
|
13
|
+
import { node } from "../globals.js"
|
|
7
14
|
|
|
8
|
-
type
|
|
9
|
-
id: string
|
|
10
|
-
subs: Map<string, Function>
|
|
11
|
-
fn: (...values: SignalValues<Deps>) => T
|
|
12
|
-
deps?: Deps
|
|
13
|
-
onDepChanged: () => void
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Executes an effect function with dependency tracking enabled, and manages
|
|
18
|
-
* the effect's subscriptions.
|
|
19
|
-
* @param ctx - The execution context
|
|
20
|
-
* @returns The result of the effect function
|
|
21
|
-
*/
|
|
22
|
-
export function executeWithTracking<T, Deps extends readonly Signal<unknown>[]>(
|
|
23
|
-
ctx: TrackedExecutionContext<T, Deps>
|
|
24
|
-
): T {
|
|
25
|
-
const { id, subs, fn, deps = [], onDepChanged } = ctx
|
|
26
|
-
let observations: Map<string, Signal<unknown>> | undefined
|
|
27
|
-
|
|
28
|
-
effectQueue.delete(id)
|
|
29
|
-
const isServer = !!node.current && !sideEffectsEnabled()
|
|
30
|
-
|
|
31
|
-
if (!isServer) {
|
|
32
|
-
observations = new Map<string, Signal<unknown>>()
|
|
33
|
-
tracking.stack.push(observations)
|
|
34
|
-
}
|
|
15
|
+
type EffectCallbackReturn = (() => void) | void
|
|
35
16
|
|
|
36
|
-
|
|
17
|
+
export class Effect<const Deps extends readonly Signal<unknown>[] = []> {
|
|
18
|
+
protected id: string
|
|
19
|
+
protected callback: (...values: SignalValues<Deps>) => EffectCallbackReturn
|
|
20
|
+
protected deps?: Deps
|
|
21
|
+
protected unsubs: Map<string, Function>
|
|
22
|
+
protected cleanup: (() => void) | null
|
|
23
|
+
protected isRunning?: boolean
|
|
37
24
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
25
|
+
constructor(
|
|
26
|
+
callback: (...values: SignalValues<Deps>) => EffectCallbackReturn,
|
|
27
|
+
deps?: Deps
|
|
28
|
+
) {
|
|
29
|
+
this.id = generateRandomID()
|
|
30
|
+
this.callback = callback
|
|
31
|
+
this.deps = deps
|
|
32
|
+
this.unsubs = new Map()
|
|
33
|
+
this.isRunning = false
|
|
34
|
+
this.cleanup = null
|
|
35
|
+
if (__DEV__ && isBrowser) {
|
|
36
|
+
window.__kiru.HMRContext!.moduleEffects.push(this)
|
|
37
|
+
}
|
|
38
|
+
const n = node.current
|
|
39
|
+
if (n) {
|
|
40
|
+
if (!sideEffectsEnabled()) return // prevent side effects in non-browser environments
|
|
41
|
+
registerVNodeCleanup(n, this.id, this.stop.bind(this))
|
|
43
42
|
}
|
|
43
|
+
this.start()
|
|
44
|
+
}
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
effectQueue.set(id, onDepChanged)
|
|
46
|
+
start() {
|
|
47
|
+
if (this.isRunning) {
|
|
48
|
+
return
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
this.isRunning = true
|
|
52
|
+
|
|
53
|
+
// postpone execution during HMR
|
|
54
|
+
if (__DEV__ && isBrowser && window.__kiru.HMRContext?.isReplacement()) {
|
|
55
|
+
return queueMicrotask(() => {
|
|
56
|
+
if (this.isRunning) {
|
|
57
|
+
Effect.run(this as Effect)
|
|
58
|
+
}
|
|
59
|
+
})
|
|
56
60
|
}
|
|
57
|
-
|
|
61
|
+
Effect.run(this as Effect)
|
|
58
62
|
}
|
|
59
63
|
|
|
60
|
-
|
|
64
|
+
stop() {
|
|
65
|
+
effectQueue.delete(this.id)
|
|
66
|
+
this.unsubs.forEach(call)
|
|
67
|
+
this.unsubs.clear()
|
|
68
|
+
this.cleanup?.()
|
|
69
|
+
this.cleanup = null
|
|
70
|
+
this.isRunning = false
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private static run(watchEffect: Effect) {
|
|
74
|
+
const effect = latest(watchEffect)
|
|
75
|
+
const { id, callback: getter, unsubs: subs, deps } = effect
|
|
76
|
+
|
|
77
|
+
effect.cleanup =
|
|
78
|
+
executeWithTracking({
|
|
79
|
+
id,
|
|
80
|
+
subs,
|
|
81
|
+
fn: getter,
|
|
82
|
+
deps,
|
|
83
|
+
onDepChanged: () => {
|
|
84
|
+
effect.cleanup?.()
|
|
85
|
+
Effect.run(effect)
|
|
86
|
+
},
|
|
87
|
+
}) ?? null
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function effect(callback: () => EffectCallbackReturn): Effect
|
|
92
|
+
export function effect<const Deps extends readonly Signal<unknown>[]>(
|
|
93
|
+
dependencies: Deps,
|
|
94
|
+
callback: (...values: SignalValues<Deps>) => EffectCallbackReturn
|
|
95
|
+
): Effect<Deps>
|
|
96
|
+
export function effect<const Deps extends readonly Signal<unknown>[]>(
|
|
97
|
+
depsOrGetter: Deps | (() => EffectCallbackReturn),
|
|
98
|
+
callback?: (...values: SignalValues<Deps>) => EffectCallbackReturn
|
|
99
|
+
): Effect<Deps> | Effect {
|
|
100
|
+
if (typeof depsOrGetter === "function") {
|
|
101
|
+
return new Effect<[]>(depsOrGetter)
|
|
102
|
+
}
|
|
103
|
+
const dependencies = depsOrGetter
|
|
104
|
+
const effectGetter = callback!
|
|
105
|
+
return new Effect(effectGetter, dependencies)
|
|
61
106
|
}
|