diff options
author | Kevin Decker <kpdecker@gmail.com> | 2014-08-13 21:14:32 -0500 |
---|---|---|
committer | Kevin Decker <kpdecker@gmail.com> | 2014-08-13 21:14:32 -0500 |
commit | d95725d5fd57636078583791705cfa814bdf2258 (patch) | |
tree | 364862d90bc601284d35f5c19e8fed1abad7e4f4 /lib/handlebars/compiler/javascript-compiler.js | |
parent | 867322adf28a2babfa22c46558d388091b5756e8 (diff) | |
parent | c98613b711a70a82a960c20c00d8d92d5eed1024 (diff) | |
download | handlebars.js-d95725d5fd57636078583791705cfa814bdf2258.zip handlebars.js-d95725d5fd57636078583791705cfa814bdf2258.tar.gz handlebars.js-d95725d5fd57636078583791705cfa814bdf2258.tar.bz2 |
Merge pull request #819 from wycats/compat-mode
Implement recursive field lookup
Diffstat (limited to 'lib/handlebars/compiler/javascript-compiler.js')
-rw-r--r-- | lib/handlebars/compiler/javascript-compiler.js | 66 |
1 files changed, 45 insertions, 21 deletions
diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js index c92cf58..b9b858d 100644 --- a/lib/handlebars/compiler/javascript-compiler.js +++ b/lib/handlebars/compiler/javascript-compiler.js @@ -17,6 +17,11 @@ JavaScriptCompiler.prototype = { return parent + "['" + name + "']"; } }, + depthedLookup: function(name) { + this.aliases.lookup = 'this.lookup'; + + return 'lookup(depths, "' + name + '")'; + }, compilerInfo: function() { var revision = COMPILER_REVISION, @@ -69,6 +74,8 @@ JavaScriptCompiler.prototype = { this.compileChildren(environment, options); + this.useDepths = this.useDepths || environment.depths.list.length || this.options.compat; + var opcodes = environment.opcodes, opcode, i, @@ -115,6 +122,9 @@ JavaScriptCompiler.prototype = { if (this.options.data) { ret.useData = true; } + if (this.useDepths) { + ret.depths = true; + } if (!asObject) { ret.compiler = JSON.stringify(ret.compiler); @@ -151,8 +161,8 @@ JavaScriptCompiler.prototype = { var params = ["depth0", "helpers", "partials", "data"]; - for(var i=0, l=this.environment.depths.list.length; i<l; i++) { - params.push("depth" + this.environment.depths.list[i]); + if (this.useDepths) { + params.push('depths'); } // Perform a second pass over the output to merge content when possible @@ -230,7 +240,7 @@ JavaScriptCompiler.prototype = { blockValue: function(name) { this.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; - var params = ["depth0"]; + var params = [this.contextName(0)]; this.setupParams(name, 0, params); this.replaceStack(function(current) { @@ -249,7 +259,7 @@ JavaScriptCompiler.prototype = { this.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; // We're being a bit cheeky and reusing the options value from the prior exec - var params = ["depth0"]; + var params = [this.contextName(0)]; this.setupParams('', 0, params, true); this.flushInline(); @@ -341,7 +351,7 @@ JavaScriptCompiler.prototype = { // // Pushes the value of the current context onto the stack. pushContext: function() { - this.pushStackLiteral('depth' + this.lastContext); + this.pushStackLiteral(this.contextName(this.lastContext)); }, // [lookupOnContext] @@ -351,15 +361,20 @@ JavaScriptCompiler.prototype = { // // Looks up the value of `name` on the current context and pushes // it onto the stack. - lookupOnContext: function(parts, falsy) { + lookupOnContext: function(parts, falsy, scoped) { /*jshint -W083 */ - this.pushContext(); - if (!parts) { - return; + var i = 0, + len = parts.length; + + if (!scoped && this.isChild && this.options.compat && !this.lastContext) { + // The depthed query is expected to handle the undefined logic for the root level that + // is implemented below, so we evaluate that directly in compat mode + this.pushStackLiteral(this.depthedLookup(parts[i++])); + } else { + this.pushContext(); } - var len = parts.length; - for (var i = 0; i < len; i++) { + for (; i < len; i++) { this.replaceStack(function(current) { var lookup = this.nameLookup(current, parts[i], 'context'); // We want to ensure that zero and false are handled properly for the first element @@ -410,7 +425,7 @@ JavaScriptCompiler.prototype = { resolvePossibleLambda: function() { this.aliases.lambda = 'this.lambda'; - this.push('lambda(' + this.popStack() + ', depth0)'); + this.push('lambda(' + this.popStack() + ', ' + this.contextName(0) + ')'); }, // [pushStringParam] @@ -422,8 +437,7 @@ JavaScriptCompiler.prototype = { // provides the string value of a parameter along with its // depth rather than resolving it immediately. pushStringParam: function(string, type) { - this.pushStackLiteral('depth' + this.lastContext); - + this.pushContext(); this.pushString(type); // If it's a subexpression, the string result @@ -669,6 +683,8 @@ JavaScriptCompiler.prototype = { child.name = 'program' + index; this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); this.context.environments[index] = child; + + this.useDepths = this.useDepths || compiler.useDepths; } else { child.index = index; child.name = 'program' + index; @@ -690,17 +706,17 @@ JavaScriptCompiler.prototype = { } var child = this.environment.children[guid], - depths = child.depths.list, depth; + depths = child.depths.list, + useDepths = this.useDepths, + depth; var programParams = [child.index, 'data']; - for(var i=0, l = depths.length; i<l; i++) { - depth = depths[i]; - - programParams.push('depth' + (depth - 1)); + if (useDepths) { + programParams.push('depths'); } - return (depths.length === 0 ? 'this.program(' : 'this.programWithDepth(') + programParams.join(', ') + ')'; + return 'this.program(' + programParams.join(', ') + ')'; }, useRegister: function(name) { @@ -847,6 +863,14 @@ JavaScriptCompiler.prototype = { } }, + contextName: function(context) { + if (this.useDepths && context) { + return 'depths[' + context + ']'; + } else { + return 'depth' + context; + } + }, + quotedString: function(str) { return '"' + str .replace(/\\/g, '\\\\') @@ -878,7 +902,7 @@ JavaScriptCompiler.prototype = { params: params, paramsInit: paramsInit, name: foundHelper, - callParams: ["depth0"].concat(params).join(", ") + callParams: [this.contextName(0)].concat(params).join(", ") }; }, |