vendor/assets/javascripts/handlebars.js in handlebars_assets-0.4.3 vs vendor/assets/javascripts/handlebars.js in handlebars_assets-0.4.4

- old
+ new

@@ -1,9 +1,9 @@ // lib/handlebars/base.js var Handlebars = {}; -Handlebars.VERSION = "1.0.beta.5"; +Handlebars.VERSION = "1.0.beta.6"; Handlebars.helpers = {}; Handlebars.partials = {}; Handlebars.registerHelper = function(name, fn, inverse) { @@ -192,192 +192,107 @@ defaultActions: {16:[2,1],37:[2,23],53:[2,21]}, parseError: function parseError(str, hash) { throw new Error(str); }, parse: function parse(input) { - var self = this, - stack = [0], - vstack = [null], // semantic value stack - lstack = [], // location stack - table = this.table, - yytext = '', - yylineno = 0, - yyleng = 0, - recovering = 0, - TERROR = 2, - EOF = 1; - - //this.reductionCount = this.shiftCount = 0; - + var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; this.lexer.setInput(input); this.lexer.yy = this.yy; this.yy.lexer = this.lexer; - if (typeof this.lexer.yylloc == 'undefined') + if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {}; var yyloc = this.lexer.yylloc; lstack.push(yyloc); - - if (typeof this.yy.parseError === 'function') + if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError; - - function popStack (n) { - stack.length = stack.length - 2*n; + function popStack(n) { + stack.length = stack.length - 2 * n; vstack.length = vstack.length - n; lstack.length = lstack.length - n; } - function lex() { var token; - token = self.lexer.lex() || 1; // $end = 1 - // if token isn't its numeric value, convert - if (typeof token !== 'number') { + token = self.lexer.lex() || 1; + if (typeof token !== "number") { token = self.symbols_[token] || token; } return token; - }; - - var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + } + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; while (true) { - // retreive state number from top of stack - state = stack[stack.length-1]; - - // use default actions if available + state = stack[stack.length - 1]; if (this.defaultActions[state]) { action = this.defaultActions[state]; } else { if (symbol == null) symbol = lex(); - // read action for current state and first input action = table[state] && table[state][symbol]; } - - // handle parse error - if (typeof action === 'undefined' || !action.length || !action[0]) { - + if (typeof action === "undefined" || !action.length || !action[0]) { if (!recovering) { - // Report error expected = []; - for (p in table[state]) if (this.terminals_[p] && p > 2) { - expected.push("'"+this.terminals_[p]+"'"); - } - var errStr = ''; + for (p in table[state]) + if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + var errStr = ""; if (this.lexer.showPosition) { - errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+'\nExpecting '+expected.join(', '); + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + this.terminals_[symbol] + "'"; } else { - errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + - (symbol == 1 /*EOF*/ ? "end of input" : - ("'"+(this.terminals_[symbol] || symbol)+"'")); + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); } - this.parseError(errStr, - {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); } - - // just recovered from another error - if (recovering == 3) { - if (symbol == EOF) { - throw new Error(errStr || 'Parsing halted.'); - } - - // discard current lookahead and grab another + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { yyleng = this.lexer.yyleng; yytext = this.lexer.yytext; yylineno = this.lexer.yylineno; yyloc = this.lexer.yylloc; - symbol = lex(); + if (recovering > 0) + recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; } - - // try to recover from error - while (1) { - // check for error recovery rule in this state - if ((TERROR.toString()) in table[state]) { - break; - } - if (state == 0) { - throw new Error(errStr || 'Parsing halted.'); - } - popStack(1); - state = stack[stack.length-1]; + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; } - - preErrorSymbol = symbol; // save the lookahead token - symbol = TERROR; // insert generic error symbol as new lookahead - state = stack[stack.length-1]; - action = table[state] && table[state][TERROR]; - recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; } - - // this shouldn't happen, unless resolve defaults are off - if (action[0] instanceof Array && action.length > 1) { - throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); - } - - switch (action[0]) { - - case 1: // shift - //this.shiftCount++; - - stack.push(symbol); - vstack.push(this.lexer.yytext); - lstack.push(this.lexer.yylloc); - stack.push(action[1]); // push state - symbol = null; - if (!preErrorSymbol) { // normal execution/no error - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - if (recovering > 0) - recovering--; - } else { // error just occurred, resume old lookahead f/ before error - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - - case 2: // reduce - //this.reductionCount++; - - len = this.productions_[action[1]][1]; - - // perform semantic action - yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 - // default location, uses first token for firsts, last for lasts - yyval._$ = { - first_line: lstack[lstack.length-(len||1)].first_line, - last_line: lstack[lstack.length-1].last_line, - first_column: lstack[lstack.length-(len||1)].first_column, - last_column: lstack[lstack.length-1].last_column - }; - r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); - - if (typeof r !== 'undefined') { - return r; - } - - // pop off stack - if (len) { - stack = stack.slice(0,-1*len*2); - vstack = vstack.slice(0, -1*len); - lstack = lstack.slice(0, -1*len); - } - - stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) - vstack.push(yyval.$); - lstack.push(yyval._$); - // goto new state = table[STATE][NONTERMINAL] - newState = table[stack[stack.length-2]][stack[stack.length-1]]; - stack.push(newState); - break; - - case 3: // accept - return true; - } - } - return true; -}};/* Jison generated lexer */ +} +};/* Jison generated lexer */ var lexer = (function(){ var lexer = ({EOF:1, parseError:function parseError(str, hash) { if (this.yy.parseError) { @@ -487,10 +402,16 @@ popState:function popState() { return this.conditionStack.pop(); }, _currentRules:function _currentRules() { return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, +topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, +pushState:function begin(condition) { + this.begin(condition); }}); lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { var YYSTATE=YY_START switch($avoiding_name_collisions) { @@ -1076,17 +997,17 @@ JavaScriptCompiler.prototype = { // PUBLIC API: You can override these methods in a subclass to provide // alternative compiled forms for name lookup and buffering semantics nameLookup: function(parent, name, type) { - if (/^[0-9]+$/.test(name)) { + if (/^[0-9]+$/.test(name)) { return parent + "[" + name + "]"; } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { - return parent + "." + name; - } - else { - return parent + "['" + name + "']"; + return parent + "." + name; + } + else { + return parent + "['" + name + "']"; } }, appendToBuffer: function(string) { if (this.environment.isSimple) { @@ -1168,10 +1089,16 @@ }, preamble: function() { var out = []; + // this register will disambiguate helper lookup from finding a function in + // a context. This is necessary for mustache compatibility, which requires + // that context functions in blocks are evaluated by blockHelperMissing, and + // then proceed as if the resulting value was provided to blockHelperMissing. + this.useRegister('foundHelper'); + if (!this.isChild) { var namespace = this.namespace; var copies = "helpers = helpers || " + namespace + ".helpers;"; if(this.environment.usePartial) { copies = copies + " partials = partials || " + namespace + ".partials;"; } out.push(copies); @@ -1280,14 +1207,12 @@ toPush = topStack + " = " + this.nameLookup('helpers', name, 'helper'); this.usingKnownHelper = true; } else if (isScoped || this.options.knownHelpersOnly) { toPush = topStack + " = " + this.nameLookup('depth' + this.lastContext, name, 'context'); } else { - toPush = topStack + " = " - + this.nameLookup('helpers', name, 'helper') - + " || " - + this.nameLookup('depth' + this.lastContext, name, 'context'); + this.register('foundHelper', this.nameLookup('helpers', name, 'helper')); + toPush = topStack + " = foundHelper || " + this.nameLookup('depth' + this.lastContext, name, 'context'); } toPush += ';'; this.source.push(toPush); } else { @@ -1296,11 +1221,11 @@ }, lookup: function(name) { var topStack = this.topStack(); this.source.push(topStack + " = (" + topStack + " === null || " + topStack + " === undefined || " + topStack + " === false ? " + - topStack + " : " + this.nameLookup(topStack, name, 'context') + ");"); + topStack + " : " + this.nameLookup(topStack, name, 'context') + ");"); }, pushStringParam: function(string) { this.pushStack('depth' + this.lastContext); this.pushString(string); @@ -1378,24 +1303,25 @@ this.source.push('tmp1.data = data;'); } params.push(stringOptions); - this.populateCall(params, id, helperId || id, fn); + this.populateCall(params, id, helperId || id, fn, program !== '{}'); }, - populateCall: function(params, id, helperId, fn) { + populateCall: function(params, id, helperId, fn, program) { var paramString = ["depth0"].concat(params).join(", "); var helperMissingString = ["depth0"].concat(helperId).concat(params).join(", "); var nextStack = this.nextStack(); if (this.usingKnownHelper) { this.source.push(nextStack + " = " + id + ".call(" + paramString + ");"); } else { this.context.aliases.functionType = '"function"'; - this.source.push("if(typeof " + id + " === functionType) { " + nextStack + " = " + id + ".call(" + paramString + "); }"); + var condition = program ? "foundHelper && " : "" + this.source.push("if(" + condition + "typeof " + id + " === functionType) { " + nextStack + " = " + id + ".call(" + paramString + "); }"); } fn.call(this, nextStack, helperMissingString, id); this.usingKnownHelper = false; }, @@ -1495,25 +1421,39 @@ .replace(/\n/g, '\\n') .replace(/\r/g, '\\r') + '"'; } }; - var reservedWords = ("break case catch continue default delete do else finally " + - "for function if in instanceof new return switch this throw " + - "try typeof var void while with null true false").split(" "); + var reservedWords = ( + "break else new var" + + " case finally return void" + + " catch for switch while" + + " continue function this with" + + " default if throw" + + " delete in try" + + " do instanceof typeof" + + " abstract enum int short" + + " boolean export interface static" + + " byte extends long super" + + " char final native synchronized" + + " class float package throws" + + " const goto private transient" + + " debugger implements protected volatile" + + " double import public let yield" + ).split(" "); var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; for(var i=0, l=reservedWords.length; i<l; i++) { compilerWords[reservedWords[i]] = true; } - JavaScriptCompiler.isValidJavaScriptVariableName = function(name) { - if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) { - return true; - } - return false; - } + JavaScriptCompiler.isValidJavaScriptVariableName = function(name) { + if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) { + return true; + } + return false; + } })(Handlebars.Compiler, Handlebars.JavaScriptCompiler); Handlebars.precompile = function(string, options) { options = options || {};