Files
memoizee/lib/primitive.js
2013-07-22 19:35:28 +02:00

91 lines
2.3 KiB
JavaScript

// Memoize working in primitive mode
'use strict';
var CustomError = require('es5-ext/lib/Error/custom')
, hasListeners = require('event-emitter/lib/has-listeners')
, getId0 = function () { return ''; }
, getId1 = function (args) { return args[0]; }
, apply = Function.prototype.apply, call = Function.prototype.call;
module.exports = require('./_base')(function (conf, length) {
var get, cache = conf.cache = {}, fn
, hitListeners, initListeners, purgeListeners;
if (length === 1) {
get = conf.get = getId1;
} else if (length === false) {
get = conf.get = function (args) {
var id = '', i, length = args.length;
if (length) {
id += args[i = 0];
while (--length) {
id += '\u0001' + args[++i];
}
} else {
id = '\u0002';
}
return id;
};
} else if (length) {
get = conf.get = function (args) {
var id = String(args[0]), i = 0, l = length;
while (--l) { id += '\u0001' + args[++i]; }
return id;
};
} else {
get = conf.get = getId0;
}
conf.memoized = (length === 1) ? function (id) {
var value;
if (cache.hasOwnProperty(id)) {
hitListeners && conf.emit('hit', id, arguments, this);
return cache[id];
} else {
if (arguments.length === 1) {
value = call.call(fn, this, id);
} 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;
}
} : function () {
var id = get(arguments), value;
if (cache.hasOwnProperty(id)) {
hitListeners && conf.emit('hit', id, arguments, this);
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;
}
};
conf.clear = function (id) {
if (cache.hasOwnProperty(id)) {
purgeListeners && conf.emit('purge', id);
delete cache[id];
}
};
conf.clearAll = function () { cache = conf.cache = {}; };
conf.once('ready', function () {
fn = conf.fn;
hitListeners = hasListeners(conf, 'hit');
initListeners = hasListeners(conf, 'init');
purgeListeners = hasListeners(conf, 'purge');
});
});