From d600a18bc85ad611254e0a2ef775f41f43dd2660 Mon Sep 17 00:00:00 2001 From: Kabir Shah Date: Thu, 13 Jun 2019 19:47:40 -0700 Subject: [PATCH] remove view current --- packages/moon/dist/moon.js | 19 +- packages/moon/dist/moon.min.js | 2 +- packages/moon/src/executor/executor.js | 4 +- packages/moon/src/index.js | 8 +- packages/moon/src/util/globals.js | 11 +- packages/moon/test/performance/list.js | 1578 +++++++++++++++++++++++- 6 files changed, 1585 insertions(+), 37 deletions(-) diff --git a/packages/moon/dist/moon.js b/packages/moon/dist/moon.js index 74a29201..7f9fdc6e 100644 --- a/packages/moon/dist/moon.js +++ b/packages/moon/dist/moon.js @@ -1101,7 +1101,7 @@ /** * Global views */ - var viewOld, viewCurrent, viewNew; + var viewOld, viewNew; /** * Global component store */ @@ -1131,15 +1131,6 @@ function setViewOld(viewOldNew) { viewOld = viewOldNew; } - /** - * Set current view to a new function. - * - * @param {Function} viewCurrentNew - */ - - function setViewCurrent(viewCurrentNew) { - viewCurrent = viewCurrentNew; - } /** * Set new view to a new object. * @@ -1430,7 +1421,7 @@ } // Begin the view phase. - setViewNew(viewCurrent(m, md, mc, ms.Root)); + setViewNew(components.Root(m, md, mc, ms.Root)); executeView([viewNew]); } /** @@ -1517,7 +1508,7 @@ ms[name] = []; // Create a wrapper view function that processes default data if needed. - var viewComponent = dataDefault === undefined ? view : function (m, md, mc, ms) { + components[name] = dataDefault === undefined ? view : function (m, md, mc, ms) { for (var key in dataDefault) { if (!(key in md)) { md[key] = dataDefault[key]; @@ -1550,11 +1541,7 @@ } setViewOld(new NodeOld(new NodeNew(types.element, root.tagName.toLowerCase(), dataNode, []), root, [])); - setViewCurrent(viewComponent); execute(defaultValue(dataDefault, {})); - } else { - // Store it as a component if no `root` is given. - components[name] = viewComponent; } } Moon.lex = lex; diff --git a/packages/moon/dist/moon.min.js b/packages/moon/dist/moon.min.js index f87be9db..a9fa7ed8 100644 --- a/packages/moon/dist/moon.min.js +++ b/packages/moon/dist/moon.min.js @@ -4,4 +4,4 @@ * Released under the MIT License * https://kbrsh.github.io/moon */ -!function(e,t){"undefined"==typeof module?e.Moon=t():module.exports=t()}(this,function(){"use strict";var O={element:0,text:1,component:2};function f(e,t,a){this.node=e,this.element=t,this.children=a}function v(e,t,a,n){this.type=e,this.name=t,this.data=a,this.children=n}function L(e,t){return void 0===e?t:e}function o(e,t,a,n){return new v(e,t,a,n)}var c,d,u,M=/^\s+$/,q=/<([\w\d-_]+)([^>]*?)(\/?)>/g,t=/"[^"]*"|'[^']*'|\d+[a-zA-Z$_]\w*|\.[a-zA-Z$_]\w*|[a-zA-Z$_]\w*:|([a-zA-Z$_]\w*)/g,E=/&|>|<| |"|\\|"|\n|\r/g,n=["NaN","false","in","null","this","true","typeof","undefined","window"],N={class:"className",for:"htmlFor"},$={"&":"&",">":">","<":"<"," ":" ",""":'\\"',"\\":"\\\\",'"':'\\"',"\n":"\\n","\r":"\\r"};function D(e){var a=!0;return{value:e.replace(t,function(e,t){return void 0===t||-1!==n.indexOf(t)?e:(a=!1,"$"===t[0]?t:"md."+t)}),isStatic:a}}function a(e){e=e.trim();for(var t=[],a=0;a",a+2),s=e.slice(a+2,i);0,t.push({type:"tagClose",value:s}),a=i+1;continue}if("!"===r&&"-"===e[a+2]&&"-"===e[a+3]){var l=e.indexOf("--\x3e",a+4);0,a=l+3;continue}q.lastIndex=a;var o=q.exec(e);0;for(var u=o[0],v=o[1],f=o[2],c=o[3],d={},h=0;h]*?)(\/?)>/g,t=/"[^"]*"|'[^']*'|\d+[a-zA-Z$_]\w*|\.[a-zA-Z$_]\w*|[a-zA-Z$_]\w*:|([a-zA-Z$_]\w*)/g,E=/&|>|<| |"|\\|"|\n|\r/g,n=["NaN","false","in","null","this","true","typeof","undefined","window"],N={class:"className",for:"htmlFor"},$={"&":"&",">":">","<":"<"," ":" ",""":'\\"',"\\":"\\\\",'"':'\\"',"\n":"\\n","\r":"\\r"};function D(e){var a=!0;return{value:e.replace(t,function(e,t){return void 0===t||-1!==n.indexOf(t)?e:(a=!1,"$"===t[0]?t:"md."+t)}),isStatic:a}}function a(e){e=e.trim();for(var t=[],a=0;a",a+2),s=e.slice(a+2,i);0,t.push({type:"tagClose",value:s}),a=i+1;continue}if("!"===r&&"-"===e[a+2]&&"-"===e[a+3]){var l=e.indexOf("--\x3e",a+4);0,a=l+3;continue}q.lastIndex=a;var o=q.exec(e);0;for(var u=o[0],v=o[1],f=o[2],c=o[3],d={},h=0;h { @@ -100,11 +100,7 @@ export default function Moon(options) { root, [] )); - setViewCurrent(viewComponent); execute(defaultValue(dataDefault, {})); - } else { - // Store it as a component if no `root` is given. - components[name] = viewComponent; } } diff --git a/packages/moon/src/util/globals.js b/packages/moon/src/util/globals.js index fe711396..c9314b36 100644 --- a/packages/moon/src/util/globals.js +++ b/packages/moon/src/util/globals.js @@ -1,7 +1,7 @@ /** * Global views */ -export let viewOld, viewCurrent, viewNew; +export let viewOld, viewNew; /** * Global component store @@ -32,15 +32,6 @@ export function setViewOld(viewOldNew) { viewOld = viewOldNew; } -/** - * Set current view to a new function. - * - * @param {Function} viewCurrentNew - */ -export function setViewCurrent(viewCurrentNew) { - viewCurrent = viewCurrentNew; -} - /** * Set new view to a new object. * diff --git a/packages/moon/test/performance/list.js b/packages/moon/test/performance/list.js index 7a594b15..c612edc3 100644 --- a/packages/moon/test/performance/list.js +++ b/packages/moon/test/performance/list.js @@ -1,4 +1,1573 @@ /* Start Moon Source */ +/** + * Moon v1.0.0-beta.2 + * Copyright 2016-2019 Kabir Shah + * Released under the MIT License + * https://kbrsh.github.io/moon + */ +(function(root, factory) { + if (typeof module === "undefined") { + root.Moon = factory(); + } else { + module.exports = factory(); + } +}(this, function() { + "use strict"; + + /** + * View node types. + */ + var types = { + element: 0, + text: 1, + component: 2 + }; + /** + * Old Node Constructor + */ + + function NodeOld(node, element, children) { + this.node = node; + this.element = element; + this.children = children; + } + /** + * New Node Constructor + */ + + function NodeNew(type, name, data, children) { + this.type = type; + this.name = name; + this.data = data; + this.children = children; + } + /** + * Logs an error message to the console. + * @param {string} message + */ + + function error(message) { + console.error("[Moon] ERROR: " + message); + } + /** + * Returns a value or a default fallback if the value is undefined. + * + * @param value + * @param fallback + * @returns Value or default fallback + */ + + function defaultValue(value, fallback) { + return value === undefined ? fallback : value; + } + /** + * Returns a new node. + * + * @param {number} type + * @param {string} name + * @param {Object} data + * @param {Array} children + */ + + function m(type, name, data, children) { + return new NodeNew(type, name, data, children); + } + + /** + * Capture whitespace-only text. + */ + + var whitespaceRE = /^\s+$/; + /** + * Capture the tag name, attribute text, and closing slash from an opening tag. + */ + + var nameRE = /<([\w\d-_]+)([^>]*?)(\/?)>/g; + /** + * Capture the variables in expressions to scope them within the data + * parameter. This ignores property names and deep object accesses. + */ + + var expressionRE = /"[^"]*"|'[^']*'|\d+[a-zA-Z$_]\w*|\.[a-zA-Z$_]\w*|[a-zA-Z$_]\w*:|([a-zA-Z$_]\w*)/g; + /** + * Capture special characters in text that need to be escaped. + */ + + var textRE = /&|>|<| |"|\\|"|\n|\r/g; + /** + * List of global variables to ignore in expression scoping + */ + + var globals = ["NaN", "false", "in", "null", "this", "true", "typeof", "undefined", "window"]; + /* + * Map from attribute keys to equivalent DOM properties. + */ + + var normalizeAttributeKeyMap = { + "class": "className", + "for": "htmlFor" + }; + /** + * Map from special characters to a safe format for JavaScript string literals. + */ + + var escapeTextMap = { + "&": "&", + ">": ">", + "<": "<", + " ": " ", + """: "\\\"", + "\\": "\\\\", + "\"": "\\\"", + "\n": "\\n", + "\r": "\\r" + }; + /** + * Scope an expression to use variables within the `md` object. + * + * @param {string} expression + * @returns {Object} scoped expression and static status + */ + + function scopeExpression(expression) { + var isStatic = true; + var value = expression.replace(expressionRE, function (match, name) { + if (name === undefined || globals.indexOf(name) !== -1) { + // Return a static match if there are no dynamic names or if it is a + // global variable. + return match; + } else { + // Return a dynamic match if there is a dynamic name or a local. + isStatic = false; + return name[0] === "$" ? name : "md." + name; + } + }); + return { + value: value, + isStatic: isStatic + }; + } + /** + * Convert a token into a string, accounting for `` components. + * + * @param {Object} token + * @returns {string} token converted into a string + */ + + + function tokenString(token) { + if (token.type === "tagOpen") { + if (token.value === "text") { + var content = token.attributes[""]; // If the text content is surrounded with quotes, it was normal text + // and doesn't need the quotes. If not, it was an expression and + // needs to be formatted with curly braces. + + if (content.isStatic) { + return content.value.slice(1, -1); + } else { + return "{" + content.value + "}"; + } + } else { + var tag = "<" + token.value; + var attributes = token.attributes; + + for (var attributeKey in attributes) { + var attributeValue = attributes[attributeKey]; + tag += " " + attributeKey + "=" + (attributeValue.isStatic ? attributeValue.value : "{" + attributeValue.value + "}"); + } + + if (token.closed) { + tag += "/"; + } + + return tag + ">"; + } + } else { + return ""; + } + } + /** + * Logs a lexer error message to the console along with the surrounding + * characters. + * + * @param {string} message + * @param {string} input + * @param {number} index + */ + + function lexError(message, input, index) { + var lexMessage = message + "\n\n"; // Show input characters surrounding the source of the error. + + for (var i = Math.max(0, index - 16); i < Math.min(index + 16, input.length); i++) { + lexMessage += input[i]; + } + + error(lexMessage); + } + /** + * Lexer + * + * The lexer is responsible for taking an input view template and converting it + * into a list of tokens. To make the parser's job easier, it does some extra + * processing and handles tag names, attribute key/value pairs, and converting + * text into `` components. + * + * It works by running through the input text and checking for specific initial + * characters such as "<", "{", or any text. After identifying the type of + * token, it processes each part individually until the end of the token. The + * lexer appends the new token to a cumulative list and eventually returns it. + * + * @param {string} input + * @returns {Object[]} list of tokens + */ + + + function lex(input) { + // Remove leading and trailing whitespace because the lexer should only + // accept one element as an input, and whitespace counts as text. + input = input.trim(); + var tokens = []; + + for (var i = 0; i < input.length;) { + var _char = input[i]; + + if (_char === "<") { + var charNext = input[i + 1]; + + if ("development" === "development" && charNext === undefined) { + lexError("Lexer expected a character after \"<\".", input, i); + break; + } + + if (charNext === "/") { + // Append a closing tag token if a sequence of characters begins + // with "", i + 2); + + var _name = input.slice(i + 2, closeIndex); + + if ("development" === "development" && closeIndex === -1) { + lexError("Lexer expected a closing \">\" after \"", i + 4); + + if ("development" === "development" && _closeIndex === -1) { + lexError("Lexer expected a closing \"-->\" after \"