summaryrefslogtreecommitdiffstats
path: root/lib/handlebars/compiler/javascript-compiler.js
diff options
context:
space:
mode:
authorKevin Decker <kpdecker@gmail.com>2014-08-13 21:14:32 -0500
committerKevin Decker <kpdecker@gmail.com>2014-08-13 21:14:32 -0500
commitd95725d5fd57636078583791705cfa814bdf2258 (patch)
tree364862d90bc601284d35f5c19e8fed1abad7e4f4 /lib/handlebars/compiler/javascript-compiler.js
parent867322adf28a2babfa22c46558d388091b5756e8 (diff)
parentc98613b711a70a82a960c20c00d8d92d5eed1024 (diff)
downloadhandlebars.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.js66
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(", ")
};
},