kiru 0.46.1 → 0.47.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.
Files changed (105) hide show
  1. package/dist/appContext.d.ts +6 -17
  2. package/dist/appContext.d.ts.map +1 -1
  3. package/dist/appContext.js +39 -95
  4. package/dist/appContext.js.map +1 -1
  5. package/dist/constants.d.ts +3 -1
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/constants.js +3 -1
  8. package/dist/constants.js.map +1 -1
  9. package/dist/context.d.ts.map +1 -1
  10. package/dist/context.js +0 -2
  11. package/dist/context.js.map +1 -1
  12. package/dist/dom.d.ts.map +1 -1
  13. package/dist/dom.js +12 -14
  14. package/dist/dom.js.map +1 -1
  15. package/dist/element.js +2 -2
  16. package/dist/element.js.map +1 -1
  17. package/dist/hmr.d.ts +3 -3
  18. package/dist/hmr.d.ts.map +1 -1
  19. package/dist/hmr.js +0 -2
  20. package/dist/hmr.js.map +1 -1
  21. package/dist/index.d.ts +1 -4
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -21
  24. package/dist/index.js.map +1 -1
  25. package/dist/memo.d.ts.map +1 -1
  26. package/dist/memo.js +1 -3
  27. package/dist/memo.js.map +1 -1
  28. package/dist/portal.d.ts +2 -5
  29. package/dist/portal.d.ts.map +1 -1
  30. package/dist/portal.js +22 -22
  31. package/dist/portal.js.map +1 -1
  32. package/dist/profiling.d.ts +1 -1
  33. package/dist/props.js +1 -1
  34. package/dist/props.js.map +1 -1
  35. package/dist/reconciler.d.ts.map +1 -1
  36. package/dist/reconciler.js +3 -3
  37. package/dist/reconciler.js.map +1 -1
  38. package/dist/renderToString.d.ts +1 -1
  39. package/dist/renderToString.d.ts.map +1 -1
  40. package/dist/renderToString.js +4 -7
  41. package/dist/renderToString.js.map +1 -1
  42. package/dist/scheduler.d.ts +3 -3
  43. package/dist/scheduler.d.ts.map +1 -1
  44. package/dist/scheduler.js +55 -71
  45. package/dist/scheduler.js.map +1 -1
  46. package/dist/signals/base.d.ts +1 -1
  47. package/dist/signals/base.d.ts.map +1 -1
  48. package/dist/signals/base.js +2 -2
  49. package/dist/signals/base.js.map +1 -1
  50. package/dist/signals/computed.d.ts +1 -1
  51. package/dist/signals/computed.d.ts.map +1 -1
  52. package/dist/signals/computed.js +3 -3
  53. package/dist/signals/computed.js.map +1 -1
  54. package/dist/signals/effect.d.ts +1 -1
  55. package/dist/signals/effect.d.ts.map +1 -1
  56. package/dist/signals/effect.js +3 -2
  57. package/dist/signals/effect.js.map +1 -1
  58. package/dist/signals/globals.d.ts +1 -1
  59. package/dist/signals/globals.d.ts.map +1 -1
  60. package/dist/signals/jsx.d.ts +1 -1
  61. package/dist/signals/jsx.d.ts.map +1 -1
  62. package/dist/signals/types.d.ts +1 -1
  63. package/dist/signals/types.d.ts.map +1 -1
  64. package/dist/signals/utils.d.ts +1 -1
  65. package/dist/signals/utils.d.ts.map +1 -1
  66. package/dist/signals/utils.js +1 -1
  67. package/dist/signals/utils.js.map +1 -1
  68. package/dist/ssr/client.d.ts +1 -2
  69. package/dist/ssr/client.d.ts.map +1 -1
  70. package/dist/ssr/client.js +6 -4
  71. package/dist/ssr/client.js.map +1 -1
  72. package/dist/ssr/server.d.ts +1 -1
  73. package/dist/ssr/server.d.ts.map +1 -1
  74. package/dist/ssr/server.js +23 -26
  75. package/dist/ssr/server.js.map +1 -1
  76. package/dist/types.d.ts +0 -1
  77. package/dist/types.d.ts.map +1 -1
  78. package/dist/utils.d.ts.map +1 -1
  79. package/dist/utils.js +4 -2
  80. package/dist/utils.js.map +1 -1
  81. package/package.json +1 -1
  82. package/src/appContext.ts +50 -117
  83. package/src/constants.ts +4 -0
  84. package/src/context.ts +0 -1
  85. package/src/dom.ts +12 -11
  86. package/src/element.ts +2 -2
  87. package/src/hmr.ts +4 -5
  88. package/src/index.ts +1 -41
  89. package/src/memo.ts +1 -3
  90. package/src/portal.ts +22 -26
  91. package/src/props.ts +1 -1
  92. package/src/reconciler.ts +3 -2
  93. package/src/renderToString.ts +4 -10
  94. package/src/scheduler.ts +54 -72
  95. package/src/signals/base.ts +4 -4
  96. package/src/signals/computed.ts +4 -4
  97. package/src/signals/effect.ts +4 -3
  98. package/src/signals/globals.ts +1 -1
  99. package/src/signals/jsx.ts +1 -1
  100. package/src/signals/types.ts +1 -1
  101. package/src/signals/utils.ts +1 -1
  102. package/src/ssr/client.ts +13 -19
  103. package/src/ssr/server.ts +24 -34
  104. package/src/types.ts +0 -1
  105. package/src/utils.ts +3 -1
package/src/scheduler.ts CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  $CONTEXT_PROVIDER,
8
8
  CONSECUTIVE_DIRTY_LIMIT,
9
9
  FLAG_DELETION,
10
+ FLAG_MEMO,
10
11
  } from "./constants.js"
11
12
  import { commitDeletion, commitWork, createDom, hydrateDom } from "./dom.js"
12
13
  import { __DEV__ } from "./env.js"
@@ -31,7 +32,7 @@ let appCtx: AppContext | null
31
32
  let nextUnitOfWork: VNode | null = null
32
33
  let treesInProgress: VNode[] = []
33
34
  let currentTreeIndex = 0
34
- let isRunning = false
35
+ let isRunningOrQueued = false
35
36
  let nextIdleEffects: (() => void)[] = []
36
37
  let deletions: VNode[] = []
37
38
  let isImmediateEffectsMode = false
@@ -41,20 +42,27 @@ let consecutiveDirtyCount = 0
41
42
  let pendingContextChanges = new Set<ContextProviderNode<any>>()
42
43
  let preEffects: Array<Function> = []
43
44
  let postEffects: Array<Function> = []
45
+ let animationFrameHandle = -1
44
46
 
45
47
  /**
46
- * Runs a function after any existing work has been completed, or if the scheduler is already idle.
48
+ * Runs a function after any existing work has been completed,
49
+ * or immediately if the scheduler is already idle.
47
50
  */
48
- export function nextIdle(fn: () => void, wakeUpIfIdle = true) {
49
- nextIdleEffects.push(fn)
50
- if (wakeUpIfIdle) wake()
51
+ export function nextIdle(fn: () => void) {
52
+ if (isRunningOrQueued) {
53
+ nextIdleEffects.push(fn)
54
+ return
55
+ }
56
+ fn()
51
57
  }
52
58
 
53
59
  /**
54
60
  * Syncronously flushes any pending work.
55
61
  */
56
62
  export function flushSync() {
57
- workLoop()
63
+ if (!isRunningOrQueued) return
64
+ window.cancelAnimationFrame(animationFrameHandle)
65
+ doWork()
58
66
  }
59
67
 
60
68
  /**
@@ -65,33 +73,22 @@ export function requestUpdate(vNode: VNode): void {
65
73
  if (renderMode.current === "hydrate") {
66
74
  return nextIdle(() => {
67
75
  vNode.flags & FLAG_DELETION || queueUpdate(vNode)
68
- }, false)
76
+ })
69
77
  }
70
78
  queueUpdate(vNode)
71
79
  }
72
80
 
73
- export function requestDelete(vNode: VNode): void {
74
- if (vNode.flags & FLAG_DELETION) return
75
- if (renderMode.current === "hydrate") {
76
- return nextIdle(() => {
77
- vNode.flags & FLAG_DELETION || queueDelete(vNode)
78
- }, false)
79
- }
80
- queueDelete(vNode)
81
- }
82
-
83
- function queueWorkLoop() {
84
- queueMicrotask(workLoop)
85
- }
86
-
87
- function wake() {
88
- if (isRunning) return
89
- isRunning = true
90
- queueWorkLoop()
81
+ function queueBeginWork() {
82
+ if (isRunningOrQueued) return
83
+ isRunningOrQueued = true
84
+ animationFrameHandle = window.requestAnimationFrame(doWork)
91
85
  }
92
86
 
93
- function sleep() {
94
- isRunning = false
87
+ function onWorkFinished() {
88
+ isRunningOrQueued = false
89
+ while (nextIdleEffects.length) {
90
+ nextIdleEffects.shift()!()
91
+ }
95
92
  }
96
93
 
97
94
  function queueUpdate(vNode: VNode) {
@@ -117,7 +114,7 @@ function queueUpdate(vNode: VNode) {
117
114
  if (nextUnitOfWork === null) {
118
115
  treesInProgress.push(vNode)
119
116
  nextUnitOfWork = vNode
120
- return wake()
117
+ return queueBeginWork()
121
118
  }
122
119
 
123
120
  for (let i = 0; i < treesInProgress.length; i++) {
@@ -202,7 +199,7 @@ function queueDelete(vNode: VNode) {
202
199
  deletions.push(vNode)
203
200
  }
204
201
 
205
- function workLoop(): void {
202
+ function doWork(): void {
206
203
  if (__DEV__) {
207
204
  const n = nextUnitOfWork ?? deletions[0] ?? treesInProgress[0]
208
205
  if (n) {
@@ -220,55 +217,40 @@ function workLoop(): void {
220
217
  queueBlockedContextDependencyRoots()
221
218
  }
222
219
 
223
- if (!nextUnitOfWork && (deletions.length || treesInProgress.length)) {
224
- while (deletions.length) {
225
- commitDeletion(deletions.shift()!)
226
- }
227
- const workRoots = [...treesInProgress]
228
- treesInProgress.length = 0
229
- currentTreeIndex = 0
230
- for (const root of workRoots) {
231
- commitWork(root)
232
- }
233
-
234
- isImmediateEffectsMode = true
235
- flushEffects(preEffects)
236
- isImmediateEffectsMode = false
220
+ while (deletions.length) {
221
+ commitDeletion(deletions.shift()!)
222
+ }
223
+ const workRoots = [...treesInProgress]
224
+ treesInProgress.length = 0
225
+ currentTreeIndex = 0
226
+ for (const root of workRoots) {
227
+ commitWork(root)
228
+ }
237
229
 
238
- if (immediateEffectDirtiedRender) {
239
- checkForTooManyConsecutiveDirtyRenders()
240
- flushEffects(postEffects)
241
- immediateEffectDirtiedRender = false
242
- consecutiveDirtyCount++
243
- if (__DEV__) {
244
- window.__kiru?.profilingContext?.endTick(appCtx!)
245
- window.__kiru?.profilingContext?.emit("updateDirtied", appCtx!)
246
- }
247
- return flushSync()
248
- }
249
- consecutiveDirtyCount = 0
230
+ isImmediateEffectsMode = true
231
+ flushEffects(preEffects)
232
+ isImmediateEffectsMode = false
250
233
 
234
+ if (immediateEffectDirtiedRender) {
235
+ checkForTooManyConsecutiveDirtyRenders()
251
236
  flushEffects(postEffects)
237
+ immediateEffectDirtiedRender = false
238
+ consecutiveDirtyCount++
252
239
  if (__DEV__) {
253
- window.__kiru!.emit("update", appCtx!)
254
- window.__kiru?.profilingContext?.emit("update", appCtx!)
240
+ window.__kiru?.profilingContext?.endTick(appCtx!)
241
+ window.__kiru?.profilingContext?.emit("updateDirtied", appCtx!)
255
242
  }
243
+ return flushSync()
256
244
  }
245
+ consecutiveDirtyCount = 0
257
246
 
258
- if (!nextUnitOfWork) {
259
- sleep()
260
- while (nextIdleEffects.length) {
261
- nextIdleEffects.shift()!()
262
- }
263
- if (__DEV__) {
264
- if (appCtx) {
265
- window.__kiru?.profilingContext?.endTick(appCtx)
266
- }
267
- }
268
- return
247
+ onWorkFinished()
248
+ flushEffects(postEffects)
249
+ if (__DEV__) {
250
+ window.__kiru!.emit("update", appCtx!)
251
+ window.__kiru?.profilingContext?.emit("update", appCtx!)
252
+ window.__kiru?.profilingContext?.endTick(appCtx!)
269
253
  }
270
-
271
- queueWorkLoop()
272
254
  }
273
255
 
274
256
  function queueBlockedContextDependencyRoots(): VNode | null {
@@ -382,8 +364,8 @@ function performUnitOfWork(vNode: VNode): VNode | void {
382
364
  }
383
365
 
384
366
  function updateFunctionComponent(vNode: FunctionVNode) {
385
- const { type, props, subs, prev, isMemoized } = vNode
386
- if (isMemoized) {
367
+ const { type, props, subs, prev, flags } = vNode
368
+ if (flags & FLAG_MEMO) {
387
369
  vNode.memoizedProps = props
388
370
  if (
389
371
  prev?.memoizedProps &&
@@ -1,13 +1,13 @@
1
+ import { latest, safeStringify, sideEffectsEnabled } from "../utils.js"
1
2
  import { $HMR_ACCEPT, $SIGNAL } from "../constants.js"
2
3
  import { __DEV__ } from "../env.js"
3
- import type { HMRAccept } from "../hmr.js"
4
- import { latest, safeStringify, sideEffectsEnabled } from "../utils.js"
5
- import { tracking, signalSubsMap } from "./globals.js"
6
- import { type SignalSubscriber, ReadonlySignal } from "./types.js"
7
4
  import { node } from "../globals.js"
8
5
  import { useHook } from "../hooks/utils.js"
9
6
  import { generateRandomID } from "../generateId.js"
10
7
  import { requestUpdate } from "../scheduler.js"
8
+ import { tracking, signalSubsMap } from "./globals.js"
9
+ import type { SignalSubscriber, ReadonlySignal } from "./types.js"
10
+ import type { HMRAccept } from "../hmr.js"
11
11
 
12
12
  export class Signal<T> {
13
13
  [$SIGNAL] = true;
@@ -1,11 +1,11 @@
1
1
  import { __DEV__ } from "../env.js"
2
- import { Signal } from "./index.js"
3
- import { effectQueue, signalSubsMap } from "./globals.js"
4
2
  import { $HMR_ACCEPT } from "../constants.js"
5
- import type { HMRAccept } from "../hmr.js"
6
3
  import { useHook } from "../hooks/utils.js"
7
- import { executeWithTracking } from "./effect.js"
8
4
  import { latest } from "../utils.js"
5
+ import { effectQueue, signalSubsMap } from "./globals.js"
6
+ import { executeWithTracking } from "./effect.js"
7
+ import { Signal } from "./base.js"
8
+ import type { HMRAccept } from "../hmr.js"
9
9
 
10
10
  export class ComputedSignal<T> extends Signal<T> {
11
11
  protected $getter: (prev?: T) => T
@@ -1,7 +1,8 @@
1
1
  import { node } from "../globals.js"
2
2
  import { sideEffectsEnabled } from "../utils.js"
3
3
  import { tracking, effectQueue } from "./globals.js"
4
- import type { Signal } from "./index.js"
4
+ import { tick } from "./utils.js"
5
+ import type { Signal } from "./base.js"
5
6
  import type { SignalValues } from "./types.js"
6
7
 
7
8
  type TrackedExecutionContext<T, Deps extends readonly Signal<unknown>[]> = {
@@ -42,8 +43,8 @@ export function executeWithTracking<T, Deps extends readonly Signal<unknown>[]>(
42
43
  }
43
44
 
44
45
  const effect = () => {
45
- if (!effectQueue.has(id)) {
46
- queueMicrotask(() => effectQueue.get(id)?.())
46
+ if (!effectQueue.size) {
47
+ queueMicrotask(tick)
47
48
  }
48
49
  effectQueue.set(id, onDepChanged)
49
50
  }
@@ -1,4 +1,4 @@
1
- import type { Signal } from "./index.js"
1
+ import type { Signal } from "./base.js"
2
2
  import type { SignalSubscriber } from "./types.js"
3
3
 
4
4
  export const tracking = {
@@ -1,4 +1,4 @@
1
- import type { Signal } from "./index.js"
1
+ import type { Signal } from "./base.js"
2
2
  import type { SignalValues } from "./types.js"
3
3
 
4
4
  type InferArraySignalItemType<T extends Signal<any[]>> = T extends Signal<
@@ -1,4 +1,4 @@
1
- import { type Signal } from "./index.js"
1
+ import type { Signal } from "./base.js"
2
2
 
3
3
  export type ReadonlySignal<T> = Signal<T> & {
4
4
  readonly value: T
@@ -1,4 +1,4 @@
1
- import { Signal } from "./index.js"
1
+ import { Signal } from "./base.js"
2
2
  import { effectQueue } from "./globals.js"
3
3
 
4
4
  export function unwrap<T>(value: T | Signal<T>, reactive = false): T {
package/src/ssr/client.ts CHANGED
@@ -3,27 +3,21 @@ import { hydrationStack } from "../hydration.js"
3
3
  import { renderMode } from "../globals.js"
4
4
  import { mount } from "../index.js"
5
5
 
6
- export function hydrate<T extends Record<string, unknown>>(
7
- appFunc: (props: T) => JSX.Element,
8
- container: AppContextOptions,
9
- appProps?: T
10
- ): Promise<AppContext<T>>
11
-
12
- export function hydrate<T extends Record<string, unknown>>(
13
- appFunc: (props: T) => JSX.Element,
6
+ export function hydrate(
7
+ children: JSX.Element,
14
8
  container: HTMLElement,
15
- appProps?: T
16
- ): Promise<AppContext<T>>
17
-
18
- export function hydrate<T extends Record<string, unknown>>(
19
- appFunc: (props: T) => JSX.Element,
20
- optionsOrRoot: HTMLElement | AppContextOptions,
21
- appProps = {} as T
22
- ) {
9
+ options?: AppContextOptions
10
+ ): AppContext {
23
11
  hydrationStack.clear()
12
+
24
13
  const prevRenderMode = renderMode.current
25
14
  renderMode.current = "hydrate"
26
- return mount(appFunc, optionsOrRoot as any, appProps).finally(() => {
27
- renderMode.current = prevRenderMode
28
- })
15
+ hydrationStack.captureEvents(container)
16
+
17
+ const app = mount(children, container, options)
18
+
19
+ renderMode.current = prevRenderMode
20
+ hydrationStack.releaseEvents(container)
21
+
22
+ return app
29
23
  }
package/src/ssr/server.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { Readable } from "node:stream"
2
2
  import { Fragment } from "../element.js"
3
- import { AppContext, createAppContext } from "../appContext.js"
4
3
  import { renderMode, node } from "../globals.js"
5
4
  import {
6
5
  isVNode,
@@ -14,30 +13,21 @@ import { assertValidElementProps } from "../props.js"
14
13
  import { HYDRATION_BOUNDARY_MARKER } from "./hydrationBoundary.js"
15
14
  import { __DEV__ } from "../env.js"
16
15
 
17
- type RequestState = {
18
- stream: Readable
19
- ctx: AppContext
20
- }
21
-
22
- export function renderToReadableStream<T extends Record<string, unknown>>(
23
- appFunc: (props: T) => JSX.Element,
24
- appProps = {} as T
25
- ): Readable {
16
+ export function renderToReadableStream(element: JSX.Element): Readable {
26
17
  const prev = renderMode.current
27
18
  renderMode.current = "stream"
28
- const state: RequestState = {
29
- stream: new Readable(),
30
- ctx: createAppContext(appFunc, appProps, { rootType: Fragment }),
31
- }
32
- renderToStream_internal(state, state.ctx.rootNode, null, 0)
33
- state.stream.push(null)
19
+ const stream = new Readable()
20
+ const rootNode = Fragment({ children: element })
21
+
22
+ renderToStream_internal(stream, rootNode, null, 0)
23
+ stream.push(null)
34
24
  renderMode.current = prev
35
25
 
36
- return state.stream
26
+ return stream
37
27
  }
38
28
 
39
29
  function renderToStream_internal(
40
- state: RequestState,
30
+ stream: Readable,
41
31
  el: unknown,
42
32
  parent: Kiru.VNode | null,
43
33
  idx: number
@@ -46,23 +36,23 @@ function renderToStream_internal(
46
36
  if (el === undefined) return
47
37
  if (typeof el === "boolean") return
48
38
  if (typeof el === "string") {
49
- state.stream.push(encodeHtmlEntities(el))
39
+ stream.push(encodeHtmlEntities(el))
50
40
  return
51
41
  }
52
42
  if (typeof el === "number" || typeof el === "bigint") {
53
- state.stream.push(el.toString())
43
+ stream.push(el.toString())
54
44
  return
55
45
  }
56
46
  if (el instanceof Array) {
57
- el.forEach((c, i) => renderToStream_internal(state, c, parent, i))
47
+ el.forEach((c, i) => renderToStream_internal(stream, c, parent, i))
58
48
  return
59
49
  }
60
50
  if (Signal.isSignal(el)) {
61
- state.stream.push(String(el.peek()))
51
+ stream.push(String(el.peek()))
62
52
  return
63
53
  }
64
54
  if (!isVNode(el)) {
65
- state.stream.push(String(el))
55
+ stream.push(String(el))
66
56
  return
67
57
  }
68
58
  el.parent = parent
@@ -72,35 +62,35 @@ function renderToStream_internal(
72
62
  const children = props.children
73
63
  const type = el.type
74
64
  if (type === "#text") {
75
- state.stream.push(encodeHtmlEntities(props.nodeValue ?? ""))
65
+ stream.push(encodeHtmlEntities(props.nodeValue ?? ""))
76
66
  return
77
67
  }
78
68
  if (isExoticType(type)) {
79
69
  if (type === $HYDRATION_BOUNDARY) {
80
- state.stream.push(`<!--${HYDRATION_BOUNDARY_MARKER}-->`)
81
- renderToStream_internal(state, children, el, idx)
82
- state.stream.push(`<!--/${HYDRATION_BOUNDARY_MARKER}-->`)
70
+ stream.push(`<!--${HYDRATION_BOUNDARY_MARKER}-->`)
71
+ renderToStream_internal(stream, children, el, idx)
72
+ stream.push(`<!--/${HYDRATION_BOUNDARY_MARKER}-->`)
83
73
  return
84
74
  }
85
- return renderToStream_internal(state, children, el, idx)
75
+ return renderToStream_internal(stream, children, el, idx)
86
76
  }
87
77
 
88
78
  if (typeof type !== "string") {
89
79
  node.current = el
90
80
  const res = type(props)
91
81
  node.current = null
92
- return renderToStream_internal(state, res, parent, idx)
82
+ return renderToStream_internal(stream, res, parent, idx)
93
83
  }
94
84
 
95
85
  if (__DEV__) {
96
86
  assertValidElementProps(el)
97
87
  }
98
88
  const attrs = propsToElementAttributes(props)
99
- state.stream.push(`<${type}${attrs.length ? ` ${attrs}` : ""}>`)
89
+ stream.push(`<${type}${attrs.length ? ` ${attrs}` : ""}>`)
100
90
 
101
91
  if (!voidElements.has(type)) {
102
92
  if ("innerHTML" in props) {
103
- state.stream.push(
93
+ stream.push(
104
94
  String(
105
95
  Signal.isSignal(props.innerHTML)
106
96
  ? props.innerHTML.peek()
@@ -109,12 +99,12 @@ function renderToStream_internal(
109
99
  )
110
100
  } else {
111
101
  if (Array.isArray(children)) {
112
- children.forEach((c, i) => renderToStream_internal(state, c, el, i))
102
+ children.forEach((c, i) => renderToStream_internal(stream, c, el, i))
113
103
  } else {
114
- renderToStream_internal(state, children, el, 0)
104
+ renderToStream_internal(stream, children, el, 0)
115
105
  }
116
106
  }
117
107
 
118
- state.stream.push(`</${type}>`)
108
+ stream.push(`</${type}>`)
119
109
  }
120
110
  }
package/src/types.ts CHANGED
@@ -194,7 +194,6 @@ declare global {
194
194
  effects?: Array<Function>
195
195
  immediateEffects?: Array<Function>
196
196
  memoizedProps?: Record<string, any>
197
- isMemoized?: boolean
198
197
  arePropsEqual?: (
199
198
  prev: Record<string, any>,
200
199
  next: Record<string, any>
package/src/utils.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  FLAG_HAS_MEMO_ANCESTOR,
9
9
  FLAG_PLACEMENT,
10
10
  FLAG_UPDATE,
11
+ FLAG_MEMO,
11
12
  REGEX_UNIT,
12
13
  } from "./constants.js"
13
14
  import { unwrap } from "./signals/utils.js"
@@ -162,8 +163,9 @@ function willMemoBlockUpdate(root: VNode, target: VNode): boolean {
162
163
 
163
164
  while (node && node !== root && node.flags & FLAG_HAS_MEMO_ANCESTOR) {
164
165
  const parent = node.parent
166
+ if (!parent) return false
165
167
  if (
166
- parent?.isMemoized &&
168
+ parent.flags & FLAG_MEMO &&
167
169
  parent.prev?.memoizedProps &&
168
170
  parent.arePropsEqual!(parent.prev.memoizedProps, parent.props)
169
171
  ) {