Skip to content

Commit

Permalink
Only provide aliases for multiple use calls
Browse files Browse the repository at this point in the history
Fixes #903
  • Loading branch information
kpdecker committed Nov 9, 2014
1 parent 8dfeabd commit ac208b1
Showing 1 changed file with 39 additions and 26 deletions.
65 changes: 39 additions & 26 deletions lib/handlebars/compiler/javascript-compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ JavaScriptCompiler.prototype = {
}
},
depthedLookup: function(name) {
this.aliases.lookup = 'this.lookup';

return ['lookup(depths, "', name, '")'];
return [this.aliasable('this.lookup'), '(depths, "', name, '")'];
},

compilerInfo: function() {
Expand Down Expand Up @@ -171,9 +169,18 @@ JavaScriptCompiler.prototype = {
}

// Generate minimizer alias mappings
//
// When using true SourceNodes, this will update all references to the given alias
// as the source nodes are reused in situ. For the non-source node compilation mode,
// aliases will not be used, but this case is already being run on the client and
// we aren't concern about minimizing the template size.
var aliasCount = 0;
for (var alias in this.aliases) {
if (this.aliases.hasOwnProperty(alias)) {
varDeclarations += ', ' + alias + '=' + this.aliases[alias];
var node = this.aliases[alias];

if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) {
varDeclarations += ', alias' + (++aliasCount) + '=' + alias;
node.children[0] = 'alias' + aliasCount;
}
}

Expand Down Expand Up @@ -264,15 +271,14 @@ JavaScriptCompiler.prototype = {
// replace it on the stack with the result of properly
// invoking blockHelperMissing.
blockValue: function(name) {
this.aliases.blockHelperMissing = 'helpers.blockHelperMissing';

var params = [this.contextName(0)];
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
params = [this.contextName(0)];
this.setupParams(name, 0, params);

var blockName = this.popStack();
params.splice(1, 0, blockName);

this.push(this.source.functionCall('blockHelperMissing', 'call', params));
this.push(this.source.functionCall(blockHelperMissing, 'call', params));
},

// [ambiguousBlockValue]
Expand All @@ -282,10 +288,9 @@ JavaScriptCompiler.prototype = {
// On stack, after, if no lastHelper: same as [blockValue]
// On stack, after, if lastHelper: value
ambiguousBlockValue: function() {
this.aliases.blockHelperMissing = 'helpers.blockHelperMissing';

// We're being a bit cheeky and reusing the options value from the prior exec
var params = [this.contextName(0)];
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
params = [this.contextName(0)];
this.setupParams('', 0, params, true);

this.flushInline();
Expand All @@ -295,7 +300,7 @@ JavaScriptCompiler.prototype = {

this.pushSource([
'if (!', this.lastHelper, ') { ',
current, ' = ', this.source.functionCall('blockHelperMissing', 'call', params),
current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params),
'}']);
},

Expand Down Expand Up @@ -347,9 +352,8 @@ JavaScriptCompiler.prototype = {
//
// Escape `value` and append it to the buffer
appendEscaped: function() {
this.aliases.escapeExpression = 'this.escapeExpression';

this.pushSource(this.appendToBuffer(['escapeExpression(', this.popStack(), ')']));
this.pushSource(this.appendToBuffer(
[this.aliasable('this.escapeExpression'), '(', this.popStack(), ')']));
},

// [getContext]
Expand Down Expand Up @@ -438,9 +442,7 @@ JavaScriptCompiler.prototype = {
// If the `value` is a lambda, replace it on the stack by
// the return value of the lambda
resolvePossibleLambda: function() {
this.aliases.lambda = 'this.lambda';

this.push(['lambda(', this.popStack(), ', ', this.contextName(0), ')']);
this.push([this.aliasable('this.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']);
},

// [pushStringParam]
Expand Down Expand Up @@ -546,15 +548,13 @@ JavaScriptCompiler.prototype = {
//
// If the helper is not found, `helperMissing` is called.
invokeHelper: function(paramSize, name, isSimple) {
this.aliases.helperMissing = 'helpers.helperMissing';

var nonHelper = this.popStack();
var helper = this.setupHelper(paramSize, name);
var simple = isSimple ? [helper.name, ' || '] : '';

this.push(
this.source.functionCall(
['('].concat(simple, nonHelper, ' || ', 'helperMissing)'),
['('].concat(simple, nonHelper, ' || ', this.aliasable('helpers.helperMissing'), ')'),
'call',
helper.callParams));
},
Expand Down Expand Up @@ -584,8 +584,6 @@ JavaScriptCompiler.prototype = {
// and can be avoided by passing the `knownHelpers` and
// `knownHelpersOnly` flags at compile-time.
invokeAmbiguous: function(name, helperCall) {
this.aliases.functionType = '"function"';
this.aliases.helperMissing = 'helpers.helperMissing';
this.useRegister('helper');

var nonHelper = this.popStack();
Expand All @@ -596,9 +594,10 @@ JavaScriptCompiler.prototype = {
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');

this.push([
'((helper = (helper = ', helperName, ' || ', nonHelper, ') != null ? helper : helperMissing',
'((helper = (helper = ', helperName, ' || ', nonHelper, ') != null ? helper : ',
this.aliasable('helpers.helperMissing'),
(helper.paramsInit ? ['),(', helper.paramsInit] : []), '),',
'(typeof helper === functionType ? ',
'(typeof helper === ', this.aliasable('"function"'), ' ? ',
this.source.functionCall('helper','call', helper.callParams), ' : helper))'
]);
},
Expand Down Expand Up @@ -865,6 +864,20 @@ JavaScriptCompiler.prototype = {
return this.source.objectLiteral(obj);
},

aliasable: function(name) {
var ret = this.aliases[name];
if (ret) {
ret.referenceCount++;
return ret;
}

ret = this.aliases[name] = this.source.wrap(name);
ret.aliasable = true;
ret.referenceCount = 1;

return ret;
},

setupHelper: function(paramSize, name, blockHelper) {
var params = [],
paramsInit = this.setupParams(name, paramSize, params, blockHelper);
Expand Down

0 comments on commit ac208b1

Please sign in to comment.