import { assign, blankObject, differs, dispatchObservers, get, observe } from './shared.js'; function Store(state) { this._state = state ? assign({}, state) : {}; this._observers = { pre: blankObject(), post: blankObject() }; this._changeHandlers = []; this._dependents = []; } assign(Store.prototype, { get, observe }, { _add: function(component, props) { this._dependents.push({ component: component, props: props }); }, _init: function(props) { var state = {}; for (let i = 0; i < props.length; i += 1) { var prop = props[i]; state['$' + prop] = this._state[prop]; } return state; }, _remove: function(component) { let i = this._dependents.length; while (i--) { if (this._dependents[i].component === component) { this._dependents.splice(i, 1); return; } } }, onchange: function(callback) { this._changeHandlers.push(callback); return { cancel: function() { var index = this._changeHandlers.indexOf(callback); if (~index) this._changeHandlers.splice(index, 1); } }; }, set: function(newState) { var oldState = this._state, changed = {}, dirty = false; for (var key in newState) { if (differs(newState[key], oldState[key])) changed[key] = dirty = true; } if (!dirty) return; this._state = assign({}, oldState, newState); for (var i = 0; i < this._changeHandlers.length; i += 1) { this._changeHandlers[i](this._state, changed); } dispatchObservers(this, this._observers.pre, changed, this._state, oldState); var dependents = this._dependents.slice(); // guard against mutations for (var i = 0; i < dependents.length; i += 1) { var dependent = dependents[i]; var componentState = {}; dirty = false; for (var j = 0; j < dependent.props.length; j += 1) { var prop = dependent.props[j]; if (prop in changed) { componentState['$' + prop] = this._state[prop]; dirty = true; } } if (dirty) dependent.component.set(componentState); } dispatchObservers(this, this._observers.post, changed, this._state, oldState); } }); export default Store;