diff options
author | kpdecker <kpdecker@gmail.com> | 2014-12-26 00:31:57 -0600 |
---|---|---|
committer | kpdecker <kpdecker@gmail.com> | 2014-12-26 00:31:57 -0600 |
commit | 396795c983273bb5ca4dc67ddc74eb12f00bf110 (patch) | |
tree | 8fa69873ed195fc7b0aa1c909373fa7ccac6785a /lib/handlebars/compiler/compiler.js | |
parent | 9e907e67854ea1ae208fe061452a9c9e2ce9468b (diff) | |
download | handlebars.js-396795c983273bb5ca4dc67ddc74eb12f00bf110.zip handlebars.js-396795c983273bb5ca4dc67ddc74eb12f00bf110.tar.gz handlebars.js-396795c983273bb5ca4dc67ddc74eb12f00bf110.tar.bz2 |
Implement block parameters
Fixes #907
Diffstat (limited to 'lib/handlebars/compiler/compiler.js')
-rw-r--r-- | lib/handlebars/compiler/compiler.js | 65 |
1 files changed, 49 insertions, 16 deletions
diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js index 7be96cb..13143cc 100644 --- a/lib/handlebars/compiler/compiler.js +++ b/lib/handlebars/compiler/compiler.js @@ -51,6 +51,8 @@ Compiler.prototype = { this.stringParams = options.stringParams; this.trackIds = options.trackIds; + options.blockParams = options.blockParams || []; + // These changes will propagate to the other compiler components var knownHelpers = options.knownHelpers; options.knownHelpers = { @@ -92,14 +94,17 @@ Compiler.prototype = { }, Program: function(program) { - var body = program.body; + this.options.blockParams.unshift(program.blockParams); + var body = program.body; for(var i=0, l=body.length; i<l; i++) { this.accept(body[i]); } - this.isSimple = l === 1; + this.options.blockParams.shift(); + this.isSimple = l === 1; + this.blockParams = program.blockParams ? program.blockParams.length : 0; return this; }, @@ -231,15 +236,20 @@ Compiler.prototype = { this.addDepth(path.depth); this.opcode('getContext', path.depth); - var name = path.parts[0]; - if (!name) { + var name = path.parts[0], + scoped = AST.helpers.scopedId(path), + blockParamId = !path.depth && !scoped && this.blockParamIndex(name); + + if (blockParamId) { + this.opcode('lookupBlockParam', blockParamId, path.parts); + } else if (!name) { // Context reference, i.e. `{{foo .}}` or `{{foo ..}}` this.opcode('pushContext'); } else if (path.data) { this.options.data = true; this.opcode('lookupData', path.depth, path.parts); } else { - this.opcode('lookupOnContext', path.parts, path.falsy, AST.helpers.scopedId(path)); + this.opcode('lookupOnContext', path.parts, path.falsy, scoped); } }, @@ -283,14 +293,18 @@ Compiler.prototype = { }, classifySexpr: function(sexpr) { + var isSimple = AST.helpers.simpleId(sexpr.path); + + var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]); + // a mustache is an eligible helper if: // * its id is simple (a single part, not `this` or `..`) - var isHelper = AST.helpers.helperExpression(sexpr); + var isHelper = !isBlockParam && AST.helpers.helperExpression(sexpr); // if a mustache is an eligible helper but not a definite // helper, it is ambiguous, and will be resolved in a later // pass or at runtime. - var isEligible = isHelper || AST.helpers.simpleId(sexpr.path); + var isEligible = !isBlockParam && (isHelper || isSimple); var options = this.options; @@ -345,14 +359,23 @@ Compiler.prototype = { } } else { if (this.trackIds) { - value = val.original || value; - if (value.replace) { - value = value - .replace(/^\.\//g, '') - .replace(/^\.$/g, ''); + var blockParamIndex; + if (val.parts && !AST.helpers.scopedId(val) && !val.depth) { + blockParamIndex = this.blockParamIndex(val.parts[0]); + } + if (blockParamIndex) { + var blockParamChild = val.parts.slice(1).join('.'); + this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild); + } else { + value = val.original || value; + if (value.replace) { + value = value + .replace(/^\.\//g, '') + .replace(/^\.$/g, ''); + } + + this.opcode('pushId', val.type, value); } - - this.opcode('pushId', val.type, value); } this.accept(val); } @@ -372,6 +395,16 @@ Compiler.prototype = { } return params; + }, + + blockParamIndex: function(name) { + for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) { + var blockParams = this.options.blockParams[depth], + param = blockParams && blockParams.indexOf(name); + if (blockParams && param >= 0) { + return [depth, param]; + } + } } }; @@ -429,11 +462,11 @@ export function compile(input, options, env) { } return compiled._setup(options); }; - ret._child = function(i, data, depths) { + ret._child = function(i, data, blockParams, depths) { if (!compiled) { compiled = compileInput(); } - return compiled._child(i, data, depths); + return compiled._child(i, data, blockParams, depths); }; return ret; } |