@@ -2,49 +2,82 @@ import { WINDOW, rewriteFramesIntegration } from '@sentry/browser';
2
2
import { defineIntegration } from '@sentry/core' ;
3
3
4
4
export const nextjsClientStackFrameNormalizationIntegration = defineIntegration (
5
- ( { assetPrefix, basePath } : { assetPrefix ?: string ; basePath ?: string } ) => {
6
- const windowOrigin = WINDOW . location . origin ;
7
-
5
+ ( {
6
+ assetPrefix,
7
+ basePath,
8
+ rewriteFramesAssetPrefixPath,
9
+ experimentalThirdPartyOriginStackFrames,
10
+ } : {
11
+ assetPrefix ?: string ;
12
+ basePath ?: string ;
13
+ rewriteFramesAssetPrefixPath : string ;
14
+ experimentalThirdPartyOriginStackFrames : boolean ;
15
+ } ) => {
8
16
const rewriteFramesInstance = rewriteFramesIntegration ( {
9
17
// Turn `<origin>/<path>/_next/static/...` into `app:///_next/static/...`
10
18
iteratee : frame => {
11
- // A filename starting with the local origin and not ending with JS is most likely JS in HTML which we do not want to rewrite
12
- if ( frame . filename ?. startsWith ( windowOrigin ) && ! frame . filename . endsWith ( '.js' ) ) {
13
- return frame ;
14
- }
19
+ if ( experimentalThirdPartyOriginStackFrames ) {
20
+ const windowOrigin = WINDOW . location . origin ;
21
+ // A filename starting with the local origin and not ending with JS is most likely JS in HTML which we do not want to rewrite
22
+ if ( frame . filename ?. startsWith ( windowOrigin ) && ! frame . filename . endsWith ( '.js' ) ) {
23
+ return frame ;
24
+ }
15
25
16
- if ( assetPrefix ) {
17
- // If the user defined an asset prefix, we need to strip it so that we can match it with uploaded sourcemaps.
18
- // assetPrefix always takes priority over basePath.
19
- if ( frame . filename ?. startsWith ( assetPrefix ) ) {
20
- frame . filename = frame . filename . replace ( assetPrefix , 'app://' ) ;
26
+ if ( assetPrefix ) {
27
+ // If the user defined an asset prefix, we need to strip it so that we can match it with uploaded sourcemaps.
28
+ // assetPrefix always takes priority over basePath.
29
+ if ( frame . filename ?. startsWith ( assetPrefix ) ) {
30
+ frame . filename = frame . filename . replace ( assetPrefix , 'app://' ) ;
31
+ }
32
+ } else if ( basePath ) {
33
+ // If the user defined a base path, we need to strip it to match with uploaded sourcemaps.
34
+ // We should only do this for same-origin filenames though, so that third party assets are not rewritten.
35
+ try {
36
+ const { origin : frameOrigin } = new URL ( frame . filename as string ) ;
37
+ if ( frameOrigin === windowOrigin ) {
38
+ frame . filename = frame . filename ?. replace ( frameOrigin , 'app://' ) . replace ( basePath , '' ) ;
39
+ }
40
+ } catch ( err ) {
41
+ // Filename wasn't a properly formed URL, so there's nothing we can do
42
+ }
21
43
}
22
- } else if ( basePath ) {
23
- // If the user defined a base path, we need to strip it to match with uploaded sourcemaps.
24
- // We should only do this for same-origin filenames though, so that third party assets are not rewritten.
44
+ } else {
25
45
try {
26
- const { origin : frameOrigin } = new URL ( frame . filename as string ) ;
27
- if ( frameOrigin === windowOrigin ) {
28
- frame . filename = frame . filename ?. replace ( frameOrigin , 'app://' ) . replace ( basePath , '' ) ;
29
- }
46
+ const { origin } = new URL ( frame . filename as string ) ;
47
+ frame . filename = frame . filename ?. replace ( origin , 'app://' ) . replace ( rewriteFramesAssetPrefixPath , '' ) ;
30
48
} catch ( err ) {
31
49
// Filename wasn't a properly formed URL, so there's nothing we can do
32
50
}
33
51
}
34
52
35
53
// We need to URI-decode the filename because Next.js has wildcard routes like "/users/[id].js" which show up as "/users/%5id%5.js" in Error stacktraces.
36
54
// The corresponding sources that Next.js generates have proper brackets so we also need proper brackets in the frame so that source map resolving works.
37
- if ( frame . filename ?. includes ( '/_next' ) ) {
38
- frame . filename = decodeURI ( frame . filename ) ;
39
- }
55
+ if ( experimentalThirdPartyOriginStackFrames ) {
56
+ if ( frame . filename ?. includes ( '/_next' ) ) {
57
+ frame . filename = decodeURI ( frame . filename ) ;
58
+ }
59
+
60
+ if (
61
+ frame . filename ?. match (
62
+ / \/ _ n e x t \/ s t a t i c \/ c h u n k s \/ ( m a i n - | m a i n - a p p - | p o l y f i l l s - | w e b p a c k - | f r a m e w o r k - | f r a m e w o r k \. ) [ 0 - 9 a - f ] + \. j s $ / ,
63
+ )
64
+ ) {
65
+ // We don't care about these frames. It's Next.js internal code.
66
+ frame . in_app = false ;
67
+ }
68
+ } else {
69
+ if ( frame . filename ?. startsWith ( 'app:///_next' ) ) {
70
+ frame . filename = decodeURI ( frame . filename ) ;
71
+ }
40
72
41
- if (
42
- frame . filename ?. match (
43
- / \/ _ n e x t \/ s t a t i c \/ c h u n k s \/ ( m a i n - | m a i n - a p p - | p o l y f i l l s - | w e b p a c k - | f r a m e w o r k - | f r a m e w o r k \. ) [ 0 - 9 a - f ] + \. j s $ / ,
44
- )
45
- ) {
46
- // We don't care about these frames. It's Next.js internal code.
47
- frame . in_app = false ;
73
+ if (
74
+ frame . filename ?. match (
75
+ / ^ a p p : \/ \/ \/ _ n e x t \/ s t a t i c \/ c h u n k s \/ ( m a i n - | m a i n - a p p - | p o l y f i l l s - | w e b p a c k - | f r a m e w o r k - | f r a m e w o r k \. ) [ 0 - 9 a - f ] + \. j s $ / ,
76
+ )
77
+ ) {
78
+ // We don't care about these frames. It's Next.js internal code.
79
+ frame . in_app = false ;
80
+ }
48
81
}
49
82
50
83
return frame ;
0 commit comments