@kunpeng-js/properties-panel 2026.0.0-alpha2 → 2026.10.2

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 (127) hide show
  1. package/LICENSE +9 -2
  2. package/dist/index.esm.js +3760 -3762
  3. package/dist/index.esm.js.map +1 -1
  4. package/dist/index.js +3724 -3804
  5. package/dist/index.js.map +1 -1
  6. package/package.json +22 -48
  7. package/preact/README.md +5 -5
  8. package/preact/compat/client.d.ts +1 -3
  9. package/preact/compat/dist/compat.mjs +2 -2
  10. package/preact/compat/dist/compat.mjs.map +1 -0
  11. package/preact/compat/package.json +2 -41
  12. package/preact/compat/scheduler.d.ts +12 -0
  13. package/preact/compat/server.d.ts +17 -0
  14. package/preact/compat/src/Children.js +3 -3
  15. package/preact/compat/src/PureComponent.js +20 -12
  16. package/preact/compat/src/forwardRef.js +4 -17
  17. package/preact/compat/src/hooks.js +17 -51
  18. package/preact/compat/src/index.d.ts +249 -164
  19. package/preact/compat/src/index.js +52 -43
  20. package/preact/compat/src/internal.d.ts +1 -2
  21. package/preact/compat/src/memo.js +2 -2
  22. package/preact/compat/src/portals.js +2 -68
  23. package/preact/compat/src/render.js +182 -73
  24. package/preact/compat/src/suspense.d.ts +1 -3
  25. package/preact/compat/src/suspense.js +169 -179
  26. package/preact/compat/src/util.js +5 -22
  27. package/preact/debug/dist/debug.mjs +2 -2
  28. package/preact/debug/dist/debug.mjs.map +1 -0
  29. package/preact/debug/package.json +3 -14
  30. package/preact/debug/src/check-props.js +2 -6
  31. package/preact/debug/src/component-stack.js +67 -16
  32. package/preact/debug/src/debug.js +80 -35
  33. package/preact/debug/src/index.d.ts +11 -1
  34. package/preact/debug/src/index.js +3 -1
  35. package/preact/debug/src/util.js +1 -11
  36. package/preact/devtools/dist/devtools.mjs +2 -2
  37. package/preact/devtools/dist/devtools.mjs.map +1 -0
  38. package/preact/devtools/package.json +3 -15
  39. package/preact/devtools/src/devtools.js +1 -1
  40. package/preact/dist/preact.mjs +2 -2
  41. package/preact/dist/preact.mjs.map +1 -0
  42. package/preact/hooks/dist/hooks.mjs +2 -2
  43. package/preact/hooks/dist/hooks.mjs.map +1 -0
  44. package/preact/hooks/package.json +5 -24
  45. package/preact/hooks/src/index.d.ts +6 -13
  46. package/preact/hooks/src/index.js +95 -73
  47. package/preact/hooks/src/internal.d.ts +8 -3
  48. package/preact/jsx-runtime/dist/jsxRuntime.mjs +2 -2
  49. package/preact/jsx-runtime/dist/jsxRuntime.mjs.map +1 -0
  50. package/preact/jsx-runtime/package.json +4 -16
  51. package/preact/jsx-runtime/src/index.d.ts +11 -11
  52. package/preact/jsx-runtime/src/index.js +25 -40
  53. package/preact/jsx-runtime/src/utils.js +3 -3
  54. package/preact/package.json +59 -115
  55. package/preact/src/component.js +54 -47
  56. package/preact/src/constants.js +17 -2
  57. package/preact/src/create-context.js +4 -14
  58. package/preact/src/create-element.js +42 -17
  59. package/preact/src/create-portal.js +20 -0
  60. package/preact/src/diff/catch-error.js +26 -8
  61. package/preact/src/diff/children.js +158 -96
  62. package/preact/src/diff/index.js +265 -146
  63. package/preact/src/diff/props.js +39 -50
  64. package/preact/src/dom.d.ts +796 -147
  65. package/preact/src/index.d.ts +7 -18
  66. package/preact/src/index.js +2 -1
  67. package/preact/src/internal.d.ts +16 -24
  68. package/preact/src/jsx.d.ts +222 -2910
  69. package/preact/src/render.js +30 -34
  70. package/preact/src/util.js +5 -20
  71. package/preact/test-utils/dist/testUtils.mjs +1 -1
  72. package/preact/test-utils/dist/testUtils.mjs.map +1 -0
  73. package/preact/test-utils/package.json +5 -17
  74. package/README.md +0 -35
  75. package/preact/compat/dist/compat.js +0 -2
  76. package/preact/compat/dist/compat.js.map +0 -1
  77. package/preact/compat/dist/compat.module.js +0 -2
  78. package/preact/compat/dist/compat.module.js.map +0 -1
  79. package/preact/compat/dist/compat.umd.js +0 -2
  80. package/preact/compat/dist/compat.umd.js.map +0 -1
  81. package/preact/compat/src/suspense-list.d.ts +0 -16
  82. package/preact/compat/src/suspense-list.js +0 -127
  83. package/preact/debug/dist/debug.js +0 -2
  84. package/preact/debug/dist/debug.js.map +0 -1
  85. package/preact/debug/dist/debug.module.js +0 -2
  86. package/preact/debug/dist/debug.module.js.map +0 -1
  87. package/preact/debug/dist/debug.umd.js +0 -2
  88. package/preact/debug/dist/debug.umd.js.map +0 -1
  89. package/preact/devtools/dist/devtools.js +0 -2
  90. package/preact/devtools/dist/devtools.js.map +0 -1
  91. package/preact/devtools/dist/devtools.module.js +0 -2
  92. package/preact/devtools/dist/devtools.module.js.map +0 -1
  93. package/preact/devtools/dist/devtools.umd.js +0 -2
  94. package/preact/devtools/dist/devtools.umd.js.map +0 -1
  95. package/preact/dist/preact.js +0 -2
  96. package/preact/dist/preact.js.map +0 -1
  97. package/preact/dist/preact.min.js +0 -2
  98. package/preact/dist/preact.min.js.map +0 -1
  99. package/preact/dist/preact.min.module.js +0 -2
  100. package/preact/dist/preact.min.module.js.map +0 -1
  101. package/preact/dist/preact.min.umd.js +0 -2
  102. package/preact/dist/preact.min.umd.js.map +0 -1
  103. package/preact/dist/preact.module.js +0 -2
  104. package/preact/dist/preact.module.js.map +0 -1
  105. package/preact/dist/preact.umd.js +0 -2
  106. package/preact/dist/preact.umd.js.map +0 -1
  107. package/preact/hooks/dist/hooks.js +0 -2
  108. package/preact/hooks/dist/hooks.js.map +0 -1
  109. package/preact/hooks/dist/hooks.module.js +0 -2
  110. package/preact/hooks/dist/hooks.module.js.map +0 -1
  111. package/preact/hooks/dist/hooks.umd.js +0 -2
  112. package/preact/hooks/dist/hooks.umd.js.map +0 -1
  113. package/preact/jsx-runtime/dist/jsxRuntime.js +0 -2
  114. package/preact/jsx-runtime/dist/jsxRuntime.js.map +0 -1
  115. package/preact/jsx-runtime/dist/jsxRuntime.module.js +0 -2
  116. package/preact/jsx-runtime/dist/jsxRuntime.module.js.map +0 -1
  117. package/preact/jsx-runtime/dist/jsxRuntime.umd.js +0 -2
  118. package/preact/jsx-runtime/dist/jsxRuntime.umd.js.map +0 -1
  119. package/preact/src/cjs.js +0 -3
  120. package/preact/src/clone-element.js +0 -48
  121. package/preact/src/index-5.d.ts +0 -399
  122. package/preact/test-utils/dist/testUtils.js +0 -2
  123. package/preact/test-utils/dist/testUtils.js.map +0 -1
  124. package/preact/test-utils/dist/testUtils.module.js +0 -2
  125. package/preact/test-utils/dist/testUtils.module.js.map +0 -1
  126. package/preact/test-utils/dist/testUtils.umd.js +0 -2
  127. package/preact/test-utils/dist/testUtils.umd.js.map +0 -1
@@ -0,0 +1,20 @@
1
+ import { createVNode } from './create-element';
2
+
3
+ /**
4
+ * Portal component. A unique type is used instead of Fragment so that a
5
+ * portal returned directly from a component isn't collapsed into the
6
+ * component's children array by the Fragment unwrapping in `diff()`.
7
+ * @param {object} props
8
+ */
9
+ function Portal(props) {
10
+ return props.children;
11
+ }
12
+
13
+ /**
14
+ * Create a `Portal` to continue rendering the vnode tree at a different DOM node
15
+ * @param {import('./internal').ComponentChildren} vnode The vnode to render
16
+ * @param {import('./internal').PreactElement} container The DOM node to continue rendering in to
17
+ */
18
+ export function createPortal(vnode, container) {
19
+ return createVNode(Portal, { _parentDom: container, children: vnode });
20
+ }
@@ -1,4 +1,10 @@
1
- import { NULL } from '../constants';
1
+ import { resetRenderCount } from '../component';
2
+ import {
3
+ COMPONENT_DIRTY,
4
+ COMPONENT_PENDING_ERROR,
5
+ COMPONENT_PROCESSING_EXCEPTION,
6
+ COMPONENT_FORCE
7
+ } from '../constants';
2
8
 
3
9
  /**
4
10
  * Find the closest error boundary to a thrown error and call it
@@ -14,33 +20,45 @@ export function _catchError(error, vnode, oldVNode, errorInfo) {
14
20
  let component,
15
21
  /** @type {import('../internal').ComponentType} */
16
22
  ctor,
17
- /** @type {boolean} */
23
+ /** @type {number} */
18
24
  handled;
19
25
 
20
26
  for (; (vnode = vnode._parent); ) {
21
- if ((component = vnode._component) && !component._processingException) {
27
+ if (
28
+ (component = vnode._component) &&
29
+ !(component._bits & COMPONENT_PROCESSING_EXCEPTION)
30
+ ) {
31
+ component._bits |= COMPONENT_FORCE;
22
32
  try {
23
33
  ctor = component.constructor;
24
34
 
25
- if (ctor && ctor.getDerivedStateFromError != NULL) {
35
+ if (ctor && ctor.getDerivedStateFromError) {
26
36
  component.setState(ctor.getDerivedStateFromError(error));
27
- handled = component._dirty;
37
+ handled = component._bits & COMPONENT_DIRTY;
28
38
  }
29
39
 
30
- if (component.componentDidCatch != NULL) {
40
+ if (component.componentDidCatch) {
31
41
  component.componentDidCatch(error, errorInfo || {});
32
- handled = component._dirty;
42
+ handled = component._bits & COMPONENT_DIRTY;
33
43
  }
34
44
 
35
45
  // This is an error boundary. Mark it as having bailed out, and whether it was mid-hydration.
36
46
  if (handled) {
37
- return (component._pendingError = component);
47
+ component._bits |= COMPONENT_PENDING_ERROR;
48
+ return;
38
49
  }
39
50
  } catch (e) {
40
51
  error = e;
52
+ // This component failed to handle the error, so what its
53
+ // getDerivedStateFromError did must not make the next ancestor a
54
+ // boundary.
55
+ handled = 0;
41
56
  }
42
57
  }
43
58
  }
44
59
 
60
+ // Reset rerender count to 0, so that the next render will not be skipped
61
+ // when we leverage prefresh
62
+ resetRenderCount();
45
63
  throw error;
46
64
  }
@@ -5,6 +5,7 @@ import {
5
5
  EMPTY_ARR,
6
6
  INSERT_VNODE,
7
7
  MATCHED,
8
+ REF_DETACHED,
8
9
  UNDEFINED,
9
10
  NULL
10
11
  } from '../constants';
@@ -39,6 +40,7 @@ import { getDomSibling } from '../component';
39
40
  * siblings. In most cases, it starts out as `oldChildren[0]._dom`.
40
41
  * @param {boolean} isHydrating Whether or not we are in hydration
41
42
  * @param {any[]} refQueue an array of elements needed to invoke refs
43
+ * @returns {PreactElement} The next sibling DOM element to insert new elements
42
44
  */
43
45
  export function diffChildren(
44
46
  parentDom,
@@ -63,10 +65,11 @@ export function diffChildren(
63
65
  /** @type {PreactElement} */
64
66
  firstChildDom;
65
67
 
66
- // This is a compression of oldParentVNode!=null && oldParentVNode != EMPTY_OBJ && oldParentVNode._children || EMPTY_ARR
67
- // as EMPTY_OBJ._children should be `undefined`.
68
+ // This is a compression of oldParentVNode != EMPTY_OBJ && oldParentVNode._children || EMPTY_ARR
69
+ // as EMPTY_OBJ._children should be `undefined`. Callers always pass at
70
+ // least EMPTY_OBJ, so a null check isn't needed.
68
71
  /** @type {VNode[]} */
69
- let oldChildren = (oldParentVNode && oldParentVNode._children) || EMPTY_ARR;
72
+ let oldChildren = oldParentVNode._children || EMPTY_ARR;
70
73
 
71
74
  let newChildrenLength = renderResult.length;
72
75
 
@@ -84,8 +87,10 @@ export function diffChildren(
84
87
 
85
88
  // At this point, constructNewChildrenArray has assigned _index to be the
86
89
  // matchingIndex for this VNode's oldVNode (or -1 if there is no oldVNode).
90
+ // ~_index guards the -1 case: a negative array index is a named property
91
+ // access which V8 can't serve from the fast elements path.
87
92
  oldVNode =
88
- (childVNode._index != -1 && oldChildren[childVNode._index]) || EMPTY_OBJ;
93
+ (~childVNode._index && oldChildren[childVNode._index]) || EMPTY_OBJ;
89
94
 
90
95
  // Update childVNode._index to its final index
91
96
  childVNode._index = i;
@@ -106,23 +111,23 @@ export function diffChildren(
106
111
 
107
112
  // Adjust DOM nodes
108
113
  newDom = childVNode._dom;
109
- if (childVNode.ref && oldVNode.ref != childVNode.ref) {
110
- if (oldVNode.ref) {
111
- applyRef(oldVNode.ref, NULL, childVNode);
114
+ // A ref detached while its subtree was parked by Suspense is attached
115
+ // again on reveal.
116
+ if (oldVNode.ref != childVNode.ref || oldVNode._flags & REF_DETACHED) {
117
+ if (oldVNode.ref) applyRef(oldVNode.ref, NULL, childVNode, oldVNode);
118
+ if (childVNode.ref) {
119
+ refQueue.push(
120
+ childVNode.ref,
121
+ childVNode._component || newDom,
122
+ childVNode
123
+ );
112
124
  }
113
- refQueue.push(
114
- childVNode.ref,
115
- childVNode._component || newDom,
116
- childVNode
117
- );
118
125
  }
119
126
 
120
- if (firstChildDom == NULL && newDom != NULL) {
121
- firstChildDom = newDom;
122
- }
127
+ firstChildDom = firstChildDom || newDom;
123
128
 
124
129
  if (childVNode._flags & INSERT_VNODE) {
125
- oldDom = insert(childVNode, oldDom, parentDom);
130
+ oldDom = insert(childVNode, oldDom, parentDom, !oldVNode._original);
126
131
 
127
132
  // When a matched VNode is physically moved via INSERT_VNODE, its old
128
133
  // _dom pointer becomes a stale positional reference. Clear it so that
@@ -170,7 +175,14 @@ function constructNewChildrenArray(
170
175
 
171
176
  let skew = 0;
172
177
 
173
- newParentVNode._children = new Array(newChildrenLength);
178
+ /** Whether any matched child was found far from its skewed index, i.e. a
179
+ * real reorder happened and we need to compute the minimal set of moves. */
180
+ let moved = false;
181
+
182
+ // Hoisted: every normalization branch below writes through this array, so
183
+ // reading `_children` off the vnode each time is a wasted property load.
184
+ /** @type {VNode[]} */
185
+ let newChildren = (newParentVNode._children = Array(newChildrenLength));
174
186
  for (i = 0; i < newChildrenLength; i++) {
175
187
  // @ts-expect-error We are reusing the childVNode variable to hold both the
176
188
  // pre and post normalized childVNode
@@ -181,48 +193,38 @@ function constructNewChildrenArray(
181
193
  typeof childVNode == 'boolean' ||
182
194
  typeof childVNode == 'function'
183
195
  ) {
184
- newParentVNode._children[i] = NULL;
196
+ newChildren[i] = NULL;
185
197
  continue;
186
198
  }
187
199
  // If this newVNode is being reused (e.g. <div>{reuse}{reuse}</div>) in the same diff,
188
200
  // or we are rendering a component (e.g. setState) copy the oldVNodes so it can have
189
201
  // it's own DOM & etc. pointers
202
+ // Anything that isn't an object at this point is a string, number or
203
+ // bigint (null, booleans and functions are handled above), String
204
+ // objects are the lone object type rendered as text.
190
205
  else if (
191
- typeof childVNode == 'string' ||
192
- typeof childVNode == 'number' ||
193
- // eslint-disable-next-line valid-typeof
194
- typeof childVNode == 'bigint' ||
206
+ typeof childVNode != 'object' ||
195
207
  childVNode.constructor == String
196
208
  ) {
197
- childVNode = newParentVNode._children[i] = createVNode(
198
- NULL,
199
- childVNode,
200
- NULL,
201
- NULL,
202
- NULL
203
- );
209
+ childVNode = newChildren[i] = createVNode(NULL, childVNode);
204
210
  } else if (isArray(childVNode)) {
205
- childVNode = newParentVNode._children[i] = createVNode(
206
- Fragment,
207
- { children: childVNode },
208
- NULL,
209
- NULL,
210
- NULL
211
- );
212
- } else if (childVNode.constructor === UNDEFINED && childVNode._depth > 0) {
211
+ childVNode = newChildren[i] = createVNode(Fragment, {
212
+ children: childVNode
213
+ });
214
+ } else if (childVNode.constructor === UNDEFINED && childVNode._depth) {
213
215
  // VNode is already in use, clone it. This can happen in the following
214
216
  // scenario:
215
217
  // const reuse = <div />
216
218
  // <div>{reuse}<span />{reuse}</div>
217
- childVNode = newParentVNode._children[i] = createVNode(
219
+ childVNode = newChildren[i] = createVNode(
218
220
  childVNode.type,
219
221
  childVNode.props,
220
222
  childVNode.key,
221
- childVNode.ref ? childVNode.ref : NULL,
223
+ childVNode.ref,
222
224
  childVNode._original
223
225
  );
224
226
  } else {
225
- newParentVNode._children[i] = childVNode;
227
+ newChildren[i] = childVNode;
226
228
  }
227
229
 
228
230
  const skewedIndex = i + skew;
@@ -240,7 +242,8 @@ function constructNewChildrenArray(
240
242
  ));
241
243
 
242
244
  oldVNode = NULL;
243
- if (matchingIndex != -1) {
245
+ // ~matchingIndex is only falsy for -1, i.e. when no match was found
246
+ if (~matchingIndex) {
244
247
  oldVNode = oldChildren[matchingIndex];
245
248
  remainingOldChildren--;
246
249
  if (oldVNode) {
@@ -251,10 +254,8 @@ function constructNewChildrenArray(
251
254
  // Here, we define isMounting for the purposes of the skew diffing
252
255
  // algorithm. Nodes that are unsuspending are considered mounting and we detect
253
256
  // this by checking if oldVNode._original == null
254
- const isMounting = oldVNode == NULL || oldVNode._original == NULL;
255
-
256
- if (isMounting) {
257
- if (matchingIndex == -1) {
257
+ if (!oldVNode || !oldVNode._original) {
258
+ if (!~matchingIndex) {
258
259
  // When the array of children is growing we need to decrease the skew
259
260
  // as we are adding a new element to the array.
260
261
  // Example:
@@ -280,38 +281,74 @@ function constructNewChildrenArray(
280
281
  if (typeof childVNode.type != 'function') {
281
282
  childVNode._flags |= INSERT_VNODE;
282
283
  }
283
- } else if (matchingIndex != skewedIndex) {
284
- // When we move elements around i.e. [0, 1, 2] --> [1, 0, 2]
285
- // --> we diff 1, we find it at position 1 while our skewed index is 0 and our skew is 0
286
- // we set the skew to 1 as we found an offset.
287
- // --> we diff 0, we find it at position 0 while our skewed index is at 2 and our skew is 1
288
- // this makes us increase the skew again.
289
- // --> we diff 2, we find it at position 2 while our skewed index is at 4 and our skew is 2
290
- //
291
- // this becomes an optimization question where currently we see a 1 element offset as an insertion
292
- // or deletion i.e. we optimize for [0, 1, 2] --> [9, 0, 1, 2]
293
- // while a more than 1 offset we see as a swap.
294
- // We could probably build heuristics for having an optimized course of action here as well, but
295
- // might go at the cost of some bytes.
296
- //
297
- // If we wanted to optimize for i.e. only swaps we'd just do the last two code-branches and have
298
- // only the first item be a re-scouting and all the others fall in their skewed counter-part.
299
- // We could also further optimize for swaps
284
+ } else {
285
+ // Matched children are candidates for the minimal-move pass below;
286
+ // MATCHED on a _new_ vnode is cleared in diffChildren's placement loop.
287
+ childVNode._flags |= MATCHED;
288
+
289
+ // The skew adjustments keep findMatchingIndex's search centered for
290
+ // shift patterns (insertions/removals at the front). A match further
291
+ // than one position away means children were genuinely reordered:
292
+ // flag it so the minimal set of moves is computed below. Off-by-one
293
+ // matches provably keep matched old indices in increasing order, so
294
+ // no moves are needed for them.
300
295
  if (matchingIndex == skewedIndex - 1) {
301
296
  skew--;
302
297
  } else if (matchingIndex == skewedIndex + 1) {
303
298
  skew++;
304
- } else {
299
+ } else if (matchingIndex != skewedIndex) {
305
300
  if (matchingIndex > skewedIndex) {
306
301
  skew--;
307
302
  } else {
308
303
  skew++;
309
304
  }
310
305
 
311
- // Move this VNode's DOM if the original index (matchingIndex) doesn't
312
- // match the new skew index (i + new skew)
313
- // In the former two branches we know that it matches after skewing
314
- childVNode._flags |= INSERT_VNODE;
306
+ moved = true;
307
+ }
308
+ }
309
+ }
310
+
311
+ if (moved) {
312
+ // Children were reordered: mark the minimal set of matched (MATCHED flag)
313
+ // children for insertion by finding the longest increasing subsequence of
314
+ // old indices (patience sorting). Children on the subsequence stay in
315
+ // place, all others get INSERT_VNODE. `_index` still holds the
316
+ // matchingIndex here.
317
+ /** @type {number[]} tails[x] is the smallest old index ending an increasing subsequence of length x+1 */
318
+ let tails = [];
319
+ /** @type {number[]} length of the longest increasing subsequence ending at child i */
320
+ let lisLengths = [];
321
+ for (i = 0; i < newChildrenLength; i++) {
322
+ childVNode = newChildren[i];
323
+ if (childVNode && childVNode._flags & MATCHED) {
324
+ // Binary search for the insertion point, keeping the pass at
325
+ // O(n log n) even for pathological reorders.
326
+ let lo = 0,
327
+ hi = tails.length;
328
+ while (lo < hi) {
329
+ const mid = (lo + hi) >> 1;
330
+ if (tails[mid] < childVNode._index) {
331
+ lo = mid + 1;
332
+ } else {
333
+ hi = mid;
334
+ }
335
+ }
336
+ tails[lo] = childVNode._index;
337
+ lisLengths[i] = lo + 1;
338
+ }
339
+ }
340
+
341
+ // `skew` is dead after the main loop; reuse it as the remaining
342
+ // subsequence length while walking backwards. Likewise `i` is left at
343
+ // newChildrenLength by the loop above.
344
+ skew = tails.length;
345
+ while (i--) {
346
+ if (lisLengths[i]) {
347
+ if (lisLengths[i] == skew) {
348
+ skew--;
349
+ } else {
350
+ newChildren[i]._flags |= INSERT_VNODE;
351
+ }
315
352
  }
316
353
  }
317
354
  }
@@ -319,11 +356,12 @@ function constructNewChildrenArray(
319
356
  // Remove remaining oldChildren if there are any. Loop forwards so that as we
320
357
  // unmount DOM from the beginning of the oldChildren, we can adjust oldDom to
321
358
  // point to the next child, which needs to be the first DOM node that won't be
322
- // unmounted.
359
+ // unmounted. Keep this a plain loop: an arrow function here would capture
360
+ // `oldDom`, forcing V8 to context-allocate it on every call to this function.
323
361
  if (remainingOldChildren) {
324
362
  for (i = 0; i < oldChildrenLength; i++) {
325
363
  oldVNode = oldChildren[i];
326
- if (oldVNode != NULL && (oldVNode._flags & MATCHED) == 0) {
364
+ if (oldVNode && !(oldVNode._flags & MATCHED)) {
327
365
  if (oldVNode._dom == oldDom) {
328
366
  oldDom = getDomSibling(oldVNode);
329
367
  }
@@ -340,35 +378,56 @@ function constructNewChildrenArray(
340
378
  * @param {VNode} parentVNode
341
379
  * @param {PreactElement} oldDom
342
380
  * @param {PreactElement} parentDom
381
+ * @param {boolean} isMounting
343
382
  * @returns {PreactElement}
344
383
  */
345
- function insert(parentVNode, oldDom, parentDom) {
384
+ function insert(parentVNode, oldDom, parentDom, isMounting) {
346
385
  // Note: VNodes in nested suspended trees may be missing _children.
347
-
348
386
  if (typeof parentVNode.type == 'function') {
387
+ // Root children live in another container, they never move with the
388
+ // host tree and contribute nothing to the host insertion cursor.
389
+ if (parentVNode.props._parentDom) return oldDom;
349
390
  let children = parentVNode._children;
350
- for (let i = 0; children && i < children.length; i++) {
351
- if (children[i]) {
352
- // If we enter this code path on sCU bailout, where we copy
353
- // oldVNode._children to newVNode._children, we need to update the old
354
- // children's _parent pointer to point to the newVNode (parentVNode
355
- // here).
356
- children[i]._parent = parentVNode;
357
- oldDom = insert(children[i], oldDom, parentDom);
391
+ if (children) {
392
+ for (let i = 0; i < children.length; i++) {
393
+ if (children[i]) {
394
+ // If we enter this code path on sCU bailout, where we copy
395
+ // oldVNode._children to newVNode._children, we need to update the old
396
+ // children's _parent pointer to point to the newVNode (parentVNode
397
+ // here).
398
+ children[i]._parent = parentVNode;
399
+ oldDom = insert(children[i], oldDom, parentDom, false);
400
+ }
358
401
  }
359
402
  }
360
403
 
361
404
  return oldDom;
362
- } else if (parentVNode._dom != oldDom) {
363
- if (oldDom && parentVNode.type && !oldDom.parentNode) {
405
+ } else {
406
+ // A cursor a parked Suspense subtree detached can't be a reference node:
407
+ // retry from the vnode tree, then give up and append.
408
+ if (oldDom && !oldDom.parentNode) {
364
409
  oldDom = getDomSibling(parentVNode);
410
+ if (oldDom && !oldDom.parentNode) oldDom = NULL;
365
411
  }
366
- oldDom = parentDom.insertBefore(parentVNode._dom, oldDom || NULL);
412
+
413
+ // Comments (e.g. server `$s` markers) are never ours: a node right after
414
+ // them is already in place.
415
+ let next = oldDom;
416
+ while (next && next.nodeType == 8) next = next.nextSibling;
417
+
418
+ if (parentVNode._dom != next) {
419
+ // Containers that aren't DOM nodes may not implement moveBefore()
420
+ if (!isMounting && parentDom.moveBefore && parentVNode._dom.parentNode) {
421
+ // @ts-expect-error This isn't added to TypeScript lib.d.ts yet
422
+ parentDom.moveBefore(parentVNode._dom, oldDom);
423
+ } else {
424
+ parentDom.insertBefore(parentVNode._dom, oldDom || NULL);
425
+ }
426
+ }
427
+ oldDom = parentVNode._dom;
367
428
  }
368
429
 
369
- do {
370
- oldDom = oldDom && oldDom.nextSibling;
371
- } while (oldDom != NULL && oldDom.nodeType == 8);
430
+ while ((oldDom = oldDom && oldDom.nextSibling) && oldDom.nodeType == 8);
372
431
 
373
432
  return oldDom;
374
433
  }
@@ -381,13 +440,14 @@ function insert(parentVNode, oldDom, parentDom) {
381
440
  */
382
441
  export function toChildArray(children, out) {
383
442
  out = out || [];
384
- if (children == NULL || typeof children == 'boolean') {
385
- } else if (isArray(children)) {
386
- children.some(child => {
387
- toChildArray(child, out);
388
- });
389
- } else {
390
- out.push(children);
443
+ if (children != NULL && typeof children != 'boolean') {
444
+ if (isArray(children)) {
445
+ children.some(child => {
446
+ toChildArray(child, out);
447
+ });
448
+ } else {
449
+ out.push(children);
450
+ }
391
451
  }
392
452
  return out;
393
453
  }
@@ -408,7 +468,7 @@ function findMatchingIndex(
408
468
  const key = childVNode.key;
409
469
  const type = childVNode.type;
410
470
  let oldVNode = oldChildren[skewedIndex];
411
- const matched = oldVNode != NULL && (oldVNode._flags & MATCHED) == 0;
471
+ const matched = oldVNode && !(oldVNode._flags & MATCHED);
412
472
 
413
473
  // We only need to perform a search if there are more children
414
474
  // (remainingOldChildren) to search. However, if the oldVNode we just looked
@@ -423,10 +483,12 @@ function findMatchingIndex(
423
483
  // we should not search as we risk re-using state of an unrelated VNode. (reverted for now)
424
484
  let shouldSearch =
425
485
  // (typeof type != 'function' || type === Fragment || key) &&
486
+ // The ternary keeps this a Smi comparison; `> matched` would compare
487
+ // number to boolean which V8 can't serve from the fast path.
426
488
  remainingOldChildren > (matched ? 1 : 0);
427
489
 
428
490
  if (
429
- (oldVNode === NULL && key == null) ||
491
+ (oldVNode === NULL && key == NULL) ||
430
492
  (matched && key == oldVNode.key && type == oldVNode.type)
431
493
  ) {
432
494
  return skewedIndex;
@@ -437,8 +499,8 @@ function findMatchingIndex(
437
499
  const childIndex = x >= 0 ? x-- : y++;
438
500
  oldVNode = oldChildren[childIndex];
439
501
  if (
440
- oldVNode != NULL &&
441
- (oldVNode._flags & MATCHED) == 0 &&
502
+ oldVNode &&
503
+ !(oldVNode._flags & MATCHED) &&
442
504
  key == oldVNode.key &&
443
505
  type == oldVNode.type
444
506
  ) {