@reckona/mreact-compat 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +32 -0
- package/dist/class-component.d.ts +48 -0
- package/dist/class-component.d.ts.map +1 -0
- package/dist/class-component.js +186 -0
- package/dist/class-component.js.map +1 -0
- package/dist/context.d.ts +31 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +83 -0
- package/dist/context.js.map +1 -0
- package/dist/devtools.d.ts +5 -0
- package/dist/devtools.d.ts.map +1 -0
- package/dist/devtools.js +839 -0
- package/dist/devtools.js.map +1 -0
- package/dist/dom-children.d.ts +3 -0
- package/dist/dom-children.d.ts.map +1 -0
- package/dist/dom-children.js +23 -0
- package/dist/dom-children.js.map +1 -0
- package/dist/dom-props.d.ts +4 -0
- package/dist/dom-props.d.ts.map +1 -0
- package/dist/dom-props.js +266 -0
- package/dist/dom-props.js.map +1 -0
- package/dist/element.d.ts +94 -0
- package/dist/element.d.ts.map +1 -0
- package/dist/element.js +160 -0
- package/dist/element.js.map +1 -0
- package/dist/event-listeners.d.ts +12 -0
- package/dist/event-listeners.d.ts.map +1 -0
- package/dist/event-listeners.js +11 -0
- package/dist/event-listeners.js.map +1 -0
- package/dist/event-replay.d.ts +18 -0
- package/dist/event-replay.d.ts.map +1 -0
- package/dist/event-replay.js +94 -0
- package/dist/event-replay.js.map +1 -0
- package/dist/event-types.d.ts +19 -0
- package/dist/event-types.d.ts.map +1 -0
- package/dist/event-types.js +2 -0
- package/dist/event-types.js.map +1 -0
- package/dist/events.d.ts +6 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +306 -0
- package/dist/events.js.map +1 -0
- package/dist/fiber-child.d.ts +4 -0
- package/dist/fiber-child.d.ts.map +1 -0
- package/dist/fiber-child.js +262 -0
- package/dist/fiber-child.js.map +1 -0
- package/dist/fiber-commit.d.ts +4 -0
- package/dist/fiber-commit.d.ts.map +1 -0
- package/dist/fiber-commit.js +54 -0
- package/dist/fiber-commit.js.map +1 -0
- package/dist/fiber-flags.d.ts +15 -0
- package/dist/fiber-flags.d.ts.map +1 -0
- package/dist/fiber-flags.js +18 -0
- package/dist/fiber-flags.js.map +1 -0
- package/dist/fiber-host.d.ts +16 -0
- package/dist/fiber-host.d.ts.map +1 -0
- package/dist/fiber-host.js +892 -0
- package/dist/fiber-host.js.map +1 -0
- package/dist/fiber-lanes.d.ts +30 -0
- package/dist/fiber-lanes.d.ts.map +1 -0
- package/dist/fiber-lanes.js +71 -0
- package/dist/fiber-lanes.js.map +1 -0
- package/dist/fiber-reconciler.d.ts +8 -0
- package/dist/fiber-reconciler.d.ts.map +1 -0
- package/dist/fiber-reconciler.js +385 -0
- package/dist/fiber-reconciler.js.map +1 -0
- package/dist/fiber-scheduler.d.ts +37 -0
- package/dist/fiber-scheduler.d.ts.map +1 -0
- package/dist/fiber-scheduler.js +307 -0
- package/dist/fiber-scheduler.js.map +1 -0
- package/dist/fiber-work-loop.d.ts +21 -0
- package/dist/fiber-work-loop.d.ts.map +1 -0
- package/dist/fiber-work-loop.js +116 -0
- package/dist/fiber-work-loop.js.map +1 -0
- package/dist/fiber.d.ts +50 -0
- package/dist/fiber.d.ts.map +1 -0
- package/dist/fiber.js +73 -0
- package/dist/fiber.js.map +1 -0
- package/dist/flight-decoder.d.ts +8 -0
- package/dist/flight-decoder.d.ts.map +1 -0
- package/dist/flight-decoder.js +132 -0
- package/dist/flight-decoder.js.map +1 -0
- package/dist/flight-element-builder.d.ts +6 -0
- package/dist/flight-element-builder.d.ts.map +1 -0
- package/dist/flight-element-builder.js +56 -0
- package/dist/flight-element-builder.js.map +1 -0
- package/dist/flight-parser.d.ts +3 -0
- package/dist/flight-parser.d.ts.map +1 -0
- package/dist/flight-parser.js +508 -0
- package/dist/flight-parser.js.map +1 -0
- package/dist/flight-protocol.d.ts +11 -0
- package/dist/flight-protocol.d.ts.map +1 -0
- package/dist/flight-protocol.js +61 -0
- package/dist/flight-protocol.js.map +1 -0
- package/dist/flight-types.d.ts +98 -0
- package/dist/flight-types.d.ts.map +1 -0
- package/dist/flight-types.js +2 -0
- package/dist/flight-types.js.map +1 -0
- package/dist/flight.d.ts +26 -0
- package/dist/flight.d.ts.map +1 -0
- package/dist/flight.js +66 -0
- package/dist/flight.js.map +1 -0
- package/dist/hooks.d.ts +214 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +1296 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hydration.d.ts +34 -0
- package/dist/hydration.d.ts.map +1 -0
- package/dist/hydration.js +164 -0
- package/dist/hydration.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +2 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +19 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +6 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +24 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +21 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/prop-comparison.d.ts +6 -0
- package/dist/prop-comparison.d.ts.map +1 -0
- package/dist/prop-comparison.js +28 -0
- package/dist/prop-comparison.js.map +1 -0
- package/dist/reconcile-types.d.ts +10 -0
- package/dist/reconcile-types.d.ts.map +1 -0
- package/dist/reconcile-types.js +2 -0
- package/dist/reconcile-types.js.map +1 -0
- package/dist/reconciler.d.ts +7 -0
- package/dist/reconciler.d.ts.map +1 -0
- package/dist/reconciler.js +318 -0
- package/dist/reconciler.js.map +1 -0
- package/dist/render.d.ts +7 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +4 -0
- package/dist/render.js.map +1 -0
- package/dist/root.d.ts +44 -0
- package/dist/root.d.ts.map +1 -0
- package/dist/root.js +278 -0
- package/dist/root.js.map +1 -0
- package/dist/scheduler.d.ts +30 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +90 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/suspense.d.ts +8 -0
- package/dist/suspense.d.ts.map +1 -0
- package/dist/suspense.js +164 -0
- package/dist/suspense.js.map +1 -0
- package/dist/thenable.d.ts +2 -0
- package/dist/thenable.d.ts.map +1 -0
- package/dist/thenable.js +6 -0
- package/dist/thenable.js.map +1 -0
- package/dist/url-safety.d.ts +2 -0
- package/dist/url-safety.d.ts.map +1 -0
- package/dist/url-safety.js +2 -0
- package/dist/url-safety.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,892 @@
|
|
|
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";
|
|
3
|
+
import { applyPostChildFormProps, applyProps } from "./dom-props.js";
|
|
4
|
+
import { syncChildNodes, syncScopedChildNodes } from "./dom-children.js";
|
|
5
|
+
import { setLogicalEventParent } from "./events.js";
|
|
6
|
+
import { createFiber, createWorkInProgress } from "./fiber.js";
|
|
7
|
+
import { renderWithRootRuntime, renderWithProfiler, renderWithStrictMode, restoreRuntimeSnapshot, takeRuntimeSnapshot, getDevToolsHookState, } from "./hooks.js";
|
|
8
|
+
import { isThenable } from "./thenable.js";
|
|
9
|
+
import { isClassComponentType, recoverClassComponentError, renderClassComponentWithRuntime, } from "./class-component.js";
|
|
10
|
+
import { areMemoPropsEqual, getPendingProps } from "./prop-comparison.js";
|
|
11
|
+
import { reportElementTextMismatch, reportExtraHydrationNodes, reportHydrationNodeTypeMismatch, reportMissingHydrationNode, reportReactSuspenseServerError, reportRecoverable, withHydrationComponentStack, } from "./hydration.js";
|
|
12
|
+
let suspensePrimaryRenderDepth = 0;
|
|
13
|
+
export function canRenderHostFiber(node) {
|
|
14
|
+
if (node === null ||
|
|
15
|
+
node === undefined ||
|
|
16
|
+
typeof node === "boolean" ||
|
|
17
|
+
typeof node === "string" ||
|
|
18
|
+
typeof node === "number") {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
if (Array.isArray(node)) {
|
|
22
|
+
return node.every(canRenderHostFiber);
|
|
23
|
+
}
|
|
24
|
+
if (isReactCompatPortal(node)) {
|
|
25
|
+
return canRenderHostFiber(node.children);
|
|
26
|
+
}
|
|
27
|
+
if (!isReactCompatElement(node)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
if (node.type === Fragment ||
|
|
31
|
+
node.type === Profiler ||
|
|
32
|
+
node.type === STRICT_MODE_TYPE) {
|
|
33
|
+
return canRenderHostFiber(node.props.children);
|
|
34
|
+
}
|
|
35
|
+
if (node.type === Activity) {
|
|
36
|
+
return node.props.mode === "hidden"
|
|
37
|
+
? true
|
|
38
|
+
: canRenderHostFiber(node.props.children);
|
|
39
|
+
}
|
|
40
|
+
if (node.type === Suspense || node.type === SuspenseList) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (node.type === ERROR_BOUNDARY_TYPE) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
if (isReactCompatProvider(node.type)) {
|
|
47
|
+
return canRenderHostFiber(node.props.children);
|
|
48
|
+
}
|
|
49
|
+
if (isReactCompatConsumer(node.type)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if (isForwardRefType(node.type)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
if (isMemoType(node.type)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (isLazyType(node.type)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
if (isClassComponentType(node.type)) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
return (typeof node.type === "string" &&
|
|
65
|
+
canRenderHostFiber(node.props.children)) || isFunctionComponentType(node.type);
|
|
66
|
+
}
|
|
67
|
+
export function renderHostFiberRoot(root, element, runtime, options = {}) {
|
|
68
|
+
const workInProgress = createWorkInProgress(root.current, { children: element });
|
|
69
|
+
const result = reconcileHostChild(workInProgress, root.current.child, element, runtime, options.previousNodes === undefined ? "0" : "", options);
|
|
70
|
+
workInProgress.child = result.fiber;
|
|
71
|
+
workInProgress.memoizedProps = { children: element };
|
|
72
|
+
return workInProgress;
|
|
73
|
+
}
|
|
74
|
+
export function renderHydratingHostFiberRoot(root, element, runtime, scope, options = {}) {
|
|
75
|
+
root.hydrationState = {
|
|
76
|
+
parent: scope.parent,
|
|
77
|
+
nextHydratableNode: scope.previousNodes[0] ?? null,
|
|
78
|
+
before: scope.before,
|
|
79
|
+
after: scope.after,
|
|
80
|
+
...(options.resumeId === undefined ? {} : { resumeId: options.resumeId }),
|
|
81
|
+
};
|
|
82
|
+
return renderHostFiberRoot(root, element, runtime, {
|
|
83
|
+
...options,
|
|
84
|
+
previousNodes: scope.previousNodes,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
export function commitHostFiberRoot(root, finishedWork, options = {}) {
|
|
88
|
+
const nodes = commitHostChildren(finishedWork.child, root.container, root.container, "0", options);
|
|
89
|
+
syncChildNodes(root.container, nodes);
|
|
90
|
+
}
|
|
91
|
+
export function commitHydratingHostFiberRoot(root, finishedWork, scope, options = {}) {
|
|
92
|
+
const eventRoot = root.container;
|
|
93
|
+
const nodes = commitHostChildren(finishedWork.child, scope.parent, eventRoot, "", options);
|
|
94
|
+
syncScopedChildNodes(scope.parent, scope.before, scope.after, nodes);
|
|
95
|
+
if (options.consumeResumeMarkers === true) {
|
|
96
|
+
scope.before?.parentNode?.removeChild(scope.before);
|
|
97
|
+
scope.after?.parentNode?.removeChild(scope.after);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function reconcileHostChild(parent, currentFirstChild, node, runtime, path, options = {}) {
|
|
101
|
+
const children = normalizeChildren(node);
|
|
102
|
+
const existingByKey = collectExistingKeyedFibers(currentFirstChild);
|
|
103
|
+
let currentUnkeyed = currentFirstChild;
|
|
104
|
+
let first;
|
|
105
|
+
let previous;
|
|
106
|
+
let consumed = 0;
|
|
107
|
+
children.forEach((child, index) => {
|
|
108
|
+
const key = getNodeKey(child);
|
|
109
|
+
const matchedCurrent = key === undefined ? currentUnkeyed : existingByKey.get(key);
|
|
110
|
+
const previousNodes = options.previousNodes === undefined
|
|
111
|
+
? undefined
|
|
112
|
+
: options.previousNodes.slice(consumed);
|
|
113
|
+
const result = createHostFiber(parent, matchedCurrent, child, key, runtime, joinPath(path, getNodePathSegment(child, index)), previousNodes === undefined ? options : { ...options, previousNodes });
|
|
114
|
+
const fiber = result.fiber;
|
|
115
|
+
if (fiber === undefined) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (key === undefined) {
|
|
119
|
+
currentUnkeyed = currentUnkeyed?.sibling;
|
|
120
|
+
}
|
|
121
|
+
consumed += result.consumed;
|
|
122
|
+
if (first === undefined) {
|
|
123
|
+
first = fiber;
|
|
124
|
+
}
|
|
125
|
+
else if (previous !== undefined) {
|
|
126
|
+
previous.sibling = fiber;
|
|
127
|
+
}
|
|
128
|
+
fiber.return = parent;
|
|
129
|
+
fiber.sibling = undefined;
|
|
130
|
+
fiber.pendingProps = getPendingProps(child);
|
|
131
|
+
if (fiber.tag !== "memo" &&
|
|
132
|
+
fiber.tag !== "function-component" &&
|
|
133
|
+
fiber.tag !== "forward-ref" &&
|
|
134
|
+
fiber.tag !== "profiler" &&
|
|
135
|
+
fiber.tag !== "suspense" &&
|
|
136
|
+
fiber.tag !== "suspense-list"
|
|
137
|
+
&& fiber.memoizedState === undefined) {
|
|
138
|
+
fiber.memoizedState = index;
|
|
139
|
+
}
|
|
140
|
+
previous = fiber;
|
|
141
|
+
});
|
|
142
|
+
return { fiber: first, consumed };
|
|
143
|
+
}
|
|
144
|
+
function createHostFiber(parent, current, node, key, runtime, path, options = {}) {
|
|
145
|
+
if (node === null || node === undefined || typeof node === "boolean") {
|
|
146
|
+
return { fiber: undefined, consumed: 0 };
|
|
147
|
+
}
|
|
148
|
+
if (typeof node === "string" || typeof node === "number") {
|
|
149
|
+
const existing = options.previousNodes?.[0];
|
|
150
|
+
const fiber = current?.tag === "host-text"
|
|
151
|
+
? createWorkInProgress(current, String(node))
|
|
152
|
+
: createFiber("host-text", String(node), key);
|
|
153
|
+
if (existing === undefined && options.previousNodes !== undefined) {
|
|
154
|
+
reportMissingHydrationNode(options, path);
|
|
155
|
+
}
|
|
156
|
+
else if (existing !== undefined && !(existing instanceof Text)) {
|
|
157
|
+
reportHydrationNodeTypeMismatch(options, path, "text", existing);
|
|
158
|
+
}
|
|
159
|
+
fiber.stateNode =
|
|
160
|
+
existing instanceof Text
|
|
161
|
+
? existing
|
|
162
|
+
: current?.tag === "host-text" && current.stateNode instanceof Text
|
|
163
|
+
? current.stateNode
|
|
164
|
+
: document.createTextNode("");
|
|
165
|
+
if (existing instanceof Text && existing.data !== String(node)) {
|
|
166
|
+
reportRecoverable(options, "text", path, new Error("Hydration text mismatch."));
|
|
167
|
+
}
|
|
168
|
+
return { fiber, consumed: existing instanceof Text ? 1 : 0 };
|
|
169
|
+
}
|
|
170
|
+
if (Array.isArray(node)) {
|
|
171
|
+
const fiber = current?.tag === "fragment"
|
|
172
|
+
? createWorkInProgress(current, node)
|
|
173
|
+
: createFiber("fragment", node, key);
|
|
174
|
+
const childResult = reconcileHostChild(fiber, current?.child, node, runtime, path, options);
|
|
175
|
+
fiber.child = childResult.fiber;
|
|
176
|
+
return { fiber, consumed: childResult.consumed };
|
|
177
|
+
}
|
|
178
|
+
if (!isReactCompatElement(node)) {
|
|
179
|
+
if (isReactCompatPortal(node)) {
|
|
180
|
+
return createPortalFiber(parent, current, node, key, runtime, path, options);
|
|
181
|
+
}
|
|
182
|
+
return { fiber: undefined, consumed: 0 };
|
|
183
|
+
}
|
|
184
|
+
if (node.type === Fragment) {
|
|
185
|
+
const fiber = current?.tag === "fragment"
|
|
186
|
+
? createWorkInProgress(current, node.props.children)
|
|
187
|
+
: createFiber("fragment", node.props.children, key);
|
|
188
|
+
const childResult = reconcileHostChild(fiber, current?.child, node.props.children, runtime, `${path}.f`, options);
|
|
189
|
+
fiber.child = childResult.fiber;
|
|
190
|
+
return { fiber, consumed: childResult.consumed };
|
|
191
|
+
}
|
|
192
|
+
if (node.type === Activity) {
|
|
193
|
+
const children = node.props.mode === "hidden"
|
|
194
|
+
? null
|
|
195
|
+
: node.props.children;
|
|
196
|
+
const fiber = current?.tag === "fragment"
|
|
197
|
+
? createWorkInProgress(current, children)
|
|
198
|
+
: createFiber("fragment", children, key);
|
|
199
|
+
fiber.type = node.type;
|
|
200
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "fragment" ? current.child : undefined, children, runtime, `${path}.activity`, options);
|
|
201
|
+
fiber.child = childResult.fiber;
|
|
202
|
+
return { fiber, consumed: childResult.consumed };
|
|
203
|
+
}
|
|
204
|
+
if (node.type === Profiler) {
|
|
205
|
+
if (runtime === undefined) {
|
|
206
|
+
return { fiber: undefined, consumed: 0 };
|
|
207
|
+
}
|
|
208
|
+
const fiber = current?.tag === "profiler" && current.type === node.type
|
|
209
|
+
? createWorkInProgress(current, node.props)
|
|
210
|
+
: createFiber("profiler", node.props, key);
|
|
211
|
+
fiber.type = node.type;
|
|
212
|
+
const childResult = renderWithProfiler(runtime, `${path}.profiler`, node.props, () => reconcileHostChild(fiber, current?.tag === "profiler" ? current.child : undefined, node.props.children, runtime, `${path}.profiler`, options));
|
|
213
|
+
fiber.child = childResult.fiber;
|
|
214
|
+
return { fiber, consumed: childResult.consumed };
|
|
215
|
+
}
|
|
216
|
+
if (node.type === STRICT_MODE_TYPE) {
|
|
217
|
+
return createStrictModeFiber(current, node, key, runtime, path, options);
|
|
218
|
+
}
|
|
219
|
+
if (node.type === Suspense) {
|
|
220
|
+
return createSuspenseFiber(current, node, key, runtime, path, options);
|
|
221
|
+
}
|
|
222
|
+
if (node.type === SuspenseList) {
|
|
223
|
+
return createSuspenseListFiber(current, node, key, runtime, path, options);
|
|
224
|
+
}
|
|
225
|
+
if (node.type === ERROR_BOUNDARY_TYPE) {
|
|
226
|
+
const fiber = current?.tag === "error-boundary"
|
|
227
|
+
? createWorkInProgress(current, node.props)
|
|
228
|
+
: createFiber("error-boundary", node.props, key);
|
|
229
|
+
fiber.type = node.type;
|
|
230
|
+
try {
|
|
231
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "error-boundary" ? current.child : undefined, node.props.children, runtime, `${path}.eb`, options);
|
|
232
|
+
fiber.child = childResult.fiber;
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
if (isThenable(error)) {
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
239
|
+
const onError = node.props.onError;
|
|
240
|
+
if (typeof onError === "function") {
|
|
241
|
+
onError(normalizedError);
|
|
242
|
+
}
|
|
243
|
+
const fallback = node.props.fallback;
|
|
244
|
+
const fallbackNode = typeof fallback === "function"
|
|
245
|
+
? fallback(normalizedError)
|
|
246
|
+
: null;
|
|
247
|
+
const fallbackResult = reconcileHostChild(fiber, current?.tag === "error-boundary" ? current.child : undefined, fallbackNode, runtime, `${path}.eb.fallback`, options);
|
|
248
|
+
fiber.child = fallbackResult.fiber;
|
|
249
|
+
}
|
|
250
|
+
return { fiber, consumed: options.previousNodes?.length ?? 0 };
|
|
251
|
+
}
|
|
252
|
+
if (isReactCompatProvider(node.type)) {
|
|
253
|
+
const fiber = current?.tag === "context-provider" && current.type === node.type
|
|
254
|
+
? createWorkInProgress(current, node.props)
|
|
255
|
+
: createFiber("context-provider", node.props, key);
|
|
256
|
+
fiber.type = node.type;
|
|
257
|
+
const childResult = renderWithContextProvider(node.type, node.props.value, () => reconcileHostChild(fiber, current?.tag === "context-provider" ? current.child : undefined, node.props.children, runtime, `${path}.provider`, options));
|
|
258
|
+
fiber.child = childResult.fiber;
|
|
259
|
+
return { fiber, consumed: childResult.consumed };
|
|
260
|
+
}
|
|
261
|
+
if (isReactCompatConsumer(node.type)) {
|
|
262
|
+
const fiber = current?.tag === "context-consumer" && current.type === node.type
|
|
263
|
+
? createWorkInProgress(current, node.props)
|
|
264
|
+
: createFiber("context-consumer", node.props, key);
|
|
265
|
+
fiber.type = node.type;
|
|
266
|
+
const children = node.props.children;
|
|
267
|
+
const render = typeof children === "function"
|
|
268
|
+
? children
|
|
269
|
+
: () => null;
|
|
270
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "context-consumer" ? current.child : undefined, render(useContext(node.type.context)), runtime, `${path}.consumer`, options);
|
|
271
|
+
fiber.child = childResult.fiber;
|
|
272
|
+
return { fiber, consumed: childResult.consumed };
|
|
273
|
+
}
|
|
274
|
+
if (isForwardRefType(node.type)) {
|
|
275
|
+
if (runtime === undefined) {
|
|
276
|
+
return { fiber: undefined, consumed: 0 };
|
|
277
|
+
}
|
|
278
|
+
const forwardRefType = node.type;
|
|
279
|
+
const fiber = current?.tag === "forward-ref" && current.type === forwardRefType
|
|
280
|
+
? createWorkInProgress(current, node.props)
|
|
281
|
+
: createFiber("forward-ref", node.props, key);
|
|
282
|
+
fiber.type = forwardRefType;
|
|
283
|
+
const rendered = renderWithRootRuntime(runtime, path, () => forwardRefType.render(node.props, node.ref));
|
|
284
|
+
fiber.memoizedState = getDevToolsHookState(runtime, path);
|
|
285
|
+
const childOptions = withHydrationComponentStack(options, getComponentName(forwardRefType.render));
|
|
286
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "forward-ref" ? current.child : undefined, rendered, runtime, `${path}.forwardRef`, childOptions);
|
|
287
|
+
fiber.child = childResult.fiber;
|
|
288
|
+
return { fiber, consumed: childResult.consumed };
|
|
289
|
+
}
|
|
290
|
+
if (isMemoType(node.type)) {
|
|
291
|
+
if (runtime === undefined) {
|
|
292
|
+
return { fiber: undefined, consumed: 0 };
|
|
293
|
+
}
|
|
294
|
+
const memoType = node.type;
|
|
295
|
+
const memoPath = `${path}.memo`;
|
|
296
|
+
const previousMemoState = current?.tag === "memo"
|
|
297
|
+
? current.memoizedState
|
|
298
|
+
: undefined;
|
|
299
|
+
const fiber = current?.tag === "memo" && current.type === memoType
|
|
300
|
+
? createWorkInProgress(current, node.props)
|
|
301
|
+
: createFiber("memo", node.props, key);
|
|
302
|
+
fiber.type = memoType;
|
|
303
|
+
if (previousMemoState !== undefined &&
|
|
304
|
+
!hasDirtyInstance(runtime, previousMemoState.instanceKeys) &&
|
|
305
|
+
areMemoPropsEqual(memoType, previousMemoState.props, node.props)) {
|
|
306
|
+
markActiveInstanceKeys(runtime, previousMemoState.instanceKeys);
|
|
307
|
+
fiber.child = current?.child;
|
|
308
|
+
fiber.memoizedState = previousMemoState;
|
|
309
|
+
return { fiber, consumed: options.previousNodes?.length ?? 0 };
|
|
310
|
+
}
|
|
311
|
+
const renderedElement = {
|
|
312
|
+
...node,
|
|
313
|
+
type: memoType.type,
|
|
314
|
+
};
|
|
315
|
+
const childResult = createHostFiber(fiber, current?.tag === "memo" ? current.child : undefined, renderedElement, key, runtime, memoPath, options);
|
|
316
|
+
fiber.child = childResult.fiber;
|
|
317
|
+
fiber.memoizedState = {
|
|
318
|
+
props: { ...node.props },
|
|
319
|
+
instanceKeys: collectInstanceKeys(runtime, memoPath),
|
|
320
|
+
};
|
|
321
|
+
return { fiber, consumed: childResult.consumed };
|
|
322
|
+
}
|
|
323
|
+
if (isLazyType(node.type)) {
|
|
324
|
+
if (runtime === undefined) {
|
|
325
|
+
return { fiber: undefined, consumed: 0 };
|
|
326
|
+
}
|
|
327
|
+
const lazyType = node.type;
|
|
328
|
+
const fiber = current?.tag === "lazy" && current.type === lazyType
|
|
329
|
+
? createWorkInProgress(current, node.props)
|
|
330
|
+
: createFiber("lazy", node.props, key);
|
|
331
|
+
fiber.type = lazyType;
|
|
332
|
+
if (lazyType.status === "resolved" && lazyType.resolved !== undefined) {
|
|
333
|
+
const renderedElement = {
|
|
334
|
+
...node,
|
|
335
|
+
type: lazyType.resolved,
|
|
336
|
+
};
|
|
337
|
+
const childResult = createHostFiber(fiber, current?.tag === "lazy" ? current.child : undefined, renderedElement, key, runtime, `${path}.lazy`, options);
|
|
338
|
+
fiber.child = childResult.fiber;
|
|
339
|
+
return { fiber, consumed: childResult.consumed };
|
|
340
|
+
}
|
|
341
|
+
if (lazyType.status === "rejected") {
|
|
342
|
+
throw lazyType.error;
|
|
343
|
+
}
|
|
344
|
+
if (lazyType.status === "uninitialized") {
|
|
345
|
+
lazyType.status = "pending";
|
|
346
|
+
lazyType.promise = lazyType
|
|
347
|
+
.load()
|
|
348
|
+
.then((module) => {
|
|
349
|
+
lazyType.status = "resolved";
|
|
350
|
+
lazyType.resolved = module.default;
|
|
351
|
+
runtime.rerender();
|
|
352
|
+
})
|
|
353
|
+
.catch((error) => {
|
|
354
|
+
lazyType.status = "rejected";
|
|
355
|
+
lazyType.error = error;
|
|
356
|
+
runtime.rerender();
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
if (suspensePrimaryRenderDepth > 0) {
|
|
360
|
+
throw lazyType.promise;
|
|
361
|
+
}
|
|
362
|
+
fiber.child = undefined;
|
|
363
|
+
return { fiber, consumed: 0 };
|
|
364
|
+
}
|
|
365
|
+
if (isClassComponentType(node.type)) {
|
|
366
|
+
if (runtime === undefined) {
|
|
367
|
+
return { fiber: undefined, consumed: 0 };
|
|
368
|
+
}
|
|
369
|
+
const classType = node.type;
|
|
370
|
+
const fiber = current?.tag === "class-component" && current.type === classType
|
|
371
|
+
? createWorkInProgress(current, node.props)
|
|
372
|
+
: createFiber("class-component", node.props, key);
|
|
373
|
+
fiber.type = classType;
|
|
374
|
+
const rendered = renderClassComponentWithRuntime(classType, node.props, runtime, path);
|
|
375
|
+
applyRef(node.ref, rendered.kind === "skip" ? current?.stateNode : rendered.instance);
|
|
376
|
+
if (rendered.kind === "skip") {
|
|
377
|
+
fiber.child = current?.child;
|
|
378
|
+
return { fiber, consumed: options.previousNodes?.length ?? 0 };
|
|
379
|
+
}
|
|
380
|
+
const childOptions = withHydrationComponentStack(options, getComponentName(classType));
|
|
381
|
+
try {
|
|
382
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "class-component" ? current.child : undefined, rendered.node, runtime, `${path}.class`, childOptions);
|
|
383
|
+
fiber.child = childResult.fiber;
|
|
384
|
+
fiber.stateNode = rendered.instance;
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
const fallbackNode = recoverClassComponentError(rendered.type, rendered.instance, error);
|
|
388
|
+
if (fallbackNode === undefined) {
|
|
389
|
+
throw error;
|
|
390
|
+
}
|
|
391
|
+
const fallbackResult = reconcileHostChild(fiber, current?.tag === "class-component" ? current.child : undefined, fallbackNode, runtime, `${path}.class.fallback`, childOptions);
|
|
392
|
+
fiber.child = fallbackResult.fiber;
|
|
393
|
+
}
|
|
394
|
+
return { fiber, consumed: options.previousNodes?.length ?? 0 };
|
|
395
|
+
}
|
|
396
|
+
if (isFunctionComponentType(node.type)) {
|
|
397
|
+
if (runtime === undefined) {
|
|
398
|
+
return { fiber: undefined, consumed: 0 };
|
|
399
|
+
}
|
|
400
|
+
const fiber = current?.tag === "function-component" && current.type === node.type
|
|
401
|
+
? createWorkInProgress(current, node.props)
|
|
402
|
+
: createFiber("function-component", node.props, key);
|
|
403
|
+
fiber.type = node.type;
|
|
404
|
+
const rendered = renderWithRootRuntime(runtime, path, () => node.type(node.props));
|
|
405
|
+
fiber.memoizedState = getDevToolsHookState(runtime, path);
|
|
406
|
+
const childOptions = withHydrationComponentStack(options, getComponentName(node.type));
|
|
407
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "function-component" ? current.child : undefined, rendered, runtime, `${path}.0`, childOptions);
|
|
408
|
+
fiber.child = childResult.fiber;
|
|
409
|
+
return { fiber, consumed: childResult.consumed };
|
|
410
|
+
}
|
|
411
|
+
if (typeof node.type !== "string") {
|
|
412
|
+
return { fiber: undefined, consumed: 0 };
|
|
413
|
+
}
|
|
414
|
+
const fiber = current?.tag === "host-component" && current.type === node.type
|
|
415
|
+
? createWorkInProgress(current, node.props)
|
|
416
|
+
: createFiber("host-component", node.props, key);
|
|
417
|
+
const existing = options.previousNodes?.[0];
|
|
418
|
+
const existingElement = existing instanceof HTMLElement ? existing : undefined;
|
|
419
|
+
const tagMatches = existingElement !== undefined &&
|
|
420
|
+
existingElement.tagName.toLowerCase() === node.type;
|
|
421
|
+
if (existing === undefined && options.previousNodes !== undefined) {
|
|
422
|
+
reportMissingHydrationNode(options, path);
|
|
423
|
+
}
|
|
424
|
+
else if (existing !== undefined && !(existing instanceof HTMLElement)) {
|
|
425
|
+
reportHydrationNodeTypeMismatch(options, path, `<${node.type}>`, existing);
|
|
426
|
+
}
|
|
427
|
+
if (existingElement !== undefined && !tagMatches) {
|
|
428
|
+
reportRecoverable(options, "tag", path, new Error(`Hydration tag mismatch: expected <${node.type}> but found <${existingElement.tagName.toLowerCase()}>.`));
|
|
429
|
+
reportElementTextMismatch(options, `${path}.c`, existingElement, node.props.children);
|
|
430
|
+
}
|
|
431
|
+
fiber.type = node.type;
|
|
432
|
+
fiber.stateNode =
|
|
433
|
+
tagMatches
|
|
434
|
+
? existingElement
|
|
435
|
+
: current?.tag === "host-component" &&
|
|
436
|
+
current.type === node.type &&
|
|
437
|
+
current.stateNode instanceof HTMLElement
|
|
438
|
+
? current.stateNode
|
|
439
|
+
: document.createElement(node.type);
|
|
440
|
+
fiber.hydrateExisting = tagMatches && options.previousNodes !== undefined;
|
|
441
|
+
const previousChildNodes = tagMatches && existingElement !== undefined
|
|
442
|
+
? Array.from(existingElement.childNodes)
|
|
443
|
+
: undefined;
|
|
444
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "host-component" ? current.child : undefined, node.props.children, runtime, `${path}.c`, previousChildNodes === undefined
|
|
445
|
+
? options
|
|
446
|
+
: { ...options, previousNodes: previousChildNodes });
|
|
447
|
+
fiber.child = childResult.fiber;
|
|
448
|
+
if (previousChildNodes !== undefined) {
|
|
449
|
+
reportExtraHydrationNodes(options, `${path}.c`, previousChildNodes, childResult.consumed);
|
|
450
|
+
}
|
|
451
|
+
parent.child ??= fiber;
|
|
452
|
+
return { fiber, consumed: existing === undefined ? 0 : 1 };
|
|
453
|
+
}
|
|
454
|
+
function isFunctionComponentType(value) {
|
|
455
|
+
return (typeof value === "function" &&
|
|
456
|
+
typeof value.prototype?.render !==
|
|
457
|
+
"function");
|
|
458
|
+
}
|
|
459
|
+
function commitHostChildren(fiber, parent, eventRoot, path, options = {}) {
|
|
460
|
+
const nodes = [];
|
|
461
|
+
let cursor = fiber;
|
|
462
|
+
let index = 0;
|
|
463
|
+
while (cursor !== undefined) {
|
|
464
|
+
nodes.push(...commitHostFiber(cursor, parent, eventRoot, joinPath(path, String(index)), options));
|
|
465
|
+
cursor = cursor.sibling;
|
|
466
|
+
index += 1;
|
|
467
|
+
}
|
|
468
|
+
return nodes;
|
|
469
|
+
}
|
|
470
|
+
function commitHostFiber(fiber, parent, eventRoot, path, options = {}) {
|
|
471
|
+
if (fiber.tag === "host-text") {
|
|
472
|
+
const text = fiber.stateNode;
|
|
473
|
+
if (!(text instanceof Text)) {
|
|
474
|
+
return [];
|
|
475
|
+
}
|
|
476
|
+
text.data = String(fiber.pendingProps);
|
|
477
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
478
|
+
return [text];
|
|
479
|
+
}
|
|
480
|
+
if (fiber.tag === "host-component") {
|
|
481
|
+
const element = fiber.stateNode;
|
|
482
|
+
if (!(element instanceof HTMLElement)) {
|
|
483
|
+
return [];
|
|
484
|
+
}
|
|
485
|
+
applyProps(element, fiber.pendingProps, path, {
|
|
486
|
+
...options,
|
|
487
|
+
eventRoot,
|
|
488
|
+
preserveHydrationAttributes: fiber.hydrateExisting,
|
|
489
|
+
});
|
|
490
|
+
applyRef(fiber.pendingProps.ref, element);
|
|
491
|
+
const childNodes = commitHostChildren(fiber.child, element, eventRoot, `${path}.c`, options);
|
|
492
|
+
syncChildNodes(element, childNodes);
|
|
493
|
+
applyPostChildFormProps(element, fiber.pendingProps);
|
|
494
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
495
|
+
return [element];
|
|
496
|
+
}
|
|
497
|
+
if (fiber.tag === "fragment") {
|
|
498
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
499
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.f`, options);
|
|
500
|
+
}
|
|
501
|
+
if (fiber.tag === "profiler") {
|
|
502
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
503
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.profiler`, options);
|
|
504
|
+
}
|
|
505
|
+
if (fiber.tag === "strict-mode") {
|
|
506
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
507
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.strict`, options);
|
|
508
|
+
}
|
|
509
|
+
if (fiber.tag === "suspense") {
|
|
510
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
511
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.s`, options);
|
|
512
|
+
}
|
|
513
|
+
if (fiber.tag === "suspense-list") {
|
|
514
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
515
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.sl`, options);
|
|
516
|
+
}
|
|
517
|
+
if (fiber.tag === "context-provider" || fiber.tag === "context-consumer") {
|
|
518
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
519
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.ctx`, options);
|
|
520
|
+
}
|
|
521
|
+
if (fiber.tag === "function-component") {
|
|
522
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
523
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.fc`, options);
|
|
524
|
+
}
|
|
525
|
+
if (fiber.tag === "forward-ref") {
|
|
526
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
527
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.fr`, options);
|
|
528
|
+
}
|
|
529
|
+
if (fiber.tag === "memo") {
|
|
530
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
531
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.memo`, options);
|
|
532
|
+
}
|
|
533
|
+
if (fiber.tag === "lazy") {
|
|
534
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
535
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.lazy`, options);
|
|
536
|
+
}
|
|
537
|
+
if (fiber.tag === "error-boundary") {
|
|
538
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
539
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.eb`, options);
|
|
540
|
+
}
|
|
541
|
+
if (fiber.tag === "class-component") {
|
|
542
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
543
|
+
return commitHostChildren(fiber.child, parent, eventRoot, `${path}.class`, options);
|
|
544
|
+
}
|
|
545
|
+
if (fiber.tag === "portal") {
|
|
546
|
+
const container = fiber.stateNode;
|
|
547
|
+
if (!(container instanceof Element)) {
|
|
548
|
+
return [];
|
|
549
|
+
}
|
|
550
|
+
setLogicalEventParent(container, parent);
|
|
551
|
+
const childNodes = commitHostChildren(fiber.child, container, container, `${path}.portal`, options);
|
|
552
|
+
syncChildNodes(container, childNodes);
|
|
553
|
+
fiber.memoizedProps = fiber.pendingProps;
|
|
554
|
+
return [];
|
|
555
|
+
}
|
|
556
|
+
return [];
|
|
557
|
+
}
|
|
558
|
+
function createSuspenseFiber(current, element, key, runtime, path, options = {}) {
|
|
559
|
+
if (runtime === undefined) {
|
|
560
|
+
return { fiber: undefined, consumed: 0 };
|
|
561
|
+
}
|
|
562
|
+
const boundary = findReactSuspenseBoundary(options.previousNodes ?? []);
|
|
563
|
+
if (boundary?.serverError !== undefined) {
|
|
564
|
+
reportReactSuspenseServerError(options, path, boundary.serverError.message, boundary.serverError.componentStack);
|
|
565
|
+
}
|
|
566
|
+
const { previousNodes: _previousNodes, ...optionsWithoutPreviousNodes } = options;
|
|
567
|
+
const boundaryOptions = boundary === undefined
|
|
568
|
+
? options
|
|
569
|
+
: boundary.serverError === undefined
|
|
570
|
+
? boundary.previousNodes === undefined
|
|
571
|
+
? optionsWithoutPreviousNodes
|
|
572
|
+
: { ...options, previousNodes: boundary.previousNodes }
|
|
573
|
+
: optionsWithoutPreviousNodes;
|
|
574
|
+
const fiber = current?.tag === "suspense" && current.type === element.type
|
|
575
|
+
? createWorkInProgress(current, element.props)
|
|
576
|
+
: createFiber("suspense", element.props, key);
|
|
577
|
+
fiber.type = element.type;
|
|
578
|
+
try {
|
|
579
|
+
suspensePrimaryRenderDepth += 1;
|
|
580
|
+
let childResult;
|
|
581
|
+
try {
|
|
582
|
+
childResult = reconcileHostChild(fiber, current?.tag === "suspense" ? current.child : undefined, element.props.children, runtime, `${path}.s`, boundaryOptions);
|
|
583
|
+
}
|
|
584
|
+
finally {
|
|
585
|
+
suspensePrimaryRenderDepth -= 1;
|
|
586
|
+
}
|
|
587
|
+
fiber.child = childResult.fiber;
|
|
588
|
+
fiber.memoizedState = { didSuspend: false };
|
|
589
|
+
}
|
|
590
|
+
catch (error) {
|
|
591
|
+
if (!isThenable(error)) {
|
|
592
|
+
throw error;
|
|
593
|
+
}
|
|
594
|
+
error.then(() => runtime.rerender(), () => runtime.rerender());
|
|
595
|
+
const fallbackResult = reconcileHostChild(fiber, current?.tag === "suspense" ? current.child : undefined, element.props.fallback, runtime, `${path}.fallback`, boundaryOptions);
|
|
596
|
+
fiber.child = fallbackResult.fiber;
|
|
597
|
+
fiber.memoizedState = { didSuspend: true };
|
|
598
|
+
}
|
|
599
|
+
return {
|
|
600
|
+
fiber,
|
|
601
|
+
consumed: boundary?.consumed ?? options.previousNodes?.length ?? 0,
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
function createStrictModeFiber(current, element, key, runtime, path, options = {}) {
|
|
605
|
+
if (runtime === undefined) {
|
|
606
|
+
return { fiber: undefined, consumed: 0 };
|
|
607
|
+
}
|
|
608
|
+
const fiber = current?.tag === "strict-mode" && current.type === element.type
|
|
609
|
+
? createWorkInProgress(current, element.props)
|
|
610
|
+
: createFiber("strict-mode", element.props, key);
|
|
611
|
+
fiber.type = element.type;
|
|
612
|
+
const snapshot = takeRuntimeSnapshot(runtime);
|
|
613
|
+
try {
|
|
614
|
+
createHostFiber(fiber, undefined, element.props.children, undefined, runtime, `${path}.strict.preview`, options.previousNodes === undefined
|
|
615
|
+
? options
|
|
616
|
+
: { ...options, previousNodes: [] });
|
|
617
|
+
}
|
|
618
|
+
finally {
|
|
619
|
+
restoreRuntimeSnapshot(runtime, snapshot);
|
|
620
|
+
}
|
|
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
|
+
return { fiber, consumed: childResult.consumed };
|
|
624
|
+
}
|
|
625
|
+
function createSuspenseListFiber(current, element, key, runtime, path, options = {}) {
|
|
626
|
+
if (runtime === undefined) {
|
|
627
|
+
return { fiber: undefined, consumed: 0 };
|
|
628
|
+
}
|
|
629
|
+
const fiber = current?.tag === "suspense-list" && current.type === element.type
|
|
630
|
+
? createWorkInProgress(current, element.props)
|
|
631
|
+
: createFiber("suspense-list", element.props, key);
|
|
632
|
+
fiber.type = element.type;
|
|
633
|
+
const children = normalizeChildren(element.props.children);
|
|
634
|
+
const revealOrder = element.props.revealOrder;
|
|
635
|
+
if (revealOrder === "forwards") {
|
|
636
|
+
const childResult = reconcileSuspenseListForwards(fiber, current?.tag === "suspense-list" ? current.child : undefined, children, runtime, path, options);
|
|
637
|
+
fiber.child = childResult.fiber;
|
|
638
|
+
fiber.memoizedState = {
|
|
639
|
+
didSuspend: hasSuspendedChild(fiber.child),
|
|
640
|
+
};
|
|
641
|
+
return { fiber, consumed: childResult.consumed };
|
|
642
|
+
}
|
|
643
|
+
else if (revealOrder === "backwards") {
|
|
644
|
+
const childResult = reconcileSuspenseListBackwards(fiber, current?.tag === "suspense-list" ? current.child : undefined, children, runtime, path, options);
|
|
645
|
+
fiber.child = childResult.fiber;
|
|
646
|
+
fiber.memoizedState = {
|
|
647
|
+
didSuspend: hasSuspendedChild(fiber.child),
|
|
648
|
+
};
|
|
649
|
+
return { fiber, consumed: childResult.consumed };
|
|
650
|
+
}
|
|
651
|
+
else {
|
|
652
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "suspense-list" ? current.child : undefined, children, runtime, `${path}.sl`, options);
|
|
653
|
+
fiber.child = childResult.fiber;
|
|
654
|
+
fiber.memoizedState = {
|
|
655
|
+
didSuspend: hasSuspendedChild(fiber.child),
|
|
656
|
+
};
|
|
657
|
+
return { fiber, consumed: childResult.consumed };
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
function reconcileSuspenseListForwards(parent, currentFirstChild, children, runtime, path, options = {}) {
|
|
661
|
+
let first;
|
|
662
|
+
let previous;
|
|
663
|
+
let consumed = 0;
|
|
664
|
+
const currentByKey = collectExistingKeyedFibers(currentFirstChild);
|
|
665
|
+
let currentUnkeyed = currentFirstChild;
|
|
666
|
+
for (const [index, child] of children.entries()) {
|
|
667
|
+
const key = getNodeKey(child);
|
|
668
|
+
const current = key === undefined ? currentUnkeyed : currentByKey.get(key);
|
|
669
|
+
const childOptions = options.previousNodes === undefined
|
|
670
|
+
? options
|
|
671
|
+
: { ...options, previousNodes: options.previousNodes.slice(consumed) };
|
|
672
|
+
const result = createHostFiber(parent, current, child, key, runtime, `${path}.sl.${getNodePathSegment(child, index)}`, childOptions);
|
|
673
|
+
const fiber = result.fiber;
|
|
674
|
+
if (key === undefined) {
|
|
675
|
+
currentUnkeyed = currentUnkeyed?.sibling;
|
|
676
|
+
}
|
|
677
|
+
consumed += result.consumed;
|
|
678
|
+
if (fiber === undefined) {
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
fiber.return = parent;
|
|
682
|
+
fiber.sibling = undefined;
|
|
683
|
+
if (first === undefined) {
|
|
684
|
+
first = fiber;
|
|
685
|
+
}
|
|
686
|
+
else if (previous !== undefined) {
|
|
687
|
+
previous.sibling = fiber;
|
|
688
|
+
}
|
|
689
|
+
previous = fiber;
|
|
690
|
+
if (isSuspendedSuspenseFiber(fiber)) {
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
return { fiber: first, consumed };
|
|
695
|
+
}
|
|
696
|
+
function reconcileSuspenseListBackwards(parent, currentFirstChild, children, runtime, path, options = {}) {
|
|
697
|
+
const fibers = [];
|
|
698
|
+
const currentByKey = collectExistingKeyedFibers(currentFirstChild);
|
|
699
|
+
let consumed = 0;
|
|
700
|
+
for (let index = children.length - 1; index >= 0; index -= 1) {
|
|
701
|
+
const child = children[index];
|
|
702
|
+
const key = getNodeKey(child);
|
|
703
|
+
const result = createHostFiber(parent, key === undefined ? undefined : currentByKey.get(key), child, key, runtime, `${path}.sl.${getNodePathSegment(child, index)}`, options.previousNodes === undefined
|
|
704
|
+
? options
|
|
705
|
+
: { ...options, previousNodes: options.previousNodes.slice(consumed) });
|
|
706
|
+
const fiber = result.fiber;
|
|
707
|
+
consumed += result.consumed;
|
|
708
|
+
if (fiber === undefined) {
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
fiber.return = parent;
|
|
712
|
+
fiber.sibling = undefined;
|
|
713
|
+
fibers.unshift(fiber);
|
|
714
|
+
if (isSuspendedSuspenseFiber(fiber)) {
|
|
715
|
+
break;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return { fiber: linkFiberSiblings(fibers), consumed };
|
|
719
|
+
}
|
|
720
|
+
function linkFiberSiblings(fibers) {
|
|
721
|
+
let previous;
|
|
722
|
+
for (const fiber of fibers) {
|
|
723
|
+
if (previous !== undefined) {
|
|
724
|
+
previous.sibling = fiber;
|
|
725
|
+
}
|
|
726
|
+
previous = fiber;
|
|
727
|
+
}
|
|
728
|
+
return fibers[0];
|
|
729
|
+
}
|
|
730
|
+
function hasSuspendedChild(fiber) {
|
|
731
|
+
let cursor = fiber;
|
|
732
|
+
while (cursor !== undefined) {
|
|
733
|
+
if (isSuspendedSuspenseFiber(cursor)) {
|
|
734
|
+
return true;
|
|
735
|
+
}
|
|
736
|
+
cursor = cursor.sibling;
|
|
737
|
+
}
|
|
738
|
+
return false;
|
|
739
|
+
}
|
|
740
|
+
function isSuspendedSuspenseFiber(fiber) {
|
|
741
|
+
return (fiber.tag === "suspense" &&
|
|
742
|
+
fiber.memoizedState?.didSuspend === true);
|
|
743
|
+
}
|
|
744
|
+
function findReactSuspenseBoundary(previousNodes) {
|
|
745
|
+
const startIndex = previousNodes.findIndex(isReactSuspenseStartComment);
|
|
746
|
+
if (startIndex < 0) {
|
|
747
|
+
return undefined;
|
|
748
|
+
}
|
|
749
|
+
let depth = 0;
|
|
750
|
+
for (let index = startIndex; index < previousNodes.length; index += 1) {
|
|
751
|
+
const node = previousNodes[index];
|
|
752
|
+
if (isReactSuspenseStartComment(node)) {
|
|
753
|
+
depth += 1;
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
if (isReactSuspenseEndComment(node)) {
|
|
757
|
+
depth -= 1;
|
|
758
|
+
if (depth === 0) {
|
|
759
|
+
const start = previousNodes[startIndex];
|
|
760
|
+
const boundaryNodes = previousNodes.slice(startIndex + 1, index);
|
|
761
|
+
const boundary = {
|
|
762
|
+
consumed: index - startIndex + 1,
|
|
763
|
+
...readReactSuspenseServerError(start, boundaryNodes),
|
|
764
|
+
};
|
|
765
|
+
if (!isReactSuspenseErrorStartComment(start)) {
|
|
766
|
+
boundary.previousNodes = isReactSuspensePendingStartComment(start)
|
|
767
|
+
? removeReactSuspensePendingTemplate(boundaryNodes)
|
|
768
|
+
: boundaryNodes;
|
|
769
|
+
}
|
|
770
|
+
return boundary;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
return undefined;
|
|
775
|
+
}
|
|
776
|
+
function isReactSuspenseStartComment(node) {
|
|
777
|
+
return node instanceof Comment && reactSuspenseStartComments.has(node.data);
|
|
778
|
+
}
|
|
779
|
+
function isReactSuspensePendingStartComment(node) {
|
|
780
|
+
return node.data === "$?" || node.data === "$!";
|
|
781
|
+
}
|
|
782
|
+
function isReactSuspenseErrorStartComment(node) {
|
|
783
|
+
return node.data === "$!";
|
|
784
|
+
}
|
|
785
|
+
function isReactSuspenseEndComment(node) {
|
|
786
|
+
return node instanceof Comment && node.data === "/$";
|
|
787
|
+
}
|
|
788
|
+
function removeReactSuspensePendingTemplate(nodes) {
|
|
789
|
+
const [firstNode, ...remainingNodes] = nodes;
|
|
790
|
+
return firstNode instanceof HTMLTemplateElement
|
|
791
|
+
? remainingNodes
|
|
792
|
+
: [...nodes];
|
|
793
|
+
}
|
|
794
|
+
const reactSuspenseStartComments = new Set(["$", "$?", "$!"]);
|
|
795
|
+
function readReactSuspenseServerError(start, boundaryNodes) {
|
|
796
|
+
if (start.data !== "$!") {
|
|
797
|
+
return {};
|
|
798
|
+
}
|
|
799
|
+
const template = boundaryNodes[0];
|
|
800
|
+
const message = template instanceof HTMLTemplateElement
|
|
801
|
+
? template.getAttribute("data-msg")
|
|
802
|
+
: null;
|
|
803
|
+
const componentStack = template instanceof HTMLTemplateElement
|
|
804
|
+
? template.getAttribute("data-stck")
|
|
805
|
+
: null;
|
|
806
|
+
return {
|
|
807
|
+
serverError: {
|
|
808
|
+
message: message ?? "React Suspense server rendering error.",
|
|
809
|
+
...(componentStack === null ? {} : { componentStack }),
|
|
810
|
+
},
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
function createPortalFiber(parent, current, portal, key, runtime, path, options = {}) {
|
|
814
|
+
if (runtime === undefined) {
|
|
815
|
+
return { fiber: undefined, consumed: 0 };
|
|
816
|
+
}
|
|
817
|
+
runtime.portalContainers.add(portal.container);
|
|
818
|
+
const fiber = current?.tag === "portal" && current.stateNode === portal.container
|
|
819
|
+
? createWorkInProgress(current, portal.children)
|
|
820
|
+
: createFiber("portal", portal.children, key);
|
|
821
|
+
fiber.stateNode = portal.container;
|
|
822
|
+
const childResult = reconcileHostChild(fiber, current?.tag === "portal" ? current.child : undefined, portal.children, runtime, `${path}.portal`, options);
|
|
823
|
+
fiber.child = childResult.fiber;
|
|
824
|
+
fiber.return = parent;
|
|
825
|
+
return { fiber, consumed: childResult.consumed };
|
|
826
|
+
}
|
|
827
|
+
function normalizeChildren(node) {
|
|
828
|
+
if (node === null || node === undefined || typeof node === "boolean") {
|
|
829
|
+
return [];
|
|
830
|
+
}
|
|
831
|
+
return Array.isArray(node) ? node : [node];
|
|
832
|
+
}
|
|
833
|
+
function collectExistingKeyedFibers(firstChild) {
|
|
834
|
+
const keyed = new Map();
|
|
835
|
+
let cursor = firstChild;
|
|
836
|
+
while (cursor !== undefined) {
|
|
837
|
+
if (cursor.key !== undefined) {
|
|
838
|
+
keyed.set(cursor.key, cursor);
|
|
839
|
+
}
|
|
840
|
+
cursor = cursor.sibling;
|
|
841
|
+
}
|
|
842
|
+
return keyed;
|
|
843
|
+
}
|
|
844
|
+
function getNodeKey(node) {
|
|
845
|
+
return isReactCompatElement(node) && node.key !== null ? node.key : undefined;
|
|
846
|
+
}
|
|
847
|
+
function getNodePathSegment(node, index) {
|
|
848
|
+
const key = getNodeKey(node);
|
|
849
|
+
return key === undefined ? String(index) : `k:${key}`;
|
|
850
|
+
}
|
|
851
|
+
function getComponentName(component) {
|
|
852
|
+
return component.name === "" ? "Anonymous" : component.name;
|
|
853
|
+
}
|
|
854
|
+
function joinPath(path, segment) {
|
|
855
|
+
return path === "" ? segment : `${path}.${segment}`;
|
|
856
|
+
}
|
|
857
|
+
function isForwardRefType(value) {
|
|
858
|
+
return (typeof value === "object" &&
|
|
859
|
+
value !== null &&
|
|
860
|
+
value.$$typeof === FORWARD_REF_TYPE);
|
|
861
|
+
}
|
|
862
|
+
function isMemoType(value) {
|
|
863
|
+
return (typeof value === "object" &&
|
|
864
|
+
value !== null &&
|
|
865
|
+
value.$$typeof === MEMO_TYPE);
|
|
866
|
+
}
|
|
867
|
+
function isLazyType(value) {
|
|
868
|
+
return (typeof value === "object" &&
|
|
869
|
+
value !== null &&
|
|
870
|
+
value.$$typeof === LAZY_TYPE);
|
|
871
|
+
}
|
|
872
|
+
function collectInstanceKeys(runtime, prefix) {
|
|
873
|
+
return Array.from(runtime.instances.keys()).filter((key) => key === prefix || key.startsWith(`${prefix}.`));
|
|
874
|
+
}
|
|
875
|
+
function markActiveInstanceKeys(runtime, keys) {
|
|
876
|
+
for (const key of keys) {
|
|
877
|
+
runtime.activeInstanceKeys?.add(key);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
function hasDirtyInstance(runtime, keys) {
|
|
881
|
+
return keys.some((key) => runtime.instances.get(key)?.dirty === true);
|
|
882
|
+
}
|
|
883
|
+
function applyRef(ref, node) {
|
|
884
|
+
if (typeof ref === "function") {
|
|
885
|
+
ref(node);
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
if (typeof ref === "object" && ref !== null && "current" in ref) {
|
|
889
|
+
ref.current = node;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
//# sourceMappingURL=fiber-host.js.map
|