Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/filterClasses.js

Issue 30022555: Issue 7324 - Simplify logic for domains property (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Created March 4, 2019, 11:39 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/filterClasses.js » ('j') | test/filterClasses.js » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 Definition of Filter class and its subclasses. 21 * @fileOverview Definition of Filter class and its subclasses.
22 */ 22 */
23 23
24 const {extend} = require("./coreUtils"); 24 const {extend} = require("./coreUtils");
25 const {filterToRegExp} = require("./common"); 25 const {filterToRegExp} = require("./common");
26 const {normalizeHostname, domainSuffixes} = require("./url"); 26 const {normalizeHostname, domainSuffixes} = require("./url");
27 const {Cache} = require("./caching");
27 const {filterNotifier} = require("./filterNotifier"); 28 const {filterNotifier} = require("./filterNotifier");
28 29
29 const resources = require("../data/resources.json"); 30 const resources = require("../data/resources.json");
30 31
31 /** 32 /**
32 * Map of internal resources for URL rewriting. 33 * Map of internal resources for URL rewriting.
33 * @type {Map.<string,string>} 34 * @type {Map.<string,string>}
34 */ 35 */
35 let resourceMap = new Map( 36 let resourceMap = new Map(
36 Object.keys(resources).map(key => [key, resources[key]]) 37 Object.keys(resources).map(key => [key, resources[key]])
37 ); 38 );
38 39
39 /** 40 /**
40 * Regular expression used to match the <code>||</code> prefix in an otherwise 41 * Regular expression used to match the <code>||</code> prefix in an otherwise
41 * literal pattern. 42 * literal pattern.
42 * @type {RegExp} 43 * @type {RegExp}
43 */ 44 */
44 let doubleAnchorRegExp = new RegExp(filterToRegExp("||") + "$"); 45 let doubleAnchorRegExp = new RegExp(filterToRegExp("||") + "$");
45 46
46 /** 47 /**
47 * Regular expression used to match the <code>^</code> suffix in an otherwise 48 * Regular expression used to match the <code>^</code> suffix in an otherwise
48 * literal pattern. 49 * literal pattern.
49 * @type {RegExp} 50 * @type {RegExp}
50 */ 51 */
51 // Note: This should match the pattern in lib/common.js 52 // Note: This should match the pattern in lib/common.js
52 let separatorRegExp = /[\x00-\x24\x26-\x2C\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/; 53 let separatorRegExp = /[\x00-\x24\x26-\x2C\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/;
53 54
54 /** 55 /**
55 * All known unique domain sources mapped to their parsed values. 56 * Cache of domain maps. The domains part of filter text
56 * @type {Map.<string,Map.<string,boolean>>} 57 * (e.g. <code>example.com,~mail.example.com</code>) is often repeated across
58 * filters. This cache enables deduplication of the <code>Map</code> objects
59 * that specify on which domains the filter does and does not apply, which
60 * reduces memory usage and improves performance.
61 * @type {Map.<string, Map.<string, boolean>>}
57 */ 62 */
58 let knownDomainMaps = new Map(); 63 let domainMapCache = new Cache(1000);
59 64
60 /** 65 /**
61 * Checks whether the given pattern is a string of literal characters with no 66 * Checks whether the given pattern is a string of literal characters with no
62 * wildcards or any other special characters. If the pattern is prefixed with a 67 * wildcards or any other special characters. If the pattern is prefixed with a
63 * <code>||</code> or suffixed with a <code>^</code> but otherwise contains no 68 * <code>||</code> or suffixed with a <code>^</code> but otherwise contains no
64 * special characters, it is still considered to be a literal pattern. 69 * special characters, it is still considered to be a literal pattern.
65 * @param {string} pattern 70 * @param {string} pattern
66 * @returns {boolean} 71 * @returns {boolean}
67 */ 72 */
68 function isLiteralPattern(pattern) 73 function isLiteralPattern(pattern)
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 * Domains that the filter is restricted to separated by domainSeparator 405 * Domains that the filter is restricted to separated by domainSeparator
401 * e.g. "foo.com|bar.com|~baz.com" 406 * e.g. "foo.com|bar.com|~baz.com"
402 * @constructor 407 * @constructor
403 * @augments Filter 408 * @augments Filter
404 */ 409 */
405 function ActiveFilter(text, domains) 410 function ActiveFilter(text, domains)
406 { 411 {
407 Filter.call(this, text); 412 Filter.call(this, text);
408 413
409 if (domains) 414 if (domains)
410 this.domainSource = domains; 415 this.domainSource = domains.toLowerCase();
Manish Jethani 2019/03/04 12:02:54 Lower-case in advance during initialization.
hub 2019/03/06 13:10:40 Do we know if there is a performance difference be
Manish Jethani 2019/03/06 18:11:10 You mean that we could require that the domains ar
hub 2019/03/06 18:14:25 I was just wondering if toLowerCase() is faster wh
Manish Jethani 2019/03/06 18:28:10 Ah, I see what you mean. I don't expect it to be f
411 } 416 }
412 exports.ActiveFilter = ActiveFilter; 417 exports.ActiveFilter = ActiveFilter;
413 418
414 ActiveFilter.prototype = extend(Filter, { 419 ActiveFilter.prototype = extend(Filter, {
415 _disabled: false, 420 _disabled: false,
416 _hitCount: 0, 421 _hitCount: 0,
417 _lastHit: 0, 422 _lastHit: 0,
418 423
419 /** 424 /**
420 * Defines whether the filter is disabled 425 * Defines whether the filter is disabled
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 */ 492 */
488 domainSeparator: null, 493 domainSeparator: null,
489 494
490 /** 495 /**
491 * Map containing domains that this filter should match on/not match 496 * Map containing domains that this filter should match on/not match
492 * on or null if the filter should match on all domains 497 * on or null if the filter should match on all domains
493 * @type {?Map.<string,boolean>} 498 * @type {?Map.<string,boolean>}
494 */ 499 */
495 get domains() 500 get domains()
496 { 501 {
497 let domains = null; 502 let {domainSource} = this;
Manish Jethani 2019/03/04 12:02:54 Tip: The diff of this function is smaller with the
503 if (!domainSource)
504 return null;
498 505
499 if (this.domainSource) 506 let domains = domainMapCache.get(domainSource);
507 if (domains)
508 return domains;
509
510 let list = domainSource.split(this.domainSeparator);
511 if (list.length == 1 && list[0][0] != "~")
500 { 512 {
501 // For most filter types this property is accessed only rarely, 513 // Fast track for the common one-domain scenario
502 // especially when the subscriptions are initially loaded. We defer any 514 domains = new Map([[list[0], true], ["", false]]);
503 // caching by default. 515 }
504 let cacheDomains = this._cacheDomains; 516 else
517 {
518 let hasIncludes = false;
519 for (let i = 0; i < list.length; i++)
520 {
521 let domain = list[i];
522 if (domain == "")
523 continue;
505 524
506 let source = this.domainSource.toLowerCase(); 525 let include;
507 526 if (domain[0] == "~")
508 let knownMap = knownDomainMaps.get(source);
509 if (knownMap)
510 {
511 domains = knownMap;
512 }
513 else
514 {
515 let list = source.split(this.domainSeparator);
516 if (list.length == 1 && list[0][0] != "~")
517 { 527 {
518 // Fast track for the common one-domain scenario 528 include = false;
519 domains = new Map([[list[0], true], ["", false]]); 529 domain = domain.substring(1);
520 } 530 }
521 else 531 else
522 { 532 {
523 let hasIncludes = false; 533 include = true;
524 for (let i = 0; i < list.length; i++) 534 hasIncludes = true;
525 {
526 let domain = list[i];
527 if (domain == "")
528 continue;
529
530 let include;
531 if (domain[0] == "~")
532 {
533 include = false;
534 domain = domain.substring(1);
535 }
536 else
537 {
538 include = true;
539 hasIncludes = true;
540 }
541
542 if (!domains)
543 domains = new Map();
544
545 domains.set(domain, include);
546 }
547
548 if (domains)
549 domains.set("", !hasIncludes);
550 } 535 }
551 536
552 if (!domains || cacheDomains) 537 if (!domains)
553 knownDomainMaps.set(source, domains); 538 domains = new Map();
539
540 domains.set(domain, include);
554 } 541 }
555 542
556 if (!domains || cacheDomains) 543 if (domains)
557 { 544 domains.set("", !hasIncludes);
558 this.domainSource = null;
559 Object.defineProperty(this, "domains", {value: domains});
560 }
561 } 545 }
562 546
563 this._cacheDomains = true; 547 domainMapCache.set(domainSource, domains);
564 548
565 return domains; 549 return domains;
566 }, 550 },
567 551
568 /** 552 /**
569 * Whether the value of {@link ActiveFilter#domains} should be cached.
570 * @type {boolean}
571 * @private
572 */
573 _cacheDomains: false,
574
575 /**
576 * Array containing public keys of websites that this filter should apply to 553 * Array containing public keys of websites that this filter should apply to
577 * @type {?string[]} 554 * @type {?string[]}
578 */ 555 */
579 sitekeys: null, 556 sitekeys: null,
580 557
581 /** 558 /**
582 * Checks whether this filter is active on a domain. 559 * Checks whether this filter is active on a domain.
583 * @param {string} [docDomain] domain name of the document that loads the URL 560 * @param {string} [docDomain] domain name of the document that loads the URL
584 * @param {string} [sitekey] public key provided by the document 561 * @param {string} [sitekey] public key provided by the document
585 * @return {boolean} true in case of the filter being active 562 * @return {boolean} true in case of the filter being active
(...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after
1433 1410
1434 /** 1411 /**
1435 * Script that should be executed 1412 * Script that should be executed
1436 * @type {string} 1413 * @type {string}
1437 */ 1414 */
1438 get script() 1415 get script()
1439 { 1416 {
1440 return this.body; 1417 return this.body;
1441 } 1418 }
1442 }); 1419 });
OLDNEW
« no previous file with comments | « no previous file | test/filterClasses.js » ('j') | test/filterClasses.js » ('J')

Powered by Google App Engine
This is Rietveld