Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge with v0.2

  • Loading branch information...
commit f57bac383c79d011677bd030204f11969a43ec19 2 parents 83f31df + ec90653
Mariusz Nowak authored
3  CHANGES
... ...
@@ -1,3 +1,6 @@
  1
+v0.2.4  --  2013.03.23
  2
+* Throw on circular invocations, they cannot be memoized as intended.
  3
+
1 4
 v0.2.3  --  2012.10.04
2 5
 * Fixed serious bug related to not properly cleared cache when working in
3 6
   regular mode
9  lib/primitive.js
@@ -2,7 +2,8 @@
2 2
 
3 3
 'use strict';
4 4
 
5  
-var hasListeners = require('event-emitter/lib/has-listeners')
  5
+var CustomError  = require('es5-ext/lib/Error/custom')
  6
+  , hasListeners = require('event-emitter/lib/has-listeners')
6 7
 
7 8
   , getId0 = function () { return ''; }
8 9
   , getId1 = function (args) { return args[0]; }
@@ -49,6 +50,9 @@ module.exports = require('./_base')(function (conf, length) {
49 50
 			} else {
50 51
 				value = apply.call(fn, this, arguments);
51 52
 			}
  53
+			if (cache.hasOwnProperty(id)) {
  54
+				throw new CustomError("Circular invocation", 'CIRCULAR_INVOCATION');
  55
+			}
52 56
 			cache[id] = value;
53 57
 			initListeners && conf.emit('init', id);
54 58
 			return value;
@@ -60,6 +64,9 @@ module.exports = require('./_base')(function (conf, length) {
60 64
 			return cache[id];
61 65
 		} else {
62 66
 			value = apply.call(conf.fn, this, arguments);
  67
+			if (cache.hasOwnProperty(id)) {
  68
+				throw new CustomError("Circular invocation", 'CIRCULAR_INVOCATION');
  69
+			}
63 70
 			cache[id] = value;
64 71
 			initListeners && conf.emit('init', id);
65 72
 			return value;
49  lib/regular.js
@@ -2,11 +2,11 @@
2 2
 
3 3
 'use strict';
4 4
 
5  
-var indexOf      = require('es5-ext/lib/Array/prototype/e-index-of')
  5
+var CustomError  = require('es5-ext/lib/Error/custom')
  6
+  , indexOf      = require('es5-ext/lib/Array/prototype/e-index-of')
6 7
   , hasListeners = require('event-emitter/lib/has-listeners')
7 8
 
8  
-  , apply = Function.prototype.apply
9  
-  , getId0 = function () { return ''; };
  9
+  , apply = Function.prototype.apply;
10 10
 
11 11
 // Results are saved internally within array matrix:
12 12
 // [0] -> Result of calling function with no arguments
@@ -30,15 +30,22 @@ module.exports = require('./_base')(function (conf, length) {
30 30
 	  , cache = conf.cache = {}, argsCache;
31 31
 
32 32
 	if (length === 0) {
33  
-		get = set = clear = conf.get = getId0;
34  
-		conf.clearAll = function () { cache = conf.cache = {}; };
  33
+		map = null;
  34
+		get = conf.get = function () { return map; };
  35
+		set = function () { return ((map = 1)); };
  36
+		clear = function () { map = null; };
  37
+		conf.clearAll = function () {
  38
+			map = null;
  39
+			cache = conf.cache = {};
  40
+		};
35 41
 	} else {
36 42
 		count = 0;
37 43
 		if (length === 1) {
38 44
 			map1 = [];
39 45
 			map2 = [];
40 46
 			get = conf.get = function (args) {
41  
-				return map2[indexOf.call(map1, args[0])];
  47
+				var index = indexOf.call(map1, args[0]);
  48
+				return (index === -1) ? null : map2[index];
42 49
 			};
43 50
 			set = function (args) {
44 51
 				map1.push(args[0]);
@@ -63,23 +70,19 @@ module.exports = require('./_base')(function (conf, length) {
63 70
 			get = conf.get = function (args) {
64 71
 				var index = 0, set = map, i, length = args.length;
65 72
 				if (length === 0) {
66  
-					return set[length];
  73
+					return set[length] || null;
67 74
 				} else if ((set = set[length])) {
68 75
 					while (index < (length - 1)) {
69 76
 						i = indexOf.call(set[0], args[index]);
70  
-						if (i === -1) {
71  
-							return;
72  
-						}
  77
+						if (i === -1) return null;
73 78
 						set = set[1][i];
74 79
 						++index;
75 80
 					}
76 81
 					i = indexOf.call(set[0], args[index]);
77  
-					if (i === -1) {
78  
-						return;
79  
-					}
80  
-					return set[1][i];
  82
+					if (i === -1) return null;
  83
+					return set[1][i] || null;
81 84
 				}
82  
-				return;
  85
+				return null;
83 86
 			};
84 87
 			set = function (args) {
85 88
 				var index = 0, set = map, i, length = args.length;
@@ -151,17 +154,13 @@ module.exports = require('./_base')(function (conf, length) {
151 154
 				var index = 0, set = map, i;
152 155
 				while (index < (length - 1)) {
153 156
 					i = indexOf.call(set[0], args[index]);
154  
-					if (i === -1) {
155  
-						return null;
156  
-					}
  157
+					if (i === -1) return null;
157 158
 					set = set[1][i];
158 159
 					++index;
159 160
 				}
160 161
 				i = indexOf.call(set[0], args[index]);
161  
-				if (i === -1) {
162  
-					return null;
163  
-				}
164  
-				return set[1][i];
  162
+				if (i === -1) return null;
  163
+				return set[1][i] || null;
165 164
 			};
166 165
 			set = function (args) {
167 166
 				var index = 0, set = map, i;
@@ -217,11 +216,15 @@ module.exports = require('./_base')(function (conf, length) {
217 216
 	}
218 217
 	conf.memoized = function () {
219 218
 		var id = get(arguments), value;
220  
-		if (cache.hasOwnProperty(id)) {
  219
+		if (id != null) {
221 220
 			hitListeners && conf.emit('hit', id, arguments, this);
222 221
 			return cache[id];
223 222
 		} else {
224 223
 			value = apply.call(fn, this, arguments);
  224
+			id = get(arguments);
  225
+			if (id != null) {
  226
+				throw new CustomError("Circular invocation", 'CIRCULAR_INVOCATION');
  227
+			}
225 228
 			id = set(arguments);
226 229
 			cache[id] = value;
227 230
 			initListeners && conf.emit('init', id);
4  package.json
@@ -34,12 +34,12 @@
34 34
     "node": ">=0.4"
35 35
   },
36 36
   "dependencies": {
37  
-    "es5-ext": "0.9.x",
  37
+    "es5-ext": "~0.9.2",
38 38
     "event-emitter": "~0.2.1",
39 39
     "next-tick": "0.1.x"
40 40
   },
41 41
   "devDependencies": {
42  
-    "tad": "0.1.x"
  42
+    "tad": "~0.1.15"
43 43
   },
44 44
   "author": "Mariusz Nowak <medikoo+memoize@medikoo.com> (http://www.medikoo.com/)",
45 45
   "license": "MIT"
17  test/primitive.js
@@ -36,6 +36,23 @@ module.exports = function (t) {
36 36
 				'zeta');
37 37
 			a(mfn(y, 'bar', 'zeta'), 'foobarzeta', "#3");
38 38
 			a(i, 2, "Called twice");
  39
+		},
  40
+		"Circular": function (a) {
  41
+			var i = 0, fn;
  42
+			fn = t(function (x) {
  43
+				if (++i < 2) fn(x);
  44
+			});
  45
+			a.throws(function () {
  46
+				fn('foo');
  47
+			}, 'CIRCULAR_INVOCATION');
  48
+
  49
+			i = 0;
  50
+			fn = t(function (x, y) {
  51
+				if (++i < 2) fn(x, y);
  52
+			});
  53
+			a.throws(function () {
  54
+				fn('foo', 'bar');
  55
+			}, 'CIRCULAR_INVOCATION');
39 56
 		}
40 57
 	};
41 58
 };
11  test/regular.js
@@ -188,7 +188,7 @@ module.exports = function (t, a) {
188 188
 					}
189 189
 				};
190 190
 			},
191  
-			"All": function () {
  191
+			"All": function (a) {
192 192
 				var i = 0, fn, x = {};
193 193
 
194 194
 				fn = function () {
@@ -209,6 +209,15 @@ module.exports = function (t, a) {
209 209
 				fn(1, x, 4);
210 210
 				a(i, 4, "After clear");
211 211
 			}
  212
+		},
  213
+		"Circular": function (a) {
  214
+			var i = 0, fn;
  215
+			fn = t(function (x) {
  216
+				if (++i < 2) fn(x);
  217
+			});
  218
+			a.throws(function () {
  219
+				fn(34);
  220
+			}, 'CIRCULAR_INVOCATION');
212 221
 		}
213 222
 	};
214 223
 };

0 notes on commit f57bac3

Please sign in to comment.
Something went wrong with that request. Please try again.