kiru 0.44.4

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.
Files changed (70) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +5 -0
  3. package/package.json +81 -0
  4. package/src/appContext.ts +186 -0
  5. package/src/cloneVNode.ts +14 -0
  6. package/src/constants.ts +146 -0
  7. package/src/context.ts +56 -0
  8. package/src/dom.ts +712 -0
  9. package/src/element.ts +54 -0
  10. package/src/env.ts +6 -0
  11. package/src/error.ts +85 -0
  12. package/src/flags.ts +15 -0
  13. package/src/form/index.ts +662 -0
  14. package/src/form/types.ts +261 -0
  15. package/src/form/utils.ts +19 -0
  16. package/src/generateId.ts +19 -0
  17. package/src/globalContext.ts +161 -0
  18. package/src/globals.ts +21 -0
  19. package/src/hmr.ts +178 -0
  20. package/src/hooks/index.ts +14 -0
  21. package/src/hooks/useAsync.ts +136 -0
  22. package/src/hooks/useCallback.ts +31 -0
  23. package/src/hooks/useContext.ts +79 -0
  24. package/src/hooks/useEffect.ts +44 -0
  25. package/src/hooks/useEffectEvent.ts +24 -0
  26. package/src/hooks/useId.ts +42 -0
  27. package/src/hooks/useLayoutEffect.ts +47 -0
  28. package/src/hooks/useMemo.ts +33 -0
  29. package/src/hooks/useReducer.ts +50 -0
  30. package/src/hooks/useRef.ts +40 -0
  31. package/src/hooks/useState.ts +62 -0
  32. package/src/hooks/useSyncExternalStore.ts +59 -0
  33. package/src/hooks/useViewTransition.ts +26 -0
  34. package/src/hooks/utils.ts +259 -0
  35. package/src/hydration.ts +67 -0
  36. package/src/index.ts +61 -0
  37. package/src/jsx.ts +11 -0
  38. package/src/lazy.ts +238 -0
  39. package/src/memo.ts +48 -0
  40. package/src/portal.ts +43 -0
  41. package/src/profiling.ts +105 -0
  42. package/src/props.ts +36 -0
  43. package/src/reconciler.ts +531 -0
  44. package/src/renderToString.ts +91 -0
  45. package/src/router/index.ts +2 -0
  46. package/src/router/route.ts +51 -0
  47. package/src/router/router.ts +275 -0
  48. package/src/router/routerUtils.ts +49 -0
  49. package/src/scheduler.ts +522 -0
  50. package/src/signals/base.ts +237 -0
  51. package/src/signals/computed.ts +139 -0
  52. package/src/signals/effect.ts +60 -0
  53. package/src/signals/globals.ts +11 -0
  54. package/src/signals/index.ts +12 -0
  55. package/src/signals/jsx.ts +45 -0
  56. package/src/signals/types.ts +10 -0
  57. package/src/signals/utils.ts +12 -0
  58. package/src/signals/watch.ts +151 -0
  59. package/src/ssr/client.ts +29 -0
  60. package/src/ssr/hydrationBoundary.ts +63 -0
  61. package/src/ssr/index.ts +1 -0
  62. package/src/ssr/server.ts +124 -0
  63. package/src/store.ts +241 -0
  64. package/src/swr.ts +360 -0
  65. package/src/transition.ts +80 -0
  66. package/src/types.dom.ts +1250 -0
  67. package/src/types.ts +209 -0
  68. package/src/types.utils.ts +39 -0
  69. package/src/utils.ts +581 -0
  70. package/src/warning.ts +9 -0
@@ -0,0 +1,261 @@
1
+ type ObjectValuesArray<T extends object> = T[keyof T][]
2
+
3
+ type IsObject<T> = T extends object ? (T extends any[] ? false : true) : false
4
+
5
+ type InferKeyWithIndices<T, Prefix extends string = ""> = {
6
+ [K in keyof T & string]: T[K] extends Array<infer U> | undefined
7
+ ? IsObject<U> extends true
8
+ ? // If it's an array of objects, infer the index and recurse into the object properties
9
+ | `${Prefix}${K}`
10
+ | `${Prefix}${K}.${number}`
11
+ | InferKeyWithIndices<U, `${Prefix}${K}.${number}.`>
12
+ : `${Prefix}${K}` | `${Prefix}${K}.${number}` // For arrays of primitives, only support indices
13
+ : IsObject<T[K]> extends true
14
+ ? // If it's an object, recurse into its properties
15
+ `${Prefix}${K}` | InferKeyWithIndices<T[K], `${Prefix}${K}.`>
16
+ : `${Prefix}${K}` // If it's a primitive, return the key
17
+ }[keyof T & string]
18
+
19
+ export type RecordKey<T extends Record<string, unknown>> =
20
+ InferKeyWithIndices<T>
21
+
22
+ type InferValue<
23
+ T,
24
+ Path extends string
25
+ > = Path extends `${infer K}.${infer Rest}`
26
+ ? K extends keyof T
27
+ ? InferValue<T[K], Rest> // Recursively resolve objects
28
+ : K extends `${number}` // Check if it's a numeric index for an array
29
+ ? T extends Array<infer U> | undefined
30
+ ? InferValue<U, Rest> // Recursively resolve array elements
31
+ : never
32
+ : never
33
+ : Path extends keyof T
34
+ ? T[Path] // Direct lookup for simple keys
35
+ : Path extends `${number}` // If the path is numeric (array index)
36
+ ? T extends Array<infer U> | undefined
37
+ ? U // Resolve the array element type
38
+ : never
39
+ : never
40
+
41
+ export type InferRecordKeyValue<
42
+ T extends Record<string, unknown>,
43
+ K extends RecordKey<T>
44
+ > = InferValue<T, K>
45
+
46
+ export type ValidatorContext<T> = {
47
+ value: T
48
+ }
49
+
50
+ type FormFieldValidator<T extends unknown> = (
51
+ context: ValidatorContext<T>
52
+ ) => any
53
+
54
+ export type AsyncValidatorContext<T> = {
55
+ value: T
56
+ abortSignal: AbortSignal
57
+ }
58
+
59
+ type AsyncFormFieldValidator<T extends unknown> = (
60
+ context: AsyncValidatorContext<T>
61
+ ) => Promise<any>
62
+
63
+ export type FormFieldValidators<RecordKey extends string, Value> = {
64
+ dependentOn: RecordKey[]
65
+ onBlur: FormFieldValidator<Value>
66
+ onChange: FormFieldValidator<Value>
67
+ onChangeAsyncDebounceMs: number
68
+ onChangeAsync: AsyncFormFieldValidator<Value>
69
+ onMount: FormFieldValidator<Value>
70
+ onSubmit: FormFieldValidator<Value>
71
+ }
72
+
73
+ type Falsy = false | null | undefined
74
+
75
+ type InferValidatorReturn<T> = T extends Falsy
76
+ ? never
77
+ : T extends Promise<infer U>
78
+ ? InferValidatorReturn<U>
79
+ : T
80
+
81
+ type InferFormFieldErrors<
82
+ RecordKey extends string,
83
+ T extends FormFieldValidators<RecordKey, any>
84
+ > = ObjectValuesArray<{
85
+ [K in keyof T]: T[K] extends FormFieldValidator<any>
86
+ ? InferValidatorReturn<ReturnType<T[K]>>
87
+ : never
88
+ }>
89
+
90
+ export type FormFieldContext<
91
+ T extends Record<string, unknown>,
92
+ Name extends RecordKey<T>,
93
+ Validators extends FormFieldValidators<
94
+ RecordKey<T>,
95
+ InferRecordKeyValue<T, Name>
96
+ >,
97
+ IsArray extends Boolean
98
+ > = {
99
+ name: Name
100
+ state: {
101
+ value: InferRecordKeyValue<T, Name>
102
+ errors: InferFormFieldErrors<RecordKey<T>, Validators>
103
+ isTouched: boolean
104
+ isValidating: boolean
105
+ }
106
+ handleChange: (value: InferRecordKeyValue<T, Name>) => void
107
+ handleBlur: () => void
108
+ } & (IsArray extends true
109
+ ? {
110
+ items: {
111
+ replace: (
112
+ index: number,
113
+ value: InferRecordKeyValue<T, Name> extends Array<infer U> ? U : any
114
+ ) => void
115
+ push: (
116
+ value: InferRecordKeyValue<T, Name> extends Array<infer U> ? U : any
117
+ ) => void
118
+ remove: (index: number) => void
119
+ }
120
+ }
121
+ : {})
122
+
123
+ export type AnyFormFieldContext<
124
+ T extends Record<string, any> = Record<string, any>
125
+ > = FormFieldContext<T, any, any, any>
126
+
127
+ export type FormFieldState<
128
+ T extends Record<string, any>,
129
+ K extends RecordKey<T>
130
+ > = {
131
+ value: InferRecordKeyValue<T, K>
132
+ errors: InferFormFieldErrors<
133
+ K,
134
+ FormFieldValidators<K, InferRecordKeyValue<T, K>>
135
+ >
136
+ isTouched: boolean
137
+ isValidating: boolean
138
+ }
139
+
140
+ export type FormFieldProps<
141
+ T extends Record<string, unknown>,
142
+ Name extends RecordKey<T>,
143
+ Validators extends FormFieldValidators<
144
+ RecordKey<T>,
145
+ InferRecordKeyValue<T, Name>
146
+ >,
147
+ IsArray extends boolean
148
+ > = {
149
+ name: Name
150
+ validators?: Partial<Validators>
151
+
152
+ array?: IsArray
153
+ children: (
154
+ context: FormFieldContext<T, Name, Validators, IsArray>
155
+ ) => JSX.Element
156
+ }
157
+
158
+ export type FormFieldComponent<T extends Record<string, unknown>> = <
159
+ Name extends RecordKey<T>,
160
+ Validators extends FormFieldValidators<
161
+ RecordKey<T>,
162
+ InferRecordKeyValue<T, Name>
163
+ >,
164
+ IsArray extends boolean
165
+ >(
166
+ props: FormFieldProps<T, Name, Validators, IsArray>
167
+ ) => JSX.Element
168
+
169
+ export type SelectorState<T extends Record<string, unknown>> = {
170
+ values: T
171
+ canSubmit: boolean
172
+ isSubmitting: boolean
173
+ }
174
+
175
+ export type FormSubscribeProps<
176
+ T extends Record<string, unknown>,
177
+ SelectorFunction extends (state: SelectorState<T>) => unknown,
178
+ U
179
+ > = {
180
+ selector: SelectorFunction
181
+ children: (selection: U) => JSX.Element
182
+ }
183
+
184
+ type FormSubscribeComponent<T extends Record<string, unknown>> = <
185
+ Selector extends (state: SelectorState<T>) => unknown
186
+ >(
187
+ props: FormSubscribeProps<T, Selector, ReturnType<Selector>>
188
+ ) => JSX.Element
189
+
190
+ export type UseFormState<T extends Record<string, unknown>> = {
191
+ Field: FormFieldComponent<T>
192
+ Subscribe: FormSubscribeComponent<T>
193
+ getFieldState: <K extends RecordKey<T>>(name: K) => FormFieldState<T, K>
194
+ handleSubmit: () => Promise<void>
195
+ reset: () => void
196
+ }
197
+
198
+ export type FormContext<T extends Record<string, unknown>> = {
199
+ state: T
200
+ validateForm: () => Promise<any[]>
201
+ resetField: (name: RecordKey<T>) => void
202
+ deleteField: (name: RecordKey<T>) => void
203
+ setFieldValue: <K extends RecordKey<T>>(
204
+ name: K,
205
+ value: InferRecordKeyValue<T, K>
206
+ ) => void
207
+ }
208
+
209
+ export type UseFormConfig<T extends Record<string, unknown>> = {
210
+ initialValues?: T
211
+ onSubmit?: (ctx: FormContext<T>) => void | Promise<void>
212
+ onSubmitInvalid?: (ctx: FormContext<T>) => void | Promise<void>
213
+ }
214
+
215
+ export interface FormStateSubscriber<T extends Record<string, unknown>> {
216
+ selector: (state: SelectorState<T>) => unknown
217
+ selection: ReturnType<this["selector"]>
218
+ update: () => void
219
+ }
220
+
221
+ export type UseFormInternalState<T extends Record<string, unknown>> = {
222
+ Field: FormFieldComponent<T>
223
+ Subscribe: FormSubscribeComponent<T>
224
+ formController: FormController<T>
225
+ }
226
+
227
+ export type FormController<T extends Record<string, unknown>> = {
228
+ subscribers: Set<FormStateSubscriber<T>>
229
+ state: T
230
+ validateField: (
231
+ name: RecordKey<T>,
232
+ type: "onChange" | "onSubmit" | "onMount" | "onBlur"
233
+ ) => Promise<void>
234
+ getFieldState: <K extends RecordKey<T>>(name: K) => FormFieldState<T, K>
235
+ setFieldValue: (
236
+ name: RecordKey<T>,
237
+ value: InferRecordKeyValue<T, RecordKey<T>>
238
+ ) => void
239
+ arrayFieldReplace: <K extends RecordKey<T>>(
240
+ name: K,
241
+ index: number,
242
+ value: InferRecordKeyValue<T, K> extends Array<infer U> ? U : any
243
+ ) => void
244
+ arrayFieldPush: <K extends RecordKey<T>>(
245
+ name: K,
246
+ value: InferRecordKeyValue<T, K> extends Array<infer U> ? U : any
247
+ ) => void
248
+ arrayFieldRemove: (name: RecordKey<T>, index: number) => void
249
+ connectField: (name: RecordKey<T>, update: () => void) => void
250
+ disconnectField: (name: RecordKey<T>, update: () => void) => void
251
+ setFieldValidators: <K extends RecordKey<T>>(
252
+ name: K,
253
+ validators: Partial<
254
+ FormFieldValidators<RecordKey<T>, InferRecordKeyValue<T, K>>
255
+ >
256
+ ) => void
257
+ getSelectorState: () => any
258
+ validateForm: () => Promise<string[]>
259
+ getFormContext: () => FormContext<T>
260
+ reset: (values?: T) => void
261
+ }
@@ -0,0 +1,19 @@
1
+ export const objSet = (
2
+ obj: Record<string, any>,
3
+ path: string[],
4
+ value: any
5
+ ) => {
6
+ let o = obj
7
+ for (let i = 0; i < path.length; i++) {
8
+ const key = path[i]
9
+ if (i === path.length - 1) {
10
+ o[key] = value
11
+ } else {
12
+ o = o[key]
13
+ }
14
+ }
15
+ }
16
+
17
+ export const objGet = <T>(obj: Record<string, any>, path: string[]): T => {
18
+ return path.reduce((o, key) => o[key], obj) as T
19
+ }
@@ -0,0 +1,19 @@
1
+ const DEFAULT_CHARACTERS =
2
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz-" as const
3
+
4
+ /**
5
+ * Generates a random id
6
+ * @param {number} [size=10] size of the id (in number of characters)
7
+ * @param {string} [characterSet=defaultCharacterSet] set of characters to be used in the generation of the id
8
+ * @returns {string} random id of length {@link size}
9
+ */
10
+ export function generateRandomID(
11
+ size: number = 10,
12
+ characterSet: string = DEFAULT_CHARACTERS
13
+ ): string {
14
+ let id = ""
15
+ for (let i = 0; i < size; i++) {
16
+ id += characterSet[(Math.random() * characterSet.length) | 0] // bitwise OR `|` is faster than `Math.floor()`
17
+ }
18
+ return id
19
+ }
@@ -0,0 +1,161 @@
1
+ import type { AppContext } from "./appContext"
2
+ import { __DEV__ } from "./env.js"
3
+ import { createHMRContext } from "./hmr.js"
4
+ import { createProfilingContext } from "./profiling.js"
5
+ import { Store } from "./store"
6
+
7
+ export {
8
+ createKaiokenGlobalContext,
9
+ type GlobalKaiokenEvent,
10
+ type KaiokenGlobalContext,
11
+ }
12
+
13
+ interface ReactiveMap<V> {
14
+ add(key: string, value: V): void
15
+ delete(key: string): void
16
+ subscribe(cb: (value: Record<string, V>) => void): () => void
17
+ readonly size: number
18
+ }
19
+
20
+ function createReactiveMap<V>(): ReactiveMap<V> {
21
+ const map = new Map<string, V>()
22
+ const listeners = new Set<(value: Record<string, V>) => void>()
23
+
24
+ function add(key: string, value: V): void {
25
+ if (map.has(key)) return
26
+ map.set(key, value)
27
+ notify()
28
+ }
29
+
30
+ function deleteKey(key: string): void {
31
+ if (!map.has(key)) return
32
+ map.delete(key)
33
+ notify()
34
+ }
35
+
36
+ function notify(): void {
37
+ const val = Object.fromEntries(map)
38
+ listeners.forEach((cb) => cb(val))
39
+ }
40
+
41
+ function subscribe(cb: (value: Record<string, V>) => void): () => void {
42
+ listeners.add(cb)
43
+ cb(Object.fromEntries(map))
44
+ return () => listeners.delete(cb)
45
+ }
46
+
47
+ return {
48
+ add,
49
+ delete: deleteKey,
50
+ subscribe,
51
+ get size() {
52
+ return map.size
53
+ },
54
+ }
55
+ }
56
+
57
+ type Evt =
58
+ | {
59
+ name: "mount"
60
+ data?: undefined
61
+ }
62
+ | {
63
+ name: "unmount"
64
+ data?: undefined
65
+ }
66
+ | {
67
+ name: "update"
68
+ data?: undefined
69
+ }
70
+ | {
71
+ name: "error"
72
+ data: Error
73
+ }
74
+
75
+ type GlobalKaiokenEvent = Evt["name"]
76
+
77
+ interface KaiokenGlobalContext {
78
+ readonly apps: AppContext[]
79
+ stores?: ReactiveMap<Store<any, any>>
80
+ HMRContext?: ReturnType<typeof createHMRContext>
81
+ profilingContext?: ReturnType<typeof createProfilingContext>
82
+ globalState: Record<symbol, any>
83
+ emit<T extends Evt>(event: T["name"], ctx: AppContext, data?: T["data"]): void
84
+ on<T extends Evt>(
85
+ event: T["name"],
86
+ callback: (ctx: AppContext, data: T["data"]) => void
87
+ ): void
88
+ off<T extends Evt>(
89
+ event: T["name"],
90
+ callback: (ctx: AppContext, data?: T["data"]) => void
91
+ ): void
92
+ }
93
+
94
+ function createKaiokenGlobalContext(): KaiokenGlobalContext {
95
+ const contexts = new Set<AppContext>()
96
+ const listeners = new Map<
97
+ GlobalKaiokenEvent,
98
+ Set<(ctx: AppContext, data?: Evt["data"]) => void>
99
+ >()
100
+ const globalState: Record<symbol, any> = {}
101
+
102
+ let stores: ReactiveMap<Store<any, any>> | undefined
103
+ let HMRContext: ReturnType<typeof createHMRContext> | undefined
104
+ let profilingContext: ReturnType<typeof createProfilingContext> | undefined
105
+
106
+ function emit<T extends Evt>(
107
+ event: T["name"],
108
+ ctx: AppContext,
109
+ data?: T["data"]
110
+ ): void {
111
+ listeners.get(event)?.forEach((cb) => cb(ctx, data))
112
+ }
113
+
114
+ function on<T extends Evt>(
115
+ event: T["name"],
116
+ callback: (ctx: AppContext, data: T["data"]) => void
117
+ ): void {
118
+ if (!listeners.has(event)) {
119
+ listeners.set(event, new Set())
120
+ }
121
+ listeners.get(event)!.add(callback)
122
+ }
123
+
124
+ function off<T extends Evt>(
125
+ event: T["name"],
126
+ callback: (ctx: AppContext, data?: T["data"]) => void
127
+ ): void {
128
+ listeners.get(event)?.delete(callback)
129
+ }
130
+
131
+ const globalContext: KaiokenGlobalContext = {
132
+ get apps() {
133
+ return Array.from(contexts)
134
+ },
135
+ get stores() {
136
+ return stores
137
+ },
138
+ get HMRContext() {
139
+ return HMRContext
140
+ },
141
+ get profilingContext() {
142
+ return profilingContext
143
+ },
144
+ globalState,
145
+ emit,
146
+ on,
147
+ off,
148
+ }
149
+
150
+ // Initialize event listeners
151
+ on("mount", (ctx) => contexts.add(ctx))
152
+ on("unmount", (ctx) => contexts.delete(ctx))
153
+
154
+ if (__DEV__) {
155
+ HMRContext = createHMRContext()
156
+ profilingContext = createProfilingContext()
157
+ stores = createReactiveMap()
158
+ }
159
+
160
+ return globalContext
161
+ }
package/src/globals.ts ADDED
@@ -0,0 +1,21 @@
1
+ import type { AppContext } from "./appContext"
2
+
3
+ export { node, hookIndex, ctx, renderMode, nodeToCtxMap }
4
+
5
+ const node = {
6
+ current: null as Kaioken.VNode | null,
7
+ }
8
+
9
+ const hookIndex = {
10
+ current: 0,
11
+ }
12
+
13
+ const ctx = {
14
+ current: null! as AppContext<any>,
15
+ }
16
+
17
+ const renderMode = {
18
+ current: ("window" in globalThis ? "dom" : "string") as Kaioken.RenderMode,
19
+ }
20
+
21
+ const nodeToCtxMap = new WeakMap<Kaioken.VNode, AppContext<any>>()
package/src/hmr.ts ADDED
@@ -0,0 +1,178 @@
1
+ import type { Store } from "./store"
2
+ import type { WatchEffect } from "./signals/watch"
3
+ import { $HMR_ACCEPT } from "./constants.js"
4
+ import { __DEV__ } from "./env.js"
5
+ import { Signal } from "./signals/base.js"
6
+ import { traverseApply } from "./utils.js"
7
+ import type { AppContext } from "./appContext"
8
+
9
+ export type HMRAccept<T = {}> = {
10
+ provide: () => T
11
+ inject: (prev: T) => void
12
+ destroy: () => void
13
+ }
14
+
15
+ export type GenericHMRAcceptor<T = {}> = {
16
+ [$HMR_ACCEPT]: HMRAccept<T>
17
+ }
18
+ type HotVar = Kaioken.FC | Store<any, any> | Signal<any> | Kaioken.Context<any>
19
+
20
+ type HotVarDesc = {
21
+ type: string
22
+ value: HotVar
23
+ hooks?: Array<{ name: string; args: string }>
24
+ link: string
25
+ }
26
+
27
+ export function isGenericHmrAcceptor(
28
+ thing: unknown
29
+ ): thing is GenericHMRAcceptor<any> {
30
+ return (
31
+ !!thing &&
32
+ (typeof thing === "object" || typeof thing === "function") &&
33
+ $HMR_ACCEPT in thing &&
34
+ typeof thing[$HMR_ACCEPT] === "object" &&
35
+ !!thing[$HMR_ACCEPT]
36
+ )
37
+ }
38
+
39
+ type ModuleMemory = {
40
+ hotVars: Map<string, HotVarDesc>
41
+ unnamedWatchers: Array<WatchEffect>
42
+ }
43
+
44
+ type HotVarRegistrationEntry = {
45
+ type: string
46
+ value: HotVar
47
+ link: string
48
+ }
49
+
50
+ export function createHMRContext() {
51
+ type FilePath = string
52
+ const moduleMap = new Map<FilePath, ModuleMemory>()
53
+ let currentModuleMemory: ModuleMemory | null = null
54
+ let isModuleReplacementExecution = false
55
+ const isReplacement = () => isModuleReplacementExecution
56
+ let isWaitingForNextWatchCall = false
57
+ let tmpUnnamedWatchers: WatchEffect[] = []
58
+
59
+ const onHmrCallbacks: Array<() => void> = []
60
+ const onHmr = (callback: () => void) => {
61
+ onHmrCallbacks.push(callback)
62
+ }
63
+
64
+ const prepare = (filePath: string) => {
65
+ let mod = moduleMap.get(filePath)
66
+ isModuleReplacementExecution = !!mod
67
+ if (!mod) {
68
+ mod = {
69
+ hotVars: new Map(),
70
+ unnamedWatchers: [],
71
+ }
72
+ moduleMap.set(filePath, mod)
73
+ } else {
74
+ while (onHmrCallbacks.length) onHmrCallbacks.shift()!()
75
+ }
76
+ currentModuleMemory = mod!
77
+ }
78
+
79
+ const register = (
80
+ hotVarRegistrationEntries: Record<string, HotVarRegistrationEntry>
81
+ ) => {
82
+ if (currentModuleMemory === null)
83
+ throw new Error("[kaioken]: HMR could not register: No active module")
84
+
85
+ let dirtiedApps: Set<AppContext> = new Set()
86
+ for (const [name, newEntry] of Object.entries(hotVarRegistrationEntries)) {
87
+ const oldEntry = currentModuleMemory.hotVars.get(name)
88
+
89
+ // @ts-ignore - this is how we tell devtools what file the hotvar is from
90
+ newEntry.value.__devtoolsFileLink = newEntry.link
91
+
92
+ if (typeof newEntry.value === "function") {
93
+ if (oldEntry?.value) {
94
+ /**
95
+ * this is how, when the previous function has been stored somewhere else (eg. in a Map, or by Vike),
96
+ * we can trace it to its latest version
97
+ */
98
+ // @ts-ignore
99
+ oldEntry.value.__next = newEntry.value
100
+ }
101
+ }
102
+
103
+ if (newEntry.type === "createStore") {
104
+ window.__kaioken!.stores!.add(name, newEntry.value as Store<any, any>)
105
+ }
106
+
107
+ currentModuleMemory.hotVars.set(name, newEntry)
108
+ if (!oldEntry) continue
109
+ if (
110
+ isGenericHmrAcceptor(oldEntry.value) &&
111
+ isGenericHmrAcceptor(newEntry.value)
112
+ ) {
113
+ newEntry.value[$HMR_ACCEPT].inject(
114
+ oldEntry.value[$HMR_ACCEPT].provide()
115
+ )
116
+ oldEntry.value[$HMR_ACCEPT].destroy()
117
+ continue
118
+ }
119
+ if (oldEntry.type === "component" && newEntry.type === "component") {
120
+ window.__kaioken!.apps.forEach((ctx) => {
121
+ if (!ctx.mounted || !ctx.rootNode) return
122
+ traverseApply(ctx.rootNode, (vNode) => {
123
+ if (vNode.type === oldEntry.value) {
124
+ vNode.type = newEntry.value as any
125
+ dirtiedApps.add(ctx)
126
+ vNode.hmrUpdated = true
127
+ if (vNode.prev) {
128
+ vNode.prev.type = newEntry.value as any
129
+ }
130
+ }
131
+ })
132
+ })
133
+ }
134
+ }
135
+ dirtiedApps.forEach((ctx) => ctx.requestUpdate())
136
+ isModuleReplacementExecution = false
137
+
138
+ if (tmpUnnamedWatchers.length) {
139
+ let i = 0
140
+ for (; i < tmpUnnamedWatchers.length; i++) {
141
+ const newWatcher = tmpUnnamedWatchers[i]
142
+ const oldWatcher = currentModuleMemory.unnamedWatchers[i]
143
+ if (oldWatcher) {
144
+ newWatcher[$HMR_ACCEPT]!.inject(oldWatcher[$HMR_ACCEPT]!.provide())
145
+ oldWatcher[$HMR_ACCEPT]!.destroy()
146
+ }
147
+ currentModuleMemory.unnamedWatchers[i] = newWatcher
148
+ }
149
+ for (; i < currentModuleMemory.unnamedWatchers.length; i++) {
150
+ const oldWatcher = currentModuleMemory.unnamedWatchers[i]
151
+ oldWatcher[$HMR_ACCEPT]!.destroy()
152
+ }
153
+ currentModuleMemory.unnamedWatchers.length = tmpUnnamedWatchers.length
154
+ tmpUnnamedWatchers.length = 0
155
+ }
156
+ }
157
+
158
+ const signals = {
159
+ registerNextWatch() {
160
+ isWaitingForNextWatchCall = true
161
+ },
162
+ isWaitingForNextWatchCall() {
163
+ return isWaitingForNextWatchCall
164
+ },
165
+ pushWatch(watch: WatchEffect) {
166
+ tmpUnnamedWatchers.push(watch)
167
+ isWaitingForNextWatchCall = false
168
+ },
169
+ }
170
+
171
+ return {
172
+ register,
173
+ prepare,
174
+ isReplacement,
175
+ signals,
176
+ onHmr,
177
+ }
178
+ }
@@ -0,0 +1,14 @@
1
+ export * from "./useAsync.js"
2
+ export * from "./useCallback.js"
3
+ export * from "./useContext.js"
4
+ export * from "./useEffect.js"
5
+ export * from "./useEffectEvent.js"
6
+ export * from "./useId.js"
7
+ export * from "./useLayoutEffect.js"
8
+ export * from "./useMemo.js"
9
+ export * from "./useReducer.js"
10
+ export * from "./useRef.js"
11
+ export * from "./useState.js"
12
+ export * from "./useSyncExternalStore.js"
13
+ export * from "./useViewTransition.js"
14
+ export * from "./utils.js"