diff options
author | Kevin Decker <kpdecker@gmail.com> | 2014-02-08 20:01:52 -0600 |
---|---|---|
committer | Kevin Decker <kpdecker@gmail.com> | 2014-02-08 20:01:52 -0600 |
commit | bc8f6792e8ab8eb5028b667065e410bd510479f5 (patch) | |
tree | c38023e9cd894844ad07b3116048123f8a151ce5 /lib/handlebars/compiler/javascript-compiler.js | |
parent | b0e72985239504e7d70643bfd767cf14fd14920b (diff) | |
parent | 2812fe27758e38dbefad8b02c61ffb19aabf2410 (diff) | |
download | handlebars.js-bc8f6792e8ab8eb5028b667065e410bd510479f5.zip handlebars.js-bc8f6792e8ab8eb5028b667065e410bd510479f5.tar.gz handlebars.js-bc8f6792e8ab8eb5028b667065e410bd510479f5.tar.bz2 |
Merge pull request #729 from wycats/precompile-literal
Convert template spec to object literal
Diffstat (limited to 'lib/handlebars/compiler/javascript-compiler.js')
-rw-r--r-- | lib/handlebars/compiler/javascript-compiler.js | 112 |
1 files changed, 55 insertions, 57 deletions
diff --git a/lib/handlebars/compiler/javascript-compiler.js b/lib/handlebars/compiler/javascript-compiler.js index 55edb9a..8222506 100644 --- a/lib/handlebars/compiler/javascript-compiler.js +++ b/lib/handlebars/compiler/javascript-compiler.js @@ -33,7 +33,7 @@ JavaScriptCompiler.prototype = { compilerInfo: function() { var revision = COMPILER_REVISION, versions = REVISION_CHANGES[revision]; - return "this.compilerInfo = ["+revision+",'"+versions+"'];\n"; + return [revision, versions]; }, appendToBuffer: function(string) { @@ -60,6 +60,7 @@ JavaScriptCompiler.prototype = { this.options = options || {}; this.stringParams = this.options.stringParams; this.trackIds = this.options.trackIds; + this.precompile = !asObject; log('debug', this.environment.disassemble() + "\n\n"); @@ -67,14 +68,14 @@ JavaScriptCompiler.prototype = { this.isChild = !!context; this.context = context || { programs: [], - environments: [], - aliases: { } + environments: [] }; this.preamble(); this.stackSlot = 0; this.stackVars = []; + this.aliases = {}; this.registers = { list: [] }; this.hashes = []; this.compileStack = []; @@ -108,22 +109,38 @@ JavaScriptCompiler.prototype = { throw new Exception('Compile completed with content left on stack'); } - return this.createFunctionContext(asObject); - }, + var fn = this.createFunctionContext(asObject); + if (!this.isChild) { + var ret = { + compiler: this.compilerInfo(), + main: fn + }; + this.context.programs.map(function(program, index) { + if (program) { + ret[index] = program; + } + }); - preamble: function() { - var out = []; + if (this.environment.usePartial) { + ret.usePartial = true; + } + if (this.options.data) { + ret.useData = true; + } - if (!this.isChild) { - var namespace = this.namespace; + if (!asObject) { + ret.compiler = JSON.stringify(ret.compiler); + ret = this.objectLiteral(ret); + } - var copies = "helpers = this.merge(helpers, " + namespace + ".helpers);"; - if (this.environment.usePartial) { copies = copies + " partials = this.merge(partials, " + namespace + ".partials);"; } - if (this.options.data) { copies = copies + " data = this.initData(depth0, data);"; } - out.push(copies); + return ret; } else { - out.push(''); + return fn; } + }, + + preamble: function() { + var out = []; if (!this.environment.isSimple) { out.push(", buffer = " + this.initializeBuffer()); @@ -141,32 +158,25 @@ JavaScriptCompiler.prototype = { var locals = this.stackVars.concat(this.registers.list); if(locals.length > 0) { - this.source[1] = this.source[1] + ", " + locals.join(", "); + this.source[0] += ", " + locals.join(", "); } // Generate minimizer alias mappings - if (!this.isChild) { - for (var alias in this.context.aliases) { - if (this.context.aliases.hasOwnProperty(alias)) { - this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; - } + for (var alias in this.aliases) { + if (this.aliases.hasOwnProperty(alias)) { + this.source[0] += ', ' + alias + '=' + this.aliases[alias]; } } - if (this.source[1]) { - this.source[1] = "var " + this.source[1].substring(2) + ";"; - } - - // Merge children - if (!this.isChild) { - this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; + if (this.source[0]) { + this.source[0] = "var " + this.source[0].substring(2) + ";"; } if (!this.environment.isSimple) { this.pushSource("return buffer;"); } - var params = this.isChild ? ["depth0", "data"] : [this.namespace, "depth0", "helpers", "partials", "data"]; + 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]); @@ -175,18 +185,12 @@ JavaScriptCompiler.prototype = { // Perform a second pass over the output to merge content when possible var source = this.mergeSource(); - if (!this.isChild) { - source = this.compilerInfo()+source; - } - if (asObject) { params.push(source); return Function.apply(this, params); } else { - var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}'; - log('debug', functionSource + "\n\n"); - return functionSource; + return 'function(' + params.join(',') + ') {\n ' + source + '}'; } }, mergeSource: function() { @@ -223,7 +227,7 @@ JavaScriptCompiler.prototype = { // replace it on the stack with the result of properly // invoking blockHelperMissing. blockValue: function(name) { - this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; + this.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; var params = ["depth0"]; this.setupParams(name, 0, params); @@ -241,7 +245,7 @@ JavaScriptCompiler.prototype = { // On stack, after, if no lastHelper: same as [blockValue] // On stack, after, if lastHelper: value ambiguousBlockValue: function() { - this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; + this.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; // We're being a bit cheeky and reusing the options value from the prior exec var params = ["depth0"]; @@ -313,7 +317,7 @@ JavaScriptCompiler.prototype = { // // Escape `value` and append it to the buffer appendEscaped: function() { - this.context.aliases.escapeExpression = 'this.escapeExpression'; + this.aliases.escapeExpression = 'this.escapeExpression'; this.pushSource(this.appendToBuffer("escapeExpression(" + this.popStack() + ")")); }, @@ -360,7 +364,7 @@ JavaScriptCompiler.prototype = { // If the `value` is a lambda, replace it on the stack by // the return value of the lambda resolvePossibleLambda: function() { - this.context.aliases.functionType = '"function"'; + this.aliases.functionType = '"function"'; this.replaceStack(function(current) { return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current; @@ -505,7 +509,7 @@ JavaScriptCompiler.prototype = { // // If the helper is not found, `helperMissing` is called. invokeHelper: function(paramSize, name, isRoot) { - this.context.aliases.helperMissing = 'helpers.helperMissing'; + this.aliases.helperMissing = 'helpers.helperMissing'; this.useRegister('helper'); var nonHelper = this.popStack(); @@ -551,7 +555,7 @@ JavaScriptCompiler.prototype = { // and can be avoided by passing the `knownHelpers` and // `knownHelpersOnly` flags at compile-time. invokeAmbiguous: function(name, helperCall) { - this.context.aliases.functionType = '"function"'; + this.aliases.functionType = '"function"'; this.useRegister('helper'); this.emptyHash(); @@ -580,8 +584,7 @@ JavaScriptCompiler.prototype = { params.push("data"); } - this.context.aliases.self = "this"; - this.push("self.invokePartial(" + params.join(", ") + ")"); + this.push("this.invokePartial(" + params.join(", ") + ")"); }, // [assignToHash] @@ -646,7 +649,7 @@ JavaScriptCompiler.prototype = { index = this.context.programs.length; child.index = index; child.name = 'program' + index; - this.context.programs[index] = compiler.compile(child, options, this.context); + this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); this.context.environments[index] = child; } else { child.index = index; @@ -664,25 +667,22 @@ JavaScriptCompiler.prototype = { }, programExpression: function(guid) { - this.context.aliases.self = "this"; - if(guid == null) { - return "self.noop"; + return 'this.noop'; } var child = this.environment.children[guid], depths = child.depths.list, depth; - var programParams = [child.index, child.name, "data"]; + var programParams = [child.index, 'data']; for(var i=0, l = depths.length; i<l; i++) { depth = depths[i]; - if(depth === 1) { programParams.push("depth0"); } - else { programParams.push("depth" + (depth - 1)); } + programParams.push('depth' + (depth - 1)); } - return (depths.length === 0 ? "self.program(" : "self.programWithDepth(") + programParams.join(", ") + ")"; + return (depths.length === 0 ? 'this.program(' : 'this.programWithDepth(') + programParams.join(', ') + ')'; }, register: function(name, val) { @@ -840,7 +840,7 @@ JavaScriptCompiler.prototype = { .replace(/\u2029/g, '\\u2029') + '"'; }, - setupHash: function(obj) { + objectLiteral: function(obj) { var pairs = []; for (var key in obj) { @@ -886,13 +886,11 @@ JavaScriptCompiler.prototype = { // helpers to do a check for `if (options.fn)` if (program || inverse) { if (!program) { - this.context.aliases.self = "this"; - program = "self.noop"; + program = 'this.noop'; } if (!inverse) { - this.context.aliases.self = "this"; - inverse = "self.noop"; + inverse = 'this.noop'; } options.fn = program; @@ -930,7 +928,7 @@ JavaScriptCompiler.prototype = { // the params and contexts arguments are passed in arrays // to fill in setupParams: function(helperName, paramSize, params, useRegister) { - var options = this.setupHash(this.setupOptions(helperName, paramSize, params)); + var options = this.objectLiteral(this.setupOptions(helperName, paramSize, params)); if (useRegister) { this.useRegister('options'); |