 Issue 29336525:
  Issue 3584 - Work around WebKit uppercase ID matching bug  (Closed)
    
  
    Issue 29336525:
  Issue 3584 - Work around WebKit uppercase ID matching bug  (Closed) 
  | Index: abp2blocklist.js | 
| diff --git a/abp2blocklist.js b/abp2blocklist.js | 
| index 71d227f3e66f9a9f9c044409840967523982d923..01f21bf132717872dc7c71ea7485ce711e694641 100644 | 
| --- a/abp2blocklist.js | 
| +++ b/abp2blocklist.js | 
| @@ -254,6 +254,62 @@ function hasNonASCI(obj) | 
| return false; | 
| } | 
| +function attributeSyntaxForIDs(selector) | 
| 
Sebastian Noack
2016/02/17 14:40:59
Perhaps a better name for this function: convertID
 
kzar
2016/02/17 15:13:52
Done.
 | 
| +{ | 
| + if (selector.indexOf("#") == -1) | 
| 
Sebastian Noack
2016/02/17 14:22:19
Does this optimization has any measurable impact o
 
kzar
2016/02/17 15:13:52
No, removed.
 | 
| + return selector; | 
| + | 
| + // First we figure out where all the IDs are | 
| + let sep = ""; | 
| + let IDstart = null; | 
| 
Sebastian Noack
2016/02/17 14:40:59
Nit: Since we only have one kind of start value an
 
kzar
2016/02/17 15:13:52
Done.
 | 
| + let IDpositions = []; | 
| + for (let i = 0; i < selector.length; i++) | 
| + { | 
| + let chr = selector[i]; | 
| + | 
| + if (chr == "\\") // ignore escaped characters | 
| + i++; | 
| + else if (chr == sep) // don't split within quoted text | 
| + sep = ""; // e.g. [attr=","] | 
| + else if (sep == "") | 
| + { | 
| + if (chr == '"' || chr == "'") | 
| + sep = chr; | 
| + else if (IDstart == null) // look for the start of an ID | 
| + { | 
| + if (chr == "#") | 
| + IDstart = i; | 
| + } | 
| + else if (chr < "0" && chr != "-" || | 
| + chr > "9" && chr < "A" || | 
| + chr > "Z" && chr != "_" && chr < "a" || | 
| + chr > "z" && chr < "\x80") // look for the end of the ID | 
| + { | 
| + IDpositions.push({start: IDstart, end: i}); | 
| 
Sebastian Noack
2016/02/17 14:22:19
I wonder we should do the replace inline:
selecto
 
Sebastian Noack
2016/02/17 14:41:00
Here is an example how that could look like:
  fu
 
kzar
2016/02/17 15:13:52
Mind if I leave this as is? It works fine and I fi
 | 
| + IDstart = null; | 
| + } | 
| + } | 
| + } | 
| + if (IDstart != null) | 
| + IDpositions.push({start: IDstart, end: selector.length}); | 
| + | 
| + if (IDpositions.length == 0) | 
| 
Sebastian Noack
2016/02/17 14:22:20
Does this optimization has any measurable impact o
 
kzar
2016/02/17 15:13:52
No, removed.
 | 
| + return selector; | 
| + | 
| + // Now replace them all with the [id="someID"] form | 
| + let newSelector = ""; | 
| + let position = 0; | 
| + for (let ID of IDpositions) | 
| + { | 
| + newSelector += selector.substring(position, ID.start); | 
| + newSelector += '[id="' + selector.substring(ID.start + 1, ID.end) + '"]'; | 
| 
Sebastian Noack
2016/02/17 14:22:19
The quotes are actually redundant, as we copy an u
 
kzar
2016/02/17 15:13:52
Acknowledged.
 | 
| + position = ID.end; | 
| + } | 
| + newSelector += selector.substring(position); | 
| + | 
| + return newSelector; | 
| +} | 
| + | 
| function logRules() | 
| { | 
| let rules = []; | 
| @@ -286,10 +342,16 @@ function logRules() | 
| { | 
| while (selectors.length) | 
| { | 
| + let selector = selectors.splice(0, selectorLimit).join(", "); | 
| + | 
| + // As of Safari 9.0 element IDs are matched as lowercase. We work around | 
| + // this by converting to the attribute format [id="elementID"] | 
| + selector = attributeSyntaxForIDs(selector); | 
| + | 
| addRule({ | 
| trigger: {"url-filter": matchDomain}, | 
| action: {type: "css-display-none", | 
| - selector: selectors.splice(0, selectorLimit).join(", ")} | 
| + selector: selector} | 
| }); | 
| } | 
| }); |