-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathprevent-requestAnimationFrame.js
143 lines (132 loc) · 4.23 KB
/
prevent-requestAnimationFrame.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import {
hit,
noopFunc,
parseMatchArg,
isValidStrPattern,
isValidCallback,
logMessage,
escapeRegExp,
toRegExp,
} from '../helpers';
/* eslint-disable max-len */
/**
* @scriptlet prevent-requestAnimationFrame
*
* @description
* Prevents a `requestAnimationFrame` call
* if the text of the callback is matching the specified search string which does not start with `!`;
* otherwise mismatched calls should be defused.
*
* Related UBO scriptlet:
* https://github.com/gorhill/uBlock/wiki/Resources-Library#no-requestanimationframe-ifjs-
*
* ### Syntax
*
* ```text
* example.org#%#//scriptlet('prevent-requestAnimationFrame'[, search])
* ```
*
* - `search` — optional, string or regular expression;
* invalid regular expression will be skipped and all callbacks will be matched.
* If starts with `!`, scriptlet will not match the stringified callback but all other will be defused.
* If do not start with `!`, the stringified callback will be matched.
*
* > Call with no argument will log all requestAnimationFrame calls,
* > it may be useful for debugging but it is not allowed for prod versions of filter lists.
*
* ### Examples
*
* 1. Prevents `requestAnimationFrame` calls if the callback matches `/\.test/`
*
* ```adblock
* example.org#%#//scriptlet('prevent-requestAnimationFrame', '/\.test/')
* ```
*
* For instance, the following call will be prevented:
*
* ```javascript
* var times = 0;
* requestAnimationFrame(function change() {
* window.test = 'new value';
* if (times < 2) {
* times += 1;
* requestAnimationFrame(change);
* }
* });
* ```
*
* 1. Prevents `requestAnimationFrame` calls if **does not match** 'check'
*
* ```adblock
* example.org#%#//scriptlet('prevent-requestAnimationFrame', '!check')
* ```
*
* For instance, only the first call will be prevented:
*
* ```javascript
* var timesFirst = 0;
* requestAnimationFrame(function changeFirst() {
* window.check = 'should not be prevented';
* if (timesFirst < 2) {
* timesFirst += 1;
* requestAnimationFrame(changeFirst);
* }
* });
*
* var timesSecond = 0;
* requestAnimationFrame(function changeSecond() {
* window.second = 'should be prevented';
* if (timesSecond < 2) {
* timesSecond += 1;
* requestAnimationFrame(changeSecond);
* }
* });
* ```
*
* @added v1.1.15.
*/
/* eslint-enable max-len */
export function preventRequestAnimationFrame(source, match) {
const nativeRequestAnimationFrame = window.requestAnimationFrame;
// logs requestAnimationFrame to console if no arguments have been specified
const shouldLog = typeof match === 'undefined';
const { isInvertedMatch, matchRegexp } = parseMatchArg(match);
const rafWrapper = (callback, ...args) => {
let shouldPrevent = false;
if (shouldLog) {
hit(source);
logMessage(source, `requestAnimationFrame(${String(callback)})`, true);
} else if (isValidCallback(callback) && isValidStrPattern(match)) {
shouldPrevent = matchRegexp.test(callback.toString()) !== isInvertedMatch;
}
if (shouldPrevent) {
hit(source);
return nativeRequestAnimationFrame(noopFunc);
}
return nativeRequestAnimationFrame.apply(window, [callback, ...args]);
};
window.requestAnimationFrame = rafWrapper;
}
export const preventRequestAnimationFrameNames = [
'prevent-requestAnimationFrame',
// aliases are needed for matching the related scriptlet converted into our syntax
'no-requestAnimationFrame-if.js',
'ubo-no-requestAnimationFrame-if.js',
'norafif.js',
'ubo-norafif.js',
'ubo-no-requestAnimationFrame-if',
'ubo-norafif',
];
// eslint-disable-next-line prefer-destructuring
preventRequestAnimationFrame.primaryName = preventRequestAnimationFrameNames[0];
preventRequestAnimationFrame.injections = [
hit,
noopFunc,
parseMatchArg,
isValidStrPattern,
isValidCallback,
logMessage,
// following helpers should be injected as helpers above use them
escapeRegExp,
toRegExp,
];