Fix missing parameters for pathed mustaches

Fixes #658
This commit is contained in:
kpdecker
2014-01-17 22:56:40 -06:00
parent d4cfe90959
commit 33921beaa0
4 changed files with 37 additions and 7 deletions
+5 -5
View File
@@ -83,14 +83,14 @@ var AST = {
var id = this.id = rawParams[0]; var id = this.id = rawParams[0];
var params = this.params = rawParams.slice(1); var params = this.params = rawParams.slice(1);
// a mustache is an eligible helper if:
// * its id is simple (a single part, not `this` or `..`)
var eligibleHelper = this.eligibleHelper = id.isSimple;
// a mustache is definitely a helper if: // a mustache is definitely a helper if:
// * it is an eligible helper, and // * it is an eligible helper, and
// * it has at least one parameter or hash segment // * it has at least one parameter or hash segment
this.isHelper = eligibleHelper && (params.length || hash); this.isHelper = params.length || hash;
// a mustache is an eligible helper if:
// * its id is simple (a single part, not `this` or `..`)
this.eligibleHelper = this.isHelper || id.isSimple;
// if a mustache is an eligible helper but not a definite // if a mustache is an eligible helper but not a definite
// helper, it is ambiguous, and will be resolved in a later // helper, it is ambiguous, and will be resolved in a later
+3 -1
View File
@@ -265,13 +265,15 @@ Compiler.prototype = {
helperSexpr: function(sexpr, program, inverse) { helperSexpr: function(sexpr, program, inverse) {
var params = this.setupFullMustacheParams(sexpr, program, inverse), var params = this.setupFullMustacheParams(sexpr, program, inverse),
name = sexpr.id.parts[0]; id = sexpr.id,
name = id.parts[0];
if (this.options.knownHelpers[name]) { if (this.options.knownHelpers[name]) {
this.opcode('invokeKnownHelper', params.length, name); this.opcode('invokeKnownHelper', params.length, name);
} else if (this.options.knownHelpersOnly) { } else if (this.options.knownHelpersOnly) {
throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr); throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
} else { } else {
this.ID(id);
this.opcode('invokeHelper', params.length, name, sexpr.isRoot); this.opcode('invokeHelper', params.length, name, sexpr.isRoot);
} }
}, },
@@ -503,8 +503,8 @@ JavaScriptCompiler.prototype = {
this.context.aliases.helperMissing = 'helpers.helperMissing'; this.context.aliases.helperMissing = 'helpers.helperMissing';
this.useRegister('helper'); this.useRegister('helper');
var nonHelper = this.popStack();
var helper = this.setupHelper(paramSize, name); var helper = this.setupHelper(paramSize, name);
var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
var lookup = 'helper = ' + helper.name + ' || ' + nonHelper + ' || helperMissing'; var lookup = 'helper = ' + helper.name + ' || ' + nonHelper + ' || helperMissing';
if (helper.paramsInit) { if (helper.paramsInit) {
+28
View File
@@ -97,6 +97,18 @@ describe("basic context", function() {
frank: "Frank"}, frank: "Frank"},
"Frank", "functions are called with context arguments"); "Frank", "functions are called with context arguments");
}); });
it("pathed functions with context argument", function() {
shouldCompileTo("{{bar.awesome frank}}",
{bar: {awesome: function(context) { return context; }},
frank: "Frank"},
"Frank", "functions are called with context arguments");
});
it("depthed functions with context argument", function() {
shouldCompileTo("{{#with frank}}{{../awesome .}}{{/with}}",
{awesome: function(context) { return context; },
frank: "Frank"},
"Frank", "functions are called with context arguments");
});
it("block functions with context argument", function() { it("block functions with context argument", function() {
shouldCompileTo("{{#awesome 1}}inner {{.}}{{/awesome}}", shouldCompileTo("{{#awesome 1}}inner {{.}}{{/awesome}}",
@@ -104,11 +116,27 @@ describe("basic context", function() {
"inner 1", "block functions are called with context and options"); "inner 1", "block functions are called with context and options");
}); });
it("depthed block functions with context argument", function() {
shouldCompileTo("{{#with value}}{{#../awesome 1}}inner {{.}}{{/../awesome}}{{/with}}",
{value: true, awesome: function(context, options) { return options.fn(context); }},
"inner 1", "block functions are called with context and options");
});
it("block functions without context argument", function() { it("block functions without context argument", function() {
shouldCompileTo("{{#awesome}}inner{{/awesome}}", shouldCompileTo("{{#awesome}}inner{{/awesome}}",
{awesome: function(options) { return options.fn(this); }}, {awesome: function(options) { return options.fn(this); }},
"inner", "block functions are called with options"); "inner", "block functions are called with options");
}); });
it("pathed block functions without context argument", function() {
shouldCompileTo("{{#foo.awesome}}inner{{/foo.awesome}}",
{foo: {awesome: function(options) { return this; }}},
"inner", "block functions are called with options");
});
it("depthed block functions without context argument", function() {
shouldCompileTo("{{#with value}}{{#../awesome}}inner{{/../awesome}}{{/with}}",
{value: true, awesome: function(options) { return this; }},
"inner", "block functions are called with options");
});
it("paths with hyphens", function() { it("paths with hyphens", function() {