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

Delta Between Two Patch Sets: lib/content/elemHideEmulation.js

Issue 29676761: Issue 6296 - Handle relative prefix in :-abp-has() (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Left Patch Set: Created Jan. 22, 2018, 9:20 p.m.
Right Patch Set: No longer use regexp for relative selector. Created Jan. 30, 2018, 4:03 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | test/browser/elemHideEmulation.js » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 let priority = rule.style.getPropertyPriority(property); 115 let priority = rule.style.getPropertyPriority(property);
116 styles.push(`${property}: ${value}${priority ? " !" + priority : ""};`); 116 styles.push(`${property}: ${value}${priority ? " !" + priority : ""};`);
117 } 117 }
118 styles.sort(); 118 styles.sort();
119 return { 119 return {
120 style: styles.join(" "), 120 style: styles.join(" "),
121 subSelectors: splitSelector(rule.selectorText) 121 subSelectors: splitSelector(rule.selectorText)
122 }; 122 };
123 } 123 }
124 124
125 let scopeSupported = null;
126
127 function tryQuerySelector(subtree, selector, all)
128 {
129 let elements = null;
130 try
131 {
132 elements = all ? subtree.querySelectorAll(selector) :
133 subtree.querySelector(selector);
134 scopeSupported = true;
135 }
136 catch (e)
137 {
138 // Edge doesn't support ":scope"
139 scopeSupported = false;
140 }
141 return elements;
142 }
143
144 /**
145 * Query selector. If it is relative, will try :scope.
146 * @param {Node} subtree the element to query selector
147 * @param {string} selector the selector to query
148 * @param {bool} [all=false] true to perform querySelectorAll()
149 * @returns {?(Node|NodeList)} result of the query. null in case of error.
150 */
151 function scopedQuerySelector(subtree, selector, all)
152 {
153 if (selector[0] == ">")
154 {
155 selector = ":scope" + selector;
156 if (scopeSupported)
157 {
158 return all ? subtree.querySelectorAll(selector) :
159 subtree.querySelector(selector);
160 }
161 if (scopeSupported == null)
162 return tryQuerySelector(subtree, selector, all);
163 return null;
164 }
165 return all ? subtree.querySelectorAll(selector) :
166 subtree.querySelector(selector);
167 }
168
169 function scopedQuerySelectorAll(subtree, selector)
170 {
171 return scopedQuerySelector(subtree, selector, true);
172 }
173
125 function* evaluate(chain, index, prefix, subtree, styles) 174 function* evaluate(chain, index, prefix, subtree, styles)
126 { 175 {
127 if (index >= chain.length) 176 if (index >= chain.length)
128 { 177 {
129 yield prefix; 178 yield prefix;
130 return; 179 return;
131 } 180 }
132 for (let [selector, element] of 181 for (let [selector, element] of
133 chain[index].getSelectors(prefix, subtree, styles)) 182 chain[index].getSelectors(prefix, subtree, styles))
134 { 183 {
(...skipping 20 matching lines...) Expand all
155 * @param {string} prefix the prefix for the selector. 204 * @param {string} prefix the prefix for the selector.
156 * @param {Node} subtree the subtree we work on. 205 * @param {Node} subtree the subtree we work on.
157 * @param {StringifiedStyle[]} styles the stringified style objects. 206 * @param {StringifiedStyle[]} styles the stringified style objects.
158 */ 207 */
159 *getSelectors(prefix, subtree, styles) 208 *getSelectors(prefix, subtree, styles)
160 { 209 {
161 yield [prefix + this._selector, subtree]; 210 yield [prefix + this._selector, subtree];
162 } 211 }
163 }; 212 };
164 213
165 const incompletePrefixRegexp = /[\s>+~]$/; 214 const incompletePrefixRegexp = /[\s>+~]$/;
lainverse 2018/01/30 18:07:28 Since that other regexp were replaced with string
Manish Jethani 2018/01/30 20:23:20 If we do this then I think that it should be a sep
166 const relativeSelectorRegexp = /^[>+~]/;
167 215
168 function HasSelector(selectors) 216 function HasSelector(selectors)
169 { 217 {
170 this._innerSelectors = selectors; 218 this._innerSelectors = selectors;
171 } 219 }
172 220
173 HasSelector.prototype = { 221 HasSelector.prototype = {
174 requiresHiding: true, 222 requiresHiding: true,
175 223
176 get dependsOnStyles() 224 get dependsOnStyles()
(...skipping 10 matching lines...) Expand all
187 /** 235 /**
188 * Generator function returning selected elements. 236 * Generator function returning selected elements.
189 * @param {string} prefix the prefix for the selector. 237 * @param {string} prefix the prefix for the selector.
190 * @param {Node} subtree the subtree we work on. 238 * @param {Node} subtree the subtree we work on.
191 * @param {StringifiedStyle[]} styles the stringified style objects. 239 * @param {StringifiedStyle[]} styles the stringified style objects.
192 */ 240 */
193 *getElements(prefix, subtree, styles) 241 *getElements(prefix, subtree, styles)
194 { 242 {
195 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? 243 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ?
196 prefix + "*" : prefix; 244 prefix + "*" : prefix;
197 if (relativeSelectorRegexp.test(actualPrefix)) 245 let elements = scopedQuerySelectorAll(subtree, actualPrefix);
Manish Jethani 2018/01/23 16:42:11 If I understand this correctly, "+" and "~" don't
hub 2018/01/25 21:58:34 Done.
198 actualPrefix = ":scope" + actualPrefix; 246 if (elements)
199 try 247 {
200 {
201 let elements = subtree.querySelectorAll(actualPrefix);
lainverse 2018/01/23 01:02:51 As I understand if this fails it's still possible
Manish Jethani 2018/01/23 16:42:11 I agree this could probably be made to work on Edg
hub 2018/01/23 16:51:11 Filed https://issues.adblockplus.org/ticket/6304
202 for (let element of elements) 248 for (let element of elements)
203 { 249 {
204 let iter = evaluate(this._innerSelectors, 0, "", element, styles); 250 let iter = evaluate(this._innerSelectors, 0, "", element, styles);
205 for (let selector of iter) 251 for (let selector of iter)
206 { 252 {
207 if (selector == null) 253 if (selector == null)
208 {
209 yield null; 254 yield null;
210 continue; 255 else if (scopedQuerySelector(element, selector))
211 } 256 yield element;
212 if (relativeSelectorRegexp.test(selector))
Manish Jethani 2018/01/23 16:42:11 So this and the try..catch could be made generic a
hub 2018/01/25 21:58:34 This should allow us to fix issue #6304 more easil
213 selector = ":scope" + selector;
214 try
215 {
216 if (element.querySelector(selector))
217 yield element;
218 }
219 catch (e)
220 {
221 // :scope isn't supported on Edge, ignore error caused by it.
222 }
223 } 257 }
224 yield null; 258 yield null;
225 } 259 }
226 } 260 }
227 catch (e)
228 {
229 // :scope isn't supported on Edge, ignore error caused by it.
230 }
231 } 261 }
232 }; 262 };
233 263
234 function ContainsSelector(textContent) 264 function ContainsSelector(textContent)
235 { 265 {
236 this._text = textContent; 266 this._text = textContent;
237 } 267 }
238 268
239 ContainsSelector.prototype = { 269 ContainsSelector.prototype = {
240 requiresHiding: true, 270 requiresHiding: true,
241 271
242 *getSelectors(prefix, subtree, stylesheet) 272 *getSelectors(prefix, subtree, stylesheet)
243 { 273 {
244 for (let element of this.getElements(prefix, subtree, stylesheet)) 274 for (let element of this.getElements(prefix, subtree, stylesheet))
245 yield [makeSelector(element, ""), subtree]; 275 yield [makeSelector(element, ""), subtree];
246 }, 276 },
247 277
248 *getElements(prefix, subtree, stylesheet) 278 *getElements(prefix, subtree, stylesheet)
249 { 279 {
250 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ? 280 let actualPrefix = (!prefix || incompletePrefixRegexp.test(prefix)) ?
251 prefix + "*" : prefix; 281 prefix + "*" : prefix;
252 if (relativeSelectorRegexp.test(actualPrefix)) 282
253 actualPrefix = ":scope" + actualPrefix; 283 let elements = scopedQuerySelectorAll(subtree, actualPrefix);
254 try 284 if (elements)
255 { 285 {
256 let elements = subtree.querySelectorAll(actualPrefix);
257
258 for (let element of elements) 286 for (let element of elements)
259 { 287 {
260 if (element.textContent.includes(this._text)) 288 if (element.textContent.includes(this._text))
261 yield element; 289 yield element;
262 else 290 else
263 yield null; 291 yield null;
264 } 292 }
265 }
266 catch (e)
267 {
268 // :scope isn't supported on Edge, ignore error caused by it.
269 } 293 }
270 } 294 }
271 }; 295 };
272 296
273 function PropsSelector(propertyExpression) 297 function PropsSelector(propertyExpression)
274 { 298 {
275 let regexpString; 299 let regexpString;
276 if (propertyExpression.length >= 2 && propertyExpression[0] == "/" && 300 if (propertyExpression.length >= 2 && propertyExpression[0] == "/" &&
277 propertyExpression[propertyExpression.length - 1] == "/") 301 propertyExpression[propertyExpression.length - 1] == "/")
278 { 302 {
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 characterData: true, 646 characterData: true,
623 subtree: true 647 subtree: true
624 } 648 }
625 ); 649 );
626 this.document.addEventListener("load", this.onLoad.bind(this), true); 650 this.document.addEventListener("load", this.onLoad.bind(this), true);
627 } 651 }
628 } 652 }
629 }; 653 };
630 654
631 exports.ElemHideEmulation = ElemHideEmulation; 655 exports.ElemHideEmulation = ElemHideEmulation;
LEFTRIGHT

Powered by Google App Engine
This is Rietveld