@depup/sentry__react 10.47.0-depup.0 → 10.67.0-depup.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 (122) hide show
  1. package/README.md +9 -3
  2. package/build/cjs/constants.js +3 -5
  3. package/build/cjs/constants.js.map +1 -1
  4. package/build/cjs/debug-build.js +0 -5
  5. package/build/cjs/debug-build.js.map +1 -1
  6. package/build/cjs/error.js +14 -77
  7. package/build/cjs/error.js.map +1 -1
  8. package/build/cjs/errorboundary.js +22 -77
  9. package/build/cjs/errorboundary.js.map +1 -1
  10. package/build/cjs/hoist-non-react-statics.js +16 -84
  11. package/build/cjs/hoist-non-react-statics.js.map +1 -1
  12. package/build/cjs/index.js +6 -0
  13. package/build/cjs/index.js.map +1 -1
  14. package/build/cjs/isSyntheticEvent.js +10 -0
  15. package/build/cjs/isSyntheticEvent.js.map +1 -0
  16. package/build/cjs/profiler.js +35 -110
  17. package/build/cjs/profiler.js.map +1 -1
  18. package/build/cjs/reactrouter-compat-utils/instrumentation.js +236 -692
  19. package/build/cjs/reactrouter-compat-utils/instrumentation.js.map +1 -1
  20. package/build/cjs/reactrouter-compat-utils/lazy-routes.js +24 -85
  21. package/build/cjs/reactrouter-compat-utils/lazy-routes.js.map +1 -1
  22. package/build/cjs/reactrouter-compat-utils/route-manifest.js +18 -96
  23. package/build/cjs/reactrouter-compat-utils/route-manifest.js.map +1 -1
  24. package/build/cjs/reactrouter-compat-utils/utils.js +82 -193
  25. package/build/cjs/reactrouter-compat-utils/utils.js.map +1 -1
  26. package/build/cjs/reactrouter.compat.js +29 -0
  27. package/build/cjs/reactrouter.compat.js.map +1 -0
  28. package/build/cjs/reactrouter.js +34 -111
  29. package/build/cjs/reactrouter.js.map +1 -1
  30. package/build/cjs/reactrouterv3.js +31 -60
  31. package/build/cjs/reactrouterv3.js.map +1 -1
  32. package/build/cjs/reactrouterv6.js +10 -42
  33. package/build/cjs/reactrouterv6.js.map +1 -1
  34. package/build/cjs/reactrouterv7.js +10 -42
  35. package/build/cjs/reactrouterv7.js.map +1 -1
  36. package/build/cjs/redux.js +61 -90
  37. package/build/cjs/redux.js.map +1 -1
  38. package/build/cjs/sdk.js +15 -10
  39. package/build/cjs/sdk.js.map +1 -1
  40. package/build/cjs/tanstackrouter.js +90 -92
  41. package/build/cjs/tanstackrouter.js.map +1 -1
  42. package/build/esm/constants.js +3 -5
  43. package/build/esm/constants.js.map +1 -1
  44. package/build/esm/debug-build.js +0 -5
  45. package/build/esm/debug-build.js.map +1 -1
  46. package/build/esm/error.js +13 -76
  47. package/build/esm/error.js.map +1 -1
  48. package/build/esm/errorboundary.js +22 -77
  49. package/build/esm/errorboundary.js.map +1 -1
  50. package/build/esm/hoist-non-react-statics.js +16 -84
  51. package/build/esm/hoist-non-react-statics.js.map +1 -1
  52. package/build/esm/index.js +1 -0
  53. package/build/esm/index.js.map +1 -1
  54. package/build/esm/isSyntheticEvent.js +8 -0
  55. package/build/esm/isSyntheticEvent.js.map +1 -0
  56. package/build/esm/package.json +1 -1
  57. package/build/esm/profiler.js +35 -110
  58. package/build/esm/profiler.js.map +1 -1
  59. package/build/esm/reactrouter-compat-utils/instrumentation.js +237 -693
  60. package/build/esm/reactrouter-compat-utils/instrumentation.js.map +1 -1
  61. package/build/esm/reactrouter-compat-utils/lazy-routes.js +24 -85
  62. package/build/esm/reactrouter-compat-utils/lazy-routes.js.map +1 -1
  63. package/build/esm/reactrouter-compat-utils/route-manifest.js +18 -96
  64. package/build/esm/reactrouter-compat-utils/route-manifest.js.map +1 -1
  65. package/build/esm/reactrouter-compat-utils/utils.js +80 -191
  66. package/build/esm/reactrouter-compat-utils/utils.js.map +1 -1
  67. package/build/esm/reactrouter.compat.js +23 -0
  68. package/build/esm/reactrouter.compat.js.map +1 -0
  69. package/build/esm/reactrouter.js +34 -111
  70. package/build/esm/reactrouter.js.map +1 -1
  71. package/build/esm/reactrouterv3.js +29 -58
  72. package/build/esm/reactrouterv3.js.map +1 -1
  73. package/build/esm/reactrouterv6.js +10 -42
  74. package/build/esm/reactrouterv6.js.map +1 -1
  75. package/build/esm/reactrouterv7.js +10 -42
  76. package/build/esm/reactrouterv7.js.map +1 -1
  77. package/build/esm/redux.js +61 -90
  78. package/build/esm/redux.js.map +1 -1
  79. package/build/esm/sdk.js +15 -10
  80. package/build/esm/sdk.js.map +1 -1
  81. package/build/esm/tanstackrouter.js +91 -93
  82. package/build/esm/tanstackrouter.js.map +1 -1
  83. package/build/types/error.d.ts.map +1 -1
  84. package/build/types/index.d.ts +1 -0
  85. package/build/types/index.d.ts.map +1 -1
  86. package/build/types/isSyntheticEvent.d.ts +10 -0
  87. package/build/types/isSyntheticEvent.d.ts.map +1 -0
  88. package/build/types/reactrouter-compat-utils/instrumentation.d.ts +1 -1
  89. package/build/types/reactrouter-compat-utils/instrumentation.d.ts.map +1 -1
  90. package/build/types/reactrouter-compat-utils/utils.d.ts +1 -1
  91. package/build/types/reactrouter-compat-utils/utils.d.ts.map +1 -1
  92. package/build/types/reactrouter.compat.d.ts +42 -0
  93. package/build/types/reactrouter.compat.d.ts.map +1 -0
  94. package/build/types/reactrouter.d.ts.map +1 -1
  95. package/build/types/reactrouterv3.d.ts +1 -1
  96. package/build/types/reactrouterv3.d.ts.map +1 -1
  97. package/build/types/reactrouterv6.d.ts +10 -0
  98. package/build/types/reactrouterv6.d.ts.map +1 -1
  99. package/build/types/reactrouterv7.d.ts +10 -0
  100. package/build/types/reactrouterv7.d.ts.map +1 -1
  101. package/build/types/redux.d.ts +1 -1
  102. package/build/types/redux.d.ts.map +1 -1
  103. package/build/types/sdk.d.ts +1 -1
  104. package/build/types/sdk.d.ts.map +1 -1
  105. package/build/types/tanstackrouter.d.ts +1 -1
  106. package/build/types/tanstackrouter.d.ts.map +1 -1
  107. package/build/types/vendor/tanstackrouter-types.d.ts +2 -1
  108. package/build/types/vendor/tanstackrouter-types.d.ts.map +1 -1
  109. package/build/types-ts3.8/index.d.ts +1 -0
  110. package/build/types-ts3.8/isSyntheticEvent.d.ts +10 -0
  111. package/build/types-ts3.8/reactrouter-compat-utils/instrumentation.d.ts +1 -1
  112. package/build/types-ts3.8/reactrouter-compat-utils/utils.d.ts +1 -1
  113. package/build/types-ts3.8/reactrouter.compat.d.ts +42 -0
  114. package/build/types-ts3.8/reactrouterv3.d.ts +1 -1
  115. package/build/types-ts3.8/reactrouterv6.d.ts +10 -0
  116. package/build/types-ts3.8/reactrouterv7.d.ts +10 -0
  117. package/build/types-ts3.8/redux.d.ts +1 -1
  118. package/build/types-ts3.8/sdk.d.ts +1 -1
  119. package/build/types-ts3.8/tanstackrouter.d.ts +1 -1
  120. package/build/types-ts3.8/vendor/tanstackrouter-types.d.ts +2 -1
  121. package/changes.json +8 -3
  122. package/package.json +18 -8
@@ -1,57 +1,33 @@
1
- import { browserTracingIntegration, WINDOW, startBrowserTracingPageLoadSpan, startBrowserTracingNavigationSpan } from '@sentry/browser';
1
+ import { WINDOW, browserTracingIntegration, startBrowserTracingPageLoadSpan, startBrowserTracingNavigationSpan } from '@sentry/browser';
2
2
  import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, debug, addNonEnumerableProperty, spanToJSON, getCurrentScope, getClient } from '@sentry/core';
3
3
  import * as React from 'react';
4
4
  import { DEBUG_BUILD } from '../debug-build.js';
5
5
  import { hoistNonReactStatics } from '../hoist-non-react-statics.js';
6
6
  import { checkRouteForAsyncHandler } from './lazy-routes.js';
7
7
  import { getActiveRootSpan, setNavigationContext, clearNavigationContext, resolveRouteNameAndSource, transactionNameHasWildcard, initializeRouterUtils } from './utils.js';
8
-
9
- /* eslint-disable max-lines */
10
- // Inspired from Donnie McNeal's solution:
11
- // https://gist.github.com/wontondon/e8c4bdf2888875e4c755712e99279536
12
-
8
+ import { URL_TEMPLATE } from '@sentry/conventions/attributes';
13
9
 
14
10
  let _useEffect;
15
11
  let _useLocation;
16
12
  let _useNavigationType;
17
13
  let _createRoutesFromChildren;
18
14
  let _matchRoutes;
19
-
20
15
  let _enableAsyncRouteHandlers = false;
21
- let _lazyRouteTimeout = 3000;
16
+ let _lazyRouteTimeout = 3e3;
22
17
  let _lazyRouteManifest;
23
- let _basename = '';
24
-
25
- const CLIENTS_WITH_INSTRUMENT_NAVIGATION = new WeakSet();
26
-
27
- // Prevents duplicate spans when router.subscribe fires multiple times
28
- const activeNavigationSpans = new WeakMap
29
-
30
- ();
31
-
32
- // Exported for testing only
33
- const allRoutes = new Set();
34
-
35
- // Tracks lazy route loads to wait before finalizing span names
36
- const pendingLazyRouteLoads = new WeakMap();
37
-
38
- // Tracks deferred lazy route promises that can be resolved when patchRoutesOnNavigation is called
39
- const deferredLazyRouteResolvers = new WeakMap();
40
-
41
- /**
42
- * Schedules a callback using requestAnimationFrame when available (browser),
43
- * or falls back to setTimeout for SSR environments (Node.js, createMemoryRouter tests).
44
- */
18
+ let _basename = "";
19
+ const CLIENTS_WITH_INSTRUMENT_NAVIGATION = /* @__PURE__ */ new WeakSet();
20
+ const useIsomorphicLayoutEffect = WINDOW?.document ? React.useLayoutEffect : React.useEffect;
21
+ const activeNavigationSpans = /* @__PURE__ */ new WeakMap();
22
+ const allRoutes = /* @__PURE__ */ new Set();
23
+ const pendingLazyRouteLoads = /* @__PURE__ */ new WeakMap();
24
+ const deferredLazyRouteResolvers = /* @__PURE__ */ new WeakMap();
45
25
  function scheduleCallback(callback) {
46
26
  if (WINDOW?.requestAnimationFrame) {
47
27
  return WINDOW.requestAnimationFrame(callback);
48
28
  }
49
- return setTimeout(callback, 0) ;
29
+ return setTimeout(callback, 0);
50
30
  }
51
-
52
- /**
53
- * Cancels a scheduled callback, handling both RAF (browser) and timeout (SSR) IDs.
54
- */
55
31
  function cancelScheduledCallback(id) {
56
32
  if (WINDOW?.cancelAnimationFrame) {
57
33
  WINDOW.cancelAnimationFrame(id);
@@ -59,103 +35,48 @@ function cancelScheduledCallback(id) {
59
35
  clearTimeout(id);
60
36
  }
61
37
  }
62
-
63
- /**
64
- * Computes location key for duplicate detection. Normalizes undefined/null to empty strings.
65
- * Exported for testing.
66
- */
67
38
  function computeLocationKey(location) {
68
- return `${location.pathname}${location.search || ''}${location.hash || ''}`;
39
+ return `${location.pathname}${location.search || ""}${location.hash || ""}`;
69
40
  }
70
-
71
- /**
72
- * Checks if a route name is parameterized (contains route parameters like :id or wildcards like *)
73
- * vs a raw URL path.
74
- */
75
41
  function isParameterizedRoute(routeName) {
76
- return routeName.includes(':') || routeName.includes('*');
42
+ return routeName.includes(":") || routeName.includes("*");
77
43
  }
78
-
79
- /**
80
- * Determines if a navigation should be skipped as a duplicate, and if an existing span should be updated.
81
- * Exported for testing.
82
- *
83
- * @returns An object with:
84
- * - skip: boolean - Whether to skip creating a new span
85
- * - shouldUpdate: boolean - Whether to update the existing span name (wildcard upgrade)
86
- */
87
- function shouldSkipNavigation(
88
- trackedNav
89
-
90
- ,
91
- locationKey,
92
- proposedName,
93
- spanHasEnded,
94
- ) {
44
+ function shouldSkipNavigation(trackedNav, locationKey, proposedName, spanHasEnded) {
95
45
  if (!trackedNav) {
96
46
  return { skip: false, shouldUpdate: false };
97
47
  }
98
-
99
- // Check if this is a duplicate navigation (same location)
100
- // 1. If it's a placeholder, it's always a duplicate (we're waiting for the real one)
101
- // 2. If it's a real span, it's a duplicate only if it hasn't ended yet
102
48
  const isDuplicate = trackedNav.locationKey === locationKey && (trackedNav.isPlaceholder || !spanHasEnded);
103
-
104
49
  if (isDuplicate) {
105
- // Check if we should update the span name with a better route
106
- // Allow updates if:
107
- // 1. Current has wildcard and new doesn't (wildcard → parameterized upgrade)
108
- // 2. Current is raw path and new is parameterized (raw → parameterized upgrade)
109
- // 3. New name is different and more specific (longer, indicating nested routes resolved)
110
50
  const currentHasWildcard = !!trackedNav.routeName && transactionNameHasWildcard(trackedNav.routeName);
111
51
  const proposedHasWildcard = transactionNameHasWildcard(proposedName);
112
52
  const currentIsParameterized = !!trackedNav.routeName && isParameterizedRoute(trackedNav.routeName);
113
53
  const proposedIsParameterized = isParameterizedRoute(proposedName);
114
-
115
54
  const isWildcardUpgrade = currentHasWildcard && !proposedHasWildcard;
116
55
  const isRawToParameterized = !currentIsParameterized && proposedIsParameterized;
117
- const isMoreSpecific =
118
- proposedName !== trackedNav.routeName &&
119
- proposedName.length > (trackedNav.routeName?.length || 0) &&
120
- !proposedHasWildcard;
121
-
56
+ const isMoreSpecific = proposedName !== trackedNav.routeName && proposedName.length > (trackedNav.routeName?.length || 0) && !proposedHasWildcard;
122
57
  const shouldUpdate = !!(trackedNav.routeName && (isWildcardUpgrade || isRawToParameterized || isMoreSpecific));
123
-
124
58
  return { skip: true, shouldUpdate };
125
59
  }
126
-
127
60
  return { skip: false, shouldUpdate: false };
128
61
  }
129
-
130
62
  function addResolvedRoutesToParent(resolvedRoutes, parentRoute) {
131
63
  const existingChildren = parentRoute.children || [];
132
-
133
64
  const newRoutes = resolvedRoutes.filter(
134
- newRoute =>
135
- !existingChildren.some(
136
- existing =>
137
- existing === newRoute ||
138
- (newRoute.path && existing.path === newRoute.path) ||
139
- (newRoute.id && existing.id === newRoute.id),
140
- ),
65
+ (newRoute) => !existingChildren.some(
66
+ (existing) => existing === newRoute || newRoute.path && existing.path === newRoute.path || newRoute.id && existing.id === newRoute.id
67
+ )
141
68
  );
142
-
143
69
  if (newRoutes.length > 0) {
144
70
  parentRoute.children = [...existingChildren, ...newRoutes];
145
71
  }
146
72
  }
147
-
148
- /** Registers a pending lazy route load promise for a span. */
149
73
  function trackLazyRouteLoad(span, promise) {
150
74
  let promises = pendingLazyRouteLoads.get(span);
151
75
  if (!promises) {
152
- promises = new Set();
76
+ promises = /* @__PURE__ */ new Set();
153
77
  pendingLazyRouteLoads.set(span, promises);
154
78
  }
155
79
  promises.add(promise);
156
-
157
- // Clean up when promise resolves/rejects
158
- // oxlint-disable-next-line typescript/no-floating-promises
159
80
  promise.finally(() => {
160
81
  const currentPromises = pendingLazyRouteLoads.get(span);
161
82
  if (currentPromises) {
@@ -163,192 +84,125 @@ function trackLazyRouteLoad(span, promise) {
163
84
  }
164
85
  });
165
86
  }
166
-
167
- /**
168
- * Creates a deferred promise for a span that will be resolved when patchRoutesOnNavigation is called.
169
- * This ensures that patchedEnd waits for patchRoutesOnNavigation to be called before ending the span.
170
- */
171
87
  function createDeferredLazyRoutePromise(span) {
172
- const deferredPromise = new Promise(resolve => {
88
+ const deferredPromise = new Promise((resolve) => {
173
89
  deferredLazyRouteResolvers.set(span, resolve);
174
90
  });
175
-
176
91
  trackLazyRouteLoad(span, deferredPromise);
177
92
  }
178
-
179
- /**
180
- * Resolves the deferred lazy route promise for a span.
181
- * Called when patchRoutesOnNavigation is invoked.
182
- */
183
93
  function resolveDeferredLazyRoutePromise(span) {
184
94
  const resolver = deferredLazyRouteResolvers.get(span);
185
95
  if (resolver) {
186
96
  resolver();
187
97
  deferredLazyRouteResolvers.delete(span);
188
- // Clear the flag so patchSpanEnd doesn't wait unnecessarily for routes that have already loaded
189
- if ((span ).__sentry_may_have_lazy_routes__) {
190
- (span ).__sentry_may_have_lazy_routes__ = false;
98
+ if (span.__sentry_may_have_lazy_routes__) {
99
+ span.__sentry_may_have_lazy_routes__ = false;
191
100
  }
192
101
  }
193
102
  }
194
-
195
- /**
196
- * Processes resolved routes by adding them to allRoutes and checking for nested async handlers.
197
- * When capturedSpan is provided, updates that specific span instead of the current active span.
198
- * This prevents race conditions where a lazy handler resolves after the user has navigated away.
199
- */
200
- function processResolvedRoutes(
201
- resolvedRoutes,
202
- parentRoute,
203
- currentLocation = null,
204
- capturedSpan,
205
- ) {
206
- resolvedRoutes.forEach(child => {
103
+ function processResolvedRoutes(resolvedRoutes, parentRoute, currentLocation = null, capturedSpan) {
104
+ resolvedRoutes.forEach((child) => {
207
105
  allRoutes.add(child);
208
- // Only check for async handlers if the feature is enabled
209
106
  if (_enableAsyncRouteHandlers) {
210
107
  checkRouteForAsyncHandler(child, processResolvedRoutes);
211
108
  }
212
109
  });
213
-
214
110
  if (parentRoute) {
215
- // If a parent route is provided, add the resolved routes as children to the parent route
216
111
  addResolvedRoutesToParent(resolvedRoutes, parentRoute);
217
112
  }
218
-
219
- // Use captured span if provided, otherwise fall back to current active span
220
113
  const targetSpan = capturedSpan ?? getActiveRootSpan();
221
114
  if (targetSpan) {
222
115
  const spanJson = spanToJSON(targetSpan);
223
-
224
- // Skip update if span has already ended (timestamp is set when span.end() is called)
225
116
  if (spanJson.timestamp) {
226
- DEBUG_BUILD && debug.warn('[React Router] Lazy handler resolved after span ended - skipping update');
117
+ DEBUG_BUILD && debug.warn("[React Router] Lazy handler resolved after span ended - skipping update");
227
118
  return;
228
119
  }
229
-
230
120
  const spanOp = spanJson.op;
231
-
232
- // Use captured location for route matching (ensures we match against the correct route)
233
- // Fall back to window.location only if no captured location and no captured span
234
- // (i.e., this is not from an async handler)
235
121
  let location = currentLocation;
236
122
  if (!location && !capturedSpan) {
237
- if (typeof WINDOW !== 'undefined') {
123
+ if (typeof WINDOW !== "undefined") {
238
124
  const globalLocation = WINDOW.location;
239
125
  if (globalLocation?.pathname) {
240
126
  location = { pathname: globalLocation.pathname };
241
127
  }
242
128
  }
243
129
  }
244
-
245
130
  if (location) {
246
- if (spanOp === 'pageload') {
247
- // Re-run the pageload transaction update with the newly loaded routes
131
+ if (spanOp === "pageload") {
248
132
  updatePageloadTransaction({
249
133
  activeRootSpan: targetSpan,
250
134
  location: { pathname: location.pathname },
251
135
  routes: Array.from(allRoutes),
252
- allRoutes: Array.from(allRoutes),
136
+ allRoutes: Array.from(allRoutes)
253
137
  });
254
- } else if (spanOp === 'navigation') {
255
- // For navigation spans, update the name with the newly loaded routes
138
+ } else if (spanOp === "navigation") {
256
139
  updateNavigationSpan(targetSpan, location, Array.from(allRoutes), false, _matchRoutes);
257
140
  }
258
141
  }
259
142
  }
260
143
  }
261
-
262
- /**
263
- * Updates a navigation span with the correct route name after lazy routes have been loaded.
264
- */
265
- function updateNavigationSpan(
266
- activeRootSpan,
267
- location,
268
- allRoutes,
269
- forceUpdate = false,
270
- matchRoutes,
271
- ) {
144
+ function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate = false, matchRoutes) {
272
145
  const spanJson = spanToJSON(activeRootSpan);
273
146
  const currentName = spanJson.description;
274
-
275
- const hasBeenNamed = (activeRootSpan )?.__sentry_navigation_name_set__;
147
+ const hasBeenNamed = activeRootSpan?.__sentry_navigation_name_set__;
276
148
  const currentNameHasWildcard = currentName && transactionNameHasWildcard(currentName);
277
149
  const shouldUpdate = !hasBeenNamed || forceUpdate || currentNameHasWildcard;
278
-
279
150
  if (shouldUpdate && !spanJson.timestamp) {
280
- const currentBranches = matchRoutes(allRoutes, location);
151
+ const currentBranches = matchRoutes(allRoutes2, location);
281
152
  const [name, source] = resolveRouteNameAndSource(
282
153
  location,
283
- allRoutes,
284
- allRoutes,
285
- (currentBranches ) || [],
154
+ allRoutes2,
155
+ allRoutes2,
156
+ currentBranches || [],
286
157
  _basename,
287
158
  _lazyRouteManifest,
288
- _enableAsyncRouteHandlers,
159
+ _enableAsyncRouteHandlers
289
160
  );
290
-
291
161
  const currentSource = spanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
292
- const isImprovement =
293
- name &&
294
- (!currentName || // No current name - always set
295
- (!hasBeenNamed && (currentSource !== 'route' || source === 'route')) || // Not finalized - allow unless downgrading route→url
296
- (currentSource !== 'route' && source === 'route') || // URL → route upgrade
297
- (currentSource === 'route' && source === 'route' && currentNameHasWildcard)); // Route → better route (only if current has wildcard)
162
+ const isImprovement = name && (!currentName || // No current name - always set
163
+ !hasBeenNamed && (currentSource !== "route" || source === "route") || // Not finalized - allow unless downgrading route→url
164
+ currentSource !== "route" && source === "route" || // URL → route upgrade
165
+ currentSource === "route" && source === "route" && currentNameHasWildcard);
298
166
  if (isImprovement) {
299
167
  activeRootSpan.updateName(name);
300
168
  activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
301
-
302
- // Only mark as finalized for non-wildcard route names (allows URL→route upgrades).
303
- if (!transactionNameHasWildcard(name) && source === 'route') {
169
+ if (source === "route") {
170
+ activeRootSpan.setAttribute(URL_TEMPLATE, name);
171
+ }
172
+ if (!transactionNameHasWildcard(name) && source === "route") {
304
173
  addNonEnumerableProperty(
305
- activeRootSpan ,
306
- '__sentry_navigation_name_set__',
307
- true,
174
+ activeRootSpan,
175
+ "__sentry_navigation_name_set__",
176
+ true
308
177
  );
309
178
  }
310
179
  }
311
180
  }
312
181
  }
313
-
314
- function setupRouterSubscription(
315
- router,
316
- routes,
317
- version,
318
- basename,
319
- activeRootSpan,
320
- ) {
182
+ function setupRouterSubscription(router, routes, version, basename, activeRootSpan) {
321
183
  let isInitialPageloadComplete = false;
322
- let hasSeenPageloadSpan = !!activeRootSpan && spanToJSON(activeRootSpan).op === 'pageload';
184
+ let hasSeenPageloadSpan = !!activeRootSpan && spanToJSON(activeRootSpan).op === "pageload";
323
185
  let hasSeenPopAfterPageload = false;
324
186
  let scheduledNavigationHandler = null;
325
187
  let lastHandledPathname = null;
326
-
327
188
  router.subscribe((state) => {
328
189
  if (!isInitialPageloadComplete) {
329
190
  const currentRootSpan = getActiveRootSpan();
330
- const isCurrentlyInPageload = currentRootSpan && spanToJSON(currentRootSpan).op === 'pageload';
331
-
191
+ const isCurrentlyInPageload = currentRootSpan && spanToJSON(currentRootSpan).op === "pageload";
332
192
  if (isCurrentlyInPageload) {
333
193
  hasSeenPageloadSpan = true;
334
194
  } else if (hasSeenPageloadSpan) {
335
- if (state.historyAction === 'POP' && !hasSeenPopAfterPageload) {
195
+ if (state.historyAction === "POP" && !hasSeenPopAfterPageload) {
336
196
  hasSeenPopAfterPageload = true;
337
197
  } else {
338
198
  isInitialPageloadComplete = true;
339
199
  }
340
200
  }
341
201
  }
342
-
343
- const shouldHandleNavigation =
344
- state.historyAction === 'PUSH' || (state.historyAction === 'POP' && isInitialPageloadComplete);
345
-
202
+ const shouldHandleNavigation = state.historyAction === "PUSH" || state.historyAction === "POP" && isInitialPageloadComplete;
346
203
  if (shouldHandleNavigation) {
347
- // Include search and hash to allow query/hash-only navigations
348
- // Use computeLocationKey() to ensure undefined/null values are normalized to empty strings
349
204
  const currentLocationKey = computeLocationKey(state.location);
350
205
  const navigationHandler = () => {
351
- // Prevent multiple calls for the same location within the same navigation cycle
352
206
  if (lastHandledPathname === currentLocationKey) {
353
207
  return;
354
208
  }
@@ -360,207 +214,119 @@ function setupRouterSubscription(
360
214
  navigationType: state.historyAction,
361
215
  version,
362
216
  basename,
363
- allRoutes: Array.from(allRoutes),
217
+ allRoutes: Array.from(allRoutes)
364
218
  });
365
219
  };
366
-
367
- if (state.navigation.state !== 'idle') {
368
- // Navigation in progress - reset if location changed
220
+ if (state.navigation.state !== "idle") {
369
221
  if (lastHandledPathname !== currentLocationKey) {
370
222
  lastHandledPathname = null;
371
223
  }
372
- // Cancel any previously scheduled handler to avoid duplicates
373
224
  if (scheduledNavigationHandler !== null) {
374
225
  cancelScheduledCallback(scheduledNavigationHandler);
375
226
  }
376
227
  scheduledNavigationHandler = scheduleCallback(navigationHandler);
377
228
  } else {
378
- // Navigation completed - cancel scheduled handler if any, then call immediately
379
229
  if (scheduledNavigationHandler !== null) {
380
230
  cancelScheduledCallback(scheduledNavigationHandler);
381
231
  scheduledNavigationHandler = null;
382
232
  }
383
233
  navigationHandler();
384
- // Don't reset - next navigation cycle resets to prevent duplicates within same cycle.
385
234
  }
386
235
  }
387
236
  });
388
237
  }
389
-
390
- /**
391
- * Creates a wrapCreateBrowserRouter function that can be used with all React Router v6 compatible versions.
392
- */
393
- function createV6CompatibleWrapCreateBrowserRouter
394
-
395
- (
396
- createRouterFunction,
397
- version,
398
- ) {
238
+ function createV6CompatibleWrapCreateBrowserRouter(createRouterFunction, version) {
399
239
  if (!_useEffect || !_useLocation || !_useNavigationType || !_matchRoutes) {
400
- DEBUG_BUILD &&
401
- debug.warn(
402
- `reactRouterV${version}Instrumentation was unable to wrap the \`createRouter\` function because of one or more missing parameters.`,
403
- );
404
-
240
+ DEBUG_BUILD && debug.warn(
241
+ `reactRouter${version ? `V${version}` : ""}Instrumentation was unable to wrap the \`createRouter\` function because of one or more missing parameters.`
242
+ );
405
243
  return createRouterFunction;
406
244
  }
407
-
408
- return function (routes, opts) {
245
+ return function(routes, opts) {
409
246
  addRoutesToAllRoutes(routes);
410
-
411
247
  if (_enableAsyncRouteHandlers) {
412
248
  for (const route of routes) {
413
249
  checkRouteForAsyncHandler(route, processResolvedRoutes);
414
250
  }
415
251
  }
416
-
417
- // Capture the active span BEFORE creating the router.
418
- // This is important because the span might end (due to idle timeout) before
419
- // patchRoutesOnNavigation is called by React Router.
420
252
  const activeRootSpan = getActiveRootSpan();
421
-
422
- // If patchRoutesOnNavigation is provided and we have an active span,
423
- // mark the span as having potential lazy routes and create a deferred promise.
424
- const hasPatchRoutesOnNavigation =
425
- opts && 'patchRoutesOnNavigation' in opts && typeof opts.patchRoutesOnNavigation === 'function';
253
+ const hasPatchRoutesOnNavigation = opts && "patchRoutesOnNavigation" in opts && typeof opts.patchRoutesOnNavigation === "function";
426
254
  if (hasPatchRoutesOnNavigation && activeRootSpan) {
427
- // Mark the span as potentially having lazy routes
428
255
  addNonEnumerableProperty(
429
- activeRootSpan ,
430
- '__sentry_may_have_lazy_routes__',
431
- true,
256
+ activeRootSpan,
257
+ "__sentry_may_have_lazy_routes__",
258
+ true
432
259
  );
433
260
  createDeferredLazyRoutePromise(activeRootSpan);
434
261
  }
435
-
436
- // Pass the captured span to wrapPatchRoutesOnNavigation so it uses the same span
437
- // even if the span has ended by the time patchRoutesOnNavigation is called.
438
262
  const wrappedOpts = wrapPatchRoutesOnNavigation(opts, false, activeRootSpan);
439
263
  const router = createRouterFunction(routes, wrappedOpts);
440
264
  const basename = opts?.basename;
441
-
442
- if (router.state.historyAction === 'POP' && activeRootSpan) {
265
+ if (router.state.historyAction === "POP" && activeRootSpan) {
443
266
  updatePageloadTransaction({
444
267
  activeRootSpan,
445
268
  location: router.state.location,
446
269
  routes,
447
270
  basename,
448
- allRoutes: Array.from(allRoutes),
271
+ allRoutes: Array.from(allRoutes)
449
272
  });
450
273
  }
451
-
452
- // Store basename for use in updateNavigationSpan
453
- _basename = basename || '';
454
-
274
+ _basename = basename || "";
455
275
  setupRouterSubscription(router, routes, version, basename, activeRootSpan);
456
-
457
276
  return router;
458
277
  };
459
278
  }
460
-
461
- /**
462
- * Creates a wrapCreateMemoryRouter function that can be used with all React Router v6 compatible versions.
463
- */
464
- function createV6CompatibleWrapCreateMemoryRouter
465
-
466
- (
467
- createRouterFunction,
468
- version,
469
- ) {
279
+ function createV6CompatibleWrapCreateMemoryRouter(createRouterFunction, version) {
470
280
  if (!_useEffect || !_useLocation || !_useNavigationType || !_matchRoutes) {
471
- DEBUG_BUILD &&
472
- debug.warn(
473
- `reactRouterV${version}Instrumentation was unable to wrap the \`createMemoryRouter\` function because of one or more missing parameters.`,
474
- );
475
-
281
+ DEBUG_BUILD && debug.warn(
282
+ `reactRouter${version ? `V${version}` : ""}Instrumentation was unable to wrap the \`createMemoryRouter\` function because of one or more missing parameters.`
283
+ );
476
284
  return createRouterFunction;
477
285
  }
478
-
479
- return function (
480
- routes,
481
- opts
482
-
483
- ,
484
- ) {
286
+ return function(routes, opts) {
485
287
  addRoutesToAllRoutes(routes);
486
-
487
288
  if (_enableAsyncRouteHandlers) {
488
289
  for (const route of routes) {
489
290
  checkRouteForAsyncHandler(route, processResolvedRoutes);
490
291
  }
491
292
  }
492
-
493
- // Capture the active span BEFORE creating the router (same as browser router)
494
293
  const memoryActiveRootSpanEarly = getActiveRootSpan();
495
-
496
- // If patchRoutesOnNavigation is provided and we have an active span,
497
- // mark the span as having potential lazy routes and create a deferred promise.
498
- const hasPatchRoutesOnNavigation =
499
- opts && 'patchRoutesOnNavigation' in opts && typeof opts.patchRoutesOnNavigation === 'function';
294
+ const hasPatchRoutesOnNavigation = opts && "patchRoutesOnNavigation" in opts && typeof opts.patchRoutesOnNavigation === "function";
500
295
  if (hasPatchRoutesOnNavigation && memoryActiveRootSpanEarly) {
501
296
  addNonEnumerableProperty(
502
- memoryActiveRootSpanEarly ,
503
- '__sentry_may_have_lazy_routes__',
504
- true,
297
+ memoryActiveRootSpanEarly,
298
+ "__sentry_may_have_lazy_routes__",
299
+ true
505
300
  );
506
301
  createDeferredLazyRoutePromise(memoryActiveRootSpanEarly);
507
302
  }
508
-
509
303
  const wrappedOpts = wrapPatchRoutesOnNavigation(opts, true, memoryActiveRootSpanEarly);
510
-
511
304
  const router = createRouterFunction(routes, wrappedOpts);
512
305
  const basename = opts?.basename;
513
-
514
- let initialEntry = undefined;
515
-
306
+ let initialEntry = void 0;
516
307
  const initialEntries = opts?.initialEntries;
517
308
  const initialIndex = opts?.initialIndex;
518
-
519
309
  const hasOnlyOneInitialEntry = initialEntries?.length === 1;
520
- const hasIndexedEntry = initialIndex !== undefined && initialEntries?.[initialIndex];
521
-
522
- initialEntry = hasOnlyOneInitialEntry
523
- ? initialEntries[0]
524
- : hasIndexedEntry
525
- ? initialEntries[initialIndex]
526
- : undefined;
527
-
528
- const location = initialEntry
529
- ? typeof initialEntry === 'string'
530
- ? { pathname: initialEntry }
531
- : initialEntry
532
- : router.state.location;
533
-
310
+ const hasIndexedEntry = initialIndex !== void 0 && initialEntries?.[initialIndex];
311
+ initialEntry = hasOnlyOneInitialEntry ? initialEntries[0] : hasIndexedEntry ? initialEntries[initialIndex] : void 0;
312
+ const location = initialEntry ? typeof initialEntry === "string" ? { pathname: initialEntry } : initialEntry : router.state.location;
534
313
  const memoryActiveRootSpan = getActiveRootSpan();
535
-
536
- if (router.state.historyAction === 'POP' && memoryActiveRootSpan) {
314
+ if (router.state.historyAction === "POP" && memoryActiveRootSpan) {
537
315
  updatePageloadTransaction({
538
316
  activeRootSpan: memoryActiveRootSpan,
539
317
  location,
540
318
  routes,
541
319
  basename,
542
- allRoutes: Array.from(allRoutes),
320
+ allRoutes: Array.from(allRoutes)
543
321
  });
544
322
  }
545
-
546
- // Store basename for use in updateNavigationSpan
547
- _basename = basename || '';
548
-
323
+ _basename = basename || "";
549
324
  setupRouterSubscription(router, routes, version, basename, memoryActiveRootSpan);
550
-
551
325
  return router;
552
326
  };
553
327
  }
554
-
555
- /**
556
- * Creates a browser tracing integration that can be used with all React Router v6 compatible versions.
557
- */
558
- function createReactRouterV6CompatibleTracingIntegration(
559
- options,
560
- version,
561
- ) {
328
+ function createReactRouterV6CompatibleTracingIntegration(options, version) {
562
329
  const integration = browserTracingIntegration({ ...options, instrumentPageLoad: false, instrumentNavigation: false });
563
-
564
330
  const {
565
331
  useEffect,
566
332
  useLocation,
@@ -572,44 +338,36 @@ function createReactRouterV6CompatibleTracingIntegration(
572
338
  instrumentPageLoad = true,
573
339
  instrumentNavigation = true,
574
340
  lazyRouteTimeout,
575
- lazyRouteManifest,
341
+ lazyRouteManifest
576
342
  } = options;
577
-
578
343
  return {
579
344
  ...integration,
580
345
  setup(client) {
581
346
  integration.setup(client);
582
-
583
- const finalTimeout = options.finalTimeout ?? 30000;
584
- const defaultMaxWait = (options.idleTimeout ?? 1000) * 3;
347
+ const finalTimeout = options.finalTimeout ?? 3e4;
348
+ const defaultMaxWait = (options.idleTimeout ?? 1e3) * 3;
585
349
  const configuredMaxWait = lazyRouteTimeout ?? defaultMaxWait;
586
-
587
- // Cap Infinity at finalTimeout to prevent indefinite hangs
588
350
  if (configuredMaxWait === Infinity) {
589
351
  _lazyRouteTimeout = finalTimeout;
590
- DEBUG_BUILD &&
591
- debug.log(
592
- '[React Router] lazyRouteTimeout set to Infinity, capping at finalTimeout:',
593
- finalTimeout,
594
- 'ms to prevent indefinite hangs',
595
- );
352
+ DEBUG_BUILD && debug.log(
353
+ "[React Router] lazyRouteTimeout set to Infinity, capping at finalTimeout:",
354
+ finalTimeout,
355
+ "ms to prevent indefinite hangs"
356
+ );
596
357
  } else if (Number.isNaN(configuredMaxWait)) {
597
- DEBUG_BUILD &&
598
- debug.warn('[React Router] lazyRouteTimeout must be a number, falling back to default:', defaultMaxWait);
358
+ DEBUG_BUILD && debug.warn("[React Router] lazyRouteTimeout must be a number, falling back to default:", defaultMaxWait);
599
359
  _lazyRouteTimeout = defaultMaxWait;
600
360
  } else if (configuredMaxWait < 0) {
601
- DEBUG_BUILD &&
602
- debug.warn(
603
- '[React Router] lazyRouteTimeout must be non-negative or Infinity, got:',
604
- configuredMaxWait,
605
- 'falling back to:',
606
- defaultMaxWait,
607
- );
361
+ DEBUG_BUILD && debug.warn(
362
+ "[React Router] lazyRouteTimeout must be non-negative or Infinity, got:",
363
+ configuredMaxWait,
364
+ "falling back to:",
365
+ defaultMaxWait
366
+ );
608
367
  _lazyRouteTimeout = defaultMaxWait;
609
368
  } else {
610
369
  _lazyRouteTimeout = configuredMaxWait;
611
370
  }
612
-
613
371
  _useEffect = useEffect;
614
372
  _useLocation = useLocation;
615
373
  _useNavigationType = useNavigationType;
@@ -617,278 +375,191 @@ function createReactRouterV6CompatibleTracingIntegration(
617
375
  _createRoutesFromChildren = createRoutesFromChildren;
618
376
  _enableAsyncRouteHandlers = enableAsyncRouteHandlers;
619
377
  _lazyRouteManifest = lazyRouteManifest;
620
-
621
- // Initialize the router utils with the required dependencies
622
378
  initializeRouterUtils(matchRoutes, stripBasename || false);
623
379
  },
624
380
  afterAllSetup(client) {
625
381
  integration.afterAllSetup(client);
626
-
627
382
  const initPathName = WINDOW.location?.pathname;
628
383
  if (instrumentPageLoad && initPathName) {
629
384
  startBrowserTracingPageLoadSpan(client, {
630
385
  name: initPathName,
631
386
  attributes: {
632
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
633
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload',
634
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.pageload.react.reactrouter_v${version}`,
635
- },
387
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
388
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "pageload",
389
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.pageload.react.reactrouter${version ? `_v${version}` : ""}`
390
+ }
636
391
  });
637
392
  }
638
-
639
393
  if (instrumentNavigation) {
640
394
  CLIENTS_WITH_INSTRUMENT_NAVIGATION.add(client);
641
395
  }
642
- },
396
+ }
643
397
  };
644
398
  }
645
-
646
399
  function createV6CompatibleWrapUseRoutes(origUseRoutes, version) {
647
400
  if (!_useEffect || !_useLocation || !_useNavigationType || !_matchRoutes) {
648
- DEBUG_BUILD &&
649
- debug.warn(
650
- 'reactRouterV6Instrumentation was unable to wrap `useRoutes` because of one or more missing parameters.',
651
- );
652
-
401
+ DEBUG_BUILD && debug.warn(
402
+ "reactRouterV6Instrumentation was unable to wrap `useRoutes` because of one or more missing parameters."
403
+ );
653
404
  return origUseRoutes;
654
405
  }
655
-
656
- const SentryRoutes
657
-
658
- = (props) => {
406
+ const SentryRoutes = (props) => {
659
407
  const isMountRenderPass = React.useRef(true);
660
408
  const { routes, locationArg } = props;
661
-
662
409
  const Routes = origUseRoutes(routes, locationArg);
663
-
664
410
  const location = _useLocation();
665
411
  const navigationType = _useNavigationType();
666
-
667
- // A value with stable identity to either pick `locationArg` if available or `location` if not
668
- const stableLocationParam =
669
- typeof locationArg === 'string' || locationArg?.pathname ? (locationArg ) : location;
670
-
671
- _useEffect(() => {
672
- const normalizedLocation =
673
- typeof stableLocationParam === 'string' ? { pathname: stableLocationParam } : stableLocationParam;
674
-
412
+ const stableLocationParam = typeof locationArg === "string" || locationArg?.pathname ? locationArg : location;
413
+ useIsomorphicLayoutEffect(() => {
414
+ const normalizedLocation = typeof stableLocationParam === "string" ? { pathname: stableLocationParam } : stableLocationParam;
675
415
  if (isMountRenderPass.current) {
676
416
  addRoutesToAllRoutes(routes);
677
-
678
417
  updatePageloadTransaction({
679
418
  activeRootSpan: getActiveRootSpan(),
680
419
  location: normalizedLocation,
681
420
  routes,
682
- allRoutes: Array.from(allRoutes),
421
+ allRoutes: Array.from(allRoutes)
683
422
  });
684
423
  isMountRenderPass.current = false;
685
424
  } else {
686
- // Note: Component-based routes don't support lazy route tracking via lazyRouteTimeout
687
- // because React.lazy() loads happen at the component level, not the router level.
688
- // Use createBrowserRouter with patchRoutesOnNavigation for lazy route tracking.
689
425
  handleNavigation({
690
426
  location: normalizedLocation,
691
427
  routes,
692
428
  navigationType,
693
429
  version,
694
- allRoutes: Array.from(allRoutes),
430
+ allRoutes: Array.from(allRoutes)
695
431
  });
696
432
  }
697
433
  }, [navigationType, stableLocationParam]);
698
-
699
434
  return Routes;
700
435
  };
701
-
702
- // eslint-disable-next-line react/display-name
703
436
  return (routes, locationArg) => {
704
- return React.createElement(SentryRoutes, { routes: routes, locationArg: locationArg,} );
437
+ return /* @__PURE__ */ React.createElement(SentryRoutes, { routes, locationArg });
705
438
  };
706
439
  }
707
- function wrapPatchRoutesOnNavigation(
708
- opts,
709
- isMemoryRouter = false,
710
- capturedSpan,
711
- ) {
712
- if (!opts || !('patchRoutesOnNavigation' in opts) || typeof opts.patchRoutesOnNavigation !== 'function') {
440
+ function wrapPatchRoutesOnNavigation(opts, isMemoryRouter = false, capturedSpan) {
441
+ if (!opts || !("patchRoutesOnNavigation" in opts) || typeof opts.patchRoutesOnNavigation !== "function") {
713
442
  return opts || {};
714
443
  }
715
-
716
444
  const originalPatchRoutes = opts.patchRoutesOnNavigation;
717
445
  return {
718
446
  ...opts,
719
447
  patchRoutesOnNavigation: async (args) => {
720
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
721
- const targetPath = (args )?.path;
722
-
723
- // Use current active span if available, otherwise fall back to captured span (from router creation time).
724
- // This ensures navigation spans use their own span (not the stale pageload span), while still
725
- // supporting pageload spans that may have ended before patchRoutesOnNavigation is called.
448
+ const targetPath = args?.path;
726
449
  const activeRootSpan = getActiveRootSpan() ?? capturedSpan;
727
-
728
450
  if (!isMemoryRouter) {
729
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
730
- const originalPatch = (args )?.patch;
731
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
732
- const matches = (args )?.matches ;
451
+ const originalPatch = args?.patch;
452
+ const matches = args?.matches;
733
453
  if (originalPatch) {
734
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
735
- (args ).patch = (routeId, children) => {
454
+ args.patch = (routeId, children) => {
736
455
  addRoutesToAllRoutes(children);
737
-
738
- // Find the parent route from matches and attach children to it in allRoutes.
739
- // React Router's patch attaches children to its internal route copies, but we need
740
- // to update the route objects in our allRoutes Set for proper route matching.
741
456
  if (matches && matches.length > 0) {
742
457
  const leafMatch = matches[matches.length - 1];
743
458
  const leafRoute = leafMatch?.route;
744
459
  if (leafRoute) {
745
- // Find the matching route in allRoutes by id, reference, or path
746
- const matchingRoute = Array.from(allRoutes).find(route => {
747
- const idMatches = route.id !== undefined && route.id === routeId;
460
+ const matchingRoute = Array.from(allRoutes).find((route) => {
461
+ const idMatches = route.id !== void 0 && route.id === routeId;
748
462
  const referenceMatches = route === leafRoute;
749
- const pathMatches =
750
- route.path !== undefined && leafRoute.path !== undefined && route.path === leafRoute.path;
751
-
463
+ const pathMatches = route.path !== void 0 && leafRoute.path !== void 0 && route.path === leafRoute.path;
752
464
  return idMatches || referenceMatches || pathMatches;
753
465
  });
754
-
755
466
  if (matchingRoute) {
756
467
  addResolvedRoutesToParent(children, matchingRoute);
757
468
  }
758
469
  }
759
470
  }
760
-
761
- // Use the captured activeRootSpan instead of getActiveRootSpan() to avoid race conditions
762
- // where user navigates away during lazy route loading and we'd update the wrong span
763
- const spanJson = activeRootSpan ? spanToJSON(activeRootSpan) : undefined;
764
- // Only update if we have a valid targetPath (patchRoutesOnNavigation can be called without path),
765
- // the captured span exists, hasn't ended, and is a navigation span
766
- if (
767
- targetPath &&
768
- activeRootSpan &&
769
- spanJson &&
770
- !spanJson.timestamp && // Span hasn't ended yet
771
- spanJson.op === 'navigation'
772
- ) {
471
+ const spanJson = activeRootSpan ? spanToJSON(activeRootSpan) : void 0;
472
+ if (targetPath && activeRootSpan && spanJson && !spanJson.timestamp && // Span hasn't ended yet
473
+ spanJson.op === "navigation") {
773
474
  updateNavigationSpan(
774
475
  activeRootSpan,
775
- { pathname: targetPath, search: '', hash: '', state: null, key: 'default' },
476
+ { pathname: targetPath, search: "", hash: "", state: null, key: "default" },
776
477
  Array.from(allRoutes),
777
478
  true,
778
- _matchRoutes,
479
+ _matchRoutes
779
480
  );
780
481
  }
781
482
  return originalPatch(routeId, children);
782
483
  };
783
484
  }
784
485
  }
785
-
786
486
  const lazyLoadPromise = (async () => {
787
- // Set context so async handlers can access correct targetPath and span
788
487
  const contextToken = setNavigationContext(targetPath, activeRootSpan);
789
488
  let result;
790
489
  try {
791
490
  result = await originalPatchRoutes(args);
792
491
  } finally {
793
492
  clearNavigationContext(contextToken);
794
- // Resolve the deferred promise now that patchRoutesOnNavigation has completed.
795
- // This ensures patchedEnd has waited long enough for the lazy routes to load.
796
493
  if (activeRootSpan) {
797
494
  resolveDeferredLazyRoutePromise(activeRootSpan);
798
495
  }
799
496
  }
800
-
801
- // Use the captured activeRootSpan instead of getActiveRootSpan() to avoid race conditions
802
- // where user navigates away during lazy route loading and we'd update the wrong span
803
- const spanJson = activeRootSpan ? spanToJSON(activeRootSpan) : undefined;
804
- if (
805
- activeRootSpan &&
806
- spanJson &&
807
- !spanJson.timestamp && // Span hasn't ended yet
808
- spanJson.op === 'navigation'
809
- ) {
810
- // Use targetPath consistently - don't fall back to WINDOW.location which may have changed
811
- // if the user navigated away during async loading
497
+ const spanJson = activeRootSpan ? spanToJSON(activeRootSpan) : void 0;
498
+ if (activeRootSpan && spanJson && !spanJson.timestamp && // Span hasn't ended yet
499
+ spanJson.op === "navigation") {
812
500
  const pathname = targetPath;
813
-
814
501
  if (pathname) {
815
502
  updateNavigationSpan(
816
503
  activeRootSpan,
817
- { pathname, search: '', hash: '', state: null, key: 'default' },
504
+ { pathname, search: "", hash: "", state: null, key: "default" },
818
505
  Array.from(allRoutes),
819
506
  false,
820
- _matchRoutes,
507
+ _matchRoutes
821
508
  );
822
509
  }
823
510
  }
824
-
825
511
  return result;
826
512
  })();
827
-
828
513
  if (activeRootSpan) {
829
514
  trackLazyRouteLoad(activeRootSpan, lazyLoadPromise);
830
515
  }
831
-
832
516
  return lazyLoadPromise;
833
- },
517
+ }
834
518
  };
835
519
  }
836
-
837
- // eslint-disable-next-line complexity
838
- function handleNavigation(opts
839
-
840
- ) {
841
- const { location, routes, navigationType, version, matches, basename, allRoutes } = opts;
842
- const branches = Array.isArray(matches) ? matches : _matchRoutes(allRoutes || routes, location, basename);
843
-
520
+ function handleNavigation(opts) {
521
+ const { location, routes, navigationType, version, matches, basename, allRoutes: allRoutes2 } = opts;
522
+ const branches = Array.isArray(matches) ? matches : _matchRoutes(allRoutes2 || routes, location, basename);
844
523
  const client = getClient();
845
524
  if (!client || !CLIENTS_WITH_INSTRUMENT_NAVIGATION.has(client)) {
846
525
  return;
847
526
  }
848
-
849
527
  const activeRootSpan = getActiveRootSpan();
850
- if (activeRootSpan && spanToJSON(activeRootSpan).op === 'pageload' && navigationType === 'POP') {
528
+ if (activeRootSpan && spanToJSON(activeRootSpan).op === "pageload" && navigationType === "POP") {
851
529
  return;
852
530
  }
853
-
854
- if ((navigationType === 'PUSH' || navigationType === 'POP') && branches) {
531
+ if ((navigationType === "PUSH" || navigationType === "POP") && branches) {
855
532
  const [name, source] = resolveRouteNameAndSource(
856
533
  location,
857
- allRoutes || routes,
858
- allRoutes || routes,
859
- branches ,
534
+ allRoutes2 || routes,
535
+ allRoutes2 || routes,
536
+ branches,
860
537
  basename,
861
538
  _lazyRouteManifest,
862
- _enableAsyncRouteHandlers,
539
+ _enableAsyncRouteHandlers
863
540
  );
864
-
865
541
  const locationKey = computeLocationKey(location);
866
542
  const trackedNav = activeNavigationSpans.get(client);
867
-
868
- // Determine if this navigation should be skipped as a duplicate
869
- const trackedSpanHasEnded =
870
- trackedNav && !trackedNav.isPlaceholder ? !!spanToJSON(trackedNav.span).timestamp : false;
543
+ const trackedSpanHasEnded = trackedNav && !trackedNav.isPlaceholder ? !!spanToJSON(trackedNav.span).timestamp : false;
871
544
  const { skip, shouldUpdate } = shouldSkipNavigation(trackedNav, locationKey, name, trackedSpanHasEnded);
872
-
873
545
  if (skip) {
874
546
  if (shouldUpdate && trackedNav) {
875
547
  const oldName = trackedNav.routeName;
876
-
877
548
  if (trackedNav.isPlaceholder) {
878
- // Update placeholder's route name - the real span will be created with this name
879
549
  trackedNav.routeName = name;
880
- DEBUG_BUILD &&
881
- debug.log(
882
- `[Tracing] Updated placeholder navigation name from "${oldName}" to "${name}" (will apply to real span)`,
883
- );
550
+ DEBUG_BUILD && debug.log(
551
+ `[Tracing] Updated placeholder navigation name from "${oldName}" to "${name}" (will apply to real span)`
552
+ );
884
553
  } else {
885
- // Update existing real span from wildcard to parameterized route name
886
554
  trackedNav.span.updateName(name);
887
- trackedNav.span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source );
555
+ trackedNav.span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
556
+ if (source === "route") {
557
+ trackedNav.span.setAttribute(URL_TEMPLATE, name);
558
+ }
888
559
  addNonEnumerableProperty(
889
- trackedNav.span ,
890
- '__sentry_navigation_name_set__',
891
- true,
560
+ trackedNav.span,
561
+ "__sentry_navigation_name_set__",
562
+ true
892
563
  );
893
564
  trackedNav.routeName = name;
894
565
  DEBUG_BUILD && debug.log(`[Tracing] Updated navigation span name from "${oldName}" to "${name}"`);
@@ -898,191 +569,128 @@ function handleNavigation(opts
898
569
  }
899
570
  return;
900
571
  }
901
-
902
- // Create new navigation span (first navigation or legitimate new navigation)
903
- // Reserve the spot in the map first to prevent race conditions
904
- // Mark as placeholder to prevent concurrent handleNavigation calls from creating duplicates
905
- const placeholderSpan = { end: () => {} } ;
572
+ const placeholderSpan = { end: () => {
573
+ } };
906
574
  const placeholderEntry = {
907
575
  span: placeholderSpan,
908
576
  routeName: name,
909
577
  pathname: location.pathname,
910
578
  locationKey,
911
- isPlaceholder: true ,
579
+ isPlaceholder: true
912
580
  };
913
581
  activeNavigationSpans.set(client, placeholderEntry);
914
-
915
582
  let navigationSpan;
916
583
  try {
917
584
  navigationSpan = startBrowserTracingNavigationSpan(client, {
918
- name: placeholderEntry.routeName, // Use placeholder's routeName in case it was updated
585
+ name: placeholderEntry.routeName,
586
+ // Use placeholder's routeName in case it was updated
919
587
  attributes: {
920
588
  [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
921
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
922
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.navigation.react.reactrouter_v${version}`,
923
- },
589
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
590
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.navigation.react.reactrouter${version ? `_v${version}` : ""}`,
591
+ ...source === "route" && { [URL_TEMPLATE]: placeholderEntry.routeName }
592
+ }
924
593
  });
925
594
  } catch (e) {
926
- // If span creation fails, remove the placeholder so we don't block future navigations
927
595
  activeNavigationSpans.delete(client);
928
596
  throw e;
929
597
  }
930
-
931
598
  if (navigationSpan) {
932
- // Update the map with the real span (isPlaceholder omitted, defaults to false)
933
599
  activeNavigationSpans.set(client, {
934
600
  span: navigationSpan,
935
- routeName: placeholderEntry.routeName, // Use the (potentially updated) placeholder routeName
601
+ routeName: placeholderEntry.routeName,
602
+ // Use the (potentially updated) placeholder routeName
936
603
  pathname: location.pathname,
937
- locationKey,
604
+ locationKey
938
605
  });
939
- patchSpanEnd(navigationSpan, location, routes, basename, 'navigation');
606
+ patchSpanEnd(navigationSpan, location, routes, basename, "navigation");
940
607
  } else {
941
- // If no span was created, remove the placeholder
942
608
  activeNavigationSpans.delete(client);
943
609
  }
944
610
  }
945
611
  }
946
-
947
- /* Only exported for testing purposes */
948
612
  function addRoutesToAllRoutes(routes) {
949
- routes.forEach(route => {
613
+ routes.forEach((route) => {
950
614
  const extractedChildRoutes = getChildRoutesRecursively(route);
951
-
952
- extractedChildRoutes.forEach(r => {
615
+ extractedChildRoutes.forEach((r) => {
953
616
  allRoutes.add(r);
954
617
  });
955
618
  });
956
619
  }
957
-
958
- function getChildRoutesRecursively(route, allRoutes = new Set()) {
959
- if (!allRoutes.has(route)) {
960
- allRoutes.add(route);
961
-
620
+ function getChildRoutesRecursively(route, allRoutes2 = /* @__PURE__ */ new Set()) {
621
+ if (!allRoutes2.has(route)) {
622
+ allRoutes2.add(route);
962
623
  if (route.children && !route.index) {
963
- route.children.forEach(child => {
964
- const childRoutes = getChildRoutesRecursively(child, allRoutes);
965
-
966
- childRoutes.forEach(r => {
967
- allRoutes.add(r);
624
+ route.children.forEach((child) => {
625
+ const childRoutes = getChildRoutesRecursively(child, allRoutes2);
626
+ childRoutes.forEach((r) => {
627
+ allRoutes2.add(r);
968
628
  });
969
629
  });
970
630
  }
971
631
  }
972
-
973
- return allRoutes;
632
+ return allRoutes2;
974
633
  }
975
-
976
634
  function updatePageloadTransaction({
977
635
  activeRootSpan,
978
636
  location,
979
637
  routes,
980
638
  matches,
981
639
  basename,
982
- allRoutes,
983
- }
984
-
985
- ) {
986
- const branches = Array.isArray(matches)
987
- ? matches
988
- : (_matchRoutes(allRoutes || routes, location, basename) );
989
-
640
+ allRoutes: allRoutes2
641
+ }) {
642
+ const branches = Array.isArray(matches) ? matches : _matchRoutes(allRoutes2 || routes, location, basename);
990
643
  if (branches) {
991
644
  const [name, source] = resolveRouteNameAndSource(
992
645
  location,
993
- allRoutes || routes,
994
- allRoutes || routes,
646
+ allRoutes2 || routes,
647
+ allRoutes2 || routes,
995
648
  branches,
996
649
  basename,
997
650
  _lazyRouteManifest,
998
- _enableAsyncRouteHandlers,
651
+ _enableAsyncRouteHandlers
999
652
  );
1000
-
1001
- getCurrentScope().setTransactionName(name || '/');
1002
-
653
+ getCurrentScope().setTransactionName(name || "/");
1003
654
  if (activeRootSpan) {
1004
655
  activeRootSpan.updateName(name);
1005
656
  activeRootSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
1006
-
1007
- // Patch span.end() to ensure we update the name one last time before the span is sent
1008
- patchSpanEnd(activeRootSpan, location, routes, basename, 'pageload');
657
+ if (source === "route") {
658
+ activeRootSpan.setAttribute(URL_TEMPLATE, name);
659
+ }
660
+ patchSpanEnd(activeRootSpan, location, routes, basename, "pageload");
1009
661
  }
1010
662
  } else if (activeRootSpan) {
1011
- // Even if branches is null (can happen when lazy routes haven't loaded yet),
1012
- // we still need to patch span.end() so that when lazy routes load and the span ends,
1013
- // we can update the transaction name correctly.
1014
- patchSpanEnd(activeRootSpan, location, routes, basename, 'pageload');
663
+ patchSpanEnd(activeRootSpan, location, routes, basename, "pageload");
1015
664
  }
1016
665
  }
1017
-
1018
- /**
1019
- * Determines if a span name should be updated during wildcard route resolution.
1020
- *
1021
- * Update conditions (in priority order):
1022
- * 1. No current name + allowNoCurrentName: true → always update (pageload spans)
1023
- * 2. Current name has wildcard + new is route without wildcard → upgrade (e.g., "/users/*" → "/users/:id")
1024
- * 3. Current source is not 'route' + new source is 'route' → upgrade (e.g., URL → parameterized route)
1025
- *
1026
- * @param currentName - The current span name (may be undefined)
1027
- * @param currentSource - The current span source ('route', 'url', or undefined)
1028
- * @param newName - The proposed new span name
1029
- * @param newSource - The proposed new span source
1030
- * @param allowNoCurrentName - If true, allow updates when there's no current name (for pageload spans)
1031
- * @returns true if the span name should be updated
1032
- */
1033
- function shouldUpdateWildcardSpanName(
1034
- currentName,
1035
- currentSource,
1036
- newName,
1037
- newSource,
1038
- allowNoCurrentName = false,
1039
- ) {
666
+ function shouldUpdateWildcardSpanName(currentName, currentSource, newName, newSource, allowNoCurrentName = false) {
1040
667
  if (!newName) {
1041
668
  return false;
1042
669
  }
1043
-
1044
670
  if (!currentName && allowNoCurrentName) {
1045
671
  return true;
1046
672
  }
1047
-
1048
673
  const hasWildcard = currentName && transactionNameHasWildcard(currentName);
1049
-
1050
- if (hasWildcard && newSource === 'route' && !transactionNameHasWildcard(newName)) {
674
+ if (hasWildcard && newSource === "route" && !transactionNameHasWildcard(newName)) {
1051
675
  return true;
1052
676
  }
1053
-
1054
- if (currentSource !== 'route' && newSource === 'route') {
677
+ if (currentSource !== "route" && newSource === "route") {
1055
678
  return true;
1056
679
  }
1057
-
1058
680
  return false;
1059
681
  }
1060
-
1061
- function tryUpdateSpanNameBeforeEnd(
1062
- span,
1063
- spanJson,
1064
- currentName,
1065
- location,
1066
- routes,
1067
- basename,
1068
- spanType,
1069
- allRoutes,
1070
- ) {
682
+ function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes, basename, spanType, allRoutes2) {
1071
683
  try {
1072
684
  const currentSource = spanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
1073
-
1074
- if (currentSource === 'route' && currentName && !transactionNameHasWildcard(currentName)) {
685
+ if (currentSource === "route" && currentName && !transactionNameHasWildcard(currentName)) {
1075
686
  return;
1076
687
  }
1077
-
1078
- const currentAllRoutes = Array.from(allRoutes);
688
+ const currentAllRoutes = Array.from(allRoutes2);
1079
689
  const routesToUse = currentAllRoutes.length > 0 ? currentAllRoutes : routes;
1080
- const branches = _matchRoutes(routesToUse, location, basename) ;
1081
-
690
+ const branches = _matchRoutes(routesToUse, location, basename);
1082
691
  if (!branches) {
1083
692
  return;
1084
693
  }
1085
-
1086
694
  const [name, source] = resolveRouteNameAndSource(
1087
695
  location,
1088
696
  routesToUse,
@@ -1090,82 +698,51 @@ function tryUpdateSpanNameBeforeEnd(
1090
698
  branches,
1091
699
  basename,
1092
700
  _lazyRouteManifest,
1093
- _enableAsyncRouteHandlers,
701
+ _enableAsyncRouteHandlers
1094
702
  );
1095
-
1096
703
  const isImprovement = shouldUpdateWildcardSpanName(currentName, currentSource, name, source, true);
1097
- const spanNotEnded = spanType === 'pageload' || !spanJson.timestamp;
1098
-
704
+ const spanNotEnded = spanType === "pageload" || !spanJson.timestamp;
1099
705
  if (isImprovement && spanNotEnded) {
1100
706
  span.updateName(name);
1101
707
  span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
708
+ if (source === "route") {
709
+ span.setAttribute(URL_TEMPLATE, name);
710
+ }
1102
711
  }
1103
712
  } catch (error) {
1104
713
  DEBUG_BUILD && debug.warn(`Error updating span details before ending: ${error}`);
1105
714
  }
1106
715
  }
1107
-
1108
- /**
1109
- * Patches the span.end() method to update the transaction name one last time before the span is sent.
1110
- * This handles cases where the span is cancelled early (e.g., document.hidden) before lazy routes have finished loading.
1111
- */
1112
- function patchSpanEnd(
1113
- span,
1114
- location,
1115
- routes,
1116
- basename,
1117
- spanType,
1118
- ) {
1119
- const patchedPropertyName = `__sentry_${spanType}_end_patched__` ;
1120
- const hasEndBeenPatched = (span )?.[patchedPropertyName];
1121
-
716
+ function patchSpanEnd(span, location, routes, basename, spanType) {
717
+ const patchedPropertyName = `__sentry_${spanType}_end_patched__`;
718
+ const hasEndBeenPatched = span?.[patchedPropertyName];
1122
719
  if (hasEndBeenPatched || !span.end) {
1123
720
  return;
1124
721
  }
1125
-
1126
- // Uses global allRoutes to access lazy-loaded routes added after this function was called.
1127
-
1128
722
  const originalEnd = span.end.bind(span);
1129
723
  let endCalled = false;
1130
-
1131
724
  span.end = function patchedEnd(...args) {
1132
725
  if (endCalled) {
1133
726
  return;
1134
727
  }
1135
728
  endCalled = true;
1136
-
1137
- // Capture timestamp immediately to avoid delay from async operations
1138
- // If no timestamp was provided, capture the current time now
1139
- const endTimestamp = args.length > 0 ? args[0] : Date.now() / 1000;
1140
-
729
+ const endTimestamp = args.length > 0 ? args[0] : Date.now() / 1e3;
1141
730
  const spanJson = spanToJSON(span);
1142
731
  const currentName = spanJson.description;
1143
732
  const currentSource = spanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
1144
-
1145
- // Helper to clean up activeNavigationSpans after span ends
1146
733
  const cleanupNavigationSpan = () => {
1147
734
  const client = getClient();
1148
- if (client && spanType === 'navigation') {
735
+ if (client && spanType === "navigation") {
1149
736
  const trackedNav = activeNavigationSpans.get(client);
1150
737
  if (trackedNav && trackedNav.span === span) {
1151
738
  activeNavigationSpans.delete(client);
1152
739
  }
1153
740
  }
1154
741
  };
1155
-
1156
742
  const pendingPromises = pendingLazyRouteLoads.get(span);
1157
- const mayHaveLazyRoutes = (span ).__sentry_may_have_lazy_routes__;
1158
-
1159
- // Wait for lazy routes if:
1160
- // 1. (There are pending promises OR the span was marked as potentially having lazy routes) AND
1161
- // 2. Current name exists AND
1162
- // 3. Either the name has a wildcard OR the source is not 'route' (URL-based names)
1163
- const hasPendingOrMayHaveLazyRoutes = (pendingPromises && pendingPromises.size > 0) || mayHaveLazyRoutes;
1164
- const shouldWaitForLazyRoutes =
1165
- hasPendingOrMayHaveLazyRoutes &&
1166
- currentName &&
1167
- (transactionNameHasWildcard(currentName) || currentSource !== 'route');
1168
-
743
+ const mayHaveLazyRoutes = span.__sentry_may_have_lazy_routes__;
744
+ const hasPendingOrMayHaveLazyRoutes = pendingPromises && pendingPromises.size > 0 || mayHaveLazyRoutes;
745
+ const shouldWaitForLazyRoutes = hasPendingOrMayHaveLazyRoutes && currentName && (transactionNameHasWildcard(currentName) || currentSource !== "route");
1169
746
  if (shouldWaitForLazyRoutes) {
1170
747
  if (_lazyRouteTimeout === 0) {
1171
748
  tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes, basename, spanType, allRoutes);
@@ -1173,107 +750,74 @@ function patchSpanEnd(
1173
750
  originalEnd(endTimestamp);
1174
751
  return;
1175
752
  }
1176
-
1177
- // If we have pending promises, wait for them. Otherwise, just wait for the timeout.
1178
- // This handles the case where we know lazy routes might load but patchRoutesOnNavigation
1179
- // hasn't been called yet.
1180
- const timeoutPromise = new Promise(r => setTimeout(r, _lazyRouteTimeout));
753
+ const timeoutPromise = new Promise((r) => setTimeout(r, _lazyRouteTimeout));
1181
754
  let waitPromise;
1182
-
1183
755
  if (pendingPromises && pendingPromises.size > 0) {
1184
- const allSettled = Promise.allSettled(pendingPromises).then(() => {});
756
+ const allSettled = Promise.allSettled(pendingPromises).then(() => {
757
+ });
1185
758
  waitPromise = _lazyRouteTimeout === Infinity ? allSettled : Promise.race([allSettled, timeoutPromise]);
1186
759
  } else {
1187
- // No pending promises yet, but we know lazy routes might load
1188
- // Wait for the timeout to give React Router time to call patchRoutesOnNavigation
1189
760
  waitPromise = timeoutPromise;
1190
761
  }
1191
-
1192
- waitPromise
1193
- .then(() => {
1194
- const updatedSpanJson = spanToJSON(span);
1195
- tryUpdateSpanNameBeforeEnd(
1196
- span,
1197
- updatedSpanJson,
1198
- updatedSpanJson.description,
1199
- location,
1200
- routes,
1201
- basename,
1202
- spanType,
1203
- allRoutes,
1204
- );
1205
- cleanupNavigationSpan();
1206
- originalEnd(endTimestamp);
1207
- })
1208
- .catch(() => {
1209
- cleanupNavigationSpan();
1210
- originalEnd(endTimestamp);
1211
- });
762
+ waitPromise.then(() => {
763
+ const updatedSpanJson = spanToJSON(span);
764
+ tryUpdateSpanNameBeforeEnd(
765
+ span,
766
+ updatedSpanJson,
767
+ updatedSpanJson.description,
768
+ location,
769
+ routes,
770
+ basename,
771
+ spanType,
772
+ allRoutes
773
+ );
774
+ cleanupNavigationSpan();
775
+ originalEnd(endTimestamp);
776
+ }).catch(() => {
777
+ cleanupNavigationSpan();
778
+ originalEnd(endTimestamp);
779
+ });
1212
780
  return;
1213
781
  }
1214
-
1215
782
  tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes, basename, spanType, allRoutes);
1216
783
  cleanupNavigationSpan();
1217
784
  originalEnd(endTimestamp);
1218
785
  };
1219
-
1220
- addNonEnumerableProperty(span , patchedPropertyName, true);
786
+ addNonEnumerableProperty(span, patchedPropertyName, true);
1221
787
  }
1222
-
1223
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1224
- function createV6CompatibleWithSentryReactRouterRouting(
1225
- Routes,
1226
- version,
1227
- ) {
788
+ function createV6CompatibleWithSentryReactRouterRouting(Routes, version) {
1228
789
  if (!_useEffect || !_useLocation || !_useNavigationType || !_createRoutesFromChildren || !_matchRoutes) {
1229
- DEBUG_BUILD &&
1230
- debug.warn(`reactRouterV6Instrumentation was unable to wrap Routes because of one or more missing parameters.
790
+ DEBUG_BUILD && debug.warn(`reactRouterV6Instrumentation was unable to wrap Routes because of one or more missing parameters.
1231
791
  useEffect: ${_useEffect}. useLocation: ${_useLocation}. useNavigationType: ${_useNavigationType}.
1232
792
  createRoutesFromChildren: ${_createRoutesFromChildren}. matchRoutes: ${_matchRoutes}.`);
1233
-
1234
793
  return Routes;
1235
794
  }
1236
-
1237
795
  const SentryRoutes = (props) => {
1238
796
  const isMountRenderPass = React.useRef(true);
1239
-
1240
797
  const location = _useLocation();
1241
798
  const navigationType = _useNavigationType();
1242
-
1243
- _useEffect(
799
+ useIsomorphicLayoutEffect(
1244
800
  () => {
1245
- const routes = _createRoutesFromChildren(props.children) ;
1246
-
801
+ const routes = _createRoutesFromChildren(props.children);
1247
802
  if (isMountRenderPass.current) {
1248
803
  addRoutesToAllRoutes(routes);
1249
-
1250
804
  updatePageloadTransaction({
1251
805
  activeRootSpan: getActiveRootSpan(),
1252
806
  location,
1253
807
  routes,
1254
- allRoutes: Array.from(allRoutes),
808
+ allRoutes: Array.from(allRoutes)
1255
809
  });
1256
810
  isMountRenderPass.current = false;
1257
811
  } else {
1258
- // Note: Component-based routes don't support lazy route tracking via lazyRouteTimeout
1259
- // because React.lazy() loads happen at the component level, not the router level.
1260
- // Use createBrowserRouter with patchRoutesOnNavigation for lazy route tracking.
1261
812
  handleNavigation({ location, routes, navigationType, version, allRoutes: Array.from(allRoutes) });
1262
813
  }
1263
814
  },
1264
815
  // Re-run only on location/navigation changes, not children changes
1265
- [location, navigationType],
816
+ [location, navigationType]
1266
817
  );
1267
-
1268
- // @ts-expect-error Setting more specific React Component typing for `R` generic above
1269
- // will break advanced type inference done by react router params
1270
- return React.createElement(Routes, { ...props,} );
818
+ return /* @__PURE__ */ React.createElement(Routes, { ...props });
1271
819
  };
1272
-
1273
820
  hoistNonReactStatics(SentryRoutes, Routes);
1274
-
1275
- // @ts-expect-error Setting more specific React Component typing for `R` generic above
1276
- // will break advanced type inference done by react router params
1277
821
  return SentryRoutes;
1278
822
  }
1279
823