From 1dfdd75f87bdb901817ae5c54cc1dfc7ff9e6893 Mon Sep 17 00:00:00 2001 From: Josh Perez Date: Sat, 11 Apr 2015 15:30:13 -0700 Subject: [PATCH] Catch errors in stores --- dist/alt-browser-with-addons.js | 13 ++++- dist/alt-browser.js | 13 ++++- dist/alt-with-runtime.js | 13 ++++- dist/alt.js | 13 ++++- src/alt.js | 18 ++++++- test/failed-dispatch-test.js | 95 +++++++++++++++++++++++++++++++++ 6 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 test/failed-dispatch-test.js diff --git a/dist/alt-browser-with-addons.js b/dist/alt-browser-with-addons.js index 9144d2df..f79edca7 100644 --- a/dist/alt-browser-with-addons.js +++ b/dist/alt-browser-with-addons.js @@ -1078,7 +1078,18 @@ var AltStore = (function () { } if (model[LISTENERS][payload.action]) { _this8[SET_STATE] = false; - var result = model[LISTENERS][payload.action](payload.data); + var result = false; + + try { + result = model[LISTENERS][payload.action](payload.data); + } catch (e) { + if (_this8[LIFECYCLE].error) { + _this8[LIFECYCLE].error(e, payload.action.toString(), payload.data, _this8[STATE_CONTAINER]); + } else { + throw e; + } + } + if (result !== false && _this8[SET_STATE] === false) { _this8.emitChange(); } diff --git a/dist/alt-browser.js b/dist/alt-browser.js index fe126aa5..74b31ba2 100644 --- a/dist/alt-browser.js +++ b/dist/alt-browser.js @@ -822,7 +822,18 @@ var AltStore = (function () { } if (model[LISTENERS][payload.action]) { _this8[SET_STATE] = false; - var result = model[LISTENERS][payload.action](payload.data); + var result = false; + + try { + result = model[LISTENERS][payload.action](payload.data); + } catch (e) { + if (_this8[LIFECYCLE].error) { + _this8[LIFECYCLE].error(e, payload.action.toString(), payload.data, _this8[STATE_CONTAINER]); + } else { + throw e; + } + } + if (result !== false && _this8[SET_STATE] === false) { _this8.emitChange(); } diff --git a/dist/alt-with-runtime.js b/dist/alt-with-runtime.js index 824a3ab1..9db0de62 100644 --- a/dist/alt-with-runtime.js +++ b/dist/alt-with-runtime.js @@ -79,7 +79,18 @@ var AltStore = (function () { } if (model[LISTENERS][payload.action]) { _this8[SET_STATE] = false; - var result = model[LISTENERS][payload.action](payload.data); + var result = false; + + try { + result = model[LISTENERS][payload.action](payload.data); + } catch (e) { + if (_this8[LIFECYCLE].error) { + _this8[LIFECYCLE].error(e, payload.action.toString(), payload.data, _this8[STATE_CONTAINER]); + } else { + throw e; + } + } + if (result !== false && _this8[SET_STATE] === false) { _this8.emitChange(); } diff --git a/dist/alt.js b/dist/alt.js index a3802d53..ca7d4731 100644 --- a/dist/alt.js +++ b/dist/alt.js @@ -91,7 +91,18 @@ var AltStore = (function () { } if (model[LISTENERS][payload.action]) { _this8[SET_STATE] = false; - var result = model[LISTENERS][payload.action](payload.data); + var result = false; + + try { + result = model[LISTENERS][payload.action](payload.data); + } catch (e) { + if (_this8[LIFECYCLE].error) { + _this8[LIFECYCLE].error(e, payload.action.toString(), payload.data, _this8[STATE_CONTAINER]); + } else { + throw e; + } + } + if (result !== false && _this8[SET_STATE] === false) { _this8.emitChange(); } diff --git a/src/alt.js b/src/alt.js index 23c5abbc..623a26d5 100644 --- a/src/alt.js +++ b/src/alt.js @@ -78,7 +78,23 @@ class AltStore { } if (model[LISTENERS][payload.action]) { this[SET_STATE] = false - const result = model[LISTENERS][payload.action](payload.data) + let result = false + + try { + result = model[LISTENERS][payload.action](payload.data) + } catch (e) { + if (this[LIFECYCLE].error) { + this[LIFECYCLE].error( + e, + payload.action.toString(), + payload.data, + this[STATE_CONTAINER] + ) + } else { + throw e + } + } + if (result !== false && this[SET_STATE] === false) { this.emitChange() } diff --git a/test/failed-dispatch-test.js b/test/failed-dispatch-test.js new file mode 100644 index 00000000..b6e59ff6 --- /dev/null +++ b/test/failed-dispatch-test.js @@ -0,0 +1,95 @@ +import { assert } from 'chai' +import Alt from '../dist/alt-with-runtime' +import sinon from 'sinon' + +export default { + 'catch failed dispatches': { + 'uncaught dispatches result in an error'() { + const alt = new Alt() + const actions = alt.generateActions('fire') + + class Uncaught { + constructor() { + this.bindListeners({ fire: actions.FIRE }) + } + + fire() { + throw new Error('oops') + } + } + + const uncaught = alt.createStore(Uncaught) + + assert.throws(() => actions.fire()) + }, + + 'errors can be caught though'() { + const alt = new Alt() + const actions = alt.generateActions('fire') + + class Caught { + constructor() { + this.x = 0 + this.bindListeners({ fire: actions.FIRE }) + + this.on('error', () => { + this.x = 1 + }) + } + + fire() { + throw new Error('oops') + } + } + + const caught = alt.createStore(Caught) + + const storeListener = sinon.spy() + + caught.listen(storeListener) + + assert(caught.getState().x === 0) + assert.doesNotThrow(() => actions.fire()) + assert(caught.getState().x === 1) + + assert.notOk(storeListener.calledOnce, 'the store did not emit a change') + + caught.unlisten(storeListener) + }, + + 'you have to emit changes yourself'() { + const alt = new Alt() + const actions = alt.generateActions('fire') + + class CaughtReturn { + constructor() { + this.x = 0 + this.bindListeners({ fire: actions.FIRE }) + + this.on('error', () => { + this.x = 1 + this.emitChange() + }) + } + + fire() { + throw new Error('oops') + } + } + + const caughtReturn = alt.createStore(CaughtReturn) + + const storeListener = sinon.spy() + + caughtReturn.listen(storeListener) + + assert(caughtReturn.getState().x === 0) + assert.doesNotThrow(() => actions.fire()) + assert(caughtReturn.getState().x === 1) + + assert.ok(storeListener.calledOnce) + + caughtReturn.unlisten(storeListener) + }, + } +}