Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/1445
A third (optional) argument has been added to `remove-attr`
scriptlet, which can be one or more space-separated tokens
dictating the behavior of the scriptlet:
`stay`: This tells the scriplet to stay and act on DOM
changes, whiĺe the default behavior is to act only once
when the document becomes interactive.
`complete`: This tells the scriplet to start acting only
when the document is complete, i.e. once all secondary
resources have been loaded, while the default is to start
acting when the document is interactive -- which is earlier
than when the document is complete.
Example:
...##+js(remove-attr, class, .j-mini-player, stay)
When no-fetch-if scriptlet is used without argument, the
parameters passed to no-fetch-if will be output to the
console, as `uBO: fetch([...list of arguments...])`.
The new scriptlet allows to defuse calls to fetch() by returning
a promise which always resolve to an empty response.
There is only one argument, which is a space-separated list
of conditions which must be ALL fulfilled in order for the
defusing to take place.
Each condition is a pair of property name and property value
separated by a column. Valid property names are those
documented as valid `init` options:
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
The URL of the fetch() is a special case and does not have to
be associated with a property name. Example of usage:
...##+js(no-fetch-if, method:HEAD)
Which means: defuse the call to fetch() if there is an
explicit option which contains `HEAD`. Another example:
...##+js(no-fetch-if, adsbygoogle.js)
Which means: defuse the call to fetch() if the URL contains
`adsbygoogle.js`. Multiple conditions can be provided:
...##+js(no-fetch-if, adsbygoogle.js method:HEAD)
If at least one condition does not match, the defusing will
not take place.
The string against which to match can be a literal regular
expression:
...##+js(no-fetch-if, /adsbygoogle.js$/ method:/HEAD|POST/)
Additonally, the following deprecated scriplets have been
removed:
- requestAnimationFrame-if.js
- setInterval-defuser.js
- setTimeout-logger.js
This new scriplet has become necessary as a
countermeasure to new bypass mechanisms by
some websites, as discussed with filter list
maintainers.
Also related discussion:
https://github.com/AdguardTeam/Scriptlets/issues/82
Scriptlet: abort-on-stack-trace
Alias: aost
Argument 1:
The property to trap in order to launch the
stack trace matching code, ex. Math.random
Argument 2:
The string (needle) to match against the stack
trace. If the empty string, always match. There
is a special string which can be used to match
inline script context, <inline-script>.
Argument 3:
Whether to log, and if so how:
Empty string: do not log
1: log stack trace for all access to trapped
property
2: log stack trace for defused access to trapped
property
3: log stack trace for non-defused access to
trapped property
Reported internally by team.
Explicit conversion was causing an exception to be
thrown when the type argument was not supporting
`toString()`, for example when `type` argument was
literal `null`.
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.
Specifically:
- Log entries as received by client code
- Prettier and more readable console output
- Ability to only log entries matching a
specific needle
As per internal discussion at
<https://github.com/uBlockOrigin/uAssets>; limited
logging capabilities of json-prune originally raised
by <https://github.com/gwarser>.
Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/981
To be consistent with no-setTimeout-if.js.
requestAnimationFrame-if.js is deprecated and must no longer be
used, it will be removed in the near future when it's no longer
in use in default filter lists.
no-requestAnimationFrame-if.js is aliased to norafif.js.
The scriptlet will now still try to trap a specific
property if a segment of the chain is not undefined
while yet not an object either.
For example, this now allows to set a value on
`document.body.onselectstart` when `document.body` has
not been instantiated yet by the browser parser,
whereas this would previously fail because
`document.body` would be `null` while the scriptlet
was testing against `undefined`.
As per feedback from filter list maintainers, the
whitelist approach has been deemed to confusing.
The scriptlet has been renamed `no-setTimeout-if`
alias `nostif` to reflect the blacklist approach.
`setInterval-if` has been Similarly changed to
`no-setInterval-if` alias `nosiif`.
The scriptlet will trap calls to JSON.parse, and
if the result of the parsing is an Object, it
will remove specified properties from the result
before returning to the caller.
Usage:
##+js(json-prune, arg1, [arg2])
Where:
- arg1: a list of space-separated properties to remove
- arg2: optional, a list of space-separated properties
which must be all present for the pruning to
occur
Example:
##+js(json-prune, enabled, adpath config)
A property in a list of properties can be a chain
of properties, example: adpath.url.first
This also apply to setInterval-if. Thus to defuse
calls to setTimeout(fn, 1000), the filter could be:
##+js(stif, , !1000)
Meaning "allow setTimeout if the delay is not 1000".
Usage is similar to that of raf-if introduced in
commit 6831967f5f.
The two new scriptlets are meant to replace:
- setTimeout-defuser
- setTimeout-logger
- setInterval-defuser
- setInterval-logger
setTimeout-logger and setInterval-logger have been
removed, since they are not to be used in production.
To log setTimeout and setInterval usage, respectively
(using aliases):
- ##+js(stif)
- ##+js(siif)
To defuse setTimeout unconditionally:
- ##+js(stif, !)
Usage of setTimeout-defuser and setInterval-defuser
is deprecated and will be removed in some future when
they are no longer in use.
Keep in mind that the new scriptlets function on a
whitelist basis, whereas the deprecated ones
function on a blacklist basis. Prefixing the needle
with `!` allow to use the new scriptlets on a
blacklist basis.
Scriptlet name: `raf-if.js`
Usage: `example.com##+js(raf-if, !/(\d+){4}/)`
Argument: one single argument, which is the "needle" to
find in the stringified argument passed to
requestAnimationFrame.
requestAnimationFrame will be defused when:
- The needle is not prefixed with `!` and the needle
does not match the stringified argument; OR
- The needle is prefixed with `!` and the needle
matches the stringified argument.
The `raf-if.js` scriptlet will log calls to
requestAnimationFrame to the console when no parameter
is provided, i.e.:
example.com##+js(raf-if)
Otherwise no logging occurs.
Since https://github.com/uBlockOrigin/uBlock-issues/issues/156
won't be fixed in next release, no need to ship
with code which will be unused, and anyways only once
the fix is worked on will it be clear exactly what needs
to be used by scriptlets to deal harmoniously with
property listener collisions.
Make sure the parser is safely compatible with old
resources format -- for those users still using
custom resources (via `userResourcesLocation`).
Prepare code for future fix to
<https://github.com/uBlockOrigin/uBlock-issues/issues/156>:
This commit introduces a new private Map() object,
`uBOSafe`, accessible by all injected scriptlets. This
private safe can be used to store data which can be shared
with different scriptlets. The idea is for scriptlets to
use that safe to graciously deal with the need to install
multiple listeners for the same property.