@browserless.io/browserless 2.24.1 → 2.24.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -4
- package/README.md +3 -4
- package/build/browsers/browsers.playwright.js +6 -1
- package/build/browsers/index.js +1 -1
- package/build/routes/chrome/http/content.post.body.json +8 -8
- package/build/routes/chrome/http/pdf.post.body.json +8 -8
- package/build/routes/chrome/http/scrape.post.body.json +8 -8
- package/build/routes/chrome/http/screenshot.post.body.json +8 -8
- package/build/routes/chromium/http/content.post.body.json +8 -8
- package/build/routes/chromium/http/pdf.post.body.json +8 -8
- package/build/routes/chromium/http/scrape.post.body.json +8 -8
- package/build/routes/chromium/http/screenshot.post.body.json +8 -8
- package/build/routes/management/http/meta.get.js +3 -1
- package/extensions/ublock/_locales/ar/messages.json +3 -3
- package/extensions/ublock/_locales/bg/messages.json +1 -1
- package/extensions/ublock/_locales/br_FR/messages.json +2 -2
- package/extensions/ublock/_locales/cy/messages.json +11 -11
- package/extensions/ublock/_locales/el/messages.json +2 -2
- package/extensions/ublock/_locales/hu/messages.json +1 -1
- package/extensions/ublock/_locales/id/messages.json +1 -1
- package/extensions/ublock/_locales/lv/messages.json +4 -4
- package/extensions/ublock/_locales/mk/messages.json +130 -130
- package/extensions/ublock/_locales/oc/messages.json +1 -1
- package/extensions/ublock/_locales/pt_BR/messages.json +1 -1
- package/extensions/ublock/_locales/pt_PT/messages.json +2 -2
- package/extensions/ublock/_locales/si/messages.json +100 -100
- package/extensions/ublock/_locales/sr/messages.json +4 -4
- package/extensions/ublock/_locales/vi/messages.json +19 -19
- package/extensions/ublock/_locales/zh_TW/messages.json +28 -28
- package/extensions/ublock/assets/assets.json +33 -29
- package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +2984 -3287
- package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +150 -171
- package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +37 -27
- package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +802 -888
- package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +2355 -2071
- package/extensions/ublock/assets/ublock/badlists.txt +9 -1
- package/extensions/ublock/assets/ublock/badware.min.txt +354 -243
- package/extensions/ublock/assets/ublock/filters.min.txt +5837 -5737
- package/extensions/ublock/assets/ublock/privacy.min.txt +151 -38
- package/extensions/ublock/assets/ublock/quick-fixes.min.txt +83 -127
- package/extensions/ublock/assets/ublock/unbreak.min.txt +66 -50
- package/extensions/ublock/css/codemirror.css +4 -0
- package/extensions/ublock/document-blocked.html +3 -1
- package/extensions/ublock/js/arglist-parser.js +116 -0
- package/extensions/ublock/js/background.js +1 -1
- package/extensions/ublock/js/logger-ui.js +1 -1
- package/extensions/ublock/js/messaging.js +9 -2
- package/extensions/ublock/js/pagestore.js +3 -1
- package/extensions/ublock/js/redirect-engine.js +3 -1
- package/extensions/ublock/{assets/resources/set-attr.js → js/resources/attribute.js} +115 -11
- package/extensions/ublock/js/resources/base.js +38 -0
- package/extensions/ublock/js/resources/cookie.js +419 -0
- package/extensions/ublock/js/resources/href-sanitizer.js +188 -0
- package/extensions/ublock/js/resources/localstorage.js +235 -0
- package/extensions/ublock/js/resources/parse-replace.js +54 -0
- package/extensions/ublock/js/resources/prevent-settimeout.js +236 -0
- package/extensions/ublock/js/resources/proxy-apply.js +109 -0
- package/extensions/ublock/js/resources/replace-argument.js +120 -0
- package/extensions/ublock/{assets → js}/resources/run-at.js +20 -4
- package/extensions/ublock/{assets → js}/resources/safe-self.js +5 -4
- package/extensions/ublock/{assets → js}/resources/scriptlets.js +90 -1589
- package/extensions/ublock/js/resources/set-constant.js +287 -0
- package/extensions/ublock/js/resources/shared.js +44 -0
- package/extensions/ublock/js/resources/spoof-css.js +163 -0
- package/extensions/ublock/js/s14e-serializer.js +2 -1
- package/extensions/ublock/js/scriptlet-filtering-core.js +1 -1
- package/extensions/ublock/js/scriptlet-filtering.js +1 -31
- package/extensions/ublock/js/static-dnr-filtering.js +143 -129
- package/extensions/ublock/js/static-filtering-parser.js +27 -117
- package/extensions/ublock/js/static-net-filtering.js +53 -141
- package/extensions/ublock/js/traffic.js +1 -1
- package/extensions/ublock/js/urlskip.js +166 -0
- package/extensions/ublock/js/vapi-background-ext.js +38 -14
- package/extensions/ublock/manifest.json +1 -1
- package/package.json +12 -12
- package/src/browsers/browsers.playwright.ts +8 -1
- package/src/browsers/index.ts +1 -1
- package/src/routes/management/http/meta.get.ts +6 -1
- package/src/routes/management/http/static.get.ts +1 -1
- package/static/docs/swagger.json +10 -10
- package/static/docs/swagger.min.json +9 -9
- package/static/function/client.js +66 -186
- package/static/function/index.html +66 -186
|
@@ -90,6 +90,39 @@ const keyFromSelector = selector => {
|
|
|
90
90
|
|
|
91
91
|
/******************************************************************************/
|
|
92
92
|
|
|
93
|
+
function addGenericCosmeticFilter(context, selector, isException) {
|
|
94
|
+
if ( selector === undefined ) { return; }
|
|
95
|
+
if ( selector.length <= 1 ) { return; }
|
|
96
|
+
if ( isException ) {
|
|
97
|
+
if ( context.genericCosmeticExceptions === undefined ) {
|
|
98
|
+
context.genericCosmeticExceptions = new Set();
|
|
99
|
+
}
|
|
100
|
+
context.genericCosmeticExceptions.add(selector);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if ( selector.charCodeAt(0) === 0x7B /* '{' */ ) { return; }
|
|
104
|
+
const key = keyFromSelector(selector);
|
|
105
|
+
if ( key === undefined ) {
|
|
106
|
+
if ( context.genericHighCosmeticFilters === undefined ) {
|
|
107
|
+
context.genericHighCosmeticFilters = new Set();
|
|
108
|
+
}
|
|
109
|
+
context.genericHighCosmeticFilters.add(selector);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const type = key.charCodeAt(0);
|
|
113
|
+
const hash = hashFromStr(type, key.slice(1));
|
|
114
|
+
if ( context.genericCosmeticFilters === undefined ) {
|
|
115
|
+
context.genericCosmeticFilters = new Map();
|
|
116
|
+
}
|
|
117
|
+
let bucket = context.genericCosmeticFilters.get(hash);
|
|
118
|
+
if ( bucket === undefined ) {
|
|
119
|
+
context.genericCosmeticFilters.set(hash, bucket = []);
|
|
120
|
+
}
|
|
121
|
+
bucket.push(selector);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/******************************************************************************/
|
|
125
|
+
|
|
93
126
|
function addExtendedToDNR(context, parser) {
|
|
94
127
|
if ( parser.isExtendedFilter() === false ) { return false; }
|
|
95
128
|
|
|
@@ -195,35 +228,8 @@ function addExtendedToDNR(context, parser) {
|
|
|
195
228
|
|
|
196
229
|
// Generic cosmetic filtering
|
|
197
230
|
if ( parser.hasOptions() === false ) {
|
|
198
|
-
const { compiled } = parser.result;
|
|
199
|
-
|
|
200
|
-
if ( compiled.length <= 1 ) { return; }
|
|
201
|
-
if ( parser.isException() ) {
|
|
202
|
-
if ( context.genericCosmeticExceptions === undefined ) {
|
|
203
|
-
context.genericCosmeticExceptions = new Set();
|
|
204
|
-
}
|
|
205
|
-
context.genericCosmeticExceptions.add(compiled);
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
if ( compiled.charCodeAt(0) === 0x7B /* '{' */ ) { return; }
|
|
209
|
-
const key = keyFromSelector(compiled);
|
|
210
|
-
if ( key === undefined ) {
|
|
211
|
-
if ( context.genericHighCosmeticFilters === undefined ) {
|
|
212
|
-
context.genericHighCosmeticFilters = new Set();
|
|
213
|
-
}
|
|
214
|
-
context.genericHighCosmeticFilters.add(compiled);
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
const type = key.charCodeAt(0);
|
|
218
|
-
const hash = hashFromStr(type, key.slice(1));
|
|
219
|
-
if ( context.genericCosmeticFilters === undefined ) {
|
|
220
|
-
context.genericCosmeticFilters = new Map();
|
|
221
|
-
}
|
|
222
|
-
let bucket = context.genericCosmeticFilters.get(hash);
|
|
223
|
-
if ( bucket === undefined ) {
|
|
224
|
-
context.genericCosmeticFilters.set(hash, bucket = []);
|
|
225
|
-
}
|
|
226
|
-
bucket.push(compiled);
|
|
231
|
+
const { compiled, exception } = parser.result;
|
|
232
|
+
addGenericCosmeticFilter(context, compiled, exception);
|
|
227
233
|
return;
|
|
228
234
|
}
|
|
229
235
|
|
|
@@ -234,26 +240,22 @@ function addExtendedToDNR(context, parser) {
|
|
|
234
240
|
if ( context.specificCosmeticFilters === undefined ) {
|
|
235
241
|
context.specificCosmeticFilters = new Map();
|
|
236
242
|
}
|
|
243
|
+
const { compiled, exception, raw } = parser.result;
|
|
244
|
+
if ( compiled === undefined ) {
|
|
245
|
+
context.specificCosmeticFilters.set(`Invalid filter: ...##${raw}`, {
|
|
246
|
+
rejected: true
|
|
247
|
+
});
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
let details = context.specificCosmeticFilters.get(compiled);
|
|
237
251
|
for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) {
|
|
238
252
|
if ( bad ) { continue; }
|
|
253
|
+
if ( not && exception ) { continue; }
|
|
239
254
|
if ( isRegex(hn) ) { continue; }
|
|
240
|
-
let { compiled, exception, raw } = parser.result;
|
|
241
|
-
if ( exception ) { continue; }
|
|
242
|
-
let rejected;
|
|
243
|
-
if ( compiled === undefined ) {
|
|
244
|
-
rejected = `Invalid filter: ${hn}##${raw}`;
|
|
245
|
-
}
|
|
246
|
-
if ( rejected ) {
|
|
247
|
-
compiled = rejected;
|
|
248
|
-
}
|
|
249
|
-
let details = context.specificCosmeticFilters.get(compiled);
|
|
250
255
|
if ( details === undefined ) {
|
|
251
|
-
details = {};
|
|
252
|
-
if ( rejected ) { details.rejected = true; }
|
|
253
|
-
context.specificCosmeticFilters.set(compiled, details);
|
|
256
|
+
context.specificCosmeticFilters.set(compiled, details = {});
|
|
254
257
|
}
|
|
255
|
-
if (
|
|
256
|
-
if ( not ) {
|
|
258
|
+
if ( exception ) {
|
|
257
259
|
if ( details.excludeMatches === undefined ) {
|
|
258
260
|
details.excludeMatches = [];
|
|
259
261
|
}
|
|
@@ -270,6 +272,13 @@ function addExtendedToDNR(context, parser) {
|
|
|
270
272
|
}
|
|
271
273
|
details.matches.push(hn);
|
|
272
274
|
}
|
|
275
|
+
if ( details === undefined ) { return; }
|
|
276
|
+
if ( exception ) { return; }
|
|
277
|
+
if ( compiled.startsWith('{') ) { return; }
|
|
278
|
+
if ( details.matches === undefined || details.matches.includes('*') ) {
|
|
279
|
+
addGenericCosmeticFilter(context, compiled, false);
|
|
280
|
+
details.matches = undefined;
|
|
281
|
+
}
|
|
273
282
|
}
|
|
274
283
|
|
|
275
284
|
/******************************************************************************/
|
|
@@ -284,6 +293,7 @@ function addToDNR(context, list) {
|
|
|
284
293
|
toDNR: true,
|
|
285
294
|
nativeCssHas: env.includes('native_css_has'),
|
|
286
295
|
badTypes: [ sfp.NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE ],
|
|
296
|
+
trustedSource: list.trustedSource || undefined,
|
|
287
297
|
});
|
|
288
298
|
const compiler = staticNetFilteringEngine.createCompiler();
|
|
289
299
|
|
|
@@ -344,105 +354,109 @@ function addToDNR(context, list) {
|
|
|
344
354
|
|
|
345
355
|
/******************************************************************************/
|
|
346
356
|
|
|
347
|
-
|
|
348
|
-
|
|
357
|
+
// Merge rules where possible by merging arrays of a specific property.
|
|
358
|
+
//
|
|
359
|
+
// https://github.com/uBlockOrigin/uBOL-home/issues/10#issuecomment-1304822579
|
|
360
|
+
// Do not merge rules which have errors.
|
|
349
361
|
|
|
350
|
-
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
for ( const rule of ruleset ) {
|
|
355
|
-
rulesetMap.set(ruleId++, rule);
|
|
362
|
+
function mergeRules(rulesetMap, mergeTarget) {
|
|
363
|
+
const sorter = (_, v) => {
|
|
364
|
+
if ( Array.isArray(v) ) {
|
|
365
|
+
return typeof v[0] === 'string' ? v.sort() : v;
|
|
356
366
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
// Do not merge rules which have errors.
|
|
362
|
-
const mergeRules = (rulesetMap, mergeTarget) => {
|
|
363
|
-
const mergeMap = new Map();
|
|
364
|
-
const sorter = (_, v) => {
|
|
365
|
-
if ( Array.isArray(v) ) {
|
|
366
|
-
return typeof v[0] === 'string' ? v.sort() : v;
|
|
367
|
+
if ( v instanceof Object ) {
|
|
368
|
+
const sorted = {};
|
|
369
|
+
for ( const kk of Object.keys(v).sort() ) {
|
|
370
|
+
sorted[kk] = v[kk];
|
|
367
371
|
}
|
|
372
|
+
return sorted;
|
|
373
|
+
}
|
|
374
|
+
return v;
|
|
375
|
+
};
|
|
376
|
+
const ruleHasher = (rule, target) => {
|
|
377
|
+
return JSON.stringify(rule, (k, v) => {
|
|
378
|
+
if ( k.startsWith('_') ) { return; }
|
|
379
|
+
if ( k === target ) { return; }
|
|
380
|
+
return sorter(k, v);
|
|
381
|
+
});
|
|
382
|
+
};
|
|
383
|
+
const extractTargetValue = (obj, target) => {
|
|
384
|
+
for ( const [ k, v ] of Object.entries(obj) ) {
|
|
385
|
+
if ( Array.isArray(v) && k === target ) { return v; }
|
|
368
386
|
if ( v instanceof Object ) {
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
sorted[kk] = v[kk];
|
|
372
|
-
}
|
|
373
|
-
return sorted;
|
|
387
|
+
const r = extractTargetValue(v, target);
|
|
388
|
+
if ( r !== undefined ) { return r; }
|
|
374
389
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
};
|
|
384
|
-
const extractTargetValue = (obj, target) => {
|
|
385
|
-
for ( const [ k, v ] of Object.entries(obj) ) {
|
|
386
|
-
if ( Array.isArray(v) && k === target ) { return v; }
|
|
387
|
-
if ( v instanceof Object ) {
|
|
388
|
-
const r = extractTargetValue(v, target);
|
|
389
|
-
if ( r !== undefined ) { return r; }
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
const extractTargetOwner = (obj, target) => {
|
|
394
|
-
for ( const [ k, v ] of Object.entries(obj) ) {
|
|
395
|
-
if ( Array.isArray(v) && k === target ) { return obj; }
|
|
396
|
-
if ( v instanceof Object ) {
|
|
397
|
-
const r = extractTargetOwner(v, target);
|
|
398
|
-
if ( r !== undefined ) { return r; }
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
for ( const [ id, rule ] of rulesetMap ) {
|
|
403
|
-
if ( rule._error !== undefined ) { continue; }
|
|
404
|
-
const hash = ruleHasher(rule, mergeTarget);
|
|
405
|
-
if ( mergeMap.has(hash) === false ) {
|
|
406
|
-
mergeMap.set(hash, []);
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
const extractTargetOwner = (obj, target) => {
|
|
393
|
+
for ( const [ k, v ] of Object.entries(obj) ) {
|
|
394
|
+
if ( Array.isArray(v) && k === target ) { return obj; }
|
|
395
|
+
if ( v instanceof Object ) {
|
|
396
|
+
const r = extractTargetOwner(v, target);
|
|
397
|
+
if ( r !== undefined ) { return r; }
|
|
407
398
|
}
|
|
408
|
-
mergeMap.get(hash).push(id);
|
|
409
399
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
400
|
+
};
|
|
401
|
+
const mergeMap = new Map();
|
|
402
|
+
for ( const [ id, rule ] of rulesetMap ) {
|
|
403
|
+
if ( rule._error !== undefined ) { continue; }
|
|
404
|
+
const hash = ruleHasher(rule, mergeTarget);
|
|
405
|
+
if ( mergeMap.has(hash) === false ) {
|
|
406
|
+
mergeMap.set(hash, []);
|
|
407
|
+
}
|
|
408
|
+
mergeMap.get(hash).push(id);
|
|
409
|
+
}
|
|
410
|
+
for ( const ids of mergeMap.values() ) {
|
|
411
|
+
if ( ids.length === 1 ) { continue; }
|
|
412
|
+
const leftHand = rulesetMap.get(ids[0]);
|
|
413
|
+
const leftHandSet = new Set(
|
|
414
|
+
extractTargetValue(leftHand, mergeTarget) || []
|
|
415
|
+
);
|
|
416
|
+
for ( let i = 1; i < ids.length; i++ ) {
|
|
417
|
+
const rightHandId = ids[i];
|
|
418
|
+
const rightHand = rulesetMap.get(rightHandId);
|
|
419
|
+
const rightHandArray = extractTargetValue(rightHand, mergeTarget);
|
|
420
|
+
if ( rightHandArray !== undefined ) {
|
|
421
|
+
if ( leftHandSet.size !== 0 ) {
|
|
422
|
+
for ( const item of rightHandArray ) {
|
|
423
|
+
leftHandSet.add(item);
|
|
425
424
|
}
|
|
426
|
-
} else {
|
|
427
|
-
leftHandSet.clear();
|
|
428
425
|
}
|
|
429
|
-
|
|
426
|
+
} else {
|
|
427
|
+
leftHandSet.clear();
|
|
430
428
|
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
429
|
+
rulesetMap.delete(rightHandId);
|
|
430
|
+
}
|
|
431
|
+
const leftHandOwner = extractTargetOwner(leftHand, mergeTarget);
|
|
432
|
+
if ( leftHandSet.size > 1 ) {
|
|
433
|
+
//if ( leftHandOwner === undefined ) { debugger; }
|
|
434
|
+
leftHandOwner[mergeTarget] = Array.from(leftHandSet).sort();
|
|
435
|
+
} else if ( leftHandSet.size === 0 ) {
|
|
436
|
+
if ( leftHandOwner !== undefined ) {
|
|
437
|
+
leftHandOwner[mergeTarget] = undefined;
|
|
439
438
|
}
|
|
440
439
|
}
|
|
441
|
-
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/******************************************************************************/
|
|
444
|
+
|
|
445
|
+
function finalizeRuleset(context, network) {
|
|
446
|
+
const ruleset = network.ruleset;
|
|
447
|
+
|
|
448
|
+
// Assign rule ids
|
|
449
|
+
const rulesetMap = new Map();
|
|
450
|
+
{
|
|
451
|
+
let ruleId = 1;
|
|
452
|
+
for ( const rule of ruleset ) {
|
|
453
|
+
rulesetMap.set(ruleId++, rule);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
442
456
|
mergeRules(rulesetMap, 'resourceTypes');
|
|
457
|
+
mergeRules(rulesetMap, 'removeParams');
|
|
443
458
|
mergeRules(rulesetMap, 'initiatorDomains');
|
|
444
459
|
mergeRules(rulesetMap, 'requestDomains');
|
|
445
|
-
mergeRules(rulesetMap, 'removeParams');
|
|
446
460
|
mergeRules(rulesetMap, 'responseHeaders');
|
|
447
461
|
|
|
448
462
|
// Patch id
|
|
@@ -498,4 +512,4 @@ async function dnrRulesetFromRawLists(lists, options = {}) {
|
|
|
498
512
|
|
|
499
513
|
/******************************************************************************/
|
|
500
514
|
|
|
501
|
-
export { dnrRulesetFromRawLists };
|
|
515
|
+
export { dnrRulesetFromRawLists, mergeRules };
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
/******************************************************************************/
|
|
23
23
|
|
|
24
24
|
import * as cssTree from '../lib/csstree/css-tree.js';
|
|
25
|
+
import { ArglistParser } from './arglist-parser.js';
|
|
25
26
|
import Regex from '../lib/regexanalyzer/regex.js';
|
|
26
27
|
|
|
27
28
|
/*******************************************************************************
|
|
@@ -606,102 +607,6 @@ const exCharCodeAt = (s, i) => {
|
|
|
606
607
|
|
|
607
608
|
/******************************************************************************/
|
|
608
609
|
|
|
609
|
-
class ArgListParser {
|
|
610
|
-
constructor(separatorChar = ',', mustQuote = false) {
|
|
611
|
-
this.separatorChar = this.actualSeparatorChar = separatorChar;
|
|
612
|
-
this.separatorCode = this.actualSeparatorCode = separatorChar.charCodeAt(0);
|
|
613
|
-
this.mustQuote = mustQuote;
|
|
614
|
-
this.quoteBeg = 0; this.quoteEnd = 0;
|
|
615
|
-
this.argBeg = 0; this.argEnd = 0;
|
|
616
|
-
this.separatorBeg = 0; this.separatorEnd = 0;
|
|
617
|
-
this.transform = false;
|
|
618
|
-
this.failed = false;
|
|
619
|
-
this.reWhitespaceStart = /^\s+/;
|
|
620
|
-
this.reWhitespaceEnd = /\s+$/;
|
|
621
|
-
this.reOddTrailingEscape = /(?:^|[^\\])(?:\\\\)*\\$/;
|
|
622
|
-
this.reTrailingEscapeChars = /\\+$/;
|
|
623
|
-
}
|
|
624
|
-
nextArg(pattern, beg = 0) {
|
|
625
|
-
const len = pattern.length;
|
|
626
|
-
this.quoteBeg = beg + this.leftWhitespaceCount(pattern.slice(beg));
|
|
627
|
-
this.failed = false;
|
|
628
|
-
const qc = pattern.charCodeAt(this.quoteBeg);
|
|
629
|
-
if ( qc === 0x22 /* " */ || qc === 0x27 /* ' */ || qc === 0x60 /* ` */ ) {
|
|
630
|
-
this.indexOfNextArgSeparator(pattern, qc);
|
|
631
|
-
if ( this.argEnd !== len ) {
|
|
632
|
-
this.quoteEnd = this.argEnd + 1;
|
|
633
|
-
this.separatorBeg = this.separatorEnd = this.quoteEnd;
|
|
634
|
-
this.separatorEnd += this.leftWhitespaceCount(pattern.slice(this.quoteEnd));
|
|
635
|
-
if ( this.separatorEnd === len ) { return this; }
|
|
636
|
-
if ( pattern.charCodeAt(this.separatorEnd) === this.separatorCode ) {
|
|
637
|
-
this.separatorEnd += 1;
|
|
638
|
-
return this;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
this.indexOfNextArgSeparator(pattern, this.separatorCode);
|
|
643
|
-
this.separatorBeg = this.separatorEnd = this.argEnd;
|
|
644
|
-
if ( this.separatorBeg < len ) {
|
|
645
|
-
this.separatorEnd += 1;
|
|
646
|
-
}
|
|
647
|
-
this.argEnd -= this.rightWhitespaceCount(pattern.slice(0, this.separatorBeg));
|
|
648
|
-
this.quoteEnd = this.argEnd;
|
|
649
|
-
if ( this.mustQuote ) {
|
|
650
|
-
this.failed = true;
|
|
651
|
-
}
|
|
652
|
-
return this;
|
|
653
|
-
}
|
|
654
|
-
normalizeArg(s, char = '') {
|
|
655
|
-
if ( char === '' ) { char = this.actualSeparatorChar; }
|
|
656
|
-
let out = '';
|
|
657
|
-
let pos = 0;
|
|
658
|
-
while ( (pos = s.lastIndexOf(char)) !== -1 ) {
|
|
659
|
-
out = s.slice(pos) + out;
|
|
660
|
-
s = s.slice(0, pos);
|
|
661
|
-
const match = this.reTrailingEscapeChars.exec(s);
|
|
662
|
-
if ( match === null ) { continue; }
|
|
663
|
-
const tail = (match[0].length & 1) !== 0
|
|
664
|
-
? match[0].slice(0, -1)
|
|
665
|
-
: match[0];
|
|
666
|
-
out = tail + out;
|
|
667
|
-
s = s.slice(0, -match[0].length);
|
|
668
|
-
}
|
|
669
|
-
if ( out === '' ) { return s; }
|
|
670
|
-
return s + out;
|
|
671
|
-
}
|
|
672
|
-
leftWhitespaceCount(s) {
|
|
673
|
-
const match = this.reWhitespaceStart.exec(s);
|
|
674
|
-
return match === null ? 0 : match[0].length;
|
|
675
|
-
}
|
|
676
|
-
rightWhitespaceCount(s) {
|
|
677
|
-
const match = this.reWhitespaceEnd.exec(s);
|
|
678
|
-
return match === null ? 0 : match[0].length;
|
|
679
|
-
}
|
|
680
|
-
indexOfNextArgSeparator(pattern, separatorCode) {
|
|
681
|
-
this.argBeg = this.argEnd = separatorCode !== this.separatorCode
|
|
682
|
-
? this.quoteBeg + 1
|
|
683
|
-
: this.quoteBeg;
|
|
684
|
-
this.transform = false;
|
|
685
|
-
if ( separatorCode !== this.actualSeparatorCode ) {
|
|
686
|
-
this.actualSeparatorCode = separatorCode;
|
|
687
|
-
this.actualSeparatorChar = String.fromCharCode(separatorCode);
|
|
688
|
-
}
|
|
689
|
-
while ( this.argEnd < pattern.length ) {
|
|
690
|
-
const pos = pattern.indexOf(this.actualSeparatorChar, this.argEnd);
|
|
691
|
-
if ( pos === -1 ) {
|
|
692
|
-
return (this.argEnd = pattern.length);
|
|
693
|
-
}
|
|
694
|
-
if ( this.reOddTrailingEscape.test(pattern.slice(0, pos)) === false ) {
|
|
695
|
-
return (this.argEnd = pos);
|
|
696
|
-
}
|
|
697
|
-
this.transform = true;
|
|
698
|
-
this.argEnd = pos + 1;
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
/******************************************************************************/
|
|
704
|
-
|
|
705
610
|
class AstWalker {
|
|
706
611
|
constructor(parser, from = 0) {
|
|
707
612
|
this.parser = parser;
|
|
@@ -904,8 +809,8 @@ export class AstFilterParser {
|
|
|
904
809
|
this.reBadPP = /(?:^|[;,])\s*report-to\b/i;
|
|
905
810
|
this.reNetOption = /^(~?)([134a-z_-]+)(=?)/;
|
|
906
811
|
this.reNoopOption = /^_+$/;
|
|
907
|
-
this.netOptionValueParser = new
|
|
908
|
-
this.scriptletArgListParser = new
|
|
812
|
+
this.netOptionValueParser = new ArglistParser(',');
|
|
813
|
+
this.scriptletArgListParser = new ArglistParser(',');
|
|
909
814
|
}
|
|
910
815
|
|
|
911
816
|
finish() {
|
|
@@ -1572,18 +1477,15 @@ export class AstFilterParser {
|
|
|
1572
1477
|
if ( j === -1 ) { return end; }
|
|
1573
1478
|
if ( (j+1) === end ) { return end; }
|
|
1574
1479
|
for (;;) {
|
|
1575
|
-
const before = s.
|
|
1576
|
-
if (
|
|
1577
|
-
const after = s.
|
|
1578
|
-
if (
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
before !== 0x5C /* \ */
|
|
1583
|
-
) {
|
|
1584
|
-
return j;
|
|
1480
|
+
const before = s.charAt(j-1);
|
|
1481
|
+
if ( before === '$' ) { return -1; }
|
|
1482
|
+
const after = s.charAt(j+1);
|
|
1483
|
+
if ( ')/|'.includes(after) === false ) {
|
|
1484
|
+
if ( before === '' || '"\'\\`'.includes(before) === false ) {
|
|
1485
|
+
return j;
|
|
1486
|
+
}
|
|
1585
1487
|
}
|
|
1586
|
-
if ( j
|
|
1488
|
+
if ( j === start ) { break; }
|
|
1587
1489
|
j = s.lastIndexOf('$', j-1);
|
|
1588
1490
|
if ( j === -1 ) { break; }
|
|
1589
1491
|
}
|
|
@@ -3100,7 +3002,7 @@ export function parseHeaderValue(arg) {
|
|
|
3100
3002
|
|
|
3101
3003
|
export function parseReplaceValue(s) {
|
|
3102
3004
|
if ( s.charCodeAt(0) !== 0x2F /* / */ ) { return; }
|
|
3103
|
-
const parser = new
|
|
3005
|
+
const parser = new ArglistParser('/');
|
|
3104
3006
|
parser.nextArg(s, 1);
|
|
3105
3007
|
let pattern = s.slice(parser.argBeg, parser.argEnd);
|
|
3106
3008
|
if ( parser.transform ) {
|
|
@@ -3345,10 +3247,13 @@ class ExtSelectorCompiler {
|
|
|
3345
3247
|
// We have an Adguard/ABP cosmetic filter if and only if the
|
|
3346
3248
|
// character is `$`, `%` or `?`, otherwise it's not a cosmetic
|
|
3347
3249
|
// filter.
|
|
3348
|
-
// Adguard
|
|
3349
|
-
if (
|
|
3350
|
-
|
|
3351
|
-
if (
|
|
3250
|
+
// Adguard/EasyList style injection: translate to uBO's format.
|
|
3251
|
+
if ( this.isStyleInjectionFilter(raw) ) {
|
|
3252
|
+
const translated = this.translateStyleInjectionFilter(raw);
|
|
3253
|
+
if ( translated === undefined ) { return false; }
|
|
3254
|
+
raw = translated;
|
|
3255
|
+
} else if ( compileOptions.adgStyleSyntax === true ) {
|
|
3256
|
+
return false;
|
|
3352
3257
|
}
|
|
3353
3258
|
|
|
3354
3259
|
// Normalize AdGuard's attribute-based procedural operators.
|
|
@@ -3884,9 +3789,14 @@ class ExtSelectorCompiler {
|
|
|
3884
3789
|
return true;
|
|
3885
3790
|
}
|
|
3886
3791
|
|
|
3887
|
-
|
|
3888
|
-
const
|
|
3889
|
-
|
|
3792
|
+
isStyleInjectionFilter(selector) {
|
|
3793
|
+
const len = selector.length;
|
|
3794
|
+
return len !== 0 && selector.charCodeAt(len-1) === 0x7D /* } */;
|
|
3795
|
+
}
|
|
3796
|
+
|
|
3797
|
+
translateStyleInjectionFilter(raw) {
|
|
3798
|
+
const matches = /^(.+)\s*\{([^}]+)\}$/.exec(raw);
|
|
3799
|
+
if ( matches === null ) { return; }
|
|
3890
3800
|
const selector = matches[1].trim();
|
|
3891
3801
|
const style = matches[2].trim();
|
|
3892
3802
|
// Special style directive `remove: true` is converted into a
|