| OLD | NEW | 
|    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 Element hiding implementation. |   21  * @fileOverview Element hiding implementation. | 
|   22  */ |   22  */ | 
|   23  |   23  | 
|   24 const {ElemHideException} = require("./filterClasses"); |   24 const {ElemHideException} = require("./filterClasses"); | 
|   25 const {FilterNotifier} = require("./filterNotifier"); |   25 const {FilterNotifier} = require("./filterNotifier"); | 
|   26  |   26  | 
|   27 /** |   27 /** | 
|   28  * Lookup table, active flag, by filter by domain. |   28  * Lookup table, active flag, by filter by domain. | 
|   29  * (Only contains filters that aren't unconditionally matched for all domains.) |   29  * (Only contains filters that aren't unconditionally matched for all domains.) | 
|   30  * @type {Map.<string,Map.<Filter,boolean>>} |   30  * @type {Map.<string,Array.<Set.<Filter>>>} | 
|   31  */ |   31  */ | 
|   32 let filtersByDomain = new Map(); |   32 let filtersByDomain = new Map(); | 
|   33  |   33  | 
|   34 /** |   34 /** | 
|   35  * Lookup table, filter by selector. (Only used for selectors that are |   35  * Lookup table, filter by selector. (Only used for selectors that are | 
|   36  * unconditionally matched for all domains.) |   36  * unconditionally matched for all domains.) | 
|   37  * @type {Map.<string,Filter>} |   37  * @type {Map.<string,Filter>} | 
|   38  */ |   38  */ | 
|   39 let filterBySelector = new Map(); |   39 let filterBySelector = new Map(); | 
|   40  |   40  | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   85   { |   85   { | 
|   86     let domains = filter.domains || defaultDomains; |   86     let domains = filter.domains || defaultDomains; | 
|   87     for (let [domain, isIncluded] of domains) |   87     for (let [domain, isIncluded] of domains) | 
|   88     { |   88     { | 
|   89       // There's no need to note that a filter is generically disabled. |   89       // There's no need to note that a filter is generically disabled. | 
|   90       if (!isIncluded && domain == "") |   90       if (!isIncluded && domain == "") | 
|   91         continue; |   91         continue; | 
|   92  |   92  | 
|   93       let filters = filtersByDomain.get(domain); |   93       let filters = filtersByDomain.get(domain); | 
|   94       if (!filters) |   94       if (!filters) | 
|   95         filtersByDomain.set(domain, filters = new Map()); |   95         filtersByDomain.set(domain, filters = []); | 
|   96       filters.set(filter, isIncluded); |   96  | 
 |   97       let setIndex = +isIncluded; | 
 |   98       if (!filters[setIndex]) | 
 |   99         filters[setIndex] = new Set(); | 
 |  100  | 
 |  101       filters[setIndex].add(filter); | 
|   97     } |  102     } | 
|   98   }, |  103   }, | 
|   99  |  104  | 
|  100   /** |  105   /** | 
|  101    * Add a new element hiding filter |  106    * Add a new element hiding filter | 
|  102    * @param {ElemHideBase} filter |  107    * @param {ElemHideBase} filter | 
|  103    */ |  108    */ | 
|  104   add(filter) |  109   add(filter) | 
|  105   { |  110   { | 
|  106     if (knownFilters.has(filter)) |  111     if (knownFilters.has(filter)) | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  164     { |  169     { | 
|  165       filterBySelector.delete(filter.selector); |  170       filterBySelector.delete(filter.selector); | 
|  166       unconditionalSelectors = null; |  171       unconditionalSelectors = null; | 
|  167     } |  172     } | 
|  168     // Conditionally applied element hiding filters |  173     // Conditionally applied element hiding filters | 
|  169     else |  174     else | 
|  170     { |  175     { | 
|  171       let domains = filter.domains || defaultDomains; |  176       let domains = filter.domains || defaultDomains; | 
|  172       for (let domain of domains.keys()) |  177       for (let domain of domains.keys()) | 
|  173       { |  178       { | 
|  174         let filters = filtersByDomain.get(domain); |  179         let filters = filtersByDomain.get(domain) || []; | 
|  175         if (filters) |  180         for (let i = 0; i < filters.length; i++) | 
|  176           filters.delete(filter); |  181         { | 
 |  182           if (!filters[i]) | 
 |  183             continue; | 
 |  184  | 
 |  185           filters[i].delete(filter); | 
 |  186  | 
 |  187           if (filters[i].size == 0) | 
 |  188             delete filters[i]; | 
 |  189         } | 
|  177       } |  190       } | 
|  178     } |  191     } | 
|  179  |  192  | 
|  180     knownFilters.delete(filter); |  193     knownFilters.delete(filter); | 
|  181     FilterNotifier.emit("elemhideupdate"); |  194     FilterNotifier.emit("elemhideupdate"); | 
|  182   }, |  195   }, | 
|  183  |  196  | 
|  184   /** |  197   /** | 
|  185    * Checks whether an exception rule is registered for a filter on a particular |  198    * Checks whether an exception rule is registered for a filter on a particular | 
|  186    * domain. |  199    * domain. | 
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  245   getSelectorsForDomain(domain, criteria) |  258   getSelectorsForDomain(domain, criteria) | 
|  246   { |  259   { | 
|  247     let selectors = []; |  260     let selectors = []; | 
|  248  |  261  | 
|  249     if (typeof criteria == "undefined") |  262     if (typeof criteria == "undefined") | 
|  250       criteria = ElemHide.ALL_MATCHING; |  263       criteria = ElemHide.ALL_MATCHING; | 
|  251     if (criteria < ElemHide.NO_UNCONDITIONAL) |  264     if (criteria < ElemHide.NO_UNCONDITIONAL) | 
|  252       selectors = this.getUnconditionalSelectors(); |  265       selectors = this.getUnconditionalSelectors(); | 
|  253  |  266  | 
|  254     let specificOnly = (criteria >= ElemHide.SPECIFIC_ONLY); |  267     let specificOnly = (criteria >= ElemHide.SPECIFIC_ONLY); | 
|  255     let excludedFilters = new Set(); |  268     let excludedFilters = []; | 
|  256  |  269  | 
|  257     let currentDomain = domain ? domain.toUpperCase() : ""; |  270     let currentDomain = domain ? domain.toUpperCase() : ""; | 
|  258     let currentDomainIsGeneric = currentDomain == ""; |  271     let currentDomainIsGeneric = currentDomain == ""; | 
|  259  |  272  | 
|  260     // This code is a performance hot-spot, which is why we've made certain |  273     // This code is a performance hot-spot, which is why we've made certain | 
|  261     // micro-optimisations. Please be careful before making changes. |  274     // micro-optimisations. Please be careful before making changes. | 
|  262     while (true) |  275     while (true) | 
|  263     { |  276     { | 
|  264       if (specificOnly && currentDomainIsGeneric) |  277       if (specificOnly && currentDomainIsGeneric) | 
|  265         break; |  278         break; | 
|  266  |  279  | 
|  267       let filters = filtersByDomain.get(currentDomain); |  280       let [excluded, included] = filtersByDomain.get(currentDomain) || []; | 
|  268       if (filters) |  281  | 
 |  282       if (excluded) | 
 |  283         excludedFilters.push(excluded); | 
 |  284  | 
 |  285       if (included) | 
|  269       { |  286       { | 
|  270         for (let [filter, isIncluded] of filters) |  287         for (let filter of included) | 
|  271         { |  288         { | 
|  272           if (excludedFilters.size > 0 && excludedFilters.has(filter)) |  289           for (let i = 0; i < excludedFilters.length; i++) | 
|  273             continue; |  290           { | 
 |  291             if (excludedFilters[i].has(filter)) | 
 |  292             { | 
 |  293               filter = null; | 
 |  294               break; | 
 |  295             } | 
 |  296           } | 
|  274  |  297  | 
|  275           if (isIncluded) |  298           if (filter && !this.getException(filter, domain)) | 
|  276           { |  299             selectors.push(filter.selector); | 
|  277             if (!this.getException(filter, domain)) |  | 
|  278               selectors.push(filter.selector); |  | 
|  279           } |  | 
|  280           else if (!currentDomainIsGeneric) |  | 
|  281             excludedFilters.add(filter); |  | 
|  282         } |  300         } | 
|  283       } |  301       } | 
|  284  |  302  | 
|  285       if (currentDomainIsGeneric) |  303       if (currentDomainIsGeneric) | 
|  286         break; |  304         break; | 
|  287  |  305  | 
|  288       let nextDot = currentDomain.indexOf("."); |  306       let nextDot = currentDomain.indexOf("."); | 
|  289       if (nextDot == -1) |  307       if (nextDot == -1) | 
|  290       { |  308       { | 
|  291         currentDomain = ""; |  309         currentDomain = ""; | 
|  292         currentDomainIsGeneric = true; |  310         currentDomainIsGeneric = true; | 
|  293       } |  311       } | 
|  294       else |  312       else | 
|  295         currentDomain = currentDomain.substr(nextDot + 1); |  313         currentDomain = currentDomain.substr(nextDot + 1); | 
|  296     } |  314     } | 
|  297  |  315  | 
|  298     return selectors; |  316     return selectors; | 
|  299   } |  317   } | 
|  300 }; |  318 }; | 
| OLD | NEW |