diff --git a/src/plugins/props/util/Prop.js b/src/plugins/props/util/Prop.js index 3a36bc78..47315077 100644 --- a/src/plugins/props/util/Prop.js +++ b/src/plugins/props/util/Prop.js @@ -215,12 +215,16 @@ let Self = class Prop { parsedValue = this.spec.convert.call(element, parsedValue); } - if (this.equals(parsedValue, oldValue)) { - return; + // Resolve the default lazily so equality and propchange.oldValue match the getter. + if ( + oldValue === undefined && + !this.spec.get && + this.default !== undefined && + typeof this.default !== "function" + ) { + oldValue = this.get(element); } - element.props[this.name] = parsedValue; - let change = { element, source, @@ -228,6 +232,7 @@ let Self = class Prop { oldValue, }; + // Reflect before the equality check: an explicit equal-value write still updates the attribute. if (source === "property") { // Reflect to attribute? if (this.toAttribute) { @@ -254,6 +259,12 @@ let Self = class Prop { }); } + if (this.equals(parsedValue, oldValue)) { + return; + } + + element.props[this.name] = parsedValue; + this.changed(element, change); } diff --git a/test/plugins/props/propchange.js b/test/plugins/props/propchange.js index bdcb7da7..e8d00bef 100644 --- a/test/plugins/props/propchange.js +++ b/test/plugins/props/propchange.js @@ -132,11 +132,25 @@ export default { { name: "Assigning current default-resolved value is a no-op", run () { - this.data.element.v = 42; - return this.data.events; + let { element, events } = this.data; + let before = events.length; + element.v = 42; + return events.length - before; }, arg: { props: { v: { type: Number, default: 42 } } }, - expect: [["v", 42]], + expect: 0, + }, + { + name: "First write reports the resolved default as oldValue", + run () { + let { element } = this.data; + let oldValue; + element.addEventListener("propchange", e => (oldValue = e.detail.oldValue)); + element.prop = "new"; + return oldValue; + }, + arg: { props: { prop: { default: "initial" } } }, + expect: "initial", }, { name: "Three writes fire three propchange events in order, synchronously",