-
Notifications
You must be signed in to change notification settings - Fork 4
/
each.js
92 lines (85 loc) · 3.13 KB
/
each.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/**
* Use this to create keyed fragments more safely. Keys are always converted to
* properties, so `null`/`undefined` *are* valid keys and are equivalent to
* `"null"` and `"undefined"` respectively. Note that keys still must be unique
* when coerced to property keys.
*
* This is just a preview of something I'm looking to add in my redesign.
*/
;(function () {
"use strict"
var Vnode
var symbolIterator = typeof Symbol === "function"
? Symbol.iterator
: null
var from = Array.from || function (list, func) {
var result = []
if (
symbolIterator != null &&
typeof list[symbolIterator] === "function"
) {
var iter = list[symbolIterator]()
var i = 0
for (var next = iter.next(); !next.done; next = iter.next()) {
result.push(func(next.value, i))
i++
}
} else {
for (var i = 0; i < list.length; i++) {
result.push(func(list[i], i))
}
}
return result
}
// This is coded specifically for efficiency, so it's necessarily a bit
// messy. The `Array.from` calls are also written to be easily inlined by
// JIT engines.
//
// Here's it simplified, with roughly equivalent semantics:
//
// ```js
// function each(list, by, view) {
// // So it doesn't get coerced in the loop
// if (typeof by !== "function" && typeof by !== "symbol") by = "" + by
// var found = Object.create(null)
// return m.fragment(from(list, function (item, i) {
// var key = typeof by === "function" ? by(item, i) : item[by]
// if (typeof key !== "symbol") key = "" + key
// if (found[key]) throw new Error("Duplicate keys are not allowed.")
// found[key] = true
// return m.fragment({key: key}, view(item, i))
// }))
// }
// ```
function cast(view, found, item, i, key) {
if (typeof key !== "symbol") key = "" + key
if (found[key]) throw new Error("Duplicate keys are not allowed.")
found[key] = true
return Vnode("[", key, null, [Vnode.normalize(view(item, i))], null, null)
}
function each(list, by, view) {
var found = Object.create(null)
var children
if (typeof by === "function") {
children = from(list, function (item, i) {
return cast(view, found, item, i, by(item, i))
})
} else {
// So it doesn't get coerced in the loop
if (typeof by !== "symbol") by = "" + by
children = from(list, function (item, i) {
return cast(view, found, item, i, item[by])
})
}
return Vnode("[", null, null, children, null, null)
}
if (typeof module === "object" && module && module.exports) {
Vnode = require("mithril/render/vnode")
module.exports = each
} else if (typeof m === "function") {
Vnode = m.vnode
(m.helpers || (m.helpers = {})).each = each
} else {
throw new Error("Mithril must be loaded first!")
}
})()