FiltersCompiler icon indicating copy to clipboard operation
FiltersCompiler copied to clipboard

Migrate to scriptlets and get rid of JS rules

Open ameshkov opened this issue 8 years ago • 0 comments

@ameshkov commented on Wed Feb 08 2017

Adguard scriptlet is a named script, which can be used further by JS or basic rules. Scriptlets are configured in a special "scriptlets" configuration file and maintained by us.

Why do we need it

  1. JS rules are simply hard to support. We currently have more than 700 JS rules in all the AG filters, and the number is growing.
  2. Some JS rules are almost identical. For instance, Object.defineProperty(window) is used by ~200 rules.
  3. AMO and Opera review. It will make reviewers life much easier.

I don't say we should get rid of JS rules completely, though. It should be allowed in the user filter, just not in other filters.

Scriptlets configuration file will be updated automatically along with the filters. However, in the case of AMO and Opera, automatic update will be disabled so that we comply with remote scripts policy.

Scriptlets usage syntax

There are two options.

Injecting and executing scriptlet on a per-domain basis:

example.org#&#scriptlet:scriptletName(param1, param2);

Replacing JS file content with a scriptlet

I am not sure about it, though. I suppose we should start with injection only. ||example.org/file.js$replace=scriptlet:scriptletName(param1, param2);

Scriptlets configuration file

Here is an example of the scriptlet configuration file.

/**
 * Scriptlets configuration object.
 */
var scriptlets = {

	// Scriptlets file version
	version: "1.0.0"
};

/**
 * Empty scriptlet, just to show you the idea.
 *
 * @param context 		Scriptlet execution context
 */
scriptlets["empty"] = function(context) {
	// context.log 		Prints message to the console
	// context.version	Scriptlets configuration file version
	context.log(context.version);

	// scriptlet parameter
	console.log(context.params[0]);
};

/**
 * Defines "window" property.
 *
 * Example: 
 * example.org#%#scriptlet:defineWindowProperty("test", 1);
 */
scriptlets["defineWindowProperty"] = function(context) {

	var propertyName = context.params[0];
	var propertyValue = context.params[1];

	Object.defineProperty(window, propertyName, {
		get: function() {
			if (typeof(propertyValue) === "undefined") {
				return;
			}
			return propertyValue;
		},
		set: function() {}
	});
};

@ameshkov commented on Wed Feb 08 2017

@atropnikov @seanl-adg @Alex-302 Guys, I need your feedback on this proposition.


@Alex-302 commented on Wed Feb 08 2017

Are scriptlets will be hardcoded for AMO version as before?

Replacing JS file content with a scriptlet

is it possible to replace only specific function in the file(for example in some library)?


@ameshkov commented on Wed Feb 08 2017

Are scriptlets will be hardcoded for AMO version as before?

The difference between AMO, Opera, and other versions will be that scriptlets configuration file won't be updated automatically.

is it possible to replace only specific function in the file(for example in some library)?

No, that's possible with $replace rules only.


@ameshkov commented on Wed Feb 08 2017

I've found the first problem with the proposed syntax; it is not backward compatible with the old JS rules, so it will break previous versions of Adguard.

We should "mark" them differently, use #&# mark instead of #%#. I've updated the first message.


@ameshkov commented on Wed Apr 26 2017

What we also need:

  1. Add support for the base64-encoded resources (transparent.png and such)
  2. Scriptlet should have more props, content type for instance.
  3. We should also handle Content-MD5 header properly

@ameshkov commented on Thu Jul 27 2017

@seanl-adg

  1. We should have unit-tests for scriptlets.
  2. Consider having scriptlets dependencies. Do we actually need it?
  3. I suppose that base64-encoded resource redirects should be a separate structure, otherwise it may cause confusion.

ameshkov avatar Feb 14 '18 17:02 ameshkov