UNPKG

144 kBJavaScriptView Raw
1/** MobX - (c) Michel Weststrate 2015, 2016 - MIT Licensed */
2/*! *****************************************************************************
3Copyright (c) Microsoft Corporation. All rights reserved.
4Licensed under the Apache License, Version 2.0 (the "License"); you may not use
5this file except in compliance with the License. You may obtain a copy of the
6License at http://www.apache.org/licenses/LICENSE-2.0
7
8THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
9KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
10WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
11MERCHANTABLITY OR NON-INFRINGEMENT.
12
13See the Apache Version 2.0 License for specific language governing permissions
14and limitations under the License.
15***************************************************************************** */
16/* global Reflect, Promise */
17
18var extendStatics = Object.setPrototypeOf ||
19 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
20 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
21
22function __extends(d, b) {
23 extendStatics(d, b);
24 function __() { this.constructor = d; }
25 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
26}
27
28/**
29 * Anything that can be used to _store_ state is an Atom in mobx. Atoms have two important jobs
30 *
31 * 1) detect when they are being _used_ and report this (using reportObserved). This allows mobx to make the connection between running functions and the data they used
32 * 2) they should notify mobx whenever they have _changed_. This way mobx can re-run any functions (derivations) that are using this atom.
33 */
34var BaseAtom = (function () {
35 /**
36 * Create a new atom. For debugging purposes it is recommended to give it a name.
37 * The onBecomeObserved and onBecomeUnobserved callbacks can be used for resource management.
38 */
39 function BaseAtom(name) {
40 if (name === void 0) { name = "Atom@" + getNextId(); }
41 this.name = name;
42 this.isPendingUnobservation = true; // for effective unobserving. BaseAtom has true, for extra optimization, so its onBecomeUnobserved never gets called, because it's not needed
43 this.observers = [];
44 this.observersIndexes = {};
45 this.diffValue = 0;
46 this.lastAccessedBy = 0;
47 this.lowestObserverState = IDerivationState.NOT_TRACKING;
48 }
49 BaseAtom.prototype.onBecomeUnobserved = function () {
50 // noop
51 };
52 /**
53 * Invoke this method to notify mobx that your atom has been used somehow.
54 */
55 BaseAtom.prototype.reportObserved = function () {
56 reportObserved(this);
57 };
58 /**
59 * Invoke this method _after_ this method has changed to signal mobx that all its observers should invalidate.
60 */
61 BaseAtom.prototype.reportChanged = function () {
62 startBatch();
63 propagateChanged(this);
64 endBatch();
65 };
66 BaseAtom.prototype.toString = function () {
67 return this.name;
68 };
69 return BaseAtom;
70}());
71var Atom = (function (_super) {
72 __extends(Atom, _super);
73 /**
74 * Create a new atom. For debugging purposes it is recommended to give it a name.
75 * The onBecomeObserved and onBecomeUnobserved callbacks can be used for resource management.
76 */
77 function Atom(name, onBecomeObservedHandler, onBecomeUnobservedHandler) {
78 if (name === void 0) { name = "Atom@" + getNextId(); }
79 if (onBecomeObservedHandler === void 0) { onBecomeObservedHandler = noop; }
80 if (onBecomeUnobservedHandler === void 0) { onBecomeUnobservedHandler = noop; }
81 var _this = _super.call(this, name) || this;
82 _this.name = name;
83 _this.onBecomeObservedHandler = onBecomeObservedHandler;
84 _this.onBecomeUnobservedHandler = onBecomeUnobservedHandler;
85 _this.isPendingUnobservation = false; // for effective unobserving.
86 _this.isBeingTracked = false;
87 return _this;
88 }
89 Atom.prototype.reportObserved = function () {
90 startBatch();
91 _super.prototype.reportObserved.call(this);
92 if (!this.isBeingTracked) {
93 this.isBeingTracked = true;
94 this.onBecomeObservedHandler();
95 }
96 endBatch();
97 return !!globalState.trackingDerivation;
98 // return doesn't really give useful info, because it can be as well calling computed which calls atom (no reactions)
99 // also it could not trigger when calculating reaction dependent on Atom because Atom's value was cached by computed called by given reaction.
100 };
101 Atom.prototype.onBecomeUnobserved = function () {
102 this.isBeingTracked = false;
103 this.onBecomeUnobservedHandler();
104 };
105 return Atom;
106}(BaseAtom));
107var isAtom = createInstanceofPredicate("Atom", BaseAtom);
108
109function hasInterceptors(interceptable) {
110 return interceptable.interceptors && interceptable.interceptors.length > 0;
111}
112function registerInterceptor(interceptable, handler) {
113 var interceptors = interceptable.interceptors || (interceptable.interceptors = []);
114 interceptors.push(handler);
115 return once(function () {
116 var idx = interceptors.indexOf(handler);
117 if (idx !== -1)
118 interceptors.splice(idx, 1);
119 });
120}
121function interceptChange(interceptable, change) {
122 var prevU = untrackedStart();
123 try {
124 var interceptors = interceptable.interceptors;
125 if (interceptors)
126 for (var i = 0, l = interceptors.length; i < l; i++) {
127 change = interceptors[i](change);
128 invariant(!change || change.type, "Intercept handlers should return nothing or a change object");
129 if (!change)
130 break;
131 }
132 return change;
133 }
134 finally {
135 untrackedEnd(prevU);
136 }
137}
138
139function hasListeners(listenable) {
140 return listenable.changeListeners && listenable.changeListeners.length > 0;
141}
142function registerListener(listenable, handler) {
143 var listeners = listenable.changeListeners || (listenable.changeListeners = []);
144 listeners.push(handler);
145 return once(function () {
146 var idx = listeners.indexOf(handler);
147 if (idx !== -1)
148 listeners.splice(idx, 1);
149 });
150}
151function notifyListeners(listenable, change) {
152 var prevU = untrackedStart();
153 var listeners = listenable.changeListeners;
154 if (!listeners)
155 return;
156 listeners = listeners.slice();
157 for (var i = 0, l = listeners.length; i < l; i++) {
158 listeners[i](change);
159 }
160 untrackedEnd(prevU);
161}
162
163function isSpyEnabled() {
164 return !!globalState.spyListeners.length;
165}
166function spyReport(event) {
167 if (!globalState.spyListeners.length)
168 return;
169 var listeners = globalState.spyListeners;
170 for (var i = 0, l = listeners.length; i < l; i++)
171 listeners[i](event);
172}
173function spyReportStart(event) {
174 var change = objectAssign({}, event, { spyReportStart: true });
175 spyReport(change);
176}
177var END_EVENT = { spyReportEnd: true };
178function spyReportEnd(change) {
179 if (change)
180 spyReport(objectAssign({}, change, END_EVENT));
181 else
182 spyReport(END_EVENT);
183}
184function spy(listener) {
185 globalState.spyListeners.push(listener);
186 return once(function () {
187 var idx = globalState.spyListeners.indexOf(listener);
188 if (idx !== -1)
189 globalState.spyListeners.splice(idx, 1);
190 });
191}
192
193function iteratorSymbol() {
194 return (typeof Symbol === "function" && Symbol.iterator) || "@@iterator";
195}
196var IS_ITERATING_MARKER = "__$$iterating";
197function arrayAsIterator(array) {
198 // returning an array for entries(), values() etc for maps was a mis-interpretation of the specs..,
199 // yet it is quite convenient to be able to use the response both as array directly and as iterator
200 // it is suboptimal, but alas...
201 invariant(array[IS_ITERATING_MARKER] !== true, "Illegal state: cannot recycle array as iterator");
202 addHiddenFinalProp(array, IS_ITERATING_MARKER, true);
203 var idx = -1;
204 addHiddenFinalProp(array, "next", function next() {
205 idx++;
206 return {
207 done: idx >= this.length,
208 value: idx < this.length ? this[idx] : undefined
209 };
210 });
211 return array;
212}
213function declareIterator(prototType, iteratorFactory) {
214 addHiddenFinalProp(prototType, iteratorSymbol(), iteratorFactory);
215}
216
217var MAX_SPLICE_SIZE = 10000; // See e.g. https://github.com/mobxjs/mobx/issues/859
218// Detects bug in safari 9.1.1 (or iOS 9 safari mobile). See #364
219var safariPrototypeSetterInheritanceBug = (function () {
220 var v = false;
221 var p = {};
222 Object.defineProperty(p, "0", {
223 set: function () {
224 v = true;
225 }
226 });
227 Object.create(p)["0"] = 1;
228 return v === false;
229})();
230/**
231 * This array buffer contains two lists of properties, so that all arrays
232 * can recycle their property definitions, which significantly improves performance of creating
233 * properties on the fly.
234 */
235var OBSERVABLE_ARRAY_BUFFER_SIZE = 0;
236// Typescript workaround to make sure ObservableArray extends Array
237var StubArray = (function () {
238 function StubArray() {
239 }
240 return StubArray;
241}());
242function inherit(ctor, proto) {
243 if (typeof Object["setPrototypeOf"] !== "undefined") {
244 Object["setPrototypeOf"](ctor.prototype, proto);
245 }
246 else if (typeof ctor.prototype.__proto__ !== "undefined") {
247 ctor.prototype.__proto__ = proto;
248 }
249 else {
250 ctor["prototype"] = proto;
251 }
252}
253inherit(StubArray, Array.prototype);
254// Weex freeze Array.prototype
255// Make them writeable and configurable in prototype chain
256// https://github.com/alibaba/weex/pull/1529
257if (Object.isFrozen(Array)) {
258
259 [
260 "constructor",
261 "push",
262 "shift",
263 "concat",
264 "pop",
265 "unshift",
266 "replace",
267 "find",
268 "findIndex",
269 "splice",
270 "reverse",
271 "sort"
272 ].forEach(function (key) {
273 Object.defineProperty(StubArray.prototype, key, {
274 configurable: true,
275 writable: true,
276 value: Array.prototype[key]
277 });
278 });
279}
280var ObservableArrayAdministration = (function () {
281 function ObservableArrayAdministration(name, enhancer, array, owned) {
282 this.array = array;
283 this.owned = owned;
284 this.values = [];
285 this.lastKnownLength = 0;
286 this.interceptors = null;
287 this.changeListeners = null;
288 this.atom = new BaseAtom(name || "ObservableArray@" + getNextId());
289 this.enhancer = function (newV, oldV) { return enhancer(newV, oldV, name + "[..]"); };
290 }
291 ObservableArrayAdministration.prototype.dehanceValue = function (value) {
292 if (this.dehancer !== undefined)
293 return this.dehancer(value);
294 return value;
295 };
296 ObservableArrayAdministration.prototype.dehanceValues = function (values) {
297 if (this.dehancer !== undefined)
298 return values.map(this.dehancer);
299 return values;
300 };
301 ObservableArrayAdministration.prototype.intercept = function (handler) {
302 return registerInterceptor(this, handler);
303 };
304 ObservableArrayAdministration.prototype.observe = function (listener, fireImmediately) {
305 if (fireImmediately === void 0) { fireImmediately = false; }
306 if (fireImmediately) {
307 listener({
308 object: this.array,
309 type: "splice",
310 index: 0,
311 added: this.values.slice(),
312 addedCount: this.values.length,
313 removed: [],
314 removedCount: 0
315 });
316 }
317 return registerListener(this, listener);
318 };
319 ObservableArrayAdministration.prototype.getArrayLength = function () {
320 this.atom.reportObserved();
321 return this.values.length;
322 };
323 ObservableArrayAdministration.prototype.setArrayLength = function (newLength) {
324 if (typeof newLength !== "number" || newLength < 0)
325 throw new Error("[mobx.array] Out of range: " + newLength);
326 var currentLength = this.values.length;
327 if (newLength === currentLength)
328 return;
329 else if (newLength > currentLength) {
330 var newItems = new Array(newLength - currentLength);
331 for (var i = 0; i < newLength - currentLength; i++)
332 newItems[i] = undefined; // No Array.fill everywhere...
333 this.spliceWithArray(currentLength, 0, newItems);
334 }
335 else
336 this.spliceWithArray(newLength, currentLength - newLength);
337 };
338 // adds / removes the necessary numeric properties to this object
339 ObservableArrayAdministration.prototype.updateArrayLength = function (oldLength, delta) {
340 if (oldLength !== this.lastKnownLength)
341 throw new Error("[mobx] Modification exception: the internal structure of an observable array was changed. Did you use peek() to change it?");
342 this.lastKnownLength += delta;
343 if (delta > 0 && oldLength + delta + 1 > OBSERVABLE_ARRAY_BUFFER_SIZE)
344 reserveArrayBuffer(oldLength + delta + 1);
345 };
346 ObservableArrayAdministration.prototype.spliceWithArray = function (index, deleteCount, newItems) {
347 var _this = this;
348 checkIfStateModificationsAreAllowed(this.atom);
349 var length = this.values.length;
350 if (index === undefined)
351 index = 0;
352 else if (index > length)
353 index = length;
354 else if (index < 0)
355 index = Math.max(0, length + index);
356 if (arguments.length === 1)
357 deleteCount = length - index;
358 else if (deleteCount === undefined || deleteCount === null)
359 deleteCount = 0;
360 else
361 deleteCount = Math.max(0, Math.min(deleteCount, length - index));
362 if (newItems === undefined)
363 newItems = [];
364 if (hasInterceptors(this)) {
365 var change = interceptChange(this, {
366 object: this.array,
367 type: "splice",
368 index: index,
369 removedCount: deleteCount,
370 added: newItems
371 });
372 if (!change)
373 return EMPTY_ARRAY;
374 deleteCount = change.removedCount;
375 newItems = change.added;
376 }
377 newItems = newItems.map(function (v) { return _this.enhancer(v, undefined); });
378 var lengthDelta = newItems.length - deleteCount;
379 this.updateArrayLength(length, lengthDelta); // create or remove new entries
380 var res = this.spliceItemsIntoValues(index, deleteCount, newItems);
381 if (deleteCount !== 0 || newItems.length !== 0)
382 this.notifyArraySplice(index, newItems, res);
383 return this.dehanceValues(res);
384 };
385 ObservableArrayAdministration.prototype.spliceItemsIntoValues = function (index, deleteCount, newItems) {
386 if (newItems.length < MAX_SPLICE_SIZE) {
387 return (_a = this.values).splice.apply(_a, [index, deleteCount].concat(newItems));
388 }
389 else {
390 var res = this.values.slice(index, index + deleteCount);
391 this.values = this.values
392 .slice(0, index)
393 .concat(newItems, this.values.slice(index + deleteCount));
394 return res;
395 }
396 var _a;
397 };
398 ObservableArrayAdministration.prototype.notifyArrayChildUpdate = function (index, newValue, oldValue) {
399 var notifySpy = !this.owned && isSpyEnabled();
400 var notify = hasListeners(this);
401 var change = notify || notifySpy
402 ? {
403 object: this.array,
404 type: "update",
405 index: index,
406 newValue: newValue,
407 oldValue: oldValue
408 }
409 : null;
410 if (notifySpy)
411 spyReportStart(change);
412 this.atom.reportChanged();
413 if (notify)
414 notifyListeners(this, change);
415 if (notifySpy)
416 spyReportEnd();
417 };
418 ObservableArrayAdministration.prototype.notifyArraySplice = function (index, added, removed) {
419 var notifySpy = !this.owned && isSpyEnabled();
420 var notify = hasListeners(this);
421 var change = notify || notifySpy
422 ? {
423 object: this.array,
424 type: "splice",
425 index: index,
426 removed: removed,
427 added: added,
428 removedCount: removed.length,
429 addedCount: added.length
430 }
431 : null;
432 if (notifySpy)
433 spyReportStart(change);
434 this.atom.reportChanged();
435 // conform: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/observe
436 if (notify)
437 notifyListeners(this, change);
438 if (notifySpy)
439 spyReportEnd();
440 };
441 return ObservableArrayAdministration;
442}());
443var ObservableArray = (function (_super) {
444 __extends(ObservableArray, _super);
445 function ObservableArray(initialValues, enhancer, name, owned) {
446 if (name === void 0) { name = "ObservableArray@" + getNextId(); }
447 if (owned === void 0) { owned = false; }
448 var _this = _super.call(this) || this;
449 var adm = new ObservableArrayAdministration(name, enhancer, _this, owned);
450 addHiddenFinalProp(_this, "$mobx", adm);
451 if (initialValues && initialValues.length) {
452 _this.spliceWithArray(0, 0, initialValues);
453 }
454 if (safariPrototypeSetterInheritanceBug) {
455 // Seems that Safari won't use numeric prototype setter untill any * numeric property is
456 // defined on the instance. After that it works fine, even if this property is deleted.
457 Object.defineProperty(adm.array, "0", ENTRY_0);
458 }
459 return _this;
460 }
461 ObservableArray.prototype.intercept = function (handler) {
462 return this.$mobx.intercept(handler);
463 };
464 ObservableArray.prototype.observe = function (listener, fireImmediately) {
465 if (fireImmediately === void 0) { fireImmediately = false; }
466 return this.$mobx.observe(listener, fireImmediately);
467 };
468 ObservableArray.prototype.clear = function () {
469 return this.splice(0);
470 };
471 ObservableArray.prototype.concat = function () {
472 var arrays = [];
473 for (var _i = 0; _i < arguments.length; _i++) {
474 arrays[_i] = arguments[_i];
475 }
476 this.$mobx.atom.reportObserved();
477 return Array.prototype.concat.apply(this.peek(), arrays.map(function (a) { return (isObservableArray(a) ? a.peek() : a); }));
478 };
479 ObservableArray.prototype.replace = function (newItems) {
480 return this.$mobx.spliceWithArray(0, this.$mobx.values.length, newItems);
481 };
482 /**
483 * Converts this array back to a (shallow) javascript structure.
484 * For a deep clone use mobx.toJS
485 */
486 ObservableArray.prototype.toJS = function () {
487 return this.slice();
488 };
489 ObservableArray.prototype.toJSON = function () {
490 // Used by JSON.stringify
491 return this.toJS();
492 };
493 ObservableArray.prototype.peek = function () {
494 this.$mobx.atom.reportObserved();
495 return this.$mobx.dehanceValues(this.$mobx.values);
496 };
497 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
498 ObservableArray.prototype.find = function (predicate, thisArg, fromIndex) {
499 if (fromIndex === void 0) { fromIndex = 0; }
500 var idx = this.findIndex.apply(this, arguments);
501 return idx === -1 ? undefined : this.get(idx);
502 };
503 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex
504 ObservableArray.prototype.findIndex = function (predicate, thisArg, fromIndex) {
505 if (fromIndex === void 0) { fromIndex = 0; }
506 var items = this.peek(), l = items.length;
507 for (var i = fromIndex; i < l; i++)
508 if (predicate.call(thisArg, items[i], i, this))
509 return i;
510 return -1;
511 };
512 /*
513 * functions that do alter the internal structure of the array, (based on lib.es6.d.ts)
514 * since these functions alter the inner structure of the array, the have side effects.
515 * Because the have side effects, they should not be used in computed function,
516 * and for that reason the do not call dependencyState.notifyObserved
517 */
518 ObservableArray.prototype.splice = function (index, deleteCount) {
519 var newItems = [];
520 for (var _i = 2; _i < arguments.length; _i++) {
521 newItems[_i - 2] = arguments[_i];
522 }
523 switch (arguments.length) {
524 case 0:
525 return [];
526 case 1:
527 return this.$mobx.spliceWithArray(index);
528 case 2:
529 return this.$mobx.spliceWithArray(index, deleteCount);
530 }
531 return this.$mobx.spliceWithArray(index, deleteCount, newItems);
532 };
533 ObservableArray.prototype.spliceWithArray = function (index, deleteCount, newItems) {
534 return this.$mobx.spliceWithArray(index, deleteCount, newItems);
535 };
536 ObservableArray.prototype.push = function () {
537 var items = [];
538 for (var _i = 0; _i < arguments.length; _i++) {
539 items[_i] = arguments[_i];
540 }
541 var adm = this.$mobx;
542 adm.spliceWithArray(adm.values.length, 0, items);
543 return adm.values.length;
544 };
545 ObservableArray.prototype.pop = function () {
546 return this.splice(Math.max(this.$mobx.values.length - 1, 0), 1)[0];
547 };
548 ObservableArray.prototype.shift = function () {
549 return this.splice(0, 1)[0];
550 };
551 ObservableArray.prototype.unshift = function () {
552 var items = [];
553 for (var _i = 0; _i < arguments.length; _i++) {
554 items[_i] = arguments[_i];
555 }
556 var adm = this.$mobx;
557 adm.spliceWithArray(0, 0, items);
558 return adm.values.length;
559 };
560 ObservableArray.prototype.reverse = function () {
561 // reverse by default mutates in place before returning the result
562 // which makes it both a 'derivation' and a 'mutation'.
563 // so we deviate from the default and just make it an dervitation
564 var clone = this.slice();
565 return clone.reverse.apply(clone, arguments);
566 };
567 ObservableArray.prototype.sort = function (compareFn) {
568 // sort by default mutates in place before returning the result
569 // which goes against all good practices. Let's not change the array in place!
570 var clone = this.slice();
571 return clone.sort.apply(clone, arguments);
572 };
573 ObservableArray.prototype.remove = function (value) {
574 var idx = this.$mobx.dehanceValues(this.$mobx.values).indexOf(value);
575 if (idx > -1) {
576 this.splice(idx, 1);
577 return true;
578 }
579 return false;
580 };
581 ObservableArray.prototype.move = function (fromIndex, toIndex) {
582 function checkIndex(index) {
583 if (index < 0) {
584 throw new Error("[mobx.array] Index out of bounds: " + index + " is negative");
585 }
586 var length = this.$mobx.values.length;
587 if (index >= length) {
588 throw new Error("[mobx.array] Index out of bounds: " + index + " is not smaller than " + length);
589 }
590 }
591 checkIndex.call(this, fromIndex);
592 checkIndex.call(this, toIndex);
593 if (fromIndex === toIndex) {
594 return;
595 }
596 var oldItems = this.$mobx.values;
597 var newItems;
598 if (fromIndex < toIndex) {
599 newItems = oldItems.slice(0, fromIndex).concat(oldItems.slice(fromIndex + 1, toIndex + 1), [
600 oldItems[fromIndex]
601 ], oldItems.slice(toIndex + 1));
602 }
603 else {
604 // toIndex < fromIndex
605 newItems = oldItems.slice(0, toIndex).concat([
606 oldItems[fromIndex]
607 ], oldItems.slice(toIndex, fromIndex), oldItems.slice(fromIndex + 1));
608 }
609 this.replace(newItems);
610 };
611 // See #734, in case property accessors are unreliable...
612 ObservableArray.prototype.get = function (index) {
613 var impl = this.$mobx;
614 if (impl) {
615 if (index < impl.values.length) {
616 impl.atom.reportObserved();
617 return impl.dehanceValue(impl.values[index]);
618 }
619 console.warn("[mobx.array] Attempt to read an array index (" + index + ") that is out of bounds (" + impl
620 .values
621 .length + "). Please check length first. Out of bound indices will not be tracked by MobX");
622 }
623 return undefined;
624 };
625 // See #734, in case property accessors are unreliable...
626 ObservableArray.prototype.set = function (index, newValue) {
627 var adm = this.$mobx;
628 var values = adm.values;
629 if (index < values.length) {
630 // update at index in range
631 checkIfStateModificationsAreAllowed(adm.atom);
632 var oldValue = values[index];
633 if (hasInterceptors(adm)) {
634 var change = interceptChange(adm, {
635 type: "update",
636 object: this,
637 index: index,
638 newValue: newValue
639 });
640 if (!change)
641 return;
642 newValue = change.newValue;
643 }
644 newValue = adm.enhancer(newValue, oldValue);
645 var changed = newValue !== oldValue;
646 if (changed) {
647 values[index] = newValue;
648 adm.notifyArrayChildUpdate(index, newValue, oldValue);
649 }
650 }
651 else if (index === values.length) {
652 // add a new item
653 adm.spliceWithArray(index, 0, [newValue]);
654 }
655 else {
656 // out of bounds
657 throw new Error("[mobx.array] Index out of bounds, " + index + " is larger than " + values.length);
658 }
659 };
660 return ObservableArray;
661}(StubArray));
662declareIterator(ObservableArray.prototype, function () {
663 return arrayAsIterator(this.slice());
664});
665Object.defineProperty(ObservableArray.prototype, "length", {
666 enumerable: false,
667 configurable: true,
668 get: function () {
669 return this.$mobx.getArrayLength();
670 },
671 set: function (newLength) {
672 this.$mobx.setArrayLength(newLength);
673 }
674});
675[
676 "every",
677 "filter",
678 "forEach",
679 "indexOf",
680 "join",
681 "lastIndexOf",
682 "map",
683 "reduce",
684 "reduceRight",
685 "slice",
686 "some",
687 "toString",
688 "toLocaleString"
689].forEach(function (funcName) {
690 var baseFunc = Array.prototype[funcName];
691 invariant(typeof baseFunc === "function", "Base function not defined on Array prototype: '" + funcName + "'");
692 addHiddenProp(ObservableArray.prototype, funcName, function () {
693 return baseFunc.apply(this.peek(), arguments);
694 });
695});
696/**
697 * We don't want those to show up in `for (const key in ar)` ...
698 */
699makeNonEnumerable(ObservableArray.prototype, [
700 "constructor",
701 "intercept",
702 "observe",
703 "clear",
704 "concat",
705 "get",
706 "replace",
707 "toJS",
708 "toJSON",
709 "peek",
710 "find",
711 "findIndex",
712 "splice",
713 "spliceWithArray",
714 "push",
715 "pop",
716 "set",
717 "shift",
718 "unshift",
719 "reverse",
720 "sort",
721 "remove",
722 "move",
723 "toString",
724 "toLocaleString"
725]);
726// See #364
727var ENTRY_0 = createArrayEntryDescriptor(0);
728function createArrayEntryDescriptor(index) {
729 return {
730 enumerable: false,
731 configurable: false,
732 get: function () {
733 // TODO: Check `this`?, see #752?
734 return this.get(index);
735 },
736 set: function (value) {
737 this.set(index, value);
738 }
739 };
740}
741function createArrayBufferItem(index) {
742 Object.defineProperty(ObservableArray.prototype, "" + index, createArrayEntryDescriptor(index));
743}
744function reserveArrayBuffer(max) {
745 for (var index = OBSERVABLE_ARRAY_BUFFER_SIZE; index < max; index++)
746 createArrayBufferItem(index);
747 OBSERVABLE_ARRAY_BUFFER_SIZE = max;
748}
749reserveArrayBuffer(1000);
750var isObservableArrayAdministration = createInstanceofPredicate("ObservableArrayAdministration", ObservableArrayAdministration);
751function isObservableArray(thing) {
752 return isObject(thing) && isObservableArrayAdministration(thing.$mobx);
753}
754
755var UNCHANGED = {};
756var ObservableValue = (function (_super) {
757 __extends(ObservableValue, _super);
758 function ObservableValue(value, enhancer, name, notifySpy) {
759 if (name === void 0) { name = "ObservableValue@" + getNextId(); }
760 if (notifySpy === void 0) { notifySpy = true; }
761 var _this = _super.call(this, name) || this;
762 _this.enhancer = enhancer;
763 _this.hasUnreportedChange = false;
764 _this.dehancer = undefined;
765 _this.value = enhancer(value, undefined, name);
766 if (notifySpy && isSpyEnabled()) {
767 // only notify spy if this is a stand-alone observable
768 spyReport({ type: "create", object: _this, newValue: _this.value });
769 }
770 return _this;
771 }
772 ObservableValue.prototype.dehanceValue = function (value) {
773 if (this.dehancer !== undefined)
774 return this.dehancer(value);
775 return value;
776 };
777 ObservableValue.prototype.set = function (newValue) {
778 var oldValue = this.value;
779 newValue = this.prepareNewValue(newValue);
780 if (newValue !== UNCHANGED) {
781 var notifySpy = isSpyEnabled();
782 if (notifySpy) {
783 spyReportStart({
784 type: "update",
785 object: this,
786 newValue: newValue,
787 oldValue: oldValue
788 });
789 }
790 this.setNewValue(newValue);
791 if (notifySpy)
792 spyReportEnd();
793 }
794 };
795 ObservableValue.prototype.prepareNewValue = function (newValue) {
796 checkIfStateModificationsAreAllowed(this);
797 if (hasInterceptors(this)) {
798 var change = interceptChange(this, {
799 object: this,
800 type: "update",
801 newValue: newValue
802 });
803 if (!change)
804 return UNCHANGED;
805 newValue = change.newValue;
806 }
807 // apply modifier
808 newValue = this.enhancer(newValue, this.value, this.name);
809 return this.value !== newValue ? newValue : UNCHANGED;
810 };
811 ObservableValue.prototype.setNewValue = function (newValue) {
812 var oldValue = this.value;
813 this.value = newValue;
814 this.reportChanged();
815 if (hasListeners(this)) {
816 notifyListeners(this, {
817 type: "update",
818 object: this,
819 newValue: newValue,
820 oldValue: oldValue
821 });
822 }
823 };
824 ObservableValue.prototype.get = function () {
825 this.reportObserved();
826 return this.dehanceValue(this.value);
827 };
828 ObservableValue.prototype.intercept = function (handler) {
829 return registerInterceptor(this, handler);
830 };
831 ObservableValue.prototype.observe = function (listener, fireImmediately) {
832 if (fireImmediately)
833 listener({
834 object: this,
835 type: "update",
836 newValue: this.value,
837 oldValue: undefined
838 });
839 return registerListener(this, listener);
840 };
841 ObservableValue.prototype.toJSON = function () {
842 return this.get();
843 };
844 ObservableValue.prototype.toString = function () {
845 return this.name + "[" + this.value + "]";
846 };
847 ObservableValue.prototype.valueOf = function () {
848 return toPrimitive(this.get());
849 };
850 return ObservableValue;
851}(BaseAtom));
852ObservableValue.prototype[primitiveSymbol()] = ObservableValue.prototype.valueOf;
853var isObservableValue = createInstanceofPredicate("ObservableValue", ObservableValue);
854
855var messages = {
856 m001: "It is not allowed to assign new values to @action fields",
857 m002: "`runInAction` expects a function",
858 m003: "`runInAction` expects a function without arguments",
859 m004: "autorun expects a function",
860 m005: "Warning: attempted to pass an action to autorun. Actions are untracked and will not trigger on state changes. Use `reaction` or wrap only your state modification code in an action.",
861 m006: "Warning: attempted to pass an action to autorunAsync. Actions are untracked and will not trigger on state changes. Use `reaction` or wrap only your state modification code in an action.",
862 m007: "reaction only accepts 2 or 3 arguments. If migrating from MobX 2, please provide an options object",
863 m008: "wrapping reaction expression in `asReference` is no longer supported, use options object instead",
864 m009: "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'. It looks like it was used on a property.",
865 m010: "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'",
866 m011: "First argument to `computed` should be an expression. If using computed as decorator, don't pass it arguments",
867 m012: "computed takes one or two arguments if used as function",
868 m013: "[mobx.expr] 'expr' should only be used inside other reactive functions.",
869 m014: "extendObservable expected 2 or more arguments",
870 m015: "extendObservable expects an object as first argument",
871 m016: "extendObservable should not be used on maps, use map.merge instead",
872 m017: "all arguments of extendObservable should be objects",
873 m018: "extending an object with another observable (object) is not supported. Please construct an explicit propertymap, using `toJS` if need. See issue #540",
874 m019: "[mobx.isObservable] isObservable(object, propertyName) is not supported for arrays and maps. Use map.has or array.length instead.",
875 m020: "modifiers can only be used for individual object properties",
876 m021: "observable expects zero or one arguments",
877 m022: "@observable can not be used on getters, use @computed instead",
878 m024: "whyRun() can only be used if a derivation is active, or by passing an computed value / reaction explicitly. If you invoked whyRun from inside a computation; the computation is currently suspended but re-evaluating because somebody requested its value.",
879 m025: "whyRun can only be used on reactions and computed values",
880 m026: "`action` can only be invoked on functions",
881 m028: "It is not allowed to set `useStrict` when a derivation is running",
882 m029: "INTERNAL ERROR only onBecomeUnobserved shouldn't be called twice in a row",
883 m030a: "Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: ",
884 m030b: "Side effects like changing state are not allowed at this point. Are you trying to modify state from, for example, the render function of a React component? Tried to modify: ",
885 m031: "Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: ",
886 m032: "* This computation is suspended (not in use by any reaction) and won't run automatically.\n Didn't expect this computation to be suspended at this point?\n 1. Make sure this computation is used by a reaction (reaction, autorun, observer).\n 2. Check whether you are using this computation synchronously (in the same stack as they reaction that needs it).",
887 m033: "`observe` doesn't support the fire immediately property for observable maps.",
888 m034: "`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead",
889 m035: "Cannot make the designated object observable; it is not extensible",
890 m036: "It is not possible to get index atoms from arrays",
891 m037: "Hi there! I'm sorry you have just run into an exception.\nIf your debugger ends up here, know that some reaction (like the render() of an observer component, autorun or reaction)\nthrew an exception and that mobx caught it, to avoid that it brings the rest of your application down.\nThe original cause of the exception (the code that caused this reaction to run (again)), is still in the stack.\n\nHowever, more interesting is the actual stack trace of the error itself.\nHopefully the error is an instanceof Error, because in that case you can inspect the original stack of the error from where it was thrown.\nSee `error.stack` property, or press the very subtle \"(...)\" link you see near the console.error message that probably brought you here.\nThat stack is more interesting than the stack of this console.error itself.\n\nIf the exception you see is an exception you created yourself, make sure to use `throw new Error(\"Oops\")` instead of `throw \"Oops\"`,\nbecause the javascript environment will only preserve the original stack trace in the first form.\n\nYou can also make sure the debugger pauses the next time this very same exception is thrown by enabling \"Pause on caught exception\".\n(Note that it might pause on many other, unrelated exception as well).\n\nIf that all doesn't help you out, feel free to open an issue https://github.com/mobxjs/mobx/issues!\n",
892 m038: "Missing items in this list?\n 1. Check whether all used values are properly marked as observable (use isObservable to verify)\n 2. Make sure you didn't dereference values too early. MobX observes props, not primitives. E.g: use 'person.name' instead of 'name' in your computation.\n"
893};
894function getMessage(id) {
895 return messages[id];
896}
897
898function createAction(actionName, fn) {
899 invariant(typeof fn === "function", getMessage("m026"));
900 invariant(typeof actionName === "string" && actionName.length > 0, "actions should have valid names, got: '" + actionName + "'");
901 var res = function () {
902 return executeAction(actionName, fn, this, arguments);
903 };
904 res.originalFn = fn;
905 res.isMobxAction = true;
906 return res;
907}
908function executeAction(actionName, fn, scope, args) {
909 var runInfo = startAction(actionName, fn, scope, args);
910 try {
911 return fn.apply(scope, args);
912 }
913 finally {
914 endAction(runInfo);
915 }
916}
917function startAction(actionName, fn, scope, args) {
918 var notifySpy = isSpyEnabled() && !!actionName;
919 var startTime = 0;
920 if (notifySpy) {
921 startTime = Date.now();
922 var l = (args && args.length) || 0;
923 var flattendArgs = new Array(l);
924 if (l > 0)
925 for (var i = 0; i < l; i++)
926 flattendArgs[i] = args[i];
927 spyReportStart({
928 type: "action",
929 name: actionName,
930 fn: fn,
931 object: scope,
932 arguments: flattendArgs
933 });
934 }
935 var prevDerivation = untrackedStart();
936 startBatch();
937 var prevAllowStateChanges = allowStateChangesStart(true);
938 return {
939 prevDerivation: prevDerivation,
940 prevAllowStateChanges: prevAllowStateChanges,
941 notifySpy: notifySpy,
942 startTime: startTime
943 };
944}
945function endAction(runInfo) {
946 allowStateChangesEnd(runInfo.prevAllowStateChanges);
947 endBatch();
948 untrackedEnd(runInfo.prevDerivation);
949 if (runInfo.notifySpy)
950 spyReportEnd({ time: Date.now() - runInfo.startTime });
951}
952function useStrict(strict) {
953 invariant(globalState.trackingDerivation === null, getMessage("m028"));
954 globalState.strictMode = strict;
955 globalState.allowStateChanges = !strict;
956}
957function isStrictModeEnabled() {
958 return globalState.strictMode;
959}
960function allowStateChanges(allowStateChanges, func) {
961 // TODO: deprecate / refactor this function in next major
962 // Currently only used by `@observer`
963 // Proposed change: remove first param, rename to `forbidStateChanges`,
964 // require error callback instead of the hardcoded error message now used
965 // Use `inAction` instead of allowStateChanges in derivation.ts to check strictMode
966 var prev = allowStateChangesStart(allowStateChanges);
967 var res;
968 try {
969 res = func();
970 }
971 finally {
972 allowStateChangesEnd(prev);
973 }
974 return res;
975}
976function allowStateChangesStart(allowStateChanges) {
977 var prev = globalState.allowStateChanges;
978 globalState.allowStateChanges = allowStateChanges;
979 return prev;
980}
981function allowStateChangesEnd(prev) {
982 globalState.allowStateChanges = prev;
983}
984
985/**
986 * Constructs a decorator, that normalizes the differences between
987 * TypeScript and Babel. Mainly caused by the fact that legacy-decorator cannot assign
988 * values during instance creation to properties that have a getter setter.
989 *
990 * - Sigh -
991 *
992 * Also takes care of the difference between @decorator field and @decorator(args) field, and different forms of values.
993 * For performance (cpu and mem) reasons the properties are always defined on the prototype (at least initially).
994 * This means that these properties despite being enumerable might not show up in Object.keys() (but they will show up in for...in loops).
995 */
996function createClassPropertyDecorator(
997 /**
998 * This function is invoked once, when the property is added to a new instance.
999 * When this happens is not strictly determined due to differences in TS and Babel:
1000 * Typescript: Usually when constructing the new instance
1001 * Babel, sometimes Typescript: during the first get / set
1002 * Both: when calling `runLazyInitializers(instance)`
1003 */
1004 onInitialize, get, set, enumerable,
1005 /**
1006 * Can this decorator invoked with arguments? e.g. @decorator(args)
1007 */
1008 allowCustomArguments) {
1009 function classPropertyDecorator(target, key, descriptor, customArgs, argLen) {
1010 if (argLen === void 0) { argLen = 0; }
1011 invariant(allowCustomArguments || quacksLikeADecorator(arguments), "This function is a decorator, but it wasn't invoked like a decorator");
1012 if (!descriptor) {
1013 // typescript (except for getter / setters)
1014 var newDescriptor = {
1015 enumerable: enumerable,
1016 configurable: true,
1017 get: function () {
1018 if (!this.__mobxInitializedProps || this.__mobxInitializedProps[key] !== true)
1019 typescriptInitializeProperty(this, key, undefined, onInitialize, customArgs, descriptor);
1020 return get.call(this, key);
1021 },
1022 set: function (v) {
1023 if (!this.__mobxInitializedProps || this.__mobxInitializedProps[key] !== true) {
1024 typescriptInitializeProperty(this, key, v, onInitialize, customArgs, descriptor);
1025 }
1026 else {
1027 set.call(this, key, v);
1028 }
1029 }
1030 };
1031 if (arguments.length < 3 || (arguments.length === 5 && argLen < 3)) {
1032 // Typescript target is ES3, so it won't define property for us
1033 // or using Reflect.decorate polyfill, which will return no descriptor
1034 // (see https://github.com/mobxjs/mobx/issues/333)
1035 Object.defineProperty(target, key, newDescriptor);
1036 }
1037 return newDescriptor;
1038 }
1039 else {
1040 // babel and typescript getter / setter props
1041 if (!hasOwnProperty(target, "__mobxLazyInitializers")) {
1042 addHiddenProp(target, "__mobxLazyInitializers", (target.__mobxLazyInitializers && target.__mobxLazyInitializers.slice()) || [] // support inheritance
1043 );
1044 }
1045 var value_1 = descriptor.value, initializer_1 = descriptor.initializer;
1046 target.__mobxLazyInitializers.push(function (instance) {
1047 onInitialize(instance, key, initializer_1 ? initializer_1.call(instance) : value_1, customArgs, descriptor);
1048 });
1049 return {
1050 enumerable: enumerable,
1051 configurable: true,
1052 get: function () {
1053 if (this.__mobxDidRunLazyInitializers !== true)
1054 runLazyInitializers(this);
1055 return get.call(this, key);
1056 },
1057 set: function (v) {
1058 if (this.__mobxDidRunLazyInitializers !== true)
1059 runLazyInitializers(this);
1060 set.call(this, key, v);
1061 }
1062 };
1063 }
1064 }
1065 if (allowCustomArguments) {
1066 /** If custom arguments are allowed, we should return a function that returns a decorator */
1067 return function () {
1068 /** Direct invocation: @decorator bla */
1069 if (quacksLikeADecorator(arguments))
1070 return classPropertyDecorator.apply(null, arguments);
1071 /** Indirect invocation: @decorator(args) bla */
1072 var outerArgs = arguments;
1073 var argLen = arguments.length;
1074 return function (target, key, descriptor) {
1075 return classPropertyDecorator(target, key, descriptor, outerArgs, argLen);
1076 };
1077 };
1078 }
1079 return classPropertyDecorator;
1080}
1081function typescriptInitializeProperty(instance, key, v, onInitialize, customArgs, baseDescriptor) {
1082 if (!hasOwnProperty(instance, "__mobxInitializedProps"))
1083 addHiddenProp(instance, "__mobxInitializedProps", {});
1084 instance.__mobxInitializedProps[key] = true;
1085 onInitialize(instance, key, v, customArgs, baseDescriptor);
1086}
1087function runLazyInitializers(instance) {
1088 if (instance.__mobxDidRunLazyInitializers === true)
1089 return;
1090 if (instance.__mobxLazyInitializers) {
1091 addHiddenProp(instance, "__mobxDidRunLazyInitializers", true);
1092 instance.__mobxDidRunLazyInitializers &&
1093 instance.__mobxLazyInitializers.forEach(function (initializer) { return initializer(instance); });
1094 }
1095}
1096function quacksLikeADecorator(args) {
1097 return (args.length === 2 || args.length === 3) && typeof args[1] === "string";
1098}
1099
1100var actionFieldDecorator = createClassPropertyDecorator(function (target, key, value, args, originalDescriptor) {
1101 var actionName = args && args.length === 1 ? args[0] : value.name || key || "<unnamed action>";
1102 var wrappedAction = action(actionName, value);
1103 addHiddenProp(target, key, wrappedAction);
1104}, function (key) {
1105 return this[key];
1106}, function () {
1107 invariant(false, getMessage("m001"));
1108}, false, true);
1109var boundActionDecorator = createClassPropertyDecorator(function (target, key, value) {
1110 defineBoundAction(target, key, value);
1111}, function (key) {
1112 return this[key];
1113}, function () {
1114 invariant(false, getMessage("m001"));
1115}, false, false);
1116var action = function action(arg1, arg2, arg3, arg4) {
1117 if (arguments.length === 1 && typeof arg1 === "function")
1118 return createAction(arg1.name || "<unnamed action>", arg1);
1119 if (arguments.length === 2 && typeof arg2 === "function")
1120 return createAction(arg1, arg2);
1121 if (arguments.length === 1 && typeof arg1 === "string")
1122 return namedActionDecorator(arg1);
1123 return namedActionDecorator(arg2).apply(null, arguments);
1124};
1125action.bound = function boundAction(arg1, arg2, arg3) {
1126 if (typeof arg1 === "function") {
1127 var action_1 = createAction("<not yet bound action>", arg1);
1128 action_1.autoBind = true;
1129 return action_1;
1130 }
1131 return boundActionDecorator.apply(null, arguments);
1132};
1133function namedActionDecorator(name) {
1134 return function (target, prop, descriptor) {
1135 if (descriptor && typeof descriptor.value === "function") {
1136 // TypeScript @action method() { }. Defined on proto before being decorated
1137 // Don't use the field decorator if we are just decorating a method
1138 descriptor.value = createAction(name, descriptor.value);
1139 descriptor.enumerable = false;
1140 descriptor.configurable = true;
1141 return descriptor;
1142 }
1143 if (descriptor !== undefined && descriptor.get !== undefined) {
1144 throw new Error("[mobx] action is not expected to be used with getters");
1145 }
1146 // bound instance methods
1147 return actionFieldDecorator(name).apply(this, arguments);
1148 };
1149}
1150function runInAction(arg1, arg2, arg3) {
1151 var actionName = typeof arg1 === "string" ? arg1 : arg1.name || "<unnamed action>";
1152 var fn = typeof arg1 === "function" ? arg1 : arg2;
1153 var scope = typeof arg1 === "function" ? arg2 : arg3;
1154 invariant(typeof fn === "function", getMessage("m002"));
1155 invariant(fn.length === 0, getMessage("m003"));
1156 invariant(typeof actionName === "string" && actionName.length > 0, "actions should have valid names, got: '" + actionName + "'");
1157 return executeAction(actionName, fn, scope, undefined);
1158}
1159function isAction(thing) {
1160 return typeof thing === "function" && thing.isMobxAction === true;
1161}
1162function defineBoundAction(target, propertyName, fn) {
1163 var res = function () {
1164 return executeAction(propertyName, fn, target, arguments);
1165 };
1166 res.isMobxAction = true;
1167 addHiddenProp(target, propertyName, res);
1168}
1169
1170function identityComparer(a, b) {
1171 return a === b;
1172}
1173function structuralComparer(a, b) {
1174 if (typeof a === "number" && typeof b === "number" && isNaN(a) && isNaN(b)) {
1175 return true;
1176 }
1177 return deepEqual(a, b);
1178}
1179function defaultComparer(a, b) {
1180 if (typeof a === "number" && typeof b === "number" && isNaN(a) && isNaN(b)) {
1181 return true;
1182 }
1183 return identityComparer(a, b);
1184}
1185var comparer = {
1186 identity: identityComparer,
1187 structural: structuralComparer,
1188 default: defaultComparer
1189};
1190
1191function autorun(arg1, arg2, arg3) {
1192 var name, view, scope;
1193 if (typeof arg1 === "string") {
1194 name = arg1;
1195 view = arg2;
1196 scope = arg3;
1197 }
1198 else {
1199 name = arg1.name || "Autorun@" + getNextId();
1200 view = arg1;
1201 scope = arg2;
1202 }
1203 invariant(typeof view === "function", getMessage("m004"));
1204 invariant(isAction(view) === false, getMessage("m005"));
1205 if (scope)
1206 view = view.bind(scope);
1207 var reaction = new Reaction(name, function () {
1208 this.track(reactionRunner);
1209 });
1210 function reactionRunner() {
1211 view(reaction);
1212 }
1213 reaction.schedule();
1214 return reaction.getDisposer();
1215}
1216function when(arg1, arg2, arg3, arg4) {
1217 var name, predicate, effect, scope;
1218 if (typeof arg1 === "string") {
1219 name = arg1;
1220 predicate = arg2;
1221 effect = arg3;
1222 scope = arg4;
1223 }
1224 else {
1225 name = "When@" + getNextId();
1226 predicate = arg1;
1227 effect = arg2;
1228 scope = arg3;
1229 }
1230 var disposer = autorun(name, function (r) {
1231 if (predicate.call(scope)) {
1232 r.dispose();
1233 var prevUntracked = untrackedStart();
1234 effect.call(scope);
1235 untrackedEnd(prevUntracked);
1236 }
1237 });
1238 return disposer;
1239}
1240function autorunAsync(arg1, arg2, arg3, arg4) {
1241 var name, func, delay, scope;
1242 if (typeof arg1 === "string") {
1243 name = arg1;
1244 func = arg2;
1245 delay = arg3;
1246 scope = arg4;
1247 }
1248 else {
1249 name = arg1.name || "AutorunAsync@" + getNextId();
1250 func = arg1;
1251 delay = arg2;
1252 scope = arg3;
1253 }
1254 invariant(isAction(func) === false, getMessage("m006"));
1255 if (delay === void 0)
1256 delay = 1;
1257 if (scope)
1258 func = func.bind(scope);
1259 var isScheduled = false;
1260 var r = new Reaction(name, function () {
1261 if (!isScheduled) {
1262 isScheduled = true;
1263 setTimeout(function () {
1264 isScheduled = false;
1265 if (!r.isDisposed)
1266 r.track(reactionRunner);
1267 }, delay);
1268 }
1269 });
1270 function reactionRunner() {
1271 func(r);
1272 }
1273 r.schedule();
1274 return r.getDisposer();
1275}
1276function reaction(expression, effect, arg3) {
1277 if (arguments.length > 3) {
1278 fail(getMessage("m007"));
1279 }
1280 if (isModifierDescriptor(expression)) {
1281 fail(getMessage("m008"));
1282 }
1283 var opts;
1284 if (typeof arg3 === "object") {
1285 opts = arg3;
1286 }
1287 else {
1288 opts = {};
1289 }
1290 opts.name =
1291 opts.name || expression.name || effect.name || "Reaction@" + getNextId();
1292 opts.fireImmediately = arg3 === true || opts.fireImmediately === true;
1293 opts.delay = opts.delay || 0;
1294 opts.compareStructural = opts.compareStructural || opts.struct || false;
1295 // TODO: creates ugly spy events, use `effect = (r) => runInAction(opts.name, () => effect(r))` instead
1296 effect = action(opts.name, opts.context ? effect.bind(opts.context) : effect);
1297 if (opts.context) {
1298 expression = expression.bind(opts.context);
1299 }
1300 var firstTime = true;
1301 var isScheduled = false;
1302 var value;
1303 var equals = opts.equals
1304 ? opts.equals
1305 : opts.compareStructural || opts.struct ? comparer.structural : comparer.default;
1306 var r = new Reaction(opts.name, function () {
1307 if (firstTime || opts.delay < 1) {
1308 reactionRunner();
1309 }
1310 else if (!isScheduled) {
1311 isScheduled = true;
1312 setTimeout(function () {
1313 isScheduled = false;
1314 reactionRunner();
1315 }, opts.delay);
1316 }
1317 });
1318 function reactionRunner() {
1319 if (r.isDisposed)
1320 return;
1321 var changed = false;
1322 r.track(function () {
1323 var nextValue = expression(r);
1324 changed = firstTime || !equals(value, nextValue);
1325 value = nextValue;
1326 });
1327 if (firstTime && opts.fireImmediately)
1328 effect(value, r);
1329 if (!firstTime && changed === true)
1330 effect(value, r);
1331 if (firstTime)
1332 firstTime = false;
1333 }
1334 r.schedule();
1335 return r.getDisposer();
1336}
1337
1338/**
1339 * A node in the state dependency root that observes other nodes, and can be observed itself.
1340 *
1341 * ComputedValue will remember the result of the computation for the duration of the batch, or
1342 * while being observed.
1343 *
1344 * During this time it will recompute only when one of its direct dependencies changed,
1345 * but only when it is being accessed with `ComputedValue.get()`.
1346 *
1347 * Implementation description:
1348 * 1. First time it's being accessed it will compute and remember result
1349 * give back remembered result until 2. happens
1350 * 2. First time any deep dependency change, propagate POSSIBLY_STALE to all observers, wait for 3.
1351 * 3. When it's being accessed, recompute if any shallow dependency changed.
1352 * if result changed: propagate STALE to all observers, that were POSSIBLY_STALE from the last step.
1353 * go to step 2. either way
1354 *
1355 * If at any point it's outside batch and it isn't observed: reset everything and go to 1.
1356 */
1357var ComputedValue = (function () {
1358 /**
1359 * Create a new computed value based on a function expression.
1360 *
1361 * The `name` property is for debug purposes only.
1362 *
1363 * The `equals` property specifies the comparer function to use to determine if a newly produced
1364 * value differs from the previous value. Two comparers are provided in the library; `defaultComparer`
1365 * compares based on identity comparison (===), and `structualComparer` deeply compares the structure.
1366 * Structural comparison can be convenient if you always produce an new aggregated object and
1367 * don't want to notify observers if it is structurally the same.
1368 * This is useful for working with vectors, mouse coordinates etc.
1369 */
1370 function ComputedValue(derivation, scope, equals, name, setter) {
1371 this.derivation = derivation;
1372 this.scope = scope;
1373 this.equals = equals;
1374 this.dependenciesState = IDerivationState.NOT_TRACKING;
1375 this.observing = []; // nodes we are looking at. Our value depends on these nodes
1376 this.newObserving = null; // during tracking it's an array with new observed observers
1377 this.isPendingUnobservation = false;
1378 this.observers = [];
1379 this.observersIndexes = {};
1380 this.diffValue = 0;
1381 this.runId = 0;
1382 this.lastAccessedBy = 0;
1383 this.lowestObserverState = IDerivationState.UP_TO_DATE;
1384 this.unboundDepsCount = 0;
1385 this.__mapid = "#" + getNextId();
1386 this.value = new CaughtException(null);
1387 this.isComputing = false; // to check for cycles
1388 this.isRunningSetter = false;
1389 this.name = name || "ComputedValue@" + getNextId();
1390 if (setter)
1391 this.setter = createAction(name + "-setter", setter);
1392 }
1393 ComputedValue.prototype.onBecomeStale = function () {
1394 propagateMaybeChanged(this);
1395 };
1396 ComputedValue.prototype.onBecomeUnobserved = function () {
1397 clearObserving(this);
1398 this.value = undefined;
1399 };
1400 /**
1401 * Returns the current value of this computed value.
1402 * Will evaluate its computation first if needed.
1403 */
1404 ComputedValue.prototype.get = function () {
1405 invariant(!this.isComputing, "Cycle detected in computation " + this.name, this.derivation);
1406 if (globalState.inBatch === 0) {
1407 // This is an minor optimization which could be omitted to simplify the code
1408 // The computedValue is accessed outside of any mobx stuff. Batch observing should be enough and don't need
1409 // tracking as it will never be called again inside this batch.
1410 startBatch();
1411 if (shouldCompute(this))
1412 this.value = this.computeValue(false);
1413 endBatch();
1414 }
1415 else {
1416 reportObserved(this);
1417 if (shouldCompute(this))
1418 if (this.trackAndCompute())
1419 propagateChangeConfirmed(this);
1420 }
1421 var result = this.value;
1422 if (isCaughtException(result))
1423 throw result.cause;
1424 return result;
1425 };
1426 ComputedValue.prototype.peek = function () {
1427 var res = this.computeValue(false);
1428 if (isCaughtException(res))
1429 throw res.cause;
1430 return res;
1431 };
1432 ComputedValue.prototype.set = function (value) {
1433 if (this.setter) {
1434 invariant(!this.isRunningSetter, "The setter of computed value '" + this
1435 .name + "' is trying to update itself. Did you intend to update an _observable_ value, instead of the computed property?");
1436 this.isRunningSetter = true;
1437 try {
1438 this.setter.call(this.scope, value);
1439 }
1440 finally {
1441 this.isRunningSetter = false;
1442 }
1443 }
1444 else
1445 invariant(false, "[ComputedValue '" + this
1446 .name + "'] It is not possible to assign a new value to a computed value.");
1447 };
1448 ComputedValue.prototype.trackAndCompute = function () {
1449 if (isSpyEnabled()) {
1450 spyReport({
1451 object: this.scope,
1452 type: "compute",
1453 fn: this.derivation
1454 });
1455 }
1456 var oldValue = this.value;
1457 var newValue = (this.value = this.computeValue(true));
1458 return (isCaughtException(oldValue) ||
1459 isCaughtException(newValue) ||
1460 !this.equals(oldValue, newValue));
1461 };
1462 ComputedValue.prototype.computeValue = function (track) {
1463 this.isComputing = true;
1464 globalState.computationDepth++;
1465 var res;
1466 if (track) {
1467 res = trackDerivedFunction(this, this.derivation, this.scope);
1468 }
1469 else {
1470 try {
1471 res = this.derivation.call(this.scope);
1472 }
1473 catch (e) {
1474 res = new CaughtException(e);
1475 }
1476 }
1477 globalState.computationDepth--;
1478 this.isComputing = false;
1479 return res;
1480 };
1481 ComputedValue.prototype.observe = function (listener, fireImmediately) {
1482 var _this = this;
1483 var firstTime = true;
1484 var prevValue = undefined;
1485 return autorun(function () {
1486 var newValue = _this.get();
1487 if (!firstTime || fireImmediately) {
1488 var prevU = untrackedStart();
1489 listener({
1490 type: "update",
1491 object: _this,
1492 newValue: newValue,
1493 oldValue: prevValue
1494 });
1495 untrackedEnd(prevU);
1496 }
1497 firstTime = false;
1498 prevValue = newValue;
1499 });
1500 };
1501 ComputedValue.prototype.toJSON = function () {
1502 return this.get();
1503 };
1504 ComputedValue.prototype.toString = function () {
1505 return this.name + "[" + this.derivation.toString() + "]";
1506 };
1507 ComputedValue.prototype.valueOf = function () {
1508 return toPrimitive(this.get());
1509 };
1510 ComputedValue.prototype.whyRun = function () {
1511 var isTracking = Boolean(globalState.trackingDerivation);
1512 var observing = unique(this.isComputing ? this.newObserving : this.observing).map(function (dep) { return dep.name; });
1513 var observers = unique(getObservers(this).map(function (dep) { return dep.name; }));
1514 return ("\nWhyRun? computation '" + this.name + "':\n * Running because: " + (isTracking
1515 ? "[active] the value of this computation is needed by a reaction"
1516 : this.isComputing
1517 ? "[get] The value of this computed was requested outside a reaction"
1518 : "[idle] not running at the moment") + "\n" +
1519 (this.dependenciesState === IDerivationState.NOT_TRACKING
1520 ? getMessage("m032")
1521 : " * This computation will re-run if any of the following observables changes:\n " + joinStrings(observing) + "\n " + (this.isComputing && isTracking
1522 ? " (... or any observable accessed during the remainder of the current run)"
1523 : "") + "\n\t" + getMessage("m038") + "\n\n * If the outcome of this computation changes, the following observers will be re-run:\n " + joinStrings(observers) + "\n"));
1524 };
1525 return ComputedValue;
1526}());
1527ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
1528var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
1529
1530var ObservableObjectAdministration = (function () {
1531 function ObservableObjectAdministration(target, name) {
1532 this.target = target;
1533 this.name = name;
1534 this.values = {};
1535 this.changeListeners = null;
1536 this.interceptors = null;
1537 }
1538 /**
1539 * Observes this object. Triggers for the events 'add', 'update' and 'delete'.
1540 * See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/observe
1541 * for callback details
1542 */
1543 ObservableObjectAdministration.prototype.observe = function (callback, fireImmediately) {
1544 invariant(fireImmediately !== true, "`observe` doesn't support the fire immediately property for observable objects.");
1545 return registerListener(this, callback);
1546 };
1547 ObservableObjectAdministration.prototype.intercept = function (handler) {
1548 return registerInterceptor(this, handler);
1549 };
1550 return ObservableObjectAdministration;
1551}());
1552function asObservableObject(target, name) {
1553 if (isObservableObject(target) && target.hasOwnProperty("$mobx"))
1554 return target.$mobx;
1555 invariant(Object.isExtensible(target), getMessage("m035"));
1556 if (!isPlainObject(target))
1557 name = (target.constructor.name || "ObservableObject") + "@" + getNextId();
1558 if (!name)
1559 name = "ObservableObject@" + getNextId();
1560 var adm = new ObservableObjectAdministration(target, name);
1561 addHiddenFinalProp(target, "$mobx", adm);
1562 return adm;
1563}
1564function defineObservablePropertyFromDescriptor(adm, propName, descriptor, defaultEnhancer) {
1565 if (adm.values[propName] && !isComputedValue(adm.values[propName])) {
1566 // already observable property
1567 invariant("value" in descriptor, "The property " + propName + " in " + adm.name + " is already observable, cannot redefine it as computed property");
1568 adm.target[propName] = descriptor.value; // the property setter will make 'value' reactive if needed.
1569 return;
1570 }
1571 // not yet observable property
1572 if ("value" in descriptor) {
1573 // not a computed value
1574 if (isModifierDescriptor(descriptor.value)) {
1575 // x : ref(someValue)
1576 var modifierDescriptor = descriptor.value;
1577 defineObservableProperty(adm, propName, modifierDescriptor.initialValue, modifierDescriptor.enhancer);
1578 }
1579 else if (isAction(descriptor.value) && descriptor.value.autoBind === true) {
1580 defineBoundAction(adm.target, propName, descriptor.value.originalFn);
1581 }
1582 else if (isComputedValue(descriptor.value)) {
1583 // x: computed(someExpr)
1584 defineComputedPropertyFromComputedValue(adm, propName, descriptor.value);
1585 }
1586 else {
1587 // x: someValue
1588 defineObservableProperty(adm, propName, descriptor.value, defaultEnhancer);
1589 }
1590 }
1591 else {
1592 // get x() { return 3 } set x(v) { }
1593 defineComputedProperty(adm, propName, descriptor.get, descriptor.set, comparer.default, true);
1594 }
1595}
1596function defineObservableProperty(adm, propName, newValue, enhancer) {
1597 assertPropertyConfigurable(adm.target, propName);
1598 if (hasInterceptors(adm)) {
1599 var change = interceptChange(adm, {
1600 object: adm.target,
1601 name: propName,
1602 type: "add",
1603 newValue: newValue
1604 });
1605 if (!change)
1606 return;
1607 newValue = change.newValue;
1608 }
1609 var observable = (adm.values[propName] = new ObservableValue(newValue, enhancer, adm.name + "." + propName, false));
1610 newValue = observable.value; // observableValue might have changed it
1611 Object.defineProperty(adm.target, propName, generateObservablePropConfig(propName));
1612 notifyPropertyAddition(adm, adm.target, propName, newValue);
1613}
1614function defineComputedProperty(adm, propName, getter, setter, equals, asInstanceProperty) {
1615 if (asInstanceProperty)
1616 assertPropertyConfigurable(adm.target, propName);
1617 adm.values[propName] = new ComputedValue(getter, adm.target, equals, adm.name + "." + propName, setter);
1618 if (asInstanceProperty) {
1619 Object.defineProperty(adm.target, propName, generateComputedPropConfig(propName));
1620 }
1621}
1622function defineComputedPropertyFromComputedValue(adm, propName, computedValue) {
1623 var name = adm.name + "." + propName;
1624 computedValue.name = name;
1625 if (!computedValue.scope)
1626 computedValue.scope = adm.target;
1627 adm.values[propName] = computedValue;
1628 Object.defineProperty(adm.target, propName, generateComputedPropConfig(propName));
1629}
1630var observablePropertyConfigs = {};
1631var computedPropertyConfigs = {};
1632function generateObservablePropConfig(propName) {
1633 return (observablePropertyConfigs[propName] ||
1634 (observablePropertyConfigs[propName] = {
1635 configurable: true,
1636 enumerable: true,
1637 get: function () {
1638 return this.$mobx.values[propName].get();
1639 },
1640 set: function (v) {
1641 setPropertyValue(this, propName, v);
1642 }
1643 }));
1644}
1645function generateComputedPropConfig(propName) {
1646 return (computedPropertyConfigs[propName] ||
1647 (computedPropertyConfigs[propName] = {
1648 configurable: true,
1649 enumerable: false,
1650 get: function () {
1651 return this.$mobx.values[propName].get();
1652 },
1653 set: function (v) {
1654 return this.$mobx.values[propName].set(v);
1655 }
1656 }));
1657}
1658function setPropertyValue(instance, name, newValue) {
1659 var adm = instance.$mobx;
1660 var observable = adm.values[name];
1661 // intercept
1662 if (hasInterceptors(adm)) {
1663 var change = interceptChange(adm, {
1664 type: "update",
1665 object: instance,
1666 name: name,
1667 newValue: newValue
1668 });
1669 if (!change)
1670 return;
1671 newValue = change.newValue;
1672 }
1673 newValue = observable.prepareNewValue(newValue);
1674 // notify spy & observers
1675 if (newValue !== UNCHANGED) {
1676 var notify = hasListeners(adm);
1677 var notifySpy = isSpyEnabled();
1678 var change = notify || notifySpy
1679 ? {
1680 type: "update",
1681 object: instance,
1682 oldValue: observable.value,
1683 name: name,
1684 newValue: newValue
1685 }
1686 : null;
1687 if (notifySpy)
1688 spyReportStart(change);
1689 observable.setNewValue(newValue);
1690 if (notify)
1691 notifyListeners(adm, change);
1692 if (notifySpy)
1693 spyReportEnd();
1694 }
1695}
1696function notifyPropertyAddition(adm, object, name, newValue) {
1697 var notify = hasListeners(adm);
1698 var notifySpy = isSpyEnabled();
1699 var change = notify || notifySpy
1700 ? {
1701 type: "add",
1702 object: object,
1703 name: name,
1704 newValue: newValue
1705 }
1706 : null;
1707 if (notifySpy)
1708 spyReportStart(change);
1709 if (notify)
1710 notifyListeners(adm, change);
1711 if (notifySpy)
1712 spyReportEnd();
1713}
1714var isObservableObjectAdministration = createInstanceofPredicate("ObservableObjectAdministration", ObservableObjectAdministration);
1715function isObservableObject(thing) {
1716 if (isObject(thing)) {
1717 // Initializers run lazily when transpiling to babel, so make sure they are run...
1718 runLazyInitializers(thing);
1719 return isObservableObjectAdministration(thing.$mobx);
1720 }
1721 return false;
1722}
1723
1724/**
1725 * Returns true if the provided value is reactive.
1726 * @param value object, function or array
1727 * @param property if property is specified, checks whether value.property is reactive.
1728 */
1729function isObservable(value, property) {
1730 if (value === null || value === undefined)
1731 return false;
1732 if (property !== undefined) {
1733 if (isObservableArray(value) || isObservableMap(value))
1734 throw new Error(getMessage("m019"));
1735 else if (isObservableObject(value)) {
1736 var o = value.$mobx;
1737 return o.values && !!o.values[property];
1738 }
1739 return false;
1740 }
1741 // For first check, see #701
1742 return (isObservableObject(value) ||
1743 !!value.$mobx ||
1744 isAtom(value) ||
1745 isReaction(value) ||
1746 isComputedValue(value));
1747}
1748
1749function createDecoratorForEnhancer(enhancer) {
1750 invariant(!!enhancer, ":(");
1751 return createClassPropertyDecorator(function (target, name, baseValue, _, baseDescriptor) {
1752 assertPropertyConfigurable(target, name);
1753 invariant(!baseDescriptor || !baseDescriptor.get, getMessage("m022"));
1754 var adm = asObservableObject(target, undefined);
1755 defineObservableProperty(adm, name, baseValue, enhancer);
1756 }, function (name) {
1757 var observable = this.$mobx.values[name];
1758 if (observable === undefined // See #505
1759 )
1760 return undefined;
1761 return observable.get();
1762 }, function (name, value) {
1763 setPropertyValue(this, name, value);
1764 }, true, false);
1765}
1766
1767function extendObservable(target) {
1768 var properties = [];
1769 for (var _i = 1; _i < arguments.length; _i++) {
1770 properties[_i - 1] = arguments[_i];
1771 }
1772 return extendObservableHelper(target, deepEnhancer, properties);
1773}
1774function extendShallowObservable(target) {
1775 var properties = [];
1776 for (var _i = 1; _i < arguments.length; _i++) {
1777 properties[_i - 1] = arguments[_i];
1778 }
1779 return extendObservableHelper(target, referenceEnhancer, properties);
1780}
1781function extendObservableHelper(target, defaultEnhancer, properties) {
1782 invariant(arguments.length >= 2, getMessage("m014"));
1783 invariant(typeof target === "object", getMessage("m015"));
1784 invariant(!isObservableMap(target), getMessage("m016"));
1785 properties.forEach(function (propSet) {
1786 invariant(typeof propSet === "object", getMessage("m017"));
1787 invariant(!isObservable(propSet), getMessage("m018"));
1788 });
1789 var adm = asObservableObject(target);
1790 var definedProps = {};
1791 // Note could be optimised if properties.length === 1
1792 for (var i = properties.length - 1; i >= 0; i--) {
1793 var propSet = properties[i];
1794 for (var key in propSet)
1795 if (definedProps[key] !== true && hasOwnProperty(propSet, key)) {
1796 definedProps[key] = true;
1797 if (target === propSet && !isPropertyConfigurable(target, key))
1798 continue; // see #111, skip non-configurable or non-writable props for `observable(object)`.
1799 var descriptor = Object.getOwnPropertyDescriptor(propSet, key);
1800 defineObservablePropertyFromDescriptor(adm, key, descriptor, defaultEnhancer);
1801 }
1802 }
1803 return target;
1804}
1805
1806var deepDecorator = createDecoratorForEnhancer(deepEnhancer);
1807var shallowDecorator = createDecoratorForEnhancer(shallowEnhancer);
1808var refDecorator = createDecoratorForEnhancer(referenceEnhancer);
1809var deepStructDecorator = createDecoratorForEnhancer(deepStructEnhancer);
1810var refStructDecorator = createDecoratorForEnhancer(refStructEnhancer);
1811/**
1812 * Turns an object, array or function into a reactive structure.
1813 * @param v the value which should become observable.
1814 */
1815function createObservable(v) {
1816 if (v === void 0) { v = undefined; }
1817 // @observable someProp;
1818 if (typeof arguments[1] === "string")
1819 return deepDecorator.apply(null, arguments);
1820 invariant(arguments.length <= 1, getMessage("m021"));
1821 invariant(!isModifierDescriptor(v), getMessage("m020"));
1822 // it is an observable already, done
1823 if (isObservable(v))
1824 return v;
1825 // something that can be converted and mutated?
1826 var res = deepEnhancer(v, undefined, undefined);
1827 // this value could be converted to a new observable data structure, return it
1828 if (res !== v)
1829 return res;
1830 // otherwise, just box it
1831 return observable.box(v);
1832}
1833var IObservableFactories = (function () {
1834 function IObservableFactories() {
1835 }
1836 IObservableFactories.prototype.box = function (value, name) {
1837 if (arguments.length > 2)
1838 incorrectlyUsedAsDecorator("box");
1839 return new ObservableValue(value, deepEnhancer, name);
1840 };
1841 IObservableFactories.prototype.shallowBox = function (value, name) {
1842 if (arguments.length > 2)
1843 incorrectlyUsedAsDecorator("shallowBox");
1844 return new ObservableValue(value, referenceEnhancer, name);
1845 };
1846 IObservableFactories.prototype.array = function (initialValues, name) {
1847 if (arguments.length > 2)
1848 incorrectlyUsedAsDecorator("array");
1849 return new ObservableArray(initialValues, deepEnhancer, name);
1850 };
1851 IObservableFactories.prototype.shallowArray = function (initialValues, name) {
1852 if (arguments.length > 2)
1853 incorrectlyUsedAsDecorator("shallowArray");
1854 return new ObservableArray(initialValues, referenceEnhancer, name);
1855 };
1856 IObservableFactories.prototype.map = function (initialValues, name) {
1857 if (arguments.length > 2)
1858 incorrectlyUsedAsDecorator("map");
1859 return new ObservableMap(initialValues, deepEnhancer, name);
1860 };
1861 IObservableFactories.prototype.shallowMap = function (initialValues, name) {
1862 if (arguments.length > 2)
1863 incorrectlyUsedAsDecorator("shallowMap");
1864 return new ObservableMap(initialValues, referenceEnhancer, name);
1865 };
1866 IObservableFactories.prototype.object = function (props, name) {
1867 if (arguments.length > 2)
1868 incorrectlyUsedAsDecorator("object");
1869 var res = {};
1870 // convert to observable object
1871 asObservableObject(res, name);
1872 // add properties
1873 extendObservable(res, props);
1874 return res;
1875 };
1876 IObservableFactories.prototype.shallowObject = function (props, name) {
1877 if (arguments.length > 2)
1878 incorrectlyUsedAsDecorator("shallowObject");
1879 var res = {};
1880 asObservableObject(res, name);
1881 extendShallowObservable(res, props);
1882 return res;
1883 };
1884 IObservableFactories.prototype.ref = function () {
1885 if (arguments.length < 2) {
1886 // although ref creates actually a modifier descriptor, the type of the resultig properties
1887 // of the object is `T` in the end, when the descriptors are interpreted
1888 return createModifierDescriptor(referenceEnhancer, arguments[0]);
1889 }
1890 else {
1891 return refDecorator.apply(null, arguments);
1892 }
1893 };
1894 IObservableFactories.prototype.shallow = function () {
1895 if (arguments.length < 2) {
1896 // although ref creates actually a modifier descriptor, the type of the resultig properties
1897 // of the object is `T` in the end, when the descriptors are interpreted
1898 return createModifierDescriptor(shallowEnhancer, arguments[0]);
1899 }
1900 else {
1901 return shallowDecorator.apply(null, arguments);
1902 }
1903 };
1904 IObservableFactories.prototype.deep = function () {
1905 if (arguments.length < 2) {
1906 // although ref creates actually a modifier descriptor, the type of the resultig properties
1907 // of the object is `T` in the end, when the descriptors are interpreted
1908 return createModifierDescriptor(deepEnhancer, arguments[0]);
1909 }
1910 else {
1911 return deepDecorator.apply(null, arguments);
1912 }
1913 };
1914 IObservableFactories.prototype.struct = function () {
1915 if (arguments.length < 2) {
1916 // although ref creates actually a modifier descriptor, the type of the resultig properties
1917 // of the object is `T` in the end, when the descriptors are interpreted
1918 return createModifierDescriptor(deepStructEnhancer, arguments[0]);
1919 }
1920 else {
1921 return deepStructDecorator.apply(null, arguments);
1922 }
1923 };
1924 return IObservableFactories;
1925}());
1926var observable = createObservable;
1927// weird trick to keep our typings nicely with our funcs, and still extend the observable function
1928// ES6 class methods aren't enumerable, can't use Object.keys
1929Object.getOwnPropertyNames(IObservableFactories.prototype)
1930 .filter(function (name) { return name !== "constructor"; })
1931 .forEach(function (name) { return (observable[name] = IObservableFactories.prototype[name]); });
1932observable.deep.struct = observable.struct;
1933observable.ref.struct = function () {
1934 if (arguments.length < 2) {
1935 return createModifierDescriptor(refStructEnhancer, arguments[0]);
1936 }
1937 else {
1938 return refStructDecorator.apply(null, arguments);
1939 }
1940};
1941function incorrectlyUsedAsDecorator(methodName) {
1942 fail("Expected one or two arguments to observable." + methodName + ". Did you accidentally try to use observable." + methodName + " as decorator?");
1943}
1944
1945function isModifierDescriptor(thing) {
1946 return typeof thing === "object" && thing !== null && thing.isMobxModifierDescriptor === true;
1947}
1948function createModifierDescriptor(enhancer, initialValue) {
1949 invariant(!isModifierDescriptor(initialValue), "Modifiers cannot be nested");
1950 return {
1951 isMobxModifierDescriptor: true,
1952 initialValue: initialValue,
1953 enhancer: enhancer
1954 };
1955}
1956function deepEnhancer(v, _, name) {
1957 if (isModifierDescriptor(v))
1958 fail("You tried to assign a modifier wrapped value to a collection, please define modifiers when creating the collection, not when modifying it");
1959 // it is an observable already, done
1960 if (isObservable(v))
1961 return v;
1962 // something that can be converted and mutated?
1963 if (Array.isArray(v))
1964 return observable.array(v, name);
1965 if (isPlainObject(v))
1966 return observable.object(v, name);
1967 if (isES6Map(v))
1968 return observable.map(v, name);
1969 return v;
1970}
1971function shallowEnhancer(v, _, name) {
1972 if (isModifierDescriptor(v))
1973 fail("You tried to assign a modifier wrapped value to a collection, please define modifiers when creating the collection, not when modifying it");
1974 if (v === undefined || v === null)
1975 return v;
1976 if (isObservableObject(v) || isObservableArray(v) || isObservableMap(v))
1977 return v;
1978 if (Array.isArray(v))
1979 return observable.shallowArray(v, name);
1980 if (isPlainObject(v))
1981 return observable.shallowObject(v, name);
1982 if (isES6Map(v))
1983 return observable.shallowMap(v, name);
1984 return fail("The shallow modifier / decorator can only used in combination with arrays, objects and maps");
1985}
1986function referenceEnhancer(newValue) {
1987 // never turn into an observable
1988 return newValue;
1989}
1990function deepStructEnhancer(v, oldValue, name) {
1991 // don't confuse structurally compare enhancer with ref enhancer! The latter is probably
1992 // more suited for immutable objects
1993 if (deepEqual(v, oldValue))
1994 return oldValue;
1995 // it is an observable already, done
1996 if (isObservable(v))
1997 return v;
1998 // something that can be converted and mutated?
1999 if (Array.isArray(v))
2000 return new ObservableArray(v, deepStructEnhancer, name);
2001 if (isES6Map(v))
2002 return new ObservableMap(v, deepStructEnhancer, name);
2003 if (isPlainObject(v)) {
2004 var res = {};
2005 asObservableObject(res, name);
2006 extendObservableHelper(res, deepStructEnhancer, [v]);
2007 return res;
2008 }
2009 return v;
2010}
2011function refStructEnhancer(v, oldValue, name) {
2012 if (deepEqual(v, oldValue))
2013 return oldValue;
2014 return v;
2015}
2016
2017/**
2018 * During a transaction no views are updated until the end of the transaction.
2019 * The transaction will be run synchronously nonetheless.
2020 *
2021 * @param action a function that updates some reactive state
2022 * @returns any value that was returned by the 'action' parameter.
2023 */
2024function transaction(action, thisArg) {
2025 if (thisArg === void 0) { thisArg = undefined; }
2026 startBatch();
2027 try {
2028 return action.apply(thisArg);
2029 }
2030 finally {
2031 endBatch();
2032 }
2033}
2034
2035var ObservableMapMarker = {};
2036var ObservableMap = (function () {
2037 function ObservableMap(initialData, enhancer, name) {
2038 if (enhancer === void 0) { enhancer = deepEnhancer; }
2039 if (name === void 0) { name = "ObservableMap@" + getNextId(); }
2040 this.enhancer = enhancer;
2041 this.name = name;
2042 this.$mobx = ObservableMapMarker;
2043 this._data = Object.create(null);
2044 this._hasMap = Object.create(null); // hasMap, not hashMap >-).
2045 this._keys = new ObservableArray(undefined, referenceEnhancer, this.name + ".keys()", true);
2046 this.interceptors = null;
2047 this.changeListeners = null;
2048 this.dehancer = undefined;
2049 this.merge(initialData);
2050 }
2051 ObservableMap.prototype._has = function (key) {
2052 return typeof this._data[key] !== "undefined";
2053 };
2054 ObservableMap.prototype.has = function (key) {
2055 if (!this.isValidKey(key))
2056 return false;
2057 key = "" + key;
2058 if (this._hasMap[key])
2059 return this._hasMap[key].get();
2060 return this._updateHasMapEntry(key, false).get();
2061 };
2062 ObservableMap.prototype.set = function (key, value) {
2063 this.assertValidKey(key);
2064 key = "" + key;
2065 var hasKey = this._has(key);
2066 if (hasInterceptors(this)) {
2067 var change = interceptChange(this, {
2068 type: hasKey ? "update" : "add",
2069 object: this,
2070 newValue: value,
2071 name: key
2072 });
2073 if (!change)
2074 return this;
2075 value = change.newValue;
2076 }
2077 if (hasKey) {
2078 this._updateValue(key, value);
2079 }
2080 else {
2081 this._addValue(key, value);
2082 }
2083 return this;
2084 };
2085 ObservableMap.prototype.delete = function (key) {
2086 var _this = this;
2087 this.assertValidKey(key);
2088 key = "" + key;
2089 if (hasInterceptors(this)) {
2090 var change = interceptChange(this, {
2091 type: "delete",
2092 object: this,
2093 name: key
2094 });
2095 if (!change)
2096 return false;
2097 }
2098 if (this._has(key)) {
2099 var notifySpy = isSpyEnabled();
2100 var notify = hasListeners(this);
2101 var change = notify || notifySpy
2102 ? {
2103 type: "delete",
2104 object: this,
2105 oldValue: this._data[key].value,
2106 name: key
2107 }
2108 : null;
2109 if (notifySpy)
2110 spyReportStart(change);
2111 transaction(function () {
2112 _this._keys.remove(key);
2113 _this._updateHasMapEntry(key, false);
2114 var observable$$1 = _this._data[key];
2115 observable$$1.setNewValue(undefined);
2116 _this._data[key] = undefined;
2117 });
2118 if (notify)
2119 notifyListeners(this, change);
2120 if (notifySpy)
2121 spyReportEnd();
2122 return true;
2123 }
2124 return false;
2125 };
2126 ObservableMap.prototype._updateHasMapEntry = function (key, value) {
2127 // optimization; don't fill the hasMap if we are not observing, or remove entry if there are no observers anymore
2128 var entry = this._hasMap[key];
2129 if (entry) {
2130 entry.setNewValue(value);
2131 }
2132 else {
2133 entry = this._hasMap[key] = new ObservableValue(value, referenceEnhancer, this.name + "." + key + "?", false);
2134 }
2135 return entry;
2136 };
2137 ObservableMap.prototype._updateValue = function (name, newValue) {
2138 var observable$$1 = this._data[name];
2139 newValue = observable$$1.prepareNewValue(newValue);
2140 if (newValue !== UNCHANGED) {
2141 var notifySpy = isSpyEnabled();
2142 var notify = hasListeners(this);
2143 var change = notify || notifySpy
2144 ? {
2145 type: "update",
2146 object: this,
2147 oldValue: observable$$1.value,
2148 name: name,
2149 newValue: newValue
2150 }
2151 : null;
2152 if (notifySpy)
2153 spyReportStart(change);
2154 observable$$1.setNewValue(newValue);
2155 if (notify)
2156 notifyListeners(this, change);
2157 if (notifySpy)
2158 spyReportEnd();
2159 }
2160 };
2161 ObservableMap.prototype._addValue = function (name, newValue) {
2162 var _this = this;
2163 transaction(function () {
2164 var observable$$1 = (_this._data[name] = new ObservableValue(newValue, _this.enhancer, _this.name + "." + name, false));
2165 newValue = observable$$1.value; // value might have been changed
2166 _this._updateHasMapEntry(name, true);
2167 _this._keys.push(name);
2168 });
2169 var notifySpy = isSpyEnabled();
2170 var notify = hasListeners(this);
2171 var change = notify || notifySpy
2172 ? {
2173 type: "add",
2174 object: this,
2175 name: name,
2176 newValue: newValue
2177 }
2178 : null;
2179 if (notifySpy)
2180 spyReportStart(change);
2181 if (notify)
2182 notifyListeners(this, change);
2183 if (notifySpy)
2184 spyReportEnd();
2185 };
2186 ObservableMap.prototype.get = function (key) {
2187 key = "" + key;
2188 if (this.has(key))
2189 return this.dehanceValue(this._data[key].get());
2190 return this.dehanceValue(undefined);
2191 };
2192 ObservableMap.prototype.dehanceValue = function (value) {
2193 if (this.dehancer !== undefined) {
2194 return this.dehancer(value);
2195 }
2196 return value;
2197 };
2198 ObservableMap.prototype.keys = function () {
2199 return arrayAsIterator(this._keys.slice());
2200 };
2201 ObservableMap.prototype.values = function () {
2202 return arrayAsIterator(this._keys.map(this.get, this));
2203 };
2204 ObservableMap.prototype.entries = function () {
2205 var _this = this;
2206 return arrayAsIterator(this._keys.map(function (key) { return [key, _this.get(key)]; }));
2207 };
2208 ObservableMap.prototype.forEach = function (callback, thisArg) {
2209 var _this = this;
2210 this.keys().forEach(function (key) { return callback.call(thisArg, _this.get(key), key, _this); });
2211 };
2212 /** Merge another object into this object, returns this. */
2213 ObservableMap.prototype.merge = function (other) {
2214 var _this = this;
2215 if (isObservableMap(other)) {
2216 other = other.toJS();
2217 }
2218 transaction(function () {
2219 if (isPlainObject(other))
2220 Object.keys(other).forEach(function (key) { return _this.set(key, other[key]); });
2221 else if (Array.isArray(other))
2222 other.forEach(function (_a) {
2223 var key = _a[0], value = _a[1];
2224 return _this.set(key, value);
2225 });
2226 else if (isES6Map(other))
2227 other.forEach(function (value, key) { return _this.set(key, value); });
2228 else if (other !== null && other !== undefined)
2229 fail("Cannot initialize map from " + other);
2230 });
2231 return this;
2232 };
2233 ObservableMap.prototype.clear = function () {
2234 var _this = this;
2235 transaction(function () {
2236 untracked(function () {
2237 _this.keys().forEach(_this.delete, _this);
2238 });
2239 });
2240 };
2241 ObservableMap.prototype.replace = function (values) {
2242 var _this = this;
2243 transaction(function () {
2244 _this.clear();
2245 _this.merge(values);
2246 });
2247 return this;
2248 };
2249 Object.defineProperty(ObservableMap.prototype, "size", {
2250 get: function () {
2251 return this._keys.length;
2252 },
2253 enumerable: true,
2254 configurable: true
2255 });
2256 /**
2257 * Returns a shallow non observable object clone of this map.
2258 * Note that the values might still be observable. For a deep clone use mobx.toJS.
2259 */
2260 ObservableMap.prototype.toJS = function () {
2261 var _this = this;
2262 var res = {};
2263 this.keys().forEach(function (key) { return (res[key] = _this.get(key)); });
2264 return res;
2265 };
2266 ObservableMap.prototype.toJSON = function () {
2267 // Used by JSON.stringify
2268 return this.toJS();
2269 };
2270 ObservableMap.prototype.isValidKey = function (key) {
2271 if (key === null || key === undefined)
2272 return false;
2273 if (typeof key === "string" || typeof key === "number" || typeof key === "boolean")
2274 return true;
2275 return false;
2276 };
2277 ObservableMap.prototype.assertValidKey = function (key) {
2278 if (!this.isValidKey(key))
2279 throw new Error("[mobx.map] Invalid key: '" + key + "', only strings, numbers and booleans are accepted as key in observable maps.");
2280 };
2281 ObservableMap.prototype.toString = function () {
2282 var _this = this;
2283 return (this.name +
2284 "[{ " +
2285 this.keys().map(function (key) { return key + ": " + ("" + _this.get(key)); }).join(", ") +
2286 " }]");
2287 };
2288 /**
2289 * Observes this object. Triggers for the events 'add', 'update' and 'delete'.
2290 * See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/observe
2291 * for callback details
2292 */
2293 ObservableMap.prototype.observe = function (listener, fireImmediately) {
2294 invariant(fireImmediately !== true, getMessage("m033"));
2295 return registerListener(this, listener);
2296 };
2297 ObservableMap.prototype.intercept = function (handler) {
2298 return registerInterceptor(this, handler);
2299 };
2300 return ObservableMap;
2301}());
2302declareIterator(ObservableMap.prototype, function () {
2303 return this.entries();
2304});
2305function map(initialValues) {
2306 deprecated("`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead");
2307 return observable.map(initialValues);
2308}
2309/* 'var' fixes small-build issue */
2310var isObservableMap = createInstanceofPredicate("ObservableMap", ObservableMap);
2311
2312var EMPTY_ARRAY = [];
2313Object.freeze(EMPTY_ARRAY);
2314function getGlobal() {
2315 return typeof window !== "undefined" ? window : global;
2316}
2317function getNextId() {
2318 return ++globalState.mobxGuid;
2319}
2320function fail(message, thing) {
2321 invariant(false, message, thing);
2322 throw "X"; // unreachable
2323}
2324function invariant(check, message, thing) {
2325 if (!check)
2326 throw new Error("[mobx] Invariant failed: " + message + (thing ? " in '" + thing + "'" : ""));
2327}
2328/**
2329 * Prints a deprecation message, but only one time.
2330 * Returns false if the deprecated message was already printed before
2331 */
2332var deprecatedMessages = [];
2333function deprecated(msg) {
2334 if (deprecatedMessages.indexOf(msg) !== -1)
2335 return false;
2336 deprecatedMessages.push(msg);
2337 console.error("[mobx] Deprecated: " + msg);
2338 return true;
2339}
2340/**
2341 * Makes sure that the provided function is invoked at most once.
2342 */
2343function once(func) {
2344 var invoked = false;
2345 return function () {
2346 if (invoked)
2347 return;
2348 invoked = true;
2349 return func.apply(this, arguments);
2350 };
2351}
2352var noop = function () { };
2353function unique(list) {
2354 var res = [];
2355 list.forEach(function (item) {
2356 if (res.indexOf(item) === -1)
2357 res.push(item);
2358 });
2359 return res;
2360}
2361function joinStrings(things, limit, separator) {
2362 if (limit === void 0) { limit = 100; }
2363 if (separator === void 0) { separator = " - "; }
2364 if (!things)
2365 return "";
2366 var sliced = things.slice(0, limit);
2367 return "" + sliced.join(separator) + (things.length > limit
2368 ? " (... and " + (things.length - limit) + "more)"
2369 : "");
2370}
2371function isObject(value) {
2372 return value !== null && typeof value === "object";
2373}
2374function isPlainObject(value) {
2375 if (value === null || typeof value !== "object")
2376 return false;
2377 var proto = Object.getPrototypeOf(value);
2378 return proto === Object.prototype || proto === null;
2379}
2380function objectAssign() {
2381 var res = arguments[0];
2382 for (var i = 1, l = arguments.length; i < l; i++) {
2383 var source = arguments[i];
2384 for (var key in source)
2385 if (hasOwnProperty(source, key)) {
2386 res[key] = source[key];
2387 }
2388 }
2389 return res;
2390}
2391var prototypeHasOwnProperty = Object.prototype.hasOwnProperty;
2392function hasOwnProperty(object, propName) {
2393 return prototypeHasOwnProperty.call(object, propName);
2394}
2395function makeNonEnumerable(object, propNames) {
2396 for (var i = 0; i < propNames.length; i++) {
2397 addHiddenProp(object, propNames[i], object[propNames[i]]);
2398 }
2399}
2400function addHiddenProp(object, propName, value) {
2401 Object.defineProperty(object, propName, {
2402 enumerable: false,
2403 writable: true,
2404 configurable: true,
2405 value: value
2406 });
2407}
2408function addHiddenFinalProp(object, propName, value) {
2409 Object.defineProperty(object, propName, {
2410 enumerable: false,
2411 writable: false,
2412 configurable: true,
2413 value: value
2414 });
2415}
2416function isPropertyConfigurable(object, prop) {
2417 var descriptor = Object.getOwnPropertyDescriptor(object, prop);
2418 return !descriptor || (descriptor.configurable !== false && descriptor.writable !== false);
2419}
2420function assertPropertyConfigurable(object, prop) {
2421 invariant(isPropertyConfigurable(object, prop), "Cannot make property '" + prop + "' observable, it is not configurable and writable in the target object");
2422}
2423function getEnumerableKeys(obj) {
2424 var res = [];
2425 for (var key in obj)
2426 res.push(key);
2427 return res;
2428}
2429/**
2430 * Naive deepEqual. Doesn't check for prototype, non-enumerable or out-of-range properties on arrays.
2431 * If you have such a case, you probably should use this function but something fancier :).
2432 */
2433function deepEqual(a, b) {
2434 if (a === null && b === null)
2435 return true;
2436 if (a === undefined && b === undefined)
2437 return true;
2438 if (typeof a !== "object")
2439 return a === b;
2440 var aIsArray = isArrayLike(a);
2441 var aIsMap = isMapLike(a);
2442 if (aIsArray !== isArrayLike(b)) {
2443 return false;
2444 }
2445 else if (aIsMap !== isMapLike(b)) {
2446 return false;
2447 }
2448 else if (aIsArray) {
2449 if (a.length !== b.length)
2450 return false;
2451 for (var i = a.length - 1; i >= 0; i--)
2452 if (!deepEqual(a[i], b[i]))
2453 return false;
2454 return true;
2455 }
2456 else if (aIsMap) {
2457 if (a.size !== b.size)
2458 return false;
2459 var equals_1 = true;
2460 a.forEach(function (value, key) {
2461 equals_1 = equals_1 && deepEqual(b.get(key), value);
2462 });
2463 return equals_1;
2464 }
2465 else if (typeof a === "object" && typeof b === "object") {
2466 if (a === null || b === null)
2467 return false;
2468 if (isMapLike(a) && isMapLike(b)) {
2469 if (a.size !== b.size)
2470 return false;
2471 // Freaking inefficient.... Create PR if you run into this :) Much appreciated!
2472 return deepEqual(observable.shallowMap(a).entries(), observable.shallowMap(b).entries());
2473 }
2474 if (getEnumerableKeys(a).length !== getEnumerableKeys(b).length)
2475 return false;
2476 for (var prop in a) {
2477 if (!(prop in b))
2478 return false;
2479 if (!deepEqual(a[prop], b[prop]))
2480 return false;
2481 }
2482 return true;
2483 }
2484 return false;
2485}
2486function createInstanceofPredicate(name, clazz) {
2487 var propName = "isMobX" + name;
2488 clazz.prototype[propName] = true;
2489 return function (x) {
2490 return isObject(x) && x[propName] === true;
2491 };
2492}
2493/**
2494 * Returns whether the argument is an array, disregarding observability.
2495 */
2496function isArrayLike(x) {
2497 return Array.isArray(x) || isObservableArray(x);
2498}
2499function isMapLike(x) {
2500 return isES6Map(x) || isObservableMap(x);
2501}
2502function isES6Map(thing) {
2503 if (getGlobal().Map !== undefined && thing instanceof getGlobal().Map)
2504 return true;
2505 return false;
2506}
2507function primitiveSymbol() {
2508 return (typeof Symbol === "function" && Symbol.toPrimitive) || "@@toPrimitive";
2509}
2510function toPrimitive(value) {
2511 return value === null ? null : typeof value === "object" ? "" + value : value;
2512}
2513
2514/**
2515 * These values will persist if global state is reset
2516 */
2517var persistentKeys = ["mobxGuid", "resetId", "spyListeners", "strictMode", "runId"];
2518var MobXGlobals = (function () {
2519 function MobXGlobals() {
2520 /**
2521 * MobXGlobals version.
2522 * MobX compatiblity with other versions loaded in memory as long as this version matches.
2523 * It indicates that the global state still stores similar information
2524 */
2525 this.version = 5;
2526 /**
2527 * Currently running derivation
2528 */
2529 this.trackingDerivation = null;
2530 /**
2531 * Are we running a computation currently? (not a reaction)
2532 */
2533 this.computationDepth = 0;
2534 /**
2535 * Each time a derivation is tracked, it is assigned a unique run-id
2536 */
2537 this.runId = 0;
2538 /**
2539 * 'guid' for general purpose. Will be persisted amongst resets.
2540 */
2541 this.mobxGuid = 0;
2542 /**
2543 * Are we in a batch block? (and how many of them)
2544 */
2545 this.inBatch = 0;
2546 /**
2547 * Observables that don't have observers anymore, and are about to be
2548 * suspended, unless somebody else accesses it in the same batch
2549 *
2550 * @type {IObservable[]}
2551 */
2552 this.pendingUnobservations = [];
2553 /**
2554 * List of scheduled, not yet executed, reactions.
2555 */
2556 this.pendingReactions = [];
2557 /**
2558 * Are we currently processing reactions?
2559 */
2560 this.isRunningReactions = false;
2561 /**
2562 * Is it allowed to change observables at this point?
2563 * In general, MobX doesn't allow that when running computations and React.render.
2564 * To ensure that those functions stay pure.
2565 */
2566 this.allowStateChanges = true;
2567 /**
2568 * If strict mode is enabled, state changes are by default not allowed
2569 */
2570 this.strictMode = false;
2571 /**
2572 * Used by createTransformer to detect that the global state has been reset.
2573 */
2574 this.resetId = 0;
2575 /**
2576 * Spy callbacks
2577 */
2578 this.spyListeners = [];
2579 /**
2580 * Globally attached error handlers that react specifically to errors in reactions
2581 */
2582 this.globalReactionErrorHandlers = [];
2583 }
2584 return MobXGlobals;
2585}());
2586var globalState = new MobXGlobals();
2587var shareGlobalStateCalled = false;
2588var runInIsolationCalled = false;
2589var warnedAboutMultipleInstances = false;
2590{
2591 var global_1 = getGlobal();
2592 if (!global_1.__mobxInstanceCount) {
2593 global_1.__mobxInstanceCount = 1;
2594 }
2595 else {
2596 global_1.__mobxInstanceCount++;
2597 setTimeout(function () {
2598 if (!shareGlobalStateCalled && !runInIsolationCalled && !warnedAboutMultipleInstances) {
2599 warnedAboutMultipleInstances = true;
2600 console.warn("[mobx] Warning: there are multiple mobx instances active. This might lead to unexpected results. See https://github.com/mobxjs/mobx/issues/1082 for details.");
2601 }
2602 });
2603 }
2604}
2605function isolateGlobalState() {
2606 runInIsolationCalled = true;
2607 getGlobal().__mobxInstanceCount--;
2608}
2609function shareGlobalState() {
2610 // TODO: remove in 4.0; just use peer dependencies instead.
2611 deprecated("Using `shareGlobalState` is not recommended, use peer dependencies instead. See https://github.com/mobxjs/mobx/issues/1082 for details.");
2612 shareGlobalStateCalled = true;
2613 var global = getGlobal();
2614 var ownState = globalState;
2615 /**
2616 * Backward compatibility check
2617 */
2618 if (global.__mobservableTrackingStack || global.__mobservableViewStack)
2619 throw new Error("[mobx] An incompatible version of mobservable is already loaded.");
2620 if (global.__mobxGlobal && global.__mobxGlobal.version !== ownState.version)
2621 throw new Error("[mobx] An incompatible version of mobx is already loaded.");
2622 if (global.__mobxGlobal)
2623 globalState = global.__mobxGlobal;
2624 else
2625 global.__mobxGlobal = ownState;
2626}
2627function getGlobalState() {
2628 return globalState;
2629}
2630
2631/**
2632 * For testing purposes only; this will break the internal state of existing observables,
2633 * but can be used to get back at a stable state after throwing errors
2634 */
2635function resetGlobalState() {
2636 globalState.resetId++;
2637 var defaultGlobals = new MobXGlobals();
2638 for (var key in defaultGlobals)
2639 if (persistentKeys.indexOf(key) === -1)
2640 globalState[key] = defaultGlobals[key];
2641 globalState.allowStateChanges = !globalState.strictMode;
2642}
2643
2644function hasObservers(observable) {
2645 return observable.observers && observable.observers.length > 0;
2646}
2647function getObservers(observable) {
2648 return observable.observers;
2649}
2650function addObserver(observable, node) {
2651 // invariant(node.dependenciesState !== -1, "INTERNAL ERROR, can add only dependenciesState !== -1");
2652 // invariant(observable._observers.indexOf(node) === -1, "INTERNAL ERROR add already added node");
2653 // invariantObservers(observable);
2654 var l = observable.observers.length;
2655 if (l) {
2656 // because object assignment is relatively expensive, let's not store data about index 0.
2657 observable.observersIndexes[node.__mapid] = l;
2658 }
2659 observable.observers[l] = node;
2660 if (observable.lowestObserverState > node.dependenciesState)
2661 observable.lowestObserverState = node.dependenciesState;
2662 // invariantObservers(observable);
2663 // invariant(observable._observers.indexOf(node) !== -1, "INTERNAL ERROR didn't add node");
2664}
2665function removeObserver(observable, node) {
2666 // invariant(globalState.inBatch > 0, "INTERNAL ERROR, remove should be called only inside batch");
2667 // invariant(observable._observers.indexOf(node) !== -1, "INTERNAL ERROR remove already removed node");
2668 // invariantObservers(observable);
2669 if (observable.observers.length === 1) {
2670 // deleting last observer
2671 observable.observers.length = 0;
2672 queueForUnobservation(observable);
2673 }
2674 else {
2675 // deleting from _observersIndexes is straight forward, to delete from _observers, let's swap `node` with last element
2676 var list = observable.observers;
2677 var map = observable.observersIndexes;
2678 var filler = list.pop(); // get last element, which should fill the place of `node`, so the array doesn't have holes
2679 if (filler !== node) {
2680 // otherwise node was the last element, which already got removed from array
2681 var index = map[node.__mapid] || 0; // getting index of `node`. this is the only place we actually use map.
2682 if (index) {
2683 // map store all indexes but 0, see comment in `addObserver`
2684 map[filler.__mapid] = index;
2685 }
2686 else {
2687 delete map[filler.__mapid];
2688 }
2689 list[index] = filler;
2690 }
2691 delete map[node.__mapid];
2692 }
2693 // invariantObservers(observable);
2694 // invariant(observable._observers.indexOf(node) === -1, "INTERNAL ERROR remove already removed node2");
2695}
2696function queueForUnobservation(observable) {
2697 if (!observable.isPendingUnobservation) {
2698 // invariant(globalState.inBatch > 0, "INTERNAL ERROR, remove should be called only inside batch");
2699 // invariant(observable._observers.length === 0, "INTERNAL ERROR, should only queue for unobservation unobserved observables");
2700 observable.isPendingUnobservation = true;
2701 globalState.pendingUnobservations.push(observable);
2702 }
2703}
2704/**
2705 * Batch starts a transaction, at least for purposes of memoizing ComputedValues when nothing else does.
2706 * During a batch `onBecomeUnobserved` will be called at most once per observable.
2707 * Avoids unnecessary recalculations.
2708 */
2709function startBatch() {
2710 globalState.inBatch++;
2711}
2712function endBatch() {
2713 if (--globalState.inBatch === 0) {
2714 runReactions();
2715 // the batch is actually about to finish, all unobserving should happen here.
2716 var list = globalState.pendingUnobservations;
2717 for (var i = 0; i < list.length; i++) {
2718 var observable = list[i];
2719 observable.isPendingUnobservation = false;
2720 if (observable.observers.length === 0) {
2721 observable.onBecomeUnobserved();
2722 // NOTE: onBecomeUnobserved might push to `pendingUnobservations`
2723 }
2724 }
2725 globalState.pendingUnobservations = [];
2726 }
2727}
2728function reportObserved(observable) {
2729 var derivation = globalState.trackingDerivation;
2730 if (derivation !== null) {
2731 /**
2732 * Simple optimization, give each derivation run an unique id (runId)
2733 * Check if last time this observable was accessed the same runId is used
2734 * if this is the case, the relation is already known
2735 */
2736 if (derivation.runId !== observable.lastAccessedBy) {
2737 observable.lastAccessedBy = derivation.runId;
2738 derivation.newObserving[derivation.unboundDepsCount++] = observable;
2739 }
2740 }
2741 else if (observable.observers.length === 0) {
2742 queueForUnobservation(observable);
2743 }
2744}
2745/**
2746 * NOTE: current propagation mechanism will in case of self reruning autoruns behave unexpectedly
2747 * It will propagate changes to observers from previous run
2748 * It's hard or maybe impossible (with reasonable perf) to get it right with current approach
2749 * Hopefully self reruning autoruns aren't a feature people should depend on
2750 * Also most basic use cases should be ok
2751 */
2752// Called by Atom when its value changes
2753function propagateChanged(observable) {
2754 // invariantLOS(observable, "changed start");
2755 if (observable.lowestObserverState === IDerivationState.STALE)
2756 return;
2757 observable.lowestObserverState = IDerivationState.STALE;
2758 var observers = observable.observers;
2759 var i = observers.length;
2760 while (i--) {
2761 var d = observers[i];
2762 if (d.dependenciesState === IDerivationState.UP_TO_DATE)
2763 d.onBecomeStale();
2764 d.dependenciesState = IDerivationState.STALE;
2765 }
2766 // invariantLOS(observable, "changed end");
2767}
2768// Called by ComputedValue when it recalculate and its value changed
2769function propagateChangeConfirmed(observable) {
2770 // invariantLOS(observable, "confirmed start");
2771 if (observable.lowestObserverState === IDerivationState.STALE)
2772 return;
2773 observable.lowestObserverState = IDerivationState.STALE;
2774 var observers = observable.observers;
2775 var i = observers.length;
2776 while (i--) {
2777 var d = observers[i];
2778 if (d.dependenciesState === IDerivationState.POSSIBLY_STALE)
2779 d.dependenciesState = IDerivationState.STALE;
2780 else if (d.dependenciesState === IDerivationState.UP_TO_DATE // this happens during computing of `d`, just keep lowestObserverState up to date.
2781 )
2782 observable.lowestObserverState = IDerivationState.UP_TO_DATE;
2783 }
2784 // invariantLOS(observable, "confirmed end");
2785}
2786// Used by computed when its dependency changed, but we don't wan't to immediately recompute.
2787function propagateMaybeChanged(observable) {
2788 // invariantLOS(observable, "maybe start");
2789 if (observable.lowestObserverState !== IDerivationState.UP_TO_DATE)
2790 return;
2791 observable.lowestObserverState = IDerivationState.POSSIBLY_STALE;
2792 var observers = observable.observers;
2793 var i = observers.length;
2794 while (i--) {
2795 var d = observers[i];
2796 if (d.dependenciesState === IDerivationState.UP_TO_DATE) {
2797 d.dependenciesState = IDerivationState.POSSIBLY_STALE;
2798 d.onBecomeStale();
2799 }
2800 }
2801 // invariantLOS(observable, "maybe end");
2802}
2803
2804var IDerivationState;
2805(function (IDerivationState) {
2806 // before being run or (outside batch and not being observed)
2807 // at this point derivation is not holding any data about dependency tree
2808 IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
2809 // no shallow dependency changed since last computation
2810 // won't recalculate derivation
2811 // this is what makes mobx fast
2812 IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
2813 // some deep dependency changed, but don't know if shallow dependency changed
2814 // will require to check first if UP_TO_DATE or POSSIBLY_STALE
2815 // currently only ComputedValue will propagate POSSIBLY_STALE
2816 //
2817 // having this state is second big optimization:
2818 // don't have to recompute on every dependency change, but only when it's needed
2819 IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
2820 // A shallow dependency has changed since last computation and the derivation
2821 // will need to recompute when it's needed next.
2822 IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
2823})(IDerivationState || (IDerivationState = {}));
2824var CaughtException = (function () {
2825 function CaughtException(cause) {
2826 this.cause = cause;
2827 // Empty
2828 }
2829 return CaughtException;
2830}());
2831function isCaughtException(e) {
2832 return e instanceof CaughtException;
2833}
2834/**
2835 * Finds out whether any dependency of the derivation has actually changed.
2836 * If dependenciesState is 1 then it will recalculate dependencies,
2837 * if any dependency changed it will propagate it by changing dependenciesState to 2.
2838 *
2839 * By iterating over the dependencies in the same order that they were reported and
2840 * stopping on the first change, all the recalculations are only called for ComputedValues
2841 * that will be tracked by derivation. That is because we assume that if the first x
2842 * dependencies of the derivation doesn't change then the derivation should run the same way
2843 * up until accessing x-th dependency.
2844 */
2845function shouldCompute(derivation) {
2846 switch (derivation.dependenciesState) {
2847 case IDerivationState.UP_TO_DATE:
2848 return false;
2849 case IDerivationState.NOT_TRACKING:
2850 case IDerivationState.STALE:
2851 return true;
2852 case IDerivationState.POSSIBLY_STALE: {
2853 var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
2854 var obs = derivation.observing, l = obs.length;
2855 for (var i = 0; i < l; i++) {
2856 var obj = obs[i];
2857 if (isComputedValue(obj)) {
2858 try {
2859 obj.get();
2860 }
2861 catch (e) {
2862 // we are not interested in the value *or* exception at this moment, but if there is one, notify all
2863 untrackedEnd(prevUntracked);
2864 return true;
2865 }
2866 // if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
2867 // and `derivation` is an observer of `obj`
2868 if (derivation.dependenciesState === IDerivationState.STALE) {
2869 untrackedEnd(prevUntracked);
2870 return true;
2871 }
2872 }
2873 }
2874 changeDependenciesStateTo0(derivation);
2875 untrackedEnd(prevUntracked);
2876 return false;
2877 }
2878 }
2879}
2880function isComputingDerivation() {
2881 return globalState.trackingDerivation !== null; // filter out actions inside computations
2882}
2883function checkIfStateModificationsAreAllowed(atom) {
2884 var hasObservers$$1 = atom.observers.length > 0;
2885 // Should never be possible to change an observed observable from inside computed, see #798
2886 if (globalState.computationDepth > 0 && hasObservers$$1)
2887 fail(getMessage("m031") + atom.name);
2888 // Should not be possible to change observed state outside strict mode, except during initialization, see #563
2889 if (!globalState.allowStateChanges && hasObservers$$1)
2890 fail(getMessage(globalState.strictMode ? "m030a" : "m030b") + atom.name);
2891}
2892/**
2893 * Executes the provided function `f` and tracks which observables are being accessed.
2894 * The tracking information is stored on the `derivation` object and the derivation is registered
2895 * as observer of any of the accessed observables.
2896 */
2897function trackDerivedFunction(derivation, f, context) {
2898 // pre allocate array allocation + room for variation in deps
2899 // array will be trimmed by bindDependencies
2900 changeDependenciesStateTo0(derivation);
2901 derivation.newObserving = new Array(derivation.observing.length + 100);
2902 derivation.unboundDepsCount = 0;
2903 derivation.runId = ++globalState.runId;
2904 var prevTracking = globalState.trackingDerivation;
2905 globalState.trackingDerivation = derivation;
2906 var result;
2907 try {
2908 result = f.call(context);
2909 }
2910 catch (e) {
2911 result = new CaughtException(e);
2912 }
2913 globalState.trackingDerivation = prevTracking;
2914 bindDependencies(derivation);
2915 return result;
2916}
2917/**
2918 * diffs newObserving with observing.
2919 * update observing to be newObserving with unique observables
2920 * notify observers that become observed/unobserved
2921 */
2922function bindDependencies(derivation) {
2923 // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
2924 var prevObserving = derivation.observing;
2925 var observing = (derivation.observing = derivation.newObserving);
2926 var lowestNewObservingDerivationState = IDerivationState.UP_TO_DATE;
2927 // Go through all new observables and check diffValue: (this list can contain duplicates):
2928 // 0: first occurrence, change to 1 and keep it
2929 // 1: extra occurrence, drop it
2930 var i0 = 0, l = derivation.unboundDepsCount;
2931 for (var i = 0; i < l; i++) {
2932 var dep = observing[i];
2933 if (dep.diffValue === 0) {
2934 dep.diffValue = 1;
2935 if (i0 !== i)
2936 observing[i0] = dep;
2937 i0++;
2938 }
2939 // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
2940 // not hitting the condition
2941 if (dep.dependenciesState > lowestNewObservingDerivationState) {
2942 lowestNewObservingDerivationState = dep.dependenciesState;
2943 }
2944 }
2945 observing.length = i0;
2946 derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
2947 // Go through all old observables and check diffValue: (it is unique after last bindDependencies)
2948 // 0: it's not in new observables, unobserve it
2949 // 1: it keeps being observed, don't want to notify it. change to 0
2950 l = prevObserving.length;
2951 while (l--) {
2952 var dep = prevObserving[l];
2953 if (dep.diffValue === 0) {
2954 removeObserver(dep, derivation);
2955 }
2956 dep.diffValue = 0;
2957 }
2958 // Go through all new observables and check diffValue: (now it should be unique)
2959 // 0: it was set to 0 in last loop. don't need to do anything.
2960 // 1: it wasn't observed, let's observe it. set back to 0
2961 while (i0--) {
2962 var dep = observing[i0];
2963 if (dep.diffValue === 1) {
2964 dep.diffValue = 0;
2965 addObserver(dep, derivation);
2966 }
2967 }
2968 // Some new observed derivations may become stale during this derivation computation
2969 // so they have had no chance to propagate staleness (#916)
2970 if (lowestNewObservingDerivationState !== IDerivationState.UP_TO_DATE) {
2971 derivation.dependenciesState = lowestNewObservingDerivationState;
2972 derivation.onBecomeStale();
2973 }
2974}
2975function clearObserving(derivation) {
2976 // invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
2977 var obs = derivation.observing;
2978 derivation.observing = [];
2979 var i = obs.length;
2980 while (i--)
2981 removeObserver(obs[i], derivation);
2982 derivation.dependenciesState = IDerivationState.NOT_TRACKING;
2983}
2984function untracked(action) {
2985 var prev = untrackedStart();
2986 var res = action();
2987 untrackedEnd(prev);
2988 return res;
2989}
2990function untrackedStart() {
2991 var prev = globalState.trackingDerivation;
2992 globalState.trackingDerivation = null;
2993 return prev;
2994}
2995function untrackedEnd(prev) {
2996 globalState.trackingDerivation = prev;
2997}
2998/**
2999 * needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
3000 *
3001 */
3002function changeDependenciesStateTo0(derivation) {
3003 if (derivation.dependenciesState === IDerivationState.UP_TO_DATE)
3004 return;
3005 derivation.dependenciesState = IDerivationState.UP_TO_DATE;
3006 var obs = derivation.observing;
3007 var i = obs.length;
3008 while (i--)
3009 obs[i].lowestObserverState = IDerivationState.UP_TO_DATE;
3010}
3011
3012var Reaction = (function () {
3013 function Reaction(name, onInvalidate) {
3014 if (name === void 0) { name = "Reaction@" + getNextId(); }
3015 this.name = name;
3016 this.onInvalidate = onInvalidate;
3017 this.observing = []; // nodes we are looking at. Our value depends on these nodes
3018 this.newObserving = [];
3019 this.dependenciesState = IDerivationState.NOT_TRACKING;
3020 this.diffValue = 0;
3021 this.runId = 0;
3022 this.unboundDepsCount = 0;
3023 this.__mapid = "#" + getNextId();
3024 this.isDisposed = false;
3025 this._isScheduled = false;
3026 this._isTrackPending = false;
3027 this._isRunning = false;
3028 }
3029 Reaction.prototype.onBecomeStale = function () {
3030 this.schedule();
3031 };
3032 Reaction.prototype.schedule = function () {
3033 if (!this._isScheduled) {
3034 this._isScheduled = true;
3035 globalState.pendingReactions.push(this);
3036 runReactions();
3037 }
3038 };
3039 Reaction.prototype.isScheduled = function () {
3040 return this._isScheduled;
3041 };
3042 /**
3043 * internal, use schedule() if you intend to kick off a reaction
3044 */
3045 Reaction.prototype.runReaction = function () {
3046 if (!this.isDisposed) {
3047 startBatch();
3048 this._isScheduled = false;
3049 if (shouldCompute(this)) {
3050 this._isTrackPending = true;
3051 this.onInvalidate();
3052 if (this._isTrackPending && isSpyEnabled()) {
3053 // onInvalidate didn't trigger track right away..
3054 spyReport({
3055 object: this,
3056 type: "scheduled-reaction"
3057 });
3058 }
3059 }
3060 endBatch();
3061 }
3062 };
3063 Reaction.prototype.track = function (fn) {
3064 startBatch();
3065 var notify = isSpyEnabled();
3066 var startTime;
3067 if (notify) {
3068 startTime = Date.now();
3069 spyReportStart({
3070 object: this,
3071 type: "reaction",
3072 fn: fn
3073 });
3074 }
3075 this._isRunning = true;
3076 var result = trackDerivedFunction(this, fn, undefined);
3077 this._isRunning = false;
3078 this._isTrackPending = false;
3079 if (this.isDisposed) {
3080 // disposed during last run. Clean up everything that was bound after the dispose call.
3081 clearObserving(this);
3082 }
3083 if (isCaughtException(result))
3084 this.reportExceptionInDerivation(result.cause);
3085 if (notify) {
3086 spyReportEnd({
3087 time: Date.now() - startTime
3088 });
3089 }
3090 endBatch();
3091 };
3092 Reaction.prototype.reportExceptionInDerivation = function (error) {
3093 var _this = this;
3094 if (this.errorHandler) {
3095 this.errorHandler(error, this);
3096 return;
3097 }
3098 var message = "[mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: '" + this;
3099 var messageToUser = getMessage("m037");
3100 console.error(message || messageToUser /* latter will not be true, make sure uglify doesn't remove */, error);
3101 /** If debugging brought you here, please, read the above message :-). Tnx! */
3102 if (isSpyEnabled()) {
3103 spyReport({
3104 type: "error",
3105 message: message,
3106 error: error,
3107 object: this
3108 });
3109 }
3110 globalState.globalReactionErrorHandlers.forEach(function (f) { return f(error, _this); });
3111 };
3112 Reaction.prototype.dispose = function () {
3113 if (!this.isDisposed) {
3114 this.isDisposed = true;
3115 if (!this._isRunning) {
3116 // if disposed while running, clean up later. Maybe not optimal, but rare case
3117 startBatch();
3118 clearObserving(this);
3119 endBatch();
3120 }
3121 }
3122 };
3123 Reaction.prototype.getDisposer = function () {
3124 var r = this.dispose.bind(this);
3125 r.$mobx = this;
3126 r.onError = registerErrorHandler;
3127 return r;
3128 };
3129 Reaction.prototype.toString = function () {
3130 return "Reaction[" + this.name + "]";
3131 };
3132 Reaction.prototype.whyRun = function () {
3133 var observing = unique(this._isRunning ? this.newObserving : this.observing).map(function (dep) { return dep.name; });
3134 return "\nWhyRun? reaction '" + this.name + "':\n * Status: [" + (this.isDisposed
3135 ? "stopped"
3136 : this._isRunning ? "running" : this.isScheduled() ? "scheduled" : "idle") + "]\n * This reaction will re-run if any of the following observables changes:\n " + joinStrings(observing) + "\n " + (this._isRunning
3137 ? " (... or any observable accessed during the remainder of the current run)"
3138 : "") + "\n\t" + getMessage("m038") + "\n";
3139 };
3140 return Reaction;
3141}());
3142function registerErrorHandler(handler) {
3143 invariant(this && this.$mobx && isReaction(this.$mobx), "Invalid `this`");
3144 invariant(!this.$mobx.errorHandler, "Only one onErrorHandler can be registered");
3145 this.$mobx.errorHandler = handler;
3146}
3147function onReactionError(handler) {
3148 globalState.globalReactionErrorHandlers.push(handler);
3149 return function () {
3150 var idx = globalState.globalReactionErrorHandlers.indexOf(handler);
3151 if (idx >= 0)
3152 globalState.globalReactionErrorHandlers.splice(idx, 1);
3153 };
3154}
3155/**
3156 * Magic number alert!
3157 * Defines within how many times a reaction is allowed to re-trigger itself
3158 * until it is assumed that this is gonna be a never ending loop...
3159 */
3160var MAX_REACTION_ITERATIONS = 100;
3161var reactionScheduler = function (f) { return f(); };
3162function runReactions() {
3163 // Trampolining, if runReactions are already running, new reactions will be picked up
3164 if (globalState.inBatch > 0 || globalState.isRunningReactions)
3165 return;
3166 reactionScheduler(runReactionsHelper);
3167}
3168function runReactionsHelper() {
3169 globalState.isRunningReactions = true;
3170 var allReactions = globalState.pendingReactions;
3171 var iterations = 0;
3172 // While running reactions, new reactions might be triggered.
3173 // Hence we work with two variables and check whether
3174 // we converge to no remaining reactions after a while.
3175 while (allReactions.length > 0) {
3176 if (++iterations === MAX_REACTION_ITERATIONS) {
3177 console.error("Reaction doesn't converge to a stable state after " + MAX_REACTION_ITERATIONS + " iterations." +
3178 (" Probably there is a cycle in the reactive function: " + allReactions[0]));
3179 allReactions.splice(0); // clear reactions
3180 }
3181 var remainingReactions = allReactions.splice(0);
3182 for (var i = 0, l = remainingReactions.length; i < l; i++)
3183 remainingReactions[i].runReaction();
3184 }
3185 globalState.isRunningReactions = false;
3186}
3187var isReaction = createInstanceofPredicate("Reaction", Reaction);
3188function setReactionScheduler(fn) {
3189 var baseScheduler = reactionScheduler;
3190 reactionScheduler = function (f) { return fn(function () { return baseScheduler(f); }); };
3191}
3192
3193function asReference(value) {
3194 deprecated("asReference is deprecated, use observable.ref instead");
3195 return observable.ref(value);
3196}
3197function asStructure(value) {
3198 deprecated("asStructure is deprecated. Use observable.struct, computed.struct or reaction options instead.");
3199 return observable.struct(value);
3200}
3201function asFlat(value) {
3202 deprecated("asFlat is deprecated, use observable.shallow instead");
3203 return observable.shallow(value);
3204}
3205function asMap(data) {
3206 deprecated("asMap is deprecated, use observable.map or observable.shallowMap instead");
3207 return observable.map(data || {});
3208}
3209
3210function createComputedDecorator(equals) {
3211 return createClassPropertyDecorator(function (target, name, _, __, originalDescriptor) {
3212 invariant(typeof originalDescriptor !== "undefined", getMessage("m009"));
3213 invariant(typeof originalDescriptor.get === "function", getMessage("m010"));
3214 var adm = asObservableObject(target, "");
3215 defineComputedProperty(adm, name, originalDescriptor.get, originalDescriptor.set, equals, false);
3216 }, function (name) {
3217 var observable = this.$mobx.values[name];
3218 if (observable === undefined // See #505
3219 )
3220 return undefined;
3221 return observable.get();
3222 }, function (name, value) {
3223 this.$mobx.values[name].set(value);
3224 }, false, false);
3225}
3226var computedDecorator = createComputedDecorator(comparer.default);
3227var computedStructDecorator = createComputedDecorator(comparer.structural);
3228/**
3229 * Decorator for class properties: @computed get value() { return expr; }.
3230 * For legacy purposes also invokable as ES5 observable created: `computed(() => expr)`;
3231 */
3232var computed = function computed(arg1, arg2, arg3) {
3233 if (typeof arg2 === "string") {
3234 return computedDecorator.apply(null, arguments);
3235 }
3236 invariant(typeof arg1 === "function", getMessage("m011"));
3237 invariant(arguments.length < 3, getMessage("m012"));
3238 var opts = typeof arg2 === "object" ? arg2 : {};
3239 opts.setter = typeof arg2 === "function" ? arg2 : opts.setter;
3240 var equals = opts.equals
3241 ? opts.equals
3242 : opts.compareStructural || opts.struct ? comparer.structural : comparer.default;
3243 return new ComputedValue(arg1, opts.context, equals, opts.name || arg1.name || "", opts.setter);
3244};
3245computed.struct = computedStructDecorator;
3246computed.equals = createComputedDecorator;
3247
3248function getAtom(thing, property) {
3249 if (typeof thing === "object" && thing !== null) {
3250 if (isObservableArray(thing)) {
3251 invariant(property === undefined, getMessage("m036"));
3252 return thing.$mobx.atom;
3253 }
3254 if (isObservableMap(thing)) {
3255 var anyThing = thing;
3256 if (property === undefined)
3257 return getAtom(anyThing._keys);
3258 var observable = anyThing._data[property] || anyThing._hasMap[property];
3259 invariant(!!observable, "the entry '" + property + "' does not exist in the observable map '" + getDebugName(thing) + "'");
3260 return observable;
3261 }
3262 // Initializers run lazily when transpiling to babel, so make sure they are run...
3263 runLazyInitializers(thing);
3264 if (property && !thing.$mobx)
3265 thing[property]; // See #1072 // TODO: remove in 4.0
3266 if (isObservableObject(thing)) {
3267 if (!property)
3268 return fail("please specify a property");
3269 var observable = thing.$mobx.values[property];
3270 invariant(!!observable, "no observable property '" + property + "' found on the observable object '" + getDebugName(thing) + "'");
3271 return observable;
3272 }
3273 if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) {
3274 return thing;
3275 }
3276 }
3277 else if (typeof thing === "function") {
3278 if (isReaction(thing.$mobx)) {
3279 // disposer function
3280 return thing.$mobx;
3281 }
3282 }
3283 return fail("Cannot obtain atom from " + thing);
3284}
3285function getAdministration(thing, property) {
3286 invariant(thing, "Expecting some object");
3287 if (property !== undefined)
3288 return getAdministration(getAtom(thing, property));
3289 if (isAtom(thing) || isComputedValue(thing) || isReaction(thing))
3290 return thing;
3291 if (isObservableMap(thing))
3292 return thing;
3293 // Initializers run lazily when transpiling to babel, so make sure they are run...
3294 runLazyInitializers(thing);
3295 if (thing.$mobx)
3296 return thing.$mobx;
3297 invariant(false, "Cannot obtain administration from " + thing);
3298}
3299function getDebugName(thing, property) {
3300 var named;
3301 if (property !== undefined)
3302 named = getAtom(thing, property);
3303 else if (isObservableObject(thing) || isObservableMap(thing))
3304 named = getAdministration(thing);
3305 else
3306 named = getAtom(thing); // valid for arrays as well
3307 return named.name;
3308}
3309
3310function isComputed(value, property) {
3311 if (value === null || value === undefined)
3312 return false;
3313 if (property !== undefined) {
3314 if (isObservableObject(value) === false)
3315 return false;
3316 if (!value.$mobx.values[property])
3317 return false;
3318 var atom = getAtom(value, property);
3319 return isComputedValue(atom);
3320 }
3321 return isComputedValue(value);
3322}
3323
3324function observe(thing, propOrCb, cbOrFire, fireImmediately) {
3325 if (typeof cbOrFire === "function")
3326 return observeObservableProperty(thing, propOrCb, cbOrFire, fireImmediately);
3327 else
3328 return observeObservable(thing, propOrCb, cbOrFire);
3329}
3330function observeObservable(thing, listener, fireImmediately) {
3331 return getAdministration(thing).observe(listener, fireImmediately);
3332}
3333function observeObservableProperty(thing, property, listener, fireImmediately) {
3334 return getAdministration(thing, property).observe(listener, fireImmediately);
3335}
3336
3337function intercept(thing, propOrHandler, handler) {
3338 if (typeof handler === "function")
3339 return interceptProperty(thing, propOrHandler, handler);
3340 else
3341 return interceptInterceptable(thing, propOrHandler);
3342}
3343function interceptInterceptable(thing, handler) {
3344 return getAdministration(thing).intercept(handler);
3345}
3346function interceptProperty(thing, property, handler) {
3347 return getAdministration(thing, property).intercept(handler);
3348}
3349
3350/**
3351 * expr can be used to create temporarily views inside views.
3352 * This can be improved to improve performance if a value changes often, but usually doesn't affect the outcome of an expression.
3353 *
3354 * In the following example the expression prevents that a component is rerender _each time_ the selection changes;
3355 * instead it will only rerenders when the current todo is (de)selected.
3356 *
3357 * reactiveComponent((props) => {
3358 * const todo = props.todo;
3359 * const isSelected = mobx.expr(() => props.viewState.selection === todo);
3360 * return <div className={isSelected ? "todo todo-selected" : "todo"}>{todo.title}</div>
3361 * });
3362 *
3363 */
3364function expr(expr, scope) {
3365 if (!isComputingDerivation())
3366 console.warn(getMessage("m013"));
3367 // optimization: would be more efficient if the expr itself wouldn't be evaluated first on the next change, but just a 'changed' signal would be fired
3368 return computed(expr, { context: scope }).get();
3369}
3370
3371function toJS(source, detectCycles, __alreadySeen) {
3372 if (detectCycles === void 0) { detectCycles = true; }
3373 if (__alreadySeen === void 0) { __alreadySeen = []; }
3374 // optimization: using ES6 map would be more efficient!
3375 // optimization: lift this function outside toJS, this makes recursion expensive
3376 function cache(value) {
3377 if (detectCycles)
3378 __alreadySeen.push([source, value]);
3379 return value;
3380 }
3381 if (isObservable(source)) {
3382 if (detectCycles && __alreadySeen === null)
3383 __alreadySeen = [];
3384 if (detectCycles && source !== null && typeof source === "object") {
3385 for (var i = 0, l = __alreadySeen.length; i < l; i++)
3386 if (__alreadySeen[i][0] === source)
3387 return __alreadySeen[i][1];
3388 }
3389 if (isObservableArray(source)) {
3390 var res = cache([]);
3391 var toAdd = source.map(function (value) { return toJS(value, detectCycles, __alreadySeen); });
3392 res.length = toAdd.length;
3393 for (var i = 0, l = toAdd.length; i < l; i++)
3394 res[i] = toAdd[i];
3395 return res;
3396 }
3397 if (isObservableObject(source)) {
3398 var res = cache({});
3399 for (var key in source)
3400 res[key] = toJS(source[key], detectCycles, __alreadySeen);
3401 return res;
3402 }
3403 if (isObservableMap(source)) {
3404 var res_1 = cache({});
3405 source.forEach(function (value, key) { return (res_1[key] = toJS(value, detectCycles, __alreadySeen)); });
3406 return res_1;
3407 }
3408 if (isObservableValue(source))
3409 return toJS(source.get(), detectCycles, __alreadySeen);
3410 }
3411 return source;
3412}
3413
3414function createTransformer(transformer, onCleanup) {
3415 invariant(typeof transformer === "function" && transformer.length < 2, "createTransformer expects a function that accepts one argument");
3416 // Memoizes: object id -> reactive view that applies transformer to the object
3417 var objectCache = {};
3418 // If the resetId changes, we will clear the object cache, see #163
3419 // This construction is used to avoid leaking refs to the objectCache directly
3420 var resetId = globalState.resetId;
3421 // Local transformer class specifically for this transformer
3422 var Transformer = (function (_super) {
3423 __extends(Transformer, _super);
3424 function Transformer(sourceIdentifier, sourceObject) {
3425 var _this = _super.call(this, function () { return transformer(sourceObject); }, undefined, comparer.default, "Transformer-" + transformer.name + "-" + sourceIdentifier, undefined) || this;
3426 _this.sourceIdentifier = sourceIdentifier;
3427 _this.sourceObject = sourceObject;
3428 return _this;
3429 }
3430 Transformer.prototype.onBecomeUnobserved = function () {
3431 var lastValue = this.value;
3432 _super.prototype.onBecomeUnobserved.call(this);
3433 delete objectCache[this.sourceIdentifier];
3434 if (onCleanup)
3435 onCleanup(lastValue, this.sourceObject);
3436 };
3437 return Transformer;
3438 }(ComputedValue));
3439 return function (object) {
3440 if (resetId !== globalState.resetId) {
3441 objectCache = {};
3442 resetId = globalState.resetId;
3443 }
3444 var identifier = getMemoizationId(object);
3445 var reactiveTransformer = objectCache[identifier];
3446 if (reactiveTransformer)
3447 return reactiveTransformer.get();
3448 // Not in cache; create a reactive view
3449 reactiveTransformer = objectCache[identifier] = new Transformer(identifier, object);
3450 return reactiveTransformer.get();
3451 };
3452}
3453function getMemoizationId(object) {
3454 if (typeof object === "string" || typeof object === "number")
3455 return object;
3456 if (object === null || typeof object !== "object")
3457 throw new Error("[mobx] transform expected some kind of object or primitive value, got: " + object);
3458 var tid = object.$transformId;
3459 if (tid === undefined) {
3460 tid = getNextId();
3461 addHiddenProp(object, "$transformId", tid);
3462 }
3463 return tid;
3464}
3465
3466function log(msg) {
3467 console.log(msg);
3468 return msg;
3469}
3470function whyRun(thing, prop) {
3471 switch (arguments.length) {
3472 case 0:
3473 thing = globalState.trackingDerivation;
3474 if (!thing)
3475 return log(getMessage("m024"));
3476 break;
3477 case 2:
3478 thing = getAtom(thing, prop);
3479 break;
3480 }
3481 thing = getAtom(thing);
3482 if (isComputedValue(thing))
3483 return log(thing.whyRun());
3484 else if (isReaction(thing))
3485 return log(thing.whyRun());
3486 return fail(getMessage("m025"));
3487}
3488
3489function getDependencyTree(thing, property) {
3490 return nodeToDependencyTree(getAtom(thing, property));
3491}
3492function nodeToDependencyTree(node) {
3493 var result = {
3494 name: node.name
3495 };
3496 if (node.observing && node.observing.length > 0)
3497 result.dependencies = unique(node.observing).map(nodeToDependencyTree);
3498 return result;
3499}
3500function getObserverTree(thing, property) {
3501 return nodeToObserverTree(getAtom(thing, property));
3502}
3503function nodeToObserverTree(node) {
3504 var result = {
3505 name: node.name
3506 };
3507 if (hasObservers(node))
3508 result.observers = getObservers(node).map(nodeToObserverTree);
3509 return result;
3510}
3511
3512function interceptReads(thing, propOrHandler, handler) {
3513 var target;
3514 if (isObservableMap(thing) || isObservableArray(thing) || isObservableValue(thing)) {
3515 target = getAdministration(thing);
3516 }
3517 else if (isObservableObject(thing)) {
3518 if (typeof propOrHandler !== "string")
3519 return fail("InterceptReads can only be used with a specific property, not with an object in general");
3520 target = getAdministration(thing, propOrHandler);
3521 }
3522 else {
3523 return fail("Expected observable map, object or array as first array");
3524 }
3525 if (target.dehancer !== undefined)
3526 return fail("An intercept reader was already established");
3527 target.dehancer = typeof propOrHandler === "function" ? propOrHandler : handler;
3528 return function () {
3529 target.dehancer = undefined;
3530 };
3531}
3532
3533/**
3534 * (c) Michel Weststrate 2015 - 2016
3535 * MIT Licensed
3536 *
3537 * Welcome to the mobx sources! To get an global overview of how MobX internally works,
3538 * this is a good place to start:
3539 * https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254#.xvbh6qd74
3540 *
3541 * Source folders:
3542 * ===============
3543 *
3544 * - api/ Most of the public static methods exposed by the module can be found here.
3545 * - core/ Implementation of the MobX algorithm; atoms, derivations, reactions, dependency trees, optimizations. Cool stuff can be found here.
3546 * - types/ All the magic that is need to have observable objects, arrays and values is in this folder. Including the modifiers like `asFlat`.
3547 * - utils/ Utility stuff.
3548 *
3549 */
3550var extras = {
3551 allowStateChanges: allowStateChanges,
3552 deepEqual: deepEqual,
3553 getAtom: getAtom,
3554 getDebugName: getDebugName,
3555 getDependencyTree: getDependencyTree,
3556 getAdministration: getAdministration,
3557 getGlobalState: getGlobalState,
3558 getObserverTree: getObserverTree,
3559 interceptReads: interceptReads,
3560 isComputingDerivation: isComputingDerivation,
3561 isSpyEnabled: isSpyEnabled,
3562 onReactionError: onReactionError,
3563 reserveArrayBuffer: reserveArrayBuffer,
3564 resetGlobalState: resetGlobalState,
3565 isolateGlobalState: isolateGlobalState,
3566 shareGlobalState: shareGlobalState,
3567 spyReport: spyReport,
3568 spyReportEnd: spyReportEnd,
3569 spyReportStart: spyReportStart,
3570 setReactionScheduler: setReactionScheduler
3571};
3572var everything = {
3573 Reaction: Reaction,
3574 untracked: untracked,
3575 Atom: Atom,
3576 BaseAtom: BaseAtom,
3577 useStrict: useStrict,
3578 isStrictModeEnabled: isStrictModeEnabled,
3579 spy: spy,
3580 comparer: comparer,
3581 asReference: asReference,
3582 asFlat: asFlat,
3583 asStructure: asStructure,
3584 asMap: asMap,
3585 isModifierDescriptor: isModifierDescriptor,
3586 isObservableObject: isObservableObject,
3587 isBoxedObservable: isObservableValue,
3588 isObservableArray: isObservableArray,
3589 ObservableMap: ObservableMap,
3590 isObservableMap: isObservableMap,
3591 map: map,
3592 transaction: transaction,
3593 observable: observable,
3594 computed: computed,
3595 isObservable: isObservable,
3596 isComputed: isComputed,
3597 extendObservable: extendObservable,
3598 extendShallowObservable: extendShallowObservable,
3599 observe: observe,
3600 intercept: intercept,
3601 autorun: autorun,
3602 autorunAsync: autorunAsync,
3603 when: when,
3604 reaction: reaction,
3605 action: action,
3606 isAction: isAction,
3607 runInAction: runInAction,
3608 expr: expr,
3609 toJS: toJS,
3610 createTransformer: createTransformer,
3611 whyRun: whyRun,
3612 isArrayLike: isArrayLike,
3613 extras: extras
3614};
3615var warnedAboutDefaultExport = false;
3616var _loop_1 = function (p) {
3617 var val = everything[p];
3618 Object.defineProperty(everything, p, {
3619 get: function () {
3620 if (!warnedAboutDefaultExport) {
3621 warnedAboutDefaultExport = true;
3622 console.warn("Using default export (`import mobx from 'mobx'`) is deprecated " +
3623 "and won’t work in mobx@4.0.0\n" +
3624 "Use `import * as mobx from 'mobx'` instead");
3625 }
3626 return val;
3627 }
3628 });
3629};
3630for (var p in everything) {
3631 _loop_1(p);
3632}
3633if (typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ === "object") {
3634 __MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobx({ spy: spy, extras: extras });
3635}
3636
3637export { extras, Reaction, untracked, IDerivationState, Atom, BaseAtom, useStrict, isStrictModeEnabled, spy, comparer, asReference, asFlat, asStructure, asMap, isModifierDescriptor, isObservableObject, isObservableValue as isBoxedObservable, isObservableArray, ObservableMap, isObservableMap, map, transaction, observable, IObservableFactories, computed, isObservable, isComputed, extendObservable, extendShallowObservable, observe, intercept, autorun, autorunAsync, when, reaction, action, isAction, runInAction, expr, toJS, createTransformer, whyRun, isArrayLike };export default everything;