@@ -46,6 +46,7 @@ function safeSelf() {
4646 return scriptletGlobals . get ( 'safeSelf' ) ;
4747 }
4848 const safe = {
49+ 'Error' : self . Error ,
4950 'Object_defineProperty' : Object . defineProperty . bind ( Object ) ,
5051 'RegExp' : self . RegExp ,
5152 'RegExp_test' : self . RegExp . prototype . test ,
@@ -620,6 +621,7 @@ builtinScriptlets.push({
620621 name : 'object-prune.fn' ,
621622 fn : objectPrune ,
622623 dependencies : [
624+ 'matches-stack-trace.fn' ,
623625 'pattern-to-regex.fn' ,
624626 ] ,
625627} ) ;
@@ -632,9 +634,10 @@ builtinScriptlets.push({
632634function objectPrune (
633635 obj ,
634636 rawPrunePaths ,
635- rawNeedlePaths
637+ rawNeedlePaths ,
638+ stackNeedle = ''
636639) {
637- if ( typeof rawPrunePaths !== 'string' ) { return ; }
640+ if ( typeof rawPrunePaths !== 'string' ) { return obj ; }
638641 const prunePaths = rawPrunePaths !== ''
639642 ? rawPrunePaths . split ( / + / )
640643 : [ ] ;
@@ -648,6 +651,11 @@ function objectPrune(
648651 log = console . log . bind ( console ) ;
649652 reLogNeedle = patternToRegex ( rawNeedlePaths ) ;
650653 }
654+ if ( stackNeedle !== '' ) {
655+ if ( matchesStackTrace ( patternToRegex ( stackNeedle ) , log ? '1' : 0 ) === false ) {
656+ return obj ;
657+ }
658+ }
651659 const findOwner = function ( root , path , prune = false ) {
652660 let owner = root ;
653661 let chain = path ;
@@ -802,6 +810,60 @@ function setLocalStorageItemCore(
802810 }
803811}
804812
813+ /******************************************************************************/
814+
815+ builtinScriptlets . push ( {
816+ name : 'matches-stack-trace.fn' ,
817+ fn : matchesStackTrace ,
818+ dependencies : [
819+ 'safe-self.fn' ,
820+ ] ,
821+ } ) ;
822+ function matchesStackTrace (
823+ reNeedle ,
824+ logLevel = 0
825+ ) {
826+ if ( reNeedle === undefined ) { return false ; }
827+ const safe = safeSelf ( ) ;
828+ const exceptionToken = getExceptionToken ( ) ;
829+ const error = new safe . Error ( exceptionToken ) ;
830+ const docURL = new URL ( self . location . href ) ;
831+ docURL . hash = '' ;
832+ // Normalize stack trace
833+ const reLine = / ( .* ?@ ) ? ( \S + ) ( : \d + ) : \d + \) ? $ / ;
834+ const lines = [ ] ;
835+ for ( let line of error . stack . split ( / [ \n \r ] + / ) ) {
836+ if ( line . includes ( exceptionToken ) ) { continue ; }
837+ line = line . trim ( ) ;
838+ const match = safe . RegExp_exec . call ( reLine , line ) ;
839+ if ( match === null ) { continue ; }
840+ let url = match [ 2 ] ;
841+ if ( url . startsWith ( '(' ) ) { url = url . slice ( 1 ) ; }
842+ if ( url === docURL . href ) {
843+ url = 'inlineScript' ;
844+ } else if ( url . startsWith ( '<anonymous>' ) ) {
845+ url = 'injectedScript' ;
846+ }
847+ let fn = match [ 1 ] !== undefined
848+ ? match [ 1 ] . slice ( 0 , - 1 )
849+ : line . slice ( 0 , match . index ) . trim ( ) ;
850+ if ( fn . startsWith ( 'at' ) ) { fn = fn . slice ( 2 ) . trim ( ) ; }
851+ let rowcol = match [ 3 ] ;
852+ lines . push ( ' ' + `${ fn } ${ url } ${ rowcol } :1` . trim ( ) ) ;
853+ }
854+ lines [ 0 ] = `stackDepth:${ lines . length - 1 } ` ;
855+ const stack = lines . join ( '\t' ) ;
856+ const r = safe . RegExp_test . call ( reNeedle , stack ) ;
857+ if (
858+ logLevel === '1' ||
859+ logLevel === '2' && r ||
860+ logLevel === '3' && ! r
861+ ) {
862+ safe . uboLog ( stack . replace ( / \t / g, '\n' ) ) ;
863+ }
864+ return r ;
865+ }
866+
805867/*******************************************************************************
806868
807869 Injectable scriptlets
@@ -931,8 +993,8 @@ builtinScriptlets.push({
931993 fn : abortOnStackTrace ,
932994 dependencies : [
933995 'get-exception-token.fn' ,
996+ 'matches-stack-trace.fn' ,
934997 'pattern-to-regex.fn' ,
935- 'safe-self.fn' ,
936998 ] ,
937999} ) ;
9381000// Status is currently experimental
@@ -942,64 +1004,21 @@ function abortOnStackTrace(
9421004 logLevel = ''
9431005) {
9441006 if ( typeof chain !== 'string' ) { return ; }
945- const safe = safeSelf ( ) ;
9461007 const reNeedle = patternToRegex ( needle ) ;
947- const exceptionToken = getExceptionToken ( ) ;
948- const ErrorCtor = self . Error ;
949- const mustAbort = function ( err ) {
950- let docURL = self . location . href ;
951- const pos = docURL . indexOf ( '#' ) ;
952- if ( pos !== - 1 ) {
953- docURL = docURL . slice ( 0 , pos ) ;
954- }
955- // Normalize stack trace
956- const reLine = / ( .* ?@ ) ? ( \S + ) ( : \d + ) : \d + \) ? $ / ;
957- const lines = [ ] ;
958- for ( let line of err . stack . split ( / [ \n \r ] + / ) ) {
959- if ( line . includes ( exceptionToken ) ) { continue ; }
960- line = line . trim ( ) ;
961- const match = safe . RegExp_exec . call ( reLine , line ) ;
962- if ( match === null ) { continue ; }
963- let url = match [ 2 ] ;
964- if ( url . startsWith ( '(' ) ) { url = url . slice ( 1 ) ; }
965- if ( url === docURL ) {
966- url = 'inlineScript' ;
967- } else if ( url . startsWith ( '<anonymous>' ) ) {
968- url = 'injectedScript' ;
969- }
970- let fn = match [ 1 ] !== undefined
971- ? match [ 1 ] . slice ( 0 , - 1 )
972- : line . slice ( 0 , match . index ) . trim ( ) ;
973- if ( fn . startsWith ( 'at' ) ) { fn = fn . slice ( 2 ) . trim ( ) ; }
974- let rowcol = match [ 3 ] ;
975- lines . push ( ' ' + `${ fn } ${ url } ${ rowcol } :1` . trim ( ) ) ;
976- }
977- lines [ 0 ] = `stackDepth:${ lines . length - 1 } ` ;
978- const stack = lines . join ( '\t' ) ;
979- const r = safe . RegExp_test . call ( reNeedle , stack ) ;
980- if (
981- logLevel === '1' ||
982- logLevel === '2' && r ||
983- logLevel === '3' && ! r
984- ) {
985- safe . uboLog ( stack . replace ( / \t / g, '\n' ) ) ;
986- }
987- return r ;
988- } ;
9891008 const makeProxy = function ( owner , chain ) {
9901009 const pos = chain . indexOf ( '.' ) ;
9911010 if ( pos === - 1 ) {
9921011 let v = owner [ chain ] ;
9931012 Object . defineProperty ( owner , chain , {
9941013 get : function ( ) {
995- if ( mustAbort ( new ErrorCtor ( exceptionToken ) ) ) {
996- throw new ReferenceError ( exceptionToken ) ;
1014+ if ( matchesStackTrace ( reNeedle , logLevel ) ) {
1015+ throw new ReferenceError ( getExceptionToken ( ) ) ;
9971016 }
9981017 return v ;
9991018 } ,
10001019 set : function ( a ) {
1001- if ( mustAbort ( new ErrorCtor ( exceptionToken ) ) ) {
1002- throw new ReferenceError ( exceptionToken ) ;
1020+ if ( matchesStackTrace ( reNeedle , logLevel ) ) {
1021+ throw new ReferenceError ( getExceptionToken ( ) ) ;
10031022 }
10041023 v = a ;
10051024 } ,
@@ -1114,21 +1133,23 @@ builtinScriptlets.push({
11141133// - Add support for "remove everything if needle matches" case
11151134function jsonPrune (
11161135 rawPrunePaths = '' ,
1117- rawNeedlePaths = ''
1136+ rawNeedlePaths = '' ,
1137+ stackNeedle = ''
11181138) {
11191139 JSON . parse = new Proxy ( JSON . parse , {
11201140 apply : function ( target , thisArg , args ) {
11211141 return objectPrune (
11221142 Reflect . apply ( target , thisArg , args ) ,
11231143 rawPrunePaths ,
1124- rawNeedlePaths
1144+ rawNeedlePaths ,
1145+ stackNeedle
11251146 ) ;
11261147 } ,
11271148 } ) ;
11281149 Response . prototype . json = new Proxy ( Response . prototype . json , {
11291150 apply : function ( target , thisArg , args ) {
11301151 return Reflect . apply ( target , thisArg , args ) . then ( o =>
1131- objectPrune ( o , rawPrunePaths , rawNeedlePaths )
1152+ objectPrune ( o , rawPrunePaths , rawNeedlePaths , stackNeedle )
11321153 ) ;
11331154 } ,
11341155 } ) ;
0 commit comments