@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
|
@@ -7,10 +7,12 @@ import {
|
|
|
7
7
|
type ReactNode,
|
|
8
8
|
} from '../../../core'
|
|
9
9
|
import { attributeName, STRING_BOOLEAN_ATTRS } from '../../../core/attributes'
|
|
10
|
-
import { createHostNode, setProp } from '../../dom'
|
|
10
|
+
import { createHostNode, setProp, syncTextareaValue } from '../../dom'
|
|
11
|
+
import { queueMutation, queueProp, queueText } from '../../commit'
|
|
11
12
|
import { drainReplayQueue } from '../../event-replay'
|
|
12
|
-
import { discardPendingWork, findRoot, flushSyncWork, renderRoot } from '../../reconcile'
|
|
13
|
+
import { discardPendingWork, discardPendingEffects, findRoot, flushSyncWork, renderRoot, scheduleRootRender, recoverRootError, unmountFiber } from '../../reconcile'
|
|
13
14
|
import { attachRootFiber, createFiberRoot } from '../../root-internal'
|
|
15
|
+
import { componentStack } from '../../error-info'
|
|
14
16
|
|
|
15
17
|
// Re-export from event-replay so all hydration concerns live behind one
|
|
16
18
|
// feature boundary — the plugin's stub swap strips drainReplayQueue too.
|
|
@@ -146,9 +148,9 @@ export function abortHydration(cause: unknown, fiber: Fiber | null = null): neve
|
|
|
146
148
|
|
|
147
149
|
interface HydrateRootOptions {
|
|
148
150
|
identifierPrefix?: string
|
|
149
|
-
onRecoverableError?: (
|
|
150
|
-
onCaughtError?: (
|
|
151
|
-
onUncaughtError?: (
|
|
151
|
+
onRecoverableError?: import('../../../core').RecoverableErrorHandler
|
|
152
|
+
onCaughtError?: import('../../../core').RecoverableErrorHandler
|
|
153
|
+
onUncaughtError?: import('../../../core').RecoverableErrorHandler
|
|
152
154
|
}
|
|
153
155
|
|
|
154
156
|
interface HydratedRoot {
|
|
@@ -186,7 +188,7 @@ export function hydrateRootImpl(
|
|
|
186
188
|
|
|
187
189
|
return {
|
|
188
190
|
render(children) {
|
|
189
|
-
|
|
191
|
+
scheduleRootRender(root, () => {
|
|
190
192
|
const normalized = isDocument ? normalizeDocumentChildren(children) : children
|
|
191
193
|
renderRoot(
|
|
192
194
|
root,
|
|
@@ -224,13 +226,19 @@ function headAttrsMatch(
|
|
|
224
226
|
if (!keys) return true
|
|
225
227
|
for (const k of keys) {
|
|
226
228
|
const propVal = props[k]
|
|
227
|
-
const elVal = el
|
|
229
|
+
const elVal = hydrationAttribute(el, attributeName(k))
|
|
228
230
|
if (propVal == null && elVal == null) continue
|
|
229
231
|
if (propVal == null || elVal == null || String(propVal) !== elVal) return false
|
|
230
232
|
}
|
|
231
233
|
return true
|
|
232
234
|
}
|
|
233
235
|
|
|
236
|
+
function hydrationAttribute(el: Element, name: string): string | null {
|
|
237
|
+
return name === 'nonce' && 'nonce' in el && el.hasAttribute(name)
|
|
238
|
+
? (el as HTMLElement).nonce ?? ''
|
|
239
|
+
: el.getAttribute(name)
|
|
240
|
+
}
|
|
241
|
+
|
|
234
242
|
export function beginHydration(root: FiberRoot): void {
|
|
235
243
|
root.ic = 0
|
|
236
244
|
root.h = true
|
|
@@ -247,7 +255,7 @@ export function endHydration(root: FiberRoot): void {
|
|
|
247
255
|
* marker emitted by the server. Returns info + advances the cursor past the
|
|
248
256
|
* marker pair (start comment + fallback/real content + end comment).
|
|
249
257
|
*/
|
|
250
|
-
export type BoundaryInfo = [0 | 1, number, Comment, Comment]
|
|
258
|
+
export type BoundaryInfo = [0 | 1 | 2 | 3, number, Comment, Comment]
|
|
251
259
|
|
|
252
260
|
export function tryConsumeBoundary(parent: Fiber): BoundaryInfo | null {
|
|
253
261
|
const cursor = hydrationCursors.get(findHostParent(parent))
|
|
@@ -255,9 +263,9 @@ export function tryConsumeBoundary(parent: Fiber): BoundaryInfo | null {
|
|
|
255
263
|
const peek = cursor.n
|
|
256
264
|
if (!peek || peek.nodeType !== 8) return null
|
|
257
265
|
const data = (peek as Comment).data
|
|
258
|
-
const m = /^(
|
|
266
|
+
const m = /^(\$[?!E]?)(\d+)$/.exec(data)
|
|
259
267
|
if (!m) return null
|
|
260
|
-
const kind = m[1] === '$?' ? 1 : 0
|
|
268
|
+
const kind = m[1] === '$?' ? 1 : m[1] === '$!' ? 2 : m[1] === '$E' ? 3 : 0
|
|
261
269
|
const id = Number(m[2])
|
|
262
270
|
const startMark = peek as Comment
|
|
263
271
|
// Advance past the start comment
|
|
@@ -265,8 +273,11 @@ export function tryConsumeBoundary(parent: Fiber): BoundaryInfo | null {
|
|
|
265
273
|
// Locate end comment: closest <!--/$-->
|
|
266
274
|
let endMark: Comment | null = null
|
|
267
275
|
let scan = startMark.nextSibling
|
|
276
|
+
let depth = 0
|
|
268
277
|
while (scan) {
|
|
278
|
+
if (scan.nodeType === 8 && /^\$[?!E]?\d+$/.test((scan as Comment).data)) depth++
|
|
269
279
|
if (scan.nodeType === 8 && (scan as Comment).data === '/$') {
|
|
280
|
+
if (depth) { depth--; scan = scan.nextSibling; continue }
|
|
270
281
|
endMark = scan as Comment
|
|
271
282
|
break
|
|
272
283
|
}
|
|
@@ -360,26 +371,43 @@ export function adoptHostDom(fiber: Fiber, parent: Fiber): boolean {
|
|
|
360
371
|
!props.suppressHydrationWarning &&
|
|
361
372
|
canRecoverHydrationPropMismatch(candidate, tag)
|
|
362
373
|
validateHydrationProps(fiber, candidate as Element, props, tag, isSvg)
|
|
374
|
+
// Form state can change between server paint and hydration. Initialize reset
|
|
375
|
+
// defaults without treating the live value or selection as a mismatch.
|
|
376
|
+
if (tag === 'input' || tag === 'textarea') queueHydrationFormState(candidate as Element, props, tag)
|
|
363
377
|
for (const k in props) {
|
|
364
378
|
if (
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
) continue
|
|
371
|
-
if (
|
|
372
|
-
syncHydrationProps ||
|
|
379
|
+
(syncHydrationProps &&
|
|
380
|
+
k !== 'children' && k !== 'key' && k !== 'ref' &&
|
|
381
|
+
(k !== 'nonce' || hydrationAttribute(candidate as Element, k) !== props[k]) &&
|
|
382
|
+
k !== 'suppressHydrationWarning' && k !== 'suppressContentEditableWarning' &&
|
|
383
|
+
!isHydrationFormProp(tag, k)) ||
|
|
373
384
|
(k[0] === 'o' && k[1] === 'n' && typeof props[k] == 'function')
|
|
374
|
-
)
|
|
375
|
-
setProp(candidate as Element, k, props[k], undefined, isSvg)
|
|
376
|
-
}
|
|
385
|
+
) queueProp(candidate as Element, k, props[k], undefined, isSvg)
|
|
377
386
|
}
|
|
378
387
|
// Set up child cursor for this host's children
|
|
379
388
|
hydrationCursors.set(fiber, new HydrationCursor(candidate))
|
|
380
389
|
return true
|
|
381
390
|
}
|
|
382
391
|
|
|
392
|
+
function queueHydrationFormState(el: Element, props: any, tag: string): void {
|
|
393
|
+
queueMutation(() => {
|
|
394
|
+
if (tag === 'input') {
|
|
395
|
+
const input = el as HTMLInputElement
|
|
396
|
+
if (props.type != null) input.type = props.type
|
|
397
|
+
const value = props.value ?? props.defaultValue
|
|
398
|
+
if (value != null && (props.value != null || (input.type !== 'submit' && input.type !== 'reset'))) {
|
|
399
|
+
input.defaultValue = '' + value
|
|
400
|
+
}
|
|
401
|
+
// Mark checked as dirty before changing its default, including clean SSR
|
|
402
|
+
// inputs whose client default differs. This also preserves radio groups.
|
|
403
|
+
input.checked = input.checked
|
|
404
|
+
input.defaultChecked = !!(props.checked ?? props.defaultChecked)
|
|
405
|
+
} else {
|
|
406
|
+
syncTextareaValue(el as HTMLTextAreaElement, props, true)
|
|
407
|
+
}
|
|
408
|
+
})
|
|
409
|
+
}
|
|
410
|
+
|
|
383
411
|
export function adoptTextDom(fiber: Fiber, parent: Fiber, text: string): boolean {
|
|
384
412
|
const cursor = hydrationCursors.get(findHostParent(parent))
|
|
385
413
|
if (!cursor) return false
|
|
@@ -400,7 +428,7 @@ export function adoptTextDom(fiber: Fiber, parent: Fiber, text: string): boolean
|
|
|
400
428
|
canRecoverHydrationPropMismatch(candidate),
|
|
401
429
|
)
|
|
402
430
|
if (recovered) {
|
|
403
|
-
|
|
431
|
+
queueText(candidate as Text, text)
|
|
404
432
|
}
|
|
405
433
|
}
|
|
406
434
|
fiber.dom = candidate
|
|
@@ -447,7 +475,7 @@ function failHydration(
|
|
|
447
475
|
): boolean {
|
|
448
476
|
const root = findRoot(fiber)
|
|
449
477
|
if (root?.re) {
|
|
450
|
-
root.re(error)
|
|
478
|
+
root.re(error, { componentStack: componentStack(fiber) })
|
|
451
479
|
}
|
|
452
480
|
if (recoverInPlace) return true
|
|
453
481
|
abortHydration(error, findHostRecoveryParent(fiber) ?? fiber)
|
|
@@ -533,6 +561,7 @@ export function recoverHydration(root: FiberRoot, error: unknown): boolean {
|
|
|
533
561
|
flushSyncWork(() => renderRoot(root, children))
|
|
534
562
|
} catch (clientError) {
|
|
535
563
|
resetAfterHydrationFailure(root, container)
|
|
564
|
+
if (recoverRootError(clientError)) return true
|
|
536
565
|
throw clientError
|
|
537
566
|
}
|
|
538
567
|
return true
|
|
@@ -542,25 +571,30 @@ function resetAfterHydrationFailure(
|
|
|
542
571
|
root: FiberRoot,
|
|
543
572
|
container: Element | Document,
|
|
544
573
|
): void {
|
|
574
|
+
// Retire committed subscriptions and portals without removing the document shell.
|
|
575
|
+
unmountFiber(root.r, container, false)
|
|
545
576
|
discardPendingWork(root)
|
|
577
|
+
discardPendingEffects(root)
|
|
546
578
|
clearHydrationContainer(container)
|
|
547
579
|
attachRootFiber(root, container)
|
|
548
580
|
root.h = false
|
|
549
581
|
}
|
|
550
582
|
|
|
551
583
|
function clearHydrationContainer(container: Element | Document): void {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
584
|
+
queueMutation(() => {
|
|
585
|
+
if (container.nodeType === 9) {
|
|
586
|
+
let node = container.firstChild
|
|
587
|
+
while (node) {
|
|
588
|
+
const next = node.nextSibling
|
|
589
|
+
if (node.nodeType !== 10 /* DOCUMENT_TYPE_NODE */) {
|
|
590
|
+
container.removeChild(node)
|
|
591
|
+
}
|
|
592
|
+
node = next
|
|
558
593
|
}
|
|
559
|
-
|
|
594
|
+
return
|
|
560
595
|
}
|
|
561
|
-
|
|
562
|
-
}
|
|
563
|
-
;(container as Element).textContent = ''
|
|
596
|
+
;(container as Element).textContent = ''
|
|
597
|
+
})
|
|
564
598
|
}
|
|
565
599
|
|
|
566
600
|
function getRecoverableHostChildren(
|
|
@@ -684,6 +718,14 @@ function createHostElement(type: string, props: Record<string, unknown>): ReactE
|
|
|
684
718
|
}
|
|
685
719
|
}
|
|
686
720
|
|
|
721
|
+
function isHydrationFormProp(tag: string, key: string): boolean {
|
|
722
|
+
return (
|
|
723
|
+
((tag === 'input' || tag === 'textarea' || tag === 'select') && (key === 'value' || key === 'defaultValue')) ||
|
|
724
|
+
(tag === 'input' && (key === 'checked' || key === 'defaultChecked')) ||
|
|
725
|
+
(tag === 'option' && key === 'selected')
|
|
726
|
+
)
|
|
727
|
+
}
|
|
728
|
+
|
|
687
729
|
function validateHydrationProps(
|
|
688
730
|
fiber: Fiber,
|
|
689
731
|
el: Element,
|
|
@@ -708,13 +750,14 @@ function validateHydrationProps(
|
|
|
708
750
|
) continue
|
|
709
751
|
|
|
710
752
|
if (k === 'dangerouslySetInnerHTML') {
|
|
711
|
-
let html =
|
|
753
|
+
let html = value?.__html
|
|
754
|
+
if (html == null) continue
|
|
712
755
|
if (tag !== 'script' && tag !== 'style') {
|
|
713
|
-
const probe =
|
|
756
|
+
const probe = createHostNode(tag, isSvg)
|
|
714
757
|
probe.innerHTML = html
|
|
715
758
|
html = probe.innerHTML
|
|
716
759
|
}
|
|
717
|
-
if ((el as HTMLElement).innerHTML !== html) {
|
|
760
|
+
if ((el as HTMLElement).innerHTML !== '' + html) {
|
|
718
761
|
failHydration(
|
|
719
762
|
fiber,
|
|
720
763
|
process.env.NODE_ENV !== 'production'
|
|
@@ -726,51 +769,7 @@ function validateHydrationProps(
|
|
|
726
769
|
continue
|
|
727
770
|
}
|
|
728
771
|
|
|
729
|
-
if (
|
|
730
|
-
if (tag === 'select') continue
|
|
731
|
-
if (tag === 'input' || tag === 'textarea') {
|
|
732
|
-
if (k === 'value' || props.value == null) {
|
|
733
|
-
if (value != null && (el as HTMLInputElement).value !== '' + value) {
|
|
734
|
-
failHydration(
|
|
735
|
-
fiber,
|
|
736
|
-
process.env.NODE_ENV !== 'production'
|
|
737
|
-
? new Error(`Hydration ${tag} value mismatch on <${tag}>.`)
|
|
738
|
-
: undefined,
|
|
739
|
-
recoverInPlace,
|
|
740
|
-
)
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
continue
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
if (tag === 'input' && (k === 'checked' || k === 'defaultChecked')) {
|
|
748
|
-
if (k === 'checked' || props.checked == null) {
|
|
749
|
-
if (value != null && (el as HTMLInputElement).checked !== !!value) {
|
|
750
|
-
failHydration(
|
|
751
|
-
fiber,
|
|
752
|
-
process.env.NODE_ENV !== 'production'
|
|
753
|
-
? new Error(`Hydration checked mismatch on <input>.`)
|
|
754
|
-
: undefined,
|
|
755
|
-
recoverInPlace,
|
|
756
|
-
)
|
|
757
|
-
}
|
|
758
|
-
}
|
|
759
|
-
continue
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
if (tag === 'option' && k === 'selected') {
|
|
763
|
-
if (value != null && (el as HTMLOptionElement).selected !== !!value) {
|
|
764
|
-
failHydration(
|
|
765
|
-
fiber,
|
|
766
|
-
process.env.NODE_ENV !== 'production'
|
|
767
|
-
? new Error(`Hydration selected mismatch on <option>.`)
|
|
768
|
-
: undefined,
|
|
769
|
-
recoverInPlace,
|
|
770
|
-
)
|
|
771
|
-
}
|
|
772
|
-
continue
|
|
773
|
-
}
|
|
772
|
+
if (isHydrationFormProp(tag, k)) continue
|
|
774
773
|
|
|
775
774
|
if (k === 'style') {
|
|
776
775
|
expected ??= createHostNode(tag, isSvg)
|
|
@@ -802,12 +801,15 @@ function validateHydrationProps(
|
|
|
802
801
|
} else if (k === 'muted' && !isSvg && (tag === 'video' || tag === 'audio')) {
|
|
803
802
|
// The muted property controls playback; defaultMuted reflects the SSR attribute.
|
|
804
803
|
expectedValue = value ? '' : null
|
|
804
|
+
} else if (stringifiedBoolean && k.length > 5) {
|
|
805
|
+
// These attributes use setAttribute string coercion, not DOM property normalization.
|
|
806
|
+
expectedValue = '' + value
|
|
805
807
|
} else {
|
|
806
808
|
expected ??= createHostNode(tag, isSvg)
|
|
807
809
|
setProp(expected, k, value, undefined, isSvg)
|
|
808
810
|
expectedValue = expected.getAttribute(attr)
|
|
809
811
|
}
|
|
810
|
-
const actualValue = el
|
|
812
|
+
const actualValue = hydrationAttribute(el, attr)
|
|
811
813
|
if (expectedValue !== actualValue) {
|
|
812
814
|
failHydration(
|
|
813
815
|
fiber,
|
|
@@ -24,7 +24,7 @@ export class HydrationCursor {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export type BoundaryInfo = [0 | 1, number, Comment, Comment]
|
|
27
|
+
export type BoundaryInfo = [0 | 1 | 2 | 3, number, Comment, Comment]
|
|
28
28
|
|
|
29
29
|
export function beginHydration(_root: FiberRoot): void {
|
|
30
30
|
throw new Error(
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
renderFiber,
|
|
11
11
|
getForceRerenderingFiber,
|
|
12
12
|
} from '../../reconcile'
|
|
13
|
+
import { ownContextChanged, renderContextConsumers } from '../context'
|
|
13
14
|
|
|
14
15
|
function shallowEqual(a: any, b: any): boolean {
|
|
15
16
|
if (a === b) return true
|
|
@@ -33,10 +34,10 @@ function renderMemo(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
|
33
34
|
// useSyncExternalStore notification), props haven't changed by definition —
|
|
34
35
|
// bailing would swallow the state change and the subscriber never re-runs.
|
|
35
36
|
// rerenderFiber tags the fiber so we skip the gate here.
|
|
36
|
-
const bypassMemo = fiber === getForceRerenderingFiber()
|
|
37
|
+
const bypassMemo = fiber.dy || fiber === getForceRerenderingFiber()
|
|
37
38
|
const eq = !bypassMemo && prev && (compare ? compare(prev, props) : shallowEqual(prev, props))
|
|
38
|
-
if (eq) {
|
|
39
|
-
|
|
39
|
+
if (eq && !ownContextChanged(fiber)) {
|
|
40
|
+
renderContextConsumers(fiber)
|
|
40
41
|
return
|
|
41
42
|
}
|
|
42
43
|
|