Skip to content

Commit

Permalink
Fix issue with isAbortingSuspended in abort-current-inline-script
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamWr committed Oct 18, 2022
1 parent e1489ee commit f0cf3ee
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 5 deletions.
18 changes: 15 additions & 3 deletions src/helpers/get-descriptor-addon.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { randomId } from './random-id';
/**
* Prevent infinite loops when trapping props that could be used by scriptlet's own helpers
* Example: window.RegExp, that is used by matchStackTrace > toRegExp
*
* https://github.com/AdguardTeam/Scriptlets/issues/251
* https://github.com/AdguardTeam/Scriptlets/issues/226
* https://github.com/AdguardTeam/Scriptlets/issues/232
*
Expand All @@ -12,9 +14,19 @@ export function getDescriptorAddon() {
isAbortingSuspended: false,
isolateCallback(cb, ...args) {
this.isAbortingSuspended = true;
const result = cb(...args);
this.isAbortingSuspended = false;
return result;
// try...catch is required in case if there are more than one inline scripts
// which should be aborted
try {
const result = cb(...args);
this.isAbortingSuspended = false;
return result;
} catch {
this.isAbortingSuspended = false;
const rid = randomId();
// It's necessary to throw error
// otherwise scriptt will be not aborted
throw new ReferenceError(rid);
}
},
};
}
25 changes: 23 additions & 2 deletions tests/scriptlets/abort-current-inline-script.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ module(name, { beforeEach, afterEach });

const onError = (assert) => (message) => {
const browserErrorMessage = 'Script error.';
const nodePuppeteerErrorMessageRgx = /Reference error/g;
const nodePuppeteerErrorMessageRgx = /Reference error|ReferenceError/g;
const checkResult = message === browserErrorMessage
|| message.test(nodePuppeteerErrorMessageRgx);
|| nodePuppeteerErrorMessageRgx.test(message);
assert.ok(checkResult);
};

Expand Down Expand Up @@ -246,3 +246,24 @@ test('Protected from infinite loop when prop is used in a helper', (assert) => {

assert.strictEqual(window.hit, undefined, 'hit should NOT fire');
});

test('searches script by regexp - abort few inline scripts', (assert) => {
window.onerror = onError(assert);
window.shouldBeAborted = true;
window.shouldNotBeAborted = false;
const property = 'console.log';
const shouldBeAborted = 'shouldBeAborted';
const shouldNotBeAborted = 'shouldNotBeAborted';
const search = '/test|abcd|1234|qwerty/';
const scriptletArgs = [property, search];
runScriptlet(name, scriptletArgs);
addAndRemoveInlineScript(`window.${property}('test'); window.${shouldBeAborted} = false;`);
addAndRemoveInlineScript(`window.${property}('abcd'); window.${shouldBeAborted} = false;`);
addAndRemoveInlineScript(`window.${property}('1234'); window.${shouldBeAborted} = false;`);
addAndRemoveInlineScript(`window.${property}('should not be aborted'); window.${shouldNotBeAborted} = true;`);
addAndRemoveInlineScript(`window.${property}('qwerty'); window.${shouldBeAborted} = false;`);

assert.strictEqual(window.shouldBeAborted, true);
assert.strictEqual(window.shouldNotBeAborted, true);
assert.strictEqual(window.hit, 'FIRED', 'hit fired');
});
56 changes: 56 additions & 0 deletions wiki/about-scriptlets.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
* [set-local-storage-item](#set-local-storage-item)
* [set-popads-dummy](#set-popads-dummy)
* [set-session-storage-item](#set-session-storage-item)
* [trusted-click-element](#trusted-click-element)
* [xml-prune](#xml-prune)
* * *
### <a id="abort-current-inline-script"></a> ⚡️ abort-current-inline-script
Expand Down Expand Up @@ -1695,6 +1696,61 @@ example.org#%#//scriptlet('set-session-storage-item', 'exit-intent-marketing', '
[Scriptlet source](../src/scriptlets/set-session-storage-item.js)
* * *
### <a id="trusted-click-element"></a> ⚡️ trusted-click-element
Clicks selected elements in a strict sequence, ordered by selectors passed, and waiting for them to render in the DOM first.
Deactivates after all elements have been clicked or by 10s timeout.
**Syntax**
```
example.com#%#//scriptlet('trusted-click-element', selectors[, extraMatch[, delay]])
```
- `selectors` — required, string with query selectors delimited by comma
- `extraMatch` — optional, extra condition to check on a page; allows to match `cookie` and `localStorage`; can be set as `name:key[=value]` where `value` is optional.
Multiple conditions are allowed inside one `extraMatch` but they should be delimited by comma and each of them should match the syntax. Possible `name`s:
- `cookie` - test string or regex against cookies on a page
- `localStorage` - check if localStorage item is present
- 'delay' - optional, time in ms to delay scriptlet execution, defaults to instant execution.
**Examples**
1. Click single element by selector
```
example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]')
```
2. Delay click execution by 500ms
```
example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', '', '500')
```
3. Click multiple elements by selector with a delay
```
example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"], button[name='check"], input[type="submit"][value="akkoord"]', '', '500')
```
4. Match cookies by keys using regex and string
```
example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', 'cookie:userConsentCommunity, cookie:/cmpconsent|cmp/')
```
5. Match by cookie key=value pairs using regex and string
```
example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', 'cookie:userConsentCommunity=true, cookie:/cmpconsent|cmp/=/[a-z]{1,5}/')
```
6. Match by localStorage item 'promo' key
```
example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"]', 'localStorage:promo')
```
7. Click multiple elements with delay and matching by both cookie string and localStorage item
```
example.com#%#//scriptlet('trusted-click-element', 'button[name="agree"], input[type="submit"][value="akkoord"]', 'cookie:cmpconsent, localStorage:promo', '250')
```
[Scriptlet source](../src/scriptlets/trusted-click-element.js)
* * *
### <a id="xml-prune"></a> ⚡️ xml-prune
Removes an element from the specified XML.
Expand Down

0 comments on commit f0cf3ee

Please sign in to comment.