Strengthen the self-return prevention logic (for recycled nodes and updates)
This commit is contained in:
parent
aeb1c41bde
commit
7be2ff5feb
2 changed files with 35 additions and 2 deletions
|
|
@ -119,12 +119,12 @@ module.exports = function($window) {
|
|||
if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
|
||||
initLifecycle(vnode.state, vnode, hooks)
|
||||
vnode.instance = Vnode.normalize(vnode.state.view(vnode))
|
||||
if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument")
|
||||
sentinel.$$reentrantLock$$ = null
|
||||
}
|
||||
function createComponent(parent, vnode, hooks, ns, nextSibling) {
|
||||
initComponent(vnode, hooks)
|
||||
if (vnode.instance != null) {
|
||||
if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as arguments")
|
||||
var element = createNode(parent, vnode.instance, hooks, ns, nextSibling)
|
||||
vnode.dom = vnode.instance.dom
|
||||
vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0
|
||||
|
|
@ -317,6 +317,7 @@ module.exports = function($window) {
|
|||
initComponent(vnode, hooks)
|
||||
} else {
|
||||
vnode.instance = Vnode.normalize(vnode.state.view(vnode))
|
||||
if (vnode.instance === vnode) throw Error("A view cannot return the vnode it received as argument")
|
||||
if (vnode.attrs != null) updateLifecycle(vnode.attrs, vnode, hooks)
|
||||
updateLifecycle(vnode.state, vnode, hooks)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,8 +260,9 @@ o.spec("component", function() {
|
|||
|
||||
o(root.childNodes.length).equals(0)
|
||||
})
|
||||
o("throws a custom error if it returns itself", function() {
|
||||
o("throws a custom error if it returns itself when created", function() {
|
||||
// A view that returns its vnode would otherwise trigger an infinite loop
|
||||
var threw = false
|
||||
var component = createComponent({
|
||||
view: function(vnode) {
|
||||
return vnode
|
||||
|
|
@ -271,10 +272,41 @@ o.spec("component", function() {
|
|||
render(root, [{tag: component}])
|
||||
}
|
||||
catch (e) {
|
||||
threw = true
|
||||
o(e instanceof Error).equals(true)
|
||||
// Call stack exception is a RangeError
|
||||
o(e instanceof RangeError).equals(false)
|
||||
}
|
||||
o(threw).equals(true)
|
||||
})
|
||||
o("throws a custom error if it returns itself when updated", function() {
|
||||
// A view that returns its vnode would otherwise trigger an infinite loop
|
||||
var threw = false
|
||||
var init = true
|
||||
var oninit = o.spy()
|
||||
var component = createComponent({
|
||||
oninit: oninit,
|
||||
view: function(vnode) {
|
||||
if (init) return init = false
|
||||
else return vnode
|
||||
}
|
||||
})
|
||||
render(root, [{tag: component}])
|
||||
|
||||
o(root.firstChild.nodeType).equals(3)
|
||||
o(root.firstChild.nodeValue).equals("")
|
||||
|
||||
try {
|
||||
render(root, [{tag: component}])
|
||||
}
|
||||
catch (e) {
|
||||
threw = true
|
||||
o(e instanceof Error).equals(true)
|
||||
// Call stack exception is a RangeError
|
||||
o(e instanceof RangeError).equals(false)
|
||||
}
|
||||
o(threw).equals(true)
|
||||
o(oninit.callCount).equals(1)
|
||||
})
|
||||
o("can update when returning fragments", function() {
|
||||
var component = createComponent({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue