store.umd.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (factory((global.svelte = global.svelte || {})));
  5. }(this, (function (exports) { 'use strict';
  6. function assign(tar, src) {
  7. for (var k in src) tar[k] = src[k];
  8. return tar;
  9. }
  10. function blankObject() {
  11. return Object.create(null);
  12. }
  13. function _differs(a, b) {
  14. return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
  15. }
  16. function _differsImmutable(a, b) {
  17. return a != a ? b == b : a !== b;
  18. }
  19. function fire(eventName, data) {
  20. var handlers =
  21. eventName in this._handlers && this._handlers[eventName].slice();
  22. if (!handlers) return;
  23. for (var i = 0; i < handlers.length; i += 1) {
  24. var handler = handlers[i];
  25. if (!handler.__calling) {
  26. handler.__calling = true;
  27. handler.call(this, data);
  28. handler.__calling = false;
  29. }
  30. }
  31. }
  32. function get() {
  33. return this._state;
  34. }
  35. function on(eventName, handler) {
  36. var handlers = this._handlers[eventName] || (this._handlers[eventName] = []);
  37. handlers.push(handler);
  38. return {
  39. cancel: function() {
  40. var index = handlers.indexOf(handler);
  41. if (~index) handlers.splice(index, 1);
  42. }
  43. };
  44. }
  45. function Store(state, options) {
  46. this._handlers = {};
  47. this._dependents = [];
  48. this._computed = blankObject();
  49. this._sortedComputedProperties = [];
  50. this._state = assign({}, state);
  51. this._differs = options && options.immutable ? _differsImmutable : _differs;
  52. }
  53. assign(Store.prototype, {
  54. _add(component, props) {
  55. this._dependents.push({
  56. component: component,
  57. props: props
  58. });
  59. },
  60. _init(props) {
  61. const state = {};
  62. for (let i = 0; i < props.length; i += 1) {
  63. const prop = props[i];
  64. state['$' + prop] = this._state[prop];
  65. }
  66. return state;
  67. },
  68. _remove(component) {
  69. let i = this._dependents.length;
  70. while (i--) {
  71. if (this._dependents[i].component === component) {
  72. this._dependents.splice(i, 1);
  73. return;
  74. }
  75. }
  76. },
  77. _set(newState, changed) {
  78. const previous = this._state;
  79. this._state = assign(assign({}, previous), newState);
  80. for (let i = 0; i < this._sortedComputedProperties.length; i += 1) {
  81. this._sortedComputedProperties[i].update(this._state, changed);
  82. }
  83. this.fire('state', {
  84. changed,
  85. previous,
  86. current: this._state
  87. });
  88. const dependents = this._dependents.slice(); // guard against mutations
  89. for (let i = 0; i < dependents.length; i += 1) {
  90. const dependent = dependents[i];
  91. const componentState = {};
  92. let dirty = false;
  93. for (let j = 0; j < dependent.props.length; j += 1) {
  94. const prop = dependent.props[j];
  95. if (prop in changed) {
  96. componentState['$' + prop] = this._state[prop];
  97. dirty = true;
  98. }
  99. }
  100. if (dirty) dependent.component.set(componentState);
  101. }
  102. this.fire('update', {
  103. changed,
  104. previous,
  105. current: this._state
  106. });
  107. },
  108. _sortComputedProperties() {
  109. const computed = this._computed;
  110. const sorted = this._sortedComputedProperties = [];
  111. const visited = blankObject();
  112. let currentKey;
  113. function visit(key) {
  114. const c = computed[key];
  115. if (c) {
  116. c.deps.forEach(dep => {
  117. if (dep === currentKey) {
  118. throw new Error(`Cyclical dependency detected between ${dep} <-> ${key}`);
  119. }
  120. visit(dep);
  121. });
  122. if (!visited[key]) {
  123. visited[key] = true;
  124. sorted.push(c);
  125. }
  126. }
  127. }
  128. for (const key in this._computed) {
  129. visit(currentKey = key);
  130. }
  131. },
  132. compute(key, deps, fn) {
  133. let value;
  134. const c = {
  135. deps,
  136. update: (state, changed, dirty) => {
  137. const values = deps.map(dep => {
  138. if (dep in changed) dirty = true;
  139. return state[dep];
  140. });
  141. if (dirty) {
  142. const newValue = fn.apply(null, values);
  143. if (this._differs(newValue, value)) {
  144. value = newValue;
  145. changed[key] = true;
  146. state[key] = value;
  147. }
  148. }
  149. }
  150. };
  151. this._computed[key] = c;
  152. this._sortComputedProperties();
  153. const state = assign({}, this._state);
  154. const changed = {};
  155. c.update(state, changed, true);
  156. this._set(state, changed);
  157. },
  158. fire,
  159. get,
  160. on,
  161. set(newState) {
  162. const oldState = this._state;
  163. const changed = this._changed = {};
  164. let dirty = false;
  165. for (const key in newState) {
  166. if (this._computed[key]) throw new Error(`'${key}' is a read-only property`);
  167. if (this._differs(newState[key], oldState[key])) changed[key] = dirty = true;
  168. }
  169. if (!dirty) return;
  170. this._set(newState, changed);
  171. }
  172. });
  173. exports.Store = Store;
  174. Object.defineProperty(exports, '__esModule', { value: true });
  175. })));