barber 0.2.1 → 0.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.
- data/lib/barber/javascripts/ember-template-compiler.js +310 -95
- data/lib/barber/javascripts/handlebars.js +298 -89
- data/lib/barber/precompiler.rb +1 -1
- data/lib/barber/version.rb +1 -1
- metadata +4 -4
@@ -1,10 +1,34 @@
|
|
1
1
|
(function() {
|
2
2
|
var Ember = { assert: function() {} };
|
3
|
-
// Version: v1.0.0-
|
4
|
-
// Last commit:
|
3
|
+
// Version: v1.0.0-rc.1
|
4
|
+
// Last commit: 8b061b4 (2013-02-15 12:10:22 -0800)
|
5
5
|
|
6
6
|
|
7
7
|
(function() {
|
8
|
+
/*
|
9
|
+
|
10
|
+
Copyright (C) 2011 by Yehuda Katz
|
11
|
+
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
14
|
+
in the Software without restriction, including without limitation the rights
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
17
|
+
furnished to do so, subject to the following conditions:
|
18
|
+
|
19
|
+
The above copyright notice and this permission notice shall be included in
|
20
|
+
all copies or substantial portions of the Software.
|
21
|
+
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
28
|
+
THE SOFTWARE.
|
29
|
+
|
30
|
+
*/
|
31
|
+
|
8
32
|
// lib/handlebars/base.js
|
9
33
|
|
10
34
|
/*jshint eqnull:true*/
|
@@ -12,7 +36,13 @@ this.Handlebars = {};
|
|
12
36
|
|
13
37
|
(function(Handlebars) {
|
14
38
|
|
15
|
-
Handlebars.VERSION = "1.0.rc.
|
39
|
+
Handlebars.VERSION = "1.0.0-rc.3";
|
40
|
+
Handlebars.COMPILER_REVISION = 2;
|
41
|
+
|
42
|
+
Handlebars.REVISION_CHANGES = {
|
43
|
+
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
|
44
|
+
2: '>= 1.0.0-rc.3'
|
45
|
+
};
|
16
46
|
|
17
47
|
Handlebars.helpers = {};
|
18
48
|
Handlebars.partials = {};
|
@@ -625,9 +655,13 @@ return new Parser;
|
|
625
655
|
// lib/handlebars/compiler/base.js
|
626
656
|
Handlebars.Parser = handlebars;
|
627
657
|
|
628
|
-
Handlebars.parse = function(
|
658
|
+
Handlebars.parse = function(input) {
|
659
|
+
|
660
|
+
// Just return if an already-compile AST was passed in.
|
661
|
+
if(input.constructor === Handlebars.AST.ProgramNode) { return input; }
|
662
|
+
|
629
663
|
Handlebars.Parser.yy = Handlebars.AST;
|
630
|
-
return Handlebars.Parser.parse(
|
664
|
+
return Handlebars.Parser.parse(input);
|
631
665
|
};
|
632
666
|
|
633
667
|
Handlebars.print = function(ast) {
|
@@ -709,8 +743,11 @@ Handlebars.print = function(ast) {
|
|
709
743
|
for(var i=0,l=parts.length; i<l; i++) {
|
710
744
|
var part = parts[i];
|
711
745
|
|
712
|
-
if(part === "..") {
|
713
|
-
|
746
|
+
if (part === ".." || part === "." || part === "this") {
|
747
|
+
if (dig.length > 0) { throw new Handlebars.Exception("Invalid path: " + this.original); }
|
748
|
+
else if (part === "..") { depth++; }
|
749
|
+
else { this.isScoped = true; }
|
750
|
+
}
|
714
751
|
else { dig.push(part); }
|
715
752
|
}
|
716
753
|
|
@@ -860,6 +897,26 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
860
897
|
|
861
898
|
return out.join("\n");
|
862
899
|
},
|
900
|
+
equals: function(other) {
|
901
|
+
var len = this.opcodes.length;
|
902
|
+
if (other.opcodes.length !== len) {
|
903
|
+
return false;
|
904
|
+
}
|
905
|
+
|
906
|
+
for (var i = 0; i < len; i++) {
|
907
|
+
var opcode = this.opcodes[i],
|
908
|
+
otherOpcode = other.opcodes[i];
|
909
|
+
if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
|
910
|
+
return false;
|
911
|
+
}
|
912
|
+
for (var j = 0; j < opcode.args.length; j++) {
|
913
|
+
if (opcode.args[j] !== otherOpcode.args[j]) {
|
914
|
+
return false;
|
915
|
+
}
|
916
|
+
}
|
917
|
+
}
|
918
|
+
return true;
|
919
|
+
},
|
863
920
|
|
864
921
|
guid: 0,
|
865
922
|
|
@@ -951,7 +1008,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
951
1008
|
// evaluate it by executing `blockHelperMissing`
|
952
1009
|
this.opcode('pushProgram', program);
|
953
1010
|
this.opcode('pushProgram', inverse);
|
954
|
-
this.opcode('
|
1011
|
+
this.opcode('emptyHash');
|
955
1012
|
this.opcode('blockValue');
|
956
1013
|
} else {
|
957
1014
|
this.ambiguousMustache(mustache, program, inverse);
|
@@ -960,7 +1017,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
960
1017
|
// evaluate it by executing `blockHelperMissing`
|
961
1018
|
this.opcode('pushProgram', program);
|
962
1019
|
this.opcode('pushProgram', inverse);
|
963
|
-
this.opcode('
|
1020
|
+
this.opcode('emptyHash');
|
964
1021
|
this.opcode('ambiguousBlockValue');
|
965
1022
|
}
|
966
1023
|
|
@@ -984,6 +1041,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
984
1041
|
|
985
1042
|
this.opcode('assignToHash', pair[0]);
|
986
1043
|
}
|
1044
|
+
this.opcode('popHash');
|
987
1045
|
},
|
988
1046
|
|
989
1047
|
partial: function(partial) {
|
@@ -1024,17 +1082,19 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1024
1082
|
},
|
1025
1083
|
|
1026
1084
|
ambiguousMustache: function(mustache, program, inverse) {
|
1027
|
-
var id = mustache.id,
|
1085
|
+
var id = mustache.id,
|
1086
|
+
name = id.parts[0],
|
1087
|
+
isBlock = program != null || inverse != null;
|
1028
1088
|
|
1029
1089
|
this.opcode('getContext', id.depth);
|
1030
1090
|
|
1031
1091
|
this.opcode('pushProgram', program);
|
1032
1092
|
this.opcode('pushProgram', inverse);
|
1033
1093
|
|
1034
|
-
this.opcode('invokeAmbiguous', name);
|
1094
|
+
this.opcode('invokeAmbiguous', name, isBlock);
|
1035
1095
|
},
|
1036
1096
|
|
1037
|
-
simpleMustache: function(mustache
|
1097
|
+
simpleMustache: function(mustache) {
|
1038
1098
|
var id = mustache.id;
|
1039
1099
|
|
1040
1100
|
if (id.type === 'DATA') {
|
@@ -1165,7 +1225,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1165
1225
|
if(mustache.hash) {
|
1166
1226
|
this.hash(mustache.hash);
|
1167
1227
|
} else {
|
1168
|
-
this.opcode('
|
1228
|
+
this.opcode('emptyHash');
|
1169
1229
|
}
|
1170
1230
|
|
1171
1231
|
return params;
|
@@ -1182,7 +1242,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1182
1242
|
if(mustache.hash) {
|
1183
1243
|
this.hash(mustache.hash);
|
1184
1244
|
} else {
|
1185
|
-
this.opcode('
|
1245
|
+
this.opcode('emptyHash');
|
1186
1246
|
}
|
1187
1247
|
|
1188
1248
|
return params;
|
@@ -1196,7 +1256,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1196
1256
|
JavaScriptCompiler.prototype = {
|
1197
1257
|
// PUBLIC API: You can override these methods in a subclass to provide
|
1198
1258
|
// alternative compiled forms for name lookup and buffering semantics
|
1199
|
-
nameLookup: function(parent, name, type) {
|
1259
|
+
nameLookup: function(parent, name /* , type*/) {
|
1200
1260
|
if (/^[0-9]+$/.test(name)) {
|
1201
1261
|
return parent + "[" + name + "]";
|
1202
1262
|
} else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
@@ -1211,7 +1271,11 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1211
1271
|
if (this.environment.isSimple) {
|
1212
1272
|
return "return " + string + ";";
|
1213
1273
|
} else {
|
1214
|
-
return
|
1274
|
+
return {
|
1275
|
+
appendToBuffer: true,
|
1276
|
+
content: string,
|
1277
|
+
toString: function() { return "buffer += " + string + ";"; }
|
1278
|
+
};
|
1215
1279
|
}
|
1216
1280
|
},
|
1217
1281
|
|
@@ -1232,6 +1296,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1232
1296
|
this.isChild = !!context;
|
1233
1297
|
this.context = context || {
|
1234
1298
|
programs: [],
|
1299
|
+
environments: [],
|
1235
1300
|
aliases: { }
|
1236
1301
|
};
|
1237
1302
|
|
@@ -1241,6 +1306,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1241
1306
|
this.stackVars = [];
|
1242
1307
|
this.registers = { list: [] };
|
1243
1308
|
this.compileStack = [];
|
1309
|
+
this.inlineStack = [];
|
1244
1310
|
|
1245
1311
|
this.compileChildren(environment, options);
|
1246
1312
|
|
@@ -1262,11 +1328,11 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1262
1328
|
},
|
1263
1329
|
|
1264
1330
|
nextOpcode: function() {
|
1265
|
-
var opcodes = this.environment.opcodes
|
1331
|
+
var opcodes = this.environment.opcodes;
|
1266
1332
|
return opcodes[this.i + 1];
|
1267
1333
|
},
|
1268
1334
|
|
1269
|
-
eat: function(
|
1335
|
+
eat: function() {
|
1270
1336
|
this.i = this.i + 1;
|
1271
1337
|
},
|
1272
1338
|
|
@@ -1304,7 +1370,6 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1304
1370
|
|
1305
1371
|
// Generate minimizer alias mappings
|
1306
1372
|
if (!this.isChild) {
|
1307
|
-
var aliases = [];
|
1308
1373
|
for (var alias in this.context.aliases) {
|
1309
1374
|
this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
|
1310
1375
|
}
|
@@ -1329,16 +1394,48 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1329
1394
|
params.push("depth" + this.environment.depths.list[i]);
|
1330
1395
|
}
|
1331
1396
|
|
1397
|
+
// Perform a second pass over the output to merge content when possible
|
1398
|
+
var source = this.mergeSource();
|
1399
|
+
|
1400
|
+
if (!this.isChild) {
|
1401
|
+
var revision = Handlebars.COMPILER_REVISION,
|
1402
|
+
versions = Handlebars.REVISION_CHANGES[revision];
|
1403
|
+
source = "this.compilerInfo = ["+revision+",'"+versions+"'];\n"+source;
|
1404
|
+
}
|
1405
|
+
|
1332
1406
|
if (asObject) {
|
1333
|
-
params.push(
|
1407
|
+
params.push(source);
|
1334
1408
|
|
1335
1409
|
return Function.apply(this, params);
|
1336
1410
|
} else {
|
1337
|
-
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' +
|
1411
|
+
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}';
|
1338
1412
|
Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
|
1339
1413
|
return functionSource;
|
1340
1414
|
}
|
1341
1415
|
},
|
1416
|
+
mergeSource: function() {
|
1417
|
+
// WARN: We are not handling the case where buffer is still populated as the source should
|
1418
|
+
// not have buffer append operations as their final action.
|
1419
|
+
var source = '',
|
1420
|
+
buffer;
|
1421
|
+
for (var i = 0, len = this.source.length; i < len; i++) {
|
1422
|
+
var line = this.source[i];
|
1423
|
+
if (line.appendToBuffer) {
|
1424
|
+
if (buffer) {
|
1425
|
+
buffer = buffer + '\n + ' + line.content;
|
1426
|
+
} else {
|
1427
|
+
buffer = line.content;
|
1428
|
+
}
|
1429
|
+
} else {
|
1430
|
+
if (buffer) {
|
1431
|
+
source += 'buffer += ' + buffer + ';\n ';
|
1432
|
+
buffer = undefined;
|
1433
|
+
}
|
1434
|
+
source += line + '\n ';
|
1435
|
+
}
|
1436
|
+
}
|
1437
|
+
return source;
|
1438
|
+
},
|
1342
1439
|
|
1343
1440
|
// [blockValue]
|
1344
1441
|
//
|
@@ -1376,6 +1473,9 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1376
1473
|
var current = this.topStack();
|
1377
1474
|
params.splice(1, 0, current);
|
1378
1475
|
|
1476
|
+
// Use the options value generated from the invocation
|
1477
|
+
params[params.length-1] = 'options';
|
1478
|
+
|
1379
1479
|
this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
|
1380
1480
|
},
|
1381
1481
|
|
@@ -1399,6 +1499,9 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1399
1499
|
// If `value` is truthy, or 0, it is coerced into a string and appended
|
1400
1500
|
// Otherwise, the empty string is appended
|
1401
1501
|
append: function() {
|
1502
|
+
// Force anything that is inlined onto the stack so we don't have duplication
|
1503
|
+
// when we examine local
|
1504
|
+
this.flushInline();
|
1402
1505
|
var local = this.popStack();
|
1403
1506
|
this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
|
1404
1507
|
if (this.environment.isSimple) {
|
@@ -1413,15 +1516,9 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1413
1516
|
//
|
1414
1517
|
// Escape `value` and append it to the buffer
|
1415
1518
|
appendEscaped: function() {
|
1416
|
-
var opcode = this.nextOpcode(), extra = "";
|
1417
1519
|
this.context.aliases.escapeExpression = 'this.escapeExpression';
|
1418
1520
|
|
1419
|
-
|
1420
|
-
extra = " + " + this.quotedString(opcode.args[0]);
|
1421
|
-
this.eat(opcode);
|
1422
|
-
}
|
1423
|
-
|
1424
|
-
this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")" + extra));
|
1521
|
+
this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
|
1425
1522
|
},
|
1426
1523
|
|
1427
1524
|
// [getContext]
|
@@ -1445,7 +1542,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1445
1542
|
// Looks up the value of `name` on the current context and pushes
|
1446
1543
|
// it onto the stack.
|
1447
1544
|
lookupOnContext: function(name) {
|
1448
|
-
this.
|
1545
|
+
this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
|
1449
1546
|
},
|
1450
1547
|
|
1451
1548
|
// [pushContext]
|
@@ -1493,7 +1590,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1493
1590
|
//
|
1494
1591
|
// Push the result of looking up `id` on the current data
|
1495
1592
|
lookupData: function(id) {
|
1496
|
-
this.
|
1593
|
+
this.push(this.nameLookup('data', id, 'data'));
|
1497
1594
|
},
|
1498
1595
|
|
1499
1596
|
// [pushStringParam]
|
@@ -1516,13 +1613,25 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1516
1613
|
}
|
1517
1614
|
},
|
1518
1615
|
|
1519
|
-
|
1520
|
-
this.
|
1616
|
+
emptyHash: function() {
|
1617
|
+
this.pushStackLiteral('{}');
|
1521
1618
|
|
1522
1619
|
if (this.options.stringParams) {
|
1523
1620
|
this.register('hashTypes', '{}');
|
1524
1621
|
}
|
1525
1622
|
},
|
1623
|
+
pushHash: function() {
|
1624
|
+
this.hash = {values: [], types: []};
|
1625
|
+
},
|
1626
|
+
popHash: function() {
|
1627
|
+
var hash = this.hash;
|
1628
|
+
this.hash = undefined;
|
1629
|
+
|
1630
|
+
if (this.options.stringParams) {
|
1631
|
+
this.register('hashTypes', '{' + hash.types.join(',') + '}');
|
1632
|
+
}
|
1633
|
+
this.push('{\n ' + hash.values.join(',\n ') + '\n }');
|
1634
|
+
},
|
1526
1635
|
|
1527
1636
|
// [pushString]
|
1528
1637
|
//
|
@@ -1541,7 +1650,8 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1541
1650
|
//
|
1542
1651
|
// Push an expression onto the stack
|
1543
1652
|
push: function(expr) {
|
1544
|
-
this.
|
1653
|
+
this.inlineStack.push(expr);
|
1654
|
+
return expr;
|
1545
1655
|
},
|
1546
1656
|
|
1547
1657
|
// [pushLiteral]
|
@@ -1584,12 +1694,14 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1584
1694
|
invokeHelper: function(paramSize, name) {
|
1585
1695
|
this.context.aliases.helperMissing = 'helpers.helperMissing';
|
1586
1696
|
|
1587
|
-
var helper = this.lastHelper = this.setupHelper(paramSize, name);
|
1588
|
-
this.register('foundHelper', helper.name);
|
1697
|
+
var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
|
1589
1698
|
|
1590
|
-
this.
|
1591
|
-
|
1592
|
-
|
1699
|
+
this.push(helper.name);
|
1700
|
+
this.replaceStack(function(name) {
|
1701
|
+
return name + ' ? ' + name + '.call(' +
|
1702
|
+
helper.callParams + ") " + ": helperMissing.call(" +
|
1703
|
+
helper.helperMissingParams + ")";
|
1704
|
+
});
|
1593
1705
|
},
|
1594
1706
|
|
1595
1707
|
// [invokeKnownHelper]
|
@@ -1601,7 +1713,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1601
1713
|
// so a `helperMissing` fallback is not required.
|
1602
1714
|
invokeKnownHelper: function(paramSize, name) {
|
1603
1715
|
var helper = this.setupHelper(paramSize, name);
|
1604
|
-
this.
|
1716
|
+
this.push(helper.name + ".call(" + helper.callParams + ")");
|
1605
1717
|
},
|
1606
1718
|
|
1607
1719
|
// [invokeAmbiguous]
|
@@ -1616,19 +1728,18 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1616
1728
|
// This operation emits more code than the other options,
|
1617
1729
|
// and can be avoided by passing the `knownHelpers` and
|
1618
1730
|
// `knownHelpersOnly` flags at compile-time.
|
1619
|
-
invokeAmbiguous: function(name) {
|
1731
|
+
invokeAmbiguous: function(name, helperCall) {
|
1620
1732
|
this.context.aliases.functionType = '"function"';
|
1621
1733
|
|
1622
|
-
this.pushStackLiteral('{}');
|
1623
|
-
var helper = this.setupHelper(0, name);
|
1734
|
+
this.pushStackLiteral('{}'); // Hash value
|
1735
|
+
var helper = this.setupHelper(0, name, helperCall);
|
1624
1736
|
|
1625
1737
|
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
|
1626
|
-
this.register('foundHelper', helperName);
|
1627
1738
|
|
1628
1739
|
var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
|
1629
1740
|
var nextStack = this.nextStack();
|
1630
1741
|
|
1631
|
-
this.source.push('if (
|
1742
|
+
this.source.push('if (' + nextStack + ' = ' + helperName + ') { ' + nextStack + ' = ' + nextStack + '.call(' + helper.callParams + '); }');
|
1632
1743
|
this.source.push('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '.apply(depth0) : ' + nextStack + '; }');
|
1633
1744
|
},
|
1634
1745
|
|
@@ -1647,7 +1758,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1647
1758
|
}
|
1648
1759
|
|
1649
1760
|
this.context.aliases.self = "this";
|
1650
|
-
this.
|
1761
|
+
this.push("self.invokePartial(" + params.join(", ") + ")");
|
1651
1762
|
},
|
1652
1763
|
|
1653
1764
|
// [assignToHash]
|
@@ -1658,17 +1769,19 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1658
1769
|
// Pops a value and hash off the stack, assigns `hash[key] = value`
|
1659
1770
|
// and pushes the hash back onto the stack.
|
1660
1771
|
assignToHash: function(key) {
|
1661
|
-
var value = this.popStack()
|
1772
|
+
var value = this.popStack(),
|
1773
|
+
type;
|
1662
1774
|
|
1663
1775
|
if (this.options.stringParams) {
|
1664
|
-
|
1776
|
+
type = this.popStack();
|
1665
1777
|
this.popStack();
|
1666
|
-
this.source.push("hashTypes['" + key + "'] = " + type + ";");
|
1667
1778
|
}
|
1668
1779
|
|
1669
|
-
var hash = this.
|
1670
|
-
|
1671
|
-
|
1780
|
+
var hash = this.hash;
|
1781
|
+
if (type) {
|
1782
|
+
hash.types.push("'" + key + "': " + type);
|
1783
|
+
}
|
1784
|
+
hash.values.push("'" + key + "': (" + value + ")");
|
1672
1785
|
},
|
1673
1786
|
|
1674
1787
|
// HELPERS
|
@@ -1682,11 +1795,27 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1682
1795
|
child = children[i];
|
1683
1796
|
compiler = new this.compiler();
|
1684
1797
|
|
1685
|
-
this.
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1798
|
+
var index = this.matchExistingProgram(child);
|
1799
|
+
|
1800
|
+
if (index == null) {
|
1801
|
+
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
|
1802
|
+
index = this.context.programs.length;
|
1803
|
+
child.index = index;
|
1804
|
+
child.name = 'program' + index;
|
1805
|
+
this.context.programs[index] = compiler.compile(child, options, this.context);
|
1806
|
+
this.context.environments[index] = child;
|
1807
|
+
} else {
|
1808
|
+
child.index = index;
|
1809
|
+
child.name = 'program' + index;
|
1810
|
+
}
|
1811
|
+
}
|
1812
|
+
},
|
1813
|
+
matchExistingProgram: function(child) {
|
1814
|
+
for (var i = 0, len = this.context.environments.length; i < len; i++) {
|
1815
|
+
var environment = this.context.environments[i];
|
1816
|
+
if (environment && environment.equals(child)) {
|
1817
|
+
return i;
|
1818
|
+
}
|
1690
1819
|
}
|
1691
1820
|
},
|
1692
1821
|
|
@@ -1730,57 +1859,111 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1730
1859
|
},
|
1731
1860
|
|
1732
1861
|
pushStackLiteral: function(item) {
|
1733
|
-
this.
|
1734
|
-
return item;
|
1862
|
+
return this.push(new Literal(item));
|
1735
1863
|
},
|
1736
1864
|
|
1737
1865
|
pushStack: function(item) {
|
1866
|
+
this.flushInline();
|
1867
|
+
|
1738
1868
|
var stack = this.incrStack();
|
1739
|
-
|
1869
|
+
if (item) {
|
1870
|
+
this.source.push(stack + " = " + item + ";");
|
1871
|
+
}
|
1740
1872
|
this.compileStack.push(stack);
|
1741
1873
|
return stack;
|
1742
1874
|
},
|
1743
1875
|
|
1744
1876
|
replaceStack: function(callback) {
|
1745
|
-
var
|
1746
|
-
|
1877
|
+
var prefix = '',
|
1878
|
+
inline = this.isInline(),
|
1879
|
+
stack;
|
1880
|
+
|
1881
|
+
// If we are currently inline then we want to merge the inline statement into the
|
1882
|
+
// replacement statement via ','
|
1883
|
+
if (inline) {
|
1884
|
+
var top = this.popStack(true);
|
1885
|
+
|
1886
|
+
if (top instanceof Literal) {
|
1887
|
+
// Literals do not need to be inlined
|
1888
|
+
stack = top.value;
|
1889
|
+
} else {
|
1890
|
+
// Get or create the current stack name for use by the inline
|
1891
|
+
var name = this.stackSlot ? this.topStackName() : this.incrStack();
|
1747
1892
|
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1893
|
+
prefix = '(' + this.push(name) + ' = ' + top + '),';
|
1894
|
+
stack = this.topStack();
|
1895
|
+
}
|
1896
|
+
} else {
|
1897
|
+
stack = this.topStack();
|
1751
1898
|
}
|
1752
1899
|
|
1753
|
-
|
1900
|
+
var item = callback.call(this, stack);
|
1901
|
+
|
1902
|
+
if (inline) {
|
1903
|
+
if (this.inlineStack.length || this.compileStack.length) {
|
1904
|
+
this.popStack();
|
1905
|
+
}
|
1906
|
+
this.push('(' + prefix + item + ')');
|
1907
|
+
} else {
|
1908
|
+
// Prevent modification of the context depth variable. Through replaceStack
|
1909
|
+
if (!/^stack/.test(stack)) {
|
1910
|
+
stack = this.nextStack();
|
1911
|
+
}
|
1912
|
+
|
1913
|
+
this.source.push(stack + " = (" + prefix + item + ");");
|
1914
|
+
}
|
1754
1915
|
return stack;
|
1755
1916
|
},
|
1756
1917
|
|
1757
|
-
nextStack: function(
|
1758
|
-
|
1759
|
-
this.compileStack.push(name);
|
1760
|
-
return name;
|
1918
|
+
nextStack: function() {
|
1919
|
+
return this.pushStack();
|
1761
1920
|
},
|
1762
1921
|
|
1763
1922
|
incrStack: function() {
|
1764
1923
|
this.stackSlot++;
|
1765
1924
|
if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
|
1925
|
+
return this.topStackName();
|
1926
|
+
},
|
1927
|
+
topStackName: function() {
|
1766
1928
|
return "stack" + this.stackSlot;
|
1767
1929
|
},
|
1930
|
+
flushInline: function() {
|
1931
|
+
var inlineStack = this.inlineStack;
|
1932
|
+
if (inlineStack.length) {
|
1933
|
+
this.inlineStack = [];
|
1934
|
+
for (var i = 0, len = inlineStack.length; i < len; i++) {
|
1935
|
+
var entry = inlineStack[i];
|
1936
|
+
if (entry instanceof Literal) {
|
1937
|
+
this.compileStack.push(entry);
|
1938
|
+
} else {
|
1939
|
+
this.pushStack(entry);
|
1940
|
+
}
|
1941
|
+
}
|
1942
|
+
}
|
1943
|
+
},
|
1944
|
+
isInline: function() {
|
1945
|
+
return this.inlineStack.length;
|
1946
|
+
},
|
1768
1947
|
|
1769
|
-
popStack: function() {
|
1770
|
-
var
|
1948
|
+
popStack: function(wrapped) {
|
1949
|
+
var inline = this.isInline(),
|
1950
|
+
item = (inline ? this.inlineStack : this.compileStack).pop();
|
1771
1951
|
|
1772
|
-
if (item instanceof Literal) {
|
1952
|
+
if (!wrapped && (item instanceof Literal)) {
|
1773
1953
|
return item.value;
|
1774
1954
|
} else {
|
1775
|
-
|
1955
|
+
if (!inline) {
|
1956
|
+
this.stackSlot--;
|
1957
|
+
}
|
1776
1958
|
return item;
|
1777
1959
|
}
|
1778
1960
|
},
|
1779
1961
|
|
1780
|
-
topStack: function() {
|
1781
|
-
var
|
1962
|
+
topStack: function(wrapped) {
|
1963
|
+
var stack = (this.isInline() ? this.inlineStack : this.compileStack),
|
1964
|
+
item = stack[stack.length - 1];
|
1782
1965
|
|
1783
|
-
if (item instanceof Literal) {
|
1966
|
+
if (!wrapped && (item instanceof Literal)) {
|
1784
1967
|
return item.value;
|
1785
1968
|
} else {
|
1786
1969
|
return item;
|
@@ -1795,22 +1978,22 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1795
1978
|
.replace(/\r/g, '\\r') + '"';
|
1796
1979
|
},
|
1797
1980
|
|
1798
|
-
setupHelper: function(paramSize, name) {
|
1981
|
+
setupHelper: function(paramSize, name, missingParams) {
|
1799
1982
|
var params = [];
|
1800
|
-
this.setupParams(paramSize, params);
|
1983
|
+
this.setupParams(paramSize, params, missingParams);
|
1801
1984
|
var foundHelper = this.nameLookup('helpers', name, 'helper');
|
1802
1985
|
|
1803
1986
|
return {
|
1804
1987
|
params: params,
|
1805
1988
|
name: foundHelper,
|
1806
1989
|
callParams: ["depth0"].concat(params).join(", "),
|
1807
|
-
helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ")
|
1990
|
+
helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ")
|
1808
1991
|
};
|
1809
1992
|
},
|
1810
1993
|
|
1811
1994
|
// the params and contexts arguments are passed in arrays
|
1812
1995
|
// to fill in
|
1813
|
-
setupParams: function(paramSize, params) {
|
1996
|
+
setupParams: function(paramSize, params, useRegister) {
|
1814
1997
|
var options = [], contexts = [], types = [], param, inverse, program;
|
1815
1998
|
|
1816
1999
|
options.push("hash:" + this.popStack());
|
@@ -1855,7 +2038,13 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1855
2038
|
options.push("data:data");
|
1856
2039
|
}
|
1857
2040
|
|
1858
|
-
|
2041
|
+
options = "{" + options.join(",") + "}";
|
2042
|
+
if (useRegister) {
|
2043
|
+
this.register('options', options);
|
2044
|
+
params.push('options');
|
2045
|
+
} else {
|
2046
|
+
params.push(options);
|
2047
|
+
}
|
1859
2048
|
return params.join(", ");
|
1860
2049
|
}
|
1861
2050
|
};
|
@@ -1893,23 +2082,23 @@ Handlebars.JavaScriptCompiler = function() {};
|
|
1893
2082
|
|
1894
2083
|
})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);
|
1895
2084
|
|
1896
|
-
Handlebars.precompile = function(
|
1897
|
-
if (typeof
|
1898
|
-
throw new Handlebars.Exception("You must pass a string to Handlebars.compile. You passed " +
|
2085
|
+
Handlebars.precompile = function(input, options) {
|
2086
|
+
if (!input || (typeof input !== 'string' && input.constructor !== Handlebars.AST.ProgramNode)) {
|
2087
|
+
throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
|
1899
2088
|
}
|
1900
2089
|
|
1901
2090
|
options = options || {};
|
1902
2091
|
if (!('data' in options)) {
|
1903
2092
|
options.data = true;
|
1904
2093
|
}
|
1905
|
-
var ast = Handlebars.parse(
|
2094
|
+
var ast = Handlebars.parse(input);
|
1906
2095
|
var environment = new Handlebars.Compiler().compile(ast, options);
|
1907
2096
|
return new Handlebars.JavaScriptCompiler().compile(environment, options);
|
1908
2097
|
};
|
1909
2098
|
|
1910
|
-
Handlebars.compile = function(
|
1911
|
-
if (typeof
|
1912
|
-
throw new Handlebars.Exception("You must pass a string to Handlebars.compile. You passed " +
|
2099
|
+
Handlebars.compile = function(input, options) {
|
2100
|
+
if (!input || (typeof input !== 'string' && input.constructor !== Handlebars.AST.ProgramNode)) {
|
2101
|
+
throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
|
1913
2102
|
}
|
1914
2103
|
|
1915
2104
|
options = options || {};
|
@@ -1918,7 +2107,7 @@ Handlebars.compile = function(string, options) {
|
|
1918
2107
|
}
|
1919
2108
|
var compiled;
|
1920
2109
|
function compile() {
|
1921
|
-
var ast = Handlebars.parse(
|
2110
|
+
var ast = Handlebars.parse(input);
|
1922
2111
|
var environment = new Handlebars.Compiler().compile(ast, options);
|
1923
2112
|
var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
|
1924
2113
|
return Handlebars.template(templateSpec);
|
@@ -1953,12 +2142,32 @@ Handlebars.VM = {
|
|
1953
2142
|
}
|
1954
2143
|
},
|
1955
2144
|
programWithDepth: Handlebars.VM.programWithDepth,
|
1956
|
-
noop: Handlebars.VM.noop
|
2145
|
+
noop: Handlebars.VM.noop,
|
2146
|
+
compilerInfo: null
|
1957
2147
|
};
|
1958
2148
|
|
1959
2149
|
return function(context, options) {
|
1960
2150
|
options = options || {};
|
1961
|
-
|
2151
|
+
var result = templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
|
2152
|
+
|
2153
|
+
var compilerInfo = container.compilerInfo || [],
|
2154
|
+
compilerRevision = compilerInfo[0] || 1,
|
2155
|
+
currentRevision = Handlebars.COMPILER_REVISION;
|
2156
|
+
|
2157
|
+
if (compilerRevision !== currentRevision) {
|
2158
|
+
if (compilerRevision < currentRevision) {
|
2159
|
+
var runtimeVersions = Handlebars.REVISION_CHANGES[currentRevision],
|
2160
|
+
compilerVersions = Handlebars.REVISION_CHANGES[compilerRevision];
|
2161
|
+
throw "Template was precompiled with an older version of Handlebars than the current runtime. "+
|
2162
|
+
"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").";
|
2163
|
+
} else {
|
2164
|
+
// Use the embedded version info since the runtime doesn't know about this revision yet
|
2165
|
+
throw "Template was precompiled with a newer version of Handlebars than the current runtime. "+
|
2166
|
+
"Please update your runtime to a newer version ("+compilerInfo[1]+").";
|
2167
|
+
}
|
2168
|
+
}
|
2169
|
+
|
2170
|
+
return result;
|
1962
2171
|
};
|
1963
2172
|
},
|
1964
2173
|
|
@@ -2014,7 +2223,7 @@ var objectCreate = Object.create || function(parent) {
|
|
2014
2223
|
};
|
2015
2224
|
|
2016
2225
|
var Handlebars = this.Handlebars || Ember.imports.Handlebars;
|
2017
|
-
Ember.assert("Ember Handlebars requires Handlebars 1.0.rc.
|
2226
|
+
Ember.assert("Ember Handlebars requires Handlebars 1.0.0-rc.3 or greater", Handlebars && Handlebars.VERSION.match(/^1\.0\.[0-9](\.rc\.[23456789]+)?/));
|
2018
2227
|
|
2019
2228
|
/**
|
2020
2229
|
Prepares the Handlebars templating library for use inside Ember's view
|
@@ -2091,6 +2300,8 @@ Ember.Handlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string)
|
|
2091
2300
|
return "data.buffer.push("+string+");";
|
2092
2301
|
};
|
2093
2302
|
|
2303
|
+
var prefix = "ember" + (+new Date()), incr = 1;
|
2304
|
+
|
2094
2305
|
/**
|
2095
2306
|
@private
|
2096
2307
|
|
@@ -2103,8 +2314,11 @@ Ember.Handlebars.JavaScriptCompiler.prototype.appendToBuffer = function(string)
|
|
2103
2314
|
@param mustache
|
2104
2315
|
*/
|
2105
2316
|
Ember.Handlebars.Compiler.prototype.mustache = function(mustache) {
|
2106
|
-
if (mustache.
|
2107
|
-
|
2317
|
+
if (mustache.isHelper && mustache.id.string === 'control') {
|
2318
|
+
mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]);
|
2319
|
+
mustache.hash.pairs.push(["controlID", new Handlebars.AST.StringNode(prefix + incr++)]);
|
2320
|
+
} else if (mustache.params.length || mustache.hash) {
|
2321
|
+
// no changes required
|
2108
2322
|
} else {
|
2109
2323
|
var id = new Handlebars.AST.IdNode(['_triageMustache']);
|
2110
2324
|
|
@@ -2116,8 +2330,9 @@ Ember.Handlebars.Compiler.prototype.mustache = function(mustache) {
|
|
2116
2330
|
mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]);
|
2117
2331
|
}
|
2118
2332
|
mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped);
|
2119
|
-
return Handlebars.Compiler.prototype.mustache.call(this, mustache);
|
2120
2333
|
}
|
2334
|
+
|
2335
|
+
return Handlebars.Compiler.prototype.mustache.call(this, mustache);
|
2121
2336
|
};
|
2122
2337
|
|
2123
2338
|
/**
|