store.umd.js 4.7 KB

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