From e4ee6ce5679ae99f3c571a149a552ff1d9f716bf Mon Sep 17 00:00:00 2001 From: Daniel Compton Date: Fri, 9 Feb 2018 04:11:52 +1300 Subject: [PATCH] Provide not run subscriptions and avoid subs with a nil path --- src/day8/re_frame/trace/metamorphic.cljc | 47 +++++++++++++++--------- src/day8/re_frame/trace/subs.cljs | 2 +- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/day8/re_frame/trace/metamorphic.cljc b/src/day8/re_frame/trace/metamorphic.cljc index 95bf97d..925ae51 100644 --- a/src/day8/re_frame/trace/metamorphic.cljc +++ b/src/day8/re_frame/trace/metamorphic.cljc @@ -293,30 +293,43 @@ state)) + (defn process-sub-traces [initial-state traces] (let [first-pass (reduce (fn [state trace] (let [tags (get trace :tags) - reaction-id (:reaction tags)] - (case (:op-type trace) - :sub/create (assoc state reaction-id {:created? true - :subscription (:query-v tags) - :order [:sub/create]}) - :sub/run (update state reaction-id (fn [sub-state] - (-> (if (contains? sub-state :value) - ;; TODO: this should only update once per phase, even if a sub runs multiple times - (assoc sub-state :previous-value (:value sub-state)) - sub-state) - (assoc :run? true - :value (:value tags)) - (update :order (fnil conj []) :sub/run)))) - :sub/dispose (-> (assoc-in state [reaction-id :disposed?] true) - (update-in [reaction-id :order] (fnil conj []) :sub/dispose)) - (do #?(:cljs (js/console.warn "Unhandled sub trace, this is a bug, report to re-frame-trace please" trace)) - state)))) + reaction-id (:reaction tags) + state (-> state + (update-in [reaction-id :order] (fnil conj []) (:op-type trace)) + ;; In a perfect world we could provide this only in the :sub/create branch, but we have + ;; zombie reactions roaming the DOM, so we re-add it on every trace in case a sub was + ;; disposed of previously (and removed from the sub state). + (assoc-in [reaction-id :subscription] (:query-v tags))) + new-state + (case (:op-type trace) + :sub/create (-> state + (assoc-in [reaction-id :created?] true) + (assoc-in [reaction-id :subscription] (:query-v tags))) + :sub/run (update state reaction-id (fn [sub-state] + ;; TODO: should we keep track of subscriptions that have been disposed + ;; so we can detect zombies? + + ;; TODO: this should only update once per phase, even if a sub runs multiple times + (-> (if (contains? sub-state :value) + (assoc sub-state :previous-value (:value sub-state)) + sub-state) + (assoc :run? true + :value (:value tags))))) + :sub/dispose (assoc-in state [reaction-id :disposed?] true))] + (when-not (contains? (get new-state reaction-id) :subscription) + #?(:cljs (js/console.warn trace (get new-state reaction-id)))) + + + new-state)) initial-state traces) second-pass (reduce (fn [all-state [sub-id sub-state]] + ;; TODO: integrate this into the first pass for efficiency (if (and (contains? sub-state :previous-value) (contains? sub-state :value) (= (:previous-value sub-state) (:value sub-state))) diff --git a/src/day8/re_frame/trace/subs.cljs b/src/day8/re_frame/trace/subs.cljs index 15e4851..ce756ce 100644 --- a/src/day8/re_frame/trace/subs.cljs +++ b/src/day8/re_frame/trace/subs.cljs @@ -446,7 +446,7 @@ :layer (get-in sub-info [(first subscription) :layer]) :path-data subscription :path (pr-str subscription) - :order (:order state) + :order (or (:order state) [:sub/not-run]) :sub/traits (:sub/traits state)} sub (if (contains? state :value) (assoc sub :value (:value state))