handlebars-source 1.2.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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;