From 348655b0e42a832e694d8656f06e4ca2cd692136 Mon Sep 17 00:00:00 2001 From: Daniel Reisel Date: Wed, 18 Jan 2017 16:47:01 +0200 Subject: [PATCH 1/7] moved constand Strings to messages.js --- src/api/action.ts | 10 +++++--- src/api/autorun.ts | 11 +++++---- src/api/computed.ts | 10 ++++---- src/api/expr.ts | 3 ++- src/api/extendobservable.ts | 12 +++++---- src/api/isobservable.ts | 3 ++- src/api/observable.ts | 6 +++-- src/api/observabledecorator.ts | 4 ++- src/api/transaction.ts | 4 ++- src/api/whyrun.ts | 5 ++-- src/core/action.ts | 8 +++--- src/core/computedvalue.ts | 18 +++++--------- src/core/derivation.ts | 6 +++-- src/core/reaction.ts | 31 ++++++----------------- src/types/observablemap.ts | 4 ++- src/types/observableobject.ts | 4 ++- src/types/type-utils.ts | 4 ++- src/utils/messages.ts | 45 ++++++++++++++++++++++++++++++++++ 18 files changed, 118 insertions(+), 70 deletions(-) create mode 100644 src/utils/messages.ts diff --git a/src/api/action.ts b/src/api/action.ts index 6e6c2ef6d..50cf9e3ed 100644 --- a/src/api/action.ts +++ b/src/api/action.ts @@ -1,6 +1,8 @@ import {invariant, addHiddenProp} from "../utils/utils"; import {createClassPropertyDecorator} from "../utils/decorators"; import {createAction, executeAction} from "../core/action"; +import {message} from "../utils/messages"; + export interface IActionFactory { // nameless actions @@ -51,7 +53,7 @@ const actionFieldDecorator = createClassPropertyDecorator( return this[key]; }, function () { - invariant(false, "It is not allowed to assign new values to @action fields"); + invariant(false, message("m001")); }, false, true @@ -65,7 +67,7 @@ const boundActionDecorator = createClassPropertyDecorator( return this[key]; }, function () { - invariant(false, "It is not allowed to assign new values to @action fields"); + invariant(false, message("m001")); }, false, false @@ -115,8 +117,8 @@ export function runInAction(arg1, arg2?, arg3?) { const fn = typeof arg1 === "function" ? arg1 : arg2; const scope = typeof arg1 === "function" ? arg2 : arg3; - invariant(typeof fn === "function", "`runInAction` expects a function"); - invariant(fn.length === 0, "`runInAction` expects a function without arguments"); + invariant(typeof fn === "function", message("m002")); + invariant(fn.length === 0, message("m003")); invariant(typeof actionName === "string" && actionName.length > 0, `actions should have valid names, got: '${actionName}'`); return executeAction(actionName, fn, scope, undefined); diff --git a/src/api/autorun.ts b/src/api/autorun.ts index cf65ad767..ce3c00aa9 100644 --- a/src/api/autorun.ts +++ b/src/api/autorun.ts @@ -3,6 +3,7 @@ import {isModifierDescriptor} from "../types/modifiers"; import {Reaction, IReactionPublic, IReactionDisposer} from "../core/reaction"; import {untrackedStart, untrackedEnd} from "../core/derivation"; import {action, isAction} from "../api/action"; +import {message} from "../utils/messages"; /** * Creates a reactive view and keeps it alive, so that the view is always @@ -37,10 +38,10 @@ export function autorun(arg1: any, arg2: any, arg3?: any) { scope = arg2; } - invariant(typeof view === "function", "autorun expects a function"); + invariant(typeof view === "function", message("m004")); invariant( isAction(view) === false, - "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." + message("m005") ); if (scope) view = view.bind(scope); @@ -121,7 +122,7 @@ export function autorunAsync(arg1: any, arg2: any, arg3?: any, arg4?: any) { } invariant( isAction(func) === false, - "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." + message("m006") ); if (delay === void 0) delay = 1; @@ -167,10 +168,10 @@ export function reaction(expression: (r: IReactionPublic) => T, effect: (arg: export function reaction(expression: (r: IReactionPublic) => T, effect: (arg: T, r: IReactionPublic) => void, fireImmediately?: boolean): IReactionDisposer; export function reaction(expression: (r: IReactionPublic) => T, effect: (arg: T, r: IReactionPublic) => void, arg3: any) { if (arguments.length > 3) { - fail("reaction only accepts 2 or 3 arguments. If migrating from MobX 2, please provide an options object"); + fail(message("m007")); } if (isModifierDescriptor(expression)) { - fail("wrapping reaction expression in `asReference` is no longer supported, use options object instead"); + fail(message("m008")); } let opts: IReactionOptions; diff --git a/src/api/computed.ts b/src/api/computed.ts index fd955a6cf..28830f59e 100644 --- a/src/api/computed.ts +++ b/src/api/computed.ts @@ -2,7 +2,7 @@ import {asObservableObject, defineComputedProperty} from "../types/observableobj import {invariant} from "../utils/utils"; import {createClassPropertyDecorator} from "../utils/decorators"; import {ComputedValue, IComputedValue} from "../core/computedvalue"; - +import {message} from "../utils/messages"; export interface IComputedValueOptions { compareStructural?: boolean; @@ -22,8 +22,8 @@ export interface IComputed { function createComputedDecorator(compareStructural) { return createClassPropertyDecorator( (target, name, _, __, originalDescriptor) => { - invariant(typeof originalDescriptor !== "undefined", "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'. It looks like it was used on a property."); - invariant(typeof originalDescriptor.get === "function", "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'"); + invariant(typeof originalDescriptor !== "undefined", message("m009")); + invariant(typeof originalDescriptor.get === "function", message("m010")); const adm = asObservableObject(target, ""); defineComputedProperty(adm, name, originalDescriptor.get, originalDescriptor.set, compareStructural, false); @@ -54,8 +54,8 @@ export var computed: IComputed = ( if (typeof arg2 === "string") { return computedDecorator.apply(null, arguments); } - invariant(typeof arg1 === "function", "First argument to `computed` should be an expression. If using computed as decorator, don't pass it arguments"); - invariant(arguments.length < 3, "computed takes one or two arguments if used as function"); + invariant(typeof arg1 === "function", message("m011")); + invariant(arguments.length < 3, message("m012")); const opts: IComputedValueOptions = typeof arg2 === "object" ? arg2 : {}; opts.setter = typeof arg2 === "function" ? arg2 : opts.setter; return new ComputedValue(arg1, opts.context, opts.compareStructural || false, opts.name || arg1.name || "", opts.setter); diff --git a/src/api/expr.ts b/src/api/expr.ts index 56045641f..9afb11cd0 100644 --- a/src/api/expr.ts +++ b/src/api/expr.ts @@ -1,5 +1,6 @@ import {computed} from "../api/computed"; import {isComputingDerivation} from "../core/derivation"; +import {message} from "../utils/messages"; /** * expr can be used to create temporarily views inside views. @@ -17,7 +18,7 @@ import {isComputingDerivation} from "../core/derivation"; */ export function expr(expr: () => T, scope?): T { if (!isComputingDerivation()) - console.warn("[mobx.expr] 'expr' should only be used inside other reactive functions."); + console.warn(message("m013")); // 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 return computed(expr, { context: scope }).get(); } diff --git a/src/api/extendobservable.ts b/src/api/extendobservable.ts index f7f5b92d4..7d8bbe3a1 100644 --- a/src/api/extendobservable.ts +++ b/src/api/extendobservable.ts @@ -3,6 +3,8 @@ import {asObservableObject, defineObservablePropertyFromDescriptor} from "../typ import {isObservable} from "../api/isobservable"; import {invariant, isPropertyConfigurable, hasOwnProperty} from "../utils/utils"; import {deepEnhancer, referenceEnhancer, IEnhancer} from "../types/modifiers"; +import {message} from "../utils/messages"; + export function extendObservable(target: A, ...properties: B[]): A & B { return extendObservableHelper(target, deepEnhancer, properties) as any; @@ -13,13 +15,13 @@ export function extendShallowObservable(targ } function extendObservableHelper(target: Object, defaultEnhancer: IEnhancer, properties: Object[]): Object { - invariant(arguments.length >= 2, "extendObservable expected 2 or more arguments"); - invariant(typeof target === "object", "extendObservable expects an object as first argument"); - invariant(!(isObservableMap(target)), "extendObservable should not be used on maps, use map.merge instead"); + invariant(arguments.length >= 2, message("m014")); + invariant(typeof target === "object", message("m015")); + invariant(!(isObservableMap(target)), message("m016")); properties.forEach(propSet => { - invariant(typeof propSet === "object", "all arguments of extendObservable should be objects"); - invariant(!isObservable(propSet), "extending an object with another observable (object) is not supported. Please construct an explicit propertymap, using `toJS` if need. See issue #540"); + invariant(typeof propSet === "object", message("m017")); + invariant(!isObservable(propSet), message("m018")); }); const adm = asObservableObject(target); diff --git a/src/api/isobservable.ts b/src/api/isobservable.ts index 9ced10a9d..26ab8d316 100644 --- a/src/api/isobservable.ts +++ b/src/api/isobservable.ts @@ -4,6 +4,7 @@ import {isObservableObject, ObservableObjectAdministration} from "../types/obser import {isAtom} from "../core/atom"; import {isComputedValue} from "../core/computedvalue"; import {isReaction} from "../core/reaction"; +import {message} from "../utils/messages"; /** * Returns true if the provided value is reactive. @@ -15,7 +16,7 @@ export function isObservable(value, property?: string): boolean { return false; if (property !== undefined) { if (isObservableArray(value) || isObservableMap(value)) - throw new Error("[mobx.isObservable] isObservable(object, propertyName) is not supported for arrays and maps. Use map.has or array.length instead."); + throw new Error(message("m019")); else if (isObservableObject(value)) { const o = (value as any).$mobx; return o.values && !!o.values[property]; diff --git a/src/api/observable.ts b/src/api/observable.ts index 2500b5084..0300610a4 100644 --- a/src/api/observable.ts +++ b/src/api/observable.ts @@ -7,6 +7,8 @@ import {isObservable} from "./isobservable"; import {IObservableObject, asObservableObject} from "../types/observableobject"; import {extendObservable, extendShallowObservable} from "../api/extendobservable"; import {IObservableMapInitialValues, ObservableMap, IMap} from "../types/observablemap"; +import {message} from "../utils/messages"; + const deepObservableDecorator = createDecoratorForEnhancer(deepEnhancer); const shallowObservableDecorator = createDecoratorForEnhancer(shallowEnhancer); @@ -21,8 +23,8 @@ function createObservable(v: any = undefined) { if (typeof arguments[1] === "string") return deepObservableDecorator.apply(null, arguments); - invariant(arguments.length <= 1, "observable expects zero or one arguments"); - invariant(!isModifierDescriptor(v), "modifiers can only be used for individual object properties"); + invariant(arguments.length <= 1, message("m021")); + invariant(!isModifierDescriptor(v), message("m020")); // it is an observable already, done if (isObservable(v)) diff --git a/src/api/observabledecorator.ts b/src/api/observabledecorator.ts index dad82ccad..eaeb2446e 100644 --- a/src/api/observabledecorator.ts +++ b/src/api/observabledecorator.ts @@ -3,13 +3,15 @@ import {asObservableObject, defineObservableProperty, setPropertyValue} from ".. import {invariant, assertPropertyConfigurable} from "../utils/utils"; import {createClassPropertyDecorator} from "../utils/decorators"; import {IEnhancer} from "../types/modifiers"; +import {message} from "../utils/messages"; + export function createDecoratorForEnhancer(enhancer: IEnhancer) { invariant(!!enhancer, ":("); return createClassPropertyDecorator( (target, name, baseValue, _, baseDescriptor) => { assertPropertyConfigurable(target, name); - invariant(!baseDescriptor || !baseDescriptor.get, "@observable can not be used on getters, use @computed instead"); + invariant(!baseDescriptor || !baseDescriptor.get, message("m022")); // might happen lazily (on first read), so temporarily allow state changes.. const prevA = allowStateChangesStart(true); diff --git a/src/api/transaction.ts b/src/api/transaction.ts index 8dc6c864c..e7c5c4ecd 100644 --- a/src/api/transaction.ts +++ b/src/api/transaction.ts @@ -1,5 +1,7 @@ import {deprecated} from "../utils/utils"; import {executeAction} from "../core/action"; +import {message} from "../utils/messages"; + /** * @deprecated @@ -12,7 +14,7 @@ import {executeAction} from "../core/action"; * @returns any value that was returned by the 'action' parameter. */ export function transaction(action: () => T, thisArg = undefined): T { - deprecated("Using `transaction` is deprecated, use `runInAction` or `(@)action` instead."); + deprecated(message("m023")); return runInTransaction.apply(undefined, arguments); } diff --git a/src/api/whyrun.ts b/src/api/whyrun.ts index 034d11dfb..3ca6b5200 100644 --- a/src/api/whyrun.ts +++ b/src/api/whyrun.ts @@ -3,6 +3,7 @@ import {isComputedValue} from "../core/computedvalue"; import {isReaction} from "../core/reaction"; import {getAtom} from "../types/type-utils"; import {fail, deprecated} from "../utils/utils"; +import {message} from "../utils/messages"; function log(msg: string): string { console.log(msg); @@ -14,7 +15,7 @@ export function whyRun(thing?: any, prop?: string) { case 0: thing = globalState.trackingDerivation; if (!thing) - return log("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 it's value."); + return log(message("m024")); break; case 2: thing = getAtom(thing, prop); @@ -25,5 +26,5 @@ export function whyRun(thing?: any, prop?: string) { return log(thing.whyRun()); else if (isReaction(thing)) return log(thing.whyRun()); - return fail("whyRun can only be used on reactions and computed values"); + return fail(message("m025")); } diff --git a/src/core/action.ts b/src/core/action.ts index 2e60e1f62..adde22237 100644 --- a/src/core/action.ts +++ b/src/core/action.ts @@ -5,9 +5,11 @@ import {startBatch, endBatch} from "../core/observable"; import {isSpyEnabled, spyReportStart, spyReportEnd} from "../core/spy"; import {isComputedValue} from "../core/computedvalue"; import {globalState} from "../core/globalstate"; +import {message} from "../utils/messages"; + export function createAction(actionName: string, fn: Function): Function { - invariant(typeof fn === "function", "`action` can only be invoked on functions"); + invariant(typeof fn === "function", message("m026")); invariant(typeof actionName === "string" && actionName.length > 0, `actions should have valid names, got: '${actionName}'`); const res = function () { return executeAction(actionName, fn, this, arguments); @@ -36,7 +38,7 @@ interface IActionRunInfo { function startAction(actionName: string, fn: Function, scope: any, args?: IArguments): IActionRunInfo { // actions should not be called from computeds. check only works if the computed is actively observed, but that is fine enough as heuristic - invariant(!isComputedValue(globalState.trackingDerivation), "Computed values or transformers should not invoke actions or trigger other side effects"); + invariant(!isComputedValue(globalState.trackingDerivation), message("m027")); const notifySpy = isSpyEnabled() && !!actionName; let startTime: number = 0; @@ -74,7 +76,7 @@ function endAction(runInfo: IActionRunInfo) { } export function useStrict(strict: boolean): any { - invariant(globalState.trackingDerivation === null, "It is not allowed to set `useStrict` when a derivation is running"); + invariant(globalState.trackingDerivation === null, message("m028")); globalState.strictMode = strict; globalState.allowStateChanges = !strict; } diff --git a/src/core/computedvalue.ts b/src/core/computedvalue.ts index 8355b2a35..a3c44bc17 100644 --- a/src/core/computedvalue.ts +++ b/src/core/computedvalue.ts @@ -6,6 +6,8 @@ import {createInstanceofPredicate, getNextId, valueDidChange, invariant, Lambda, import {isSpyEnabled, spyReport} from "../core/spy"; import {autorun} from "../api/autorun"; import {IValueDidChange} from "../types/observablevalue"; +import {message} from "../utils/messages"; + export interface IComputedValue { get(): T; @@ -71,7 +73,7 @@ export class ComputedValue implements IObservable, IComputedValue, IDeriva } onBecomeUnobserved() { - invariant(this.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR only onBecomeUnobserved shouldn't be called twice in a row"); + invariant(this.dependenciesState !== IDerivationState.NOT_TRACKING, message("m029")); clearObserving(this); this.value = undefined; } @@ -191,20 +193,12 @@ export class ComputedValue implements IObservable, IComputedValue, IDeriva WhyRun? computation '${this.name}': * Running because: ${isTracking ? "[active] the value of this computation is needed by a reaction" : this.isComputing ? "[get] The value of this computed was requested outside a reaction" : "[idle] not running at the moment"} ` + -(this.dependenciesState === IDerivationState.NOT_TRACKING -? -` * This computation is suspended (not in use by any reaction) and won't run automatically. - Didn't expect this computation to be suspended at this point? - 1. Make sure this computation is used by a reaction (reaction, autorun, observer). - 2. Check whether you are using this computation synchronously (in the same stack as they reaction that needs it). -` -: +(this.dependenciesState === IDerivationState.NOT_TRACKING ? message("m032") : ` * This computation will re-run if any of the following observables changes: ${joinStrings(observing)} ${(this.isComputing && isTracking) ? " (... or any observable accessed during the remainder of the current run)" : ""} - Missing items in this list? - 1. Check whether all used values are properly marked as observable (use isObservable to verify) - 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. + ${message("m038")} + * If the outcome of this computation changes, the following observers will be re-run: ${joinStrings(observers)} ` diff --git a/src/core/derivation.ts b/src/core/derivation.ts index cf0215a9f..682171d0e 100644 --- a/src/core/derivation.ts +++ b/src/core/derivation.ts @@ -2,6 +2,8 @@ import {IObservable, IDepTreeNode, addObserver, removeObserver} from "./observab import {globalState} from "./globalstate"; import {invariant} from "../utils/utils"; import {isComputedValue} from "./computedvalue"; +import {message} from "../utils/messages"; + export enum IDerivationState { // before being run or (outside batch and not being observed) @@ -103,8 +105,8 @@ export function isComputingDerivation() { export function checkIfStateModificationsAreAllowed() { if (!globalState.allowStateChanges) { invariant(false, globalState.strictMode - ? "It is not allowed to create or change state outside an `action` when MobX is in strict mode. Wrap the current method in `action` if this state change is intended" - : "It is not allowed to change the state when a computed value or transformer is being evaluated. Use 'autorun' to create reactive functions with side-effects." + ? message("m030") + :message("m031") ); } } diff --git a/src/core/reaction.ts b/src/core/reaction.ts index 7772d2e5d..c1c8263c9 100644 --- a/src/core/reaction.ts +++ b/src/core/reaction.ts @@ -3,6 +3,8 @@ import {IObservable, startBatch, endBatch} from "./observable"; import {globalState} from "./globalstate"; import {createInstanceofPredicate, getNextId, invariant, unique, joinStrings} from "../utils/utils"; import {isSpyEnabled, spyReport, spyReportStart, spyReportEnd} from "./spy"; +import {message} from "../utils/messages"; + /** * Reactions are a special kind of derivations. Several things distinguishes them from normal reactive computations @@ -124,36 +126,21 @@ export class Reaction implements IDerivation, IReactionPublic { return; } - const message = `[mobx] Catched uncaught exception that was thrown by a reaction or observer component, in: '${this}`; + const messageToConsole = `[mobx] Catched uncaught exception that was thrown by a reaction or observer component, in: '${this}`; const messageToUser = ` Hi there! I'm sorry you have just run into an exception. If your debugger ends up here, know that some reaction (like the render() of an observer component, autorun or reaction) - threw an exception and that mobx catched it, too avoid that it brings the rest of your application down. - - The original cause of the exception (the code that caused this reaction to run (again)), is still in the stack. - - However, more interesting is the actual stack trace of the error itself. - Hopefully the error is an instanceof Error, because in that case you can inspect the original stack of the error from where it was thrown. - See \`error.stack\` property, or press the very subtle "(...)" link you see near the console.error message that probably brought you here. - That stack is more interesting than the stack of this console.error itself. - - If the exception you see is an exception you created yourself, make sure to use \`throw new Error("Oops")\` instead of \`throw "Oops"\`, - because the javascript environment will only preserve the original stack trace in the first form. - - You can also make sure the debugger pauses the next time this very same exception is thrown by enabling "Pause on caught exception". - (Note that it might pause on many other, unrelated exception as well). - - If that all doesn't help you out, feel free to open an issue https://github.com/mobxjs/mobx/issues! - `; + threw an exception and that mobx caught it, to avoid that it brings the rest of your application down. + ` + message("m037"); - console.error(message || messageToUser /* latter will not be true, make sure uglify doesn't remove */, error); + console.error(messageToConsole || messageToUser /* latter will not be true, make sure uglify doesn't remove */, error); /** If debugging brough you here, please, read the above message :-). Tnx! */ if (isSpyEnabled()) { spyReport({ type: "error", - message, + messageToConsole, error, object: this }); @@ -193,9 +180,7 @@ WhyRun? reaction '${this.name}': * This reaction will re-run if any of the following observables changes: ${joinStrings(observing)} ${(this._isRunning) ? " (... or any observable accessed during the remainder of the current run)" : ""} - Missing items in this list? - 1. Check whether all used values are properly marked as observable (use isObservable to verify) - 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. + ${message("m038")} ` ); } diff --git a/src/types/observablemap.ts b/src/types/observablemap.ts index bdf2a65e3..02df122fe 100644 --- a/src/types/observablemap.ts +++ b/src/types/observablemap.ts @@ -11,6 +11,8 @@ import {arrayAsIterator, declareIterator, Iterator} from "../utils/iterable"; import {observable} from "../api/observable"; import {runInTransaction} from "../api/transaction"; import {referenceEnhancer} from "./modifiers"; +import {message} from "../utils/messages"; + /** * Map as defined by Typescript's lib.es2015.collection.d.ts @@ -303,7 +305,7 @@ export class ObservableMap implements IInterceptable>, ILis * for callback details */ observe(listener: (changes: IMapChange) => void, fireImmediately?: boolean): Lambda { - invariant(fireImmediately !== true, "`observe` doesn't support the fire immediately property for observable maps."); + invariant(fireImmediately !== true, message("m033")); return registerListener(this, listener); } diff --git a/src/types/observableobject.ts b/src/types/observableobject.ts index 1278d2fb2..9b35e6adb 100644 --- a/src/types/observableobject.ts +++ b/src/types/observableobject.ts @@ -7,6 +7,8 @@ import {IListenable, registerListener, hasListeners, notifyListeners} from "./li import {isSpyEnabled, spyReportStart, spyReportEnd} from "../core/spy"; import {IEnhancer, isModifierDescriptor, IModifierDescriptor} from "../types/modifiers"; import {isAction, defineBoundAction} from "../api/action"; +import {message} from "../utils/messages"; + export interface IObservableObject { @@ -59,7 +61,7 @@ export function asObservableObject(target, name?: string): ObservableObjectAdmin if (isObservableObject(target)) return (target as any).$mobx; - invariant(Object.isExtensible(target), "Cannot make the designated object observable; it is not extensible"); + invariant(Object.isExtensible(target), message("m035")); if (!isPlainObject(target)) name = (target.constructor.name || "ObservableObject") + "@" + getNextId(); if (!name) diff --git a/src/types/type-utils.ts b/src/types/type-utils.ts index d6477318d..e72e93866 100644 --- a/src/types/type-utils.ts +++ b/src/types/type-utils.ts @@ -7,11 +7,13 @@ import {isReaction} from "../core/reaction"; import {isObservableArray} from "../types/observablearray"; import {isObservableMap} from "../types/observablemap"; import {isObservableObject} from "../types/observableobject"; +import {message} from "../utils/messages"; + export function getAtom(thing: any, property?: string): IDepTreeNode { if (typeof thing === "object" && thing !== null) { if (isObservableArray(thing)) { - invariant(property === undefined, "It is not possible to get index atoms from arrays"); + invariant(property === undefined, message("m036")); return (thing as any).$mobx.atom; } if (isObservableMap(thing)) { diff --git a/src/utils/messages.ts b/src/utils/messages.ts new file mode 100644 index 000000000..32197d9e9 --- /dev/null +++ b/src/utils/messages.ts @@ -0,0 +1,45 @@ +const messages = { +"m001" : "It is not allowed to assign new values to @action fields" , +"m002" : "`runInAction` expects a function" , +"m003" : "`runInAction` expects a function without arguments" , +"m004" : "autorun expects a function" , +"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." , +"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." , +"m007" : "reaction only accepts 2 or 3 arguments. If migrating from MobX 2, please provide an options object" , +"m008" : "wrapping reaction expression in `asReference` is no longer supported, use options object instead" , +"m009" : "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'. It looks like it was used on a property." , +"m010" : "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'" , +"m011" : "First argument to `computed` should be an expression. If using computed as decorator, don't pass it arguments" , +"m012" : "computed takes one or two arguments if used as function" , +"m013" : "[mobx.expr] 'expr' should only be used inside other reactive functions." , +"m014" : "extendObservable expected 2 or more arguments" , +"m015" : "extendObservable expects an object as first argument" , +"m016" : "extendObservable should not be used on maps, use map.merge instead" , +"m017" : "all arguments of extendObservable should be objects" , +"m018" : "extending an object with another observable (object) is not supported. Please construct an explicit propertymap, using `toJS` if need. See issue #540" , +"m019" : "[mobx.isObservable] isObservable(object, propertyName) is not supported for arrays and maps. Use map.has or array.length instead." , +"m020" : "modifiers can only be used for individual object properties" , +"m021" : "observable expects zero or one arguments" , +"m022" : "@observable can not be used on getters, use @computed instead" , +"m023" : "Using `transaction` is deprecated, use `runInAction` or `(@)action` instead." , +"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 it's value." , +"m025" : "whyRun can only be used on reactions and computed values" , +"m026" : "`action` can only be invoked on functions" , +"m027" : "Computed values or transformers should not invoke actions or trigger other side effects" , +"m028" : "It is not allowed to set `useStrict` when a derivation is running" , +"m029" : "INTERNAL ERROR only onBecomeUnobserved shouldn't be called twice in a row" , +"m030" : "It is not allowed to create or change state outside an `action` when MobX is in strict mode. Wrap the current method in `action` if this state change is intended" , +"m031" : "It is not allowed to change the state when a computed value or transformer is being evaluated. Use 'autorun' to create reactive functions with side-effects." , +"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).", +"m033" : "`observe` doesn't support the fire immediately property for observable maps." , +"m034" : "`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead" , +"m035" : "Cannot make the designated object observable; it is not extensible" , +"m036" : "It is not possible to get index atoms from arrays" , +"m037" : "The original cause of the exception (the code that caused this reaction to run (again)), is still in the stack.\n\n However, more interesting is the actual stack trace of the error itself.\n Hopefully the error is an instanceof Error, because in that case you can inspect the original stack of the error from where it was thrown.\n See \`error.stack\` property, or press the very subtle \"(...)\" link you see near the console.error message that probably brought you here.\n That stack is more interesting than the stack of this console.error itself.\n\n If the exception you see is an exception you created yourself, make sure to use \`throw new Error(\"Oops\")\` instead of \`throw \"Oops\"\`,\n because the javascript environment will only preserve the original stack trace in the first form.\n\n You 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\n If that all doesn't help you out, feel free to open an issue https://github.com/mobxjs/mobx/issues!\n", +"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.", + +} + +export function message(id) { + return messages[id]; +}; \ No newline at end of file From 80639dd3fcfcfd2cdde6d45b2228e719c3a1a8a0 Mon Sep 17 00:00:00 2001 From: Daniel Reisel Date: Fri, 20 Jan 2017 01:26:14 +0200 Subject: [PATCH 2/7] renamed messages function --- src/api/action.ts | 10 +++++----- src/api/autorun.ts | 12 ++++++------ src/api/computed.ts | 10 +++++----- src/api/expr.ts | 4 ++-- src/api/extendobservable.ts | 12 ++++++------ src/api/isobservable.ts | 4 ++-- src/api/observable.ts | 6 +++--- src/api/observabledecorator.ts | 4 ++-- src/api/transaction.ts | 4 ++-- src/api/whyrun.ts | 6 +++--- src/core/action.ts | 8 ++++---- src/core/computedvalue.ts | 8 ++++---- src/core/derivation.ts | 6 +++--- src/core/reaction.ts | 17 ++++++----------- src/types/observablemap.ts | 4 ++-- src/types/observableobject.ts | 4 ++-- src/types/type-utils.ts | 4 ++-- src/utils/messages.ts | 4 ++-- 18 files changed, 61 insertions(+), 66 deletions(-) diff --git a/src/api/action.ts b/src/api/action.ts index 50cf9e3ed..786c880aa 100644 --- a/src/api/action.ts +++ b/src/api/action.ts @@ -1,7 +1,7 @@ import {invariant, addHiddenProp} from "../utils/utils"; import {createClassPropertyDecorator} from "../utils/decorators"; import {createAction, executeAction} from "../core/action"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; export interface IActionFactory { @@ -53,7 +53,7 @@ const actionFieldDecorator = createClassPropertyDecorator( return this[key]; }, function () { - invariant(false, message("m001")); + invariant(false, getMessage("m001")); }, false, true @@ -67,7 +67,7 @@ const boundActionDecorator = createClassPropertyDecorator( return this[key]; }, function () { - invariant(false, message("m001")); + invariant(false, getMessage("m001")); }, false, false @@ -117,8 +117,8 @@ export function runInAction(arg1, arg2?, arg3?) { const fn = typeof arg1 === "function" ? arg1 : arg2; const scope = typeof arg1 === "function" ? arg2 : arg3; - invariant(typeof fn === "function", message("m002")); - invariant(fn.length === 0, message("m003")); + invariant(typeof fn === "function", getMessage("m002")); + invariant(fn.length === 0, getMessage("m003")); invariant(typeof actionName === "string" && actionName.length > 0, `actions should have valid names, got: '${actionName}'`); return executeAction(actionName, fn, scope, undefined); diff --git a/src/api/autorun.ts b/src/api/autorun.ts index ce3c00aa9..b2db94ffd 100644 --- a/src/api/autorun.ts +++ b/src/api/autorun.ts @@ -3,7 +3,7 @@ import {isModifierDescriptor} from "../types/modifiers"; import {Reaction, IReactionPublic, IReactionDisposer} from "../core/reaction"; import {untrackedStart, untrackedEnd} from "../core/derivation"; import {action, isAction} from "../api/action"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; /** * Creates a reactive view and keeps it alive, so that the view is always @@ -38,10 +38,10 @@ export function autorun(arg1: any, arg2: any, arg3?: any) { scope = arg2; } - invariant(typeof view === "function", message("m004")); + invariant(typeof view === "function", getMessage("m004")); invariant( isAction(view) === false, - message("m005") + getMessage("m005") ); if (scope) view = view.bind(scope); @@ -122,7 +122,7 @@ export function autorunAsync(arg1: any, arg2: any, arg3?: any, arg4?: any) { } invariant( isAction(func) === false, - message("m006") + getMessage("m006") ); if (delay === void 0) delay = 1; @@ -168,10 +168,10 @@ export function reaction(expression: (r: IReactionPublic) => T, effect: (arg: export function reaction(expression: (r: IReactionPublic) => T, effect: (arg: T, r: IReactionPublic) => void, fireImmediately?: boolean): IReactionDisposer; export function reaction(expression: (r: IReactionPublic) => T, effect: (arg: T, r: IReactionPublic) => void, arg3: any) { if (arguments.length > 3) { - fail(message("m007")); + fail(getMessage("m007")); } if (isModifierDescriptor(expression)) { - fail(message("m008")); + fail(getMessage("m008")); } let opts: IReactionOptions; diff --git a/src/api/computed.ts b/src/api/computed.ts index 28830f59e..766648b7f 100644 --- a/src/api/computed.ts +++ b/src/api/computed.ts @@ -2,7 +2,7 @@ import {asObservableObject, defineComputedProperty} from "../types/observableobj import {invariant} from "../utils/utils"; import {createClassPropertyDecorator} from "../utils/decorators"; import {ComputedValue, IComputedValue} from "../core/computedvalue"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; export interface IComputedValueOptions { compareStructural?: boolean; @@ -22,8 +22,8 @@ export interface IComputed { function createComputedDecorator(compareStructural) { return createClassPropertyDecorator( (target, name, _, __, originalDescriptor) => { - invariant(typeof originalDescriptor !== "undefined", message("m009")); - invariant(typeof originalDescriptor.get === "function", message("m010")); + invariant(typeof originalDescriptor !== "undefined", getMessage("m009")); + invariant(typeof originalDescriptor.get === "function", getMessage("m010")); const adm = asObservableObject(target, ""); defineComputedProperty(adm, name, originalDescriptor.get, originalDescriptor.set, compareStructural, false); @@ -54,8 +54,8 @@ export var computed: IComputed = ( if (typeof arg2 === "string") { return computedDecorator.apply(null, arguments); } - invariant(typeof arg1 === "function", message("m011")); - invariant(arguments.length < 3, message("m012")); + invariant(typeof arg1 === "function", getMessage("m011")); + invariant(arguments.length < 3, getMessage("m012")); const opts: IComputedValueOptions = typeof arg2 === "object" ? arg2 : {}; opts.setter = typeof arg2 === "function" ? arg2 : opts.setter; return new ComputedValue(arg1, opts.context, opts.compareStructural || false, opts.name || arg1.name || "", opts.setter); diff --git a/src/api/expr.ts b/src/api/expr.ts index 9afb11cd0..a5fc98f5d 100644 --- a/src/api/expr.ts +++ b/src/api/expr.ts @@ -1,6 +1,6 @@ import {computed} from "../api/computed"; import {isComputingDerivation} from "../core/derivation"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; /** * expr can be used to create temporarily views inside views. @@ -18,7 +18,7 @@ import {message} from "../utils/messages"; */ export function expr(expr: () => T, scope?): T { if (!isComputingDerivation()) - console.warn(message("m013")); + console.warn(getMessage("m013")); // 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 return computed(expr, { context: scope }).get(); } diff --git a/src/api/extendobservable.ts b/src/api/extendobservable.ts index 7d8bbe3a1..a59802089 100644 --- a/src/api/extendobservable.ts +++ b/src/api/extendobservable.ts @@ -3,7 +3,7 @@ import {asObservableObject, defineObservablePropertyFromDescriptor} from "../typ import {isObservable} from "../api/isobservable"; import {invariant, isPropertyConfigurable, hasOwnProperty} from "../utils/utils"; import {deepEnhancer, referenceEnhancer, IEnhancer} from "../types/modifiers"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; export function extendObservable(target: A, ...properties: B[]): A & B { @@ -15,13 +15,13 @@ export function extendShallowObservable(targ } function extendObservableHelper(target: Object, defaultEnhancer: IEnhancer, properties: Object[]): Object { - invariant(arguments.length >= 2, message("m014")); - invariant(typeof target === "object", message("m015")); - invariant(!(isObservableMap(target)), message("m016")); + invariant(arguments.length >= 2, getMessage("m014")); + invariant(typeof target === "object", getMessage("m015")); + invariant(!(isObservableMap(target)), getMessage("m016")); properties.forEach(propSet => { - invariant(typeof propSet === "object", message("m017")); - invariant(!isObservable(propSet), message("m018")); + invariant(typeof propSet === "object", getMessage("m017")); + invariant(!isObservable(propSet), getMessage("m018")); }); const adm = asObservableObject(target); diff --git a/src/api/isobservable.ts b/src/api/isobservable.ts index 26ab8d316..36ae3f626 100644 --- a/src/api/isobservable.ts +++ b/src/api/isobservable.ts @@ -4,7 +4,7 @@ import {isObservableObject, ObservableObjectAdministration} from "../types/obser import {isAtom} from "../core/atom"; import {isComputedValue} from "../core/computedvalue"; import {isReaction} from "../core/reaction"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; /** * Returns true if the provided value is reactive. @@ -16,7 +16,7 @@ export function isObservable(value, property?: string): boolean { return false; if (property !== undefined) { if (isObservableArray(value) || isObservableMap(value)) - throw new Error(message("m019")); + throw new Error(getMessage("m019")); else if (isObservableObject(value)) { const o = (value as any).$mobx; return o.values && !!o.values[property]; diff --git a/src/api/observable.ts b/src/api/observable.ts index 0300610a4..e6c546f17 100644 --- a/src/api/observable.ts +++ b/src/api/observable.ts @@ -7,7 +7,7 @@ import {isObservable} from "./isobservable"; import {IObservableObject, asObservableObject} from "../types/observableobject"; import {extendObservable, extendShallowObservable} from "../api/extendobservable"; import {IObservableMapInitialValues, ObservableMap, IMap} from "../types/observablemap"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; const deepObservableDecorator = createDecoratorForEnhancer(deepEnhancer); @@ -23,8 +23,8 @@ function createObservable(v: any = undefined) { if (typeof arguments[1] === "string") return deepObservableDecorator.apply(null, arguments); - invariant(arguments.length <= 1, message("m021")); - invariant(!isModifierDescriptor(v), message("m020")); + invariant(arguments.length <= 1, getMessage("m021")); + invariant(!isModifierDescriptor(v), getMessage("m020")); // it is an observable already, done if (isObservable(v)) diff --git a/src/api/observabledecorator.ts b/src/api/observabledecorator.ts index eaeb2446e..b7a86b56a 100644 --- a/src/api/observabledecorator.ts +++ b/src/api/observabledecorator.ts @@ -3,7 +3,7 @@ import {asObservableObject, defineObservableProperty, setPropertyValue} from ".. import {invariant, assertPropertyConfigurable} from "../utils/utils"; import {createClassPropertyDecorator} from "../utils/decorators"; import {IEnhancer} from "../types/modifiers"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; export function createDecoratorForEnhancer(enhancer: IEnhancer) { @@ -11,7 +11,7 @@ export function createDecoratorForEnhancer(enhancer: IEnhancer) { return createClassPropertyDecorator( (target, name, baseValue, _, baseDescriptor) => { assertPropertyConfigurable(target, name); - invariant(!baseDescriptor || !baseDescriptor.get, message("m022")); + invariant(!baseDescriptor || !baseDescriptor.get, getMessage("m022")); // might happen lazily (on first read), so temporarily allow state changes.. const prevA = allowStateChangesStart(true); diff --git a/src/api/transaction.ts b/src/api/transaction.ts index e7c5c4ecd..c7074ce23 100644 --- a/src/api/transaction.ts +++ b/src/api/transaction.ts @@ -1,6 +1,6 @@ import {deprecated} from "../utils/utils"; import {executeAction} from "../core/action"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; /** @@ -14,7 +14,7 @@ import {message} from "../utils/messages"; * @returns any value that was returned by the 'action' parameter. */ export function transaction(action: () => T, thisArg = undefined): T { - deprecated(message("m023")); + deprecated(getMessage("m023")); return runInTransaction.apply(undefined, arguments); } diff --git a/src/api/whyrun.ts b/src/api/whyrun.ts index 3ca6b5200..deefd39fa 100644 --- a/src/api/whyrun.ts +++ b/src/api/whyrun.ts @@ -3,7 +3,7 @@ import {isComputedValue} from "../core/computedvalue"; import {isReaction} from "../core/reaction"; import {getAtom} from "../types/type-utils"; import {fail, deprecated} from "../utils/utils"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; function log(msg: string): string { console.log(msg); @@ -15,7 +15,7 @@ export function whyRun(thing?: any, prop?: string) { case 0: thing = globalState.trackingDerivation; if (!thing) - return log(message("m024")); + return log(getMessage("m024")); break; case 2: thing = getAtom(thing, prop); @@ -26,5 +26,5 @@ export function whyRun(thing?: any, prop?: string) { return log(thing.whyRun()); else if (isReaction(thing)) return log(thing.whyRun()); - return fail(message("m025")); + return fail(getMessage("m025")); } diff --git a/src/core/action.ts b/src/core/action.ts index adde22237..0d509f149 100644 --- a/src/core/action.ts +++ b/src/core/action.ts @@ -5,11 +5,11 @@ import {startBatch, endBatch} from "../core/observable"; import {isSpyEnabled, spyReportStart, spyReportEnd} from "../core/spy"; import {isComputedValue} from "../core/computedvalue"; import {globalState} from "../core/globalstate"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; export function createAction(actionName: string, fn: Function): Function { - invariant(typeof fn === "function", message("m026")); + invariant(typeof fn === "function", getMessage("m026")); invariant(typeof actionName === "string" && actionName.length > 0, `actions should have valid names, got: '${actionName}'`); const res = function () { return executeAction(actionName, fn, this, arguments); @@ -38,7 +38,7 @@ interface IActionRunInfo { function startAction(actionName: string, fn: Function, scope: any, args?: IArguments): IActionRunInfo { // actions should not be called from computeds. check only works if the computed is actively observed, but that is fine enough as heuristic - invariant(!isComputedValue(globalState.trackingDerivation), message("m027")); + invariant(!isComputedValue(globalState.trackingDerivation), getMessage("m027")); const notifySpy = isSpyEnabled() && !!actionName; let startTime: number = 0; @@ -76,7 +76,7 @@ function endAction(runInfo: IActionRunInfo) { } export function useStrict(strict: boolean): any { - invariant(globalState.trackingDerivation === null, message("m028")); + invariant(globalState.trackingDerivation === null, getMessage("m028")); globalState.strictMode = strict; globalState.allowStateChanges = !strict; } diff --git a/src/core/computedvalue.ts b/src/core/computedvalue.ts index a3c44bc17..957adff0b 100644 --- a/src/core/computedvalue.ts +++ b/src/core/computedvalue.ts @@ -6,7 +6,7 @@ import {createInstanceofPredicate, getNextId, valueDidChange, invariant, Lambda, import {isSpyEnabled, spyReport} from "../core/spy"; import {autorun} from "../api/autorun"; import {IValueDidChange} from "../types/observablevalue"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; export interface IComputedValue { @@ -73,7 +73,7 @@ export class ComputedValue implements IObservable, IComputedValue, IDeriva } onBecomeUnobserved() { - invariant(this.dependenciesState !== IDerivationState.NOT_TRACKING, message("m029")); + invariant(this.dependenciesState !== IDerivationState.NOT_TRACKING, getMessage("m029")); clearObserving(this); this.value = undefined; } @@ -193,11 +193,11 @@ export class ComputedValue implements IObservable, IComputedValue, IDeriva WhyRun? computation '${this.name}': * Running because: ${isTracking ? "[active] the value of this computation is needed by a reaction" : this.isComputing ? "[get] The value of this computed was requested outside a reaction" : "[idle] not running at the moment"} ` + -(this.dependenciesState === IDerivationState.NOT_TRACKING ? message("m032") : +(this.dependenciesState === IDerivationState.NOT_TRACKING ? getMessage("m032") : ` * This computation will re-run if any of the following observables changes: ${joinStrings(observing)} ${(this.isComputing && isTracking) ? " (... or any observable accessed during the remainder of the current run)" : ""} - ${message("m038")} + ${getMessage("m038")} * If the outcome of this computation changes, the following observers will be re-run: ${joinStrings(observers)} diff --git a/src/core/derivation.ts b/src/core/derivation.ts index 682171d0e..efa20114e 100644 --- a/src/core/derivation.ts +++ b/src/core/derivation.ts @@ -2,7 +2,7 @@ import {IObservable, IDepTreeNode, addObserver, removeObserver} from "./observab import {globalState} from "./globalstate"; import {invariant} from "../utils/utils"; import {isComputedValue} from "./computedvalue"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; export enum IDerivationState { @@ -105,8 +105,8 @@ export function isComputingDerivation() { export function checkIfStateModificationsAreAllowed() { if (!globalState.allowStateChanges) { invariant(false, globalState.strictMode - ? message("m030") - :message("m031") + ? getMessage("m030") + :getMessage("m031") ); } } diff --git a/src/core/reaction.ts b/src/core/reaction.ts index c1c8263c9..eea71ae3a 100644 --- a/src/core/reaction.ts +++ b/src/core/reaction.ts @@ -3,7 +3,7 @@ import {IObservable, startBatch, endBatch} from "./observable"; import {globalState} from "./globalstate"; import {createInstanceofPredicate, getNextId, invariant, unique, joinStrings} from "../utils/utils"; import {isSpyEnabled, spyReport, spyReportStart, spyReportEnd} from "./spy"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; /** @@ -126,21 +126,16 @@ export class Reaction implements IDerivation, IReactionPublic { return; } - const messageToConsole = `[mobx] Catched uncaught exception that was thrown by a reaction or observer component, in: '${this}`; - const messageToUser = ` - Hi there! I'm sorry you have just run into an exception. + const message = `[mobx] Catched uncaught exception that was thrown by a reaction or observer component, in: '${this}`; + const messageToUser = getMessage("m037"); - If your debugger ends up here, know that some reaction (like the render() of an observer component, autorun or reaction) - threw an exception and that mobx caught it, to avoid that it brings the rest of your application down. - ` + message("m037"); - - console.error(messageToConsole || messageToUser /* latter will not be true, make sure uglify doesn't remove */, error); + console.error(message || messageToUser /* latter will not be true, make sure uglify doesn't remove */, error); /** If debugging brough you here, please, read the above message :-). Tnx! */ if (isSpyEnabled()) { spyReport({ type: "error", - messageToConsole, + message, error, object: this }); @@ -180,7 +175,7 @@ WhyRun? reaction '${this.name}': * This reaction will re-run if any of the following observables changes: ${joinStrings(observing)} ${(this._isRunning) ? " (... or any observable accessed during the remainder of the current run)" : ""} - ${message("m038")} + ${getMessage("m038")} ` ); } diff --git a/src/types/observablemap.ts b/src/types/observablemap.ts index 02df122fe..4e2bf9cf1 100644 --- a/src/types/observablemap.ts +++ b/src/types/observablemap.ts @@ -11,7 +11,7 @@ import {arrayAsIterator, declareIterator, Iterator} from "../utils/iterable"; import {observable} from "../api/observable"; import {runInTransaction} from "../api/transaction"; import {referenceEnhancer} from "./modifiers"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; /** @@ -305,7 +305,7 @@ export class ObservableMap implements IInterceptable>, ILis * for callback details */ observe(listener: (changes: IMapChange) => void, fireImmediately?: boolean): Lambda { - invariant(fireImmediately !== true, message("m033")); + invariant(fireImmediately !== true, getMessage("m033")); return registerListener(this, listener); } diff --git a/src/types/observableobject.ts b/src/types/observableobject.ts index 9b35e6adb..b30b8ed0d 100644 --- a/src/types/observableobject.ts +++ b/src/types/observableobject.ts @@ -7,7 +7,7 @@ import {IListenable, registerListener, hasListeners, notifyListeners} from "./li import {isSpyEnabled, spyReportStart, spyReportEnd} from "../core/spy"; import {IEnhancer, isModifierDescriptor, IModifierDescriptor} from "../types/modifiers"; import {isAction, defineBoundAction} from "../api/action"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; @@ -61,7 +61,7 @@ export function asObservableObject(target, name?: string): ObservableObjectAdmin if (isObservableObject(target)) return (target as any).$mobx; - invariant(Object.isExtensible(target), message("m035")); + invariant(Object.isExtensible(target), getMessage("m035")); if (!isPlainObject(target)) name = (target.constructor.name || "ObservableObject") + "@" + getNextId(); if (!name) diff --git a/src/types/type-utils.ts b/src/types/type-utils.ts index e72e93866..cb45a806b 100644 --- a/src/types/type-utils.ts +++ b/src/types/type-utils.ts @@ -7,13 +7,13 @@ import {isReaction} from "../core/reaction"; import {isObservableArray} from "../types/observablearray"; import {isObservableMap} from "../types/observablemap"; import {isObservableObject} from "../types/observableobject"; -import {message} from "../utils/messages"; +import {getMessage} from "../utils/messages"; export function getAtom(thing: any, property?: string): IDepTreeNode { if (typeof thing === "object" && thing !== null) { if (isObservableArray(thing)) { - invariant(property === undefined, message("m036")); + invariant(property === undefined, getMessage("m036")); return (thing as any).$mobx.atom; } if (isObservableMap(thing)) { diff --git a/src/utils/messages.ts b/src/utils/messages.ts index 32197d9e9..76310fc3b 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -35,11 +35,11 @@ const messages = { "m034" : "`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead" , "m035" : "Cannot make the designated object observable; it is not extensible" , "m036" : "It is not possible to get index atoms from arrays" , -"m037" : "The original cause of the exception (the code that caused this reaction to run (again)), is still in the stack.\n\n However, more interesting is the actual stack trace of the error itself.\n Hopefully the error is an instanceof Error, because in that case you can inspect the original stack of the error from where it was thrown.\n See \`error.stack\` property, or press the very subtle \"(...)\" link you see near the console.error message that probably brought you here.\n That stack is more interesting than the stack of this console.error itself.\n\n If the exception you see is an exception you created yourself, make sure to use \`throw new Error(\"Oops\")\` instead of \`throw \"Oops\"\`,\n because the javascript environment will only preserve the original stack trace in the first form.\n\n You 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\n If that all doesn't help you out, feel free to open an issue https://github.com/mobxjs/mobx/issues!\n", +"m037" : "\nHi there! I'm sorry you have just run into an exception.\n\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\n However, more interesting is the actual stack trace of the error itself.\n Hopefully the error is an instanceof Error, because in that case you can inspect the original stack of the error from where it was thrown.\n See \`error.stack\` property, or press the very subtle \"(...)\" link you see near the console.error message that probably brought you here.\n That stack is more interesting than the stack of this console.error itself.\n\n If the exception you see is an exception you created yourself, make sure to use \`throw new Error(\"Oops\")\` instead of \`throw \"Oops\"\`,\n because the javascript environment will only preserve the original stack trace in the first form.\n\n You 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\n If that all doesn't help you out, feel free to open an issue https://github.com/mobxjs/mobx/issues!\n", "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.", } -export function message(id) { +export function getMessage(id) { return messages[id]; }; \ No newline at end of file From 0c5cfbe406cf4e50310ee5778763deb015d8b5ff Mon Sep 17 00:00:00 2001 From: Daniel Reisel Date: Fri, 20 Jan 2017 02:00:21 +0200 Subject: [PATCH 3/7] message typo --- src/utils/messages.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/messages.ts b/src/utils/messages.ts index 76310fc3b..1e10eda78 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -22,7 +22,7 @@ const messages = { "m021" : "observable expects zero or one arguments" , "m022" : "@observable can not be used on getters, use @computed instead" , "m023" : "Using `transaction` is deprecated, use `runInAction` or `(@)action` instead." , -"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 it's value." , +"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." , "m025" : "whyRun can only be used on reactions and computed values" , "m026" : "`action` can only be invoked on functions" , "m027" : "Computed values or transformers should not invoke actions or trigger other side effects" , From ac9aaac54b5dccae2e4e6816c6ec152a841ada56 Mon Sep 17 00:00:00 2001 From: Daniel Reisel Date: Fri, 20 Jan 2017 10:20:09 +0200 Subject: [PATCH 4/7] added type annotation --- src/utils/messages.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/messages.ts b/src/utils/messages.ts index 1e10eda78..b8b11152f 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -40,6 +40,6 @@ const messages = { } -export function getMessage(id) { +export function getMessage(id : string) { return messages[id]; }; \ No newline at end of file From 199f91428391eb3020c0321b50a1d1c583930a21 Mon Sep 17 00:00:00 2001 From: Daniel Reisel Date: Mon, 23 Jan 2017 18:21:30 +0200 Subject: [PATCH 5/7] added space --- test/perf/perf.txt | 76 +++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/test/perf/perf.txt b/test/perf/perf.txt index 130cec343..9824e0c85 100644 --- a/test/perf/perf.txt +++ b/test/perf/perf.txt @@ -1,51 +1,51 @@ -One observers many observes one - Started/Updated in 60/34 ms. -500 props observing sibling - Started/Updated in 3/11 ms. -Late dependency change - Updated in 135ms. +One observers many observes one - Started/Updated in 32/20 ms. +500 props observing sibling - Started/Updated in 4/2 ms. +Late dependency change - Updated in 48ms. Unused computables - Updated in 0 ms. -Unused observables - Updated in 25 ms. -Array reduce - Started/Updated in 57/44 ms. -Array loop - Started/Updated in 127/231 ms. -Order system batched: false tracked: true Started/Updated in 473/37 ms. -Order system batched: true tracked: true Started/Updated in 102/28 ms. -Order system batched: false tracked: false Started/Updated in 117/37 ms. -Order system batched: true tracked: false Started/Updated in 118/35 ms. +Unused observables - Updated in 8 ms. +Array reduce - Started/Updated in 29/26 ms. +Array loop - Started/Updated in 90/146 ms. +Order system batched: false tracked: true Started/Updated in 458/31 ms. +Order system batched: true tracked: true Started/Updated in 497/28 ms. +Order system batched: false tracked: false Started/Updated in 111/38 ms. +Order system batched: true tracked: false Started/Updated in 116/36 ms. -Create array - Created in 552ms. +Create array - Created in 277ms. -Create array (non-recursive) Created in 297ms. -Observable with many observers + dispose: 768ms -expensive sort: created 2787 -expensive sort: updated 12518 -expensive sort: disposed561 -native plain sort: updated 1087 +Create array (non-recursive) Created in 117ms. +Observable with many observers + dispose: 660ms +expensive sort: created 3013 +expensive sort: updated 10730 +expensive sort: disposed506 +native plain sort: updated 859 computed memoization 1ms create folders 0ms. create displayfolders 1ms. -create text 471ms. +create text 223ms. collapse folder 1ms. -uncollapse folder 1ms. -change name of folder 498ms. -search 103ms. -unsearch 438ms. +uncollapse folder 0ms. +change name of folder 217ms. +search 46ms. +unsearch 219ms. reactive folder tree [total] - 1517ms. -create folders 21ms. + 708ms. +create folders 24ms. create displayfolders 1ms. -create text 51ms. -collapse folder 2ms. -uncollapse folder 5ms. -change name of folder 10ms. -search 15ms. -unsearch 24ms. +create text 67ms. +collapse folder 3ms. +uncollapse folder 9ms. +change name of folder 8ms. +search 27ms. +unsearch 14ms. reactive folder tree [total] - 131ms. -create boxes 89ms. -mutations 523ms. -total 625ms. -create boxes 90ms. -mutations 928ms. -total 1084ms. + 154ms. +create boxes 83ms. +mutations 464ms. +total 558ms. +create boxes 91ms. +mutations 952ms. +total 1110ms. -Completed performance suite in 25.475 sec. \ No newline at end of file +Completed performance suite in 21.494 sec. \ No newline at end of file From 9f8cdab77d19b86da6af401c86b0212d1e413c8c Mon Sep 17 00:00:00 2001 From: Daniel Reisel Date: Mon, 23 Jan 2017 18:26:31 +0200 Subject: [PATCH 6/7] code cleaning --- src/core/derivation.ts | 2 +- src/utils/messages.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/derivation.ts b/src/core/derivation.ts index efa20114e..0d0a3f57c 100644 --- a/src/core/derivation.ts +++ b/src/core/derivation.ts @@ -106,7 +106,7 @@ export function checkIfStateModificationsAreAllowed() { if (!globalState.allowStateChanges) { invariant(false, globalState.strictMode ? getMessage("m030") - :getMessage("m031") + : getMessage("m031") ); } } diff --git a/src/utils/messages.ts b/src/utils/messages.ts index b8b11152f..270c64479 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -37,7 +37,6 @@ const messages = { "m036" : "It is not possible to get index atoms from arrays" , "m037" : "\nHi there! I'm sorry you have just run into an exception.\n\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\n However, more interesting is the actual stack trace of the error itself.\n Hopefully the error is an instanceof Error, because in that case you can inspect the original stack of the error from where it was thrown.\n See \`error.stack\` property, or press the very subtle \"(...)\" link you see near the console.error message that probably brought you here.\n That stack is more interesting than the stack of this console.error itself.\n\n If the exception you see is an exception you created yourself, make sure to use \`throw new Error(\"Oops\")\` instead of \`throw \"Oops\"\`,\n because the javascript environment will only preserve the original stack trace in the first form.\n\n You 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\n If that all doesn't help you out, feel free to open an issue https://github.com/mobxjs/mobx/issues!\n", "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.", - } export function getMessage(id : string) { From 7473ad5c57b1862612422e41a8a8c4886ee1b8a9 Mon Sep 17 00:00:00 2001 From: Daniel Reisel Date: Mon, 23 Jan 2017 22:42:49 +0200 Subject: [PATCH 7/7] Revert "added space" This reverts commit 199f91428391eb3020c0321b50a1d1c583930a21. --- test/perf/perf.txt | 76 +++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/test/perf/perf.txt b/test/perf/perf.txt index 9824e0c85..130cec343 100644 --- a/test/perf/perf.txt +++ b/test/perf/perf.txt @@ -1,51 +1,51 @@ -One observers many observes one - Started/Updated in 32/20 ms. -500 props observing sibling - Started/Updated in 4/2 ms. -Late dependency change - Updated in 48ms. +One observers many observes one - Started/Updated in 60/34 ms. +500 props observing sibling - Started/Updated in 3/11 ms. +Late dependency change - Updated in 135ms. Unused computables - Updated in 0 ms. -Unused observables - Updated in 8 ms. -Array reduce - Started/Updated in 29/26 ms. -Array loop - Started/Updated in 90/146 ms. -Order system batched: false tracked: true Started/Updated in 458/31 ms. -Order system batched: true tracked: true Started/Updated in 497/28 ms. -Order system batched: false tracked: false Started/Updated in 111/38 ms. -Order system batched: true tracked: false Started/Updated in 116/36 ms. +Unused observables - Updated in 25 ms. +Array reduce - Started/Updated in 57/44 ms. +Array loop - Started/Updated in 127/231 ms. +Order system batched: false tracked: true Started/Updated in 473/37 ms. +Order system batched: true tracked: true Started/Updated in 102/28 ms. +Order system batched: false tracked: false Started/Updated in 117/37 ms. +Order system batched: true tracked: false Started/Updated in 118/35 ms. -Create array - Created in 277ms. +Create array - Created in 552ms. -Create array (non-recursive) Created in 117ms. -Observable with many observers + dispose: 660ms -expensive sort: created 3013 -expensive sort: updated 10730 -expensive sort: disposed506 -native plain sort: updated 859 +Create array (non-recursive) Created in 297ms. +Observable with many observers + dispose: 768ms +expensive sort: created 2787 +expensive sort: updated 12518 +expensive sort: disposed561 +native plain sort: updated 1087 computed memoization 1ms create folders 0ms. create displayfolders 1ms. -create text 223ms. +create text 471ms. collapse folder 1ms. -uncollapse folder 0ms. -change name of folder 217ms. -search 46ms. -unsearch 219ms. +uncollapse folder 1ms. +change name of folder 498ms. +search 103ms. +unsearch 438ms. reactive folder tree [total] - 708ms. -create folders 24ms. + 1517ms. +create folders 21ms. create displayfolders 1ms. -create text 67ms. -collapse folder 3ms. -uncollapse folder 9ms. -change name of folder 8ms. -search 27ms. -unsearch 14ms. +create text 51ms. +collapse folder 2ms. +uncollapse folder 5ms. +change name of folder 10ms. +search 15ms. +unsearch 24ms. reactive folder tree [total] - 154ms. -create boxes 83ms. -mutations 464ms. -total 558ms. -create boxes 91ms. -mutations 952ms. -total 1110ms. + 131ms. +create boxes 89ms. +mutations 523ms. +total 625ms. +create boxes 90ms. +mutations 928ms. +total 1084ms. -Completed performance suite in 21.494 sec. \ No newline at end of file +Completed performance suite in 25.475 sec. \ No newline at end of file