Skip to content

Commit 2f8c7dd

Browse files
committed
Removals, take 2
1 parent ddd9ed1 commit 2f8c7dd

File tree

4 files changed

+107
-81
lines changed

4 files changed

+107
-81
lines changed

src/Halogen/VDom/DOM.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,6 @@ exports.createElementNS = function (ns, name, doc) {
2424
};
2525
};
2626

27-
exports.tryRemoveChild = function (a, b) {
28-
return function () {
29-
try {
30-
b.removeChild(a);
31-
} catch (e) {
32-
}
33-
};
34-
};
35-
3627
exports.removeLastChild = function (a) {
3728
return function () {
3829
a.removeChild(a.lastChild);
@@ -50,3 +41,9 @@ exports.unsafeChildIx = function (i, d) {
5041
return d.childNodes.item(i);
5142
};
5243
};
44+
45+
exports.childNodesLength = function (a) {
46+
return function () {
47+
return a.childNodes.length | 0;
48+
};
49+
};

src/Halogen/VDom/DOM.purs

Lines changed: 85 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module Halogen.VDom.DOM
1313
import Prelude
1414
import Control.Monad.Eff (Eff, foreachE)
1515

16+
import Data.Array as Array
1617
import Data.Function.Uncurried as Fn
1718
import Data.Maybe (Maybe(..))
1819
import Data.Tuple (Tuple(..), fst)
@@ -23,7 +24,7 @@ import DOM.Node.Types (Element, Node, Document, elementToNode) as DOM
2324
import Halogen.VDom.Machine (Step(..), Machine)
2425
import Halogen.VDom.Machine as Machine
2526
import 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

2829
type 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+
3841
buildVDom
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
4245
buildVDom spec = render
4346
where
4447
render = case _ of
@@ -50,9 +53,9 @@ buildVDom spec = render
5053

5154
buildText
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
5659
buildText (VDomSpec spec) = render
5760
where
5861
render s = do
@@ -77,10 +80,10 @@ buildText (VDomSpec spec) = render
7780

7881
buildElem
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
8487
buildElem (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 len1case _ 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, 0do
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

135146
buildKeyed
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
141152
buildKeyed (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 len1case _ 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, 0do
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

198211
buildWidget
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
203216
buildWidget (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-
261270
foreign import removeLastChild
262271
eff
263272
. DOM.Node (Eff (dom DOM | eff) Unit)
@@ -269,3 +278,7 @@ foreign import insertChildIx
269278
foreign 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)

src/Halogen/VDom/Util.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ exports.forInE = function (o, f) {
2020
};
2121
};
2222

23+
exports.replicateE = function (n, f) {
24+
return function () {
25+
for (var i = 0; i < n; i++) {
26+
f();
27+
}
28+
};
29+
};
30+
2331
exports.diffWithIxE = function (a1, a2, f1, f2, f3) {
2432
return function () {
2533
var a3 = [];

src/Halogen/VDom/Util.purs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module Halogen.VDom.Util
22
( forE
33
, forInE
4+
, replicateE
45
, diffWithIxE
56
, diffWithKeyAndIxE
67
, strMapWithIxE
@@ -26,6 +27,13 @@ foreign import forInE
2627
(Fn.Fn2 String a (Eff eff Unit))
2728
(Eff eff Unit)
2829

30+
foreign import replicateE
31+
eff a
32+
. Fn.Fn2
33+
Int
34+
(Eff eff a)
35+
(Eff eff Unit)
36+
2937
foreign import diffWithIxE
3038
eff b c d
3139
. Fn.Fn5

0 commit comments

Comments
 (0)