Diff implementation appears to be working smoothly and correctly in my tests so far. Still disabled for now, but may turn switch soon.

This commit is contained in:
Aaron Craelius 2014-11-26 20:54:02 -05:00
parent 359f868fa4
commit 7cfced0678

View file

@ -120,12 +120,9 @@
(defn- remove-dom-node [dom-node] (defn- remove-dom-node [dom-node]
;(println "removing dom node") ;(println "removing dom node")
(let [state (aget element-state-lookup dom-node)] (dispose-node dom-node)
(dispose-node dom-node state) (when-let [parent (.-parentNode dom-node)]
(when-let [parent (.-parentNode dom-node)] (.removeChild parent dom-node)))
(.removeChild parent dom-node)
(when state
(js-delete (.-parent-state state) state)))))
(defn remove! [x] (defn remove! [x]
(if (dom-node? x) (if (dom-node? x)
@ -199,9 +196,9 @@
(def ^:private last-instrumentation-time) (def ^:private last-instrumentation-time)
(def fps (r/atom nil)) (defonce fps (r/atom nil))
(def frame-time (r/atom nil)) (defonce frame-time (r/atom nil))
(defonce (defonce
render-loop render-loop
@ -315,9 +312,9 @@
(defn- bind-event-listener! [element event-name handler node-state] (defn- bind-event-listener! [element event-name handler node-state]
(let [attr-state #js {:disposed false :handler handler (let [attr-state #js {:disposed false :handler handler
:disposed-callback (fn [] (unlisten! :disposed-callback
element event-name (let [unlisten!* unlisten!]
handler))}] (fn [] (unlisten!* element event-name handler)))}]
(register-with-parent-state node-state (str "-" "event" "." event-name) attr-state) (register-with-parent-state node-state (str "-" "event" "." event-name) attr-state)
(listen! element event-name handler))) (listen! element event-name handler)))
@ -413,48 +410,49 @@
(let [k (name k)] (let [k (name k)]
(rebind-attr! node k v node-state))))) (rebind-attr! node k v node-state)))))
(defn- replace-attrs!* [node node-state old-attrs new-attrs rebinder]
(let [hit #js {}]
(doseq [[k new-val] new-attrs]
(let [attr-name (name k)]
(rebinder node attr-name new-val node-state)
(when (get old-attrs k)
(aset hit attr-name true))))
(doseq [[k _] old-attrs]
(let [attr-name (name k)]
(when-not (aget hit attr-name)
(rebinder node attr-name nil node-state))))))
;(defn- replace-attrs!* [node node-state old-attrs new-attrs rebinder] ;(defn- replace-attrs!* [node node-state old-attrs new-attrs rebinder]
; (let [hit #js {}] ; (loop [[[k new-val] & new-attrs] (seq new-attrs)
; (doseq [[k new-val] new-attrs] ; old-attrs old-attrs]
; (if k
; (let [attr-name (name k)] ; (let [attr-name (name k)]
; (if-let [existing (get old-attrs k)] ; (if-let [existing (get old-attrs k)]
; (do ; (do
; (when-not (identical? existing new-val) ; (when-not (identical? existing new-val)
; (rebinder node attr-name new-val node-state)) ; (rebinder node attr-name new-val node-state))
; (aset hit attr-name true)) ; (recur new-attrs (dissoc old-attrs k)))
; (rebinder node attr-name new-val node-state)))) ; (do
; (doseq [[k _] old-attrs] ; (rebinder node attr-name new-val node-state)
; (let [attr-name (name k)] ; (recur new-attrs old-attrs))))
; (when-not (aget hit attr-name) ; (loop [[[k v] & old-attrs] (seq old-attrs)]
; (rebinder node attr-name nil node-state)))))) ; (when k
; (rebinder node (name k) nil node-state)
(defn- replace-attrs!* [node node-state old-attrs new-attrs rebinder] ; (recur old-attrs))))))
(loop [[[k new-val] & new-attrs] (seq new-attrs)
old-attrs old-attrs]
(if k
(let [attr-name (name k)]
(if-let [existing (get old-attrs k)]
(do
(when-not (identical? existing new-val)
(rebinder node attr-name new-val node-state))
(recur new-attrs (dissoc old-attrs k)))
(do
(rebinder node attr-name new-val node-state)
(recur new-attrs old-attrs))))
(loop [[[k v] & old-attrs] (seq old-attrs)]
(when k
(rebinder node (name k) nil node-state)
(recur old-attrs))))))
(defn- dispose-attrs [state] (defn- dispose-attrs [state]
(goog.object/forEach (let [child-states (.-child-states state)
(.-child-states state) to-remove #js []]
(fn [child-state child-key _] (goog.object/forEach
(when (identical? (aget child-key 0) "-") child-states
(set! (.-disposed child-state) true) (fn [child-state child-key _]
(when-let [cb (.-disposed-callback child-state)] (when (identical? (aget child-key 0) "-")
(cb)) (.push to-remove child-key)
(js-delete state child-key))))) (set! (.-disposed child-state) true)
(when-let [cb (.-disposed-callback child-state)]
(cb)))))
(doseq [child-key to-remove]
(js-delete child-states child-key))))
(defn- replace-attrs! [node old-attrs new-attrs] (defn- replace-attrs! [node old-attrs new-attrs]
(let [node-state (get-element-state node) (let [node-state (get-element-state node)
@ -464,11 +462,11 @@
(replace-attrs!* node node-state (replace-attrs!* node node-state
(dissoc old-attrs :style) (dissoc old-attrs :style)
(dissoc new-attrs :style) (dissoc new-attrs :style)
rebind-attr!) bind-attr!)
(replace-attrs!* node node-state (replace-attrs!* node node-state
old-style old-style
new-style new-style
rebind-style-prop!))) bind-style-prop!)))
;; From hiccup.compiler: ;; From hiccup.compiler:
(def ^{:doc "Regular expression that parses a CSS-style id and class from an element name." (def ^{:doc "Regular expression that parses a CSS-style id and class from an element name."
@ -495,16 +493,16 @@
(when class (set! (.-className node) (.replace class "." " "))) (when class (set! (.-className node) (.replace class "." " ")))
node)) node))
(defn- create-dom-node-simple [tag] ;(defn- create-dom-node-simple [tag]
(let [tag-ns (namespace tag) ; (let [tag-ns (namespace tag)
node (if tag-ns ; node (if tag-ns
(let [resolved-ns ; (let [resolved-ns
(if (identical? tag-ns "svg") ; (if (identical? tag-ns "svg")
"http://www.w3.org/2000/svg" ; "http://www.w3.org/2000/svg"
(get-xml-namespace tag-ns))] ; (get-xml-namespace tag-ns))]
(.createElementNS js/document resolved-ns tag)) ; (.createElementNS js/document resolved-ns tag))
(.createElement js/document tag))] ; (.createElement js/document tag))]
node)) ; node))
;; ## Core DOM Manipulation Methods ;; ## Core DOM Manipulation Methods
@ -585,15 +583,13 @@
(replace-attrs! cur-dom-node (replace-attrs! cur-dom-node
(when (map? old-attrs?) old-attrs?) (when (map? old-attrs?) old-attrs?)
new-attrs) new-attrs)
(when-not top-level
(dispose-child-state (get-element-state cur-dom-node) "-reactive"))
(reset-element-spec! cur-dom-node vdom) (reset-element-spec! cur-dom-node vdom)
(let [new-children (if new-attrs (nnext vdom) (next vdom)) (let [new-children (if new-attrs (nnext vdom) (next vdom))
dangling-child (try-diff-subseq cur-dom-node (.-firstChild cur-dom-node) new-children)] dangling-child (try-diff-subseq cur-dom-node (.-firstChild cur-dom-node) new-children)]
(loop [cur-child dangling-child] (loop [cur-child dangling-child]
(when cur-child (when cur-child
(let [next-sib (.-nextSibling cur-child)] (let [next-sib (.-nextSibling cur-child)]
(.removeChild cur-dom-node cur-child) (remove-dom-node cur-child)
(recur next-sib))))) (recur next-sib)))))
cur-dom-node)) cur-dom-node))
(do (do
@ -612,9 +608,8 @@
(if enable-diffing (if enable-diffing
(if top-level (if top-level
(do (do
(println "starting diff replace") ;(println "starting diff replace")
(time (try-diff parent new-virtual-dom cur-dom-node top-level))
(try-diff parent new-virtual-dom cur-dom-node top-level)))
(try-diff parent new-virtual-dom cur-dom-node top-level)) (try-diff parent new-virtual-dom cur-dom-node top-level))
(replace-node-completely parent new-elem-spec cur-dom-node top-level))))) (replace-node-completely parent new-elem-spec cur-dom-node top-level)))))