From 2b319bef2faf0b52fd48bb56881051186603e9b1 Mon Sep 17 00:00:00 2001 From: tomhuda Date: Mon, 14 Feb 2011 16:05:01 -0800 Subject: [PATCH 1/2] Make the function passed to a block helper have an identical signature to top-level template methods --- lib/handlebars/vm.js | 9 ++++++--- spec/qunit_spec.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/handlebars/vm.js b/lib/handlebars/vm.js index 5dca8479..3f44a36f 100644 --- a/lib/handlebars/vm.js +++ b/lib/handlebars/vm.js @@ -627,13 +627,16 @@ Handlebars.JavaScriptCompiler = function() {}; Handlebars.VM = { programWithDepth: function(fn) { var args = Array.prototype.slice.call(arguments, 1); - return function(context) { + return function(context, helpers, partials, data) { + args[0] = helpers || args[0]; + args[1] = partials || args[1]; + args[2] = data || args[2]; return fn.apply(this, [context].concat(args)); }; }, program: function(fn, helpers, partials, data) { - return function(context) { - return fn(context, helpers, partials, data); + return function(context, h2, p2, d2) { + return fn(context, h2 || helpers, p2 || partials, d2 || data); }; }, noop: function() { return ""; }, diff --git a/spec/qunit_spec.js b/spec/qunit_spec.js index 7dcac84e..7ec0cf2e 100644 --- a/spec/qunit_spec.js +++ b/spec/qunit_spec.js @@ -599,5 +599,36 @@ test("passing in data to a compiled function that expects data - works with bloc equals("#win happy world?", result); }); +test("you can override inherited data when invoking a helper", function() { + var template = Handlebars.compile("{{#hello}}{{world zomg}}{{/hello}}", true); + + var helpers = { + hello: function(fn) { + return fn({exclaim: "?", zomg: "world"}, null, null, {adjective: "sad"}); + }, + world: function(thing, data) { + return data.adjective + " " + thing + (this.exclaim || ""); + } + }; + + var result = template({exclaim: true, zomg: "planet"}, helpers, null, {adjective: "happy"}); + equals("sad world?", result); +}); +test("you can override inherited data when invoking a helper with depth", function() { + var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", true); + + var helpers = { + hello: function(fn) { + return fn({exclaim: "?"}, null, null, {adjective: "sad"}); + }, + world: function(thing, data) { + return data.adjective + " " + thing + (this.exclaim || ""); + } + }; + + var result = template({exclaim: true, zomg: "world"}, helpers, null, {adjective: "happy"}); + equals("sad world?", result); +}); + From 32d7e52182414ae48ff82d4456d982049f0203a5 Mon Sep 17 00:00:00 2001 From: tomhuda Date: Fri, 25 Feb 2011 23:01:11 -0800 Subject: [PATCH 2/2] Helpers take precedence over context properties with the same name. This is useful in scenarios where your context object is inherited from another system (such as a framework or JSON API) that may contain properties that conflict with helpers you explicitly define. --- lib/handlebars/vm.js | 20 +++++++++++++------- spec/qunit_spec.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/lib/handlebars/vm.js b/lib/handlebars/vm.js index 3f44a36f..1c2b4eef 100644 --- a/lib/handlebars/vm.js +++ b/lib/handlebars/vm.js @@ -8,7 +8,7 @@ Handlebars.JavaScriptCompiler = function() {}; Compiler.OPCODE_MAP = { appendContent: 1, getContext: 2, - lookupWithFallback: 3, + lookupWithHelpers: 3, lookup: 4, append: 5, invokeMustache: 6, @@ -25,7 +25,7 @@ Handlebars.JavaScriptCompiler = function() {}; Compiler.MULTI_PARAM_OPCODES = { appendContent: 1, getContext: 1, - lookupWithFallback: 1, + lookupWithHelpers: 1, lookup: 1, invokeMustache: 2, pushString: 1, @@ -201,7 +201,7 @@ Handlebars.JavaScriptCompiler = function() {}; this.opcode('getContext', id.depth); - this.opcode('lookupWithFallback', id.parts[0] || null); + this.opcode('lookupWithHelpers', id.parts[0] || null); for(var i=1, l=id.parts.length; i