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

Side by Side Diff: chrome/content/elemHideEmulation.js

Issue 29464703: Issue 5313 - Make error reporting more robust. (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Also fixed a comment about parseSelector() that was wrong. Created June 14, 2017, 2:52 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 | no next file » | 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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 if (parens == 0) 123 if (parens == 0)
124 break; 124 break;
125 } 125 }
126 } 126 }
127 127
128 if (parens > 0) 128 if (parens > 0)
129 return null; 129 return null;
130 return {text: content.substring(startIndex, i), end: i}; 130 return {text: content.substring(startIndex, i), end: i};
131 } 131 }
132 132
133 /** Parse the selector
134 * @param {string} selector the selector to parse
135 * @return {Object} selectors is an array of objects,
136 * or null in case of errors. hide is true if we'll hide
137 * elements instead of styles..
138 */
139 function parseSelector(selector)
140 {
141 if (selector.length == 0)
142 return [];
143
144 let match = abpSelectorRegexp.exec(selector);
145 if (!match)
146 return [new PlainSelector(selector)];
147
148 let selectors = [];
149 if (match.index > 0)
150 selectors.push(new PlainSelector(selector.substr(0, match.index)));
151
152 let startIndex = match.index + match[0].length;
153 let content = parseSelectorContent(selector, startIndex);
154 if (!content)
155 {
156 reportError(new SyntaxError("Failed to parse Adblock Plus " +
157 `selector ${selector}, ` +
158 "due to unmatched parentheses."));
159 return null;
160 }
161 if (match[1] == "properties")
162 selectors.push(new PropsSelector(content.text));
163 else if (match[1] == "has")
164 {
165 let hasSelector = new HasSelector(content.text);
166 if (!hasSelector.valid())
167 return null;
168 selectors.push(hasSelector);
169 }
170 else
171 {
172 // this is an error, can't parse selector.
173 reportError(new SyntaxError("Failed to parse Adblock Plus " +
174 `selector ${selector}, invalid ` +
175 `pseudo-class :-abp-${match[1]}().`));
176 return null;
177 }
178
179 let suffix = parseSelector(selector.substr(content.end + 1));
180 if (suffix == null)
181 return null;
182
183 selectors.push(...suffix);
184
185 return selectors;
186 }
187
188 /** Stringified style objects 133 /** Stringified style objects
189 * @typedef {Object} StringifiedStyle 134 * @typedef {Object} StringifiedStyle
190 * @property {string} style CSS style represented by a string. 135 * @property {string} style CSS style represented by a string.
191 * @property {string[]} subSelectors selectors the CSS properties apply to. 136 * @property {string[]} subSelectors selectors the CSS properties apply to.
192 */ 137 */
193 138
194 /** 139 /**
195 * Produce a string representation of the stylesheet entry. 140 * Produce a string representation of the stylesheet entry.
196 * @param {CSSStyleRule} rule the CSS style rule. 141 * @param {CSSStyleRule} rule the CSS style rule.
197 * @return {StringifiedStyle} the stringified style. 142 * @return {StringifiedStyle} the stringified style.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 * @param {StringifiedStyle[]} styles the stringified style objects. 184 * @param {StringifiedStyle[]} styles the stringified style objects.
240 */ 185 */
241 *getSelectors(prefix, subtree, styles) 186 *getSelectors(prefix, subtree, styles)
242 { 187 {
243 yield [prefix + this._selector, subtree]; 188 yield [prefix + this._selector, subtree];
244 } 189 }
245 }; 190 };
246 191
247 const incompletePrefixRegexp = /[\s>+~]$/; 192 const incompletePrefixRegexp = /[\s>+~]$/;
248 193
249 function HasSelector(selector) 194 function HasSelector(selectors)
250 { 195 {
251 this._innerSelectors = parseSelector(selector); 196 this._innerSelectors = selectors;
252 } 197 }
253 198
254 HasSelector.prototype = { 199 HasSelector.prototype = {
255 requiresHiding: true, 200 requiresHiding: true,
256 201
257 valid()
258 {
259 return this._innerSelectors != null;
260 },
261
262 *getSelectors(prefix, subtree, styles) 202 *getSelectors(prefix, subtree, styles)
263 { 203 {
264 for (let element of this.getElements(prefix, subtree, styles)) 204 for (let element of this.getElements(prefix, subtree, styles))
265 yield [makeSelector(element, ""), element]; 205 yield [makeSelector(element, ""), element];
266 }, 206 },
267 207
268 /** 208 /**
269 * Generator function returning selected elements. 209 * Generator function returning selected elements.
270 * @param {string} prefix the prefix for the selector. 210 * @param {string} prefix the prefix for the selector.
271 * @param {Node} subtree the subtree we work on. 211 * @param {Node} subtree the subtree we work on.
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 { 277 {
338 return new URL(stylesheet.href).origin == this.window.location.origin; 278 return new URL(stylesheet.href).origin == this.window.location.origin;
339 } 279 }
340 catch (e) 280 catch (e)
341 { 281 {
342 // Invalid URL, assume that it is first-party. 282 // Invalid URL, assume that it is first-party.
343 return true; 283 return true;
344 } 284 }
345 }, 285 },
346 286
287 /** Parse the selector
288 * @param {string} selector the selector to parse
289 * @return {Array} selectors is an array of objects,
290 * or null in case of errors.
291 */
292 parseSelector(selector)
293 {
294 if (selector.length == 0)
295 return [];
296
297 let match = abpSelectorRegexp.exec(selector);
298 if (!match)
299 return [new PlainSelector(selector)];
300
301 let selectors = [];
302 if (match.index > 0)
303 selectors.push(new PlainSelector(selector.substr(0, match.index)));
304
305 let startIndex = match.index + match[0].length;
306 let content = parseSelectorContent(selector, startIndex);
307 if (!content)
308 {
309 this.window.console.error(
310 new SyntaxError("Failed to parse Adblock Plus " +
311 `selector ${selector}, ` +
Wladimir Palant 2017/06/19 11:22:37 Nit: There should be no comma here, I vaguely reme
hub 2017/06/19 13:24:42 Done.
312 "due to unmatched parentheses."));
313 return null;
314 }
315 if (match[1] == "properties")
316 selectors.push(new PropsSelector(content.text));
317 else if (match[1] == "has")
318 {
319 let hasSelectors = this.parseSelector(content.text);
320 if (hasSelectors == null)
321 return null;
322 let hasSelector = new HasSelector(hasSelectors);
323 selectors.push(hasSelector);
Wladimir Palant 2017/06/19 11:22:37 Nit: The temporary hasSelector variable no longer
hub 2017/06/19 13:24:42 Done.
324 }
325 else
326 {
327 // this is an error, can't parse selector.
328 this.window.console.error(
329 new SyntaxError("Failed to parse Adblock Plus " +
330 `selector ${selector}, invalid ` +
331 `pseudo-class :-abp-${match[1]}().`));
332 return null;
333 }
334
335 let suffix = this.parseSelector(selector.substr(content.end + 1));
336 if (suffix == null)
337 return null;
338
339 selectors.push(...suffix);
340
341 return selectors;
342 },
343
347 addSelectors(stylesheets) 344 addSelectors(stylesheets)
348 { 345 {
349 let selectors = []; 346 let selectors = [];
350 let selectorFilters = []; 347 let selectorFilters = [];
351 348
352 let elements = []; 349 let elements = [];
353 let elementFilters = []; 350 let elementFilters = [];
354 351
355 let cssStyles = []; 352 let cssStyles = [];
356 353
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 { 401 {
405 let stylesheet = event.target.sheet; 402 let stylesheet = event.target.sheet;
406 if (stylesheet) 403 if (stylesheet)
407 this.addSelectors([stylesheet]); 404 this.addSelectors([stylesheet]);
408 }, 405 },
409 406
410 apply() 407 apply()
411 { 408 {
412 this.getFiltersFunc(patterns => 409 this.getFiltersFunc(patterns =>
413 { 410 {
414 let oldReportError = reportError;
415 reportError = error => this.window.console.error(error);
416
417 this.patterns = []; 411 this.patterns = [];
418 for (let pattern of patterns) 412 for (let pattern of patterns)
419 { 413 {
420 let selectors = parseSelector(pattern.selector); 414 let selectors = this.parseSelector(pattern.selector);
421 if (selectors != null && selectors.length > 0) 415 if (selectors != null && selectors.length > 0)
422 this.patterns.push({selectors, text: pattern.text}); 416 this.patterns.push({selectors, text: pattern.text});
423 } 417 }
424 418
425 if (this.patterns.length > 0) 419 if (this.patterns.length > 0)
426 { 420 {
427 let {document} = this.window; 421 let {document} = this.window;
428 this.addSelectors(document.styleSheets); 422 this.addSelectors(document.styleSheets);
429 document.addEventListener("load", this.onLoad.bind(this), true); 423 document.addEventListener("load", this.onLoad.bind(this), true);
430 } 424 }
431 reportError = oldReportError;
432 }); 425 });
433 } 426 }
434 }; 427 };
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld