@@ -191,7 +191,7 @@ const FilterContainer = function() {
191
191
this.rePlainSelectorEscaped = /^[#.](?:\\[0-9A-Fa-f]+ |\\.|\w|-)+/;
192
192
this.rePlainSelectorEx = /^[^#.\[(]+([#.][\w-]+)|([#.][\w-]+)$/;
193
193
this.reEscapeSequence = /\\([0-9A-Fa-f]+ |.)/g;
194
-
this.reSimpleHighGeneric1 = /^[a-z]*\[[^[]+]$/;
194
+
this.reSimpleHighGeneric = /^(?:[a-z]*\[[^\]]+\]|\S+)$/;
195
195
this.reHighMedium = /^\[href\^="https?:\/\/([^"]{8})[^"]*"\]$/;
196
196
197
197
this.selectorCache = new Map();
@@ -274,8 +274,8 @@ FilterContainer.prototype.reset = function() {
274
274
this.selectorCacheTimer = null;
275
275
}
276
276
277
-
// generic filters
278
-
this.hasGenericHide = false;
277
+
// whether there is at least one surveyor-based filter
278
+
this.needDOMSurveyor = false;
279
279
280
280
// hostname, entity-based filters
281
281
this.specificFilters.clear();
@@ -301,13 +301,11 @@ FilterContainer.prototype.freeze = function() {
301
301
this.duplicateBuster.clear();
302
302
this.specificFilters.collectGarbage();
303
303
304
-
this.hasGenericHide =
304
+
this.needDOMSurveyor =
305
305
this.lowlyGeneric.id.simple.size !== 0 ||
306
306
this.lowlyGeneric.id.complex.size !== 0 ||
307
307
this.lowlyGeneric.cl.simple.size !== 0 ||
308
-
this.lowlyGeneric.cl.complex.size !== 0 ||
309
-
this.highlyGeneric.simple.dict.size !== 0 ||
310
-
this.highlyGeneric.complex.dict.size !== 0;
308
+
this.lowlyGeneric.cl.complex.size !== 0;
311
309
312
310
this.highlyGeneric.simple.str = Array.from(this.highlyGeneric.simple.dict).join(',\n');
313
311
this.highlyGeneric.simple.mru.reset();
@@ -333,8 +331,8 @@ FilterContainer.prototype.keyFromSelector = function(selector) {
333
331
matches = this.rePlainSelectorEscaped.exec(selector);
334
332
if ( matches === null ) { return; }
335
333
key = '';
336
-
let escaped = matches[0],
337
-
beg = 0;
334
+
const escaped = matches[0];
335
+
let beg = 0;
338
336
this.reEscapeSequence.lastIndex = 0;
339
337
for (;;) {
340
338
matches = this.reEscapeSequence.exec(escaped);
@@ -402,22 +400,19 @@ FilterContainer.prototype.compileGenericHideSelector = function(
402
400
const type = selector.charCodeAt(0);
403
401
let key;
404
402
403
+
// Simple selector-based CSS rule: no need to test for whether the
404
+
// selector is valid, the regex took care of this. Most generic selector
405
+
// falls into that category:
406
+
// - ###ad-bigbox
407
+
// - ##.ads-bigbox
405
408
if ( type === 0x23 /* '#' */ ) {
406
409
key = this.keyFromSelector(selector);
407
-
// Simple selector-based CSS rule: no need to test for whether the
408
-
// selector is valid, the regex took care of this. Most generic
409
-
// selector falls into that category.
410
-
// - ###ad-bigbox
411
410
if ( key === selector ) {
412
411
writer.push([ 0, key.slice(1) ]);
413
412
return;
414
413
}
415
414
} else if ( type === 0x2E /* '.' */ ) {
416
415
key = this.keyFromSelector(selector);
417
-
// Simple selector-based CSS rule: no need to test for whether the
418
-
// selector is valid, the regex took care of this. Most generic
419
-
// selector falls into that category.
420
-
// - ##.ads-bigbox
421
416
if ( key === selector ) {
422
417
writer.push([ 2, key.slice(1) ]);
423
418
return;
@@ -484,12 +479,7 @@ FilterContainer.prototype.compileGenericHideSelector = function(
484
479
// For efficiency purpose, we will distinguish between simple and complex
485
480
// selectors.
486
481
487
-
if ( this.reSimpleHighGeneric1.test(selector) ) {
488
-
writer.push([ 4 /* simple */, selector ]);
489
-
return;
490
-
}
491
-
492
-
if ( selector.indexOf(' ') === -1 ) {
482
+
if ( this.reSimpleHighGeneric.test(selector) ) {
493
483
writer.push([ 4 /* simple */, selector ]);
494
484
} else {
495
485
writer.push([ 5 /* complex */, selector ]);
@@ -551,10 +541,13 @@ FilterContainer.prototype.compileSpecificSelector = function(
551
541
552
542
let kind = 0;
553
543
if ( unhide === 1 ) {
554
-
kind |= 0b01; // Exception
544
+
kind |= 0b001; // Exception
555
545
}
556
546
if ( compiled.charCodeAt(0) === 0x7B /* '{' */ ) {
557
-
kind |= 0b10; // Procedural
547
+
kind |= 0b010; // Procedural
548
+
}
549
+
if ( hostname === '*' ) {
550
+
kind |= 0b100; // Applies everywhere
558
551
}
559
552
560
553
writer.push([ 8, hostname, kind, compiled ]);
@@ -637,8 +630,21 @@ FilterContainer.prototype.fromCompiledContent = function(reader, options) {
637
630
638
631
// hash, example.com, .promoted-tweet
639
632
// hash, example.*, .promoted-tweet
633
+
//
634
+
// https://github.com/uBlockOrigin/uBlock-issues/issues/803
635
+
// Handle specific filters meant to apply everywhere, i.e. selectors
636
+
// not to be injected conditionally through the DOM surveyor.
637
+
// hash, *, .promoted-tweet
640
638
case 8:
641
-
this.specificFilters.store(args[1], args[2], args[3]);
639
+
if ( args[2] === 0b100 ) {
640
+
if ( this.reSimpleHighGeneric.test(args[3]) )
641
+
this.highlyGeneric.simple.dict.add(args[3]);
642
+
else {
643
+
this.highlyGeneric.complex.dict.add(args[3]);
644
+
}
645
+
break;
646
+
}
647
+
this.specificFilters.store(args[1], args[2] & 0b011, args[3]);
642
648
break;
643
649
644
650
default:
@@ -666,11 +672,21 @@ FilterContainer.prototype.skipGenericCompiledContent = function(reader) {
666
672
667
673
switch ( args[0] ) {
668
674
669
-
// hash, example.com, .promoted-tweet
670
-
// hash, example.*, .promoted-tweet
675
+
// https://github.com/uBlockOrigin/uBlock-issues/issues/803
676
+
// Handle specific filters meant to apply everywhere, i.e. selectors
677
+
// not to be injected conditionally through the DOM surveyor.
678
+
// hash, *, .promoted-tweet
671
679
case 8:
672
680
this.duplicateBuster.add(fingerprint);
673
-
this.specificFilters.store(args[1], args[2], args[3]);
681
+
if ( args[2] === 0b100 ) {
682
+
if ( this.reSimpleHighGeneric.test(args[3]) )
683
+
this.highlyGeneric.simple.dict.add(args[3]);
684
+
else {
685
+
this.highlyGeneric.complex.dict.add(args[3]);
686
+
}
687
+
break;
688
+
}
689
+
this.specificFilters.store(args[1], args[2] & 0b011, args[3]);
674
690
break;
675
691
676
692
default:
@@ -699,7 +715,6 @@ FilterContainer.prototype.toSelfie = function() {
699
715
acceptedCount: this.acceptedCount,
700
716
discardedCount: this.discardedCount,
701
717
specificFilters: this.specificFilters.toSelfie(),
702
-
hasGenericHide: this.hasGenericHide,
703
718
lowlyGenericSID: Array.from(this.lowlyGeneric.id.simple),
704
719
lowlyGenericCID: Array.from(this.lowlyGeneric.id.complex),
705
720
lowlyGenericSCL: Array.from(this.lowlyGeneric.cl.simple),
@@ -715,7 +730,6 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
715
730
this.acceptedCount = selfie.acceptedCount;
716
731
this.discardedCount = selfie.discardedCount;
717
732
this.specificFilters.fromSelfie(selfie.specificFilters);
718
-
this.hasGenericHide = selfie.hasGenericHide;
719
733
this.lowlyGeneric.id.simple = new Set(selfie.lowlyGenericSID);
720
734
this.lowlyGeneric.id.complex = new Map(selfie.lowlyGenericCID);
721
735
this.lowlyGeneric.cl.simple = new Set(selfie.lowlyGenericSCL);
@@ -724,6 +738,11 @@ FilterContainer.prototype.fromSelfie = function(selfie) {
724
738
this.highlyGeneric.simple.str = selfie.highSimpleGenericHideArray.join(',\n');
725
739
this.highlyGeneric.complex.dict = new Set(selfie.highComplexGenericHideArray);
726
740
this.highlyGeneric.complex.str = selfie.highComplexGenericHideArray.join(',\n');
741
+
this.needDOMSurveyor =
742
+
selfie.lowlyGenericSID.length !== 0 ||
743
+
selfie.lowlyGenericCID.length !== 0 ||
744
+
selfie.lowlyGenericSCL.length !== 0 ||
745
+
selfie.lowlyGenericCCL.length !== 0;
727
746
this.frozen = true;
728
747
};
729
748
@@ -986,7 +1005,7 @@ FilterContainer.prototype.retrieveSpecificSelectors = function(
986
1005
highGenericHideComplex: '',
987
1006
injectedHideFilters: '',
988
1007
networkFilters: '',
989
-
noDOMSurveying: this.hasGenericHide === false,
1008
+
noDOMSurveying: this.needDOMSurveyor === false,
990
1009
proceduralFilters: []
991
1010
};
992
1011
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4