Files
memoizee/lib/primitive.js
2013-07-22 20:37:15 +02:00

93 lines
2.5 KiB
JavaScript

// Memoize working in primitive mode
'use strict';
var CustomError = require('es5-ext/lib/Error/custom')
, callable = require('es5-ext/lib/Object/valid-callable')
, hasListeners = require('event-emitter/lib/has-listeners')
, serialize0 = function () { return ''; }
, serialize1 = function (args) { return args[0]; }
, apply = Function.prototype.apply, call = Function.prototype.call
, serializeN;
serializeN = 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;
};
module.exports = require('./_base')(function (conf, length, options) {
var get, cache = conf.cache = {}, fn
, hitListeners, initListeners, purgeListeners, serialize;
if (options.serialize) {
serialize = callable(options.serialize);
get = conf.get = function (args) { return serialize.apply(this, args); };
} else if (length === 1) {
get = conf.get = serialize1;
} else if (length === false) {
get = conf.get = serializeN;
} 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 = serialize0;
}
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');
});
});