kiru 0.47.1 → 0.48.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 (75) hide show
  1. package/dist/appContext.d.ts.map +1 -1
  2. package/dist/appContext.js +3 -5
  3. package/dist/appContext.js.map +1 -1
  4. package/dist/constants.d.ts +4 -2
  5. package/dist/constants.d.ts.map +1 -1
  6. package/dist/constants.js +6 -4
  7. package/dist/constants.js.map +1 -1
  8. package/dist/customEvents.d.ts +6 -0
  9. package/dist/customEvents.d.ts.map +1 -0
  10. package/dist/customEvents.js +12 -0
  11. package/dist/customEvents.js.map +1 -0
  12. package/dist/dom.d.ts +3 -1
  13. package/dist/dom.d.ts.map +1 -1
  14. package/dist/dom.js +102 -102
  15. package/dist/dom.js.map +1 -1
  16. package/dist/globalContext.d.ts +4 -3
  17. package/dist/globalContext.d.ts.map +1 -1
  18. package/dist/globalContext.js +0 -2
  19. package/dist/globalContext.js.map +1 -1
  20. package/dist/hooks/useAsync.d.ts +2 -13
  21. package/dist/hooks/useAsync.d.ts.map +1 -1
  22. package/dist/hooks/useAsync.js.map +1 -1
  23. package/dist/index.d.ts +2 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +7 -3
  26. package/dist/index.js.map +1 -1
  27. package/dist/lazy.d.ts +2 -2
  28. package/dist/lazy.d.ts.map +1 -1
  29. package/dist/lazy.js.map +1 -1
  30. package/dist/portal.d.ts +2 -2
  31. package/dist/portal.d.ts.map +1 -1
  32. package/dist/profiling.d.ts +2 -2
  33. package/dist/profiling.d.ts.map +1 -1
  34. package/dist/reconciler.d.ts.map +1 -1
  35. package/dist/reconciler.js +13 -10
  36. package/dist/reconciler.js.map +1 -1
  37. package/dist/scheduler.d.ts +1 -0
  38. package/dist/scheduler.d.ts.map +1 -1
  39. package/dist/scheduler.js +51 -156
  40. package/dist/scheduler.js.map +1 -1
  41. package/dist/swr.d.ts +6 -17
  42. package/dist/swr.d.ts.map +1 -1
  43. package/dist/swr.js +26 -18
  44. package/dist/swr.js.map +1 -1
  45. package/dist/transition.d.ts +2 -2
  46. package/dist/transition.d.ts.map +1 -1
  47. package/dist/types.d.ts +20 -18
  48. package/dist/types.d.ts.map +1 -1
  49. package/dist/types.dom.d.ts +57 -38
  50. package/dist/types.dom.d.ts.map +1 -1
  51. package/dist/types.utils.d.ts +31 -19
  52. package/dist/types.utils.d.ts.map +1 -1
  53. package/dist/utils.d.ts +1 -10
  54. package/dist/utils.d.ts.map +1 -1
  55. package/dist/utils.js +9 -56
  56. package/dist/utils.js.map +1 -1
  57. package/package.json +1 -1
  58. package/src/appContext.ts +3 -5
  59. package/src/constants.ts +9 -4
  60. package/src/customEvents.ts +22 -0
  61. package/src/dom.ts +124 -113
  62. package/src/globalContext.ts +4 -6
  63. package/src/hooks/useAsync.ts +7 -24
  64. package/src/index.ts +7 -4
  65. package/src/lazy.ts +6 -2
  66. package/src/portal.ts +1 -1
  67. package/src/profiling.ts +1 -1
  68. package/src/reconciler.ts +13 -16
  69. package/src/scheduler.ts +69 -158
  70. package/src/swr.ts +28 -37
  71. package/src/transition.ts +1 -1
  72. package/src/types.dom.ts +98 -36
  73. package/src/types.ts +12 -10
  74. package/src/types.utils.ts +43 -14
  75. package/src/utils.ts +7 -74
package/src/dom.ts CHANGED
@@ -3,16 +3,16 @@ import {
3
3
  commitSnapshot,
4
4
  propFilters,
5
5
  propToHtmlAttr,
6
- postOrderApply,
7
6
  getVNodeAppContext,
8
7
  } from "./utils.js"
9
8
  import {
10
9
  booleanAttributes,
11
- FLAG_DELETION,
12
10
  FLAG_PLACEMENT,
13
11
  FLAG_UPDATE,
14
12
  FLAG_STATIC_DOM,
15
13
  svgTags,
14
+ FLAG_NOOP,
15
+ EVENT_PREFIX_REGEX,
16
16
  } from "./constants.js"
17
17
  import { Signal } from "./signals/base.js"
18
18
  import { unwrap } from "./signals/utils.js"
@@ -30,17 +30,47 @@ import type {
30
30
  } from "./types.utils"
31
31
  import type { AppContext } from "./appContext.js"
32
32
 
33
- export { commitWork, commitDeletion, createDom, hydrateDom }
33
+ export {
34
+ commitWork,
35
+ onBeforeFlushDomChanges,
36
+ onAfterFlushDomChanges,
37
+ commitDeletion,
38
+ createDom,
39
+ hydrateDom,
40
+ }
34
41
 
35
42
  type VNode = Kiru.VNode
36
43
  type HostNode = {
37
44
  node: ElementVNode
38
- lastChild?: DomVNode
45
+ lastChild?: SomeDom
39
46
  }
40
- type PlacementScope = {
41
- parent: VNode
42
- active: boolean
43
- child?: VNode
47
+
48
+ let persistingFocus = false
49
+ let didBlurActiveElement = false
50
+ const placementBlurHandler = (event: Event) => {
51
+ event.preventDefault()
52
+ event.stopPropagation()
53
+ didBlurActiveElement = true
54
+ }
55
+
56
+ let currentActiveElement: Element | null = null
57
+ function onBeforeFlushDomChanges() {
58
+ persistingFocus = true
59
+ currentActiveElement = document.activeElement
60
+ if (currentActiveElement && currentActiveElement !== document.body) {
61
+ currentActiveElement.addEventListener("blur", placementBlurHandler)
62
+ }
63
+ }
64
+
65
+ function onAfterFlushDomChanges() {
66
+ if (didBlurActiveElement) {
67
+ currentActiveElement!.removeEventListener("blur", placementBlurHandler)
68
+ if (currentActiveElement!.isConnected) {
69
+ ;(currentActiveElement as any).focus()
70
+ }
71
+ didBlurActiveElement = false
72
+ }
73
+ persistingFocus = false
44
74
  }
45
75
 
46
76
  function setDomRef(ref: Kiru.Ref<SomeDom | null>, value: SomeDom | null) {
@@ -82,42 +112,6 @@ function createTextNode(vNode: VNode): Text {
82
112
  return textNode
83
113
  }
84
114
 
85
- /**
86
- * toggled when we fire a focus event on an element
87
- * persist focus when the currently focused element is moved.
88
- */
89
- let persistingFocus = false
90
-
91
- // gets set prior to dom commits
92
- let currentActiveElement: Element | null = null
93
-
94
- let didBlurActiveElement = false
95
- const placementBlurHandler = (event: Event) => {
96
- event.preventDefault()
97
- event.stopPropagation()
98
- didBlurActiveElement = true
99
- }
100
-
101
- function handlePrePlacementFocusPersistence() {
102
- persistingFocus = true
103
- currentActiveElement = document.activeElement
104
- if (currentActiveElement && currentActiveElement !== document.body) {
105
- currentActiveElement.addEventListener("blur", placementBlurHandler)
106
- }
107
- }
108
-
109
- function handlePostPlacementFocusPersistence() {
110
- if (!didBlurActiveElement) {
111
- persistingFocus = false
112
- return
113
- }
114
- currentActiveElement?.removeEventListener("blur", placementBlurHandler)
115
- if (currentActiveElement?.isConnected) {
116
- if ("focus" in currentActiveElement) (currentActiveElement as any).focus()
117
- }
118
- persistingFocus = false
119
- }
120
-
121
115
  function wrapFocusEventHandler(
122
116
  vNode: VNode,
123
117
  evtName: "focus" | "blur",
@@ -170,7 +164,8 @@ function updateDom(vNode: VNode) {
170
164
 
171
165
  if (propFilters.isEvent(key)) {
172
166
  if (prev !== next || renderMode.current === "hydrate") {
173
- const evtName = key.toLowerCase().substring(2)
167
+ const evtName = key.replace(EVENT_PREFIX_REGEX, "")
168
+
174
169
  const isFocusEvent = evtName === "focus" || evtName === "blur"
175
170
  if (key in prevProps) {
176
171
  dom.removeEventListener(
@@ -551,7 +546,7 @@ function placeDom(vNode: DomVNode, hostNode: HostNode) {
551
546
  const { node: parentVNodeWithDom, lastChild } = hostNode
552
547
  const dom = vNode.dom
553
548
  if (lastChild) {
554
- lastChild.dom.after(dom)
549
+ lastChild.after(dom)
555
550
  return
556
551
  }
557
552
  // TODO: we can probably skip the 'next sibling search' if we're appending
@@ -605,76 +600,49 @@ function commitWork(vNode: VNode) {
605
600
  if (renderMode.current === "hydrate") {
606
601
  return traverseApply(vNode, commitSnapshot)
607
602
  }
608
- handlePrePlacementFocusPersistence()
609
-
610
- const hostNodes: HostNode[] = []
611
- let currentHostNode: HostNode
612
- const placementScopes: PlacementScope[] = []
613
- let currentPlacementScope: PlacementScope | undefined
614
-
615
- postOrderApply(vNode, {
616
- onDescent: (node) => {
617
- if (node.dom) {
618
- // collect host nodes as we go
619
- currentHostNode = { node: node as ElementVNode }
620
- hostNodes.push(currentHostNode)
621
-
622
- if (node.prev && "innerHTML" in node.prev.props) {
623
- /**
624
- * We need to update innerHTML during descent in cases
625
- * where we previously set innerHTML on this element but
626
- * now we provide children. Setting innerHTML _after_
627
- * appending children will yeet em into the abyss.
628
- */
629
- delete node.props.innerHTML
630
- setInnerHTML(node.dom as SomeElement, "")
631
- // remove innerHTML from prev to prevent our ascension pass from doing this again
632
- delete node.prev.props.innerHTML
633
- }
634
603
 
635
- if (currentPlacementScope?.active) {
636
- currentPlacementScope.child = node
637
- // prevent scope applying to descendants of this element node
638
- currentPlacementScope.active = false
639
- }
640
- } else if (node.flags & FLAG_PLACEMENT) {
641
- currentPlacementScope = { parent: node, active: true }
642
- placementScopes.push(currentPlacementScope)
643
- }
644
- },
645
- onAscent: (node) => {
646
- let inheritsPlacement = false
647
- if (currentPlacementScope?.child === node) {
648
- currentPlacementScope.active = true
649
- inheritsPlacement = true
650
- }
651
- if (node.flags & FLAG_DELETION) {
652
- return commitDeletion(node)
653
- }
654
- if (node.dom) {
655
- if (!currentHostNode) {
656
- currentHostNode = { node: getDomParent(node) }
657
- hostNodes.push(currentHostNode)
658
- }
659
- if (!(node.flags & FLAG_STATIC_DOM)) {
660
- commitDom(node as DomVNode, currentHostNode, inheritsPlacement)
661
- }
662
- }
663
- commitSnapshot(node)
664
- },
665
- onBeforeAscent(node) {
666
- if (currentPlacementScope?.parent === node) {
667
- placementScopes.pop()
668
- currentPlacementScope = placementScopes[placementScopes.length - 1]
604
+ const host: HostNode = {
605
+ node: vNode.dom ? (vNode as ElementVNode) : getDomParent(vNode),
606
+ }
607
+ commitWork_impl(vNode, host, (vNode.flags & FLAG_PLACEMENT) > 0)
608
+ if (vNode.dom && !(vNode.flags & FLAG_STATIC_DOM)) {
609
+ commitDom(vNode as DomVNode, host, false)
610
+ }
611
+ commitSnapshot(vNode)
612
+ }
613
+
614
+ function commitWork_impl(
615
+ vNode: VNode,
616
+ currentHostNode: HostNode,
617
+ inheritsPlacement: boolean
618
+ ) {
619
+ let child: VNode | null = vNode.child
620
+ while (child) {
621
+ if (child.flags & FLAG_NOOP) {
622
+ if (child.flags & FLAG_PLACEMENT) {
623
+ placeAndCommitNoopChildren(child, currentHostNode)
669
624
  }
670
- if (currentHostNode?.node === node.parent) {
671
- hostNodes.pop()
672
- currentHostNode = hostNodes[hostNodes.length - 1]
625
+ commitSnapshot(child)
626
+ child = child.sibling
627
+ continue
628
+ }
629
+
630
+ if (child.dom) {
631
+ commitWork_impl(child, { node: child as ElementVNode }, false)
632
+ if (!(child.flags & FLAG_STATIC_DOM)) {
633
+ commitDom(child as DomVNode, currentHostNode, inheritsPlacement)
673
634
  }
674
- },
675
- })
635
+ } else {
636
+ commitWork_impl(
637
+ child,
638
+ currentHostNode,
639
+ (child.flags & FLAG_PLACEMENT) > 0 || inheritsPlacement
640
+ )
641
+ }
676
642
 
677
- handlePostPlacementFocusPersistence()
643
+ commitSnapshot(child)
644
+ child = child.sibling
645
+ }
678
646
  }
679
647
 
680
648
  function commitDom(
@@ -692,7 +660,7 @@ function commitDom(
692
660
  if (!vNode.prev || vNode.flags & FLAG_UPDATE) {
693
661
  updateDom(vNode)
694
662
  }
695
- hostNode.lastChild = vNode
663
+ hostNode.lastChild = vNode.dom
696
664
  }
697
665
 
698
666
  function commitDeletion(vNode: VNode) {
@@ -711,12 +679,16 @@ function commitDeletion(vNode: VNode) {
711
679
  dom,
712
680
  props: { ref },
713
681
  } = node
682
+
714
683
  subs?.forEach((unsub) => unsub())
715
684
  if (cleanups) Object.values(cleanups).forEach((c) => c())
716
685
  while (hooks?.length) hooks.pop()!.cleanup?.()
717
686
 
718
687
  if (__DEV__) {
719
688
  window.__kiru?.profilingContext?.emit("removeNode", ctx)
689
+ if (dom instanceof Element) {
690
+ delete dom.__kiruNode
691
+ }
720
692
  }
721
693
 
722
694
  if (dom) {
@@ -730,3 +702,42 @@ function commitDeletion(vNode: VNode) {
730
702
 
731
703
  vNode.parent = null
732
704
  }
705
+
706
+ function placeAndCommitNoopChildren(
707
+ parent: VNode,
708
+ currentHostNode: HostNode
709
+ ): void {
710
+ if (!parent.child) return
711
+
712
+ const domChildren: SomeDom[] = []
713
+ collectDomNodes(parent.child, domChildren)
714
+ if (domChildren.length === 0) return
715
+
716
+ const { node, lastChild } = currentHostNode
717
+ if (lastChild) {
718
+ lastChild.after(...domChildren)
719
+ } else {
720
+ const nextSiblingDom = getNextSiblingDom(parent, node)
721
+ const parentDom = node.dom
722
+ if (nextSiblingDom) {
723
+ const [first, ...rest] = domChildren
724
+ parentDom.insertBefore(first, nextSiblingDom)
725
+ first.after(...rest)
726
+ } else {
727
+ parentDom.append(...domChildren)
728
+ }
729
+ }
730
+ currentHostNode.lastChild = domChildren[domChildren.length - 1]
731
+ }
732
+
733
+ function collectDomNodes(firstChild: VNode, children: SomeDom[]): void {
734
+ let child: VNode | null = firstChild
735
+ while (child) {
736
+ if (child.dom) {
737
+ children.push(child.dom)
738
+ } else if (child.child) {
739
+ collectDomNodes(child.child, children)
740
+ }
741
+ child = child.sibling
742
+ }
743
+ }
@@ -1,8 +1,9 @@
1
- import type { AppContext } from "./appContext"
2
1
  import { __DEV__ } from "./env.js"
3
2
  import { createHMRContext } from "./hmr.js"
4
3
  import { createProfilingContext } from "./profiling.js"
5
- import { Store } from "./store"
4
+ import type { AppContext } from "./appContext"
5
+ import type { Store } from "./store"
6
+ import type { SWRCache } from "./swr"
6
7
 
7
8
  export { createKiruGlobalContext, type GlobalKiruEvent, type KiruGlobalContext }
8
9
 
@@ -75,7 +76,7 @@ interface KiruGlobalContext {
75
76
  stores?: ReactiveMap<Store<any, any>>
76
77
  HMRContext?: ReturnType<typeof createHMRContext>
77
78
  profilingContext?: ReturnType<typeof createProfilingContext>
78
- globalState: Record<symbol, any>
79
+ SWRGlobalCache?: SWRCache
79
80
  emit<T extends Evt>(event: T["name"], ctx: AppContext, data?: T["data"]): void
80
81
  on<T extends Evt>(
81
82
  event: T["name"],
@@ -93,8 +94,6 @@ function createKiruGlobalContext(): KiruGlobalContext {
93
94
  GlobalKiruEvent,
94
95
  Set<(ctx: AppContext, data?: Evt["data"]) => void>
95
96
  >()
96
- const globalState: Record<symbol, any> = {}
97
-
98
97
  let stores: ReactiveMap<Store<any, any>> | undefined
99
98
  let HMRContext: ReturnType<typeof createHMRContext> | undefined
100
99
  let profilingContext: ReturnType<typeof createProfilingContext> | undefined
@@ -137,7 +136,6 @@ function createKiruGlobalContext(): KiruGlobalContext {
137
136
  get profilingContext() {
138
137
  return profilingContext
139
138
  },
140
- globalState,
141
139
  emit,
142
140
  on,
143
141
  off,
@@ -1,24 +1,9 @@
1
1
  import { __DEV__ } from "../env.js"
2
2
  import { noop } from "../utils.js"
3
3
  import { depsRequireChange, sideEffectsEnabled, useHook } from "./utils.js"
4
+ import type { AsyncTaskState } from "../types.utils.js"
4
5
 
5
- export type UseAsyncState<T> = (
6
- | /** loading*/ {
7
- data: null
8
- loading: true
9
- error: null
10
- }
11
- | /** loaded */ {
12
- data: T
13
- loading: false
14
- error: null
15
- }
16
- | /** error */ {
17
- data: null
18
- loading: false
19
- error: UseAsyncError
20
- }
21
- ) & {
6
+ export type UseAsyncState<T> = AsyncTaskState<T, UseAsyncError> & {
22
7
  invalidate: () => void
23
8
  }
24
9
 
@@ -34,7 +19,7 @@ export class UseAsyncError extends Error {
34
19
  }
35
20
  }
36
21
 
37
- type AsyncTaskState<T> = {
22
+ type InternalTaskState<T> = {
38
23
  data: T | null
39
24
  loading: boolean
40
25
  error: Error | null
@@ -62,10 +47,8 @@ export function useAsync<T>(
62
47
  {
63
48
  deps,
64
49
  id: 0,
65
- task: null as any as AsyncTaskState<T>,
66
- load: noop as (
67
- func: (ctx: UseAsyncCallbackContext) => Promise<T>
68
- ) => void,
50
+ task: null as any as InternalTaskState<T>,
51
+ load: noop as (func: (ctx: UseAsyncCallbackContext) => Promise<T>) => void,
69
52
  },
70
53
  ({ hook, isInit, isHMR, update }) => {
71
54
  if (__DEV__) {
@@ -83,7 +66,7 @@ export function useAsync<T>(
83
66
  invalidated = true
84
67
  })
85
68
  const id = ++hook.id
86
- const task: AsyncTaskState<T> = (hook.task = {
69
+ const task: InternalTaskState<T> = (hook.task = {
87
70
  abortController,
88
71
  data: null,
89
72
  loading: true,
@@ -130,7 +113,7 @@ export function useAsync<T>(
130
113
  )
131
114
  }
132
115
 
133
- function abortTask<T>(task: AsyncTaskState<T> | null): void {
116
+ function abortTask<T>(task: InternalTaskState<T> | null): void {
134
117
  if (task === null || task.abortController.signal.aborted) return
135
118
  task.abortController.abort()
136
119
  }
package/src/index.ts CHANGED
@@ -1,11 +1,12 @@
1
- import { createKiruGlobalContext } from "./globalContext.js"
2
1
  import { __DEV__ } from "./env.js"
2
+ import { createKiruGlobalContext } from "./globalContext.js"
3
3
 
4
4
  export type * from "./types"
5
5
  export * from "./signals/index.js"
6
6
  export * from "./appContext.js"
7
- export * from "./context.js"
8
7
  export * from "./cloneVNode.js"
8
+ export * from "./context.js"
9
+ export * from "./customEvents.js"
9
10
  export * from "./element.js"
10
11
  export * from "./hooks/index.js"
11
12
  export * from "./lazy.js"
@@ -16,6 +17,8 @@ export { nextIdle, flushSync, requestUpdate } from "./scheduler.js"
16
17
  export * from "./store.js"
17
18
  export * from "./transition.js"
18
19
 
19
- if ("window" in globalThis) {
20
- globalThis.window.__kiru ??= createKiruGlobalContext()
20
+ if (__DEV__) {
21
+ if ("window" in globalThis) {
22
+ globalThis.window.__kiru ??= createKiruGlobalContext()
23
+ }
21
24
  }
package/src/lazy.ts CHANGED
@@ -14,13 +14,17 @@ import {
14
14
  import type { SomeDom } from "./types.utils"
15
15
  import { noop } from "./utils.js"
16
16
 
17
- type FCModule = { default: Kiru.FC<any> }
17
+ interface FCModule {
18
+ default: Kiru.FC<any>
19
+ }
20
+
18
21
  type LazyImportValue = Kiru.FC<any> | FCModule
22
+
19
23
  type InferLazyImportProps<T extends LazyImportValue> = T extends FCModule
20
24
  ? Kiru.InferProps<T["default"]>
21
25
  : Kiru.InferProps<T>
22
26
 
23
- type LazyState = {
27
+ interface LazyState {
24
28
  fn: string
25
29
  promise: Promise<LazyImportValue>
26
30
  result: Kiru.FC | null
package/src/portal.ts CHANGED
@@ -5,7 +5,7 @@ import { renderMode } from "./globals.js"
5
5
  import { useVNode } from "./hooks/utils.js"
6
6
  import { nextIdle, requestUpdate } from "./scheduler.js"
7
7
 
8
- type PortalProps = {
8
+ interface PortalProps {
9
9
  children?: JSX.Children
10
10
  container: HTMLElement | (() => HTMLElement)
11
11
  }
package/src/profiling.ts CHANGED
@@ -14,7 +14,7 @@ const ProfilingEvents = [
14
14
 
15
15
  export type ProfilingEvent = (typeof ProfilingEvents)[number]
16
16
 
17
- type TickTS = {
17
+ interface TickTS {
18
18
  start: number
19
19
  end: number
20
20
  }
package/src/reconciler.ts CHANGED
@@ -1,10 +1,4 @@
1
- import {
2
- $FRAGMENT,
3
- FLAG_HAS_MEMO_ANCESTOR,
4
- FLAG_MEMO,
5
- FLAG_PLACEMENT,
6
- FLAG_UPDATE,
7
- } from "./constants.js"
1
+ import { $FRAGMENT, FLAG_PLACEMENT, FLAG_UPDATE } from "./constants.js"
8
2
  import { getVNodeAppContext, isVNode, latest } from "./utils.js"
9
3
  import { Signal } from "./signals/base.js"
10
4
  import { __DEV__ } from "./env.js"
@@ -32,7 +26,6 @@ export function reconcileChildren(parent: VNode, children: unknown) {
32
26
  }
33
27
 
34
28
  function reconcileSingleChild(parent: VNode, child: unknown) {
35
- const deletions: VNode[] = (parent.deletions = [])
36
29
  const oldChild = parent.child
37
30
  if (oldChild === null) {
38
31
  return createChild(parent, child)
@@ -60,13 +53,12 @@ function reconcileSingleChild(parent: VNode, child: unknown) {
60
53
  }
61
54
  placeChild(newNode, 0, 0)
62
55
  }
63
- existingChildren.forEach((child) => deletions.push(child))
56
+ existingChildren.forEach((child) => deleteChild(parent, child))
64
57
  return newNode
65
58
  }
66
59
  }
67
60
 
68
61
  function reconcileChildrenArray(parent: VNode, children: unknown[]) {
69
- const deletions: VNode[] = (parent.deletions = [])
70
62
  let resultingChild: VNode | null = null
71
63
  let prevNewChild: VNode | null = null
72
64
 
@@ -90,7 +82,7 @@ function reconcileChildrenArray(parent: VNode, children: unknown[]) {
90
82
  break
91
83
  }
92
84
  if (oldChild && !newChild.prev) {
93
- deletions.push(oldChild)
85
+ deleteChild(parent, oldChild)
94
86
  }
95
87
  lastPlacedIndex = placeChild(newChild, lastPlacedIndex, newIdx)
96
88
  if (prevNewChild === null) {
@@ -151,7 +143,7 @@ function reconcileChildrenArray(parent: VNode, children: unknown[]) {
151
143
  }
152
144
  }
153
145
 
154
- existingChildren.forEach((child) => deletions.push(child))
146
+ existingChildren.forEach((child) => deleteChild(parent, child))
155
147
  return resultingChild
156
148
  }
157
149
 
@@ -460,9 +452,6 @@ function propsChanged(oldProps: VNode["props"], newProps: VNode["props"]) {
460
452
  function setParent(child: VNode, parent: VNode) {
461
453
  child.parent = parent
462
454
  child.depth = parent.depth + 1
463
- if (parent.flags & (FLAG_MEMO | FLAG_HAS_MEMO_ANCESTOR)) {
464
- child.flags |= FLAG_HAS_MEMO_ANCESTOR
465
- }
466
455
  }
467
456
 
468
457
  function dev_emitUpdateNode() {
@@ -490,9 +479,17 @@ function mapRemainingChildren(child: VNode | null) {
490
479
  return map
491
480
  }
492
481
 
482
+ function deleteChild(parent: VNode, child: VNode) {
483
+ if (parent.deletions === null) {
484
+ parent.deletions = [child]
485
+ } else {
486
+ parent.deletions.push(child)
487
+ }
488
+ }
489
+
493
490
  function deleteRemainingChildren(parent: VNode, child: VNode | null) {
494
491
  while (child) {
495
- parent.deletions!.push(child)
492
+ deleteChild(parent, child)
496
493
  child = child.sibling
497
494
  }
498
495
  }