Spaces:
Runtime error
Runtime error
/* eslint no-eq-null: 0, eqeqeq: 0, no-unused-vars: 0 */ | |
; | |
var customError = require("es5-ext/error/custom") | |
, defineLength = require("es5-ext/function/_define-length") | |
, d = require("d") | |
, ee = require("event-emitter").methods | |
, resolveResolve = require("./resolve-resolve") | |
, resolveNormalize = require("./resolve-normalize"); | |
var apply = Function.prototype.apply | |
, call = Function.prototype.call | |
, create = Object.create | |
, defineProperties = Object.defineProperties | |
, on = ee.on | |
, emit = ee.emit; | |
module.exports = function (original, length, options) { | |
var cache = create(null) | |
, conf | |
, memLength | |
, get | |
, set | |
, del | |
, clear | |
, extDel | |
, extGet | |
, extHas | |
, normalizer | |
, getListeners | |
, setListeners | |
, deleteListeners | |
, memoized | |
, resolve; | |
if (length !== false) memLength = length; | |
else if (isNaN(original.length)) memLength = 1; | |
else memLength = original.length; | |
if (options.normalizer) { | |
normalizer = resolveNormalize(options.normalizer); | |
get = normalizer.get; | |
set = normalizer.set; | |
del = normalizer.delete; | |
clear = normalizer.clear; | |
} | |
if (options.resolvers != null) resolve = resolveResolve(options.resolvers); | |
if (get) { | |
memoized = defineLength(function (arg) { | |
var id, result, args = arguments; | |
if (resolve) args = resolve(args); | |
id = get(args); | |
if (id !== null) { | |
if (hasOwnProperty.call(cache, id)) { | |
if (getListeners) conf.emit("get", id, args, this); | |
return cache[id]; | |
} | |
} | |
if (args.length === 1) result = call.call(original, this, args[0]); | |
else result = apply.call(original, this, args); | |
if (id === null) { | |
id = get(args); | |
if (id !== null) throw customError("Circular invocation", "CIRCULAR_INVOCATION"); | |
id = set(args); | |
} else if (hasOwnProperty.call(cache, id)) { | |
throw customError("Circular invocation", "CIRCULAR_INVOCATION"); | |
} | |
cache[id] = result; | |
if (setListeners) conf.emit("set", id, null, result); | |
return result; | |
}, memLength); | |
} else if (length === 0) { | |
memoized = function () { | |
var result; | |
if (hasOwnProperty.call(cache, "data")) { | |
if (getListeners) conf.emit("get", "data", arguments, this); | |
return cache.data; | |
} | |
if (arguments.length) result = apply.call(original, this, arguments); | |
else result = call.call(original, this); | |
if (hasOwnProperty.call(cache, "data")) { | |
throw customError("Circular invocation", "CIRCULAR_INVOCATION"); | |
} | |
cache.data = result; | |
if (setListeners) conf.emit("set", "data", null, result); | |
return result; | |
}; | |
} else { | |
memoized = function (arg) { | |
var result, args = arguments, id; | |
if (resolve) args = resolve(arguments); | |
id = String(args[0]); | |
if (hasOwnProperty.call(cache, id)) { | |
if (getListeners) conf.emit("get", id, args, this); | |
return cache[id]; | |
} | |
if (args.length === 1) result = call.call(original, this, args[0]); | |
else result = apply.call(original, this, args); | |
if (hasOwnProperty.call(cache, id)) { | |
throw customError("Circular invocation", "CIRCULAR_INVOCATION"); | |
} | |
cache[id] = result; | |
if (setListeners) conf.emit("set", id, null, result); | |
return result; | |
}; | |
} | |
conf = { | |
original: original, | |
memoized: memoized, | |
profileName: options.profileName, | |
get: function (args) { | |
if (resolve) args = resolve(args); | |
if (get) return get(args); | |
return String(args[0]); | |
}, | |
has: function (id) { return hasOwnProperty.call(cache, id); }, | |
delete: function (id) { | |
var result; | |
if (!hasOwnProperty.call(cache, id)) return; | |
if (del) del(id); | |
result = cache[id]; | |
delete cache[id]; | |
if (deleteListeners) conf.emit("delete", id, result); | |
}, | |
clear: function () { | |
var oldCache = cache; | |
if (clear) clear(); | |
cache = create(null); | |
conf.emit("clear", oldCache); | |
}, | |
on: function (type, listener) { | |
if (type === "get") getListeners = true; | |
else if (type === "set") setListeners = true; | |
else if (type === "delete") deleteListeners = true; | |
return on.call(this, type, listener); | |
}, | |
emit: emit, | |
updateEnv: function () { original = conf.original; } | |
}; | |
if (get) { | |
extDel = defineLength(function (arg) { | |
var id, args = arguments; | |
if (resolve) args = resolve(args); | |
id = get(args); | |
if (id === null) return; | |
conf.delete(id); | |
}, memLength); | |
} else if (length === 0) { | |
extDel = function () { return conf.delete("data"); }; | |
} else { | |
extDel = function (arg) { | |
if (resolve) arg = resolve(arguments)[0]; | |
return conf.delete(arg); | |
}; | |
} | |
extGet = defineLength(function () { | |
var id, args = arguments; | |
if (length === 0) return cache.data; | |
if (resolve) args = resolve(args); | |
if (get) id = get(args); | |
else id = String(args[0]); | |
return cache[id]; | |
}); | |
extHas = defineLength(function () { | |
var id, args = arguments; | |
if (length === 0) return conf.has("data"); | |
if (resolve) args = resolve(args); | |
if (get) id = get(args); | |
else id = String(args[0]); | |
if (id === null) return false; | |
return conf.has(id); | |
}); | |
defineProperties(memoized, { | |
__memoized__: d(true), | |
delete: d(extDel), | |
clear: d(conf.clear), | |
_get: d(extGet), | |
_has: d(extHas) | |
}); | |
return conf; | |
}; | |