summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/handlebars/compiler/helpers.js15
-rw-r--r--spec/basic.js19
-rw-r--r--src/handlebars.l2
-rw-r--r--src/handlebars.yy8
4 files changed, 33 insertions, 11 deletions
diff --git a/lib/handlebars/compiler/helpers.js b/lib/handlebars/compiler/helpers.js
index beaf988..4a502d8 100644
--- a/lib/handlebars/compiler/helpers.js
+++ b/lib/handlebars/compiler/helpers.js
@@ -12,6 +12,14 @@ export function SourceLocation(source, locInfo) {
};
}
+export function id(token) {
+ if (/^\[.*\]$/.test(token)) {
+ return token.substr(1, token.length - 2);
+ } else {
+ return token;
+ }
+}
+
export function stripFlags(open, close) {
return {
open: open.charAt(2) === '~',
@@ -34,10 +42,13 @@ export function preparePath(data, parts, locInfo) {
depthString = '';
for(var i=0,l=parts.length; i<l; i++) {
- var part = parts[i].part;
+ var part = parts[i].part,
+ // If we have [] syntax then we do not treat path references as operators,
+ // i.e. foo.[this] resolves to approximately context.foo['this']
+ isLiteral = parts[i].original !== part;
original += (parts[i].separator || '') + part;
- if (part === '..' || part === '.' || part === 'this') {
+ if (!isLiteral && (part === '..' || part === '.' || part === 'this')) {
if (dig.length > 0) {
throw new Exception('Invalid path: ' + original, {loc: locInfo});
} else if (part === '..') {
diff --git a/spec/basic.js b/spec/basic.js
index e634d41..37aa8cf 100644
--- a/spec/basic.js
+++ b/spec/basic.js
@@ -227,10 +227,12 @@ describe("basic context", function() {
});
it("this keyword nested inside path", function() {
- var string = "{{#hellos}}{{text/this/foo}}{{/hellos}}";
shouldThrow(function() {
- CompilerContext.compile(string);
- }, Error);
+ CompilerContext.compile('{{#hellos}}{{text/this/foo}}{{/hellos}}');
+ }, Error, 'Invalid path: text/this - 1:13');
+
+ shouldCompileTo('{{[this]}}', {'this': 'bar'}, 'bar');
+ shouldCompileTo('{{text/[this]}}', {text: {'this': 'bar'}}, 'bar');
});
it("this keyword in helpers", function() {
@@ -251,7 +253,16 @@ describe("basic context", function() {
var string = "{{#hellos}}{{foo text/this/foo}}{{/hellos}}";
shouldThrow(function() {
CompilerContext.compile(string);
- }, Error);
+ }, Error, 'Invalid path: text/this - 1:17');
+
+ shouldCompileTo(
+ '{{foo [this]}}',
+ {foo: function(value) { return value; }, 'this': 'bar'},
+ 'bar');
+ shouldCompileTo(
+ '{{foo text/[this]}}',
+ {foo: function(value) { return value; }, text: {'this': 'bar'}},
+ 'bar');
});
it('pass string literals', function() {
diff --git a/src/handlebars.l b/src/handlebars.l
index 55d8efc..ff21283 100644
--- a/src/handlebars.l
+++ b/src/handlebars.l
@@ -110,7 +110,7 @@ ID [^\s!"#%-,\.\/;->@\[-\^`\{-~]+/{LOOKAHEAD}
<mu>{ID} return 'ID';
-<mu>'['[^\]]*']' yytext = strip(1,2); return 'ID';
+<mu>'['[^\]]*']' return 'ID';
<mu>. return 'INVALID';
<INITIAL,mu><<EOF>> return 'EOF';
diff --git a/src/handlebars.yy b/src/handlebars.yy
index 01ef7fb..d67a7da 100644
--- a/src/handlebars.yy
+++ b/src/handlebars.yy
@@ -94,11 +94,11 @@ hash
;
hashSegment
- : ID EQUALS param -> new yy.HashPair($1, $3, yy.locInfo(@$))
+ : ID EQUALS param -> new yy.HashPair(yy.id($1), $3, yy.locInfo(@$))
;
blockParams
- : OPEN_BLOCK_PARAMS ID+ CLOSE_BLOCK_PARAMS -> $2
+ : OPEN_BLOCK_PARAMS ID+ CLOSE_BLOCK_PARAMS -> yy.id($2)
;
helperName
@@ -125,6 +125,6 @@ path
;
pathSegments
- : pathSegments SEP ID { $1.push({part: $3, separator: $2}); $$ = $1; }
- | ID -> [{part: $1}]
+ : pathSegments SEP ID { $1.push({part: yy.id($3), original: $3, separator: $2}); $$ = $1; }
+ | ID -> [{part: yy.id($1), original: $1}]
;