From 792aa6a7b702baba0599524cb30f7ca52e277dae Mon Sep 17 00:00:00 2001 From: Dylan Piercey Date: Fri, 3 Apr 2020 12:43:00 -0700 Subject: [PATCH] perf: optimize merge html attrs (#1538) (cherry picked from commit 17f0335503d30c46ef4f44090d8931c7e6915470) --- .../src/runtime/html/helpers/_dynamic-attr.js | 35 ++++++++++++ .../marko/src/runtime/html/helpers/attr.js | 29 +++++++--- .../marko/src/runtime/html/helpers/attrs.js | 57 ++++--------------- .../src/runtime/html/helpers/merge-attrs.js | 28 +++------ packages/marko/test/render/index.test.js | 15 ++++- 5 files changed, 89 insertions(+), 75 deletions(-) create mode 100644 packages/marko/src/runtime/html/helpers/_dynamic-attr.js diff --git a/packages/marko/src/runtime/html/helpers/_dynamic-attr.js b/packages/marko/src/runtime/html/helpers/_dynamic-attr.js new file mode 100644 index 000000000..87ecbcd74 --- /dev/null +++ b/packages/marko/src/runtime/html/helpers/_dynamic-attr.js @@ -0,0 +1,35 @@ +"use strict"; +var attrHelper = require("./attr"); +var notEmptyAttr = attrHelper.___notEmptyAttr; +var isEmptyAttrValue = attrHelper.___isEmptyAttrValue; +var classHelper = require("./class-attr"); +var styleHelper = require("./style-attr"); + +module.exports = function dynamicAttr(name, value) { + switch (name) { + case "class": + return classHelper(value); + case "style": + return styleHelper(value); + case "renderBody": + return ""; + default: + return isEmptyAttrValue(value) || isInvalidAttrName(name) + ? "" + : notEmptyAttr(name, value); + } +}; + +// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 +// Technically the above includes more invalid characters for attributes. +// In practice however the only character that does not become an attribute name +// is when there is a >. +function isInvalidAttrName(name) { + for (let i = name.length; i--; ) { + if (name[i] === ">") { + return true; + } + } + + return false; +} diff --git a/packages/marko/src/runtime/html/helpers/attr.js b/packages/marko/src/runtime/html/helpers/attr.js index a8c41f49f..47de9cc9e 100644 --- a/packages/marko/src/runtime/html/helpers/attr.js +++ b/packages/marko/src/runtime/html/helpers/attr.js @@ -4,28 +4,39 @@ var escapeQuoteHelpers = require("./escape-quotes"); var escapeDoubleQuotes = escapeQuoteHelpers.___escapeDoubleQuotes; var escapeSingleQuotes = escapeQuoteHelpers.___escapeSingleQuotes; -module.exports = function attr(name, value) { +module.exports = maybeEmptyAttr; + +maybeEmptyAttr.___notEmptyAttr = notEmptyAttr; +maybeEmptyAttr.___isEmptyAttrValue = isEmpty; + +function maybeEmptyAttr(name, value) { + if (isEmpty(value)) { + return ""; + } + + return notEmptyAttr(name, value); +} + +function notEmptyAttr(name, value) { switch (typeof value) { case "string": return " " + name + guessQuotes(value); case "boolean": - return value ? " " + name : ""; + return " " + name; case "number": return " " + name + "=" + value; - case "undefined": - return ""; case "object": - if (value === null) { - return ""; - } - if (value instanceof RegExp) { return " " + name + doubleQuote(value.source); } } return " " + name + guessQuotes(value + ""); -}; +} + +function isEmpty(value) { + return value == null || value === false; +} function doubleQuote(value) { return '="' + escapeDoubleQuotes(value) + '"'; diff --git a/packages/marko/src/runtime/html/helpers/attrs.js b/packages/marko/src/runtime/html/helpers/attrs.js index 654715489..e0a9e8e77 100644 --- a/packages/marko/src/runtime/html/helpers/attrs.js +++ b/packages/marko/src/runtime/html/helpers/attrs.js @@ -1,51 +1,18 @@ "use strict"; -var attrHelper = require("./attr"); -var classAttrHelper = require("./class-attr"); -var styleAttrHelper = require("./style-attr"); +var dynamicAttrHelper = require("./_dynamic-attr"); -// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 -var invalidAttrNameCharacters = /[\s'" a.name.localeCompare(b.name)) + .forEach(attr => { + node.removeAttributeNode(attr); + node.setAttributeNode(attr); + }); } }