@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
package/src/dom/dom.ts
CHANGED
|
@@ -9,6 +9,7 @@ const BOOLEAN_ATTRS = new Set([
|
|
|
9
9
|
'autoplay',
|
|
10
10
|
'checked',
|
|
11
11
|
'controls',
|
|
12
|
+
'credentialless',
|
|
12
13
|
'default',
|
|
13
14
|
'defer',
|
|
14
15
|
'disabled',
|
|
@@ -51,6 +52,54 @@ export function isSvgElement(el: Element): boolean {
|
|
|
51
52
|
return (el as any).ownerSVGElement !== undefined || el.tagName === 'svg'
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
export function syncInputValue(el: HTMLInputElement, props: any, prev?: any): void {
|
|
56
|
+
if (!prev) {
|
|
57
|
+
el.checked = el.defaultChecked = !!(props.checked ?? props.defaultChecked)
|
|
58
|
+
} else if (props.checked != null) {
|
|
59
|
+
el.checked = !!props.checked
|
|
60
|
+
} else if (props.defaultChecked != null) {
|
|
61
|
+
el.defaultChecked = !!props.defaultChecked
|
|
62
|
+
}
|
|
63
|
+
const value = props.value
|
|
64
|
+
const fallback = props.defaultValue
|
|
65
|
+
if (!prev) {
|
|
66
|
+
if (value == null && (el.type === 'submit' || el.type === 'reset')) return
|
|
67
|
+
if (value != null || fallback != null) {
|
|
68
|
+
const initial = '' + (value ?? fallback)
|
|
69
|
+
if (el.value !== initial) el.value = initial
|
|
70
|
+
el.defaultValue = initial
|
|
71
|
+
}
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
if (value != null) {
|
|
75
|
+
// Number inputs keep equivalent user spelling, including trailing zeroes.
|
|
76
|
+
if (el.type === 'number' ? (value === 0 && el.value === '') || el.value != value : el.value !== '' + value) {
|
|
77
|
+
el.value = '' + value
|
|
78
|
+
}
|
|
79
|
+
const nextDefault = el.type === 'number' && el.value == value ? el.value : '' + value
|
|
80
|
+
if (el.defaultValue !== nextDefault) el.defaultValue = nextDefault
|
|
81
|
+
} else if (fallback != null) {
|
|
82
|
+
if (el.defaultValue !== '' + fallback) el.defaultValue = '' + fallback
|
|
83
|
+
} else if (prev.defaultValue != null || el.type === 'submit' || el.type === 'reset') {
|
|
84
|
+
el.removeAttribute('value')
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function syncTextareaValue(el: HTMLTextAreaElement, props: any, mounting = false): void {
|
|
89
|
+
if (mounting) {
|
|
90
|
+
const children = props.children
|
|
91
|
+
const initial = props.value ?? props.defaultValue ?? (Array.isArray(children) ? children[0] : children) ?? ''
|
|
92
|
+
el.defaultValue = initial
|
|
93
|
+
// The strict check also preserves React's clean numeric-default state.
|
|
94
|
+
if (initial !== '' && el.textContent === initial) el.value = initial
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
const value = props.value
|
|
98
|
+
if (value != null && el.value !== '' + value) el.value = '' + value
|
|
99
|
+
const fallback = props.defaultValue ?? value ?? ''
|
|
100
|
+
if (el.defaultValue !== '' + fallback) el.defaultValue = '' + fallback
|
|
101
|
+
}
|
|
102
|
+
|
|
54
103
|
export function setProp(
|
|
55
104
|
el: Element,
|
|
56
105
|
name: string,
|
|
@@ -59,6 +108,14 @@ export function setProp(
|
|
|
59
108
|
isSvg: boolean,
|
|
60
109
|
): void {
|
|
61
110
|
if (name === 'children' || name === 'key' || name === 'ref') return
|
|
111
|
+
// These names need no alias or boolean-attribute normalization.
|
|
112
|
+
if (name.length > 5 && (name.charCodeAt(0) === 97 || name.charCodeAt(0) === 100)) {
|
|
113
|
+
if (name.startsWith('aria-') || name.startsWith('data-')) {
|
|
114
|
+
if (next == null) el.removeAttribute(name)
|
|
115
|
+
else el.setAttribute(name, '' + next)
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
}
|
|
62
119
|
const attr = attributeName(name, isSvg)
|
|
63
120
|
|
|
64
121
|
// defaultValue / defaultChecked are IDL-property-only — they seed the
|
|
@@ -76,19 +133,8 @@ export function setProp(
|
|
|
76
133
|
return
|
|
77
134
|
}
|
|
78
135
|
|
|
79
|
-
if (name === 'className') {
|
|
80
|
-
|
|
81
|
-
if (next == null) el.removeAttribute('class')
|
|
82
|
-
else el.setAttribute('class', '' + next)
|
|
83
|
-
} else {
|
|
84
|
-
;(el as HTMLElement).className = next == null ? '' : '' + next
|
|
85
|
-
}
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (name === 'class') {
|
|
90
|
-
if (next == null) el.removeAttribute('class')
|
|
91
|
-
else el.setAttribute('class', '' + next)
|
|
136
|
+
if (name === 'className' && !isSvg) {
|
|
137
|
+
;(el as HTMLElement).className = next == null ? '' : '' + next
|
|
92
138
|
return
|
|
93
139
|
}
|
|
94
140
|
|
|
@@ -105,17 +151,11 @@ export function setProp(
|
|
|
105
151
|
}
|
|
106
152
|
|
|
107
153
|
if (name[0] === 'o' && name[1] === 'n') {
|
|
108
|
-
setEventHandler(el, name, next
|
|
154
|
+
setEventHandler(el, name, next)
|
|
109
155
|
return
|
|
110
156
|
}
|
|
111
157
|
|
|
112
|
-
if (name === 'htmlFor') {
|
|
113
|
-
if (next == null) el.removeAttribute('for')
|
|
114
|
-
else el.setAttribute('for', '' + next)
|
|
115
|
-
return
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (STRING_BOOLEAN_ATTRS.has(attr)) {
|
|
158
|
+
if (name === 'className' || name === 'class' || name === 'htmlFor' || STRING_BOOLEAN_ATTRS.has(attr)) {
|
|
119
159
|
if (next == null) el.removeAttribute(attr)
|
|
120
160
|
else el.setAttribute(attr, '' + next)
|
|
121
161
|
return
|
|
@@ -128,32 +168,12 @@ export function setProp(
|
|
|
128
168
|
} catch {}
|
|
129
169
|
}
|
|
130
170
|
|
|
131
|
-
if (BOOLEAN_ATTRS.has(
|
|
132
|
-
if (next) el.setAttribute(attr, '')
|
|
133
|
-
else el.removeAttribute(attr)
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// aria-* and data-* attributes stringify booleans to `"true"`/`"false"`
|
|
138
|
-
// rather than using the HTML boolean-attribute presence/absence semantics.
|
|
139
|
-
// This matches React and the ARIA spec (aria-hidden="false" is meaningful).
|
|
140
|
-
if (name.length > 5 && (name.charCodeAt(0) === 97 /* a */ || name.charCodeAt(0) === 100 /* d */)) {
|
|
141
|
-
if (name.startsWith('aria-') || name.startsWith('data-')) {
|
|
142
|
-
if (next == null) {
|
|
143
|
-
el.removeAttribute(attr)
|
|
144
|
-
} else {
|
|
145
|
-
el.setAttribute(attr, '' + next)
|
|
146
|
-
}
|
|
147
|
-
return
|
|
148
|
-
}
|
|
149
|
-
}
|
|
171
|
+
if (BOOLEAN_ATTRS.has(attr)) next = !!next
|
|
150
172
|
|
|
151
173
|
if (next == null || next === false) {
|
|
152
174
|
el.removeAttribute(attr)
|
|
153
|
-
} else if (next === true) {
|
|
154
|
-
el.setAttribute(attr, '')
|
|
155
175
|
} else {
|
|
156
|
-
el.setAttribute(attr, ''
|
|
176
|
+
el.setAttribute(attr, next === true ? '' : next)
|
|
157
177
|
}
|
|
158
178
|
}
|
|
159
179
|
|
|
@@ -241,7 +261,7 @@ export interface SyntheticEvent extends Event {
|
|
|
241
261
|
currentTarget: EventTarget & Element
|
|
242
262
|
}
|
|
243
263
|
|
|
244
|
-
function setEventHandler(el: Element, name: string, next: any
|
|
264
|
+
function setEventHandler(el: Element, name: string, next: any): void {
|
|
245
265
|
// Only function handlers are accepted. Reject strings/objects/etc — the
|
|
246
266
|
// legacy `onclick="..."` HTML attribute (string handler) is a known XSS
|
|
247
267
|
// vector if a parent spreads untrusted props onto a host element. React
|
|
@@ -256,13 +276,11 @@ function setEventHandler(el: Element, name: string, next: any, prev: any): void
|
|
|
256
276
|
// `onInput` on the same text input — which both dispatch from the native
|
|
257
277
|
// `input` event — can coexist without clobbering each other's handlers.
|
|
258
278
|
const handlers = ((el as any).__handlers ||= Object.create(null))
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
const existing = handlers[key]
|
|
279
|
+
const existing = handlers[name]
|
|
262
280
|
|
|
263
281
|
if (existing && !next) {
|
|
264
|
-
el.removeEventListener(existing.event, existing.listener,
|
|
265
|
-
handlers[
|
|
282
|
+
el.removeEventListener(existing.event, existing.listener, capture)
|
|
283
|
+
handlers[name] = null
|
|
266
284
|
return
|
|
267
285
|
}
|
|
268
286
|
|
|
@@ -271,7 +289,6 @@ function setEventHandler(el: Element, name: string, next: any, prev: any): void
|
|
|
271
289
|
current: next as Function,
|
|
272
290
|
listener: null as any,
|
|
273
291
|
event: eventName,
|
|
274
|
-
capture,
|
|
275
292
|
}
|
|
276
293
|
entry.listener = (e: Event) => {
|
|
277
294
|
// React hands handlers a SyntheticEvent that carries `.nativeEvent`.
|
|
@@ -282,7 +299,7 @@ function setEventHandler(el: Element, name: string, next: any, prev: any): void
|
|
|
282
299
|
if ((e as any).nativeEvent === undefined) (e as any).nativeEvent = e
|
|
283
300
|
entry.current(e)
|
|
284
301
|
}
|
|
285
|
-
handlers[
|
|
302
|
+
handlers[name] = entry
|
|
286
303
|
el.addEventListener(eventName, entry.listener, capture)
|
|
287
304
|
return
|
|
288
305
|
}
|
|
@@ -291,10 +308,9 @@ function setEventHandler(el: Element, name: string, next: any, prev: any): void
|
|
|
291
308
|
// Re-bind if the effective DOM event changed (e.g. <input> whose `type`
|
|
292
309
|
// flipped from "text" to "checkbox" — onChange should now follow `change`
|
|
293
310
|
// instead of `input`). This is rare but keeps semantics correct.
|
|
294
|
-
if (existing.event !== eventName
|
|
295
|
-
el.removeEventListener(existing.event, existing.listener,
|
|
311
|
+
if (existing.event !== eventName) {
|
|
312
|
+
el.removeEventListener(existing.event, existing.listener, capture)
|
|
296
313
|
existing.event = eventName
|
|
297
|
-
existing.capture = capture
|
|
298
314
|
el.addEventListener(eventName, existing.listener, capture)
|
|
299
315
|
}
|
|
300
316
|
existing.current = next
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FiberTag, type Fiber } from '../core'
|
|
2
|
+
|
|
3
|
+
export function componentStack(fiber: Fiber | null): string {
|
|
4
|
+
let stack = ''
|
|
5
|
+
for (; fiber; fiber = fiber.parent) {
|
|
6
|
+
let type = fiber.type
|
|
7
|
+
while (type && typeof type === 'object') type = type.type || type.render
|
|
8
|
+
const name = typeof type === 'string' ? type
|
|
9
|
+
: typeof type === 'function' ? type.displayName || type.name || 'Anonymous'
|
|
10
|
+
: fiber.tag === FiberTag.Suspense ? 'Suspense'
|
|
11
|
+
: fiber.tag === FiberTag.Activity ? 'Activity' : ''
|
|
12
|
+
if (name) stack += '\n at ' + name
|
|
13
|
+
}
|
|
14
|
+
return stack
|
|
15
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { FiberTag, type Fiber } from '../../../core'
|
|
2
|
+
import { REACT_ACTIVITY_TYPE } from '../../../react/activity'
|
|
3
|
+
import { onCommitRollback, queueMutation } from '../../commit'
|
|
4
|
+
import { retainedEffects as effects, inSuspensePrimary, setLayoutDisconnected, walkRetained as walk } from '../../retained-effects'
|
|
5
|
+
import {
|
|
6
|
+
attachRef,
|
|
7
|
+
childrenToArray,
|
|
8
|
+
detachRef,
|
|
9
|
+
enqueueEffect,
|
|
10
|
+
findRoot,
|
|
11
|
+
flushFiberCommits,
|
|
12
|
+
getCurrentRoot,
|
|
13
|
+
handleCommitError,
|
|
14
|
+
installCapability,
|
|
15
|
+
reconcileChildren,
|
|
16
|
+
registerRenderer,
|
|
17
|
+
registerTypeMatcher,
|
|
18
|
+
scheduleLifecycle,
|
|
19
|
+
scheduleUpdate,
|
|
20
|
+
} from '../../reconcile'
|
|
21
|
+
|
|
22
|
+
// Retain effect descriptions, not subscriptions, while a subtree is hidden.
|
|
23
|
+
// Weak keys keep this bookkeeping out of fibers that do not use Activity.
|
|
24
|
+
const disconnected = new WeakSet<Fiber>()
|
|
25
|
+
const hiddenDoms = new WeakSet<Fiber>()
|
|
26
|
+
|
|
27
|
+
function setMembership(set: WeakSet<Fiber>, fiber: Fiber, present: boolean): boolean {
|
|
28
|
+
const previous = set.has(fiber)
|
|
29
|
+
if (previous === present) return previous
|
|
30
|
+
onCommitRollback(() => { if (previous) set.add(fiber); else set.delete(fiber) })
|
|
31
|
+
if (present) set.add(fiber)
|
|
32
|
+
else set.delete(fiber)
|
|
33
|
+
return previous
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isHidden(fiber: Fiber): boolean {
|
|
37
|
+
if (!(fiber.root ?? findRoot(fiber))?.a) return false
|
|
38
|
+
for (let parent: Fiber | null = fiber; parent; parent = parent.parent) {
|
|
39
|
+
if (parent.tag === FiberTag.Activity && parent.pp?.mode === 'hidden') return true
|
|
40
|
+
}
|
|
41
|
+
return false
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function report(fiber: Fiber, fn: () => void): void {
|
|
45
|
+
try { fn() } catch (error) { handleCommitError(fiber, error) }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function disconnect(fiber: Fiber): void {
|
|
49
|
+
if (disconnected.has(fiber)) return
|
|
50
|
+
setMembership(disconnected, fiber, true)
|
|
51
|
+
queueMutation(() => {
|
|
52
|
+
// Insertion effects remain connected, just as they do in React.
|
|
53
|
+
const insertion = new Set<() => void>()
|
|
54
|
+
for (const [hook, effect] of effects.get(fiber) ?? []) {
|
|
55
|
+
if (effect.t === 2 && hook.c) insertion.add(hook.c)
|
|
56
|
+
}
|
|
57
|
+
if (fiber.cu) {
|
|
58
|
+
const keep = fiber.cu.filter(cleanup => insertion.has(cleanup))
|
|
59
|
+
for (const cleanup of fiber.cu) {
|
|
60
|
+
if (!insertion.has(cleanup)) report(fiber, cleanup)
|
|
61
|
+
}
|
|
62
|
+
fiber.cu = keep.length ? keep : null
|
|
63
|
+
}
|
|
64
|
+
for (const [hook, effect] of effects.get(fiber) ?? []) {
|
|
65
|
+
if (effect.t !== 2) hook.c = null
|
|
66
|
+
}
|
|
67
|
+
detachRef(fiber.cr ?? fiber.ref)
|
|
68
|
+
fiber.cr = null
|
|
69
|
+
fiber.rc = null
|
|
70
|
+
const instance = fiber.sn?._fiber === fiber ? fiber.sn : null
|
|
71
|
+
if (!fiber.ld && instance?.componentWillUnmount) {
|
|
72
|
+
const props = instance.props, state = instance.state, committed = fiber.ms?.c
|
|
73
|
+
if (committed) { instance.props = committed.props; instance.state = committed.state }
|
|
74
|
+
try { report(fiber, () => instance.componentWillUnmount()) }
|
|
75
|
+
finally { instance.props = props; instance.state = state }
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function prepare(fiber: Fiber): void {
|
|
81
|
+
if (!isHidden(fiber) || disconnected.has(fiber)) return
|
|
82
|
+
if (fiber.mp == null) setMembership(disconnected, fiber, true)
|
|
83
|
+
else disconnect(fiber)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function needsHiddenDom(fiber: Fiber): boolean {
|
|
87
|
+
for (let parent = fiber.parent; parent; parent = parent.parent) {
|
|
88
|
+
if (parent.tag === FiberTag.Activity && parent.pp?.mode === 'hidden') return true
|
|
89
|
+
if (parent.tag === FiberTag.Host) return false
|
|
90
|
+
// A portal starts a new DOM tree, but keeps the parent's Activity state.
|
|
91
|
+
if (parent.tag === FiberTag.Portal) return isHidden(parent)
|
|
92
|
+
}
|
|
93
|
+
return false
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function syncDom(fiber: Fiber): void {
|
|
97
|
+
if (!(fiber.root ?? findRoot(fiber))?.a) return
|
|
98
|
+
if (!fiber.dom || (fiber.tag !== FiberTag.Host && fiber.tag !== FiberTag.Text)) return
|
|
99
|
+
if (needsHiddenDom(fiber)) {
|
|
100
|
+
setMembership(hiddenDoms, fiber, true)
|
|
101
|
+
queueMutation(() => {
|
|
102
|
+
if (fiber.tag === FiberTag.Text) fiber.dom!.nodeValue = ''
|
|
103
|
+
else (fiber.dom as HTMLElement).style.setProperty('display', 'none', 'important')
|
|
104
|
+
})
|
|
105
|
+
} else if (setMembership(hiddenDoms, fiber, false)) {
|
|
106
|
+
// A Suspense fallback can remain active after its Activity is revealed.
|
|
107
|
+
// Its preserved primary DOM must stay hidden until that boundary resumes.
|
|
108
|
+
for (let parent = fiber.parent; parent; parent = parent.parent) {
|
|
109
|
+
if (parent.tag === FiberTag.Suspense && parent.ms?.d?.some(([node]: [Node, string]) => node === fiber.dom)) return
|
|
110
|
+
}
|
|
111
|
+
const props = fiber.pp
|
|
112
|
+
queueMutation(() => {
|
|
113
|
+
if (fiber.tag === FiberTag.Text) fiber.dom!.nodeValue = props
|
|
114
|
+
else {
|
|
115
|
+
const display = props?.style?.display
|
|
116
|
+
;(fiber.dom as HTMLElement).style.display = display == null || typeof display === 'boolean' ? '' : ('' + display).trim()
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function reconnect(fiber: Fiber): void {
|
|
123
|
+
syncDom(fiber)
|
|
124
|
+
if (isHidden(fiber) || inSuspensePrimary(fiber) || !setMembership(disconnected, fiber, false)) return
|
|
125
|
+
setLayoutDisconnected(fiber, false)
|
|
126
|
+
const instance = fiber.sn?._fiber === fiber ? fiber.sn : null
|
|
127
|
+
if (fiber.tag === FiberTag.Host || fiber.tag === FiberTag.Resource) attachRef(fiber, fiber.dom)
|
|
128
|
+
else if (instance || fiber.tag === FiberTag.Fragment) attachRef(fiber, fiber.sn)
|
|
129
|
+
for (const effect of effects.get(fiber)?.values() ?? []) {
|
|
130
|
+
if (effect.t !== 2) enqueueEffect(fiber, effect)
|
|
131
|
+
}
|
|
132
|
+
if (instance?.componentDidMount) {
|
|
133
|
+
scheduleLifecycle(fiber, () => instance.componentDidMount())
|
|
134
|
+
}
|
|
135
|
+
flushFiberCommits(fiber)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function finish(fiber: Fiber): void {
|
|
139
|
+
if (fiber.tag === FiberTag.Suspense && (fiber.root ?? findRoot(fiber))?.a) walk(fiber, reconnect, true)
|
|
140
|
+
else syncDom(fiber)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function renderActivity(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
144
|
+
const root = fiber.root ?? findRoot(fiber)
|
|
145
|
+
if (root) root.a = true
|
|
146
|
+
const props = fiber.pp ?? {}
|
|
147
|
+
// Hidden content is absent from server HTML. Mount it after hydration so it
|
|
148
|
+
// cannot consume a following visible sibling's hydration cursor.
|
|
149
|
+
if (getCurrentRoot()?.h && props.mode === 'hidden' && !fiber.mp) {
|
|
150
|
+
fiber.mp = props
|
|
151
|
+
queueMicrotask(() => scheduleUpdate(fiber))
|
|
152
|
+
return
|
|
153
|
+
}
|
|
154
|
+
if (isHidden(fiber)) walk(fiber, prepare)
|
|
155
|
+
else walk(fiber, syncDom)
|
|
156
|
+
reconcileChildren(fiber, childrenToArray(props.children), domParent, anchor)
|
|
157
|
+
walk(fiber, reconnect, true)
|
|
158
|
+
fiber.mp = props
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
installCapability('isActivityHidden', isHidden)
|
|
162
|
+
installCapability('activityIsDisconnected', fiber => disconnected.has(fiber))
|
|
163
|
+
installCapability('prepareActivityFiber', prepare)
|
|
164
|
+
installCapability('syncActivity', finish)
|
|
165
|
+
registerTypeMatcher(type => type === REACT_ACTIVITY_TYPE ? FiberTag.Activity : null)
|
|
166
|
+
registerRenderer(FiberTag.Activity, renderActivity)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './full'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FiberTag, type Fiber } from '../../../core'
|
|
2
|
+
import { REACT_ACTIVITY_TYPE } from '../../../react/activity'
|
|
3
|
+
import { childrenToArray, reconcileChildren, registerRenderer, registerTypeMatcher } from '../../reconcile'
|
|
4
|
+
|
|
5
|
+
// Explicit small-preset downgrade: hidden children unmount instead of being
|
|
6
|
+
// retained. Showing them again creates fresh state, DOM, effects, and refs.
|
|
7
|
+
function renderActivity(fiber: Fiber, parent: Node, anchor: Node | null): void {
|
|
8
|
+
const props = fiber.pp ?? {}
|
|
9
|
+
reconcileChildren(fiber, props.mode === 'hidden' ? [] : childrenToArray(props.children), parent, anchor)
|
|
10
|
+
fiber.mp = props
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
registerTypeMatcher(type => type === REACT_ACTIVITY_TYPE ? FiberTag.Activity : null)
|
|
14
|
+
registerRenderer(FiberTag.Activity, renderActivity)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FiberTag, type Fiber, type ReactNode } from '../../../core'
|
|
2
|
+
import { checkpointCommit, rewindCommit, queueBeforeMutation, queueMutation } from '../../commit'
|
|
2
3
|
import {
|
|
3
4
|
registerRenderer,
|
|
4
5
|
reconcileChildren,
|
|
@@ -8,17 +9,30 @@ import {
|
|
|
8
9
|
isThenable,
|
|
9
10
|
handleSuspended,
|
|
10
11
|
handleErrorInRender,
|
|
12
|
+
readContext,
|
|
13
|
+
attachRef,
|
|
14
|
+
syncRefIfChanged,
|
|
15
|
+
isActivityHidden,
|
|
16
|
+
layoutIsDisconnected,
|
|
17
|
+
RenderErrorCapture,
|
|
18
|
+
handleCommitError,
|
|
11
19
|
} from '../../reconcile'
|
|
12
20
|
|
|
13
21
|
function renderClass(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
22
|
+
fiber.cx?.clear()
|
|
14
23
|
const Ctor = fiber.type as any
|
|
15
24
|
let instance = fiber.sn
|
|
16
25
|
const props = fiber.pp ?? {}
|
|
17
26
|
const isNew = !instance
|
|
27
|
+
const previous = fiber.ms?.c
|
|
28
|
+
let didRender = true
|
|
29
|
+
let captured = fiber.ms?.error instanceof RenderErrorCapture ? fiber.ms.error as RenderErrorCapture : undefined
|
|
30
|
+
if (captured) delete fiber.ms.error
|
|
18
31
|
|
|
19
32
|
// Class contextType: read the current value of the subscribed context so
|
|
20
33
|
// `this.context` reflects the nearest Provider. Evaluated every render.
|
|
21
|
-
const ctxValue = Ctor.contextType ? Ctor.contextType
|
|
34
|
+
const ctxValue = Ctor.contextType ? readContext(fiber, Ctor.contextType) : undefined
|
|
35
|
+
const contextChanged = instance && !Object.is(instance.context, ctxValue)
|
|
22
36
|
|
|
23
37
|
if (isNew) {
|
|
24
38
|
instance = new Ctor(props, ctxValue)
|
|
@@ -47,39 +61,31 @@ function renderClass(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
|
47
61
|
if (d) instance.state = { ...instance.state, ...d }
|
|
48
62
|
}
|
|
49
63
|
} else {
|
|
50
|
-
const prevProps = instance.props
|
|
51
|
-
const prevState = instance.state
|
|
52
64
|
// Refresh context on every render — Providers higher up may have changed.
|
|
53
65
|
instance.context = ctxValue
|
|
54
66
|
if (Ctor.getDerivedStateFromProps) {
|
|
55
67
|
const d = Ctor.getDerivedStateFromProps(props, instance.state)
|
|
56
68
|
if (d) instance.state = { ...instance.state, ...d }
|
|
57
69
|
}
|
|
58
|
-
if (instance.shouldComponentUpdate) {
|
|
70
|
+
if (!captured && instance.shouldComponentUpdate && !contextChanged) {
|
|
59
71
|
if (!instance.shouldComponentUpdate(props, instance.state, instance.context)) {
|
|
60
|
-
|
|
61
|
-
fiber.mp = props
|
|
62
|
-
// Still need to render children with previous output
|
|
63
|
-
if (fiber.ms?.r) {
|
|
64
|
-
reconcileChildren(fiber, childrenToArray(fiber.ms.r), domParent, anchor)
|
|
65
|
-
}
|
|
66
|
-
return
|
|
72
|
+
didRender = false
|
|
67
73
|
}
|
|
68
74
|
}
|
|
69
75
|
instance.props = props
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
}
|
|
77
|
+
if (captured && Ctor.getDerivedStateFromError) {
|
|
78
|
+
const update = Ctor.getDerivedStateFromError(captured.error)
|
|
79
|
+
if (update != null) instance.state = { ...instance.state, ...update }
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
let rendered: ReactNode
|
|
77
83
|
try {
|
|
78
|
-
rendered = instance.render()
|
|
84
|
+
rendered = captured && !Ctor.getDerivedStateFromError ? null : didRender ? instance.render() : fiber.ms?.r
|
|
79
85
|
} catch (e: any) {
|
|
80
86
|
if (isThenable(e)) {
|
|
81
87
|
handleSuspended(fiber, e)
|
|
82
|
-
|
|
88
|
+
return
|
|
83
89
|
} else {
|
|
84
90
|
handleErrorInRender(fiber, e)
|
|
85
91
|
return
|
|
@@ -87,24 +93,62 @@ function renderClass(fiber: Fiber, domParent: Node, anchor: Node | null): void {
|
|
|
87
93
|
}
|
|
88
94
|
fiber.ms = { ...(fiber.ms ?? {}), r: rendered }
|
|
89
95
|
|
|
90
|
-
|
|
96
|
+
const canCatch = Ctor.getDerivedStateFromError || instance.componentDidCatch
|
|
97
|
+
if (canCatch) fiber.ms.b = Ctor
|
|
98
|
+
if (canCatch && fiber.root) fiber.root.eb = true
|
|
99
|
+
const checkpoint = canCatch ? checkpointCommit(fiber) : -1
|
|
100
|
+
try {
|
|
101
|
+
reconcileChildren(fiber, childrenToArray(rendered), domParent, anchor)
|
|
102
|
+
} catch (error) {
|
|
103
|
+
if (!(error instanceof RenderErrorCapture) || error.boundary !== fiber) throw error
|
|
104
|
+
rewindCommit(checkpoint)
|
|
105
|
+
captured = error
|
|
106
|
+
didRender = true
|
|
107
|
+
if (Ctor.getDerivedStateFromError) {
|
|
108
|
+
const update = Ctor.getDerivedStateFromError(error.error)
|
|
109
|
+
if (update != null) instance.state = { ...instance.state, ...update }
|
|
110
|
+
try { rendered = instance.render() } catch (fallbackError) {
|
|
111
|
+
handleErrorInRender(fiber, fallbackError)
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
} else rendered = null
|
|
115
|
+
fiber.ms = { ...(fiber.ms ?? {}), r: rendered }
|
|
116
|
+
reconcileChildren(fiber, childrenToArray(rendered), domParent, anchor)
|
|
117
|
+
}
|
|
91
118
|
fiber.mp = props
|
|
119
|
+
const state = instance.state
|
|
120
|
+
queueMutation(() => { fiber.ms.c = { props, state } })
|
|
121
|
+
|
|
122
|
+
if (isNew) attachRef(fiber, instance)
|
|
123
|
+
else syncRefIfChanged(fiber, instance)
|
|
92
124
|
|
|
93
125
|
// Schedule lifecycle
|
|
94
126
|
if (isNew) {
|
|
95
|
-
if (instance.componentDidMount
|
|
96
|
-
scheduleLifecycle(fiber, () =>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
127
|
+
if (instance.componentDidMount) {
|
|
128
|
+
scheduleLifecycle(fiber, () => instance.componentDidMount())
|
|
129
|
+
}
|
|
130
|
+
} else if (previous && didRender) {
|
|
131
|
+
let snapshot: any
|
|
132
|
+
if (instance.getSnapshotBeforeUpdate && !layoutIsDisconnected(fiber)) {
|
|
133
|
+
queueBeforeMutation(() => {
|
|
134
|
+
if (!fiber.um && !fiber.pd && !isActivityHidden(fiber) && !layoutIsDisconnected(fiber)) {
|
|
135
|
+
try { snapshot = instance.getSnapshotBeforeUpdate(previous.props, previous.state) }
|
|
136
|
+
catch (error) { handleCommitError(fiber, error) }
|
|
101
137
|
}
|
|
102
|
-
instance.componentDidMount?.()
|
|
103
138
|
})
|
|
104
139
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
140
|
+
if (instance.componentDidUpdate) {
|
|
141
|
+
scheduleLifecycle(fiber, () => instance.componentDidUpdate(previous.props, previous.state, snapshot))
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (captured) {
|
|
145
|
+
const error = captured.error
|
|
146
|
+
const info = { componentStack: captured.stack }
|
|
147
|
+
scheduleLifecycle(fiber, () => {
|
|
148
|
+
try { fiber.root?.ce?.(error, { ...info, errorBoundary: instance }) }
|
|
149
|
+
catch (callbackError) { setTimeout(() => { throw callbackError }) }
|
|
150
|
+
instance.componentDidCatch?.(error, info)
|
|
151
|
+
})
|
|
108
152
|
}
|
|
109
153
|
}
|
|
110
154
|
|