@reckona/mreact-compat 0.0.90 → 0.0.92
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.
- package/README.md +1 -0
- package/dist/class-component.d.ts +20 -6
- package/dist/class-component.d.ts.map +1 -1
- package/dist/class-component.js +94 -51
- package/dist/class-component.js.map +1 -1
- package/dist/context.d.ts +19 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +55 -6
- package/dist/context.js.map +1 -1
- package/dist/dom-children.d.ts +2 -0
- package/dist/dom-children.d.ts.map +1 -1
- package/dist/dom-children.js +103 -1
- package/dist/dom-children.js.map +1 -1
- package/dist/dom-host-rules.d.ts +10 -0
- package/dist/dom-host-rules.d.ts.map +1 -0
- package/dist/dom-host-rules.js +86 -0
- package/dist/dom-host-rules.js.map +1 -0
- package/dist/dom-props.d.ts +3 -2
- package/dist/dom-props.d.ts.map +1 -1
- package/dist/dom-props.js +229 -33
- package/dist/dom-props.js.map +1 -1
- package/dist/element.d.ts +9 -4
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +101 -26
- package/dist/element.js.map +1 -1
- package/dist/event-listeners.d.ts +4 -4
- package/dist/event-listeners.d.ts.map +1 -1
- package/dist/event-listeners.js +1 -1
- package/dist/event-listeners.js.map +1 -1
- package/dist/event-types.d.ts +10 -0
- package/dist/event-types.d.ts.map +1 -1
- package/dist/event-types.js.map +1 -1
- package/dist/events.js +22 -1
- package/dist/events.js.map +1 -1
- package/dist/fiber-commit.d.ts +2 -1
- package/dist/fiber-commit.d.ts.map +1 -1
- package/dist/fiber-commit.js +13 -1
- package/dist/fiber-commit.js.map +1 -1
- package/dist/fiber-reconciler.d.ts.map +1 -1
- package/dist/fiber-reconciler.js +28 -7
- package/dist/fiber-reconciler.js.map +1 -1
- package/dist/fiber-work-loop.d.ts.map +1 -1
- package/dist/fiber-work-loop.js +4 -3
- package/dist/fiber-work-loop.js.map +1 -1
- package/dist/fiber.d.ts +5 -0
- package/dist/fiber.d.ts.map +1 -1
- package/dist/fiber.js +9 -0
- package/dist/fiber.js.map +1 -1
- package/dist/hooks-entry.d.ts +3 -0
- package/dist/hooks-entry.d.ts.map +1 -0
- package/dist/hooks-entry.js +2 -0
- package/dist/hooks-entry.js.map +1 -0
- package/dist/hooks.d.ts +39 -5
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +373 -326
- package/dist/hooks.js.map +1 -1
- package/dist/host-reconciler.d.ts +3 -0
- package/dist/host-reconciler.d.ts.map +1 -1
- package/dist/host-reconciler.js +1152 -64
- package/dist/host-reconciler.js.map +1 -1
- package/dist/hydration.d.ts +1 -1
- package/dist/hydration.d.ts.map +1 -1
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/react-default.d.ts +4 -4
- package/dist/react-default.d.ts.map +1 -1
- package/dist/react-default.js +2 -1
- package/dist/react-default.js.map +1 -1
- package/dist/reconciler.d.ts.map +1 -1
- package/dist/reconciler.js +38 -22
- package/dist/reconciler.js.map +1 -1
- package/dist/root.d.ts.map +1 -1
- package/dist/root.js +48 -13
- package/dist/root.js.map +1 -1
- package/dist/server-render.d.ts +6 -0
- package/dist/server-render.d.ts.map +1 -0
- package/dist/server-render.js +307 -0
- package/dist/server-render.js.map +1 -0
- package/package.json +6 -2
- package/src/class-component.ts +216 -51
- package/src/context.ts +108 -9
- package/src/dom-children.ts +155 -1
- package/src/dom-host-rules.ts +115 -0
- package/src/dom-props.ts +297 -46
- package/src/element.ts +141 -31
- package/src/event-listeners.ts +6 -6
- package/src/event-types.ts +10 -0
- package/src/events.ts +32 -10
- package/src/fiber-commit.ts +16 -1
- package/src/fiber-reconciler.ts +39 -6
- package/src/fiber-work-loop.ts +4 -3
- package/src/fiber.ts +14 -0
- package/src/hooks-entry.ts +24 -0
- package/src/hooks.ts +482 -479
- package/src/host-reconciler.ts +1628 -94
- package/src/hydration.ts +1 -1
- package/src/index.ts +1 -1
- package/src/react-default.ts +1 -1
- package/src/reconciler.ts +61 -22
- package/src/root.ts +55 -12
- package/src/server-render.ts +478 -0
package/dist/host-reconciler.js
CHANGED
|
@@ -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,
|
|
9
|
+
import { renderWithRootRuntime, renderWithProfiler, renderWithStrictModeMemoCapture, renderStrictModeReplay, runWithHostCommit, restoreRuntimeSnapshot, takeRuntimeSnapshot, getDevToolsHookState, hasContextDependency, hasChangedContextDependency, } from "./hooks.js";
|
|
8
10
|
import { isThenable } from "./thenable.js";
|
|
9
11
|
import { isClassComponentType, recoverClassComponentError, renderClassComponentWithRuntime, } from "./class-component.js";
|
|
10
|
-
import { areMemoPropsEqual, getPendingProps } from "./prop-comparison.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
|
|
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
|
-
|
|
89
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
-
|
|
102
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
-
:
|
|
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
|
|
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);
|
|
@@ -302,6 +736,7 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
|
|
|
302
736
|
fiber.type = memoType;
|
|
303
737
|
if (previousMemoState !== undefined &&
|
|
304
738
|
!hasDirtyInstance(runtime, previousMemoState.instanceKeys) &&
|
|
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,8 @@ 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
|
|
819
|
+
const previousClassChildKeys = collectInstanceKeys(runtime, `${path}.class`);
|
|
820
|
+
const rendered = renderClassComponentWithRuntime(classType, node.props, runtime, path, { hasDirtyDescendant: hasDirtyInstance(runtime, previousClassChildKeys) });
|
|
375
821
|
applyRef(node.ref, rendered.kind === "skip" ? current?.stateNode : rendered.instance);
|
|
376
822
|
if (rendered.kind === "skip") {
|
|
377
823
|
fiber.child = current?.child;
|
|
@@ -397,31 +843,62 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
|
|
|
397
843
|
if (runtime === undefined) {
|
|
398
844
|
return { fiber: undefined, consumed: 0 };
|
|
399
845
|
}
|
|
846
|
+
const previousFunctionState = current?.tag === "function-component"
|
|
847
|
+
? current.stateNode
|
|
848
|
+
: undefined;
|
|
400
849
|
const fiber = current?.tag === "function-component" && current.type === node.type
|
|
401
850
|
? createWorkInProgress(current, node.props)
|
|
402
851
|
: createFiber("function-component", node.props, key);
|
|
403
852
|
fiber.type = node.type;
|
|
404
|
-
const
|
|
853
|
+
const canReuseSameElement = previousFunctionState !== undefined &&
|
|
854
|
+
previousFunctionState.hasContextDependencies !== true &&
|
|
855
|
+
previousFunctionState.element === node;
|
|
856
|
+
const canReuseExternalStoreSnapshot = previousFunctionState !== undefined &&
|
|
857
|
+
runtime.externalStoreUpdate &&
|
|
858
|
+
shallowEqual(previousFunctionState.props, node.props) &&
|
|
859
|
+
!hasChangedContextDependency(runtime, previousFunctionState.instanceKeys);
|
|
860
|
+
if (runtime.strictReplayDepth === 0 &&
|
|
861
|
+
previousFunctionState !== undefined &&
|
|
862
|
+
(canReuseSameElement || canReuseExternalStoreSnapshot) &&
|
|
863
|
+
!hasDirtyInstance(runtime, previousFunctionState.instanceKeys) &&
|
|
864
|
+
!hasUnflushedMountEffectInstance(runtime, previousFunctionState.instanceKeys) &&
|
|
865
|
+
!hasPendingAsyncChild(current?.child)) {
|
|
866
|
+
markActiveInstanceKeys(runtime, previousFunctionState.instanceKeys);
|
|
867
|
+
fiber.child = current?.child;
|
|
868
|
+
fiber.memoizedState = current?.memoizedState;
|
|
869
|
+
fiber.stateNode = previousFunctionState;
|
|
870
|
+
return { fiber, consumed: options.previousNodes?.length ?? 0 };
|
|
871
|
+
}
|
|
872
|
+
const rendered = renderWithRootRuntime(runtime, path, () => node.type(node.props), node.type);
|
|
405
873
|
fiber.memoizedState = getDevToolsHookState(runtime, path);
|
|
406
874
|
const childOptions = withHydrationComponentStack(options, getComponentName(node.type));
|
|
407
875
|
const childResult = reconcileHostChild(fiber, current?.tag === "function-component" ? current.child : undefined, rendered, runtime, `${path}.0`, childOptions);
|
|
408
876
|
fiber.child = childResult.fiber;
|
|
877
|
+
const instanceKeys = collectInstanceKeys(runtime, path);
|
|
878
|
+
fiber.stateNode = {
|
|
879
|
+
element: node,
|
|
880
|
+
props: { ...node.props },
|
|
881
|
+
instanceKeys,
|
|
882
|
+
hasContextDependencies: hasContextDependency(runtime, instanceKeys),
|
|
883
|
+
};
|
|
409
884
|
return { fiber, consumed: childResult.consumed };
|
|
410
885
|
}
|
|
411
886
|
if (typeof node.type !== "string") {
|
|
412
887
|
return { fiber: undefined, consumed: 0 };
|
|
413
888
|
}
|
|
889
|
+
const elementNamespace = namespaceForHostElement(options.namespace ?? "html", node.type);
|
|
890
|
+
const childNamespace = namespaceForHostChildren(elementNamespace, node.type);
|
|
414
891
|
const fiber = current?.tag === "host-component" && current.type === node.type
|
|
415
892
|
? createWorkInProgress(current, node.props)
|
|
416
893
|
: createFiber("host-component", node.props, key);
|
|
417
894
|
const existing = options.previousNodes?.[0];
|
|
418
|
-
const existingElement = existing
|
|
895
|
+
const existingElement = isHostElement(existing) ? existing : undefined;
|
|
419
896
|
const tagMatches = existingElement !== undefined &&
|
|
420
|
-
existingElement
|
|
897
|
+
hostElementMatches(existingElement, node.type, elementNamespace);
|
|
421
898
|
if (existing === undefined && options.previousNodes !== undefined) {
|
|
422
899
|
reportMissingHydrationNode(options, path);
|
|
423
900
|
}
|
|
424
|
-
else if (existing !== undefined && !(existing
|
|
901
|
+
else if (existing !== undefined && !isHostElement(existing)) {
|
|
425
902
|
reportHydrationNodeTypeMismatch(options, path, `<${node.type}>`, existing);
|
|
426
903
|
}
|
|
427
904
|
if (existingElement !== undefined && !tagMatches) {
|
|
@@ -434,16 +911,39 @@ function createHostFiber(parent, current, node, key, runtime, path, options = {}
|
|
|
434
911
|
? existingElement
|
|
435
912
|
: current?.tag === "host-component" &&
|
|
436
913
|
current.type === node.type &&
|
|
437
|
-
current.stateNode
|
|
914
|
+
isHostElement(current.stateNode) &&
|
|
915
|
+
hostElementMatches(current.stateNode, node.type, elementNamespace)
|
|
438
916
|
? current.stateNode
|
|
439
|
-
:
|
|
917
|
+
: createHostElement(getDocumentRef(options), node.type, options.namespace ?? "html");
|
|
440
918
|
fiber.hydrateExisting = tagMatches && options.previousNodes !== undefined;
|
|
441
919
|
const previousChildNodes = tagMatches && existingElement !== undefined
|
|
442
920
|
? Array.from(existingElement.childNodes)
|
|
443
921
|
: undefined;
|
|
444
|
-
const
|
|
445
|
-
?
|
|
446
|
-
:
|
|
922
|
+
const directTextChild = shouldUseDirectHostTextChild() && previousChildNodes === undefined
|
|
923
|
+
? getDirectHostTextChild(node.props.children)
|
|
924
|
+
: undefined;
|
|
925
|
+
if (previousChildNodes === undefined &&
|
|
926
|
+
current?.tag === "host-component" &&
|
|
927
|
+
current.type === node.type &&
|
|
928
|
+
Object.is(hostFiberChildrenProp(current.memoizedProps), node.props.children) &&
|
|
929
|
+
canReuseStaticHostSubtree(current.child)) {
|
|
930
|
+
fiber.child = current.child;
|
|
931
|
+
if (fiber.child !== undefined) {
|
|
932
|
+
fiber.child.return = fiber;
|
|
933
|
+
}
|
|
934
|
+
parent.child ??= fiber;
|
|
935
|
+
return { fiber, consumed: existing === undefined ? 0 : 1 };
|
|
936
|
+
}
|
|
937
|
+
if (directTextChild !== undefined) {
|
|
938
|
+
fiber.child = undefined;
|
|
939
|
+
parent.child ??= fiber;
|
|
940
|
+
return { fiber, consumed: existing === undefined ? 0 : 1 };
|
|
941
|
+
}
|
|
942
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "host-component" ? current.child : undefined, node.props.children, runtime, `${path}.c`, {
|
|
943
|
+
...options,
|
|
944
|
+
namespace: childNamespace,
|
|
945
|
+
...(previousChildNodes === undefined ? {} : { previousNodes: previousChildNodes }),
|
|
946
|
+
});
|
|
447
947
|
fiber.child = childResult.fiber;
|
|
448
948
|
if (previousChildNodes !== undefined) {
|
|
449
949
|
reportExtraHydrationNodes(options, `${path}.c`, previousChildNodes, childResult.consumed);
|
|
@@ -461,86 +961,416 @@ function commitHostChildren(fiber, parent, eventRoot, path, options = {}) {
|
|
|
461
961
|
let cursor = fiber;
|
|
462
962
|
let index = 0;
|
|
463
963
|
while (cursor !== undefined) {
|
|
464
|
-
|
|
964
|
+
for (const node of commitHostFiber(cursor, parent, eventRoot, joinCommitPath(path, String(index)), options)) {
|
|
965
|
+
nodes.push(node);
|
|
966
|
+
}
|
|
465
967
|
cursor = cursor.sibling;
|
|
466
968
|
index += 1;
|
|
467
969
|
}
|
|
468
970
|
return nodes;
|
|
469
971
|
}
|
|
972
|
+
function commitHostDirtyChildren(fiber, parent, eventRoot, path, options = {}) {
|
|
973
|
+
let cursor = fiber;
|
|
974
|
+
let index = 0;
|
|
975
|
+
while (cursor !== undefined) {
|
|
976
|
+
if (hasHostCommitWork(cursor)) {
|
|
977
|
+
commitHostDirtyFiber(cursor, parent, eventRoot, joinCommitPath(path, String(index)), options);
|
|
978
|
+
}
|
|
979
|
+
cursor = cursor.sibling;
|
|
980
|
+
index += 1;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
function commitHostDirtyFiber(fiber, parent, eventRoot, path, options = {}) {
|
|
984
|
+
if (fiber.tag === "host-text") {
|
|
985
|
+
commitHostFiber(fiber, parent, eventRoot, path, options);
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
if (fiber.tag === "host-component") {
|
|
989
|
+
const element = fiber.stateNode;
|
|
990
|
+
if (!isHostElement(element)) {
|
|
991
|
+
finishCommittedFiber(fiber);
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
const props = fiber.pendingProps;
|
|
995
|
+
const propsAreUnchanged = fiber.hydrateExisting !== true &&
|
|
996
|
+
hostPropsEqual(fiber.memoizedProps, props);
|
|
997
|
+
const propsAreChildrenOnly = fiber.hydrateExisting !== true &&
|
|
998
|
+
hostPropsAreChildrenOnly(fiber.memoizedProps) &&
|
|
999
|
+
hostPropsAreChildrenOnly(props);
|
|
1000
|
+
const textOnlyRowUpdate = fiber.hydrateExisting !== true &&
|
|
1001
|
+
isRowTextOnlyUpdate(fiber.memoizedProps, props);
|
|
1002
|
+
if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
|
|
1003
|
+
applyProps(element, props, path, {
|
|
1004
|
+
...options,
|
|
1005
|
+
eventRoot,
|
|
1006
|
+
preserveHydrationAttributes: fiber.hydrateExisting,
|
|
1007
|
+
});
|
|
1008
|
+
applyRef(props.ref, element);
|
|
1009
|
+
}
|
|
1010
|
+
const directTextChild = fiber.child === undefined && fiber.hydrateExisting !== true
|
|
1011
|
+
? getDirectHostTextChild(props.children)
|
|
1012
|
+
: undefined;
|
|
1013
|
+
if (directTextChild !== undefined) {
|
|
1014
|
+
syncDirectHostTextChild(element, directTextChild);
|
|
1015
|
+
}
|
|
1016
|
+
else if (fiber.subtreeFlags !== NoFlags) {
|
|
1017
|
+
commitHostDirtyChildren(fiber.child, element, eventRoot, `${path}.c`, options);
|
|
1018
|
+
}
|
|
1019
|
+
if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
|
|
1020
|
+
applyPostChildFormProps(element, props);
|
|
1021
|
+
}
|
|
1022
|
+
fiber.memoizedProps = props;
|
|
1023
|
+
finishCommittedFiber(fiber);
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
if (fiber.tag === "portal") {
|
|
1027
|
+
const container = fiber.stateNode;
|
|
1028
|
+
if (container instanceof Element) {
|
|
1029
|
+
setLogicalEventParent(container, parent);
|
|
1030
|
+
commitHostDirtyChildren(fiber.child, container, container, `${path}.portal`, options);
|
|
1031
|
+
}
|
|
1032
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
1033
|
+
finishCommittedFiber(fiber);
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
if (fiber.subtreeFlags !== NoFlags) {
|
|
1037
|
+
commitHostDirtyChildren(fiber.child, parent, eventRoot, path, options);
|
|
1038
|
+
}
|
|
1039
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
1040
|
+
finishCommittedFiber(fiber);
|
|
1041
|
+
}
|
|
1042
|
+
function hasHostCommitWork(fiber) {
|
|
1043
|
+
return (fiber.flags !== NoFlags ||
|
|
1044
|
+
fiber.subtreeFlags !== NoFlags ||
|
|
1045
|
+
fiber.hostChildListChanged ||
|
|
1046
|
+
fiber.childListChanged ||
|
|
1047
|
+
fiber.subtreeChildListChanged ||
|
|
1048
|
+
fiber.hydrateExisting);
|
|
1049
|
+
}
|
|
1050
|
+
function commitHostKeyedChildListMutation(fiber, parent, eventRoot, path, options = {}) {
|
|
1051
|
+
let cursor = fiber;
|
|
1052
|
+
let index = 0;
|
|
1053
|
+
let committed = false;
|
|
1054
|
+
while (cursor !== undefined) {
|
|
1055
|
+
if (!hasHostCommitWork(cursor)) {
|
|
1056
|
+
cursor = cursor.sibling;
|
|
1057
|
+
index += 1;
|
|
1058
|
+
continue;
|
|
1059
|
+
}
|
|
1060
|
+
const childPath = joinCommitPath(path, String(index));
|
|
1061
|
+
const didCommit = commitHostKeyedChildListMutationFiber(cursor, parent, eventRoot, childPath, options);
|
|
1062
|
+
if (!didCommit) {
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
committed = true;
|
|
1066
|
+
cursor = cursor.sibling;
|
|
1067
|
+
index += 1;
|
|
1068
|
+
}
|
|
1069
|
+
return committed;
|
|
1070
|
+
}
|
|
1071
|
+
function commitHostKeyedChildListMutationFiber(fiber, parent, eventRoot, path, options = {}) {
|
|
1072
|
+
if (fiber.childListChanged) {
|
|
1073
|
+
const mutationParent = fiber.tag === "host-component" && isHostElement(fiber.stateNode)
|
|
1074
|
+
? fiber.stateNode
|
|
1075
|
+
: parent;
|
|
1076
|
+
if (fiber.tag === "host-component" && !isHostElement(fiber.stateNode)) {
|
|
1077
|
+
return false;
|
|
1078
|
+
}
|
|
1079
|
+
if (commitHostAppendSuffix(fiber, mutationParent, eventRoot, path, options)) {
|
|
1080
|
+
finishHostPassthroughFiber(fiber);
|
|
1081
|
+
return true;
|
|
1082
|
+
}
|
|
1083
|
+
if (commitHostSingleRemoval(fiber, mutationParent)) {
|
|
1084
|
+
finishHostPassthroughFiber(fiber);
|
|
1085
|
+
return true;
|
|
1086
|
+
}
|
|
1087
|
+
return false;
|
|
1088
|
+
}
|
|
1089
|
+
if (fiber.subtreeChildListChanged) {
|
|
1090
|
+
if (fiber.tag === "host-component") {
|
|
1091
|
+
const element = fiber.stateNode;
|
|
1092
|
+
if (!isHostElement(element)) {
|
|
1093
|
+
return false;
|
|
1094
|
+
}
|
|
1095
|
+
if (!commitHostKeyedChildListMutation(fiber.child, element, eventRoot, `${path}.c`, options)) {
|
|
1096
|
+
return false;
|
|
1097
|
+
}
|
|
1098
|
+
finishHostPassthroughFiber(fiber);
|
|
1099
|
+
return true;
|
|
1100
|
+
}
|
|
1101
|
+
if (!commitHostKeyedChildListMutation(fiber.child, parent, eventRoot, path, options)) {
|
|
1102
|
+
return false;
|
|
1103
|
+
}
|
|
1104
|
+
finishHostPassthroughFiber(fiber);
|
|
1105
|
+
return true;
|
|
1106
|
+
}
|
|
1107
|
+
commitHostDirtyFiber(fiber, parent, eventRoot, path, options);
|
|
1108
|
+
return true;
|
|
1109
|
+
}
|
|
1110
|
+
function commitHostAppendSuffix(fiber, parent, eventRoot, path, options) {
|
|
1111
|
+
const append = getPlacementAppendSuffix(fiber.child) ?? getAppendSuffix(fiber.alternate?.child, fiber.child);
|
|
1112
|
+
if (append === undefined) {
|
|
1113
|
+
return false;
|
|
1114
|
+
}
|
|
1115
|
+
let cursor = append.fiber;
|
|
1116
|
+
let index = append.index;
|
|
1117
|
+
while (cursor !== undefined) {
|
|
1118
|
+
for (const node of commitHostFiber(cursor, parent, eventRoot, joinCommitPath(path, String(index)), options)) {
|
|
1119
|
+
parent.appendChild(node);
|
|
1120
|
+
}
|
|
1121
|
+
cursor = cursor.sibling;
|
|
1122
|
+
index += 1;
|
|
1123
|
+
}
|
|
1124
|
+
return true;
|
|
1125
|
+
}
|
|
1126
|
+
function getPlacementAppendSuffix(next) {
|
|
1127
|
+
let nextCursor = next;
|
|
1128
|
+
let index = 0;
|
|
1129
|
+
while (nextCursor !== undefined) {
|
|
1130
|
+
if ((nextCursor.flags & Placement) !== NoFlags) {
|
|
1131
|
+
if (index === 0) {
|
|
1132
|
+
return undefined;
|
|
1133
|
+
}
|
|
1134
|
+
let appendCursor = nextCursor;
|
|
1135
|
+
while (appendCursor !== undefined) {
|
|
1136
|
+
if ((appendCursor.flags & Placement) === NoFlags) {
|
|
1137
|
+
return undefined;
|
|
1138
|
+
}
|
|
1139
|
+
appendCursor = appendCursor.sibling;
|
|
1140
|
+
}
|
|
1141
|
+
return { fiber: nextCursor, index };
|
|
1142
|
+
}
|
|
1143
|
+
if (hasHostCommitWork(nextCursor)) {
|
|
1144
|
+
return undefined;
|
|
1145
|
+
}
|
|
1146
|
+
nextCursor = nextCursor.sibling;
|
|
1147
|
+
index += 1;
|
|
1148
|
+
}
|
|
1149
|
+
return undefined;
|
|
1150
|
+
}
|
|
1151
|
+
function commitHostSingleRemoval(fiber, parent) {
|
|
1152
|
+
const removed = getSingleRemovedFiber(fiber.alternate?.child, fiber.child);
|
|
1153
|
+
if (removed === undefined) {
|
|
1154
|
+
return false;
|
|
1155
|
+
}
|
|
1156
|
+
let removedAny = false;
|
|
1157
|
+
for (const node of collectCommittedHostNodes(removed)) {
|
|
1158
|
+
if (node.parentNode !== parent) {
|
|
1159
|
+
return false;
|
|
1160
|
+
}
|
|
1161
|
+
parent.removeChild(node);
|
|
1162
|
+
removedAny = true;
|
|
1163
|
+
}
|
|
1164
|
+
return removedAny;
|
|
1165
|
+
}
|
|
1166
|
+
function getAppendSuffix(current, next) {
|
|
1167
|
+
let currentCursor = current;
|
|
1168
|
+
let nextCursor = next;
|
|
1169
|
+
let index = 0;
|
|
1170
|
+
while (currentCursor !== undefined && nextCursor !== undefined) {
|
|
1171
|
+
if (!isSameFiberSlot(currentCursor, nextCursor) || hasHostCommitWork(nextCursor)) {
|
|
1172
|
+
return undefined;
|
|
1173
|
+
}
|
|
1174
|
+
currentCursor = currentCursor.sibling;
|
|
1175
|
+
nextCursor = nextCursor.sibling;
|
|
1176
|
+
index += 1;
|
|
1177
|
+
}
|
|
1178
|
+
if (currentCursor !== undefined || nextCursor === undefined) {
|
|
1179
|
+
return undefined;
|
|
1180
|
+
}
|
|
1181
|
+
return { fiber: nextCursor, index };
|
|
1182
|
+
}
|
|
1183
|
+
function getSingleRemovedFiber(current, next) {
|
|
1184
|
+
let currentCursor = current;
|
|
1185
|
+
let nextCursor = next;
|
|
1186
|
+
while (currentCursor !== undefined && nextCursor !== undefined) {
|
|
1187
|
+
if (!isSameFiberSlot(currentCursor, nextCursor)) {
|
|
1188
|
+
break;
|
|
1189
|
+
}
|
|
1190
|
+
if (hasHostCommitWork(nextCursor)) {
|
|
1191
|
+
return undefined;
|
|
1192
|
+
}
|
|
1193
|
+
currentCursor = currentCursor.sibling;
|
|
1194
|
+
nextCursor = nextCursor.sibling;
|
|
1195
|
+
}
|
|
1196
|
+
if (currentCursor === undefined) {
|
|
1197
|
+
return undefined;
|
|
1198
|
+
}
|
|
1199
|
+
const removed = currentCursor;
|
|
1200
|
+
currentCursor = currentCursor.sibling;
|
|
1201
|
+
while (currentCursor !== undefined && nextCursor !== undefined) {
|
|
1202
|
+
if (!isSameFiberSlot(currentCursor, nextCursor) || hasHostCommitWork(nextCursor)) {
|
|
1203
|
+
return undefined;
|
|
1204
|
+
}
|
|
1205
|
+
currentCursor = currentCursor.sibling;
|
|
1206
|
+
nextCursor = nextCursor.sibling;
|
|
1207
|
+
}
|
|
1208
|
+
return currentCursor === undefined && nextCursor === undefined ? removed : undefined;
|
|
1209
|
+
}
|
|
1210
|
+
function isSameFiberSlot(current, next) {
|
|
1211
|
+
return ((next === current || next.alternate === current) &&
|
|
1212
|
+
current.tag === next.tag &&
|
|
1213
|
+
current.type === next.type &&
|
|
1214
|
+
current.key === next.key);
|
|
1215
|
+
}
|
|
1216
|
+
function collectCommittedHostNodes(fiber) {
|
|
1217
|
+
if ((fiber.tag === "host-component" || fiber.tag === "host-text") &&
|
|
1218
|
+
fiber.stateNode instanceof Node) {
|
|
1219
|
+
return [fiber.stateNode];
|
|
1220
|
+
}
|
|
1221
|
+
const nodes = [];
|
|
1222
|
+
let child = fiber.child;
|
|
1223
|
+
while (child !== undefined) {
|
|
1224
|
+
nodes.push(...collectCommittedHostNodes(child));
|
|
1225
|
+
child = child.sibling;
|
|
1226
|
+
}
|
|
1227
|
+
return nodes;
|
|
1228
|
+
}
|
|
1229
|
+
function finishHostPassthroughFiber(fiber) {
|
|
1230
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
1231
|
+
finishCommittedFiber(fiber);
|
|
1232
|
+
}
|
|
470
1233
|
function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
|
|
471
1234
|
if (fiber.tag === "host-text") {
|
|
472
1235
|
const text = fiber.stateNode;
|
|
473
1236
|
if (!(text instanceof Text)) {
|
|
1237
|
+
finishCommittedFiber(fiber);
|
|
474
1238
|
return [];
|
|
475
1239
|
}
|
|
476
|
-
|
|
1240
|
+
const nextText = String(fiber.pendingProps);
|
|
1241
|
+
if (text.data !== nextText) {
|
|
1242
|
+
text.data = nextText;
|
|
1243
|
+
}
|
|
477
1244
|
fiber.memoizedProps = fiber.pendingProps;
|
|
1245
|
+
finishCommittedFiber(fiber);
|
|
478
1246
|
return [text];
|
|
479
1247
|
}
|
|
480
1248
|
if (fiber.tag === "host-component") {
|
|
481
1249
|
const element = fiber.stateNode;
|
|
482
|
-
if (!(element
|
|
1250
|
+
if (!isHostElement(element)) {
|
|
1251
|
+
finishCommittedFiber(fiber);
|
|
483
1252
|
return [];
|
|
484
1253
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
1254
|
+
if (fiber.hydrateExisting !== true &&
|
|
1255
|
+
fiber.flags === NoFlags &&
|
|
1256
|
+
fiber.subtreeFlags === NoFlags &&
|
|
1257
|
+
fiber.hostChildListChanged !== true) {
|
|
1258
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
1259
|
+
return [element];
|
|
1260
|
+
}
|
|
1261
|
+
const props = fiber.pendingProps;
|
|
1262
|
+
const propsAreUnchanged = fiber.hydrateExisting !== true &&
|
|
1263
|
+
hostPropsEqual(fiber.memoizedProps, props);
|
|
1264
|
+
const propsAreChildrenOnly = fiber.hydrateExisting !== true &&
|
|
1265
|
+
hostPropsAreChildrenOnly(fiber.memoizedProps) &&
|
|
1266
|
+
hostPropsAreChildrenOnly(props);
|
|
1267
|
+
const textOnlyRowUpdate = fiber.hydrateExisting !== true &&
|
|
1268
|
+
isRowTextOnlyUpdate(fiber.memoizedProps, props);
|
|
1269
|
+
if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
|
|
1270
|
+
applyProps(element, props, path, {
|
|
1271
|
+
...options,
|
|
1272
|
+
eventRoot,
|
|
1273
|
+
preserveHydrationAttributes: fiber.hydrateExisting,
|
|
1274
|
+
});
|
|
1275
|
+
applyRef(props.ref, element);
|
|
1276
|
+
}
|
|
1277
|
+
const directTextChild = fiber.child === undefined && fiber.hydrateExisting !== true
|
|
1278
|
+
? getDirectHostTextChild(props.children)
|
|
1279
|
+
: undefined;
|
|
1280
|
+
if (directTextChild !== undefined) {
|
|
1281
|
+
syncDirectHostTextChild(element, directTextChild);
|
|
1282
|
+
}
|
|
1283
|
+
else if (fiber.hostChildListChanged ||
|
|
1284
|
+
fiber.childListChanged ||
|
|
1285
|
+
fiber.hydrateExisting === true ||
|
|
1286
|
+
(fiber.subtreeFlags & Placement) !== NoFlags) {
|
|
1287
|
+
const childNodes = commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
|
|
1288
|
+
if (!(childNodes.length === 0 && committedPortalContainers.has(element)) &&
|
|
1289
|
+
!shouldPreserveContentEditableChildren(element, props, childNodes)) {
|
|
1290
|
+
syncChildNodes(element, childNodes);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
else if (fiber.subtreeFlags !== NoFlags) {
|
|
1294
|
+
commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
|
|
1295
|
+
}
|
|
1296
|
+
if (!propsAreUnchanged && !propsAreChildrenOnly && !textOnlyRowUpdate) {
|
|
1297
|
+
applyPostChildFormProps(element, props);
|
|
1298
|
+
}
|
|
1299
|
+
fiber.memoizedProps = props;
|
|
1300
|
+
finishCommittedFiber(fiber);
|
|
495
1301
|
return [element];
|
|
496
1302
|
}
|
|
497
1303
|
if (fiber.tag === "fragment") {
|
|
498
1304
|
fiber.memoizedProps = fiber.pendingProps;
|
|
499
|
-
|
|
1305
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.f`, options);
|
|
1306
|
+
finishCommittedFiber(fiber);
|
|
1307
|
+
return nodes;
|
|
500
1308
|
}
|
|
501
1309
|
if (fiber.tag === "profiler") {
|
|
502
1310
|
fiber.memoizedProps = fiber.pendingProps;
|
|
503
|
-
|
|
1311
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.profiler`, options);
|
|
1312
|
+
finishCommittedFiber(fiber);
|
|
1313
|
+
return nodes;
|
|
504
1314
|
}
|
|
505
1315
|
if (fiber.tag === "strict-mode") {
|
|
506
1316
|
fiber.memoizedProps = fiber.pendingProps;
|
|
507
|
-
|
|
1317
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.strict`, options);
|
|
1318
|
+
finishCommittedFiber(fiber);
|
|
1319
|
+
return nodes;
|
|
508
1320
|
}
|
|
509
1321
|
if (fiber.tag === "suspense") {
|
|
510
1322
|
fiber.memoizedProps = fiber.pendingProps;
|
|
511
|
-
|
|
1323
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.s`, options);
|
|
1324
|
+
finishCommittedFiber(fiber);
|
|
1325
|
+
return nodes;
|
|
512
1326
|
}
|
|
513
1327
|
if (fiber.tag === "suspense-list") {
|
|
514
1328
|
fiber.memoizedProps = fiber.pendingProps;
|
|
515
|
-
|
|
1329
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.sl`, options);
|
|
1330
|
+
finishCommittedFiber(fiber);
|
|
1331
|
+
return nodes;
|
|
516
1332
|
}
|
|
517
1333
|
if (fiber.tag === "context-provider" || fiber.tag === "context-consumer") {
|
|
518
1334
|
fiber.memoizedProps = fiber.pendingProps;
|
|
519
|
-
|
|
1335
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.ctx`, options);
|
|
1336
|
+
finishCommittedFiber(fiber);
|
|
1337
|
+
return nodes;
|
|
520
1338
|
}
|
|
521
1339
|
if (fiber.tag === "function-component") {
|
|
522
1340
|
fiber.memoizedProps = fiber.pendingProps;
|
|
523
|
-
|
|
1341
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.fc`, options);
|
|
1342
|
+
finishCommittedFiber(fiber);
|
|
1343
|
+
return nodes;
|
|
524
1344
|
}
|
|
525
1345
|
if (fiber.tag === "forward-ref") {
|
|
526
1346
|
fiber.memoizedProps = fiber.pendingProps;
|
|
527
|
-
|
|
1347
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.fr`, options);
|
|
1348
|
+
finishCommittedFiber(fiber);
|
|
1349
|
+
return nodes;
|
|
528
1350
|
}
|
|
529
1351
|
if (fiber.tag === "memo") {
|
|
530
1352
|
fiber.memoizedProps = fiber.pendingProps;
|
|
531
|
-
|
|
1353
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.memo`, options);
|
|
1354
|
+
finishCommittedFiber(fiber);
|
|
1355
|
+
return nodes;
|
|
532
1356
|
}
|
|
533
1357
|
if (fiber.tag === "lazy") {
|
|
534
1358
|
fiber.memoizedProps = fiber.pendingProps;
|
|
535
|
-
|
|
1359
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.lazy`, options);
|
|
1360
|
+
finishCommittedFiber(fiber);
|
|
1361
|
+
return nodes;
|
|
536
1362
|
}
|
|
537
1363
|
if (fiber.tag === "error-boundary") {
|
|
538
1364
|
fiber.memoizedProps = fiber.pendingProps;
|
|
539
|
-
|
|
1365
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.eb`, options);
|
|
1366
|
+
finishCommittedFiber(fiber);
|
|
1367
|
+
return nodes;
|
|
540
1368
|
}
|
|
541
1369
|
if (fiber.tag === "class-component") {
|
|
542
1370
|
fiber.memoizedProps = fiber.pendingProps;
|
|
543
|
-
|
|
1371
|
+
const nodes = commitHostChildren(fiber.child, parent, eventRoot, `${path}.class`, options);
|
|
1372
|
+
finishCommittedFiber(fiber);
|
|
1373
|
+
return nodes;
|
|
544
1374
|
}
|
|
545
1375
|
if (fiber.tag === "portal") {
|
|
546
1376
|
const container = fiber.stateNode;
|
|
@@ -548,13 +1378,206 @@ function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
|
|
|
548
1378
|
return [];
|
|
549
1379
|
}
|
|
550
1380
|
setLogicalEventParent(container, parent);
|
|
551
|
-
|
|
552
|
-
|
|
1381
|
+
committedPortalContainers.add(container);
|
|
1382
|
+
const portalEventRoot = eventRoot !== container && eventRoot.contains(container) ? eventRoot : container;
|
|
1383
|
+
const childNodes = commitHostChildren(fiber.child, container, portalEventRoot, `${path}.portal`, options);
|
|
1384
|
+
const previousNodes = Array.isArray(fiber.alternate?.memoizedState)
|
|
1385
|
+
? fiber.alternate.memoizedState.filter((node) => node instanceof Node)
|
|
1386
|
+
: [];
|
|
1387
|
+
syncOwnedChildNodes(container, previousNodes, childNodes);
|
|
1388
|
+
fiber.memoizedState = childNodes;
|
|
553
1389
|
fiber.memoizedProps = fiber.pendingProps;
|
|
1390
|
+
finishCommittedFiber(fiber);
|
|
554
1391
|
return [];
|
|
555
1392
|
}
|
|
1393
|
+
finishCommittedFiber(fiber);
|
|
556
1394
|
return [];
|
|
557
1395
|
}
|
|
1396
|
+
function finishCommittedFiber(fiber) {
|
|
1397
|
+
fiber.flags = NoFlags;
|
|
1398
|
+
fiber.subtreeFlags = NoFlags;
|
|
1399
|
+
fiber.childListChanged = false;
|
|
1400
|
+
fiber.subtreeChildListChanged = false;
|
|
1401
|
+
fiber.hostChildListChanged = false;
|
|
1402
|
+
}
|
|
1403
|
+
function hasChildListMutation(fiber) {
|
|
1404
|
+
return fiber.childListChanged || fiber.subtreeChildListChanged;
|
|
1405
|
+
}
|
|
1406
|
+
function hostPropsEqual(previous, next) {
|
|
1407
|
+
if (previous === next) {
|
|
1408
|
+
return true;
|
|
1409
|
+
}
|
|
1410
|
+
if (typeof previous !== "object" || previous === null) {
|
|
1411
|
+
return false;
|
|
1412
|
+
}
|
|
1413
|
+
const previousProps = previous;
|
|
1414
|
+
let previousCount = 0;
|
|
1415
|
+
let nextCount = 0;
|
|
1416
|
+
for (const key in previousProps) {
|
|
1417
|
+
if (!hasOwnProperty.call(previousProps, key)) {
|
|
1418
|
+
continue;
|
|
1419
|
+
}
|
|
1420
|
+
previousCount += 1;
|
|
1421
|
+
if (!hasOwnProperty.call(next, key)) {
|
|
1422
|
+
return false;
|
|
1423
|
+
}
|
|
1424
|
+
if (!Object.is(previousProps[key], next[key])) {
|
|
1425
|
+
return false;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
for (const key in next) {
|
|
1429
|
+
if (hasOwnProperty.call(next, key)) {
|
|
1430
|
+
nextCount += 1;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
return previousCount === nextCount;
|
|
1434
|
+
}
|
|
1435
|
+
function hostOwnPropsEqual(previous, next) {
|
|
1436
|
+
if (previous === next) {
|
|
1437
|
+
return true;
|
|
1438
|
+
}
|
|
1439
|
+
if (typeof previous !== "object" || previous === null) {
|
|
1440
|
+
return false;
|
|
1441
|
+
}
|
|
1442
|
+
const previousProps = previous;
|
|
1443
|
+
const previousMeta = getHostOwnPropsMeta(previousProps);
|
|
1444
|
+
const nextMeta = getHostOwnPropsMeta(next);
|
|
1445
|
+
if (previousMeta !== undefined && nextMeta !== undefined) {
|
|
1446
|
+
return previousMeta === nextMeta;
|
|
1447
|
+
}
|
|
1448
|
+
let previousCount = 0;
|
|
1449
|
+
let nextCount = 0;
|
|
1450
|
+
for (const key in previousProps) {
|
|
1451
|
+
if (!hasOwnProperty.call(previousProps, key) || key === "children") {
|
|
1452
|
+
continue;
|
|
1453
|
+
}
|
|
1454
|
+
previousCount += 1;
|
|
1455
|
+
if (!hasOwnProperty.call(next, key)) {
|
|
1456
|
+
return false;
|
|
1457
|
+
}
|
|
1458
|
+
if (!Object.is(previousProps[key], next[key])) {
|
|
1459
|
+
return false;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
for (const key in next) {
|
|
1463
|
+
if (hasOwnProperty.call(next, key) && key !== "children") {
|
|
1464
|
+
nextCount += 1;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
return previousCount === nextCount;
|
|
1468
|
+
}
|
|
1469
|
+
function getHostOwnPropsMeta(props) {
|
|
1470
|
+
return props[HOST_OWN_PROPS_META];
|
|
1471
|
+
}
|
|
1472
|
+
function hostDirectTextChildChanged(previous, next) {
|
|
1473
|
+
const previousText = getDirectHostTextChild(hostFiberChildrenProp(previous));
|
|
1474
|
+
const nextText = getDirectHostTextChild(next.children);
|
|
1475
|
+
return (previousText !== undefined || nextText !== undefined) && previousText !== nextText;
|
|
1476
|
+
}
|
|
1477
|
+
function hostChildListChanged(previous, next) {
|
|
1478
|
+
const previousChildren = hostFiberChildrenProp(previous);
|
|
1479
|
+
const nextChildren = next.children;
|
|
1480
|
+
if (Object.is(previousChildren, nextChildren)) {
|
|
1481
|
+
return false;
|
|
1482
|
+
}
|
|
1483
|
+
if (getDirectHostTextChild(previousChildren) !== undefined ||
|
|
1484
|
+
getDirectHostTextChild(nextChildren) !== undefined) {
|
|
1485
|
+
return false;
|
|
1486
|
+
}
|
|
1487
|
+
if (sameSingleHostChild(previousChildren, nextChildren)) {
|
|
1488
|
+
return false;
|
|
1489
|
+
}
|
|
1490
|
+
if (sameHostChildList(previousChildren, nextChildren)) {
|
|
1491
|
+
return false;
|
|
1492
|
+
}
|
|
1493
|
+
return true;
|
|
1494
|
+
}
|
|
1495
|
+
function sameSingleHostChild(previous, next) {
|
|
1496
|
+
return (isReactCompatElement(previous) &&
|
|
1497
|
+
isReactCompatElement(next) &&
|
|
1498
|
+
previous.key === next.key &&
|
|
1499
|
+
previous.type === next.type);
|
|
1500
|
+
}
|
|
1501
|
+
function sameHostChildList(previous, next) {
|
|
1502
|
+
if (!Array.isArray(previous) || !Array.isArray(next) || previous.length !== next.length) {
|
|
1503
|
+
return false;
|
|
1504
|
+
}
|
|
1505
|
+
for (let index = 0; index < previous.length; index += 1) {
|
|
1506
|
+
const previousChild = previous[index];
|
|
1507
|
+
const nextChild = next[index];
|
|
1508
|
+
if (Object.is(previousChild, nextChild)) {
|
|
1509
|
+
continue;
|
|
1510
|
+
}
|
|
1511
|
+
if (!sameSingleHostChild(previousChild, nextChild)) {
|
|
1512
|
+
return false;
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
return (previous.length > 0 ||
|
|
1516
|
+
(Array.isArray(previous) && Array.isArray(next)));
|
|
1517
|
+
}
|
|
1518
|
+
function hostPropsAreChildrenOnly(props) {
|
|
1519
|
+
if (typeof props !== "object" || props === null) {
|
|
1520
|
+
return false;
|
|
1521
|
+
}
|
|
1522
|
+
for (const key in props) {
|
|
1523
|
+
if (Object.prototype.hasOwnProperty.call(props, key) &&
|
|
1524
|
+
key !== "children") {
|
|
1525
|
+
return false;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
return true;
|
|
1529
|
+
}
|
|
1530
|
+
function isRowTextOnlyUpdate(previous, next) {
|
|
1531
|
+
if (typeof previous !== "object" || previous === null) {
|
|
1532
|
+
return false;
|
|
1533
|
+
}
|
|
1534
|
+
const previousProps = previous;
|
|
1535
|
+
const previousMeta = getHostOwnPropsMeta(previousProps);
|
|
1536
|
+
const nextMeta = getHostOwnPropsMeta(next);
|
|
1537
|
+
if (previousMeta === undefined || previousMeta !== nextMeta) {
|
|
1538
|
+
return false;
|
|
1539
|
+
}
|
|
1540
|
+
const previousText = getDirectHostTextChild(previousProps.children);
|
|
1541
|
+
const nextText = getDirectHostTextChild(next.children);
|
|
1542
|
+
return previousText !== undefined && nextText !== undefined && previousText !== nextText;
|
|
1543
|
+
}
|
|
1544
|
+
function hostFiberChildrenProp(props) {
|
|
1545
|
+
return typeof props === "object" && props !== null
|
|
1546
|
+
? props.children
|
|
1547
|
+
: undefined;
|
|
1548
|
+
}
|
|
1549
|
+
function getDirectHostTextChild(children) {
|
|
1550
|
+
return typeof children === "string" || typeof children === "number"
|
|
1551
|
+
? String(children)
|
|
1552
|
+
: undefined;
|
|
1553
|
+
}
|
|
1554
|
+
function shouldUseDirectHostTextChild() {
|
|
1555
|
+
const globalProcess = globalThis
|
|
1556
|
+
.process;
|
|
1557
|
+
return globalProcess?.env?.NODE_ENV === "production";
|
|
1558
|
+
}
|
|
1559
|
+
function syncDirectHostTextChild(element, text) {
|
|
1560
|
+
const firstChild = element.firstChild;
|
|
1561
|
+
if (firstChild instanceof Text && firstChild.nextSibling === null) {
|
|
1562
|
+
if (firstChild.data !== text) {
|
|
1563
|
+
firstChild.data = text;
|
|
1564
|
+
}
|
|
1565
|
+
return;
|
|
1566
|
+
}
|
|
1567
|
+
element.textContent = text;
|
|
1568
|
+
}
|
|
1569
|
+
function shouldPreserveContentEditableChildren(element, props, childNodes) {
|
|
1570
|
+
void childNodes;
|
|
1571
|
+
if (!element.hasAttribute("contenteditable") ||
|
|
1572
|
+
element.getAttribute("contenteditable") === "false") {
|
|
1573
|
+
return false;
|
|
1574
|
+
}
|
|
1575
|
+
const children = props.children;
|
|
1576
|
+
return (children === undefined ||
|
|
1577
|
+
children === null ||
|
|
1578
|
+
children === false ||
|
|
1579
|
+
(Array.isArray(children) && children.length === 0));
|
|
1580
|
+
}
|
|
558
1581
|
function createSuspenseFiber(current, element, key, runtime, path, options = {}) {
|
|
559
1582
|
if (runtime === undefined) {
|
|
560
1583
|
return { fiber: undefined, consumed: 0 };
|
|
@@ -609,17 +1632,17 @@ function createStrictModeFiber(current, element, key, runtime, path, options = {
|
|
|
609
1632
|
? createWorkInProgress(current, element.props)
|
|
610
1633
|
: createFiber("strict-mode", element.props, key);
|
|
611
1634
|
fiber.type = element.type;
|
|
1635
|
+
const { result: childResult, memoValues, memoValuesByHook } = renderWithStrictModeMemoCapture(runtime, () => reconcileHostChild(fiber, current?.tag === "strict-mode" ? current.child : undefined, element.props.children, runtime, `${path}.strict`, options));
|
|
1636
|
+
fiber.child = childResult.fiber;
|
|
612
1637
|
const snapshot = takeRuntimeSnapshot(runtime);
|
|
613
1638
|
try {
|
|
614
|
-
|
|
1639
|
+
renderStrictModeReplay(runtime, memoValues, memoValuesByHook, () => reconcileHostChild(fiber, childResult.fiber, element.props.children, runtime, `${path}.strict`, options.previousNodes === undefined
|
|
615
1640
|
? options
|
|
616
|
-
: { ...options, previousNodes: [] });
|
|
1641
|
+
: { ...options, previousNodes: [] }));
|
|
617
1642
|
}
|
|
618
1643
|
finally {
|
|
619
1644
|
restoreRuntimeSnapshot(runtime, snapshot);
|
|
620
1645
|
}
|
|
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
1646
|
return { fiber, consumed: childResult.consumed };
|
|
624
1647
|
}
|
|
625
1648
|
function createSuspenseListFiber(current, element, key, runtime, path, options = {}) {
|
|
@@ -680,6 +1703,7 @@ function reconcileSuspenseListForwards(parent, currentFirstChild, children, runt
|
|
|
680
1703
|
}
|
|
681
1704
|
fiber.return = parent;
|
|
682
1705
|
fiber.sibling = undefined;
|
|
1706
|
+
bubbleHostChild(parent, fiber);
|
|
683
1707
|
if (first === undefined) {
|
|
684
1708
|
first = fiber;
|
|
685
1709
|
}
|
|
@@ -710,6 +1734,7 @@ function reconcileSuspenseListBackwards(parent, currentFirstChild, children, run
|
|
|
710
1734
|
}
|
|
711
1735
|
fiber.return = parent;
|
|
712
1736
|
fiber.sibling = undefined;
|
|
1737
|
+
bubbleHostChild(parent, fiber);
|
|
713
1738
|
fibers.unshift(fiber);
|
|
714
1739
|
if (isSuspendedSuspenseFiber(fiber)) {
|
|
715
1740
|
break;
|
|
@@ -737,6 +1762,25 @@ function hasSuspendedChild(fiber) {
|
|
|
737
1762
|
}
|
|
738
1763
|
return false;
|
|
739
1764
|
}
|
|
1765
|
+
function hasPendingAsyncChild(fiber) {
|
|
1766
|
+
let cursor = fiber;
|
|
1767
|
+
while (cursor !== undefined) {
|
|
1768
|
+
if (isPendingLazyFiber(cursor) || isSuspendedSuspenseFiber(cursor)) {
|
|
1769
|
+
return true;
|
|
1770
|
+
}
|
|
1771
|
+
if (cursor.child !== undefined && hasPendingAsyncChild(cursor.child)) {
|
|
1772
|
+
return true;
|
|
1773
|
+
}
|
|
1774
|
+
cursor = cursor.sibling;
|
|
1775
|
+
}
|
|
1776
|
+
return false;
|
|
1777
|
+
}
|
|
1778
|
+
function isPendingLazyFiber(fiber) {
|
|
1779
|
+
if (fiber.tag !== "lazy" || !isLazyType(fiber.type)) {
|
|
1780
|
+
return false;
|
|
1781
|
+
}
|
|
1782
|
+
return fiber.type.status !== "resolved" || fiber.child === undefined;
|
|
1783
|
+
}
|
|
740
1784
|
function isSuspendedSuspenseFiber(fiber) {
|
|
741
1785
|
return (fiber.tag === "suspense" &&
|
|
742
1786
|
fiber.memoizedState?.didSuspend === true);
|
|
@@ -819,7 +1863,7 @@ function createPortalFiber(parent, current, portal, key, runtime, path, options
|
|
|
819
1863
|
? createWorkInProgress(current, portal.children)
|
|
820
1864
|
: createFiber("portal", portal.children, key);
|
|
821
1865
|
fiber.stateNode = portal.container;
|
|
822
|
-
const childResult = reconcileHostChild(fiber, current?.tag === "portal" ? current.child : undefined, portal.children, runtime, `${path}.portal`, options);
|
|
1866
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "portal" ? current.child : undefined, portal.children, runtime, `${path}.portal`, { ...options, documentRef: portal.container.ownerDocument });
|
|
823
1867
|
fiber.child = childResult.fiber;
|
|
824
1868
|
fiber.return = parent;
|
|
825
1869
|
return { fiber, consumed: childResult.consumed };
|
|
@@ -830,6 +1874,9 @@ function normalizeChildren(node) {
|
|
|
830
1874
|
}
|
|
831
1875
|
return Array.isArray(node) ? node : [node];
|
|
832
1876
|
}
|
|
1877
|
+
function getDocumentRef(options) {
|
|
1878
|
+
return options.documentRef ?? document;
|
|
1879
|
+
}
|
|
833
1880
|
function collectExistingKeyedFibers(firstChild) {
|
|
834
1881
|
const keyed = new Map();
|
|
835
1882
|
let cursor = firstChild;
|
|
@@ -844,10 +1891,43 @@ function collectExistingKeyedFibers(firstChild) {
|
|
|
844
1891
|
function getNodeKey(node) {
|
|
845
1892
|
return isReactCompatElement(node) && node.key !== null ? node.key : undefined;
|
|
846
1893
|
}
|
|
1894
|
+
function hasKeyedChild(children) {
|
|
1895
|
+
for (const child of children) {
|
|
1896
|
+
if (getNodeKey(child) !== undefined) {
|
|
1897
|
+
return true;
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
return false;
|
|
1901
|
+
}
|
|
847
1902
|
function getNodePathSegment(node, index) {
|
|
848
1903
|
const key = getNodeKey(node);
|
|
849
1904
|
return key === undefined ? String(index) : `k:${key}`;
|
|
850
1905
|
}
|
|
1906
|
+
function getReconcileChildPath(path, node, index, options) {
|
|
1907
|
+
if (!shouldTrackReconcilePath(node, options)) {
|
|
1908
|
+
return "";
|
|
1909
|
+
}
|
|
1910
|
+
return joinPath(path, getNodePathSegment(node, index));
|
|
1911
|
+
}
|
|
1912
|
+
function shouldTrackReconcilePath(node, options) {
|
|
1913
|
+
if (options.previousNodes !== undefined ||
|
|
1914
|
+
options.hydration?.onRecoverableError !== undefined ||
|
|
1915
|
+
options.resumeId !== undefined) {
|
|
1916
|
+
return true;
|
|
1917
|
+
}
|
|
1918
|
+
return !isHostElementWithDirectTextChild(node);
|
|
1919
|
+
}
|
|
1920
|
+
function isHostElementWithDirectTextChild(node) {
|
|
1921
|
+
return (isReactCompatElement(node) &&
|
|
1922
|
+
typeof node.type === "string" &&
|
|
1923
|
+
getDirectHostTextChild(node.props.children) !== undefined);
|
|
1924
|
+
}
|
|
1925
|
+
function getRootCommitPath(options) {
|
|
1926
|
+
return options.hydration?.onRecoverableError === undefined ? SKIP_COMMIT_PATH : "0";
|
|
1927
|
+
}
|
|
1928
|
+
function joinCommitPath(path, segment) {
|
|
1929
|
+
return path === SKIP_COMMIT_PATH ? "" : joinPath(path, segment);
|
|
1930
|
+
}
|
|
851
1931
|
function getComponentName(component) {
|
|
852
1932
|
return component.name === "" ? "Anonymous" : component.name;
|
|
853
1933
|
}
|
|
@@ -880,6 +1960,14 @@ function markActiveInstanceKeys(runtime, keys) {
|
|
|
880
1960
|
function hasDirtyInstance(runtime, keys) {
|
|
881
1961
|
return keys.some((key) => runtime.instances.get(key)?.dirty === true);
|
|
882
1962
|
}
|
|
1963
|
+
function hasUnflushedMountEffectInstance(runtime, keys) {
|
|
1964
|
+
return keys.some((key) => {
|
|
1965
|
+
const instance = runtime.instances.get(key);
|
|
1966
|
+
return instance?.hooks?.some((slot) => slot?.kind === "effect" &&
|
|
1967
|
+
slot.disposed !== true &&
|
|
1968
|
+
slot.mounted !== true) === true;
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
883
1971
|
function applyRef(ref, node) {
|
|
884
1972
|
if (typeof ref === "function") {
|
|
885
1973
|
ref(node);
|