| Index: include.preload.js | 
| diff --git a/include.preload.js b/include.preload.js | 
| index 86e52c32afceb894f6591a84b0eca3b1842383ce..56d9e1b27b45b5316b8c728ce8758099f6bd4869 100644 | 
| --- a/include.preload.js | 
| +++ b/include.preload.js | 
| @@ -15,7 +15,9 @@ | 
| * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| */ | 
|  | 
| -var typeMap = { | 
| +"use strict"; | 
| + | 
| +let typeMap = { | 
| "img": "IMAGE", | 
| "input": "IMAGE", | 
| "picture": "IMAGE", | 
| @@ -29,24 +31,23 @@ var typeMap = { | 
|  | 
| function getURLsFromObjectElement(element) | 
| { | 
| -  var url = element.getAttribute("data"); | 
| +  let url = element.getAttribute("data"); | 
| if (url) | 
| return [url]; | 
|  | 
| -  for (var i = 0; i < element.children.length; i++) | 
| +  for (let child of element.children) | 
| { | 
| -    var child = element.children[i]; | 
| if (child.localName != "param") | 
| continue; | 
|  | 
| -    var name = child.getAttribute("name"); | 
| +    let name = child.getAttribute("name"); | 
| if (name != "movie"  && // Adobe Flash | 
| name != "source" && // Silverlight | 
| name != "src"    && // Real Media + Quicktime | 
| name != "FileName") // Windows Media | 
| continue; | 
|  | 
| -    var value = child.getAttribute("value"); | 
| +    let value = child.getAttribute("value"); | 
| if (!value) | 
| continue; | 
|  | 
| @@ -58,17 +59,16 @@ function getURLsFromObjectElement(element) | 
|  | 
| function getURLsFromAttributes(element) | 
| { | 
| -  var urls = []; | 
| +  let urls = []; | 
|  | 
| if (element.src) | 
| urls.push(element.src); | 
|  | 
| if (element.srcset) | 
| { | 
| -    var candidates = element.srcset.split(","); | 
| -    for (var i = 0; i < candidates.length; i++) | 
| +    for (let candidate of element.srcset.split(",")) | 
| { | 
| -      var url = candidates[i].trim().replace(/\s+\S+$/, ""); | 
| +      let url = candidate.trim().replace(/\s+\S+$/, ""); | 
| if (url) | 
| urls.push(url); | 
| } | 
| @@ -79,14 +79,11 @@ function getURLsFromAttributes(element) | 
|  | 
| function getURLsFromMediaElement(element) | 
| { | 
| -  var urls = getURLsFromAttributes(element); | 
| +  let urls = getURLsFromAttributes(element); | 
|  | 
| -  for (var i = 0; i < element.children.length; i++) | 
| -  { | 
| -    var child = element.children[i]; | 
| +  for (let child of element.children) | 
| if (child.localName == "source" || child.localName == "track") | 
| urls.push.apply(urls, getURLsFromAttributes(child)); | 
| -  } | 
|  | 
| if (element.poster) | 
| urls.push(element.poster); | 
| @@ -96,7 +93,7 @@ function getURLsFromMediaElement(element) | 
|  | 
| function getURLsFromElement(element) | 
| { | 
| -  var urls; | 
| +  let urls; | 
| switch (element.localName) | 
| { | 
| case "object": | 
| @@ -114,7 +111,7 @@ function getURLsFromElement(element) | 
| break; | 
| } | 
|  | 
| -  for (var i = 0; i < urls.length; i++) | 
| +  for (let i = 0; i < urls.length; i++) | 
| { | 
| if (/^(?!https?:)[\w-]+:/i.test(urls[i])) | 
| urls.splice(i--, 1); | 
| @@ -125,11 +122,11 @@ function getURLsFromElement(element) | 
|  | 
| function checkCollapse(element) | 
| { | 
| -  var mediatype = typeMap[element.localName]; | 
| +  let mediatype = typeMap[element.localName]; | 
| if (!mediatype) | 
| return; | 
|  | 
| -  var urls = getURLsFromElement(element); | 
| +  let urls = getURLsFromElement(element); | 
| if (urls.length == 0) | 
| return; | 
|  | 
| @@ -141,12 +138,12 @@ function checkCollapse(element) | 
| baseURL: document.location.href | 
| }, | 
|  | 
| -    function(collapse) | 
| +    collapse => | 
| { | 
| function collapseElement() | 
| { | 
| -        var propertyName = "display"; | 
| -        var propertyValue = "none"; | 
| +        let propertyName = "display"; | 
| +        let propertyValue = "none"; | 
| if (element.localName == "frame") | 
| { | 
| propertyName = "visibility"; | 
| @@ -175,7 +172,7 @@ function checkCollapse(element) | 
|  | 
| function checkSitekey() | 
| { | 
| -  var attr = document.documentElement.getAttribute("data-adblockkey"); | 
| +  let attr = document.documentElement.getAttribute("data-adblockkey"); | 
| if (attr) | 
| ext.backgroundPage.sendMessage({type: "filters.addKey", token: attr}); | 
| } | 
| @@ -208,26 +205,24 @@ function ElementHidingTracer(selectors) | 
| this.trace(); | 
| } | 
| ElementHidingTracer.prototype = { | 
| -  checkNodes: function(nodes) | 
| +  checkNodes(nodes) | 
| { | 
| -    var matchedSelectors = []; | 
| +    let matchedSelectors = []; | 
|  | 
| // Find all selectors that match any hidden element inside the given nodes. | 
| -    for (var i = 0; i < this.selectors.length; i++) | 
| +    for (let selector of this.selectors) | 
| { | 
| -      var selector = this.selectors[i]; | 
| - | 
| -      for (var j = 0; j < nodes.length; j++) | 
| +      for (let node of nodes) | 
| { | 
| -        var elements = nodes[j].querySelectorAll(selector); | 
| -        var matched = false; | 
| +        let elements = node.querySelectorAll(selector); | 
| +        let matched = false; | 
|  | 
| -        for (var k = 0; k < elements.length; k++) | 
| +        for (let element of elements) | 
| { | 
| // Only consider selectors that actually have an effect on the | 
| // computed styles, and aren't overridden by rules with higher | 
| // priority, or haven't been circumvented in a different way. | 
| -          if (getComputedStyle(elements[k]).display == "none") | 
| +          if (getComputedStyle(element).display == "none") | 
| { | 
| matchedSelectors.push(selector); | 
| matched = true; | 
| @@ -247,26 +242,25 @@ ElementHidingTracer.prototype = { | 
| }); | 
| }, | 
|  | 
| -  onTimeout: function() | 
| +  onTimeout() | 
| { | 
| this.checkNodes(this.changedNodes); | 
| this.changedNodes = []; | 
| this.timeout = null; | 
| }, | 
|  | 
| -  observe: function(mutations) | 
| +  observe(mutations) | 
| { | 
| // Forget previously changed nodes that are no longer in the DOM. | 
| -    for (var i = 0; i < this.changedNodes.length; i++) | 
| +    for (let i = 0; i < this.changedNodes.length; i++) | 
| { | 
| if (!document.contains(this.changedNodes[i])) | 
| this.changedNodes.splice(i--, 1); | 
| } | 
|  | 
| -    for (var j = 0; j < mutations.length; j++) | 
| +    for (let mutation of mutations) | 
| { | 
| -      var mutation = mutations[j]; | 
| -      var node = mutation.target; | 
| +      let node = mutation.target; | 
|  | 
| // Ignore mutations of nodes that aren't in the DOM anymore. | 
| if (!document.contains(node)) | 
| @@ -278,10 +272,10 @@ ElementHidingTracer.prototype = { | 
| if (mutation.type == "attributes") | 
| node = node.parentNode; | 
|  | 
| -      var addNode = true; | 
| -      for (var k = 0; k < this.changedNodes.length; k++) | 
| +      let addNode = true; | 
| +      for (let i = 0; i < this.changedNodes.length; i++) | 
| { | 
| -        var previouslyChangedNode = this.changedNodes[k]; | 
| +        let previouslyChangedNode = this.changedNodes[i]; | 
|  | 
| // If we are already going to check an ancestor of this node, | 
| // we can ignore this node, since it will be considered anyway | 
| @@ -296,7 +290,7 @@ ElementHidingTracer.prototype = { | 
| // we can ignore that node, since it will be considered anyway | 
| // when checking one of its ancestors. | 
| if (node.contains(previouslyChangedNode)) | 
| -          this.changedNodes.splice(k--, 1); | 
| +          this.changedNodes.splice(i--, 1); | 
| } | 
|  | 
| if (addNode) | 
| @@ -310,7 +304,7 @@ ElementHidingTracer.prototype = { | 
| this.timeout = setTimeout(this.onTimeout.bind(this), 1000); | 
| }, | 
|  | 
| -  trace: function() | 
| +  trace() | 
| { | 
| this.checkNodes([document]); | 
|  | 
| @@ -324,7 +318,7 @@ ElementHidingTracer.prototype = { | 
| ); | 
| }, | 
|  | 
| -  disconnect: function() | 
| +  disconnect() | 
| { | 
| document.removeEventListener("DOMContentLoaded", this.trace); | 
| this.observer.disconnect(); | 
| @@ -334,7 +328,7 @@ ElementHidingTracer.prototype = { | 
|  | 
| function runInPageContext(fn, arg) | 
| { | 
| -  var script = document.createElement("script"); | 
| +  let script = document.createElement("script"); | 
| script.type = "application/javascript"; | 
| script.async = false; | 
| script.textContent = "(" + fn + ")(" + JSON.stringify(arg) + ");"; | 
| @@ -349,14 +343,14 @@ function runInPageContext(fn, arg) | 
| // [1] - https://bugs.chromium.org/p/chromium/issues/detail?id=129353 | 
| function wrapWebSocket() | 
| { | 
| -  var eventName = "abpws-" + Math.random().toString(36).substr(2); | 
| +  let eventName = "abpws-" + Math.random().toString(36).substr(2); | 
|  | 
| -  document.addEventListener(eventName, function(event) | 
| +  document.addEventListener(eventName, event => | 
| { | 
| ext.backgroundPage.sendMessage({ | 
| type: "request.websocket", | 
| url: event.detail.url | 
| -    }, function (block) | 
| +    }, block => | 
| { | 
| document.dispatchEvent( | 
| new CustomEvent(eventName + "-" + event.detail.url, {detail: block}) | 
| @@ -364,20 +358,20 @@ function wrapWebSocket() | 
| }); | 
| }); | 
|  | 
| -  runInPageContext(function(eventName) | 
| +  runInPageContext(eventName => | 
| { | 
| // As far as possible we must track everything we use that could be | 
| // sabotaged by the website later in order to circumvent us. | 
| -    var RealWebSocket = WebSocket; | 
| -    var closeWebSocket = Function.prototype.call.bind(RealWebSocket.prototype.close); | 
| -    var addEventListener = document.addEventListener.bind(document); | 
| -    var removeEventListener = document.removeEventListener.bind(document); | 
| -    var dispatchEvent = document.dispatchEvent.bind(document); | 
| -    var CustomEvent = window.CustomEvent; | 
| +    let RealWebSocket = WebSocket; | 
| +    let closeWebSocket = Function.prototype.call.bind(RealWebSocket.prototype.close); | 
| +    let addEventListener = document.addEventListener.bind(document); | 
| +    let removeEventListener = document.removeEventListener.bind(document); | 
| +    let dispatchEvent = document.dispatchEvent.bind(document); | 
| +    let CustomEvent = window.CustomEvent; | 
|  | 
| function checkRequest(url, callback) | 
| { | 
| -      var incomingEventName = eventName + "-" + url; | 
| +      let incomingEventName = eventName + "-" + url; | 
| function listener(event) | 
| { | 
| callback(event.detail); | 
| @@ -396,13 +390,13 @@ function wrapWebSocket() | 
| if (!(this instanceof WrappedWebSocket)) return RealWebSocket(); | 
| if (arguments.length < 1) return new RealWebSocket(); | 
|  | 
| -      var websocket; | 
| +      let websocket; | 
| if (arguments.length == 1) | 
| websocket = new RealWebSocket(url); | 
| else | 
| websocket = new RealWebSocket(url, arguments[1]); | 
|  | 
| -      checkRequest(websocket.url, function(blocked) | 
| +      checkRequest(websocket.url, blocked => | 
| { | 
| if (blocked) | 
| closeWebSocket(websocket); | 
| @@ -432,7 +426,7 @@ function ElemHide() | 
|  | 
| this.elemHideEmulation = new ElemHideEmulation( | 
| window, | 
| -    function(callback) | 
| +    callback => | 
| { | 
| ext.backgroundPage.sendMessage({ | 
| type: "filters.get", | 
| @@ -445,7 +439,7 @@ function ElemHide() | 
| ElemHide.prototype = { | 
| selectorGroupSize: 200, | 
|  | 
| -  createShadowTree: function() | 
| +  createShadowTree() | 
| { | 
| // Use Shadow DOM if available as to not mess with with web pages that | 
| // rely on the order of their own <style> tags (#309). However, creating | 
| @@ -462,25 +456,25 @@ ElemHide.prototype = { | 
| // Finally since some users have both AdBlock and Adblock Plus installed we | 
| // have to consider how the two extensions interact. For example we want to | 
| // avoid creating the shadowRoot twice. | 
| -    var shadow = document.documentElement.shadowRoot || | 
| +    let shadow = document.documentElement.shadowRoot || | 
| document.documentElement.createShadowRoot(); | 
| shadow.appendChild(document.createElement("shadow")); | 
|  | 
| // Stop the website from messing with our shadow root (#4191, #4298). | 
| if ("shadowRoot" in Element.prototype) | 
| { | 
| -      runInPageContext(function() | 
| +      runInPageContext(() => | 
| { | 
| -        var ourShadowRoot = document.documentElement.shadowRoot; | 
| +        let ourShadowRoot = document.documentElement.shadowRoot; | 
| if (!ourShadowRoot) | 
| return; | 
| -        var desc = Object.getOwnPropertyDescriptor(Element.prototype, "shadowRoot"); | 
| -        var shadowRoot = Function.prototype.call.bind(desc.get); | 
| +        let desc = Object.getOwnPropertyDescriptor(Element.prototype, "shadowRoot"); | 
| +        let shadowRoot = Function.prototype.call.bind(desc.get); | 
|  | 
| Object.defineProperty(Element.prototype, "shadowRoot", { | 
| -          configurable: true, enumerable: true, get: function() | 
| +          configurable: true, enumerable: true, get() | 
| { | 
| -            var shadow = shadowRoot(this); | 
| +            let shadow = shadowRoot(this); | 
| return shadow == ourShadowRoot ? null : shadow; | 
| } | 
| }); | 
| @@ -490,7 +484,7 @@ ElemHide.prototype = { | 
| return shadow; | 
| }, | 
|  | 
| -  addSelectors: function(selectors) | 
| +  addSelectors(selectors) | 
| { | 
| if (selectors.length == 0) | 
| return; | 
| @@ -518,12 +512,12 @@ ElemHide.prototype = { | 
| // insertion point. | 
| if (this.shadow) | 
| { | 
| -      var preparedSelectors = []; | 
| -      for (var i = 0; i < selectors.length; i++) | 
| +      let preparedSelectors = []; | 
| +      for (let selector of selectors) | 
| { | 
| -        var subSelectors = splitSelector(selectors[i]); | 
| -        for (var j = 0; j < subSelectors.length; j++) | 
| -          preparedSelectors.push("::content " + subSelectors[j]); | 
| +        let subSelectors = splitSelector(selector); | 
| +        for (let subSelector of subSelectors) | 
| +          preparedSelectors.push("::content " + subSelector); | 
| } | 
| selectors = preparedSelectors; | 
| } | 
| @@ -533,20 +527,20 @@ ElemHide.prototype = { | 
| // (Chrome also has a limit, larger... but we're not certain exactly what it | 
| //  is! Edge apparently has no such limit.) | 
| // [1] - https://github.com/WebKit/webkit/blob/1cb2227f6b2a1035f7bdc46e5ab69debb75fc1de/Source/WebCore/css/RuleSet.h#L68 | 
| -    for (var i = 0; i < selectors.length; i += this.selectorGroupSize) | 
| +    for (let i = 0; i < selectors.length; i += this.selectorGroupSize) | 
| { | 
| -      var selector = selectors.slice(i, i + this.selectorGroupSize).join(", "); | 
| +      let selector = selectors.slice(i, i + this.selectorGroupSize).join(", "); | 
| this.style.sheet.insertRule(selector + "{display: none !important;}", | 
| this.style.sheet.cssRules.length); | 
| } | 
| }, | 
|  | 
| -  apply: function() | 
| +  apply() | 
| { | 
| -    var selectors = null; | 
| -    var elemHideEmulationLoaded = false; | 
| +    let selectors = null; | 
| +    let elemHideEmulationLoaded = false; | 
|  | 
| -    var checkLoaded = function() | 
| +    let checkLoaded = function() | 
| { | 
| if (!selectors || !elemHideEmulationLoaded) | 
| return; | 
| @@ -566,13 +560,13 @@ ElemHide.prototype = { | 
| this.tracer = new ElementHidingTracer(selectors.selectors); | 
| }.bind(this); | 
|  | 
| -    ext.backgroundPage.sendMessage({type: "get-selectors"}, function(response) | 
| +    ext.backgroundPage.sendMessage({type: "get-selectors"}, response => | 
| { | 
| selectors = response; | 
| checkLoaded(); | 
| }); | 
|  | 
| -    this.elemHideEmulation.load(function() | 
| +    this.elemHideEmulation.load(() => | 
| { | 
| elemHideEmulationLoaded = true; | 
| checkLoaded(); | 
| @@ -585,17 +579,17 @@ if (document instanceof HTMLDocument) | 
| checkSitekey(); | 
| wrapWebSocket(); | 
|  | 
| -  var elemhide = new ElemHide(); | 
| +  let elemhide = new ElemHide(); | 
| elemhide.apply(); | 
|  | 
| -  document.addEventListener("error", function(event) | 
| +  document.addEventListener("error", event => | 
| { | 
| checkCollapse(event.target); | 
| }, true); | 
|  | 
| -  document.addEventListener("load", function(event) | 
| +  document.addEventListener("load", event => | 
| { | 
| -    var element = event.target; | 
| +    let element = event.target; | 
| if (/^i?frame$/.test(element.localName)) | 
| checkCollapse(element); | 
| }, true); | 
|  |