diff --git a/packages/liveui/liveui_tests.js b/packages/liveui/liveui_tests.js
index 1ba76bf8f9..a16ef38ac2 100644
--- a/packages/liveui/liveui_tests.js
+++ b/packages/liveui/liveui_tests.js
@@ -1215,128 +1215,6 @@ Tinytest.add("liveui - basic chunk matching", function(test) {
test.equal(buf, "off0,off1".split(','));
});
-
-Tinytest.add("liveui - constant chunk", function(test) {
-
- var R, div;
-
- // top-level { constant: true }
-
- R = ReactiveVar(0);
- var ranges = [];
- div = OnscreenDiv(Meteor.ui.render(function() {
- R.get(); // create dependency
- return '';
- }, {
- constant: true,
- onscreen: function(start, end, range) {
- ranges.push(range);
- }
- }));
-
- var nodes = _.toArray(div.node().childNodes);
- test.equal(nodes.length, 3);
- Meteor.flush();
- test.equal(ranges.length, 1);
- R.set(1);
- Meteor.flush();
- test.equal(ranges.length, 2);
- test.isTrue(ranges[0] === ranges[1]);
- var nodes2 = _.toArray(div.node().childNodes);
- test.equal(nodes2.length, 3);
- test.isTrue(nodes[0] === nodes2[0]);
- test.isTrue(nodes[1] === nodes2[1]);
- test.isTrue(nodes[2] === nodes2[2]);
- div.kill();
- Meteor.flush();
- test.equal(R.numListeners(), 0);
-
- // non-top-level
-
- // run test with and without branch
- _.each([null, 'foo'], function(brnch) {
- // run test with node before or after, or neither or both
- _.each([false, true], function(nodeBefore) {
- _.each([false, true], function(nodeAfter) {
- var hasSpan = true;
- var isConstant = true;
-
- R = ReactiveVar('foo');
- div = OnscreenDiv(Meteor.ui.render(function() {
- R.get(); // create unconditional dependency
- return (nodeBefore ? R.get() : '') +
- Meteor.ui.chunk(function() {
- return hasSpan ? 'stuff' :
- 'blah';
- }, { branch: brnch, constant: isConstant }) +
- (nodeAfter ? R.get() : '');
- }));
-
- var span = div.node().getElementsByTagName('span')[0];
- hasSpan = false;
-
- test.equal(div.text(),
- (nodeBefore ? 'foo' : '')+
- 'stuff'+
- (nodeAfter ? 'foo' : ''));
-
- R.set('bar');
- Meteor.flush();
-
- // only absence of branch should cause the constant
- // chunk to be re-rendered
- test.equal(div.text(),
- (nodeBefore ? 'bar' : '')+
- (brnch ? 'stuff' : 'blah')+
- (nodeAfter ? 'bar' : ''));
-
- R.set('baz');
- Meteor.flush();
-
- // should be repeatable (liveranges not damaged)
- test.equal(div.text(),
- (nodeBefore ? 'baz' : '')+
- (brnch ? 'stuff' : 'blah')+
- (nodeAfter ? 'baz' : ''));
-
- isConstant = false; // no longer constant:true!
- R.set('qux');
- Meteor.flush();
- test.equal(div.text(),
- (nodeBefore ? 'qux' : '')+
- 'blah'+
- (nodeAfter ? 'qux' : ''));
-
- // turn constant back on
- isConstant = true;
- hasSpan = true;
- R.set('popsicle');
- Meteor.flush();
- // we don't get the span, instead old "blah" is preserved
- test.equal(div.text(),
- (nodeBefore ? 'popsicle' : '')+
- (brnch ? 'blah' : 'stuff')+
- (nodeAfter ? 'popsicle' : ''));
-
- isConstant = false;
- R.set('hi');
- Meteor.flush();
- // now we get the span!
- test.equal(div.text(),
- (nodeBefore ? 'hi' : '')+
- 'stuff'+
- (nodeAfter ? 'hi' : ''));
-
- div.kill();
- Meteor.flush();
- });
- });
- });
-
-
-});
-
-
Tinytest.add("liveui - branch keys", function(test) {
var R, div;
diff --git a/packages/spark/spark.js b/packages/spark/spark.js
index e1a1bd356a..f643b3a9df 100644
--- a/packages/spark/spark.js
+++ b/packages/spark/spark.js
@@ -553,7 +553,7 @@ var computePreservations = function (oldRange, newRange) {
preservations.push({
type: "region",
fromStart: from.firstNode(), fromEnd: from.lastNode(),
- newRange: newRange
+ newRange: to
});
_.each(to.preserve, function (nodeLabeler, selector) {
@@ -640,6 +640,7 @@ var notifyLandmarksRendered = function (range) {
r.createCallback.call(r.state);
r.created = true;
}
+ // XXX should be render(start, end) ??
r.renderCallback.call(r.state);
}
});
diff --git a/packages/spark/spark_tests.js b/packages/spark/spark_tests.js
index 1d3c520ebd..0b2a2944c8 100644
--- a/packages/spark/spark_tests.js
+++ b/packages/spark/spark_tests.js
@@ -1185,7 +1185,7 @@ var legacyLabels = {
};
-Tinytest.add("spark - preserved nodes (diff/patch)", function(test) {
+Tinytest.add("spark - landmark preserve", function(test) {
var rand;
@@ -1336,6 +1336,125 @@ Tinytest.add("spark - preserved nodes (diff/patch)", function(test) {
});
+Tinytest.add("spark - landmark constant", function(test) {
+ var R, div;
+
+ // top-level { constant: true }
+
+ R = ReactiveVar(0);
+ var states = [];
+ div = OnscreenDiv(Meteor.render(function() {
+ R.get(); // create dependency
+ return Spark.createLandmark({
+ constant: true,
+ render: function() {
+ states.push(this);
+ }
+ }, '');
+ }));
+
+ var nodes = _.toArray(div.node().childNodes);
+ test.equal(nodes.length, 3);
+ Meteor.flush();
+ test.equal(states.length, 1);
+ R.set(1);
+ Meteor.flush();
+ test.equal(states.length, 2);
+ test.isTrue(states[0] === states[1]);
+ var nodes2 = _.toArray(div.node().childNodes);
+ test.equal(nodes2.length, 3);
+ test.isTrue(nodes[0] === nodes2[0]);
+ test.isTrue(nodes[1] === nodes2[1]);
+ test.isTrue(nodes[2] === nodes2[2]);
+ div.kill();
+ Meteor.flush();
+ test.equal(R.numListeners(), 0);
+
+ // non-top-level
+
+ var i = 1;
+ // run test with and without branch
+ _.each([false, true], function(matchLandmark) {
+ // run test with node before or after, or neither or both
+ _.each([false, true], function(nodeBefore) {
+ _.each([false, true], function(nodeAfter) {
+ var hasSpan = true;
+ var isConstant = true;
+
+ R = ReactiveVar('foo');
+ div = OnscreenDiv(Meteor.render(function() {
+ R.get(); // create unconditional dependency
+ var brnch = matchLandmark ? 'myBranch' : ('branch'+(++i));
+ return (nodeBefore ? R.get() : '') +
+ Spark.labelBranch(
+ brnch,
+ Spark.createLandmark({ constant: isConstant },
+ hasSpan ? 'stuff' : 'blah')) +
+ (nodeAfter ? R.get() : '');
+ }));
+
+ var span = div.node().getElementsByTagName('span')[0];
+ hasSpan = false;
+
+ test.equal(div.text(),
+ (nodeBefore ? 'foo' : '')+
+ 'stuff'+
+ (nodeAfter ? 'foo' : ''));
+
+ R.set('bar');
+ Meteor.flush();
+
+ // only absence of branch should cause the constant
+ // chunk to be re-rendered
+ test.equal(div.text(),
+ (nodeBefore ? 'bar' : '')+
+ (matchLandmark ? 'stuff' : 'blah')+
+ (nodeAfter ? 'bar' : ''));
+
+ R.set('baz');
+ Meteor.flush();
+
+ // should be repeatable (liveranges not damaged)
+ test.equal(div.text(),
+ (nodeBefore ? 'baz' : '')+
+ (matchLandmark ? 'stuff' : 'blah')+
+ (nodeAfter ? 'baz' : ''));
+
+ isConstant = false; // no longer constant:true!
+ R.set('qux');
+ Meteor.flush();
+ test.equal(div.text(),
+ (nodeBefore ? 'qux' : '')+
+ 'blah'+
+ (nodeAfter ? 'qux' : ''));
+
+ // turn constant back on
+ isConstant = true;
+ hasSpan = true;
+ R.set('popsicle');
+ Meteor.flush();
+ // we don't get the span, instead old "blah" is preserved
+ test.equal(div.text(),
+ (nodeBefore ? 'popsicle' : '')+
+ (matchLandmark ? 'blah' : 'stuff')+
+ (nodeAfter ? 'popsicle' : ''));
+
+ isConstant = false;
+ R.set('hi');
+ Meteor.flush();
+ // now we get the span!
+ test.equal(div.text(),
+ (nodeBefore ? 'hi' : '')+
+ 'stuff'+
+ (nodeAfter ? 'hi' : ''));
+
+ div.kill();
+ Meteor.flush();
+ });
+ });
+ });
+
+});
})();