Fix keys, normalize holes (#2452)
* Fix #2434 * Treat holes as unkeyed, normalize boolean/null/undefined This brings a lot better consistency with that API, even though it's slightly breaking. (I had to update a bunch of tests to correspond with it.) * Fill in PR number [skip ci]
This commit is contained in:
parent
86d64e213f
commit
6c562d2b9b
12 changed files with 200 additions and 182 deletions
|
|
@ -110,7 +110,7 @@ o.spec("component", function() {
|
|||
visible = false
|
||||
render(root, [{tag: component}])
|
||||
|
||||
o(root.firstChild.nodeValue).equals("")
|
||||
o(root.childNodes.length).equals(0)
|
||||
})
|
||||
o("updates root from null to null", function() {
|
||||
var component = createComponent({
|
||||
|
|
@ -218,7 +218,7 @@ o.spec("component", function() {
|
|||
o(root.firstChild.nodeType).equals(3)
|
||||
o(root.firstChild.nodeValue).equals("0")
|
||||
})
|
||||
o("can return boolean", function() {
|
||||
o("can return `true`", function() {
|
||||
var component = createComponent({
|
||||
view: function() {
|
||||
return true
|
||||
|
|
@ -226,10 +226,9 @@ o.spec("component", function() {
|
|||
})
|
||||
render(root, [{tag: component}])
|
||||
|
||||
o(root.firstChild.nodeType).equals(3)
|
||||
o(root.firstChild.nodeValue).equals("true")
|
||||
o(root.childNodes.length).equals(0)
|
||||
})
|
||||
o("can return falsy boolean", function() {
|
||||
o("can return `false`", function() {
|
||||
var component = createComponent({
|
||||
view: function() {
|
||||
return false
|
||||
|
|
@ -237,8 +236,7 @@ o.spec("component", function() {
|
|||
})
|
||||
render(root, [{tag: component}])
|
||||
|
||||
o(root.firstChild.nodeType).equals(3)
|
||||
o(root.firstChild.nodeValue).equals("")
|
||||
o(root.childNodes.length).equals(0)
|
||||
})
|
||||
o("can return null", function() {
|
||||
var component = createComponent({
|
||||
|
|
@ -293,8 +291,7 @@ o.spec("component", function() {
|
|||
})
|
||||
render(root, [{tag: component}])
|
||||
|
||||
o(root.firstChild.nodeType).equals(3)
|
||||
o(root.firstChild.nodeValue).equals("")
|
||||
o(root.childNodes.length).equals(0)
|
||||
|
||||
try {
|
||||
render(root, [{tag: component}])
|
||||
|
|
|
|||
|
|
@ -57,25 +57,23 @@ function runTest(name, fragment) {
|
|||
var vnode = fragment([1])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(1)
|
||||
o(vnode.children[0].children).equals("1")
|
||||
})
|
||||
o("handles falsy number single child", function() {
|
||||
var vnode = fragment([0])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(0)
|
||||
o(vnode.children[0].children).equals("0")
|
||||
})
|
||||
o("handles boolean single child", function() {
|
||||
var vnode = fragment([true])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(true)
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles falsy boolean single child", function() {
|
||||
var vnode = fragment([false])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals("")
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles null single child", function() {
|
||||
var vnode = fragment([null])
|
||||
|
|
@ -85,7 +83,7 @@ function runTest(name, fragment) {
|
|||
o("handles undefined single child", function() {
|
||||
var vnode = fragment([undefined])
|
||||
|
||||
o(vnode.children[0]).equals(undefined)
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles multiple string children", function() {
|
||||
var vnode = fragment(["", "a"])
|
||||
|
|
@ -99,29 +97,25 @@ function runTest(name, fragment) {
|
|||
var vnode = fragment([0, 1])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(0)
|
||||
o(vnode.children[0].children).equals("0")
|
||||
o(vnode.children[1].tag).equals("#")
|
||||
o(vnode.children[1].children).equals(1)
|
||||
o(vnode.children[1].children).equals("1")
|
||||
})
|
||||
o("handles multiple boolean children", function() {
|
||||
var vnode = fragment([false, true])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals("")
|
||||
o(vnode.children[1].tag).equals("#")
|
||||
o(vnode.children[1].children).equals(true)
|
||||
o(vnode.children).deepEquals([null, null])
|
||||
})
|
||||
o("handles multiple null/undefined child", function() {
|
||||
var vnode = fragment([null, undefined])
|
||||
|
||||
o(vnode.children[0]).equals(null)
|
||||
o(vnode.children[1]).equals(undefined)
|
||||
o(vnode.children).deepEquals([null, null])
|
||||
})
|
||||
o("handles falsy number single child without attrs", function() {
|
||||
var vnode = fragment(0)
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(0)
|
||||
o(vnode.children[0].children).equals("0")
|
||||
})
|
||||
})
|
||||
o.spec("children with attrs", function() {
|
||||
|
|
@ -141,35 +135,33 @@ function runTest(name, fragment) {
|
|||
var vnode = fragment({}, [1])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(1)
|
||||
o(vnode.children[0].children).equals("1")
|
||||
})
|
||||
o("handles falsy number single child", function() {
|
||||
var vnode = fragment({}, [0])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(0)
|
||||
o(vnode.children[0].children).equals("0")
|
||||
})
|
||||
o("handles boolean single child", function() {
|
||||
var vnode = fragment({}, [true])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(true)
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles falsy boolean single child", function() {
|
||||
var vnode = fragment({}, [false])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals("")
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles null single child", function() {
|
||||
var vnode = fragment({}, [null])
|
||||
|
||||
o(vnode.children[0]).equals(null)
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles undefined single child", function() {
|
||||
var vnode = fragment({}, [undefined])
|
||||
|
||||
o(vnode.children[0]).equals(undefined)
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles multiple string children", function() {
|
||||
var vnode = fragment({}, ["", "a"])
|
||||
|
|
@ -183,23 +175,19 @@ function runTest(name, fragment) {
|
|||
var vnode = fragment({}, [0, 1])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(0)
|
||||
o(vnode.children[0].children).equals("0")
|
||||
o(vnode.children[1].tag).equals("#")
|
||||
o(vnode.children[1].children).equals(1)
|
||||
o(vnode.children[1].children).equals("1")
|
||||
})
|
||||
o("handles multiple boolean children", function() {
|
||||
var vnode = fragment({}, [false, true])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals("")
|
||||
o(vnode.children[1].tag).equals("#")
|
||||
o(vnode.children[1].children).equals(true)
|
||||
o(vnode.children).deepEquals([null, null])
|
||||
})
|
||||
o("handles multiple null/undefined child", function() {
|
||||
var vnode = fragment({}, [null, undefined])
|
||||
|
||||
o(vnode.children[0]).equals(null)
|
||||
o(vnode.children[1]).equals(undefined)
|
||||
o(vnode.children).deepEquals([null, null])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -382,32 +382,32 @@ o.spec("hyperscript", function() {
|
|||
o("handles number single child", function() {
|
||||
var vnode = m("div", {}, [1])
|
||||
|
||||
o(vnode.text).equals(1)
|
||||
o(vnode.text).equals("1")
|
||||
})
|
||||
o("handles falsy number single child", function() {
|
||||
var vnode = m("div", {}, [0])
|
||||
|
||||
o(vnode.text).equals(0)
|
||||
o(vnode.text).equals("0")
|
||||
})
|
||||
o("handles boolean single child", function() {
|
||||
var vnode = m("div", {}, [true])
|
||||
|
||||
o(vnode.text).equals(true)
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles falsy boolean single child", function() {
|
||||
var vnode = m("div", {}, [false])
|
||||
|
||||
o(vnode.text).equals("")
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles null single child", function() {
|
||||
var vnode = m("div", {}, [null])
|
||||
|
||||
o(vnode.children[0]).equals(null)
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles undefined single child", function() {
|
||||
var vnode = m("div", {}, [undefined])
|
||||
|
||||
o(vnode.children[0]).equals(undefined)
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles multiple string children", function() {
|
||||
var vnode = m("div", {}, ["", "a"])
|
||||
|
|
@ -421,28 +421,24 @@ o.spec("hyperscript", function() {
|
|||
var vnode = m("div", {}, [0, 1])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals(0)
|
||||
o(vnode.children[0].children).equals("0")
|
||||
o(vnode.children[1].tag).equals("#")
|
||||
o(vnode.children[1].children).equals(1)
|
||||
o(vnode.children[1].children).equals("1")
|
||||
})
|
||||
o("handles multiple boolean children", function() {
|
||||
var vnode = m("div", {}, [false, true])
|
||||
|
||||
o(vnode.children[0].tag).equals("#")
|
||||
o(vnode.children[0].children).equals("")
|
||||
o(vnode.children[1].tag).equals("#")
|
||||
o(vnode.children[1].children).equals(true)
|
||||
o(vnode.children).deepEquals([null, null])
|
||||
})
|
||||
o("handles multiple null/undefined child", function() {
|
||||
var vnode = m("div", {}, [null, undefined])
|
||||
|
||||
o(vnode.children[0]).equals(null)
|
||||
o(vnode.children[1]).equals(undefined)
|
||||
o(vnode.children).deepEquals([null, null])
|
||||
})
|
||||
o("handles falsy number single child without attrs", function() {
|
||||
var vnode = m("div", 0)
|
||||
|
||||
o(vnode.text).equals(0)
|
||||
o(vnode.text).equals("0")
|
||||
})
|
||||
})
|
||||
o.spec("permutations", function() {
|
||||
|
|
@ -511,31 +507,31 @@ o.spec("hyperscript", function() {
|
|||
var vnode = m("div", {a: "b"}, [1])
|
||||
|
||||
o(vnode.attrs.a).equals("b")
|
||||
o(vnode.text).equals(1)
|
||||
o(vnode.text).equals("1")
|
||||
})
|
||||
o("handles attr and single falsy number text child", function() {
|
||||
var vnode = m("div", {a: "b"}, [0])
|
||||
|
||||
o(vnode.attrs.a).equals("b")
|
||||
o(vnode.text).equals(0)
|
||||
o(vnode.text).equals("0")
|
||||
})
|
||||
o("handles attr and single boolean text child", function() {
|
||||
var vnode = m("div", {a: "b"}, [true])
|
||||
|
||||
o(vnode.attrs.a).equals("b")
|
||||
o(vnode.text).equals(true)
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles attr and single falsy boolean text child", function() {
|
||||
var vnode = m("div", {a: "b"}, [0])
|
||||
|
||||
o(vnode.attrs.a).equals("b")
|
||||
o(vnode.text).equals(0)
|
||||
o(vnode.text).equals("0")
|
||||
})
|
||||
o("handles attr and single false boolean text child", function() {
|
||||
var vnode = m("div", {a: "b"}, [false])
|
||||
|
||||
o(vnode.attrs.a).equals("b")
|
||||
o(vnode.text).equals("")
|
||||
o(vnode.children).deepEquals([null])
|
||||
})
|
||||
o("handles attr and single text child unwrapped", function() {
|
||||
var vnode = m("div", {a: "b"}, "c")
|
||||
|
|
|
|||
|
|
@ -34,24 +34,22 @@ o.spec("normalize", function() {
|
|||
var node = Vnode.normalize(1)
|
||||
|
||||
o(node.tag).equals("#")
|
||||
o(node.children).equals(1)
|
||||
o(node.children).equals("1")
|
||||
})
|
||||
o("normalizes falsy number into text node", function() {
|
||||
var node = Vnode.normalize(0)
|
||||
|
||||
o(node.tag).equals("#")
|
||||
o(node.children).equals(0)
|
||||
o(node.children).equals("0")
|
||||
})
|
||||
o("normalizes boolean into text node", function() {
|
||||
o("normalizes `true` to `null`", function() {
|
||||
var node = Vnode.normalize(true)
|
||||
|
||||
o(node.tag).equals("#")
|
||||
o(node.children).equals(true)
|
||||
o(node).equals(null)
|
||||
})
|
||||
o("normalizes falsy boolean into empty text node", function() {
|
||||
o("normalizes `false` to `null`", function() {
|
||||
var node = Vnode.normalize(false)
|
||||
|
||||
o(node.tag).equals("#")
|
||||
o(node.children).equals("")
|
||||
o(node).equals(null)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -16,10 +16,9 @@ o.spec("normalizeChildren", function() {
|
|||
o(children[0].tag).equals("#")
|
||||
o(children[0].children).equals("a")
|
||||
})
|
||||
o("normalizes `false` values into empty string text nodes", function() {
|
||||
o("normalizes `false` values into `null`s", function() {
|
||||
var children = Vnode.normalizeChildren([false])
|
||||
|
||||
o(children[0].tag).equals("#")
|
||||
o(children[0].children).equals("")
|
||||
o(children[0]).equals(null)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -451,9 +451,9 @@ o.spec("updateNodes", function() {
|
|||
o(updated[1].dom.nodeName).equals("I")
|
||||
o(updated[1].dom).equals(root.childNodes[2])
|
||||
})
|
||||
o("populates array followed by null then el", function() {
|
||||
var vnodes = [{tag: "[", key: 1, children: []}, null, {tag: "i", key: 2}]
|
||||
var updated = [{tag: "[", key: 1, children: [{tag: "a"}, {tag: "b"}]}, null, {tag: "i", key: 2}]
|
||||
o("populates array followed by el keyed", function() {
|
||||
var vnodes = [{tag: "[", key: 1, children: []}, {tag: "i", key: 2}]
|
||||
var updated = [{tag: "[", key: 1, children: [{tag: "a"}, {tag: "b"}]}, {tag: "i", key: 2}]
|
||||
|
||||
render(root, vnodes)
|
||||
render(root, updated)
|
||||
|
|
@ -464,10 +464,38 @@ o.spec("updateNodes", function() {
|
|||
o(updated[0].domSize).equals(2)
|
||||
o(updated[0].dom.nextSibling.nodeName).equals("B")
|
||||
o(updated[0].dom.nextSibling).equals(root.childNodes[1])
|
||||
o(updated[2].dom.nodeName).equals("I")
|
||||
o(updated[2].dom).equals(root.childNodes[2])
|
||||
o(updated[1].dom.nodeName).equals("I")
|
||||
o(updated[1].dom).equals(root.childNodes[2])
|
||||
})
|
||||
o("populates childless array followed by el", function() {
|
||||
o("throws populates array followed by el keyed", function() {
|
||||
var vnodes = [{tag: "[", key: 1, children: []}, {tag: "i", key: 2}]
|
||||
var updated = [{tag: "[", key: 1, children: [{tag: "a"}, {tag: "b"}]}, {tag: "i", key: 2}]
|
||||
|
||||
render(root, vnodes)
|
||||
render(root, updated)
|
||||
|
||||
o(root.childNodes.length).equals(3)
|
||||
o(updated[0].dom.nodeName).equals("A")
|
||||
o(updated[0].dom).equals(root.childNodes[0])
|
||||
o(updated[0].domSize).equals(2)
|
||||
o(updated[0].dom.nextSibling.nodeName).equals("B")
|
||||
o(updated[0].dom.nextSibling).equals(root.childNodes[1])
|
||||
o(updated[1].dom.nodeName).equals("I")
|
||||
o(updated[1].dom).equals(root.childNodes[2])
|
||||
})
|
||||
o("throws if array followed by null then el on first render keyed", function() {
|
||||
var vnodes = [{tag: "[", key: 1, children: []}, null, {tag: "i", key: 2}]
|
||||
|
||||
o(function () { render(root, vnodes) }).throws(TypeError)
|
||||
})
|
||||
o("throws if array followed by null then el on next render keyed", function() {
|
||||
var vnodes = [{tag: "[", key: 1, children: []}, {tag: "i", key: 2}]
|
||||
var updated = [{tag: "[", key: 1, children: [{tag: "a"}, {tag: "b"}]}, null, {tag: "i", key: 2}]
|
||||
|
||||
render(root, vnodes)
|
||||
o(function () { render(root, updated) }).throws(TypeError)
|
||||
})
|
||||
o("populates childless array replaced followed by el keyed", function() {
|
||||
var vnodes = [{tag: "[", key: 1}, {tag: "i", key: 2}]
|
||||
var updated = [{tag: "[", key: 1, children: [{tag: "a"}, {tag: "b"}]}, {tag: "i", key: 2}]
|
||||
|
||||
|
|
@ -483,21 +511,12 @@ o.spec("updateNodes", function() {
|
|||
o(updated[1].dom.nodeName).equals("I")
|
||||
o(updated[1].dom).equals(root.childNodes[2])
|
||||
})
|
||||
o("populates childless array followed by null then el", function() {
|
||||
var vnodes = [{tag: "[", key: 1}, null, {tag: "i", key: 2}]
|
||||
o("throws if childless array replaced followed by null then el keyed", function() {
|
||||
var vnodes = [{tag: "[", key: 1}, {tag: "i", key: 2}]
|
||||
var updated = [{tag: "[", key: 1, children: [{tag: "a"}, {tag: "b"}]}, null, {tag: "i", key: 2}]
|
||||
|
||||
render(root, vnodes)
|
||||
render(root, updated)
|
||||
|
||||
o(root.childNodes.length).equals(3)
|
||||
o(updated[0].dom.nodeName).equals("A")
|
||||
o(updated[0].dom).equals(root.childNodes[0])
|
||||
o(updated[0].domSize).equals(2)
|
||||
o(updated[0].dom.nextSibling.nodeName).equals("B")
|
||||
o(updated[0].dom.nextSibling).equals(root.childNodes[1])
|
||||
o(updated[2].dom.nodeName).equals("I")
|
||||
o(updated[2].dom).equals(root.childNodes[2])
|
||||
o(function () { render(root, updated) }).throws(TypeError)
|
||||
})
|
||||
o("moves from end to start", function() {
|
||||
var vnodes = [{tag: "a", key: 1}, {tag: "b", key: 2}, {tag: "i", key: 3}, {tag: "s", key: 4}]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue