diff --git a/mithril.js b/mithril.js index fe9db874..c3cf4c53 100644 --- a/mithril.js +++ b/mithril.js @@ -1,7 +1,7 @@ ;(function() { "use strict" function Vnode(tag, key, attrs0, children, text, dom) { - return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: undefined, events: undefined, instance: undefined, skip: false} + return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: undefined, _state: undefined, events: undefined, instance: undefined, skip: false} } Vnode.normalize = function(node) { if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined) @@ -465,28 +465,28 @@ var coreRenderer = function($window) { } function initComponent(vnode, hooks) { var sentinel - if (typeof vnode.tag === "function") { - vnode.state = null - sentinel = vnode.tag - if (sentinel.$$reentrantLock$$ != null) return $emptyFragment - sentinel.$$reentrantLock$$ = true - vnode.state = (vnode.tag.prototype != null && typeof vnode.tag.prototype.view === "function") ? new vnode.tag(vnode) : vnode.tag(vnode) - } else { - // For object literals since `Vnode()` always sets the `state` field. + if (typeof vnode.tag.view === "function") { vnode.state = Object.create(vnode.tag) sentinel = vnode.state.view if (sentinel.$$reentrantLock$$ != null) return $emptyFragment sentinel.$$reentrantLock$$ = true + } else { + vnode.state = void 0 + sentinel = vnode.tag + if (sentinel.$$reentrantLock$$ != null) return $emptyFragment + sentinel.$$reentrantLock$$ = true + vnode.state = (vnode.tag.prototype != null && typeof vnode.tag.prototype.view === "function") ? new vnode.tag(vnode) : vnode.tag(vnode) } + vnode._state = vnode.state if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) - initLifecycle(vnode.state, vnode, hooks) - vnode.instance = Vnode.normalize(vnode.state.view(vnode)) + initLifecycle(vnode._state, vnode, hooks) + vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, 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 @@ -594,6 +594,7 @@ var coreRenderer = function($window) { var oldTag = old.tag, tag = vnode.tag if (oldTag === tag) { vnode.state = old.state + vnode._state = old._state vnode.events = old.events if (!recycling && shouldNotUpdate(vnode, old)) return if (typeof oldTag === "string") { @@ -676,9 +677,10 @@ var coreRenderer = function($window) { if (recycling) { initComponent(vnode, hooks) } else { - vnode.instance = Vnode.normalize(vnode.state.view(vnode)) + vnode.instance = Vnode.normalize(vnode._state.view.call(vnode.state, 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) + updateLifecycle(vnode._state, vnode, hooks) } if (vnode.instance != null) { if (old.instance == null) createNode(parent, vnode.instance, hooks, ns, nextSibling) @@ -761,15 +763,15 @@ var coreRenderer = function($window) { } function removeNode(vnode, context) { var expected = 1, called = 0 - if (vnode.attrs && vnode.attrs.onbeforeremove) { + if (vnode.attrs && typeof vnode.attrs.onbeforeremove === "function") { var result = vnode.attrs.onbeforeremove.call(vnode.state, vnode) if (result != null && typeof result.then === "function") { expected++ result.then(continuation, continuation) } } - if (typeof vnode.tag !== "string" && vnode.state.onbeforeremove) { - var result = vnode.state.onbeforeremove(vnode) + if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeremove === "function") { + var result = vnode._state.onbeforeremove.call(vnode.state, vnode) if (result != null && typeof result.then === "function") { expected++ result.then(continuation, continuation) @@ -801,8 +803,8 @@ var coreRenderer = function($window) { if (parent != null) parent.removeChild(node) } function onremove(vnode) { - if (vnode.attrs && vnode.attrs.onremove) vnode.attrs.onremove.call(vnode.state, vnode) - if (typeof vnode.tag !== "string" && vnode.state.onremove) vnode.state.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 { var children = vnode.children @@ -937,7 +939,7 @@ var coreRenderer = function($window) { function shouldNotUpdate(vnode, old) { var forceVnodeUpdate, forceComponentUpdate if (vnode.attrs != null && typeof vnode.attrs.onbeforeupdate === "function") forceVnodeUpdate = vnode.attrs.onbeforeupdate.call(vnode.state, vnode, old) - if (typeof vnode.tag !== "string" && typeof vnode.state.onbeforeupdate === "function") forceComponentUpdate = vnode.state.onbeforeupdate(vnode, old) + if (typeof vnode.tag !== "string" && typeof vnode._state.onbeforeupdate === "function") forceComponentUpdate = vnode._state.onbeforeupdate.call(vnode.state, vnode, old) if (!(forceVnodeUpdate === undefined && forceComponentUpdate === undefined) && !forceVnodeUpdate && !forceComponentUpdate) { vnode.dom = old.dom vnode.domSize = old.domSize diff --git a/mithril.min.js b/mithril.min.js index 168bea22..a7ddf4e9 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1,43 +1,43 @@ -(function(){function B(a,d,f,g,e,p){return{tag:a,key:d,attrs:f,children:g,text:e,dom:p,domSize:void 0,state:void 0,events:void 0,instance:void 0,skip:!1}}function C(a){var d=arguments[1],f=2,g;if(null==a||"string"!==typeof a&&"function"!==typeof a&&"function"!==typeof a.view)throw Error("The selector must be either a string or a component.");if("string"===typeof a){var e;if(!(e=M[a])){g="div";for(var p=[],k={};e=P.exec(a);){var q=e[1],n=e[2];""===q&&""!==n?g=n:"#"===q?k.id=n:"."===q?p.push(n):"["=== -e[3][0]&&((q=e[6])&&(q=q.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")),"class"===e[4]?p.push(q):k[e[4]]=q||!0)}0