Skip to content

Commit

Permalink
Merge pull request #491 from wycats/data-depth
Browse files Browse the repository at this point in the history
For nested helpers: get the @ variables of the outer helper from the inner one
  • Loading branch information
kpdecker committed Feb 10, 2014
2 parents fcec69a + 16f1358 commit db651e7
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 24 deletions.
4 changes: 3 additions & 1 deletion lib/handlebars/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,5 +223,7 @@ export var logger = {
export function log(level, obj) { logger.log(level, obj); }

export var createFrame = function(object) {
return Utils.extend({}, object);
var frame = Utils.extend({}, object);
frame._parent = object;
return frame;
};
6 changes: 1 addition & 5 deletions lib/handlebars/compiler/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,11 +310,7 @@ Compiler.prototype = {

DATA: function(data) {
this.options.data = true;
if (data.id.isScoped || data.id.depth) {
throw new Exception('Scoped data references are not supported: ' + data.original, data);
}

this.opcode('lookupData');
this.opcode('lookupData', data.id.depth);
var parts = data.id.parts;
for(var i=0, l=parts.length; i<l; i++) {
this.opcode('lookup', parts[i]);
Expand Down
8 changes: 6 additions & 2 deletions lib/handlebars/compiler/javascript-compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,12 @@ JavaScriptCompiler.prototype = {
// On stack, after: data, ...
//
// Push the data lookup operator
lookupData: function() {
this.pushStackLiteral('data');
lookupData: function(depth) {
if (!depth) {
this.pushStackLiteral('data');
} else {
this.pushStackLiteral('this.data(data, ' + depth + ')');
}
},

// [pushStringParam]
Expand Down
6 changes: 6 additions & 0 deletions lib/handlebars/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ export function template(templateSpec, env) {
}
return data;
},
data: function(data, depth) {
while (data && depth--) {
data = data._parent;
}
return data;
},
merge: function(param, common) {
var ret = param || common;

Expand Down
35 changes: 19 additions & 16 deletions spec/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,6 @@ describe('data', function() {
equals("Hello undefined", result, "@foo as a parameter retrieves template data");
});

it("parameter data throws when using this scope references", function() {
var string = "{{#goodbyes}}{{text}} cruel {{@./name}}! {{/goodbyes}}";

shouldThrow(function() {
CompilerContext.compile(string);
}, Error);
});

it("parameter data throws when using parent scope references", function() {
var string = "{{#goodbyes}}{{text}} cruel {{@../name}}! {{/goodbyes}}";

shouldThrow(function() {
CompilerContext.compile(string);
}, Error);
});

it("parameter data throws when using complex scope references", function() {
var string = "{{#goodbyes}}{{text}} cruel {{@foo/../name}}! {{/goodbyes}}";

Expand Down Expand Up @@ -251,4 +235,23 @@ describe('data', function() {
equals('hello', result);
});
});

describe('nesting', function() {
it('the root context can be looked up via @root', function() {
var template = CompilerContext.compile('{{#helper}}{{#helper}}{{@./depth}} {{@../depth}} {{@../../depth}}{{/helper}}{{/helper}}');
var result = template({foo: 'hello'}, {
helpers: {
helper: function(options) {
var frame = Handlebars.createFrame(options.data);
frame.depth = options.data.depth + 1;
return options.fn(this, {data: frame});
}
},
data: {
depth: 0
}
});
equals('2 1 0', result);
});
});
});
4 changes: 4 additions & 0 deletions spec/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ describe('parser', function() {
equals(ast_for("{{@foo}}"), "{{ @ID:foo [] }}\n");
});

it('parses simple mustaches with data paths', function() {
equals(ast_for("{{@../foo}}"), "{{ @ID:foo [] }}\n");
});

it('parses mustaches with paths', function() {
equals(ast_for("{{foo/bar}}"), "{{ PATH:foo/bar [] }}\n");
});
Expand Down

0 comments on commit db651e7

Please sign in to comment.