mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-06 09:37:12 +02:00
Add evaldata-prune
scriptlet
Related issue: - https://github.com/uBlockOrigin/uAssets/issues/18278
This commit is contained in:
parent
86d67e3f3e
commit
c8de904191
@ -614,6 +614,101 @@ function replaceNodeTextCore(
|
|||||||
}, 'interactive');
|
}, 'interactive');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
builtinScriptlets.push({
|
||||||
|
name: 'object-prune.fn',
|
||||||
|
fn: objectPrune,
|
||||||
|
dependencies: [
|
||||||
|
'pattern-to-regex.fn',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
// When no "prune paths" argument is provided, the scriptlet is
|
||||||
|
// used for logging purpose and the "needle paths" argument is
|
||||||
|
// used to filter logging output.
|
||||||
|
//
|
||||||
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/1545
|
||||||
|
// - Add support for "remove everything if needle matches" case
|
||||||
|
function objectPrune(
|
||||||
|
obj,
|
||||||
|
rawPrunePaths,
|
||||||
|
rawNeedlePaths
|
||||||
|
) {
|
||||||
|
if ( typeof rawPrunePaths !== 'string' ) { return; }
|
||||||
|
const prunePaths = rawPrunePaths !== ''
|
||||||
|
? rawPrunePaths.split(/ +/)
|
||||||
|
: [];
|
||||||
|
let needlePaths;
|
||||||
|
let log, reLogNeedle;
|
||||||
|
if ( prunePaths.length !== 0 ) {
|
||||||
|
needlePaths = prunePaths.length !== 0 && rawNeedlePaths !== ''
|
||||||
|
? rawNeedlePaths.split(/ +/)
|
||||||
|
: [];
|
||||||
|
} else {
|
||||||
|
log = console.log.bind(console);
|
||||||
|
reLogNeedle = patternToRegex(rawNeedlePaths);
|
||||||
|
}
|
||||||
|
const findOwner = function(root, path, prune = false) {
|
||||||
|
let owner = root;
|
||||||
|
let chain = path;
|
||||||
|
for (;;) {
|
||||||
|
if ( typeof owner !== 'object' || owner === null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const pos = chain.indexOf('.');
|
||||||
|
if ( pos === -1 ) {
|
||||||
|
if ( prune === false ) {
|
||||||
|
return owner.hasOwnProperty(chain);
|
||||||
|
}
|
||||||
|
if ( chain === '*' ) {
|
||||||
|
for ( const key in owner ) {
|
||||||
|
if ( owner.hasOwnProperty(key) === false ) { continue; }
|
||||||
|
delete owner[key];
|
||||||
|
}
|
||||||
|
} else if ( owner.hasOwnProperty(chain) ) {
|
||||||
|
delete owner[chain];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const prop = chain.slice(0, pos);
|
||||||
|
if (
|
||||||
|
prop === '[]' && Array.isArray(owner) ||
|
||||||
|
prop === '*' && owner instanceof Object
|
||||||
|
) {
|
||||||
|
const next = chain.slice(pos + 1);
|
||||||
|
let found = false;
|
||||||
|
for ( const key of Object.keys(owner) ) {
|
||||||
|
found = findOwner(owner[key], next, prune) || found;
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
if ( owner.hasOwnProperty(prop) === false ) { return false; }
|
||||||
|
owner = owner[prop];
|
||||||
|
chain = chain.slice(pos + 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const mustProcess = function(root) {
|
||||||
|
for ( const needlePath of needlePaths ) {
|
||||||
|
if ( findOwner(root, needlePath) === false ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
if ( log !== undefined ) {
|
||||||
|
const json = JSON.stringify(obj, null, 2);
|
||||||
|
if ( reLogNeedle.test(json) ) {
|
||||||
|
log('uBO:', location.hostname, json);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
if ( mustProcess(obj) === false ) { return obj; }
|
||||||
|
for ( const path of prunePaths ) {
|
||||||
|
findOwner(obj, path, true);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Injectable scriptlets
|
Injectable scriptlets
|
||||||
@ -906,7 +1001,7 @@ builtinScriptlets.push({
|
|||||||
name: 'json-prune.js',
|
name: 'json-prune.js',
|
||||||
fn: jsonPrune,
|
fn: jsonPrune,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
'pattern-to-regex.fn',
|
'object-prune.fn',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
// When no "prune paths" argument is provided, the scriptlet is
|
// When no "prune paths" argument is provided, the scriptlet is
|
||||||
@ -919,95 +1014,61 @@ function jsonPrune(
|
|||||||
rawPrunePaths = '',
|
rawPrunePaths = '',
|
||||||
rawNeedlePaths = ''
|
rawNeedlePaths = ''
|
||||||
) {
|
) {
|
||||||
if ( typeof rawPrunePaths !== 'string' ) { return; }
|
|
||||||
const prunePaths = rawPrunePaths !== ''
|
|
||||||
? rawPrunePaths.split(/ +/)
|
|
||||||
: [];
|
|
||||||
let needlePaths;
|
|
||||||
let log, reLogNeedle;
|
|
||||||
if ( prunePaths.length !== 0 ) {
|
|
||||||
needlePaths = prunePaths.length !== 0 && rawNeedlePaths !== ''
|
|
||||||
? rawNeedlePaths.split(/ +/)
|
|
||||||
: [];
|
|
||||||
} else {
|
|
||||||
log = console.log.bind(console);
|
|
||||||
reLogNeedle = patternToRegex(rawNeedlePaths);
|
|
||||||
}
|
|
||||||
const findOwner = function(root, path, prune = false) {
|
|
||||||
let owner = root;
|
|
||||||
let chain = path;
|
|
||||||
for (;;) {
|
|
||||||
if ( typeof owner !== 'object' || owner === null ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const pos = chain.indexOf('.');
|
|
||||||
if ( pos === -1 ) {
|
|
||||||
if ( prune === false ) {
|
|
||||||
return owner.hasOwnProperty(chain);
|
|
||||||
}
|
|
||||||
if ( chain === '*' ) {
|
|
||||||
for ( const key in owner ) {
|
|
||||||
if ( owner.hasOwnProperty(key) === false ) { continue; }
|
|
||||||
delete owner[key];
|
|
||||||
}
|
|
||||||
} else if ( owner.hasOwnProperty(chain) ) {
|
|
||||||
delete owner[chain];
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const prop = chain.slice(0, pos);
|
|
||||||
if (
|
|
||||||
prop === '[]' && Array.isArray(owner) ||
|
|
||||||
prop === '*' && owner instanceof Object
|
|
||||||
) {
|
|
||||||
const next = chain.slice(pos + 1);
|
|
||||||
let found = false;
|
|
||||||
for ( const key of Object.keys(owner) ) {
|
|
||||||
found = findOwner(owner[key], next, prune) || found;
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
if ( owner.hasOwnProperty(prop) === false ) { return false; }
|
|
||||||
owner = owner[prop];
|
|
||||||
chain = chain.slice(pos + 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const mustProcess = function(root) {
|
|
||||||
for ( const needlePath of needlePaths ) {
|
|
||||||
if ( findOwner(root, needlePath) === false ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
const pruner = function(o) {
|
|
||||||
if ( log !== undefined ) {
|
|
||||||
const json = JSON.stringify(o, null, 2);
|
|
||||||
if ( reLogNeedle.test(json) ) {
|
|
||||||
log('uBO:', location.hostname, json);
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
if ( mustProcess(o) === false ) { return o; }
|
|
||||||
for ( const path of prunePaths ) {
|
|
||||||
findOwner(o, path, true);
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
};
|
|
||||||
JSON.parse = new Proxy(JSON.parse, {
|
JSON.parse = new Proxy(JSON.parse, {
|
||||||
apply: function() {
|
apply: function(target, thisArg, args) {
|
||||||
return pruner(Reflect.apply(...arguments));
|
return objectPrune(
|
||||||
|
Reflect.apply(target, thisArg, args),
|
||||||
|
rawPrunePaths,
|
||||||
|
rawNeedlePaths
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
Response.prototype.json = new Proxy(Response.prototype.json, {
|
Response.prototype.json = new Proxy(Response.prototype.json, {
|
||||||
apply: function() {
|
apply: function(target, thisArg, args) {
|
||||||
return Reflect.apply(...arguments).then(o => pruner(o));
|
return Reflect.apply(target, thisArg, args).then(o =>
|
||||||
|
objectPrune(o, rawPrunePaths, rawNeedlePaths)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// There is still code out there which uses `eval` in lieu of `JSON.parse`.
|
||||||
|
|
||||||
|
builtinScriptlets.push({
|
||||||
|
name: 'evaldata-prune.js',
|
||||||
|
fn: evaldataPrune,
|
||||||
|
dependencies: [
|
||||||
|
'object-prune.fn',
|
||||||
|
],
|
||||||
|
});
|
||||||
|
function evaldataPrune(
|
||||||
|
rawPrunePaths = '',
|
||||||
|
rawNeedlePaths = ''
|
||||||
|
) {
|
||||||
|
self.eval = new Proxy(self.eval, {
|
||||||
|
apply(target, thisArg, args) {
|
||||||
|
let dataToEval = `${args[0]}`;
|
||||||
|
const match = /^\s*\(\s*(\{.+\})\s*\)\s*$/.exec(dataToEval);
|
||||||
|
if ( match !== null ) {
|
||||||
|
dataToEval = match[1];
|
||||||
|
}
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(dataToEval);
|
||||||
|
if ( typeof data === 'object' ) {
|
||||||
|
args[0] = objectPrune(dataToEval, rawPrunePaths, rawNeedlePaths);
|
||||||
|
}
|
||||||
|
} catch(ex) {
|
||||||
|
}
|
||||||
|
return Reflect.apply(target, thisArg, args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
builtinScriptlets.push({
|
builtinScriptlets.push({
|
||||||
name: 'nano-setInterval-booster.js',
|
name: 'nano-setInterval-booster.js',
|
||||||
aliases: [ 'nano-sib.js' ],
|
aliases: [ 'nano-sib.js' ],
|
||||||
|
Loading…
Reference in New Issue
Block a user