diff --git a/src/js/resources/json-prune.js b/src/js/resources/json-prune.js index ec4207a2b..aa7878418 100644 --- a/src/js/resources/json-prune.js +++ b/src/js/resources/json-prune.js @@ -42,32 +42,31 @@ function jsonPrune( const logPrefix = safe.makeLogPrefix('json-prune', rawPrunePaths, rawNeedlePaths, stackNeedle); const stackNeedleDetails = safe.initPattern(stackNeedle, { canNegate: true }); const extraArgs = safe.getExtraArgs(Array.from(arguments), 3); - JSON.parse = new Proxy(JSON.parse, { - apply: function(target, thisArg, args) { - const objBefore = Reflect.apply(target, thisArg, args); - if ( rawPrunePaths === '' ) { - safe.uboLog(logPrefix, safe.JSON_stringify(objBefore, null, 2)); - } - const objAfter = objectPruneFn( - objBefore, - rawPrunePaths, - rawNeedlePaths, - stackNeedleDetails, - extraArgs - ); - if ( objAfter === undefined ) { return objBefore; } - safe.uboLog(logPrefix, 'Pruned'); - if ( safe.logLevel > 1 ) { - safe.uboLog(logPrefix, `After pruning:\n${safe.JSON_stringify(objAfter, null, 2)}`); - } - return objAfter; - }, + proxyApplyFn('JSON.parse', function(context) { + const objBefore = context.reflect(); + if ( rawPrunePaths === '' ) { + safe.uboLog(logPrefix, safe.JSON_stringify(objBefore, null, 2)); + } + const objAfter = objectPruneFn( + objBefore, + rawPrunePaths, + rawNeedlePaths, + stackNeedleDetails, + extraArgs + ); + if ( objAfter === undefined ) { return objBefore; } + safe.uboLog(logPrefix, 'Pruned'); + if ( safe.logLevel > 1 ) { + safe.uboLog(logPrefix, `After pruning:\n${safe.JSON_stringify(objAfter, null, 2)}`); + } + return objAfter; }); } registerScriptlet(jsonPrune, { name: 'json-prune.js', dependencies: [ objectPruneFn, + proxyApplyFn, safeSelf, ], }); diff --git a/src/js/resources/proxy-apply.js b/src/js/resources/proxy-apply.js index 5fc6d7e55..125e4300a 100644 --- a/src/js/resources/proxy-apply.js +++ b/src/js/resources/proxy-apply.js @@ -86,27 +86,38 @@ export function proxyApplyFn( } }; proxyApplyFn.isCtor = new Map(); + proxyApplyFn.proxies = new WeakMap(); + proxyApplyFn.nativeToString = Function.prototype.toString; + const proxiedToString = new Proxy(Function.prototype.toString, { + apply(target, thisArg) { + let proxied = thisArg; + for(;;) { + const fn = proxyApplyFn.proxies.get(proxied); + if ( fn === undefined ) { break; } + proxied = fn; + } + return proxyApplyFn.nativeToString.call(proxied); + } + }); + proxyApplyFn.proxies.set(proxiedToString, proxyApplyFn.nativeToString); + Function.prototype.toString = proxiedToString; } if ( proxyApplyFn.isCtor.has(target) === false ) { proxyApplyFn.isCtor.set(target, fn.prototype?.constructor === fn); } - 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 ( proxyApplyFn.isCtor.get(target) ) { proxyDetails.construct = function(target, args) { return handler(proxyApplyFn.CtorContext.factory(target, args)); }; } - context[prop] = new Proxy(fn, proxyDetails); + const proxiedTarget = new Proxy(fn, proxyDetails); + proxyApplyFn.proxies.set(proxiedTarget, fn); + context[prop] = proxiedTarget; } registerScriptlet(proxyApplyFn, { name: 'proxy-apply.fn',