123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /* eslint no-eq-null: 0, eqeqeq: 0, no-unused-vars: 0 */
- "use strict";
- 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;
- };
|