diff --git a/lib/mixins/property-effects.html b/lib/mixins/property-effects.html index cf8b22088d..dcc1dec0cc 100644 --- a/lib/mixins/property-effects.html +++ b/lib/mixins/property-effects.html @@ -1284,17 +1284,17 @@ * @protected */ _setPendingPropertyOrPath(path, value, shouldNotify, isPathNotification) { - let rootProperty = Polymer.Path.root(Array.isArray(path) ? path[0] : path); - if (rootProperty !== path) { + if (isPathNotification || + Polymer.Path.root(Array.isArray(path) ? path[0] : path) !== path) { + // Dirty check changes being set to a path against the actual object, + // since this is the entry point for paths into the system; from here + // the only dirty checks are against the `__dataTemp` cache to prevent + // duplicate work in the same turn only. Note, if this was a notification + // of a change already set to a path (isPathNotification: true), + // we always let the change through and skip the `set` since it was + // already dirty checked at the point of entry and the underlying + // object has already been updated if (!isPathNotification) { - // Dirty check changes being set to a path against the actual object, - // since this is the entry point for paths into the system; from here - // the only dirty checks are against the `__dataTemp` cache to prevent - // duplicate work in the same turn only. Note, if this was a notification - // of a change already set to a path (isPathNotification: true), - // we always let the change through and skip the `set` since it was - // already dirty checked at the point of entry and the underlying - // object has already been updated let old = Polymer.Path.get(this, path); path = /** @type {string} */ (Polymer.Path.set(this, path, value)); // Use property-accessor's simpler dirty check @@ -1308,7 +1308,7 @@ return true; } } else { - if (this.__dataHasAccessor && this.__dataHasAccessor[rootProperty]) { + if (this.__dataHasAccessor && this.__dataHasAccessor[path]) { return this._setPendingProperty(path, value, shouldNotify); } else { this[path] = value; diff --git a/test/unit/path-effects-elements.html b/test/unit/path-effects-elements.html index 0def2656a3..b409c254b6 100644 --- a/test/unit/path-effects-elements.html +++ b/test/unit/path-effects-elements.html @@ -114,6 +114,9 @@ computedFromPaths: { computed: 'computeFromPaths(a, nested.b, nested.obj.c)' }, + computedFromLinkedPaths: { + computed: 'computeFromLinkedPaths(a, linked1.prop, linked2.prop)' + }, computed: { computed: 'compute(nested.obj.value)' } @@ -163,6 +166,9 @@ computeFromPaths: function(a, b, c) { return a + b + c; }, + computeFromLinkedPaths: sinon.spy(function(a, b, c) { + return a + b + c; + }), compute: function(val) { return '[' + val + ']'; } diff --git a/test/unit/path-effects.html b/test/unit/path-effects.html index c208b2d8b9..f432e531dd 100644 --- a/test/unit/path-effects.html +++ b/test/unit/path-effects.html @@ -909,6 +909,69 @@ assert.equal(el.aChanged.callCount, 3); }); + test('multiple linked dependencies to computed property', function() { + let linkedObj = {prop: 'Linked'}; + el.computeFromLinkedPaths.reset(); + el.setProperties({ + linked1: linkedObj, + linked2: linkedObj, + a: 'A' + }); + assert.equal(el.computeFromLinkedPaths.callCount, 1); + assert.equal(el.computedFromLinkedPaths, 'ALinkedLinked'); + + el.linkPaths('linked1', 'linked2'); + el.set('linked1.prop', 'Linked+'); + assert.equal(el.computeFromLinkedPaths.callCount, 2); + assert.equal(el.computedFromLinkedPaths, 'ALinked+Linked+'); + el.linked3 = el.linked2; + el.linkPaths('linked2', 'linked3'); + el.set('linked3.prop', 'Linked++'); + assert.equal(el.computeFromLinkedPaths.callCount, 3); + assert.equal(el.computedFromLinkedPaths, 'ALinked++Linked++'); + el.set('linked2.prop', 'Linked+++'); + assert.equal(el.computeFromLinkedPaths.callCount, 4); + assert.equal(el.computedFromLinkedPaths, 'ALinked+++Linked+++'); + el.set('linked1.prop', 'Linked++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 5); + assert.equal(el.computedFromLinkedPaths, 'ALinked++++Linked++++'); + + el.linked4 = el.linked1; + el.linkPaths('linked4', 'linked1'); + el.set('linked4.prop', 'Linked+++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 6); + assert.equal(el.computedFromLinkedPaths, 'ALinked+++++Linked+++++'); + el.set('linked3.prop', 'Linked++++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 7); + assert.equal(el.computedFromLinkedPaths, 'ALinked++++++Linked++++++'); + el.set('linked2.prop', 'Linked+++++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 8); + assert.equal(el.computedFromLinkedPaths, 'ALinked+++++++Linked+++++++'); + el.set('linked1.prop', 'Linked++++++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 9); + assert.equal(el.computedFromLinkedPaths, 'ALinked++++++++Linked++++++++'); + + el.linked5 = el.linked3; + el.linkPaths('linked5', 'linked3'); + el.set('linked4.prop', 'Linked+++++++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 10); + assert.equal(el.computedFromLinkedPaths, 'ALinked+++++++++Linked+++++++++'); + el.set('linked3.prop', 'Linked++++++++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 11); + assert.equal(el.computedFromLinkedPaths, 'ALinked++++++++++Linked++++++++++'); + el.set('linked2.prop', 'Linked+++++++++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 12); + assert.equal(el.computedFromLinkedPaths, 'ALinked+++++++++++Linked+++++++++++'); + el.set('linked1.prop', 'Linked++++++++++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 13); + assert.equal(el.computedFromLinkedPaths, 'ALinked++++++++++++Linked++++++++++++'); + + el.unlinkPaths('linked4'); + el.set('linked4.prop', 'Linked+++++++++++++'); + assert.equal(el.computeFromLinkedPaths.callCount, 13); + assert.equal(el.computedFromLinkedPaths, 'ALinked++++++++++++Linked++++++++++++'); + }); + test('link two arrays', function() { el.x = el.y = []; el.linkPaths('y', 'x');