@tanstack/redact 0.0.21 → 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 -27
  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 -77
  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 +197 -52
  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 +689 -221
  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 -28
  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 -85
  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 +192 -55
  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 +695 -242
  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,115 @@
1
+ import { resourceHintDispatcher, resourceURL, type ResourceHintKind, type ResourceHintOptions } from '../core/resource-hints'
2
+ import { adoptResourceProps, getResources, insertResource, resourceAttribute, resourceSelector } from './resource-store'
3
+ const requestOptions = 'integrity fetchPriority'
4
+
5
+ function options(input: any, fields: string, as?: string): ResourceHintOptions {
6
+ const result: ResourceHintOptions = {}
7
+ for (const name of fields ? fields.split(' ') : []) {
8
+ const value = input?.[name]
9
+ if (typeof value === 'string') result[name] = value
10
+ }
11
+ const crossOrigin = input?.crossOrigin
12
+ if (as === 'font' || typeof crossOrigin === 'string') {
13
+ result.crossOrigin = as !== 'font' && crossOrigin === 'use-credentials' ? crossOrigin : ''
14
+ }
15
+ return result
16
+ }
17
+
18
+ function scriptDestination(as: string): boolean {
19
+ return /^(script|audioworklet|paintworklet|serviceworker|sharedworker|worker)$/.test(as)
20
+ }
21
+
22
+ function emit(kind: ResourceHintKind, href: string, props: ResourceHintOptions): void {
23
+ if (!href || resourceHintDispatcher.emit?.(kind, href, props) || typeof document === 'undefined') return
24
+ const resources = getResources(document)
25
+
26
+ const style = kind === 'stylesheet'
27
+ const script = kind === 'script' || kind === 'module-script'
28
+ const preload = kind === 'preload' || kind === 'modulepreload'
29
+ const as = props.as || 'script'
30
+ let selector: string
31
+ let tag = 'link'
32
+ if (style || script) {
33
+ selector = resourceSelector(href, style ? 'style' : 'script')
34
+ if (resources.instances.has(selector)) return
35
+ const existing = document.querySelector(selector)
36
+ if (existing) { resources.instances.set(selector, existing); return }
37
+ adoptResourceProps(props, resources.preloads.get(selector), script)
38
+ if (style) {
39
+ props = { rel: 'stylesheet', href, 'data-precedence': props.precedence!, ...props }
40
+ delete props.precedence
41
+ } else {
42
+ tag = 'script'
43
+ props = { src: href, async: '', ...(kind === 'module-script' ? { type: 'module' } : {}), ...props }
44
+ }
45
+ } else {
46
+ selector = `link[rel="${kind}"]`
47
+ let resource = ''
48
+ if (preload) {
49
+ selector += resourceAttribute('as', as)
50
+ if (as === 'image' && props.imageSrcSet) {
51
+ selector += resourceAttribute('imagesrcset', props.imageSrcSet)
52
+ if (typeof props.imageSizes === 'string') selector += resourceAttribute('imagesizes', props.imageSizes)
53
+ } else selector += resourceAttribute('href', href)
54
+ resource = (kind === 'preload' ? as === 'script' || as === 'style' : scriptDestination(as))
55
+ ? resourceSelector(href, as)
56
+ : ''
57
+ } else {
58
+ selector += resourceAttribute('href', href)
59
+ if (props.crossOrigin != null) selector += resourceAttribute('crossorigin', props.crossOrigin)
60
+ }
61
+ const key = resource || selector
62
+ if (resources.preloads.has(key)) return
63
+ resources.preloads.set(key, props)
64
+ if (document.querySelector(selector) || resource && document.querySelector(resource)) return
65
+ props = { rel: kind, ...(kind === 'preload' && as === 'image' && props.imageSrcSet ? {} : { href }), ...props }
66
+ }
67
+
68
+ const node = document.createElement(tag)
69
+ for (const name in props) {
70
+ const value = props[name]!
71
+ node.setAttribute(name.toLowerCase(), name === 'href' || name === 'src' ? resourceURL(value) : value)
72
+ }
73
+ if (style || script) resources.instances.set(selector, node)
74
+ insertResource(node, style ? props['data-precedence'] : undefined)
75
+ }
76
+
77
+ export function prefetchDNS(href: string): void {
78
+ if (typeof href === 'string') emit('dns-prefetch', href, {})
79
+ }
80
+
81
+ export function preconnect(href: string, input?: any): void {
82
+ if (typeof href === 'string') emit('preconnect', href, options(input, ''))
83
+ }
84
+
85
+ export function preload(href: string, input?: any): void {
86
+ if (typeof href === 'string' && input && typeof input === 'object' && typeof input.as === 'string' && input.as) {
87
+ emit('preload', href, options(input, 'as nonce type referrerPolicy imageSrcSet imageSizes media ' + requestOptions, input.as))
88
+ }
89
+ }
90
+
91
+ export function preinit(href: string, input?: any): void {
92
+ if (typeof href === 'string' && input) {
93
+ if (input.as === 'style') {
94
+ const props = options(input, 'precedence ' + requestOptions)
95
+ props.precedence ||= 'default'
96
+ emit('stylesheet', href, props)
97
+ } else if (input.as === 'script') {
98
+ emit('script', href, options(input, 'nonce ' + requestOptions))
99
+ }
100
+ }
101
+ }
102
+
103
+ export function preloadModule(href: string, input?: any): void {
104
+ if (typeof href === 'string') {
105
+ const props = options(input, 'as nonce ' + requestOptions, input?.as)
106
+ if (props.as === 'script') delete props.as
107
+ emit('modulepreload', href, props)
108
+ }
109
+ }
110
+
111
+ export function preinitModule(href: string, input?: any): void {
112
+ if (typeof href === 'string' && (input == null || typeof input === 'object' && (input.as == null || input.as === 'script'))) {
113
+ emit('module-script', href, options(input, 'nonce ' + requestOptions))
114
+ }
115
+ }
@@ -0,0 +1,52 @@
1
+ import type { ResourceHintOptions } from '../core/resource-hints'
2
+
3
+ interface Resources {
4
+ // Connection and preload selectors are disjoint, so one map deduplicates both.
5
+ preloads: Map<string, ResourceHintOptions>
6
+ instances: Map<string, Element>
7
+ }
8
+
9
+ export type ResourceRoot = Document | DocumentFragment
10
+
11
+ const roots = /*#__PURE__*/ new WeakMap<ResourceRoot, Resources>()
12
+ // Existing document links can satisfy a shadow declaration. Links created by
13
+ // the resource system belong to their original root instead.
14
+ export const createdStylesheets = /*#__PURE__*/ new WeakSet<Element>()
15
+
16
+ export function resourceAttribute(name: string, value: string): string {
17
+ return `[${name}="${value.replace(/[\n"\\]/g, char => '\\' + char.charCodeAt(0).toString(16) + ' ')}"]`
18
+ }
19
+
20
+ export function resourceSelector(href: string, as: string): string {
21
+ return as === 'style'
22
+ ? 'link[rel="stylesheet"]' + resourceAttribute('href', href)
23
+ : 'script[async]' + resourceAttribute('src', href)
24
+ }
25
+
26
+ export function getResources(root: ResourceRoot): Resources {
27
+ let resources = roots.get(root)
28
+ if (!resources) roots.set(root, resources = { preloads: new Map(), instances: new Map() })
29
+ return resources
30
+ }
31
+
32
+ export function adoptResourceProps(props: any, prior: ResourceHintOptions | undefined, script: boolean): void {
33
+ if (prior) for (const name of ['crossOrigin', 'referrerPolicy', script ? 'integrity' : 'title']) {
34
+ if (props[name] == null && prior[name] != null) props[name] = prior[name]
35
+ }
36
+ }
37
+
38
+ export function insertResource(node: Element, precedence?: string, root: ResourceRoot = node.ownerDocument): void {
39
+ const container = root.nodeType === 9 ? (root as Document).head : root
40
+ if (precedence != null) {
41
+ if (node.localName === 'link') createdStylesheets.add(node)
42
+ let previous: Element | undefined
43
+ let matched = false
44
+ for (const sibling of root.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]')) {
45
+ if (sibling.getAttribute('data-precedence') === precedence) matched = true
46
+ else if (matched) break
47
+ previous = sibling
48
+ }
49
+ if (previous) previous.parentNode!.insertBefore(node, previous.nextSibling)
50
+ else container.insertBefore(node, container.firstChild)
51
+ } else container.appendChild(node)
52
+ }
@@ -0,0 +1,39 @@
1
+ import { resourceURL } from '../core/resource-hints'
2
+ import { setProp } from './dom'
3
+ import { adoptResourceProps, createdStylesheets, getResources, insertResource, resourceAttribute, resourceSelector, type ResourceRoot } from './resource-store'
4
+
5
+ // Called only during commit. Resource nodes are shared by href and are not
6
+ // owned by a component's placement or unmount operations.
7
+ // The renderer has already checked this host's resource eligibility.
8
+ export function acquireResource(type: string, props: any, container: Node): Element {
9
+ const script = type === 'script'
10
+ const style = type === 'style'
11
+ const ownerDocument = (container.nodeType === 9 ? container : container.ownerDocument) as Document
12
+ const tree = script ? ownerDocument : container.getRootNode()
13
+ const root = (tree.nodeType === 9 || tree.nodeType === 11 ? tree : ownerDocument) as ResourceRoot
14
+ const href = script ? props.src : props.href
15
+ const resources = getResources(root)
16
+ const key = resourceSelector(href, script ? 'script' : 'style')
17
+ let node = resources.instances.get(key)
18
+ if (node) return node
19
+ const existing = !style && !script && root !== ownerDocument ? ownerDocument.querySelector(key) : null
20
+ node = existing && !createdStylesheets.has(existing) && !(existing as any)._p ? existing
21
+ : root.querySelector(style ? 'style' + resourceAttribute('data-href~', href) : key) || undefined
22
+ if (node) { resources.instances.set(key, node); return node }
23
+
24
+ const next = { ...props }
25
+ if (!script) {
26
+ next['data-precedence'] = props.precedence
27
+ delete next.precedence
28
+ if (style) { next['data-href'] = props.href; delete next.href }
29
+ }
30
+ if (!style) adoptResourceProps(next, getResources(ownerDocument).preloads.get(key), script)
31
+ node = ownerDocument.createElement(type)
32
+ for (const name in next) {
33
+ setProp(node, name, name === 'href' || name === 'src' ? resourceURL(next[name]) : next[name], undefined, false)
34
+ }
35
+ if (style && next.dangerouslySetInnerHTML == null && (typeof next.children === 'string' || typeof next.children === 'number' || typeof next.children === 'bigint')) node.textContent = '' + next.children
36
+ resources.instances.set(key, node)
37
+ insertResource(node, script ? undefined : props.precedence, root)
38
+ return node
39
+ }
@@ -0,0 +1,38 @@
1
+ import { FiberTag, type Fiber, type Hook, type Effect } from '../core'
2
+ import { onCommitRollback } from './commit'
3
+
4
+ export const retainedEffects = new WeakMap<Fiber, Map<Hook, Effect>>()
5
+
6
+ export function rememberRetainedEffect(fiber: Fiber, hook: Hook, effect: Effect): void {
7
+ let entries = retainedEffects.get(fiber)
8
+ if (!entries) {
9
+ retainedEffects.set(fiber, entries = new Map())
10
+ onCommitRollback(() => { retainedEffects.delete(fiber) })
11
+ }
12
+ const previous = entries.get(hook), target = entries
13
+ onCommitRollback(() => { if (previous) target.set(hook, previous); else target.delete(hook) })
14
+ entries.set(hook, effect)
15
+ }
16
+
17
+ export function setLayoutDisconnected(fiber: Fiber, disconnected: boolean): boolean {
18
+ const previous = !!fiber.ld
19
+ if (previous !== disconnected) {
20
+ onCommitRollback(() => { fiber.ld = previous })
21
+ fiber.ld = disconnected
22
+ }
23
+ return previous
24
+ }
25
+
26
+ export function walkRetained(fiber: Fiber, visit: (fiber: Fiber) => void, postorder = false): void {
27
+ if (!postorder) visit(fiber)
28
+ for (let child = fiber.child; child; child = child.sibling) walkRetained(child, visit, postorder)
29
+ if (fiber.tag === FiberTag.Suspense && fiber.ms?.f) walkRetained(fiber.ms.f, visit, postorder)
30
+ if (postorder) visit(fiber)
31
+ }
32
+
33
+ export function inSuspensePrimary(fiber: Fiber): boolean {
34
+ for (let child = fiber, parent = fiber.parent; parent; child = parent, parent = parent.parent) {
35
+ if (parent.tag === FiberTag.Suspense && parent.ms?.d && parent.ms.f !== child) return true
36
+ }
37
+ return false
38
+ }
@@ -1,10 +1,10 @@
1
- import { FiberTag, createFiber, type Fiber, type FiberRoot } from '../core'
1
+ import { FiberTag, createFiber, type Fiber, type FiberRoot, type RecoverableErrorHandler } from '../core'
2
2
 
3
3
  export interface RootOptionsInternal {
4
4
  identifierPrefix?: string
5
- onRecoverableError?: (error: unknown) => void
6
- onCaughtError?: (error: unknown) => void
7
- onUncaughtError?: (error: unknown) => void
5
+ onRecoverableError?: RecoverableErrorHandler
6
+ onCaughtError?: RecoverableErrorHandler
7
+ onUncaughtError?: RecoverableErrorHandler
8
8
  }
9
9
 
10
10
  export function createFiberRoot(
package/src/dom/root.ts CHANGED
@@ -1,13 +1,14 @@
1
- import type { ReactNode } from '../core'
2
- import { renderRoot, flushSyncWork, batchedUpdates } from './reconcile'
1
+ import type { ReactNode, RecoverableErrorHandler } from '../core'
2
+ import { renderRoot, scheduleRootRender, flushSyncWork, batchedUpdates } from './reconcile'
3
3
  import { hydrateRootImpl } from './features/hydration'
4
4
  import { createFiberRoot } from './root-internal'
5
+ import { queueMutation } from './commit'
5
6
 
6
7
  export interface RootOptions {
7
8
  identifierPrefix?: string
8
- onRecoverableError?: (error: unknown) => void
9
- onCaughtError?: (error: unknown) => void
10
- onUncaughtError?: (error: unknown) => void
9
+ onRecoverableError?: RecoverableErrorHandler
10
+ onCaughtError?: RecoverableErrorHandler
11
+ onUncaughtError?: RecoverableErrorHandler
11
12
  }
12
13
 
13
14
  export interface Root {
@@ -21,16 +22,13 @@ export function createRoot(container: Element | DocumentFragment, options: RootO
21
22
  let firstRender = true
22
23
  return {
23
24
  render(children) {
24
- if (firstRender) {
25
- firstRender = false
26
- // Match real React's `clearContainer` semantics: blow away any pre-render
27
- // markup (server-rendered placeholder, splash shells, etc.) on the
28
- // initial commit so it doesn't stack with the React tree.
29
- if ((container as Node).nodeType === 1 /* ELEMENT_NODE */) {
30
- ;(container as Element).textContent = ''
25
+ scheduleRootRender(root, () => {
26
+ if (firstRender) {
27
+ queueMutation(() => {
28
+ firstRender = false
29
+ if ((container as Node).nodeType === 1) container.textContent = ''
30
+ })
31
31
  }
32
- }
33
- flushSyncWork(() => {
34
32
  renderRoot(root, children)
35
33
  })
36
34
  },
@@ -0,0 +1,10 @@
1
+ import type { ReactNode } from '../core'
2
+
3
+ export const REACT_ACTIVITY_TYPE = Symbol.for('react.activity')
4
+
5
+ export interface ActivityProps {
6
+ children?: ReactNode
7
+ mode?: 'hidden' | 'visible'
8
+ }
9
+
10
+ export const Activity = REACT_ACTIVITY_TYPE as any as (props: ActivityProps) => any
@@ -4,17 +4,21 @@ import {
4
4
  REACT_FRAGMENT_TYPE,
5
5
  type ReactElement,
6
6
  type ReactNode,
7
+ type Ref,
7
8
  } from '../core'
9
+ import type { FragmentInstance } from '../dom/fragment-instance'
8
10
 
9
11
  export const Fragment = REACT_FRAGMENT_TYPE as unknown as (props: {
10
12
  children?: ReactNode
13
+ key?: string | number
14
+ ref?: Ref<FragmentInstance>
11
15
  }) => ReactElement
12
16
 
13
17
  const RESERVED_PROPS: Record<string, 1> = { key: 1, ref: 1, __self: 1, __source: 1 }
14
18
 
15
19
  export function createElement(
16
20
  type: any,
17
- config: Record<string, any> | null,
21
+ config?: Record<string, any> | null,
18
22
  ...children: ReactNode[]
19
23
  ): ReactElement {
20
24
  let key: string | null = null
@@ -46,7 +50,7 @@ export function createElement(
46
50
 
47
51
  export function cloneElement(
48
52
  element: ReactElement,
49
- config: Record<string, any> | null,
53
+ config?: Record<string, any> | null,
50
54
  ...children: ReactNode[]
51
55
  ): ReactElement {
52
56
  let key = element.key
@@ -5,7 +5,8 @@ import type {
5
5
  DependencyList,
6
6
  } from '../core'
7
7
  import type { Context } from './context'
8
- import { getDispatcher } from './shared-internals'
8
+ import { getDispatcher, ReactSharedInternals } from './shared-internals'
9
+ import type { BrowserToken } from '../core/browser'
9
10
 
10
11
  export function useState<S>(initial: S | (() => S)): [S, Dispatch<SetStateAction<S>>] {
11
12
  return getDispatcher().useState(initial)
@@ -82,12 +83,20 @@ export function useSyncExternalStore<T>(
82
83
  return getDispatcher().useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot)
83
84
  }
84
85
 
85
- export function use<T>(resource: PromiseLike<T> | { _currentValue: T } | { $$typeof: symbol; _currentValue: T }): T {
86
+ export function use(resource: BrowserToken): undefined
87
+ export function use<T>(resource: PromiseLike<T> | { _currentValue: T } | { $$typeof: symbol; _currentValue: T }): T
88
+ export function use<T>(resource: BrowserToken | PromiseLike<T> | { _currentValue: T } | { $$typeof: symbol; _currentValue: T }): T {
86
89
  return getDispatcher().use(resource)
87
90
  }
88
91
 
92
+ export function unstable_useCacheRefresh(): () => void {
93
+ return getDispatcher().useCacheRefresh()
94
+ }
95
+
89
96
  export function startTransition(fn: () => void): void {
90
- fn()
97
+ const previous = ReactSharedInternals.T
98
+ ReactSharedInternals.T = previous || new Set()
99
+ try { fn() } finally { ReactSharedInternals.T = previous }
91
100
  }
92
101
 
93
102
  export function useActionState<S, P>(
@@ -39,6 +39,7 @@ export {
39
39
  useOptimistic,
40
40
  useEffectEvent,
41
41
  startTransition,
42
+ unstable_useCacheRefresh,
42
43
  } from './hooks'
43
44
  export {
44
45
  createContext,
@@ -64,10 +65,18 @@ export {
64
65
  } from './suspense'
65
66
  export { REACT_PORTAL_TYPE } from './portal'
66
67
  export { Children } from './children'
68
+ export { ViewTransition, addTransitionType, REACT_VIEW_TRANSITION_TYPE } from './view-transition'
69
+ export type { ViewTransitionProps, ViewTransitionClass, ViewTransitionInstance, ViewTransitionPseudoElement } from './view-transition'
70
+ export { Activity, REACT_ACTIVITY_TYPE } from './activity'
71
+ export type { ActivityProps } from './activity'
72
+ export type { FragmentInstance } from '../dom/fragment-instance'
67
73
  export { ReactSharedInternals } from './shared-internals'
68
74
 
69
75
  // Stub exports
70
76
  export const cache = <T extends Function>(fn: T): T => fn
77
+ // The client/DOM-server entry has no RSC cache lifetime, matching React's
78
+ // client export. The upstream Flight renderer remains responsible for RSC.
79
+ export const cacheSignal = (): AbortSignal | null => null
71
80
  export const act = async (fn: () => any) => {
72
81
  const r = fn()
73
82
  if (r && typeof r.then == 'function') await r
@@ -101,12 +110,15 @@ import {
101
110
  useOptimistic,
102
111
  useEffectEvent,
103
112
  startTransition,
113
+ unstable_useCacheRefresh,
104
114
  } from './hooks'
105
115
  import { createContext } from './context'
106
116
  import { Component, PureComponent } from './class'
107
117
  import { memo, forwardRef, lazy } from './memo'
108
118
  import { Suspense, StrictMode, Profiler } from './suspense'
109
119
  import { Children } from './children'
120
+ import { ViewTransition, addTransitionType } from './view-transition'
121
+ import { Activity } from './activity'
110
122
 
111
123
  export default {
112
124
  createElement,
@@ -135,6 +147,7 @@ export default {
135
147
  useOptimistic,
136
148
  useEffectEvent,
137
149
  startTransition,
150
+ unstable_useCacheRefresh,
138
151
  createContext,
139
152
  Component,
140
153
  PureComponent,
@@ -145,5 +158,10 @@ export default {
145
158
  StrictMode,
146
159
  Profiler,
147
160
  Children,
161
+ ViewTransition,
162
+ Activity,
163
+ addTransitionType,
164
+ cache,
165
+ cacheSignal,
148
166
  version: '19.2.3',
149
167
  }
@@ -1,4 +1,4 @@
1
- import type { Fiber, Hook } from '../core'
1
+ import type { Fiber } from '../core'
2
2
 
3
3
  export interface Dispatcher {
4
4
  useState<S>(initial: S | (() => S)): [S, (s: S | ((p: S) => S)) => void]
@@ -25,13 +25,14 @@ export interface Dispatcher {
25
25
  getServerSnapshot?: () => T,
26
26
  ): T
27
27
  use<T>(promiseOrContext: any): T
28
+ useCacheRefresh(): () => void
28
29
  }
29
30
 
30
31
  interface SharedInternals {
31
32
  H: Dispatcher | null
32
33
  F: Fiber | null
33
- K: Hook | null
34
34
  I: number
35
+ T?: Set<string> | null | undefined
35
36
  }
36
37
 
37
38
  // Stash the singleton on `globalThis` under a registered symbol. Module-scoped
@@ -52,7 +53,6 @@ export const ReactSharedInternals: SharedInternals =
52
53
  (g[KEY] = {
53
54
  H: null,
54
55
  F: null,
55
- K: null,
56
56
  I: 0,
57
57
  })
58
58
 
@@ -0,0 +1,41 @@
1
+ import type { ReactNode } from '../core'
2
+ import { ReactSharedInternals } from './shared-internals'
3
+
4
+ export const REACT_VIEW_TRANSITION_TYPE = Symbol.for('react.view_transition')
5
+
6
+ export type ViewTransitionClass = string | Record<string, string>
7
+ export interface ViewTransitionPseudoElement {
8
+ animate(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions): Animation
9
+ getAnimations(): Animation[]
10
+ getComputedStyle(): CSSStyleDeclaration
11
+ }
12
+
13
+ export interface ViewTransitionInstance {
14
+ name: string
15
+ group: ViewTransitionPseudoElement
16
+ imagePair: ViewTransitionPseudoElement
17
+ old: ViewTransitionPseudoElement
18
+ new: ViewTransitionPseudoElement
19
+ }
20
+
21
+ type ViewTransitionEvent = (instance: ViewTransitionInstance, types: string[]) => void | (() => void)
22
+ export interface ViewTransitionProps {
23
+ children?: ReactNode
24
+ name?: string | Record<string, string> | undefined
25
+ default?: ViewTransitionClass | undefined
26
+ enter?: ViewTransitionClass | undefined
27
+ exit?: ViewTransitionClass | undefined
28
+ update?: ViewTransitionClass | undefined
29
+ share?: ViewTransitionClass | undefined
30
+ onEnter?: ViewTransitionEvent | undefined
31
+ onExit?: ViewTransitionEvent | undefined
32
+ onUpdate?: ViewTransitionEvent | undefined
33
+ onShare?: ViewTransitionEvent | undefined
34
+ }
35
+
36
+ // Animation support belongs to the optional DOM feature, not this public entry.
37
+ export const ViewTransition = REACT_VIEW_TRANSITION_TYPE as unknown as (props: ViewTransitionProps) => any
38
+
39
+ export function addTransitionType(type: string): void {
40
+ ReactSharedInternals.T?.add(type)
41
+ }
@@ -20,9 +20,17 @@
20
20
  * listeners for a small set of interactive events and push them into a buffer.
21
21
  * The bundle drains and replays them via the replay code in @tanstack/redact/dom.
22
22
  */
23
+ import { escapeAttr } from './escape'
24
+
23
25
  export const BOUNDARY_REVEAL_RUNTIME =
24
26
  `(function(){` +
25
- `var c={};` +
27
+ `var c={},r=new Map;` +
28
+ `function place(n,v){` +
29
+ `var a=document.head.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),t=a.length?a[a.length-1]:null,p=t;` +
30
+ `for(var k=0;k<a.length;k++){if(a[k].getAttribute("data-precedence")===v)p=a[k];else if(p!==t)break}` +
31
+ `document.head.insertBefore(n,p?p.nextSibling:document.head.firstChild);` +
32
+ `}` +
33
+ `function load(n,e){return new Promise(function(y,x){n.onload=function(){e.p=null;y()};n.onerror=function(){e.p=null;x()}})}` +
26
34
  `window.$RH=function(i,f){` +
27
35
  `if(!document.getElementById("B:"+i))f();` +
28
36
  `else c[i]=f;` +
@@ -30,6 +38,10 @@ export const BOUNDARY_REVEAL_RUNTIME =
30
38
  `window.$RC=function(i){` +
31
39
  `var s=document.getElementById("S:"+i),b=document.getElementById("B:"+i);` +
32
40
  `if(!s||!b)return;` +
41
+ `var a=document.querySelectorAll('body link[rel="stylesheet"][data-precedence],body style[data-precedence]');` +
42
+ `for(var j=0;j<a.length;j++){` +
43
+ `var n=a[j];if(n.getAttribute("media")==="not all")n.removeAttribute("media");place(n,n.getAttribute("data-precedence"));` +
44
+ `}` +
33
45
  `var p=b.parentNode,m=b.previousSibling;` +
34
46
  `while(s.firstChild)p.insertBefore(s.firstChild,b);` +
35
47
  `s.parentNode.removeChild(s);` +
@@ -37,6 +49,25 @@ export const BOUNDARY_REVEAL_RUNTIME =
37
49
  `if(m&&m.nodeType===8)m.data="$"+i;` +
38
50
  `if(c[i]){var f=c[i];delete c[i];f()}` +
39
51
  `};` +
52
+ `window.$RL=function(i,d){` +
53
+ `var w=[];for(var j=0;j<d.length;j++){` +
54
+ `var a=d[j],e=r.get(a[0]);if(!e){` +
55
+ `var n=null,l=document.querySelectorAll('link[rel="stylesheet"]');for(var k=0;k<l.length;k++)if(l[k].getAttribute("href")===a[0]){n=l[k];break}` +
56
+ `e={n:n,p:null};r.set(a[0],e);if(!n){` +
57
+ `n=e.n=document.createElement("link");n.rel="stylesheet";n.href=a[0];n.setAttribute("data-precedence",a[1]);` +
58
+ `for(var k=2;k<a.length;k+=2)n.setAttribute(a[k],a[k+1]);` +
59
+ `e.p=load(n,e);place(n,a[1]);` +
60
+ `}` +
61
+ `}` +
62
+ `var m=e.n.getAttribute("media");if(e.p&&(!m||matchMedia(m).matches))w.push(e.p);` +
63
+ `}` +
64
+ `Promise.all(w).then(function(){$RC(i)},function(){$RB(i,1)});` +
65
+ `};` +
66
+ `window.$RB=function(i,e){` +
67
+ `var b=document.getElementById("B:"+i);if(!b)return;` +
68
+ `var m=b.previousSibling;if(m&&m.nodeType===8)m.data=(e?"$E":"$!")+i;` +
69
+ `b.removeAttribute("id");if(c[i]){var f=c[i];delete c[i];f()}` +
70
+ `};` +
40
71
  `var q=[];window.$RE_q=q;` +
41
72
  `var evs=["click","submit","input","change","keydown"];` +
42
73
  `function h(e){q.push([e.type,e.target,e.timeStamp])}` +
@@ -45,11 +76,11 @@ export const BOUNDARY_REVEAL_RUNTIME =
45
76
  `})();`
46
77
 
47
78
  export function injectBootstrapScript(nonce?: string): string {
48
- const n = nonce ? ` nonce="${nonce}"` : ''
79
+ const n = nonce ? ` nonce="${escapeAttr(nonce)}"` : ''
49
80
  return `<script${n}>${BOUNDARY_REVEAL_RUNTIME}</script>`
50
81
  }
51
82
 
52
- export function revealScript(id: number, nonce?: string): string {
53
- const n = nonce ? ` nonce="${nonce}"` : ''
54
- return `<script${n}>$RC(${id})</script>`
83
+ export function revealScript(id: number, nonce?: string, styles?: string[][]): string {
84
+ const n = nonce ? ` nonce="${escapeAttr(nonce)}"` : ''
85
+ return `<script${n}>${styles?.length ? `$RL(${id},${JSON.stringify(styles).replace(/</g, '\\u003c')})` : `$RC(${id})`}</script>`
55
86
  }