@tanstack/router-devtools-core 1.167.0 → 1.167.2

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.
@@ -3,7 +3,7 @@ type ExpanderProps = {
3
3
  expanded: boolean;
4
4
  style?: JSX.CSSProperties;
5
5
  };
6
- export declare const Expander: ({ expanded, style }: ExpanderProps) => JSX.Element;
6
+ export declare const Expander: ({ expanded, style: _style }: ExpanderProps) => JSX.Element;
7
7
  type Entry = {
8
8
  label: string;
9
9
  };
@@ -40,7 +40,7 @@ var TanStackRouterDevtoolsCore = class {
40
40
  let Devtools;
41
41
  if (this.#Component) Devtools = this.#Component;
42
42
  else {
43
- Devtools = require_context.lazy(() => Promise.resolve().then(() => require("../FloatingTanStackRouterDevtools-M-UhaKLc.cjs")));
43
+ Devtools = require_context.lazy(() => Promise.resolve().then(() => require("../FloatingTanStackRouterDevtools-eF_9_NhU.cjs")));
44
44
  this.#Component = Devtools;
45
45
  }
46
46
  return require_context.createComponent(require_context.ShadowDomTargetContext.Provider, {
@@ -114,7 +114,7 @@ var TanStackRouterDevtoolsPanelCore = class {
114
114
  let BaseTanStackRouterDevtoolsPanel;
115
115
  if (this.#Component) BaseTanStackRouterDevtoolsPanel = this.#Component;
116
116
  else {
117
- BaseTanStackRouterDevtoolsPanel = require_context.lazy(() => Promise.resolve().then(() => require("../BaseTanStackRouterDevtoolsPanel-BlI6Kawa.cjs")));
117
+ BaseTanStackRouterDevtoolsPanel = require_context.lazy(() => Promise.resolve().then(() => require("../BaseTanStackRouterDevtoolsPanel-CKR5l6C5.cjs")));
118
118
  this.#Component = BaseTanStackRouterDevtoolsPanel;
119
119
  }
120
120
  return require_context.createComponent(require_context.ShadowDomTargetContext.Provider, {
@@ -10,6 +10,30 @@ export declare function styled<T extends keyof HTMLElementTagNameMap>(type: T, n
10
10
  ref?: HTMLElementTagNameMap[T] | undefined;
11
11
  }) => JSX.Element;
12
12
  export declare function useIsMounted(): import('solid-js').Accessor<boolean>;
13
+ export type RscSlotUsageEvent = {
14
+ slot: string;
15
+ args?: Array<any>;
16
+ };
17
+ export type ServerComponentType = 'compositeSource' | 'renderableValue' | null;
18
+ /**
19
+ * Checks if a value is any kind of server component
20
+ */
21
+ export declare const isServerComponent: (value: unknown) => boolean;
22
+ /**
23
+ * Gets the type of server component.
24
+ * - RENDERABLE_RSC === true → renderable (from renderServerComponent)
25
+ * - RENDERABLE_RSC === false or not present → composite (from createCompositeComponent)
26
+ */
27
+ export declare const getServerComponentType: (value: unknown) => ServerComponentType;
28
+ /**
29
+ * Gets the slot names from a composite server component (dev only)
30
+ */
31
+ export declare const getServerComponentSlots: (value: unknown) => Array<string>;
32
+ export declare const getServerComponentSlotUsages: (value: unknown) => Array<RscSlotUsageEvent>;
33
+ export declare const getServerComponentSlotUsageSummary: (value: unknown) => Record<string, {
34
+ count: number;
35
+ invocations: Array<Array<any>>;
36
+ }>;
13
37
  /**
14
38
  * Displays a string regardless the type of the data
15
39
  * @param {unknown} value Value to be stringified
@@ -3,7 +3,7 @@ type ExpanderProps = {
3
3
  expanded: boolean;
4
4
  style?: JSX.CSSProperties;
5
5
  };
6
- export declare const Expander: ({ expanded, style }: ExpanderProps) => JSX.Element;
6
+ export declare const Expander: ({ expanded, style: _style }: ExpanderProps) => JSX.Element;
7
7
  type Entry = {
8
8
  label: string;
9
9
  };
package/dist/esm/index.js CHANGED
@@ -39,7 +39,7 @@ var TanStackRouterDevtoolsCore = class {
39
39
  let Devtools;
40
40
  if (this.#Component) Devtools = this.#Component;
41
41
  else {
42
- Devtools = lazy(() => import("../FloatingTanStackRouterDevtools-U4pxMObm.js"));
42
+ Devtools = lazy(() => import("../FloatingTanStackRouterDevtools-5lmIMjR6.js"));
43
43
  this.#Component = Devtools;
44
44
  }
45
45
  return createComponent(ShadowDomTargetContext.Provider, {
@@ -113,7 +113,7 @@ var TanStackRouterDevtoolsPanelCore = class {
113
113
  let BaseTanStackRouterDevtoolsPanel;
114
114
  if (this.#Component) BaseTanStackRouterDevtoolsPanel = this.#Component;
115
115
  else {
116
- BaseTanStackRouterDevtoolsPanel = lazy(() => import("../BaseTanStackRouterDevtoolsPanel-DwUaC87U.js"));
116
+ BaseTanStackRouterDevtoolsPanel = lazy(() => import("../BaseTanStackRouterDevtoolsPanel-BYamTwOT.js"));
117
117
  this.#Component = BaseTanStackRouterDevtoolsPanel;
118
118
  }
119
119
  return createComponent(ShadowDomTargetContext.Provider, {
@@ -10,6 +10,30 @@ export declare function styled<T extends keyof HTMLElementTagNameMap>(type: T, n
10
10
  ref?: HTMLElementTagNameMap[T] | undefined;
11
11
  }) => JSX.Element;
12
12
  export declare function useIsMounted(): import('solid-js').Accessor<boolean>;
13
+ export type RscSlotUsageEvent = {
14
+ slot: string;
15
+ args?: Array<any>;
16
+ };
17
+ export type ServerComponentType = 'compositeSource' | 'renderableValue' | null;
18
+ /**
19
+ * Checks if a value is any kind of server component
20
+ */
21
+ export declare const isServerComponent: (value: unknown) => boolean;
22
+ /**
23
+ * Gets the type of server component.
24
+ * - RENDERABLE_RSC === true → renderable (from renderServerComponent)
25
+ * - RENDERABLE_RSC === false or not present → composite (from createCompositeComponent)
26
+ */
27
+ export declare const getServerComponentType: (value: unknown) => ServerComponentType;
28
+ /**
29
+ * Gets the slot names from a composite server component (dev only)
30
+ */
31
+ export declare const getServerComponentSlots: (value: unknown) => Array<string>;
32
+ export declare const getServerComponentSlotUsages: (value: unknown) => Array<RscSlotUsageEvent>;
33
+ export declare const getServerComponentSlotUsageSummary: (value: unknown) => Record<string, {
34
+ count: number;
35
+ invocations: Array<Array<any>>;
36
+ }>;
13
37
  /**
14
38
  * Displays a string regardless the type of the data
15
39
  * @param {unknown} value Value to be stringified
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/router-devtools-core",
3
- "version": "1.167.0",
3
+ "version": "1.167.2",
4
4
  "description": "Modern and scalable routing for Web applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -50,8 +50,7 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "clsx": "^2.1.1",
53
- "goober": "^2.1.16",
54
- "tiny-invariant": "^1.3.3"
53
+ "goober": "^2.1.16"
55
54
  },
56
55
  "devDependencies": {
57
56
  "solid-js": "^1.9.10",
@@ -60,7 +59,7 @@
60
59
  },
61
60
  "peerDependencies": {
62
61
  "csstype": "^3.0.10",
63
- "@tanstack/router-core": "^1.168.0"
62
+ "@tanstack/router-core": "^1.168.10"
64
63
  },
65
64
  "peerDependenciesMeta": {
66
65
  "csstype": {
@@ -71,12 +70,12 @@
71
70
  "clean": "rimraf ./dist && rimraf ./coverage",
72
71
  "test:eslint": "eslint ./src",
73
72
  "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"",
74
- "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js",
75
73
  "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js",
76
74
  "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js",
77
75
  "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js",
78
76
  "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js",
79
- "test:types:ts59": "tsc",
77
+ "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js",
78
+ "test:types:ts60": "tsc",
80
79
  "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .",
81
80
  "build": "vite build"
82
81
  }
@@ -1,5 +1,4 @@
1
1
  import { clsx as cx } from 'clsx'
2
- import { default as invariant } from 'tiny-invariant'
3
2
  import { interpolatePath, rootRouteId, trimPath } from '@tanstack/router-core'
4
3
  import {
5
4
  For,
@@ -264,11 +263,6 @@ export const BaseTanStackRouterDevtoolsPanel =
264
263
  const styles = useStyles()
265
264
  const { className, style, ...otherPanelProps } = panelProps
266
265
 
267
- invariant(
268
- router,
269
- 'No router was found for the TanStack Router Devtools. Please place the devtools in the <RouterProvider> component tree or pass the router instance to the devtools manually.',
270
- )
271
-
272
266
  // useStore(router.stores.__store)
273
267
 
274
268
  const [currentTab, setCurrentTab] = useLocalStorage<
@@ -300,30 +294,30 @@ export const BaseTanStackRouterDevtoolsPanel =
300
294
  type Subscribe = (fn: () => void) => { unsubscribe: () => void }
301
295
  createEffect(() => {
302
296
  const pendingMatchesStore = router().stores.pendingMatchesSnapshot
303
- setPendingMatches(pendingMatchesStore.state)
297
+ setPendingMatches(pendingMatchesStore.get())
304
298
  const subscription = (
305
299
  (pendingMatchesStore as any).subscribe as Subscribe
306
300
  )(() => {
307
- setPendingMatches(pendingMatchesStore.state)
301
+ setPendingMatches(pendingMatchesStore.get())
308
302
  })
309
303
  onCleanup(() => subscription.unsubscribe())
310
304
  })
311
305
 
312
306
  createEffect(() => {
313
307
  const cachedMatchesStore = router().stores.cachedMatchesSnapshot
314
- setCachedMatches(cachedMatchesStore.state)
308
+ setCachedMatches(cachedMatchesStore.get())
315
309
  const subscription = (
316
310
  (cachedMatchesStore as any).subscribe as Subscribe
317
311
  )(() => {
318
- setCachedMatches(cachedMatchesStore.state)
312
+ setCachedMatches(cachedMatchesStore.get())
319
313
  })
320
314
  onCleanup(() => subscription.unsubscribe())
321
315
  })
322
316
  }
323
317
  // signal implementation
324
318
  else {
325
- pendingMatches = () => router().stores.pendingMatchesSnapshot.state
326
- cachedMatches = () => router().stores.cachedMatchesSnapshot.state
319
+ pendingMatches = () => router().stores.pendingMatchesSnapshot.get()
320
+ cachedMatches = () => router().stores.cachedMatchesSnapshot.get()
327
321
  }
328
322
 
329
323
  createEffect(() => {
package/src/Explorer.tsx CHANGED
@@ -3,7 +3,12 @@ import { clsx as cx } from 'clsx'
3
3
  import * as goober from 'goober'
4
4
  import { createMemo, createSignal, useContext } from 'solid-js'
5
5
  import { tokens } from './tokens'
6
- import { displayValue } from './utils'
6
+ import {
7
+ displayValue,
8
+ getServerComponentSlotUsageSummary,
9
+ getServerComponentSlots,
10
+ getServerComponentType,
11
+ } from './utils'
7
12
  import { ShadowDomTargetContext } from './context'
8
13
  import type { Accessor, JSX } from 'solid-js'
9
14
 
@@ -12,7 +17,7 @@ type ExpanderProps = {
12
17
  style?: JSX.CSSProperties
13
18
  }
14
19
 
15
- export const Expander = ({ expanded, style = {} }: ExpanderProps) => {
20
+ export const Expander = ({ expanded, style: _style = {} }: ExpanderProps) => {
16
21
  const styles = useStyles()
17
22
  return (
18
23
  <span class={styles().expander}>
@@ -90,6 +95,12 @@ function isIterable(x: any): x is Iterable<unknown> {
90
95
  return Symbol.iterator in x
91
96
  }
92
97
 
98
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
99
+ if (!value || typeof value !== 'object') return false
100
+ const proto = Object.getPrototypeOf(value)
101
+ return proto === Object.prototype || proto === null
102
+ }
103
+
93
104
  export function Explorer({
94
105
  value,
95
106
  defaultExpanded,
@@ -116,7 +127,22 @@ export function Explorer({
116
127
  }
117
128
  }
118
129
 
119
- if (Array.isArray(value())) {
130
+ if (
131
+ Array.isArray(value()) &&
132
+ (value() as Array<any>).length === 2 &&
133
+ (value() as Array<any>)[0] === 'React element' &&
134
+ isPlainObject((value() as Array<any>)[1])
135
+ ) {
136
+ // Special case: treat `["React element", { ...meta }]` as sibling entries
137
+ // to avoid the meta object being rendered as a deeper nested tree.
138
+ const v = value() as ['React element', Record<string, unknown>]
139
+ entries = [
140
+ makeProperty({ label: '0', value: v[0] }),
141
+ ...Object.entries(v[1]).map(([key, val]) =>
142
+ makeProperty({ label: key, value: val }),
143
+ ),
144
+ ]
145
+ } else if (Array.isArray(value())) {
120
146
  // any[]
121
147
  entries = (value() as Array<any>).map((d, i) =>
122
148
  makeProperty({
@@ -169,9 +195,72 @@ export function Explorer({
169
195
  />
170
196
  )
171
197
 
198
+ const serverComponentType = createMemo(() => getServerComponentType(value()))
199
+ const serverComponentSlots = createMemo(() =>
200
+ getServerComponentSlots(value()),
201
+ )
202
+ const serverComponentSlotUsageSummary = createMemo(() =>
203
+ getServerComponentSlotUsageSummary(value()),
204
+ )
205
+
206
+ const isCompositeWithSlots = createMemo(
207
+ () =>
208
+ serverComponentType() === 'compositeSource' &&
209
+ serverComponentSlots().length > 0,
210
+ )
211
+
172
212
  return (
173
213
  <div class={styles().entry}>
174
- {subEntryPages().length ? (
214
+ {serverComponentType() !== null ? (
215
+ isCompositeWithSlots() ? (
216
+ <>
217
+ <button
218
+ class={styles().expandButton}
219
+ onClick={() => toggleExpanded()}
220
+ >
221
+ <Expander expanded={expanded() ?? false} />
222
+ <span>{rest.label}:</span>
223
+ <span class={styles().compositeComponent}>
224
+ {displayValue(value())}
225
+ </span>
226
+ </button>
227
+ {(expanded() ?? false) ? (
228
+ <div class={styles().rscMetaRow}>
229
+ <span class={styles().rscMetaLabel}>slots</span>
230
+ <div class={styles().subEntries}>
231
+ {serverComponentSlots().map((name) => {
232
+ const usage = serverComponentSlotUsageSummary()[name]
233
+ if (!usage) return null
234
+ return (
235
+ <Explorer
236
+ label={`${name}:`}
237
+ value={() =>
238
+ usage.invocations.map((args) =>
239
+ args.length === 1 ? args[0] : args,
240
+ )
241
+ }
242
+ />
243
+ )
244
+ })}
245
+ </div>
246
+ </div>
247
+ ) : null}
248
+ </>
249
+ ) : (
250
+ <>
251
+ <span>{rest.label}:</span>{' '}
252
+ <span
253
+ class={
254
+ serverComponentType() === 'compositeSource'
255
+ ? styles().compositeComponent
256
+ : styles().renderableComponent
257
+ }
258
+ >
259
+ {displayValue(value())}
260
+ </span>
261
+ </>
262
+ )
263
+ ) : subEntryPages().length ? (
175
264
  <>
176
265
  <button
177
266
  class={styles().expandButton}
@@ -250,7 +339,7 @@ export function Explorer({
250
339
  }
251
340
 
252
341
  const stylesFactory = (shadowDOMTarget?: ShadowRoot) => {
253
- const { colors, font, size, alpha, shadow, border } = tokens
342
+ const { colors, font, size, border } = tokens
254
343
  const { fontFamily, lineHeight, size: fontSize } = font
255
344
  const css = shadowDOMTarget
256
345
  ? goober.css.bind({ target: shadowDOMTarget })
@@ -309,6 +398,67 @@ const stylesFactory = (shadowDOMTarget?: ShadowRoot) => {
309
398
  value: css`
310
399
  color: ${colors.purple[400]};
311
400
  `,
401
+ compositeComponent: css`
402
+ display: inline-flex;
403
+ align-items: center;
404
+ padding: 1px ${size[1]};
405
+ border-radius: ${border.radius.full};
406
+ border: 1px solid ${colors.darkGray[500]};
407
+ background: ${colors.darkGray[700]};
408
+ color: ${colors.cyan[300]};
409
+ font-style: normal;
410
+ font-weight: ${font.weight.medium};
411
+ `,
412
+ renderableComponent: css`
413
+ display: inline-flex;
414
+ align-items: center;
415
+ padding: 1px ${size[1]};
416
+ border-radius: ${border.radius.full};
417
+ border: 1px solid ${colors.darkGray[500]};
418
+ background: ${colors.darkGray[700]};
419
+ color: ${colors.teal[300]};
420
+ font-style: normal;
421
+ font-weight: ${font.weight.medium};
422
+ `,
423
+ rscMetaRow: css`
424
+ display: flex;
425
+ gap: ${size[1]};
426
+ align-items: flex-start;
427
+ margin-left: calc(${size[3]} + ${size[1]});
428
+ margin-top: ${size[0.5]};
429
+ flex-wrap: wrap;
430
+ `,
431
+ rscMetaLabel: css`
432
+ color: ${colors.gray[500]};
433
+ font-size: ${fontSize['2xs']};
434
+ text-transform: uppercase;
435
+ letter-spacing: 0.06em;
436
+ padding-top: 2px;
437
+ `,
438
+ rscChipRow: css`
439
+ display: flex;
440
+ gap: ${size[1]};
441
+ flex-wrap: wrap;
442
+ `,
443
+ rscChip: css`
444
+ display: inline-flex;
445
+ align-items: center;
446
+ gap: ${size[0.5]};
447
+ padding: 1px ${size[1]};
448
+ border-radius: ${border.radius.full};
449
+ border: 1px solid ${colors.darkGray[500]};
450
+ background: ${colors.darkGray[800]};
451
+ color: ${colors.gray[200]};
452
+ font-size: ${fontSize['2xs']};
453
+ line-height: ${lineHeight.xs};
454
+ `,
455
+ rscChipName: css`
456
+ color: ${colors.gray[100]};
457
+ `,
458
+ rscChipMeta: css`
459
+ color: ${colors.gray[400]};
460
+ font-size: ${fontSize['2xs']};
461
+ `,
312
462
  subEntries: css`
313
463
  margin-left: ${size[2]};
314
464
  padding-left: ${size[2]};
package/src/utils.tsx CHANGED
@@ -104,16 +104,144 @@ export function useIsMounted() {
104
104
  return isMounted
105
105
  }
106
106
 
107
+ // Symbols for RSC detection
108
+ const SERVER_COMPONENT_STREAM = Symbol.for('tanstack.rsc.stream')
109
+ const RENDERABLE_RSC = Symbol.for('tanstack.rsc.renderable')
110
+ const RSC_SLOT_USAGES = Symbol.for('tanstack.rsc.slotUsages')
111
+
112
+ export type RscSlotUsageEvent = {
113
+ slot: string
114
+ args?: Array<any>
115
+ }
116
+
117
+ function trimTrailingUndefined<T>(arr: Array<T>): Array<T> {
118
+ let end = arr.length
119
+ while (end > 0 && arr[end - 1] === undefined) end--
120
+ if (end === 0) return arr
121
+ return end === arr.length ? arr : arr.slice(0, end)
122
+ }
123
+
124
+ export type ServerComponentType =
125
+ | 'compositeSource' // createCompositeComponent result (render via <CompositeComponent src={...} />)
126
+ | 'renderableValue' // renderServerComponent result (inline renderable value)
127
+ | null // not a server component
128
+
129
+ /**
130
+ * Checks if a value is any kind of server component
131
+ */
132
+ export const isServerComponent = (value: unknown): boolean => {
133
+ return (
134
+ (typeof value === 'object' || typeof value === 'function') &&
135
+ value !== null &&
136
+ SERVER_COMPONENT_STREAM in value
137
+ )
138
+ }
139
+
140
+ /**
141
+ * Gets the type of server component.
142
+ * - RENDERABLE_RSC === true → renderable (from renderServerComponent)
143
+ * - RENDERABLE_RSC === false or not present → composite (from createCompositeComponent)
144
+ */
145
+ export const getServerComponentType = (value: unknown): ServerComponentType => {
146
+ if (!isServerComponent(value)) {
147
+ return null
148
+ }
149
+ const v = value as Record<symbol, unknown>
150
+ if (RENDERABLE_RSC in v && v[RENDERABLE_RSC] === true) {
151
+ return 'renderableValue'
152
+ }
153
+ // RENDERABLE_RSC is false or not present → composite
154
+ return 'compositeSource'
155
+ }
156
+
157
+ /**
158
+ * Gets the slot names from a composite server component (dev only)
159
+ */
160
+ export const getServerComponentSlots = (value: unknown): Array<string> => {
161
+ if (!isServerComponent(value)) {
162
+ return []
163
+ }
164
+
165
+ const v = value as Record<symbol, unknown>
166
+ const out: Array<string> = []
167
+ // Include any slot names observed via dev-only slot usage events
168
+ if (RSC_SLOT_USAGES in v) {
169
+ const usages = v[RSC_SLOT_USAGES]
170
+ if (Array.isArray(usages)) {
171
+ for (const evt of usages) {
172
+ const name = evt?.slot
173
+ if (typeof name === 'string' && !out.includes(name)) {
174
+ out.push(name)
175
+ }
176
+ }
177
+ }
178
+ }
179
+
180
+ return out
181
+ }
182
+
183
+ export const getServerComponentSlotUsages = (
184
+ value: unknown,
185
+ ): Array<RscSlotUsageEvent> => {
186
+ if (!isServerComponent(value)) {
187
+ return []
188
+ }
189
+
190
+ const v = value as Record<symbol, unknown>
191
+ if (!(RSC_SLOT_USAGES in v)) return []
192
+ const usages = v[RSC_SLOT_USAGES]
193
+ if (!Array.isArray(usages)) return []
194
+
195
+ return usages.filter((d): d is RscSlotUsageEvent => {
196
+ return (
197
+ d &&
198
+ typeof d === 'object' &&
199
+ typeof d.slot === 'string' &&
200
+ (d.args === undefined || Array.isArray(d.args))
201
+ )
202
+ })
203
+ }
204
+
205
+ export const getServerComponentSlotUsageSummary = (
206
+ value: unknown,
207
+ ): Record<string, { count: number; invocations: Array<Array<any>> }> => {
208
+ const usages = getServerComponentSlotUsages(value)
209
+ const out: Record<string, { count: number; invocations: Array<Array<any>> }> =
210
+ {}
211
+ for (const evt of usages) {
212
+ const args = trimTrailingUndefined(evt.args ?? [])
213
+ const prev =
214
+ out[evt.slot] ?? (out[evt.slot] = { count: 0, invocations: [] })
215
+ prev.count++
216
+ prev.invocations.push(args)
217
+ }
218
+ return out
219
+ }
220
+
107
221
  /**
108
222
  * Displays a string regardless the type of the data
109
223
  * @param {unknown} value Value to be stringified
110
224
  */
111
225
  export const displayValue = (value: unknown) => {
226
+ if (value === 'React element') return 'React element'
227
+ const componentType = getServerComponentType(value)
228
+ if (componentType === 'compositeSource') {
229
+ const slots = getServerComponentSlots(value)
230
+ if (slots.length > 0) {
231
+ return `RSC composite source (${slots.length} ${
232
+ slots.length === 1 ? 'slot' : 'slots'
233
+ })`
234
+ }
235
+ return 'RSC composite source'
236
+ }
237
+ if (componentType === 'renderableValue') {
238
+ return 'RSC renderable value'
239
+ }
112
240
  const name = Object.getOwnPropertyNames(Object(value))
113
241
  const newValue = typeof value === 'bigint' ? `${value.toString()}n` : value
114
242
  try {
115
243
  return JSON.stringify(newValue, name)
116
- } catch (e) {
244
+ } catch {
117
245
  return `unable to stringify`
118
246
  }
119
247
  }