From 6d71f48ab5c7378d20e6f1103da75e47ed148b23 Mon Sep 17 00:00:00 2001 From: Adrian Leonhard Date: Mon, 4 Dec 2017 21:01:53 +0100 Subject: [PATCH] Don't try/catch errors when globalstate.disableErrorBoundaries is on. Fixes https://github.com/mobxjs/mobx/issues/1241 --- CHANGELOG.md | 3 +++ src/core/computedvalue.ts | 10 +++++++--- src/core/derivation.ts | 24 ++++++++++++++++-------- src/core/globalstate.ts | 22 ++++++++++++++++++++++ src/mobx.ts | 8 ++++++-- 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e3b247f4..65be7e574 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 3.5.0 +* Added extras.disableErrorBoundaries() + # 3.4.0 * Improve Flow support support by exposing typings regularly. Flow will automatically include them now. In your `.flowconfig` will have to remove the import in the `[libs]` section (as it's done [here](https://github.com/mobxjs/mobx/pull/1254#issuecomment-348926416)). Fixes [#1232](https://github.com/mobxjs/mobx/issues/1232). diff --git a/src/core/computedvalue.ts b/src/core/computedvalue.ts index b40307c0a..ee2a53914 100644 --- a/src/core/computedvalue.ts +++ b/src/core/computedvalue.ts @@ -189,10 +189,14 @@ export class ComputedValue implements IObservable, IComputedValue, IDeriva if (track) { res = trackDerivedFunction(this, this.derivation, this.scope) } else { - try { + if (globalState.disableErrorBoundaries) { res = this.derivation.call(this.scope) - } catch (e) { - res = new CaughtException(e) + } else { + try { + res = this.derivation.call(this.scope) + } catch (e) { + res = new CaughtException(e) + } } } globalState.computationDepth-- diff --git a/src/core/derivation.ts b/src/core/derivation.ts index e6091fccc..ef25a65cc 100644 --- a/src/core/derivation.ts +++ b/src/core/derivation.ts @@ -81,12 +81,16 @@ export function shouldCompute(derivation: IDerivation): boolean { for (let i = 0; i < l; i++) { const obj = obs[i] if (isComputedValue(obj)) { - try { + if (globalState.disableErrorBoundaries) { obj.get() - } catch (e) { - // we are not interested in the value *or* exception at this moment, but if there is one, notify all - untrackedEnd(prevUntracked) - return true + } else { + try { + obj.get() + } catch (e) { + // we are not interested in the value *or* exception at this moment, but if there is one, notify all + untrackedEnd(prevUntracked) + return true + } } // if ComputedValue `obj` actually changed it will be computed and propagated to its observers. // and `derivation` is an observer of `obj` @@ -131,10 +135,14 @@ export function trackDerivedFunction(derivation: IDerivation, f: () => T, con const prevTracking = globalState.trackingDerivation globalState.trackingDerivation = derivation let result - try { + if (globalState.disableErrorBoundaries) { result = f.call(context) - } catch (e) { - result = new CaughtException(e) + } else { + try { + result = f.call(context) + } catch (e) { + result = new CaughtException(e) + } } globalState.trackingDerivation = prevTracking bindDependencies(derivation) diff --git a/src/core/globalstate.ts b/src/core/globalstate.ts index d74190e97..59e98d9a2 100644 --- a/src/core/globalstate.ts +++ b/src/core/globalstate.ts @@ -84,6 +84,12 @@ export class MobXGlobals { * Globally attached error handlers that react specifically to errors in reactions */ globalReactionErrorHandlers: ((error: any, derivation: IDerivation) => void)[] = [] + + /** + * Don't catch and rethrow exceptions. This is useful for inspecting the state of + * the stack when an exception occurs while debugging. + */ + disableErrorBoundaries = false } export let globalState: MobXGlobals = new MobXGlobals() @@ -153,3 +159,19 @@ export function resetGlobalState() { if (persistentKeys.indexOf(key) === -1) globalState[key] = defaultGlobals[key] globalState.allowStateChanges = !globalState.strictMode } + +/** + * Don't catch and rethrow exceptions. This is useful for inspecting the state of + * the stack when an exception occurs while debugging. + */ +export function disableErrorBoundaries() { + console.warn("WARNING: Debug feature only. MobX will NOT recover from errors if this is on.") + globalState.disableErrorBoundaries = true +} + +/** + * Opposite of disableErrorBoundaries + */ +export function enableErrorBoundaries() { + globalState.disableErrorBoundaries = false +} \ No newline at end of file diff --git a/src/mobx.ts b/src/mobx.ts index 81f5d4695..7a5335d76 100644 --- a/src/mobx.ts +++ b/src/mobx.ts @@ -98,7 +98,9 @@ import { resetGlobalState, shareGlobalState, getGlobalState, - isolateGlobalState + isolateGlobalState, + disableErrorBoundaries, + enableErrorBoundaries } from "./core/globalstate" import { IDerivation } from "./core/derivation" import { IDepTreeNode } from "./core/observable" @@ -139,7 +141,9 @@ export const extras = { spyReport, spyReportEnd, spyReportStart, - setReactionScheduler + setReactionScheduler, + disableErrorBoundaries, + enableErrorBoundaries, } // Deprecated default export (will be removed in 4.0)