diff --git a/src/re_frame/events.cljs b/src/re_frame/events.cljs index c0bd4b7..560518b 100644 --- a/src/re_frame/events.cljs +++ b/src/re_frame/events.cljs @@ -95,5 +95,12 @@ (if *handling* (console :error "re-frame: while handling \"" *handling* "\" dispatch-sync was called for \"" event-v "\". You can't call dispatch-sync in an event handler.") (binding [*handling* event-v] - (handler-fn app-db event-v)))))) + (let [stack (some-> event-v + meta + :stack)] + (try + (handler-fn app-db event-v) + (catch :default e + (console :warn stack) ;; output a msg to help to track down dispatching point + (throw e))))))))) diff --git a/src/re_frame/router.cljs b/src/re_frame/router.cljs index c64b025..3538a2c 100644 --- a/src/re_frame/router.cljs +++ b/src/re_frame/router.cljs @@ -144,7 +144,7 @@ [:paused :add-event] [:paused #(-add-event this arg)] [:paused :resume ] [:running #(-resume this)] - (throw (ex-info "re-frame: router state transition not found" {:fsm-state fsm-state :trigger trigger})))] + (throw (js/Error. (str "re-frame: router state transition not found. " fsm-state " " trigger))))] ;; The "case" above computed both the new FSM state, and the action. Now, make it happen. (set! fsm-state new-fsm-state) @@ -219,9 +219,15 @@ Usage example: (dispatch [:delete-item 42])" [event-v] - (if (nil? event-v) - (throw (ex-info "re-frame: you called \"dispatch\" without an event vector" {})) - (push event-queue event-v)) + (let [stack (->> (js/Error. + (str "Error thrown in event handler " (first event-v))) + .-stack + clojure.string/split-lines + (remove #(re-find #"react.inc.js|\(native\)" %)) ;; get rid of the react frames + (clojure.string/join "\n"))] ;; grab a stack here so that give it to events + (if (nil? event-v) + (throw (js/Error. "re-frame: you called \"dispatch\" without an event vector.")) + (push event-queue (with-meta event-v {:stack stack})))) nil) ;; Ensure nil return. See https://github.com/Day8/re-frame/wiki/Beware-Returning-False diff --git a/test/re-frame/event_test.cljs b/test/re-frame/event_test.cljs new file mode 100644 index 0000000..5167f7b --- /dev/null +++ b/test/re-frame/event_test.cljs @@ -0,0 +1,30 @@ +(ns re-frame.event-test + (:require [cljs.test :refer-macros [is deftest]] + [re-frame.db :as db] + [re-frame.core :as re-frame])) + +;=====test basic subscriptions ====== + +;; disabled as it doesn't really test anything +#_(deftest test-event-def + "tests that an error thrown generates an informational warning" + (re-frame/clear-all-events!) + + (re-frame/def-event + :test-event + (fn [db [event-kw stack]] + (throw (js/Error. "thrown in handler")) + db)) + + (defn test-fn1 + [] + (re-frame/dispatch [:test-event])) + + (defn test-fn2 + [] + (test-fn1)) + + (test-fn2) + ) + +