@reckona/mreact-compat 0.0.163 → 0.0.165

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.
@@ -3,8 +3,8 @@ import { consumerContext, isReactCompatConsumer, isReactCompatProvider, renderWi
3
3
  import { applyPostChildFormProps, applyProps } from "./dom-props.js";
4
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
+ import { ChildDeletion, NoFlags, Placement, Update } from "./fiber-flags.js";
7
+ import { createHostElement, hostElementMatches, isDomHostElement, isHostElement, namespaceForHostChildren, namespaceForHostElement, } from "./dom-host-rules.js";
8
8
  import { createFiber, createWorkInProgress } from "./fiber.js";
9
9
  import { renderWithRootRuntime, renderWithProfiler, renderWithStrictModeMemoCapture, renderStrictModeReplay, runWithHostCommit, restoreRuntimeSnapshot, takeRuntimeSnapshot, getDevToolsHookState, collectRuntimeInstanceKeys, hasContextDependency, hasChangedContextDependency, subscribeReactiveTextBinding, } from "./hooks.js";
10
10
  import { isThenable } from "./thenable.js";
@@ -12,6 +12,7 @@ import { hasDirtyClassUpdate, isClassComponentType, recoverClassComponentError,
12
12
  import { areMemoPropsEqual, getPendingProps, shallowEqual } from "./prop-comparison.js";
13
13
  import { reportElementTextMismatch, reportExtraHydrationNodes, reportHydrationNodeTypeMismatch, reportMissingHydrationNode, reportReactSuspenseServerError, reportRecoverable, withHydrationComponentStack, } from "./hydration.js";
14
14
  const committedPortalContainers = new Set();
15
+ const pendingHostRefUpdates = [];
15
16
  const SKIP_COMMIT_PATH = "\0";
16
17
  const hasOwnProperty = Object.prototype.hasOwnProperty;
17
18
  let suspensePrimaryRenderDepth = 0;
@@ -93,35 +94,55 @@ export function renderHydratingHostFiberRoot(root, element, runtime, scope, opti
93
94
  }
94
95
  export function commitHostFiberRoot(root, finishedWork, options = {}) {
95
96
  runWithHostCommit(() => {
97
+ let committed = false;
96
98
  try {
97
99
  committedPortalContainers.clear();
100
+ pendingHostRefUpdates.length = 0;
98
101
  const commitPath = getRootCommitPath(options);
99
102
  if (!hasChildListMutation(finishedWork)) {
100
103
  commitHostDirtyChildren(finishedWork.child, root.container, root.container, commitPath, options);
104
+ committed = true;
101
105
  return;
102
106
  }
103
107
  if (!finishedWork.childListChanged &&
104
108
  finishedWork.subtreeChildListChanged &&
105
109
  commitHostKeyedChildListMutation(finishedWork.child, root.container, root.container, commitPath, options)) {
110
+ committed = true;
106
111
  return;
107
112
  }
108
113
  const nodes = commitHostChildren(finishedWork.child, root.container, root.container, commitPath, options);
109
114
  syncChildNodes(root.container, nodes);
115
+ committed = true;
110
116
  }
111
117
  finally {
118
+ if (committed) {
119
+ flushPendingHostRefUpdates();
120
+ }
121
+ else {
122
+ pendingHostRefUpdates.length = 0;
123
+ }
112
124
  committedPortalContainers.clear();
113
125
  }
114
126
  });
115
127
  }
116
128
  export function commitHydratingHostFiberRoot(root, finishedWork, scope, options = {}) {
117
129
  runWithHostCommit(() => {
130
+ let committed = false;
118
131
  try {
119
132
  committedPortalContainers.clear();
133
+ pendingHostRefUpdates.length = 0;
120
134
  const eventRoot = root.container;
121
135
  const nodes = commitHostChildren(finishedWork.child, scope.parent, eventRoot, "", options);
122
136
  syncScopedChildNodes(scope.parent, scope.before, scope.after, nodes);
137
+ committed = true;
123
138
  }
124
139
  finally {
140
+ if (committed) {
141
+ flushPendingHostRefUpdates();
142
+ }
143
+ else {
144
+ pendingHostRefUpdates.length = 0;
145
+ }
125
146
  committedPortalContainers.clear();
126
147
  }
127
148
  });
@@ -137,6 +158,9 @@ function reconcileHostChild(parent, currentFirstChild, node, runtime, path, opti
137
158
  parent.subtreeChildListChanged = false;
138
159
  if (node === null || node === undefined || typeof node === "boolean") {
139
160
  parent.childListChanged = currentFirstChild !== undefined;
161
+ if (currentFirstChild !== undefined) {
162
+ markOptimizedChildrenForDeletion(parent, currentFirstChild);
163
+ }
140
164
  return { fiber: undefined, consumed: 0 };
141
165
  }
142
166
  const children = Array.isArray(node) ? node : undefined;
@@ -155,6 +179,7 @@ function reconcileHostChild(parent, currentFirstChild, node, runtime, path, opti
155
179
  let previous;
156
180
  let consumed = 0;
157
181
  let skipRemainingKeyedLookup = false;
182
+ const usedCurrentChildren = currentFirstChild === undefined ? undefined : new Set();
158
183
  for (let index = 0; index < childCount; index += 1) {
159
184
  const child = children === undefined ? node : children[index];
160
185
  const key = getNodeKey(child);
@@ -196,8 +221,18 @@ function reconcileHostChild(parent, currentFirstChild, node, runtime, path, opti
196
221
  const result = createHostFiber(parent, matchedCurrent, child, key, runtime, getReconcileChildPath(path, child, index, options), previousNodes === undefined ? options : { ...options, previousNodes });
197
222
  const fiber = result.fiber;
198
223
  if (fiber === undefined) {
224
+ if (matchedCurrent !== undefined) {
225
+ usedCurrentChildren?.add(matchedCurrent);
226
+ markOptimizedChildForDeletion(parent, matchedCurrent);
227
+ }
199
228
  continue;
200
229
  }
230
+ if (matchedCurrent !== undefined) {
231
+ usedCurrentChildren?.add(matchedCurrent);
232
+ if (fiber !== matchedCurrent && fiber.alternate !== matchedCurrent) {
233
+ markOptimizedChildForDeletion(parent, matchedCurrent);
234
+ }
235
+ }
201
236
  if (key === undefined) {
202
237
  currentUnkeyed = currentUnkeyed?.sibling;
203
238
  }
@@ -222,6 +257,7 @@ function reconcileHostChild(parent, currentFirstChild, node, runtime, path, opti
222
257
  }
223
258
  previous = fiber;
224
259
  }
260
+ markUnusedCurrentChildrenForDeletion(parent, currentFirstChild, usedCurrentChildren);
225
261
  parent.childListChanged = childFiberListShapeChanged(currentFirstChild, first);
226
262
  return { fiber: first, consumed };
227
263
  }
@@ -240,9 +276,8 @@ function reconcileKeyedRowHostChildren(parent, currentFirstChild, children, opti
240
276
  let subtreeFlags = NoFlags;
241
277
  let subtreeChildListChanged = false;
242
278
  let hasRefSubtree = false;
243
- const currentSiblingCount = countFiberSiblings(currentFirstChild);
244
- const canReuseUnchangedRows = currentSiblingCount === children.length ||
245
- isKeyedAppendOnly(currentFirstChild, children, currentSiblingCount);
279
+ let appendSuffix;
280
+ const canReuseUnchangedRows = hasSameKeyOrderPrefix(currentFirstChild, children);
246
281
  const row = createKeyedRowHostElementScratch();
247
282
  for (let index = 0; index < children.length; index += 1) {
248
283
  const child = children[index];
@@ -250,12 +285,14 @@ function reconcileKeyedRowHostChildren(parent, currentFirstChild, children, opti
250
285
  return undefined;
251
286
  }
252
287
  let matchedCurrent;
288
+ let matchedByAppendSuffix = false;
253
289
  if (skipRemainingKeyedLookup) {
254
290
  matchedCurrent = undefined;
255
291
  }
256
292
  else if (currentKeyed === undefined) {
257
293
  listShapeChanged = true;
258
294
  skipRemainingKeyedLookup = true;
295
+ matchedByAppendSuffix = true;
259
296
  matchedCurrent = undefined;
260
297
  }
261
298
  else if (currentKeyed?.key === row.key) {
@@ -264,12 +301,16 @@ function reconcileKeyedRowHostChildren(parent, currentFirstChild, children, opti
264
301
  }
265
302
  else if (currentKeyed?.sibling?.key === row.key &&
266
303
  canSkipSingleDeletedKeyedFiber(children, index, currentKeyed.sibling)) {
304
+ const deleted = currentKeyed;
305
+ const matched = currentKeyed.sibling;
267
306
  listShapeChanged = true;
268
- matchedCurrent = currentKeyed.sibling;
269
- currentKeyed = currentKeyed.sibling.sibling;
307
+ markOptimizedChildForDeletion(parent, deleted);
308
+ matchedCurrent = matched;
309
+ currentKeyed = matched.sibling;
270
310
  }
271
311
  else if (canSkipRemainingKeyedLookup(currentKeyed, children, index)) {
272
312
  listShapeChanged = true;
313
+ markOptimizedChildrenForDeletion(parent, currentKeyed);
273
314
  skipRemainingKeyedLookup = true;
274
315
  currentKeyed = undefined;
275
316
  matchedCurrent = undefined;
@@ -281,6 +322,9 @@ function reconcileKeyedRowHostChildren(parent, currentFirstChild, children, opti
281
322
  ? createKeyedRowHostFiber(parent, undefined, row, options)
282
323
  : (canReuseUnchangedRows ? getReusableKeyedRowHostFiber(matchedCurrent, row) : undefined) ??
283
324
  createKeyedRowHostFiber(parent, matchedCurrent, row, options);
325
+ if (matchedByAppendSuffix && appendSuffix === undefined) {
326
+ appendSuffix = { fiber, index };
327
+ }
284
328
  if (first === undefined) {
285
329
  first = fiber;
286
330
  }
@@ -304,29 +348,48 @@ function reconcileKeyedRowHostChildren(parent, currentFirstChild, children, opti
304
348
  }
305
349
  if (currentKeyed !== undefined) {
306
350
  listShapeChanged = true;
351
+ markOptimizedChildrenForDeletion(parent, currentKeyed);
307
352
  }
308
353
  parent.hasRefSubtree = hasRefSubtree;
309
354
  parent.subtreeFlags = subtreeFlags;
310
355
  parent.subtreeChildListChanged = subtreeChildListChanged;
311
356
  parent.childListChanged = listShapeChanged;
357
+ if (appendSuffix !== undefined && canStoreAppendSuffixCommitHint(parent)) {
358
+ parent.memoizedState = appendSuffix;
359
+ }
312
360
  return { fiber: first, consumed: 0 };
313
361
  }
314
- function countFiberSiblings(first) {
315
- let count = 0;
316
- let cursor = first;
362
+ function canStoreAppendSuffixCommitHint(parent) {
363
+ return (parent.tag === "fragment" ||
364
+ parent.tag === "host-component" ||
365
+ parent.tag === "host-root");
366
+ }
367
+ function markOptimizedChildForDeletion(parent, _child) {
368
+ parent.flags |= ChildDeletion;
369
+ }
370
+ function markOptimizedChildrenForDeletion(parent, _firstChild) {
371
+ parent.flags |= ChildDeletion;
372
+ }
373
+ function markUnusedCurrentChildrenForDeletion(parent, firstChild, used) {
374
+ if (firstChild === undefined || used === undefined) {
375
+ return;
376
+ }
377
+ let cursor = firstChild;
317
378
  while (cursor !== undefined) {
318
- count += 1;
379
+ if (!used.has(cursor)) {
380
+ parent.flags |= ChildDeletion;
381
+ return;
382
+ }
319
383
  cursor = cursor.sibling;
320
384
  }
321
- return count;
322
385
  }
323
- function isKeyedAppendOnly(currentFirstChild, children, currentSiblingCount) {
324
- if (children.length <= currentSiblingCount) {
325
- return false;
326
- }
386
+ function hasSameKeyOrderPrefix(currentFirstChild, children) {
327
387
  let current = currentFirstChild;
328
- for (let index = 0; index < currentSiblingCount; index += 1) {
329
- if (current === undefined || current.key !== getNodeKey(children[index])) {
388
+ for (let index = 0; index < children.length; index += 1) {
389
+ if (current === undefined) {
390
+ return true;
391
+ }
392
+ if (current.key !== getNodeKey(children[index])) {
330
393
  return false;
331
394
  }
332
395
  current = current.sibling;
@@ -590,7 +653,7 @@ function createHostFiberImpl(parent, current, node, key, runtime, path, options
590
653
  ? existing
591
654
  : current?.tag === "host-text" && current.stateNode instanceof Text
592
655
  ? current.stateNode
593
- : getDocumentRef(options).createTextNode("");
656
+ : createHostTextNode(getDocumentRef(options));
594
657
  if (existing instanceof Text && existing.data !== String(node)) {
595
658
  reportRecoverable(options, "text", path, new Error("Hydration text mismatch."));
596
659
  }
@@ -1016,13 +1079,12 @@ function commitHostDirtyFiber(fiber, parent, eventRoot, path, options = {}) {
1016
1079
  !propsAreChildrenOnly &&
1017
1080
  fiber.hydrateExisting !== true &&
1018
1081
  isRowTextOnlyUpdate(fiber.memoizedProps, props);
1019
- if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
1082
+ if (isDomHostElement(element) && !propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
1020
1083
  applyProps(element, props, path, {
1021
1084
  ...options,
1022
1085
  eventRoot,
1023
1086
  preserveHydrationAttributes: fiber.hydrateExisting,
1024
1087
  });
1025
- applyChangedRef(previousProps?.ref, props.ref, element);
1026
1088
  }
1027
1089
  if (directTextChild !== undefined) {
1028
1090
  const text = syncDirectHostTextChild(element, directTextChild);
@@ -1032,24 +1094,45 @@ function commitHostDirtyFiber(fiber, parent, eventRoot, path, options = {}) {
1032
1094
  fiber.childListChanged ||
1033
1095
  fiber.subtreeChildListChanged) {
1034
1096
  const childNodes = commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
1035
- if (!(childNodes.length === 0 && committedPortalContainers.has(element)) &&
1036
- !shouldPreserveContentEditableChildren(element, props, childNodes)) {
1097
+ if (!(isDomHostElement(element) && childNodes.length === 0 && committedPortalContainers.has(element)) &&
1098
+ !(isDomHostElement(element) && shouldPreserveContentEditableChildren(element, props, childNodes))) {
1037
1099
  syncChildNodes(element, childNodes);
1038
1100
  }
1039
1101
  }
1040
1102
  else if (fiber.subtreeFlags !== NoFlags) {
1041
1103
  commitHostDirtyChildren(fiber.child, element, eventRoot, `${path}.c`, options);
1042
1104
  }
1043
- applyPostChildFormProps(element, props, previousProps);
1105
+ if (isDomHostElement(element)) {
1106
+ applyPostChildFormProps(element, props, previousProps);
1107
+ }
1108
+ applyChangedRef(previousProps?.ref, props.ref, element);
1044
1109
  fiber.memoizedProps = props;
1045
1110
  finishCommittedFiber(fiber);
1046
1111
  return;
1047
1112
  }
1048
1113
  if (fiber.tag === "portal") {
1049
1114
  const container = fiber.stateNode;
1050
- if (container instanceof Element) {
1051
- setLogicalEventParent(container, parent);
1052
- commitHostDirtyChildren(fiber.child, container, container, `${path}.portal`, options);
1115
+ if (isPortalHostContainer(container)) {
1116
+ if (container instanceof Element) {
1117
+ setLogicalEventParent(container, parent);
1118
+ }
1119
+ const portalEventRoot = container instanceof Element && eventRoot !== container && eventRoot.contains(container)
1120
+ ? eventRoot
1121
+ : container instanceof Element
1122
+ ? container
1123
+ : eventRoot;
1124
+ const portalOptions = withPortalDocumentRef(options, container);
1125
+ if (fiber.childListChanged ||
1126
+ fiber.subtreeChildListChanged ||
1127
+ (fiber.subtreeFlags & Placement) !== NoFlags) {
1128
+ const childNodes = commitHostChildren(fiber.child, container, portalEventRoot, `${path}.portal`, portalOptions);
1129
+ const previousNodes = committedHostNodesFromState(fiber.alternate?.memoizedState);
1130
+ syncOwnedChildNodes(container, previousNodes, childNodes);
1131
+ fiber.memoizedState = childNodes;
1132
+ }
1133
+ else {
1134
+ commitHostDirtyChildren(fiber.child, container, portalEventRoot, `${path}.portal`, portalOptions);
1135
+ }
1053
1136
  }
1054
1137
  fiber.memoizedProps = fiber.pendingProps;
1055
1138
  finishCommittedFiber(fiber);
@@ -1091,6 +1174,10 @@ function commitHostKeyedChildListMutation(fiber, parent, eventRoot, path, option
1091
1174
  return committed;
1092
1175
  }
1093
1176
  function commitHostKeyedChildListMutationFiber(fiber, parent, eventRoot, path, options = {}) {
1177
+ if (fiber.tag === "portal") {
1178
+ commitHostDirtyFiber(fiber, parent, eventRoot, path, options);
1179
+ return true;
1180
+ }
1094
1181
  if (fiber.childListChanged) {
1095
1182
  const mutationParent = fiber.tag === "host-component" && isHostElement(fiber.stateNode)
1096
1183
  ? fiber.stateNode
@@ -1130,10 +1217,14 @@ function commitHostKeyedChildListMutationFiber(fiber, parent, eventRoot, path, o
1130
1217
  return true;
1131
1218
  }
1132
1219
  function commitHostAppendSuffix(fiber, parent, eventRoot, path, options) {
1133
- const append = getAppendSuffix(fiber.alternate?.child, fiber.child);
1220
+ const appendHint = readAppendSuffixCommitHint(fiber.memoizedState);
1221
+ const append = appendHint ?? getAppendSuffix(fiber.alternate?.child, fiber.child);
1134
1222
  if (append === undefined) {
1135
1223
  return false;
1136
1224
  }
1225
+ if (appendHint !== undefined) {
1226
+ fiber.memoizedState = undefined;
1227
+ }
1137
1228
  let cursor = append.fiber;
1138
1229
  let index = append.index;
1139
1230
  while (cursor !== undefined) {
@@ -1145,6 +1236,15 @@ function commitHostAppendSuffix(fiber, parent, eventRoot, path, options) {
1145
1236
  }
1146
1237
  return true;
1147
1238
  }
1239
+ function readAppendSuffixCommitHint(value) {
1240
+ if (typeof value !== "object" || value === null) {
1241
+ return undefined;
1242
+ }
1243
+ const candidate = value;
1244
+ return candidate.fiber !== undefined && typeof candidate.index === "number"
1245
+ ? { fiber: candidate.fiber, index: candidate.index }
1246
+ : undefined;
1247
+ }
1148
1248
  function commitHostSingleRemoval(fiber, parent) {
1149
1249
  const removed = getSingleRemovedFiber(fiber.alternate?.child, fiber.child);
1150
1250
  if (removed === undefined) {
@@ -1287,13 +1387,12 @@ function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
1287
1387
  !propsAreChildrenOnly &&
1288
1388
  fiber.hydrateExisting !== true &&
1289
1389
  isRowTextOnlyUpdate(fiber.memoizedProps, props);
1290
- if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
1390
+ if (isDomHostElement(element) && !propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
1291
1391
  applyProps(element, props, path, {
1292
1392
  ...options,
1293
1393
  eventRoot,
1294
1394
  preserveHydrationAttributes: fiber.hydrateExisting,
1295
1395
  });
1296
- applyChangedRef(previousProps?.ref, props.ref, element);
1297
1396
  }
1298
1397
  if (directTextChild !== undefined) {
1299
1398
  const text = syncDirectHostTextChild(element, directTextChild);
@@ -1305,15 +1404,18 @@ function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
1305
1404
  fiber.hydrateExisting === true ||
1306
1405
  (fiber.subtreeFlags & Placement) !== NoFlags) {
1307
1406
  const childNodes = commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
1308
- if (!(childNodes.length === 0 && committedPortalContainers.has(element)) &&
1309
- !shouldPreserveContentEditableChildren(element, props, childNodes)) {
1407
+ if (!(isDomHostElement(element) && childNodes.length === 0 && committedPortalContainers.has(element)) &&
1408
+ !(isDomHostElement(element) && shouldPreserveContentEditableChildren(element, props, childNodes))) {
1310
1409
  syncChildNodes(element, childNodes);
1311
1410
  }
1312
1411
  }
1313
1412
  else if (fiber.subtreeFlags !== NoFlags) {
1314
1413
  commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
1315
1414
  }
1316
- applyPostChildFormProps(element, props, previousProps);
1415
+ if (isDomHostElement(element)) {
1416
+ applyPostChildFormProps(element, props, previousProps);
1417
+ }
1418
+ applyChangedRef(previousProps?.ref, props.ref, element);
1317
1419
  fiber.memoizedProps = props;
1318
1420
  finishCommittedFiber(fiber);
1319
1421
  return [element];
@@ -1392,16 +1494,21 @@ function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
1392
1494
  }
1393
1495
  if (fiber.tag === "portal") {
1394
1496
  const container = fiber.stateNode;
1395
- if (!(container instanceof Element)) {
1497
+ if (!isPortalHostContainer(container)) {
1396
1498
  return [];
1397
1499
  }
1398
- setLogicalEventParent(container, parent);
1399
- committedPortalContainers.add(container);
1400
- const portalEventRoot = eventRoot !== container && eventRoot.contains(container) ? eventRoot : container;
1401
- const childNodes = commitHostChildren(fiber.child, container, portalEventRoot, `${path}.portal`, options);
1402
- const previousNodes = Array.isArray(fiber.alternate?.memoizedState)
1403
- ? fiber.alternate.memoizedState.filter((node) => node instanceof Node)
1404
- : [];
1500
+ if (container instanceof Element) {
1501
+ setLogicalEventParent(container, parent);
1502
+ committedPortalContainers.add(container);
1503
+ }
1504
+ const portalEventRoot = container instanceof Element && eventRoot !== container && eventRoot.contains(container)
1505
+ ? eventRoot
1506
+ : container instanceof Element
1507
+ ? container
1508
+ : eventRoot;
1509
+ const portalOptions = withPortalDocumentRef(options, container);
1510
+ const childNodes = commitHostChildren(fiber.child, container, portalEventRoot, `${path}.portal`, portalOptions);
1511
+ const previousNodes = committedHostNodesFromState(fiber.alternate?.memoizedState);
1405
1512
  syncOwnedChildNodes(container, previousNodes, childNodes);
1406
1513
  fiber.memoizedState = childNodes;
1407
1514
  fiber.memoizedProps = fiber.pendingProps;
@@ -1918,6 +2025,12 @@ function normalizeChildren(node) {
1918
2025
  function getDocumentRef(options) {
1919
2026
  return options.documentRef ?? document;
1920
2027
  }
2028
+ function createHostTextNode(documentRef) {
2029
+ if ("createTextNode" in documentRef && typeof documentRef.createTextNode === "function") {
2030
+ return documentRef.createTextNode("");
2031
+ }
2032
+ return document.createTextNode("");
2033
+ }
1921
2034
  function collectExistingKeyedFibers(firstChild) {
1922
2035
  const keyed = new Map();
1923
2036
  let cursor = firstChild;
@@ -2040,7 +2153,47 @@ function applyChangedRef(previousRef, nextRef, node) {
2040
2153
  if (Object.is(previousRef, nextRef)) {
2041
2154
  return;
2042
2155
  }
2043
- applyRef(previousRef, null);
2044
- applyRef(nextRef, node);
2156
+ queueHostRefUpdate(previousRef, null);
2157
+ queueHostRefUpdate(nextRef, node);
2158
+ }
2159
+ function queueHostRefUpdate(ref, node) {
2160
+ if (ref === null || ref === undefined) {
2161
+ return;
2162
+ }
2163
+ pendingHostRefUpdates.push({ ref, node });
2164
+ }
2165
+ function flushPendingHostRefUpdates() {
2166
+ const pending = pendingHostRefUpdates.splice(0);
2167
+ for (const { ref, node } of pending) {
2168
+ applyRef(ref, node);
2169
+ }
2170
+ }
2171
+ function isPortalHostContainer(value) {
2172
+ if (value instanceof Element) {
2173
+ return true;
2174
+ }
2175
+ if (typeof value !== "object" || value === null) {
2176
+ return false;
2177
+ }
2178
+ const candidate = value;
2179
+ return (typeof candidate.appendChild === "function" &&
2180
+ typeof candidate.insertBefore === "function" &&
2181
+ typeof candidate.removeChild === "function" &&
2182
+ typeof candidate.ownerDocument?.createElement === "function");
2183
+ }
2184
+ function withPortalDocumentRef(options, container) {
2185
+ const ownerDocument = container.ownerDocument;
2186
+ if (typeof ownerDocument === "object" &&
2187
+ ownerDocument !== null &&
2188
+ typeof ownerDocument.createElement === "function") {
2189
+ return {
2190
+ ...options,
2191
+ documentRef: ownerDocument,
2192
+ };
2193
+ }
2194
+ return options;
2195
+ }
2196
+ function committedHostNodesFromState(state) {
2197
+ return Array.isArray(state) ? state : [];
2045
2198
  }
2046
2199
  //# sourceMappingURL=host-reconciler.js.map