Add stackNeedle argument to json-prune scriptlet · gorhill/uBlock@4649ae4 (original) (raw)

`@@ -46,6 +46,7 @@ function safeSelf() {

`

46

46

`return scriptletGlobals.get('safeSelf');

`

47

47

`}

`

48

48

`const safe = {

`

``

49

`+

'Error': self.Error,

`

49

50

`'Object_defineProperty': Object.defineProperty.bind(Object),

`

50

51

`'RegExp': self.RegExp,

`

51

52

`'RegExp_test': self.RegExp.prototype.test,

`

`@@ -620,6 +621,7 @@ builtinScriptlets.push({

`

620

621

`name: 'object-prune.fn',

`

621

622

`fn: objectPrune,

`

622

623

`dependencies: [

`

``

624

`+

'matches-stack-trace.fn',

`

623

625

`'pattern-to-regex.fn',

`

624

626

`],

`

625

627

`});

`

`@@ -632,9 +634,10 @@ builtinScriptlets.push({

`

632

634

`function objectPrune(

`

633

635

`obj,

`

634

636

`rawPrunePaths,

`

635

``

`-

rawNeedlePaths

`

``

637

`+

rawNeedlePaths,

`

``

638

`+

stackNeedle = ''

`

636

639

`) {

`

637

``

`-

if ( typeof rawPrunePaths !== 'string' ) { return; }

`

``

640

`+

if ( typeof rawPrunePaths !== 'string' ) { return obj; }

`

638

641

`const prunePaths = rawPrunePaths !== ''

`

639

642

` ? rawPrunePaths.split(/ +/)

`

640

643

` : [];

`

`@@ -648,6 +651,11 @@ function objectPrune(

`

648

651

`log = console.log.bind(console);

`

649

652

`reLogNeedle = patternToRegex(rawNeedlePaths);

`

650

653

`}

`

``

654

`+

if ( stackNeedle !== '' ) {

`

``

655

`+

if ( matchesStackTrace(patternToRegex(stackNeedle), log ? '1' : 0) === false ) {

`

``

656

`+

return obj;

`

``

657

`+

}

`

``

658

`+

}

`

651

659

`const findOwner = function(root, path, prune = false) {

`

652

660

`let owner = root;

`

653

661

`let chain = path;

`

`@@ -802,6 +810,60 @@ function setLocalStorageItemCore(

`

802

810

`}

`

803

811

`}

`

804

812

``

``

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('') ) {

`

``

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} <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi><mi>r</mi><mi>l</mi></mrow><annotation encoding="application/x-tex">{url}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span></span></span></span></span>{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

+

805

867

`/*******************************************************************************

`

806

868

``

807

869

` Injectable scriptlets

`

`@@ -931,8 +993,8 @@ builtinScriptlets.push({

`

931

993

`fn: abortOnStackTrace,

`

932

994

`dependencies: [

`

933

995

`'get-exception-token.fn',

`

``

996

`+

'matches-stack-trace.fn',

`

934

997

`'pattern-to-regex.fn',

`

935

``

`-

'safe-self.fn',

`

936

998

`],

`

937

999

`});

`

938

1000

`// Status is currently experimental

`

`@@ -942,64 +1004,21 @@ function abortOnStackTrace(

`

942

1004

`logLevel = ''

`

943

1005

`) {

`

944

1006

`if ( typeof chain !== 'string' ) { return; }

`

945

``

`-

const safe = safeSelf();

`

946

1007

`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('') ) {

`

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} <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi><mi>r</mi><mi>l</mi></mrow><annotation encoding="application/x-tex">{url}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span></span></span></span></span>{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

``

`-

};

`

989

1008

`const makeProxy = function(owner, chain) {

`

990

1009

`const pos = chain.indexOf('.');

`

991

1010

`if ( pos === -1 ) {

`

992

1011

`let v = owner[chain];

`

993

1012

`Object.defineProperty(owner, chain, {

`

994

1013

`get: function() {

`

995

``

`-

if ( mustAbort(new ErrorCtor(exceptionToken)) ) {

`

996

``

`-

throw new ReferenceError(exceptionToken);

`

``

1014

`+

if ( matchesStackTrace(reNeedle, logLevel) ) {

`

``

1015

`+

throw new ReferenceError(getExceptionToken());

`

997

1016

`}

`

998

1017

`return v;

`

999

1018

`},

`

1000

1019

`set: function(a) {

`

1001

``

`-

if ( mustAbort(new ErrorCtor(exceptionToken)) ) {

`

1002

``

`-

throw new ReferenceError(exceptionToken);

`

``

1020

`+

if ( matchesStackTrace(reNeedle, logLevel) ) {

`

``

1021

`+

throw new ReferenceError(getExceptionToken());

`

1003

1022

`}

`

1004

1023

`v = a;

`

1005

1024

`},

`

`@@ -1114,21 +1133,23 @@ builtinScriptlets.push({

`

1114

1133

`// - Add support for "remove everything if needle matches" case

`

1115

1134

`function jsonPrune(

`

1116

1135

`rawPrunePaths = '',

`

1117

``

`-

rawNeedlePaths = ''

`

``

1136

`+

rawNeedlePaths = '',

`

``

1137

`+

stackNeedle = ''

`

1118

1138

`) {

`

1119

1139

`JSON.parse = new Proxy(JSON.parse, {

`

1120

1140

`apply: function(target, thisArg, args) {

`

1121

1141

`return objectPrune(

`

1122

1142

`Reflect.apply(target, thisArg, args),

`

1123

1143

`rawPrunePaths,

`

1124

``

`-

rawNeedlePaths

`

``

1144

`+

rawNeedlePaths,

`

``

1145

`+

stackNeedle

`

1125

1146

`);

`

1126

1147

`},

`

1127

1148

`});

`

1128

1149

`Response.prototype.json = new Proxy(Response.prototype.json, {

`

1129

1150

`apply: function(target, thisArg, args) {

`

1130

1151

`return Reflect.apply(target, thisArg, args).then(o =>

`

1131

``

`-

objectPrune(o, rawPrunePaths, rawNeedlePaths)

`

``

1152

`+

objectPrune(o, rawPrunePaths, rawNeedlePaths, stackNeedle)

`

1132

1153

`);

`

1133

1154

`},

`

1134

1155

`});

`