Related discussion:
https://github.com/ameshkov/diffupdates
The benefits of diff-patching filter lists is much shorter update
schedule and significantly less bandwidth consumed.
At the moment, only default filter lists are subject to be
diff-patched.
External filter lists can make their lists diff-patchable by
following the specification link above.
Only filter lists fetched by the auto-updater are candidate for
diff-patching.
Forcing a manual update of the filter lists will prevent the
diff-patcher from kicking in until one or more lists are
auto-updated.
Some back-of-the-envelop calculations regarding the load on free
CDN solutions used by uBO to distribute its own filter lists:
Currently, for each CDN (with lists updating after days):
~560 M req/month, ~78 TB/month
With diff-patching lists on a 6-hour schedule:
~390 M req/month, 1 TB/month
Those estimates were done according to statistics shown by
jsDelivr, which is one of 4 CDNs picked randomly when a list
updates:
https://www.jsdelivr.com/package/gh/uBlockOrigin/uAssetsCDN?tab=stats
Essentially a complement of `trusted-prune-inbound-object.js` added in
1c9da227d7
To perform object pruning on any object returned synchronously by
any given call.
The arguments for `trusted-prune-outbound-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 properties to prune (as with `json-prune`)
- The properties which must all be present for pruning to occur
(as with `json-prune`)
The scriptlets `json-prune.js` and `evaldata-prune.js` essentially
perform the same function, and will eventually be rewritten to
internally delegate to generic `trusted-prune-outbound-object.js`.
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)
If the `version` vararg is present and set to `2`, and if a
fetch Request argument is present, it will be cloned before
being matched to `propsToMatch` properties.
Additionally, created a `.fn` version of `[...]-fetch-response`
scriptlets to avoid redundant code in final injected scriptlets.
Prevent usage of specific or all (default) canvas APIs.
Syntax
```text
example.com##+js(prevent-canvas [, contextType])
```
- `contextType`: A specific type of canvas API to prevent (default to all
APIs). Can be a string or regex which will be matched against the type
used in getContext() call. Prepend with `!` to test for no-match.
Examples
1. Prevent `example.com` from accessing all canvas APIs
```adblock
example.com##+js(prevent-canvas)
```
2. Prevent access to any flavor of WebGL API, everywhere
```adblock
*##+js(prevent-canvas, /webgl/)
```
3. Prevent `example.com` from accessing any flavor of canvas API except `2d`
```adblock
example.com##+js(prevent-canvas, !2d)
```
References
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
To prepare for better compatibility with AdGuard's own `set-constant`
scriptlet.
The 3rd position parameter which dictates how to set the value has
been converted into a vararg paramater, as follow:
..., as, function
..., as, callback
..., as, resolved
..., as, rejected
Similarly, the parameter used to dictate when the scriptlet
should become effective is now to be used as a vararg:
..., runAt, load
Related issue:
https://github.com/uBlockOrigin/uBlock-issues/issues/2783
Ideally, AdGuard would support its `stack` parameter as a
vararg, to be discussed.
Related issue:
https://github.com/uBlockOrigin/uBlock-issues/issues/2773
The `randomize` paramater introduced in https://github.com/gorhill/uBlock/commit/418087de9c
is now named `directive`, and beside the `true` value which is meant
to respond with a random 10-character string, it can now take the
following value:
war:[web_accessible_resource name]
In order to mock the XHR response with a web accessible resource. For
example:
piquark6046.github.io##+js(no-xhr-if, adsbygoogle.js, war:googlesyndication_adsbygoogle.js)
Will cause the XHR performed by the webpage to resolve to the content
of `/web_accessible_resources/googlesyndication_adsbygoogle.js`.
Should the resource not exist, the empty string will be returned.
Now support AdGuard's `randomize` parameter. If `true`,
the scriplet will generate a random 10-character string
to be returned as the response.
Reference:
https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-xhr
AdGuard's `prevent-xhr` also support `length:n-m` form,
but since I do not see it being used, for now it's not
supported in uBO's `no-xhr-if`.
Additionally, the scriptlet will now honor `responseType` and
return the proper response type accordingly.
`fetchPropsToMatch` is an optional variable argument. If provided,
the scriplet will take effect only when the JSON data is obtained
through `Response.json()` and if there is a match with the value of
`fetchPropsToMatch` and the properties of the `Response` instance.
Examples of usage:
...##+js(json-prune, ads, , , fetchPropsToMatch, ?param=)
...##+js(json-prune, ads, , , fetchPropsToMatch, url:?param= method:get)
The optional variable argument `fetchPropsToMatch` acts as an additional
narrowing condition to fulfill before the JSON data is pruned.
Specifically, the variable argument `log` can take one of three
values to enable logging mechanism:
..., log, match => log only when there is a match
..., log, nomatch => log only when there is no match
..., log, all => log unconditionally
Prepend pattern with `!` to test for unmatched patterns in
stack trace. This applies to sctiplet parameters which purpose
is to test against the stack, i.e. `aost` and `json-prune`.
Additionally, dropped support for JSON notation in favor of
optional variable arguments notation.
Related discussion:
- https://github.com/uBlockOrigin/uBlock-discussions/discussions/789#discussioncomment-6520330
This extends logging capabilities of `json-prune` scriptlet as
follow:
...##+js(json-prune, a, b, stackNeedle, log, [logneedle], logstack, 1)
Whereas before, the only way to log `json-prune` usage was to skip
providing the property chain:
...##+js(json-prune, , b)
Where `b` was the expression to filter out logging output.
With the extended logging capabilities, the logging output can
be filtered out with `logneedle`, which can be a regex literal.
Additionally, to log the stack trace the `stackNeedle` argument
must be set to non-empty string. You can use `/.^/` to log the
stack trace without matching it.
Related issue:
- https://github.com/AdguardTeam/Scriptlets/issues/332
Additionally, uBO's own scriplet syntax now also accept quoting
the parameters with either `'` or `"`. This can be used to avoid
having to escape commas when they are present in a parameter.
Related issue:
- https://github.com/uBlockOrigin/uAssets/issues/18725
Testing the context was causing the deprecated static property
RegExp.$1 to be clobbered, causing webpage breakage because this
property was subsequently used used by the caller.
New official name: `no-window-open-if`.
The pattern will now be matched against all arguments passed
to `window.open()`: all the arguments are joined as a single
space-spearated string, and the result is used as the target
for matching the pattern.
To enable logging, used the extra parameters approach, i.e.
`log, 1`, which should come after the positional arguments
`pattern`, `delay`, and `decoy`.
Added support for extra parameter `reload, 1`. If present,
the scriplet will force a reload of the webpage if the cookie
being set was not already set.
As per feedback from filter list maintainers.
The scriptlet remove the *whole* text of a DOM node. Usage:
example.com##+js(remote-node-text, nodeName, condition, ...)
Where `condition` is a pattern to find in the target node for the
removal to occur. Since the text of the node is wholly removed,
this is not a scriplet which requires a trusted-source, as it is
virtually a similar capability as removing DOM nodes through
procedural cosmetic operator `:remove()` (which can't target
`#text` nodes), which does not require trusted-source.
Alias: `rmnt`
The extra parameters are the same as those documented for
`replace-node-text`.
For consistency, the alias for `replace-node-text` has been renamed
`rpnt`.
When scriptlets can receive extra optional paramaters, these will
now be passed as pair of extra paramaters in the filter declaration,
whereas each pair is a `name, value` instance.
As a result, the optional paramaters that can be passed to the
`aeld` scriptlet can be passed this way, i.e. no longer need
a JSON approach, example:
github.com##+js(aeld, click, , log, 1)
github.com##+js(aeld, , , runAt, idle, log, 1)
The non-optional paramaters are always positional, after which
the optional paramaters are non-positional pairs of values.
Alias: `trusted-set`
Behaves exactly like set-constant, except that any arbitrary JSON-
compatible value can be set.
By default the value is treated as a string, which can be anything.
If the value starts with `{` and ends with `}`, the value will be
JSON-parsed, and the `value` property of the resulting object will
be used.
As with any scriptlet requiring trust, filters using
`trusted-set-constant` can only come from trusted filter lists,
otherwise they are discarded.
Related discussion:
- https://github.com/uBlockOrigin/uAssets/discussions/18185#discussioncomment-5977456
This reflects the _world_ of the MV3 scripting API:
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/scripting/ExecutionWorld
MAIN: page's world
ISOLATED: extension's content script world
Some scriptlets are best executed in either world, so this
commit allows to pick in which world a scriptlet should execute
(default to MAIN).
For instance, the new sed.js scriptlet will now execute in
the ISOLATED world.
Related commit:
- 41876336db
The `tryCount` parameter has been removed.
The new default behavior of the sed.js scriptlet is to bail out
when the document itself has been fully loaded, i.e. when
DOMContentLoaded event is fired.
Two new parameters have been added to override the default quit out
behavior:
`stay, 1`
Use to force the scriptlet to stay at work forever.
`quitAfter, ms`
This tells the scriptlet to quit `ms` milliseconds after the
page has been loaded, i.e. after the DOMContentLoaded event has
been fired.
The mutation observer of the sed.js scriptlet can be a significant
overhead for pages with dynamically updated DOM, and in most cases
the scriptlet is useful only for DOM changes occurring before the
DOMContentLoaded event, so the default is to quit out when that
event is received ("quit out" means discarding the mutation observer
and having the scriptlet garbage-collected by the JS engine).
To ensure smooth transition in next stable release: people on
an older version of uBO could end up updating assets.json,
hence we needs to keep a local URL to the non-minified packaged
version of the lists.
At the moment, the only filter lists deemed from a "trusted source"
are uBO-specific filter lists (i.e. "uBlock filters -- ..."), and
the user's own filters from "My filters".
A new scriptlet which can only be used by filter lists from trusted
sources has been introduced: `sed.js`.
The new `sed.js` scriptlet provides the ability to perform
text-level substitutions. Usage:
example.org##+js(sed, nodeName, pattern, replacement, ...)
`nodeName`
The name of the node for which the text content must be substituted.
Valid node names can be found at:
https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeName
`pattern`
A string or regex to find in the text content of the node as the target of
substitution.
`replacement`
The replacement text. Can be omitted if the goal is to delete the text which
matches the pattern. Cannot be omitted if extra pairs of parameters have to be
used (see below).
Optionally, extra pairs of parameters to modify the behavior of the scriptlet:
`condition, pattern`
A string or regex which must be found in the text content of the node
in order for the substitution to occur.
`sedCount, n`
This will cause the scriptlet to stop after n instances of substitution. Since
a mutation oberver is used by the scriptlet, it's advised to stop it whenever
it becomes pointless. Default to zero, which means the scriptlet never stops.
`tryCount, n`
This will cause the scriptlet to stop after n instances of mutation observer
run (regardless of whether a substitution occurred). Default to zero, which
means the scriptlet never stops.
`log, 1`
This will cause the scriptlet to output information at the console, useful as
a debugging tool for filter authors. The logging ability is supported only
in the dev build of uBO.
Examples of usage:
example.com##+js(sed, script, /devtoolsDetector\.launch\(\)\;/, , sedCount, 1)
example.com##+js(sed, #text, /^Advertisement$/)
Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/2618
Usage:
example.com##+js(spoof-css, selector, property-name, property-value, ...)
- selector: a valid CSS selector which matches the elements for which
the spoofing must apply.
- property-name: a CSS property name (can be dashed- or camel-cased)
- property-value: the value to return regardless of the currently
computed value.
There can be any number of property-name/property-value pairs, all
separated by commas.
A special property-name/property-value pair `debug/1` can be used
to force the browser to break when `getComputedStyle()` or
`getBoundingClientrect()` is called, useful to help pinpoint usage
of those calls in the page's source code:
example.com##+js(spoof-css, .ad, debug, 1)
Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/2615
Expand `set-constant`: 3rd parameter and beyond are tokens which
modify the behavior of `set-contant`. Valid tokens:
- `interactive`, `end`, `2`: set the constant when the event
`DOMContentInteractive` is fired.
- `complete`, `idle`, `3`: set the constant when the event
`load` is fired.
- `asFunction`: the constant will be a function returning the
specified value.
- `asCallback`: the constant will be a function returning a
function returning the specified value.
- `asResolved`: the constant will be a promise resolving to
the specified value.
- `asRejected`: the constant will be a promise failing with
the specified value.
Harden `no-setimeout-if` and `no-setinterval-if` as per feedback
from filter list maintainers.
As discussed internally with filter list maintainers.
Additionally, added a search field to filter out lists. This
is still a work in progress, no need to open issues about this,
I am aware of what is missing (i18n, more tags, etc.)
To be replaced with five sublists.
Users who are already subscribed to the list will have to manually
unsubscribe from it, which will be moved to _Custom_ section, and
subscribe to the sublists which have narrower purpose.
As per discussion with filter list maintainers.
THis requires to use JSON notation for parameter passing:
- "runAt": "end" = execute scriptlet at `DOMContentLoaded` event
- "runAt": "idle" = execute scriptlet at `load` event
A new optional parameter has been added to `set-constant`
scriptlet: `runAt`, default to `0`.
..##+js(set, document.body.oncontextmenu, null, 2)
When the `runAt` parameter is present, uBO will take it into
account to possibly defer execution of `set-constant`:
- `runAt` not present: execute immediately
- `runAt` = 1: execute immediately
- `runAt` = 2: execute when document state is "interactive"
- `runAt` = 3: execute when document state is `"complete"
maintainers.
To enable logging, use the JSON approach to pass parameters to
`acs` scriptlet. Example:
..##+js(acs, { "target": "document.oncontextmenu", "log": true })
Whereas "target", "needle", and "context" correspond to their
respective positional argument. Using JSON form to pass parameters
allows to specify extra paramters to facilitate debugging of that
scriptlet:
- `"log": true` => output useful information at the dev console.
- `"debug": true` => break at key locations in the scriptlet.
The added logging/debugging capabilities work only in the dev build
of uBO or if the advanced setting `filterAuthorMode` is set to
`true`.
The scriptlet addEventListenerLogger has been removed.
The logging of addEventListener() calls can now be done with the
addEventListenerDefuser scriptlet, which now supports the
following named arguments:
"type": the event type to match. Default to '', i.e. match-all.
"pattern": the pattern to match against the handler argument
Default to '', i.e. match-all.
"log": an integer value telling when to log:
- 1: log only when both type and pattern matches, i.e. when a
call to addEventListener() is defused
- 2: log when either the type or pattern matches
- 3: log all calls to addEventListener()
"debug": an integer value telling when to break into the
debugger, useful to inspect the debugger's call stack.
- 1: break into the debugger when both type and pattern match,
so effectively when defusing is taking place.
- 2: break into the debugger when either type or pattern matches.
The usage of named arguments is optional, positional arguments
are still supported as documented. Named arguments is required
to use "log" and/or "debug" arguments.
Obviously, do not use "log" or "debug" in any filter list, these
are investigative tools for filter list authors.
Examples of usage using named arguments:
wikipedia.org##+js(aeld, { "type": "/mouse/", "pattern": "/.^/", "log": 2 })
Above filter will log calls to addEventListener() which have the
pattern "mouse" in the event type (so "mouseover", "mouseout",
etc.) without defusing any of them (because pattern can't match
anything).
wikipedia.org##+js(aeld, { "type": "/.^/", "log": 2 })
Above filter will log all calls without defusing any of them
(because type can't match anything)
wikipedia.org##+js(aeld, { "log": 1 })
Above filter will log and defuse all calls to addEventListener().
Builtin scriptlets are no longer parsed as text-based resources,
they are imported as JS functions, and `toString()` is used to
obtain text-based representation of a scriptlet.
Scriptlet parameters are now passed as function call arguments
rather than by replacing text-based occurrences of `{{i}}`. The
arguments are always string values (see below for exception).
Support for argument as Object has been added. This opens the
door to have scriptlets using named arguments rather than
positional arguments, and hence easier to extend functionality
of existing scriptlets. Example:
example.com##+js(scriplet, { "prop": "adblock", "value": false, "log": true })
Compatibility with user-provided scriptlets has been preserved.
User-provided scriptlets can benefit some of the changes:
Use the form `function(..){..}` instead of `(function(..){..})();`
in order to received scriptlet arguments as part of function call
-- instead of using `{{i}}`.
If using the form `function(..){..}`, you can choose to receive
an Object as argument -- just be sure that your scriptlet's
parameter is valid JSON notation.
The purpose is to prevent a call to an existing function from
throwing an exception. The exception will be caught by the
scriptlet and neutralized.
The first argument must be a reference to a function call. At
the moment, the function call must exist at the time the
scriptlet is called.
Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/2508
If the first argument is a regex with multine flag set, the
scriptlet will execute the regex against the whole text, and
remove matching text from the whole text.
If the matching text does not contains whole lines, the text
won't be removed, i.e. it is not allowed to remove only part
of a line.
Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/2531#issuecomment-1462389539
Usage:
- example.com##+js(href-sanitizer, a[href^="/go?to="]:not([title]))
- example.com##+js(href-sanitizer, a[href^="/go?to="][title], [title])
The second argument is the attribute from which to extract the text
to be used for the `href` attribute of the link. If the second
attribute is absent, the text content of the element will be used.
Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/2531
Usage:
example.com##+js(href-from-text, a[href^="/tracker-link?to="]
The above scriptlet will find all elements matching the selector
passed as 1st argument, and replace the `href` attribute with the
text content of the element, if all the following conditions are
met:
- The element is a link (`a`) element
- The link element has an existing `href` attribute
- The text content of the element is a valid `https`-based URL
Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/2358
We need two different branches of uAssets to properly add the
default filter lists into the packages. I couldn't figure out
how to do this with submodules, using simple `git clone` as a
dependency just work.