kiru 1.0.1 → 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/appHandle.js +2 -2
- package/dist/appHandle.js.map +1 -1
- package/dist/components/lazy.d.ts.map +1 -1
- package/dist/components/lazy.js +2 -2
- package/dist/components/lazy.js.map +1 -1
- package/dist/components/transition.js +1 -5
- package/dist/components/transition.js.map +1 -1
- package/dist/devtools.d.ts.map +1 -1
- package/dist/devtools.js +6 -2
- package/dist/devtools.js.map +1 -1
- 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 +3 -8
- package/dist/globalContext.d.ts.map +1 -1
- package/dist/globalContext.js +4 -16
- package/dist/globalContext.js.map +1 -1
- package/dist/globals.d.ts +21 -1
- package/dist/globals.d.ts.map +1 -1
- package/dist/globals.js +22 -2
- package/dist/globals.js.map +1 -1
- package/dist/hmr.d.ts +17 -2
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +31 -5
- package/dist/hmr.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/onBeforeMount.d.ts +1 -1
- package/dist/hooks/onBeforeMount.d.ts.map +1 -1
- package/dist/hooks/onBeforeMount.js +10 -3
- package/dist/hooks/onBeforeMount.js.map +1 -1
- package/dist/hooks/onCleanup.d.ts +1 -1
- package/dist/hooks/onCleanup.d.ts.map +1 -1
- package/dist/hooks/onCleanup.js +7 -4
- package/dist/hooks/onCleanup.js.map +1 -1
- package/dist/hooks/onMount.d.ts +2 -2
- package/dist/hooks/onMount.d.ts.map +1 -1
- package/dist/hooks/onMount.js +11 -4
- package/dist/hooks/onMount.js.map +1 -1
- 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 -3
- package/dist/hooks/utils.d.ts.map +1 -1
- package/dist/hooks/utils.js +9 -14
- package/dist/hooks/utils.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/reconciler.js +3 -3
- package/dist/reconciler.js.map +1 -1
- package/dist/router/head.js +2 -2
- package/dist/router/head.js.map +1 -1
- package/dist/router/pageConfig.js +2 -2
- package/dist/router/pageConfig.js.map +1 -1
- package/dist/scheduler.js +62 -57
- package/dist/scheduler.js.map +1 -1
- package/dist/signals/base.js +3 -3
- package/dist/signals/base.js.map +1 -1
- package/dist/signals/effect.d.ts.map +1 -1
- package/dist/signals/effect.js +6 -6
- package/dist/signals/effect.js.map +1 -1
- package/dist/signals/tracking.d.ts +3 -2
- package/dist/signals/tracking.d.ts.map +1 -1
- package/dist/signals/tracking.js.map +1 -1
- package/dist/statefulPromise.js +2 -2
- package/dist/statefulPromise.js.map +1 -1
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.dom.d.ts +1 -1
- package/dist/types.dom.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 +2 -2
- package/dist/utils/vdom.d.ts.map +1 -1
- package/dist/utils/vdom.js +2 -2
- package/dist/utils/vdom.js.map +1 -1
- package/dist/viewTransitions.d.ts.map +1 -1
- package/dist/viewTransitions.js +2 -1
- package/dist/viewTransitions.js.map +1 -1
- package/package.json +1 -1
- package/src/appHandle.ts +2 -2
- package/src/components/lazy.ts +5 -6
- package/src/components/transition.ts +2 -6
- package/src/devtools.ts +4 -2
- 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 +7 -24
- package/src/globals.ts +25 -2
- package/src/hmr.ts +32 -5
- package/src/hooks/index.ts +1 -0
- package/src/hooks/onBeforeMount.ts +9 -3
- package/src/hooks/onCleanup.ts +10 -4
- package/src/hooks/onMount.ts +10 -4
- package/src/hooks/setup.ts +70 -0
- package/src/hooks/utils.ts +14 -19
- package/src/index.ts +4 -2
- package/src/reconciler.ts +3 -3
- package/src/router/head.ts +2 -2
- package/src/router/pageConfig.ts +2 -2
- package/src/scheduler.ts +79 -64
- package/src/signals/base.ts +3 -3
- package/src/signals/effect.ts +5 -7
- package/src/signals/tracking.ts +3 -2
- package/src/statefulPromise.ts +2 -2
- package/src/types.dom.ts +2 -2
- package/src/types.ts +7 -1
- package/src/utils/format.ts +3 -1
- package/src/utils/vdom.ts +2 -2
- package/src/viewTransitions.ts +2 -1
- package/dist/dom.d.ts +0 -10
- package/dist/dom.d.ts.map +0 -1
- package/dist/dom.js +0 -601
- package/dist/dom.js.map +0 -1
- package/src/dom.ts +0 -775
package/src/env.ts
CHANGED
package/src/globalContext.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { __DEV__ } from "./env.js"
|
|
2
|
-
import {
|
|
2
|
+
import { createHmrContext } from "./hmr.js"
|
|
3
3
|
import { createProfilingContext } from "./profiling.js"
|
|
4
4
|
import { fileRouterInstance } from "./router/globals.js"
|
|
5
5
|
import type { FileRouterController } from "./router/fileRouterController"
|
|
6
6
|
import type { AppHandle } from "./appHandle"
|
|
7
|
-
import type { requestUpdate } from "./index.js"
|
|
8
7
|
|
|
9
8
|
export { createKiruGlobalContext, type GlobalKiruEvent, type KiruGlobalContext }
|
|
10
9
|
|
|
11
10
|
type Evt =
|
|
12
11
|
| {
|
|
13
12
|
name: "mount"
|
|
14
|
-
data?:
|
|
13
|
+
data?: undefined
|
|
15
14
|
}
|
|
16
15
|
| {
|
|
17
16
|
name: "unmount"
|
|
@@ -28,10 +27,6 @@ type Evt =
|
|
|
28
27
|
|
|
29
28
|
type GlobalKiruEvent = Evt["name"]
|
|
30
29
|
|
|
31
|
-
interface SchedulerInterface {
|
|
32
|
-
requestUpdate: (vNode: Kiru.VNode) => void
|
|
33
|
-
}
|
|
34
|
-
|
|
35
30
|
export type DebuggerEntry = {
|
|
36
31
|
label: string
|
|
37
32
|
signal: Kiru.Signal<unknown>
|
|
@@ -53,17 +48,15 @@ interface KiruGlobalContext {
|
|
|
53
48
|
untrack: (signal: Kiru.Signal<unknown>) => void
|
|
54
49
|
subscribe: (callback: (entries: Set<DebuggerEntry>) => void) => () => void
|
|
55
50
|
}
|
|
56
|
-
HMRContext?: ReturnType<typeof
|
|
51
|
+
HMRContext?: ReturnType<typeof createHmrContext>
|
|
57
52
|
profilingContext?: ReturnType<typeof createProfilingContext>
|
|
58
53
|
fileRouterInstance?: {
|
|
59
54
|
current: FileRouterController | null
|
|
60
55
|
}
|
|
61
|
-
getSchedulerInterface?: (app: AppHandle) => SchedulerInterface | null
|
|
62
56
|
}
|
|
63
57
|
|
|
64
58
|
function createKiruGlobalContext(): KiruGlobalContext {
|
|
65
59
|
const apps = new Set<AppHandle>()
|
|
66
|
-
const appToSchedulerInterface = new WeakMap<AppHandle, SchedulerInterface>()
|
|
67
60
|
const listeners = new Map<
|
|
68
61
|
GlobalKiruEvent,
|
|
69
62
|
Set<(app: AppHandle, data?: Evt["data"]) => void>
|
|
@@ -103,23 +96,13 @@ function createKiruGlobalContext(): KiruGlobalContext {
|
|
|
103
96
|
}
|
|
104
97
|
|
|
105
98
|
// Initialize event listeners
|
|
106
|
-
on("mount", (app
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
appToSchedulerInterface.set(app, { requestUpdate })
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
on("unmount", (app) => {
|
|
113
|
-
apps.delete(app)
|
|
114
|
-
appToSchedulerInterface.delete(app)
|
|
115
|
-
})
|
|
99
|
+
on("mount", (app) => apps.add(app))
|
|
100
|
+
on("unmount", (app) => apps.delete(app))
|
|
101
|
+
|
|
116
102
|
if (__DEV__) {
|
|
117
|
-
globalContext.HMRContext =
|
|
103
|
+
globalContext.HMRContext = createHmrContext()
|
|
118
104
|
globalContext.profilingContext = createProfilingContext()
|
|
119
105
|
globalContext.fileRouterInstance = fileRouterInstance
|
|
120
|
-
globalContext.getSchedulerInterface = (app) => {
|
|
121
|
-
return appToSchedulerInterface.get(app) ?? null
|
|
122
|
-
}
|
|
123
106
|
|
|
124
107
|
const debuggerEntries = new Set<DebuggerEntry>()
|
|
125
108
|
const subscribers = new Set<(debuggerEntries: Set<DebuggerEntry>) => void>()
|
package/src/globals.ts
CHANGED
|
@@ -1,13 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
import { Setup } from "./hooks/index.js"
|
|
2
|
+
import { isBrowser } from "./env.js"
|
|
3
|
+
export { node, renderMode, hydrationMode, setups, postEffectCleanups }
|
|
2
4
|
|
|
5
|
+
/**
|
|
6
|
+
* A reference to the current VNode (always a component) being rendered.
|
|
7
|
+
*/
|
|
3
8
|
const node = {
|
|
4
9
|
current: null as Kiru.VNode | null,
|
|
5
10
|
}
|
|
6
11
|
|
|
12
|
+
/**
|
|
13
|
+
* The current render mode. Can be "dom" "string", "stream", or "hydrate".
|
|
14
|
+
*/
|
|
7
15
|
const renderMode = {
|
|
8
|
-
current: (
|
|
16
|
+
current: (isBrowser ? "dom" : "string") as Kiru.RenderMode,
|
|
9
17
|
}
|
|
10
18
|
|
|
19
|
+
/**
|
|
20
|
+
* The current hydration mode. Can be "static" or "dynamic".
|
|
21
|
+
* Used to indicate whether the page being hydrated will contain streamed content.
|
|
22
|
+
*/
|
|
11
23
|
const hydrationMode = {
|
|
12
24
|
current: "dynamic" as "static" | "dynamic",
|
|
13
25
|
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A map of VNodes (components) to their setup functions.
|
|
29
|
+
*/
|
|
30
|
+
const setups: WeakMap<Kiru.VNode, Setup<any>> = new WeakMap()
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Cleanup functions from onMount() that run after components
|
|
34
|
+
* have been unmounted and the browser has painted.
|
|
35
|
+
*/
|
|
36
|
+
const postEffectCleanups: (() => void)[] = []
|
package/src/hmr.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type HMRAccept<T = {}> = {
|
|
|
13
13
|
export type GenericHMRAcceptor<T = {}> = {
|
|
14
14
|
[$HMR_ACCEPT]: HMRAccept<T>
|
|
15
15
|
}
|
|
16
|
-
type HotVar = Kiru.FC | Signal<any> | Kiru.
|
|
16
|
+
type HotVar = Kiru.FC | Signal<any> | Kiru.Context<any>
|
|
17
17
|
|
|
18
18
|
type HotVarDesc = {
|
|
19
19
|
type: string
|
|
@@ -42,6 +42,7 @@ export function isGenericHmrAcceptor(
|
|
|
42
42
|
type ModuleMemory = {
|
|
43
43
|
hotVars: Map<string, HotVarDesc>
|
|
44
44
|
unnamedEffects: Array<Effect>
|
|
45
|
+
hmrCallbacks: Array<() => void>
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
type HotVarRegistrationEntry = {
|
|
@@ -50,7 +51,7 @@ type HotVarRegistrationEntry = {
|
|
|
50
51
|
link: string
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
export function
|
|
54
|
+
export function createHmrContext() {
|
|
54
55
|
type FilePath = string
|
|
55
56
|
const moduleMap = new Map<FilePath, ModuleMemory>()
|
|
56
57
|
let currentModuleFilePath: string | null = null
|
|
@@ -59,9 +60,13 @@ export function createHMRContext() {
|
|
|
59
60
|
const isReplacement = () => isModuleReplacementExecution
|
|
60
61
|
let isWaitingForNextEffect = false
|
|
61
62
|
|
|
62
|
-
const
|
|
63
|
+
const globalHmrCallbacks: Array<() => void> = []
|
|
63
64
|
const onHmr = (callback: () => void) => {
|
|
64
|
-
|
|
65
|
+
if (currentModuleMemory) {
|
|
66
|
+
currentModuleMemory.hmrCallbacks.push(callback)
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
globalHmrCallbacks.push(callback)
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
const prepare = (filePath: string) => {
|
|
@@ -71,10 +76,12 @@ export function createHMRContext() {
|
|
|
71
76
|
mod = {
|
|
72
77
|
hotVars: new Map(),
|
|
73
78
|
unnamedEffects: [],
|
|
79
|
+
hmrCallbacks: [],
|
|
74
80
|
}
|
|
75
81
|
moduleMap.set(filePath, mod)
|
|
76
82
|
} else {
|
|
77
|
-
while (
|
|
83
|
+
while (mod.hmrCallbacks.length) mod.hmrCallbacks.shift()!()
|
|
84
|
+
while (globalHmrCallbacks.length) globalHmrCallbacks.shift()!()
|
|
78
85
|
for (const effect of mod.unnamedEffects) {
|
|
79
86
|
effect.stop()
|
|
80
87
|
}
|
|
@@ -165,3 +172,23 @@ export function createHMRContext() {
|
|
|
165
172
|
},
|
|
166
173
|
}
|
|
167
174
|
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Queues a callback to be fired when HMR is triggered. This is a no-op in non-browser environments or in production.
|
|
178
|
+
* - If called during current module evaluation, the callback will be fired the next time the current module is evaluated.
|
|
179
|
+
* - If called at any other time, the callback will be fired the next time HMR is triggered.
|
|
180
|
+
* @see https://kirujs.dev/docs/api/lifecycles#onHmr
|
|
181
|
+
*
|
|
182
|
+
* ```ts
|
|
183
|
+
* import { onHmr } from "kiru"
|
|
184
|
+
* // start an interval in the module scope
|
|
185
|
+
* const interval = setInterval(() => {...}, 1000)
|
|
186
|
+
* // stop the interval when this file is reloaded
|
|
187
|
+
* onHmr(() => clearInterval(interval))
|
|
188
|
+
```
|
|
189
|
+
*/
|
|
190
|
+
export function onHmr(callback: () => void): void {
|
|
191
|
+
if ("window" in globalThis && window.__kiru.HMRContext) {
|
|
192
|
+
window.__kiru.HMRContext.onHmr(callback)
|
|
193
|
+
}
|
|
194
|
+
}
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sideEffectsEnabled } from "../utils/index.js"
|
|
2
|
+
import { getVNodeLifecycleHooks, wrapLifecycleHookCallback } from "./utils.js"
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Registers a callback that runs after the component is first mounted to the DOM, but before the DOM is painted.
|
|
5
6
|
* Optionally returns a cleanup function that will run when the component unmounts.
|
|
6
7
|
* Intended for use during component setup when the component returns a render function.
|
|
7
8
|
*
|
|
8
|
-
* @see https://kirujs.dev/docs/
|
|
9
|
+
* @see https://kirujs.dev/docs/api/lifecycles#onBeforeMount
|
|
9
10
|
*/
|
|
10
11
|
export function onBeforeMount(fn: () => (() => void) | void): void {
|
|
11
|
-
|
|
12
|
+
if (!sideEffectsEnabled()) return
|
|
13
|
+
const hooks = getVNodeLifecycleHooks()
|
|
14
|
+
if (!hooks) {
|
|
15
|
+
throw new Error("Cannot queue beforeMount effect outside of a component")
|
|
16
|
+
}
|
|
17
|
+
hooks.pre.push(wrapLifecycleHookCallback(fn, hooks.preCleanups))
|
|
12
18
|
}
|
package/src/hooks/onCleanup.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { node } from "../globals.js"
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
generateRandomID,
|
|
4
|
+
registerVNodeCleanup,
|
|
5
|
+
sideEffectsEnabled,
|
|
6
|
+
} from "../utils/index.js"
|
|
3
7
|
|
|
4
8
|
/**
|
|
5
9
|
* Registers a cleanup function that runs when the component unmounts.
|
|
6
10
|
* Intended for use during component setup when the component returns a render function.
|
|
7
11
|
*
|
|
8
|
-
* @see https://kirujs.dev/docs/
|
|
12
|
+
* @see https://kirujs.dev/docs/api/lifecycles#onCleanup
|
|
9
13
|
*/
|
|
10
14
|
export function onCleanup(fn: () => void): void {
|
|
15
|
+
if (!sideEffectsEnabled()) return
|
|
11
16
|
const vNode = node.current!
|
|
12
|
-
if (!vNode)
|
|
13
|
-
throw new Error("Cannot queue
|
|
17
|
+
if (!vNode) {
|
|
18
|
+
throw new Error("Cannot queue onCleanup effect outside of a component")
|
|
19
|
+
}
|
|
14
20
|
registerVNodeCleanup(vNode, generateRandomID(10), fn)
|
|
15
21
|
}
|
package/src/hooks/onMount.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sideEffectsEnabled } from "../utils/index.js"
|
|
2
|
+
import { getVNodeLifecycleHooks, wrapLifecycleHookCallback } from "./utils.js"
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Registers a callback that runs after the component is first mounted to the DOM.
|
|
5
|
-
* Optionally returns a cleanup function that will run
|
|
6
|
+
* Optionally returns a cleanup function that will run after the component unmounts.
|
|
6
7
|
* Intended for use during component setup when the component returns a render function.
|
|
7
8
|
*
|
|
8
|
-
* @see https://kirujs.dev/docs/
|
|
9
|
+
* @see https://kirujs.dev/docs/api/lifecycles#onMount
|
|
9
10
|
*/
|
|
10
11
|
export function onMount(fn: () => (() => void) | void): void {
|
|
11
|
-
|
|
12
|
+
if (!sideEffectsEnabled()) return
|
|
13
|
+
const hooks = getVNodeLifecycleHooks()
|
|
14
|
+
if (!hooks) {
|
|
15
|
+
throw new Error("Cannot queue onMount effect outside of a component")
|
|
16
|
+
}
|
|
17
|
+
hooks.post.push(wrapLifecycleHookCallback(fn, hooks.postCleanups))
|
|
12
18
|
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { node, setups } from "../globals.js"
|
|
2
|
+
import { signal } from "../signals/index.js"
|
|
3
|
+
import type { Signal } from "../signals/base.js"
|
|
4
|
+
import { createVNodeId } from "../utils/vdom.js"
|
|
5
|
+
import { __DEV__ } from "../env.js"
|
|
6
|
+
|
|
7
|
+
export interface Setup<Props extends {}> {
|
|
8
|
+
readonly derive: <T>(
|
|
9
|
+
selector: (props: Props extends Kiru.FC<infer P> ? P : Props) => T
|
|
10
|
+
) => Signal<T>
|
|
11
|
+
readonly id: Signal<string>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Creates a per‑VNode setup context that can be used during
|
|
16
|
+
* component setup to derive props into signals.
|
|
17
|
+
*
|
|
18
|
+
* @see https://kirujs.dev/docs/api/lifecycles#setup
|
|
19
|
+
*/
|
|
20
|
+
export function setup<Props extends {}>(): Setup<Props> {
|
|
21
|
+
const vNode = node.current!
|
|
22
|
+
if (__DEV__) {
|
|
23
|
+
if (!vNode) {
|
|
24
|
+
throw new Error("setup() must be called inside a Kiru component")
|
|
25
|
+
}
|
|
26
|
+
if (vNode.render) {
|
|
27
|
+
throw new Error("setup() cannot be used inside a render function")
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (setups.has(vNode)) {
|
|
32
|
+
return setups.get(vNode)!
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const setup = createSetup<Props>(vNode)
|
|
36
|
+
setups.set(vNode, setup)
|
|
37
|
+
return setup
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function createSetup<Props extends {}>(vNode: Kiru.VNode): Setup<Props> {
|
|
41
|
+
let id: Signal<string>
|
|
42
|
+
|
|
43
|
+
type InferredProps = Props extends Kiru.FC<infer R> ? R : Props
|
|
44
|
+
const propSyncs = (vNode.propSyncs = []) as ((props: InferredProps) => void)[]
|
|
45
|
+
|
|
46
|
+
let prevIndex = -1
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
derive(selector) {
|
|
50
|
+
const props = { ...vNode.props } as InferredProps
|
|
51
|
+
const sig = signal(selector(props))
|
|
52
|
+
propSyncs.push((p) => (sig.value = selector(p)))
|
|
53
|
+
return sig
|
|
54
|
+
},
|
|
55
|
+
get id() {
|
|
56
|
+
if (!id) {
|
|
57
|
+
id = signal(createVNodeId(vNode))
|
|
58
|
+
prevIndex = vNode.index
|
|
59
|
+
propSyncs.push(() => {
|
|
60
|
+
if (prevIndex !== vNode.index) {
|
|
61
|
+
id.value = createVNodeId(vNode)
|
|
62
|
+
prevIndex = vNode.index
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return id
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
}
|
package/src/hooks/utils.ts
CHANGED
|
@@ -1,32 +1,27 @@
|
|
|
1
1
|
import { node } from "../globals.js"
|
|
2
|
-
import { sideEffectsEnabled } from "../utils/index.js"
|
|
3
2
|
|
|
4
|
-
export function
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
): void {
|
|
8
|
-
if (!sideEffectsEnabled()) return
|
|
3
|
+
export function getVNodeLifecycleHooks(): null | NonNullable<
|
|
4
|
+
Kiru.VNode["hooks"]
|
|
5
|
+
> {
|
|
9
6
|
const vNode = node.current!
|
|
10
|
-
if (!vNode)
|
|
11
|
-
throw new Error("Cannot queue setup effect outside of a component")
|
|
7
|
+
if (!vNode) return null
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
return (vNode.hooks ??= {
|
|
14
10
|
pre: [],
|
|
15
11
|
preCleanups: [],
|
|
16
12
|
post: [],
|
|
17
13
|
postCleanups: [],
|
|
18
14
|
})
|
|
15
|
+
}
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
if (typeof
|
|
27
|
-
cleanups.push(
|
|
17
|
+
export function wrapLifecycleHookCallback(
|
|
18
|
+
callback: Kiru.LifecycleHookCallback,
|
|
19
|
+
cleanups: (() => void)[]
|
|
20
|
+
): Kiru.LifecycleHookCallback {
|
|
21
|
+
return () => {
|
|
22
|
+
const cleanup = callback()
|
|
23
|
+
if (typeof cleanup === "function") {
|
|
24
|
+
cleanups.push(cleanup)
|
|
28
25
|
}
|
|
29
26
|
}
|
|
30
|
-
|
|
31
|
-
bag.push(wrapped)
|
|
32
27
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createKiruGlobalContext } from "./globalContext.js"
|
|
2
|
+
import { isBrowser } from "./env.js"
|
|
2
3
|
|
|
3
4
|
export type * from "./types"
|
|
4
5
|
export * from "./signals/index.js"
|
|
@@ -10,6 +11,7 @@ export * from "./customEvents.js"
|
|
|
10
11
|
export * from "./devtools.js"
|
|
11
12
|
export * from "./element.js"
|
|
12
13
|
export * from "./error.js"
|
|
14
|
+
export { onHmr } from "./hmr.js"
|
|
13
15
|
export * from "./hooks/index.js"
|
|
14
16
|
export type { ProfilingEvent, AppStats } from "./profiling.js"
|
|
15
17
|
export * from "./renderToString.js"
|
|
@@ -23,6 +25,6 @@ export {
|
|
|
23
25
|
export * from "./statefulPromise.js"
|
|
24
26
|
export * from "./viewTransitions.js"
|
|
25
27
|
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
+
if (isBrowser) {
|
|
29
|
+
window.__kiru ??= createKiruGlobalContext()
|
|
28
30
|
}
|
package/src/reconciler.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
propsChanged,
|
|
8
8
|
} from "./utils/index.js"
|
|
9
9
|
import { Signal } from "./signals/base.js"
|
|
10
|
-
import { __DEV__ } from "./env.js"
|
|
10
|
+
import { __DEV__, isBrowser } from "./env.js"
|
|
11
11
|
import type { AppHandle } from "./appHandle.js"
|
|
12
12
|
import { createVNode as createBaseVNode } from "./vNode.js"
|
|
13
13
|
|
|
@@ -376,7 +376,7 @@ function updateFromMap(
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
function dev_emitUpdateNode() {
|
|
379
|
-
if (!
|
|
379
|
+
if (!isBrowser) return
|
|
380
380
|
window.__kiru.profilingContext?.emit("updateNode", app)
|
|
381
381
|
}
|
|
382
382
|
|
|
@@ -479,7 +479,7 @@ function createVNode(
|
|
|
479
479
|
const node = createBaseVNode(type, parent, props, key, index)
|
|
480
480
|
node.flags |= FLAG_PLACEMENT
|
|
481
481
|
|
|
482
|
-
if (__DEV__ &&
|
|
482
|
+
if (__DEV__ && isBrowser) {
|
|
483
483
|
window.__kiru.profilingContext?.emit("createNode", app)
|
|
484
484
|
}
|
|
485
485
|
return node
|
package/src/router/head.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Signal } from "../signals/base.js"
|
|
2
2
|
import { isValidTextChild, isVNode } from "../utils/index.js"
|
|
3
3
|
import { createElement } from "../element.js"
|
|
4
|
-
import { __DEV__ } from "../env.js"
|
|
4
|
+
import { __DEV__, isBrowser } from "../env.js"
|
|
5
5
|
import { KiruError } from "../error.js"
|
|
6
6
|
import { node } from "../globals.js"
|
|
7
7
|
|
|
@@ -28,7 +28,7 @@ function HeadContent({ children }: { children: JSX.Children }): JSX.Element {
|
|
|
28
28
|
})
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
if (
|
|
31
|
+
if (isBrowser) {
|
|
32
32
|
const asArray = Array.isArray(children) ? children : [children]
|
|
33
33
|
const titleNode = asArray.find(
|
|
34
34
|
(c) => isVNode(c) && c.type === "title"
|
package/src/router/pageConfig.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { __DEV__ } from "../env.js"
|
|
1
|
+
import { __DEV__, isBrowser } from "../env.js"
|
|
2
2
|
import { fileRouterInstance } from "./globals.js"
|
|
3
3
|
import type { PageConfig } from "./types"
|
|
4
4
|
|
|
5
5
|
export function definePageConfig<T>(config: PageConfig<T>): PageConfig<T> {
|
|
6
|
-
if (__DEV__ &&
|
|
6
|
+
if (__DEV__ && isBrowser) {
|
|
7
7
|
const filePath = window.__kiru?.HMRContext?.getCurrentFilePath()
|
|
8
8
|
const fileRouter = fileRouterInstance.current
|
|
9
9
|
if (filePath && fileRouter) {
|