Permalink
Browse files

Merge with v0.2

  • Loading branch information...
2 parents 83f31df + ec90653 commit f57bac383c79d011677bd030204f11969a43ec19 @medikoo committed Mar 23, 2013
Showing with 66 additions and 27 deletions.
  1. +3 −0 CHANGES
  2. +8 −1 lib/primitive.js
  3. +26 −23 lib/regular.js
  4. +2 −2 package.json
  5. +17 −0 test/primitive.js
  6. +10 −1 test/regular.js
View
@@ -1,3 +1,6 @@
+v0.2.4 -- 2013.03.23
+* Throw on circular invocations, they cannot be memoized as intended.
+
v0.2.3 -- 2012.10.04
* Fixed serious bug related to not properly cleared cache when working in
regular mode
View
@@ -2,7 +2,8 @@
'use strict';
-var hasListeners = require('event-emitter/lib/has-listeners')
+var CustomError = require('es5-ext/lib/Error/custom')
+ , hasListeners = require('event-emitter/lib/has-listeners')
, getId0 = function () { return ''; }
, getId1 = function (args) { return args[0]; }
@@ -49,6 +50,9 @@ module.exports = require('./_base')(function (conf, length) {
} else {
value = apply.call(fn, this, arguments);
}
+ if (cache.hasOwnProperty(id)) {
+ throw new CustomError("Circular invocation", 'CIRCULAR_INVOCATION');
+ }
cache[id] = value;
initListeners && conf.emit('init', id);
return value;
@@ -60,6 +64,9 @@ module.exports = require('./_base')(function (conf, length) {
return cache[id];
} else {
value = apply.call(conf.fn, this, arguments);
+ if (cache.hasOwnProperty(id)) {
+ throw new CustomError("Circular invocation", 'CIRCULAR_INVOCATION');
+ }
cache[id] = value;
initListeners && conf.emit('init', id);
return value;
View
@@ -2,11 +2,11 @@
'use strict';
-var indexOf = require('es5-ext/lib/Array/prototype/e-index-of')
+var CustomError = require('es5-ext/lib/Error/custom')
+ , indexOf = require('es5-ext/lib/Array/prototype/e-index-of')
, hasListeners = require('event-emitter/lib/has-listeners')
- , apply = Function.prototype.apply
- , getId0 = function () { return ''; };
+ , apply = Function.prototype.apply;
// Results are saved internally within array matrix:
// [0] -> Result of calling function with no arguments
@@ -30,15 +30,22 @@ module.exports = require('./_base')(function (conf, length) {
, cache = conf.cache = {}, argsCache;
if (length === 0) {
- get = set = clear = conf.get = getId0;
- conf.clearAll = function () { cache = conf.cache = {}; };
+ map = null;
+ get = conf.get = function () { return map; };
+ set = function () { return ((map = 1)); };
+ clear = function () { map = null; };
+ conf.clearAll = function () {
+ map = null;
+ cache = conf.cache = {};
+ };
} else {
count = 0;
if (length === 1) {
map1 = [];
map2 = [];
get = conf.get = function (args) {
- return map2[indexOf.call(map1, args[0])];
+ var index = indexOf.call(map1, args[0]);
+ return (index === -1) ? null : map2[index];
};
set = function (args) {
map1.push(args[0]);
@@ -63,23 +70,19 @@ module.exports = require('./_base')(function (conf, length) {
get = conf.get = function (args) {
var index = 0, set = map, i, length = args.length;
if (length === 0) {
- return set[length];
+ return set[length] || null;
} else if ((set = set[length])) {
while (index < (length - 1)) {
i = indexOf.call(set[0], args[index]);
- if (i === -1) {
- return;
- }
+ if (i === -1) return null;
set = set[1][i];
++index;
}
i = indexOf.call(set[0], args[index]);
- if (i === -1) {
- return;
- }
- return set[1][i];
+ if (i === -1) return null;
+ return set[1][i] || null;
}
- return;
+ return null;
};
set = function (args) {
var index = 0, set = map, i, length = args.length;
@@ -151,17 +154,13 @@ module.exports = require('./_base')(function (conf, length) {
var index = 0, set = map, i;
while (index < (length - 1)) {
i = indexOf.call(set[0], args[index]);
- if (i === -1) {
- return null;
- }
+ if (i === -1) return null;
set = set[1][i];
++index;
}
i = indexOf.call(set[0], args[index]);
- if (i === -1) {
- return null;
- }
- return set[1][i];
+ if (i === -1) return null;
+ return set[1][i] || null;
};
set = function (args) {
var index = 0, set = map, i;
@@ -217,11 +216,15 @@ module.exports = require('./_base')(function (conf, length) {
}
conf.memoized = function () {
var id = get(arguments), value;
- if (cache.hasOwnProperty(id)) {
+ if (id != null) {
hitListeners && conf.emit('hit', id, arguments, this);
return cache[id];
} else {
value = apply.call(fn, this, arguments);
+ id = get(arguments);
+ if (id != null) {
+ throw new CustomError("Circular invocation", 'CIRCULAR_INVOCATION');
+ }
id = set(arguments);
cache[id] = value;
initListeners && conf.emit('init', id);
View
@@ -34,12 +34,12 @@
"node": ">=0.4"
},
"dependencies": {
- "es5-ext": "0.9.x",
+ "es5-ext": "~0.9.2",
"event-emitter": "~0.2.1",
"next-tick": "0.1.x"
},
"devDependencies": {
- "tad": "0.1.x"
+ "tad": "~0.1.15"
},
"author": "Mariusz Nowak <medikoo+memoize@medikoo.com> (http://www.medikoo.com/)",
"license": "MIT"
View
@@ -36,6 +36,23 @@ module.exports = function (t) {
'zeta');
a(mfn(y, 'bar', 'zeta'), 'foobarzeta', "#3");
a(i, 2, "Called twice");
+ },
+ "Circular": function (a) {
+ var i = 0, fn;
+ fn = t(function (x) {
+ if (++i < 2) fn(x);
+ });
+ a.throws(function () {
+ fn('foo');
+ }, 'CIRCULAR_INVOCATION');
+
+ i = 0;
+ fn = t(function (x, y) {
+ if (++i < 2) fn(x, y);
+ });
+ a.throws(function () {
+ fn('foo', 'bar');
+ }, 'CIRCULAR_INVOCATION');
}
};
};
View
@@ -188,7 +188,7 @@ module.exports = function (t, a) {
}
};
},
- "All": function () {
+ "All": function (a) {
var i = 0, fn, x = {};
fn = function () {
@@ -209,6 +209,15 @@ module.exports = function (t, a) {
fn(1, x, 4);
a(i, 4, "After clear");
}
+ },
+ "Circular": function (a) {
+ var i = 0, fn;
+ fn = t(function (x) {
+ if (++i < 2) fn(x);
+ });
+ a.throws(function () {
+ fn(34);
+ }, 'CIRCULAR_INVOCATION');
}
};
};

0 comments on commit f57bac3

Please sign in to comment.