diff options
-rw-r--r-- | lib/handlebars/ast.js | 2 | ||||
-rw-r--r-- | lib/handlebars/compiler.js | 19 | ||||
-rw-r--r-- | spec/qunit_spec.js | 44 |
3 files changed, 58 insertions, 7 deletions
diff --git a/lib/handlebars/ast.js b/lib/handlebars/ast.js index d7cc150..6c3711b 100644 --- a/lib/handlebars/ast.js +++ b/lib/handlebars/ast.js @@ -68,7 +68,7 @@ var Handlebars = require("handlebars"); var part = parts[i]; if(part === "..") { depth++; } - else if(part === "." || part === "this") { continue; } + else if(part === "." || part === "this") { this.isScoped = true; } else { dig.push(part); } } diff --git a/lib/handlebars/compiler.js b/lib/handlebars/compiler.js index b8a9e04..843e0b9 100644 --- a/lib/handlebars/compiler.js +++ b/lib/handlebars/compiler.js @@ -26,7 +26,7 @@ Handlebars.JavaScriptCompiler = function() {}; Compiler.MULTI_PARAM_OPCODES = { appendContent: 1, getContext: 1, - lookupWithHelpers: 1, + lookupWithHelpers: 2, lookup: 1, invokeMustache: 2, pushString: 1, @@ -214,7 +214,7 @@ Handlebars.JavaScriptCompiler = function() {}; this.opcode('getContext', id.depth); - this.opcode('lookupWithHelpers', id.parts[0] || null); + this.opcode('lookupWithHelpers', id.parts[0] || null, id.isScoped || false); for(var i=1, l=id.parts.length; i<l; i++) { this.opcode('lookup', id.parts[i]); @@ -479,15 +479,22 @@ Handlebars.JavaScriptCompiler = function() {}; } }, - lookupWithHelpers: function(name) { + lookupWithHelpers: function(name, isScoped) { if(name) { var topStack = this.nextStack(); - var toPush = "if('" + name + "' in helpers) { " + topStack + + var lookupScoped = topStack + " = " + this.nameLookup('currentContext', name, 'context'), + toPush; + + if (isScoped) { + toPush = lookupScoped; + } else { + toPush = "if('" + name + "' in helpers) { " + topStack + " = " + this.nameLookup('helpers', name, 'helper') + - "; } else { " + topStack + " = " + - this.nameLookup('currentContext', name, 'context') + + "; } else { " + + lookupScoped + "; }"; + } this.source.push(toPush); } else { diff --git a/spec/qunit_spec.js b/spec/qunit_spec.js index bdec68b..3b08bc5 100644 --- a/spec/qunit_spec.js +++ b/spec/qunit_spec.js @@ -683,6 +683,50 @@ test("helpers take precedence over same-named context properties", function() { equals(result, "GOODBYE cruel WORLD", "Helper executed"); }); +test("Scoped names take precedence over helpers", function() { + var template = Handlebars.compile("{{this.goodbye}} {{cruel world}} {{cruel this.goodbye}}"); + + var helpers = { + goodbye: function() { + return this.goodbye.toUpperCase(); + } + }; + + var context = { + cruel: function(world) { + return "cruel " + world.toUpperCase(); + }, + + goodbye: "goodbye", + world: "world" + }; + + var result = template(context, {helpers: helpers}); + equals(result, "goodbye cruel WORLD cruel GOODBYE", "Helper not executed"); +}); + +test("Scoped names take precedence over block helpers", function() { + var template = Handlebars.compile("{{#goodbye}} {{cruel world}}{{/goodbye}} {{this.goodbye}}"); + + var helpers = { + goodbye: function(fn) { + return this.goodbye.toUpperCase() + fn(this); + } + }; + + var context = { + cruel: function(world) { + return "cruel " + world.toUpperCase(); + }, + + goodbye: "goodbye", + world: "world" + }; + + var result = template(context, {helpers: helpers}); + equals(result, "GOODBYE cruel WORLD goodbye", "Helper executed"); +}); + test("helpers can take an optional hash", function() { var template = Handlebars.compile('{{goodbye cruel="CRUEL" world="WORLD" times=12}}'); |