LEFT | RIGHT |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
16 */ | 16 */ |
17 | 17 |
18 "use strict"; | 18 "use strict"; |
19 | 19 |
20 /** | 20 /** |
21 * @fileOverview Matcher class implementing matching addresses against | 21 * @fileOverview Matcher class implementing matching addresses against |
22 * a list of filters. | 22 * a list of filters. |
23 */ | 23 */ |
24 | 24 |
25 const {RegExpFilter, WhitelistFilter} = require("./filterClasses"); | 25 const {RegExpFilter, WhitelistFilter} = require("./filterClasses"); |
26 const {normalizeHostname, domainSuffixes} = require("./url"); | 26 const {normalizeHostname, domainSuffixes} = require("./url"); |
| 27 const {Cache} = require("./caching"); |
27 | 28 |
28 /** | 29 /** |
29 * Regular expression for matching a keyword in a filter. | 30 * Regular expression for matching a keyword in a filter. |
30 * @type {RegExp} | 31 * @type {RegExp} |
31 */ | 32 */ |
32 const keywordRegExp = /[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])/; | 33 const keywordRegExp = /[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])/; |
33 | 34 |
34 /** | 35 /** |
35 * Regular expression for matching all keywords in a filter. | 36 * Regular expression for matching all keywords in a filter. |
36 * @type {RegExp} | 37 * @type {RegExp} |
(...skipping 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
618 | 619 |
619 /** | 620 /** |
620 * Combines a matcher for blocking and exception rules, automatically sorts | 621 * Combines a matcher for blocking and exception rules, automatically sorts |
621 * rules into two {@link Matcher} instances. | 622 * rules into two {@link Matcher} instances. |
622 */ | 623 */ |
623 class CombinedMatcher | 624 class CombinedMatcher |
624 { | 625 { |
625 constructor() | 626 constructor() |
626 { | 627 { |
627 /** | 628 /** |
628 * Maximal number of matching cache entries to be kept | |
629 * @type {number} | |
630 */ | |
631 this.maxCacheEntries = 10000; | |
632 | |
633 /** | |
634 * Matcher for blocking rules. | 629 * Matcher for blocking rules. |
635 * @type {Matcher} | 630 * @type {Matcher} |
636 * @private | 631 * @private |
637 */ | 632 */ |
638 this._blacklist = new Matcher(); | 633 this._blacklist = new Matcher(); |
639 | 634 |
640 /** | 635 /** |
641 * Matcher for exception rules. | 636 * Matcher for exception rules. |
642 * @type {Matcher} | 637 * @type {Matcher} |
643 * @private | 638 * @private |
644 */ | 639 */ |
645 this._whitelist = new Matcher(); | 640 this._whitelist = new Matcher(); |
646 | 641 |
647 /** | 642 /** |
648 * Lookup table of previous {@link Matcher#matchesAny} results | 643 * Lookup table of previous {@link Matcher#matchesAny} results |
649 * @type {Map.<string,Filter>} | 644 * @type {Cache.<string, ?Filter>} |
650 * @private | 645 * @private |
651 */ | 646 */ |
652 this._resultCache = new Map(); | 647 this._resultCache = new Cache(10000); |
653 } | 648 } |
654 | 649 |
655 /** | 650 /** |
656 * @see Matcher#clear | 651 * @see Matcher#clear |
657 */ | 652 */ |
658 clear() | 653 clear() |
659 { | 654 { |
660 this._blacklist.clear(); | 655 this._blacklist.clear(); |
661 this._whitelist.clear(); | 656 this._whitelist.clear(); |
662 this._resultCache.clear(); | 657 this._resultCache.clear(); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 return hits; | 797 return hits; |
803 } | 798 } |
804 | 799 |
805 /** | 800 /** |
806 * @see Matcher#matchesAny | 801 * @see Matcher#matchesAny |
807 * @inheritdoc | 802 * @inheritdoc |
808 */ | 803 */ |
809 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) | 804 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) |
810 { | 805 { |
811 let key = location + " " + typeMask + " " + docDomain + " " + thirdParty + | 806 let key = location + " " + typeMask + " " + docDomain + " " + thirdParty + |
812 " " + sitekey + " " + specificOnly; | 807 " " + sitekey + " " + specificOnly; |
813 | 808 |
814 let result = this._resultCache.get(key); | 809 let result = this._resultCache.get(key); |
815 if (typeof result != "undefined") | 810 if (typeof result != "undefined") |
816 return result; | 811 return result; |
817 | 812 |
818 result = this._matchesAnyInternal(location, typeMask, docDomain, | 813 result = this._matchesAnyInternal(location, typeMask, docDomain, |
819 thirdParty, sitekey, specificOnly); | 814 thirdParty, sitekey, specificOnly); |
820 | |
821 if (this._resultCache.size >= this.maxCacheEntries) | |
822 this._resultCache.clear(); | |
823 | 815 |
824 this._resultCache.set(key, result); | 816 this._resultCache.set(key, result); |
825 | 817 |
826 return result; | 818 return result; |
827 } | 819 } |
828 | 820 |
829 /** | 821 /** |
830 * @typedef {object} MatcherSearchResults | 822 * @typedef {object} MatcherSearchResults |
831 * @property {Array.<BlockingFilter>} [blocking] List of blocking filters | 823 * @property {Array.<BlockingFilter>} [blocking] List of blocking filters |
832 * found. | 824 * found. |
(...skipping 24 matching lines...) Expand all Loading... |
857 thirdParty + " " + sitekey + " " + specificOnly + " " + | 849 thirdParty + " " + sitekey + " " + specificOnly + " " + |
858 filterType; | 850 filterType; |
859 | 851 |
860 let result = this._resultCache.get(key); | 852 let result = this._resultCache.get(key); |
861 if (typeof result != "undefined") | 853 if (typeof result != "undefined") |
862 return result; | 854 return result; |
863 | 855 |
864 result = this._searchInternal(location, typeMask, docDomain, thirdParty, | 856 result = this._searchInternal(location, typeMask, docDomain, thirdParty, |
865 sitekey, specificOnly, filterType); | 857 sitekey, specificOnly, filterType); |
866 | 858 |
867 if (this._resultCache.size >= this.maxCacheEntries) | |
868 this._resultCache.clear(); | |
869 | |
870 this._resultCache.set(key, result); | 859 this._resultCache.set(key, result); |
871 | 860 |
872 return result; | 861 return result; |
873 } | 862 } |
874 | 863 |
875 /** | 864 /** |
876 * Tests whether the URL is whitelisted | 865 * Tests whether the URL is whitelisted |
877 * @see Matcher#matchesAny | 866 * @see Matcher#matchesAny |
878 * @inheritdoc | 867 * @inheritdoc |
879 * @returns {boolean} | 868 * @returns {boolean} |
880 */ | 869 */ |
881 isWhitelisted(location, typeMask, docDomain, thirdParty, sitekey) | 870 isWhitelisted(location, typeMask, docDomain, thirdParty, sitekey) |
882 { | 871 { |
883 return !!this._whitelist.matchesAny(location, typeMask, docDomain, | 872 return !!this._whitelist.matchesAny(location, typeMask, docDomain, |
884 thirdParty, sitekey); | 873 thirdParty, sitekey); |
885 } | 874 } |
886 } | 875 } |
887 | 876 |
888 exports.CombinedMatcher = CombinedMatcher; | 877 exports.CombinedMatcher = CombinedMatcher; |
889 | 878 |
890 /** | 879 /** |
891 * Shared {@link CombinedMatcher} instance that should usually be used. | 880 * Shared {@link CombinedMatcher} instance that should usually be used. |
892 * @type {CombinedMatcher} | 881 * @type {CombinedMatcher} |
893 */ | 882 */ |
894 let defaultMatcher = new CombinedMatcher(); | 883 let defaultMatcher = new CombinedMatcher(); |
895 | 884 |
896 exports.defaultMatcher = defaultMatcher; | 885 exports.defaultMatcher = defaultMatcher; |
LEFT | RIGHT |