mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Fix {{#with}} over a data context that is mutated
In `Spacebars.With` we embox the data context. This commit makes
that emboxing happen modulo `safeEquals`. So now if you
{{#with}} over a helper that returns an object, any time
that helper gets invalidated we re-run the computations in the block.
Fixes #2046 (though notably that example mutates the data context
from within a helper, which could lead to other types of unintended
behavior; it's probably in this particular example -- the data context
just gets added properties)
This commit is contained in:
@@ -712,3 +712,9 @@ Hi there!
|
||||
{{bar}}
|
||||
--}}
|
||||
</template>
|
||||
|
||||
<template name="spacebars_test_with_mutated_data_context">
|
||||
{{#with foo}}
|
||||
{{value}}
|
||||
{{/with}}
|
||||
</template>
|
||||
|
||||
@@ -1877,7 +1877,7 @@ Tinytest.add(
|
||||
}
|
||||
);
|
||||
|
||||
Tinytest.add("spacebars - templates - UI.toHTML", function (test) {
|
||||
Tinytest.add("spacebars - template - UI.toHTML", function (test) {
|
||||
// run once, verifying that autoruns are stopped
|
||||
var once = function (tmplToRender, tmplForHelper, helper, val) {
|
||||
var count = 0;
|
||||
@@ -1919,3 +1919,24 @@ Tinytest.add(
|
||||
test.equal(canonicalizeHtml(div.innerHTML), '');
|
||||
}
|
||||
);
|
||||
|
||||
// Originally reported at https://github.com/meteor/meteor/issues/2046
|
||||
Tinytest.add(
|
||||
"spacebars - template - {{#with}} with mutated data context",
|
||||
function (test) {
|
||||
var tmpl = Template.spacebars_test_with_mutated_data_context;
|
||||
var foo = {value: 0};
|
||||
var dep = new Deps.Dependency;
|
||||
tmpl.foo = function () {
|
||||
dep.depend();
|
||||
return foo;
|
||||
};
|
||||
|
||||
var div = renderToDiv(tmpl);
|
||||
test.equal(canonicalizeHtml(div.innerHTML), '0');
|
||||
|
||||
foo.value = 1;
|
||||
dep.changed();
|
||||
Deps.flush();
|
||||
test.equal(canonicalizeHtml(div.innerHTML), '1');
|
||||
});
|
||||
|
||||
@@ -216,7 +216,7 @@ Spacebars.dot = function (value, id1/*, id2, ...*/) {
|
||||
Spacebars.With = function (argFunc, contentBlock, elseContentBlock) {
|
||||
return UI.Component.extend({
|
||||
init: function () {
|
||||
this.v = UI.emboxValue(argFunc);
|
||||
this.v = UI.emboxValue(argFunc, UI.safeEquals);
|
||||
},
|
||||
render: function () {
|
||||
return UI.If(this.v, UI.With(this.v, contentBlock), elseContentBlock);
|
||||
|
||||
@@ -38,7 +38,7 @@ UI.Unless = function (argFunc, contentBlock, elseContentBlock) {
|
||||
// (Because then, they may be equal references to an object that was mutated,
|
||||
// and we'll never know. We save only a reference to the old object; we don't
|
||||
// do any deep-copying or diffing.)
|
||||
var safeEquals = function (a, b) {
|
||||
UI.safeEquals = function (a, b) {
|
||||
if (a !== b)
|
||||
return false;
|
||||
else
|
||||
@@ -67,7 +67,7 @@ UI.With = function (argFunc, contentBlock) {
|
||||
};
|
||||
|
||||
block.init = function () {
|
||||
this.data = UI.emboxValue(argFunc, safeEquals);
|
||||
this.data = UI.emboxValue(argFunc, UI.safeEquals);
|
||||
};
|
||||
|
||||
block.materialized = function () {
|
||||
|
||||
Reference in New Issue
Block a user