diff --git a/lib/handlebars/vm.js b/lib/handlebars/vm.js index b21bad9b..cf821bcd 100644 --- a/lib/handlebars/vm.js +++ b/lib/handlebars/vm.js @@ -1,5 +1,8 @@ var Handlebars = {}; +Handlebars.Utils = require("handlebars/utils").Utils; Handlebars.parse = require("handlebars/compiler").Handlebars.parse; +Handlebars.logger = require("handlebars/compiler").Handlebars.logger; +Handlebars.log = require("handlebars/compiler").Handlebars.log; // BEGIN(BROWSER) Handlebars.Compiler = function() {}; @@ -7,13 +10,13 @@ Handlebars.JavaScriptCompiler = function() {}; (function(Compiler, JavaScriptCompiler) { Compiler.OPCODE_MAP = { - invokeContent: 1, + appendContent: 1, getContext: 2, lookupWithFallback: 3, lookup: 4, append: 5, invokeMustache: 6, - escape: 7, + appendEscaped: 7, pushString: 8, truthyOrFallback: 9, functionOrFallback: 10, @@ -24,7 +27,7 @@ Handlebars.JavaScriptCompiler = function() {}; }; Compiler.MULTI_PARAM_OPCODES = { - invokeContent: 1, + appendContent: 1, getContext: 1, lookupWithFallback: 1, lookup: 1, @@ -38,9 +41,9 @@ Handlebars.JavaScriptCompiler = function() {}; invokeInverse: 1 }; - Compiler.DISASSEMBLE_MAP = {} + Compiler.DISASSEMBLE_MAP = {}; - for(prop in Compiler.OPCODE_MAP) { + for(var prop in Compiler.OPCODE_MAP) { var value = Compiler.OPCODE_MAP[prop]; Compiler.DISASSEMBLE_MAP[value] = prop; } @@ -83,7 +86,7 @@ Handlebars.JavaScriptCompiler = function() {}; } } - return out.join("\n") + return out.join("\n"); }, guid: 0, @@ -118,6 +121,8 @@ Handlebars.JavaScriptCompiler = function() {}; var result = new Compiler().compile(program); var guid = this.guid++; + this.usePartial = this.usePartial || result.usePartial; + this.children[guid] = result; for(var i=0, l=result.depths.list.length; i 0) { - this.source[this.locals] = "var " + this.stackVars.join(", ") + ";"; + if(locals.length > 0) { + this.source[0] = this.source[0] + ", " + locals.join(", "); } - this.source.push("return buffer;") + this.source[0] = this.source[0] + ";"; + + this.source.push("return buffer;"); var params = ["context", "helpers", "partials"]; @@ -309,10 +355,12 @@ Handlebars.JavaScriptCompiler = function() {}; params.push("depth" + this.environment.depths.list[i]); } + if(params.length === 3 && !this.environment.usePartial) { params.pop(); } + params.push(this.source.join("\n")); var fn = Function.apply(this, params); - fn.displayName = "Handlebars.js" + fn.displayName = "Handlebars.js"; Handlebars.log(Handlebars.logger.DEBUG, fn.toString() + "\n\n"); @@ -322,20 +370,31 @@ Handlebars.JavaScriptCompiler = function() {}; return function(context, helpers, partials, depth) { try { - return container.render.apply(container, arguments) + return container.render.apply(container, arguments); } catch(e) { throw e; } - } + }; }, - invokeContent: function(content) { + appendContent: function(content) { this.source.push("buffer = buffer + " + this.quotedString(content) + ";"); }, append: function() { var local = this.popStack(); - this.source.push("buffer = buffer + ((" + local + " || " + local + " === 0) ? " + local + " : '');"); + this.source.push("if(" + local + " || " + local + " === 0) { buffer = buffer + " + local + "; }"); + }, + + appendEscaped: function() { + var opcode = this.nextOpcode(1), extra = ""; + + if(opcode[0] === 'appendContent') { + extra = " + " + this.quotedString(opcode[1][0]); + this.eat(opcode); + } + + this.source.push("buffer = buffer + this.escapeExpression(" + this.popStack() + ")" + extra + ";"); }, getContext: function(depth) { @@ -347,7 +406,6 @@ Handlebars.JavaScriptCompiler = function() {}; } else { this.source.push("currentContext = depth" + depth + ";"); } - // TODO: handle depths other than 0 } }, @@ -363,7 +421,7 @@ Handlebars.JavaScriptCompiler = function() {}; if(name) { this.pushStack(this.nameLookup('currentContext', name)); var topStack = this.topStack(); - this.source.push("if(" + topStack + " == null) { " + topStack + " = " + this.nameLookup('helpers', name) + "; }"); + this.source.push("if(" + topStack + " === undefined) { " + topStack + " = " + this.nameLookup('helpers', name) + "; }"); } else { this.pushStack("currentContext"); } @@ -383,49 +441,32 @@ Handlebars.JavaScriptCompiler = function() {}; }, invokeMustache: function(paramSize, original) { - this.source.push("tmp1 = " + this.popStack() + ";"); - this.source.push("tmp2 = (typeof tmp1 === 'function');"); + var params = ["context"], fn, slot; - var params = ["context"]; + fn = this.popStack(); for(var i=0; i