handlebars-source 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of handlebars-source might be problematic. Click here for more details.

Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/handlebars.js +1292 -1157
  3. data/handlebars.runtime.js +20 -8
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 42e42b5fbfef4fc72734eabaccfce5bc234bb335
4
- data.tar.gz: 3f7418ae0da21f1702031bfa667f50e4ecdbeb18
3
+ metadata.gz: f7ed070b2fd379233146670c48e214ac5a591487
4
+ data.tar.gz: 4957de32810607c0596f94202f44f7832a296a77
5
5
  SHA512:
6
- metadata.gz: 7f544f5f177b97546f3c0cfd34145c04f648426a0d759e2f0109d383c8bd0bf9240653d9a62b53668c75535b9c4729f286b81268f5e6142a8dcb3c49f06e0638
7
- data.tar.gz: 6b298ec0e1db4dc2486d34be2e2bb24cd21cbb98d2c10ff5722ebafcd8db6025b7aec61115ddaff1a07b0f17bdf0ff903304e310f93506d633d707361efb17dc
6
+ metadata.gz: 44792c0ed6c83f3e3434bf2f06454015a897d55a0417006a4845dec1f6895f3b6f1696e2542591da36a0a883dffdbdba9e06c10bc172a16c37ef98535320339c
7
+ data.tar.gz: 6428de98a351d402e2ea81e6fbf8fb649fb72e1d24b7f424de3b53db7d6dfe061461137ab8019b59ef8afb98bbfb97b44edbdd5d229309869890c04ee5ca304d
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
 
3
- handlebars v1.2.1
3
+ handlebars v1.3.0
4
4
 
5
5
  Copyright (C) 2011 by Yehuda Katz
6
6
 
@@ -132,13 +132,25 @@ var __module5__ = (function() {
132
132
 
133
133
  var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
134
134
 
135
- function Exception(/* message */) {
136
- var tmp = Error.prototype.constructor.apply(this, arguments);
135
+ function Exception(message, node) {
136
+ var line;
137
+ if (node && node.firstLine) {
138
+ line = node.firstLine;
139
+
140
+ message += ' - ' + line + ':' + node.firstColumn;
141
+ }
142
+
143
+ var tmp = Error.prototype.constructor.call(this, message);
137
144
 
138
145
  // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
139
146
  for (var idx = 0; idx < errorProps.length; idx++) {
140
147
  this[errorProps[idx]] = tmp[errorProps[idx]];
141
148
  }
149
+
150
+ if (line) {
151
+ this.lineNumber = line;
152
+ this.column = node.firstColumn;
153
+ }
142
154
  }
143
155
 
144
156
  Exception.prototype = new Error();
@@ -154,7 +166,7 @@ var __module2__ = (function(__dependency1__, __dependency2__) {
154
166
  var Utils = __dependency1__;
155
167
  var Exception = __dependency2__;
156
168
 
157
- var VERSION = "1.2.1";
169
+ var VERSION = "1.3.0";
158
170
  __exports__.VERSION = VERSION;var COMPILER_REVISION = 4;
159
171
  __exports__.COMPILER_REVISION = COMPILER_REVISION;
160
172
  var REVISION_CHANGES = {
@@ -206,7 +218,7 @@ var __module2__ = (function(__dependency1__, __dependency2__) {
206
218
  if(arguments.length === 2) {
207
219
  return undefined;
208
220
  } else {
209
- throw new Error("Missing helper: '" + arg + "'");
221
+ throw new Exception("Missing helper: '" + arg + "'");
210
222
  }
211
223
  });
212
224
 
@@ -350,11 +362,11 @@ var __module6__ = (function(__dependency1__, __dependency2__, __dependency3__) {
350
362
  if (compilerRevision < currentRevision) {
351
363
  var runtimeVersions = REVISION_CHANGES[currentRevision],
352
364
  compilerVersions = REVISION_CHANGES[compilerRevision];
353
- throw new Error("Template was precompiled with an older version of Handlebars than the current runtime. "+
365
+ throw new Exception("Template was precompiled with an older version of Handlebars than the current runtime. "+
354
366
  "Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").");
355
367
  } else {
356
368
  // Use the embedded version info since the runtime doesn't know about this revision yet
357
- throw new Error("Template was precompiled with a newer version of Handlebars than the current runtime. "+
369
+ throw new Exception("Template was precompiled with a newer version of Handlebars than the current runtime. "+
358
370
  "Please update your runtime to a newer version ("+compilerInfo[1]+").");
359
371
  }
360
372
  }
@@ -364,7 +376,7 @@ var __module6__ = (function(__dependency1__, __dependency2__, __dependency3__) {
364
376
 
365
377
  function template(templateSpec, env) {
366
378
  if (!env) {
367
- throw new Error("No environment passed to template");
379
+ throw new Exception("No environment passed to template");
368
380
  }
369
381
 
370
382
  // Note: Using env.VM references rather than local var references throughout this section to allow
@@ -520,23 +532,52 @@ var __module7__ = (function(__dependency1__) {
520
532
  var __exports__;
521
533
  var Exception = __dependency1__;
522
534
 
535
+ function LocationInfo(locInfo){
536
+ locInfo = locInfo || {};
537
+ this.firstLine = locInfo.first_line;
538
+ this.firstColumn = locInfo.first_column;
539
+ this.lastColumn = locInfo.last_column;
540
+ this.lastLine = locInfo.last_line;
541
+ }
542
+
523
543
  var AST = {
524
- ProgramNode: function(statements, inverseStrip, inverse) {
544
+ ProgramNode: function(statements, inverseStrip, inverse, locInfo) {
545
+ var inverseLocationInfo, firstInverseNode;
546
+ if (arguments.length === 3) {
547
+ locInfo = inverse;
548
+ inverse = null;
549
+ } else if (arguments.length === 2) {
550
+ locInfo = inverseStrip;
551
+ inverseStrip = null;
552
+ }
553
+
554
+ LocationInfo.call(this, locInfo);
525
555
  this.type = "program";
526
556
  this.statements = statements;
527
557
  this.strip = {};
528
558
 
529
559
  if(inverse) {
530
- this.inverse = new AST.ProgramNode(inverse, inverseStrip);
560
+ firstInverseNode = inverse[0];
561
+ if (firstInverseNode) {
562
+ inverseLocationInfo = {
563
+ first_line: firstInverseNode.firstLine,
564
+ last_line: firstInverseNode.lastLine,
565
+ last_column: firstInverseNode.lastColumn,
566
+ first_column: firstInverseNode.firstColumn
567
+ };
568
+ this.inverse = new AST.ProgramNode(inverse, inverseStrip, inverseLocationInfo);
569
+ } else {
570
+ this.inverse = new AST.ProgramNode(inverse, inverseStrip);
571
+ }
531
572
  this.strip.right = inverseStrip.left;
532
573
  } else if (inverseStrip) {
533
574
  this.strip.left = inverseStrip.right;
534
575
  }
535
576
  },
536
577
 
537
- MustacheNode: function(rawParams, hash, open, strip) {
578
+ MustacheNode: function(rawParams, hash, open, strip, locInfo) {
579
+ LocationInfo.call(this, locInfo);
538
580
  this.type = "mustache";
539
- this.hash = hash;
540
581
  this.strip = strip;
541
582
 
542
583
  // Open may be a string parsed from the parser or a passed boolean flag
@@ -548,6 +589,29 @@ var __module7__ = (function(__dependency1__) {
548
589
  this.escaped = !!open;
549
590
  }
550
591
 
592
+ if (rawParams instanceof AST.SexprNode) {
593
+ this.sexpr = rawParams;
594
+ } else {
595
+ // Support old AST API
596
+ this.sexpr = new AST.SexprNode(rawParams, hash);
597
+ }
598
+
599
+ this.sexpr.isRoot = true;
600
+
601
+ // Support old AST API that stored this info in MustacheNode
602
+ this.id = this.sexpr.id;
603
+ this.params = this.sexpr.params;
604
+ this.hash = this.sexpr.hash;
605
+ this.eligibleHelper = this.sexpr.eligibleHelper;
606
+ this.isHelper = this.sexpr.isHelper;
607
+ },
608
+
609
+ SexprNode: function(rawParams, hash, locInfo) {
610
+ LocationInfo.call(this, locInfo);
611
+
612
+ this.type = "sexpr";
613
+ this.hash = hash;
614
+
551
615
  var id = this.id = rawParams[0];
552
616
  var params = this.params = rawParams.slice(1);
553
617
 
@@ -565,19 +629,22 @@ var __module7__ = (function(__dependency1__) {
565
629
  // pass or at runtime.
566
630
  },
567
631
 
568
- PartialNode: function(partialName, context, strip) {
632
+ PartialNode: function(partialName, context, strip, locInfo) {
633
+ LocationInfo.call(this, locInfo);
569
634
  this.type = "partial";
570
635
  this.partialName = partialName;
571
636
  this.context = context;
572
637
  this.strip = strip;
573
638
  },
574
639
 
575
- BlockNode: function(mustache, program, inverse, close) {
576
- if(mustache.id.original !== close.path.original) {
577
- throw new Exception(mustache.id.original + " doesn't match " + close.path.original);
640
+ BlockNode: function(mustache, program, inverse, close, locInfo) {
641
+ LocationInfo.call(this, locInfo);
642
+
643
+ if(mustache.sexpr.id.original !== close.path.original) {
644
+ throw new Exception(mustache.sexpr.id.original + " doesn't match " + close.path.original, this);
578
645
  }
579
646
 
580
- this.type = "block";
647
+ this.type = 'block';
581
648
  this.mustache = mustache;
582
649
  this.program = program;
583
650
  this.inverse = inverse;
@@ -595,17 +662,20 @@ var __module7__ = (function(__dependency1__) {
595
662
  }
596
663
  },
597
664
 
598
- ContentNode: function(string) {
665
+ ContentNode: function(string, locInfo) {
666
+ LocationInfo.call(this, locInfo);
599
667
  this.type = "content";
600
668
  this.string = string;
601
669
  },
602
670
 
603
- HashNode: function(pairs) {
671
+ HashNode: function(pairs, locInfo) {
672
+ LocationInfo.call(this, locInfo);
604
673
  this.type = "hash";
605
674
  this.pairs = pairs;
606
675
  },
607
676
 
608
- IdNode: function(parts) {
677
+ IdNode: function(parts, locInfo) {
678
+ LocationInfo.call(this, locInfo);
609
679
  this.type = "ID";
610
680
 
611
681
  var original = "",
@@ -617,11 +687,16 @@ var __module7__ = (function(__dependency1__) {
617
687
  original += (parts[i].separator || '') + part;
618
688
 
619
689
  if (part === ".." || part === "." || part === "this") {
620
- if (dig.length > 0) { throw new Exception("Invalid path: " + original); }
621
- else if (part === "..") { depth++; }
622
- else { this.isScoped = true; }
690
+ if (dig.length > 0) {
691
+ throw new Exception("Invalid path: " + original, this);
692
+ } else if (part === "..") {
693
+ depth++;
694
+ } else {
695
+ this.isScoped = true;
696
+ }
697
+ } else {
698
+ dig.push(part);
623
699
  }
624
- else { dig.push(part); }
625
700
  }
626
701
 
627
702
  this.original = original;
@@ -636,37 +711,43 @@ var __module7__ = (function(__dependency1__) {
636
711
  this.stringModeValue = this.string;
637
712
  },
638
713
 
639
- PartialNameNode: function(name) {
714
+ PartialNameNode: function(name, locInfo) {
715
+ LocationInfo.call(this, locInfo);
640
716
  this.type = "PARTIAL_NAME";
641
717
  this.name = name.original;
642
718
  },
643
719
 
644
- DataNode: function(id) {
720
+ DataNode: function(id, locInfo) {
721
+ LocationInfo.call(this, locInfo);
645
722
  this.type = "DATA";
646
723
  this.id = id;
647
724
  },
648
725
 
649
- StringNode: function(string) {
726
+ StringNode: function(string, locInfo) {
727
+ LocationInfo.call(this, locInfo);
650
728
  this.type = "STRING";
651
729
  this.original =
652
730
  this.string =
653
731
  this.stringModeValue = string;
654
732
  },
655
733
 
656
- IntegerNode: function(integer) {
734
+ IntegerNode: function(integer, locInfo) {
735
+ LocationInfo.call(this, locInfo);
657
736
  this.type = "INTEGER";
658
737
  this.original =
659
738
  this.integer = integer;
660
739
  this.stringModeValue = Number(integer);
661
740
  },
662
741
 
663
- BooleanNode: function(bool) {
742
+ BooleanNode: function(bool, locInfo) {
743
+ LocationInfo.call(this, locInfo);
664
744
  this.type = "BOOLEAN";
665
745
  this.bool = bool;
666
746
  this.stringModeValue = bool === "true";
667
747
  },
668
748
 
669
- CommentNode: function(comment) {
749
+ CommentNode: function(comment, locInfo) {
750
+ LocationInfo.call(this, locInfo);
670
751
  this.type = "comment";
671
752
  this.comment = comment;
672
753
  }
@@ -687,103 +768,105 @@ var __module9__ = (function() {
687
768
  var handlebars = (function(){
688
769
  var parser = {trace: function trace() { },
689
770
  yy: {},
690
- symbols_: {"error":2,"root":3,"statements":4,"EOF":5,"program":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,"CLOSE_UNESCAPED":24,"OPEN_PARTIAL":25,"partialName":26,"partial_option0":27,"inMustache_repetition0":28,"inMustache_option0":29,"dataName":30,"param":31,"STRING":32,"INTEGER":33,"BOOLEAN":34,"hash":35,"hash_repetition_plus0":36,"hashSegment":37,"ID":38,"EQUALS":39,"DATA":40,"pathSegments":41,"SEP":42,"$accept":0,"$end":1},
691
- 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:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",32:"STRING",33:"INTEGER",34:"BOOLEAN",38:"ID",39:"EQUALS",40:"DATA",42:"SEP"},
692
- productions_: [0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[35,1],[37,3],[26,1],[26,1],[26,1],[30,2],[21,1],[41,3],[41,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[36,1],[36,2]],
771
+ symbols_: {"error":2,"root":3,"statements":4,"EOF":5,"program":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"sexpr":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"CLOSE_UNESCAPED":24,"OPEN_PARTIAL":25,"partialName":26,"partial_option0":27,"sexpr_repetition0":28,"sexpr_option0":29,"dataName":30,"param":31,"STRING":32,"INTEGER":33,"BOOLEAN":34,"OPEN_SEXPR":35,"CLOSE_SEXPR":36,"hash":37,"hash_repetition_plus0":38,"hashSegment":39,"ID":40,"EQUALS":41,"DATA":42,"pathSegments":43,"SEP":44,"$accept":0,"$end":1},
772
+ 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:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",32:"STRING",33:"INTEGER",34:"BOOLEAN",35:"OPEN_SEXPR",36:"CLOSE_SEXPR",40:"ID",41:"EQUALS",42:"DATA",44:"SEP"},
773
+ productions_: [0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[31,3],[37,1],[39,3],[26,1],[26,1],[26,1],[30,2],[21,1],[43,3],[43,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[38,1],[38,2]],
693
774
  performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
694
775
 
695
776
  var $0 = $$.length - 1;
696
777
  switch (yystate) {
697
- case 1: return new yy.ProgramNode($$[$0-1]);
778
+ case 1: return new yy.ProgramNode($$[$0-1], this._$);
698
779
  break;
699
- case 2: return new yy.ProgramNode([]);
780
+ case 2: return new yy.ProgramNode([], this._$);
700
781
  break;
701
- case 3:this.$ = new yy.ProgramNode([], $$[$0-1], $$[$0]);
782
+ case 3:this.$ = new yy.ProgramNode([], $$[$0-1], $$[$0], this._$);
702
783
  break;
703
- case 4:this.$ = new yy.ProgramNode($$[$0-2], $$[$0-1], $$[$0]);
784
+ case 4:this.$ = new yy.ProgramNode($$[$0-2], $$[$0-1], $$[$0], this._$);
704
785
  break;
705
- case 5:this.$ = new yy.ProgramNode($$[$0-1], $$[$0], []);
786
+ case 5:this.$ = new yy.ProgramNode($$[$0-1], $$[$0], [], this._$);
706
787
  break;
707
- case 6:this.$ = new yy.ProgramNode($$[$0]);
788
+ case 6:this.$ = new yy.ProgramNode($$[$0], this._$);
708
789
  break;
709
- case 7:this.$ = new yy.ProgramNode([]);
790
+ case 7:this.$ = new yy.ProgramNode([], this._$);
710
791
  break;
711
- case 8:this.$ = new yy.ProgramNode([]);
792
+ case 8:this.$ = new yy.ProgramNode([], this._$);
712
793
  break;
713
794
  case 9:this.$ = [$$[$0]];
714
795
  break;
715
796
  case 10: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
716
797
  break;
717
- case 11:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0]);
798
+ case 11:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0], this._$);
718
799
  break;
719
- case 12:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0]);
800
+ case 12:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0], this._$);
720
801
  break;
721
802
  case 13:this.$ = $$[$0];
722
803
  break;
723
804
  case 14:this.$ = $$[$0];
724
805
  break;
725
- case 15:this.$ = new yy.ContentNode($$[$0]);
806
+ case 15:this.$ = new yy.ContentNode($$[$0], this._$);
726
807
  break;
727
- case 16:this.$ = new yy.CommentNode($$[$0]);
808
+ case 16:this.$ = new yy.CommentNode($$[$0], this._$);
728
809
  break;
729
- case 17:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0]));
810
+ case 17:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
730
811
  break;
731
- case 18:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0]));
812
+ case 18:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
732
813
  break;
733
814
  case 19:this.$ = {path: $$[$0-1], strip: stripFlags($$[$0-2], $$[$0])};
734
815
  break;
735
- case 20:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0]));
816
+ case 20:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
736
817
  break;
737
- case 21:this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], $$[$0-2], stripFlags($$[$0-2], $$[$0]));
818
+ case 21:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
738
819
  break;
739
- case 22:this.$ = new yy.PartialNode($$[$0-2], $$[$0-1], stripFlags($$[$0-3], $$[$0]));
820
+ case 22:this.$ = new yy.PartialNode($$[$0-2], $$[$0-1], stripFlags($$[$0-3], $$[$0]), this._$);
740
821
  break;
741
822
  case 23:this.$ = stripFlags($$[$0-1], $$[$0]);
742
823
  break;
743
- case 24:this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]];
824
+ case 24:this.$ = new yy.SexprNode([$$[$0-2]].concat($$[$0-1]), $$[$0], this._$);
744
825
  break;
745
- case 25:this.$ = [[$$[$0]], null];
826
+ case 25:this.$ = new yy.SexprNode([$$[$0]], null, this._$);
746
827
  break;
747
828
  case 26:this.$ = $$[$0];
748
829
  break;
749
- case 27:this.$ = new yy.StringNode($$[$0]);
830
+ case 27:this.$ = new yy.StringNode($$[$0], this._$);
750
831
  break;
751
- case 28:this.$ = new yy.IntegerNode($$[$0]);
832
+ case 28:this.$ = new yy.IntegerNode($$[$0], this._$);
752
833
  break;
753
- case 29:this.$ = new yy.BooleanNode($$[$0]);
834
+ case 29:this.$ = new yy.BooleanNode($$[$0], this._$);
754
835
  break;
755
836
  case 30:this.$ = $$[$0];
756
837
  break;
757
- case 31:this.$ = new yy.HashNode($$[$0]);
838
+ case 31:$$[$0-1].isHelper = true; this.$ = $$[$0-1];
839
+ break;
840
+ case 32:this.$ = new yy.HashNode($$[$0], this._$);
758
841
  break;
759
- case 32:this.$ = [$$[$0-2], $$[$0]];
842
+ case 33:this.$ = [$$[$0-2], $$[$0]];
760
843
  break;
761
- case 33:this.$ = new yy.PartialNameNode($$[$0]);
844
+ case 34:this.$ = new yy.PartialNameNode($$[$0], this._$);
762
845
  break;
763
- case 34:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0]));
846
+ case 35:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0], this._$), this._$);
764
847
  break;
765
- case 35:this.$ = new yy.PartialNameNode(new yy.IntegerNode($$[$0]));
848
+ case 36:this.$ = new yy.PartialNameNode(new yy.IntegerNode($$[$0], this._$));
766
849
  break;
767
- case 36:this.$ = new yy.DataNode($$[$0]);
850
+ case 37:this.$ = new yy.DataNode($$[$0], this._$);
768
851
  break;
769
- case 37:this.$ = new yy.IdNode($$[$0]);
852
+ case 38:this.$ = new yy.IdNode($$[$0], this._$);
770
853
  break;
771
- case 38: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2];
854
+ case 39: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2];
772
855
  break;
773
- case 39:this.$ = [{part: $$[$0]}];
856
+ case 40:this.$ = [{part: $$[$0]}];
774
857
  break;
775
- case 42:this.$ = [];
858
+ case 43:this.$ = [];
776
859
  break;
777
- case 43:$$[$0-1].push($$[$0]);
860
+ case 44:$$[$0-1].push($$[$0]);
778
861
  break;
779
- case 46:this.$ = [$$[$0]];
862
+ case 47:this.$ = [$$[$0]];
780
863
  break;
781
- case 47:$$[$0-1].push($$[$0]);
864
+ case 48:$$[$0-1].push($$[$0]);
782
865
  break;
783
866
  }
784
867
  },
785
- table: [{3:1,4:2,5:[1,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],25:[1,15]},{1:[3]},{5:[1,16],8:17,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],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],25:[2,16]},{17:23,21:24,30:25,38:[1,28],40:[1,27],41:26},{17:29,21:24,30:25,38:[1,28],40:[1,27],41:26},{17:30,21:24,30:25,38:[1,28],40:[1,27],41:26},{17:31,21:24,30:25,38:[1,28],40:[1,27],41:26},{21:33,26:32,32:[1,34],33:[1,35],38:[1,28],41:26},{1:[2,1]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{10:36,20:[1,37]},{4:38,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,7],22:[1,13],23:[1,14],25:[1,15]},{7:39,8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,6],22:[1,13],23:[1,14],25:[1,15]},{17:23,18:[1,40],21:24,30:25,38:[1,28],40:[1,27],41:26},{10:41,20:[1,37]},{18:[1,42]},{18:[2,42],24:[2,42],28:43,32:[2,42],33:[2,42],34:[2,42],38:[2,42],40:[2,42]},{18:[2,25],24:[2,25]},{18:[2,37],24:[2,37],32:[2,37],33:[2,37],34:[2,37],38:[2,37],40:[2,37],42:[1,44]},{21:45,38:[1,28],41:26},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],38:[2,39],40:[2,39],42:[2,39]},{18:[1,46]},{18:[1,47]},{24:[1,48]},{18:[2,40],21:50,27:49,38:[1,28],41:26},{18:[2,33],38:[2,33]},{18:[2,34],38:[2,34]},{18:[2,35],38:[2,35]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{21:51,38:[1,28],41:26},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,3],22:[1,13],23:[1,14],25:[1,15]},{4:52,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,5],22:[1,13],23:[1,14],25:[1,15]},{14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]},{18:[2,44],21:56,24:[2,44],29:53,30:60,31:54,32:[1,57],33:[1,58],34:[1,59],35:55,36:61,37:62,38:[1,63],40:[1,27],41:26},{38:[1,64]},{18:[2,36],24:[2,36],32:[2,36],33:[2,36],34:[2,36],38:[2,36],40:[2,36]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,65]},{18:[2,41]},{18:[1,66]},{8:17,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],25:[1,15]},{18:[2,24],24:[2,24]},{18:[2,43],24:[2,43],32:[2,43],33:[2,43],34:[2,43],38:[2,43],40:[2,43]},{18:[2,45],24:[2,45]},{18:[2,26],24:[2,26],32:[2,26],33:[2,26],34:[2,26],38:[2,26],40:[2,26]},{18:[2,27],24:[2,27],32:[2,27],33:[2,27],34:[2,27],38:[2,27],40:[2,27]},{18:[2,28],24:[2,28],32:[2,28],33:[2,28],34:[2,28],38:[2,28],40:[2,28]},{18:[2,29],24:[2,29],32:[2,29],33:[2,29],34:[2,29],38:[2,29],40:[2,29]},{18:[2,30],24:[2,30],32:[2,30],33:[2,30],34:[2,30],38:[2,30],40:[2,30]},{18:[2,31],24:[2,31],37:67,38:[1,68]},{18:[2,46],24:[2,46],38:[2,46]},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],38:[2,39],39:[1,69],40:[2,39],42:[2,39]},{18:[2,38],24:[2,38],32:[2,38],33:[2,38],34:[2,38],38:[2,38],40:[2,38],42:[2,38]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{18:[2,47],24:[2,47],38:[2,47]},{39:[1,69]},{21:56,30:60,31:70,32:[1,57],33:[1,58],34:[1,59],38:[1,28],40:[1,27],41:26},{18:[2,32],24:[2,32],38:[2,32]}],
786
- defaultActions: {3:[2,2],16:[2,1],50:[2,41]},
868
+ table: [{3:1,4:2,5:[1,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],25:[1,15]},{1:[3]},{5:[1,16],8:17,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],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],25:[2,16]},{17:23,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:29,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:30,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:31,21:24,30:25,40:[1,28],42:[1,27],43:26},{21:33,26:32,32:[1,34],33:[1,35],40:[1,28],43:26},{1:[2,1]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{10:36,20:[1,37]},{4:38,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,7],22:[1,13],23:[1,14],25:[1,15]},{7:39,8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,6],22:[1,13],23:[1,14],25:[1,15]},{17:23,18:[1,40],21:24,30:25,40:[1,28],42:[1,27],43:26},{10:41,20:[1,37]},{18:[1,42]},{18:[2,43],24:[2,43],28:43,32:[2,43],33:[2,43],34:[2,43],35:[2,43],36:[2,43],40:[2,43],42:[2,43]},{18:[2,25],24:[2,25],36:[2,25]},{18:[2,38],24:[2,38],32:[2,38],33:[2,38],34:[2,38],35:[2,38],36:[2,38],40:[2,38],42:[2,38],44:[1,44]},{21:45,40:[1,28],43:26},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],42:[2,40],44:[2,40]},{18:[1,46]},{18:[1,47]},{24:[1,48]},{18:[2,41],21:50,27:49,40:[1,28],43:26},{18:[2,34],40:[2,34]},{18:[2,35],40:[2,35]},{18:[2,36],40:[2,36]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{21:51,40:[1,28],43:26},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,3],22:[1,13],23:[1,14],25:[1,15]},{4:52,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,5],22:[1,13],23:[1,14],25:[1,15]},{14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]},{18:[2,45],21:56,24:[2,45],29:53,30:60,31:54,32:[1,57],33:[1,58],34:[1,59],35:[1,61],36:[2,45],37:55,38:62,39:63,40:[1,64],42:[1,27],43:26},{40:[1,65]},{18:[2,37],24:[2,37],32:[2,37],33:[2,37],34:[2,37],35:[2,37],36:[2,37],40:[2,37],42:[2,37]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,66]},{18:[2,42]},{18:[1,67]},{8:17,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],25:[1,15]},{18:[2,24],24:[2,24],36:[2,24]},{18:[2,44],24:[2,44],32:[2,44],33:[2,44],34:[2,44],35:[2,44],36:[2,44],40:[2,44],42:[2,44]},{18:[2,46],24:[2,46],36:[2,46]},{18:[2,26],24:[2,26],32:[2,26],33:[2,26],34:[2,26],35:[2,26],36:[2,26],40:[2,26],42:[2,26]},{18:[2,27],24:[2,27],32:[2,27],33:[2,27],34:[2,27],35:[2,27],36:[2,27],40:[2,27],42:[2,27]},{18:[2,28],24:[2,28],32:[2,28],33:[2,28],34:[2,28],35:[2,28],36:[2,28],40:[2,28],42:[2,28]},{18:[2,29],24:[2,29],32:[2,29],33:[2,29],34:[2,29],35:[2,29],36:[2,29],40:[2,29],42:[2,29]},{18:[2,30],24:[2,30],32:[2,30],33:[2,30],34:[2,30],35:[2,30],36:[2,30],40:[2,30],42:[2,30]},{17:68,21:24,30:25,40:[1,28],42:[1,27],43:26},{18:[2,32],24:[2,32],36:[2,32],39:69,40:[1,70]},{18:[2,47],24:[2,47],36:[2,47],40:[2,47]},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],41:[1,71],42:[2,40],44:[2,40]},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],35:[2,39],36:[2,39],40:[2,39],42:[2,39],44:[2,39]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{36:[1,72]},{18:[2,48],24:[2,48],36:[2,48],40:[2,48]},{41:[1,71]},{21:56,30:60,31:73,32:[1,57],33:[1,58],34:[1,59],35:[1,61],40:[1,28],42:[1,27],43:26},{18:[2,31],24:[2,31],32:[2,31],33:[2,31],34:[2,31],35:[2,31],36:[2,31],40:[2,31],42:[2,31]},{18:[2,33],24:[2,33],36:[2,33],40:[2,33]}],
869
+ defaultActions: {3:[2,2],16:[2,1],50:[2,42]},
787
870
  parseError: function parseError(str, hash) {
788
871
  throw new Error(str);
789
872
  },
@@ -1101,64 +1184,68 @@ var __module9__ = (function() {
1101
1184
  break;
1102
1185
  case 3:strip(0,4); this.popState(); return 15;
1103
1186
  break;
1104
- case 4:return 25;
1187
+ case 4:return 35;
1188
+ break;
1189
+ case 5:return 36;
1190
+ break;
1191
+ case 6:return 25;
1105
1192
  break;
1106
- case 5:return 16;
1193
+ case 7:return 16;
1107
1194
  break;
1108
- case 6:return 20;
1195
+ case 8:return 20;
1109
1196
  break;
1110
- case 7:return 19;
1197
+ case 9:return 19;
1111
1198
  break;
1112
- case 8:return 19;
1199
+ case 10:return 19;
1113
1200
  break;
1114
- case 9:return 23;
1201
+ case 11:return 23;
1115
1202
  break;
1116
- case 10:return 22;
1203
+ case 12:return 22;
1117
1204
  break;
1118
- case 11:this.popState(); this.begin('com');
1205
+ case 13:this.popState(); this.begin('com');
1119
1206
  break;
1120
- case 12:strip(3,5); this.popState(); return 15;
1207
+ case 14:strip(3,5); this.popState(); return 15;
1121
1208
  break;
1122
- case 13:return 22;
1209
+ case 15:return 22;
1123
1210
  break;
1124
- case 14:return 39;
1211
+ case 16:return 41;
1125
1212
  break;
1126
- case 15:return 38;
1213
+ case 17:return 40;
1127
1214
  break;
1128
- case 16:return 38;
1215
+ case 18:return 40;
1129
1216
  break;
1130
- case 17:return 42;
1217
+ case 19:return 44;
1131
1218
  break;
1132
- case 18:// ignore whitespace
1219
+ case 20:// ignore whitespace
1133
1220
  break;
1134
- case 19:this.popState(); return 24;
1221
+ case 21:this.popState(); return 24;
1135
1222
  break;
1136
- case 20:this.popState(); return 18;
1223
+ case 22:this.popState(); return 18;
1137
1224
  break;
1138
- case 21:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 32;
1225
+ case 23:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 32;
1139
1226
  break;
1140
- case 22:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 32;
1227
+ case 24:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 32;
1141
1228
  break;
1142
- case 23:return 40;
1229
+ case 25:return 42;
1143
1230
  break;
1144
- case 24:return 34;
1231
+ case 26:return 34;
1145
1232
  break;
1146
- case 25:return 34;
1233
+ case 27:return 34;
1147
1234
  break;
1148
- case 26:return 33;
1235
+ case 28:return 33;
1149
1236
  break;
1150
- case 27:return 38;
1237
+ case 29:return 40;
1151
1238
  break;
1152
- case 28:yy_.yytext = strip(1,2); return 38;
1239
+ case 30:yy_.yytext = strip(1,2); return 40;
1153
1240
  break;
1154
- case 29:return 'INVALID';
1241
+ case 31:return 'INVALID';
1155
1242
  break;
1156
- case 30:return 5;
1243
+ case 32:return 5;
1157
1244
  break;
1158
1245
  }
1159
1246
  };
1160
- lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s])))/,/^(?:false(?=([~}\s])))/,/^(?:-?[0-9]+(?=([~}\s])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
1161
- lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"INITIAL":{"rules":[0,1,30],"inclusive":true}};
1247
+ lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?=([~}\s)])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
1248
+ lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"INITIAL":{"rules":[0,1,32],"inclusive":true}};
1162
1249
  return lexer;})()
1163
1250
  parser.lexer = lexer;
1164
1251
  function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
@@ -1189,1382 +1276,1428 @@ var __module8__ = (function(__dependency1__, __dependency2__) {
1189
1276
  return __exports__;
1190
1277
  })(__module9__, __module7__);
1191
1278
 
1192
- // handlebars/compiler/javascript-compiler.js
1193
- var __module11__ = (function(__dependency1__) {
1279
+ // handlebars/compiler/compiler.js
1280
+ var __module10__ = (function(__dependency1__) {
1194
1281
  "use strict";
1195
- var __exports__;
1196
- var COMPILER_REVISION = __dependency1__.COMPILER_REVISION;
1197
- var REVISION_CHANGES = __dependency1__.REVISION_CHANGES;
1198
- var log = __dependency1__.log;
1282
+ var __exports__ = {};
1283
+ var Exception = __dependency1__;
1199
1284
 
1200
- function Literal(value) {
1201
- this.value = value;
1202
- }
1285
+ function Compiler() {}
1203
1286
 
1204
- function JavaScriptCompiler() {}
1287
+ __exports__.Compiler = Compiler;// the foundHelper register will disambiguate helper lookup from finding a
1288
+ // function in a context. This is necessary for mustache compatibility, which
1289
+ // requires that context functions in blocks are evaluated by blockHelperMissing,
1290
+ // and then proceed as if the resulting value was provided to blockHelperMissing.
1205
1291
 
1206
- JavaScriptCompiler.prototype = {
1207
- // PUBLIC API: You can override these methods in a subclass to provide
1208
- // alternative compiled forms for name lookup and buffering semantics
1209
- nameLookup: function(parent, name /* , type*/) {
1210
- var wrap,
1211
- ret;
1212
- if (parent.indexOf('depth') === 0) {
1213
- wrap = true;
1214
- }
1292
+ Compiler.prototype = {
1293
+ compiler: Compiler,
1215
1294
 
1216
- if (/^[0-9]+$/.test(name)) {
1217
- ret = parent + "[" + name + "]";
1218
- } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
1219
- ret = parent + "." + name;
1220
- }
1221
- else {
1222
- ret = parent + "['" + name + "']";
1223
- }
1295
+ disassemble: function() {
1296
+ var opcodes = this.opcodes, opcode, out = [], params, param;
1224
1297
 
1225
- if (wrap) {
1226
- return '(' + parent + ' && ' + ret + ')';
1227
- } else {
1228
- return ret;
1298
+ for (var i=0, l=opcodes.length; i<l; i++) {
1299
+ opcode = opcodes[i];
1300
+
1301
+ if (opcode.opcode === 'DECLARE') {
1302
+ out.push("DECLARE " + opcode.name + "=" + opcode.value);
1303
+ } else {
1304
+ params = [];
1305
+ for (var j=0; j<opcode.args.length; j++) {
1306
+ param = opcode.args[j];
1307
+ if (typeof param === "string") {
1308
+ param = "\"" + param.replace("\n", "\\n") + "\"";
1309
+ }
1310
+ params.push(param);
1311
+ }
1312
+ out.push(opcode.opcode + " " + params.join(" "));
1313
+ }
1229
1314
  }
1230
- },
1231
1315
 
1232
- compilerInfo: function() {
1233
- var revision = COMPILER_REVISION,
1234
- versions = REVISION_CHANGES[revision];
1235
- return "this.compilerInfo = ["+revision+",'"+versions+"'];\n";
1316
+ return out.join("\n");
1236
1317
  },
1237
1318
 
1238
- appendToBuffer: function(string) {
1239
- if (this.environment.isSimple) {
1240
- return "return " + string + ";";
1241
- } else {
1242
- return {
1243
- appendToBuffer: true,
1244
- content: string,
1245
- toString: function() { return "buffer += " + string + ";"; }
1246
- };
1319
+ equals: function(other) {
1320
+ var len = this.opcodes.length;
1321
+ if (other.opcodes.length !== len) {
1322
+ return false;
1247
1323
  }
1248
- },
1249
1324
 
1250
- initializeBuffer: function() {
1251
- return this.quotedString("");
1252
- },
1325
+ for (var i = 0; i < len; i++) {
1326
+ var opcode = this.opcodes[i],
1327
+ otherOpcode = other.opcodes[i];
1328
+ if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
1329
+ return false;
1330
+ }
1331
+ for (var j = 0; j < opcode.args.length; j++) {
1332
+ if (opcode.args[j] !== otherOpcode.args[j]) {
1333
+ return false;
1334
+ }
1335
+ }
1336
+ }
1253
1337
 
1254
- namespace: "Handlebars",
1255
- // END PUBLIC API
1338
+ len = this.children.length;
1339
+ if (other.children.length !== len) {
1340
+ return false;
1341
+ }
1342
+ for (i = 0; i < len; i++) {
1343
+ if (!this.children[i].equals(other.children[i])) {
1344
+ return false;
1345
+ }
1346
+ }
1256
1347
 
1257
- compile: function(environment, options, context, asObject) {
1258
- this.environment = environment;
1259
- this.options = options || {};
1348
+ return true;
1349
+ },
1260
1350
 
1261
- log('debug', this.environment.disassemble() + "\n\n");
1351
+ guid: 0,
1262
1352
 
1263
- this.name = this.environment.name;
1264
- this.isChild = !!context;
1265
- this.context = context || {
1266
- programs: [],
1267
- environments: [],
1268
- aliases: { }
1269
- };
1353
+ compile: function(program, options) {
1354
+ this.opcodes = [];
1355
+ this.children = [];
1356
+ this.depths = {list: []};
1357
+ this.options = options;
1270
1358
 
1271
- this.preamble();
1359
+ // These changes will propagate to the other compiler components
1360
+ var knownHelpers = this.options.knownHelpers;
1361
+ this.options.knownHelpers = {
1362
+ 'helperMissing': true,
1363
+ 'blockHelperMissing': true,
1364
+ 'each': true,
1365
+ 'if': true,
1366
+ 'unless': true,
1367
+ 'with': true,
1368
+ 'log': true
1369
+ };
1370
+ if (knownHelpers) {
1371
+ for (var name in knownHelpers) {
1372
+ this.options.knownHelpers[name] = knownHelpers[name];
1373
+ }
1374
+ }
1272
1375
 
1273
- this.stackSlot = 0;
1274
- this.stackVars = [];
1275
- this.registers = { list: [] };
1276
- this.compileStack = [];
1277
- this.inlineStack = [];
1376
+ return this.accept(program);
1377
+ },
1278
1378
 
1279
- this.compileChildren(environment, options);
1379
+ accept: function(node) {
1380
+ var strip = node.strip || {},
1381
+ ret;
1382
+ if (strip.left) {
1383
+ this.opcode('strip');
1384
+ }
1280
1385
 
1281
- var opcodes = environment.opcodes, opcode;
1386
+ ret = this[node.type](node);
1282
1387
 
1283
- this.i = 0;
1388
+ if (strip.right) {
1389
+ this.opcode('strip');
1390
+ }
1284
1391
 
1285
- for(var l=opcodes.length; this.i<l; this.i++) {
1286
- opcode = opcodes[this.i];
1392
+ return ret;
1393
+ },
1287
1394
 
1288
- if(opcode.opcode === 'DECLARE') {
1289
- this[opcode.name] = opcode.value;
1290
- } else {
1291
- this[opcode.opcode].apply(this, opcode.args);
1292
- }
1395
+ program: function(program) {
1396
+ var statements = program.statements;
1293
1397
 
1294
- // Reset the stripNext flag if it was not set by this operation.
1295
- if (opcode.opcode !== this.stripNext) {
1296
- this.stripNext = false;
1297
- }
1398
+ for(var i=0, l=statements.length; i<l; i++) {
1399
+ this.accept(statements[i]);
1298
1400
  }
1401
+ this.isSimple = l === 1;
1299
1402
 
1300
- // Flush any trailing content that might be pending.
1301
- this.pushSource('');
1403
+ this.depths.list = this.depths.list.sort(function(a, b) {
1404
+ return a - b;
1405
+ });
1302
1406
 
1303
- return this.createFunctionContext(asObject);
1407
+ return this;
1304
1408
  },
1305
1409
 
1306
- preamble: function() {
1307
- var out = [];
1410
+ compileProgram: function(program) {
1411
+ var result = new this.compiler().compile(program, this.options);
1412
+ var guid = this.guid++, depth;
1308
1413
 
1309
- if (!this.isChild) {
1310
- var namespace = this.namespace;
1414
+ this.usePartial = this.usePartial || result.usePartial;
1311
1415
 
1312
- var copies = "helpers = this.merge(helpers, " + namespace + ".helpers);";
1313
- if (this.environment.usePartial) { copies = copies + " partials = this.merge(partials, " + namespace + ".partials);"; }
1314
- if (this.options.data) { copies = copies + " data = data || {};"; }
1315
- out.push(copies);
1316
- } else {
1317
- out.push('');
1318
- }
1416
+ this.children[guid] = result;
1319
1417
 
1320
- if (!this.environment.isSimple) {
1321
- out.push(", buffer = " + this.initializeBuffer());
1322
- } else {
1323
- out.push("");
1418
+ for(var i=0, l=result.depths.list.length; i<l; i++) {
1419
+ depth = result.depths.list[i];
1420
+
1421
+ if(depth < 2) { continue; }
1422
+ else { this.addDepth(depth - 1); }
1324
1423
  }
1325
1424
 
1326
- // track the last context pushed into place to allow skipping the
1327
- // getContext opcode when it would be a noop
1328
- this.lastContext = 0;
1329
- this.source = out;
1425
+ return guid;
1330
1426
  },
1331
1427
 
1332
- createFunctionContext: function(asObject) {
1333
- var locals = this.stackVars.concat(this.registers.list);
1428
+ block: function(block) {
1429
+ var mustache = block.mustache,
1430
+ program = block.program,
1431
+ inverse = block.inverse;
1334
1432
 
1335
- if(locals.length > 0) {
1336
- this.source[1] = this.source[1] + ", " + locals.join(", ");
1433
+ if (program) {
1434
+ program = this.compileProgram(program);
1337
1435
  }
1338
1436
 
1339
- // Generate minimizer alias mappings
1340
- if (!this.isChild) {
1341
- for (var alias in this.context.aliases) {
1342
- if (this.context.aliases.hasOwnProperty(alias)) {
1343
- this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
1344
- }
1345
- }
1437
+ if (inverse) {
1438
+ inverse = this.compileProgram(inverse);
1346
1439
  }
1347
1440
 
1348
- if (this.source[1]) {
1349
- this.source[1] = "var " + this.source[1].substring(2) + ";";
1350
- }
1441
+ var sexpr = mustache.sexpr;
1442
+ var type = this.classifySexpr(sexpr);
1351
1443
 
1352
- // Merge children
1353
- if (!this.isChild) {
1354
- this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
1355
- }
1444
+ if (type === "helper") {
1445
+ this.helperSexpr(sexpr, program, inverse);
1446
+ } else if (type === "simple") {
1447
+ this.simpleSexpr(sexpr);
1356
1448
 
1357
- if (!this.environment.isSimple) {
1358
- this.pushSource("return buffer;");
1449
+ // now that the simple mustache is resolved, we need to
1450
+ // evaluate it by executing `blockHelperMissing`
1451
+ this.opcode('pushProgram', program);
1452
+ this.opcode('pushProgram', inverse);
1453
+ this.opcode('emptyHash');
1454
+ this.opcode('blockValue');
1455
+ } else {
1456
+ this.ambiguousSexpr(sexpr, program, inverse);
1457
+
1458
+ // now that the simple mustache is resolved, we need to
1459
+ // evaluate it by executing `blockHelperMissing`
1460
+ this.opcode('pushProgram', program);
1461
+ this.opcode('pushProgram', inverse);
1462
+ this.opcode('emptyHash');
1463
+ this.opcode('ambiguousBlockValue');
1359
1464
  }
1360
1465
 
1361
- var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
1466
+ this.opcode('append');
1467
+ },
1362
1468
 
1363
- for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
1364
- params.push("depth" + this.environment.depths.list[i]);
1365
- }
1469
+ hash: function(hash) {
1470
+ var pairs = hash.pairs, pair, val;
1366
1471
 
1367
- // Perform a second pass over the output to merge content when possible
1368
- var source = this.mergeSource();
1472
+ this.opcode('pushHash');
1369
1473
 
1370
- if (!this.isChild) {
1371
- source = this.compilerInfo()+source;
1372
- }
1474
+ for(var i=0, l=pairs.length; i<l; i++) {
1475
+ pair = pairs[i];
1476
+ val = pair[1];
1373
1477
 
1374
- if (asObject) {
1375
- params.push(source);
1478
+ if (this.options.stringParams) {
1479
+ if(val.depth) {
1480
+ this.addDepth(val.depth);
1481
+ }
1482
+ this.opcode('getContext', val.depth || 0);
1483
+ this.opcode('pushStringParam', val.stringModeValue, val.type);
1376
1484
 
1377
- return Function.apply(this, params);
1378
- } else {
1379
- var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}';
1380
- log('debug', functionSource + "\n\n");
1381
- return functionSource;
1382
- }
1383
- },
1384
- mergeSource: function() {
1385
- // WARN: We are not handling the case where buffer is still populated as the source should
1386
- // not have buffer append operations as their final action.
1387
- var source = '',
1388
- buffer;
1389
- for (var i = 0, len = this.source.length; i < len; i++) {
1390
- var line = this.source[i];
1391
- if (line.appendToBuffer) {
1392
- if (buffer) {
1393
- buffer = buffer + '\n + ' + line.content;
1394
- } else {
1395
- buffer = line.content;
1485
+ if (val.type === 'sexpr') {
1486
+ // Subexpressions get evaluated and passed in
1487
+ // in string params mode.
1488
+ this.sexpr(val);
1396
1489
  }
1397
1490
  } else {
1398
- if (buffer) {
1399
- source += 'buffer += ' + buffer + ';\n ';
1400
- buffer = undefined;
1401
- }
1402
- source += line + '\n ';
1491
+ this.accept(val);
1403
1492
  }
1493
+
1494
+ this.opcode('assignToHash', pair[0]);
1404
1495
  }
1405
- return source;
1496
+ this.opcode('popHash');
1406
1497
  },
1407
1498
 
1408
- // [blockValue]
1409
- //
1410
- // On stack, before: hash, inverse, program, value
1411
- // On stack, after: return value of blockHelperMissing
1412
- //
1413
- // The purpose of this opcode is to take a block of the form
1414
- // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
1415
- // replace it on the stack with the result of properly
1416
- // invoking blockHelperMissing.
1417
- blockValue: function() {
1418
- this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
1499
+ partial: function(partial) {
1500
+ var partialName = partial.partialName;
1501
+ this.usePartial = true;
1419
1502
 
1420
- var params = ["depth0"];
1421
- this.setupParams(0, params);
1503
+ if(partial.context) {
1504
+ this.ID(partial.context);
1505
+ } else {
1506
+ this.opcode('push', 'depth0');
1507
+ }
1422
1508
 
1423
- this.replaceStack(function(current) {
1424
- params.splice(1, 0, current);
1425
- return "blockHelperMissing.call(" + params.join(", ") + ")";
1426
- });
1509
+ this.opcode('invokePartial', partialName.name);
1510
+ this.opcode('append');
1427
1511
  },
1428
1512
 
1429
- // [ambiguousBlockValue]
1430
- //
1431
- // On stack, before: hash, inverse, program, value
1432
- // Compiler value, before: lastHelper=value of last found helper, if any
1433
- // On stack, after, if no lastHelper: same as [blockValue]
1434
- // On stack, after, if lastHelper: value
1435
- ambiguousBlockValue: function() {
1436
- this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
1513
+ content: function(content) {
1514
+ this.opcode('appendContent', content.string);
1515
+ },
1437
1516
 
1438
- var params = ["depth0"];
1439
- this.setupParams(0, params);
1517
+ mustache: function(mustache) {
1518
+ this.sexpr(mustache.sexpr);
1440
1519
 
1441
- var current = this.topStack();
1442
- params.splice(1, 0, current);
1520
+ if(mustache.escaped && !this.options.noEscape) {
1521
+ this.opcode('appendEscaped');
1522
+ } else {
1523
+ this.opcode('append');
1524
+ }
1525
+ },
1443
1526
 
1444
- // Use the options value generated from the invocation
1445
- params[params.length-1] = 'options';
1527
+ ambiguousSexpr: function(sexpr, program, inverse) {
1528
+ var id = sexpr.id,
1529
+ name = id.parts[0],
1530
+ isBlock = program != null || inverse != null;
1446
1531
 
1447
- this.pushSource("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
1532
+ this.opcode('getContext', id.depth);
1533
+
1534
+ this.opcode('pushProgram', program);
1535
+ this.opcode('pushProgram', inverse);
1536
+
1537
+ this.opcode('invokeAmbiguous', name, isBlock);
1448
1538
  },
1449
1539
 
1450
- // [appendContent]
1451
- //
1452
- // On stack, before: ...
1453
- // On stack, after: ...
1454
- //
1455
- // Appends the string value of `content` to the current buffer
1456
- appendContent: function(content) {
1457
- if (this.pendingContent) {
1458
- content = this.pendingContent + content;
1459
- }
1460
- if (this.stripNext) {
1461
- content = content.replace(/^\s+/, '');
1540
+ simpleSexpr: function(sexpr) {
1541
+ var id = sexpr.id;
1542
+
1543
+ if (id.type === 'DATA') {
1544
+ this.DATA(id);
1545
+ } else if (id.parts.length) {
1546
+ this.ID(id);
1547
+ } else {
1548
+ // Simplified ID for `this`
1549
+ this.addDepth(id.depth);
1550
+ this.opcode('getContext', id.depth);
1551
+ this.opcode('pushContext');
1462
1552
  }
1463
1553
 
1464
- this.pendingContent = content;
1554
+ this.opcode('resolvePossibleLambda');
1465
1555
  },
1466
1556
 
1467
- // [strip]
1468
- //
1469
- // On stack, before: ...
1470
- // On stack, after: ...
1471
- //
1472
- // Removes any trailing whitespace from the prior content node and flags
1473
- // the next operation for stripping if it is a content node.
1474
- strip: function() {
1475
- if (this.pendingContent) {
1476
- this.pendingContent = this.pendingContent.replace(/\s+$/, '');
1557
+ helperSexpr: function(sexpr, program, inverse) {
1558
+ var params = this.setupFullMustacheParams(sexpr, program, inverse),
1559
+ name = sexpr.id.parts[0];
1560
+
1561
+ if (this.options.knownHelpers[name]) {
1562
+ this.opcode('invokeKnownHelper', params.length, name);
1563
+ } else if (this.options.knownHelpersOnly) {
1564
+ throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
1565
+ } else {
1566
+ this.opcode('invokeHelper', params.length, name, sexpr.isRoot);
1477
1567
  }
1478
- this.stripNext = 'strip';
1479
1568
  },
1480
1569
 
1481
- // [append]
1482
- //
1483
- // On stack, before: value, ...
1484
- // On stack, after: ...
1485
- //
1486
- // Coerces `value` to a String and appends it to the current buffer.
1487
- //
1488
- // If `value` is truthy, or 0, it is coerced into a string and appended
1489
- // Otherwise, the empty string is appended
1490
- append: function() {
1491
- // Force anything that is inlined onto the stack so we don't have duplication
1492
- // when we examine local
1493
- this.flushInline();
1494
- var local = this.popStack();
1495
- this.pushSource("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
1496
- if (this.environment.isSimple) {
1497
- this.pushSource("else { " + this.appendToBuffer("''") + " }");
1570
+ sexpr: function(sexpr) {
1571
+ var type = this.classifySexpr(sexpr);
1572
+
1573
+ if (type === "simple") {
1574
+ this.simpleSexpr(sexpr);
1575
+ } else if (type === "helper") {
1576
+ this.helperSexpr(sexpr);
1577
+ } else {
1578
+ this.ambiguousSexpr(sexpr);
1498
1579
  }
1499
1580
  },
1500
1581
 
1501
- // [appendEscaped]
1502
- //
1503
- // On stack, before: value, ...
1504
- // On stack, after: ...
1505
- //
1506
- // Escape `value` and append it to the buffer
1507
- appendEscaped: function() {
1508
- this.context.aliases.escapeExpression = 'this.escapeExpression';
1582
+ ID: function(id) {
1583
+ this.addDepth(id.depth);
1584
+ this.opcode('getContext', id.depth);
1509
1585
 
1510
- this.pushSource(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
1586
+ var name = id.parts[0];
1587
+ if (!name) {
1588
+ this.opcode('pushContext');
1589
+ } else {
1590
+ this.opcode('lookupOnContext', id.parts[0]);
1591
+ }
1592
+
1593
+ for(var i=1, l=id.parts.length; i<l; i++) {
1594
+ this.opcode('lookup', id.parts[i]);
1595
+ }
1511
1596
  },
1512
1597
 
1513
- // [getContext]
1514
- //
1515
- // On stack, before: ...
1516
- // On stack, after: ...
1517
- // Compiler value, after: lastContext=depth
1518
- //
1519
- // Set the value of the `lastContext` compiler value to the depth
1520
- getContext: function(depth) {
1521
- if(this.lastContext !== depth) {
1522
- this.lastContext = depth;
1598
+ DATA: function(data) {
1599
+ this.options.data = true;
1600
+ if (data.id.isScoped || data.id.depth) {
1601
+ throw new Exception('Scoped data references are not supported: ' + data.original, data);
1602
+ }
1603
+
1604
+ this.opcode('lookupData');
1605
+ var parts = data.id.parts;
1606
+ for(var i=0, l=parts.length; i<l; i++) {
1607
+ this.opcode('lookup', parts[i]);
1523
1608
  }
1524
1609
  },
1525
1610
 
1526
- // [lookupOnContext]
1527
- //
1528
- // On stack, before: ...
1529
- // On stack, after: currentContext[name], ...
1530
- //
1531
- // Looks up the value of `name` on the current context and pushes
1532
- // it onto the stack.
1533
- lookupOnContext: function(name) {
1534
- this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
1611
+ STRING: function(string) {
1612
+ this.opcode('pushString', string.string);
1535
1613
  },
1536
1614
 
1537
- // [pushContext]
1538
- //
1539
- // On stack, before: ...
1540
- // On stack, after: currentContext, ...
1541
- //
1542
- // Pushes the value of the current context onto the stack.
1543
- pushContext: function() {
1544
- this.pushStackLiteral('depth' + this.lastContext);
1615
+ INTEGER: function(integer) {
1616
+ this.opcode('pushLiteral', integer.integer);
1545
1617
  },
1546
1618
 
1547
- // [resolvePossibleLambda]
1548
- //
1549
- // On stack, before: value, ...
1550
- // On stack, after: resolved value, ...
1551
- //
1552
- // If the `value` is a lambda, replace it on the stack by
1553
- // the return value of the lambda
1554
- resolvePossibleLambda: function() {
1555
- this.context.aliases.functionType = '"function"';
1556
-
1557
- this.replaceStack(function(current) {
1558
- return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current;
1559
- });
1619
+ BOOLEAN: function(bool) {
1620
+ this.opcode('pushLiteral', bool.bool);
1560
1621
  },
1561
1622
 
1562
- // [lookup]
1563
- //
1564
- // On stack, before: value, ...
1565
- // On stack, after: value[name], ...
1566
- //
1567
- // Replace the value on the stack with the result of looking
1568
- // up `name` on `value`
1569
- lookup: function(name) {
1570
- this.replaceStack(function(current) {
1571
- return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
1572
- });
1573
- },
1623
+ comment: function() {},
1574
1624
 
1575
- // [lookupData]
1576
- //
1577
- // On stack, before: ...
1578
- // On stack, after: data, ...
1579
- //
1580
- // Push the data lookup operator
1581
- lookupData: function() {
1582
- this.push('data');
1625
+ // HELPERS
1626
+ opcode: function(name) {
1627
+ this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
1583
1628
  },
1584
1629
 
1585
- // [pushStringParam]
1586
- //
1587
- // On stack, before: ...
1588
- // On stack, after: string, currentContext, ...
1589
- //
1590
- // This opcode is designed for use in string mode, which
1591
- // provides the string value of a parameter along with its
1592
- // depth rather than resolving it immediately.
1593
- pushStringParam: function(string, type) {
1594
- this.pushStackLiteral('depth' + this.lastContext);
1630
+ declare: function(name, value) {
1631
+ this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
1632
+ },
1595
1633
 
1596
- this.pushString(type);
1634
+ addDepth: function(depth) {
1635
+ if(depth === 0) { return; }
1597
1636
 
1598
- if (typeof string === 'string') {
1599
- this.pushString(string);
1600
- } else {
1601
- this.pushStackLiteral(string);
1637
+ if(!this.depths[depth]) {
1638
+ this.depths[depth] = true;
1639
+ this.depths.list.push(depth);
1602
1640
  }
1603
1641
  },
1604
1642
 
1605
- emptyHash: function() {
1606
- this.pushStackLiteral('{}');
1643
+ classifySexpr: function(sexpr) {
1644
+ var isHelper = sexpr.isHelper;
1645
+ var isEligible = sexpr.eligibleHelper;
1646
+ var options = this.options;
1607
1647
 
1608
- if (this.options.stringParams) {
1609
- this.register('hashTypes', '{}');
1610
- this.register('hashContexts', '{}');
1611
- }
1612
- },
1613
- pushHash: function() {
1614
- this.hash = {values: [], types: [], contexts: []};
1615
- },
1616
- popHash: function() {
1617
- var hash = this.hash;
1618
- this.hash = undefined;
1648
+ // if ambiguous, we can possibly resolve the ambiguity now
1649
+ if (isEligible && !isHelper) {
1650
+ var name = sexpr.id.parts[0];
1619
1651
 
1620
- if (this.options.stringParams) {
1621
- this.register('hashContexts', '{' + hash.contexts.join(',') + '}');
1622
- this.register('hashTypes', '{' + hash.types.join(',') + '}');
1652
+ if (options.knownHelpers[name]) {
1653
+ isHelper = true;
1654
+ } else if (options.knownHelpersOnly) {
1655
+ isEligible = false;
1656
+ }
1623
1657
  }
1624
- this.push('{\n ' + hash.values.join(',\n ') + '\n }');
1625
- },
1626
1658
 
1627
- // [pushString]
1628
- //
1629
- // On stack, before: ...
1630
- // On stack, after: quotedString(string), ...
1631
- //
1632
- // Push a quoted version of `string` onto the stack
1633
- pushString: function(string) {
1634
- this.pushStackLiteral(this.quotedString(string));
1659
+ if (isHelper) { return "helper"; }
1660
+ else if (isEligible) { return "ambiguous"; }
1661
+ else { return "simple"; }
1635
1662
  },
1636
1663
 
1637
- // [push]
1638
- //
1639
- // On stack, before: ...
1640
- // On stack, after: expr, ...
1641
- //
1642
- // Push an expression onto the stack
1643
- push: function(expr) {
1644
- this.inlineStack.push(expr);
1645
- return expr;
1646
- },
1664
+ pushParams: function(params) {
1665
+ var i = params.length, param;
1647
1666
 
1648
- // [pushLiteral]
1649
- //
1650
- // On stack, before: ...
1651
- // On stack, after: value, ...
1652
- //
1653
- // Pushes a value onto the stack. This operation prevents
1654
- // the compiler from creating a temporary variable to hold
1655
- // it.
1656
- pushLiteral: function(value) {
1657
- this.pushStackLiteral(value);
1658
- },
1667
+ while(i--) {
1668
+ param = params[i];
1659
1669
 
1660
- // [pushProgram]
1661
- //
1662
- // On stack, before: ...
1663
- // On stack, after: program(guid), ...
1664
- //
1665
- // Push a program expression onto the stack. This takes
1666
- // a compile-time guid and converts it into a runtime-accessible
1667
- // expression.
1668
- pushProgram: function(guid) {
1669
- if (guid != null) {
1670
- this.pushStackLiteral(this.programExpression(guid));
1671
- } else {
1672
- this.pushStackLiteral(null);
1670
+ if(this.options.stringParams) {
1671
+ if(param.depth) {
1672
+ this.addDepth(param.depth);
1673
+ }
1674
+
1675
+ this.opcode('getContext', param.depth || 0);
1676
+ this.opcode('pushStringParam', param.stringModeValue, param.type);
1677
+
1678
+ if (param.type === 'sexpr') {
1679
+ // Subexpressions get evaluated and passed in
1680
+ // in string params mode.
1681
+ this.sexpr(param);
1682
+ }
1683
+ } else {
1684
+ this[param.type](param);
1685
+ }
1673
1686
  }
1674
1687
  },
1675
1688
 
1676
- // [invokeHelper]
1677
- //
1678
- // On stack, before: hash, inverse, program, params..., ...
1679
- // On stack, after: result of helper invocation
1680
- //
1681
- // Pops off the helper's parameters, invokes the helper,
1682
- // and pushes the helper's return value onto the stack.
1683
- //
1684
- // If the helper is not found, `helperMissing` is called.
1685
- invokeHelper: function(paramSize, name) {
1686
- this.context.aliases.helperMissing = 'helpers.helperMissing';
1687
-
1688
- var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
1689
- var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
1689
+ setupFullMustacheParams: function(sexpr, program, inverse) {
1690
+ var params = sexpr.params;
1691
+ this.pushParams(params);
1690
1692
 
1691
- this.push(helper.name + ' || ' + nonHelper);
1692
- this.replaceStack(function(name) {
1693
- return name + ' ? ' + name + '.call(' +
1694
- helper.callParams + ") " + ": helperMissing.call(" +
1695
- helper.helperMissingParams + ")";
1696
- });
1697
- },
1693
+ this.opcode('pushProgram', program);
1694
+ this.opcode('pushProgram', inverse);
1698
1695
 
1699
- // [invokeKnownHelper]
1700
- //
1701
- // On stack, before: hash, inverse, program, params..., ...
1702
- // On stack, after: result of helper invocation
1703
- //
1704
- // This operation is used when the helper is known to exist,
1705
- // so a `helperMissing` fallback is not required.
1706
- invokeKnownHelper: function(paramSize, name) {
1707
- var helper = this.setupHelper(paramSize, name);
1708
- this.push(helper.name + ".call(" + helper.callParams + ")");
1709
- },
1696
+ if (sexpr.hash) {
1697
+ this.hash(sexpr.hash);
1698
+ } else {
1699
+ this.opcode('emptyHash');
1700
+ }
1710
1701
 
1711
- // [invokeAmbiguous]
1712
- //
1713
- // On stack, before: hash, inverse, program, params..., ...
1714
- // On stack, after: result of disambiguation
1715
- //
1716
- // This operation is used when an expression like `{{foo}}`
1717
- // is provided, but we don't know at compile-time whether it
1718
- // is a helper or a path.
1719
- //
1720
- // This operation emits more code than the other options,
1721
- // and can be avoided by passing the `knownHelpers` and
1722
- // `knownHelpersOnly` flags at compile-time.
1723
- invokeAmbiguous: function(name, helperCall) {
1724
- this.context.aliases.functionType = '"function"';
1702
+ return params;
1703
+ }
1704
+ };
1725
1705
 
1726
- this.pushStackLiteral('{}'); // Hash value
1727
- var helper = this.setupHelper(0, name, helperCall);
1706
+ function precompile(input, options, env) {
1707
+ if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) {
1708
+ throw new Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
1709
+ }
1728
1710
 
1729
- var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
1711
+ options = options || {};
1712
+ if (!('data' in options)) {
1713
+ options.data = true;
1714
+ }
1730
1715
 
1731
- var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
1732
- var nextStack = this.nextStack();
1716
+ var ast = env.parse(input);
1717
+ var environment = new env.Compiler().compile(ast, options);
1718
+ return new env.JavaScriptCompiler().compile(environment, options);
1719
+ }
1733
1720
 
1734
- this.pushSource('if (' + nextStack + ' = ' + helperName + ') { ' + nextStack + ' = ' + nextStack + '.call(' + helper.callParams + '); }');
1735
- this.pushSource('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '.call(' + helper.callParams + ') : ' + nextStack + '; }');
1736
- },
1721
+ __exports__.precompile = precompile;function compile(input, options, env) {
1722
+ if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) {
1723
+ throw new Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
1724
+ }
1737
1725
 
1738
- // [invokePartial]
1739
- //
1740
- // On stack, before: context, ...
1741
- // On stack after: result of partial invocation
1742
- //
1743
- // This operation pops off a context, invokes a partial with that context,
1744
- // and pushes the result of the invocation back.
1745
- invokePartial: function(name) {
1746
- var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"];
1726
+ options = options || {};
1747
1727
 
1748
- if (this.options.data) {
1749
- params.push("data");
1750
- }
1728
+ if (!('data' in options)) {
1729
+ options.data = true;
1730
+ }
1751
1731
 
1752
- this.context.aliases.self = "this";
1753
- this.push("self.invokePartial(" + params.join(", ") + ")");
1754
- },
1732
+ var compiled;
1755
1733
 
1756
- // [assignToHash]
1757
- //
1758
- // On stack, before: value, hash, ...
1759
- // On stack, after: hash, ...
1760
- //
1761
- // Pops a value and hash off the stack, assigns `hash[key] = value`
1762
- // and pushes the hash back onto the stack.
1763
- assignToHash: function(key) {
1764
- var value = this.popStack(),
1765
- context,
1766
- type;
1734
+ function compileInput() {
1735
+ var ast = env.parse(input);
1736
+ var environment = new env.Compiler().compile(ast, options);
1737
+ var templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
1738
+ return env.template(templateSpec);
1739
+ }
1767
1740
 
1768
- if (this.options.stringParams) {
1769
- type = this.popStack();
1770
- context = this.popStack();
1741
+ // Template is only compiled on first use and cached after that point.
1742
+ return function(context, options) {
1743
+ if (!compiled) {
1744
+ compiled = compileInput();
1771
1745
  }
1746
+ return compiled.call(this, context, options);
1747
+ };
1748
+ }
1772
1749
 
1773
- var hash = this.hash;
1774
- if (context) {
1775
- hash.contexts.push("'" + key + "': " + context);
1776
- }
1777
- if (type) {
1778
- hash.types.push("'" + key + "': " + type);
1779
- }
1780
- hash.values.push("'" + key + "': (" + value + ")");
1781
- },
1782
-
1783
- // HELPERS
1784
-
1785
- compiler: JavaScriptCompiler,
1750
+ __exports__.compile = compile;
1751
+ return __exports__;
1752
+ })(__module5__);
1786
1753
 
1787
- compileChildren: function(environment, options) {
1788
- var children = environment.children, child, compiler;
1754
+ // handlebars/compiler/javascript-compiler.js
1755
+ var __module11__ = (function(__dependency1__, __dependency2__) {
1756
+ "use strict";
1757
+ var __exports__;
1758
+ var COMPILER_REVISION = __dependency1__.COMPILER_REVISION;
1759
+ var REVISION_CHANGES = __dependency1__.REVISION_CHANGES;
1760
+ var log = __dependency1__.log;
1761
+ var Exception = __dependency2__;
1789
1762
 
1790
- for(var i=0, l=children.length; i<l; i++) {
1791
- child = children[i];
1792
- compiler = new this.compiler();
1763
+ function Literal(value) {
1764
+ this.value = value;
1765
+ }
1793
1766
 
1794
- var index = this.matchExistingProgram(child);
1767
+ function JavaScriptCompiler() {}
1795
1768
 
1796
- if (index == null) {
1797
- this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
1798
- index = this.context.programs.length;
1799
- child.index = index;
1800
- child.name = 'program' + index;
1801
- this.context.programs[index] = compiler.compile(child, options, this.context);
1802
- this.context.environments[index] = child;
1803
- } else {
1804
- child.index = index;
1805
- child.name = 'program' + index;
1806
- }
1807
- }
1808
- },
1809
- matchExistingProgram: function(child) {
1810
- for (var i = 0, len = this.context.environments.length; i < len; i++) {
1811
- var environment = this.context.environments[i];
1812
- if (environment && environment.equals(child)) {
1813
- return i;
1814
- }
1769
+ JavaScriptCompiler.prototype = {
1770
+ // PUBLIC API: You can override these methods in a subclass to provide
1771
+ // alternative compiled forms for name lookup and buffering semantics
1772
+ nameLookup: function(parent, name /* , type*/) {
1773
+ var wrap,
1774
+ ret;
1775
+ if (parent.indexOf('depth') === 0) {
1776
+ wrap = true;
1815
1777
  }
1816
- },
1817
-
1818
- programExpression: function(guid) {
1819
- this.context.aliases.self = "this";
1820
1778
 
1821
- if(guid == null) {
1822
- return "self.noop";
1779
+ if (/^[0-9]+$/.test(name)) {
1780
+ ret = parent + "[" + name + "]";
1781
+ } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
1782
+ ret = parent + "." + name;
1823
1783
  }
1824
-
1825
- var child = this.environment.children[guid],
1826
- depths = child.depths.list, depth;
1827
-
1828
- var programParams = [child.index, child.name, "data"];
1829
-
1830
- for(var i=0, l = depths.length; i<l; i++) {
1831
- depth = depths[i];
1832
-
1833
- if(depth === 1) { programParams.push("depth0"); }
1834
- else { programParams.push("depth" + (depth - 1)); }
1784
+ else {
1785
+ ret = parent + "['" + name + "']";
1835
1786
  }
1836
1787
 
1837
- return (depths.length === 0 ? "self.program(" : "self.programWithDepth(") + programParams.join(", ") + ")";
1788
+ if (wrap) {
1789
+ return '(' + parent + ' && ' + ret + ')';
1790
+ } else {
1791
+ return ret;
1792
+ }
1838
1793
  },
1839
1794
 
1840
- register: function(name, val) {
1841
- this.useRegister(name);
1842
- this.pushSource(name + " = " + val + ";");
1795
+ compilerInfo: function() {
1796
+ var revision = COMPILER_REVISION,
1797
+ versions = REVISION_CHANGES[revision];
1798
+ return "this.compilerInfo = ["+revision+",'"+versions+"'];\n";
1843
1799
  },
1844
1800
 
1845
- useRegister: function(name) {
1846
- if(!this.registers[name]) {
1847
- this.registers[name] = true;
1848
- this.registers.list.push(name);
1801
+ appendToBuffer: function(string) {
1802
+ if (this.environment.isSimple) {
1803
+ return "return " + string + ";";
1804
+ } else {
1805
+ return {
1806
+ appendToBuffer: true,
1807
+ content: string,
1808
+ toString: function() { return "buffer += " + string + ";"; }
1809
+ };
1849
1810
  }
1850
1811
  },
1851
1812
 
1852
- pushStackLiteral: function(item) {
1853
- return this.push(new Literal(item));
1813
+ initializeBuffer: function() {
1814
+ return this.quotedString("");
1854
1815
  },
1855
1816
 
1856
- pushSource: function(source) {
1857
- if (this.pendingContent) {
1858
- this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent)));
1859
- this.pendingContent = undefined;
1860
- }
1817
+ namespace: "Handlebars",
1818
+ // END PUBLIC API
1861
1819
 
1862
- if (source) {
1863
- this.source.push(source);
1864
- }
1865
- },
1820
+ compile: function(environment, options, context, asObject) {
1821
+ this.environment = environment;
1822
+ this.options = options || {};
1866
1823
 
1867
- pushStack: function(item) {
1868
- this.flushInline();
1824
+ log('debug', this.environment.disassemble() + "\n\n");
1869
1825
 
1870
- var stack = this.incrStack();
1871
- if (item) {
1872
- this.pushSource(stack + " = " + item + ";");
1873
- }
1874
- this.compileStack.push(stack);
1875
- return stack;
1876
- },
1826
+ this.name = this.environment.name;
1827
+ this.isChild = !!context;
1828
+ this.context = context || {
1829
+ programs: [],
1830
+ environments: [],
1831
+ aliases: { }
1832
+ };
1877
1833
 
1878
- replaceStack: function(callback) {
1879
- var prefix = '',
1880
- inline = this.isInline(),
1881
- stack;
1834
+ this.preamble();
1882
1835
 
1883
- // If we are currently inline then we want to merge the inline statement into the
1884
- // replacement statement via ','
1885
- if (inline) {
1886
- var top = this.popStack(true);
1836
+ this.stackSlot = 0;
1837
+ this.stackVars = [];
1838
+ this.registers = { list: [] };
1839
+ this.hashes = [];
1840
+ this.compileStack = [];
1841
+ this.inlineStack = [];
1887
1842
 
1888
- if (top instanceof Literal) {
1889
- // Literals do not need to be inlined
1890
- stack = top.value;
1891
- } else {
1892
- // Get or create the current stack name for use by the inline
1893
- var name = this.stackSlot ? this.topStackName() : this.incrStack();
1843
+ this.compileChildren(environment, options);
1894
1844
 
1895
- prefix = '(' + this.push(name) + ' = ' + top + '),';
1896
- stack = this.topStack();
1897
- }
1898
- } else {
1899
- stack = this.topStack();
1900
- }
1845
+ var opcodes = environment.opcodes, opcode;
1901
1846
 
1902
- var item = callback.call(this, stack);
1847
+ this.i = 0;
1903
1848
 
1904
- if (inline) {
1905
- if (this.inlineStack.length || this.compileStack.length) {
1906
- this.popStack();
1907
- }
1908
- this.push('(' + prefix + item + ')');
1909
- } else {
1910
- // Prevent modification of the context depth variable. Through replaceStack
1911
- if (!/^stack/.test(stack)) {
1912
- stack = this.nextStack();
1849
+ for(var l=opcodes.length; this.i<l; this.i++) {
1850
+ opcode = opcodes[this.i];
1851
+
1852
+ if(opcode.opcode === 'DECLARE') {
1853
+ this[opcode.name] = opcode.value;
1854
+ } else {
1855
+ this[opcode.opcode].apply(this, opcode.args);
1913
1856
  }
1914
1857
 
1915
- this.pushSource(stack + " = (" + prefix + item + ");");
1858
+ // Reset the stripNext flag if it was not set by this operation.
1859
+ if (opcode.opcode !== this.stripNext) {
1860
+ this.stripNext = false;
1861
+ }
1916
1862
  }
1917
- return stack;
1918
- },
1919
1863
 
1920
- nextStack: function() {
1921
- return this.pushStack();
1922
- },
1864
+ // Flush any trailing content that might be pending.
1865
+ this.pushSource('');
1923
1866
 
1924
- incrStack: function() {
1925
- this.stackSlot++;
1926
- if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
1927
- return this.topStackName();
1928
- },
1929
- topStackName: function() {
1930
- return "stack" + this.stackSlot;
1931
- },
1932
- flushInline: function() {
1933
- var inlineStack = this.inlineStack;
1934
- if (inlineStack.length) {
1935
- this.inlineStack = [];
1936
- for (var i = 0, len = inlineStack.length; i < len; i++) {
1937
- var entry = inlineStack[i];
1938
- if (entry instanceof Literal) {
1939
- this.compileStack.push(entry);
1940
- } else {
1941
- this.pushStack(entry);
1942
- }
1943
- }
1867
+ if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
1868
+ throw new Exception('Compile completed with content left on stack');
1944
1869
  }
1945
- },
1946
- isInline: function() {
1947
- return this.inlineStack.length;
1870
+
1871
+ return this.createFunctionContext(asObject);
1948
1872
  },
1949
1873
 
1950
- popStack: function(wrapped) {
1951
- var inline = this.isInline(),
1952
- item = (inline ? this.inlineStack : this.compileStack).pop();
1874
+ preamble: function() {
1875
+ var out = [];
1953
1876
 
1954
- if (!wrapped && (item instanceof Literal)) {
1955
- return item.value;
1877
+ if (!this.isChild) {
1878
+ var namespace = this.namespace;
1879
+
1880
+ var copies = "helpers = this.merge(helpers, " + namespace + ".helpers);";
1881
+ if (this.environment.usePartial) { copies = copies + " partials = this.merge(partials, " + namespace + ".partials);"; }
1882
+ if (this.options.data) { copies = copies + " data = data || {};"; }
1883
+ out.push(copies);
1956
1884
  } else {
1957
- if (!inline) {
1958
- this.stackSlot--;
1959
- }
1960
- return item;
1885
+ out.push('');
1961
1886
  }
1962
- },
1963
-
1964
- topStack: function(wrapped) {
1965
- var stack = (this.isInline() ? this.inlineStack : this.compileStack),
1966
- item = stack[stack.length - 1];
1967
1887
 
1968
- if (!wrapped && (item instanceof Literal)) {
1969
- return item.value;
1888
+ if (!this.environment.isSimple) {
1889
+ out.push(", buffer = " + this.initializeBuffer());
1970
1890
  } else {
1971
- return item;
1891
+ out.push("");
1972
1892
  }
1973
- },
1974
1893
 
1975
- quotedString: function(str) {
1976
- return '"' + str
1977
- .replace(/\\/g, '\\\\')
1978
- .replace(/"/g, '\\"')
1979
- .replace(/\n/g, '\\n')
1980
- .replace(/\r/g, '\\r')
1981
- .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
1982
- .replace(/\u2029/g, '\\u2029') + '"';
1894
+ // track the last context pushed into place to allow skipping the
1895
+ // getContext opcode when it would be a noop
1896
+ this.lastContext = 0;
1897
+ this.source = out;
1983
1898
  },
1984
1899
 
1985
- setupHelper: function(paramSize, name, missingParams) {
1986
- var params = [];
1987
- this.setupParams(paramSize, params, missingParams);
1988
- var foundHelper = this.nameLookup('helpers', name, 'helper');
1900
+ createFunctionContext: function(asObject) {
1901
+ var locals = this.stackVars.concat(this.registers.list);
1989
1902
 
1990
- return {
1991
- params: params,
1992
- name: foundHelper,
1993
- callParams: ["depth0"].concat(params).join(", "),
1994
- helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ")
1995
- };
1996
- },
1903
+ if(locals.length > 0) {
1904
+ this.source[1] = this.source[1] + ", " + locals.join(", ");
1905
+ }
1997
1906
 
1998
- // the params and contexts arguments are passed in arrays
1999
- // to fill in
2000
- setupParams: function(paramSize, params, useRegister) {
2001
- var options = [], contexts = [], types = [], param, inverse, program;
1907
+ // Generate minimizer alias mappings
1908
+ if (!this.isChild) {
1909
+ for (var alias in this.context.aliases) {
1910
+ if (this.context.aliases.hasOwnProperty(alias)) {
1911
+ this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
1912
+ }
1913
+ }
1914
+ }
2002
1915
 
2003
- options.push("hash:" + this.popStack());
1916
+ if (this.source[1]) {
1917
+ this.source[1] = "var " + this.source[1].substring(2) + ";";
1918
+ }
2004
1919
 
2005
- inverse = this.popStack();
2006
- program = this.popStack();
1920
+ // Merge children
1921
+ if (!this.isChild) {
1922
+ this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
1923
+ }
2007
1924
 
2008
- // Avoid setting fn and inverse if neither are set. This allows
2009
- // helpers to do a check for `if (options.fn)`
2010
- if (program || inverse) {
2011
- if (!program) {
2012
- this.context.aliases.self = "this";
2013
- program = "self.noop";
2014
- }
1925
+ if (!this.environment.isSimple) {
1926
+ this.pushSource("return buffer;");
1927
+ }
2015
1928
 
2016
- if (!inverse) {
2017
- this.context.aliases.self = "this";
2018
- inverse = "self.noop";
2019
- }
1929
+ var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
2020
1930
 
2021
- options.push("inverse:" + inverse);
2022
- options.push("fn:" + program);
1931
+ for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
1932
+ params.push("depth" + this.environment.depths.list[i]);
2023
1933
  }
2024
1934
 
2025
- for(var i=0; i<paramSize; i++) {
2026
- param = this.popStack();
2027
- params.push(param);
1935
+ // Perform a second pass over the output to merge content when possible
1936
+ var source = this.mergeSource();
2028
1937
 
2029
- if(this.options.stringParams) {
2030
- types.push(this.popStack());
2031
- contexts.push(this.popStack());
1938
+ if (!this.isChild) {
1939
+ source = this.compilerInfo()+source;
1940
+ }
1941
+
1942
+ if (asObject) {
1943
+ params.push(source);
1944
+
1945
+ return Function.apply(this, params);
1946
+ } else {
1947
+ var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}';
1948
+ log('debug', functionSource + "\n\n");
1949
+ return functionSource;
1950
+ }
1951
+ },
1952
+ mergeSource: function() {
1953
+ // WARN: We are not handling the case where buffer is still populated as the source should
1954
+ // not have buffer append operations as their final action.
1955
+ var source = '',
1956
+ buffer;
1957
+ for (var i = 0, len = this.source.length; i < len; i++) {
1958
+ var line = this.source[i];
1959
+ if (line.appendToBuffer) {
1960
+ if (buffer) {
1961
+ buffer = buffer + '\n + ' + line.content;
1962
+ } else {
1963
+ buffer = line.content;
1964
+ }
1965
+ } else {
1966
+ if (buffer) {
1967
+ source += 'buffer += ' + buffer + ';\n ';
1968
+ buffer = undefined;
1969
+ }
1970
+ source += line + '\n ';
2032
1971
  }
2033
1972
  }
1973
+ return source;
1974
+ },
2034
1975
 
2035
- if (this.options.stringParams) {
2036
- options.push("contexts:[" + contexts.join(",") + "]");
2037
- options.push("types:[" + types.join(",") + "]");
2038
- options.push("hashContexts:hashContexts");
2039
- options.push("hashTypes:hashTypes");
1976
+ // [blockValue]
1977
+ //
1978
+ // On stack, before: hash, inverse, program, value
1979
+ // On stack, after: return value of blockHelperMissing
1980
+ //
1981
+ // The purpose of this opcode is to take a block of the form
1982
+ // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
1983
+ // replace it on the stack with the result of properly
1984
+ // invoking blockHelperMissing.
1985
+ blockValue: function() {
1986
+ this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
1987
+
1988
+ var params = ["depth0"];
1989
+ this.setupParams(0, params);
1990
+
1991
+ this.replaceStack(function(current) {
1992
+ params.splice(1, 0, current);
1993
+ return "blockHelperMissing.call(" + params.join(", ") + ")";
1994
+ });
1995
+ },
1996
+
1997
+ // [ambiguousBlockValue]
1998
+ //
1999
+ // On stack, before: hash, inverse, program, value
2000
+ // Compiler value, before: lastHelper=value of last found helper, if any
2001
+ // On stack, after, if no lastHelper: same as [blockValue]
2002
+ // On stack, after, if lastHelper: value
2003
+ ambiguousBlockValue: function() {
2004
+ this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
2005
+
2006
+ var params = ["depth0"];
2007
+ this.setupParams(0, params);
2008
+
2009
+ var current = this.topStack();
2010
+ params.splice(1, 0, current);
2011
+
2012
+ this.pushSource("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
2013
+ },
2014
+
2015
+ // [appendContent]
2016
+ //
2017
+ // On stack, before: ...
2018
+ // On stack, after: ...
2019
+ //
2020
+ // Appends the string value of `content` to the current buffer
2021
+ appendContent: function(content) {
2022
+ if (this.pendingContent) {
2023
+ content = this.pendingContent + content;
2024
+ }
2025
+ if (this.stripNext) {
2026
+ content = content.replace(/^\s+/, '');
2040
2027
  }
2041
2028
 
2042
- if(this.options.data) {
2043
- options.push("data:data");
2029
+ this.pendingContent = content;
2030
+ },
2031
+
2032
+ // [strip]
2033
+ //
2034
+ // On stack, before: ...
2035
+ // On stack, after: ...
2036
+ //
2037
+ // Removes any trailing whitespace from the prior content node and flags
2038
+ // the next operation for stripping if it is a content node.
2039
+ strip: function() {
2040
+ if (this.pendingContent) {
2041
+ this.pendingContent = this.pendingContent.replace(/\s+$/, '');
2044
2042
  }
2043
+ this.stripNext = 'strip';
2044
+ },
2045
2045
 
2046
- options = "{" + options.join(",") + "}";
2047
- if (useRegister) {
2048
- this.register('options', options);
2049
- params.push('options');
2050
- } else {
2051
- params.push(options);
2046
+ // [append]
2047
+ //
2048
+ // On stack, before: value, ...
2049
+ // On stack, after: ...
2050
+ //
2051
+ // Coerces `value` to a String and appends it to the current buffer.
2052
+ //
2053
+ // If `value` is truthy, or 0, it is coerced into a string and appended
2054
+ // Otherwise, the empty string is appended
2055
+ append: function() {
2056
+ // Force anything that is inlined onto the stack so we don't have duplication
2057
+ // when we examine local
2058
+ this.flushInline();
2059
+ var local = this.popStack();
2060
+ this.pushSource("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
2061
+ if (this.environment.isSimple) {
2062
+ this.pushSource("else { " + this.appendToBuffer("''") + " }");
2052
2063
  }
2053
- return params.join(", ");
2054
- }
2055
- };
2064
+ },
2056
2065
 
2057
- var reservedWords = (
2058
- "break else new var" +
2059
- " case finally return void" +
2060
- " catch for switch while" +
2061
- " continue function this with" +
2062
- " default if throw" +
2063
- " delete in try" +
2064
- " do instanceof typeof" +
2065
- " abstract enum int short" +
2066
- " boolean export interface static" +
2067
- " byte extends long super" +
2068
- " char final native synchronized" +
2069
- " class float package throws" +
2070
- " const goto private transient" +
2071
- " debugger implements protected volatile" +
2072
- " double import public let yield"
2073
- ).split(" ");
2066
+ // [appendEscaped]
2067
+ //
2068
+ // On stack, before: value, ...
2069
+ // On stack, after: ...
2070
+ //
2071
+ // Escape `value` and append it to the buffer
2072
+ appendEscaped: function() {
2073
+ this.context.aliases.escapeExpression = 'this.escapeExpression';
2074
2074
 
2075
- var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
2075
+ this.pushSource(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
2076
+ },
2076
2077
 
2077
- for(var i=0, l=reservedWords.length; i<l; i++) {
2078
- compilerWords[reservedWords[i]] = true;
2079
- }
2078
+ // [getContext]
2079
+ //
2080
+ // On stack, before: ...
2081
+ // On stack, after: ...
2082
+ // Compiler value, after: lastContext=depth
2083
+ //
2084
+ // Set the value of the `lastContext` compiler value to the depth
2085
+ getContext: function(depth) {
2086
+ if(this.lastContext !== depth) {
2087
+ this.lastContext = depth;
2088
+ }
2089
+ },
2080
2090
 
2081
- JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
2082
- if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) {
2083
- return true;
2084
- }
2085
- return false;
2086
- };
2091
+ // [lookupOnContext]
2092
+ //
2093
+ // On stack, before: ...
2094
+ // On stack, after: currentContext[name], ...
2095
+ //
2096
+ // Looks up the value of `name` on the current context and pushes
2097
+ // it onto the stack.
2098
+ lookupOnContext: function(name) {
2099
+ this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
2100
+ },
2087
2101
 
2088
- __exports__ = JavaScriptCompiler;
2089
- return __exports__;
2090
- })(__module2__);
2102
+ // [pushContext]
2103
+ //
2104
+ // On stack, before: ...
2105
+ // On stack, after: currentContext, ...
2106
+ //
2107
+ // Pushes the value of the current context onto the stack.
2108
+ pushContext: function() {
2109
+ this.pushStackLiteral('depth' + this.lastContext);
2110
+ },
2091
2111
 
2092
- // handlebars/compiler/compiler.js
2093
- var __module10__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__) {
2094
- "use strict";
2095
- var __exports__ = {};
2096
- var Exception = __dependency1__;
2097
- var parse = __dependency2__.parse;
2098
- var JavaScriptCompiler = __dependency3__;
2099
- var AST = __dependency4__;
2112
+ // [resolvePossibleLambda]
2113
+ //
2114
+ // On stack, before: value, ...
2115
+ // On stack, after: resolved value, ...
2116
+ //
2117
+ // If the `value` is a lambda, replace it on the stack by
2118
+ // the return value of the lambda
2119
+ resolvePossibleLambda: function() {
2120
+ this.context.aliases.functionType = '"function"';
2100
2121
 
2101
- function Compiler() {}
2122
+ this.replaceStack(function(current) {
2123
+ return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current;
2124
+ });
2125
+ },
2102
2126
 
2103
- __exports__.Compiler = Compiler;// the foundHelper register will disambiguate helper lookup from finding a
2104
- // function in a context. This is necessary for mustache compatibility, which
2105
- // requires that context functions in blocks are evaluated by blockHelperMissing,
2106
- // and then proceed as if the resulting value was provided to blockHelperMissing.
2127
+ // [lookup]
2128
+ //
2129
+ // On stack, before: value, ...
2130
+ // On stack, after: value[name], ...
2131
+ //
2132
+ // Replace the value on the stack with the result of looking
2133
+ // up `name` on `value`
2134
+ lookup: function(name) {
2135
+ this.replaceStack(function(current) {
2136
+ return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
2137
+ });
2138
+ },
2107
2139
 
2108
- Compiler.prototype = {
2109
- compiler: Compiler,
2140
+ // [lookupData]
2141
+ //
2142
+ // On stack, before: ...
2143
+ // On stack, after: data, ...
2144
+ //
2145
+ // Push the data lookup operator
2146
+ lookupData: function() {
2147
+ this.pushStackLiteral('data');
2148
+ },
2110
2149
 
2111
- disassemble: function() {
2112
- var opcodes = this.opcodes, opcode, out = [], params, param;
2150
+ // [pushStringParam]
2151
+ //
2152
+ // On stack, before: ...
2153
+ // On stack, after: string, currentContext, ...
2154
+ //
2155
+ // This opcode is designed for use in string mode, which
2156
+ // provides the string value of a parameter along with its
2157
+ // depth rather than resolving it immediately.
2158
+ pushStringParam: function(string, type) {
2159
+ this.pushStackLiteral('depth' + this.lastContext);
2113
2160
 
2114
- for (var i=0, l=opcodes.length; i<l; i++) {
2115
- opcode = opcodes[i];
2161
+ this.pushString(type);
2116
2162
 
2117
- if (opcode.opcode === 'DECLARE') {
2118
- out.push("DECLARE " + opcode.name + "=" + opcode.value);
2163
+ // If it's a subexpression, the string result
2164
+ // will be pushed after this opcode.
2165
+ if (type !== 'sexpr') {
2166
+ if (typeof string === 'string') {
2167
+ this.pushString(string);
2119
2168
  } else {
2120
- params = [];
2121
- for (var j=0; j<opcode.args.length; j++) {
2122
- param = opcode.args[j];
2123
- if (typeof param === "string") {
2124
- param = "\"" + param.replace("\n", "\\n") + "\"";
2125
- }
2126
- params.push(param);
2127
- }
2128
- out.push(opcode.opcode + " " + params.join(" "));
2169
+ this.pushStackLiteral(string);
2129
2170
  }
2130
2171
  }
2131
-
2132
- return out.join("\n");
2133
2172
  },
2134
2173
 
2135
- equals: function(other) {
2136
- var len = this.opcodes.length;
2137
- if (other.opcodes.length !== len) {
2138
- return false;
2139
- }
2174
+ emptyHash: function() {
2175
+ this.pushStackLiteral('{}');
2140
2176
 
2141
- for (var i = 0; i < len; i++) {
2142
- var opcode = this.opcodes[i],
2143
- otherOpcode = other.opcodes[i];
2144
- if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
2145
- return false;
2146
- }
2147
- for (var j = 0; j < opcode.args.length; j++) {
2148
- if (opcode.args[j] !== otherOpcode.args[j]) {
2149
- return false;
2150
- }
2151
- }
2177
+ if (this.options.stringParams) {
2178
+ this.push('{}'); // hashContexts
2179
+ this.push('{}'); // hashTypes
2152
2180
  }
2153
-
2154
- len = this.children.length;
2155
- if (other.children.length !== len) {
2156
- return false;
2181
+ },
2182
+ pushHash: function() {
2183
+ if (this.hash) {
2184
+ this.hashes.push(this.hash);
2157
2185
  }
2158
- for (i = 0; i < len; i++) {
2159
- if (!this.children[i].equals(other.children[i])) {
2160
- return false;
2161
- }
2186
+ this.hash = {values: [], types: [], contexts: []};
2187
+ },
2188
+ popHash: function() {
2189
+ var hash = this.hash;
2190
+ this.hash = this.hashes.pop();
2191
+
2192
+ if (this.options.stringParams) {
2193
+ this.push('{' + hash.contexts.join(',') + '}');
2194
+ this.push('{' + hash.types.join(',') + '}');
2162
2195
  }
2163
2196
 
2164
- return true;
2197
+ this.push('{\n ' + hash.values.join(',\n ') + '\n }');
2165
2198
  },
2166
2199
 
2167
- guid: 0,
2168
-
2169
- compile: function(program, options) {
2170
- this.opcodes = [];
2171
- this.children = [];
2172
- this.depths = {list: []};
2173
- this.options = options;
2200
+ // [pushString]
2201
+ //
2202
+ // On stack, before: ...
2203
+ // On stack, after: quotedString(string), ...
2204
+ //
2205
+ // Push a quoted version of `string` onto the stack
2206
+ pushString: function(string) {
2207
+ this.pushStackLiteral(this.quotedString(string));
2208
+ },
2174
2209
 
2175
- // These changes will propagate to the other compiler components
2176
- var knownHelpers = this.options.knownHelpers;
2177
- this.options.knownHelpers = {
2178
- 'helperMissing': true,
2179
- 'blockHelperMissing': true,
2180
- 'each': true,
2181
- 'if': true,
2182
- 'unless': true,
2183
- 'with': true,
2184
- 'log': true
2185
- };
2186
- if (knownHelpers) {
2187
- for (var name in knownHelpers) {
2188
- this.options.knownHelpers[name] = knownHelpers[name];
2189
- }
2190
- }
2210
+ // [push]
2211
+ //
2212
+ // On stack, before: ...
2213
+ // On stack, after: expr, ...
2214
+ //
2215
+ // Push an expression onto the stack
2216
+ push: function(expr) {
2217
+ this.inlineStack.push(expr);
2218
+ return expr;
2219
+ },
2191
2220
 
2192
- return this.accept(program);
2221
+ // [pushLiteral]
2222
+ //
2223
+ // On stack, before: ...
2224
+ // On stack, after: value, ...
2225
+ //
2226
+ // Pushes a value onto the stack. This operation prevents
2227
+ // the compiler from creating a temporary variable to hold
2228
+ // it.
2229
+ pushLiteral: function(value) {
2230
+ this.pushStackLiteral(value);
2193
2231
  },
2194
2232
 
2195
- accept: function(node) {
2196
- var strip = node.strip || {},
2197
- ret;
2198
- if (strip.left) {
2199
- this.opcode('strip');
2233
+ // [pushProgram]
2234
+ //
2235
+ // On stack, before: ...
2236
+ // On stack, after: program(guid), ...
2237
+ //
2238
+ // Push a program expression onto the stack. This takes
2239
+ // a compile-time guid and converts it into a runtime-accessible
2240
+ // expression.
2241
+ pushProgram: function(guid) {
2242
+ if (guid != null) {
2243
+ this.pushStackLiteral(this.programExpression(guid));
2244
+ } else {
2245
+ this.pushStackLiteral(null);
2200
2246
  }
2247
+ },
2248
+
2249
+ // [invokeHelper]
2250
+ //
2251
+ // On stack, before: hash, inverse, program, params..., ...
2252
+ // On stack, after: result of helper invocation
2253
+ //
2254
+ // Pops off the helper's parameters, invokes the helper,
2255
+ // and pushes the helper's return value onto the stack.
2256
+ //
2257
+ // If the helper is not found, `helperMissing` is called.
2258
+ invokeHelper: function(paramSize, name, isRoot) {
2259
+ this.context.aliases.helperMissing = 'helpers.helperMissing';
2260
+ this.useRegister('helper');
2201
2261
 
2202
- ret = this[node.type](node);
2262
+ var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
2263
+ var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
2203
2264
 
2204
- if (strip.right) {
2205
- this.opcode('strip');
2265
+ var lookup = 'helper = ' + helper.name + ' || ' + nonHelper;
2266
+ if (helper.paramsInit) {
2267
+ lookup += ',' + helper.paramsInit;
2206
2268
  }
2207
2269
 
2208
- return ret;
2209
- },
2210
-
2211
- program: function(program) {
2212
- var statements = program.statements;
2270
+ this.push(
2271
+ '('
2272
+ + lookup
2273
+ + ',helper '
2274
+ + '? helper.call(' + helper.callParams + ') '
2275
+ + ': helperMissing.call(' + helper.helperMissingParams + '))');
2213
2276
 
2214
- for(var i=0, l=statements.length; i<l; i++) {
2215
- this.accept(statements[i]);
2277
+ // Always flush subexpressions. This is both to prevent the compounding size issue that
2278
+ // occurs when the code has to be duplicated for inlining and also to prevent errors
2279
+ // due to the incorrect options object being passed due to the shared register.
2280
+ if (!isRoot) {
2281
+ this.flushInline();
2216
2282
  }
2217
- this.isSimple = l === 1;
2218
-
2219
- this.depths.list = this.depths.list.sort(function(a, b) {
2220
- return a - b;
2221
- });
2283
+ },
2222
2284
 
2223
- return this;
2285
+ // [invokeKnownHelper]
2286
+ //
2287
+ // On stack, before: hash, inverse, program, params..., ...
2288
+ // On stack, after: result of helper invocation
2289
+ //
2290
+ // This operation is used when the helper is known to exist,
2291
+ // so a `helperMissing` fallback is not required.
2292
+ invokeKnownHelper: function(paramSize, name) {
2293
+ var helper = this.setupHelper(paramSize, name);
2294
+ this.push(helper.name + ".call(" + helper.callParams + ")");
2224
2295
  },
2225
2296
 
2226
- compileProgram: function(program) {
2227
- var result = new this.compiler().compile(program, this.options);
2228
- var guid = this.guid++, depth;
2297
+ // [invokeAmbiguous]
2298
+ //
2299
+ // On stack, before: hash, inverse, program, params..., ...
2300
+ // On stack, after: result of disambiguation
2301
+ //
2302
+ // This operation is used when an expression like `{{foo}}`
2303
+ // is provided, but we don't know at compile-time whether it
2304
+ // is a helper or a path.
2305
+ //
2306
+ // This operation emits more code than the other options,
2307
+ // and can be avoided by passing the `knownHelpers` and
2308
+ // `knownHelpersOnly` flags at compile-time.
2309
+ invokeAmbiguous: function(name, helperCall) {
2310
+ this.context.aliases.functionType = '"function"';
2311
+ this.useRegister('helper');
2229
2312
 
2230
- this.usePartial = this.usePartial || result.usePartial;
2313
+ this.emptyHash();
2314
+ var helper = this.setupHelper(0, name, helperCall);
2231
2315
 
2232
- this.children[guid] = result;
2316
+ var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
2233
2317
 
2234
- for(var i=0, l=result.depths.list.length; i<l; i++) {
2235
- depth = result.depths.list[i];
2318
+ var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
2319
+ var nextStack = this.nextStack();
2236
2320
 
2237
- if(depth < 2) { continue; }
2238
- else { this.addDepth(depth - 1); }
2321
+ if (helper.paramsInit) {
2322
+ this.pushSource(helper.paramsInit);
2239
2323
  }
2240
-
2241
- return guid;
2324
+ this.pushSource('if (helper = ' + helperName + ') { ' + nextStack + ' = helper.call(' + helper.callParams + '); }');
2325
+ this.pushSource('else { helper = ' + nonHelper + '; ' + nextStack + ' = typeof helper === functionType ? helper.call(' + helper.callParams + ') : helper; }');
2242
2326
  },
2243
2327
 
2244
- block: function(block) {
2245
- var mustache = block.mustache,
2246
- program = block.program,
2247
- inverse = block.inverse;
2248
-
2249
- if (program) {
2250
- program = this.compileProgram(program);
2251
- }
2328
+ // [invokePartial]
2329
+ //
2330
+ // On stack, before: context, ...
2331
+ // On stack after: result of partial invocation
2332
+ //
2333
+ // This operation pops off a context, invokes a partial with that context,
2334
+ // and pushes the result of the invocation back.
2335
+ invokePartial: function(name) {
2336
+ var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"];
2252
2337
 
2253
- if (inverse) {
2254
- inverse = this.compileProgram(inverse);
2338
+ if (this.options.data) {
2339
+ params.push("data");
2255
2340
  }
2256
2341
 
2257
- var type = this.classifyMustache(mustache);
2258
-
2259
- if (type === "helper") {
2260
- this.helperMustache(mustache, program, inverse);
2261
- } else if (type === "simple") {
2262
- this.simpleMustache(mustache);
2342
+ this.context.aliases.self = "this";
2343
+ this.push("self.invokePartial(" + params.join(", ") + ")");
2344
+ },
2263
2345
 
2264
- // now that the simple mustache is resolved, we need to
2265
- // evaluate it by executing `blockHelperMissing`
2266
- this.opcode('pushProgram', program);
2267
- this.opcode('pushProgram', inverse);
2268
- this.opcode('emptyHash');
2269
- this.opcode('blockValue');
2270
- } else {
2271
- this.ambiguousMustache(mustache, program, inverse);
2346
+ // [assignToHash]
2347
+ //
2348
+ // On stack, before: value, hash, ...
2349
+ // On stack, after: hash, ...
2350
+ //
2351
+ // Pops a value and hash off the stack, assigns `hash[key] = value`
2352
+ // and pushes the hash back onto the stack.
2353
+ assignToHash: function(key) {
2354
+ var value = this.popStack(),
2355
+ context,
2356
+ type;
2272
2357
 
2273
- // now that the simple mustache is resolved, we need to
2274
- // evaluate it by executing `blockHelperMissing`
2275
- this.opcode('pushProgram', program);
2276
- this.opcode('pushProgram', inverse);
2277
- this.opcode('emptyHash');
2278
- this.opcode('ambiguousBlockValue');
2358
+ if (this.options.stringParams) {
2359
+ type = this.popStack();
2360
+ context = this.popStack();
2279
2361
  }
2280
2362
 
2281
- this.opcode('append');
2363
+ var hash = this.hash;
2364
+ if (context) {
2365
+ hash.contexts.push("'" + key + "': " + context);
2366
+ }
2367
+ if (type) {
2368
+ hash.types.push("'" + key + "': " + type);
2369
+ }
2370
+ hash.values.push("'" + key + "': (" + value + ")");
2282
2371
  },
2283
2372
 
2284
- hash: function(hash) {
2285
- var pairs = hash.pairs, pair, val;
2373
+ // HELPERS
2286
2374
 
2287
- this.opcode('pushHash');
2375
+ compiler: JavaScriptCompiler,
2288
2376
 
2289
- for(var i=0, l=pairs.length; i<l; i++) {
2290
- pair = pairs[i];
2291
- val = pair[1];
2377
+ compileChildren: function(environment, options) {
2378
+ var children = environment.children, child, compiler;
2292
2379
 
2293
- if (this.options.stringParams) {
2294
- if(val.depth) {
2295
- this.addDepth(val.depth);
2296
- }
2297
- this.opcode('getContext', val.depth || 0);
2298
- this.opcode('pushStringParam', val.stringModeValue, val.type);
2380
+ for(var i=0, l=children.length; i<l; i++) {
2381
+ child = children[i];
2382
+ compiler = new this.compiler();
2383
+
2384
+ var index = this.matchExistingProgram(child);
2385
+
2386
+ if (index == null) {
2387
+ this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
2388
+ index = this.context.programs.length;
2389
+ child.index = index;
2390
+ child.name = 'program' + index;
2391
+ this.context.programs[index] = compiler.compile(child, options, this.context);
2392
+ this.context.environments[index] = child;
2299
2393
  } else {
2300
- this.accept(val);
2394
+ child.index = index;
2395
+ child.name = 'program' + index;
2396
+ }
2397
+ }
2398
+ },
2399
+ matchExistingProgram: function(child) {
2400
+ for (var i = 0, len = this.context.environments.length; i < len; i++) {
2401
+ var environment = this.context.environments[i];
2402
+ if (environment && environment.equals(child)) {
2403
+ return i;
2301
2404
  }
2302
-
2303
- this.opcode('assignToHash', pair[0]);
2304
2405
  }
2305
- this.opcode('popHash');
2306
2406
  },
2307
2407
 
2308
- partial: function(partial) {
2309
- var partialName = partial.partialName;
2310
- this.usePartial = true;
2408
+ programExpression: function(guid) {
2409
+ this.context.aliases.self = "this";
2311
2410
 
2312
- if(partial.context) {
2313
- this.ID(partial.context);
2314
- } else {
2315
- this.opcode('push', 'depth0');
2411
+ if(guid == null) {
2412
+ return "self.noop";
2316
2413
  }
2317
2414
 
2318
- this.opcode('invokePartial', partialName.name);
2319
- this.opcode('append');
2320
- },
2415
+ var child = this.environment.children[guid],
2416
+ depths = child.depths.list, depth;
2321
2417
 
2322
- content: function(content) {
2323
- this.opcode('appendContent', content.string);
2324
- },
2418
+ var programParams = [child.index, child.name, "data"];
2325
2419
 
2326
- mustache: function(mustache) {
2327
- var options = this.options;
2328
- var type = this.classifyMustache(mustache);
2420
+ for(var i=0, l = depths.length; i<l; i++) {
2421
+ depth = depths[i];
2329
2422
 
2330
- if (type === "simple") {
2331
- this.simpleMustache(mustache);
2332
- } else if (type === "helper") {
2333
- this.helperMustache(mustache);
2334
- } else {
2335
- this.ambiguousMustache(mustache);
2423
+ if(depth === 1) { programParams.push("depth0"); }
2424
+ else { programParams.push("depth" + (depth - 1)); }
2336
2425
  }
2337
2426
 
2338
- if(mustache.escaped && !options.noEscape) {
2339
- this.opcode('appendEscaped');
2340
- } else {
2341
- this.opcode('append');
2342
- }
2427
+ return (depths.length === 0 ? "self.program(" : "self.programWithDepth(") + programParams.join(", ") + ")";
2343
2428
  },
2344
2429
 
2345
- ambiguousMustache: function(mustache, program, inverse) {
2346
- var id = mustache.id,
2347
- name = id.parts[0],
2348
- isBlock = program != null || inverse != null;
2349
-
2350
- this.opcode('getContext', id.depth);
2430
+ register: function(name, val) {
2431
+ this.useRegister(name);
2432
+ this.pushSource(name + " = " + val + ";");
2433
+ },
2351
2434
 
2352
- this.opcode('pushProgram', program);
2353
- this.opcode('pushProgram', inverse);
2435
+ useRegister: function(name) {
2436
+ if(!this.registers[name]) {
2437
+ this.registers[name] = true;
2438
+ this.registers.list.push(name);
2439
+ }
2440
+ },
2354
2441
 
2355
- this.opcode('invokeAmbiguous', name, isBlock);
2442
+ pushStackLiteral: function(item) {
2443
+ return this.push(new Literal(item));
2356
2444
  },
2357
2445
 
2358
- simpleMustache: function(mustache) {
2359
- var id = mustache.id;
2446
+ pushSource: function(source) {
2447
+ if (this.pendingContent) {
2448
+ this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent)));
2449
+ this.pendingContent = undefined;
2450
+ }
2360
2451
 
2361
- if (id.type === 'DATA') {
2362
- this.DATA(id);
2363
- } else if (id.parts.length) {
2364
- this.ID(id);
2365
- } else {
2366
- // Simplified ID for `this`
2367
- this.addDepth(id.depth);
2368
- this.opcode('getContext', id.depth);
2369
- this.opcode('pushContext');
2452
+ if (source) {
2453
+ this.source.push(source);
2370
2454
  }
2455
+ },
2371
2456
 
2372
- this.opcode('resolvePossibleLambda');
2457
+ pushStack: function(item) {
2458
+ this.flushInline();
2459
+
2460
+ var stack = this.incrStack();
2461
+ if (item) {
2462
+ this.pushSource(stack + " = " + item + ";");
2463
+ }
2464
+ this.compileStack.push(stack);
2465
+ return stack;
2373
2466
  },
2374
2467
 
2375
- helperMustache: function(mustache, program, inverse) {
2376
- var params = this.setupFullMustacheParams(mustache, program, inverse),
2377
- name = mustache.id.parts[0];
2468
+ replaceStack: function(callback) {
2469
+ var prefix = '',
2470
+ inline = this.isInline(),
2471
+ stack,
2472
+ createdStack,
2473
+ usedLiteral;
2474
+
2475
+ // If we are currently inline then we want to merge the inline statement into the
2476
+ // replacement statement via ','
2477
+ if (inline) {
2478
+ var top = this.popStack(true);
2479
+
2480
+ if (top instanceof Literal) {
2481
+ // Literals do not need to be inlined
2482
+ stack = top.value;
2483
+ usedLiteral = true;
2484
+ } else {
2485
+ // Get or create the current stack name for use by the inline
2486
+ createdStack = !this.stackSlot;
2487
+ var name = !createdStack ? this.topStackName() : this.incrStack();
2378
2488
 
2379
- if (this.options.knownHelpers[name]) {
2380
- this.opcode('invokeKnownHelper', params.length, name);
2381
- } else if (this.options.knownHelpersOnly) {
2382
- throw new Error("You specified knownHelpersOnly, but used the unknown helper " + name);
2489
+ prefix = '(' + this.push(name) + ' = ' + top + '),';
2490
+ stack = this.topStack();
2491
+ }
2383
2492
  } else {
2384
- this.opcode('invokeHelper', params.length, name);
2493
+ stack = this.topStack();
2385
2494
  }
2386
- },
2387
2495
 
2388
- ID: function(id) {
2389
- this.addDepth(id.depth);
2390
- this.opcode('getContext', id.depth);
2496
+ var item = callback.call(this, stack);
2391
2497
 
2392
- var name = id.parts[0];
2393
- if (!name) {
2394
- this.opcode('pushContext');
2498
+ if (inline) {
2499
+ if (!usedLiteral) {
2500
+ this.popStack();
2501
+ }
2502
+ if (createdStack) {
2503
+ this.stackSlot--;
2504
+ }
2505
+ this.push('(' + prefix + item + ')');
2395
2506
  } else {
2396
- this.opcode('lookupOnContext', id.parts[0]);
2397
- }
2507
+ // Prevent modification of the context depth variable. Through replaceStack
2508
+ if (!/^stack/.test(stack)) {
2509
+ stack = this.nextStack();
2510
+ }
2398
2511
 
2399
- for(var i=1, l=id.parts.length; i<l; i++) {
2400
- this.opcode('lookup', id.parts[i]);
2512
+ this.pushSource(stack + " = (" + prefix + item + ");");
2401
2513
  }
2514
+ return stack;
2402
2515
  },
2403
2516
 
2404
- DATA: function(data) {
2405
- this.options.data = true;
2406
- if (data.id.isScoped || data.id.depth) {
2407
- throw new Exception('Scoped data references are not supported: ' + data.original);
2408
- }
2517
+ nextStack: function() {
2518
+ return this.pushStack();
2519
+ },
2409
2520
 
2410
- this.opcode('lookupData');
2411
- var parts = data.id.parts;
2412
- for(var i=0, l=parts.length; i<l; i++) {
2413
- this.opcode('lookup', parts[i]);
2521
+ incrStack: function() {
2522
+ this.stackSlot++;
2523
+ if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
2524
+ return this.topStackName();
2525
+ },
2526
+ topStackName: function() {
2527
+ return "stack" + this.stackSlot;
2528
+ },
2529
+ flushInline: function() {
2530
+ var inlineStack = this.inlineStack;
2531
+ if (inlineStack.length) {
2532
+ this.inlineStack = [];
2533
+ for (var i = 0, len = inlineStack.length; i < len; i++) {
2534
+ var entry = inlineStack[i];
2535
+ if (entry instanceof Literal) {
2536
+ this.compileStack.push(entry);
2537
+ } else {
2538
+ this.pushStack(entry);
2539
+ }
2540
+ }
2414
2541
  }
2415
2542
  },
2416
-
2417
- STRING: function(string) {
2418
- this.opcode('pushString', string.string);
2543
+ isInline: function() {
2544
+ return this.inlineStack.length;
2419
2545
  },
2420
2546
 
2421
- INTEGER: function(integer) {
2422
- this.opcode('pushLiteral', integer.integer);
2423
- },
2547
+ popStack: function(wrapped) {
2548
+ var inline = this.isInline(),
2549
+ item = (inline ? this.inlineStack : this.compileStack).pop();
2424
2550
 
2425
- BOOLEAN: function(bool) {
2426
- this.opcode('pushLiteral', bool.bool);
2551
+ if (!wrapped && (item instanceof Literal)) {
2552
+ return item.value;
2553
+ } else {
2554
+ if (!inline) {
2555
+ if (!this.stackSlot) {
2556
+ throw new Exception('Invalid stack pop');
2557
+ }
2558
+ this.stackSlot--;
2559
+ }
2560
+ return item;
2561
+ }
2427
2562
  },
2428
2563
 
2429
- comment: function() {},
2564
+ topStack: function(wrapped) {
2565
+ var stack = (this.isInline() ? this.inlineStack : this.compileStack),
2566
+ item = stack[stack.length - 1];
2430
2567
 
2431
- // HELPERS
2432
- opcode: function(name) {
2433
- this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
2568
+ if (!wrapped && (item instanceof Literal)) {
2569
+ return item.value;
2570
+ } else {
2571
+ return item;
2572
+ }
2434
2573
  },
2435
2574
 
2436
- declare: function(name, value) {
2437
- this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
2575
+ quotedString: function(str) {
2576
+ return '"' + str
2577
+ .replace(/\\/g, '\\\\')
2578
+ .replace(/"/g, '\\"')
2579
+ .replace(/\n/g, '\\n')
2580
+ .replace(/\r/g, '\\r')
2581
+ .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
2582
+ .replace(/\u2029/g, '\\u2029') + '"';
2438
2583
  },
2439
2584
 
2440
- addDepth: function(depth) {
2441
- if(isNaN(depth)) { throw new Error("EWOT"); }
2442
- if(depth === 0) { return; }
2585
+ setupHelper: function(paramSize, name, missingParams) {
2586
+ var params = [],
2587
+ paramsInit = this.setupParams(paramSize, params, missingParams);
2588
+ var foundHelper = this.nameLookup('helpers', name, 'helper');
2443
2589
 
2444
- if(!this.depths[depth]) {
2445
- this.depths[depth] = true;
2446
- this.depths.list.push(depth);
2447
- }
2590
+ return {
2591
+ params: params,
2592
+ paramsInit: paramsInit,
2593
+ name: foundHelper,
2594
+ callParams: ["depth0"].concat(params).join(", "),
2595
+ helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ")
2596
+ };
2448
2597
  },
2449
2598
 
2450
- classifyMustache: function(mustache) {
2451
- var isHelper = mustache.isHelper;
2452
- var isEligible = mustache.eligibleHelper;
2453
- var options = this.options;
2599
+ setupOptions: function(paramSize, params) {
2600
+ var options = [], contexts = [], types = [], param, inverse, program;
2454
2601
 
2455
- // if ambiguous, we can possibly resolve the ambiguity now
2456
- if (isEligible && !isHelper) {
2457
- var name = mustache.id.parts[0];
2602
+ options.push("hash:" + this.popStack());
2458
2603
 
2459
- if (options.knownHelpers[name]) {
2460
- isHelper = true;
2461
- } else if (options.knownHelpersOnly) {
2462
- isEligible = false;
2463
- }
2604
+ if (this.options.stringParams) {
2605
+ options.push("hashTypes:" + this.popStack());
2606
+ options.push("hashContexts:" + this.popStack());
2464
2607
  }
2465
2608
 
2466
- if (isHelper) { return "helper"; }
2467
- else if (isEligible) { return "ambiguous"; }
2468
- else { return "simple"; }
2469
- },
2609
+ inverse = this.popStack();
2610
+ program = this.popStack();
2470
2611
 
2471
- pushParams: function(params) {
2472
- var i = params.length, param;
2612
+ // Avoid setting fn and inverse if neither are set. This allows
2613
+ // helpers to do a check for `if (options.fn)`
2614
+ if (program || inverse) {
2615
+ if (!program) {
2616
+ this.context.aliases.self = "this";
2617
+ program = "self.noop";
2618
+ }
2473
2619
 
2474
- while(i--) {
2475
- param = params[i];
2620
+ if (!inverse) {
2621
+ this.context.aliases.self = "this";
2622
+ inverse = "self.noop";
2623
+ }
2476
2624
 
2477
- if(this.options.stringParams) {
2478
- if(param.depth) {
2479
- this.addDepth(param.depth);
2480
- }
2625
+ options.push("inverse:" + inverse);
2626
+ options.push("fn:" + program);
2627
+ }
2481
2628
 
2482
- this.opcode('getContext', param.depth || 0);
2483
- this.opcode('pushStringParam', param.stringModeValue, param.type);
2484
- } else {
2485
- this[param.type](param);
2629
+ for(var i=0; i<paramSize; i++) {
2630
+ param = this.popStack();
2631
+ params.push(param);
2632
+
2633
+ if(this.options.stringParams) {
2634
+ types.push(this.popStack());
2635
+ contexts.push(this.popStack());
2486
2636
  }
2487
2637
  }
2488
- },
2489
2638
 
2490
- setupMustacheParams: function(mustache) {
2491
- var params = mustache.params;
2492
- this.pushParams(params);
2639
+ if (this.options.stringParams) {
2640
+ options.push("contexts:[" + contexts.join(",") + "]");
2641
+ options.push("types:[" + types.join(",") + "]");
2642
+ }
2493
2643
 
2494
- if(mustache.hash) {
2495
- this.hash(mustache.hash);
2496
- } else {
2497
- this.opcode('emptyHash');
2644
+ if(this.options.data) {
2645
+ options.push("data:data");
2498
2646
  }
2499
2647
 
2500
- return params;
2648
+ return options;
2501
2649
  },
2502
2650
 
2503
- // this will replace setupMustacheParams when we're done
2504
- setupFullMustacheParams: function(mustache, program, inverse) {
2505
- var params = mustache.params;
2506
- this.pushParams(params);
2507
-
2508
- this.opcode('pushProgram', program);
2509
- this.opcode('pushProgram', inverse);
2651
+ // the params and contexts arguments are passed in arrays
2652
+ // to fill in
2653
+ setupParams: function(paramSize, params, useRegister) {
2654
+ var options = '{' + this.setupOptions(paramSize, params).join(',') + '}';
2510
2655
 
2511
- if(mustache.hash) {
2512
- this.hash(mustache.hash);
2656
+ if (useRegister) {
2657
+ this.useRegister('options');
2658
+ params.push('options');
2659
+ return 'options=' + options;
2513
2660
  } else {
2514
- this.opcode('emptyHash');
2661
+ params.push(options);
2662
+ return '';
2515
2663
  }
2516
-
2517
- return params;
2518
2664
  }
2519
2665
  };
2520
2666
 
2521
- function precompile(input, options) {
2522
- if (input == null || (typeof input !== 'string' && input.constructor !== AST.ProgramNode)) {
2523
- throw new Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
2524
- }
2667
+ var reservedWords = (
2668
+ "break else new var" +
2669
+ " case finally return void" +
2670
+ " catch for switch while" +
2671
+ " continue function this with" +
2672
+ " default if throw" +
2673
+ " delete in try" +
2674
+ " do instanceof typeof" +
2675
+ " abstract enum int short" +
2676
+ " boolean export interface static" +
2677
+ " byte extends long super" +
2678
+ " char final native synchronized" +
2679
+ " class float package throws" +
2680
+ " const goto private transient" +
2681
+ " debugger implements protected volatile" +
2682
+ " double import public let yield"
2683
+ ).split(" ");
2525
2684
 
2526
- options = options || {};
2527
- if (!('data' in options)) {
2528
- options.data = true;
2529
- }
2685
+ var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
2530
2686
 
2531
- var ast = parse(input);
2532
- var environment = new Compiler().compile(ast, options);
2533
- return new JavaScriptCompiler().compile(environment, options);
2687
+ for(var i=0, l=reservedWords.length; i<l; i++) {
2688
+ compilerWords[reservedWords[i]] = true;
2534
2689
  }
2535
2690
 
2536
- __exports__.precompile = precompile;function compile(input, options, env) {
2537
- if (input == null || (typeof input !== 'string' && input.constructor !== AST.ProgramNode)) {
2538
- throw new Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
2539
- }
2540
-
2541
- options = options || {};
2542
-
2543
- if (!('data' in options)) {
2544
- options.data = true;
2545
- }
2546
-
2547
- var compiled;
2548
-
2549
- function compileInput() {
2550
- var ast = parse(input);
2551
- var environment = new Compiler().compile(ast, options);
2552
- var templateSpec = new JavaScriptCompiler().compile(environment, options, undefined, true);
2553
- return env.template(templateSpec);
2691
+ JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
2692
+ if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) {
2693
+ return true;
2554
2694
  }
2695
+ return false;
2696
+ };
2555
2697
 
2556
- // Template is only compiled on first use and cached after that point.
2557
- return function(context, options) {
2558
- if (!compiled) {
2559
- compiled = compileInput();
2560
- }
2561
- return compiled.call(this, context, options);
2562
- };
2563
- }
2564
-
2565
- __exports__.compile = compile;
2698
+ __exports__ = JavaScriptCompiler;
2566
2699
  return __exports__;
2567
- })(__module5__, __module8__, __module11__, __module7__);
2700
+ })(__module2__, __module5__);
2568
2701
 
2569
2702
  // handlebars.js
2570
2703
  var __module0__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
@@ -2589,7 +2722,9 @@ var __module0__ = (function(__dependency1__, __dependency2__, __dependency3__, _
2589
2722
  hb.compile = function(input, options) {
2590
2723
  return compile(input, options, hb);
2591
2724
  };
2592
- hb.precompile = precompile;
2725
+ hb.precompile = function (input, options) {
2726
+ return precompile(input, options, hb);
2727
+ };
2593
2728
 
2594
2729
  hb.AST = AST;
2595
2730
  hb.Compiler = Compiler;