Add support for block hashes and clean up mustache/program code
This commit is contained in:
+44
-45
@@ -139,6 +139,12 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
|
||||
this.pushParams(params);
|
||||
|
||||
if(mustache.hash) {
|
||||
this.hash(mustache.hash);
|
||||
} else {
|
||||
this.opcode('push', '{}');
|
||||
}
|
||||
|
||||
// ID lookup is now on the stack
|
||||
this.ID(mustache.id);
|
||||
|
||||
@@ -485,69 +491,62 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
},
|
||||
|
||||
invokeMustache: function(paramSize, original) {
|
||||
var params = ["context"], fn, slot;
|
||||
|
||||
fn = this.popStack();
|
||||
|
||||
var hash = this.popStack();
|
||||
|
||||
for(var i=0; i<paramSize; i++) {
|
||||
params.push(this.popStack());
|
||||
}
|
||||
|
||||
this.register('tmp1', '{hash: ' + hash + '}');
|
||||
|
||||
if(this.data) {
|
||||
this.source.push('tmp1.data = data');
|
||||
}
|
||||
|
||||
params.push('tmp1');
|
||||
|
||||
var paramString = params.join(", ");
|
||||
var helperMissing = ["context"].concat(this.quotedString(original)).concat(params.slice(1));
|
||||
|
||||
slot = this.nextStack();
|
||||
|
||||
if(paramSize === 0) {
|
||||
// TODO: This case is not listed in the mustache spec. Is it important?
|
||||
this.source.push("if(typeof " + fn + " === 'function') { " + slot + " = " + fn + ".call(" + paramString + "); } else { " + slot + " = " + fn + "; }");
|
||||
} else {
|
||||
this.source.push("if(typeof " + fn + " === 'function') { " + slot + " = " + fn + ".call(" + paramString + "); } else { " + slot + " = helpers.helperMissing.call(" + helperMissing + ") }");
|
||||
}
|
||||
this.populateParams(paramSize, this.quotedString(original), "{}", null, function(nextStack, helperMissingString, id) {
|
||||
this.source.push("else if(" + id + "=== undefined) { " + nextStack + " = helpers.helperMissing.call(" + helperMissingString + "); }");
|
||||
this.source.push("else { " + nextStack + " = " + id + "; }");
|
||||
});
|
||||
},
|
||||
|
||||
invokeProgram: function(guid, paramSize) {
|
||||
var inverse = this.programExpression(this.inverse);
|
||||
var mainProgram = this.programExpression(guid);
|
||||
|
||||
var fn = this.popStack();
|
||||
var id = fn;
|
||||
this.populateParams(paramSize, null, mainProgram, inverse, function(nextStack, helperMissingString, id) {
|
||||
this.source.push("else { " + nextStack + " = helpers.blockHelperMissing.call(" + helperMissingString + "); }");
|
||||
});
|
||||
},
|
||||
|
||||
var params = ["context"];
|
||||
var blockMissingParams = ["context", id];
|
||||
populateParams: function(paramSize, helperId, program, inverse, fn) {
|
||||
var id = this.popStack(), nextStack;
|
||||
var params = [];
|
||||
|
||||
var hash = this.popStack();
|
||||
|
||||
for(var i=0; i<paramSize; i++) {
|
||||
var param = this.popStack();
|
||||
params.push(param);
|
||||
blockMissingParams.push(param);
|
||||
}
|
||||
|
||||
var mainProgram = this.programExpression(guid);
|
||||
this.register('tmp1', program);
|
||||
this.source.push('tmp1.hash = ' + hash + ';');
|
||||
|
||||
params.push(mainProgram, inverse);
|
||||
blockMissingParams.push(mainProgram, inverse);
|
||||
if(inverse) {
|
||||
this.source.push('tmp1.fn = tmp1;');
|
||||
this.source.push('tmp1.inverse = ' + inverse + ';');
|
||||
}
|
||||
|
||||
if(this.data) {
|
||||
this.register('tmp1', '{data: data}');
|
||||
params.push("tmp1");
|
||||
|
||||
params.push("tmp1");
|
||||
blockMissingParams.push("tmp1");
|
||||
this.source.push('tmp1.data = data;');
|
||||
}
|
||||
|
||||
var nextStack = this.nextStack();
|
||||
params.push('tmp1');
|
||||
|
||||
this.source.push("if(typeof " + id + " === 'function') { " + nextStack + " = " + id + ".call(" + params.join(", ") + "); }");
|
||||
this.source.push("else { " + nextStack + " = helpers.blockHelperMissing.call(" + blockMissingParams.join(", ") + "); }");
|
||||
// TODO: This is legacy behavior. Deprecate and remove.
|
||||
if(inverse) {
|
||||
params.push(inverse);
|
||||
}
|
||||
|
||||
this.populateCall(params, id, helperId || id, fn);
|
||||
},
|
||||
|
||||
populateCall: function(params, id, helperId, fn) {
|
||||
var paramString = ["context"].concat(params).join(", ");
|
||||
var helperMissingString = ["context"].concat(helperId).concat(params).join(", ");
|
||||
|
||||
nextStack = this.nextStack();
|
||||
|
||||
this.source.push("if(typeof " + id + " === 'function') { " + nextStack + " = " + id + ".call(" + paramString + "); }");
|
||||
fn.call(this, nextStack, helperMissingString, id);
|
||||
},
|
||||
|
||||
invokeInverse: function(guid) {
|
||||
|
||||
+15
-6
@@ -576,12 +576,12 @@ test("passing in data to a compiled function that expects data - works with bloc
|
||||
equals("happy world?", result);
|
||||
});
|
||||
|
||||
test("passing in data to a compiled function that expects data - works with block helpers that use ..", function() {
|
||||
test("passing in data to a compiled function that expects data - data is passed to with block helpers where children use ..", function() {
|
||||
var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", true);
|
||||
|
||||
var helpers = {
|
||||
hello: function(fn, inverse, options) {
|
||||
return options.data.accessData + " " + fn({exclaim: "?"});
|
||||
hello: function(fn, inverse) {
|
||||
return fn.data.accessData + " " + fn({exclaim: "?"});
|
||||
},
|
||||
world: function(thing, options) {
|
||||
return options.data.adjective + " " + thing + (this.exclaim || "");
|
||||
@@ -684,6 +684,15 @@ test("helpers can take an optional hash", function() {
|
||||
equals(result, "GOODBYE CRUEL WORLD");
|
||||
});
|
||||
|
||||
// test("helpers can take an optional hash", function() {
|
||||
// var template = Handlebars.compile('{{#goodbye cruel="CRUEL"}}world{{/goodbye}}')
|
||||
// });
|
||||
test("block helpers can take an optional hash", function() {
|
||||
var template = Handlebars.compile('{{#goodbye cruel="CRUEL"}}world{{/goodbye}}');
|
||||
|
||||
var helpers = {
|
||||
goodbye: function(options) {
|
||||
return "GOODBYE " + options.hash.cruel + " " + options.fn(this);
|
||||
}
|
||||
};
|
||||
|
||||
var result = template({}, helpers);
|
||||
equals(result, "GOODBYE CRUEL world");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user