fix race condition on list cleanup

This commit is contained in:
David Greenspan
2012-08-22 18:40:47 -07:00
parent 379f608043
commit 0ddc169a9c
2 changed files with 60 additions and 4 deletions

View File

@@ -865,8 +865,10 @@ Spark.list = function (cursor, itemFunc, elseFunc) {
}
}
initialContents = null; // save memory
var stopped = false;
var cleanup = function () {
handle.stop();
stopped = true;
};
html = annotate(html, Spark._ANNOTATION_LIST, function (range) {
outerRange = range;
@@ -894,10 +896,17 @@ Spark.list = function (cursor, itemFunc, elseFunc) {
walk.rendered.call(walk.landmark);
};
var later = function (f) {
atFlushTime(function () {
if (! stopped)
f();
});
};
// The DOM update callbacks.
_.extend(callbacks, {
added: function (item, beforeIndex) {
atFlushTime(function () {
later(function () {
var frag = Spark.render(_.bind(itemFunc, null, item));
DomUtils.wrapFragmentForContainer(frag, outerRange.containerNode());
var range = new LiveRange(Spark._TAG, frag);
@@ -915,7 +924,7 @@ Spark.list = function (cursor, itemFunc, elseFunc) {
},
removed: function (item, atIndex) {
atFlushTime(function () {
later(function () {
if (itemRanges.length === 1) {
var frag = Spark.render(elseFunc);
DomUtils.wrapFragmentForContainer(frag, outerRange.containerNode());
@@ -930,7 +939,7 @@ Spark.list = function (cursor, itemFunc, elseFunc) {
},
moved: function (item, oldIndex, newIndex) {
atFlushTime(function () {
later(function () {
if (oldIndex === newIndex)
return;
@@ -948,7 +957,7 @@ Spark.list = function (cursor, itemFunc, elseFunc) {
},
changed: function (item, atIndex) {
atFlushTime(function () {
later(function () {
Spark.renderToRange(itemRanges[atIndex], _.bind(itemFunc, null, item));
});
}

View File

@@ -3526,3 +3526,50 @@ Tinytest.add("spark - unique label", function (test) {
test.equal(bufstr(), 'ddd');
});
Tinytest.add("spark - list update", function (test) {
var R = ReactiveVar('foo');
var lst = [];
lst.callbacks = [];
lst.observe = function(callbacks) {
lst.callbacks.push(callbacks);
_.each(lst, function(x, i) {
callbacks.added(x, i);
});
return {
stop: function() {
lst.callbacks = _.without(lst.callbacks, callbacks);
}
};
};
lst.another = function () {
var i = lst.length;
lst.push({_id:'item'+i});
_.each(lst.callbacks, function (callbacks) {
callbacks.added(lst[i], i);
});
};
var div = OnscreenDiv(Meteor.render(function() {
return R.get() + Spark.list(lst, function () {
return '<hr>';
});
}));
lst.another();
Meteor.flush();
test.equal(div.html(), "foo<hr>");
lst.another();
R.set('bar');
Meteor.flush();
test.equal(div.html(), "bar<hr><hr>");
R.set('baz');
lst.another();
Meteor.flush();
test.equal(div.html(), "baz<hr><hr><hr>");
div.kill();
Meteor.flush();
});