diff options
| -rw-r--r-- | background_scripts/completion.coffee | 15 | ||||
| -rw-r--r-- | tests/unit_tests/completion_test.coffee | 25 |
2 files changed, 35 insertions, 5 deletions
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee index 9e12d497..9314d9be 100644 --- a/background_scripts/completion.coffee +++ b/background_scripts/completion.coffee @@ -307,12 +307,16 @@ RegexpCache = clear: -> @cache = {} - get: (string) -> + # Get rexexp for string from cache, creating the regexp if necessary. + # Regexp meta-characters in string are escaped. + # Regexp is wrapped in prefix/suffix, which may contain meta-characters. + get: (string, prefix="", suffix="") -> @init() unless @initialized - @cache[string] ||= @escapeRegexp(string) - - # Creates a Regexp from the given string, with all special Regexp characters escaped. - escapeRegexp: (string) -> new RegExp(string.replace(@escapeRegExp, "\\$&"), "i") + regexpString = string.replace(@escapeRegExp, "\\$&") + # Avoid cost of constructing new strings if prefix/suffix are empty (which is expected to be a common case). + regexpString = prefix + regexpString if prefix + regexpString = regexpString + suffix if suffix + @cache[regexpString] ||= new RegExp(regexpString, "i") # Provides cached access to Chrome's history. As the user browses to new pages, we add those pages to this # history cache. @@ -382,3 +386,4 @@ root.DomainCompleter = DomainCompleter root.TabCompleter = TabCompleter root.HistoryCache = HistoryCache root.RankingUtils = RankingUtils +root.RegexpCache = RegexpCache diff --git a/tests/unit_tests/completion_test.coffee b/tests/unit_tests/completion_test.coffee index 32b62a28..f978c57b 100644 --- a/tests/unit_tests/completion_test.coffee +++ b/tests/unit_tests/completion_test.coffee @@ -174,6 +174,31 @@ context "RankingUtils", should "every term must match at least one thing (not matching)", -> assert.isTrue not RankingUtils.matches(["cat", "dog", "wolf"], "catapult", "hound dog") +context "RegexpCache", + should "RegexpCache is in fact caching (positive case)", -> + assert.isTrue RegexpCache.get("this") is RegexpCache.get("this") + + should "RegexpCache is in fact caching (negative case)", -> + assert.isTrue RegexpCache.get("this") isnt RegexpCache.get("that") + + should "RegexpCache prefix/suffix wrapping is working (positive case)", -> + assert.isTrue RegexpCache.get("this", "(", ")") is RegexpCache.get("this", "(", ")") + + should "RegexpCache prefix/suffix wrapping is working (negative case)", -> + assert.isTrue RegexpCache.get("this", "(", ")") isnt RegexpCache.get("this") + + should "search for a string", -> + assert.isTrue "hound dog".search(RegexpCache.get("dog")) == 6 + + should "search for a string which isn't there", -> + assert.isTrue "hound dog".search(RegexpCache.get("cat")) == -1 + + should "search for a string with a prefix/suffix (positive case)", -> + assert.isTrue "hound dog".search(RegexpCache.get("dog", "\\b", "\\b")) == 6 + + should "search for a string with a prefix/suffix (negative case)", -> + assert.isTrue "hound dog".search(RegexpCache.get("do", "\\b", "\\b")) == -1 + # A convenience wrapper around completer.filter() so it can be called synchronously in tests. filterCompleter = (completer, queryTerms) -> results = [] |
