mirror of
https://github.com/gorhill/uBlock.git
synced 2024-10-06 09:37:12 +02:00
Add logging ability to acs
scriptlet, for the benefit of filter list
maintainers. To enable logging, use the JSON approach to pass parameters to `acs` scriptlet. Example: ..##+js(acs, { "target": "document.oncontextmenu", "log": true }) Whereas "target", "needle", and "context" correspond to their respective positional argument. Using JSON form to pass parameters allows to specify extra paramters to facilitate debugging of that scriptlet: - `"log": true` => output useful information at the dev console. - `"debug": true` => break at key locations in the scriptlet. The added logging/debugging capabilities work only in the dev build of uBO or if the advanced setting `filterAuthorMode` is set to `true`.
This commit is contained in:
parent
95bd52d01f
commit
edbe96a401
@ -49,6 +49,12 @@ function safeSelf() {
|
|||||||
'RegExp': self.RegExp,
|
'RegExp': self.RegExp,
|
||||||
'RegExp_test': self.RegExp.prototype.test,
|
'RegExp_test': self.RegExp.prototype.test,
|
||||||
'RegExp_exec': self.RegExp.prototype.exec,
|
'RegExp_exec': self.RegExp.prototype.exec,
|
||||||
|
'safeLog': console.log.bind(console),
|
||||||
|
'uboLog': function(msg) {
|
||||||
|
if ( msg !== '' ) {
|
||||||
|
this.safeLog(`[uBO] ${msg}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
scriptletGlobals.set('safeSelf', safe);
|
scriptletGlobals.set('safeSelf', safe);
|
||||||
return safe;
|
return safe;
|
||||||
@ -90,6 +96,28 @@ function getExceptionToken() {
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
builtinScriptlets.push({
|
||||||
|
name: 'should-debug.fn',
|
||||||
|
fn: shouldDebug,
|
||||||
|
});
|
||||||
|
function shouldDebug(details) {
|
||||||
|
if ( details instanceof Object === false ) { return false; }
|
||||||
|
return scriptletGlobals.has('canDebug') && details.debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
builtinScriptlets.push({
|
||||||
|
name: 'should-log.fn',
|
||||||
|
fn: shouldLog,
|
||||||
|
});
|
||||||
|
function shouldLog(details) {
|
||||||
|
if ( details instanceof Object === false ) { return false; }
|
||||||
|
return scriptletGlobals.has('canDebug') && details.log;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Injectable scriptlets
|
Injectable scriptlets
|
||||||
@ -105,6 +133,9 @@ builtinScriptlets.push({
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
'pattern-to-regex.fn',
|
'pattern-to-regex.fn',
|
||||||
'get-exception-token.fn',
|
'get-exception-token.fn',
|
||||||
|
'safe-self.fn',
|
||||||
|
'should-debug.fn',
|
||||||
|
'should-log.fn',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
// Issues to mind before changing anything:
|
// Issues to mind before changing anything:
|
||||||
@ -117,9 +148,10 @@ function abortCurrentScript(
|
|||||||
const details = typeof arg1 !== 'object'
|
const details = typeof arg1 !== 'object'
|
||||||
? { target: arg1, needle: arg2, context: arg3 }
|
? { target: arg1, needle: arg2, context: arg3 }
|
||||||
: arg1;
|
: arg1;
|
||||||
const { target, needle, context } = details;
|
const { target = '', needle = '', context = '' } = details;
|
||||||
if ( typeof target !== 'string' ) { return; }
|
if ( typeof target !== 'string' ) { return; }
|
||||||
if ( target === '' ) { return; }
|
if ( target === '' ) { return; }
|
||||||
|
const safe = safeSelf();
|
||||||
const reNeedle = patternToRegex(needle);
|
const reNeedle = patternToRegex(needle);
|
||||||
const reContext = patternToRegex(context);
|
const reContext = patternToRegex(context);
|
||||||
const thisScript = document.currentScript;
|
const thisScript = document.currentScript;
|
||||||
@ -141,6 +173,8 @@ function abortCurrentScript(
|
|||||||
value = owner[prop];
|
value = owner[prop];
|
||||||
desc = undefined;
|
desc = undefined;
|
||||||
}
|
}
|
||||||
|
const log = shouldLog(details);
|
||||||
|
const debug = shouldDebug(details);
|
||||||
const exceptionToken = getExceptionToken();
|
const exceptionToken = getExceptionToken();
|
||||||
const scriptTexts = new WeakMap();
|
const scriptTexts = new WeakMap();
|
||||||
const getScriptText = elem => {
|
const getScriptText = elem => {
|
||||||
@ -165,13 +199,19 @@ function abortCurrentScript(
|
|||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
const validate = ( ) => {
|
const validate = ( ) => {
|
||||||
|
if ( debug ) { debugger; } // jshint ignore: line
|
||||||
const e = document.currentScript;
|
const e = document.currentScript;
|
||||||
if ( e instanceof HTMLScriptElement === false ) { return; }
|
if ( e instanceof HTMLScriptElement === false ) { return; }
|
||||||
if ( e === thisScript ) { return; }
|
if ( e === thisScript ) { return; }
|
||||||
|
if ( e.src !== '' && log ) { safe.uboLog(`src: ${e.src}`); }
|
||||||
if ( reContext.test(e.src) === false ) { return; }
|
if ( reContext.test(e.src) === false ) { return; }
|
||||||
if ( reNeedle.test(getScriptText(e)) === false ) { return; }
|
const scriptText = getScriptText(e);
|
||||||
|
if ( log ) { safe.uboLog(`script text: ${scriptText}`); }
|
||||||
|
if ( reNeedle.test(scriptText) === false ) { return; }
|
||||||
throw new ReferenceError(exceptionToken);
|
throw new ReferenceError(exceptionToken);
|
||||||
};
|
};
|
||||||
|
if ( debug ) { debugger; } // jshint ignore: line
|
||||||
|
try {
|
||||||
Object.defineProperty(owner, prop, {
|
Object.defineProperty(owner, prop, {
|
||||||
get: function() {
|
get: function() {
|
||||||
validate();
|
validate();
|
||||||
@ -188,6 +228,9 @@ function abortCurrentScript(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} catch(ex) {
|
||||||
|
if ( log ) { safe.uboLog(ex); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -298,7 +341,6 @@ function abortOnStackTrace(
|
|||||||
const safe = safeSelf();
|
const safe = safeSelf();
|
||||||
const reNeedle = patternToRegex(needle);
|
const reNeedle = patternToRegex(needle);
|
||||||
const exceptionToken = getExceptionToken();
|
const exceptionToken = getExceptionToken();
|
||||||
const log = console.log.bind(console);
|
|
||||||
const ErrorCtor = self.Error;
|
const ErrorCtor = self.Error;
|
||||||
const mustAbort = function(err) {
|
const mustAbort = function(err) {
|
||||||
let docURL = self.location.href;
|
let docURL = self.location.href;
|
||||||
@ -336,7 +378,7 @@ function abortOnStackTrace(
|
|||||||
logLevel === '2' && r ||
|
logLevel === '2' && r ||
|
||||||
logLevel === '3' && !r
|
logLevel === '3' && !r
|
||||||
) {
|
) {
|
||||||
log(stack.replace(/\t/g, '\n'));
|
safe.uboLog(stack.replace(/\t/g, '\n'));
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
@ -392,6 +434,8 @@ builtinScriptlets.push({
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
'pattern-to-regex.fn',
|
'pattern-to-regex.fn',
|
||||||
'safe-self.fn',
|
'safe-self.fn',
|
||||||
|
'should-debug.fn',
|
||||||
|
'should-log.fn',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
// https://github.com/uBlockOrigin/uAssets/issues/9123#issuecomment-848255120
|
// https://github.com/uBlockOrigin/uAssets/issues/9123#issuecomment-848255120
|
||||||
@ -408,7 +452,8 @@ function addEventListenerDefuser(
|
|||||||
const safe = safeSelf();
|
const safe = safeSelf();
|
||||||
const reType = patternToRegex(type);
|
const reType = patternToRegex(type);
|
||||||
const rePattern = patternToRegex(pattern);
|
const rePattern = patternToRegex(pattern);
|
||||||
const logfn = console.log.bind(console);
|
const log = shouldLog(details);
|
||||||
|
const debug = shouldDebug(details);
|
||||||
const proto = self.EventTarget.prototype;
|
const proto = self.EventTarget.prototype;
|
||||||
proto.addEventListener = new Proxy(proto.addEventListener, {
|
proto.addEventListener = new Proxy(proto.addEventListener, {
|
||||||
apply: function(target, thisArg, args) {
|
apply: function(target, thisArg, args) {
|
||||||
@ -422,17 +467,10 @@ function addEventListenerDefuser(
|
|||||||
const matchesHandler = safe.RegExp_test.call(rePattern, handler);
|
const matchesHandler = safe.RegExp_test.call(rePattern, handler);
|
||||||
const matchesEither = matchesType || matchesHandler;
|
const matchesEither = matchesType || matchesHandler;
|
||||||
const matchesBoth = matchesType && matchesHandler;
|
const matchesBoth = matchesType && matchesHandler;
|
||||||
if (
|
if ( log === 1 && matchesBoth || log === 2 && matchesEither || log === 3 ) {
|
||||||
details.log === 1 && matchesBoth ||
|
safe.uboLog(`addEventListener('${type}', ${handler})`);
|
||||||
details.log === 2 && matchesEither ||
|
|
||||||
details.log === 3
|
|
||||||
) {
|
|
||||||
logfn(`uBO: addEventListener('${type}', ${handler})`);
|
|
||||||
}
|
}
|
||||||
if (
|
if ( debug === 1 && matchesBoth || debug === 2 && matchesEither ) {
|
||||||
details.debug === 1 && matchesBoth ||
|
|
||||||
details.debug === 2 && matchesEither
|
|
||||||
) {
|
|
||||||
debugger; // jshint ignore:line
|
debugger; // jshint ignore:line
|
||||||
}
|
}
|
||||||
if ( matchesBoth ) { return; }
|
if ( matchesBoth ) { return; }
|
||||||
|
@ -47,6 +47,8 @@ const scriptletDB = new StaticExtFilteringHostnameDB(1);
|
|||||||
let acceptedCount = 0;
|
let acceptedCount = 0;
|
||||||
let discardedCount = 0;
|
let discardedCount = 0;
|
||||||
|
|
||||||
|
let isDevBuild;
|
||||||
|
|
||||||
const scriptletFilteringEngine = {
|
const scriptletFilteringEngine = {
|
||||||
get acceptedCount() {
|
get acceptedCount() {
|
||||||
return acceptedCount;
|
return acceptedCount;
|
||||||
@ -386,6 +388,15 @@ scriptletFilteringEngine.retrieve = function(request, options = {}) {
|
|||||||
|
|
||||||
if ( cacheDetails.code === '' ) { return; }
|
if ( cacheDetails.code === '' ) { return; }
|
||||||
|
|
||||||
|
const scriptletGlobals = [];
|
||||||
|
|
||||||
|
if ( isDevBuild === undefined ) {
|
||||||
|
isDevBuild = vAPI.webextFlavor.soup.has('devbuild');
|
||||||
|
}
|
||||||
|
if ( isDevBuild || µb.hiddenSettings.filterAuthorMode ) {
|
||||||
|
scriptletGlobals.push([ 'canDebug', true ]);
|
||||||
|
}
|
||||||
|
|
||||||
const out = [
|
const out = [
|
||||||
'(function() {',
|
'(function() {',
|
||||||
'// >>>> start of private namespace',
|
'// >>>> start of private namespace',
|
||||||
@ -393,7 +404,7 @@ scriptletFilteringEngine.retrieve = function(request, options = {}) {
|
|||||||
µb.hiddenSettings.debugScriptlets ? 'debugger;' : ';',
|
µb.hiddenSettings.debugScriptlets ? 'debugger;' : ';',
|
||||||
'',
|
'',
|
||||||
// For use by scriptlets to share local data among themselves
|
// For use by scriptlets to share local data among themselves
|
||||||
'const scriptletGlobals = new Map();',
|
`const scriptletGlobals = new Map(${JSON.stringify(scriptletGlobals, null, 2)});`,
|
||||||
'',
|
'',
|
||||||
cacheDetails.code,
|
cacheDetails.code,
|
||||||
'',
|
'',
|
||||||
|
Loading…
Reference in New Issue
Block a user