Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

free transient observers at end of microtask #512

Merged
merged 1 commit into from
Sep 24, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions src/MutationObserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@
var globalMutationObservers = [];
var isScheduled = false;

function scheduleCallback() {
function scheduleCallback(observer) {
if (observer.scheduled_)
return;

observer.scheduled_ = true;
globalMutationObservers.push(observer);

if (isScheduled)
return;
setEndOfMicrotask(notifyObservers);
Expand All @@ -35,6 +41,7 @@

for (var i = 0; i < notifyList.length; i++) {
var mo = notifyList[i];
mo.scheduled_ = false;
var queue = mo.takeRecords();
removeTransientObserversFor(mo);
if (queue.length) {
Expand Down Expand Up @@ -150,8 +157,6 @@
}
}

var anyObserversEnqueued = false;

// 4.
for (var uid in interestedObservers) {
var observer = interestedObservers[uid];
Expand Down Expand Up @@ -184,15 +189,9 @@
record.oldValue = associatedStrings[uid];

// 8.
if (!observer.records_.length) {
globalMutationObservers.push(observer);
anyObserversEnqueued = true;
}
scheduleCallback(observer);
observer.records_.push(record);
}

if (anyObserversEnqueued)
scheduleCallback();
}

var slice = Array.prototype.slice;
Expand Down Expand Up @@ -255,6 +254,7 @@
this.nodes_ = [];
this.records_ = [];
this.uid_ = ++uidCounter;
this.scheduled_ = false;
}

MutationObserver.prototype = {
Expand Down Expand Up @@ -340,6 +340,10 @@
if (node === this.target)
return;

// Make sure we remove transient observers at the end of microtask, even
// if we didn't get any change records.
scheduleCallback(this.observer);

this.transientObservedNodes.push(node);
var registrations = registrationsTable.get(node);
if (!registrations)
Expand Down
28 changes: 28 additions & 0 deletions test/js/MutationObserver/transient.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,34 @@ suite('MutationObserver', function() {
var grandChild = child.appendChild(document.createElement('span'));
});

// https://dom.spec.whatwg.org/#notify-mutation-observers
test('removed at end of microtask', function(done) {
var div = document.createElement('div');
var child = div.appendChild(document.createTextNode('text'));
var observer = new MutationObserver(function() {});
observer.observe(div, {
characterData: true,
subtree: true
});
div.removeChild(child);

records = observer.takeRecords();
assert.equal(records.length, 0);

// Run after all other end-of-microtask things, like observers, have
// had their chance to run. Use `setTimeout(4)` to keep the test isolated
// from details of the MutationObserver system and to have it run late
// enough on browsers without true microtasks.
setTimeout(function() {
child.data = 'changed';

records = observer.takeRecords();
assert.equal(records.length, 0);

done();
}, 4);
});

});

});