From b3290955c9511c3591c5335c8afc39cb9dbe0eaa Mon Sep 17 00:00:00 2001 From: kfule Date: Sun, 27 Oct 2024 00:26:56 +0900 Subject: [PATCH] [refactor] performance improvement by replacing #2622 fix in render.js with another workaround in hyperscript.js The input[type] inspection at the beginning of setAttr() was called for each attribute. This had a negative impact on performance. The new workaround in execSelector() controls the order of setting attributes by reordering the keys in attrs. --- render/hyperscript.js | 7 +++++++ render/render.js | 16 ++++------------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/render/hyperscript.js b/render/hyperscript.js index f9a7e6782..a40004131 100644 --- a/render/hyperscript.js +++ b/render/hyperscript.js @@ -56,6 +56,13 @@ function execSelector(state, vnode) { if (hasClass) attrs.class = null + // workaround for #2622 (reorder keys in attrs to set "type" first) + // The DOM does things to inputs based on the "type", so it needs set first. + // See: https://github.com/MithrilJS/mithril.js/issues/2622 + if (state.tag === "input" && hasOwn.call(attrs, "type")) { + attrs = assign({type: attrs.type}, attrs) + } + vnode.attrs = attrs return vnode diff --git a/render/render.js b/render/render.js index a41244324..1f6ca3d7f 100644 --- a/render/render.js +++ b/render/render.js @@ -671,18 +671,13 @@ module.exports = function() { //attrs function setAttrs(vnode, attrs, ns) { - // If you assign an input type that is not supported by IE 11 with an assignment expression, an error will occur. - // - // Also, the DOM does things to inputs based on the value, so it needs set first. - // See: https://github.com/MithrilJS/mithril.js/issues/2622 - if (vnode.tag === "input" && attrs.type != null) vnode.dom.setAttribute("type", attrs.type) var isFileInput = attrs != null && vnode.tag === "input" && attrs.type === "file" for (var key in attrs) { setAttr(vnode, key, null, attrs[key], ns, isFileInput) } } function setAttr(vnode, key, old, value, ns, isFileInput) { - if (key === "key" || key === "is" || value == null || isLifecycleMethod(key) || (old === value && !isFormAttribute(vnode, key)) && typeof value !== "object" || key === "type" && vnode.tag === "input") return + if (key === "key" || key === "is" || value == null || isLifecycleMethod(key) || (old === value && !isFormAttribute(vnode, key)) && typeof value !== "object") return if (key[0] === "o" && key[1] === "n") return updateEvent(vnode, key, value) if (key.slice(0, 6) === "xlink:") vnode.dom.setAttributeNS("http://www.w3.org/1999/xlink", key.slice(6), value) else if (key === "style") updateStyle(vnode.dom, old, value) @@ -702,7 +697,9 @@ module.exports = function() { if (isFileInput && "" + value !== "") { console.error("`value` is read-only on file inputs!"); return } /* eslint-enable no-implicit-coercion */ } - vnode.dom[key] = value + // If you assign an input type that is not supported by IE 11 with an assignment expression, an error will occur. + if (vnode.tag === "input" && key === "type") vnode.dom.setAttribute(key, value) + else vnode.dom[key] = value } else { if (typeof value === "boolean") { if (value) vnode.dom.setAttribute(key, "") @@ -750,11 +747,6 @@ module.exports = function() { console.warn("Don't reuse attrs object, use new object for every redraw, this will throw in next major") } if (attrs != null) { - // If you assign an input type that is not supported by IE 11 with an assignment expression, an error will occur. - // - // Also, the DOM does things to inputs based on the value, so it needs set first. - // See: https://github.com/MithrilJS/mithril.js/issues/2622 - if (vnode.tag === "input" && attrs.type != null) vnode.dom.setAttribute("type", attrs.type) var isFileInput = vnode.tag === "input" && attrs.type === "file" for (var key in attrs) { setAttr(vnode, key, old && old[key], attrs[key], ns, isFileInput)