@@ -13,6 +13,7 @@ module Halogen.VDom.DOM
1313import Prelude
1414import Control.Monad.Eff (Eff , foreachE )
1515
16+ import Data.Array as Array
1617import Data.Function.Uncurried as Fn
1718import Data.Maybe (Maybe (..))
1819import Data.Tuple (Tuple (..), fst )
@@ -23,7 +24,7 @@ import DOM.Node.Types (Element, Node, Document, elementToNode) as DOM
2324import Halogen.VDom.Machine (Step (..), Machine )
2425import Halogen.VDom.Machine as Machine
2526import Halogen.VDom.Types (VDom (..), ElemSpec (..), ElemName , Namespace (..), runGraft )
26- import Halogen.VDom.Util (forE , forInE , diffWithIxE , diffWithKeyAndIxE , strMapWithIxE , refEq )
27+ import Halogen.VDom.Util (forE , forInE , replicateE , diffWithIxE , diffWithKeyAndIxE , strMapWithIxE , refEq )
2728
2829type VDomMachine eff a b = Machine (Eff eff ) a b
2930
@@ -35,10 +36,12 @@ newtype VDomSpec eff a w = VDomSpec
3536 , document ∷ DOM.Document
3637 }
3738
39+ type VDomEffects eff = (dom ∷ DOM | eff )
40+
3841buildVDom
3942 ∷ ∀ eff a w
40- . VDomSpec (dom ∷ DOM | eff ) a w
41- → VDomMachine (dom ∷ DOM | eff ) (VDom a w ) DOM.Node
43+ . VDomSpec (VDomEffects eff ) a w
44+ → VDomMachine (VDomEffects eff ) (VDom a w ) DOM.Node
4245buildVDom spec = render
4346 where
4447 render = case _ of
@@ -50,9 +53,9 @@ buildVDom spec = render
5053
5154buildText
5255 ∷ ∀ eff a w
53- . VDomSpec (dom ∷ DOM | eff ) a w
56+ . VDomSpec (VDomEffects eff ) a w
5457 → String
55- → VDomStep (dom ∷ DOM | eff ) (VDom a w ) DOM.Node
58+ → VDomStep (VDomEffects eff ) (VDom a w ) DOM.Node
5659buildText (VDomSpec spec) = render
5760 where
5861 render s = do
@@ -77,10 +80,10 @@ buildText (VDomSpec spec) = render
7780
7881buildElem
7982 ∷ ∀ eff a w
80- . VDomSpec (dom ∷ DOM | eff ) a w
83+ . VDomSpec (VDomEffects eff ) a w
8184 → ElemSpec a
8285 → Array (VDom a w )
83- → VDomStep (dom ∷ DOM | eff ) (VDom a w ) DOM.Node
86+ → VDomStep (VDomEffects eff ) (VDom a w ) DOM.Node
8487buildElem (VDomSpec spec) = render
8588 where
8689 render es1@(ElemSpec ns1 name1 as1) ch1 = do
@@ -95,36 +98,44 @@ buildElem (VDomSpec spec) = render
9598 attrs ← spec.buildAttributes el as1
9699 pure
97100 (Step node
98- (Fn .runFn4 patch node attrs es1 steps)
101+ (Fn .runFn5 patch node attrs es1 steps ( Array .length ch1) )
99102 (Fn .runFn2 done attrs steps))
100103
101- patch = Fn .mkFn4 \node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 → case _ of
104+ patch = Fn .mkFn5 \node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 len1 → case _ of
102105 Grafted g →
103- Fn .runFn4 patch node attrs es1 ch1 (runGraft g)
104- Elem es2@(ElemSpec ns2 name2 as2) ch2 | Fn .runFn2 eqElemSpec es1 es2 → do
105- let
106- onThese = Fn .mkFn3 \ix (Step n step halt) vdom → do
107- res@Step n' m' h' ← step vdom
108- case Fn .runFn2 refEq n' n of
109- true → pure res
110- _ → do
111- halt
112- Fn .runFn2 tryRemoveChild n node
106+ Fn .runFn5 patch node attrs es1 ch1 len1 (runGraft g)
107+ Elem es2@(ElemSpec ns2 name2 as2) ch2 | Fn .runFn2 eqElemSpec es1 es2 →
108+ case len1, Array .length ch2 of
109+ 0 , 0 → do
110+ attrs' ← Machine .step attrs as2
111+ pure
112+ (Step node
113+ (Fn .runFn5 patch node attrs' es2 ch1 0 )
114+ (Fn .runFn2 done attrs' ch1))
115+ _, len2 → do
116+ let
117+ onThese = Fn .mkFn3 \ix (Step n step halt) vdom → do
118+ res@Step n' m' h' ← step vdom
113119 Fn .runFn3 insertChildIx ix n' node
120+ case Fn .runFn2 refEq n' n of
121+ true → pure res
122+ _ → do
123+ halt
124+ pure res
125+ onThis = Fn .mkFn2 \ix (Step _ _ halt) → do
126+ halt
127+ onThat = Fn .mkFn2 \ix vdom → do
128+ res@Step n m h ← buildVDom (VDomSpec spec) vdom
129+ Fn .runFn3 insertChildIx ix n node
114130 pure res
115- onThis = Fn .mkFn2 \ix (Step n _ halt) → do
116- halt
117- Fn .runFn2 tryRemoveChild n node
118- onThat = Fn .mkFn2 \ix vdom → do
119- res@Step n m h ← buildVDom (VDomSpec spec) vdom
120- Fn .runFn3 insertChildIx ix n node
121- pure res
122- steps ← Fn .runFn5 diffWithIxE ch1 ch2 onThese onThis onThat
123- attrs' ← Machine .step attrs as2
124- pure
125- (Step node
126- (Fn .runFn4 patch node attrs' es2 steps)
127- (Fn .runFn2 done attrs' steps))
131+ steps ← Fn .runFn5 diffWithIxE ch1 ch2 onThese onThis onThat
132+ lenD ← childNodesLength node
133+ Fn .runFn2 replicateE (lenD - len2) (removeLastChild node)
134+ attrs' ← Machine .step attrs as2
135+ pure
136+ (Step node
137+ (Fn .runFn5 patch node attrs' es2 steps len2)
138+ (Fn .runFn2 done attrs' steps))
128139 vdom →
129140 buildVDom (VDomSpec spec) vdom
130141
@@ -134,10 +145,10 @@ buildElem (VDomSpec spec) = render
134145
135146buildKeyed
136147 ∷ ∀ eff a w
137- . VDomSpec (dom ∷ DOM | eff ) a w
148+ . VDomSpec (VDomEffects eff ) a w
138149 → ElemSpec a
139150 → Array (Tuple String (VDom a w ))
140- → VDomStep (dom ∷ DOM | eff ) (VDom a w ) DOM.Node
151+ → VDomStep (VDomEffects eff ) (VDom a w ) DOM.Node
141152buildKeyed (VDomSpec spec) = render
142153 where
143154 render es1@(ElemSpec ns1 name1 as1) ch1 = do
@@ -147,59 +158,61 @@ buildKeyed (VDomSpec spec) = render
147158 onChild = Fn .mkFn3 \k ix (Tuple _ vdom) → do
148159 res@Step n m h ← buildVDom (VDomSpec spec) vdom
149160 Fn .runFn3 insertChildIx ix n node
150- pure ( Tuple ix res)
161+ pure res
151162 steps ← Fn .runFn3 strMapWithIxE ch1 fst onChild
152163 attrs ← spec.buildAttributes el as1
153164 pure
154165 (Step node
155- (Fn .runFn4 patch node attrs es1 steps)
166+ (Fn .runFn5 patch node attrs es1 steps ( Array .length ch1) )
156167 (Fn .runFn2 done attrs steps))
157168
158- patch = Fn .mkFn4 \node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 → case _ of
169+ patch = Fn .mkFn5 \node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 len1 → case _ of
159170 Grafted g →
160- Fn .runFn4 patch node attrs es1 ch1 (runGraft g)
161- Keyed es2@(ElemSpec ns2 name2 as2) ch2 | Fn .runFn2 eqElemSpec es1 es2 → do
162- let
163- onThese = Fn .mkFn4 \k ix' (Tuple ix (Step n step halt)) (Tuple _ vdom) →
164- if ix == ix'
165- then do
171+ Fn .runFn5 patch node attrs es1 ch1 len1 (runGraft g)
172+ Keyed es2@(ElemSpec ns2 name2 as2) ch2 | Fn .runFn2 eqElemSpec es1 es2 →
173+ case len1, Array .length ch2 of
174+ 0 , 0 → do
175+ attrs' ← Machine .step attrs as2
176+ pure
177+ (Step node
178+ (Fn .runFn5 patch node attrs' es2 ch1 0 )
179+ (Fn .runFn2 done attrs' ch1))
180+ _, len2 → do
181+ let
182+ onThese = Fn .mkFn4 \k ix' (Step n step halt) (Tuple _ vdom) → do
166183 res@Step n' m' h' ← step vdom
167- case Fn .runFn2 refEq n n' of
168- true → pure (Tuple ix' res)
184+ Fn .runFn3 insertChildIx ix' n' node
185+ case Fn .runFn2 refEq n' n of
186+ true → pure res
169187 _ → do
170188 halt
171- Fn .runFn2 tryRemoveChild n node
172- Fn .runFn3 insertChildIx ix' n' node
173- pure (Tuple ix' res)
174- else do
175- res@Step n' m' h' ← step vdom
176- Fn .runFn3 insertChildIx ix' n' node
177- pure (Tuple ix' res)
178- onThis = Fn .mkFn2 \k (Tuple _ (Step n _ halt)) → do
179- halt
180- Fn .runFn2 tryRemoveChild n node
181- onThat = Fn .mkFn3 \k ix (Tuple _ vdom) → do
182- res@Step n' m' h' ← buildVDom (VDomSpec spec) vdom
183- Fn .runFn3 insertChildIx ix n' node
184- pure (Tuple ix res)
185- steps ← Fn .runFn6 diffWithKeyAndIxE ch1 ch2 fst onThese onThis onThat
186- attrs' ← Machine .step attrs as2
187- pure
188- (Step node
189- (Fn .runFn4 patch node attrs' es2 steps)
190- (Fn .runFn2 done attrs' steps))
189+ pure res
190+ onThis = Fn .mkFn2 \k (Step _ _ halt) → do
191+ halt
192+ onThat = Fn .mkFn3 \k ix (Tuple _ vdom) → do
193+ res@Step n' m' h' ← buildVDom (VDomSpec spec) vdom
194+ Fn .runFn3 insertChildIx ix n' node
195+ pure res
196+ steps ← Fn .runFn6 diffWithKeyAndIxE ch1 ch2 fst onThese onThis onThat
197+ lenD ← childNodesLength node
198+ Fn .runFn2 replicateE (lenD - len2) (removeLastChild node)
199+ attrs' ← Machine .step attrs as2
200+ pure
201+ (Step node
202+ (Fn .runFn5 patch node attrs' es2 steps len2)
203+ (Fn .runFn2 done attrs' steps))
191204 vdom →
192205 buildVDom (VDomSpec spec) vdom
193206
194207 done = Fn .mkFn2 \attrs steps → do
195- Fn .runFn2 forInE steps (Fn .mkFn2 \_ (Tuple _ ( Step _ _ halt) ) → halt)
208+ Fn .runFn2 forInE steps (Fn .mkFn2 \_ (Step _ _ halt) → halt)
196209 Machine .halt attrs
197210
198211buildWidget
199212 ∷ ∀ eff a w
200- . VDomSpec (dom ∷ DOM | eff ) a w
213+ . VDomSpec (VDomEffects eff ) a w
201214 → w
202- → VDomStep (dom ∷ DOM | eff ) (VDom a w ) DOM.Node
215+ → VDomStep (VDomEffects eff ) (VDom a w ) DOM.Node
203216buildWidget (VDomSpec spec) = render
204217 where
205218 render w = do
@@ -254,10 +267,6 @@ foreign import createElementNS
254267 ∷ ∀ eff
255268 . Fn.Fn3 Namespace ElemName DOM.Document (Eff (dom ∷ DOM | eff ) DOM.Element )
256269
257- foreign import tryRemoveChild
258- ∷ ∀ eff
259- . Fn.Fn2 DOM.Node DOM.Node (Eff (dom ∷ DOM | eff ) Unit )
260-
261270foreign import removeLastChild
262271 ∷ ∀ eff
263272 . DOM.Node → (Eff (dom ∷ DOM | eff ) Unit )
@@ -269,3 +278,7 @@ foreign import insertChildIx
269278foreign import unsafeChildIx
270279 ∷ ∀ eff
271280 . Fn.Fn2 Int DOM.Node (Eff (dom ∷ DOM | eff ) DOM.Node )
281+
282+ foreign import childNodesLength
283+ ∷ ∀ eff
284+ . DOM.Node → (Eff (dom ∷ DOM | eff ) Int )
0 commit comments