Skip to content

Commit db651e7

Browse files
committed
Merge pull request #491 from wycats/data-depth
For nested helpers: get the @ variables of the outer helper from the inner one
2 parents fcec69a + 16f1358 commit db651e7

File tree

6 files changed

+39
-24
lines changed

6 files changed

+39
-24
lines changed

lib/handlebars/base.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -223,5 +223,7 @@ export var logger = {
223223
export function log(level, obj) { logger.log(level, obj); }
224224

225225
export var createFrame = function(object) {
226-
return Utils.extend({}, object);
226+
var frame = Utils.extend({}, object);
227+
frame._parent = object;
228+
return frame;
227229
};

lib/handlebars/compiler/compiler.js

+1-5
Original file line numberDiff line numberDiff line change
@@ -310,11 +310,7 @@ Compiler.prototype = {
310310

311311
DATA: function(data) {
312312
this.options.data = true;
313-
if (data.id.isScoped || data.id.depth) {
314-
throw new Exception('Scoped data references are not supported: ' + data.original, data);
315-
}
316-
317-
this.opcode('lookupData');
313+
this.opcode('lookupData', data.id.depth);
318314
var parts = data.id.parts;
319315
for(var i=0, l=parts.length; i<l; i++) {
320316
this.opcode('lookup', parts[i]);

lib/handlebars/compiler/javascript-compiler.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -403,8 +403,12 @@ JavaScriptCompiler.prototype = {
403403
// On stack, after: data, ...
404404
//
405405
// Push the data lookup operator
406-
lookupData: function() {
407-
this.pushStackLiteral('data');
406+
lookupData: function(depth) {
407+
if (!depth) {
408+
this.pushStackLiteral('data');
409+
} else {
410+
this.pushStackLiteral('this.data(data, ' + depth + ')');
411+
}
408412
},
409413

410414
// [pushStringParam]

lib/handlebars/runtime.js

+6
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ export function template(templateSpec, env) {
7777
}
7878
return data;
7979
},
80+
data: function(data, depth) {
81+
while (data && depth--) {
82+
data = data._parent;
83+
}
84+
return data;
85+
},
8086
merge: function(param, common) {
8187
var ret = param || common;
8288

spec/data.js

+19-16
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,6 @@ describe('data', function() {
8585
equals("Hello undefined", result, "@foo as a parameter retrieves template data");
8686
});
8787

88-
it("parameter data throws when using this scope references", function() {
89-
var string = "{{#goodbyes}}{{text}} cruel {{@./name}}! {{/goodbyes}}";
90-
91-
shouldThrow(function() {
92-
CompilerContext.compile(string);
93-
}, Error);
94-
});
95-
96-
it("parameter data throws when using parent scope references", function() {
97-
var string = "{{#goodbyes}}{{text}} cruel {{@../name}}! {{/goodbyes}}";
98-
99-
shouldThrow(function() {
100-
CompilerContext.compile(string);
101-
}, Error);
102-
});
103-
10488
it("parameter data throws when using complex scope references", function() {
10589
var string = "{{#goodbyes}}{{text}} cruel {{@foo/../name}}! {{/goodbyes}}";
10690

@@ -251,4 +235,23 @@ describe('data', function() {
251235
equals('hello', result);
252236
});
253237
});
238+
239+
describe('nesting', function() {
240+
it('the root context can be looked up via @root', function() {
241+
var template = CompilerContext.compile('{{#helper}}{{#helper}}{{@./depth}} {{@../depth}} {{@../../depth}}{{/helper}}{{/helper}}');
242+
var result = template({foo: 'hello'}, {
243+
helpers: {
244+
helper: function(options) {
245+
var frame = Handlebars.createFrame(options.data);
246+
frame.depth = options.data.depth + 1;
247+
return options.fn(this, {data: frame});
248+
}
249+
},
250+
data: {
251+
depth: 0
252+
}
253+
});
254+
equals('2 1 0', result);
255+
});
256+
});
254257
});

spec/parser.js

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ describe('parser', function() {
2121
equals(ast_for("{{@foo}}"), "{{ @ID:foo [] }}\n");
2222
});
2323

24+
it('parses simple mustaches with data paths', function() {
25+
equals(ast_for("{{@../foo}}"), "{{ @ID:foo [] }}\n");
26+
});
27+
2428
it('parses mustaches with paths', function() {
2529
equals(ast_for("{{foo/bar}}"), "{{ PATH:foo/bar [] }}\n");
2630
});

0 commit comments

Comments
 (0)