knownHandlers and knownHandlersOnly compile options.

This commit is contained in:
kpdecker
2011-07-31 21:00:44 -05:00
parent 1a88356dc3
commit f53737ef23
2 changed files with 85 additions and 11 deletions
+45 -11
View File
@@ -94,7 +94,24 @@ Handlebars.JavaScriptCompiler = function() {};
compile: function(program, options) {
this.children = [];
this.depths = {list: []};
this.options = options || {};
this.options = options;
// These changes will propagate to the other compiler components
var knownHelpers = this.options.knownHelpers;
this.options.knownHelpers = {
'helperMissing': true,
'blockHelperMissing': true,
'each': true,
'if': true,
'unless': true,
'with': true
};
if (knownHelpers) {
for (var name in knownHelpers) {
this.options.knownHelpers[name] = knownHelpers[name];
}
}
return this.program(program);
},
@@ -475,9 +492,13 @@ Handlebars.JavaScriptCompiler = function() {};
if(name) {
var topStack = this.nextStack();
var toPush;
this.usingKnownHelper = false;
if (isScoped) {
var toPush;
if (!isScoped && this.options.knownHelpers[name]) {
toPush = topStack + " = " + this.nameLookup('helpers', name, 'helper');
this.usingKnownHelper = true;
} else if (isScoped || this.options.knownHelpersOnly) {
toPush = topStack + " = " + this.nameLookup('depth' + this.lastContext, name, 'context');
} else {
toPush = topStack + " = "
@@ -512,10 +533,12 @@ Handlebars.JavaScriptCompiler = function() {};
invokeMustache: function(paramSize, original) {
this.populateParams(paramSize, this.quotedString(original), "{}", null, function(nextStack, helperMissingString, id) {
this.context.aliases.helperMissing = 'helpers.helperMissing';
this.context.aliases.undef = 'void 0';
this.source.push("else if(" + id + "=== undef) { " + nextStack + " = helperMissing.call(" + helperMissingString + "); }");
this.source.push("else { " + nextStack + " = " + id + "; }");
if (!this.usingKnownHelper) {
this.context.aliases.helperMissing = 'helpers.helperMissing';
this.context.aliases.undef = 'void 0';
this.source.push("else if(" + id + "=== undef) { " + nextStack + " = helperMissing.call(" + helperMissingString + "); }");
this.source.push("else { " + nextStack + " = " + id + "; }");
}
});
},
@@ -524,8 +547,10 @@ Handlebars.JavaScriptCompiler = function() {};
var mainProgram = this.programExpression(guid);
this.populateParams(paramSize, null, mainProgram, inverse, function(nextStack, helperMissingString, id) {
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
this.source.push("else { " + nextStack + " = blockHelperMissing.call(" + helperMissingString + "); }");
if (!this.usingKnownHelper) {
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
this.source.push("else { " + nextStack + " = blockHelperMissing.call(" + helperMissingString + "); }");
}
});
},
@@ -571,9 +596,14 @@ Handlebars.JavaScriptCompiler = function() {};
var nextStack = this.nextStack();
this.context.aliases.functionType = '"function"';
this.source.push("if(typeof " + id + " === functionType) { " + nextStack + " = " + id + ".call(" + paramString + "); }");
if (this.usingKnownHelper) {
this.source.push(nextStack + " = " + id + ".call(" + paramString + ");");
} else {
this.context.aliases.functionType = '"function"';
this.source.push("if(typeof " + id + " === functionType) { " + nextStack + " = " + id + ".call(" + paramString + "); }");
}
fn.call(this, nextStack, helperMissingString, id);
this.usingKnownHelper = false;
},
invokePartial: function(context) {
@@ -681,12 +711,16 @@ Handlebars.JavaScriptCompiler = function() {};
})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);
Handlebars.precompile = function(string, options) {
options = options || {};
var ast = Handlebars.parse(string);
var environment = new Handlebars.Compiler().compile(ast, options);
return new Handlebars.JavaScriptCompiler().compile(environment, options);
};
Handlebars.compile = function(string, options) {
options = options || {};
var ast = Handlebars.parse(string);
var environment = new Handlebars.Compiler().compile(ast, options);
var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
+40
View File
@@ -519,6 +519,46 @@ test("if a context is not found, helperMissing is used", function() {
shouldCompileTo(string, context, "Hello <a>world</a>")
});
module("knownHelpers");
test("Known helper should render helper", function() {
var template = CompilerContext.compile("{{hello}}", {knownHelpers: {"hello" : true}})
var result = template({}, {helpers: {hello: function() { return "foo"; }}});
equal(result, "foo", "'foo' should === '" + result);
});
test("Unknown helper in knownHelpers only mode should be passed as undefined", function() {
var template = CompilerContext.compile("{{typeof hello}}", {knownHelpers: {'typeof': true}, knownHelpersOnly: true})
var result = template({}, {helpers: {'typeof': function(arg) { return typeof arg; }, hello: function() { return "foo"; }}});
equal(result, "undefined", "'undefined' should === '" + result);
});
test("Builtin helpers available in knownHelpers only mode", function() {
var template = CompilerContext.compile("{{#unless foo}}bar{{/unless}}", {knownHelpersOnly: true})
var result = template({});
equal(result, "bar", "'bar' should === '" + result);
});
test("Field lookup works in knownHelpers only mode", function() {
var template = CompilerContext.compile("{{foo}}", {knownHelpersOnly: true})
var result = template({foo: 'bar'});
equal(result, "bar", "'bar' should === '" + result);
});
test("Conditional blocks work in knownHelpers only mode", function() {
var template = CompilerContext.compile("{{#foo}}bar{{/foo}}", {knownHelpersOnly: true})
var result = template({foo: 'baz'});
equal(result, "bar", "'bar' should === '" + result);
});
test("Invert blocks work in knownHelpers only mode", function() {
var template = CompilerContext.compile("{{^foo}}bar{{/foo}}", {knownHelpersOnly: true})
var result = template({foo: false});
equal(result, "bar", "'bar' should === '" + result);
});
module("built-in helpers");
test("with", function() {