From 7f19adec990bd4bf3e0687395ee10004493fa290 Mon Sep 17 00:00:00 2001 From: Kabir Shah Date: Mon, 3 Apr 2017 16:42:54 -0700 Subject: [PATCH] generate code that flattens shallow arrays instead of doing it during runtime --- benchmarks/dbmon/index.html | 2 +- dist/moon.js | 43 ++++++++++++++++++++++--------------- dist/moon.min.js | 2 +- src/compiler/generator.js | 18 ++++++++++++---- src/directives/default.js | 12 ++++++++++- src/util/vdom.js | 13 +---------- test/js/test.js | 2 +- 7 files changed, 55 insertions(+), 37 deletions(-) diff --git a/benchmarks/dbmon/index.html b/benchmarks/dbmon/index.html index 832d2da1..357f3c97 100644 --- a/benchmarks/dbmon/index.html +++ b/benchmarks/dbmon/index.html @@ -28,7 +28,7 @@ --> -
{{db.dbname}}{{db.lastSample.nbQueries}}{{q.formatElapsed}}
{{q.query}}
+
{{db.dbname}}{{db.lastSample.nbQueries}}{{q.formatElapsed}}
{{q.query}}
diff --git a/dist/moon.js b/dist/moon.js index 05e62bc6..492bab10 100644 --- a/dist/moon.js +++ b/dist/moon.js @@ -455,7 +455,7 @@ * @param {Object|String} children * @return {Object} Object usable in Virtual DOM (VNode) */ - var h = function (tag, attrs, meta, nestedChildren) { + var h = function (tag, attrs, meta, children) { // Text Node if (tag === "#text") { // Tag => #text @@ -464,17 +464,6 @@ return createElement("#text", meta, { attrs: {} }, attrs, []); } - // Setup Children - var children = []; - for (var i = 0; i < nestedChildren.length; i++) { - var child = nestedChildren[i]; - if (Array.isArray(child)) { - children = children.concat(child); - } else { - children.push(child); - } - } - // It's a Component if (components[tag]) { // Functional component @@ -1240,9 +1229,10 @@ /** * Generates Code for Props * @param {Object} vnode + * @param {Object} parentVNode * @return {String} generated code */ - var generateProps = function (vnode) { + var generateProps = function (vnode, parentVNode) { var attrs = vnode.props.attrs; var generatedObject = "{attrs: {"; @@ -1251,7 +1241,7 @@ for (var beforeAttr in attrs) { var beforeAttrName = attrs[beforeAttr].name; if (specialDirectives[beforeAttrName] && specialDirectives[beforeAttrName].beforeGenerate) { - specialDirectives[beforeAttrName].beforeGenerate(attrs[beforeAttr].value, attrs[beforeAttr].meta, vnode); + specialDirectives[beforeAttrName].beforeGenerate(attrs[beforeAttr].value, attrs[beforeAttr].meta, vnode, parentVNode); } } @@ -1387,7 +1377,7 @@ var call = 'h("' + vnode.type + '", '; // Generate Code for Props - call += generateProps(vnode) + ", "; + call += generateProps(vnode, parentVNode) + ", "; // Generate code for children recursively here (in case modified by special directives) var children = vnode.children.map(function (item) { @@ -1403,7 +1393,15 @@ call += generateMeta(vnode.meta); // Generate Code for Children - call += children.length ? ", [" + generateArray(children) + "]" : ", []"; + if (children.length) { + if (vnode.deep) { + call += ', [].concat.apply([], [' + generateArray(children) + '])'; + } else { + call += ', [' + generateArray(children) + ']'; + } + } else { + call += ", []"; + } // Close Call call += ")"; @@ -1451,6 +1449,7 @@ if (el.type === "slot") { if (parentEl) { parentEl.meta.shouldRender = true; + parentEl.deep = true; } compiledCode = 'instance.$slots[\'' + (slotNameAttr && slotNameAttr.value || "default") + '\']'; } else { @@ -1883,17 +1882,27 @@ }; specialDirectives[Moon.config.prefix + "for"] = { + beforeGenerate: function (value, meta, vnode, parentVNode) { + // Setup Deep Flag to Flatten Array + parentVNode.deep = true; + }, afterGenerate: function (value, meta, code, vnode) { + // Get Parts var parts = value.split(" in "); + // Aliases var aliases = parts[0].split(","); - + // The Iteratable var iteratable = compileTemplate(parts[1], false); + // Get any parameters var params = aliases.join(","); + + // Change any references to the parameters in children code.replace(new RegExp('instance\\.get\\("(' + aliases.join("|") + ')"\\)', 'g'), function (match, alias) { code = code.replace(new RegExp('instance.get\\("' + alias + '"\\)', "g"), alias); }); + // Use the renderLoop runtime helper return 'instance.renderLoop(' + iteratable + ', function(' + params + ') { return ' + code + '; })'; } }; diff --git a/dist/moon.min.js b/dist/moon.min.js index 01e2ea53..e9556bdf 100644 --- a/dist/moon.min.js +++ b/dist/moon.min.js @@ -5,4 +5,4 @@ * Free to use under the MIT license. * https://kingpixil.github.io/license */ -!function(e,t){"object"==typeof module&&module.exports?module.exports=t():e.Moon=t()}(this,function(){"use strict";function e(e){this.instance=e,this.cache={},this.signals={},this.dep={target:null,map:{}}}function t(t){this.$opts=t||{},this.$id=s++,this.$name=this.$opts.name||"root",this.$data=this.$opts.data||{},this.$render=this.$opts.render||y,this.$hooks=this.$opts.hooks||{},this.$methods=this.$opts.methods||{},this.$events={},this.$dom={},this.$observer=new e(this),this.$destroyed=!1,this.$initialRender=!0,this.$queued=!1,this.$opts.computed&&a(this,this.$opts.computed),this.init()}var r={},n={},i={},o={stop:"event.stopPropagation();",prevent:"event.preventDefault();",ctrl:"if(!event.ctrlKey) {return;};",shift:"if(!event.shiftKey) {return;};",alt:"if(!event.altKey) {return;};",enter:"if(event.keyCode !== 13) {return;};"},s=0,a=function(e,t){for(var r in t)!function(r){e.$observer.observe(r);var n={get:function(){var n=null;return e.$observer.cache[r]?n=e.$observer.cache[r]:(e.$observer.dep.target=r,n=t[r].get.call(e),e.$observer.dep.target=null,e.$observer.cache[r]=n),n}};t[r].set&&(n.set=function(n){return t[r].set.call(e,n)}),Object.defineProperty(e.$data,r,n)}(r)};e.prototype.observe=function(e){var t=this;this.signals[e]=function(){t.cache[e]=null}},e.prototype.notify=function(e){if(this.dep.map[e])for(var t=0;ta?s:a,p=0;p",e.current);if(n===-1)return e.tokens.push({type:"comment",value:t.slice(e.current)}),void(e.current=r);e.tokens.push({type:"comment",value:t.slice(e.current,n)}),e.current=n+3},I=function(e){var t=e.input,r=(t.length,"/"===t.charAt(e.current+1));e.tokens.push({type:"tagStart",close:r}),e.current+=r?2:1;var n=H(e);q(e);var i="/"===t.charAt(e.current);e.tokens.push({type:"tagEnd",close:!1}),e.current+=i?2:1,i&&(e.tokens.push({type:"tagStart",close:!0}),e.tokens.push({type:"tag",value:n}),e.tokens.push({type:"attribute",value:{}}),e.tokens.push({type:"tagEnd",close:!1}))},H=function(e){for(var t=e.input,r=t.length,n=e.current;n"!==i&&" "!==i)break;n++}for(var o=n;o"===i||" "===i)break;o++}var s=t.slice(n,o);return e.tokens.push({type:"tag",value:s}),e.current=o,s},q=function(e){for(var t=e.input,r=t.length,n=e.current,i={},o=t.charAt(n),s=t.charAt(n+1),a=function(){n++,o=t.charAt(n),s=t.charAt(n+1)};n"!==o&&("/"!==o||">"!==s);)if(" "!==o){for(var u="",c=!1;"="!==o&&n"!==o||"/"===o&&">"!==s)){c=!0;break}u+=o,a()}var p={name:u,value:"",meta:{}};if(c)i[u]=p;else{var l=" ";for(a(),"'"===o||'"'===o?(l=o,a()):p.value+=o;(o!==l&&">"!==o||"/"===o&&">"!==s)&&n1&&(a=u.shift(),s=u.join("(").slice(0,-1));var c="";n.shift();for(var p=0;pa?s:a,p=0;p",e.current);if(n===-1)return e.tokens.push({type:"comment",value:t.slice(e.current)}),void(e.current=r);e.tokens.push({type:"comment",value:t.slice(e.current,n)}),e.current=n+3},I=function(e){var t=e.input,r=(t.length,"/"===t.charAt(e.current+1));e.tokens.push({type:"tagStart",close:r}),e.current+=r?2:1;var n=H(e);q(e);var i="/"===t.charAt(e.current);e.tokens.push({type:"tagEnd",close:!1}),e.current+=i?2:1,i&&(e.tokens.push({type:"tagStart",close:!0}),e.tokens.push({type:"tag",value:n}),e.tokens.push({type:"attribute",value:{}}),e.tokens.push({type:"tagEnd",close:!1}))},H=function(e){for(var t=e.input,r=t.length,n=e.current;n"!==i&&" "!==i)break;n++}for(var o=n;o"===i||" "===i)break;o++}var s=t.slice(n,o);return e.tokens.push({type:"tag",value:s}),e.current=o,s},q=function(e){for(var t=e.input,r=t.length,n=e.current,i={},o=t.charAt(n),s=t.charAt(n+1),a=function(){n++,o=t.charAt(n),s=t.charAt(n+1)};n"!==o&&("/"!==o||">"!==s);)if(" "!==o){for(var u="",c=!1;"="!==o&&n"!==o||"/"===o&&">"!==s)){c=!0;break}u+=o,a()}var p={name:u,value:"",meta:{}};if(c)i[u]=p;else{var l=" ";for(a(),"'"===o||'"'===o?(l=o,a()):p.value+=o;(o!==l&&">"!==o||"/"===o&&">"!==s)&&n1&&(a=u.shift(),s=u.join("(").slice(0,-1));var c="";n.shift();for(var p=0;p #text @@ -68,17 +68,6 @@ const h = function(tag, attrs, meta, nestedChildren) { return createElement("#text", meta, {attrs:{}}, attrs, []); } - // Setup Children - let children = []; - for(var i = 0; i < nestedChildren.length; i++) { - const child = nestedChildren[i]; - if(Array.isArray(child)) { - children = children.concat(child); - } else { - children.push(child); - } - } - // It's a Component if(components[tag]) { // Functional component diff --git a/test/js/test.js b/test/js/test.js index 8ce2423d..25a45fb7 100644 --- a/test/js/test.js +++ b/test/js/test.js @@ -601,7 +601,7 @@ describe('Functional Component', function() { Moon.component('slot-functional-component', { functional: true, render: function(h, ctx) { - return h("div", functionalComponentDivSlotProps, {shouldRender: true, eventListeners: {}}, [h("h1", {}, {shouldRender: true, eventListeners: {}}, [ctx.slots['default']]), h("h1", {}, {shouldRender: true, eventListeners: {}}, [ctx.slots.named])]); + return h("div", functionalComponentDivSlotProps, {shouldRender: true, eventListeners: {}}, [h("h1", {}, {shouldRender: true, eventListeners: {}}, ctx.slots['default']), h("h1", {}, {shouldRender: true, eventListeners: {}}, ctx.slots.named)]); } }); var functionalApp = new Moon({