diff options
Diffstat (limited to 'data/extensions/uBlock0@raymondhill.net/js/resources/stack-trace.js')
-rw-r--r-- | data/extensions/uBlock0@raymondhill.net/js/resources/stack-trace.js | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/data/extensions/uBlock0@raymondhill.net/js/resources/stack-trace.js b/data/extensions/uBlock0@raymondhill.net/js/resources/stack-trace.js new file mode 100644 index 0000000..c2e5358 --- /dev/null +++ b/data/extensions/uBlock0@raymondhill.net/js/resources/stack-trace.js @@ -0,0 +1,148 @@ +/******************************************************************************* + + uBlock Origin - a comprehensive, efficient content blocker + Copyright (C) 2019-present Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock + +*/ + +import { getExceptionTokenFn } from './utils.js'; +import { registerScriptlet } from './base.js'; +import { safeSelf } from './safe-self.js'; + +/******************************************************************************/ + +export function matchesStackTraceFn( + needleDetails, + logLevel = '' +) { + const safe = safeSelf(); + const exceptionToken = getExceptionTokenFn(); + 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 safe.String_split.call(error.stack, /[\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 = needleDetails.matchAll !== true && + safe.testPattern(needleDetails, stack); + if ( + logLevel === 'all' || + logLevel === 'match' && r || + logLevel === 'nomatch' && !r + ) { + safe.uboLog(stack.replace(/\t/g, '\n')); + } + return r; +} +registerScriptlet(matchesStackTraceFn, { + name: 'matches-stack-trace.fn', + dependencies: [ + getExceptionTokenFn, + safeSelf, + ], +}); + +/******************************************************************************/ + +function abortOnStackTrace( + chain = '', + needle = '' +) { + if ( typeof chain !== 'string' ) { return; } + const safe = safeSelf(); + const needleDetails = safe.initPattern(needle, { canNegate: true }); + const extraArgs = safe.getExtraArgs(Array.from(arguments), 2); + if ( needle === '' ) { extraArgs.log = 'all'; } + const makeProxy = function(owner, chain) { + const pos = chain.indexOf('.'); + if ( pos === -1 ) { + let v = owner[chain]; + Object.defineProperty(owner, chain, { + get: function() { + const log = safe.logLevel > 1 ? 'all' : 'match'; + if ( matchesStackTraceFn(needleDetails, log) ) { + throw new ReferenceError(getExceptionTokenFn()); + } + return v; + }, + set: function(a) { + const log = safe.logLevel > 1 ? 'all' : 'match'; + if ( matchesStackTraceFn(needleDetails, log) ) { + throw new ReferenceError(getExceptionTokenFn()); + } + v = a; + }, + }); + return; + } + const prop = chain.slice(0, pos); + let v = owner[prop]; + chain = chain.slice(pos + 1); + if ( v ) { + makeProxy(v, chain); + return; + } + const desc = Object.getOwnPropertyDescriptor(owner, prop); + if ( desc && desc.set !== undefined ) { return; } + Object.defineProperty(owner, prop, { + get: function() { return v; }, + set: function(a) { + v = a; + if ( a instanceof Object ) { + makeProxy(a, chain); + } + } + }); + }; + const owner = window; + makeProxy(owner, chain); +} +registerScriptlet(abortOnStackTrace, { + name: 'abort-on-stack-trace.js', + aliases: [ + 'aost.js', + ], + dependencies: [ + getExceptionTokenFn, + matchesStackTraceFn, + safeSelf, + ], +}); + +/******************************************************************************/ |