Skip to content

Commit dbfe6dd

Browse files
committed
Rework finalizers, work around edge cases
1 parent 2f8c7dd commit dbfe6dd

File tree

8 files changed

+250
-246
lines changed

8 files changed

+250
-246
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55
/.psci*
66
/src/.webpack.js
77
app.js
8+
.psc-ide-port

src/Halogen/VDom/DOM.js

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/Halogen/VDom/DOM.purs

Lines changed: 61 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ module Halogen.VDom.DOM
77
, buildElem
88
, buildKeyed
99
, buildWidget
10-
, createElem
1110
) where
1211

1312
import Prelude
@@ -23,8 +22,8 @@ import DOM.Node.Types (Element, Node, Document, elementToNode) as DOM
2322

2423
import Halogen.VDom.Machine (Step(..), Machine)
2524
import Halogen.VDom.Machine as Machine
26-
import Halogen.VDom.Types (VDom(..), ElemSpec(..), ElemName, Namespace(..), runGraft)
27-
import Halogen.VDom.Util (forE, forInE, replicateE, diffWithIxE, diffWithKeyAndIxE, strMapWithIxE, refEq)
25+
import Halogen.VDom.Types (VDom(..), ElemSpec(..), ElemName(..), Namespace(..), runGraft)
26+
import Halogen.VDom.Util as Util
2827

2928
type VDomMachine eff a b = Machine (Eff eff) a b
3029

@@ -59,24 +58,25 @@ buildText
5958
buildText (VDomSpec spec) = render
6059
where
6160
render s = do
62-
node ← Fn.runFn2 createTextNode s spec.document
63-
pure (Step node (Fn.runFn2 patch node s) done)
61+
node ← Fn.runFn2 Util.createTextNode s spec.document
62+
pure (Step node (Fn.runFn2 patch node s) (done node))
6463

6564
patch = Fn.mkFn2 \node s1 → case _ of
6665
Grafted g →
6766
Fn.runFn2 patch node s1 (runGraft g)
6867
Text s2 → do
69-
let
70-
res = Step node (Fn.runFn2 patch node s2) done
68+
let res = Step node (Fn.runFn2 patch node s2) (done node)
7169
case s1 == s2 of
72-
trueeffPure res
70+
truepure res
7371
_ → do
74-
Fn.runFn2 setTextContent s2 node
72+
Fn.runFn2 Util.setTextContent s2 node
7573
pure res
76-
vdom →
74+
vdom → do
75+
done node
7776
buildVDom (VDomSpec spec) vdom
7877

79-
done = pure unit
78+
done node = do
79+
Fn.runFn2 Util.removeChild node (Util.unsafeParent node)
8080

8181
buildElem
8282
eff a w
@@ -92,54 +92,49 @@ buildElem (VDomSpec spec) = render
9292
node = DOM.elementToNode el
9393
onChild = Fn.mkFn2 \ix child → do
9494
res@Step n m h ← buildVDom (VDomSpec spec) child
95-
Fn.runFn3 insertChildIx ix n node
95+
Fn.runFn3 Util.insertChildIx ix n node
9696
pure res
97-
steps ← Fn.runFn2 forE ch1 onChild
97+
steps ← Fn.runFn2 Util.forE ch1 onChild
9898
attrs ← spec.buildAttributes el as1
9999
pure
100100
(Step node
101-
(Fn.runFn5 patch node attrs es1 steps (Array.length ch1))
102-
(Fn.runFn2 done attrs steps))
101+
(Fn.runFn4 patch node attrs es1 steps)
102+
(Fn.runFn3 done node attrs steps))
103103

104-
patch = Fn.mkFn5 \node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 len1case _ of
104+
patch = Fn.mkFn4 \node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 → case _ of
105105
Grafted g →
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
106+
Fn.runFn4 patch node attrs es1 ch1 (runGraft g)
107+
Elem es2@(ElemSpec ns2 name2 as2) ch2 | Fn.runFn2 eqElemSpec es1 es2 → do
108+
case Array.length ch1, Array.length ch2 of
109109
0, 0do
110110
attrs' ← Machine.step attrs as2
111111
pure
112112
(Step node
113-
(Fn.runFn5 patch node attrs' es2 ch1 0)
114-
(Fn.runFn2 done attrs' ch1))
115-
_, len2do
113+
(Fn.runFn4 patch node attrs' es2 ch1)
114+
(Fn.runFn3 done node attrs' ch1))
115+
_, _do
116116
let
117-
onThese = Fn.mkFn3 \ix (Step n step halt) vdom → do
117+
onThese = Fn.mkFn3 \ix (prev@Step n step halt) vdom → do
118118
res@Step n' m' h' ← step vdom
119-
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
119+
Fn.runFn3 Util.insertChildIx ix n' node
120+
pure res
121+
onThis = Fn.mkFn2 \ix (res@Step n _ halt) → halt
127122
onThat = Fn.mkFn2 \ix vdom → do
128123
res@Step n m h ← buildVDom (VDomSpec spec) vdom
129-
Fn.runFn3 insertChildIx ix n node
124+
Fn.runFn3 Util.insertChildIx ix n node
130125
pure res
131-
steps ← Fn.runFn5 diffWithIxE ch1 ch2 onThese onThis onThat
132-
lenD ← childNodesLength node
133-
Fn.runFn2 replicateE (lenD - len2) (removeLastChild node)
126+
steps ← Fn.runFn5 Util.diffWithIxE ch1 ch2 onThese onThis onThat
134127
attrs' ← Machine.step attrs as2
135128
pure
136129
(Step node
137-
(Fn.runFn5 patch node attrs' es2 steps len2)
138-
(Fn.runFn2 done attrs' steps))
139-
vdom →
130+
(Fn.runFn4 patch node attrs' es2 steps)
131+
(Fn.runFn3 done node attrs' steps))
132+
vdom → do
133+
Fn.runFn3 done node attrs ch1
140134
buildVDom (VDomSpec spec) vdom
141135

142-
done = Fn.mkFn2 \attrs steps → do
136+
done = Fn.mkFn3 \node attrs steps → do
137+
Fn.runFn2 Util.removeChild node (Util.unsafeParent node)
143138
foreachE steps Machine.halt
144139
Machine.halt attrs
145140

@@ -157,14 +152,14 @@ buildKeyed (VDomSpec spec) = render
157152
node = DOM.elementToNode el
158153
onChild = Fn.mkFn3 \k ix (Tuple _ vdom) → do
159154
res@Step n m h ← buildVDom (VDomSpec spec) vdom
160-
Fn.runFn3 insertChildIx ix n node
155+
Fn.runFn3 Util.insertChildIx ix n node
161156
pure res
162-
steps ← Fn.runFn3 strMapWithIxE ch1 fst onChild
157+
steps ← Fn.runFn3 Util.strMapWithIxE ch1 fst onChild
163158
attrs ← spec.buildAttributes el as1
164159
pure
165160
(Step node
166161
(Fn.runFn5 patch node attrs es1 steps (Array.length ch1))
167-
(Fn.runFn2 done attrs steps))
162+
(Fn.runFn3 done node attrs steps))
168163

169164
patch = Fn.mkFn5 \node attrs (es1@(ElemSpec ns1 name1 as1)) ch1 len1 → case _ of
170165
Grafted g →
@@ -176,36 +171,31 @@ buildKeyed (VDomSpec spec) = render
176171
pure
177172
(Step node
178173
(Fn.runFn5 patch node attrs' es2 ch1 0)
179-
(Fn.runFn2 done attrs' ch1))
174+
(Fn.runFn3 done node attrs' ch1))
180175
_, len2 → do
181176
let
182-
onThese = Fn.mkFn4 \k ix' (Step n step halt) (Tuple _ vdom) → do
177+
onThese = Fn.mkFn4 \k ix' (Step n step _) (Tuple _ vdom) → do
183178
res@Step n' m' h' ← step vdom
184-
Fn.runFn3 insertChildIx ix' n' node
185-
case Fn.runFn2 refEq n' n of
186-
true → pure res
187-
_ → do
188-
halt
189-
pure res
190-
onThis = Fn.mkFn2 \k (Step _ _ halt) → do
191-
halt
179+
Fn.runFn3 Util.insertChildIx ix' n' node
180+
pure res
181+
onThis = Fn.mkFn2 \k (Step n _ halt) → halt
192182
onThat = Fn.mkFn3 \k ix (Tuple _ vdom) → do
193183
res@Step n' m' h' ← buildVDom (VDomSpec spec) vdom
194-
Fn.runFn3 insertChildIx ix n' node
184+
Fn.runFn3 Util.insertChildIx ix n' node
195185
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)
186+
steps ← Fn.runFn6 Util.diffWithKeyAndIxE ch1 ch2 fst onThese onThis onThat
199187
attrs' ← Machine.step attrs as2
200188
pure
201189
(Step node
202190
(Fn.runFn5 patch node attrs' es2 steps len2)
203-
(Fn.runFn2 done attrs' steps))
204-
vdom →
191+
(Fn.runFn3 done node attrs' steps))
192+
vdom → do
193+
Fn.runFn3 done node attrs ch1
205194
buildVDom (VDomSpec spec) vdom
206195

207-
done = Fn.mkFn2 \attrs steps → do
208-
Fn.runFn2 forInE steps (Fn.mkFn2 \_ (Step _ _ halt) → halt)
196+
done = Fn.mkFn3 \node attrs steps → do
197+
Fn.runFn2 Util.removeChild node (Util.unsafeParent node)
198+
Fn.runFn2 Util.forInE steps (Fn.mkFn2 \_ (Step _ _ halt) → halt)
209199
Machine.halt attrs
210200

211201
buildWidget
@@ -216,25 +206,26 @@ buildWidget
216206
buildWidget (VDomSpec spec) = render
217207
where
218208
render w = do
219-
Step n m h ← spec.buildWidget (VDomSpec spec) w
220-
pure (Step n (patch m) h)
209+
res@Step n m h ← spec.buildWidget (VDomSpec spec) w
210+
pure (Step n (patch res) h)
221211

222-
patch step = case _ of
212+
patch prev@(Step node step halt) = case _ of
223213
Grafted g →
224-
patch step (runGraft g)
214+
patch prev (runGraft g)
225215
Widget w → do
226-
Step n m h ← step w
227-
pure (Step n (patch m) h)
228-
vdom →
216+
res@Step n m h ← step w
217+
pure (Step n (patch res) h)
218+
vdom → do
219+
halt
229220
buildVDom (VDomSpec spec) vdom
230221

231222
createElem
232223
eff
233224
. Fn.Fn3 (Maybe Namespace) ElemName DOM.Document (Eff (dom DOM | eff) DOM.Element)
234-
createElem = Fn.mkFn3 \ns name doc →
225+
createElem = Fn.mkFn3 \ns (ElemName name) doc →
235226
case ns of
236-
NothingFn.runFn2 createElement name doc
237-
Just n Fn.runFn3 createElementNS n name doc
227+
NothingFn.runFn2 Util.createElement name doc
228+
Just (Namespace n) Fn.runFn3 Util.createElementNS n name doc
238229

239230
eqElemSpec
240231
a
@@ -247,38 +238,3 @@ eqElemSpec = Fn.mkFn2 \a b →
247238
Nothing, Nothingtrue
248239
_, _ → false
249240
_, _ → false
250-
251-
effPure eff a. a Eff eff a
252-
effPure = pure
253-
254-
foreign import createTextNode
255-
eff
256-
. Fn.Fn2 String DOM.Document (Eff (dom DOM | eff) DOM.Node)
257-
258-
foreign import setTextContent
259-
eff
260-
. Fn.Fn2 String DOM.Node (Eff (dom DOM | eff) Unit)
261-
262-
foreign import createElement
263-
eff
264-
. Fn.Fn2 ElemName DOM.Document (Eff (dom DOM | eff) DOM.Element)
265-
266-
foreign import createElementNS
267-
eff
268-
. Fn.Fn3 Namespace ElemName DOM.Document (Eff (dom DOM | eff) DOM.Element)
269-
270-
foreign import removeLastChild
271-
eff
272-
. DOM.Node (Eff (dom DOM | eff) Unit)
273-
274-
foreign import insertChildIx
275-
eff
276-
. Fn.Fn3 Int DOM.Node DOM.Node (Eff (dom DOM | eff) Unit)
277-
278-
foreign import unsafeChildIx
279-
eff
280-
. 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/DOM/Prop.js

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,27 +31,3 @@ exports.removeEventListener = function (ev, listener, el) {
3131
el.removeEventListener(ev, listener, false);
3232
};
3333
};
34-
35-
exports.setProperty = function (prop, val, el) {
36-
return function () {
37-
el[prop] = val;
38-
};
39-
};
40-
41-
exports.getProperty = function (prop, el) {
42-
return function () {
43-
return el[prop];
44-
};
45-
};
46-
47-
exports.removeProperty = function (prop, el) {
48-
return function () {
49-
delete el[prop];
50-
};
51-
};
52-
53-
exports.unsafeLookup = function (key, obj) {
54-
return obj[key];
55-
};
56-
57-
exports.pokeMutMap = exports.setProperty;

0 commit comments

Comments
 (0)