From 15116d5b2ed513c0a2ce2a9eb8ea9a385c2e0230 Mon Sep 17 00:00:00 2001 From: Pat Cavit Date: Thu, 18 Aug 2016 09:51:24 -0700 Subject: [PATCH 1/7] Update package metadata (#1256) --- ospec/package.json | 4 +++- package.json | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ospec/package.json b/ospec/package.json index 3e10bafd..fd0c1878 100644 --- a/ospec/package.json +++ b/ospec/package.json @@ -8,5 +8,7 @@ }, "keywords": [ "testing" ], "author": "Leo Horie ", - "license": "MIT" + "license": "MIT", + "bin": "./bin/ospec", + "repository": "lhorie/mithril.js#rewrite" } diff --git a/package.json b/package.json index 14d8f92a..d4636031 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "author": "Leo Horie", "license": "MIT", "main": "index.js", + "repository": "lhorie/mithril.js", "scripts": { "dev": "node bundler/cli browser.js -o mithril.js -w", "build": "npm run build-browser & npm run build-min", @@ -21,8 +22,5 @@ }, "publishConfig": { "tag": "beta" - }, - "bin": { - "ospec": "./ospec/bin/ospec" } } From 644f0d484b8e505721517cda4d69044a74301e02 Mon Sep 17 00:00:00 2001 From: Pat Cavit Date: Thu, 18 Aug 2016 09:52:36 -0700 Subject: [PATCH 2/7] 4 spaces != 1 tab --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d4636031..0dc53dd5 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "author": "Leo Horie", "license": "MIT", "main": "index.js", - "repository": "lhorie/mithril.js", + "repository": "lhorie/mithril.js", "scripts": { "dev": "node bundler/cli browser.js -o mithril.js -w", "build": "npm run build-browser & npm run build-min", From 305035f03bb3bc4eb180a40e3c5ec4c826fdcfe0 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Gerardy Date: Wed, 17 Aug 2016 17:49:18 +0200 Subject: [PATCH 3/7] Add `m.fragment()` --- hyperscript.js | 6 ++++++ index.js | 3 +-- render/fragment.js | 7 +++++++ render/tests/test-fragment.js | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 hyperscript.js create mode 100644 render/fragment.js create mode 100644 render/tests/test-fragment.js diff --git a/hyperscript.js b/hyperscript.js new file mode 100644 index 00000000..48f06c9e --- /dev/null +++ b/hyperscript.js @@ -0,0 +1,6 @@ +var hyperscript = require("./render/hyperscript") +hyperscript.trust = require("./render/trust") +hyperscript.fragment = require("./render/fragment") + + +module.exports = hyperscript diff --git a/index.js b/index.js index 9e290d80..955f8c3d 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ "use strict" -var m = require("./render/hyperscript") +var m = require("./hyperscript") var renderService = require("./render") var requestService = require("./request") var redrawService = require("./redraw") @@ -9,7 +9,6 @@ requestService.setCompletionCallback(redrawService.publish) m.route = require("./route") m.mount = require("./mount") -m.trust = require("./render/trust") m.withAttr = require("./util/withAttr") m.prop = require("./stream") m.render = renderService.render diff --git a/render/fragment.js b/render/fragment.js new file mode 100644 index 00000000..82918975 --- /dev/null +++ b/render/fragment.js @@ -0,0 +1,7 @@ +"use strict" + +var Vnode = require("../render/vnode") + +module.exports = function(attrs, children) { + return Vnode("[", attrs.key, attrs, Vnode.normalizeChildren(children), undefined, undefined) +} diff --git a/render/tests/test-fragment.js b/render/tests/test-fragment.js new file mode 100644 index 00000000..f0403bbc --- /dev/null +++ b/render/tests/test-fragment.js @@ -0,0 +1,35 @@ +"use strict" + +var o = require("../../ospec/ospec") +var fragment = require("../../render/fragment") + +o.spec("fragment", function() { + o("works", function() { + var attrs = {foo: 5} + var child = {tag: "p"} + var frag = fragment(attrs, [child]) + + o(frag.tag).equals("[") + + o(frag.children instanceof Array).equals(true) + o(frag.children.length).equals(1) + o(frag.children[0]).equals(child) + + o(frag.attrs).equals(attrs) + + o(frag.key).equals(undefined) + }) + o("supports keys", function() { + var attrs = {key: 7} + var frag = fragment(attrs, []) + o(frag.tag).equals("[") + + o(frag.children instanceof Array).equals(true) + o(frag.children.length).equals(0) + + o(frag.attrs).equals(attrs) + o(frag.attrs.key).equals(7) + + o(frag.key).equals(7) + }) +}) From 435b7292897a6e676d2323df77e770e76b00a658 Mon Sep 17 00:00:00 2001 From: Gandalf-the-Bot Date: Thu, 18 Aug 2016 23:28:06 +0000 Subject: [PATCH 4/7] Bundled output for commit 6bebdf8d4ba74bf9c7298ec44a27ac0167e7bdd9 [skip ci] --- mithril.js | 9 ++++-- mithril.min.js | 82 +++++++++++++++++++++++++------------------------- 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/mithril.js b/mithril.js index 4974e591..47c10332 100644 --- a/mithril.js +++ b/mithril.js @@ -72,6 +72,12 @@ function hyperscript(selector) { if (typeof selector === "string") return selectorCache[selector](attrs || {}, Vnode.normalizeChildren(children)) return Vnode(selector, attrs && attrs.key, attrs || {}, Vnode.normalizeChildren(children), undefined, undefined) } +hyperscript.trust = function(html) { + return Vnode("<", undefined, undefined, html, undefined, undefined) +} +hyperscript.fragment = function(attrs, children) { + return Vnode("[", attrs.key, attrs, Vnode.normalizeChildren(children), undefined, undefined) +} var m = hyperscript var renderService = function($window) { var $doc = $window.document @@ -1136,9 +1142,6 @@ m.mount = function(renderer, pubsub) { run() } }(renderService, redrawService) -m.trust = function(html) { - return Vnode("<", undefined, undefined, html, undefined, undefined) -} m.withAttr = function(attrName, callback, context) { return function(e) { return callback.call(context || this, attrName in e.currentTarget ? e.currentTarget[attrName] : e.currentTarget.getAttribute(attrName)) diff --git a/mithril.min.js b/mithril.min.js index 108951f9..2512a235 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1,41 +1,41 @@ -new function(){function u(b,d,r,g,n,k){return{tag:b,key:d,attrs:r,children:g,text:n,dom:k,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}u.normalize=function(b){return b instanceof Array?u("[",void 0,void 0,u.normalizeChildren(b),void 0,void 0):null!=b&&"object"!==typeof b?u("#",void 0,void 0,b,void 0,void 0):b};u.normalizeChildren=function(b){for(var d=0;d=t&&A>=B;){var h=a[t],v=f[B];if(h===v)t++,B++;else if(null!=h&&null!=v&&h.key===v.key)t++,B++,k(c,h,v,e,l(a,t,b),q,p),q&&h.tag===v.tag&&w(c,m(h),b);else if(h=a[g],h===v)g--,B++;else if(null!=h&&null!=v&&h.key===v.key)k(c,h,v,e,l(a,g+1,b),q,p),B=t&&A>=B;){h=a[g];v=f[A];if(h===v)g--;else if(null!=h&&null!=v&&h.key===v.key)k(c,h,v,e,l(a,g+1,b),q,p),q&&h.tag===v.tag&&w(c,m(h),b), -null!=h.dom&&(b=h.dom),g--;else{if(!n){n=a;var h=g,x={},u;for(u=0;ub.indexOf("?")?"?":"&";b+=p+g}return b}function n(b){try{return""!==b?JSON.parse(b):null}catch(d){throw Error(b);}}function k(b){return b.responseText}function m(b,d){if("function"===typeof b)if(d instanceof Array)for(var g=0;gp.status)d(m(e.type, -b));else{var g=Error(p.responseText),h;for(h in b)g[h]=b[h];d.error(g)}}catch(w){d.error(w)}"function"===typeof y&&y()}};h?p.send(e.data):p.send();return d},jsonp:function(e){var d=l();void 0!==e.initialValue&&d(e.initialValue);var h=e.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+w++,p=b.document.createElement("script");b[h]=function(g){p.parentNode.removeChild(p);d(m(e.type,g));"function"===typeof y&&y();delete b[h]};p.onerror=function(){p.parentNode.removeChild(p);d.error(Error("JSONP request failed")); -"function"===typeof y&&y();delete b[h]};null==e.data&&(e.data={});e.url=r(e.url,e.data);e.data[e.callbackKey||"callback"]=h;p.src=g(e.url,e.data);b.document.documentElement.appendChild(p);return d},setCompletionCallback:function(b){y=b}}}(window,console.error.bind(console)),D=function(){var b=[];return{subscribe:b.push.bind(b),unsubscribe:function(d){d=b.indexOf(d);-1=r&&A>=B;){var k=a[r],v=f[B];if(k===v)r++,B++;else if(null!=k&&null!=v&&k.key===v.key)r++,B++,h(b,k,v,d,l(a,r,c),p,u),p&&k.tag===v.tag&&w(b,m(k),c);else if(k=a[g],k===v)g--,B++;else if(null!=k&&null!=v&&k.key===v.key)h(b,k,v,d,l(a,g+1,c),p,u),B= +r&&A>=B;){k=a[g];v=f[A];if(k===v)g--;else if(null!=k&&null!=v&&k.key===v.key)h(b,k,v,d,l(a,g+1,c),p,u),p&&k.tag===v.tag&&w(b,m(k),c),null!=k.dom&&(c=k.dom),g--;else{if(!n){n=a;var k=g,t={},y;for(y=0;yc.indexOf("?")?"?":"&";c+=g+e}return c}function n(c){try{return""!==c?JSON.parse(c):null}catch(d){throw Error(c);}}function h(c){return c.responseText}function m(c,d){if("function"=== +typeof c)if(d instanceof Array)for(var e=0;eu.status)e(m(c.type,d));else{var g=Error(u.responseText),k;for(k in d)g[k]=d[k];e.error(g)}}catch(w){e.error(w)}"function"===typeof z&&z()}};k?u.send(c.data):u.send();return e},jsonp:function(c){var e=l();void 0!==c.initialValue&&e(c.initialValue);var k=c.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+w++,h=d.document.createElement("script");d[k]=function(g){h.parentNode.removeChild(h); +e(m(c.type,g));"function"===typeof z&&z();delete d[k]};h.onerror=function(){h.parentNode.removeChild(h);e.error(Error("JSONP request failed"));"function"===typeof z&&z();delete d[k]};null==c.data&&(c.data={});c.url=q(c.url,c.data);c.data[c.callbackKey||"callback"]=k;h.src=g(c.url,c.data);d.document.documentElement.appendChild(h);return e},setCompletionCallback:function(c){z=c}}}(window,console.error.bind(console)),C=function(){var d=[];return{subscribe:d.push.bind(d),unsubscribe:function(e){e=d.indexOf(e); +-1 Date: Mon, 22 Aug 2016 11:27:42 +0100 Subject: [PATCH 5/7] Throw self-returning component to avoid infinite loop #1260 --- render/render.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/render/render.js b/render/render.js index 40874142..8c19c75d 100644 --- a/render/render.js +++ b/render/render.js @@ -98,6 +98,8 @@ module.exports = function($window) { initLifecycle(vnode.tag, vnode, hooks) vnode.instance = Vnode.normalize(vnode.tag.view.call(vnode.state, vnode)) if (vnode.instance != null) { + if(vnode.instance === vnode) + throw Error("A component view mustn't return the vnode that was supplied to it.") var element = createNode(vnode.instance, hooks, ns) vnode.dom = vnode.instance.dom vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0 @@ -117,7 +119,7 @@ module.exports = function($window) { else { var recycling = isRecyclable(old, vnodes) if (recycling) old = old.concat(old.pool) - + if (old.length === vnodes.length && vnodes[0] != null && vnodes[0].key == null) { for (var i = 0; i < old.length; i++) { if (old[i] === vnodes[i] || old[i] == null && vnodes[i] == null) continue @@ -516,7 +518,7 @@ module.exports = function($window) { function render(dom, vnodes) { var hooks = [] var active = $doc.activeElement - + // First time rendering into a node clears it out if (dom.vnodes == null) dom.textContent = "" From f2f8bf825e1e4faffd01ede029eef1e8a99f1b75 Mon Sep 17 00:00:00 2001 From: Barney Carroll Date: Mon, 22 Aug 2016 11:37:42 +0100 Subject: [PATCH 6/7] Test case for circular component returns --- render/tests/test-component.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/render/tests/test-component.js b/render/tests/test-component.js index c6078469..13eb0bcc 100644 --- a/render/tests/test-component.js +++ b/render/tests/test-component.js @@ -254,6 +254,22 @@ o.spec("component", function() { o(root.childNodes.length).equals(0) }) + o("throws a custom error if it returns itself", function() { + // A view that returns its vnode would otherwise trigger an infinite loop + var component = { + view: function(vnode) { + return vnode + } + } + try { + render(root, [{tag: component}]) + } + catch(error){ + o(error instanceof Error).equals(true) + // Call stack excession is a RangeError + o(error instanceof RangeError).equals(false) + } + }) o("can update when returning fragments", function() { var component = { view: function(vnode) { From df04dacf2d38ce253b89c8a0b4c04db511b4a4ce Mon Sep 17 00:00:00 2001 From: Barney Carroll Date: Mon, 22 Aug 2016 11:38:42 +0100 Subject: [PATCH 7/7] Compiled circular view error catch --- mithril.js | 4 ++-- mithril.min.js | 44 ++++++++++++++++++++++---------------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/mithril.js b/mithril.js index 47c10332..6106cc0e 100644 --- a/mithril.js +++ b/mithril.js @@ -166,6 +166,8 @@ var renderService = function($window) { initLifecycle(vnode.tag, vnode, hooks) vnode.instance = Vnode.normalize(vnode.tag.view.call(vnode.state, vnode)) if (vnode.instance != null) { + if(vnode.instance === vnode) + throw Error("A component view mustn't return the vnode that was supplied to it.") var element = createNode(vnode.instance, hooks, ns) vnode.dom = vnode.instance.dom vnode.domSize = vnode.dom != null ? vnode.instance.domSize : 0 @@ -184,7 +186,6 @@ var renderService = function($window) { else { var recycling = isRecyclable(old, vnodes) if (recycling) old = old.concat(old.pool) - if (old.length === vnodes.length && vnodes[0] != null && vnodes[0].key == null) { for (var i = 0; i < old.length; i++) { if (old[i] === vnodes[i] || old[i] == null && vnodes[i] == null) continue @@ -575,7 +576,6 @@ var renderService = function($window) { function render(dom, vnodes) { var hooks = [] var active = $doc.activeElement - // First time rendering into a node clears it out if (dom.vnodes == null) dom.textContent = "" if (!(vnodes instanceof Array)) vnodes = [vnodes] diff --git a/mithril.min.js b/mithril.min.js index 2512a235..adef8ef9 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -3,28 +3,28 @@ n[e[4]]=h||!0)}0=r&&A>=B;){var k=a[r],v=f[B];if(k===v)r++,B++;else if(null!=k&&null!=v&&k.key===v.key)r++,B++,h(b,k,v,d,l(a,r,c),p,u),p&&k.tag===v.tag&&w(b,m(k),c);else if(k=a[g],k===v)g--,B++;else if(null!=k&&null!=v&&k.key===v.key)h(b,k,v,d,l(a,g+1,c),p,u),B= -r&&A>=B;){k=a[g];v=f[A];if(k===v)g--;else if(null!=k&&null!=v&&k.key===v.key)h(b,k,v,d,l(a,g+1,c),p,u),p&&k.tag===v.tag&&w(b,m(k),c),null!=k.dom&&(c=k.dom),g--;else{if(!n){n=a;var k=g,t={},y;for(y=0;y=r&&A>=B;){var k=a[r],v=f[B];if(k===v)r++,B++;else if(null!=k&&null!=v&&k.key===v.key)r++,B++,h(b,k,v,d,l(a,r,c),p,u),p&&k.tag===v.tag&&w(b,m(k),c);else if(k=a[g],k===v)g--,B++;else if(null!=k&&null!=v&&k.key===v.key)h(b,k,v,d,l(a,g+1,c),p,u),B=r&&A>=B;){k=a[g];v=f[A];if(k===v)g--;else if(null!=k&&null!=v&&k.key===v.key)h(b,k,v,d,l(a,g+1,c),p,u),p&&k.tag===v.tag&&w(b,m(k),c),null!=k.dom&&(c=k.dom),g--;else{if(!n){n=a;var k=g,t={},y;for(y=0;yc.indexOf("?")?"?":"&";c+=g+e}return c}function n(c){try{return""!==c?JSON.parse(c):null}catch(d){throw Error(c);}}function h(c){return c.responseText}function m(c,d){if("function"=== typeof c)if(d instanceof Array)for(var e=0;e