Exceptions from reactions are now thrown on deref only

This commit is contained in:
Dan Holmsand 2015-09-13 11:00:07 +02:00
parent b036cf938e
commit 04daf6ac57
3 changed files with 52 additions and 31 deletions

View File

@ -206,6 +206,7 @@
(def ^:const clean 0) (def ^:const clean 0)
(def ^:const maybe-dirty 1) (def ^:const maybe-dirty 1)
(def ^:const dirty 2) (def ^:const dirty 2)
(def ^:const failed 3)
(deftype Reaction [f ^:mutable state ^:mutable ^number dirtyness (deftype Reaction [f ^:mutable state ^:mutable ^number dirtyness
^:mutable watching ^:mutable watches ^:mutable watching ^:mutable watches
@ -221,7 +222,7 @@
nil watches) nil watches)
nil) nil)
(-add-watch [this key f] (-add-watch [_ key f]
(set! watches (check-watches watches (assoc watches key f)))) (set! watches (check-watches watches (assoc watches key f))))
(-remove-watch [this key] (-remove-watch [this key]
@ -234,7 +235,7 @@
(-reset! [a newval] (-reset! [a newval]
(let [oldval state] (let [oldval state]
(set! state newval) (set! state newval)
(when on-set (when (some? on-set)
(set! dirtyness dirty) (set! dirtyness dirty)
(on-set oldval newval)) (on-set oldval newval))
(-notify-watches a oldval newval) (-notify-watches a oldval newval)
@ -260,14 +261,11 @@
(-check-clean [this] (-check-clean [this]
(when (== dirtyness maybe-dirty) (when (== dirtyness maybe-dirty)
(let [ar auto-run] (let [ar auto-run]
;; TODO: try/catch
(set! auto-run nil) (set! auto-run nil)
(doseq [w watching] (doseq [w watching]
(when (and (instance? Reaction w) (when (and (instance? Reaction w)
(not (-check-clean w))) (not (-check-clean w)))
(if-some [ar (.-auto-run w)] (._try-run this w)))
(ar w)
(run w))))
(set! auto-run ar)) (set! auto-run ar))
(when (== dirtyness maybe-dirty) (when (== dirtyness maybe-dirty)
(set! dirtyness clean))) (set! dirtyness clean)))
@ -299,6 +297,17 @@
(set! watching derefed) (set! watching derefed)
nil) nil)
Object
(_try-run [_ parent]
(try
(if-some [ar (.-auto-run parent)]
(ar parent)
(run parent))
(catch :default e
(set! (.-dirtyness parent) failed)
(set! (.-state parent) e)
(set! dirtyness dirty))))
IRunnable IRunnable
(run [this] (run [this]
(let [oldstate state (let [oldstate state
@ -319,6 +328,11 @@
IDeref IDeref
(-deref [this] (-deref [this]
(-check-clean this) (-check-clean this)
(when (== dirtyness failed)
(let [e state]
(set! dirtyness dirty)
(set! state nil)
(throw e)))
(if (and (nil? auto-run) (nil? *ratom-context*)) (if (and (nil? auto-run) (nil? *ratom-context*))
(when-not (== dirtyness clean) (when-not (== dirtyness clean)
(let [oldstate state (let [oldstate state
@ -361,7 +375,9 @@
;;; Queueing ;;; Queueing
(defonce render-queue nil) ;; Gets set up from batching ;; Gets set up from batching
;; TODO: Refactor so that isn't needed
(defonce render-queue nil)
(def dirty-queue nil) (def dirty-queue nil)

View File

@ -247,15 +247,17 @@
(is (= @b 6)) (is (= @b 6))
(is (= runs (running))))) (is (= runs (running)))))
;; (deftest catching (deftest catching
;; (let [runs (running) (let [runs (running)
;; a (rv/atom false) a (rv/atom false)
;; catch-count (atom 0) catch-count (atom 0)
;; b (reaction (if @a (throw {}))) b (reaction (if @a (throw (js/Error. "fail"))))
;; c (run! (try @b (catch js/Object e c (run! (try @b (catch :default e
;; (swap! catch-count inc))))] (swap! catch-count inc))))]
;; (is (= @catch-count 0)) (is (= @catch-count 0))
;; (reset! a false) (reset! a false)
;; (is (= @catch-count 0)) (is (= @catch-count 0))
;; (reset! a true) (reset! a true)
;; (is (= @catch-count 1)))) (is (= @catch-count 1))
(reset! a false)
(is (= @catch-count 1))))

View File

@ -271,15 +271,18 @@
(is (= @b 6)) (is (= @b 6))
(is (= runs (running))))) (is (= runs (running)))))
;; (deftest catching (deftest catching
;; (let [runs (running) (let [runs (running)
;; a (rv/atom false) a (rv/atom false)
;; catch-count (atom 0) catch-count (atom 0)
;; b (reaction (if @a (throw {}))) b (reaction (if @a (throw (js/Error. "reaction fail"))))
;; c (run! (try @b (catch js/Object e c (ar (fn [] (try @b (catch js/Object e
;; (swap! catch-count inc))))] (swap! catch-count inc)))))]
;; (is (= @catch-count 0)) (is (= @catch-count 0))
;; (reset! a false) (reset! a false)
;; (is (= @catch-count 0)) (sync)
;; (reset! a true) (is (= @catch-count 0))
;; (is (= @catch-count 1)))) (reset! a true)
(is (= @catch-count 0))
(sync)
(is (= @catch-count 1))))