@@ -89,6 +89,34 @@ describe('instrumentEnv', () => {
8989 expect ( instrumentDurableObjectNamespace ) . not . toHaveBeenCalled ( ) ;
9090 } ) ;
9191
92+ it ( 'instruments only the DurableObjectNamespace bindings named in the allowlist' , ( ) => {
93+ const allowed = { idFromName : vi . fn ( ) , idFromString : vi . fn ( ) , get : vi . fn ( ) , newUniqueId : vi . fn ( ) } ;
94+ const denied = { idFromName : vi . fn ( ) , idFromString : vi . fn ( ) , get : vi . fn ( ) , newUniqueId : vi . fn ( ) } ;
95+ const env = { COUNTER : allowed , SESSIONS : denied } ;
96+ const instrumented = instrumentEnv ( env , { enableRpcTracePropagation : [ 'COUNTER' ] } ) ;
97+
98+ expect ( ( instrumented . COUNTER as any ) . __instrumented ) . toBe ( true ) ;
99+ expect ( instrumented . SESSIONS ) . toBe ( denied ) ;
100+ expect ( instrumentDurableObjectNamespace ) . toHaveBeenCalledTimes ( 1 ) ;
101+ expect ( instrumentDurableObjectNamespace ) . toHaveBeenCalledWith ( allowed ) ;
102+ } ) ;
103+
104+ it ( 'matches allowlisted binding names exactly rather than as substrings' , ( ) => {
105+ const doNamespace = { idFromName : vi . fn ( ) , idFromString : vi . fn ( ) , get : vi . fn ( ) , newUniqueId : vi . fn ( ) } ;
106+ const env = { MY_COUNTER : doNamespace } ;
107+ const instrumented = instrumentEnv ( env , { enableRpcTracePropagation : [ 'COUNTER' ] } ) ;
108+
109+ expect ( instrumented . MY_COUNTER ) . toBe ( doNamespace ) ;
110+ } ) ;
111+
112+ it ( 'supports regular expressions in the allowlist' , ( ) => {
113+ const doNamespace = { idFromName : vi . fn ( ) , idFromString : vi . fn ( ) , get : vi . fn ( ) , newUniqueId : vi . fn ( ) } ;
114+ const env = { SVC_ORDERS : doNamespace } ;
115+ const instrumented = instrumentEnv ( env , { enableRpcTracePropagation : [ / ^ S V C _ / ] } ) ;
116+
117+ expect ( ( instrumented . SVC_ORDERS as any ) . __instrumented ) . toBe ( true ) ;
118+ } ) ;
119+
92120 it ( 'detects and instruments DurableObjectNamespace bindings when enableRpcTracePropagation is enabled' , ( ) => {
93121 const doNamespace = {
94122 idFromName : vi . fn ( ) ,
@@ -486,5 +514,44 @@ describe('instrumentEnv', () => {
486514
487515 expect ( rpcMethod ) . toHaveBeenCalledWith ( 'arg1' ) ;
488516 } ) ;
517+
518+ // A receiver without Sentry never strips the trailing metadata argument, so a caller has to be
519+ // able to limit propagation to the bindings it knows are instrumented.
520+ // See https://github.com/getsentry/sentry-javascript/issues/23233.
521+ it ( 'injects meta only into JSRPC calls on allowlisted bindings' , ( ) => {
522+ vi . spyOn ( SentryCore , 'getTraceData' ) . mockReturnValue ( {
523+ 'sentry-trace' : '12345678901234567890123456789012-1234567890123456-1' ,
524+ baggage : 'sentry-environment=production' ,
525+ } ) ;
526+
527+ const allowedMethod = vi . fn ( ) ;
528+ const deniedMethod = vi . fn ( ) ;
529+ const createJsrpcBinding = ( rpcMethod : ReturnType < typeof vi . fn > ) =>
530+ new Proxy (
531+ { fetch : vi . fn ( ) , myRpcMethod : rpcMethod } ,
532+ {
533+ get ( target , prop ) {
534+ if ( prop in target ) {
535+ return Reflect . get ( target , prop ) ;
536+ }
537+ return ( ) => { } ;
538+ } ,
539+ } ,
540+ ) ;
541+
542+ const env = { ORDERS : createJsrpcBinding ( allowedMethod ) , EXTERNAL : createJsrpcBinding ( deniedMethod ) } ;
543+ const instrumented = instrumentEnv ( env , { enableRpcTracePropagation : [ 'ORDERS' ] } ) ;
544+
545+ instrumented . ORDERS . myRpcMethod ( 'first' ) ;
546+ instrumented . EXTERNAL . myRpcMethod ( 'first' ) ;
547+
548+ expect ( allowedMethod ) . toHaveBeenCalledWith ( 'first' , {
549+ __sentry_rpc_meta__ : {
550+ 'sentry-trace' : '12345678901234567890123456789012-1234567890123456-1' ,
551+ baggage : 'sentry-environment=production' ,
552+ } ,
553+ } ) ;
554+ expect ( deniedMethod ) . toHaveBeenCalledWith ( 'first' ) ;
555+ } ) ;
489556 } ) ;
490557} ) ;
0 commit comments