summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkpdecker <kpdecker@gmail.com>2014-11-27 09:11:03 -0600
committerkpdecker <kpdecker@gmail.com>2014-11-27 09:11:03 -0600
commitf990cf006422fbcbbae7d8a8a866831e58300ea4 (patch)
tree5511ccfde2f01f1018f6a73576ef393590cf5d5a
parent1124908d2a0d36493912eb2ce062545b1b5e5445 (diff)
downloadhandlebars.js-f990cf006422fbcbbae7d8a8a866831e58300ea4.zip
handlebars.js-f990cf006422fbcbbae7d8a8a866831e58300ea4.tar.gz
handlebars.js-f990cf006422fbcbbae7d8a8a866831e58300ea4.tar.bz2
Treat partial exec in a manner closer to helpers
This helps unify the code handling and will also be needed to support string/id tracking on partials.
-rw-r--r--lib/handlebars/compiler/code-gen.js5
-rw-r--r--lib/handlebars/compiler/compiler.js25
-rw-r--r--lib/handlebars/compiler/javascript-compiler.js41
-rw-r--r--lib/handlebars/runtime.js27
4 files changed, 50 insertions, 48 deletions
diff --git a/lib/handlebars/compiler/code-gen.js b/lib/handlebars/compiler/code-gen.js
index a7c1659..0fddb7c 100644
--- a/lib/handlebars/compiler/code-gen.js
+++ b/lib/handlebars/compiler/code-gen.js
@@ -113,7 +113,10 @@ CodeGen.prototype = {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
- pairs.push([this.quotedString(key), ':', castChunk(obj[key], this)]);
+ var value = castChunk(obj[key], this);
+ if (value !== 'undefined') {
+ pairs.push([this.quotedString(key), ':', value]);
+ }
}
}
diff --git a/lib/handlebars/compiler/compiler.js b/lib/handlebars/compiler/compiler.js
index e73ce37..df5a10f 100644
--- a/lib/handlebars/compiler/compiler.js
+++ b/lib/handlebars/compiler/compiler.js
@@ -166,24 +166,15 @@ Compiler.prototype = {
var partialName = partial.sexpr.path.original;
this.usePartial = true;
- if (partial.sexpr.hash) {
- this.accept(partial.sexpr.hash);
- } else {
- this.opcode('pushLiteral', partial, 'undefined');
- }
-
var params = partial.sexpr.params;
- if (params.length) {
- if (params.length > 1) {
- throw new Exception('Unsupported number of partial arguments: ' + params.length, partial);
- }
-
- this.pushParam(params[0]);
- } else {
- this.opcode('getContext', partial, 0);
- this.opcode('pushContext', partial);
+ if (params.length > 1) {
+ throw new Exception('Unsupported number of partial arguments: ' + params.length, partial);
+ } else if (!params.length) {
+ params.push({type: 'PathExpression', parts: [], depth: 0});
}
+ this.setupFullMustacheParams(partial.sexpr, undefined, undefined, true);
+
var indent = partial.indent || '';
if (this.options.preventIndent && indent) {
this.opcode('appendContent', partial, indent);
@@ -391,7 +382,7 @@ Compiler.prototype = {
}
},
- setupFullMustacheParams: function(sexpr, program, inverse) {
+ setupFullMustacheParams: function(sexpr, program, inverse, omitEmpty) {
var params = sexpr.params;
this.pushParams(params);
@@ -401,7 +392,7 @@ Compiler.prototype = {
if (sexpr.hash) {
this.accept(sexpr.hash);
} else {
- this.opcode('emptyHash', sexpr);
+ this.opcode('emptyHash', sexpr, omitEmpty);
}
return params;
diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js
index cde2ab5..db19778 100644
--- a/lib/handlebars/compiler/javascript-compiler.js
+++ b/lib/handlebars/compiler/javascript-compiler.js
@@ -275,7 +275,7 @@ JavaScriptCompiler.prototype = {
blockValue: function(name) {
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
params = [this.contextName(0)];
- this.setupParams(name, 0, params);
+ this.setupHelperArgs(name, 0, params);
var blockName = this.popStack();
params.splice(1, 0, blockName);
@@ -293,7 +293,7 @@ JavaScriptCompiler.prototype = {
// We're being a bit cheeky and reusing the options value from the prior exec
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
params = [this.contextName(0)];
- this.setupParams('', 0, params, true);
+ this.setupHelperArgs('', 0, params, true);
this.flushInline();
@@ -469,9 +469,7 @@ JavaScriptCompiler.prototype = {
}
},
- emptyHash: function() {
- this.pushStackLiteral('{}');
-
+ emptyHash: function(omitEmpty) {
if (this.trackIds) {
this.push('{}'); // hashIds
}
@@ -479,6 +477,7 @@ JavaScriptCompiler.prototype = {
this.push('{}'); // hashContexts
this.push('{}'); // hashTypes
}
+ this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
},
pushHash: function() {
if (this.hash) {
@@ -611,16 +610,22 @@ JavaScriptCompiler.prototype = {
// This operation pops off a context, invokes a partial with that context,
// and pushes the result of the invocation back.
invokePartial: function(name, indent) {
- var params = [this.nameLookup('partials', name, 'partial'), "'" + indent + "'", "'" + name + "'", this.popStack(), this.popStack(), "helpers", "partials"];
+ var params = [],
+ options = this.setupParams(name, 1, params, false);
- if (this.options.data) {
- params.push("data");
- } else if (this.options.compat) {
- params.push('undefined');
+ if (indent) {
+ options.indent = JSON.stringify(indent);
}
+ options.helpers = 'helpers';
+ options.partials = 'partials';
+
+ params.unshift(this.nameLookup('partials', name, 'partial'));
+
if (this.options.compat) {
- params.push('depths');
+ options.depths = 'depths';
}
+ options = this.objectLiteral(options);
+ params.push(options);
this.push(this.source.functionCall('this.invokePartial', '', params));
},
@@ -881,7 +886,7 @@ JavaScriptCompiler.prototype = {
setupHelper: function(paramSize, name, blockHelper) {
var params = [],
- paramsInit = this.setupParams(name, paramSize, params, blockHelper);
+ paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
var foundHelper = this.nameLookup('helpers', name, 'helper');
return {
@@ -892,8 +897,8 @@ JavaScriptCompiler.prototype = {
};
},
- setupParams: function(helper, paramSize, params, useRegister) {
- var options = {}, contexts = [], types = [], ids = [], param, inverse, program;
+ setupParams: function(helper, paramSize, params) {
+ var options = {}, contexts = [], types = [], ids = [], param;
options.name = this.quotedString(helper);
options.hash = this.popStack();
@@ -906,8 +911,8 @@ JavaScriptCompiler.prototype = {
options.hashContexts = this.popStack();
}
- inverse = this.popStack();
- program = this.popStack();
+ var inverse = this.popStack(),
+ program = this.popStack();
// Avoid setting fn and inverse if neither are set. This allows
// helpers to do a check for `if (options.fn)`
@@ -943,7 +948,11 @@ JavaScriptCompiler.prototype = {
if (this.options.data) {
options.data = "data";
}
+ return options;
+ },
+ setupHelperArgs: function(helper, paramSize, params, useRegister) {
+ var options = this.setupParams(helper, paramSize, params, true);
options = this.objectLiteral(options);
if (useRegister) {
this.useRegister('options');
diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js
index 05759cb..455dd33 100644
--- a/lib/handlebars/runtime.js
+++ b/lib/handlebars/runtime.js
@@ -35,36 +35,35 @@ export function template(templateSpec, env) {
// for external users to override these as psuedo-supported APIs.
env.VM.checkRevision(templateSpec.compiler);
- var invokePartialWrapper = function(partial, indent, name, context, hash, helpers, partials, data, depths) {
- if (hash) {
- context = Utils.extend({}, context, hash);
+ var invokePartialWrapper = function(partial, context, options) {
+ if (options.hash) {
+ context = Utils.extend({}, context, options.hash);
}
if (!partial) {
- partial = partials[name];
+ partial = options.partials[options.name];
}
- var result = env.VM.invokePartial.call(this, partial, name, context, helpers, partials, data, depths);
+ var result = env.VM.invokePartial.call(this, partial, context, options);
if (result == null && env.compile) {
- var options = { helpers: helpers, partials: partials, data: data, depths: depths };
- partials[name] = env.compile(partial, templateSpec.compilerOptions, env);
- result = partials[name](context, options);
+ options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
+ result = options.partials[options.name](context, options);
}
if (result != null) {
- if (indent) {
+ if (options.indent) {
var lines = result.split('\n');
for (var i = 0, l = lines.length; i < l; i++) {
if (!lines[i] && i + 1 === l) {
break;
}
- lines[i] = indent + lines[i];
+ lines[i] = options.indent + lines[i];
}
result = lines.join('\n');
}
return result;
} else {
- throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
+ throw new Exception("The partial " + options.name + " could not be compiled when running in runtime-only mode");
}
};
@@ -172,11 +171,11 @@ export function program(container, i, fn, data, depths) {
return prog;
}
-export function invokePartial(partial, name, context, helpers, partials, data, depths) {
- var options = { partial: true, helpers: helpers, partials: partials, data: data, depths: depths };
+export function invokePartial(partial, context, options) {
+ options.partial = true;
if(partial === undefined) {
- throw new Exception("The partial " + name + " could not be found");
+ throw new Exception("The partial " + options.name + " could not be found");
} else if(partial instanceof Function) {
return partial(context, options);
}