@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.
Files changed (253) hide show
  1. package/dist/core/attributes.js +2 -1
  2. package/dist/core/attributes.js.map +2 -2
  3. package/dist/core/browser.d.ts +9 -0
  4. package/dist/core/browser.js +35 -0
  5. package/dist/core/browser.js.map +7 -0
  6. package/dist/core/index.d.ts +2 -2
  7. package/dist/core/index.js +3 -3
  8. package/dist/core/internal.d.ts +31 -8
  9. package/dist/core/internal.js +3 -1
  10. package/dist/core/internal.js.map +2 -2
  11. package/dist/core/resource-hints.d.ts +7 -0
  12. package/dist/core/resource-hints.js +19 -0
  13. package/dist/core/resource-hints.js.map +7 -0
  14. package/dist/core/types.js +1 -1
  15. package/dist/dom/_all.d.ts +11 -16
  16. package/dist/dom/_all.js +9 -20
  17. package/dist/dom/_all.js.map +2 -2
  18. package/dist/dom/client.d.ts +4 -4
  19. package/dist/dom/client.js +4 -4
  20. package/dist/dom/commit.d.ts +23 -0
  21. package/dist/dom/commit.js +191 -0
  22. package/dist/dom/commit.js.map +7 -0
  23. package/dist/dom/dispatcher.d.ts +4 -22
  24. package/dist/dom/dispatcher.js +184 -126
  25. package/dist/dom/dispatcher.js.map +3 -3
  26. package/dist/dom/dom.d.ts +2 -0
  27. package/dist/dom/dom.js +72 -52
  28. package/dist/dom/dom.js.map +2 -2
  29. package/dist/dom/error-info.d.ts +2 -0
  30. package/dist/dom/error-info.js +16 -0
  31. package/dist/dom/error-info.js.map +7 -0
  32. package/dist/dom/event-replay.js +1 -1
  33. package/dist/dom/features/activity/full.d.ts +1 -0
  34. package/dist/dom/features/activity/full.js +162 -0
  35. package/dist/dom/features/activity/full.js.map +7 -0
  36. package/dist/dom/features/activity/index.d.ts +1 -0
  37. package/dist/dom/features/activity/index.js +3 -0
  38. package/dist/dom/features/activity/index.js.map +7 -0
  39. package/dist/dom/features/activity/stub.d.ts +1 -0
  40. package/dist/dom/features/activity/stub.js +12 -0
  41. package/dist/dom/features/activity/stub.js.map +7 -0
  42. package/dist/dom/features/class/full.js +87 -21
  43. package/dist/dom/features/class/full.js.map +2 -2
  44. package/dist/dom/features/class/index.d.ts +1 -1
  45. package/dist/dom/features/class/index.js +2 -2
  46. package/dist/dom/features/class/stub.js +3 -3
  47. package/dist/dom/features/context/full.d.ts +4 -1
  48. package/dist/dom/features/context/full.js +69 -9
  49. package/dist/dom/features/context/full.js.map +2 -2
  50. package/dist/dom/features/context/index.d.ts +1 -1
  51. package/dist/dom/features/context/index.js +2 -2
  52. package/dist/dom/features/context/stub.d.ts +4 -1
  53. package/dist/dom/features/context/stub.js +15 -4
  54. package/dist/dom/features/context/stub.js.map +2 -2
  55. package/dist/dom/features/forward-ref/full.js +12 -21
  56. package/dist/dom/features/forward-ref/full.js.map +2 -2
  57. package/dist/dom/features/forward-ref/index.d.ts +1 -1
  58. package/dist/dom/features/forward-ref/index.js +2 -2
  59. package/dist/dom/features/forward-ref/stub.js +4 -4
  60. package/dist/dom/features/fragment-refs/index.d.ts +1 -0
  61. package/dist/dom/features/fragment-refs/index.js +8 -0
  62. package/dist/dom/features/fragment-refs/index.js.map +7 -0
  63. package/dist/dom/features/fragment-refs/stub.d.ts +3 -0
  64. package/dist/dom/features/fragment-refs/stub.js +14 -0
  65. package/dist/dom/features/fragment-refs/stub.js.map +7 -0
  66. package/dist/dom/features/hydration/full.d.ts +11 -6
  67. package/dist/dom/features/hydration/full.js +76 -76
  68. package/dist/dom/features/hydration/full.js.map +2 -2
  69. package/dist/dom/features/hydration/index.d.ts +1 -1
  70. package/dist/dom/features/hydration/index.js +2 -2
  71. package/dist/dom/features/hydration/stub.d.ts +7 -2
  72. package/dist/dom/features/hydration/stub.js +1 -1
  73. package/dist/dom/features/hydration/stub.js.map +1 -1
  74. package/dist/dom/features/index.d.ts +8 -7
  75. package/dist/dom/features/index.js +9 -8
  76. package/dist/dom/features/index.js.map +2 -2
  77. package/dist/dom/features/lazy/full.js +4 -4
  78. package/dist/dom/features/lazy/index.d.ts +1 -1
  79. package/dist/dom/features/lazy/index.js +2 -2
  80. package/dist/dom/features/lazy/stub.js +4 -4
  81. package/dist/dom/features/memo/full.js +8 -6
  82. package/dist/dom/features/memo/full.js.map +2 -2
  83. package/dist/dom/features/memo/index.d.ts +1 -1
  84. package/dist/dom/features/memo/index.js +2 -2
  85. package/dist/dom/features/memo/stub.js +4 -4
  86. package/dist/dom/features/portal/full.js +4 -4
  87. package/dist/dom/features/portal/index.d.ts +1 -1
  88. package/dist/dom/features/portal/index.js +2 -2
  89. package/dist/dom/features/portal/stub.js +4 -4
  90. package/dist/dom/features/suspense/full.js +192 -47
  91. package/dist/dom/features/suspense/full.js.map +2 -2
  92. package/dist/dom/features/suspense/index.d.ts +1 -1
  93. package/dist/dom/features/suspense/index.js +2 -2
  94. package/dist/dom/features/suspense/stub.js +4 -4
  95. package/dist/dom/features/view-transition/full.d.ts +6 -0
  96. package/dist/dom/features/view-transition/full.js +280 -0
  97. package/dist/dom/features/view-transition/full.js.map +7 -0
  98. package/dist/dom/features/view-transition/index.d.ts +1 -0
  99. package/dist/dom/features/view-transition/index.js +3 -0
  100. package/dist/dom/features/view-transition/index.js.map +7 -0
  101. package/dist/dom/features/view-transition/resources.d.ts +11 -0
  102. package/dist/dom/features/view-transition/resources.js +108 -0
  103. package/dist/dom/features/view-transition/resources.js.map +7 -0
  104. package/dist/dom/features/view-transition/stub.d.ts +6 -0
  105. package/dist/dom/features/view-transition/stub.js +22 -0
  106. package/dist/dom/features/view-transition/stub.js.map +7 -0
  107. package/dist/dom/features/view-transition/visual.d.ts +14 -0
  108. package/dist/dom/features/view-transition/visual.js +356 -0
  109. package/dist/dom/features/view-transition/visual.js.map +7 -0
  110. package/dist/dom/fragment-instance.d.ts +40 -0
  111. package/dist/dom/fragment-instance.js +324 -0
  112. package/dist/dom/fragment-instance.js.map +7 -0
  113. package/dist/dom/index.d.ts +11 -11
  114. package/dist/dom/index.js +11 -18
  115. package/dist/dom/index.js.map +3 -3
  116. package/dist/dom/portal.d.ts +2 -2
  117. package/dist/dom/portal.js +2 -2
  118. package/dist/dom/portal.js.map +1 -1
  119. package/dist/dom/reconcile.d.ts +32 -3
  120. package/dist/dom/reconcile.js +686 -222
  121. package/dist/dom/reconcile.js.map +2 -2
  122. package/dist/dom/resource-hints.d.ts +6 -0
  123. package/dist/dom/resource-hints.js +115 -0
  124. package/dist/dom/resource-hints.js.map +7 -0
  125. package/dist/dom/resource-store.d.ts +13 -0
  126. package/dist/dom/resource-store.js +43 -0
  127. package/dist/dom/resource-store.js.map +7 -0
  128. package/dist/dom/resources.d.ts +1 -0
  129. package/dist/dom/resources.js +44 -0
  130. package/dist/dom/resources.js.map +7 -0
  131. package/dist/dom/retained-effects.d.ts +6 -0
  132. package/dist/dom/retained-effects.js +49 -0
  133. package/dist/dom/retained-effects.js.map +7 -0
  134. package/dist/dom/root-internal.d.ts +4 -4
  135. package/dist/dom/root-internal.js +2 -2
  136. package/dist/dom/root-internal.js.map +2 -2
  137. package/dist/dom/root.d.ts +5 -5
  138. package/dist/dom/root.js +11 -11
  139. package/dist/dom/root.js.map +2 -2
  140. package/dist/dom/test-utils.js +1 -1
  141. package/dist/react/activity.d.ts +7 -0
  142. package/dist/react/activity.js +8 -0
  143. package/dist/react/activity.js.map +7 -0
  144. package/dist/react/children.d.ts +1 -1
  145. package/dist/react/children.js +3 -3
  146. package/dist/react/children.js.map +1 -1
  147. package/dist/react/class.d.ts +1 -1
  148. package/dist/react/class.js +3 -3
  149. package/dist/react/class.js.map +1 -1
  150. package/dist/react/compiler-runtime.js +2 -2
  151. package/dist/react/context.d.ts +1 -1
  152. package/dist/react/context.js +3 -3
  153. package/dist/react/context.js.map +1 -1
  154. package/dist/react/element.d.ts +6 -3
  155. package/dist/react/element.js +2 -2
  156. package/dist/react/element.js.map +2 -2
  157. package/dist/react/hooks.d.ts +26 -7
  158. package/dist/react/hooks.js +13 -3
  159. package/dist/react/hooks.js.map +2 -2
  160. package/dist/react/index.d.ts +39 -24
  161. package/dist/react/index.js +39 -19
  162. package/dist/react/index.js.map +3 -3
  163. package/dist/react/jsx-runtime.d.ts +2 -2
  164. package/dist/react/jsx-runtime.js +3 -3
  165. package/dist/react/memo.d.ts +1 -1
  166. package/dist/react/memo.js +1 -1
  167. package/dist/react/portal.js +1 -1
  168. package/dist/react/shared-internals.d.ts +15 -5
  169. package/dist/react/shared-internals.js +2 -3
  170. package/dist/react/shared-internals.js.map +2 -2
  171. package/dist/react/suspense.js +1 -1
  172. package/dist/react/view-transition.d.ts +32 -0
  173. package/dist/react/view-transition.js +13 -0
  174. package/dist/react/view-transition.js.map +7 -0
  175. package/dist/scheduler/index.js +1 -1
  176. package/dist/server/bootstrap-script.d.ts +1 -23
  177. package/dist/server/bootstrap-script.js +7 -6
  178. package/dist/server/bootstrap-script.js.map +2 -2
  179. package/dist/server/dispatcher.d.ts +28 -6
  180. package/dist/server/dispatcher.js +33 -15
  181. package/dist/server/dispatcher.js.map +2 -2
  182. package/dist/server/escape.js +16 -15
  183. package/dist/server/escape.js.map +2 -2
  184. package/dist/server/index.d.ts +6 -6
  185. package/dist/server/index.js +7 -7
  186. package/dist/server/renderToString.d.ts +1 -1
  187. package/dist/server/renderToString.js +12 -8
  188. package/dist/server/renderToString.js.map +2 -2
  189. package/dist/server/resource-hints.d.ts +22 -0
  190. package/dist/server/resource-hints.js +148 -0
  191. package/dist/server/resource-hints.js.map +7 -0
  192. package/dist/server/stream.d.ts +15 -2
  193. package/dist/server/stream.js +155 -63
  194. package/dist/server/stream.js.map +2 -2
  195. package/dist/server/walk.d.ts +15 -2
  196. package/dist/server/walk.js +143 -96
  197. package/dist/server/walk.js.map +2 -2
  198. package/dist/vite/index.d.ts +6 -0
  199. package/dist/vite/index.js +22 -6
  200. package/dist/vite/index.js.map +2 -2
  201. package/package.json +1 -1
  202. package/src/core/attributes.ts +1 -0
  203. package/src/core/browser.ts +33 -0
  204. package/src/core/internal.ts +24 -6
  205. package/src/core/resource-hints.ts +36 -0
  206. package/src/dom/_all.ts +1 -7
  207. package/src/dom/commit.ts +186 -0
  208. package/src/dom/dispatcher.ts +190 -134
  209. package/src/dom/dom.ts +70 -54
  210. package/src/dom/error-info.ts +15 -0
  211. package/src/dom/features/activity/full.ts +166 -0
  212. package/src/dom/features/activity/index.ts +1 -0
  213. package/src/dom/features/activity/stub.ts +14 -0
  214. package/src/dom/features/class/full.ts +72 -21
  215. package/src/dom/features/context/full.ts +66 -4
  216. package/src/dom/features/context/stub.ts +6 -0
  217. package/src/dom/features/forward-ref/full.ts +9 -19
  218. package/src/dom/features/fragment-refs/index.ts +1 -0
  219. package/src/dom/features/fragment-refs/stub.ts +3 -0
  220. package/src/dom/features/hydration/full.ts +84 -82
  221. package/src/dom/features/hydration/stub.ts +1 -1
  222. package/src/dom/features/index.ts +1 -0
  223. package/src/dom/features/memo/full.ts +4 -3
  224. package/src/dom/features/suspense/full.ts +187 -50
  225. package/src/dom/features/view-transition/full.ts +288 -0
  226. package/src/dom/features/view-transition/index.ts +1 -0
  227. package/src/dom/features/view-transition/resources.ts +107 -0
  228. package/src/dom/features/view-transition/stub.ts +7 -0
  229. package/src/dom/features/view-transition/visual.ts +406 -0
  230. package/src/dom/fragment-instance.ts +337 -0
  231. package/src/dom/index.ts +6 -7
  232. package/src/dom/portal.ts +1 -1
  233. package/src/dom/reconcile.ts +691 -244
  234. package/src/dom/resource-hints.ts +115 -0
  235. package/src/dom/resource-store.ts +52 -0
  236. package/src/dom/resources.ts +39 -0
  237. package/src/dom/retained-effects.ts +38 -0
  238. package/src/dom/root-internal.ts +4 -4
  239. package/src/dom/root.ts +12 -14
  240. package/src/react/activity.ts +10 -0
  241. package/src/react/element.ts +6 -2
  242. package/src/react/hooks.ts +12 -3
  243. package/src/react/index.ts +18 -0
  244. package/src/react/shared-internals.ts +3 -3
  245. package/src/react/view-transition.ts +41 -0
  246. package/src/server/bootstrap-script.ts +36 -5
  247. package/src/server/dispatcher.ts +35 -13
  248. package/src/server/escape.ts +15 -12
  249. package/src/server/renderToString.ts +7 -5
  250. package/src/server/resource-hints.ts +165 -0
  251. package/src/server/stream.ts +154 -62
  252. package/src/server/walk.ts +72 -11
  253. package/src/vite/index.ts +30 -13
@@ -0,0 +1,288 @@
1
+ import type { FiberRoot } from '../../../core'
2
+ import { ReactSharedInternals } from '../../../react/shared-internals'
3
+ import { currentCommit, prepareCommit, commitBeforeMutation, commitMutation, commitSynchronously, type CommitPlan } from '../../commit'
4
+ import { prepareViewTransition } from './visual'
5
+ import { recoverRootError } from '../../reconcile'
6
+
7
+ type Work = { commit: () => void; scopes: Set<Set<string>> }
8
+ type Visual = NonNullable<ReturnType<typeof prepareViewTransition>>
9
+ interface Transaction {
10
+ native?: ViewTransition
11
+ visual: Visual
12
+ work: Map<FiberRoot, Work>
13
+ layout: Array<() => void>
14
+ passive: Array<() => void>
15
+ consumed: boolean
16
+ cancelled: boolean
17
+ ready: boolean
18
+ plans: CommitPlan[]
19
+ preparing: boolean
20
+ }
21
+ interface Coordinator {
22
+ queued: Map<FiberRoot, Work>
23
+ active?: Transaction | undefined
24
+ flush: () => void
25
+ scheduled: boolean
26
+ }
27
+
28
+ const marks = new Map<FiberRoot, Set<Set<string>> | null>()
29
+ const documents = new Map<Document, Coordinator>()
30
+ let committing: Transaction | undefined
31
+
32
+ function ownerDocument(root: FiberRoot): Document {
33
+ return root.c.nodeType === 9 ? root.c as unknown as Document : root.c.ownerDocument!
34
+ }
35
+
36
+ function drain(queue: Array<() => void>): void {
37
+ while (queue.length) queue.shift()!()
38
+ }
39
+
40
+ function passive(transaction: Transaction): void {
41
+ if (transaction.consumed) transaction.visual.restore()
42
+ drain(transaction.passive)
43
+ }
44
+
45
+ function release(doc: Document, coordinator: Coordinator): void {
46
+ if (!coordinator.active && !coordinator.queued.size && documents.get(doc) === coordinator) documents.delete(doc)
47
+ }
48
+
49
+ function render(work: Map<FiberRoot, Work>): void {
50
+ for (const entry of work.values()) entry.commit()
51
+ }
52
+
53
+ function prepareRoot(transaction: Transaction, root: FiberRoot, commit: () => void): void {
54
+ try {
55
+ prepareCommit(() => {
56
+ transaction.plans.push(currentCommit!)
57
+ commit()
58
+ })
59
+ } catch (error) {
60
+ transaction.plans.pop()
61
+ if (!recoverRootError(error)) throw error
62
+ transaction.work.delete(root)
63
+ transaction.visual.exclude(root)
64
+ }
65
+ }
66
+
67
+ function beforeMutation(transaction: Transaction): void {
68
+ for (const plan of transaction.plans) commitBeforeMutation(plan)
69
+ }
70
+
71
+ function mutation(transaction: Transaction): void {
72
+ for (const plan of transaction.plans) commitMutation(plan)
73
+ }
74
+
75
+ export function markTransitionUpdate(root: FiberRoot): void {
76
+ if (committing) return
77
+ const coordinator = documents.size ? documents.get(ownerDocument(root)) : undefined
78
+ if (coordinator?.active) passive(coordinator.active)
79
+ const scope = ReactSharedInternals.T
80
+ if (scope) {
81
+ if (marks.get(root) !== null) {
82
+ let scopes = marks.get(root)
83
+ if (!scopes) marks.set(root, scopes = new Set())
84
+ scopes.add(scope)
85
+ }
86
+ } else {
87
+ if (marks.has(root)) marks.set(root, null)
88
+ if (coordinator) cancel(coordinator)
89
+ }
90
+ }
91
+
92
+ export function deferTransition(root: FiberRoot, commit: () => void, flush: () => void): boolean {
93
+ if (committing?.preparing && !currentCommit && ownerDocument(root) === committing.visual.document) {
94
+ prepareRoot(committing, root, commit)
95
+ return true
96
+ }
97
+ if (!marks.size && !documents.size) return false
98
+ const scopes = marks.get(root)
99
+ marks.delete(root)
100
+ const doc = ownerDocument(root)
101
+ const activeCoordinator = documents.get(doc)
102
+ if (activeCoordinator?.active?.plans.length && !activeCoordinator.active.consumed && !currentCommit) {
103
+ // A reentrant urgent render must consume the already-rendered commit
104
+ // before reconciling another tree against it.
105
+ if (committing || !scopes) cancel(activeCoordinator)
106
+ }
107
+ if (committing || !scopes || !doc.startViewTransition) return false
108
+ let coordinator = documents.get(doc)
109
+ if (!coordinator) {
110
+ coordinator = { queued: new Map(), flush, scheduled: false }
111
+ documents.set(doc, coordinator)
112
+ }
113
+ const existing = coordinator.queued.get(root)
114
+ if (existing) for (const scope of scopes) existing.scopes.add(scope)
115
+ else coordinator.queued.set(root, { commit, scopes })
116
+ kick(doc, coordinator)
117
+ return true
118
+ }
119
+
120
+ function kick(doc: Document, coordinator: Coordinator): void {
121
+ if (coordinator.active || coordinator.scheduled || !coordinator.queued.size) return
122
+ coordinator.scheduled = true
123
+ queueMicrotask(async () => {
124
+ coordinator.scheduled = false
125
+ if (coordinator.active || !coordinator.queued.size) return
126
+ const work = coordinator.queued
127
+ coordinator.queued = new Map()
128
+ const types = new Set<string>()
129
+ for (const entry of work.values()) for (const scope of entry.scopes) for (const type of scope) types.add(type)
130
+ const visual = prepareViewTransition(work.keys(), [...types])
131
+ if (!visual) {
132
+ commitSynchronously(() => render(work))
133
+ release(doc, coordinator)
134
+ return
135
+ }
136
+ const transaction: Transaction = { visual, work, layout: [], passive: [], plans: [], preparing: true, consumed: false, cancelled: false, ready: false }
137
+ coordinator.active = transaction
138
+ try {
139
+ try {
140
+ within(transaction, () => {
141
+ for (const [root, entry] of work) prepareRoot(transaction, root, entry.commit)
142
+ coordinator.flush()
143
+ })
144
+ } finally { transaction.preparing = false }
145
+ const resources = visual.prepare()
146
+ if (resources) await resources
147
+ if (transaction.cancelled) return
148
+ within(transaction, () => beforeMutation(transaction))
149
+ if (!visual.beforeCommit()) {
150
+ cancel(coordinator)
151
+ return
152
+ }
153
+ } catch (error) {
154
+ cancel(coordinator)
155
+ report(transaction, error)
156
+ return
157
+ }
158
+ const update = () => {
159
+ if (transaction.consumed) return
160
+ transaction.consumed = true
161
+ const navigation = (doc.defaultView as any)?.navigation?.transition
162
+ const fonts = doc.fonts
163
+ const wasLoaded = fonts?.status === 'loaded'
164
+ within(transaction, () => {
165
+ mutation(transaction)
166
+ coordinator.flush()
167
+ })
168
+ const finishCommit = () => {
169
+ if (transaction.cancelled) return
170
+ within(transaction, () => { drain(transaction.layout); coordinator.flush() })
171
+ if (navigation) return navigation.finished.catch(() => {}).then(() => {
172
+ if (!transaction.cancelled) visual.afterCommit()
173
+ })
174
+ visual.afterCommit()
175
+ }
176
+ const resources = visual.waitForResources(!!wasLoaded)
177
+ if (resources) return resources.then(finishCommit)
178
+ return finishCommit()
179
+ }
180
+ try {
181
+ const native = transaction.native = doc.startViewTransition({ update, types: [...types] })
182
+ native.updateCallbackDone.catch(error => report(transaction, error))
183
+ native.ready.then(() => {
184
+ if (!transaction.cancelled) {
185
+ transaction.ready = true
186
+ try { visual.ready() } catch (error) { report(transaction, error) }
187
+ }
188
+ }, error => {
189
+ try {
190
+ if (!transaction.cancelled && reportable(error)) {
191
+ const root = transaction.work.keys().next().value
192
+ if (root?.re) root.re(error, { componentStack: null })
193
+ else if (typeof reportError === 'function') reportError(error)
194
+ else queueMicrotask(() => { throw error })
195
+ }
196
+ } finally {
197
+ transaction.cancelled = true
198
+ try { visual.cancel() } finally { consume(transaction) }
199
+ }
200
+ })
201
+ native.finished.then(() => finish(doc, coordinator, transaction), () => finish(doc, coordinator, transaction))
202
+ } catch {
203
+ cancel(coordinator)
204
+ }
205
+ })
206
+ }
207
+
208
+ function reportable(error: unknown): boolean {
209
+ return error !== null && !(error && typeof error === 'object' && 'name' in error && error.name === 'InvalidStateError' &&
210
+ 'message' in error && (
211
+ error.message === 'View transition was skipped because document visibility state is hidden.' ||
212
+ error.message === 'Skipping view transition because document visibility state has become hidden.' ||
213
+ error.message === 'Skipping view transition because viewport size changed.' ||
214
+ error.message === 'Transition was aborted because of invalid state'
215
+ ))
216
+ }
217
+
218
+ function consume(transaction: Transaction): void {
219
+ transaction.consumed = true
220
+ within(transaction, () => {
221
+ beforeMutation(transaction)
222
+ mutation(transaction)
223
+ })
224
+ drain(transaction.layout)
225
+ }
226
+
227
+ function within(transaction: Transaction, work: () => void): void {
228
+ const previous = committing
229
+ committing = transaction
230
+ try { work() } finally { committing = previous }
231
+ }
232
+
233
+ function report(transaction: Transaction, error: unknown): void {
234
+ const root = transaction.work.keys().next().value
235
+ if (root?.ue) root.ue(error, { componentStack: null })
236
+ else queueMicrotask(() => { throw error })
237
+ }
238
+
239
+ function finish(doc: Document, coordinator: Coordinator, transaction: Transaction): void {
240
+ if (coordinator.active === transaction) coordinator.active = undefined
241
+ try { passive(transaction) } catch (error) { report(transaction, error) } finally {
242
+ try { transaction.visual.finish() } catch (error) { report(transaction, error) } finally {
243
+ if (coordinator.queued.size) kick(doc, coordinator)
244
+ else release(doc, coordinator)
245
+ }
246
+ }
247
+ }
248
+
249
+ function cancel(coordinator: Coordinator): void {
250
+ const transaction = coordinator.active
251
+ const queued = coordinator.queued
252
+ const root = queued.keys().next().value
253
+ const doc = transaction?.visual.document ?? (root ? ownerDocument(root) : undefined)
254
+ coordinator.queued = new Map()
255
+ if (transaction) {
256
+ if (!transaction.ready) {
257
+ coordinator.active = undefined
258
+ transaction.cancelled = true
259
+ transaction.native?.skipTransition()
260
+ try { transaction.visual.cancel() } catch (error) { report(transaction, error) }
261
+ }
262
+ consume(transaction)
263
+ passive(transaction)
264
+ }
265
+ commitSynchronously(() => render(queued))
266
+ if (doc) release(doc, coordinator)
267
+ }
268
+
269
+ export function cancelTransitions(): void {
270
+ if (!marks.size && !documents.size) return
271
+ marks.clear()
272
+ for (const [doc, coordinator] of [...documents]) {
273
+ cancel(coordinator)
274
+ release(doc, coordinator)
275
+ }
276
+ }
277
+
278
+ export function deferTransitionLayout(work: () => void): boolean {
279
+ if (!committing) return false
280
+ committing.layout.push(work)
281
+ return true
282
+ }
283
+
284
+ export function deferTransitionPassive(work: () => void): boolean {
285
+ if (!committing) return false
286
+ committing.passive.push(work)
287
+ return true
288
+ }
@@ -0,0 +1 @@
1
+ export * from './full'
@@ -0,0 +1,107 @@
1
+ export type TransitionImages = Map<HTMLImageElement, { src?: unknown; srcSet?: unknown; onLoad?: unknown; loading?: unknown }>
2
+
3
+ let imageBudget = 0
4
+
5
+ function imageBytes(image: HTMLImageElement): number {
6
+ return (image.width || 100) * (image.height || 100) * (image.ownerDocument.defaultView?.devicePixelRatio || 1) * 0.25
7
+ }
8
+
9
+ function staticResource(type: string): boolean {
10
+ return /^(css|script|font|img|image|input|link)$/.test(type)
11
+ }
12
+
13
+ // Match React's estimate from up to eleven groups of overlapping transfers,
14
+ // falling back to the browser's downlink estimate and then 5 Mbps.
15
+ function bandwidth(doc: Document): number {
16
+ const view = doc.defaultView!
17
+ const entries = view.performance.getEntriesByType?.('resource') as PerformanceResourceTiming[] | undefined
18
+ let count = 0, bits = 0
19
+ for (let i = 0; entries && i < entries.length; i++) {
20
+ const entry = entries[i]!
21
+ if (!entry.transferSize || !entry.duration || !staticResource(entry.initiatorType)) continue
22
+ let overlap = 0
23
+ for (++i; i < entries.length; i++) {
24
+ const next = entries[i]!
25
+ if (next.startTime > entry.responseEnd) break
26
+ if (next.transferSize && staticResource(next.initiatorType)) {
27
+ overlap += next.transferSize * (next.responseEnd < entry.responseEnd ? 1 :
28
+ (entry.responseEnd - next.startTime) / (next.responseEnd - next.startTime))
29
+ }
30
+ }
31
+ i--
32
+ bits += 8 * (entry.transferSize + overlap) / (entry.duration / 1000)
33
+ if (++count > 10) break
34
+ }
35
+ if (count) return bits / count / 1000000
36
+ const downlink = (view.navigator as any).connection?.downlink
37
+ return typeof downlink === 'number' ? downlink : 5
38
+ }
39
+
40
+ export function transitionResources(doc: Document, previous: TransitionImages, next: TransitionImages) {
41
+ const pending: HTMLImageElement[] = []
42
+ const releases = new Set<() => void>()
43
+
44
+ function wait(promises: Promise<unknown>[], timeout: number, cleanups: Array<() => void> = []): Promise<void> | undefined {
45
+ if (!promises.length) return
46
+ return new Promise(resolve => {
47
+ const finish = () => {
48
+ if (!releases.delete(finish)) return
49
+ clearTimeout(timer)
50
+ for (const cleanup of cleanups) cleanup()
51
+ resolve()
52
+ }
53
+ const timer = setTimeout(finish, timeout)
54
+ releases.add(finish)
55
+ Promise.all(promises).then(finish, finish)
56
+ })
57
+ }
58
+
59
+ return {
60
+ before() {
61
+ const promises: Promise<unknown>[] = []
62
+ let bytes = 0
63
+ for (const [image, props] of next) {
64
+ const old = previous.get(image)
65
+ if (props.src == null || props.src === '' || props.onLoad != null || props.loading === 'lazy' ||
66
+ (old && props.src === old.src && props.srcSet === old.srcSet) || typeof image.decode !== 'function') continue
67
+ if (!image.complete) { pending.push(image); bytes += imageBytes(image) }
68
+ promises.push(image.decode().catch(() => {}))
69
+ }
70
+ if (bytes && !imageBudget) imageBudget = 125 * bandwidth(doc) * 500
71
+ return wait(promises, bytes > imageBudget ? 50 : 800)
72
+ },
73
+ after(fontsWereLoaded: boolean) {
74
+ const promises: Promise<unknown>[] = []
75
+ const cleanups: Array<() => void> = []
76
+ if (fontsWereLoaded) {
77
+ // Discover fonts introduced by mutation before the browser captures.
78
+ doc.documentElement.getBoundingClientRect()
79
+ if (doc.fonts.status === 'loading') promises.push(doc.fonts.ready)
80
+ }
81
+ const images: HTMLImageElement[] = []
82
+ let bytes = 0
83
+ const view = doc.defaultView!
84
+ for (const image of pending) {
85
+ if (image.complete) continue
86
+ const rect = image.getBoundingClientRect()
87
+ if (rect.bottom <= 0 || rect.right <= 0 || rect.top >= view.innerHeight || rect.left >= view.innerWidth) continue
88
+ bytes += imageBytes(image)
89
+ if (bytes > imageBudget) { images.length = 0; break }
90
+ images.push(image)
91
+ }
92
+ for (const image of images) {
93
+ promises.push(new Promise<void>(resolve => {
94
+ const loaded = () => resolve()
95
+ image.addEventListener('load', loaded)
96
+ image.addEventListener('error', loaded)
97
+ cleanups.push(() => {
98
+ image.removeEventListener('load', loaded)
99
+ image.removeEventListener('error', loaded)
100
+ })
101
+ }))
102
+ }
103
+ return wait(promises, 500, cleanups)
104
+ },
105
+ cancel() { for (const release of releases) release() },
106
+ }
107
+ }
@@ -0,0 +1,7 @@
1
+ import type { FiberRoot } from '../../../core'
2
+
3
+ export function markTransitionUpdate(_root: FiberRoot): void {}
4
+ export function deferTransition(_root: FiberRoot, _commit: () => void, _flush: () => void): boolean { return false }
5
+ export function cancelTransitions(): void {}
6
+ export function deferTransitionLayout(_work: () => void): boolean { return false }
7
+ export function deferTransitionPassive(_work: () => void): boolean { return false }