@reckona/mreact-compat 0.0.91 → 0.0.93

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 (104) hide show
  1. package/README.md +1 -0
  2. package/dist/class-component.d.ts +22 -6
  3. package/dist/class-component.d.ts.map +1 -1
  4. package/dist/class-component.js +157 -51
  5. package/dist/class-component.js.map +1 -1
  6. package/dist/context.d.ts +19 -3
  7. package/dist/context.d.ts.map +1 -1
  8. package/dist/context.js +55 -6
  9. package/dist/context.js.map +1 -1
  10. package/dist/dom-children.d.ts +2 -0
  11. package/dist/dom-children.d.ts.map +1 -1
  12. package/dist/dom-children.js +103 -1
  13. package/dist/dom-children.js.map +1 -1
  14. package/dist/dom-host-rules.d.ts +10 -0
  15. package/dist/dom-host-rules.d.ts.map +1 -0
  16. package/dist/dom-host-rules.js +86 -0
  17. package/dist/dom-host-rules.js.map +1 -0
  18. package/dist/dom-props.d.ts +3 -2
  19. package/dist/dom-props.d.ts.map +1 -1
  20. package/dist/dom-props.js +229 -33
  21. package/dist/dom-props.js.map +1 -1
  22. package/dist/element.d.ts +9 -4
  23. package/dist/element.d.ts.map +1 -1
  24. package/dist/element.js +101 -26
  25. package/dist/element.js.map +1 -1
  26. package/dist/event-listeners.d.ts +4 -4
  27. package/dist/event-listeners.d.ts.map +1 -1
  28. package/dist/event-listeners.js +1 -1
  29. package/dist/event-listeners.js.map +1 -1
  30. package/dist/event-types.d.ts +10 -0
  31. package/dist/event-types.d.ts.map +1 -1
  32. package/dist/event-types.js.map +1 -1
  33. package/dist/events.js +22 -1
  34. package/dist/events.js.map +1 -1
  35. package/dist/fiber-commit.d.ts +2 -1
  36. package/dist/fiber-commit.d.ts.map +1 -1
  37. package/dist/fiber-commit.js +13 -1
  38. package/dist/fiber-commit.js.map +1 -1
  39. package/dist/fiber-reconciler.d.ts.map +1 -1
  40. package/dist/fiber-reconciler.js +28 -7
  41. package/dist/fiber-reconciler.js.map +1 -1
  42. package/dist/fiber-work-loop.d.ts.map +1 -1
  43. package/dist/fiber-work-loop.js +4 -3
  44. package/dist/fiber-work-loop.js.map +1 -1
  45. package/dist/fiber.d.ts +5 -0
  46. package/dist/fiber.d.ts.map +1 -1
  47. package/dist/fiber.js +9 -0
  48. package/dist/fiber.js.map +1 -1
  49. package/dist/hooks-entry.d.ts +3 -0
  50. package/dist/hooks-entry.d.ts.map +1 -0
  51. package/dist/hooks-entry.js +2 -0
  52. package/dist/hooks-entry.js.map +1 -0
  53. package/dist/hooks.d.ts +39 -5
  54. package/dist/hooks.d.ts.map +1 -1
  55. package/dist/hooks.js +373 -326
  56. package/dist/hooks.js.map +1 -1
  57. package/dist/host-reconciler.d.ts +3 -0
  58. package/dist/host-reconciler.d.ts.map +1 -1
  59. package/dist/host-reconciler.js +1183 -68
  60. package/dist/host-reconciler.js.map +1 -1
  61. package/dist/hydration.d.ts +1 -1
  62. package/dist/hydration.d.ts.map +1 -1
  63. package/dist/hydration.js.map +1 -1
  64. package/dist/index.d.ts +2 -1
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +2 -1
  67. package/dist/index.js.map +1 -1
  68. package/dist/react-default.d.ts +4 -4
  69. package/dist/react-default.d.ts.map +1 -1
  70. package/dist/react-default.js +2 -1
  71. package/dist/react-default.js.map +1 -1
  72. package/dist/reconciler.d.ts.map +1 -1
  73. package/dist/reconciler.js +38 -22
  74. package/dist/reconciler.js.map +1 -1
  75. package/dist/root.d.ts.map +1 -1
  76. package/dist/root.js +48 -13
  77. package/dist/root.js.map +1 -1
  78. package/dist/server-render.d.ts +6 -0
  79. package/dist/server-render.d.ts.map +1 -0
  80. package/dist/server-render.js +307 -0
  81. package/dist/server-render.js.map +1 -0
  82. package/package.json +6 -2
  83. package/src/class-component.ts +313 -51
  84. package/src/context.ts +108 -9
  85. package/src/dom-children.ts +155 -1
  86. package/src/dom-host-rules.ts +115 -0
  87. package/src/dom-props.ts +297 -46
  88. package/src/element.ts +141 -31
  89. package/src/event-listeners.ts +6 -6
  90. package/src/event-types.ts +10 -0
  91. package/src/events.ts +32 -10
  92. package/src/fiber-commit.ts +16 -1
  93. package/src/fiber-reconciler.ts +39 -6
  94. package/src/fiber-work-loop.ts +4 -3
  95. package/src/fiber.ts +14 -0
  96. package/src/hooks-entry.ts +24 -0
  97. package/src/hooks.ts +482 -479
  98. package/src/host-reconciler.ts +1662 -83
  99. package/src/hydration.ts +1 -1
  100. package/src/index.ts +1 -1
  101. package/src/react-default.ts +1 -1
  102. package/src/reconciler.ts +61 -22
  103. package/src/root.ts +55 -12
  104. package/src/server-render.ts +478 -0
@@ -1,14 +1,19 @@
1
- import { Activity, ERROR_BOUNDARY_TYPE, FORWARD_REF_TYPE, Fragment, LAZY_TYPE, MEMO_TYPE, Profiler, STRICT_MODE_TYPE, Suspense, SuspenseList, isReactCompatElement, isReactCompatPortal, } from "./element.js";
2
- import { isReactCompatConsumer, isReactCompatProvider, renderWithContextProvider, useContext, } from "./context.js";
1
+ import { Activity, ERROR_BOUNDARY_TYPE, FORWARD_REF_TYPE, Fragment, HOST_OWN_PROPS_META, LAZY_TYPE, MEMO_TYPE, Profiler, STRICT_MODE_TYPE, Suspense, SuspenseList, isReactCompatElement, isReactCompatPortal, } from "./element.js";
2
+ import { consumerContext, isReactCompatConsumer, isReactCompatProvider, renderWithContextProvider, useContext, } from "./context.js";
3
3
  import { applyPostChildFormProps, applyProps } from "./dom-props.js";
4
- import { syncChildNodes, syncScopedChildNodes } from "./dom-children.js";
4
+ import { syncChildNodes, syncOwnedChildNodes, syncScopedChildNodes } from "./dom-children.js";
5
5
  import { setLogicalEventParent } from "./host-event-binder.js";
6
+ import { NoFlags, Placement, Update } from "./fiber-flags.js";
7
+ import { createHostElement, hostElementMatches, isHostElement, namespaceForHostChildren, namespaceForHostElement, } from "./dom-host-rules.js";
6
8
  import { createFiber, createWorkInProgress } from "./fiber.js";
7
- import { renderWithRootRuntime, renderWithProfiler, renderWithStrictMode, restoreRuntimeSnapshot, takeRuntimeSnapshot, getDevToolsHookState, } from "./hooks.js";
9
+ import { renderWithRootRuntime, renderWithProfiler, renderWithStrictModeMemoCapture, renderStrictModeReplay, runWithHostCommit, restoreRuntimeSnapshot, takeRuntimeSnapshot, getDevToolsHookState, hasContextDependency, hasChangedContextDependency, } from "./hooks.js";
8
10
  import { isThenable } from "./thenable.js";
9
- import { isClassComponentType, recoverClassComponentError, renderClassComponentWithRuntime, } from "./class-component.js";
10
- import { areMemoPropsEqual, getPendingProps } from "./prop-comparison.js";
11
+ import { hasDirtyClassUpdate, isClassComponentType, recoverClassComponentError, renderClassComponentWithRuntime, } from "./class-component.js";
12
+ import { areMemoPropsEqual, getPendingProps, shallowEqual } from "./prop-comparison.js";
11
13
  import { reportElementTextMismatch, reportExtraHydrationNodes, reportHydrationNodeTypeMismatch, reportMissingHydrationNode, reportReactSuspenseServerError, reportRecoverable, withHydrationComponentStack, } from "./hydration.js";
14
+ const committedPortalContainers = new Set();
15
+ const SKIP_COMMIT_PATH = "\0";
16
+ const hasOwnProperty = Object.prototype.hasOwnProperty;
12
17
  let suspensePrimaryRenderDepth = 0;
13
18
  export function canRenderHostFiber(node) {
14
19
  if (node === null ||
@@ -66,9 +71,11 @@ export function canRenderHostFiber(node) {
66
71
  }
67
72
  export function renderHostFiberRoot(root, element, runtime, options = {}) {
68
73
  const workInProgress = createWorkInProgress(root.current, { children: element });
69
- const result = reconcileHostChild(workInProgress, root.current.child, element, runtime, options.previousNodes === undefined ? "0" : "", options);
74
+ const rootDocument = root.container.ownerDocument;
75
+ const result = reconcileHostChild(workInProgress, root.current.child, element, runtime, options.previousNodes === undefined ? "0" : "", { ...options, documentRef: options.documentRef ?? rootDocument });
70
76
  workInProgress.child = result.fiber;
71
77
  workInProgress.memoizedProps = { children: element };
78
+ root.refCleanupKnown = true;
72
79
  return workInProgress;
73
80
  }
74
81
  export function renderHydratingHostFiberRoot(root, element, runtime, scope, options = {}) {
@@ -85,35 +92,111 @@ export function renderHydratingHostFiberRoot(root, element, runtime, scope, opti
85
92
  });
86
93
  }
87
94
  export function commitHostFiberRoot(root, finishedWork, options = {}) {
88
- const nodes = commitHostChildren(finishedWork.child, root.container, root.container, "0", options);
89
- syncChildNodes(root.container, nodes);
95
+ runWithHostCommit(() => {
96
+ try {
97
+ committedPortalContainers.clear();
98
+ const commitPath = getRootCommitPath(options);
99
+ if (!hasChildListMutation(finishedWork)) {
100
+ commitHostDirtyChildren(finishedWork.child, root.container, root.container, commitPath, options);
101
+ return;
102
+ }
103
+ if (!finishedWork.childListChanged &&
104
+ finishedWork.subtreeChildListChanged &&
105
+ commitHostKeyedChildListMutation(finishedWork.child, root.container, root.container, commitPath, options)) {
106
+ return;
107
+ }
108
+ const nodes = commitHostChildren(finishedWork.child, root.container, root.container, commitPath, options);
109
+ syncChildNodes(root.container, nodes);
110
+ }
111
+ finally {
112
+ committedPortalContainers.clear();
113
+ }
114
+ });
90
115
  }
91
116
  export function commitHydratingHostFiberRoot(root, finishedWork, scope, options = {}) {
92
- const eventRoot = root.container;
93
- const nodes = commitHostChildren(finishedWork.child, scope.parent, eventRoot, "", options);
94
- syncScopedChildNodes(scope.parent, scope.before, scope.after, nodes);
117
+ runWithHostCommit(() => {
118
+ try {
119
+ committedPortalContainers.clear();
120
+ const eventRoot = root.container;
121
+ const nodes = commitHostChildren(finishedWork.child, scope.parent, eventRoot, "", options);
122
+ syncScopedChildNodes(scope.parent, scope.before, scope.after, nodes);
123
+ }
124
+ finally {
125
+ committedPortalContainers.clear();
126
+ }
127
+ });
95
128
  if (options.consumeResumeMarkers === true) {
96
129
  scope.before?.parentNode?.removeChild(scope.before);
97
130
  scope.after?.parentNode?.removeChild(scope.after);
98
131
  }
99
132
  }
100
133
  function reconcileHostChild(parent, currentFirstChild, node, runtime, path, options = {}) {
101
- const children = normalizeChildren(node);
102
- const existingByKey = collectExistingKeyedFibers(currentFirstChild);
134
+ resetFiberRefSubtree(parent);
135
+ parent.subtreeFlags = NoFlags;
136
+ parent.childListChanged = false;
137
+ parent.subtreeChildListChanged = false;
138
+ if (node === null || node === undefined || typeof node === "boolean") {
139
+ parent.childListChanged = currentFirstChild !== undefined;
140
+ return { fiber: undefined, consumed: 0 };
141
+ }
142
+ const children = Array.isArray(node) ? node : undefined;
143
+ const rowResult = children === undefined
144
+ ? undefined
145
+ : reconcileKeyedRowHostChildren(parent, currentFirstChild, children, options);
146
+ if (rowResult !== undefined) {
147
+ return rowResult;
148
+ }
149
+ const childCount = children === undefined ? 1 : children.length;
150
+ const hasKeyedChildren = children !== undefined && hasKeyedChild(children);
151
+ let existingByKey;
152
+ let currentKeyed = currentFirstChild;
103
153
  let currentUnkeyed = currentFirstChild;
104
154
  let first;
105
155
  let previous;
106
156
  let consumed = 0;
107
- children.forEach((child, index) => {
157
+ let skipRemainingKeyedLookup = false;
158
+ for (let index = 0; index < childCount; index += 1) {
159
+ const child = children === undefined ? node : children[index];
108
160
  const key = getNodeKey(child);
109
- const matchedCurrent = key === undefined ? currentUnkeyed : existingByKey.get(key);
161
+ let matchedCurrent;
162
+ if (key === undefined) {
163
+ matchedCurrent = currentUnkeyed;
164
+ }
165
+ else if (skipRemainingKeyedLookup) {
166
+ matchedCurrent = undefined;
167
+ }
168
+ else if (existingByKey !== undefined) {
169
+ matchedCurrent = existingByKey.get(key);
170
+ }
171
+ else if (currentKeyed?.key === key) {
172
+ matchedCurrent = currentKeyed;
173
+ currentKeyed = currentKeyed.sibling;
174
+ }
175
+ else if (children !== undefined &&
176
+ currentKeyed?.sibling?.key === key &&
177
+ canSkipSingleDeletedKeyedFiber(children, index, currentKeyed.sibling)) {
178
+ matchedCurrent = currentKeyed.sibling;
179
+ currentKeyed = currentKeyed.sibling.sibling;
180
+ }
181
+ else {
182
+ if (children !== undefined &&
183
+ hasKeyedChildren &&
184
+ canSkipRemainingKeyedLookup(currentKeyed, children, index)) {
185
+ skipRemainingKeyedLookup = true;
186
+ currentKeyed = undefined;
187
+ }
188
+ else if (hasKeyedChildren) {
189
+ existingByKey = collectExistingKeyedFibers(currentKeyed);
190
+ matchedCurrent = existingByKey.get(key);
191
+ }
192
+ }
110
193
  const previousNodes = options.previousNodes === undefined
111
194
  ? undefined
112
195
  : options.previousNodes.slice(consumed);
113
- const result = createHostFiber(parent, matchedCurrent, child, key, runtime, joinPath(path, getNodePathSegment(child, index)), previousNodes === undefined ? options : { ...options, previousNodes });
196
+ const result = createHostFiber(parent, matchedCurrent, child, key, runtime, getReconcileChildPath(path, child, index, options), previousNodes === undefined ? options : { ...options, previousNodes });
114
197
  const fiber = result.fiber;
115
198
  if (fiber === undefined) {
116
- return;
199
+ continue;
117
200
  }
118
201
  if (key === undefined) {
119
202
  currentUnkeyed = currentUnkeyed?.sibling;
@@ -127,7 +210,7 @@ function reconcileHostChild(parent, currentFirstChild, node, runtime, path, opti
127
210
  }
128
211
  fiber.return = parent;
129
212
  fiber.sibling = undefined;
130
- fiber.pendingProps = getPendingProps(child);
213
+ bubbleHostChild(parent, fiber);
131
214
  if (fiber.tag !== "memo" &&
132
215
  fiber.tag !== "function-component" &&
133
216
  fiber.tag !== "forward-ref" &&
@@ -138,10 +221,361 @@ function reconcileHostChild(parent, currentFirstChild, node, runtime, path, opti
138
221
  fiber.memoizedState = index;
139
222
  }
140
223
  previous = fiber;
141
- });
224
+ }
225
+ parent.childListChanged = childFiberListShapeChanged(currentFirstChild, first);
142
226
  return { fiber: first, consumed };
143
227
  }
228
+ function reconcileKeyedRowHostChildren(parent, currentFirstChild, children, options) {
229
+ if (children.length === 0 ||
230
+ currentFirstChild === undefined ||
231
+ options.previousNodes !== undefined ||
232
+ !shouldUseDirectHostTextChild()) {
233
+ return undefined;
234
+ }
235
+ let currentKeyed = currentFirstChild;
236
+ let first;
237
+ let previous;
238
+ let listShapeChanged = currentFirstChild === undefined;
239
+ let skipRemainingKeyedLookup = false;
240
+ let subtreeFlags = NoFlags;
241
+ let subtreeChildListChanged = false;
242
+ let hasRefSubtree = false;
243
+ const currentSiblingCount = countFiberSiblings(currentFirstChild);
244
+ const canReuseUnchangedRows = currentSiblingCount === children.length ||
245
+ isKeyedAppendOnly(currentFirstChild, children, currentSiblingCount);
246
+ const row = createKeyedRowHostElementScratch();
247
+ for (let index = 0; index < children.length; index += 1) {
248
+ const child = children[index];
249
+ if (!readKeyedRowHostElement(child, row)) {
250
+ return undefined;
251
+ }
252
+ let matchedCurrent;
253
+ if (skipRemainingKeyedLookup) {
254
+ matchedCurrent = undefined;
255
+ }
256
+ else if (currentKeyed === undefined) {
257
+ listShapeChanged = true;
258
+ skipRemainingKeyedLookup = true;
259
+ matchedCurrent = undefined;
260
+ }
261
+ else if (currentKeyed?.key === row.key) {
262
+ matchedCurrent = currentKeyed;
263
+ currentKeyed = currentKeyed.sibling;
264
+ }
265
+ else if (currentKeyed?.sibling?.key === row.key &&
266
+ canSkipSingleDeletedKeyedFiber(children, index, currentKeyed.sibling)) {
267
+ listShapeChanged = true;
268
+ matchedCurrent = currentKeyed.sibling;
269
+ currentKeyed = currentKeyed.sibling.sibling;
270
+ }
271
+ else if (canSkipRemainingKeyedLookup(currentKeyed, children, index)) {
272
+ listShapeChanged = true;
273
+ skipRemainingKeyedLookup = true;
274
+ currentKeyed = undefined;
275
+ matchedCurrent = undefined;
276
+ }
277
+ else {
278
+ return undefined;
279
+ }
280
+ const fiber = matchedCurrent === undefined
281
+ ? createKeyedRowHostFiber(parent, undefined, row, options)
282
+ : (canReuseUnchangedRows ? getReusableKeyedRowHostFiber(matchedCurrent, row) : undefined) ??
283
+ createKeyedRowHostFiber(parent, matchedCurrent, row, options);
284
+ if (first === undefined) {
285
+ first = fiber;
286
+ }
287
+ else if (previous !== undefined) {
288
+ previous.sibling = fiber;
289
+ }
290
+ fiber.return = parent;
291
+ fiber.sibling = undefined;
292
+ if (fiber.hasRefSubtree) {
293
+ hasRefSubtree = true;
294
+ }
295
+ subtreeFlags |= fiber.flags | fiber.subtreeFlags;
296
+ subtreeChildListChanged =
297
+ subtreeChildListChanged ||
298
+ fiber.childListChanged ||
299
+ fiber.subtreeChildListChanged;
300
+ if (fiber.memoizedState === undefined) {
301
+ fiber.memoizedState = index;
302
+ }
303
+ previous = fiber;
304
+ }
305
+ if (currentKeyed !== undefined) {
306
+ listShapeChanged = true;
307
+ }
308
+ parent.hasRefSubtree = hasRefSubtree;
309
+ parent.subtreeFlags = subtreeFlags;
310
+ parent.subtreeChildListChanged = subtreeChildListChanged;
311
+ parent.childListChanged = listShapeChanged;
312
+ return { fiber: first, consumed: 0 };
313
+ }
314
+ function countFiberSiblings(first) {
315
+ let count = 0;
316
+ let cursor = first;
317
+ while (cursor !== undefined) {
318
+ count += 1;
319
+ cursor = cursor.sibling;
320
+ }
321
+ return count;
322
+ }
323
+ function isKeyedAppendOnly(currentFirstChild, children, currentSiblingCount) {
324
+ if (children.length <= currentSiblingCount) {
325
+ return false;
326
+ }
327
+ let current = currentFirstChild;
328
+ for (let index = 0; index < currentSiblingCount; index += 1) {
329
+ if (current === undefined || current.key !== getNodeKey(children[index])) {
330
+ return false;
331
+ }
332
+ current = current.sibling;
333
+ }
334
+ return current === undefined;
335
+ }
336
+ function getReusableKeyedRowHostFiber(current, row) {
337
+ if (current.tag !== "host-component" ||
338
+ current.type !== row.type ||
339
+ current.hydrateExisting ||
340
+ current.child !== undefined ||
341
+ !isHostElement(current.stateNode)) {
342
+ return undefined;
343
+ }
344
+ const previousProps = current.memoizedProps ?? current.pendingProps;
345
+ if (typeof previousProps !== "object" || previousProps === null) {
346
+ return undefined;
347
+ }
348
+ const previousRecord = previousProps;
349
+ if (getHostOwnPropsMeta(previousRecord) !== row.meta ||
350
+ getDirectHostTextChild(previousRecord.children) !== row.text) {
351
+ return undefined;
352
+ }
353
+ current.pendingProps = row.element.props;
354
+ current.flags = NoFlags;
355
+ current.subtreeFlags = NoFlags;
356
+ current.childListChanged = false;
357
+ current.subtreeChildListChanged = false;
358
+ current.hostChildListChanged = false;
359
+ current.hasRefSubtree = false;
360
+ return current;
361
+ }
362
+ function createKeyedRowHostElementScratch() {
363
+ return {
364
+ element: undefined,
365
+ key: "",
366
+ type: "",
367
+ meta: 0,
368
+ text: "",
369
+ };
370
+ }
371
+ function readKeyedRowHostElement(node, row) {
372
+ if (!isReactCompatElement(node) ||
373
+ typeof node.type !== "string" ||
374
+ node.key === null ||
375
+ node.ref !== null) {
376
+ return false;
377
+ }
378
+ const props = node.props;
379
+ const meta = getHostOwnPropsMeta(props);
380
+ const text = meta === undefined ? undefined : getDirectHostTextChild(props.children);
381
+ if (meta === undefined || text === undefined) {
382
+ return false;
383
+ }
384
+ row.element = node;
385
+ row.key = node.key;
386
+ row.type = node.type;
387
+ row.meta = meta;
388
+ row.text = text;
389
+ return true;
390
+ }
391
+ function createKeyedRowHostFiber(parent, current, row, options) {
392
+ const node = row.element;
393
+ const elementNamespace = namespaceForHostElement(options.namespace ?? "html", row.type);
394
+ const fiber = current?.tag === "host-component" && current.type === row.type
395
+ ? createWorkInProgress(current, node.props)
396
+ : createFiber("host-component", node.props, row.key);
397
+ fiber.type = row.type;
398
+ fiber.stateNode =
399
+ current?.tag === "host-component" &&
400
+ current.type === row.type &&
401
+ isHostElement(current.stateNode) &&
402
+ hostElementMatches(current.stateNode, row.type, elementNamespace)
403
+ ? current.stateNode
404
+ : createHostElement(getDocumentRef(options), row.type, options.namespace ?? "html");
405
+ fiber.child = undefined;
406
+ fiber.pendingProps = node.props;
407
+ fiber.hostChildListChanged = false;
408
+ fiber.hasRefSubtree = false;
409
+ if (current === undefined || fiber.alternate !== current) {
410
+ fiber.flags |= Placement;
411
+ fiber.hostChildListChanged = true;
412
+ return fiber;
413
+ }
414
+ const previousProps = current.memoizedProps ?? current.pendingProps;
415
+ const previousMeta = typeof previousProps === "object" && previousProps !== null
416
+ ? getHostOwnPropsMeta(previousProps)
417
+ : undefined;
418
+ const previousText = getDirectHostTextChild(hostFiberChildrenProp(previousProps));
419
+ if (previousMeta !== row.meta || previousText !== row.text) {
420
+ fiber.flags |= Update;
421
+ }
422
+ return fiber;
423
+ }
424
+ function canReuseStaticHostSubtree(fiber) {
425
+ let cursor = fiber;
426
+ while (cursor !== undefined) {
427
+ if (cursor.tag !== "host-component" &&
428
+ cursor.tag !== "host-text" &&
429
+ cursor.tag !== "fragment" &&
430
+ cursor.tag !== "strict-mode") {
431
+ return false;
432
+ }
433
+ if (cursor.child !== undefined && !canReuseStaticHostSubtree(cursor.child)) {
434
+ return false;
435
+ }
436
+ cursor = cursor.sibling;
437
+ }
438
+ return true;
439
+ }
440
+ function canSkipSingleDeletedKeyedFiber(children, index, matched) {
441
+ const nextKey = index + 1 < children.length ? getNodeKey(children[index + 1]) : undefined;
442
+ const afterMatched = matched.sibling;
443
+ return nextKey === undefined ? afterMatched === undefined : afterMatched?.key === nextKey;
444
+ }
445
+ function canSkipRemainingKeyedLookup(current, children, startIndex) {
446
+ const currentRange = readContiguousNumericFiberKeyRange(current);
447
+ if (currentRange === undefined) {
448
+ return false;
449
+ }
450
+ const nextRange = readContiguousNumericNodeKeyRange(children, startIndex);
451
+ if (nextRange === undefined) {
452
+ return false;
453
+ }
454
+ return (currentRange.end < nextRange.start ||
455
+ nextRange.end < currentRange.start);
456
+ }
457
+ function readContiguousNumericFiberKeyRange(fiber) {
458
+ let cursor = fiber;
459
+ let start;
460
+ let previous;
461
+ while (cursor !== undefined) {
462
+ const value = parseNumericKey(cursor.key);
463
+ if (value === undefined || (previous !== undefined && value !== previous + 1)) {
464
+ return undefined;
465
+ }
466
+ start ??= value;
467
+ previous = value;
468
+ cursor = cursor.sibling;
469
+ }
470
+ return start === undefined || previous === undefined
471
+ ? undefined
472
+ : { start, end: previous };
473
+ }
474
+ function readContiguousNumericNodeKeyRange(children, startIndex) {
475
+ let start;
476
+ let previous;
477
+ for (let index = startIndex; index < children.length; index += 1) {
478
+ const value = parseNumericKey(getNodeKey(children[index]));
479
+ if (value === undefined || (previous !== undefined && value !== previous + 1)) {
480
+ return undefined;
481
+ }
482
+ start ??= value;
483
+ previous = value;
484
+ }
485
+ return start === undefined || previous === undefined
486
+ ? undefined
487
+ : { start, end: previous };
488
+ }
489
+ function parseNumericKey(key) {
490
+ if (key === undefined || key.length === 0) {
491
+ return undefined;
492
+ }
493
+ const value = Number(key);
494
+ return Number.isSafeInteger(value) && String(value) === key ? value : undefined;
495
+ }
496
+ function childFiberListShapeChanged(current, next) {
497
+ let currentCursor = current;
498
+ let nextCursor = next;
499
+ while (currentCursor !== undefined && nextCursor !== undefined) {
500
+ const isSameSlot = nextCursor === currentCursor ||
501
+ nextCursor.alternate === currentCursor;
502
+ if (!isSameSlot ||
503
+ currentCursor.tag !== nextCursor.tag ||
504
+ currentCursor.type !== nextCursor.type ||
505
+ currentCursor.key !== nextCursor.key) {
506
+ return true;
507
+ }
508
+ currentCursor = currentCursor.sibling;
509
+ nextCursor = nextCursor.sibling;
510
+ }
511
+ return currentCursor !== undefined || nextCursor !== undefined;
512
+ }
513
+ function bubbleHostChild(parent, child) {
514
+ if (child.hasRefSubtree) {
515
+ parent.hasRefSubtree = true;
516
+ }
517
+ parent.subtreeFlags |= child.flags | child.subtreeFlags;
518
+ parent.subtreeChildListChanged =
519
+ parent.subtreeChildListChanged ||
520
+ child.childListChanged ||
521
+ child.subtreeChildListChanged;
522
+ }
523
+ function resetFiberRefSubtree(fiber) {
524
+ fiber.hasRefSubtree = false;
525
+ }
526
+ function includeNodeRef(fiber, node) {
527
+ fiber.hasRefSubtree =
528
+ fiber.hasRefSubtree ||
529
+ (isReactCompatElement(node) && node.ref !== null);
530
+ }
531
+ function markHostFiberEffects(fiber, current, node) {
532
+ if (current === undefined || fiber.alternate !== current) {
533
+ fiber.flags |= Placement;
534
+ fiber.hostChildListChanged = true;
535
+ return;
536
+ }
537
+ if (fiber.tag === "host-text") {
538
+ if (!Object.is(current.memoizedProps ?? current.pendingProps, fiber.pendingProps)) {
539
+ fiber.flags |= Update;
540
+ }
541
+ return;
542
+ }
543
+ if (fiber.tag !== "host-component") {
544
+ return;
545
+ }
546
+ const previousProps = current.memoizedProps ?? current.pendingProps;
547
+ const nextProps = fiber.pendingProps;
548
+ fiber.hostChildListChanged = hostChildListChanged(previousProps, nextProps);
549
+ if (!hostOwnPropsEqual(previousProps, nextProps) || hostDirectTextChildChanged(previousProps, nextProps)) {
550
+ fiber.flags |= Update;
551
+ }
552
+ if (isReactCompatElement(node) && node.ref !== null) {
553
+ fiber.flags |= Update;
554
+ }
555
+ }
144
556
  function createHostFiber(parent, current, node, key, runtime, path, options = {}) {
557
+ const result = createHostFiberImpl(parent, current, node, key, runtime, path, options);
558
+ if (result.fiber !== undefined) {
559
+ if (canFinalizeNewHostFiber(result.fiber, current, node, options)) {
560
+ result.fiber.flags |= Placement;
561
+ result.fiber.hostChildListChanged = true;
562
+ return result;
563
+ }
564
+ result.fiber.pendingProps = getPendingProps(node);
565
+ includeNodeRef(result.fiber, node);
566
+ markHostFiberEffects(result.fiber, current, node);
567
+ }
568
+ return result;
569
+ }
570
+ function canFinalizeNewHostFiber(fiber, current, node, options) {
571
+ return (current === undefined &&
572
+ options.previousNodes === undefined &&
573
+ fiber.tag === "host-component" &&
574
+ isReactCompatElement(node) &&
575
+ node.ref === null &&
576
+ typeof node.type === "string");
577
+ }
578
+ function createHostFiberImpl(parent, current, node, key, runtime, path, options = {}) {
145
579
  if (node === null || node === undefined || typeof node === "boolean") {
146
580
  return { fiber: undefined, consumed: 0 };
147
581
  }
@@ -161,7 +595,7 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
161
595
  ? existing
162
596
  : current?.tag === "host-text" && current.stateNode instanceof Text
163
597
  ? current.stateNode
164
- : document.createTextNode("");
598
+ : getDocumentRef(options).createTextNode("");
165
599
  if (existing instanceof Text && existing.data !== String(node)) {
166
600
  reportRecoverable(options, "text", path, new Error("Hydration text mismatch."));
167
601
  }
@@ -267,7 +701,7 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
267
701
  const render = typeof children === "function"
268
702
  ? children
269
703
  : () => null;
270
- const childResult = reconcileHostChild(fiber, current?.tag === "context-consumer" ? current.child : undefined, render(useContext(node.type.context)), runtime, `${path}.consumer`, options);
704
+ const childResult = reconcileHostChild(fiber, current?.tag === "context-consumer" ? current.child : undefined, render(useContext(consumerContext(node.type))), runtime, `${path}.consumer`, options);
271
705
  fiber.child = childResult.fiber;
272
706
  return { fiber, consumed: childResult.consumed };
273
707
  }
@@ -280,7 +714,7 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
280
714
  ? createWorkInProgress(current, node.props)
281
715
  : createFiber("forward-ref", node.props, key);
282
716
  fiber.type = forwardRefType;
283
- const rendered = renderWithRootRuntime(runtime, path, () => forwardRefType.render(node.props, node.ref));
717
+ const rendered = renderWithRootRuntime(runtime, path, () => forwardRefType.render(node.props, node.ref), forwardRefType);
284
718
  fiber.memoizedState = getDevToolsHookState(runtime, path);
285
719
  const childOptions = withHydrationComponentStack(options, getComponentName(forwardRefType.render));
286
720
  const childResult = reconcileHostChild(fiber, current?.tag === "forward-ref" ? current.child : undefined, rendered, runtime, `${path}.forwardRef`, childOptions);
@@ -301,7 +735,8 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
301
735
  : createFiber("memo", node.props, key);
302
736
  fiber.type = memoType;
303
737
  if (previousMemoState !== undefined &&
304
- !hasDirtyInstance(runtime, previousMemoState.instanceKeys) &&
738
+ !hasDirtyInstance(runtime, previousMemoState.instanceKeys, memoPath) &&
739
+ !hasUnflushedMountEffectInstance(runtime, previousMemoState.instanceKeys) &&
305
740
  areMemoPropsEqual(memoType, previousMemoState.props, node.props)) {
306
741
  markActiveInstanceKeys(runtime, previousMemoState.instanceKeys);
307
742
  fiber.child = current?.child;
@@ -314,6 +749,11 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
314
749
  };
315
750
  const childResult = createHostFiber(fiber, current?.tag === "memo" ? current.child : undefined, renderedElement, key, runtime, memoPath, options);
316
751
  fiber.child = childResult.fiber;
752
+ if (fiber.child !== undefined) {
753
+ fiber.child.return = fiber;
754
+ fiber.child.sibling = undefined;
755
+ bubbleHostChild(fiber, fiber.child);
756
+ }
317
757
  fiber.memoizedState = {
318
758
  props: { ...node.props },
319
759
  instanceKeys: collectInstanceKeys(runtime, memoPath),
@@ -336,6 +776,11 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
336
776
  };
337
777
  const childResult = createHostFiber(fiber, current?.tag === "lazy" ? current.child : undefined, renderedElement, key, runtime, `${path}.lazy`, options);
338
778
  fiber.child = childResult.fiber;
779
+ if (fiber.child !== undefined) {
780
+ fiber.child.return = fiber;
781
+ fiber.child.sibling = undefined;
782
+ bubbleHostChild(fiber, fiber.child);
783
+ }
339
784
  return { fiber, consumed: childResult.consumed };
340
785
  }
341
786
  if (lazyType.status === "rejected") {
@@ -371,7 +816,16 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
371
816
  ? createWorkInProgress(current, node.props)
372
817
  : createFiber("class-component", node.props, key);
373
818
  fiber.type = classType;
374
- const rendered = renderClassComponentWithRuntime(classType, node.props, runtime, path);
819
+ const previousClassChildKeys = collectInstanceKeys(runtime, `${path}.class`);
820
+ const currentClassInstance = current?.tag === "class-component" && current.type === classType
821
+ ? current.stateNode
822
+ : undefined;
823
+ const rendered = renderClassComponentWithRuntime(classType, node.props, runtime, path, {
824
+ ...(currentClassInstance === undefined
825
+ ? {}
826
+ : { currentInstance: currentClassInstance }),
827
+ hasDirtyDescendant: hasDirtyInstance(runtime, previousClassChildKeys, `${path}.class`),
828
+ });
375
829
  applyRef(node.ref, rendered.kind === "skip" ? current?.stateNode : rendered.instance);
376
830
  if (rendered.kind === "skip") {
377
831
  fiber.child = current?.child;
@@ -397,31 +851,62 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
397
851
  if (runtime === undefined) {
398
852
  return { fiber: undefined, consumed: 0 };
399
853
  }
854
+ const previousFunctionState = current?.tag === "function-component"
855
+ ? current.stateNode
856
+ : undefined;
400
857
  const fiber = current?.tag === "function-component" && current.type === node.type
401
858
  ? createWorkInProgress(current, node.props)
402
859
  : createFiber("function-component", node.props, key);
403
860
  fiber.type = node.type;
404
- const rendered = renderWithRootRuntime(runtime, path, () => node.type(node.props));
861
+ const canReuseSameElement = previousFunctionState !== undefined &&
862
+ previousFunctionState.hasContextDependencies !== true &&
863
+ previousFunctionState.element === node;
864
+ const canReuseExternalStoreSnapshot = previousFunctionState !== undefined &&
865
+ runtime.externalStoreUpdate &&
866
+ shallowEqual(previousFunctionState.props, node.props) &&
867
+ !hasChangedContextDependency(runtime, previousFunctionState.instanceKeys);
868
+ if (runtime.strictReplayDepth === 0 &&
869
+ previousFunctionState !== undefined &&
870
+ (canReuseSameElement || canReuseExternalStoreSnapshot) &&
871
+ !hasDirtyInstance(runtime, previousFunctionState.instanceKeys, path) &&
872
+ !hasUnflushedMountEffectInstance(runtime, previousFunctionState.instanceKeys) &&
873
+ !hasPendingAsyncChild(current?.child)) {
874
+ markActiveInstanceKeys(runtime, previousFunctionState.instanceKeys);
875
+ fiber.child = current?.child;
876
+ fiber.memoizedState = current?.memoizedState;
877
+ fiber.stateNode = previousFunctionState;
878
+ return { fiber, consumed: options.previousNodes?.length ?? 0 };
879
+ }
880
+ const rendered = renderWithRootRuntime(runtime, path, () => node.type(node.props), node.type);
405
881
  fiber.memoizedState = getDevToolsHookState(runtime, path);
406
882
  const childOptions = withHydrationComponentStack(options, getComponentName(node.type));
407
883
  const childResult = reconcileHostChild(fiber, current?.tag === "function-component" ? current.child : undefined, rendered, runtime, `${path}.0`, childOptions);
408
884
  fiber.child = childResult.fiber;
885
+ const instanceKeys = collectInstanceKeys(runtime, path);
886
+ fiber.stateNode = {
887
+ element: node,
888
+ props: { ...node.props },
889
+ instanceKeys,
890
+ hasContextDependencies: hasContextDependency(runtime, instanceKeys),
891
+ };
409
892
  return { fiber, consumed: childResult.consumed };
410
893
  }
411
894
  if (typeof node.type !== "string") {
412
895
  return { fiber: undefined, consumed: 0 };
413
896
  }
897
+ const elementNamespace = namespaceForHostElement(options.namespace ?? "html", node.type);
898
+ const childNamespace = namespaceForHostChildren(elementNamespace, node.type);
414
899
  const fiber = current?.tag === "host-component" && current.type === node.type
415
900
  ? createWorkInProgress(current, node.props)
416
901
  : createFiber("host-component", node.props, key);
417
902
  const existing = options.previousNodes?.[0];
418
- const existingElement = existing instanceof HTMLElement ? existing : undefined;
903
+ const existingElement = isHostElement(existing) ? existing : undefined;
419
904
  const tagMatches = existingElement !== undefined &&
420
- existingElement.tagName.toLowerCase() === node.type;
905
+ hostElementMatches(existingElement, node.type, elementNamespace);
421
906
  if (existing === undefined && options.previousNodes !== undefined) {
422
907
  reportMissingHydrationNode(options, path);
423
908
  }
424
- else if (existing !== undefined && !(existing instanceof HTMLElement)) {
909
+ else if (existing !== undefined && !isHostElement(existing)) {
425
910
  reportHydrationNodeTypeMismatch(options, path, `<${node.type}>`, existing);
426
911
  }
427
912
  if (existingElement !== undefined && !tagMatches) {
@@ -434,16 +919,40 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
434
919
  ? existingElement
435
920
  : current?.tag === "host-component" &&
436
921
  current.type === node.type &&
437
- current.stateNode instanceof HTMLElement
922
+ isHostElement(current.stateNode) &&
923
+ hostElementMatches(current.stateNode, node.type, elementNamespace)
438
924
  ? current.stateNode
439
- : document.createElement(node.type);
925
+ : createHostElement(getDocumentRef(options), node.type, options.namespace ?? "html");
440
926
  fiber.hydrateExisting = tagMatches && options.previousNodes !== undefined;
441
927
  const previousChildNodes = tagMatches && existingElement !== undefined
442
928
  ? Array.from(existingElement.childNodes)
443
929
  : undefined;
444
- const childResult = reconcileHostChild(fiber, current?.tag === "host-component" ? current.child : undefined, node.props.children, runtime, `${path}.c`, previousChildNodes === undefined
445
- ? options
446
- : { ...options, previousNodes: previousChildNodes });
930
+ const directTextChild = shouldUseDirectHostTextChild() && previousChildNodes === undefined
931
+ ? getDirectHostTextChild(node.props.children)
932
+ : undefined;
933
+ if (previousChildNodes === undefined &&
934
+ current?.tag === "host-component" &&
935
+ current.type === node.type &&
936
+ Object.is(hostFiberChildrenProp(current.memoizedProps), node.props.children) &&
937
+ !hasDirtyInstance(runtime, [], `${path}.c`) &&
938
+ canReuseStaticHostSubtree(current.child)) {
939
+ fiber.child = current.child;
940
+ if (fiber.child !== undefined) {
941
+ fiber.child.return = fiber;
942
+ }
943
+ parent.child ??= fiber;
944
+ return { fiber, consumed: existing === undefined ? 0 : 1 };
945
+ }
946
+ if (directTextChild !== undefined) {
947
+ fiber.child = undefined;
948
+ parent.child ??= fiber;
949
+ return { fiber, consumed: existing === undefined ? 0 : 1 };
950
+ }
951
+ const childResult = reconcileHostChild(fiber, current?.tag === "host-component" ? current.child : undefined, node.props.children, runtime, `${path}.c`, {
952
+ ...options,
953
+ namespace: childNamespace,
954
+ ...(previousChildNodes === undefined ? {} : { previousNodes: previousChildNodes }),
955
+ });
447
956
  fiber.child = childResult.fiber;
448
957
  if (previousChildNodes !== undefined) {
449
958
  reportExtraHydrationNodes(options, `${path}.c`, previousChildNodes, childResult.consumed);
@@ -461,86 +970,416 @@ function commitHostChildren(fiber, parent, eventRoot, path, options = {}) {
461
970
  let cursor = fiber;
462
971
  let index = 0;
463
972
  while (cursor !== undefined) {
464
- nodes.push(...commitHostFiber(cursor, parent, eventRoot, joinPath(path, String(index)), options));
973
+ for (const node of commitHostFiber(cursor, parent, eventRoot, joinCommitPath(path, String(index)), options)) {
974
+ nodes.push(node);
975
+ }
465
976
  cursor = cursor.sibling;
466
977
  index += 1;
467
978
  }
468
979
  return nodes;
469
980
  }
981
+ function commitHostDirtyChildren(fiber, parent, eventRoot, path, options = {}) {
982
+ let cursor = fiber;
983
+ let index = 0;
984
+ while (cursor !== undefined) {
985
+ if (hasHostCommitWork(cursor)) {
986
+ commitHostDirtyFiber(cursor, parent, eventRoot, joinCommitPath(path, String(index)), options);
987
+ }
988
+ cursor = cursor.sibling;
989
+ index += 1;
990
+ }
991
+ }
992
+ function commitHostDirtyFiber(fiber, parent, eventRoot, path, options = {}) {
993
+ if (fiber.tag === "host-text") {
994
+ commitHostFiber(fiber, parent, eventRoot, path, options);
995
+ return;
996
+ }
997
+ if (fiber.tag === "host-component") {
998
+ const element = fiber.stateNode;
999
+ if (!isHostElement(element)) {
1000
+ finishCommittedFiber(fiber);
1001
+ return;
1002
+ }
1003
+ const props = fiber.pendingProps;
1004
+ const propsAreUnchanged = fiber.hydrateExisting !== true &&
1005
+ hostPropsEqual(fiber.memoizedProps, props);
1006
+ const propsAreChildrenOnly = fiber.hydrateExisting !== true &&
1007
+ hostPropsAreChildrenOnly(fiber.memoizedProps) &&
1008
+ hostPropsAreChildrenOnly(props);
1009
+ const textOnlyRowUpdate = fiber.hydrateExisting !== true &&
1010
+ isRowTextOnlyUpdate(fiber.memoizedProps, props);
1011
+ if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
1012
+ applyProps(element, props, path, {
1013
+ ...options,
1014
+ eventRoot,
1015
+ preserveHydrationAttributes: fiber.hydrateExisting,
1016
+ });
1017
+ applyRef(props.ref, element);
1018
+ }
1019
+ const directTextChild = fiber.child === undefined && fiber.hydrateExisting !== true
1020
+ ? getDirectHostTextChild(props.children)
1021
+ : undefined;
1022
+ if (directTextChild !== undefined) {
1023
+ syncDirectHostTextChild(element, directTextChild);
1024
+ }
1025
+ else if (fiber.subtreeFlags !== NoFlags) {
1026
+ commitHostDirtyChildren(fiber.child, element, eventRoot, `${path}.c`, options);
1027
+ }
1028
+ if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
1029
+ applyPostChildFormProps(element, props);
1030
+ }
1031
+ fiber.memoizedProps = props;
1032
+ finishCommittedFiber(fiber);
1033
+ return;
1034
+ }
1035
+ if (fiber.tag === "portal") {
1036
+ const container = fiber.stateNode;
1037
+ if (container instanceof Element) {
1038
+ setLogicalEventParent(container, parent);
1039
+ commitHostDirtyChildren(fiber.child, container, container, `${path}.portal`, options);
1040
+ }
1041
+ fiber.memoizedProps = fiber.pendingProps;
1042
+ finishCommittedFiber(fiber);
1043
+ return;
1044
+ }
1045
+ if (fiber.subtreeFlags !== NoFlags) {
1046
+ commitHostDirtyChildren(fiber.child, parent, eventRoot, path, options);
1047
+ }
1048
+ fiber.memoizedProps = fiber.pendingProps;
1049
+ finishCommittedFiber(fiber);
1050
+ }
1051
+ function hasHostCommitWork(fiber) {
1052
+ return (fiber.flags !== NoFlags ||
1053
+ fiber.subtreeFlags !== NoFlags ||
1054
+ fiber.hostChildListChanged ||
1055
+ fiber.childListChanged ||
1056
+ fiber.subtreeChildListChanged ||
1057
+ fiber.hydrateExisting);
1058
+ }
1059
+ function commitHostKeyedChildListMutation(fiber, parent, eventRoot, path, options = {}) {
1060
+ let cursor = fiber;
1061
+ let index = 0;
1062
+ let committed = false;
1063
+ while (cursor !== undefined) {
1064
+ if (!hasHostCommitWork(cursor)) {
1065
+ cursor = cursor.sibling;
1066
+ index += 1;
1067
+ continue;
1068
+ }
1069
+ const childPath = joinCommitPath(path, String(index));
1070
+ const didCommit = commitHostKeyedChildListMutationFiber(cursor, parent, eventRoot, childPath, options);
1071
+ if (!didCommit) {
1072
+ return false;
1073
+ }
1074
+ committed = true;
1075
+ cursor = cursor.sibling;
1076
+ index += 1;
1077
+ }
1078
+ return committed;
1079
+ }
1080
+ function commitHostKeyedChildListMutationFiber(fiber, parent, eventRoot, path, options = {}) {
1081
+ if (fiber.childListChanged) {
1082
+ const mutationParent = fiber.tag === "host-component" && isHostElement(fiber.stateNode)
1083
+ ? fiber.stateNode
1084
+ : parent;
1085
+ if (fiber.tag === "host-component" && !isHostElement(fiber.stateNode)) {
1086
+ return false;
1087
+ }
1088
+ if (commitHostAppendSuffix(fiber, mutationParent, eventRoot, path, options)) {
1089
+ finishHostPassthroughFiber(fiber);
1090
+ return true;
1091
+ }
1092
+ if (commitHostSingleRemoval(fiber, mutationParent)) {
1093
+ finishHostPassthroughFiber(fiber);
1094
+ return true;
1095
+ }
1096
+ return false;
1097
+ }
1098
+ if (fiber.subtreeChildListChanged) {
1099
+ if (fiber.tag === "host-component") {
1100
+ const element = fiber.stateNode;
1101
+ if (!isHostElement(element)) {
1102
+ return false;
1103
+ }
1104
+ if (!commitHostKeyedChildListMutation(fiber.child, element, eventRoot, `${path}.c`, options)) {
1105
+ return false;
1106
+ }
1107
+ finishHostPassthroughFiber(fiber);
1108
+ return true;
1109
+ }
1110
+ if (!commitHostKeyedChildListMutation(fiber.child, parent, eventRoot, path, options)) {
1111
+ return false;
1112
+ }
1113
+ finishHostPassthroughFiber(fiber);
1114
+ return true;
1115
+ }
1116
+ commitHostDirtyFiber(fiber, parent, eventRoot, path, options);
1117
+ return true;
1118
+ }
1119
+ function commitHostAppendSuffix(fiber, parent, eventRoot, path, options) {
1120
+ const append = getPlacementAppendSuffix(fiber.child) ?? getAppendSuffix(fiber.alternate?.child, fiber.child);
1121
+ if (append === undefined) {
1122
+ return false;
1123
+ }
1124
+ let cursor = append.fiber;
1125
+ let index = append.index;
1126
+ while (cursor !== undefined) {
1127
+ for (const node of commitHostFiber(cursor, parent, eventRoot, joinCommitPath(path, String(index)), options)) {
1128
+ parent.appendChild(node);
1129
+ }
1130
+ cursor = cursor.sibling;
1131
+ index += 1;
1132
+ }
1133
+ return true;
1134
+ }
1135
+ function getPlacementAppendSuffix(next) {
1136
+ let nextCursor = next;
1137
+ let index = 0;
1138
+ while (nextCursor !== undefined) {
1139
+ if ((nextCursor.flags & Placement) !== NoFlags) {
1140
+ if (index === 0) {
1141
+ return undefined;
1142
+ }
1143
+ let appendCursor = nextCursor;
1144
+ while (appendCursor !== undefined) {
1145
+ if ((appendCursor.flags & Placement) === NoFlags) {
1146
+ return undefined;
1147
+ }
1148
+ appendCursor = appendCursor.sibling;
1149
+ }
1150
+ return { fiber: nextCursor, index };
1151
+ }
1152
+ if (hasHostCommitWork(nextCursor)) {
1153
+ return undefined;
1154
+ }
1155
+ nextCursor = nextCursor.sibling;
1156
+ index += 1;
1157
+ }
1158
+ return undefined;
1159
+ }
1160
+ function commitHostSingleRemoval(fiber, parent) {
1161
+ const removed = getSingleRemovedFiber(fiber.alternate?.child, fiber.child);
1162
+ if (removed === undefined) {
1163
+ return false;
1164
+ }
1165
+ let removedAny = false;
1166
+ for (const node of collectCommittedHostNodes(removed)) {
1167
+ if (node.parentNode !== parent) {
1168
+ return false;
1169
+ }
1170
+ parent.removeChild(node);
1171
+ removedAny = true;
1172
+ }
1173
+ return removedAny;
1174
+ }
1175
+ function getAppendSuffix(current, next) {
1176
+ let currentCursor = current;
1177
+ let nextCursor = next;
1178
+ let index = 0;
1179
+ while (currentCursor !== undefined && nextCursor !== undefined) {
1180
+ if (!isSameFiberSlot(currentCursor, nextCursor) || hasHostCommitWork(nextCursor)) {
1181
+ return undefined;
1182
+ }
1183
+ currentCursor = currentCursor.sibling;
1184
+ nextCursor = nextCursor.sibling;
1185
+ index += 1;
1186
+ }
1187
+ if (currentCursor !== undefined || nextCursor === undefined) {
1188
+ return undefined;
1189
+ }
1190
+ return { fiber: nextCursor, index };
1191
+ }
1192
+ function getSingleRemovedFiber(current, next) {
1193
+ let currentCursor = current;
1194
+ let nextCursor = next;
1195
+ while (currentCursor !== undefined && nextCursor !== undefined) {
1196
+ if (!isSameFiberSlot(currentCursor, nextCursor)) {
1197
+ break;
1198
+ }
1199
+ if (hasHostCommitWork(nextCursor)) {
1200
+ return undefined;
1201
+ }
1202
+ currentCursor = currentCursor.sibling;
1203
+ nextCursor = nextCursor.sibling;
1204
+ }
1205
+ if (currentCursor === undefined) {
1206
+ return undefined;
1207
+ }
1208
+ const removed = currentCursor;
1209
+ currentCursor = currentCursor.sibling;
1210
+ while (currentCursor !== undefined && nextCursor !== undefined) {
1211
+ if (!isSameFiberSlot(currentCursor, nextCursor) || hasHostCommitWork(nextCursor)) {
1212
+ return undefined;
1213
+ }
1214
+ currentCursor = currentCursor.sibling;
1215
+ nextCursor = nextCursor.sibling;
1216
+ }
1217
+ return currentCursor === undefined && nextCursor === undefined ? removed : undefined;
1218
+ }
1219
+ function isSameFiberSlot(current, next) {
1220
+ return ((next === current || next.alternate === current) &&
1221
+ current.tag === next.tag &&
1222
+ current.type === next.type &&
1223
+ current.key === next.key);
1224
+ }
1225
+ function collectCommittedHostNodes(fiber) {
1226
+ if ((fiber.tag === "host-component" || fiber.tag === "host-text") &&
1227
+ fiber.stateNode instanceof Node) {
1228
+ return [fiber.stateNode];
1229
+ }
1230
+ const nodes = [];
1231
+ let child = fiber.child;
1232
+ while (child !== undefined) {
1233
+ nodes.push(...collectCommittedHostNodes(child));
1234
+ child = child.sibling;
1235
+ }
1236
+ return nodes;
1237
+ }
1238
+ function finishHostPassthroughFiber(fiber) {
1239
+ fiber.memoizedProps = fiber.pendingProps;
1240
+ finishCommittedFiber(fiber);
1241
+ }
470
1242
  function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
471
1243
  if (fiber.tag === "host-text") {
472
1244
  const text = fiber.stateNode;
473
1245
  if (!(text instanceof Text)) {
1246
+ finishCommittedFiber(fiber);
474
1247
  return [];
475
1248
  }
476
- text.data = String(fiber.pendingProps);
1249
+ const nextText = String(fiber.pendingProps);
1250
+ if (text.data !== nextText) {
1251
+ text.data = nextText;
1252
+ }
477
1253
  fiber.memoizedProps = fiber.pendingProps;
1254
+ finishCommittedFiber(fiber);
478
1255
  return [text];
479
1256
  }
480
1257
  if (fiber.tag === "host-component") {
481
1258
  const element = fiber.stateNode;
482
- if (!(element instanceof HTMLElement)) {
1259
+ if (!isHostElement(element)) {
1260
+ finishCommittedFiber(fiber);
483
1261
  return [];
484
1262
  }
485
- applyProps(element, fiber.pendingProps, path, {
486
- ...options,
487
- eventRoot,
488
- preserveHydrationAttributes: fiber.hydrateExisting,
489
- });
490
- applyRef(fiber.pendingProps.ref, element);
491
- const childNodes = commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
492
- syncChildNodes(element, childNodes);
493
- applyPostChildFormProps(element, fiber.pendingProps);
494
- fiber.memoizedProps = fiber.pendingProps;
1263
+ if (fiber.hydrateExisting !== true &&
1264
+ fiber.flags === NoFlags &&
1265
+ fiber.subtreeFlags === NoFlags &&
1266
+ fiber.hostChildListChanged !== true) {
1267
+ fiber.memoizedProps = fiber.pendingProps;
1268
+ return [element];
1269
+ }
1270
+ const props = fiber.pendingProps;
1271
+ const propsAreUnchanged = fiber.hydrateExisting !== true &&
1272
+ hostPropsEqual(fiber.memoizedProps, props);
1273
+ const propsAreChildrenOnly = fiber.hydrateExisting !== true &&
1274
+ hostPropsAreChildrenOnly(fiber.memoizedProps) &&
1275
+ hostPropsAreChildrenOnly(props);
1276
+ const textOnlyRowUpdate = fiber.hydrateExisting !== true &&
1277
+ isRowTextOnlyUpdate(fiber.memoizedProps, props);
1278
+ if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
1279
+ applyProps(element, props, path, {
1280
+ ...options,
1281
+ eventRoot,
1282
+ preserveHydrationAttributes: fiber.hydrateExisting,
1283
+ });
1284
+ applyRef(props.ref, element);
1285
+ }
1286
+ const directTextChild = fiber.child === undefined && fiber.hydrateExisting !== true
1287
+ ? getDirectHostTextChild(props.children)
1288
+ : undefined;
1289
+ if (directTextChild !== undefined) {
1290
+ syncDirectHostTextChild(element, directTextChild);
1291
+ }
1292
+ else if (fiber.hostChildListChanged ||
1293
+ fiber.childListChanged ||
1294
+ fiber.hydrateExisting === true ||
1295
+ (fiber.subtreeFlags & Placement) !== NoFlags) {
1296
+ const childNodes = commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
1297
+ if (!(childNodes.length === 0 && committedPortalContainers.has(element)) &&
1298
+ !shouldPreserveContentEditableChildren(element, props, childNodes)) {
1299
+ syncChildNodes(element, childNodes);
1300
+ }
1301
+ }
1302
+ else if (fiber.subtreeFlags !== NoFlags) {
1303
+ commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
1304
+ }
1305
+ if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
1306
+ applyPostChildFormProps(element, props);
1307
+ }
1308
+ fiber.memoizedProps = props;
1309
+ finishCommittedFiber(fiber);
495
1310
  return [element];
496
1311
  }
497
1312
  if (fiber.tag === "fragment") {
498
1313
  fiber.memoizedProps = fiber.pendingProps;
499
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.f`, options);
1314
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.f`, options);
1315
+ finishCommittedFiber(fiber);
1316
+ return nodes;
500
1317
  }
501
1318
  if (fiber.tag === "profiler") {
502
1319
  fiber.memoizedProps = fiber.pendingProps;
503
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.profiler`, options);
1320
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.profiler`, options);
1321
+ finishCommittedFiber(fiber);
1322
+ return nodes;
504
1323
  }
505
1324
  if (fiber.tag === "strict-mode") {
506
1325
  fiber.memoizedProps = fiber.pendingProps;
507
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.strict`, options);
1326
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.strict`, options);
1327
+ finishCommittedFiber(fiber);
1328
+ return nodes;
508
1329
  }
509
1330
  if (fiber.tag === "suspense") {
510
1331
  fiber.memoizedProps = fiber.pendingProps;
511
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.s`, options);
1332
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.s`, options);
1333
+ finishCommittedFiber(fiber);
1334
+ return nodes;
512
1335
  }
513
1336
  if (fiber.tag === "suspense-list") {
514
1337
  fiber.memoizedProps = fiber.pendingProps;
515
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.sl`, options);
1338
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.sl`, options);
1339
+ finishCommittedFiber(fiber);
1340
+ return nodes;
516
1341
  }
517
1342
  if (fiber.tag === "context-provider" || fiber.tag === "context-consumer") {
518
1343
  fiber.memoizedProps = fiber.pendingProps;
519
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.ctx`, options);
1344
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.ctx`, options);
1345
+ finishCommittedFiber(fiber);
1346
+ return nodes;
520
1347
  }
521
1348
  if (fiber.tag === "function-component") {
522
1349
  fiber.memoizedProps = fiber.pendingProps;
523
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.fc`, options);
1350
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.fc`, options);
1351
+ finishCommittedFiber(fiber);
1352
+ return nodes;
524
1353
  }
525
1354
  if (fiber.tag === "forward-ref") {
526
1355
  fiber.memoizedProps = fiber.pendingProps;
527
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.fr`, options);
1356
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.fr`, options);
1357
+ finishCommittedFiber(fiber);
1358
+ return nodes;
528
1359
  }
529
1360
  if (fiber.tag === "memo") {
530
1361
  fiber.memoizedProps = fiber.pendingProps;
531
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.memo`, options);
1362
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.memo`, options);
1363
+ finishCommittedFiber(fiber);
1364
+ return nodes;
532
1365
  }
533
1366
  if (fiber.tag === "lazy") {
534
1367
  fiber.memoizedProps = fiber.pendingProps;
535
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.lazy`, options);
1368
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.lazy`, options);
1369
+ finishCommittedFiber(fiber);
1370
+ return nodes;
536
1371
  }
537
1372
  if (fiber.tag === "error-boundary") {
538
1373
  fiber.memoizedProps = fiber.pendingProps;
539
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.eb`, options);
1374
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.eb`, options);
1375
+ finishCommittedFiber(fiber);
1376
+ return nodes;
540
1377
  }
541
1378
  if (fiber.tag === "class-component") {
542
1379
  fiber.memoizedProps = fiber.pendingProps;
543
- return commitHostChildren(fiber.child, parent, eventRoot, `${path}.class`, options);
1380
+ const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.class`, options);
1381
+ finishCommittedFiber(fiber);
1382
+ return nodes;
544
1383
  }
545
1384
  if (fiber.tag === "portal") {
546
1385
  const container = fiber.stateNode;
@@ -548,13 +1387,206 @@ function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
548
1387
  return [];
549
1388
  }
550
1389
  setLogicalEventParent(container, parent);
551
- const childNodes = commitHostChildren(fiber.child, container, container, `${path}.portal`, options);
552
- syncChildNodes(container, childNodes);
1390
+ committedPortalContainers.add(container);
1391
+ const portalEventRoot = eventRoot !== container && eventRoot.contains(container) ? eventRoot : container;
1392
+ const childNodes = commitHostChildren(fiber.child, container, portalEventRoot, `${path}.portal`, options);
1393
+ const previousNodes = Array.isArray(fiber.alternate?.memoizedState)
1394
+ ? fiber.alternate.memoizedState.filter((node) => node instanceof Node)
1395
+ : [];
1396
+ syncOwnedChildNodes(container, previousNodes, childNodes);
1397
+ fiber.memoizedState = childNodes;
553
1398
  fiber.memoizedProps = fiber.pendingProps;
1399
+ finishCommittedFiber(fiber);
554
1400
  return [];
555
1401
  }
1402
+ finishCommittedFiber(fiber);
556
1403
  return [];
557
1404
  }
1405
+ function finishCommittedFiber(fiber) {
1406
+ fiber.flags = NoFlags;
1407
+ fiber.subtreeFlags = NoFlags;
1408
+ fiber.childListChanged = false;
1409
+ fiber.subtreeChildListChanged = false;
1410
+ fiber.hostChildListChanged = false;
1411
+ }
1412
+ function hasChildListMutation(fiber) {
1413
+ return fiber.childListChanged || fiber.subtreeChildListChanged;
1414
+ }
1415
+ function hostPropsEqual(previous, next) {
1416
+ if (previous === next) {
1417
+ return true;
1418
+ }
1419
+ if (typeof previous !== "object" || previous === null) {
1420
+ return false;
1421
+ }
1422
+ const previousProps = previous;
1423
+ let previousCount = 0;
1424
+ let nextCount = 0;
1425
+ for (const key in previousProps) {
1426
+ if (!hasOwnProperty.call(previousProps, key)) {
1427
+ continue;
1428
+ }
1429
+ previousCount += 1;
1430
+ if (!hasOwnProperty.call(next, key)) {
1431
+ return false;
1432
+ }
1433
+ if (!Object.is(previousProps[key], next[key])) {
1434
+ return false;
1435
+ }
1436
+ }
1437
+ for (const key in next) {
1438
+ if (hasOwnProperty.call(next, key)) {
1439
+ nextCount += 1;
1440
+ }
1441
+ }
1442
+ return previousCount === nextCount;
1443
+ }
1444
+ function hostOwnPropsEqual(previous, next) {
1445
+ if (previous === next) {
1446
+ return true;
1447
+ }
1448
+ if (typeof previous !== "object" || previous === null) {
1449
+ return false;
1450
+ }
1451
+ const previousProps = previous;
1452
+ const previousMeta = getHostOwnPropsMeta(previousProps);
1453
+ const nextMeta = getHostOwnPropsMeta(next);
1454
+ if (previousMeta !== undefined && nextMeta !== undefined) {
1455
+ return previousMeta === nextMeta;
1456
+ }
1457
+ let previousCount = 0;
1458
+ let nextCount = 0;
1459
+ for (const key in previousProps) {
1460
+ if (!hasOwnProperty.call(previousProps, key) || key === "children") {
1461
+ continue;
1462
+ }
1463
+ previousCount += 1;
1464
+ if (!hasOwnProperty.call(next, key)) {
1465
+ return false;
1466
+ }
1467
+ if (!Object.is(previousProps[key], next[key])) {
1468
+ return false;
1469
+ }
1470
+ }
1471
+ for (const key in next) {
1472
+ if (hasOwnProperty.call(next, key) && key !== "children") {
1473
+ nextCount += 1;
1474
+ }
1475
+ }
1476
+ return previousCount === nextCount;
1477
+ }
1478
+ function getHostOwnPropsMeta(props) {
1479
+ return props[HOST_OWN_PROPS_META];
1480
+ }
1481
+ function hostDirectTextChildChanged(previous, next) {
1482
+ const previousText = getDirectHostTextChild(hostFiberChildrenProp(previous));
1483
+ const nextText = getDirectHostTextChild(next.children);
1484
+ return (previousText !== undefined || nextText !== undefined) && previousText !== nextText;
1485
+ }
1486
+ function hostChildListChanged(previous, next) {
1487
+ const previousChildren = hostFiberChildrenProp(previous);
1488
+ const nextChildren = next.children;
1489
+ if (Object.is(previousChildren, nextChildren)) {
1490
+ return false;
1491
+ }
1492
+ if (getDirectHostTextChild(previousChildren) !== undefined ||
1493
+ getDirectHostTextChild(nextChildren) !== undefined) {
1494
+ return false;
1495
+ }
1496
+ if (sameSingleHostChild(previousChildren, nextChildren)) {
1497
+ return false;
1498
+ }
1499
+ if (sameHostChildList(previousChildren, nextChildren)) {
1500
+ return false;
1501
+ }
1502
+ return true;
1503
+ }
1504
+ function sameSingleHostChild(previous, next) {
1505
+ return (isReactCompatElement(previous) &&
1506
+ isReactCompatElement(next) &&
1507
+ previous.key === next.key &&
1508
+ previous.type === next.type);
1509
+ }
1510
+ function sameHostChildList(previous, next) {
1511
+ if (!Array.isArray(previous) || !Array.isArray(next) || previous.length !== next.length) {
1512
+ return false;
1513
+ }
1514
+ for (let index = 0; index < previous.length; index += 1) {
1515
+ const previousChild = previous[index];
1516
+ const nextChild = next[index];
1517
+ if (Object.is(previousChild, nextChild)) {
1518
+ continue;
1519
+ }
1520
+ if (!sameSingleHostChild(previousChild, nextChild)) {
1521
+ return false;
1522
+ }
1523
+ }
1524
+ return (previous.length > 0 ||
1525
+ (Array.isArray(previous) && Array.isArray(next)));
1526
+ }
1527
+ function hostPropsAreChildrenOnly(props) {
1528
+ if (typeof props !== "object" || props === null) {
1529
+ return false;
1530
+ }
1531
+ for (const key in props) {
1532
+ if (Object.prototype.hasOwnProperty.call(props, key) &&
1533
+ key !== "children") {
1534
+ return false;
1535
+ }
1536
+ }
1537
+ return true;
1538
+ }
1539
+ function isRowTextOnlyUpdate(previous, next) {
1540
+ if (typeof previous !== "object" || previous === null) {
1541
+ return false;
1542
+ }
1543
+ const previousProps = previous;
1544
+ const previousMeta = getHostOwnPropsMeta(previousProps);
1545
+ const nextMeta = getHostOwnPropsMeta(next);
1546
+ if (previousMeta === undefined || previousMeta !== nextMeta) {
1547
+ return false;
1548
+ }
1549
+ const previousText = getDirectHostTextChild(previousProps.children);
1550
+ const nextText = getDirectHostTextChild(next.children);
1551
+ return previousText !== undefined && nextText !== undefined && previousText !== nextText;
1552
+ }
1553
+ function hostFiberChildrenProp(props) {
1554
+ return typeof props === "object" && props !== null
1555
+ ? props.children
1556
+ : undefined;
1557
+ }
1558
+ function getDirectHostTextChild(children) {
1559
+ return typeof children === "string" || typeof children === "number"
1560
+ ? String(children)
1561
+ : undefined;
1562
+ }
1563
+ function shouldUseDirectHostTextChild() {
1564
+ const globalProcess = globalThis
1565
+ .process;
1566
+ return globalProcess?.env?.NODE_ENV === "production";
1567
+ }
1568
+ function syncDirectHostTextChild(element, text) {
1569
+ const firstChild = element.firstChild;
1570
+ if (firstChild instanceof Text && firstChild.nextSibling === null) {
1571
+ if (firstChild.data !== text) {
1572
+ firstChild.data = text;
1573
+ }
1574
+ return;
1575
+ }
1576
+ element.textContent = text;
1577
+ }
1578
+ function shouldPreserveContentEditableChildren(element, props, childNodes) {
1579
+ void childNodes;
1580
+ if (!element.hasAttribute("contenteditable") ||
1581
+ element.getAttribute("contenteditable") === "false") {
1582
+ return false;
1583
+ }
1584
+ const children = props.children;
1585
+ return (children === undefined ||
1586
+ children === null ||
1587
+ children === false ||
1588
+ (Array.isArray(children) && children.length === 0));
1589
+ }
558
1590
  function createSuspenseFiber(current, element, key, runtime, path, options = {}) {
559
1591
  if (runtime === undefined) {
560
1592
  return { fiber: undefined, consumed: 0 };
@@ -609,17 +1641,17 @@ function createStrictModeFiber(current, element, key, runtime, path, options = {
609
1641
  ? createWorkInProgress(current, element.props)
610
1642
  : createFiber("strict-mode", element.props, key);
611
1643
  fiber.type = element.type;
1644
+ const { result: childResult, memoValues, memoValuesByHook } = renderWithStrictModeMemoCapture(runtime, () => reconcileHostChild(fiber, current?.tag === "strict-mode" ? current.child : undefined, element.props.children, runtime, `${path}.strict`, options));
1645
+ fiber.child = childResult.fiber;
612
1646
  const snapshot = takeRuntimeSnapshot(runtime);
613
1647
  try {
614
- createHostFiber(fiber, undefined, element.props.children, undefined, runtime, `${path}.strict.preview`, options.previousNodes === undefined
1648
+ renderStrictModeReplay(runtime, memoValues, memoValuesByHook, () => reconcileHostChild(fiber, childResult.fiber, element.props.children, runtime, `${path}.strict`, options.previousNodes === undefined
615
1649
  ? options
616
- : { ...options, previousNodes: [] });
1650
+ : { ...options, previousNodes: [] }));
617
1651
  }
618
1652
  finally {
619
1653
  restoreRuntimeSnapshot(runtime, snapshot);
620
1654
  }
621
- const childResult = renderWithStrictMode(runtime, () => reconcileHostChild(fiber, current?.tag === "strict-mode" ? current.child : undefined, element.props.children, runtime, `${path}.strict`, options));
622
- fiber.child = childResult.fiber;
623
1655
  return { fiber, consumed: childResult.consumed };
624
1656
  }
625
1657
  function createSuspenseListFiber(current, element, key, runtime, path, options = {}) {
@@ -680,6 +1712,7 @@ function reconcileSuspenseListForwards(parent, currentFirstChild, children, runt
680
1712
  }
681
1713
  fiber.return = parent;
682
1714
  fiber.sibling = undefined;
1715
+ bubbleHostChild(parent, fiber);
683
1716
  if (first === undefined) {
684
1717
  first = fiber;
685
1718
  }
@@ -710,6 +1743,7 @@ function reconcileSuspenseListBackwards(parent, currentFirstChild, children, run
710
1743
  }
711
1744
  fiber.return = parent;
712
1745
  fiber.sibling = undefined;
1746
+ bubbleHostChild(parent, fiber);
713
1747
  fibers.unshift(fiber);
714
1748
  if (isSuspendedSuspenseFiber(fiber)) {
715
1749
  break;
@@ -737,6 +1771,25 @@ function hasSuspendedChild(fiber) {
737
1771
  }
738
1772
  return false;
739
1773
  }
1774
+ function hasPendingAsyncChild(fiber) {
1775
+ let cursor = fiber;
1776
+ while (cursor !== undefined) {
1777
+ if (isPendingLazyFiber(cursor) || isSuspendedSuspenseFiber(cursor)) {
1778
+ return true;
1779
+ }
1780
+ if (cursor.child !== undefined && hasPendingAsyncChild(cursor.child)) {
1781
+ return true;
1782
+ }
1783
+ cursor = cursor.sibling;
1784
+ }
1785
+ return false;
1786
+ }
1787
+ function isPendingLazyFiber(fiber) {
1788
+ if (fiber.tag !== "lazy" || !isLazyType(fiber.type)) {
1789
+ return false;
1790
+ }
1791
+ return fiber.type.status !== "resolved" || fiber.child === undefined;
1792
+ }
740
1793
  function isSuspendedSuspenseFiber(fiber) {
741
1794
  return (fiber.tag === "suspense" &&
742
1795
  fiber.memoizedState?.didSuspend === true);
@@ -819,7 +1872,7 @@ function createPortalFiber(parent, current, portal, key, runtime, path, options
819
1872
  ? createWorkInProgress(current, portal.children)
820
1873
  : createFiber("portal", portal.children, key);
821
1874
  fiber.stateNode = portal.container;
822
- const childResult = reconcileHostChild(fiber, current?.tag === "portal" ? current.child : undefined, portal.children, runtime, `${path}.portal`, options);
1875
+ const childResult = reconcileHostChild(fiber, current?.tag === "portal" ? current.child : undefined, portal.children, runtime, `${path}.portal`, { ...options, documentRef: portal.container.ownerDocument });
823
1876
  fiber.child = childResult.fiber;
824
1877
  fiber.return = parent;
825
1878
  return { fiber, consumed: childResult.consumed };
@@ -830,6 +1883,9 @@ function normalizeChildren(node) {
830
1883
  }
831
1884
  return Array.isArray(node) ? node : [node];
832
1885
  }
1886
+ function getDocumentRef(options) {
1887
+ return options.documentRef ?? document;
1888
+ }
833
1889
  function collectExistingKeyedFibers(firstChild) {
834
1890
  const keyed = new Map();
835
1891
  let cursor = firstChild;
@@ -844,10 +1900,43 @@ function collectExistingKeyedFibers(firstChild) {
844
1900
  function getNodeKey(node) {
845
1901
  return isReactCompatElement(node) && node.key !== null ? node.key : undefined;
846
1902
  }
1903
+ function hasKeyedChild(children) {
1904
+ for (const child of children) {
1905
+ if (getNodeKey(child) !== undefined) {
1906
+ return true;
1907
+ }
1908
+ }
1909
+ return false;
1910
+ }
847
1911
  function getNodePathSegment(node, index) {
848
1912
  const key = getNodeKey(node);
849
1913
  return key === undefined ? String(index) : `k:${key}`;
850
1914
  }
1915
+ function getReconcileChildPath(path, node, index, options) {
1916
+ if (!shouldTrackReconcilePath(node, options)) {
1917
+ return "";
1918
+ }
1919
+ return joinPath(path, getNodePathSegment(node, index));
1920
+ }
1921
+ function shouldTrackReconcilePath(node, options) {
1922
+ if (options.previousNodes !== undefined ||
1923
+ options.hydration?.onRecoverableError !== undefined ||
1924
+ options.resumeId !== undefined) {
1925
+ return true;
1926
+ }
1927
+ return !isHostElementWithDirectTextChild(node);
1928
+ }
1929
+ function isHostElementWithDirectTextChild(node) {
1930
+ return (isReactCompatElement(node) &&
1931
+ typeof node.type === "string" &&
1932
+ getDirectHostTextChild(node.props.children) !== undefined);
1933
+ }
1934
+ function getRootCommitPath(options) {
1935
+ return options.hydration?.onRecoverableError === undefined ? SKIP_COMMIT_PATH : "0";
1936
+ }
1937
+ function joinCommitPath(path, segment) {
1938
+ return path === SKIP_COMMIT_PATH ? "" : joinPath(path, segment);
1939
+ }
851
1940
  function getComponentName(component) {
852
1941
  return component.name === "" ? "Anonymous" : component.name;
853
1942
  }
@@ -877,8 +1966,34 @@ function markActiveInstanceKeys(runtime, keys) {
877
1966
  runtime.activeInstanceKeys?.add(key);
878
1967
  }
879
1968
  }
880
- function hasDirtyInstance(runtime, keys) {
881
- return keys.some((key) => runtime.instances.get(key)?.dirty === true);
1969
+ function hasDirtyInstance(runtime, keys, prefix) {
1970
+ if (runtime === undefined) {
1971
+ return false;
1972
+ }
1973
+ if (hasDirtyClassUpdate(runtime, keys, prefix)) {
1974
+ return true;
1975
+ }
1976
+ if (keys.some((key) => runtime.instances.get(key)?.dirty === true)) {
1977
+ return true;
1978
+ }
1979
+ if (prefix === undefined) {
1980
+ return false;
1981
+ }
1982
+ for (const [key, instance] of runtime.instances) {
1983
+ if ((key === prefix || key.startsWith(`${prefix}.`)) &&
1984
+ instance.dirty === true) {
1985
+ return true;
1986
+ }
1987
+ }
1988
+ return false;
1989
+ }
1990
+ function hasUnflushedMountEffectInstance(runtime, keys) {
1991
+ return keys.some((key) => {
1992
+ const instance = runtime.instances.get(key);
1993
+ return instance?.hooks?.some((slot) => slot?.kind === "effect" &&
1994
+ slot.disposed !== true &&
1995
+ slot.mounted !== true) === true;
1996
+ });
882
1997
  }
883
1998
  function applyRef(ref, node) {
884
1999
  if (typeof ref === "function") {