UNPKG

mobx

Version:

Simple, scalable state management.

1,530 lines (1,316 loc) 161 kB
'use strict'; var niceErrors = { 0: "Invalid value for configuration 'enforceActions', expected 'never', 'always' or 'observed'", 1: function _(prop) { return "Cannot decorate undefined property: '" + prop.toString() + "'"; }, 2: function _(prop) { return "invalid decorator for '" + prop.toString() + "'"; }, 3: function _(prop) { return "Cannot decorate '" + prop.toString() + "': action can only be used on properties with a function value."; }, 4: function _(prop) { return "Cannot decorate '" + prop.toString() + "': computed can only be used on getter properties."; }, 5: "'keys()' can only be used on observable objects, arrays, sets and maps", 6: "'values()' can only be used on observable objects, arrays, sets and maps", 7: "'entries()' can only be used on observable objects, arrays and maps", 8: "'set()' can only be used on observable objects, arrays and maps", 9: "'remove()' can only be used on observable objects, arrays and maps", 10: "'has()' can only be used on observable objects, arrays and maps", 11: "'get()' can only be used on observable objects, arrays and maps", 12: "Invalid annotation", 13: "Dynamic observable objects cannot be frozen", 14: "Intercept handlers should return nothing or a change object", 15: "Observable arrays cannot be frozen", 16: "Modification exception: the internal structure of an observable array was changed.", 17: function _(index, length) { return "[mobx.array] Index out of bounds, " + index + " is larger than " + length; }, 18: "mobx.map requires Map polyfill for the current browser. Check babel-polyfill or core-js/es6/map.js", 19: function _(other) { return "Cannot initialize from classes that inherit from Map: " + other.constructor.name; }, 20: function _(other) { return "Cannot initialize map from " + other; }, 21: function _(dataStructure) { return "Cannot convert to map from '" + dataStructure + "'"; }, 22: "mobx.set requires Set polyfill for the current browser. Check babel-polyfill or core-js/es6/set.js", 23: "It is not possible to get index atoms from arrays", 24: function _(thing) { return "Cannot obtain administration from " + thing; }, 25: function _(property, name) { return "the entry '" + property + "' does not exist in the observable map '" + name + "'"; }, 26: "please specify a property", 27: function _(property, name) { return "no observable property '" + property.toString() + "' found on the observable object '" + name + "'"; }, 28: function _(thing) { return "Cannot obtain atom from " + thing; }, 29: "Expecting some object", 30: "invalid action stack. did you forget to finish an action?", 31: "missing option for computed: get", 32: function _(name, derivation) { return "Cycle detected in computation " + name + ": " + derivation; }, 33: function _(name) { return "The setter of computed value '" + name + "' is trying to update itself. Did you intend to update an _observable_ value, instead of the computed property?"; }, 34: function _(name) { return "[ComputedValue '" + name + "'] It is not possible to assign a new value to a computed value."; }, 35: "There are multiple, different versions of MobX active. Make sure MobX is loaded only once or use `configure({ isolateGlobalState: true })`", 36: "isolateGlobalState should be called before MobX is running any reactions", 37: function _(method) { return "[mobx] `observableArray." + method + "()` mutates the array in-place, which is not allowed inside a derivation. Use `array.slice()." + method + "()` instead"; } }; var errors = niceErrors ; function die(error) { for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } { var e = typeof error === "string" ? error : errors[error]; if (typeof e === "function") e = e.apply(null, args); throw new Error("[MobX] " + e); } } function getGlobal() { // @ts-ignore return typeof global !== "undefined" ? global : window; } var assign = Object.assign; var getDescriptor = Object.getOwnPropertyDescriptor; var defineProperty = Object.defineProperty; var objectPrototype = Object.prototype; var EMPTY_ARRAY = []; Object.freeze(EMPTY_ARRAY); var EMPTY_OBJECT = {}; Object.freeze(EMPTY_OBJECT); var hasProxy = typeof Proxy !== "undefined"; var plainObjectString = /*#__PURE__*/Object.toString(); function assertProxies() { if (!hasProxy) { die( "`Proxy` objects are not available in the current environment. Please configure MobX to enable a fallback implementation.`" ); } } function warnAboutProxyRequirement(msg) { if ( globalState.verifyProxies) { die("MobX is currently configured to be able to run in ES5 mode, but in ES5 MobX won't be able to " + msg); } } function getNextId() { return ++globalState.mobxGuid; } /** * Makes sure that the provided function is invoked at most once. */ function once(func) { var invoked = false; return function () { if (invoked) return; invoked = true; return func.apply(this, arguments); }; } var noop = function noop() {}; function isFunction(fn) { return typeof fn === "function"; } function isStringish(value) { var t = typeof value; switch (t) { case "string": case "symbol": case "number": return true; } return false; } function isObject(value) { return value !== null && typeof value === "object"; } function isPlainObject(value) { var _proto$constructor; if (!isObject(value)) return false; var proto = Object.getPrototypeOf(value); if (proto == null) return true; return ((_proto$constructor = proto.constructor) === null || _proto$constructor === void 0 ? void 0 : _proto$constructor.toString()) === plainObjectString; } // https://stackoverflow.com/a/37865170 function isGenerator(obj) { var constructor = obj === null || obj === void 0 ? void 0 : obj.constructor; if (!constructor) return false; if ("GeneratorFunction" === constructor.name || "GeneratorFunction" === constructor.displayName) return true; return false; } function addHiddenProp(object, propName, value) { defineProperty(object, propName, { enumerable: false, writable: true, configurable: true, value: value }); } function addHiddenFinalProp(object, propName, value) { defineProperty(object, propName, { enumerable: false, writable: false, configurable: true, value: value }); } function assertPropertyConfigurable(object, prop) { { var descriptor = getDescriptor(object, prop); if ((descriptor === null || descriptor === void 0 ? void 0 : descriptor.configurable) === false || (descriptor === null || descriptor === void 0 ? void 0 : descriptor.writable) === false) die("Cannot make property '" + stringifyKey(prop) + "' observable, it is not configurable and writable in the target object"); } } function createInstanceofPredicate(name, clazz) { var propName = "isMobX" + name; clazz.prototype[propName] = true; return function (x) { return isObject(x) && x[propName] === true; }; } function isES6Map(thing) { return thing instanceof Map; } function isES6Set(thing) { return thing instanceof Set; } var hasGetOwnPropertySymbols = typeof Object.getOwnPropertySymbols !== "undefined"; /** * Returns the following: own keys, prototype keys & own symbol keys, if they are enumerable. */ function getPlainObjectKeys(object) { var keys = Object.keys(object); // Not supported in IE, so there are not going to be symbol props anyway... if (!hasGetOwnPropertySymbols) return keys; var symbols = Object.getOwnPropertySymbols(object); if (!symbols.length) return keys; return [].concat(keys, symbols.filter(function (s) { return objectPrototype.propertyIsEnumerable.call(object, s); })); } // From Immer utils // Returns all own keys, including non-enumerable and symbolic var ownKeys = typeof Reflect !== "undefined" && Reflect.ownKeys ? Reflect.ownKeys : hasGetOwnPropertySymbols ? function (obj) { return Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)); } : /* istanbul ignore next */ Object.getOwnPropertyNames; function stringifyKey(key) { if (typeof key === "string") return key; if (typeof key === "symbol") return key.toString(); return new String(key).toString(); } function toPrimitive(value) { return value === null ? null : typeof value === "object" ? "" + value : value; } function hasProp(target, prop) { return objectPrototype.hasOwnProperty.call(target, prop); } // From Immer utils var getOwnPropertyDescriptors = Object.getOwnPropertyDescriptors || function getOwnPropertyDescriptors(target) { // Polyfill needed for Hermes and IE, see https://github.com/facebook/hermes/issues/274 var res = {}; // Note: without polyfill for ownKeys, symbols won't be picked up ownKeys(target).forEach(function (key) { res[key] = getDescriptor(target, key); }); return res; }; var mobxDecoratorsSymbol = /*#__PURE__*/Symbol("mobx-decorators"); var mobxAppliedDecoratorsSymbol = /*#__PURE__*/Symbol("mobx-applied-decorators"); function createDecorator(type) { return assign(function (target, property) { if (property === undefined) { // @decorator(arg) member createDecoratorAndAnnotation(type, target); } else { // @decorator member storeDecorator(target, property, type); } }, { annotationType_: type }); } function createDecoratorAndAnnotation(type, arg_) { return assign(function (target, property) { storeDecorator(target, property, type, arg_); }, { annotationType_: type, arg_: arg_ }); } function storeDecorator(target, property, type, arg_) { var desc = getDescriptor(target, mobxDecoratorsSymbol); var map; if (desc) { map = desc.value; } else { map = {}; addHiddenProp(target, mobxDecoratorsSymbol, map); } map[property] = { annotationType_: type, arg_: arg_ }; } function applyDecorators(target) { if (target[mobxAppliedDecoratorsSymbol]) return true; var current = target; // optimization: this could be cached per prototype! // (then we can remove the weird short circuiting as well..) var annotations = []; while (current && current !== objectPrototype) { var desc = getDescriptor(current, mobxDecoratorsSymbol); if (desc) { if (!annotations.length) { for (var key in desc.value) { // second conditions is to recognize actions if (!hasProp(target, key) && !hasProp(current, key)) { // not all fields are defined yet, so we are in the makeObservable call of some super class, // short circuit, here, we will do this again in a later makeObservable call return true; } } } annotations.unshift(desc.value); } current = Object.getPrototypeOf(current); } annotations.forEach(function (a) { makeObservable(target, a); }); addHiddenProp(target, mobxAppliedDecoratorsSymbol, true); return annotations.length > 0; } var $mobx = /*#__PURE__*/Symbol("mobx administration"); var Atom = /*#__PURE__*/function () { // for effective unobserving. BaseAtom has true, for extra optimization, so its onBecomeUnobserved never gets called, because it's not needed /** * Create a new atom. For debugging purposes it is recommended to give it a name. * The onBecomeObserved and onBecomeUnobserved callbacks can be used for resource management. */ function Atom(name_) { if (name_ === void 0) { name_ = "Atom@" + getNextId(); } this.name_ = void 0; this.isPendingUnobservation_ = false; this.isBeingObserved_ = false; this.observers_ = new Set(); this.diffValue_ = 0; this.lastAccessedBy_ = 0; this.lowestObserverState_ = IDerivationState_.NOT_TRACKING_; this.onBOL = void 0; this.onBUOL = void 0; this.name_ = name_; } // onBecomeObservedListeners var _proto = Atom.prototype; _proto.onBO = function onBO() { if (this.onBOL) { this.onBOL.forEach(function (listener) { return listener(); }); } }; _proto.onBUO = function onBUO() { if (this.onBUOL) { this.onBUOL.forEach(function (listener) { return listener(); }); } } /** * Invoke this method to notify mobx that your atom has been used somehow. * Returns true if there is currently a reactive context. */ ; _proto.reportObserved = function reportObserved$1() { return reportObserved(this); } /** * Invoke this method _after_ this method has changed to signal mobx that all its observers should invalidate. */ ; _proto.reportChanged = function reportChanged() { startBatch(); propagateChanged(this); endBatch(); }; _proto.toString = function toString() { return this.name_; }; return Atom; }(); var isAtom = /*#__PURE__*/createInstanceofPredicate("Atom", Atom); function createAtom(name, onBecomeObservedHandler, onBecomeUnobservedHandler) { if (onBecomeObservedHandler === void 0) { onBecomeObservedHandler = noop; } if (onBecomeUnobservedHandler === void 0) { onBecomeUnobservedHandler = noop; } var atom = new Atom(name); // default `noop` listener will not initialize the hook Set if (onBecomeObservedHandler !== noop) { onBecomeObserved(atom, onBecomeObservedHandler); } if (onBecomeUnobservedHandler !== noop) { onBecomeUnobserved(atom, onBecomeUnobservedHandler); } return atom; } function identityComparer(a, b) { return a === b; } function structuralComparer(a, b) { return deepEqual(a, b); } function shallowComparer(a, b) { return deepEqual(a, b, 1); } function defaultComparer(a, b) { return Object.is(a, b); } var comparer = { identity: identityComparer, structural: structuralComparer, "default": defaultComparer, shallow: shallowComparer }; function deepEnhancer(v, _, name) { // it is an observable already, done if (isObservable(v)) return v; // something that can be converted and mutated? if (Array.isArray(v)) return observable.array(v, { name: name }); if (isPlainObject(v)) return observable.object(v, undefined, { name: name }); if (isES6Map(v)) return observable.map(v, { name: name }); if (isES6Set(v)) return observable.set(v, { name: name }); return v; } function shallowEnhancer(v, _, name) { if (v === undefined || v === null) return v; if (isObservableObject(v) || isObservableArray(v) || isObservableMap(v) || isObservableSet(v)) return v; if (Array.isArray(v)) return observable.array(v, { name: name, deep: false }); if (isPlainObject(v)) return observable.object(v, undefined, { name: name, deep: false }); if (isES6Map(v)) return observable.map(v, { name: name, deep: false }); if (isES6Set(v)) return observable.set(v, { name: name, deep: false }); die("The shallow modifier / decorator can only used in combination with arrays, objects, maps and sets"); } function referenceEnhancer(newValue) { // never turn into an observable return newValue; } function refStructEnhancer(v, oldValue) { if ( isObservable(v)) die("observable.struct should not be used with observable values"); if (deepEqual(v, oldValue)) return oldValue; return v; } var _annotationToEnhancer; var OBSERVABLE = "observable"; var OBSERVABLE_REF = "observable.ref"; var OBSERVABLE_SHALLOW = "observable.shallow"; var OBSERVABLE_STRUCT = "observable.struct"; // Predefined bags of create observable options, to avoid allocating temporarily option objects // in the majority of cases var defaultCreateObservableOptions = { deep: true, name: undefined, defaultDecorator: undefined, proxy: true }; Object.freeze(defaultCreateObservableOptions); function asCreateObservableOptions(thing) { return thing || defaultCreateObservableOptions; } function getEnhancerFromOption(options) { return options.deep === true ? deepEnhancer : options.deep === false ? referenceEnhancer : getEnhancerFromAnnotation(options.defaultDecorator); } var annotationToEnhancer = (_annotationToEnhancer = {}, _annotationToEnhancer[OBSERVABLE] = deepEnhancer, _annotationToEnhancer[OBSERVABLE_REF] = referenceEnhancer, _annotationToEnhancer[OBSERVABLE_SHALLOW] = shallowEnhancer, _annotationToEnhancer[OBSERVABLE_STRUCT] = refStructEnhancer, _annotationToEnhancer); function getEnhancerFromAnnotation(annotation) { var _annotationToEnhancer2; return !annotation ? deepEnhancer : (_annotationToEnhancer2 = annotationToEnhancer[annotation.annotationType_]) !== null && _annotationToEnhancer2 !== void 0 ? _annotationToEnhancer2 : die(12); } /** * Turns an object, array or function into a reactive structure. * @param v the value which should become observable. */ function createObservable(v, arg2, arg3) { // @observable someProp; if (isStringish(arg2)) { storeDecorator(v, arg2, OBSERVABLE); return; } // it is an observable already, done if (isObservable(v)) return v; // something that can be converted and mutated? var res = isPlainObject(v) ? observable.object(v, arg2, arg3) : Array.isArray(v) ? observable.array(v, arg2) : isES6Map(v) ? observable.map(v, arg2) : isES6Set(v) ? observable.set(v, arg2) : v; // this value could be converted to a new observable data structure, return it if (res !== v) return res; return observable.box(v); } createObservable.annotationType_ = OBSERVABLE; var observableFactories = { box: function box(value, options) { var o = asCreateObservableOptions(options); return new ObservableValue(value, getEnhancerFromOption(o), o.name, true, o.equals); }, array: function array(initialValues, options) { var o = asCreateObservableOptions(options); return (globalState.useProxies === false || o.proxy === false ? createLegacyArray : createObservableArray)(initialValues, getEnhancerFromOption(o), o.name); }, map: function map(initialValues, options) { var o = asCreateObservableOptions(options); return new ObservableMap(initialValues, getEnhancerFromOption(o), o.name); }, set: function set(initialValues, options) { var o = asCreateObservableOptions(options); return new ObservableSet(initialValues, getEnhancerFromOption(o), o.name); }, object: function object(props, decorators, options) { var o = asCreateObservableOptions(options); var base = {}; asObservableObject(base, options === null || options === void 0 ? void 0 : options.name, getEnhancerFromOption(o)); return extendObservable(globalState.useProxies === false || o.proxy === false ? base : createDynamicObservableObject(base), props, decorators, options); }, ref: /*#__PURE__*/createDecorator(OBSERVABLE_REF), shallow: /*#__PURE__*/createDecorator(OBSERVABLE_SHALLOW), deep: /*#__PURE__*/createDecorator(OBSERVABLE), struct: /*#__PURE__*/createDecorator(OBSERVABLE_STRUCT) }; // eslint-disable-next-line var observable = /*#__PURE__*/assign(createObservable, observableFactories); var COMPUTED = "computed"; var COMPUTED_STRUCT = "computed.struct"; /** * Decorator for class properties: @computed get value() { return expr; }. * For legacy purposes also invokable as ES5 observable created: `computed(() => expr)`; */ var computed = function computed(arg1, arg2, arg3) { if (isStringish(arg2)) { // @computed return storeDecorator(arg1, arg2, COMPUTED); } if (isPlainObject(arg1)) { // @computed({ options }) return createDecoratorAndAnnotation(COMPUTED, arg1); } // computed(expr, options?) { if (!isFunction(arg1)) die("First argument to `computed` should be an expression."); if (isFunction(arg2)) die("A setter as second argument is no longer supported, use `{set: fn }` option instead"); } var opts = isPlainObject(arg2) ? arg2 : {}; opts.get = arg1; opts.name = opts.name || arg1.name || ""; /* for generated name */ return new ComputedValue(opts); }; computed.annotationType_ = COMPUTED; computed.struct = /*#__PURE__*/assign(function (target, property) { storeDecorator(target, property, COMPUTED_STRUCT); }, { annotationType_: COMPUTED_STRUCT }); var _getDescriptor$config, _getDescriptor; // mobx versions var currentActionId = 0; var nextActionId = 1; var isFunctionNameConfigurable = (_getDescriptor$config = (_getDescriptor = /*#__PURE__*/getDescriptor(function () {}, "name")) === null || _getDescriptor === void 0 ? void 0 : _getDescriptor.configurable) !== null && _getDescriptor$config !== void 0 ? _getDescriptor$config : false; // we can safely recycle this object var tmpNameDescriptor = { value: "action", configurable: true, writable: false, enumerable: false }; function createAction(actionName, fn, autoAction, ref) { if (autoAction === void 0) { autoAction = false; } { if (!isFunction(fn)) die("`action` can only be invoked on functions"); if (typeof actionName !== "string" || !actionName) die("actions should have valid names, got: '" + actionName + "'"); } function res() { return executeAction(actionName, autoAction, fn, ref || this, arguments); } res.isMobxAction = true; if (isFunctionNameConfigurable) { tmpNameDescriptor.value = actionName; Object.defineProperty(res, "name", tmpNameDescriptor); } return res; } function executeAction(actionName, canRunAsDerivation, fn, scope, args) { var runInfo = _startAction(actionName, canRunAsDerivation, scope, args); try { return fn.apply(scope, args); } catch (err) { runInfo.error_ = err; throw err; } finally { _endAction(runInfo); } } function _startAction(actionName, canRunAsDerivation, // true for autoAction scope, args) { var notifySpy_ = isSpyEnabled() && !!actionName; var startTime_ = 0; if ( notifySpy_) { startTime_ = Date.now(); var flattenedArgs = args ? Array.from(args) : EMPTY_ARRAY; spyReportStart({ type: ACTION, name: actionName, object: scope, arguments: flattenedArgs }); } var prevDerivation_ = globalState.trackingDerivation; var runAsAction = !canRunAsDerivation || !prevDerivation_; startBatch(); var prevAllowStateChanges_ = globalState.allowStateChanges; // by default preserve previous allow if (runAsAction) { untrackedStart(); prevAllowStateChanges_ = allowStateChangesStart(true); } var prevAllowStateReads_ = allowStateReadsStart(true); var runInfo = { runAsAction_: runAsAction, prevDerivation_: prevDerivation_, prevAllowStateChanges_: prevAllowStateChanges_, prevAllowStateReads_: prevAllowStateReads_, notifySpy_: notifySpy_, startTime_: startTime_, actionId_: nextActionId++, parentActionId_: currentActionId }; currentActionId = runInfo.actionId_; return runInfo; } function _endAction(runInfo) { if (currentActionId !== runInfo.actionId_) { die(30); } currentActionId = runInfo.parentActionId_; if (runInfo.error_ !== undefined) { globalState.suppressReactionErrors = true; } allowStateChangesEnd(runInfo.prevAllowStateChanges_); allowStateReadsEnd(runInfo.prevAllowStateReads_); endBatch(); if (runInfo.runAsAction_) untrackedEnd(runInfo.prevDerivation_); if ( runInfo.notifySpy_) { spyReportEnd({ time: Date.now() - runInfo.startTime_ }); } globalState.suppressReactionErrors = false; } function allowStateChanges(allowStateChanges, func) { var prev = allowStateChangesStart(allowStateChanges); try { return func(); } finally { allowStateChangesEnd(prev); } } function allowStateChangesStart(allowStateChanges) { var prev = globalState.allowStateChanges; globalState.allowStateChanges = allowStateChanges; return prev; } function allowStateChangesEnd(prev) { globalState.allowStateChanges = prev; } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } it = o[Symbol.iterator](); return it.next.bind(it); } var _Symbol$toPrimitive; var CREATE = "create"; _Symbol$toPrimitive = Symbol.toPrimitive; var ObservableValue = /*#__PURE__*/function (_Atom) { _inheritsLoose(ObservableValue, _Atom); function ObservableValue(value, enhancer, name_, notifySpy, equals) { var _this; if (name_ === void 0) { name_ = "ObservableValue@" + getNextId(); } if (notifySpy === void 0) { notifySpy = true; } if (equals === void 0) { equals = comparer["default"]; } _this = _Atom.call(this, name_) || this; _this.enhancer = void 0; _this.name_ = void 0; _this.equals = void 0; _this.hasUnreportedChange_ = false; _this.interceptors_ = void 0; _this.changeListeners_ = void 0; _this.value_ = void 0; _this.dehancer = void 0; _this.enhancer = enhancer; _this.name_ = name_; _this.equals = equals; _this.value_ = enhancer(value, undefined, name_); if ( notifySpy && isSpyEnabled()) { // only notify spy if this is a stand-alone observable spyReport({ type: CREATE, object: _assertThisInitialized(_this), observableKind: "value", debugObjectName: _this.name_, newValue: "" + _this.value_ }); } return _this; } var _proto = ObservableValue.prototype; _proto.dehanceValue = function dehanceValue(value) { if (this.dehancer !== undefined) return this.dehancer(value); return value; }; _proto.set = function set(newValue) { var oldValue = this.value_; newValue = this.prepareNewValue_(newValue); if (newValue !== globalState.UNCHANGED) { var notifySpy = isSpyEnabled(); if ( notifySpy) { spyReportStart({ type: UPDATE, object: this, observableKind: "value", debugObjectName: this.name_, newValue: newValue, oldValue: oldValue }); } this.setNewValue_(newValue); if ( notifySpy) spyReportEnd(); } }; _proto.prepareNewValue_ = function prepareNewValue_(newValue) { checkIfStateModificationsAreAllowed(this); if (hasInterceptors(this)) { var change = interceptChange(this, { object: this, type: UPDATE, newValue: newValue }); if (!change) return globalState.UNCHANGED; newValue = change.newValue; } // apply modifier newValue = this.enhancer(newValue, this.value_, this.name_); return this.equals(this.value_, newValue) ? globalState.UNCHANGED : newValue; }; _proto.setNewValue_ = function setNewValue_(newValue) { var oldValue = this.value_; this.value_ = newValue; this.reportChanged(); if (hasListeners(this)) { notifyListeners(this, { type: UPDATE, object: this, newValue: newValue, oldValue: oldValue }); } }; _proto.get = function get() { this.reportObserved(); return this.dehanceValue(this.value_); }; _proto.intercept_ = function intercept_(handler) { return registerInterceptor(this, handler); }; _proto.observe_ = function observe_(listener, fireImmediately) { if (fireImmediately) listener({ observableKind: "value", debugObjectName: this.name_, object: this, type: UPDATE, newValue: this.value_, oldValue: undefined }); return registerListener(this, listener); }; _proto.raw = function raw() { // used by MST ot get undehanced value return this.value_; }; _proto.toJSON = function toJSON() { return this.get(); }; _proto.toString = function toString() { return this.name_ + "[" + this.value_ + "]"; }; _proto.valueOf = function valueOf() { return toPrimitive(this.get()); }; _proto[_Symbol$toPrimitive] = function () { return this.valueOf(); }; return ObservableValue; }(Atom); var isObservableValue = /*#__PURE__*/createInstanceofPredicate("ObservableValue", ObservableValue); var _Symbol$toPrimitive$1; /** * A node in the state dependency root that observes other nodes, and can be observed itself. * * ComputedValue will remember the result of the computation for the duration of the batch, or * while being observed. * * During this time it will recompute only when one of its direct dependencies changed, * but only when it is being accessed with `ComputedValue.get()`. * * Implementation description: * 1. First time it's being accessed it will compute and remember result * give back remembered result until 2. happens * 2. First time any deep dependency change, propagate POSSIBLY_STALE to all observers, wait for 3. * 3. When it's being accessed, recompute if any shallow dependency changed. * if result changed: propagate STALE to all observers, that were POSSIBLY_STALE from the last step. * go to step 2. either way * * If at any point it's outside batch and it isn't observed: reset everything and go to 1. */ _Symbol$toPrimitive$1 = Symbol.toPrimitive; var ComputedValue = /*#__PURE__*/function () { // nodes we are looking at. Our value depends on these nodes // during tracking it's an array with new observed observers // to check for cycles // N.B: unminified as it is used by MST /** * Create a new computed value based on a function expression. * * The `name` property is for debug purposes only. * * The `equals` property specifies the comparer function to use to determine if a newly produced * value differs from the previous value. Two comparers are provided in the library; `defaultComparer` * compares based on identity comparison (===), and `structuralComparer` deeply compares the structure. * Structural comparison can be convenient if you always produce a new aggregated object and * don't want to notify observers if it is structurally the same. * This is useful for working with vectors, mouse coordinates etc. */ function ComputedValue(options) { this.dependenciesState_ = IDerivationState_.NOT_TRACKING_; this.observing_ = []; this.newObserving_ = null; this.isBeingObserved_ = false; this.isPendingUnobservation_ = false; this.observers_ = new Set(); this.diffValue_ = 0; this.runId_ = 0; this.lastAccessedBy_ = 0; this.lowestObserverState_ = IDerivationState_.UP_TO_DATE_; this.unboundDepsCount_ = 0; this.mapid_ = "#" + getNextId(); this.value_ = new CaughtException(null); this.name_ = void 0; this.triggeredBy_ = void 0; this.isComputing_ = false; this.isRunningSetter_ = false; this.derivation = void 0; this.setter_ = void 0; this.isTracing_ = TraceMode.NONE; this.scope_ = void 0; this.equals_ = void 0; this.requiresReaction_ = void 0; this.keepAlive_ = void 0; this.onBOL = void 0; this.onBUOL = void 0; if (!options.get) die(31); this.derivation = options.get; this.name_ = options.name || "ComputedValue@" + getNextId(); if (options.set) this.setter_ = createAction(this.name_ + "-setter", options.set); this.equals_ = options.equals || (options.compareStructural || options.struct ? comparer.structural : comparer["default"]); this.scope_ = options.context; this.requiresReaction_ = !!options.requiresReaction; this.keepAlive_ = !!options.keepAlive; } var _proto = ComputedValue.prototype; _proto.onBecomeStale_ = function onBecomeStale_() { propagateMaybeChanged(this); }; _proto.onBO = function onBO() { if (this.onBOL) { this.onBOL.forEach(function (listener) { return listener(); }); } }; _proto.onBUO = function onBUO() { if (this.onBUOL) { this.onBUOL.forEach(function (listener) { return listener(); }); } } /** * Returns the current value of this computed value. * Will evaluate its computation first if needed. */ ; _proto.get = function get() { if (this.isComputing_) die(32, this.name_, this.derivation); if (globalState.inBatch === 0 && // !globalState.trackingDerivatpion && this.observers_.size === 0 && !this.keepAlive_) { if (shouldCompute(this)) { this.warnAboutUntrackedRead_(); startBatch(); // See perf test 'computed memoization' this.value_ = this.computeValue_(false); endBatch(); } } else { reportObserved(this); if (shouldCompute(this)) { var prevTrackingContext = globalState.trackingContext; if (this.keepAlive_ && !prevTrackingContext) globalState.trackingContext = this; if (this.trackAndCompute()) propagateChangeConfirmed(this); globalState.trackingContext = prevTrackingContext; } } var result = this.value_; if (isCaughtException(result)) throw result.cause; return result; }; _proto.set = function set(value) { if (this.setter_) { if (this.isRunningSetter_) die(33, this.name_); this.isRunningSetter_ = true; try { this.setter_.call(this.scope_, value); } finally { this.isRunningSetter_ = false; } } else die(34, this.name_); }; _proto.trackAndCompute = function trackAndCompute() { // N.B: unminified as it is used by MST var oldValue = this.value_; var wasSuspended = /* see #1208 */ this.dependenciesState_ === IDerivationState_.NOT_TRACKING_; var newValue = this.computeValue_(true); if ( isSpyEnabled()) { spyReport({ observableKind: "computed", debugObjectName: this.name_, object: this.scope_, type: "update", oldValue: this.value_, newValue: newValue }); } var changed = wasSuspended || isCaughtException(oldValue) || isCaughtException(newValue) || !this.equals_(oldValue, newValue); if (changed) { this.value_ = newValue; } return changed; }; _proto.computeValue_ = function computeValue_(track) { this.isComputing_ = true; // don't allow state changes during computation var prev = allowStateChangesStart(false); var res; if (track) { res = trackDerivedFunction(this, this.derivation, this.scope_); } else { if (globalState.disableErrorBoundaries === true) { res = this.derivation.call(this.scope_); } else { try { res = this.derivation.call(this.scope_); } catch (e) { res = new CaughtException(e); } } } allowStateChangesEnd(prev); this.isComputing_ = false; return res; }; _proto.suspend_ = function suspend_() { if (!this.keepAlive_) { clearObserving(this); this.value_ = undefined; // don't hold on to computed value! } }; _proto.observe_ = function observe_(listener, fireImmediately) { var _this = this; var firstTime = true; var prevValue = undefined; return autorun(function () { // TODO: why is this in a different place than the spyReport() function? in all other observables it's called in the same place var newValue = _this.get(); if (!firstTime || fireImmediately) { var prevU = untrackedStart(); listener({ observableKind: "computed", debugObjectName: _this.name_, type: UPDATE, object: _this, newValue: newValue, oldValue: prevValue }); untrackedEnd(prevU); } firstTime = false; prevValue = newValue; }); }; _proto.warnAboutUntrackedRead_ = function warnAboutUntrackedRead_() { if (this.requiresReaction_ === true) { die("[mobx] Computed value " + this.name_ + " is read outside a reactive context"); } if (this.isTracing_ !== TraceMode.NONE) { console.log("[mobx.trace] '" + this.name_ + "' is being read outside a reactive context. Doing a full recompute"); } if (globalState.computedRequiresReaction) { console.warn("[mobx] Computed value " + this.name_ + " is being read outside a reactive context. Doing a full recompute"); } }; _proto.toString = function toString() { return this.name_ + "[" + this.derivation.toString() + "]"; }; _proto.valueOf = function valueOf() { return toPrimitive(this.get()); }; _proto[_Symbol$toPrimitive$1] = function () { return this.valueOf(); }; return ComputedValue; }(); var isComputedValue = /*#__PURE__*/createInstanceofPredicate("ComputedValue", ComputedValue); var IDerivationState_; (function (IDerivationState_) { // before being run or (outside batch and not being observed) // at this point derivation is not holding any data about dependency tree IDerivationState_[IDerivationState_["NOT_TRACKING_"] = -1] = "NOT_TRACKING_"; // no shallow dependency changed since last computation // won't recalculate derivation // this is what makes mobx fast IDerivationState_[IDerivationState_["UP_TO_DATE_"] = 0] = "UP_TO_DATE_"; // some deep dependency changed, but don't know if shallow dependency changed // will require to check first if UP_TO_DATE or POSSIBLY_STALE // currently only ComputedValue will propagate POSSIBLY_STALE // // having this state is second big optimization: // don't have to recompute on every dependency change, but only when it's needed IDerivationState_[IDerivationState_["POSSIBLY_STALE_"] = 1] = "POSSIBLY_STALE_"; // A shallow dependency has changed since last computation and the derivation // will need to recompute when it's needed next. IDerivationState_[IDerivationState_["STALE_"] = 2] = "STALE_"; })(IDerivationState_ || (IDerivationState_ = {})); var TraceMode; (function (TraceMode) { TraceMode[TraceMode["NONE"] = 0] = "NONE"; TraceMode[TraceMode["LOG"] = 1] = "LOG"; TraceMode[TraceMode["BREAK"] = 2] = "BREAK"; })(TraceMode || (TraceMode = {})); var CaughtException = function CaughtException(cause) { this.cause = void 0; this.cause = cause; // Empty }; function isCaughtException(e) { return e instanceof CaughtException; } /** * Finds out whether any dependency of the derivation has actually changed. * If dependenciesState is 1 then it will recalculate dependencies, * if any dependency changed it will propagate it by changing dependenciesState to 2. * * By iterating over the dependencies in the same order that they were reported and * stopping on the first change, all the recalculations are only called for ComputedValues * that will be tracked by derivation. That is because we assume that if the first x * dependencies of the derivation doesn't change then the derivation should run the same way * up until accessing x-th dependency. */ function shouldCompute(derivation) { switch (derivation.dependenciesState_) { case IDerivationState_.UP_TO_DATE_: return false; case IDerivationState_.NOT_TRACKING_: case IDerivationState_.STALE_: return true; case IDerivationState_.POSSIBLY_STALE_: { // state propagation can occur outside of action/reactive context #2195 var prevAllowStateReads = allowStateReadsStart(true); var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction. var obs = derivation.observing_, l = obs.length; for (var i = 0; i < l; i++) { var obj = obs[i]; if (isComputedValue(obj)) { if (globalState.disableErrorBoundaries) { obj.get(); } else { try { obj.get(); } catch (e) { // we are not interested in the value *or* exception at this moment, but if there is one, notify all untrackedEnd(prevUntracked); allowStateReadsEnd(prevAllowStateReads); return true; } } // if ComputedValue `obj` actually changed it will be computed and propagated to its observers. // and `derivation` is an observer of `obj` // invariantShouldCompute(derivation) if (derivation.dependenciesState_ === IDerivationState_.STALE_) { untrackedEnd(prevUntracked); allowStateReadsEnd(prevAllowStateReads); return true; } } } changeDependenciesStateTo0(derivation); untrackedEnd(prevUntracked); allowStateReadsEnd(prevAllowStateReads); return false; } } } function isComputingDerivation() { return globalState.trackingDerivation !== null; // filter out actions inside computations } function checkIfStateModificationsAreAllowed(atom) { var hasObservers = atom.observers_.size > 0; // Should not be possible to change observed state outside strict mode, except during initialization, see #563 if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "always")) console.warn("[MobX] " + (globalState.enforceActions ? "Since strict-mode is enabled, changing (observed) observable values without using an action is not allowed. Tried to modify: " : "Side effects like changing state are not allowed at this point. Are you trying to modify state from, for example, a computed value or the render function of a React component? You can wrap side effects in 'runInAction' (or decorate functions with 'action') if needed. Tried to modify: ") + atom.name_); } function checkIfStateReadsAreAllowed(observable) { if ( !globalState.allowStateReads && globalState.observableRequiresReaction) { console.warn("[mobx] Observable " + observable.name_ + " being read outside a reactive context"); } } /** * Executes the provided function `f` and tracks which observables are being accessed. * The tracking information is stored on the `derivation` object and the derivation is registered * as observer of any of the accessed observables. */ function trackDerivedFunction(derivation, f, context) { var prevAllowStateReads = allowStateReadsStart(true); // pre allocate array allocation + room for variation in deps // array will be trimmed by bindDependencies changeDependenciesStateTo0(derivation); derivation.newObserving_ = new Array(derivation.observing_.length + 100); derivation.unboundDepsCount_ = 0; derivation.runId_ = ++globalState.runId; var prevTracking = globalState.trackingDerivation; globalState.trackingDerivation = derivation; globalState.inBatch++; var result; if (globalState.disableErrorBoundaries === true) { result = f.call(context); } else { try { result = f.call(context); } catch (e) { result = new CaughtException(e); } } globalState.inBatch--; globalState.trackingDerivation = prevTracking; bindDependencies(derivation); warnAboutDerivationWithoutDependencies(derivation); allowStateReadsEnd(prevAllowStateReads); return result; } function warnAboutDerivationWithoutDependencies(derivation) { if (derivation.observing_.length !== 0) return; if (globalState.reactionRequiresObservable || derivation.requiresObservable_) { console.warn("[mobx] Derivation " + derivation.name_ + " is created/updated without reading any observable value"); } } /** * diffs newObserving with observing. * update observing to be newObserving with unique observables * notify observers that become observed/unobserved */ function bindDependencies(derivation) { // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1"); var prevObserving = derivation.observing_; var observing = derivation.observing_ = derivation.newObserving_; var lowestNewObservingDerivationState = IDerivationState_.UP_TO_DATE_; // Go through all new observables and check diffValue: (this list can contain duplicates): // 0: first occurrence, change to 1 and keep it // 1: extra occurrence, drop it var i0 = 0, l = derivation.unboundDepsCount_; for (var i = 0; i < l; i++) { var dep = observing[i]; if (dep.diffValue_ === 0) { dep.diffValue_ = 1; if (i0 !== i) observing[i0] = dep; i0++; } // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined, // not hitting the condition if (dep.dependenciesState_ > lowestNewObservingDerivationState) { lowestNewObservingDerivationState = dep.dependenciesState_; } } observing.length = i0; derivation.newObserving_ = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614) // Go through all old observables and check diffValue: (it is unique after last bindDependencies) // 0: it's not in new observables, unobserve it // 1: it keeps being observed, don't want to notify it. change to 0 l = prevObserving.length; while (l--) { var _dep = prevObserving[l]; if (_dep.diffValue_ === 0) { removeObserver(_dep, derivation); } _dep.diffValue_ = 0; } // Go through all new observables and check diffValue: (now it should be unique) // 0: it was set to 0 in last loop. don't need to do anything. // 1: it wasn't observed, let's observe it. set back to 0 while (i0--) { var _dep2 = observing[i0]; if (_dep2.diffValue_ === 1) { _dep2.diffValue_ = 0; addObserver(_dep2, derivation); } } // Some new observed derivations may become stale during this derivation computation // so they have had no chance to propagate staleness (#916) if (lowestNewObservingDerivationState !== IDerivationState_.UP_TO_DATE_) { derivation.dependenciesState_ = lowestNewObservingDerivationState; derivation.onBecomeStale_(); } } function clearObserving(derivation) { // invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch"); var obs = derivation.observing_; derivation.observing_ = []; var i = obs.length; while (i--) { removeObserver(obs[i], derivation); } derivation.dependenciesState_ = IDerivationState_.NOT_TRACKING_; } function untracked(action) { var prev = untrackedStart(); try { return action(); } finally { untrackedEnd(prev); } } function untrackedStart() { var prev = globalState.trackingDerivation; globalState.trackingDerivation = null; return prev; } function untrackedEnd(prev) { globalState.trackingDerivation = prev; } function allowStateReadsStart(allowStateReads) { var prev = globalState.allowStateReads; globalState.allowStateReads = allowStateReads; return prev; } function allowStateReadsEnd(prev) { globalState.allowStateReads = prev; } /** * needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0 * */ function changeDependenciesStateTo0(derivation) { if (derivation.dependenciesState_ === IDerivationState_.UP_TO_DATE_) return; derivation.dependenciesState_ = IDerivationState_.UP_TO_DATE_; var obs = derivation.observing_; var i = obs.length; while (i--) { obs[i].lowestObserverState_ = IDerivationState_.UP_TO_DATE_; } } /** * These values will persist if global state is reset */ var persistentKeys = ["mobxGuid", "spyListeners", "enforceActions", "computedRequiresReaction", "reactionRequiresObservable", "observableRequiresReaction", "allowStateReads", "disableErrorBoundaries", "runId", "UNCHANGED", "useProxies"]; var MobXGlobals = function MobXGlobals() { this.version = 6; this.UNCHANGED = {}; this.tracki