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

Side by Side Diff: lib/abp2blocklist.js

Issue 29473555: Issue 5345 - Whitelist $elemhide and $generichide domains where possible (Closed) Base URL: https://hg.adblockplus.org/abp2blocklist
Patch Set: Generate unless-domain value outside while loop Created July 11, 2017, 11:14 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 | « abp2blocklist.js ('k') | test/abp2blocklist.js » ('j') | no next file with comments »
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-2017 eyeo GmbH 3 * Copyright (C) 2006-2017 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
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 71
72 for (let name of list) 72 for (let name of list)
73 { 73 {
74 if (name.length > suffixLength && name.slice(-suffixLength) == "." + domain) 74 if (name.length > suffixLength && name.slice(-suffixLength) == "." + domain)
75 subdomains.push(name.slice(0, -suffixLength)); 75 subdomains.push(name.slice(0, -suffixLength));
76 } 76 }
77 77
78 return subdomains; 78 return subdomains;
79 } 79 }
80 80
81 function extractFilterDomains(filters)
82 {
83 let domains = new Set();
84 for (let filter of filters)
85 {
86 let parsed = parseFilterRegexpSource(filter.regexpSource);
87 if (parsed.justHostname)
88 domains.add(parsed.hostname);
89 }
90 return domains;
91 }
92
81 function convertElemHideFilter(filter, elemhideSelectorExceptions) 93 function convertElemHideFilter(filter, elemhideSelectorExceptions)
82 { 94 {
83 let included = []; 95 let included = [];
84 let excluded = []; 96 let excluded = [];
85 let rules = []; 97 let rules = [];
86 98
87 parseDomains(filter.domains, included, excluded); 99 parseDomains(filter.domains, included, excluded);
88 100
89 if (excluded.length == 0 && !(filter.selector in elemhideSelectorExceptions)) 101 if (excluded.length == 0 && !(filter.selector in elemhideSelectorExceptions))
90 return {matchDomains: included.map(matchDomain), selector: filter.selector}; 102 return {matchDomains: included.map(matchDomain), selector: filter.selector};
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 // If we're currently inside the hostname we have to be careful not to 138 // If we're currently inside the hostname we have to be careful not to
127 // escape any characters until after we have converted it to punycode. 139 // escape any characters until after we have converted it to punycode.
128 if (hostnameStart != null && !hostnameFinished) 140 if (hostnameStart != null && !hostnameFinished)
129 { 141 {
130 let endingChar = (c == "*" || c == "^" || 142 let endingChar = (c == "*" || c == "^" ||
131 c == "?" || c == "/" || c == "|"); 143 c == "?" || c == "/" || c == "|");
132 if (!endingChar && i != lastIndex) 144 if (!endingChar && i != lastIndex)
133 continue; 145 continue;
134 146
135 hostname = punycode.toASCII( 147 hostname = punycode.toASCII(
136 text.substring(hostnameStart, endingChar ? i : i + 1) 148 text.substring(hostnameStart, endingChar ? i : i + 1).toLowerCase()
137 ); 149 );
138 hostnameFinished = justHostname = true; 150 hostnameFinished = justHostname = true;
139 regexp.push(escapeRegExp(hostname)); 151 regexp.push(escapeRegExp(hostname));
140 if (!endingChar) 152 if (!endingChar)
141 break; 153 break;
142 } 154 }
143 155
144 switch (c) 156 switch (c)
145 { 157 {
146 case "*": 158 case "*":
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 { 405 {
394 newSelector.push(selector.substring(i, pos.start)); 406 newSelector.push(selector.substring(i, pos.start));
395 newSelector.push('[id=', selector.substring(pos.start + 1, pos.end), ']'); 407 newSelector.push('[id=', selector.substring(pos.start + 1, pos.end), ']');
396 i = pos.end; 408 i = pos.end;
397 } 409 }
398 newSelector.push(selector.substring(i)); 410 newSelector.push(selector.substring(i));
399 411
400 return newSelector.join(""); 412 return newSelector.join("");
401 } 413 }
402 414
403 function addCSSRules(rules, selectors, matchDomain) 415 function addCSSRules(rules, selectors, matchDomain, exceptionDomains)
404 { 416 {
417 let unlessDomain = exceptionDomains.size > 0 ? [] : null;
kzar 2017/07/11 12:20:03 Nit: This seems like overkill since `[]` is falsey
Manish Jethani 2017/07/11 16:28:39 [] evaluates to true. If you mean checking the len
kzar 2017/07/11 16:30:36 Whoops, you're right.
418
419 exceptionDomains.forEach(name => unlessDomain.push("*" + name));
420
405 while (selectors.length) 421 while (selectors.length)
406 { 422 {
407 let selector = selectors.splice(0, selectorLimit).join(", "); 423 let selector = selectors.splice(0, selectorLimit).join(", ");
408 424
409 // As of Safari 9.0 element IDs are matched as lowercase. We work around 425 // As of Safari 9.0 element IDs are matched as lowercase. We work around
410 // this by converting to the attribute format [id="elementID"] 426 // this by converting to the attribute format [id="elementID"]
411 selector = convertIDSelectorsToAttributeSelectors(selector); 427 selector = convertIDSelectorsToAttributeSelectors(selector);
412 428
413 rules.push({ 429 let rule = {
414 trigger: {"url-filter": matchDomain, 430 trigger: {"url-filter": matchDomain,
415 "url-filter-is-case-sensitive": true}, 431 "url-filter-is-case-sensitive": true},
416 action: {type: "css-display-none", 432 action: {type: "css-display-none",
417 selector: selector} 433 selector: selector}
418 }); 434 };
435
436 if (unlessDomain)
437 rule.trigger["unless-domain"] = unlessDomain;
438
439 rules.push(rule);
419 } 440 }
420 } 441 }
421 442
422 let ContentBlockerList = 443 let ContentBlockerList =
423 /** 444 /**
424 * Create a new Adblock Plus filter to content blocker list converter 445 * Create a new Adblock Plus filter to content blocker list converter
425 * 446 *
426 * @constructor 447 * @constructor
427 */ 448 */
428 exports.ContentBlockerList = function () 449 exports.ContentBlockerList = function ()
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 { 526 {
506 for (let matchDomain of result.matchDomains) 527 for (let matchDomain of result.matchDomains)
507 { 528 {
508 let group = groupedElemhideFilters.get(matchDomain) || []; 529 let group = groupedElemhideFilters.get(matchDomain) || [];
509 group.push(result.selector); 530 group.push(result.selector);
510 groupedElemhideFilters.set(matchDomain, group); 531 groupedElemhideFilters.set(matchDomain, group);
511 } 532 }
512 } 533 }
513 } 534 }
514 535
515 addCSSRules(rules, genericSelectors, "^https?://"); 536 // Separate out the element hiding exceptions that have only a hostname part
537 // from the rest. This allows us to implement a workaround for issue #5345
538 // (WebKit bug #167423), but as a bonus it also reduces the number of
539 // generated rules. The downside is that the exception will only apply to the
540 // top-level document, not to iframes. We have to live with this until the
541 // WebKit bug is fixed in all supported versions of Safari.
542 // https://bugs.webkit.org/show_bug.cgi?id=167423
543 //
544 // Note that as a result of this workaround we end up with a huge rule set in
545 // terms of the amount of memory used. This can cause Node.js to throw
546 // "JavaScript heap out of memory". To avoid this, call Node.js with
547 // --max_old_space_size=4096
548 let elemhideExceptionDomains = extractFilterDomains(this.elemhideExceptions);
516 549
517 // Right after the generic element hiding filters, add the exceptions that 550 let genericSelectorExceptionDomains =
518 // should apply only to those filters. 551 extractFilterDomains(this.generichideExceptions);
519 for (let filter of this.generichideExceptions) 552 elemhideExceptionDomains.forEach(name =>
520 convertFilterAddRules(rules, filter, "ignore-previous-rules", false); 553 {
554 genericSelectorExceptionDomains.add(name);
555 });
556
557 addCSSRules(rules, genericSelectors, "^https?://",
558 genericSelectorExceptionDomains);
521 559
522 groupedElemhideFilters.forEach((selectors, matchDomain) => 560 groupedElemhideFilters.forEach((selectors, matchDomain) =>
523 { 561 {
524 addCSSRules(rules, selectors, matchDomain); 562 addCSSRules(rules, selectors, matchDomain, elemhideExceptionDomains);
525 }); 563 });
526 564
527 for (let filter of this.elemhideExceptions)
528 convertFilterAddRules(rules, filter, "ignore-previous-rules", false);
529
530 let requestFilterExceptionDomains = []; 565 let requestFilterExceptionDomains = [];
531 for (let filter of this.genericblockExceptions) 566 for (let filter of this.genericblockExceptions)
532 { 567 {
533 let parsed = parseFilterRegexpSource(filter.regexpSource); 568 let parsed = parseFilterRegexpSource(filter.regexpSource);
534 if (parsed.hostname) 569 if (parsed.hostname)
535 requestFilterExceptionDomains.push(parsed.hostname); 570 requestFilterExceptionDomains.push(parsed.hostname);
536 } 571 }
537 572
538 for (let filter of this.requestFilters) 573 for (let filter of this.requestFilters)
539 { 574 {
540 convertFilterAddRules(rules, filter, "block", true, 575 convertFilterAddRules(rules, filter, "block", true,
541 requestFilterExceptionDomains); 576 requestFilterExceptionDomains);
542 } 577 }
543 578
544 for (let filter of this.requestExceptions) 579 for (let filter of this.requestExceptions)
545 convertFilterAddRules(rules, filter, "ignore-previous-rules", true); 580 convertFilterAddRules(rules, filter, "ignore-previous-rules", true);
546 581
547 return rules.filter(rule => !hasNonASCI(rule)); 582 return rules.filter(rule => !hasNonASCI(rule));
548 }; 583 };
OLDNEW
« no previous file with comments | « abp2blocklist.js ('k') | test/abp2blocklist.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld