/
batching.cljs
109 lines (89 loc) · 2.64 KB
/
batching.cljs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
(ns reagent.impl.batching
(:refer-clojure :exclude [flush])
(:require [reagent.debug :refer-macros [dbg]]
[reagent.interop :refer-macros [.' .!]]
[reagent.ratom :as ratom]
[reagent.impl.util :refer [is-client]]
[clojure.string :as string]))
;;; Update batching
(defonce mount-count 0)
(defn next-mount-count []
(set! mount-count (inc mount-count)))
(defn fake-raf [f]
(js/setTimeout f 16))
(def next-tick
(if-not is-client
fake-raf
(let [w js/window]
(or (.' w :requestAnimationFrame)
(.' w :webkitRequestAnimationFrame)
(.' w :mozRequestAnimationFrame)
(.' w :msRequestAnimationFrame)
fake-raf))))
(defn compare-mount-order [c1 c2]
(- (.' c1 :cljsMountOrder)
(.' c2 :cljsMountOrder)))
(defn run-queue [a]
;; sort components by mount order, to make sure parents
;; are rendered before children
(.sort a compare-mount-order)
(dotimes [i (alength a)]
(let [c (aget a i)]
(when (.' c :cljsIsDirty)
(.' c forceUpdate)))))
(defn run-funs [a]
(dotimes [i (alength a)]
((aget a i))))
(deftype RenderQueue [^:mutable queue ^:mutable scheduled?
^:mutable after-render]
Object
(queue-render [this c]
(.push queue c)
(.schedule this))
(add-after-render [_ f]
(.push after-render f))
(schedule [this]
(when-not scheduled?
(set! scheduled? true)
(next-tick #(.run-queue this))))
(run-queue [_]
(let [q queue aq after-render]
(set! queue (array))
(set! after-render (array))
(set! scheduled? false)
(run-queue q)
(run-funs aq))))
(def render-queue (RenderQueue. (array) false (array)))
(defn flush []
(.run-queue render-queue))
(defn queue-render [c]
(.! c :cljsIsDirty true)
(.queue-render render-queue c))
(defn mark-rendered [c]
(.! c :cljsIsDirty false))
(defn do-after-flush [f]
(.add-after-render render-queue f))
(defn do-later [f]
(do-after-flush f)
(.schedule render-queue))
;; Render helper
(defn is-reagent-component [c]
(some-> c (.' :props) (.' :argv)))
(defn run-reactively [c run]
(assert (is-reagent-component c))
(mark-rendered c)
(let [rat (.' c :cljsRatom)]
(if (nil? rat)
(let [res (ratom/capture-derefed run c)
derefed (ratom/captured c)]
(when (not (nil? derefed))
(.! c :cljsRatom
(ratom/make-reaction run
:auto-run #(queue-render c)
:derefed derefed)))
res)
(ratom/run rat))))
(defn dispose [c]
(some-> (.' c :cljsRatom)
ratom/dispose!)
(mark-rendered c))