From 9beb729d9ff106359a26d1fb41f4e349a013d711 Mon Sep 17 00:00:00 2001 From: Anthony Lieuallen Date: Sat, 3 Apr 2010 02:21:16 +0800 Subject: [PATCH] Fixes #1089 * Define a general purpose memoize decorator, use it for GM_isGreasemonkeyable() and convert2RegExp(). --- content/convert2RegExp.js | 1 + content/utils.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/content/convert2RegExp.js b/content/convert2RegExp.js index 4fae6d263..13bf0939a 100644 --- a/content/convert2RegExp.js +++ b/content/convert2RegExp.js @@ -50,3 +50,4 @@ function convert2RegExp( pattern ) { } return new RegExp(res + "$", "i"); } +convert2RegExp = GM_memoize(convert2RegExp); diff --git a/content/utils.js b/content/utils.js index 0e8c2c557..acbeda744 100644 --- a/content/utils.js +++ b/content/utils.js @@ -326,6 +326,7 @@ function GM_isGreasemonkeyable(url) { return false; } +GM_isGreasemonkeyable = GM_memoize(GM_isGreasemonkeyable); function GM_getEnabled() { return GM_prefRoot.getValue("enabled", true); @@ -334,3 +335,30 @@ function GM_getEnabled() { function GM_setEnabled(enabled) { GM_prefRoot.setValue("enabled", enabled); } + +// Decorate a function with a memoization wrapper, with a limited-size cache +// to reduce peak memory utilization. Simple usage: +// +// function foo(arg1, arg2) { /* complex operation */ } +// foo = GM_memoize(foo); +// +// The memoized function may have any number of arguments, but they must be +// primitives (able to be used as object keys). +function GM_memoize(func, limit) { + limit = limit || 1000; + var cache = {}; + var keylist = []; + + return function(a) { + var args = Array.prototype.slice.call(arguments); + if (args in cache) return cache[args]; + + var result = func.apply(null, args); + + cache[args] = result; + keylist.push(args); + while (keylist.length > limit) keylist.shift(); + + return result; + } +}