summaryrefslogtreecommitdiff
path: root/data/extensions/uBlock0@raymondhill.net/js/resources/stack-trace.js
diff options
context:
space:
mode:
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.js148
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,
+ ],
+});
+
+/******************************************************************************/