summaryrefslogtreecommitdiff
path: root/data/extensions/uBlock0@raymondhill.net/js/resources/proxy-apply.js
diff options
context:
space:
mode:
Diffstat (limited to 'data/extensions/uBlock0@raymondhill.net/js/resources/proxy-apply.js')
-rw-r--r--data/extensions/uBlock0@raymondhill.net/js/resources/proxy-apply.js109
1 files changed, 109 insertions, 0 deletions
diff --git a/data/extensions/uBlock0@raymondhill.net/js/resources/proxy-apply.js b/data/extensions/uBlock0@raymondhill.net/js/resources/proxy-apply.js
new file mode 100644
index 0000000..60326f5
--- /dev/null
+++ b/data/extensions/uBlock0@raymondhill.net/js/resources/proxy-apply.js
@@ -0,0 +1,109 @@
+/*******************************************************************************
+
+ 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 { registerScriptlet } from './base.js';
+
+/******************************************************************************/
+
+export function proxyApplyFn(
+ target = '',
+ handler = ''
+) {
+ let context = globalThis;
+ let prop = target;
+ for (;;) {
+ const pos = prop.indexOf('.');
+ if ( pos === -1 ) { break; }
+ context = context[prop.slice(0, pos)];
+ if ( context instanceof Object === false ) { return; }
+ prop = prop.slice(pos+1);
+ }
+ const fn = context[prop];
+ if ( typeof fn !== 'function' ) { return; }
+ if ( proxyApplyFn.CtorContext === undefined ) {
+ proxyApplyFn.ctorContexts = [];
+ proxyApplyFn.CtorContext = class {
+ constructor(...args) {
+ this.init(...args);
+ }
+ init(callFn, callArgs) {
+ this.callFn = callFn;
+ this.callArgs = callArgs;
+ return this;
+ }
+ reflect() {
+ const r = Reflect.construct(this.callFn, this.callArgs);
+ this.callFn = this.callArgs = this.private = undefined;
+ proxyApplyFn.ctorContexts.push(this);
+ return r;
+ }
+ static factory(...args) {
+ return proxyApplyFn.ctorContexts.length !== 0
+ ? proxyApplyFn.ctorContexts.pop().init(...args)
+ : new proxyApplyFn.CtorContext(...args);
+ }
+ };
+ proxyApplyFn.applyContexts = [];
+ proxyApplyFn.ApplyContext = class {
+ constructor(...args) {
+ this.init(...args);
+ }
+ init(callFn, thisArg, callArgs) {
+ this.callFn = callFn;
+ this.thisArg = thisArg;
+ this.callArgs = callArgs;
+ return this;
+ }
+ reflect() {
+ const r = Reflect.apply(this.callFn, this.thisArg, this.callArgs);
+ this.callFn = this.thisArg = this.callArgs = this.private = undefined;
+ proxyApplyFn.applyContexts.push(this);
+ return r;
+ }
+ static factory(...args) {
+ return proxyApplyFn.applyContexts.length !== 0
+ ? proxyApplyFn.applyContexts.pop().init(...args)
+ : new proxyApplyFn.ApplyContext(...args);
+ }
+ };
+ }
+ const fnStr = fn.toString();
+ const toString = (function toString() { return fnStr; }).bind(null);
+ const proxyDetails = {
+ apply(target, thisArg, args) {
+ return handler(proxyApplyFn.ApplyContext.factory(target, thisArg, args));
+ },
+ get(target, prop) {
+ if ( prop === 'toString' ) { return toString; }
+ return Reflect.get(target, prop);
+ },
+ };
+ if ( fn.prototype?.constructor === fn ) {
+ proxyDetails.construct = function(target, args) {
+ return handler(proxyApplyFn.CtorContext.factory(target, args));
+ };
+ }
+ context[prop] = new Proxy(fn, proxyDetails);
+}
+registerScriptlet(proxyApplyFn, {
+ name: 'proxy-apply.fn',
+});