Skip to content

Commit

Permalink
Add trusted-prune-inbound-object scriptlet
Browse files Browse the repository at this point in the history
As per discussion with filter list maintainers.

To perform object pruning for any given call which has an object
as argument (hence "inbound").

Since `json-prune-stringify` scriptlet is a specific form of
pruning inbound objects, it has been removed.

The arguments for `trusted-prune-inbound-object` in order are:

- The name of the property to trap. Must be a function, and must
  exist when the scriptlet tries to install the trap.

- The position of the object to prune in the argument list when
  the trapped function is called. The position is 1-based and
  must be an integer greater than 0.

- The properties to prune (as with `json-prune`)

- The properties which must all be present for pruning to occur
  (as with `json-prune`)

- Varargs:
  - `, dontOverwrite, 1`: do not modify the target inbound object

Examples:

Remove `title` and `name` properties before passing the object to
`JSON.stringify` call:

  example.org##+js(trusted-prune-inbound-object, JSON.stringify, 1, title name)

Remove `status` property before passing the object to `Object.keys`
call but do not modify caller's instance of the object:

  example.org##+js(trusted-prune-inbound-object, Object.keys, 1, status, , dontOverwrite, 1)
  • Loading branch information
gorhill committed Oct 21, 2023
1 parent 287f771 commit 1c9da22
Showing 1 changed file with 56 additions and 36 deletions.
92 changes: 56 additions & 36 deletions assets/resources/scriptlets.js
Expand Up @@ -1429,42 +1429,6 @@ function jsonPrune(
});
}

/******************************************************************************/

builtinScriptlets.push({
name: 'json-prune-stringify.js',
fn: jsonPruneStringify,
dependencies: [
'object-prune.fn',
'safe-self.fn',
],
});
function jsonPruneStringify(
rawPrunePaths = '',
rawNeedlePaths = '',
stackNeedle = ''
) {
const safe = safeSelf();
const stackNeedleDetails = safe.initPattern(stackNeedle, { canNegate: true });
const extraArgs = safe.getExtraArgs(Array.from(arguments), 3);
JSON.stringify = new Proxy(JSON.stringify, {
apply: function(target, thisArg, args) {
const objBefore = args[0];
if ( objBefore instanceof Object ) {
const objAfter = objectPruneFn(
objBefore,
rawPrunePaths,
rawNeedlePaths,
stackNeedleDetails,
extraArgs
);
args[0] = objAfter || objBefore;
}
return Reflect.apply(target, thisArg, args);
},
});
}

/*******************************************************************************
*
* json-prune-fetch-response.js
Expand Down Expand Up @@ -4071,3 +4035,59 @@ function trustedClickElement(
}

/******************************************************************************/

builtinScriptlets.push({
name: 'trusted-prune-inbound-object.js',
requiresTrust: true,
fn: trustedPruneInboundObject,
dependencies: [
'object-prune.fn',
'safe-self.fn',
],
});
function trustedPruneInboundObject(
entryPoint = '',
argPos = '',
rawPrunePaths = '',
rawNeedlePaths = ''
) {
if ( entryPoint === '' ) { return; }
let context = globalThis;
let prop = entryPoint;
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);
}
if ( typeof context[prop] !== 'function' ) { return; }
const argIndex = parseInt(argPos);
if ( isNaN(argIndex) ) { return; }
if ( argIndex < 1 ) { return; }
const safe = safeSelf();
const extraArgs = safe.getExtraArgs(Array.from(arguments), 4);
context[prop] = new Proxy(context[prop], {
apply: function(target, thisArg, args) {
const targetArg = argIndex <= args.length
? args[argIndex-1]
: undefined;
if ( targetArg instanceof Object ) {
const objBefore = extraArgs.dontOverwrite
? safe.JSON_parse(safe.JSON_stringify(targetArg))
: targetArg;
const objAfter = objectPruneFn(
objBefore,
rawPrunePaths,
rawNeedlePaths,
{ matchAll: true },
extraArgs
);
args[argIndex-1] = objAfter || objBefore;
}
return Reflect.apply(target, thisArg, args);
},
});
}

/******************************************************************************/

0 comments on commit 1c9da22

Please sign in to comment.