From c55e50617f5ecbc509f6ca46986cb67b13355ac0 Mon Sep 17 00:00:00 2001 From: Arthur Fiorette Date: Mon, 23 Oct 2023 01:55:36 -0300 Subject: [PATCH] perf: avoid creating object in hot path --- index.js | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/index.js b/index.js index e67dbd101..c2227b904 100644 --- a/index.js +++ b/index.js @@ -372,46 +372,43 @@ function contentsToString(contents, escape) { * @returns {any} */ function createElement(name, attrs, ...children) { - // Adds the children to the attributes if it is not present. - if (attrs === null) { - attrs = { children }; - } + const hasAttrs = attrs !== null; // Calls the element creator function if the name is a function if (typeof name === 'function') { - // In case the children attributes is not present, add it as a property. - if (attrs.children === undefined) { - // When only a single child is present, unwrap it. - if (children.length > 1) { - attrs.children = children; - } else { - attrs.children = children[0]; - } + // We at least need to pass the children to the function component. We may receive null if this + // component was called without any children. + if (!hasAttrs) { + attrs = { children: children.length > 1 ? children : children[0] }; + } else if (attrs.children === undefined) { + attrs.children = children.length > 1 ? children : children[0]; } return name(attrs); } // Switches the tag name when this custom `tag` is present. - if (name === 'tag') { + if (hasAttrs && name === 'tag') { name = String(attrs.of); delete attrs.of; } + const attributes = hasAttrs ? attributesToString(attrs) : ''; + if (children.length === 0 && isVoidElement(name)) { - return '<' + name + attributesToString(attrs) + '/>'; + return '<' + name + attributes + '/>'; } - let contents = contentsToString(children, attrs.safe); + const contents = contentsToString(children, hasAttrs && attrs.safe); // Faster than checking if `children instanceof Promise` // https://jsperf.app/zipuvi if (typeof contents === 'string') { - return '<' + name + attributesToString(attrs) + '>' + contents + ''; + return '<' + name + attributes + '>' + contents + ''; } return contents.then(function asyncChildren(child) { - return '<' + name + attributesToString(attrs) + '>' + child + ''; + return '<' + name + attributes + '>' + child + ''; }); }