@tanstack/redact 0.0.21 → 0.1.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/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 -27
- 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 +72 -15
- 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 +17 -8
- 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 -77
- 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 +197 -52
- 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 +689 -221
- 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 +7 -2
- package/dist/react/context.js +3 -11
- package/dist/react/context.js.map +3 -3
- package/dist/react/element.d.ts +6 -3
- package/dist/react/element.js +7 -11
- 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 +150 -110
- 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 -28
- package/src/dom/features/context/full.ts +70 -13
- package/src/dom/features/context/stub.ts +10 -5
- 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 -85
- 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 +192 -55
- 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 +695 -242
- 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/context.ts +4 -11
- package/src/react/element.ts +11 -12
- 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 +79 -26
- package/src/vite/index.ts +30 -13
|
@@ -1,52 +1,109 @@
|
|
|
1
1
|
import { FiberTag, type Fiber } from '../../../core'
|
|
2
|
-
import { REACT_PROVIDER_TYPE, REACT_CONSUMER_TYPE } from '../../../react'
|
|
2
|
+
import { REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE, REACT_CONSUMER_TYPE } from '../../../react'
|
|
3
3
|
import {
|
|
4
4
|
registerRenderer,
|
|
5
5
|
registerTypeMatcher,
|
|
6
6
|
installCapability,
|
|
7
7
|
reconcileChildren,
|
|
8
8
|
childrenToArray,
|
|
9
|
+
renderFiber,
|
|
10
|
+
getHostParent,
|
|
11
|
+
getAnchor,
|
|
9
12
|
} from '../../reconcile'
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
let changingProviders = 0
|
|
15
|
+
|
|
16
|
+
function contextValue(fiber: Fiber, ctx: any): any {
|
|
12
17
|
let p: Fiber | null = fiber.parent
|
|
13
18
|
while (p) {
|
|
14
19
|
if (p.tag === FiberTag.Provider && (p.type as any)._context === ctx) {
|
|
15
|
-
return
|
|
20
|
+
return p.pp?.value
|
|
16
21
|
}
|
|
17
22
|
p = p.parent
|
|
18
23
|
}
|
|
19
24
|
return ctx._currentValue
|
|
20
25
|
}
|
|
21
26
|
|
|
27
|
+
function remember(fiber: Fiber, ctx: any, value: any): void {
|
|
28
|
+
;(fiber.cx ??= new Map()).set(ctx, value)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function realReadContext(fiber: Fiber, ctx: any): any {
|
|
32
|
+
const value = contextValue(fiber, ctx)
|
|
33
|
+
remember(fiber, ctx, value)
|
|
34
|
+
// Initial suspended attempts are discarded. Keep their external context
|
|
35
|
+
// reads on the boundary so a provider can retry them before a promise settles.
|
|
36
|
+
let child = fiber
|
|
37
|
+
let p = fiber.parent
|
|
38
|
+
while (p) {
|
|
39
|
+
if (p.tag === FiberTag.Provider && p.type._context === ctx) break
|
|
40
|
+
if (p.tag === FiberTag.Suspense && p.ms?.f !== child) remember(p, ctx, value)
|
|
41
|
+
child = p
|
|
42
|
+
p = p.parent
|
|
43
|
+
}
|
|
44
|
+
return value
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function ownContextChanged(fiber: Fiber): boolean {
|
|
48
|
+
if (!changingProviders) return false
|
|
49
|
+
const reads = fiber.cx
|
|
50
|
+
if (reads) {
|
|
51
|
+
for (const [ctx, value] of reads) {
|
|
52
|
+
if (!Object.is(value, contextValue(fiber, ctx))) return true
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return false
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function hasContextChanged(fiber: Fiber, includeFallback = true): boolean {
|
|
59
|
+
if (!changingProviders) return false
|
|
60
|
+
if (ownContextChanged(fiber)) return true
|
|
61
|
+
let child = fiber.child
|
|
62
|
+
while (child) {
|
|
63
|
+
if (hasContextChanged(child)) return true
|
|
64
|
+
child = child.sibling
|
|
65
|
+
}
|
|
66
|
+
return includeFallback && fiber.tag === FiberTag.Suspense && !!fiber.ms?.f && hasContextChanged(fiber.ms.f)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function renderContextConsumers(fiber: Fiber): void {
|
|
70
|
+
if (!changingProviders) return
|
|
71
|
+
let child = fiber.child
|
|
72
|
+
while (child) {
|
|
73
|
+
if (child.tag === FiberTag.Suspense ? hasContextChanged(child) : ownContextChanged(child)) {
|
|
74
|
+
const domParent = getHostParent(child)
|
|
75
|
+
renderFiber(child, domParent, getAnchor(child, domParent))
|
|
76
|
+
} else {
|
|
77
|
+
renderContextConsumers(child)
|
|
78
|
+
}
|
|
79
|
+
child = child.sibling
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
22
83
|
function renderProvider(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
23
|
-
const ctx = (fiber.type as any)._context
|
|
24
84
|
const props = fiber.pp ?? {}
|
|
25
|
-
const
|
|
26
|
-
|
|
85
|
+
const changed = fiber.mp && !Object.is(fiber.mp.value, props.value)
|
|
86
|
+
if (changed) changingProviders++
|
|
27
87
|
try {
|
|
28
88
|
reconcileChildren(fiber, childrenToArray(props.children), domParent, anchor)
|
|
29
89
|
} finally {
|
|
30
|
-
|
|
90
|
+
if (changed) changingProviders--
|
|
31
91
|
}
|
|
32
|
-
// Also store the value on the fiber so descendants rendering later (via updates)
|
|
33
|
-
// can read through by walking up.
|
|
34
|
-
fiber.ms = props.value
|
|
35
92
|
fiber.mp = props
|
|
36
93
|
}
|
|
37
94
|
|
|
38
95
|
function renderConsumer(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
39
|
-
|
|
96
|
+
fiber.cx?.clear()
|
|
40
97
|
const props = fiber.pp ?? {}
|
|
41
98
|
const children = props.children
|
|
42
|
-
const value = realReadContext(fiber,
|
|
99
|
+
const value = realReadContext(fiber, (fiber.type as any)._context)
|
|
43
100
|
const rendered = typeof children == 'function' ? children(value) : null
|
|
44
101
|
reconcileChildren(fiber, childrenToArray(rendered), domParent, anchor)
|
|
45
102
|
fiber.mp = props
|
|
46
103
|
}
|
|
47
104
|
|
|
48
105
|
registerTypeMatcher((_type, marker) =>
|
|
49
|
-
marker === REACT_PROVIDER_TYPE
|
|
106
|
+
marker === REACT_CONTEXT_TYPE || marker === REACT_PROVIDER_TYPE
|
|
50
107
|
? FiberTag.Provider
|
|
51
108
|
: marker === REACT_CONSUMER_TYPE
|
|
52
109
|
? FiberTag.Consumer
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FiberTag, type Fiber } from '../../../core'
|
|
2
|
-
import { REACT_PROVIDER_TYPE, REACT_CONSUMER_TYPE } from '../../../react'
|
|
2
|
+
import { REACT_CONTEXT_TYPE, REACT_PROVIDER_TYPE, REACT_CONSUMER_TYPE } from '../../../react'
|
|
3
3
|
import {
|
|
4
4
|
registerRenderer,
|
|
5
5
|
registerTypeMatcher,
|
|
@@ -7,6 +7,12 @@ import {
|
|
|
7
7
|
childrenToArray,
|
|
8
8
|
} from '../../reconcile'
|
|
9
9
|
|
|
10
|
+
export function hasContextChanged(_fiber: Fiber, _includeFallback = true): boolean {
|
|
11
|
+
return false
|
|
12
|
+
}
|
|
13
|
+
export const ownContextChanged = hasContextChanged
|
|
14
|
+
export function renderContextConsumers(_fiber: Fiber): void {}
|
|
15
|
+
|
|
10
16
|
// Stub: Context feature disabled. Provider elements render as Fragments
|
|
11
17
|
// (value is never propagated — descendants see only the Context's default).
|
|
12
18
|
// Consumer elements still invoke their function-children with the default
|
|
@@ -14,16 +20,15 @@ import {
|
|
|
14
20
|
// The default `readContext` capability returns `ctx._currentValue` without
|
|
15
21
|
// walking, which matches the no-Provider-fibers-in-tree reality.
|
|
16
22
|
function renderConsumerStub(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
17
|
-
const ctx = (fiber.type as any)._context
|
|
18
23
|
const props = fiber.pp ?? {}
|
|
19
|
-
const
|
|
20
|
-
|
|
24
|
+
const rendered = typeof props.children == 'function'
|
|
25
|
+
? props.children((fiber.type as any)._context._currentValue) : null
|
|
21
26
|
reconcileChildren(fiber, childrenToArray(rendered), domParent, anchor)
|
|
22
27
|
fiber.mp = props
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
registerTypeMatcher((_type, marker) =>
|
|
26
|
-
marker === REACT_PROVIDER_TYPE
|
|
31
|
+
marker === REACT_CONTEXT_TYPE || marker === REACT_PROVIDER_TYPE
|
|
27
32
|
? FiberTag.Fragment
|
|
28
33
|
: marker === REACT_CONSUMER_TYPE
|
|
29
34
|
? FiberTag.Consumer
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FiberTag, type Fiber, type ReactNode } from '../../../core'
|
|
2
|
-
import {
|
|
2
|
+
import { REACT_FORWARD_REF_TYPE } from '../../../react'
|
|
3
3
|
import {
|
|
4
4
|
registerRenderer,
|
|
5
5
|
registerTypeMatcher,
|
|
@@ -8,42 +8,32 @@ import {
|
|
|
8
8
|
isThenable,
|
|
9
9
|
handleSuspended,
|
|
10
10
|
handleErrorInRender,
|
|
11
|
+
getForceRerenderingFiber,
|
|
11
12
|
} from '../../reconcile'
|
|
12
|
-
import {
|
|
13
|
+
import { HOOK_BAILOUT, renderWithHooks } from '../../dispatcher'
|
|
13
14
|
|
|
14
15
|
function renderForwardRef(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
16
|
+
const canBail = fiber === getForceRerenderingFiber() && fiber.pp === fiber.mp
|
|
17
|
+
fiber.cx?.clear()
|
|
15
18
|
const props = fiber.pp ?? {}
|
|
16
19
|
const render = (fiber.type as any).render
|
|
17
20
|
const ref = fiber.ref ?? (props.ref ?? null)
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
const prevFiber = ReactSharedInternals.F
|
|
21
|
-
const prevHook = ReactSharedInternals.K
|
|
22
|
-
const prevIndex = ReactSharedInternals.I
|
|
23
|
-
ReactSharedInternals.H = makeDispatcher()
|
|
24
|
-
ReactSharedInternals.F = fiber
|
|
25
|
-
ReactSharedInternals.K = null
|
|
26
|
-
ReactSharedInternals.I = 0
|
|
27
|
-
|
|
28
|
-
let rendered: ReactNode
|
|
22
|
+
let rendered: ReactNode | typeof HOOK_BAILOUT
|
|
29
23
|
try {
|
|
30
24
|
const { ref: _omit, ...rest } = props
|
|
31
|
-
rendered = render
|
|
25
|
+
rendered = renderWithHooks(fiber, render, rest, ref, canBail)
|
|
32
26
|
} catch (e: any) {
|
|
33
27
|
if (isThenable(e)) {
|
|
34
28
|
handleSuspended(fiber, e)
|
|
35
|
-
|
|
29
|
+
return
|
|
36
30
|
} else {
|
|
37
31
|
handleErrorInRender(fiber, e)
|
|
38
32
|
return
|
|
39
33
|
}
|
|
40
|
-
} finally {
|
|
41
|
-
ReactSharedInternals.H = prevDispatcher
|
|
42
|
-
ReactSharedInternals.F = prevFiber
|
|
43
|
-
ReactSharedInternals.K = prevHook
|
|
44
|
-
ReactSharedInternals.I = prevIndex
|
|
45
34
|
}
|
|
46
35
|
|
|
36
|
+
if (rendered === HOOK_BAILOUT) return
|
|
47
37
|
reconcileChildren(fiber, childrenToArray(rendered), domParent, anchor)
|
|
48
38
|
fiber.mp = props
|
|
49
39
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createFragmentInstance, updateFragmentHost, refreshFragmentInstances } from '../../fragment-instance'
|
|
@@ -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, unmountFiber } 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,28 +571,30 @@ function resetAfterHydrationFailure(
|
|
|
542
571
|
root: FiberRoot,
|
|
543
572
|
container: Element | Document,
|
|
544
573
|
): void {
|
|
545
|
-
// Retire subscriptions and
|
|
546
|
-
|
|
547
|
-
unmountFiber(root.r, false)
|
|
574
|
+
// Retire committed subscriptions and portals without removing the document shell.
|
|
575
|
+
unmountFiber(root.r, container, false)
|
|
548
576
|
discardPendingWork(root)
|
|
577
|
+
discardPendingEffects(root)
|
|
549
578
|
clearHydrationContainer(container)
|
|
550
579
|
attachRootFiber(root, container)
|
|
551
580
|
root.h = false
|
|
552
581
|
}
|
|
553
582
|
|
|
554
583
|
function clearHydrationContainer(container: Element | Document): void {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
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
|
|
561
593
|
}
|
|
562
|
-
|
|
594
|
+
return
|
|
563
595
|
}
|
|
564
|
-
|
|
565
|
-
}
|
|
566
|
-
;(container as Element).textContent = ''
|
|
596
|
+
;(container as Element).textContent = ''
|
|
597
|
+
})
|
|
567
598
|
}
|
|
568
599
|
|
|
569
600
|
function getRecoverableHostChildren(
|
|
@@ -687,6 +718,14 @@ function createHostElement(type: string, props: Record<string, unknown>): ReactE
|
|
|
687
718
|
}
|
|
688
719
|
}
|
|
689
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
|
+
|
|
690
729
|
function validateHydrationProps(
|
|
691
730
|
fiber: Fiber,
|
|
692
731
|
el: Element,
|
|
@@ -711,13 +750,14 @@ function validateHydrationProps(
|
|
|
711
750
|
) continue
|
|
712
751
|
|
|
713
752
|
if (k === 'dangerouslySetInnerHTML') {
|
|
714
|
-
let html =
|
|
753
|
+
let html = value?.__html
|
|
754
|
+
if (html == null) continue
|
|
715
755
|
if (tag !== 'script' && tag !== 'style') {
|
|
716
|
-
const probe =
|
|
756
|
+
const probe = createHostNode(tag, isSvg)
|
|
717
757
|
probe.innerHTML = html
|
|
718
758
|
html = probe.innerHTML
|
|
719
759
|
}
|
|
720
|
-
if ((el as HTMLElement).innerHTML !== html) {
|
|
760
|
+
if ((el as HTMLElement).innerHTML !== '' + html) {
|
|
721
761
|
failHydration(
|
|
722
762
|
fiber,
|
|
723
763
|
process.env.NODE_ENV !== 'production'
|
|
@@ -729,51 +769,7 @@ function validateHydrationProps(
|
|
|
729
769
|
continue
|
|
730
770
|
}
|
|
731
771
|
|
|
732
|
-
if (
|
|
733
|
-
if (tag === 'select') continue
|
|
734
|
-
if (tag === 'input' || tag === 'textarea') {
|
|
735
|
-
if (k === 'value' || props.value == null) {
|
|
736
|
-
if (value != null && (el as HTMLInputElement).value !== '' + value) {
|
|
737
|
-
failHydration(
|
|
738
|
-
fiber,
|
|
739
|
-
process.env.NODE_ENV !== 'production'
|
|
740
|
-
? new Error(`Hydration ${tag} value mismatch on <${tag}>.`)
|
|
741
|
-
: undefined,
|
|
742
|
-
recoverInPlace,
|
|
743
|
-
)
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
continue
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
if (tag === 'input' && (k === 'checked' || k === 'defaultChecked')) {
|
|
751
|
-
if (k === 'checked' || props.checked == null) {
|
|
752
|
-
if (value != null && (el as HTMLInputElement).checked !== !!value) {
|
|
753
|
-
failHydration(
|
|
754
|
-
fiber,
|
|
755
|
-
process.env.NODE_ENV !== 'production'
|
|
756
|
-
? new Error(`Hydration checked mismatch on <input>.`)
|
|
757
|
-
: undefined,
|
|
758
|
-
recoverInPlace,
|
|
759
|
-
)
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
continue
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
if (tag === 'option' && k === 'selected') {
|
|
766
|
-
if (value != null && (el as HTMLOptionElement).selected !== !!value) {
|
|
767
|
-
failHydration(
|
|
768
|
-
fiber,
|
|
769
|
-
process.env.NODE_ENV !== 'production'
|
|
770
|
-
? new Error(`Hydration selected mismatch on <option>.`)
|
|
771
|
-
: undefined,
|
|
772
|
-
recoverInPlace,
|
|
773
|
-
)
|
|
774
|
-
}
|
|
775
|
-
continue
|
|
776
|
-
}
|
|
772
|
+
if (isHydrationFormProp(tag, k)) continue
|
|
777
773
|
|
|
778
774
|
if (k === 'style') {
|
|
779
775
|
expected ??= createHostNode(tag, isSvg)
|
|
@@ -805,12 +801,15 @@ function validateHydrationProps(
|
|
|
805
801
|
} else if (k === 'muted' && !isSvg && (tag === 'video' || tag === 'audio')) {
|
|
806
802
|
// The muted property controls playback; defaultMuted reflects the SSR attribute.
|
|
807
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
|
|
808
807
|
} else {
|
|
809
808
|
expected ??= createHostNode(tag, isSvg)
|
|
810
809
|
setProp(expected, k, value, undefined, isSvg)
|
|
811
810
|
expectedValue = expected.getAttribute(attr)
|
|
812
811
|
}
|
|
813
|
-
const actualValue = el
|
|
812
|
+
const actualValue = hydrationAttribute(el, attr)
|
|
814
813
|
if (expectedValue !== actualValue) {
|
|
815
814
|
failHydration(
|
|
816
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
|
|