mirror of https://github.com/gorhill/uBlock.git
Add ability for scriptlets to share local data
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1741 As a result of the new capability, usage of RegExp API in `aost` scriptlet has been shielded from the webpage tampering with the API.
This commit is contained in:
parent
c7c748862e
commit
5c9c87e485
|
@ -22,6 +22,9 @@
|
||||||
web page context.
|
web page context.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Externally added to the private namespace in which scriptlets execute.
|
||||||
|
/* global sriptletGlobals */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
export const builtinScriptlets = [];
|
export const builtinScriptlets = [];
|
||||||
|
@ -34,6 +37,25 @@ export const builtinScriptlets = [];
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
builtinScriptlets.push({
|
||||||
|
name: 'safe-self.fn',
|
||||||
|
fn: safeSelf,
|
||||||
|
});
|
||||||
|
function safeSelf() {
|
||||||
|
if ( sriptletGlobals.has('safeSelf') ) {
|
||||||
|
return sriptletGlobals.get('safeSelf');
|
||||||
|
}
|
||||||
|
const safe = {
|
||||||
|
'RegExp': self.RegExp,
|
||||||
|
'RegExp_test': self.RegExp.prototype.test,
|
||||||
|
'RegExp_exec': self.RegExp.prototype.exec,
|
||||||
|
};
|
||||||
|
sriptletGlobals.set('safeSelf', safe);
|
||||||
|
return safe;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
builtinScriptlets.push({
|
builtinScriptlets.push({
|
||||||
name: 'pattern-to-regex.fn',
|
name: 'pattern-to-regex.fn',
|
||||||
fn: patternToRegex,
|
fn: patternToRegex,
|
||||||
|
@ -257,6 +279,7 @@ builtinScriptlets.push({
|
||||||
aliases: [ 'aost.js' ],
|
aliases: [ 'aost.js' ],
|
||||||
fn: abortOnStackTrace,
|
fn: abortOnStackTrace,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
'safe-self.fn',
|
||||||
'pattern-to-regex.fn',
|
'pattern-to-regex.fn',
|
||||||
'get-exception-token.fn',
|
'get-exception-token.fn',
|
||||||
],
|
],
|
||||||
|
@ -268,6 +291,7 @@ 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 exceptionToken = getExceptionToken();
|
||||||
const log = console.log.bind(console);
|
const log = console.log.bind(console);
|
||||||
|
@ -279,11 +303,12 @@ function abortOnStackTrace(
|
||||||
docURL = docURL.slice(0, pos);
|
docURL = docURL.slice(0, pos);
|
||||||
}
|
}
|
||||||
// Normalize stack trace
|
// Normalize stack trace
|
||||||
|
const reLine = /(.*?@)?(\S+)(:\d+):\d+\)?$/;
|
||||||
const lines = [];
|
const lines = [];
|
||||||
for ( let line of err.stack.split(/[\n\r]+/) ) {
|
for ( let line of err.stack.split(/[\n\r]+/) ) {
|
||||||
if ( line.includes(exceptionToken) ) { continue; }
|
if ( line.includes(exceptionToken) ) { continue; }
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
let match = /(.*?@)?(\S+)(:\d+):\d+\)?$/.exec(line);
|
let match = safe.RegExp_exec.call(reLine, line);
|
||||||
if ( match === null ) { continue; }
|
if ( match === null ) { continue; }
|
||||||
let url = match[2];
|
let url = match[2];
|
||||||
if ( url.startsWith('(') ) { url = url.slice(1); }
|
if ( url.startsWith('(') ) { url = url.slice(1); }
|
||||||
|
@ -301,7 +326,7 @@ function abortOnStackTrace(
|
||||||
}
|
}
|
||||||
lines[0] = `stackDepth:${lines.length-1}`;
|
lines[0] = `stackDepth:${lines.length-1}`;
|
||||||
const stack = lines.join('\t');
|
const stack = lines.join('\t');
|
||||||
const r = reNeedle.test(stack);
|
const r = safe.RegExp_test.call(reNeedle, stack);
|
||||||
if (
|
if (
|
||||||
logLevel === '1' ||
|
logLevel === '1' ||
|
||||||
logLevel === '2' && r ||
|
logLevel === '2' && r ||
|
||||||
|
|
|
@ -379,22 +379,20 @@ scriptletFilteringEngine.retrieve = function(request, options = {}) {
|
||||||
|
|
||||||
if ( cacheDetails.code === '' ) { return; }
|
if ( cacheDetails.code === '' ) { return; }
|
||||||
|
|
||||||
const out = [ cacheDetails.code ];
|
const out = [
|
||||||
|
|
||||||
if ( µb.hiddenSettings.debugScriptlets ) {
|
|
||||||
out.unshift('debugger;');
|
|
||||||
}
|
|
||||||
|
|
||||||
out.unshift(
|
|
||||||
'(function() {',
|
'(function() {',
|
||||||
'// >>>> start of private namespace',
|
'// >>>> start of private namespace',
|
||||||
''
|
'',
|
||||||
);
|
µb.hiddenSettings.debugScriptlets ? 'debugger;' : ';',
|
||||||
out.push(
|
'',
|
||||||
|
// For use by scriptlets to share local data among themselves
|
||||||
|
'const sriptletGlobals = new Map();',
|
||||||
|
'',
|
||||||
|
cacheDetails.code,
|
||||||
'',
|
'',
|
||||||
'// <<<< end of private namespace',
|
'// <<<< end of private namespace',
|
||||||
'})();'
|
'})();',
|
||||||
);
|
];
|
||||||
|
|
||||||
return out.join('\n');
|
return out.join('\n');
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue