:on-reload :noop should not leave stale references

This commit is contained in:
anatoly 2017-04-06 23:33:27 -04:00
parent 095eb81488
commit 4d961b56c0
2 changed files with 24 additions and 12 deletions

View file

@ -139,6 +139,13 @@
(or (-> s-var meta :on-reload)
:restart)) ;; restart by default on ns reload
(defn running-noop? [s-name]
(let [{:keys [var status]} (@meta-state s-name)
on-reload (-> var meta :on-reload)]
(when status
(and (status :started)
(= :noop on-reload)))))
;;TODO: make private after figuring out the inconsistency betwen cljs compile stages
;; (i.e. _sometimes_ this, if private, is not seen by expanded "defmacro" on cljs side)
(defn mount-it [s-var s-name s-meta]
@ -158,16 +165,20 @@
{:keys [start stop] :as lifecycle} (apply hash-map params)
state-name (with-ns *ns* state)
order (make-state-seq state-name)]
(validate lifecycle)
(let [s-meta (cond-> {:order order
:start `(fn [] ~start)
:status #{:stopped}}
stop (assoc :stop `(fn [] ~stop)))]
`(do
;; (log (str "|| mounting... " ~state-name))
(~'defonce ~state (DerefableState. ~state-name))
(mount-it (~'var ~state) ~state-name ~s-meta)
(~'var ~state))))))
(validate lifecycle)
(let [s-meta (cond-> {:order order
:start `(fn [] ~start)
:status #{:stopped}}
stop (assoc :stop `(fn [] ~stop)))]
`(do
;; (log (str "|| mounting... " ~state-name))
;; only create/redefine a new state iff this is not a running ^{:on-reload :noop}
(if-not (running-noop? ~state-name)
(do
(~'defonce ~state (DerefableState. ~state-name))
(mount-it (~'var ~state) ~state-name ~s-meta))
(~'defonce ~state (current-state ~state-name)))
(~'var ~state))))))
#?(:clj
(defmacro defstate! [state & {:keys [start! stop!]}]

View file

@ -35,8 +35,9 @@
(require 'mount.test.on-reload-helper :reload)
;; "a" is marked as :noop on reload
(is (instance? mount.core.NotStartedState (dval a))) ;; (!) stale reference of old a is still there somewhere
(is (= (-> pre-reload :a)
;; previous behavior left a stale reference =>>> ;; (is (instance? mount.core.NotStartedState (dval a))) ;; (!) stale reference of old a is still there somewhere
(is (= :started (dval a))) ;; make sure a still has the same instance as before reload
(is (= (-> pre-reload :a) ;; and the start was not called: the counter did not change
(-> @counter :a)))
;; "b" is marked as :stop on reload