mobx-location
Version:
minimal observable wrapper around browser location utilizing popstate event of HTML5 history api
1,355 lines (1,300 loc) • 178 kB
JavaScript
// modules are defined as an array
// [ module function, map of requires ]
//
// map of requires is short require name -> numeric require
//
// anything defined in a previous bundle is accessed via the
// orig method which is the require for previous bundles
// eslint-disable-next-line no-global-assign
parcelRequire = (function (modules, cache, entry, globalName) {
// Save the require from previous bundle to this closure if any
var previousRequire = typeof parcelRequire === 'function' && parcelRequire;
var nodeRequire = typeof require === 'function' && require;
function newRequire(name, jumped) {
if (!cache[name]) {
if (!modules[name]) {
// if we cannot find the module within our internal map or
// cache jump to the current global require ie. the last bundle
// that was added to the page.
var currentRequire = typeof parcelRequire === 'function' && parcelRequire;
if (!jumped && currentRequire) {
return currentRequire(name, true);
}
// If there are other bundles on this page the require from the
// previous one is saved to 'previousRequire'. Repeat this as
// many times as there are bundles until the module is found or
// we exhaust the require chain.
if (previousRequire) {
return previousRequire(name, true);
}
// Try the node require function if it exists.
if (nodeRequire && typeof name === 'string') {
return nodeRequire(name);
}
var err = new Error('Cannot find module \'' + name + '\'');
err.code = 'MODULE_NOT_FOUND';
throw err;
}
localRequire.resolve = resolve;
var module = cache[name] = new newRequire.Module(name);
modules[name][0].call(module.exports, localRequire, module, module.exports, this);
}
return cache[name].exports;
function localRequire(x){
return newRequire(localRequire.resolve(x));
}
function resolve(x){
return modules[name][1][x] || x;
}
}
function Module(moduleName) {
this.id = moduleName;
this.bundle = newRequire;
this.exports = {};
}
newRequire.isParcelRequire = true;
newRequire.Module = Module;
newRequire.modules = modules;
newRequire.cache = cache;
newRequire.parent = previousRequire;
for (var i = 0; i < entry.length; i++) {
newRequire(entry[i]);
}
if (entry.length) {
// Expose entry point to Node, AMD or browser globals
// Based on https://github.com/ForbesLindesay/umd/blob/master/template.js
var mainExports = newRequire(entry[entry.length - 1]);
// CommonJS
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = mainExports;
// RequireJS
} else if (typeof define === "function" && define.amd) {
define(function () {
return mainExports;
});
// <script>
} else if (globalName) {
this[globalName] = mainExports;
}
}
// Override the current require with this new one
return newRequire;
})({9:[function(require,module,exports) {
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout() {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
})();
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch (e) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch (e) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while (len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) {
return [];
};
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () {
return '/';
};
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function () {
return 0;
};
},{}],5:[function(require,module,exports) {
var process = require("process");
var global = arguments[3];
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
/** MobX - (c) Michel Weststrate 2015, 2016 - MIT Licensed */
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) {
d.__proto__ = b;
} || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
};
function __extends(d, b) {
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o),
r,
ar = [],
e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
} catch (error) {
e = { error: error };
} finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
} finally {
if (e) throw e.error;
}
}
return ar;
}
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
}
var enumerableDescriptorCache = {};
var nonEnumerableDescriptorCache = {};
function createPropertyInitializerDescriptor(prop, enumerable) {
var cache = enumerable ? enumerableDescriptorCache : nonEnumerableDescriptorCache;
return cache[prop] || (cache[prop] = {
configurable: true,
enumerable: enumerable,
get: function () {
initializeInstance(this);
return this[prop];
},
set: function (value) {
initializeInstance(this);
this[prop] = value;
}
});
}
function initializeInstance(target) {
if (target.__mobxDidRunLazyInitializers === true) return;
var decorators = target.__mobxDecorators;
if (decorators) {
addHiddenProp(target, "__mobxDidRunLazyInitializers", true);
for (var key in decorators) {
var d = decorators[key];
d.propertyCreator(target, d.prop, d.descriptor, d.decoratorTarget, d.decoratorArguments);
}
}
}
function createPropDecorator(propertyInitiallyEnumerable, propertyCreator) {
return function decoratorFactory() {
var decoratorArguments;
var decorator = function decorate(target, prop, descriptor, applyImmediately
// This is a special parameter to signal the direct application of a decorator, allow extendObservable to skip the entire type decoration part,
// as the instance to apply the decorator to equals the target
) {
if (applyImmediately === true) {
propertyCreator(target, prop, descriptor, target, decoratorArguments);
return null;
}
if (undefined !== "production" && !quacksLikeADecorator(arguments)) fail$1("This function is a decorator, but it wasn't invoked like a decorator");
if (!Object.prototype.hasOwnProperty.call(target, "__mobxDecorators")) {
var inheritedDecorators = target.__mobxDecorators;
addHiddenProp(target, "__mobxDecorators", __assign({}, inheritedDecorators));
}
target.__mobxDecorators[prop] = {
prop: prop,
propertyCreator: propertyCreator,
descriptor: descriptor,
decoratorTarget: target,
decoratorArguments: decoratorArguments
};
return createPropertyInitializerDescriptor(prop, propertyInitiallyEnumerable);
};
if (quacksLikeADecorator(arguments)) {
// @decorator
decoratorArguments = EMPTY_ARRAY;
return decorator.apply(null, arguments);
} else {
// @decorator(args)
decoratorArguments = Array.prototype.slice.call(arguments);
return decorator;
}
};
}
function quacksLikeADecorator(args) {
return (args.length === 2 || args.length === 3) && typeof args[1] === "string" || args.length === 4 && args[3] === true;
}
function isSpyEnabled() {
return !!globalState.spyListeners.length;
}
function spyReport(event) {
if (!globalState.spyListeners.length) return;
var listeners = globalState.spyListeners;
for (var i = 0, l = listeners.length; i < l; i++) listeners[i](event);
}
function spyReportStart(event) {
var change = __assign({}, event, { spyReportStart: true });
spyReport(change);
}
var END_EVENT = { spyReportEnd: true };
function spyReportEnd(change) {
if (change) spyReport(__assign({}, change, { spyReportEnd: true }));else spyReport(END_EVENT);
}
function spy(listener) {
globalState.spyListeners.push(listener);
return once(function () {
globalState.spyListeners = globalState.spyListeners.filter(function (l) {
return l !== listener;
});
});
}
function createAction(actionName, fn) {
if (undefined !== "production") {
invariant(typeof fn === "function", "`action` can only be invoked on functions");
if (typeof actionName !== "string" || !actionName) fail$1("actions should have valid names, got: '" + actionName + "'");
}
var res = function () {
return executeAction(actionName, fn, this, arguments);
};
res.isMobxAction = true;
return res;
}
function executeAction(actionName, fn, scope, args) {
var runInfo = startAction(actionName, fn, scope, args);
try {
return fn.apply(scope, args);
} finally {
endAction(runInfo);
}
}
function startAction(actionName, fn, scope, args) {
var notifySpy = isSpyEnabled() && !!actionName;
var startTime = 0;
if (notifySpy) {
startTime = Date.now();
var l = args && args.length || 0;
var flattendArgs = new Array(l);
if (l > 0) for (var i = 0; i < l; i++) flattendArgs[i] = args[i];
spyReportStart({
type: "action",
name: actionName,
object: scope,
arguments: flattendArgs
});
}
var prevDerivation = untrackedStart();
startBatch();
var prevAllowStateChanges = allowStateChangesStart(true);
return {
prevDerivation: prevDerivation,
prevAllowStateChanges: prevAllowStateChanges,
notifySpy: notifySpy,
startTime: startTime
};
}
function endAction(runInfo) {
allowStateChangesEnd(runInfo.prevAllowStateChanges);
endBatch();
untrackedEnd(runInfo.prevDerivation);
if (runInfo.notifySpy) spyReportEnd({ time: Date.now() - runInfo.startTime });
}
function allowStateChanges(allowStateChanges, func) {
var prev = allowStateChangesStart(allowStateChanges);
var res;
try {
res = func();
} finally {
allowStateChangesEnd(prev);
}
return res;
}
function allowStateChangesStart(allowStateChanges) {
var prev = globalState.allowStateChanges;
globalState.allowStateChanges = allowStateChanges;
return prev;
}
function allowStateChangesEnd(prev) {
globalState.allowStateChanges = prev;
}
function dontReassignFields() {
fail$1(undefined !== "production" && "@action fields are not reassignable");
}
function namedActionDecorator(name) {
return function (target, prop, descriptor) {
if (descriptor) {
if (undefined !== "production" && descriptor.get !== undefined) {
return fail$1("@action cannot be used with getters");
}
// babel / typescript
// @action method() { }
if (descriptor.value) {
// typescript
return {
value: createAction(name, descriptor.value),
enumerable: false,
configurable: true,
writable: true // for typescript, this must be writable, otherwise it cannot inherit :/ (see inheritable actions test)
};
}
// babel only: @action method = () => {}
var initializer_1 = descriptor.initializer;
return {
enumerable: false,
configurable: true,
writable: true,
initializer: function () {
// N.B: we can't immediately invoke initializer; this would be wrong
return createAction(name, initializer_1.call(this));
}
};
}
// bound instance methods
return actionFieldDecorator(name).apply(this, arguments);
};
}
function actionFieldDecorator(name) {
// Simple property that writes on first invocation to the current instance
return function (target, prop, descriptor) {
Object.defineProperty(target, prop, {
configurable: true,
enumerable: false,
get: function () {
return undefined;
},
set: function (value) {
addHiddenFinalProp(this, prop, action(name, value));
}
});
};
}
function boundActionDecorator(target, propertyName, descriptor, applyToInstance) {
if (applyToInstance === true) {
defineBoundAction(target, propertyName, descriptor.value);
return null;
}
if (descriptor) {
// if (descriptor.value)
// Typescript / Babel: @action.bound method() { }
// also: babel @action.bound method = () => {}
return {
configurable: true,
enumerable: false,
get: function () {
defineBoundAction(this, propertyName, descriptor.value || descriptor.initializer.call(this));
return this[propertyName];
},
set: dontReassignFields
};
}
// field decorator Typescript @action.bound method = () => {}
return {
enumerable: false,
configurable: true,
set: function (v) {
defineBoundAction(this, propertyName, v);
},
get: function () {
return undefined;
}
};
}
var action = function action(arg1, arg2, arg3, arg4) {
// action(fn() {})
if (arguments.length === 1 && typeof arg1 === "function") return createAction(arg1.name || "<unnamed action>", arg1);
// action("name", fn() {})
if (arguments.length === 2 && typeof arg2 === "function") return createAction(arg1, arg2);
// @action("name") fn() {}
if (arguments.length === 1 && typeof arg1 === "string") return namedActionDecorator(arg1);
// @action fn() {}
if (arg4 === true) {
// apply to instance immediately
arg1[arg2] = createAction(arg1.name || arg2, arg3.value);
} else {
return namedActionDecorator(arg2).apply(null, arguments);
}
};
action.bound = boundActionDecorator;
function runInAction(arg1, arg2) {
// TODO: deprecate?
var actionName = typeof arg1 === "string" ? arg1 : arg1.name || "<unnamed action>";
var fn = typeof arg1 === "function" ? arg1 : arg2;
if (undefined !== "production") {
invariant(typeof fn === "function" && fn.length === 0, "`runInAction` expects a function without arguments");
if (typeof actionName !== "string" || !actionName) fail$1("actions should have valid names, got: '" + actionName + "'");
}
return executeAction(actionName, fn, this, undefined);
}
function isAction(thing) {
return typeof thing === "function" && thing.isMobxAction === true;
}
function defineBoundAction(target, propertyName, fn) {
addHiddenProp(target, propertyName, createAction(propertyName, fn.bind(target)));
}
var toString = Object.prototype.toString;
function deepEqual(a, b) {
return eq(a, b);
}
// Copied from https://github.com/jashkenas/underscore/blob/5c237a7c682fb68fd5378203f0bf22dce1624854/underscore.js#L1186-L1289
// Internal recursive comparison function for `isEqual`.
function eq(a, b, aStack, bStack) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
if (a === b) return a !== 0 || 1 / a === 1 / b;
// `null` or `undefined` only equal to itself (strict comparison).
if (a == null || b == null) return false;
// `NaN`s are equivalent, but non-reflexive.
if (a !== a) return b !== b;
// Exhaust primitive checks
var type = typeof a;
if (type !== "function" && type !== "object" && typeof b != "object") return false;
return deepEq(a, b, aStack, bStack);
}
// Internal recursive comparison function for `isEqual`.
function deepEq(a, b, aStack, bStack) {
// Unwrap any wrapped objects.
a = unwrap(a);
b = unwrap(b);
// Compare `[[Class]]` names.
var className = toString.call(a);
if (className !== toString.call(b)) return false;
switch (className) {
// Strings, numbers, regular expressions, dates, and booleans are compared by value.
case "[object RegExp]":
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
case "[object String]":
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
// equivalent to `new String("5")`.
return "" + a === "" + b;
case "[object Number]":
// `NaN`s are equivalent, but non-reflexive.
// Object(NaN) is equivalent to NaN.
if (+a !== +a) return +b !== +b;
// An `egal` comparison is performed for other numeric values.
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
case "[object Date]":
case "[object Boolean]":
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
// millisecond representations. Note that invalid dates with millisecond representations
// of `NaN` are not equivalent.
return +a === +b;
case "[object Symbol]":
return typeof Symbol !== "undefined" && Symbol.valueOf.call(a) === Symbol.valueOf.call(b);
}
var areArrays = className === "[object Array]";
if (!areArrays) {
if (typeof a != "object" || typeof b != "object") return false;
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
// from different frames are.
var aCtor = a.constructor,
bCtor = b.constructor;
if (aCtor !== bCtor && !(typeof aCtor === "function" && aCtor instanceof aCtor && typeof bCtor === "function" && bCtor instanceof bCtor) && "constructor" in a && "constructor" in b) {
return false;
}
}
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
// Initializing stack of traversed objects.
// It's done here since we only need them for objects and arrays comparison.
aStack = aStack || [];
bStack = bStack || [];
var length = aStack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
if (aStack[length] === a) return bStack[length] === b;
}
// Add the first object to the stack of traversed objects.
aStack.push(a);
bStack.push(b);
// Recursively compare objects and arrays.
if (areArrays) {
// Compare array lengths to determine if a deep comparison is necessary.
length = a.length;
if (length !== b.length) return false;
// Deep compare the contents, ignoring non-numeric properties.
while (length--) {
if (!eq(a[length], b[length], aStack, bStack)) return false;
}
} else {
// Deep compare objects.
var keys$$1 = Object.keys(a),
key;
length = keys$$1.length;
// Ensure that both objects contain the same number of properties before comparing deep equality.
if (Object.keys(b).length !== length) return false;
while (length--) {
// Deep compare each member
key = keys$$1[length];
if (!(has$$1(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
}
}
// Remove the first object from the stack of traversed objects.
aStack.pop();
bStack.pop();
return true;
}
function unwrap(a) {
if (isObservableArray(a)) return a.peek();
if (isES6Map(a) || isObservableMap(a)) return iteratorToArray(a.entries());
return a;
}
function has$$1(a, key) {
return Object.prototype.hasOwnProperty.call(a, key);
}
function identityComparer(a, b) {
return a === b;
}
function structuralComparer(a, b) {
return deepEqual(a, b);
}
function defaultComparer(a, b) {
return areBothNaN(a, b) || identityComparer(a, b);
}
var comparer = {
identity: identityComparer,
structural: structuralComparer,
default: defaultComparer
};
/**
* Creates a named reactive view and keeps it alive, so that the view is always
* updated if one of the dependencies changes, even when the view is not further used by something else.
* @param view The reactive view
* @returns disposer function, which can be used to stop the view from being updated in the future.
*/
function autorun(view, opts) {
if (opts === void 0) {
opts = EMPTY_OBJECT;
}
if (undefined !== "production") {
invariant(typeof view === "function", "Autorun expects a function as first argument");
invariant(isAction(view) === false, "Autorun does not accept actions since actions are untrackable");
}
var name = opts && opts.name || view.name || "Autorun@" + getNextId();
var runSync = !opts.scheduler && !opts.delay;
var reaction;
if (runSync) {
// normal autorun
reaction = new Reaction(name, function () {
this.track(reactionRunner);
}, opts.onError);
} else {
var scheduler_1 = createSchedulerFromOptions(opts);
// debounced autorun
var isScheduled_1 = false;
reaction = new Reaction(name, function () {
if (!isScheduled_1) {
isScheduled_1 = true;
scheduler_1(function () {
isScheduled_1 = false;
if (!reaction.isDisposed) reaction.track(reactionRunner);
});
}
}, opts.onError);
}
function reactionRunner() {
view(reaction);
}
reaction.schedule();
return reaction.getDisposer();
}
var run = function (f) {
return f();
};
function createSchedulerFromOptions(opts) {
return opts.scheduler ? opts.scheduler : opts.delay ? function (f) {
return setTimeout(f, opts.delay);
} : run;
}
function reaction(expression, effect, opts) {
if (opts === void 0) {
opts = EMPTY_OBJECT;
}
if (typeof opts === "boolean") {
opts = { fireImmediately: opts };
deprecated("Using fireImmediately as argument is deprecated. Use '{ fireImmediately: true }' instead");
}
if (undefined !== "production") {
invariant(typeof expression === "function", "First argument to reaction should be a function");
invariant(typeof opts === "object", "Third argument of reactions should be an object");
}
var name = opts.name || "Reaction@" + getNextId();
var effectAction = action(name, opts.onError ? wrapErrorHandler(opts.onError, effect) : effect);
var runSync = !opts.scheduler && !opts.delay;
var scheduler = createSchedulerFromOptions(opts);
var firstTime = true;
var isScheduled = false;
var value;
var equals = opts.compareStructural ? comparer.structural : opts.equals || comparer.default;
var r = new Reaction(name, function () {
if (firstTime || runSync) {
reactionRunner();
} else if (!isScheduled) {
isScheduled = true;
scheduler(reactionRunner);
}
}, opts.onError);
function reactionRunner() {
isScheduled = false; // Q: move into reaction runner?
if (r.isDisposed) return;
var changed = false;
r.track(function () {
var nextValue = expression(r);
changed = firstTime || !equals(value, nextValue);
value = nextValue;
});
if (firstTime && opts.fireImmediately) effectAction(value, r);
if (!firstTime && changed === true) effectAction(value, r);
if (firstTime) firstTime = false;
}
r.schedule();
return r.getDisposer();
}
function wrapErrorHandler(errorHandler, baseFn) {
return function () {
try {
return baseFn.apply(this, arguments);
} catch (e) {
errorHandler.call(this, e);
}
};
}
/**
* A node in the state dependency root that observes other nodes, and can be observed itself.
*
* ComputedValue will remember the result of the computation for the duration of the batch, or
* while being observed.
*
* During this time it will recompute only when one of its direct dependencies changed,
* but only when it is being accessed with `ComputedValue.get()`.
*
* Implementation description:
* 1. First time it's being accessed it will compute and remember result
* give back remembered result until 2. happens
* 2. First time any deep dependency change, propagate POSSIBLY_STALE to all observers, wait for 3.
* 3. When it's being accessed, recompute if any shallow dependency changed.
* if result changed: propagate STALE to all observers, that were POSSIBLY_STALE from the last step.
* go to step 2. either way
*
* If at any point it's outside batch and it isn't observed: reset everything and go to 1.
*/
var ComputedValue = /** @class */function () {
/**
* Create a new computed value based on a function expression.
*
* The `name` property is for debug purposes only.
*
* The `equals` property specifies the comparer function to use to determine if a newly produced
* value differs from the previous value. Two comparers are provided in the library; `defaultComparer`
* compares based on identity comparison (===), and `structualComparer` deeply compares the structure.
* Structural comparison can be convenient if you always produce an new aggregated object and
* don't want to notify observers if it is structurally the same.
* This is useful for working with vectors, mouse coordinates etc.
*/
function ComputedValue(options) {
var _this = this;
this.dependenciesState = IDerivationState.NOT_TRACKING;
this.observing = []; // nodes we are looking at. Our value depends on these nodes
this.newObserving = null; // during tracking it's an array with new observed observers
this.isBeingObserved = false;
this.isPendingUnobservation = false;
this.observers = [];
this.observersIndexes = {};
this.diffValue = 0;
this.runId = 0;
this.lastAccessedBy = 0;
this.lowestObserverState = IDerivationState.UP_TO_DATE;
this.unboundDepsCount = 0;
this.__mapid = "#" + getNextId();
this.value = new CaughtException(null);
this.isComputing = false; // to check for cycles
this.isRunningSetter = false;
this.isTracing = TraceMode.NONE;
if (undefined !== "production" && !options.get) return fail$1("missing option for computed: get");
this.derivation = options.get;
this.name = options.name || "ComputedValue@" + getNextId();
if (options.set) this.setter = createAction(this.name + "-setter", options.set);
this.equals = options.equals || (options.compareStructural || options.struct ? comparer.structural : comparer.default);
this.scope = options.context;
this.requiresReaction = !!options.requiresReaction;
if (options.keepAlive === true) {
// dangerous: never exposed, so this cmputed value should not depend on observables
// that live globally, or it will never get disposed! (nor anything attached to it)
autorun(function () {
return _this.get();
});
}
}
ComputedValue.prototype.onBecomeStale = function () {
propagateMaybeChanged(this);
};
ComputedValue.prototype.onBecomeUnobserved = function () {};
ComputedValue.prototype.onBecomeObserved = function () {};
/**
* Returns the current value of this computed value.
* Will evaluate its computation first if needed.
*/
ComputedValue.prototype.get = function () {
if (this.isComputing) fail$1("Cycle detected in computation " + this.name + ": " + this.derivation);
if (globalState.inBatch === 0) {
if (shouldCompute(this)) {
this.warnAboutUntrackedRead();
startBatch(); // See perf test 'computed memoization'
this.value = this.computeValue(false);
endBatch();
}
} else {
reportObserved(this);
if (shouldCompute(this)) if (this.trackAndCompute()) propagateChangeConfirmed(this);
}
var result = this.value;
if (isCaughtException(result)) throw result.cause;
return result;
};
ComputedValue.prototype.peek = function () {
var res = this.computeValue(false);
if (isCaughtException(res)) throw res.cause;
return res;
};
ComputedValue.prototype.set = function (value) {
if (this.setter) {
invariant(!this.isRunningSetter, "The setter of computed value '" + this.name + "' is trying to update itself. Did you intend to update an _observable_ value, instead of the computed property?");
this.isRunningSetter = true;
try {
this.setter.call(this.scope, value);
} finally {
this.isRunningSetter = false;
}
} else invariant(false, undefined !== "production" && "[ComputedValue '" + this.name + "'] It is not possible to assign a new value to a computed value.");
};
ComputedValue.prototype.trackAndCompute = function () {
if (isSpyEnabled()) {
spyReport({
object: this.scope,
type: "compute",
name: this.name
});
}
var oldValue = this.value;
var wasSuspended =
/* see #1208 */this.dependenciesState === IDerivationState.NOT_TRACKING;
var newValue = this.computeValue(true);
var changed = wasSuspended || isCaughtException(oldValue) || isCaughtException(newValue) || !this.equals(oldValue, newValue);
if (changed) {
this.value = newValue;
}
return changed;
};
ComputedValue.prototype.computeValue = function (track) {
this.isComputing = true;
globalState.computationDepth++;
var res;
if (track) {
res = trackDerivedFunction(this, this.derivation, this.scope);
} else {
if (globalState.disableErrorBoundaries === true) {
res = this.derivation.call(this.scope);
} else {
try {
res = this.derivation.call(this.scope);
} catch (e) {
res = new CaughtException(e);
}
}
}
globalState.computationDepth--;
this.isComputing = false;
return res;
};
ComputedValue.prototype.suspend = function () {
clearObserving(this);
this.value = undefined; // don't hold on to computed value!
};
ComputedValue.prototype.observe = function (listener, fireImmediately) {
var _this = this;
var firstTime = true;
var prevValue = undefined;
return autorun(function () {
var newValue = _this.get();
if (!firstTime || fireImmediately) {
var prevU = untrackedStart();
listener({
type: "update",
object: _this,
newValue: newValue,
oldValue: prevValue
});
untrackedEnd(prevU);
}
firstTime = false;
prevValue = newValue;
});
};
ComputedValue.prototype.warnAboutUntrackedRead = function () {
if (undefined === "production") return;
if (this.requiresReaction === true) {
fail$1("[mobx] Computed value " + this.name + " is read outside a reactive context");
}
if (this.isTracing !== TraceMode.NONE) {
console.log("[mobx.trace] '" + this.name + "' is being read outside a reactive context. Doing a full recompute");
}
if (globalState.computedRequiresReaction) {
console.warn("[mobx] Computed value " + this.name + " is being read outside a reactive context. Doing a full recompute");
}
};
ComputedValue.prototype.toJSON = function () {
return this.get();
};
ComputedValue.prototype.toString = function () {
return this.name + "[" + this.derivation.toString() + "]";
};
ComputedValue.prototype.valueOf = function () {
return toPrimitive(this.get());
};
return ComputedValue;
}();
ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
function hasInterceptors(interceptable) {
return interceptable.interceptors !== undefined && interceptable.interceptors.length > 0;
}
function registerInterceptor(interceptable, handler) {
var interceptors = interceptable.interceptors || (interceptable.interceptors = []);
interceptors.push(handler);
return once(function () {
var idx = interceptors.indexOf(handler);
if (idx !== -1) interceptors.splice(idx, 1);
});
}
function interceptChange(interceptable, change) {
var prevU = untrackedStart();
try {
var interceptors = interceptable.interceptors;
if (interceptors) for (var i = 0, l = interceptors.length; i < l; i++) {
change = interceptors[i](change);
invariant(!change || change.type, "Intercept handlers should return nothing or a change object");
if (!change) break;
}
return change;
} finally {
untrackedEnd(prevU);
}
}
function hasListeners(listenable) {
return listenable.changeListeners !== undefined && listenable.changeListeners.length > 0;
}
function registerListener(listenable, handler) {
var listeners = listenable.changeListeners || (listenable.changeListeners = []);
listeners.push(handler);
return once(function () {
var idx = listeners.indexOf(handler);
if (idx !== -1) listeners.splice(idx, 1);
});
}
function notifyListeners(listenable, change) {
var prevU = untrackedStart();
var listeners = listenable.changeListeners;
if (!listeners) return;
listeners = listeners.slice();
for (var i = 0, l = listeners.length; i < l; i++) {
listeners[i](change);
}
untrackedEnd(prevU);
}
var UNCHANGED = {};
declareAtom();
var ObservableValue = /** @class */function (_super) {
__extends(ObservableValue, _super);
function ObservableValue(value, enhancer, name, notifySpy) {
if (name === void 0) {
name = "ObservableValue@" + getNextId();
}
if (notifySpy === void 0) {
notifySpy = true;
}
var _this = _super.call(this, name) || this;
_this.enhancer = enhancer;
_this.hasUnreportedChange = false;
_this.value = enhancer(value, undefined, name);
if (notifySpy && isSpyEnabled()) {
// only notify spy if this is a stand-alone observable
spyReport({ type: "create", name: _this.name, newValue: "" + _this.value });
}
return _this;
}
ObservableValue.prototype.dehanceValue = function (value) {
if (this.dehancer !== undefined) return this.dehancer(value);
return value;
};
ObservableValue.prototype.set = function (newValue) {
var oldValue = this.value;
newValue = this.prepareNewValue(newValue);
if (newValue !== UNCHANGED) {
var notifySpy = isSpyEnabled();
if (notifySpy) {
spyReportStart({
type: "update",
name: this.name,
newValue: newValue,
oldValue: oldValue
});
}
this.setNewValue(newValue);
if (notifySpy) spyReportEnd();
}
};
ObservableValue.prototype.prepareNewValue = function (newValue) {
checkIfStateModificationsAreAllowed(this);
if (hasInterceptors(this)) {
var change = interceptChange(this, {
object: this,
type: "update",
newValue: newValue
});
if (!change) return UNCHANGED;
newValue = change.newValue;
}
// apply modifier
newValue = this.enhancer(newValue, this.value, this.name);
return this.value !== newValue ? newValue : UNCHANGED;
};
ObservableValue.prototype.setNewValue = function (newValue) {
var oldValue = this.value;
this.value = newValue;
this.reportChanged();
if (hasListeners(this)) {
notifyListeners(this, {
type: "update",
object: this,
newValue: newValue,
oldValue: oldValue
});
}
};
ObservableValue.prototype.get = function () {
this.reportObserved();
return this.dehanceValue(this.value);
};
ObservableValue.prototype.intercept = function (handler) {
return registerInterceptor(this, handler);
};
ObservableValue.prototype.observe = function (listener, fireImmediately) {
if (fireImmediately) listener({
object: this,
type: "update",
newValue: this.value,
oldValue: undefined
});
return registerListener(this, listener);
};
ObservableValue.prototype.toJSON = function () {
return this.get();
};
ObservableValue.prototype.toString = function () {
return this.name + "[" + this.value + "]";
};
ObservableValue.prototype.valueOf = function () {
return toPrimitive(this.get());
};
return ObservableValue;
}(Atom);
ObservableValue.prototype[primitiveSymbol()] = ObservableValue.prototype.valueOf;
var isObservableValue = createInstanceofPredicate("ObservableValue", ObservableValue);
var ObservableObjectAdministration = /** @class */function () {
function ObservableObjectAdministration(target, name, defaultEnhancer) {
this.target = target;
this.name = name;
this.defaultEnhancer = defaultEnhancer;
this.values = {};
}
ObservableObjectAdministration.prototype.read = function (owner, key) {
if (this.target !== owner) {
this.illegalAccess(owner, key);
return;
}
return this.values[key].get();
};
ObservableObjectAdministration.prototype.write = function (owner, key, newValue) {
var instance = this.target;
if (instance !== owner) {
this.illegalAccess(owner, key);
return;
}
var observable = this.values[key];
if (observable instanceof ComputedValue) {
observable.set(newValue);
return;
}
// intercept
if (hasInterceptors(this)) {
var change = interceptChange(this, {
type: "update",
object: instance,
name: key,
newValue: newValue
});
if (!change) return;
newValue = change.newValue;
}
newValue = observable.prepareNewValue(newValue);
// notify spy & observers
if (newValue !== UNCHANGED) {
var notify = hasListeners(this);
var notifySpy = isSpyEnabled();
var change = notify || notifySpy ? {
type: "update",
object: instance,
oldValue: observable.value,
name: key,
newValue: newValue
} : null;
if (notifySpy) spyReportStart(__assign({}, change, { name: this.name, key: key }));
observable.setNewValue(newValue);
if (notify) notifyListeners(this, change);
if (notifySpy) spyReportEnd();
}
};
ObservableObjectAdministration.prototype.remove = function (key) {
if (!this.values[key]) return;
var target = this.target;
if (hasInterceptors(this)) {
var change = interceptChange(this, {
object: target,
name: key,
type: "remove"
});
if (!change) return;
}
try {
startBatch();
var notify = hasListeners(this);
var notifySpy = isSpyEnabled();
var oldValue = this.values[key].get();
if (this.keys) this.keys.remove(key);
delete this.values[key];
delete this.target[key];
var change = notify || notifySpy ? {
type: "remove",
object: target,
oldValue: oldValue,
name: key
} : null;
if (notifySpy) spyReportStart(__assign({}, change, { name: this.name, key: key }));
if (notify) notifyListeners(this, change);
if (notifySpy) spyReportEnd();
} finally {
endBatch();
}
};
ObservableObjectAdministration.prototype.illegalAccess = function (owner, propName) {
/**
* This happens if a property is accessed through the prototype chain, but the property was
* declared directly as own property on the prototype.
*
* E.g.:
* class A {
* }
* extendObservable(A.prototype, { x: 1 })
*
* classB extens A {
* }
* console.log(new B().x)
*
* It is unclear whether the property should be considered 'static' or inherited.
* Either use `console.log(A.x)`
* or: decorate(A, { x: observable })
*
* When using decorate, the property will always be redeclared as own property on the actual instance
*/
return fail$1("Property '" + propName + "' of '" + owner + "' was accessed through the prototype chain. Use 'decorate' instead to declare the prop or access it statically through it's owner");
};
/**
* Observes this object. Triggers for the events 'add', 'update' and 'delete'.
* See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/observe
* for callback details
*/
ObservableObjectAdministration.prototype.observe = function (callback, fireImmediately) {
undefined !== "production" && invariant(fireImmediately !== true, "`observe` doesn't support the fire immediately property for observable objects.");
return registerListener(this, callback);
};
ObservableObjectAdministration.prototype.intercept = function (handler) {
return registerInterceptor(this, handler);
};
ObservableObjectAdministration.prototype.getKeys = function () {
var _this = this;
if (this.keys === undefined) {
this.keys = new ObservableArray(Object.keys(this.values).filter(function (key) {
return _this.values[key] instanceof ObservableValue;
}), referenceEnhancer, "keys(" + this.name + ")", true);
}
return this.keys.slice();
};
return ObservableObjectAdministration;
}();
function asObservableObject(target, name, defaultEnhancer) {
if (name === void 0) {
name = "";
}
if (defaultEnhancer === void 0) {
defaultEnhancer = deepEnhancer;
}
var adm = target.$mobx;
if (adm) return adm;