@@ -2,49 +2,82 @@ import { WINDOW, rewriteFramesIntegration } from '@sentry/browser';
22import { defineIntegration } from '@sentry/core' ;
33
44export 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+ } ) => {
816 const rewriteFramesInstance = rewriteFramesIntegration ( {
917 // Turn `<origin>/<path>/_next/static/...` into `app:///_next/static/...`
1018 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+ }
1525
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+ }
2143 }
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 {
2545 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 , '' ) ;
3048 } catch ( err ) {
3149 // Filename wasn't a properly formed URL, so there's nothing we can do
3250 }
3351 }
3452
3553 // 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.
3654 // 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+ }
4072
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+ }
4881 }
4982
5083 return frame ;
0 commit comments