Skip to content

Commit

Permalink
Add support for wildcard/array in json-prune
Browse files Browse the repository at this point in the history
Add support for specially-named properties:

`[]`, to iterate through all elements in an array, in
order to deal more graciously with cases where the
property to remove is an element in an array. An
actual case:

    +js(json-prune, playlist.movies.0.adserver playlist.movies.1.adserver ...)

Can be now converted to:

    +js(json-prune, playlist.movies.[].adserver)

`*`, to iterate through all own properties of an object,
in order to deal with random-named properties. For
example (not an actual case):

    +js(json-prune, playlist.*.adserver)

Where `adserver` would be a property member of an
object which is itself a property of `playlist`, but
which name is unknown or is variable.
  • Loading branch information
gorhill committed Jun 26, 2020
1 parent da6cdf9 commit f433932
Showing 1 changed file with 24 additions and 12 deletions.
36 changes: 24 additions & 12 deletions assets/resources/scriptlets.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,27 +278,42 @@
}
reLogNeedle = new RegExp(needle);
}
const findOwner = function(root, path) {
const findOwner = function(root, path, prune = false) {
let owner = root;
let chain = path;
for (;;) {
if ( owner instanceof Object === false ) { return; }
if ( owner instanceof Object === false ) { return false; }
const pos = chain.indexOf('.');
if ( pos === -1 ) {
return owner.hasOwnProperty(chain)
? [ owner, chain ]
: undefined;
const found = owner.hasOwnProperty(chain);
if ( found === false ) { return false; }
if ( prune ) {
delete owner[chain];
}
return true;
}
const prop = chain.slice(0, pos);
if ( owner.hasOwnProperty(prop) === false ) { return; }
if (
prop === '[]' && Array.isArray(owner) ||
prop === '*' && owner instanceof Object
) {
const next = chain.slice(pos + 1);
let found = false;
for ( const item of owner.values() ) {
found = findOwner(item, next, prune) || found;
}
return found;
}
if ( owner.hasOwnProperty(prop) === false ) { return false; }
owner = owner[prop];
chain = chain.slice(pos + 1);
}
};
const mustProcess = function(root) {
for ( const needlePath of needlePaths ) {
const details = findOwner(root, needlePath);
if ( details === undefined ) { return false; }
if ( findOwner(root, needlePath) === false ) {
return false;
}
}
return true;
};
Expand All @@ -314,10 +329,7 @@
}
if ( mustProcess(r) === false ) { return r; }
for ( const path of prunePaths ) {
const details = findOwner(r, path);
if ( details !== undefined ) {
delete details[0][details[1]];
}
findOwner(r, path, true);
}
return r;
},
Expand Down

2 comments on commit f433932

@gwarser
Copy link
Contributor

@gwarser gwarser commented on f433932 Jul 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An
actual case:

+js(json-prune, playlist.movies.0.adserver playlist.movies.1.adserver ...)

Can be now converted to:

+js(json-prune, playlist.movies.[].adserver)

@lain566 was this really an array? uBlockOrigin/uAssets#6955 uBlockOrigin/uAssets@8886726

I'm pretty sure this was working only on object with keys explicitly named as "0", "1", "2", and not on real array without keys.

Not easy to reproduce now, but it seems I'm right:
image

@gorhill bad exmple :/ ;) (updating wiki for json-prune now)

@gorhill
Copy link
Owner Author

@gorhill gorhill commented on f433932 Jul 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, I just looked at the filter and thought it was trying to index elements in an array, without further checking if this was really the case.

Please sign in to comment.