@tanstack/redact 0.0.20 → 0.1.0
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/dist/core/attributes.js +2 -1
- package/dist/core/attributes.js.map +2 -2
- package/dist/core/browser.d.ts +9 -0
- package/dist/core/browser.js +35 -0
- package/dist/core/browser.js.map +7 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +3 -3
- package/dist/core/internal.d.ts +31 -8
- package/dist/core/internal.js +3 -1
- package/dist/core/internal.js.map +2 -2
- package/dist/core/resource-hints.d.ts +7 -0
- package/dist/core/resource-hints.js +19 -0
- package/dist/core/resource-hints.js.map +7 -0
- package/dist/core/types.js +1 -1
- package/dist/dom/_all.d.ts +11 -16
- package/dist/dom/_all.js +9 -20
- package/dist/dom/_all.js.map +2 -2
- package/dist/dom/client.d.ts +4 -4
- package/dist/dom/client.js +4 -4
- package/dist/dom/commit.d.ts +23 -0
- package/dist/dom/commit.js +191 -0
- package/dist/dom/commit.js.map +7 -0
- package/dist/dom/dispatcher.d.ts +4 -22
- package/dist/dom/dispatcher.js +184 -126
- package/dist/dom/dispatcher.js.map +3 -3
- package/dist/dom/dom.d.ts +2 -0
- package/dist/dom/dom.js +72 -52
- package/dist/dom/dom.js.map +2 -2
- package/dist/dom/error-info.d.ts +2 -0
- package/dist/dom/error-info.js +16 -0
- package/dist/dom/error-info.js.map +7 -0
- package/dist/dom/event-replay.js +1 -1
- package/dist/dom/features/activity/full.d.ts +1 -0
- package/dist/dom/features/activity/full.js +162 -0
- package/dist/dom/features/activity/full.js.map +7 -0
- package/dist/dom/features/activity/index.d.ts +1 -0
- package/dist/dom/features/activity/index.js +3 -0
- package/dist/dom/features/activity/index.js.map +7 -0
- package/dist/dom/features/activity/stub.d.ts +1 -0
- package/dist/dom/features/activity/stub.js +12 -0
- package/dist/dom/features/activity/stub.js.map +7 -0
- package/dist/dom/features/class/full.js +87 -21
- package/dist/dom/features/class/full.js.map +2 -2
- package/dist/dom/features/class/index.d.ts +1 -1
- package/dist/dom/features/class/index.js +2 -2
- package/dist/dom/features/class/stub.js +3 -3
- package/dist/dom/features/context/full.d.ts +4 -1
- package/dist/dom/features/context/full.js +69 -9
- package/dist/dom/features/context/full.js.map +2 -2
- package/dist/dom/features/context/index.d.ts +1 -1
- package/dist/dom/features/context/index.js +2 -2
- package/dist/dom/features/context/stub.d.ts +4 -1
- package/dist/dom/features/context/stub.js +15 -4
- package/dist/dom/features/context/stub.js.map +2 -2
- package/dist/dom/features/forward-ref/full.js +12 -21
- package/dist/dom/features/forward-ref/full.js.map +2 -2
- package/dist/dom/features/forward-ref/index.d.ts +1 -1
- package/dist/dom/features/forward-ref/index.js +2 -2
- package/dist/dom/features/forward-ref/stub.js +4 -4
- package/dist/dom/features/fragment-refs/index.d.ts +1 -0
- package/dist/dom/features/fragment-refs/index.js +8 -0
- package/dist/dom/features/fragment-refs/index.js.map +7 -0
- package/dist/dom/features/fragment-refs/stub.d.ts +3 -0
- package/dist/dom/features/fragment-refs/stub.js +14 -0
- package/dist/dom/features/fragment-refs/stub.js.map +7 -0
- package/dist/dom/features/hydration/full.d.ts +11 -6
- package/dist/dom/features/hydration/full.js +76 -76
- package/dist/dom/features/hydration/full.js.map +2 -2
- package/dist/dom/features/hydration/index.d.ts +1 -1
- package/dist/dom/features/hydration/index.js +2 -2
- package/dist/dom/features/hydration/stub.d.ts +7 -2
- package/dist/dom/features/hydration/stub.js +1 -1
- package/dist/dom/features/hydration/stub.js.map +1 -1
- package/dist/dom/features/index.d.ts +8 -7
- package/dist/dom/features/index.js +9 -8
- package/dist/dom/features/index.js.map +2 -2
- package/dist/dom/features/lazy/full.js +4 -4
- package/dist/dom/features/lazy/index.d.ts +1 -1
- package/dist/dom/features/lazy/index.js +2 -2
- package/dist/dom/features/lazy/stub.js +4 -4
- package/dist/dom/features/memo/full.js +8 -6
- package/dist/dom/features/memo/full.js.map +2 -2
- package/dist/dom/features/memo/index.d.ts +1 -1
- package/dist/dom/features/memo/index.js +2 -2
- package/dist/dom/features/memo/stub.js +4 -4
- package/dist/dom/features/portal/full.js +4 -4
- package/dist/dom/features/portal/index.d.ts +1 -1
- package/dist/dom/features/portal/index.js +2 -2
- package/dist/dom/features/portal/stub.js +4 -4
- package/dist/dom/features/suspense/full.js +192 -47
- package/dist/dom/features/suspense/full.js.map +2 -2
- package/dist/dom/features/suspense/index.d.ts +1 -1
- package/dist/dom/features/suspense/index.js +2 -2
- package/dist/dom/features/suspense/stub.js +4 -4
- package/dist/dom/features/view-transition/full.d.ts +6 -0
- package/dist/dom/features/view-transition/full.js +280 -0
- package/dist/dom/features/view-transition/full.js.map +7 -0
- package/dist/dom/features/view-transition/index.d.ts +1 -0
- package/dist/dom/features/view-transition/index.js +3 -0
- package/dist/dom/features/view-transition/index.js.map +7 -0
- package/dist/dom/features/view-transition/resources.d.ts +11 -0
- package/dist/dom/features/view-transition/resources.js +108 -0
- package/dist/dom/features/view-transition/resources.js.map +7 -0
- package/dist/dom/features/view-transition/stub.d.ts +6 -0
- package/dist/dom/features/view-transition/stub.js +22 -0
- package/dist/dom/features/view-transition/stub.js.map +7 -0
- package/dist/dom/features/view-transition/visual.d.ts +14 -0
- package/dist/dom/features/view-transition/visual.js +356 -0
- package/dist/dom/features/view-transition/visual.js.map +7 -0
- package/dist/dom/fragment-instance.d.ts +40 -0
- package/dist/dom/fragment-instance.js +324 -0
- package/dist/dom/fragment-instance.js.map +7 -0
- package/dist/dom/index.d.ts +11 -11
- package/dist/dom/index.js +11 -18
- package/dist/dom/index.js.map +3 -3
- package/dist/dom/portal.d.ts +2 -2
- package/dist/dom/portal.js +2 -2
- package/dist/dom/portal.js.map +1 -1
- package/dist/dom/reconcile.d.ts +32 -3
- package/dist/dom/reconcile.js +686 -222
- package/dist/dom/reconcile.js.map +2 -2
- package/dist/dom/resource-hints.d.ts +6 -0
- package/dist/dom/resource-hints.js +115 -0
- package/dist/dom/resource-hints.js.map +7 -0
- package/dist/dom/resource-store.d.ts +13 -0
- package/dist/dom/resource-store.js +43 -0
- package/dist/dom/resource-store.js.map +7 -0
- package/dist/dom/resources.d.ts +1 -0
- package/dist/dom/resources.js +44 -0
- package/dist/dom/resources.js.map +7 -0
- package/dist/dom/retained-effects.d.ts +6 -0
- package/dist/dom/retained-effects.js +49 -0
- package/dist/dom/retained-effects.js.map +7 -0
- package/dist/dom/root-internal.d.ts +4 -4
- package/dist/dom/root-internal.js +2 -2
- package/dist/dom/root-internal.js.map +2 -2
- package/dist/dom/root.d.ts +5 -5
- package/dist/dom/root.js +11 -11
- package/dist/dom/root.js.map +2 -2
- package/dist/dom/test-utils.js +1 -1
- package/dist/react/activity.d.ts +7 -0
- package/dist/react/activity.js +8 -0
- package/dist/react/activity.js.map +7 -0
- package/dist/react/children.d.ts +1 -1
- package/dist/react/children.js +3 -3
- package/dist/react/children.js.map +1 -1
- package/dist/react/class.d.ts +1 -1
- package/dist/react/class.js +3 -3
- package/dist/react/class.js.map +1 -1
- package/dist/react/compiler-runtime.js +2 -2
- package/dist/react/context.d.ts +1 -1
- package/dist/react/context.js +3 -3
- package/dist/react/context.js.map +1 -1
- package/dist/react/element.d.ts +6 -3
- package/dist/react/element.js +2 -2
- package/dist/react/element.js.map +2 -2
- package/dist/react/hooks.d.ts +26 -7
- package/dist/react/hooks.js +13 -3
- package/dist/react/hooks.js.map +2 -2
- package/dist/react/index.d.ts +39 -24
- package/dist/react/index.js +39 -19
- package/dist/react/index.js.map +3 -3
- package/dist/react/jsx-runtime.d.ts +2 -2
- package/dist/react/jsx-runtime.js +3 -3
- package/dist/react/memo.d.ts +1 -1
- package/dist/react/memo.js +1 -1
- package/dist/react/portal.js +1 -1
- package/dist/react/shared-internals.d.ts +15 -5
- package/dist/react/shared-internals.js +2 -3
- package/dist/react/shared-internals.js.map +2 -2
- package/dist/react/suspense.js +1 -1
- package/dist/react/view-transition.d.ts +32 -0
- package/dist/react/view-transition.js +13 -0
- package/dist/react/view-transition.js.map +7 -0
- package/dist/scheduler/index.js +1 -1
- package/dist/server/bootstrap-script.d.ts +1 -23
- package/dist/server/bootstrap-script.js +7 -6
- package/dist/server/bootstrap-script.js.map +2 -2
- package/dist/server/dispatcher.d.ts +28 -6
- package/dist/server/dispatcher.js +33 -15
- package/dist/server/dispatcher.js.map +2 -2
- package/dist/server/escape.js +16 -15
- package/dist/server/escape.js.map +2 -2
- package/dist/server/index.d.ts +6 -6
- package/dist/server/index.js +7 -7
- package/dist/server/renderToString.d.ts +1 -1
- package/dist/server/renderToString.js +12 -8
- package/dist/server/renderToString.js.map +2 -2
- package/dist/server/resource-hints.d.ts +22 -0
- package/dist/server/resource-hints.js +148 -0
- package/dist/server/resource-hints.js.map +7 -0
- package/dist/server/stream.d.ts +15 -2
- package/dist/server/stream.js +155 -63
- package/dist/server/stream.js.map +2 -2
- package/dist/server/walk.d.ts +15 -2
- package/dist/server/walk.js +143 -96
- package/dist/server/walk.js.map +2 -2
- package/dist/vite/index.d.ts +6 -0
- package/dist/vite/index.js +22 -6
- package/dist/vite/index.js.map +2 -2
- package/package.json +1 -1
- package/src/core/attributes.ts +1 -0
- package/src/core/browser.ts +33 -0
- package/src/core/internal.ts +24 -6
- package/src/core/resource-hints.ts +36 -0
- package/src/dom/_all.ts +1 -7
- package/src/dom/commit.ts +186 -0
- package/src/dom/dispatcher.ts +190 -134
- package/src/dom/dom.ts +70 -54
- package/src/dom/error-info.ts +15 -0
- package/src/dom/features/activity/full.ts +166 -0
- package/src/dom/features/activity/index.ts +1 -0
- package/src/dom/features/activity/stub.ts +14 -0
- package/src/dom/features/class/full.ts +72 -21
- package/src/dom/features/context/full.ts +66 -4
- package/src/dom/features/context/stub.ts +6 -0
- package/src/dom/features/forward-ref/full.ts +9 -19
- package/src/dom/features/fragment-refs/index.ts +1 -0
- package/src/dom/features/fragment-refs/stub.ts +3 -0
- package/src/dom/features/hydration/full.ts +84 -82
- package/src/dom/features/hydration/stub.ts +1 -1
- package/src/dom/features/index.ts +1 -0
- package/src/dom/features/memo/full.ts +4 -3
- package/src/dom/features/suspense/full.ts +187 -50
- package/src/dom/features/view-transition/full.ts +288 -0
- package/src/dom/features/view-transition/index.ts +1 -0
- package/src/dom/features/view-transition/resources.ts +107 -0
- package/src/dom/features/view-transition/stub.ts +7 -0
- package/src/dom/features/view-transition/visual.ts +406 -0
- package/src/dom/fragment-instance.ts +337 -0
- package/src/dom/index.ts +6 -7
- package/src/dom/portal.ts +1 -1
- package/src/dom/reconcile.ts +691 -244
- package/src/dom/resource-hints.ts +115 -0
- package/src/dom/resource-store.ts +52 -0
- package/src/dom/resources.ts +39 -0
- package/src/dom/retained-effects.ts +38 -0
- package/src/dom/root-internal.ts +4 -4
- package/src/dom/root.ts +12 -14
- package/src/react/activity.ts +10 -0
- package/src/react/element.ts +6 -2
- package/src/react/hooks.ts +12 -3
- package/src/react/index.ts +18 -0
- package/src/react/shared-internals.ts +3 -3
- package/src/react/view-transition.ts +41 -0
- package/src/server/bootstrap-script.ts +36 -5
- package/src/server/dispatcher.ts +35 -13
- package/src/server/escape.ts +15 -12
- package/src/server/renderToString.ts +7 -5
- package/src/server/resource-hints.ts +165 -0
- package/src/server/stream.ts +154 -62
- package/src/server/walk.ts +72 -11
- package/src/vite/index.ts +30 -13
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FiberTag, createFiber, type Fiber } from '../../../core'
|
|
2
|
-
import { REACT_SUSPENSE_TYPE } from '../../../react'
|
|
2
|
+
import { REACT_SUSPENSE_TYPE, ReactSharedInternals, startTransition } from '../../../react'
|
|
3
3
|
import {
|
|
4
4
|
registerRenderer,
|
|
5
5
|
registerTypeMatcher,
|
|
@@ -15,7 +15,19 @@ import {
|
|
|
15
15
|
getCurrentRoot,
|
|
16
16
|
withCurrentRoot,
|
|
17
17
|
discardPendingWork,
|
|
18
|
+
findSuspenseBoundary,
|
|
19
|
+
RenderSuspenseCapture,
|
|
20
|
+
activityIsDisconnected,
|
|
21
|
+
isActivityHidden,
|
|
22
|
+
attachRef,
|
|
23
|
+
detachRef,
|
|
24
|
+
enqueueEffect,
|
|
25
|
+
flushFiberCommits,
|
|
26
|
+
scheduleLifecycle,
|
|
27
|
+
handleCommitError,
|
|
18
28
|
} from '../../reconcile'
|
|
29
|
+
import { cleanupEffect } from '../../dispatcher'
|
|
30
|
+
import { retainedEffects, inSuspensePrimary, setLayoutDisconnected, walkRetained } from '../../retained-effects'
|
|
19
31
|
import {
|
|
20
32
|
HydrationCursor,
|
|
21
33
|
setHydrationCursor,
|
|
@@ -24,15 +36,25 @@ import {
|
|
|
24
36
|
tryConsumeBoundary,
|
|
25
37
|
isHydrationBailout,
|
|
26
38
|
} from '../hydration'
|
|
39
|
+
import { hasContextChanged, renderContextConsumers } from '../context'
|
|
40
|
+
import { checkpointCommit, rewindCommit, queueMutation, onCommitFailure } from '../../commit'
|
|
27
41
|
|
|
28
42
|
let suspendHandler: ((t: Promise<any>) => void) | null = null
|
|
29
43
|
|
|
44
|
+
function scheduleRetry(fiber: Fiber): void {
|
|
45
|
+
const previous = ReactSharedInternals.T
|
|
46
|
+
ReactSharedInternals.T = null
|
|
47
|
+
try { startTransition(() => scheduleUpdate(fiber)) } finally { ReactSharedInternals.T = previous }
|
|
48
|
+
}
|
|
49
|
+
|
|
30
50
|
function realHandleSuspended(fiber: Fiber, thenable: Promise<any>): void {
|
|
31
51
|
if (suspendHandler) return suspendHandler(thenable)
|
|
52
|
+
const boundary = findSuspenseBoundary(fiber)
|
|
53
|
+
if (boundary) throw new RenderSuspenseCapture(boundary)
|
|
32
54
|
// Fallback: schedule re-render when promise settles
|
|
33
55
|
thenable.then(
|
|
34
|
-
() =>
|
|
35
|
-
() =>
|
|
56
|
+
() => scheduleRetry(fiber),
|
|
57
|
+
() => scheduleRetry(fiber),
|
|
36
58
|
)
|
|
37
59
|
}
|
|
38
60
|
|
|
@@ -46,14 +68,15 @@ function realHandleSuspended(fiber: Fiber, thenable: Promise<any>): void {
|
|
|
46
68
|
// their original `display` so we can restore it) and the fallback as a
|
|
47
69
|
// detached Fragment fiber in `state.f` (deliberately kept OUT of
|
|
48
70
|
// `fiber.child` so reconciles against `props.children` don't trip on it).
|
|
49
|
-
// First-mount suspensions
|
|
50
|
-
//
|
|
71
|
+
// First-mount suspensions discard the failed primary but retain a separate
|
|
72
|
+
// fallback fiber so unsuccessful retries preserve its state and DOM.
|
|
51
73
|
interface SuspenseState {
|
|
52
74
|
p?: Promise<any> | null
|
|
53
75
|
b?: Comment
|
|
54
76
|
e?: Comment
|
|
55
77
|
r?: any
|
|
56
78
|
a?: boolean
|
|
79
|
+
u?: boolean
|
|
57
80
|
// Re-suspend preservation:
|
|
58
81
|
d?: Array<[HTMLElement, string]> | null
|
|
59
82
|
f?: Fiber | null
|
|
@@ -61,11 +84,12 @@ interface SuspenseState {
|
|
|
61
84
|
|
|
62
85
|
function renderSuspense(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
63
86
|
const props = fiber.pp ?? {}
|
|
64
|
-
|
|
87
|
+
let state = (fiber.ms ??= {}) as SuspenseState
|
|
65
88
|
|
|
66
89
|
// Streaming hydration: if the next DOM node is a server-emitted boundary
|
|
67
90
|
// marker, route through the boundary-aware hydration path.
|
|
68
91
|
const root = getCurrentRoot()
|
|
92
|
+
if (root) root.sp = true
|
|
69
93
|
if (root?.h && !state.b) {
|
|
70
94
|
const boundary = tryConsumeBoundary(fiber.parent!)
|
|
71
95
|
if (boundary) {
|
|
@@ -85,14 +109,11 @@ function renderSuspense(fiber: Fiber, domParent: Node, anchor: Node | null): voi
|
|
|
85
109
|
return
|
|
86
110
|
}
|
|
87
111
|
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
// promise to fire scheduleUpdate.
|
|
92
|
-
if (state.p) {
|
|
112
|
+
// New primary children or context can unblock a boundary before its old
|
|
113
|
+
// promise settles. A fallback-only update can keep the pending primary.
|
|
114
|
+
if (state.p && !state.u && props.children === fiber.mp?.children && !hasContextChanged(fiber, false)) {
|
|
93
115
|
if (state.f) {
|
|
94
|
-
state.f
|
|
95
|
-
renderFiber(state.f, domParent, anchor)
|
|
116
|
+
renderFallback(state.f, props.fallback, domParent, anchor)
|
|
96
117
|
} else {
|
|
97
118
|
// Initial-mount suspended path: no committed primary to preserve.
|
|
98
119
|
reconcileChildren(fiber, childrenToArray(props.fallback), domParent, anchor)
|
|
@@ -105,8 +126,11 @@ function renderSuspense(fiber: Fiber, domParent: Node, anchor: Node | null): voi
|
|
|
105
126
|
// attempting the new render. If the new attempt suspends and we did have a
|
|
106
127
|
// committed primary, we keep it (hidden) rather than destroying it.
|
|
107
128
|
const hadCommittedPrimary = fiber.mp && fiber.child
|
|
129
|
+
state.u = false
|
|
130
|
+
const checkpoint = checkpointCommit(fiber)
|
|
108
131
|
|
|
109
132
|
const prevHandler = suspendHandler
|
|
133
|
+
fiber.cx?.clear()
|
|
110
134
|
let pendingThenable: any
|
|
111
135
|
suspendHandler = (thenable) => {
|
|
112
136
|
pendingThenable = thenable
|
|
@@ -118,63 +142,142 @@ function renderSuspense(fiber: Fiber, domParent: Node, anchor: Node | null): voi
|
|
|
118
142
|
}
|
|
119
143
|
|
|
120
144
|
if (pendingThenable) {
|
|
145
|
+
rewindCommit(checkpoint)
|
|
146
|
+
state = (fiber.ms ??= {}) as SuspenseState
|
|
147
|
+
const previousThenable = state.p
|
|
121
148
|
state.p = pendingThenable
|
|
122
149
|
const onSettle = () => {
|
|
123
|
-
|
|
124
|
-
|
|
150
|
+
const current = fiber.ms as SuspenseState | null
|
|
151
|
+
if (!current || current.p !== pendingThenable) return
|
|
152
|
+
current.p = null
|
|
153
|
+
scheduleRetry(fiber)
|
|
125
154
|
}
|
|
126
|
-
pendingThenable.then(onSettle, onSettle)
|
|
155
|
+
if (previousThenable !== pendingThenable) pendingThenable.then(onSettle, onSettle)
|
|
127
156
|
|
|
128
|
-
|
|
157
|
+
// Rewind restored the committed tree, including its existing hidden state.
|
|
158
|
+
// Only the first hide needs update-target, lifecycle and DOM work.
|
|
159
|
+
if (hadCommittedPrimary && !state.d) {
|
|
129
160
|
// Hide the primary subtree's root host doms so the fallback is the only
|
|
130
161
|
// thing visible, but the underlying nodes (and their scroll/state/focus)
|
|
131
162
|
// survive. Save original `display` for the resume path.
|
|
132
163
|
const hidden: Array<[HTMLElement, string]> = []
|
|
133
164
|
let c: Fiber | null = hadCommittedPrimary
|
|
165
|
+
while (c) {
|
|
166
|
+
setUpdateBoundary(c, fiber)
|
|
167
|
+
walkRetained(c, disconnectLayout)
|
|
168
|
+
c = c.sibling
|
|
169
|
+
}
|
|
170
|
+
c = hadCommittedPrimary
|
|
134
171
|
while (c) {
|
|
135
172
|
hideRootHostDoms(c, hidden)
|
|
136
173
|
c = c.sibling
|
|
137
174
|
}
|
|
138
175
|
state.d = hidden
|
|
139
176
|
|
|
140
|
-
|
|
141
|
-
// so reconciles of primary don't see it as a stale match candidate.
|
|
142
|
-
if (!state.f) {
|
|
143
|
-
state.f = createFiber(FiberTag.Fragment, null, null)
|
|
144
|
-
state.f.parent = fiber
|
|
145
|
-
}
|
|
146
|
-
state.f.pp = { children: props.fallback }
|
|
147
|
-
renderFiber(state.f, domParent, anchor)
|
|
148
|
-
} else {
|
|
177
|
+
} else if (!hadCommittedPrimary) {
|
|
149
178
|
// First-mount suspension — nothing to preserve.
|
|
150
179
|
unmountAllChildren(fiber, domParent)
|
|
151
|
-
reconcileChildren(fiber, childrenToArray(props.fallback), domParent, anchor)
|
|
152
180
|
}
|
|
181
|
+
// Keep fallback identity across unsuccessful retries of an initial mount.
|
|
182
|
+
if (!state.f) {
|
|
183
|
+
state.f = createFiber(FiberTag.Fragment, null, null)
|
|
184
|
+
state.f.parent = fiber
|
|
185
|
+
}
|
|
186
|
+
renderFallback(state.f, props.fallback, domParent, anchor)
|
|
153
187
|
} else {
|
|
188
|
+
state.p = null
|
|
189
|
+
fiber.cx?.clear()
|
|
190
|
+
const wasHidden = !!state.d
|
|
154
191
|
// Render succeeded. Clean up any preserved-suspend state from a prior
|
|
155
192
|
// suspension cycle: unhide primary, unmount the orphan fallback fiber.
|
|
156
193
|
if (state.d) {
|
|
157
|
-
for (
|
|
158
|
-
|
|
159
|
-
|
|
194
|
+
for (let child = fiber.child; child; child = child.sibling) setUpdateBoundary(child, fiber.su)
|
|
195
|
+
const hidden = state.d
|
|
196
|
+
queueMutation(() => {
|
|
197
|
+
for (const [el, origDisplay] of hidden) el.style.display = origDisplay
|
|
198
|
+
})
|
|
160
199
|
state.d = null
|
|
161
200
|
}
|
|
162
201
|
if (state.f) {
|
|
163
202
|
unmountFiber(state.f, domParent)
|
|
164
203
|
state.f = null
|
|
165
204
|
}
|
|
205
|
+
if (wasHidden) for (let child = fiber.child; child; child = child.sibling) walkRetained(child, reconnectLayout, true)
|
|
166
206
|
}
|
|
167
207
|
fiber.mp = props
|
|
168
208
|
}
|
|
169
209
|
|
|
210
|
+
function renderFallback(fiber: Fiber, children: any, domParent: Node, anchor: Node | null): void {
|
|
211
|
+
// Local updates remain independently queued, unless an outer hidden primary
|
|
212
|
+
// owns them. Context must still cross an otherwise unchanged fallback.
|
|
213
|
+
if (fiber.mp && fiber.mp.children === children && !fiber.su) renderContextConsumers(fiber)
|
|
214
|
+
else {
|
|
215
|
+
fiber.pp = { children }
|
|
216
|
+
renderFiber(fiber, domParent, anchor)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function disconnectLayout(fiber: Fiber): void {
|
|
221
|
+
if (setLayoutDisconnected(fiber, true) || activityIsDisconnected(fiber)) return
|
|
222
|
+
queueMutation(() => {
|
|
223
|
+
for (const [hook, effect] of retainedEffects.get(fiber) ?? []) {
|
|
224
|
+
if (effect.t === 1 && !effect.s) cleanupEffect(hook, fiber)
|
|
225
|
+
}
|
|
226
|
+
const cleanup = fiber.rc
|
|
227
|
+
fiber.rc = null
|
|
228
|
+
if (cleanup) {
|
|
229
|
+
const index = fiber.cu?.indexOf(cleanup) ?? -1
|
|
230
|
+
if (index >= 0) fiber.cu!.splice(index, 1)
|
|
231
|
+
try { cleanup() } catch (error) { handleCommitError(fiber, error) }
|
|
232
|
+
}
|
|
233
|
+
detachRef(fiber.cr ?? fiber.ref, fiber)
|
|
234
|
+
fiber.cr = null
|
|
235
|
+
const instance = fiber.sn?._fiber === fiber ? fiber.sn : null
|
|
236
|
+
if (instance?.componentWillUnmount) {
|
|
237
|
+
const props = instance.props, state = instance.state, committed = fiber.ms?.c
|
|
238
|
+
if (committed) { instance.props = committed.props; instance.state = committed.state }
|
|
239
|
+
try { instance.componentWillUnmount() } catch (error) { handleCommitError(fiber, error) }
|
|
240
|
+
finally { instance.props = props; instance.state = state }
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function reconnectLayout(fiber: Fiber): void {
|
|
246
|
+
if (!fiber.ld || isActivityHidden(fiber) || activityIsDisconnected(fiber)) return
|
|
247
|
+
if (inSuspensePrimary(fiber)) return
|
|
248
|
+
setLayoutDisconnected(fiber, false)
|
|
249
|
+
const instance = fiber.sn?._fiber === fiber ? fiber.sn : null
|
|
250
|
+
if (fiber.tag === FiberTag.Host || fiber.tag === FiberTag.Resource) attachRef(fiber, fiber.dom)
|
|
251
|
+
else if (instance || fiber.tag === FiberTag.Fragment) attachRef(fiber, fiber.sn)
|
|
252
|
+
for (const effect of retainedEffects.get(fiber)?.values() ?? []) {
|
|
253
|
+
if (effect.t === 1 && !effect.s) enqueueEffect(fiber, effect)
|
|
254
|
+
}
|
|
255
|
+
if (instance?.componentDidMount) scheduleLifecycle(fiber, () => instance.componentDidMount())
|
|
256
|
+
flushFiberCommits(fiber)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function setUpdateBoundary(fiber: Fiber, boundary: Fiber | null | undefined): void {
|
|
260
|
+
fiber.su = boundary ?? null
|
|
261
|
+
const primary = fiber.tag === FiberTag.Suspense && fiber.ms?.p ? fiber : boundary
|
|
262
|
+
for (let child = fiber.child; child; child = child.sibling) setUpdateBoundary(child, primary)
|
|
263
|
+
if (fiber.tag === FiberTag.Suspense && fiber.ms?.f) setUpdateBoundary(fiber.ms.f, boundary)
|
|
264
|
+
}
|
|
265
|
+
|
|
170
266
|
// Walk a fiber subtree collecting host/text DOM nodes that sit at the root
|
|
171
267
|
// of the subtree (do not descend through their children — display:none on
|
|
172
268
|
// the root hides the whole element). Used by the hide-on-suspend path.
|
|
173
269
|
function hideRootHostDoms(fiber: Fiber, out: Array<[HTMLElement, string]>): void {
|
|
174
270
|
if (fiber.tag === FiberTag.Host) {
|
|
175
271
|
const el = fiber.dom as HTMLElement
|
|
176
|
-
out.
|
|
177
|
-
el.style.display
|
|
272
|
+
const existing = out.find(([node]) => node === el)
|
|
273
|
+
const entry: [HTMLElement, string] = existing ?? [el, el.style.display]
|
|
274
|
+
if (!existing) out.push(entry)
|
|
275
|
+
const display = fiber.pp?.style?.display
|
|
276
|
+
queueMutation(() => {
|
|
277
|
+
// Earlier Activity or host updates in this commit can change display.
|
|
278
|
+
if (!existing || el.style.display !== 'none' || display === 'none') entry[1] = el.style.display
|
|
279
|
+
el.style.display = 'none'
|
|
280
|
+
})
|
|
178
281
|
return
|
|
179
282
|
}
|
|
180
283
|
if (fiber.tag === FiberTag.Portal) return
|
|
@@ -188,7 +291,7 @@ function hideRootHostDoms(fiber: Fiber, out: Array<[HTMLElement, string]>): void
|
|
|
188
291
|
function hydrateSuspenseBoundary(
|
|
189
292
|
fiber: Fiber,
|
|
190
293
|
props: any,
|
|
191
|
-
boundary: [0 | 1, number, Comment, Comment],
|
|
294
|
+
boundary: [0 | 1 | 2 | 3, number, Comment, Comment],
|
|
192
295
|
domParent: Node,
|
|
193
296
|
anchor: Node | null,
|
|
194
297
|
): void {
|
|
@@ -200,6 +303,13 @@ function hydrateSuspenseBoundary(
|
|
|
200
303
|
r: props.children,
|
|
201
304
|
}
|
|
202
305
|
|
|
306
|
+
if (pendingBoundary >= 2) {
|
|
307
|
+
if (pendingBoundary === 3) reportServerFailure(fiber)
|
|
308
|
+
recoverBoundaryHydration(fiber, props.children, startMark.parentNode!, startMark, endMark, true)
|
|
309
|
+
fiber.mp = props
|
|
310
|
+
return
|
|
311
|
+
}
|
|
312
|
+
|
|
203
313
|
if (!pendingBoundary) {
|
|
204
314
|
// Real DOM is inline between startMark and endMark. Hydrate into it.
|
|
205
315
|
const parent = startMark.parentNode!
|
|
@@ -209,8 +319,10 @@ function hydrateSuspenseBoundary(
|
|
|
209
319
|
advanceCursorPast(fiber.parent!, endMark)
|
|
210
320
|
} catch (e) {
|
|
211
321
|
if (!isHydrationBailout(e)) {
|
|
212
|
-
|
|
213
|
-
|
|
322
|
+
onCommitFailure(() => {
|
|
323
|
+
clearBoundaryRange(startMark, endMark)
|
|
324
|
+
unmountAllChildren(fiber, parent)
|
|
325
|
+
})
|
|
214
326
|
throw e
|
|
215
327
|
}
|
|
216
328
|
recoverBoundaryHydration(fiber, props.children, parent, startMark, endMark)
|
|
@@ -253,19 +365,25 @@ function recoverBoundaryHydration(
|
|
|
253
365
|
parent: Node,
|
|
254
366
|
startMark: Comment,
|
|
255
367
|
endMark: Comment,
|
|
368
|
+
retryBoundary = false,
|
|
256
369
|
): void {
|
|
257
370
|
const root = findRoot(fiber)!
|
|
258
371
|
const prevHydrating = root.h
|
|
259
|
-
discardPendingWork(root)
|
|
372
|
+
if (!retryBoundary) discardPendingWork(root)
|
|
260
373
|
clearBoundaryRange(startMark, endMark)
|
|
261
374
|
unmountAllChildren(fiber, parent)
|
|
262
375
|
root.h = false
|
|
263
376
|
try {
|
|
264
|
-
|
|
377
|
+
if (retryBoundary) {
|
|
378
|
+
fiber.ms = {}
|
|
379
|
+
renderSuspense(fiber, parent, endMark)
|
|
380
|
+
} else reconcileChildren(fiber, childrenToArray(children), parent, endMark)
|
|
265
381
|
advanceCursorPast(fiber.parent!, endMark)
|
|
266
382
|
} catch (clientError) {
|
|
267
|
-
|
|
268
|
-
|
|
383
|
+
onCommitFailure(() => {
|
|
384
|
+
clearBoundaryRange(startMark, endMark)
|
|
385
|
+
unmountAllChildren(fiber, parent)
|
|
386
|
+
})
|
|
269
387
|
throw clientError
|
|
270
388
|
} finally {
|
|
271
389
|
root.h = prevHydrating
|
|
@@ -276,14 +394,16 @@ function recoverFallbackHydration(fiber: Fiber, fallback: any, parent: HTMLEleme
|
|
|
276
394
|
const root = findRoot(fiber)!
|
|
277
395
|
const prevHydrating = root.h
|
|
278
396
|
discardPendingWork(root)
|
|
279
|
-
parent.textContent = ''
|
|
397
|
+
queueMutation(() => { parent.textContent = '' })
|
|
280
398
|
unmountAllChildren(fiber, parent)
|
|
281
399
|
root.h = false
|
|
282
400
|
try {
|
|
283
401
|
reconcileChildren(fiber, childrenToArray(fallback), parent, null)
|
|
284
402
|
} catch (clientError) {
|
|
285
|
-
|
|
286
|
-
|
|
403
|
+
onCommitFailure(() => {
|
|
404
|
+
parent.textContent = ''
|
|
405
|
+
unmountAllChildren(fiber, parent)
|
|
406
|
+
})
|
|
287
407
|
throw clientError
|
|
288
408
|
} finally {
|
|
289
409
|
root.h = prevHydrating
|
|
@@ -302,6 +422,12 @@ function rehydrateBoundary(fiber: Fiber): void {
|
|
|
302
422
|
// (or at least its container); unmounting here cleans up fibers + fx.
|
|
303
423
|
withCurrentRoot(root, () => {
|
|
304
424
|
const prevHydrating = root.h
|
|
425
|
+
if (state.b.data.startsWith('$!') || state.b.data.startsWith('$E')) {
|
|
426
|
+
if (state.b.data.startsWith('$E')) reportServerFailure(fiber)
|
|
427
|
+
recoverBoundaryHydration(fiber, state.r, parent, state.b, state.e, true)
|
|
428
|
+
runEffects(root)
|
|
429
|
+
return
|
|
430
|
+
}
|
|
305
431
|
try {
|
|
306
432
|
unmountAllChildren(fiber, parent)
|
|
307
433
|
|
|
@@ -311,8 +437,10 @@ function rehydrateBoundary(fiber: Fiber): void {
|
|
|
311
437
|
reconcileChildren(fiber, childrenToArray(state.r), parent, null)
|
|
312
438
|
} catch (e) {
|
|
313
439
|
if (!isHydrationBailout(e)) {
|
|
314
|
-
|
|
315
|
-
|
|
440
|
+
onCommitFailure(() => {
|
|
441
|
+
clearBoundaryRange(state.b, state.e)
|
|
442
|
+
unmountAllChildren(fiber, parent)
|
|
443
|
+
})
|
|
316
444
|
throw e
|
|
317
445
|
}
|
|
318
446
|
|
|
@@ -325,13 +453,22 @@ function rehydrateBoundary(fiber: Fiber): void {
|
|
|
325
453
|
})
|
|
326
454
|
}
|
|
327
455
|
|
|
456
|
+
function reportServerFailure(fiber: Fiber): void {
|
|
457
|
+
const error = new Error('Switched to client rendering because the server render did not complete.')
|
|
458
|
+
const handler = findRoot(fiber)?.re
|
|
459
|
+
if (handler) handler(error, { componentStack: null })
|
|
460
|
+
else console.error(error)
|
|
461
|
+
}
|
|
462
|
+
|
|
328
463
|
function clearBoundaryRange(startMark: Comment, endMark: Comment): void {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
464
|
+
queueMutation(() => {
|
|
465
|
+
let node = startMark.nextSibling
|
|
466
|
+
while (node && node !== endMark) {
|
|
467
|
+
const next = node.nextSibling
|
|
468
|
+
node.parentNode?.removeChild(node)
|
|
469
|
+
node = next
|
|
470
|
+
}
|
|
471
|
+
})
|
|
335
472
|
}
|
|
336
473
|
|
|
337
474
|
registerTypeMatcher((type) => (type === REACT_SUSPENSE_TYPE ? FiberTag.Suspense : null))
|