From dbee97bf04aa3876b2eb16c2734b7825e4bc862c Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Tue, 21 Apr 2015 09:23:55 -0400 Subject: [PATCH] ensure component lifecycle works for components with implicit controllers --- mithril.js | 14 +++--- tests/mithril-tests.js | 105 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/mithril.js b/mithril.js index 345aef0d..f152aac4 100644 --- a/mithril.js +++ b/mithril.js @@ -239,10 +239,10 @@ var m = (function app(window, undefined) { } } else if (data != null && dataType === OBJECT) { - var controllerConstructors = [], controllers = [] + var views = [], controllers = [] while (data.view) { - var controllerConstructor = (data.controller || {}).$original || data.controller || noop - var controllerIndex = m.redraw.strategy() == "diff" && cached.controllerConstructors ? cached.controllerConstructors.indexOf(controllerConstructor) : -1 + var view = data.view.$original || data.view + var controllerIndex = m.redraw.strategy() == "diff" && cached.views ? cached.views.indexOf(view) : -1 var controller = controllerIndex > -1 ? cached.controllers[controllerIndex] : new (data.controller || noop) var key = data && data.attrs && data.attrs.key data = pendingRequests == 0 || (cached && cached.controllers && cached.controllers.indexOf(controller) > -1) ? data.view(controller) : {tag: "placeholder"} @@ -251,7 +251,7 @@ var m = (function app(window, undefined) { data.attrs.key = key } if (controller.onunload) unloaders.push({controller: controller, handler: controller.onunload}) - controllerConstructors.push(controllerConstructor) + views.push(view) controllers.push(controller) } if (!data.tag && controllers.length) throw new Error("Component template must return a virtual element, not an array, string, etc.") @@ -290,7 +290,7 @@ var m = (function app(window, undefined) { nodes: [node] }; if (controllers.length) { - cached.controllerConstructors = controllerConstructors + cached.views = views cached.controllers = controllers for (var i = 0, controller; controller = controllers[i]; i++) { if (controller.onunload && controller.onunload.$old) controller.onunload = controller.onunload.$old @@ -313,7 +313,7 @@ var m = (function app(window, undefined) { cached.children = build(node, data.tag, undefined, undefined, data.children, cached.children, false, 0, data.attrs.contenteditable ? node : editable, namespace, configs); cached.nodes.intact = true; if (controllers.length) { - cached.controllerConstructors = controllerConstructors + cached.views = views cached.controllers = controllers } if (shouldReattach === true && node != null) parentElement.insertBefore(node, parentElement.childNodes[index] || null) @@ -556,7 +556,7 @@ var m = (function app(window, undefined) { if (arguments.length > 1) args = args.concat([].slice.call(arguments, 1)) return component.view.apply(component, args ? [ctrl].concat(args) : [ctrl]) } - controller.$original = component.controller + view.$original = component.view var output = {controller: controller, view: view} if (args[0] && args[0].key != null) output.attrs = {key: args[0].key} return output diff --git a/tests/mithril-tests.js b/tests/mithril-tests.js index 2b571de1..7c66f029 100644 --- a/tests/mithril-tests.js +++ b/tests/mithril-tests.js @@ -1234,6 +1234,111 @@ function testMithril(mock) { return redraws1 == 1 && redraws2 == 1 }) + test(function() { + var root = mock.document.createElement("div") + + var cond = true + var controller1 = null, controller2 = null + var Root = { + view: function() { + return cond ? Comp1 : Comp2 + } + } + + var Comp1 = { + view: function(ctrl) { + controller1 = ctrl + return m("div") + } + } + var Comp2 = { + view: function(ctrl) { + controller2 = ctrl + return m("div") + } + } + + m.mount(root, Root) + + mock.requestAnimationFrame.$resolve() + + cond = false + m.redraw(true) + + mock.requestAnimationFrame.$resolve() + + return controller1 !== controller2 + }) + test(function() { + var root = mock.document.createElement("div") + + var cond = true + var unloaded = false + var Root = { + view: function() { + return cond ? Comp1 : Comp2 + } + } + + var Comp1 = { + view: function(ctrl) { + return m("div", {config: function(el, init, ctx) { + ctx.onunload = function() {unloaded = true} + }}) + } + } + var Comp2 = { + view: function(ctrl) { + return m("div") + } + } + + m.mount(root, Root) + + mock.requestAnimationFrame.$resolve() + + cond = false + m.redraw(true) + + mock.requestAnimationFrame.$resolve() + + return unloaded + }) + test(function() { + var root = mock.document.createElement("div") + + var cond = true + var initialized = null + var Root = { + view: function() { + return cond ? Comp1 : Comp2 + } + } + + var Comp1 = { + view: function(ctrl) { + return m("div") + } + } + var Comp2 = { + view: function(ctrl) { + return m("div", {config: function(el, init) { + initialized = init + }}) + } + } + + m.mount(root, Root) + + mock.requestAnimationFrame.$resolve() + + cond = false + m.redraw(true) + + mock.requestAnimationFrame.$resolve() + + return initialized === false + }) m.redraw.strategy(undefined) //teardown for m.mount tests //m.withAttr