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.
This commit is contained in:
@@ -113,7 +113,10 @@ CodeGen.prototype = {
|
|||||||
|
|
||||||
for (var key in obj) {
|
for (var key in obj) {
|
||||||
if (obj.hasOwnProperty(key)) {
|
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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -166,24 +166,15 @@ Compiler.prototype = {
|
|||||||
var partialName = partial.sexpr.path.original;
|
var partialName = partial.sexpr.path.original;
|
||||||
this.usePartial = true;
|
this.usePartial = true;
|
||||||
|
|
||||||
if (partial.sexpr.hash) {
|
|
||||||
this.accept(partial.sexpr.hash);
|
|
||||||
} else {
|
|
||||||
this.opcode('pushLiteral', partial, 'undefined');
|
|
||||||
}
|
|
||||||
|
|
||||||
var params = partial.sexpr.params;
|
var params = partial.sexpr.params;
|
||||||
if (params.length) {
|
if (params.length > 1) {
|
||||||
if (params.length > 1) {
|
throw new Exception('Unsupported number of partial arguments: ' + params.length, partial);
|
||||||
throw new Exception('Unsupported number of partial arguments: ' + params.length, partial);
|
} else if (!params.length) {
|
||||||
}
|
params.push({type: 'PathExpression', parts: [], depth: 0});
|
||||||
|
|
||||||
this.pushParam(params[0]);
|
|
||||||
} else {
|
|
||||||
this.opcode('getContext', partial, 0);
|
|
||||||
this.opcode('pushContext', partial);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setupFullMustacheParams(partial.sexpr, undefined, undefined, true);
|
||||||
|
|
||||||
var indent = partial.indent || '';
|
var indent = partial.indent || '';
|
||||||
if (this.options.preventIndent && indent) {
|
if (this.options.preventIndent && indent) {
|
||||||
this.opcode('appendContent', partial, 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;
|
var params = sexpr.params;
|
||||||
this.pushParams(params);
|
this.pushParams(params);
|
||||||
|
|
||||||
@@ -401,7 +392,7 @@ Compiler.prototype = {
|
|||||||
if (sexpr.hash) {
|
if (sexpr.hash) {
|
||||||
this.accept(sexpr.hash);
|
this.accept(sexpr.hash);
|
||||||
} else {
|
} else {
|
||||||
this.opcode('emptyHash', sexpr);
|
this.opcode('emptyHash', sexpr, omitEmpty);
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ JavaScriptCompiler.prototype = {
|
|||||||
blockValue: function(name) {
|
blockValue: function(name) {
|
||||||
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
|
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
|
||||||
params = [this.contextName(0)];
|
params = [this.contextName(0)];
|
||||||
this.setupParams(name, 0, params);
|
this.setupHelperArgs(name, 0, params);
|
||||||
|
|
||||||
var blockName = this.popStack();
|
var blockName = this.popStack();
|
||||||
params.splice(1, 0, blockName);
|
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
|
// We're being a bit cheeky and reusing the options value from the prior exec
|
||||||
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
|
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
|
||||||
params = [this.contextName(0)];
|
params = [this.contextName(0)];
|
||||||
this.setupParams('', 0, params, true);
|
this.setupHelperArgs('', 0, params, true);
|
||||||
|
|
||||||
this.flushInline();
|
this.flushInline();
|
||||||
|
|
||||||
@@ -469,9 +469,7 @@ JavaScriptCompiler.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
emptyHash: function() {
|
emptyHash: function(omitEmpty) {
|
||||||
this.pushStackLiteral('{}');
|
|
||||||
|
|
||||||
if (this.trackIds) {
|
if (this.trackIds) {
|
||||||
this.push('{}'); // hashIds
|
this.push('{}'); // hashIds
|
||||||
}
|
}
|
||||||
@@ -479,6 +477,7 @@ JavaScriptCompiler.prototype = {
|
|||||||
this.push('{}'); // hashContexts
|
this.push('{}'); // hashContexts
|
||||||
this.push('{}'); // hashTypes
|
this.push('{}'); // hashTypes
|
||||||
}
|
}
|
||||||
|
this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
|
||||||
},
|
},
|
||||||
pushHash: function() {
|
pushHash: function() {
|
||||||
if (this.hash) {
|
if (this.hash) {
|
||||||
@@ -611,16 +610,22 @@ JavaScriptCompiler.prototype = {
|
|||||||
// This operation pops off a context, invokes a partial with that context,
|
// This operation pops off a context, invokes a partial with that context,
|
||||||
// and pushes the result of the invocation back.
|
// and pushes the result of the invocation back.
|
||||||
invokePartial: function(name, indent) {
|
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) {
|
if (indent) {
|
||||||
params.push("data");
|
options.indent = JSON.stringify(indent);
|
||||||
} else if (this.options.compat) {
|
|
||||||
params.push('undefined');
|
|
||||||
}
|
}
|
||||||
|
options.helpers = 'helpers';
|
||||||
|
options.partials = 'partials';
|
||||||
|
|
||||||
|
params.unshift(this.nameLookup('partials', name, 'partial'));
|
||||||
|
|
||||||
if (this.options.compat) {
|
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));
|
this.push(this.source.functionCall('this.invokePartial', '', params));
|
||||||
},
|
},
|
||||||
@@ -881,7 +886,7 @@ JavaScriptCompiler.prototype = {
|
|||||||
|
|
||||||
setupHelper: function(paramSize, name, blockHelper) {
|
setupHelper: function(paramSize, name, blockHelper) {
|
||||||
var params = [],
|
var params = [],
|
||||||
paramsInit = this.setupParams(name, paramSize, params, blockHelper);
|
paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
|
||||||
var foundHelper = this.nameLookup('helpers', name, 'helper');
|
var foundHelper = this.nameLookup('helpers', name, 'helper');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -892,8 +897,8 @@ JavaScriptCompiler.prototype = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
setupParams: function(helper, paramSize, params, useRegister) {
|
setupParams: function(helper, paramSize, params) {
|
||||||
var options = {}, contexts = [], types = [], ids = [], param, inverse, program;
|
var options = {}, contexts = [], types = [], ids = [], param;
|
||||||
|
|
||||||
options.name = this.quotedString(helper);
|
options.name = this.quotedString(helper);
|
||||||
options.hash = this.popStack();
|
options.hash = this.popStack();
|
||||||
@@ -906,8 +911,8 @@ JavaScriptCompiler.prototype = {
|
|||||||
options.hashContexts = this.popStack();
|
options.hashContexts = this.popStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
inverse = this.popStack();
|
var inverse = this.popStack(),
|
||||||
program = this.popStack();
|
program = this.popStack();
|
||||||
|
|
||||||
// Avoid setting fn and inverse if neither are set. This allows
|
// Avoid setting fn and inverse if neither are set. This allows
|
||||||
// helpers to do a check for `if (options.fn)`
|
// helpers to do a check for `if (options.fn)`
|
||||||
@@ -943,7 +948,11 @@ JavaScriptCompiler.prototype = {
|
|||||||
if (this.options.data) {
|
if (this.options.data) {
|
||||||
options.data = "data";
|
options.data = "data";
|
||||||
}
|
}
|
||||||
|
return options;
|
||||||
|
},
|
||||||
|
|
||||||
|
setupHelperArgs: function(helper, paramSize, params, useRegister) {
|
||||||
|
var options = this.setupParams(helper, paramSize, params, true);
|
||||||
options = this.objectLiteral(options);
|
options = this.objectLiteral(options);
|
||||||
if (useRegister) {
|
if (useRegister) {
|
||||||
this.useRegister('options');
|
this.useRegister('options');
|
||||||
|
|||||||
+13
-14
@@ -35,36 +35,35 @@ export function template(templateSpec, env) {
|
|||||||
// for external users to override these as psuedo-supported APIs.
|
// for external users to override these as psuedo-supported APIs.
|
||||||
env.VM.checkRevision(templateSpec.compiler);
|
env.VM.checkRevision(templateSpec.compiler);
|
||||||
|
|
||||||
var invokePartialWrapper = function(partial, indent, name, context, hash, helpers, partials, data, depths) {
|
var invokePartialWrapper = function(partial, context, options) {
|
||||||
if (hash) {
|
if (options.hash) {
|
||||||
context = Utils.extend({}, context, hash);
|
context = Utils.extend({}, context, options.hash);
|
||||||
}
|
}
|
||||||
if (!partial) {
|
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) {
|
if (result == null && env.compile) {
|
||||||
var options = { helpers: helpers, partials: partials, data: data, depths: depths };
|
options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
|
||||||
partials[name] = env.compile(partial, templateSpec.compilerOptions, env);
|
result = options.partials[options.name](context, options);
|
||||||
result = partials[name](context, options);
|
|
||||||
}
|
}
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
if (indent) {
|
if (options.indent) {
|
||||||
var lines = result.split('\n');
|
var lines = result.split('\n');
|
||||||
for (var i = 0, l = lines.length; i < l; i++) {
|
for (var i = 0, l = lines.length; i < l; i++) {
|
||||||
if (!lines[i] && i + 1 === l) {
|
if (!lines[i] && i + 1 === l) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lines[i] = indent + lines[i];
|
lines[i] = options.indent + lines[i];
|
||||||
}
|
}
|
||||||
result = lines.join('\n');
|
result = lines.join('\n');
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} 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;
|
return prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function invokePartial(partial, name, context, helpers, partials, data, depths) {
|
export function invokePartial(partial, context, options) {
|
||||||
var options = { partial: true, helpers: helpers, partials: partials, data: data, depths: depths };
|
options.partial = true;
|
||||||
|
|
||||||
if(partial === undefined) {
|
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) {
|
} else if(partial instanceof Function) {
|
||||||
return partial(context, options);
|
return partial(context, options);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user