Skip to content

Commit e2d1702

Browse files
committed
Process paths regardless of accessor, & loop on computeLinkedPaths.
Fixes #4542
1 parent 1478a06 commit e2d1702

2 files changed

Lines changed: 31 additions & 37 deletions

File tree

lib/mixins/property-effects.html

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -371,12 +371,13 @@
371371
*/
372372
function runComputedEffects(inst, changedProps, oldProps, hasPaths) {
373373
let computeEffects = inst.__computeEffects;
374-
if (computeEffects) {
375-
let inputProps = changedProps;
376-
while (runEffects(inst, computeEffects, inputProps, oldProps, hasPaths)) {
374+
let inputProps = changedProps;
375+
while (inputProps) {
376+
computeEffects && runEffects(inst, computeEffects, inputProps, oldProps, hasPaths);
377+
computeLinkedPaths(inst, inputProps, hasPaths);
378+
if ((inputProps = inst.__dataPending)) {
377379
Object.assign(oldProps, inst.__dataOld);
378380
Object.assign(changedProps, inst.__dataPending);
379-
inputProps = inst.__dataPending;
380381
inst.__dataPending = null;
381382
}
382383
}
@@ -416,21 +417,16 @@
416417
function computeLinkedPaths(inst, changedProps, hasPaths) {
417418
let links;
418419
if (hasPaths && (links = inst.__dataLinkedPaths)) {
419-
const cache = inst.__dataTemp;
420420
let link;
421421
for (let a in links) {
422422
let b = links[a];
423423
for (let path in changedProps) {
424424
if (Polymer.Path.isDescendant(a, path)) {
425425
link = Polymer.Path.translate(a, b, path);
426-
cache[link] = changedProps[link] = changedProps[path];
427-
let notifyProps = inst.__dataToNotify || (inst.__dataToNotify = {});
428-
notifyProps[link] = true;
426+
inst._setPendingPropertyOrPath(link, changedProps[path], true, true);
429427
} else if (Polymer.Path.isDescendant(b, path)) {
430428
link = Polymer.Path.translate(b, a, path);
431-
cache[link] = changedProps[link] = changedProps[path];
432-
let notifyProps = inst.__dataToNotify || (inst.__dataToNotify = {});
433-
notifyProps[link] = true;
429+
inst._setPendingPropertyOrPath(link, changedProps[path], true, true);
434430
}
435431
}
436432
}
@@ -1292,32 +1288,28 @@
12921288
*/
12931289
_setPendingPropertyOrPath(path, value, shouldNotify, isPathNotification) {
12941290
let rootProperty = Polymer.Path.root(Array.isArray(path) ? path[0] : path);
1295-
let hasAccessor = this.__dataHasAccessor && this.__dataHasAccessor[rootProperty];
1296-
let isPath = (rootProperty !== path);
1297-
if (hasAccessor) {
1298-
if (isPath) {
1299-
if (!isPathNotification) {
1300-
// Dirty check changes being set to a path against the actual object,
1301-
// since this is the entry point for paths into the system; from here
1302-
// the only dirty checks are against the `__dataTemp` cache to prevent
1303-
// duplicate work in the same turn only. Note, if this was a notification
1304-
// of a change already set to a path (isPathNotification: true),
1305-
// we always let the change through and skip the `set` since it was
1306-
// already dirty checked at the point of entry and the underlying
1307-
// object has already been updated
1308-
let old = Polymer.Path.get(this, path);
1309-
path = /** @type {string} */ (Polymer.Path.set(this, path, value));
1310-
// Use property-accessor's simpler dirty check
1311-
if (!path || !super._shouldPropertyChange(path, value, old)) {
1312-
return false;
1313-
}
1291+
if (rootProperty !== path) {
1292+
if (!isPathNotification) {
1293+
// Dirty check changes being set to a path against the actual object,
1294+
// since this is the entry point for paths into the system; from here
1295+
// the only dirty checks are against the `__dataTemp` cache to prevent
1296+
// duplicate work in the same turn only. Note, if this was a notification
1297+
// of a change already set to a path (isPathNotification: true),
1298+
// we always let the change through and skip the `set` since it was
1299+
// already dirty checked at the point of entry and the underlying
1300+
// object has already been updated
1301+
let old = Polymer.Path.get(this, path);
1302+
path = /** @type {string} */ (Polymer.Path.set(this, path, value));
1303+
// Use property-accessor's simpler dirty check
1304+
if (!path || !super._shouldPropertyChange(path, value, old)) {
1305+
return false;
13141306
}
1315-
this.__dataHasPaths = true;
13161307
}
1308+
this.__dataHasPaths = true;
13171309
return this._setPendingProperty(path, value, shouldNotify);
13181310
} else {
1319-
if (isPath) {
1320-
Polymer.Path.set(this, path, value);
1311+
if (this.__dataHasAccessor && this.__dataHasAccessor[rootProperty]) {
1312+
return this._setPendingProperty(path, value, shouldNotify);
13211313
} else {
13221314
this[path] = value;
13231315
}
@@ -1548,8 +1540,6 @@
15481540
this.__dataHasPaths = false;
15491541
// Compute properties
15501542
runComputedEffects(this, changedProps, oldProps, hasPaths);
1551-
// Compute linked paths
1552-
computeLinkedPaths(this, changedProps, hasPaths);
15531543
// Clear notify properties prior to possible reentry (propagate, observe),
15541544
// but after computing effects have a chance to add to them
15551545
let notifyProps = this.__dataToNotify;

test/unit/path-effects.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -898,11 +898,15 @@
898898
assert.equal(el.xChanged.callCount, 1);
899899
assert.equal(el.yChanged.callCount, 1);
900900
assert.equal(el.aChanged.callCount, 1);
901-
el.unlinkPaths('y');
902901
el.set('a.foo', 2);
903902
assert.equal(el.xChanged.callCount, 2);
904-
assert.equal(el.yChanged.callCount, 1);
903+
assert.equal(el.yChanged.callCount, 2);
905904
assert.equal(el.aChanged.callCount, 2);
905+
el.unlinkPaths('y');
906+
el.set('a.foo', 3);
907+
assert.equal(el.xChanged.callCount, 3);
908+
assert.equal(el.yChanged.callCount, 2);
909+
assert.equal(el.aChanged.callCount, 3);
906910
});
907911

908912
test('link two arrays', function() {

0 commit comments

Comments
 (0)