mirror of https://github.com/gorhill/uBlock.git
Add `stackNeedle` argument to `json-prune` scriptlet
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/2757
This commit is contained in:
parent
6d7674e69f
commit
4649ae4d78
|
@ -46,6 +46,7 @@ function safeSelf() {
|
||||||
return scriptletGlobals.get('safeSelf');
|
return scriptletGlobals.get('safeSelf');
|
||||||
}
|
}
|
||||||
const safe = {
|
const safe = {
|
||||||
|
'Error': self.Error,
|
||||||
'Object_defineProperty': Object.defineProperty.bind(Object),
|
'Object_defineProperty': Object.defineProperty.bind(Object),
|
||||||
'RegExp': self.RegExp,
|
'RegExp': self.RegExp,
|
||||||
'RegExp_test': self.RegExp.prototype.test,
|
'RegExp_test': self.RegExp.prototype.test,
|
||||||
|
@ -620,6 +621,7 @@ builtinScriptlets.push({
|
||||||
name: 'object-prune.fn',
|
name: 'object-prune.fn',
|
||||||
fn: objectPrune,
|
fn: objectPrune,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
'matches-stack-trace.fn',
|
||||||
'pattern-to-regex.fn',
|
'pattern-to-regex.fn',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -632,9 +634,10 @@ builtinScriptlets.push({
|
||||||
function objectPrune(
|
function objectPrune(
|
||||||
obj,
|
obj,
|
||||||
rawPrunePaths,
|
rawPrunePaths,
|
||||||
rawNeedlePaths
|
rawNeedlePaths,
|
||||||
|
stackNeedle = ''
|
||||||
) {
|
) {
|
||||||
if ( typeof rawPrunePaths !== 'string' ) { return; }
|
if ( typeof rawPrunePaths !== 'string' ) { return obj; }
|
||||||
const prunePaths = rawPrunePaths !== ''
|
const prunePaths = rawPrunePaths !== ''
|
||||||
? rawPrunePaths.split(/ +/)
|
? rawPrunePaths.split(/ +/)
|
||||||
: [];
|
: [];
|
||||||
|
@ -648,6 +651,11 @@ function objectPrune(
|
||||||
log = console.log.bind(console);
|
log = console.log.bind(console);
|
||||||
reLogNeedle = patternToRegex(rawNeedlePaths);
|
reLogNeedle = patternToRegex(rawNeedlePaths);
|
||||||
}
|
}
|
||||||
|
if ( stackNeedle !== '' ) {
|
||||||
|
if ( matchesStackTrace(patternToRegex(stackNeedle), log ? '1' : 0) === false ) {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
const findOwner = function(root, path, prune = false) {
|
const findOwner = function(root, path, prune = false) {
|
||||||
let owner = root;
|
let owner = root;
|
||||||
let chain = path;
|
let chain = path;
|
||||||
|
@ -802,6 +810,60 @@ function setLocalStorageItemCore(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
builtinScriptlets.push({
|
||||||
|
name: 'matches-stack-trace.fn',
|
||||||
|
fn: matchesStackTrace,
|
||||||
|
dependencies: [
|
||||||
|
'safe-self.fn',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
function matchesStackTrace(
|
||||||
|
reNeedle,
|
||||||
|
logLevel = 0
|
||||||
|
) {
|
||||||
|
if ( reNeedle === undefined ) { return false; }
|
||||||
|
const safe = safeSelf();
|
||||||
|
const exceptionToken = getExceptionToken();
|
||||||
|
const error = new safe.Error(exceptionToken);
|
||||||
|
const docURL = new URL(self.location.href);
|
||||||
|
docURL.hash = '';
|
||||||
|
// Normalize stack trace
|
||||||
|
const reLine = /(.*?@)?(\S+)(:\d+):\d+\)?$/;
|
||||||
|
const lines = [];
|
||||||
|
for ( let line of error.stack.split(/[\n\r]+/) ) {
|
||||||
|
if ( line.includes(exceptionToken) ) { continue; }
|
||||||
|
line = line.trim();
|
||||||
|
const match = safe.RegExp_exec.call(reLine, line);
|
||||||
|
if ( match === null ) { continue; }
|
||||||
|
let url = match[2];
|
||||||
|
if ( url.startsWith('(') ) { url = url.slice(1); }
|
||||||
|
if ( url === docURL.href ) {
|
||||||
|
url = 'inlineScript';
|
||||||
|
} else if ( url.startsWith('<anonymous>') ) {
|
||||||
|
url = 'injectedScript';
|
||||||
|
}
|
||||||
|
let fn = match[1] !== undefined
|
||||||
|
? match[1].slice(0, -1)
|
||||||
|
: line.slice(0, match.index).trim();
|
||||||
|
if ( fn.startsWith('at') ) { fn = fn.slice(2).trim(); }
|
||||||
|
let rowcol = match[3];
|
||||||
|
lines.push(' ' + `${fn} ${url}${rowcol}:1`.trim());
|
||||||
|
}
|
||||||
|
lines[0] = `stackDepth:${lines.length-1}`;
|
||||||
|
const stack = lines.join('\t');
|
||||||
|
const r = safe.RegExp_test.call(reNeedle, stack);
|
||||||
|
if (
|
||||||
|
logLevel === '1' ||
|
||||||
|
logLevel === '2' && r ||
|
||||||
|
logLevel === '3' && !r
|
||||||
|
) {
|
||||||
|
safe.uboLog(stack.replace(/\t/g, '\n'));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Injectable scriptlets
|
Injectable scriptlets
|
||||||
|
@ -931,8 +993,8 @@ builtinScriptlets.push({
|
||||||
fn: abortOnStackTrace,
|
fn: abortOnStackTrace,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
'get-exception-token.fn',
|
'get-exception-token.fn',
|
||||||
|
'matches-stack-trace.fn',
|
||||||
'pattern-to-regex.fn',
|
'pattern-to-regex.fn',
|
||||||
'safe-self.fn',
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
// Status is currently experimental
|
// Status is currently experimental
|
||||||
|
@ -942,64 +1004,21 @@ function abortOnStackTrace(
|
||||||
logLevel = ''
|
logLevel = ''
|
||||||
) {
|
) {
|
||||||
if ( typeof chain !== 'string' ) { return; }
|
if ( typeof chain !== 'string' ) { return; }
|
||||||
const safe = safeSelf();
|
|
||||||
const reNeedle = patternToRegex(needle);
|
const reNeedle = patternToRegex(needle);
|
||||||
const exceptionToken = getExceptionToken();
|
|
||||||
const ErrorCtor = self.Error;
|
|
||||||
const mustAbort = function(err) {
|
|
||||||
let docURL = self.location.href;
|
|
||||||
const pos = docURL.indexOf('#');
|
|
||||||
if ( pos !== -1 ) {
|
|
||||||
docURL = docURL.slice(0, pos);
|
|
||||||
}
|
|
||||||
// Normalize stack trace
|
|
||||||
const reLine = /(.*?@)?(\S+)(:\d+):\d+\)?$/;
|
|
||||||
const lines = [];
|
|
||||||
for ( let line of err.stack.split(/[\n\r]+/) ) {
|
|
||||||
if ( line.includes(exceptionToken) ) { continue; }
|
|
||||||
line = line.trim();
|
|
||||||
const match = safe.RegExp_exec.call(reLine, line);
|
|
||||||
if ( match === null ) { continue; }
|
|
||||||
let url = match[2];
|
|
||||||
if ( url.startsWith('(') ) { url = url.slice(1); }
|
|
||||||
if ( url === docURL ) {
|
|
||||||
url = 'inlineScript';
|
|
||||||
} else if ( url.startsWith('<anonymous>') ) {
|
|
||||||
url = 'injectedScript';
|
|
||||||
}
|
|
||||||
let fn = match[1] !== undefined
|
|
||||||
? match[1].slice(0, -1)
|
|
||||||
: line.slice(0, match.index).trim();
|
|
||||||
if ( fn.startsWith('at') ) { fn = fn.slice(2).trim(); }
|
|
||||||
let rowcol = match[3];
|
|
||||||
lines.push(' ' + `${fn} ${url}${rowcol}:1`.trim());
|
|
||||||
}
|
|
||||||
lines[0] = `stackDepth:${lines.length-1}`;
|
|
||||||
const stack = lines.join('\t');
|
|
||||||
const r = safe.RegExp_test.call(reNeedle, stack);
|
|
||||||
if (
|
|
||||||
logLevel === '1' ||
|
|
||||||
logLevel === '2' && r ||
|
|
||||||
logLevel === '3' && !r
|
|
||||||
) {
|
|
||||||
safe.uboLog(stack.replace(/\t/g, '\n'));
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
};
|
|
||||||
const makeProxy = function(owner, chain) {
|
const makeProxy = function(owner, chain) {
|
||||||
const pos = chain.indexOf('.');
|
const pos = chain.indexOf('.');
|
||||||
if ( pos === -1 ) {
|
if ( pos === -1 ) {
|
||||||
let v = owner[chain];
|
let v = owner[chain];
|
||||||
Object.defineProperty(owner, chain, {
|
Object.defineProperty(owner, chain, {
|
||||||
get: function() {
|
get: function() {
|
||||||
if ( mustAbort(new ErrorCtor(exceptionToken)) ) {
|
if ( matchesStackTrace(reNeedle, logLevel) ) {
|
||||||
throw new ReferenceError(exceptionToken);
|
throw new ReferenceError(getExceptionToken());
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
},
|
},
|
||||||
set: function(a) {
|
set: function(a) {
|
||||||
if ( mustAbort(new ErrorCtor(exceptionToken)) ) {
|
if ( matchesStackTrace(reNeedle, logLevel) ) {
|
||||||
throw new ReferenceError(exceptionToken);
|
throw new ReferenceError(getExceptionToken());
|
||||||
}
|
}
|
||||||
v = a;
|
v = a;
|
||||||
},
|
},
|
||||||
|
@ -1114,21 +1133,23 @@ builtinScriptlets.push({
|
||||||
// - Add support for "remove everything if needle matches" case
|
// - Add support for "remove everything if needle matches" case
|
||||||
function jsonPrune(
|
function jsonPrune(
|
||||||
rawPrunePaths = '',
|
rawPrunePaths = '',
|
||||||
rawNeedlePaths = ''
|
rawNeedlePaths = '',
|
||||||
|
stackNeedle = ''
|
||||||
) {
|
) {
|
||||||
JSON.parse = new Proxy(JSON.parse, {
|
JSON.parse = new Proxy(JSON.parse, {
|
||||||
apply: function(target, thisArg, args) {
|
apply: function(target, thisArg, args) {
|
||||||
return objectPrune(
|
return objectPrune(
|
||||||
Reflect.apply(target, thisArg, args),
|
Reflect.apply(target, thisArg, args),
|
||||||
rawPrunePaths,
|
rawPrunePaths,
|
||||||
rawNeedlePaths
|
rawNeedlePaths,
|
||||||
|
stackNeedle
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
Response.prototype.json = new Proxy(Response.prototype.json, {
|
Response.prototype.json = new Proxy(Response.prototype.json, {
|
||||||
apply: function(target, thisArg, args) {
|
apply: function(target, thisArg, args) {
|
||||||
return Reflect.apply(target, thisArg, args).then(o =>
|
return Reflect.apply(target, thisArg, args).then(o =>
|
||||||
objectPrune(o, rawPrunePaths, rawNeedlePaths)
|
objectPrune(o, rawPrunePaths, rawNeedlePaths, stackNeedle)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue