Skip to content
This repository
Browse code

Added sandboxed iframe example, which compiles Handlebar templates in…

… a sandboxed environment, as per Chromium bug #139271.
  • Loading branch information...
commit d0d2018d90708c9f3415db5809d6ebcb9904b7c3 1 parent b94921c
Renato Mangini authored
20  sandbox/LICENSE.handlebars
... ...
@@ -0,0 +1,20 @@
  1
+Copyright (C) 2011 by Yehuda Katz
  2
+
  3
+Permission is hereby granted, free of charge, to any person obtaining a copy
  4
+of this software and associated documentation files (the "Software"), to deal
  5
+in the Software without restriction, including without limitation the rights
  6
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7
+copies of the Software, and to permit persons to whom the Software is
  8
+furnished to do so, subject to the following conditions:
  9
+
  10
+The above copyright notice and this permission notice shall be included in
  11
+all copies or substantial portions of the Software.
  12
+
  13
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19
+THE SOFTWARE.
  20
+
17  sandbox/eventpage.html
... ...
@@ -0,0 +1,17 @@
  1
+<!--
  2
+  - Copyright (c) 2012 The Chromium Authors. All rights reserved.
  3
+  - Use of this source code is governed by a BSD-style license that can be
  4
+  - found in the LICENSE file.
  5
+  -->
  6
+<!doctype html>
  7
+<html>
  8
+  <head>
  9
+    <script src="eventpage.js"></script>
  10
+  </head>
  11
+  <body>
  12
+    <button id="sendMessage">Click me</button>
  13
+    <button id="reset">Reset counter</button>
  14
+    <div id="result"></div>
  15
+    <iframe id="theFrame" src="sandbox.html" style="display: none;"></iframe>
  16
+  </body>
  17
+</html>
28  sandbox/eventpage.js
... ...
@@ -0,0 +1,28 @@
  1
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2
+// Use of this source code is governed by a BSD-style license that can be
  3
+// found in the LICENSE file.
  4
+
  5
+var counter=0;
  6
+document.addEventListener('DOMContentLoaded', function() {
  7
+
  8
+  document.getElementById('reset').addEventListener('click', function(event) {
  9
+    counter=0;
  10
+    document.querySelector("#result").innerHTML="";
  11
+  });
  12
+
  13
+  document.getElementById('sendMessage').addEventListener('click', function(event) {
  14
+    counter++;
  15
+    var message = {
  16
+      command: 'render',
  17
+      templateName: 'sample-template-'+counter,
  18
+      context: {'counter': counter}
  19
+    };
  20
+    document.getElementById('theFrame').contentWindow.postMessage(message, '*');
  21
+  });
  22
+
  23
+  // on result from sandboxed frame:
  24
+  window.addEventListener('message', function(event) {
  25
+    document.querySelector("#result").innerHTML=event.data.result || "invalid result"
  26
+  });
  27
+});
  28
+
1,553  sandbox/handlebars-1.0.0.beta.6.js
... ...
@@ -0,0 +1,1553 @@
  1
+// Copyright (C) 2011 by Yehuda Katz
  2
+// Licensing details in LICENSE.handlebars
  3
+
  4
+// lib/handlebars/base.js
  5
+var Handlebars = {};
  6
+
  7
+Handlebars.VERSION = "1.0.beta.6";
  8
+
  9
+Handlebars.helpers  = {};
  10
+Handlebars.partials = {};
  11
+
  12
+Handlebars.registerHelper = function(name, fn, inverse) {
  13
+  if(inverse) { fn.not = inverse; }
  14
+  this.helpers[name] = fn;
  15
+};
  16
+
  17
+Handlebars.registerPartial = function(name, str) {
  18
+  this.partials[name] = str;
  19
+};
  20
+
  21
+Handlebars.registerHelper('helperMissing', function(arg) {
  22
+  if(arguments.length === 2) {
  23
+    return undefined;
  24
+  } else {
  25
+    throw new Error("Could not find property '" + arg + "'");
  26
+  }
  27
+});
  28
+
  29
+var toString = Object.prototype.toString, functionType = "[object Function]";
  30
+
  31
+Handlebars.registerHelper('blockHelperMissing', function(context, options) {
  32
+  var inverse = options.inverse || function() {}, fn = options.fn;
  33
+
  34
+
  35
+  var ret = "";
  36
+  var type = toString.call(context);
  37
+
  38
+  if(type === functionType) { context = context.call(this); }
  39
+
  40
+  if(context === true) {
  41
+    return fn(this);
  42
+  } else if(context === false || context == null) {
  43
+    return inverse(this);
  44
+  } else if(type === "[object Array]") {
  45
+    if(context.length > 0) {
  46
+      for(var i=0, j=context.length; i<j; i++) {
  47
+        ret = ret + fn(context[i]);
  48
+      }
  49
+    } else {
  50
+      ret = inverse(this);
  51
+    }
  52
+    return ret;
  53
+  } else {
  54
+    return fn(context);
  55
+  }
  56
+});
  57
+
  58
+Handlebars.registerHelper('each', function(context, options) {
  59
+  var fn = options.fn, inverse = options.inverse;
  60
+  var ret = "";
  61
+
  62
+  if(context && context.length > 0) {
  63
+    for(var i=0, j=context.length; i<j; i++) {
  64
+      ret = ret + fn(context[i]);
  65
+    }
  66
+  } else {
  67
+    ret = inverse(this);
  68
+  }
  69
+  return ret;
  70
+});
  71
+
  72
+Handlebars.registerHelper('if', function(context, options) {
  73
+  var type = toString.call(context);
  74
+  if(type === functionType) { context = context.call(this); }
  75
+
  76
+  if(!context || Handlebars.Utils.isEmpty(context)) {
  77
+    return options.inverse(this);
  78
+  } else {
  79
+    return options.fn(this);
  80
+  }
  81
+});
  82
+
  83
+Handlebars.registerHelper('unless', function(context, options) {
  84
+  var fn = options.fn, inverse = options.inverse;
  85
+  options.fn = inverse;
  86
+  options.inverse = fn;
  87
+
  88
+  return Handlebars.helpers['if'].call(this, context, options);
  89
+});
  90
+
  91
+Handlebars.registerHelper('with', function(context, options) {
  92
+  return options.fn(context);
  93
+});
  94
+
  95
+Handlebars.registerHelper('log', function(context) {
  96
+  Handlebars.log(context);
  97
+});
  98
+;
  99
+// lib/handlebars/compiler/parser.js
  100
+/* Jison generated parser */
  101
+var handlebars = (function(){
  102
+
  103
+var parser = {trace: function trace() { },
  104
+yy: {},
  105
+symbols_: {"error":2,"root":3,"program":4,"EOF":5,"statements":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"OPEN_PARTIAL":24,"params":25,"hash":26,"param":27,"STRING":28,"INTEGER":29,"BOOLEAN":30,"hashSegments":31,"hashSegment":32,"ID":33,"EQUALS":34,"pathSegments":35,"SEP":36,"$accept":0,"$end":1},
  106
+terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",28:"STRING",29:"INTEGER",30:"BOOLEAN",33:"ID",34:"EQUALS",36:"SEP"},
  107
+productions_: [0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,3],[17,2],[17,2],[17,1],[25,2],[25,1],[27,1],[27,1],[27,1],[27,1],[26,1],[31,2],[31,1],[32,3],[32,3],[32,3],[32,3],[21,1],[35,3],[35,1]],
  108
+performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
  109
+
  110
+var $0 = $$.length - 1;
  111
+switch (yystate) {
  112
+case 1: return $$[$0-1] 
  113
+break;
  114
+case 2: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]) 
  115
+break;
  116
+case 3: this.$ = new yy.ProgramNode($$[$0]) 
  117
+break;
  118
+case 4: this.$ = new yy.ProgramNode([]) 
  119
+break;
  120
+case 5: this.$ = [$$[$0]] 
  121
+break;
  122
+case 6: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] 
  123
+break;
  124
+case 7: this.$ = new yy.InverseNode($$[$0-2], $$[$0-1], $$[$0]) 
  125
+break;
  126
+case 8: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0]) 
  127
+break;
  128
+case 9: this.$ = $$[$0] 
  129
+break;
  130
+case 10: this.$ = $$[$0] 
  131
+break;
  132
+case 11: this.$ = new yy.ContentNode($$[$0]) 
  133
+break;
  134
+case 12: this.$ = new yy.CommentNode($$[$0]) 
  135
+break;
  136
+case 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) 
  137
+break;
  138
+case 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) 
  139
+break;
  140
+case 15: this.$ = $$[$0-1] 
  141
+break;
  142
+case 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) 
  143
+break;
  144
+case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true) 
  145
+break;
  146
+case 18: this.$ = new yy.PartialNode($$[$0-1]) 
  147
+break;
  148
+case 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]) 
  149
+break;
  150
+case 20: 
  151
+break;
  152
+case 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]] 
  153
+break;
  154
+case 22: this.$ = [[$$[$0-1]].concat($$[$0]), null] 
  155
+break;
  156
+case 23: this.$ = [[$$[$0-1]], $$[$0]] 
  157
+break;
  158
+case 24: this.$ = [[$$[$0]], null] 
  159
+break;
  160
+case 25: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; 
  161
+break;
  162
+case 26: this.$ = [$$[$0]] 
  163
+break;
  164
+case 27: this.$ = $$[$0] 
  165
+break;
  166
+case 28: this.$ = new yy.StringNode($$[$0]) 
  167
+break;
  168
+case 29: this.$ = new yy.IntegerNode($$[$0]) 
  169
+break;
  170
+case 30: this.$ = new yy.BooleanNode($$[$0]) 
  171
+break;
  172
+case 31: this.$ = new yy.HashNode($$[$0]) 
  173
+break;
  174
+case 32: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] 
  175
+break;
  176
+case 33: this.$ = [$$[$0]] 
  177
+break;
  178
+case 34: this.$ = [$$[$0-2], $$[$0]] 
  179
+break;
  180
+case 35: this.$ = [$$[$0-2], new yy.StringNode($$[$0])] 
  181
+break;
  182
+case 36: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])] 
  183
+break;
  184
+case 37: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])] 
  185
+break;
  186
+case 38: this.$ = new yy.IdNode($$[$0]) 
  187
+break;
  188
+case 39: $$[$0-2].push($$[$0]); this.$ = $$[$0-2]; 
  189
+break;
  190
+case 40: this.$ = [$$[$0]] 
  191
+break;
  192
+}
  193
+},
  194
+table: [{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,33:[1,25],35:24},{17:26,21:23,33:[1,25],35:24},{17:27,21:23,33:[1,25],35:24},{17:28,21:23,33:[1,25],35:24},{21:29,33:[1,25],35:24},{1:[2,1]},{6:30,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,31],21:23,33:[1,25],35:24},{10:32,20:[1,33]},{10:34,20:[1,33]},{18:[1,35]},{18:[2,24],21:40,25:36,26:37,27:38,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,38],28:[2,38],29:[2,38],30:[2,38],33:[2,38],36:[1,46]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],36:[2,40]},{18:[1,47]},{18:[1,48]},{18:[1,49]},{18:[1,50],21:51,33:[1,25],35:24},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:52,33:[1,25],35:24},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,22],21:40,26:53,27:54,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,23]},{18:[2,26],28:[2,26],29:[2,26],30:[2,26],33:[2,26]},{18:[2,31],32:55,33:[1,56]},{18:[2,27],28:[2,27],29:[2,27],30:[2,27],33:[2,27]},{18:[2,28],28:[2,28],29:[2,28],30:[2,28],33:[2,28]},{18:[2,29],28:[2,29],29:[2,29],30:[2,29],33:[2,29]},{18:[2,30],28:[2,30],29:[2,30],30:[2,30],33:[2,30]},{18:[2,33],33:[2,33]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],34:[1,57],36:[2,40]},{33:[1,58]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,59]},{18:[1,60]},{18:[2,21]},{18:[2,25],28:[2,25],29:[2,25],30:[2,25],33:[2,25]},{18:[2,32],33:[2,32]},{34:[1,57]},{21:61,28:[1,62],29:[1,63],30:[1,64],33:[1,25],35:24},{18:[2,39],28:[2,39],29:[2,39],30:[2,39],33:[2,39],36:[2,39]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{18:[2,34],33:[2,34]},{18:[2,35],33:[2,35]},{18:[2,36],33:[2,36]},{18:[2,37],33:[2,37]}],
  195
+defaultActions: {16:[2,1],37:[2,23],53:[2,21]},
  196
+parseError: function parseError(str, hash) {
  197
+    throw new Error(str);
  198
+},
  199
+parse: function parse(input) {
  200
+    var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
  201
+    this.lexer.setInput(input);
  202
+    this.lexer.yy = this.yy;
  203
+    this.yy.lexer = this.lexer;
  204
+    if (typeof this.lexer.yylloc == "undefined")
  205
+        this.lexer.yylloc = {};
  206
+    var yyloc = this.lexer.yylloc;
  207
+    lstack.push(yyloc);
  208
+    if (typeof this.yy.parseError === "function")
  209
+        this.parseError = this.yy.parseError;
  210
+    function popStack(n) {
  211
+        stack.length = stack.length - 2 * n;
  212
+        vstack.length = vstack.length - n;
  213
+        lstack.length = lstack.length - n;
  214
+    }
  215
+    function lex() {
  216
+        var token;
  217
+        token = self.lexer.lex() || 1;
  218
+        if (typeof token !== "number") {
  219
+            token = self.symbols_[token] || token;
  220
+        }
  221
+        return token;
  222
+    }
  223
+    var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
  224
+    while (true) {
  225
+        state = stack[stack.length - 1];
  226
+        if (this.defaultActions[state]) {
  227
+            action = this.defaultActions[state];
  228
+        } else {
  229
+            if (symbol == null)
  230
+                symbol = lex();
  231
+            action = table[state] && table[state][symbol];
  232
+        }
  233
+        if (typeof action === "undefined" || !action.length || !action[0]) {
  234
+            if (!recovering) {
  235
+                expected = [];
  236
+                for (p in table[state])
  237
+                    if (this.terminals_[p] && p > 2) {
  238
+                        expected.push("'" + this.terminals_[p] + "'");
  239
+                    }
  240
+                var errStr = "";
  241
+                if (this.lexer.showPosition) {
  242
+                    errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + this.terminals_[symbol] + "'";
  243
+                } else {
  244
+                    errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
  245
+                }
  246
+                this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
  247
+            }
  248
+        }
  249
+        if (action[0] instanceof Array && action.length > 1) {
  250
+            throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
  251
+        }
  252
+        switch (action[0]) {
  253
+        case 1:
  254
+            stack.push(symbol);
  255
+            vstack.push(this.lexer.yytext);
  256
+            lstack.push(this.lexer.yylloc);
  257
+            stack.push(action[1]);
  258
+            symbol = null;
  259
+            if (!preErrorSymbol) {
  260
+                yyleng = this.lexer.yyleng;
  261
+                yytext = this.lexer.yytext;
  262
+                yylineno = this.lexer.yylineno;
  263
+                yyloc = this.lexer.yylloc;
  264
+                if (recovering > 0)
  265
+                    recovering--;
  266
+            } else {
  267
+                symbol = preErrorSymbol;
  268
+                preErrorSymbol = null;
  269
+            }
  270
+            break;
  271
+        case 2:
  272
+            len = this.productions_[action[1]][1];
  273
+            yyval.$ = vstack[vstack.length - len];
  274
+            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};
  275
+            r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
  276
+            if (typeof r !== "undefined") {
  277
+                return r;
  278
+            }
  279
+            if (len) {
  280
+                stack = stack.slice(0, -1 * len * 2);
  281
+                vstack = vstack.slice(0, -1 * len);
  282
+                lstack = lstack.slice(0, -1 * len);
  283
+            }
  284
+            stack.push(this.productions_[action[1]][0]);
  285
+            vstack.push(yyval.$);
  286
+            lstack.push(yyval._$);
  287
+            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
  288
+            stack.push(newState);
  289
+            break;
  290
+        case 3:
  291
+            return true;
  292
+        }
  293
+    }
  294
+    return true;
  295
+}
  296
+};/* Jison generated lexer */
  297
+var lexer = (function(){
  298
+
  299
+var lexer = ({EOF:1,
  300
+parseError:function parseError(str, hash) {
  301
+        if (this.yy.parseError) {
  302
+            this.yy.parseError(str, hash);
  303
+        } else {
  304
+            throw new Error(str);
  305
+        }
  306
+    },
  307
+setInput:function (input) {
  308
+        this._input = input;
  309
+        this._more = this._less = this.done = false;
  310
+        this.yylineno = this.yyleng = 0;
  311
+        this.yytext = this.matched = this.match = '';
  312
+        this.conditionStack = ['INITIAL'];
  313
+        this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
  314
+        return this;
  315
+    },
  316
+input:function () {
  317
+        var ch = this._input[0];
  318
+        this.yytext+=ch;
  319
+        this.yyleng++;
  320
+        this.match+=ch;
  321
+        this.matched+=ch;
  322
+        var lines = ch.match(/\n/);
  323
+        if (lines) this.yylineno++;
  324
+        this._input = this._input.slice(1);
  325
+        return ch;
  326
+    },
  327
+unput:function (ch) {
  328
+        this._input = ch + this._input;
  329
+        return this;
  330
+    },
  331
+more:function () {
  332
+        this._more = true;
  333
+        return this;
  334
+    },
  335
+pastInput:function () {
  336
+        var past = this.matched.substr(0, this.matched.length - this.match.length);
  337
+        return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
  338
+    },
  339
+upcomingInput:function () {
  340
+        var next = this.match;
  341
+        if (next.length < 20) {
  342
+            next += this._input.substr(0, 20-next.length);
  343
+        }
  344
+        return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
  345
+    },
  346
+showPosition:function () {
  347
+        var pre = this.pastInput();
  348
+        var c = new Array(pre.length + 1).join("-");
  349
+        return pre + this.upcomingInput() + "\n" + c+"^";
  350
+    },
  351
+next:function () {
  352
+        if (this.done) {
  353
+            return this.EOF;
  354
+        }
  355
+        if (!this._input) this.done = true;
  356
+
  357
+        var token,
  358
+            match,
  359
+            col,
  360
+            lines;
  361
+        if (!this._more) {
  362
+            this.yytext = '';
  363
+            this.match = '';
  364
+        }
  365
+        var rules = this._currentRules();
  366
+        for (var i=0;i < rules.length; i++) {
  367
+            match = this._input.match(this.rules[rules[i]]);
  368
+            if (match) {
  369
+                lines = match[0].match(/\n.*/g);
  370
+                if (lines) this.yylineno += lines.length;
  371
+                this.yylloc = {first_line: this.yylloc.last_line,
  372
+                               last_line: this.yylineno+1,
  373
+                               first_column: this.yylloc.last_column,
  374
+                               last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
  375
+                this.yytext += match[0];
  376
+                this.match += match[0];
  377
+                this.matches = match;
  378
+                this.yyleng = this.yytext.length;
  379
+                this._more = false;
  380
+                this._input = this._input.slice(match[0].length);
  381
+                this.matched += match[0];
  382
+                token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);
  383
+                if (token) return token;
  384
+                else return;
  385
+            }
  386
+        }
  387
+        if (this._input === "") {
  388
+            return this.EOF;
  389
+        } else {
  390
+            this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), 
  391
+                    {text: "", token: null, line: this.yylineno});
  392
+        }
  393
+    },
  394
+lex:function lex() {
  395
+        var r = this.next();
  396
+        if (typeof r !== 'undefined') {
  397
+            return r;
  398
+        } else {
  399
+            return this.lex();
  400
+        }
  401
+    },
  402
+begin:function begin(condition) {
  403
+        this.conditionStack.push(condition);
  404
+    },
  405
+popState:function popState() {
  406
+        return this.conditionStack.pop();
  407
+    },
  408
+_currentRules:function _currentRules() {
  409
+        return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
  410
+    },
  411
+topState:function () {
  412
+        return this.conditionStack[this.conditionStack.length-2];
  413
+    },
  414
+pushState:function begin(condition) {
  415
+        this.begin(condition);
  416
+    }});
  417
+lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
  418
+
  419
+var YYSTATE=YY_START
  420
+switch($avoiding_name_collisions) {
  421
+case 0:
  422
+                                   if(yy_.yytext.slice(-1) !== "\\") this.begin("mu");
  423
+                                   if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu");
  424
+                                   if(yy_.yytext) return 14;
  425
+                                 
  426
+break;
  427
+case 1: return 14; 
  428
+break;
  429
+case 2: this.popState(); return 14; 
  430
+break;
  431
+case 3: return 24; 
  432
+break;
  433
+case 4: return 16; 
  434
+break;
  435
+case 5: return 20; 
  436
+break;
  437
+case 6: return 19; 
  438
+break;
  439
+case 7: return 19; 
  440
+break;
  441
+case 8: return 23; 
  442
+break;
  443
+case 9: return 23; 
  444
+break;
  445
+case 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15; 
  446
+break;
  447
+case 11: return 22; 
  448
+break;
  449
+case 12: return 34; 
  450
+break;
  451
+case 13: return 33; 
  452
+break;
  453
+case 14: return 33; 
  454
+break;
  455
+case 15: return 36; 
  456
+break;
  457
+case 16: /*ignore whitespace*/ 
  458
+break;
  459
+case 17: this.popState(); return 18; 
  460
+break;
  461
+case 18: this.popState(); return 18; 
  462
+break;
  463
+case 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 28; 
  464
+break;
  465
+case 20: return 30; 
  466
+break;
  467
+case 21: return 30; 
  468
+break;
  469
+case 22: return 29; 
  470
+break;
  471
+case 23: return 33; 
  472
+break;
  473
+case 24: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 33; 
  474
+break;
  475
+case 25: return 'INVALID'; 
  476
+break;
  477
+case 26: return 5; 
  478
+break;
  479
+}
  480
+};
  481
+lexer.rules = [/^[^\x00]*?(?=(\{\{))/,/^[^\x00]+/,/^[^\x00]{2,}?(?=(\{\{))/,/^\{\{>/,/^\{\{#/,/^\{\{\//,/^\{\{\^/,/^\{\{\s*else\b/,/^\{\{\{/,/^\{\{&/,/^\{\{![\s\S]*?\}\}/,/^\{\{/,/^=/,/^\.(?=[} ])/,/^\.\./,/^[\/.]/,/^\s+/,/^\}\}\}/,/^\}\}/,/^"(\\["]|[^"])*"/,/^true(?=[}\s])/,/^false(?=[}\s])/,/^[0-9]+(?=[}\s])/,/^[a-zA-Z0-9_$-]+(?=[=}\s\/.])/,/^\[[^\]]*\]/,/^./,/^$/];
  482
+lexer.conditions = {"mu":{"rules":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"INITIAL":{"rules":[0,1,26],"inclusive":true}};return lexer;})()
  483
+parser.lexer = lexer;
  484
+return parser;
  485
+})();
  486
+if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
  487
+exports.parser = handlebars;
  488
+exports.parse = function () { return handlebars.parse.apply(handlebars, arguments); }
  489
+exports.main = function commonjsMain(args) {
  490
+    if (!args[1])
  491
+        throw new Error('Usage: '+args[0]+' FILE');
  492
+    if (typeof process !== 'undefined') {
  493
+        var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8");
  494
+    } else {
  495
+        var cwd = require("file").path(require("file").cwd());
  496
+        var source = cwd.join(args[1]).read({charset: "utf-8"});
  497
+    }
  498
+    return exports.parser.parse(source);
  499
+}
  500
+if (typeof module !== 'undefined' && require.main === module) {
  501
+  exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
  502
+}
  503
+};
  504
+;
  505
+// lib/handlebars/compiler/base.js
  506
+Handlebars.Parser = handlebars;
  507
+
  508
+Handlebars.parse = function(string) {
  509
+  Handlebars.Parser.yy = Handlebars.AST;
  510
+  return Handlebars.Parser.parse(string);
  511
+};
  512
+
  513
+Handlebars.print = function(ast) {
  514
+  return new Handlebars.PrintVisitor().accept(ast);
  515
+};
  516
+
  517
+Handlebars.logger = {
  518
+  DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,
  519
+
  520
+  // override in the host environment
  521
+  log: function(level, str) {}
  522
+};
  523
+
  524
+Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
  525
+;
  526
+// lib/handlebars/compiler/ast.js
  527
+(function() {
  528
+
  529
+  Handlebars.AST = {};
  530
+
  531
+  Handlebars.AST.ProgramNode = function(statements, inverse) {
  532
+    this.type = "program";
  533
+    this.statements = statements;
  534
+    if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }
  535
+  };
  536
+
  537
+  Handlebars.AST.MustacheNode = function(params, hash, unescaped) {
  538
+    this.type = "mustache";
  539
+    this.id = params[0];
  540
+    this.params = params.slice(1);
  541
+    this.hash = hash;
  542
+    this.escaped = !unescaped;
  543
+  };
  544
+
  545
+  Handlebars.AST.PartialNode = function(id, context) {
  546
+    this.type    = "partial";
  547
+
  548
+    // TODO: disallow complex IDs
  549
+
  550
+    this.id      = id;
  551
+    this.context = context;
  552
+  };
  553
+
  554
+  var verifyMatch = function(open, close) {
  555
+    if(open.original !== close.original) {
  556
+      throw new Handlebars.Exception(open.original + " doesn't match " + close.original);
  557
+    }
  558
+  };
  559
+
  560
+  Handlebars.AST.BlockNode = function(mustache, program, close) {
  561
+    verifyMatch(mustache.id, close);
  562
+    this.type = "block";
  563
+    this.mustache = mustache;
  564
+    this.program  = program;
  565
+  };
  566
+
  567
+  Handlebars.AST.InverseNode = function(mustache, program, close) {
  568
+    verifyMatch(mustache.id, close);
  569
+    this.type = "inverse";
  570
+    this.mustache = mustache;
  571
+    this.program  = program;
  572
+  };
  573
+
  574
+  Handlebars.AST.ContentNode = function(string) {
  575
+    this.type = "content";
  576
+    this.string = string;
  577
+  };
  578
+
  579
+  Handlebars.AST.HashNode = function(pairs) {
  580
+    this.type = "hash";
  581
+    this.pairs = pairs;
  582
+  };
  583
+
  584
+  Handlebars.AST.IdNode = function(parts) {
  585
+    this.type = "ID";
  586
+    this.original = parts.join(".");
  587
+
  588
+    var dig = [], depth = 0;
  589
+
  590
+    for(var i=0,l=parts.length; i<l; i++) {
  591
+      var part = parts[i];
  592
+
  593
+      if(part === "..") { depth++; }
  594
+      else if(part === "." || part === "this") { this.isScoped = true; }
  595
+      else { dig.push(part); }
  596
+    }
  597
+
  598
+    this.parts    = dig;
  599
+    this.string   = dig.join('.');
  600
+    this.depth    = depth;
  601
+    this.isSimple = (dig.length === 1) && (depth === 0);
  602
+  };
  603
+
  604
+  Handlebars.AST.StringNode = function(string) {
  605
+    this.type = "STRING";
  606
+    this.string = string;
  607
+  };
  608
+
  609
+  Handlebars.AST.IntegerNode = function(integer) {
  610
+    this.type = "INTEGER";
  611
+    this.integer = integer;
  612
+  };
  613
+
  614
+  Handlebars.AST.BooleanNode = function(bool) {
  615
+    this.type = "BOOLEAN";
  616
+    this.bool = bool;
  617
+  };
  618
+
  619
+  Handlebars.AST.CommentNode = function(comment) {
  620
+    this.type = "comment";
  621
+    this.comment = comment;
  622
+  };
  623
+
  624
+})();;
  625
+// lib/handlebars/utils.js
  626
+Handlebars.Exception = function(message) {
  627
+  var tmp = Error.prototype.constructor.apply(this, arguments);
  628
+
  629
+  for (var p in tmp) {
  630
+    if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; }
  631
+  }
  632
+
  633
+  this.message = tmp.message;
  634
+};
  635
+Handlebars.Exception.prototype = new Error;
  636
+
  637
+// Build out our basic SafeString type
  638
+Handlebars.SafeString = function(string) {
  639
+  this.string = string;
  640
+};
  641
+Handlebars.SafeString.prototype.toString = function() {
  642
+  return this.string.toString();
  643
+};
  644
+
  645
+(function() {
  646
+  var escape = {
  647
+    "<": "&lt;",
  648
+    ">": "&gt;",
  649
+    '"': "&quot;",
  650
+    "'": "&#x27;",
  651
+    "`": "&#x60;"
  652
+  };
  653
+
  654
+  var badChars = /&(?!\w+;)|[<>"'`]/g;
  655
+  var possible = /[&<>"'`]/;
  656
+
  657
+  var escapeChar = function(chr) {
  658
+    return escape[chr] || "&amp;";
  659
+  };
  660
+
  661
+  Handlebars.Utils = {
  662
+    escapeExpression: function(string) {
  663
+      // don't escape SafeStrings, since they're already safe
  664
+      if (string instanceof Handlebars.SafeString) {
  665
+        return string.toString();
  666
+      } else if (string == null || string === false) {
  667
+        return "";
  668
+      }
  669
+
  670
+      if(!possible.test(string)) { return string; }
  671
+      return string.replace(badChars, escapeChar);
  672
+    },
  673
+
  674
+    isEmpty: function(value) {
  675
+      if (typeof value === "undefined") {
  676
+        return true;
  677
+      } else if (value === null) {
  678
+        return true;
  679
+      } else if (value === false) {
  680
+        return true;
  681
+      } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) {
  682
+        return true;
  683
+      } else {
  684
+        return false;
  685
+      }
  686
+    }
  687
+  };
  688
+})();;
  689
+// lib/handlebars/compiler/compiler.js
  690
+Handlebars.Compiler = function() {};
  691
+Handlebars.JavaScriptCompiler = function() {};
  692
+
  693
+(function(Compiler, JavaScriptCompiler) {
  694
+  Compiler.OPCODE_MAP = {
  695
+    appendContent: 1,
  696
+    getContext: 2,
  697
+    lookupWithHelpers: 3,
  698
+    lookup: 4,
  699
+    append: 5,
  700
+    invokeMustache: 6,
  701
+    appendEscaped: 7,
  702
+    pushString: 8,
  703
+    truthyOrFallback: 9,
  704
+    functionOrFallback: 10,
  705
+    invokeProgram: 11,
  706
+    invokePartial: 12,
  707
+    push: 13,
  708
+    assignToHash: 15,
  709
+    pushStringParam: 16
  710
+  };
  711
+
  712
+  Compiler.MULTI_PARAM_OPCODES = {
  713
+    appendContent: 1,
  714
+    getContext: 1,
  715
+    lookupWithHelpers: 2,
  716
+    lookup: 1,
  717
+    invokeMustache: 3,
  718
+    pushString: 1,
  719
+    truthyOrFallback: 1,
  720
+    functionOrFallback: 1,
  721
+    invokeProgram: 3,
  722
+    invokePartial: 1,
  723
+    push: 1,
  724
+    assignToHash: 1,
  725
+    pushStringParam: 1
  726
+  };
  727
+
  728
+  Compiler.DISASSEMBLE_MAP = {};
  729
+
  730
+  for(var prop in Compiler.OPCODE_MAP) {
  731
+    var value = Compiler.OPCODE_MAP[prop];
  732
+    Compiler.DISASSEMBLE_MAP[value] = prop;
  733
+  }
  734
+
  735
+  Compiler.multiParamSize = function(code) {
  736
+    return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]];
  737
+  };
  738
+
  739
+  Compiler.prototype = {
  740
+    compiler: Compiler,
  741
+
  742
+    disassemble: function() {
  743
+      var opcodes = this.opcodes, opcode, nextCode;
  744
+      var out = [], str, name, value;
  745
+
  746
+      for(var i=0, l=opcodes.length; i<l; i++) {
  747
+        opcode = opcodes[i];
  748
+
  749
+        if(opcode === 'DECLARE') {
  750
+          name = opcodes[++i];
  751
+          value = opcodes[++i];
  752
+          out.push("DECLARE " + name + " = " + value);
  753
+        } else {
  754
+          str = Compiler.DISASSEMBLE_MAP[opcode];
  755
+
  756
+          var extraParams = Compiler.multiParamSize(opcode);
  757
+          var codes = [];
  758
+
  759
+          for(var j=0; j<extraParams; j++) {
  760
+            nextCode = opcodes[++i];
  761
+
  762
+            if(typeof nextCode === "string") {
  763
+              nextCode = "\"" + nextCode.replace("\n", "\\n") + "\"";
  764
+            }
  765
+
  766
+            codes.push(nextCode);
  767
+          }
  768
+
  769
+          str = str + " " + codes.join(" ");
  770
+
  771
+          out.push(str);
  772
+        }
  773
+      }
  774
+
  775
+      return out.join("\n");
  776
+    },
  777
+
  778
+    guid: 0,
  779
+
  780
+    compile: function(program, options) {
  781
+      this.children = [];
  782
+      this.depths = {list: []};
  783
+      this.options = options;
  784
+
  785
+      // These changes will propagate to the other compiler components
  786
+      var knownHelpers = this.options.knownHelpers;
  787
+      this.options.knownHelpers = {
  788
+        'helperMissing': true,
  789
+        'blockHelperMissing': true,
  790
+        'each': true,
  791
+        'if': true,
  792
+        'unless': true,
  793
+        'with': true,
  794
+        'log': true
  795
+      };
  796
+      if (knownHelpers) {
  797
+        for (var name in knownHelpers) {
  798
+          this.options.knownHelpers[name] = knownHelpers[name];
  799
+        }
  800
+      }
  801
+
  802
+      return this.program(program);
  803
+    },
  804
+
  805
+    accept: function(node) {
  806
+      return this[node.type](node);
  807
+    },
  808
+
  809
+    program: function(program) {
  810
+      var statements = program.statements, statement;
  811
+      this.opcodes = [];
  812
+
  813
+      for(var i=0, l=statements.length; i<l; i++) {
  814
+        statement = statements[i];
  815
+        this[statement.type](statement);
  816
+      }
  817
+      this.isSimple = l === 1;
  818
+
  819
+      this.depths.list = this.depths.list.sort(function(a, b) {
  820
+        return a - b;
  821
+      });
  822
+
  823
+      return this;
  824
+    },
  825
+
  826
+    compileProgram: function(program) {
  827
+      var result = new this.compiler().compile(program, this.options);
  828
+      var guid = this.guid++;
  829
+
  830
+      this.usePartial = this.usePartial || result.usePartial;
  831
+
  832
+      this.children[guid] = result;
  833
+
  834
+      for(var i=0, l=result.depths.list.length; i<l; i++) {
  835
+        depth = result.depths.list[i];
  836
+
  837
+        if(depth < 2) { continue; }
  838
+        else { this.addDepth(depth - 1); }
  839
+      }
  840
+
  841
+      return guid;
  842
+    },
  843
+
  844
+    block: function(block) {
  845
+      var mustache = block.mustache;
  846
+      var depth, child, inverse, inverseGuid;
  847
+
  848
+      var params = this.setupStackForMustache(mustache);
  849
+
  850
+      var programGuid = this.compileProgram(block.program);
  851
+
  852
+      if(block.program.inverse) {
  853
+        inverseGuid = this.compileProgram(block.program.inverse);
  854
+        this.declare('inverse', inverseGuid);
  855
+      }
  856
+
  857
+      this.opcode('invokeProgram', programGuid, params.length, !!mustache.hash);
  858
+      this.declare('inverse', null);
  859
+      this.opcode('append');
  860
+    },
  861
+
  862
+    inverse: function(block) {
  863
+      var params = this.setupStackForMustache(block.mustache);
  864
+
  865
+      var programGuid = this.compileProgram(block.program);
  866
+
  867
+      this.declare('inverse', programGuid);
  868
+
  869
+      this.opcode('invokeProgram', null, params.length, !!block.mustache.hash);
  870
+      this.declare('inverse', null);
  871
+      this.opcode('append');
  872
+    },
  873
+
  874
+    hash: function(hash) {
  875
+      var pairs = hash.pairs, pair, val;
  876
+
  877
+      this.opcode('push', '{}');
  878
+
  879
+      for(var i=0, l=pairs.length; i<l; i++) {
  880
+        pair = pairs[i];
  881
+        val  = pair[1];
  882
+
  883
+        this.accept(val);
  884
+        this.opcode('assignToHash', pair[0]);
  885
+      }
  886
+    },
  887
+
  888
+    partial: function(partial) {
  889
+      var id = partial.id;
  890
+      this.usePartial = true;
  891
+
  892
+      if(partial.context) {
  893
+        this.ID(partial.context);
  894
+      } else {
  895
+        this.opcode('push', 'depth0');
  896
+      }
  897
+
  898
+      this.opcode('invokePartial', id.original);
  899
+      this.opcode('append');
  900
+    },
  901
+
  902
+    content: function(content) {
  903
+      this.opcode('appendContent', content.string);
  904
+    },
  905
+
  906
+    mustache: function(mustache) {
  907
+      var params = this.setupStackForMustache(mustache);
  908
+
  909
+      this.opcode('invokeMustache', params.length, mustache.id.original, !!mustache.hash);
  910
+
  911
+      if(mustache.escaped && !this.options.noEscape) {
  912
+        this.opcode('appendEscaped');
  913
+      } else {
  914
+        this.opcode('append');
  915
+      }
  916
+    },
  917
+
  918
+    ID: function(id) {
  919
+      this.addDepth(id.depth);
  920
+
  921
+      this.opcode('getContext', id.depth);
  922
+
  923
+      this.opcode('lookupWithHelpers', id.parts[0] || null, id.isScoped || false);
  924
+
  925
+      for(var i=1, l=id.parts.length; i<l; i++) {
  926
+        this.opcode('lookup', id.parts[i]);
  927
+      }
  928
+    },
  929
+
  930
+    STRING: function(string) {
  931
+      this.opcode('pushString', string.string);
  932
+    },
  933
+
  934
+    INTEGER: function(integer) {
  935
+      this.opcode('push', integer.integer);
  936
+    },
  937
+
  938
+    BOOLEAN: function(bool) {
  939
+      this.opcode('push', bool.bool);
  940
+    },
  941
+
  942
+    comment: function() {},
  943
+
  944
+    // HELPERS
  945
+    pushParams: function(params) {
  946
+      var i = params.length, param;
  947
+
  948
+      while(i--) {
  949
+        param = params[i];
  950
+
  951
+        if(this.options.stringParams) {
  952
+          if(param.depth) {
  953
+            this.addDepth(param.depth);
  954
+          }
  955
+
  956
+          this.opcode('getContext', param.depth || 0);
  957
+          this.opcode('pushStringParam', param.string);
  958
+        } else {
  959
+          this[param.type](param);
  960
+        }
  961
+      }
  962
+    },
  963
+
  964
+    opcode: function(name, val1, val2, val3) {
  965
+      this.opcodes.push(Compiler.OPCODE_MAP[name]);
  966
+      if(val1 !== undefined) { this.opcodes.push(val1); }
  967
+      if(val2 !== undefined) { this.opcodes.push(val2); }
  968
+      if(val3 !== undefined) { this.opcodes.push(val3); }
  969
+    },
  970
+
  971
+    declare: function(name, value) {
  972
+      this.opcodes.push('DECLARE');
  973
+      this.opcodes.push(name);
  974
+      this.opcodes.push(value);
  975
+    },
  976
+
  977
+    addDepth: function(depth) {
  978
+      if(depth === 0) { return; }
  979
+
  980
+      if(!this.depths[depth]) {
  981
+        this.depths[depth] = true;
  982
+        this.depths.list.push(depth);
  983
+      }
  984
+    },
  985
+
  986
+    setupStackForMustache: function(mustache) {
  987
+      var params = mustache.params;
  988
+
  989
+      this.pushParams(params);
  990
+
  991
+      if(mustache.hash) {
  992
+        this.hash(mustache.hash);
  993
+      }
  994
+
  995
+      this.ID(mustache.id);
  996
+
  997
+      return params;
  998
+    }
  999
+  };
  1000
+
  1001
+  JavaScriptCompiler.prototype = {
  1002
+    // PUBLIC API: You can override these methods in a subclass to provide
  1003
+    // alternative compiled forms for name lookup and buffering semantics
  1004
+    nameLookup: function(parent, name, type) {
  1005
+      if (/^[0-9]+$/.test(name)) {
  1006
+        return parent + "[" + name + "]";
  1007
+      } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
  1008
+        return parent + "." + name;
  1009
+      }
  1010
+      else {
  1011
+        return parent + "['" + name + "']";
  1012
+      }
  1013
+    },
  1014
+
  1015
+    appendToBuffer: function(string) {
  1016
+      if (this.environment.isSimple) {
  1017
+        return "return " + string + ";";
  1018
+      } else {
  1019
+        return "buffer += " + string + ";";
  1020
+      }
  1021
+    },
  1022
+
  1023
+    initializeBuffer: function() {
  1024
+      return this.quotedString("");
  1025
+    },
  1026
+
  1027
+    namespace: "Handlebars",
  1028
+    // END PUBLIC API
  1029
+
  1030
+    compile: function(environment, options, context, asObject) {
  1031
+      this.environment = environment;
  1032
+      this.options = options || {};
  1033
+
  1034
+      this.name = this.environment.name;
  1035
+      this.isChild = !!context;
  1036
+      this.context = context || {
  1037
+        programs: [],
  1038
+        aliases: { self: 'this' },
  1039
+        registers: {list: []}
  1040
+      };
  1041
+
  1042
+      this.preamble();
  1043
+
  1044
+      this.stackSlot = 0;
  1045
+      this.stackVars = [];
  1046
+
  1047
+      this.compileChildren(environment, options);
  1048