From ffafe51e4071f7c23bc3578eb5e4afd7fd5612ca Mon Sep 17 00:00:00 2001 From: kfule Date: Tue, 19 Nov 2024 05:27:22 +0900 Subject: [PATCH] updateStyle(): use setProperty() when css vars and dashed-properties, fixes #2989 (#2991) --- render/render.js | 6 +-- render/tests/test-updateElement.js | 69 ++++++++++++++++++++++++++++++ test-utils/domMock.js | 18 +++++--- 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/render/render.js b/render/render.js index 6888d06f5..6ecb38ee5 100644 --- a/render/render.js +++ b/render/render.js @@ -794,7 +794,7 @@ module.exports = function() { for (var key in style) { var value = style[key] if (value != null) { - if (key[0] === "-" && key[1] === "-") element.style.setProperty(key, String(value)) + if (key.includes("-")) element.style.setProperty(key, String(value)) else element.style[key] = String(value) } } @@ -804,14 +804,14 @@ module.exports = function() { for (var key in style) { var value = style[key] if (value != null && (value = String(value)) !== String(old[key])) { - if (key[0] === "-" && key[1] === "-") element.style.setProperty(key, value) + if (key.includes("-")) element.style.setProperty(key, value) else element.style[key] = value } } // Remove style properties that no longer exist for (var key in old) { if (old[key] != null && style[key] == null) { - if (key[0] === "-" && key[1] === "-") element.style.removeProperty(key) + if (key.includes("-")) element.style.removeProperty(key) else element.style[key] = "" } } diff --git a/render/tests/test-updateElement.js b/render/tests/test-updateElement.js index eb41e06f4..771b4a405 100644 --- a/render/tests/test-updateElement.js +++ b/render/tests/test-updateElement.js @@ -257,6 +257,75 @@ o.spec("updateElement", function() { } }) + o("use style property setter only when cameCase keys", function() { + var spySetProperty = o.spy() + var spyRemoveProperty = o.spy() + var spyDashed1 = o.spy() + var spyDashed2 = o.spy() + var spyDashed3 = o.spy() + var spyCamelCase1 = o.spy() + var spyCamelCase2 = o.spy() + + render(root, m("a")) + var el = root.firstChild + + el.style.setProperty = spySetProperty + el.style.removeProperty = spyRemoveProperty + Object.defineProperties(el.style, { + /* eslint-disable accessor-pairs */ + "background-color": {set: spyDashed1}, + "-webkit-border-radius": {set: spyDashed2}, + "--foo": {set: spyDashed3}, + backgroundColor: {set: spyCamelCase1}, + color: {set: spyCamelCase2} + /* eslint-enable accessor-pairs */ + }) + + // sets dashed properties + render(root, m("a", { + style: { + "background-color": "red", + "-webkit-border-radius": "10px", + "--foo": "bar" + } + })) + o(spySetProperty.callCount).equals(3) + o(spySetProperty.calls[0].args).deepEquals(["background-color", "red"]) + o(spySetProperty.calls[1].args).deepEquals(["-webkit-border-radius", "10px"]) + o(spySetProperty.calls[2].args).deepEquals(["--foo", "bar"]) + + // sets camelCase properties and removes dashed properties + render(root, m("a", { + style: { + backgroundColor: "green", + color: "red", + } + })) + o(spyCamelCase1.callCount).equals(1) + o(spyCamelCase2.callCount).equals(1) + o(spyCamelCase1.calls[0].args).deepEquals(["green"]) + o(spyCamelCase2.calls[0].args).deepEquals(["red"]) + o(spyRemoveProperty.callCount).equals(3) + o(spyRemoveProperty.calls[0].args).deepEquals(["background-color"]) + o(spyRemoveProperty.calls[1].args).deepEquals(["-webkit-border-radius"]) + o(spyRemoveProperty.calls[2].args).deepEquals(["--foo"]) + + // updates "color" and removes "backgroundColor" + render(root, m("a", {style: {color: "blue"}})) + o(spyCamelCase1.callCount).equals(2) // set and remove + o(spyCamelCase2.callCount).equals(2) // set and update + o(spyCamelCase1.calls[1].args).deepEquals([""]) + o(spyCamelCase2.calls[1].args).deepEquals(["blue"]) + + // unchanged by camelCase properties + o(spySetProperty.callCount).equals(3) + o(spyRemoveProperty.callCount).equals(3) + + // never calls dashed property setter + o(spyDashed1.callCount).equals(0) + o(spyDashed2.callCount).equals(0) + o(spyDashed3.callCount).equals(0) + }) o("replaces el", function() { var vnode = m("a") var updated = m("b") diff --git a/test-utils/domMock.js b/test-utils/domMock.js index 5536b49fd..3a86504af 100644 --- a/test-utils/domMock.js +++ b/test-utils/domMock.js @@ -284,12 +284,18 @@ module.exports = function(options) { getPropertyValue: {value: function(key){ return style[key] }}, - removeProperty: {value: function(key){ - style[key] = style[camelCase(key)] = "" - }}, - setProperty: {value: function(key, value){ - style[key] = style[camelCase(key)] = value - }} + removeProperty: { + writable: true, + value: function(key){ + style[key] = style[camelCase(key)] = "" + } + }, + setProperty: { + writable: true, + value: function(key, value){ + style[key] = style[camelCase(key)] = value + } + } }) var events = {} var element = {