configure-map.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /* eslint no-eq-null: 0, eqeqeq: 0, no-unused-vars: 0 */
  2. "use strict";
  3. var customError = require("es5-ext/error/custom")
  4. , defineLength = require("es5-ext/function/_define-length")
  5. , d = require("d")
  6. , ee = require("event-emitter").methods
  7. , resolveResolve = require("./resolve-resolve")
  8. , resolveNormalize = require("./resolve-normalize");
  9. var apply = Function.prototype.apply
  10. , call = Function.prototype.call
  11. , create = Object.create
  12. , defineProperties = Object.defineProperties
  13. , on = ee.on
  14. , emit = ee.emit;
  15. module.exports = function (original, length, options) {
  16. var cache = create(null)
  17. , conf
  18. , memLength
  19. , get
  20. , set
  21. , del
  22. , clear
  23. , extDel
  24. , extGet
  25. , extHas
  26. , normalizer
  27. , getListeners
  28. , setListeners
  29. , deleteListeners
  30. , memoized
  31. , resolve;
  32. if (length !== false) memLength = length;
  33. else if (isNaN(original.length)) memLength = 1;
  34. else memLength = original.length;
  35. if (options.normalizer) {
  36. normalizer = resolveNormalize(options.normalizer);
  37. get = normalizer.get;
  38. set = normalizer.set;
  39. del = normalizer.delete;
  40. clear = normalizer.clear;
  41. }
  42. if (options.resolvers != null) resolve = resolveResolve(options.resolvers);
  43. if (get) {
  44. memoized = defineLength(function (arg) {
  45. var id, result, args = arguments;
  46. if (resolve) args = resolve(args);
  47. id = get(args);
  48. if (id !== null) {
  49. if (hasOwnProperty.call(cache, id)) {
  50. if (getListeners) conf.emit("get", id, args, this);
  51. return cache[id];
  52. }
  53. }
  54. if (args.length === 1) result = call.call(original, this, args[0]);
  55. else result = apply.call(original, this, args);
  56. if (id === null) {
  57. id = get(args);
  58. if (id !== null) throw customError("Circular invocation", "CIRCULAR_INVOCATION");
  59. id = set(args);
  60. } else if (hasOwnProperty.call(cache, id)) {
  61. throw customError("Circular invocation", "CIRCULAR_INVOCATION");
  62. }
  63. cache[id] = result;
  64. if (setListeners) conf.emit("set", id, null, result);
  65. return result;
  66. }, memLength);
  67. } else if (length === 0) {
  68. memoized = function () {
  69. var result;
  70. if (hasOwnProperty.call(cache, "data")) {
  71. if (getListeners) conf.emit("get", "data", arguments, this);
  72. return cache.data;
  73. }
  74. if (arguments.length) result = apply.call(original, this, arguments);
  75. else result = call.call(original, this);
  76. if (hasOwnProperty.call(cache, "data")) {
  77. throw customError("Circular invocation", "CIRCULAR_INVOCATION");
  78. }
  79. cache.data = result;
  80. if (setListeners) conf.emit("set", "data", null, result);
  81. return result;
  82. };
  83. } else {
  84. memoized = function (arg) {
  85. var result, args = arguments, id;
  86. if (resolve) args = resolve(arguments);
  87. id = String(args[0]);
  88. if (hasOwnProperty.call(cache, id)) {
  89. if (getListeners) conf.emit("get", id, args, this);
  90. return cache[id];
  91. }
  92. if (args.length === 1) result = call.call(original, this, args[0]);
  93. else result = apply.call(original, this, args);
  94. if (hasOwnProperty.call(cache, id)) {
  95. throw customError("Circular invocation", "CIRCULAR_INVOCATION");
  96. }
  97. cache[id] = result;
  98. if (setListeners) conf.emit("set", id, null, result);
  99. return result;
  100. };
  101. }
  102. conf = {
  103. original: original,
  104. memoized: memoized,
  105. profileName: options.profileName,
  106. get: function (args) {
  107. if (resolve) args = resolve(args);
  108. if (get) return get(args);
  109. return String(args[0]);
  110. },
  111. has: function (id) {
  112. return hasOwnProperty.call(cache, id);
  113. },
  114. delete: function (id) {
  115. var result;
  116. if (!hasOwnProperty.call(cache, id)) return;
  117. if (del) del(id);
  118. result = cache[id];
  119. delete cache[id];
  120. if (deleteListeners) conf.emit("delete", id, result);
  121. },
  122. clear: function () {
  123. var oldCache = cache;
  124. if (clear) clear();
  125. cache = create(null);
  126. conf.emit("clear", oldCache);
  127. },
  128. on: function (type, listener) {
  129. if (type === "get") getListeners = true;
  130. else if (type === "set") setListeners = true;
  131. else if (type === "delete") deleteListeners = true;
  132. return on.call(this, type, listener);
  133. },
  134. emit: emit,
  135. updateEnv: function () {
  136. original = conf.original;
  137. }
  138. };
  139. if (get) {
  140. extDel = defineLength(function (arg) {
  141. var id, args = arguments;
  142. if (resolve) args = resolve(args);
  143. id = get(args);
  144. if (id === null) return;
  145. conf.delete(id);
  146. }, memLength);
  147. } else if (length === 0) {
  148. extDel = function () {
  149. return conf.delete("data");
  150. };
  151. } else {
  152. extDel = function (arg) {
  153. if (resolve) arg = resolve(arguments)[0];
  154. return conf.delete(arg);
  155. };
  156. }
  157. extGet = defineLength(function () {
  158. var id, args = arguments;
  159. if (length === 0) return cache.data;
  160. if (resolve) args = resolve(args);
  161. if (get) id = get(args);
  162. else id = String(args[0]);
  163. return cache[id];
  164. });
  165. extHas = defineLength(function () {
  166. var id, args = arguments;
  167. if (length === 0) return conf.has("data");
  168. if (resolve) args = resolve(args);
  169. if (get) id = get(args);
  170. else id = String(args[0]);
  171. if (id === null) return false;
  172. return conf.has(id);
  173. });
  174. defineProperties(memoized, {
  175. __memoized__: d(true),
  176. delete: d(extDel),
  177. clear: d(conf.clear),
  178. _get: d(extGet),
  179. _has: d(extHas)
  180. });
  181. return conf;
  182. };