| Index: lib/matcher.js | 
| =================================================================== | 
| --- a/lib/matcher.js | 
| +++ b/lib/matcher.js | 
| @@ -105,35 +105,45 @@ | 
| } | 
| } | 
| /** | 
| * Removes a filter by a given keyword from a map. | 
| * @param {RegExpFilter} filter | 
| * @param {string} keyword | 
| * @param {Map.<string,(RegExpFilter|Set.<RegExpFilter>)>} map | 
| + * @returns {boolean} Whether the filter was removed. | 
| */ | 
| function removeFilterByKeyword(filter, keyword, map) | 
| { | 
| let set = map.get(keyword); | 
| if (typeof set == "undefined") | 
| - return; | 
| + return false; | 
| if (set.size == 1) | 
| { | 
| - if (filter == set) | 
| - map.delete(keyword); | 
| + if (filter != set) | 
| + return false; | 
| + | 
| + map.delete(keyword); | 
| } | 
| else | 
| { | 
| + let count = set.size; | 
| + | 
| set.delete(filter); | 
| + if (set.size == count) | 
| + return false; | 
| + | 
| if (set.size == 1) | 
| map.set(keyword, [...set][0]); | 
| } | 
| + | 
| + return true; | 
| } | 
| /** | 
| * Checks whether a particular filter is slow. | 
| * @param {RegExpFilter} filter | 
| * @returns {boolean} | 
| */ | 
| function isSlowFilter(filter) | 
| @@ -211,24 +221,50 @@ | 
| } | 
| /** | 
| * Removes a filter from the matcher | 
| * @param {RegExpFilter} filter | 
| */ | 
| remove(filter) | 
| { | 
| - let keyword = this.findKeyword(filter); | 
| + let keyword = null; | 
| + let candidates = null; | 
| + | 
| + let {pattern} = filter; | 
| + if (pattern == null) | 
| + { | 
| + candidates = [""]; | 
| + } | 
| + else | 
| + { | 
| + candidates = pattern.toLowerCase().match(allKeywordsRegExp); | 
| + if (!candidates) | 
| + candidates = [""]; | 
| + } | 
| + | 
| let locationOnly = filter.isLocationOnly(); | 
| - removeFilterByKeyword(filter, keyword, | 
| - locationOnly ? this._simpleFiltersByKeyword : | 
| - this._complexFiltersByKeyword); | 
| + // The keyword used to add a filter depends on the current list of filters | 
| + // at the time of addition. At this point we don't know what keyword was | 
| + // used to add the filter. We must try all the candidates. | 
| + for (let candidate of candidates) | 
| + { | 
| + candidate = candidate.substring(1); | 
| - if (locationOnly) | 
| + if (removeFilterByKeyword(filter, candidate, | 
| + locationOnly ? this._simpleFiltersByKeyword : | 
| + this._complexFiltersByKeyword)) | 
| + { | 
| + keyword = candidate; | 
| + break; | 
| + } | 
| + } | 
| + | 
| + if (locationOnly || keyword == null) | 
| return; | 
| for (let type of nonDefaultTypes(filter.contentType)) | 
| { | 
| let map = this._filterMapsByType.get(type); | 
| if (map) | 
| removeFilterByKeyword(filter, keyword, map); | 
| } |