diff options
author | kpdecker <kpdecker@gmail.com> | 2014-11-08 18:53:43 -0600 |
---|---|---|
committer | kpdecker <kpdecker@gmail.com> | 2014-11-08 18:53:43 -0600 |
commit | ac208b1bcd5f5661a4eabaeba1b6ef0c8767bad0 (patch) | |
tree | 9174a2e3a04484d119b18735fdfaf02b8ccf617e /lib/handlebars/compiler/javascript-compiler.js | |
parent | 8dfeabdd16ddbd940e17b053a5eddc36a7e26ee8 (diff) | |
download | handlebars.js-ac208b1bcd5f5661a4eabaeba1b6ef0c8767bad0.zip handlebars.js-ac208b1bcd5f5661a4eabaeba1b6ef0c8767bad0.tar.gz handlebars.js-ac208b1bcd5f5661a4eabaeba1b6ef0c8767bad0.tar.bz2 |
Only provide aliases for multiple use calls
Fixes #903
Diffstat (limited to 'lib/handlebars/compiler/javascript-compiler.js')
-rw-r--r-- | lib/handlebars/compiler/javascript-compiler.js | 65 |
1 files changed, 39 insertions, 26 deletions
diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js index 869a672..70af132 100644 --- a/lib/handlebars/compiler/javascript-compiler.js +++ b/lib/handlebars/compiler/javascript-compiler.js @@ -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() { @@ -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; } } @@ -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] @@ -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(); @@ -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), '}']); }, @@ -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] @@ -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] @@ -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)); }, @@ -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(); @@ -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))' ]); }, @@ -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); |