Skip to content

Commit 3f03353

Browse files
authored
Merge pull request #16282 from emberjs/fix-nested-observerset-flushes
[BUGFIX beta] Fix nested ObserverSet flushes
2 parents 0e80c40 + b659214 commit 3f03353

File tree

3 files changed

+30
-12
lines changed

3 files changed

+30
-12
lines changed

packages/ember-metal/lib/observer_set.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { sendEvent } from './events';
2+
13
/**
24
ObserverSet is a data structure used to keep track of observers
35
that have been deferred.
@@ -27,25 +29,27 @@ export default class ObserverSet {
2729
}
2830

2931
if (!keys.has(key)) {
30-
this.queue.push({ object, key });
32+
this.queue.push([object, key]);
3133
keys.add(key);
3234
}
3335
}
3436

35-
forEach(cb) {
36-
for (let i = 0; i < this.queue.length; i++) {
37-
let { object, key } = this.queue[i];
37+
flush() {
38+
// The queue is saved off to support nested flushes.
39+
let queue = this.queue;
40+
this.added.clear();
41+
this.queue = [];
42+
43+
for (let i = 0; i < queue.length; i++) {
44+
let pair = queue[i];
45+
let object = pair[0];
46+
let key = pair[1];
3847

3948
if (object.isDestroying || object.isDestroyed) {
4049
continue;
4150
}
4251

43-
cb(object, key);
52+
sendEvent(object, key, pair);
4453
}
4554
}
46-
47-
clear() {
48-
this.added.clear();
49-
this.queue.length = 0;
50-
}
5155
}

packages/ember-metal/lib/property_events.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,7 @@ function beginPropertyChanges() {
188188
function endPropertyChanges() {
189189
deferred--;
190190
if (deferred <= 0) {
191-
observerSet.forEach((object, key)=> sendEvent(object, key, [object, key]));
192-
observerSet.clear();
191+
observerSet.flush();
193192
}
194193
}
195194

packages/ember-metal/tests/observer_test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,21 @@ testBoth('observers added/removed during changeProperties should do the right th
673673
assert.equal(removedAfterLastChangeObserver.didChangeCount, 0, 'removeObserver called after the last change sees none');
674674
});
675675

676+
testBoth('calling changeProperties while executing deferred observers works correctly', function(get, set, assert) {
677+
let obj = { foo: 0 };
678+
let fooDidChange = 0;
679+
680+
addObserver(obj, 'foo', () => {
681+
fooDidChange++;
682+
changeProperties(() => {});
683+
});
684+
685+
changeProperties(() => {
686+
set(obj, 'foo', 1);
687+
});
688+
689+
assert.equal(fooDidChange, 1);
690+
});
676691

677692
QUnit.module('Keys behavior with observers');
678693

0 commit comments

Comments
 (0)