Skip to content

Commit dc802bb

Browse files
authored
Merge pull request #32 from buntec/enhancements-1
Banish nulls
2 parents f3a5567 + a78effe commit dc802bb

File tree

2 files changed

+61
-65
lines changed

2 files changed

+61
-65
lines changed

snabbdom/src/main/scala/snabbdom/VNode.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,17 @@ class VNode private (
6262

6363
object VNode {
6464

65+
def empty() =
66+
new VNode(None, VNodeData.empty, None, None, Some(""), None, None)
67+
6568
def create(
6669
sel: Option[String],
6770
data: VNodeData,
6871
children: Option[Array[VNode]],
6972
text: Option[String],
7073
elm: Option[dom.Node]
71-
) = new VNode(sel, data, children, elm, text, data.key, None)
74+
) =
75+
new VNode(sel, data, children.filter(_.nonEmpty), elm, text, data.key, None)
7276

7377
def text(text: String) =
7478
new VNode(None, VNodeData.empty, None, None, Some(text), None, None)

snabbdom/src/main/scala/snabbdom/init.scala

Lines changed: 56 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,7 @@ object init {
163163
}
164164
case Some(children) =>
165165
children.foreach { child =>
166-
if (child != null) { // TODO: is this necessary
167-
api.appendChild(elm, createElm(child, insertedVNodeQueue))
168-
}
166+
api.appendChild(elm, createElm(child, insertedVNodeQueue))
169167
}
170168
}
171169
vnode.data.hook.map { hooks =>
@@ -175,18 +173,18 @@ object init {
175173

176174
case None =>
177175
vnode.children match {
178-
case None => vnode.elm = Some(api.createTextNode(vnode.text.get))
176+
case None =>
177+
vnode.elm = Some(api.createTextNode(vnode.text.getOrElse("")))
179178
case Some(children) =>
180179
val elm = api.createDocumentFragment
181180
vnode.elm = Some(elm)
182181
cbs.create.foreach(hook => hook(emptyNode, vnode))
183182
children.foreach { child =>
184-
if (child != null) {
185-
api.appendChild(
186-
elm,
187-
createElm(child, insertedVNodeQueue)
188-
)
189-
}
183+
api.appendChild(
184+
elm,
185+
createElm(child, insertedVNodeQueue)
186+
)
187+
190188
}
191189
}
192190

@@ -207,9 +205,7 @@ object init {
207205
var i = startIdx
208206
while (i <= endIdx) {
209207
val ch = vnodes(i)
210-
if (ch != null) { // TODO: is this necessary?
211-
api.insertBefore(parentElm, createElm(ch, insertedVNodeQueue), before)
212-
}
208+
api.insertBefore(parentElm, createElm(ch, insertedVNodeQueue), before)
213209
i += 1
214210
}
215211
}
@@ -220,9 +216,7 @@ object init {
220216
cbs.destroy.foreach(hook => hook(vnode))
221217
vnode.children.foreach {
222218
_.foreach { child =>
223-
if (child != null) { // TODO: is this necessary?
224-
invokeDestroyHook(child)
225-
}
219+
invokeDestroyHook(child)
226220
}
227221
}
228222
}
@@ -238,78 +232,69 @@ object init {
238232
var i = startIdx
239233
while (i <= endIdx) {
240234
val ch = vnodes(i)
241-
if (ch != null) { // TODO: is this necessary?
242-
ch.sel match {
243-
case Some(_) =>
244-
invokeDestroyHook(ch)
245-
val listeners = cbs.remove.length + 1
246-
val rm = createRmCb(ch.elm.get, listeners)
247-
cbs.remove.foreach(hook => hook(ch, rm))
248-
ch.data.hook
249-
.flatMap(_.remove)
250-
.fold(rm()) { hook => hook(ch, rm); () }
251-
case None => // text node
252-
api.removeChild(parentElm, ch.elm.get)
253-
254-
}
235+
ch.sel match {
236+
case Some(_) =>
237+
invokeDestroyHook(ch)
238+
val listeners = cbs.remove.length + 1
239+
val rm = createRmCb(ch.elm.get, listeners)
240+
cbs.remove.foreach(hook => hook(ch, rm))
241+
ch.data.hook
242+
.flatMap(_.remove)
243+
.fold(rm()) { hook => hook(ch, rm); () }
244+
case None => // text node
245+
api.removeChild(parentElm, ch.elm.get)
255246
}
256247
i += 1
257248
}
258249
}
259250

260-
def getOrNull(vnodes: Array[VNode], idx: Int): VNode = {
261-
if (idx >= 0 && idx < vnodes.length) {
262-
vnodes(idx)
263-
} else {
264-
null
265-
}
266-
}
267-
268251
def updateChildren(
269252
parentElm: dom.Node,
270253
oldCh: Array[VNode],
271254
newCh: Array[VNode],
272255
insertedVnodeQueue: VNodeQueue
273256
): Unit = {
274257

258+
assert(oldCh.nonEmpty)
259+
assert(newCh.nonEmpty)
260+
275261
var oldStartIdx = 0
276262
var newStartIdx = 0
277263
var oldEndIdx = oldCh.length - 1
278-
var oldStartVnode = getOrNull(oldCh, 0)
279-
var oldEndVnode = getOrNull(oldCh, oldEndIdx)
264+
var oldStartVnode = oldCh(0)
265+
var oldEndVnode = oldCh(oldEndIdx)
280266
var newEndIdx = newCh.length - 1
281-
var newStartVnode = getOrNull(newCh, 0)
282-
var newEndVnode = getOrNull(newCh, newEndIdx)
267+
var newStartVnode = newCh(0)
268+
var newEndVnode = newCh(newEndIdx)
283269

284270
var oldKeyToIdx: Map[String, Int] = null
285-
var elmToMove: VNode = null
286271

287272
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
288273
if (oldStartVnode == null) {
289274
oldStartIdx += 1
290-
oldStartVnode =
291-
getOrNull(oldCh, oldStartIdx) // Vnode might have been moved left
275+
// Vnode might have been moved left
276+
if (oldStartIdx <= oldEndIdx)
277+
oldStartVnode = oldCh(oldStartIdx)
292278
} else if (oldEndVnode == null) {
293279
oldEndIdx -= 1
294-
oldEndVnode = getOrNull(oldCh, oldEndIdx)
295-
} else if (newStartVnode == null) {
296-
newStartIdx += 1
297-
newStartVnode = getOrNull(newCh, newStartIdx)
298-
} else if (newEndVnode == null) {
299-
newEndIdx -= 1
300-
newEndVnode = getOrNull(newCh, newEndIdx)
280+
if (oldStartIdx <= oldEndIdx)
281+
oldEndVnode = oldCh(oldEndIdx)
301282
} else if (sameVnode(oldStartVnode, newStartVnode)) {
302283
patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)
303284
oldStartIdx += 1
304-
oldStartVnode = getOrNull(oldCh, oldStartIdx)
285+
if (oldStartIdx <= oldEndIdx)
286+
oldStartVnode = oldCh(oldStartIdx)
305287
newStartIdx += 1
306-
newStartVnode = getOrNull(newCh, newStartIdx)
288+
if (newStartIdx <= newEndIdx)
289+
newStartVnode = newCh(newStartIdx)
307290
} else if (sameVnode(oldEndVnode, newEndVnode)) {
308291
patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)
309292
oldEndIdx -= 1
310-
oldEndVnode = getOrNull(oldCh, oldEndIdx)
293+
if (oldStartIdx <= oldEndIdx)
294+
oldEndVnode = oldCh(oldEndIdx)
311295
newEndIdx -= 1
312-
newEndVnode = getOrNull(newCh, newEndIdx)
296+
if (newStartIdx <= newEndIdx)
297+
newEndVnode = newCh(newEndIdx)
313298
} else if (sameVnode(oldStartVnode, newEndVnode)) {
314299
// Vnode moved right
315300
patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)
@@ -319,9 +304,11 @@ object init {
319304
api.nextSibling(oldEndVnode.elm.get)
320305
)
321306
oldStartIdx += 1
322-
oldStartVnode = getOrNull(oldCh, oldStartIdx)
307+
if (oldStartIdx <= oldEndIdx)
308+
oldStartVnode = oldCh(oldStartIdx)
323309
newEndIdx -= 1
324-
newEndVnode = newCh(newEndIdx)
310+
if (newStartIdx <= newEndIdx)
311+
newEndVnode = newCh(newEndIdx)
325312
} else if (sameVnode(oldEndVnode, newStartVnode)) {
326313
// Vnode moved left
327314
patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)
@@ -331,9 +318,11 @@ object init {
331318
oldStartVnode.elm
332319
)
333320
oldEndIdx -= 1
334-
oldEndVnode = getOrNull(oldCh, oldEndIdx)
321+
if (oldStartIdx <= oldEndIdx)
322+
oldEndVnode = oldCh(oldEndIdx)
335323
newStartIdx += 1
336-
newStartVnode = getOrNull(newCh, newStartIdx)
324+
if (newStartIdx <= newEndIdx)
325+
newStartVnode = newCh(newStartIdx)
337326
} else {
338327
if (oldKeyToIdx == null) {
339328
oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
@@ -350,7 +339,7 @@ object init {
350339
oldStartVnode.elm
351340
)
352341
case Some(idxInOld) =>
353-
elmToMove = oldCh(idxInOld)
342+
val elmToMove = oldCh(idxInOld)
354343
if (elmToMove.sel != newStartVnode.sel) {
355344
api.insertBefore(
356345
parentElm,
@@ -359,7 +348,7 @@ object init {
359348
)
360349
} else {
361350
patchVnode(elmToMove, newStartVnode, insertedVnodeQueue)
362-
oldCh(idxInOld) = null // undefined as any
351+
oldCh(idxInOld) = null
363352
api.insertBefore(
364353
parentElm,
365354
elmToMove.elm.get,
@@ -368,12 +357,15 @@ object init {
368357
}
369358
}
370359
newStartIdx += 1
371-
newStartVnode = getOrNull(newCh, newStartIdx)
360+
if (newStartIdx <= newEndIdx)
361+
newStartVnode = newCh(newStartIdx)
372362
}
373363
}
374364

375365
if (newStartIdx <= newEndIdx) {
376-
val before = Option(getOrNull(newCh, newEndIdx + 1)).flatMap(_.elm)
366+
val before =
367+
if (newCh.length > newEndIdx + 1) newCh(newEndIdx + 1).elm
368+
else None
377369
addVnodes(
378370
parentElm,
379371
before,

0 commit comments

Comments
 (0)