diff options
author | Yehuda Katz <wycats@gmail.com> | 2012-05-28 00:15:52 -0700 |
---|---|---|
committer | Yehuda Katz <wycats@gmail.com> | 2012-05-28 00:15:52 -0700 |
commit | 8786a6c6e23ec628300ab405fdec71a888eb39e6 (patch) | |
tree | c27d5b11d72b50e39415c63d829da4f4dc86a7d5 /lib/handlebars/compiler/compiler.js | |
parent | 246325085faec21087ac177acfd9ce1492c88030 (diff) | |
download | handlebars.js-8786a6c6e23ec628300ab405fdec71a888eb39e6.zip handlebars.js-8786a6c6e23ec628300ab405fdec71a888eb39e6.tar.gz handlebars.js-8786a6c6e23ec628300ab405fdec71a888eb39e6.tar.bz2 |
Start doing earlier work on helpers
Diffstat (limited to 'lib/handlebars/compiler/compiler.js')
-rw-r--r-- | lib/handlebars/compiler/compiler.js | 155 |
1 files changed, 127 insertions, 28 deletions
diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js index 994192b..c36f7e1 100644 --- a/lib/handlebars/compiler/compiler.js +++ b/lib/handlebars/compiler/compiler.js @@ -25,7 +25,10 @@ Handlebars.JavaScriptCompiler = function() {}; pushStringParam: 16, knownHelper: 17, pushContext: 18, - lookupOnContext: 19 + lookupOnContext: 19, + resolvePossibleLambda: 20, + invokeHelper: 21, + pushLiteral: 22 }; Compiler.MULTI_PARAM_OPCODES = { @@ -44,7 +47,10 @@ Handlebars.JavaScriptCompiler = function() {}; pushStringParam: 1, knownHelper: 1, pushContext: 0, - lookupOnContext: 1 + lookupOnContext: 1, + resolvePossibleLambda: 0, + invokeHelper: 2, + pushLiteral: 1 }; Compiler.DISASSEMBLE_MAP = {}; @@ -231,9 +237,18 @@ Handlebars.JavaScriptCompiler = function() {}; }, mustache: function(mustache) { - var params = this.setupStackForMustache(mustache); + var id = mustache.id; + + if (!mustache.eligibleHelper) { + this.simpleMustache(mustache); + } else if (mustache.isHelper) { + this.helperMustache(mustache); + } else { + var params = this.setupStackForMustache(mustache), + name = id.parts[0]; - this.opcode('invokeMustache', params.length, mustache.id.original); + this.opcode('invokeMustache', params.length, mustache.id.original); + } if(mustache.escaped && !this.options.noEscape) { this.opcode('appendEscaped'); @@ -242,9 +257,32 @@ Handlebars.JavaScriptCompiler = function() {}; } }, - ID: function(id) { + simpleMustache: function(mustache) { + var id = mustache.id; + this.addDepth(id.depth); + this.opcode('getContext', id.depth); + + if (id.parts.length) { + this.opcode('lookupOnContext', id.parts[0]); + for(var i=1, l=id.parts.length; i<l; i++) { + this.opcode('lookup', id.parts[i]); + } + } else { + this.opcode('pushContext'); + } + this.opcode('resolvePossibleLambda'); + }, + helperMustache: function(mustache) { + var params = this.setupMustacheParams(mustache), + name = mustache.id.parts[0]; + + this.opcode('invokeHelper', params.length, name); + }, + + ID: function(id) { + this.addDepth(id.depth); this.opcode('getContext', id.depth); var name = id.parts[0]; @@ -282,25 +320,6 @@ Handlebars.JavaScriptCompiler = function() {}; comment: function() {}, // HELPERS - pushParams: function(params) { - var i = params.length, param; - - while(i--) { - param = params[i]; - - if(this.options.stringParams) { - if(param.depth) { - this.addDepth(param.depth); - } - - this.opcode('getContext', param.depth || 0); - this.opcode('pushStringParam', param.string); - } else { - this[param.type](param); - } - } - }, - opcode: function(name, val1, val2, val3) { this.opcodes.push(Compiler.OPCODE_MAP[name]); if(val1 !== undefined) { this.opcodes.push(val1); } @@ -323,17 +342,41 @@ Handlebars.JavaScriptCompiler = function() {}; } }, - setupStackForMustache: function(mustache) { - var params = mustache.params; + pushParams: function(params) { + var i = params.length, param; + + while(i--) { + param = params[i]; + if(this.options.stringParams) { + if(param.depth) { + this.addDepth(param.depth); + } + + this.opcode('getContext', param.depth || 0); + this.opcode('pushStringParam', param.string); + } else { + this[param.type](param); + } + } + }, + + setupMustacheParams: function(mustache) { + var params = mustache.params; this.pushParams(params); if(mustache.hash) { this.hash(mustache.hash); } else { - this.opcode('push', '{}'); + this.opcode('pushLiteral', '{}'); } + return params; + }, + + setupStackForMustache: function(mustache) { + var params = this.setupMustacheParams(mustache); + this.ID(mustache.id); return params; @@ -547,13 +590,21 @@ Handlebars.JavaScriptCompiler = function() {}; }, lookupOnContext: function(name) { - this.pushStackLiteral(this.nameLookup('depth' + this.lastContext, name, 'context')); + this.pushStack(this.nameLookup('depth' + this.lastContext, name, 'context')); }, pushContext: function() { this.pushStackLiteral('depth' + this.lastContext); }, + resolvePossibleLambda: function() { + this.context.aliases.functionType = '"function"'; + + this.replaceStack(function(current) { + return "typeof " + current + " === functionType ? " + current + "() : " + current; + }); + }, + lookupWithHelpers: function(name) { this.register('foundHelper', this.nameLookup('helpers', name, 'helper')); this.pushStack("foundHelper || " + this.nameLookup('depth' + this.lastContext, name, 'context')); @@ -578,6 +629,10 @@ Handlebars.JavaScriptCompiler = function() {}; this.pushStack(name); }, + pushLiteral: function(value) { + this.pushStackLiteral(value); + }, + // The rules for mustaches are: // // If the first parameter resolves to a function, call the function with the remaining parameters @@ -619,6 +674,50 @@ Handlebars.JavaScriptCompiler = function() {}; }); }, + invokeHelper: function(paramSize, name) { + this.context.aliases.helperMissing = 'helpers.helperMissing'; + + var params = [], contexts = []; + this.setupParams(paramSize, params, contexts); + this.register('foundHelper', this.nameLookup('helpers', name, 'helper')); + + var main = ["depth0"].concat(params).join(", "); + var helperMissing = ["depth0", this.quotedString(name)].concat(params).join(", "); + this.pushStack("foundHelper ? foundHelper.call(" + main + ") " + + ": helperMissing.call(" + helperMissing + ")"); + + //this.replaceStack(function(current) { + //}); + }, + + // the params and contexts arguments are passed in arrays + // to fill in + setupParams: function(paramSize, params) { + var options = [], contexts = [], param; + + options.push("hash:" + this.popStack()); + + for(var i=0; i<paramSize; i++) { + param = this.popStack(); + params.push(param); + + if(this.options.stringParams) { + contexts.push(this.popStack()); + } + } + + if (this.options.stringParams) { + options.push("contexts:[" + contexts.join(",") + "]"); + } + + if(this.options.data) { + options.push("data:data"); + } + + params.push("{" + options.join(",") + "}"); + return params.join(", "); + }, + populateParams: function(paramSize, helperId, options, resolveLambdas, callback) { var id = this.popStack(), nextStack; var params = [], contexts = [], param, paramString, stringOptions; |