From 4e8472e9707c18b7bbbd98c08c21308efdadd239 Mon Sep 17 00:00:00 2001 From: David Greenspan Date: Mon, 9 Jun 2014 16:35:24 -0700 Subject: [PATCH] Proper reactivity for calculated templates --- packages/spacebars-compiler/codegen.js | 11 +++-- packages/spacebars-compiler/compile_tests.js | 51 +++++++------------- packages/spacebars-tests/template_tests.js | 2 +- packages/spacebars/spacebars-runtime.js | 22 ++++++--- 4 files changed, 41 insertions(+), 45 deletions(-) diff --git a/packages/spacebars-compiler/codegen.js b/packages/spacebars-compiler/codegen.js index 91f6de7790..8e077c505a 100644 --- a/packages/spacebars-compiler/codegen.js +++ b/packages/spacebars-compiler/codegen.js @@ -97,6 +97,11 @@ _.extend(CodeGen.prototype, { } else { var compCode = self.codeGenPath(path, {lookupTemplate: true}); + if (path.length > 1) { + // capture reactivity + compCode = 'function () { return Spacebars.call(' + compCode + + '); }'; + } var dataCode = self.codeGenInclusionDataFunc(tag.args); var content = (('content' in tag) ? @@ -106,15 +111,13 @@ _.extend(CodeGen.prototype, { var includeArgs = [compCode]; if (content) { - // XXX `null` will be the data arg when we change calling convention - includeArgs.push('null', content); + includeArgs.push(content); if (elseContent) includeArgs.push(elseContent); } var includeCode = - 'Blaze.Isolate(function () { return Spacebars.include2(' + - includeArgs.join(', ') + '); })'; + 'Spacebars.include2(' + includeArgs.join(', ') + ')'; // calling convention compat -- set the data context around the // entire inclusion, so that if the name of the inclusion is diff --git a/packages/spacebars-compiler/compile_tests.js b/packages/spacebars-compiler/compile_tests.js index e6c9d81742..a4aaa24f17 100644 --- a/packages/spacebars-compiler/compile_tests.js +++ b/packages/spacebars-compiler/compile_tests.js @@ -107,12 +107,9 @@ Tinytest.add("spacebars-compiler - compiler output", function (test) { run("{{#foo}}abc{{/foo}}", function() { var self = this; - return Blaze.Isolate(function() { - return Spacebars.include2(Blaze.lookupTemplate("foo", self), - null, - (function() { return "abc"; }) - ); - }); + return Spacebars.include2(Blaze.lookupTemplate("foo", self), (function() { + return "abc"; + })); }); run("{{#if cond}}aaa{{else}}bbb{{/if}}", @@ -145,9 +142,7 @@ Tinytest.add("spacebars-compiler - compiler output", function (test) { return Spacebars.TemplateWith(function() { return Spacebars.call(Blaze.lookup("bar", self)); }, function() { - return Blaze.Isolate(function() { - return Spacebars.include2(Blaze.lookupTemplate("foo", self)); - }); + return Spacebars.include2(Blaze.lookupTemplate("foo", self)); }); }); @@ -159,11 +154,10 @@ Tinytest.add("spacebars-compiler - compiler output", function (test) { x: Spacebars.call(Blaze.lookup("bar", self)) }; }, function() { - return Blaze.Isolate(function() { - return Spacebars.include2(Blaze.lookupTemplate("foo", self)); - }); + return Spacebars.include2(Blaze.lookupTemplate("foo", self)); }); - }); + } + ); run("{{> foo bar.baz}}", function() { @@ -171,9 +165,7 @@ Tinytest.add("spacebars-compiler - compiler output", function (test) { return Spacebars.TemplateWith(function() { return Spacebars.call(Spacebars.dot(Blaze.lookup("bar", self), "baz")); }, function() { - return Blaze.Isolate(function() { - return Spacebars.include2(Blaze.lookupTemplate("foo", self)); - }); + return Spacebars.include2(Blaze.lookupTemplate("foo", self)); }); }); @@ -185,9 +177,7 @@ Tinytest.add("spacebars-compiler - compiler output", function (test) { x: Spacebars.call(Spacebars.dot(Blaze.lookup("bar", self), "baz")) }; }, function() { - return Blaze.Isolate(function() { - return Spacebars.include2(Blaze.lookupTemplate("foo", self)); - }); + return Spacebars.include2(Blaze.lookupTemplate("foo", self)); }); }); @@ -197,11 +187,10 @@ Tinytest.add("spacebars-compiler - compiler output", function (test) { return Spacebars.TemplateWith(function() { return Spacebars.dataMustache(Blaze.lookup("bar", self), Blaze.lookup("baz", self)); }, function() { - return Blaze.Isolate(function() { - return Spacebars.include2(Blaze.lookupTemplate("foo", self)); - }); + return Spacebars.include2(Blaze.lookupTemplate("foo", self)); }); - }); + } + ); run("{{#foo bar baz}}aaa{{/foo}}", function() { @@ -209,11 +198,9 @@ Tinytest.add("spacebars-compiler - compiler output", function (test) { return Spacebars.TemplateWith(function() { return Spacebars.dataMustache(Blaze.lookup("bar", self), Blaze.lookup("baz", self)); }, function() { - return Blaze.Isolate(function() { - return Spacebars.include2(Blaze.lookupTemplate("foo", self), null, (function() { - return "aaa"; - })); - }); + return Spacebars.include2(Blaze.lookupTemplate("foo", self), (function() { + return "aaa"; + })); }); }); @@ -223,11 +210,9 @@ Tinytest.add("spacebars-compiler - compiler output", function (test) { return Spacebars.TemplateWith(function() { return Spacebars.dataMustache(Spacebars.dot(Blaze.lookup("p", self), "q"), Spacebars.dot(Blaze.lookup("r", self), "s")); }, function() { - return Blaze.Isolate(function() { - return Spacebars.include2(Blaze.lookupTemplate("foo", self), null, (function() { - return "aaa"; - })); - }); + return Spacebars.include2(Blaze.lookupTemplate("foo", self), (function() { + return "aaa"; + })); }); }); diff --git a/packages/spacebars-tests/template_tests.js b/packages/spacebars-tests/template_tests.js index b378309658..0a806544c0 100644 --- a/packages/spacebars-tests/template_tests.js +++ b/packages/spacebars-tests/template_tests.js @@ -1149,7 +1149,7 @@ Tinytest.add('spacebars-tests - template_tests - inclusion helpers are isolated' test.throws(function () { Deps.flush({_throwFirstError: true}); - }, /Expected null or template/); + }, /Expected template or null/); }); Tinytest.add('spacebars-tests - template_tests - nully attributes', function (test) { diff --git a/packages/spacebars/spacebars-runtime.js b/packages/spacebars/spacebars-runtime.js index 3eac68c0d1..9ff0b43460 100644 --- a/packages/spacebars/spacebars-runtime.js +++ b/packages/spacebars/spacebars-runtime.js @@ -1,12 +1,20 @@ -Spacebars.include2 = function (templateOrFunction, dataFunc, contentFunc, elseFunc) { - var template = Spacebars.call(templateOrFunction); - if (template === null) - return null; - if (! (template instanceof Blaze.Component)) - throw new Error("Expected template or null, found: " + template); +var tripleEquals = function (a, b) { return a === b; }; - return new template.constructor(dataFunc, contentFunc, elseFunc); +Spacebars.include2 = function (templateOrFunction, contentFunc, elseFunc) { + var templateVar = Blaze.Var(templateOrFunction, tripleEquals); + return Blaze.Isolate(function () { + var template = templateVar.get(); + if (template === null) + return null; + + if (! (template instanceof Blaze.Component)) + throw new Error("Expected template or null, found: " + template); + + // Current calling convention (as of 0.8) means we have to wrap data + // around the whole inclusion, not pass it here (the `null` arg) + return new template.constructor(null, contentFunc, elseFunc); + }); }; // * `templateOrFunction` - template (component) or function returning a template