 Issue 29371763:
  Issue 4795 - Use modern JavaScript syntax  (Closed)
    
  
    Issue 29371763:
  Issue 4795 - Use modern JavaScript syntax  (Closed) 
  | Index: include.preload.js | 
| diff --git a/include.preload.js b/include.preload.js | 
| index 86e52c32afceb894f6591a84b0eca3b1842383ce..4726dc5ce4fb704f0ae3655b49e5da9d601b49b2 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) | 
| 
Sebastian Noack
2017/01/16 15:35:55
Removing the braces for the loop is unrelated, and
 
Sebastian Noack
2017/01/16 15:37:24
s/omit lines/omit braces/
 
kzar
2017/01/17 07:42:48
Whoops, Done.
 | 
| 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,19 @@ if (document instanceof HTMLDocument) | 
| checkSitekey(); | 
| wrapWebSocket(); | 
| + // This variable is also used by our other content scripts, outside of the | 
| + // current scope. | 
| var 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); |