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

Side by Side Diff: lib/compat.js

Issue 29545700: Issue 5685 - Pass ESLint (Closed) Base URL: https://hg.adblockplus.org/libadblockplus/
Patch Set: Created Sept. 15, 2017, 7:38 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
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 var window = this; 18 "use strict";
19
20 let window = this;
19 21
20 // 22 //
21 // Module framework stuff 23 // Module framework stuff
22 // 24 //
23 25
24 function require(module) 26 function require(module)
25 { 27 {
26 return require.scopes[module]; 28 return require.scopes[module];
27 } 29 }
28 require.scopes = {__proto__: null}; 30 require.scopes = {__proto__: null};
29 31
30 function importAll(module, globalObj) 32 function importAll(module, globalObj)
sergei 2017/09/18 07:59:05 It seems this function is not used, could you just
hub 2017/09/18 12:43:05 Done.
31 { 33 {
32 var exports = require(module); 34 let exports = require(module);
33 for (var key in exports) 35 for (let key in exports)
34 globalObj[key] = exports[key]; 36 globalObj[key] = exports[key];
35 } 37 }
36 38
37 const onShutdown = { 39 const onShutdown = {
38 done: false, 40 done: false,
39 add: function() {}, 41 add() {},
40 remove: function() {} 42 remove() {}
41 }; 43 };
42 44
43 // 45 //
44 // XPCOM emulation 46 // XPCOM emulation
45 // 47 //
46 48
49 // nsIHttpChannel is checked against instanceof.
50 class nsIHttpChannel
51 {
52 }
53
47 const Components = 54 const Components =
48 { 55 {
49 interfaces: 56 interfaces:
50 { 57 {
51 nsIHttpChannel: function() {}, 58 nsIHttpChannel,
hub 2017/09/15 19:44:00 This one was a bit of a corner case. eslint style
sergei 2017/09/18 07:59:05 Acknowledged.
52 nsITimer: {TYPE_REPEATING_SLACK: 0}, 59 nsITimer: {TYPE_REPEATING_SLACK: 0}
53 },
54 classes:
55 {
56 "@mozilla.org/timer;1":
57 {
58 createInstance: function()
59 {
60 return new FakeTimer();
61 }
62 }, 60 },
63 }, 61 classes:
64 utils: { 62 {
65 reportError: function(e) 63 "@mozilla.org/timer;1":
66 { 64 {
67 console.error(e); 65 createInstance()
68 console.trace(); 66 {
67 return new FakeTimer();
68 }
69 }
69 }, 70 },
70 import: function(resource) 71 utils:
71 { 72 {
72 let match = /^resource:\/\/gre\/modules\/(.+)\.jsm$/.exec(resource); 73 reportError(e)
73 let resourceName = match && match[1]; 74 {
74 if (resourceName && Cu.import.resources.has(resourceName)) 75 console.error(e);
75 return {[resourceName]: Cu.import.resources.get(resourceName)}; 76 console.trace();
76 throw new Error("Attempt to import unknown JavaScript module " + resource) ; 77 },
78 import(resource)
79 {
80 let match = /^resource:\/\/gre\/modules\/(.+)\.jsm$/.exec(resource);
81 let resourceName = match && match[1];
82 if (resourceName && Cu.import.resources.has(resourceName))
83 return {[resourceName]: Cu.import.resources.get(resourceName)};
84 throw new Error(
85 "Attempt to import unknown JavaScript module " + resource);
86 }
77 } 87 }
78 }, 88 };
79 };
80 89
81 const Cc = Components.classes; 90 const Cc = Components.classes;
82 const Ci = Components.interfaces; 91 const Ci = Components.interfaces;
83 const Cu = Components.utils; 92 const Cu = Components.utils;
84 93
85 Cu.import.resources = new Map(); 94 Cu.import.resources = new Map();
86 95
87 Cu.import.resources.set("XPCOMUtils", 96 Cu.import.resources.set("XPCOMUtils",
88 { 97 {
89 generateQI: function() {} 98 generateQI() {}
90 }); 99 });
91 100
92 // 101 //
93 // Services.jsm module emulation 102 // Services.jsm module emulation
94 // 103 //
95 104
96 Cu.import.resources.set("Services", 105 Cu.import.resources.set("Services",
97 { 106 {
98 obs: { 107 obs: {
99 addObserver: function() {}, 108 addObserver() {},
100 removeObserver: function() {} 109 removeObserver() {}
101 }, 110 },
102 vc: { 111 vc: {
103 compare: function(v1, v2) 112 compare(v1, v2)
104 { 113 {
105 function parsePart(s) 114 function parsePart(s)
106 { 115 {
107 if (!s) 116 if (!s)
108 return parsePart("0"); 117 return parsePart("0");
109 118
110 var part = { 119 let part = {
111 numA: 0, 120 numA: 0,
112 strB: "", 121 strB: "",
113 numC: 0, 122 numC: 0,
114 extraD: "" 123 extraD: ""
115 }; 124 };
116 125
117 if (s === "*") 126 if (s === "*")
118 { 127 {
119 part.numA = Number.MAX_VALUE; 128 part.numA = Number.MAX_VALUE;
129 return part;
130 }
131
132 let matches = s.match(/(\d*)(\D*)(\d*)(.*)/);
133 part.numA = parseInt(matches[1], 10) || part.numA;
134 part.strB = matches[2] || part.strB;
135 part.numC = parseInt(matches[3], 10) || part.numC;
136 part.extraD = matches[4] || part.extraD;
137
138 if (part.strB == "+")
139 {
140 part.numA++;
141 part.strB = "pre";
142 }
143
120 return part; 144 return part;
121 } 145 }
122 146
123 var matches = s.match(/(\d*)(\D*)(\d*)(.*)/); 147 function comparePartElement(s1, s2)
124 part.numA = parseInt(matches[1], 10) || part.numA; 148 {
125 part.strB = matches[2] || part.strB; 149 if (s1 === "" && s2 !== "")
126 part.numC = parseInt(matches[3], 10) || part.numC; 150 return 1;
127 part.extraD = matches[4] || part.extraD; 151 if (s1 !== "" && s2 === "")
128 152 return -1;
129 if (part.strB == "+") 153 return s1 === s2 ? 0 : (s1 > s2 ? 1 : -1);
130 { 154 }
131 part.numA++; 155
132 part.strB = "pre"; 156 function compareParts(p1, p2)
133 } 157 {
134 158 let result = 0;
135 return part; 159 let elements = ["numA", "strB", "numC", "extraD"];
136 } 160 elements.some(element =>
137 161 {
138 function comparePartElement(s1, s2) 162 result = comparePartElement(p1[element], p2[element]);
139 { 163 return result;
140 if (s1 === "" && s2 !== "") 164 });
141 return 1;
142 if (s1 !== "" && s2 === "")
143 return -1;
144 return s1 === s2 ? 0 : (s1 > s2 ? 1 : -1);
145 }
146
147 function compareParts(p1, p2)
148 {
149 var result = 0;
150 var elements = ["numA", "strB", "numC", "extraD"];
151 elements.some(function(element)
152 {
153 result = comparePartElement(p1[element], p2[element]);
154 return result; 165 return result;
155 }); 166 }
156 return result; 167
157 } 168 let parts1 = v1.split(".");
158 169 let parts2 = v2.split(".");
159 var parts1 = v1.split("."); 170 for (let i = 0; i < Math.max(parts1.length, parts2.length); i++)
160 var parts2 = v2.split("."); 171 {
161 for (var i = 0; i < Math.max(parts1.length, parts2.length); i++) 172 let result = compareParts(parsePart(parts1[i]), parsePart(parts2[i]));
162 { 173 if (result)
163 var result = compareParts(parsePart(parts1[i]), parsePart(parts2[i])); 174 return result;
164 if (result) 175 }
165 return result; 176 return 0;
166 } 177 }
167 return 0;
168 } 178 }
169 } 179 });
170 });
171 180
172 function FakeTimer() 181 function FakeTimer()
173 { 182 {
174 } 183 }
175 FakeTimer.prototype = 184 FakeTimer.prototype =
176 { 185 {
177 delay: 0, 186 delay: 0,
178 callback: null, 187 callback: null,
179 initWithCallback: function(callback, delay) 188 initWithCallback(callback, delay)
180 { 189 {
181 this.callback = callback; 190 this.callback = callback;
182 this.delay = delay; 191 this.delay = delay;
183 this.scheduleTimeout(); 192 this.scheduleTimeout();
184 }, 193 },
185 scheduleTimeout: function() 194 scheduleTimeout()
186 { 195 {
187 var me = this; 196 setTimeout(() =>
188 setTimeout(function()
189 { 197 {
190 try 198 try
191 { 199 {
192 me.callback(); 200 this.callback();
193 } 201 }
194 catch(e) 202 catch (e)
195 { 203 {
196 Cu.reportError(e); 204 Cu.reportError(e);
197 } 205 }
198 me.scheduleTimeout(); 206 this.scheduleTimeout();
199 }, this.delay); 207 }, this.delay);
200 } 208 }
201 }; 209 };
202 210
203 // 211 //
204 // Fake XMLHttpRequest implementation 212 // Fake XMLHttpRequest implementation
205 // 213 //
206 214
207 function XMLHttpRequest() 215 function XMLHttpRequest()
208 { 216 {
209 this._requestHeaders = {}; 217 this._requestHeaders = {};
210 this._loadHandlers = []; 218 this._loadHandlers = [];
211 this._errorHandlers = []; 219 this._errorHandlers = [];
212 }; 220 }
213 XMLHttpRequest.prototype = 221 XMLHttpRequest.prototype =
214 { 222 {
215 _url: null, 223 _url: null,
216 _requestHeaders: null, 224 _requestHeaders: null,
217 _responseHeaders: null, 225 _responseHeaders: null,
218 _loadHandlers: null, 226 _loadHandlers: null,
219 _errorHandlers: null, 227 _errorHandlers: null,
220 onload: null, 228 onload: null,
221 onerror: null, 229 onerror: null,
222 status: 0, 230 status: 0,
(...skipping 14 matching lines...) Expand all
237 "dnt": true, 245 "dnt": true,
238 "expect": true, 246 "expect": true,
239 "host": true, 247 "host": true,
240 "keep-alive": true, 248 "keep-alive": true,
241 "origin": true, 249 "origin": true,
242 "referer": true, 250 "referer": true,
243 "te": true, 251 "te": true,
244 "trailer": true, 252 "trailer": true,
245 "transfer-encoding": true, 253 "transfer-encoding": true,
246 "upgrade": true, 254 "upgrade": true,
247 "via": true, 255 "via": true
248 }, 256 },
249 _forbiddenRequestHeadersRe: new RegExp("^(Proxy|Sec)-", "i"), 257 _forbiddenRequestHeadersRe: new RegExp("^(Proxy|Sec)-", "i"),
250 258
251 _isRequestHeaderAllowed: function(header) 259 _isRequestHeaderAllowed(header)
252 { 260 {
253 if (this._forbiddenRequestHeaders.hasOwnProperty(header.toLowerCase())) 261 if (this._forbiddenRequestHeaders.hasOwnProperty(header.toLowerCase()))
254 return false; 262 return false;
255 if (header.match(this._forbiddenRequestHeadersRe)) 263 if (header.match(this._forbiddenRequestHeadersRe))
256 return false; 264 return false;
257 265
258 return true; 266 return true;
259 }, 267 },
260 268
261 addEventListener: function(eventName, handler, capture) 269 addEventListener(eventName, handler, capture)
262 { 270 {
263 var list; 271 let list;
264 if (eventName == "load") 272 if (eventName == "load")
265 list = this._loadHandlers; 273 list = this._loadHandlers;
266 else if (eventName == "error") 274 else if (eventName == "error")
267 list = this._errorHandlers; 275 list = this._errorHandlers;
268 else 276 else
269 throw new Error("Event type " + eventName + " not supported"); 277 throw new Error("Event type " + eventName + " not supported");
270 278
271 if (list.indexOf(handler) < 0) 279 if (list.indexOf(handler) < 0)
272 list.push(handler); 280 list.push(handler);
273 }, 281 },
274 282
275 removeEventListener: function(eventName, handler, capture) 283 removeEventListener(eventName, handler, capture)
276 { 284 {
277 var list; 285 let list;
278 if (eventName == "load") 286 if (eventName == "load")
279 list = this._loadHandlers; 287 list = this._loadHandlers;
280 else if (eventName == "error") 288 else if (eventName == "error")
281 list = this._errorHandlers; 289 list = this._errorHandlers;
282 else 290 else
283 throw new Error("Event type " + eventName + " not supported"); 291 throw new Error("Event type " + eventName + " not supported");
284 292
285 var index = list.indexOf(handler); 293 let index = list.indexOf(handler);
286 if (index >= 0) 294 if (index >= 0)
287 list.splice(index, 1); 295 list.splice(index, 1);
288 }, 296 },
289 297
290 open: function(method, url, async, user, password) 298 open(method, url, async, user, password)
291 { 299 {
292 if (method != "GET") 300 if (method != "GET")
293 throw new Error("Only GET requests are currently supported"); 301 throw new Error("Only GET requests are currently supported");
294 if (typeof async != "undefined" && !async) 302 if (typeof async != "undefined" && !async)
295 throw new Error("Sync requests are not supported"); 303 throw new Error("Sync requests are not supported");
296 if (typeof user != "undefined" || typeof password != "undefined") 304 if (typeof user != "undefined" || typeof password != "undefined")
297 throw new Error("User authentification is not supported"); 305 throw new Error("User authentification is not supported");
298 if (this.readyState != 0) 306 if (this.readyState != 0)
299 throw new Error("Already opened"); 307 throw new Error("Already opened");
300 308
301 this.readyState = 1; 309 this.readyState = 1;
302 this._url = url; 310 this._url = url;
303 }, 311 },
304 312
305 send: function(data) 313 send(data)
306 { 314 {
307 if (this.readyState != 1) 315 if (this.readyState != 1)
308 throw new Error("XMLHttpRequest.send() is being called before XMLHttpReque st.open()"); 316 throw new Error(
317 "XMLHttpRequest.send() is being called before XMLHttpRequest.open()");
309 if (typeof data != "undefined" && data) 318 if (typeof data != "undefined" && data)
310 throw new Error("Sending data to server is not supported"); 319 throw new Error("Sending data to server is not supported");
311 320
312 this.readyState = 3; 321 this.readyState = 3;
313 322
314 var onGetDone = function(result) 323 let onGetDone = function(result)
315 { 324 {
316 this.channel.status = result.status; 325 this.channel.status = result.status;
317 this.status = result.responseStatus; 326 this.status = result.responseStatus;
318 this.responseText = result.responseText; 327 this.responseText = result.responseText;
319 this._responseHeaders = result.responseHeaders; 328 this._responseHeaders = result.responseHeaders;
320 this.readyState = 4; 329 this.readyState = 4;
321 330
322 // Notify event listeners 331 // Notify event listeners
323 const NS_OK = 0; 332 const NS_OK = 0;
324 var eventName = (this.channel.status == NS_OK ? "load" : "error"); 333 let eventName = (this.channel.status == NS_OK ? "load" : "error");
325 var event = {type: eventName}; 334 let event = {type: eventName};
326 335
327 if (this["on" + eventName]) 336 if (this["on" + eventName])
328 this["on" + eventName].call(this, event); 337 this["on" + eventName].call(this, event);
329 338
330 var list = this["_" + eventName + "Handlers"]; 339 let list = this["_" + eventName + "Handlers"];
331 for (var i = 0; i < list.length; i++) 340 for (let i = 0; i < list.length; i++)
332 list[i].call(this, event); 341 list[i].call(this, event);
333 }.bind(this); 342 }.bind(this);
sergei 2017/09/18 07:59:05 Could you also turn this function into the arrow f
hub 2017/09/18 12:43:05 Done.
334 // HACK (#5066): the code checking whether the connection is allowed is temp orary, 343 // HACK (#5066): the code checking whether the connection is
335 // the actual check should be in the core when we make a decision whether 344 // allowed is temporary, the actual check should be in the core
336 // to update a subscription with current connection or not, thus whether to 345 // when we make a decision whether to update a subscription with
337 // even construct XMLHttpRequest object or not. 346 // current connection or not, thus whether to even construct
338 _isSubscriptionDownloadAllowed(function(isAllowed) 347 // XMLHttpRequest object or not.
348 _isSubscriptionDownloadAllowed(isAllowed =>
339 { 349 {
340 if (!isAllowed) 350 if (!isAllowed)
341 { 351 {
342 onGetDone({ 352 onGetDone({
343 status: 0x804b000d, //NS_ERROR_CONNECTION_REFUSED; 353 status: 0x804b000d, // NS_ERROR_CONNECTION_REFUSED;
344 responseStatus: 0 354 responseStatus: 0
345 }); 355 });
346 return; 356 return;
347 } 357 }
348 window._webRequest.GET(this._url, this._requestHeaders, onGetDone); 358 window._webRequest.GET(this._url, this._requestHeaders, onGetDone);
349 }.bind(this)); 359 });
350 }, 360 },
351 361
352 overrideMimeType: function(mime) 362 overrideMimeType(mime)
353 { 363 {
354 }, 364 },
355 365
356 setRequestHeader: function(name, value) 366 setRequestHeader(name, value)
357 { 367 {
358 if (this.readyState > 1) 368 if (this.readyState > 1)
359 throw new Error("Cannot set request header after sending"); 369 throw new Error("Cannot set request header after sending");
360 370
361 if (this._isRequestHeaderAllowed(name)) 371 if (this._isRequestHeaderAllowed(name))
362 this._requestHeaders[name] = value; 372 this._requestHeaders[name] = value;
363 else 373 else
364 console.warn("Attempt to set a forbidden header was denied: " + name); 374 console.warn("Attempt to set a forbidden header was denied: " + name);
365 }, 375 },
366 376
367 getResponseHeader: function(name) 377 getResponseHeader(name)
368 { 378 {
369 name = name.toLowerCase(); 379 name = name.toLowerCase();
370 if (!this._responseHeaders || !this._responseHeaders.hasOwnProperty(name)) 380 if (!this._responseHeaders || !this._responseHeaders.hasOwnProperty(name))
371 return null; 381 return null;
372 else 382 return this._responseHeaders[name];
373 return this._responseHeaders[name];
374 }, 383 },
375 384
376 channel: 385 channel:
377 { 386 {
378 status: -1, 387 status: -1,
379 notificationCallbacks: {}, 388 notificationCallbacks: {},
380 loadFlags: 0, 389 loadFlags: 0,
381 INHIBIT_CACHING: 0, 390 INHIBIT_CACHING: 0,
382 VALIDATE_ALWAYS: 0, 391 VALIDATE_ALWAYS: 0,
383 QueryInterface: function() 392 QueryInterface()
384 { 393 {
385 return this; 394 return this;
386 } 395 }
387 } 396 }
388 }; 397 };
389 398
390 function _isSubscriptionDownloadAllowed(callback) { 399 function _isSubscriptionDownloadAllowed(callback)
400 {
391 // It's a bit hacky, JsEngine interface which is used by FilterEngine does 401 // It's a bit hacky, JsEngine interface which is used by FilterEngine does
392 // not allow to inject an arbitrary callback, so we use triggerEvent 402 // not allow to inject an arbitrary callback, so we use triggerEvent
393 // mechanism. 403 // mechanism.
394 // Yet one hack (#5039). 404 // Yet one hack (#5039).
395 var allowed_connection_type = require("prefs").Prefs.allowed_connection_type; 405 let allowedConnectionType = require("prefs").Prefs.allowed_connection_type;
396 if (allowed_connection_type == "") 406 if (allowedConnectionType == "")
397 allowed_connection_type = null; 407 allowedConnectionType = null;
398 _triggerEvent("_isSubscriptionDownloadAllowed", allowed_connection_type, callb ack); 408 _triggerEvent("_isSubscriptionDownloadAllowed", allowedConnectionType,
409 callback);
399 } 410 }
400 411
401 // Polyfill Array.prototype.find 412 // Polyfill Array.prototype.find
402 // from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Ob jects/Array/find 413 // from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Ob jects/Array/find
403 // https://tc39.github.io/ecma262/#sec-array.prototype.find 414 // https://tc39.github.io/ecma262/#sec-array.prototype.find
404 if (!Array.prototype.find) { 415 if (!Array.prototype.find)
sergei 2017/09/18 07:59:05 Is it possible to remove this polyfill? We are alr
hub 2017/09/18 12:43:05 Done.
405 Object.defineProperty(Array.prototype, 'find', { 416 {
406 value: function (predicate) { 417 Object.defineProperty(Array.prototype, "find",
407 // 1. Let O be ? ToObject(this value). 418 {
408 if (this == null) { 419 value(predicate, ...args)
409 throw new TypeError('"this" is null or not defined'); 420 {
421 // 1. Let O be ? ToObject(this value).
422 if (this == null)
423 {
424 throw new TypeError("\"this\" is null or not defined");
425 }
426
427 let o = Object(this);
428
429 // 2. Let len be ? ToLength(? Get(O, "length")).
430 let len = o.length >>> 0;
431
432 // 3. If IsCallable(predicate) is false, throw a TypeError exception.
433 if (typeof predicate !== "function")
434 {
435 throw new TypeError("predicate must be a function");
436 }
437
438 // 4. If thisArg was supplied, let T be thisArg; else
439 // let T be undefined.
440 let thisArg = args[0];
441
442 // 5. Let k be 0.
443 let k = 0;
444
445 // 6. Repeat, while k < len
446 while (k < len)
447 {
448 // a. Let Pk be ! ToString(k).
449 // b. Let kValue be ? Get(O, Pk).
450 // c. Let testResult be ToBoolean(? Call(predicate, T, "kValue,
451 // k, O")).
452 // d. If testResult is true, return kValue.
453 let kValue = o[k];
454 if (predicate.call(thisArg, kValue, k, o))
455 {
456 return kValue;
457 }
458 // e. Increase k by 1.
459 k++;
460 }
410 } 461 }
411 462 });
412 var o = Object(this);
413
414 // 2. Let len be ? ToLength(? Get(O, "length")).
415 var len = o.length >>> 0;
416
417 // 3. If IsCallable(predicate) is false, throw a TypeError exception.
418 if (typeof predicate !== 'function') {
419 throw new TypeError('predicate must be a function');
420 }
421
422 // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
423 var thisArg = arguments[1];
424
425 // 5. Let k be 0.
426 var k = 0;
427
428 // 6. Repeat, while k < len
429 while (k < len) {
430 // a. Let Pk be ! ToString(k).
431 // b. Let kValue be ? Get(O, Pk).
432 // c. Let testResult be ToBoolean(? Call(predicate, T, "kValue, k, O")).
433 // d. If testResult is true, return kValue.
434 var kValue = o[k];
435 if (predicate.call(thisArg, kValue, k, o)) {
436 return kValue;
437 }
438 // e. Increase k by 1.
439 k++;
440 }
441 }
442 });
443 } 463 }
OLDNEW

Powered by Google App Engine
This is Rietveld