diff --git a/docs/change-log.md b/docs/change-log.md index cb2fabf0..9df82039 100644 --- a/docs/change-log.md +++ b/docs/change-log.md @@ -24,6 +24,7 @@ #### Bug fixes - API: `m.route.set()` causes all mount points to be redrawn ([#1592](https://github.com/MithrilJS/mithril.js/pull/1592)) +- core: don't call `onremove` on the children of components that return null from the view [#1921](https://github.com/MithrilJS/mithril.js/issues/1921) [octavore](https://github.com/octavore) ([#1922](https://github.com/MithrilJS/mithril.js/pull/1922)) --- diff --git a/render/render.js b/render/render.js index e24a76eb..6bebd212 100644 --- a/render/render.js +++ b/render/render.js @@ -451,9 +451,10 @@ module.exports = function($window) { } function onremove(vnode) { if (vnode.attrs && typeof vnode.attrs.onremove === "function") vnode.attrs.onremove.call(vnode.state, vnode) - if (typeof vnode.tag !== "string" && typeof vnode._state.onremove === "function") vnode._state.onremove.call(vnode.state, vnode) - if (vnode.instance != null) onremove(vnode.instance) - else { + if (typeof vnode.tag !== "string") { + if (typeof vnode._state.onremove === "function") vnode._state.onremove.call(vnode.state, vnode) + if (vnode.instance != null) onremove(vnode.instance) + } else { var children = vnode.children if (Array.isArray(children)) { for (var i = 0; i < children.length; i++) { diff --git a/render/tests/test-onremove.js b/render/tests/test-onremove.js index a7f88a6b..f509e704 100644 --- a/render/tests/test-onremove.js +++ b/render/tests/test-onremove.js @@ -89,6 +89,7 @@ o.spec("onremove", function() { o(vnode.dom.onremove).equals(undefined) o(vnode.dom.attributes["onremove"]).equals(undefined) + o(vnode.events).equals(undefined) }) o("calls onremove on recycle", function() { var remove = o.spy() @@ -150,6 +151,46 @@ o.spec("onremove", function() { o(spy.callCount).equals(1) }) + o("doesn't call onremove on children when the corresponding view returns null (after removing the parent)", function() { + var threw = false + var spy = o.spy() + var parent = createComponent({ + view: function() {} + }) + var child = createComponent({ + view: function() {}, + onremove: spy + }) + render(root, {tag: parent, children: [child]}) + try { + render(root, null) + } catch (e) { + threw = e + } + + o(spy.callCount).equals(0) + o(threw).equals(false) + }) + o("doesn't call onremove on children when the corresponding view returns null (after removing the children)", function() { + var threw = false + var spy = o.spy() + var parent = createComponent({ + view: function() {} + }) + var child = createComponent({ + view: function() {}, + onremove: spy + }) + render(root, {tag: parent, children: [child]}) + try { + render(root, {tag: parent}) + } catch (e) { + threw = true + } + + o(spy.callCount).equals(0) + o(threw).equals(false) + }) }) }) }) \ No newline at end of file