Skip to content

Commit

Permalink
Fix for #1252: Using @partial-block twice in a template not possible
Browse files Browse the repository at this point in the history
Fixes #1252
- This fix treats partial-blocks more like closures and uses the closure-context of
  the "invokePartial"-function to store the @partial-block for the partial.
- Adds a tes for the fix
  • Loading branch information
nknapp committed Feb 14, 2017
1 parent 01b0f65 commit 5a164d0
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 10 deletions.
24 changes: 14 additions & 10 deletions lib/handlebars/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,7 @@ export function wrapProgram(container, i, fn, data, declaredBlockParams, blockPa
export function resolvePartial(partial, context, options) {
if (!partial) {
if (options.name === '@partial-block') {
let data = options.data;
while (data['partial-block'] === noop) {
data = data._parent;
}
partial = data['partial-block'];
data['partial-block'] = noop;
partial = options.data['partial-block'];
} else {
partial = options.partials[options.name];
}
Expand All @@ -228,6 +223,8 @@ export function resolvePartial(partial, context, options) {
}

export function invokePartial(partial, context, options) {
// Use the current closure context to save the partial-block if this partial
const currentPartialBlock = options.data && options.data['partial-block'];
options.partial = true;
if (options.ids) {
options.data.contextPath = options.ids[0] || options.data.contextPath;
Expand All @@ -236,10 +233,17 @@ export function invokePartial(partial, context, options) {
let partialBlock;
if (options.fn && options.fn !== noop) {
options.data = createFrame(options.data);
partialBlock = options.data['partial-block'] = options.fn;

if (partialBlock.partials) {
options.partials = Utils.extend({}, options.partials, partialBlock.partials);
// Wrapper function to get access to currentPartialBlock from the closure
let fn = options.fn;
partialBlock = options.data['partial-block'] = function partialBlockWrapper(context, options) {
// Restore the partial-block from the closure for the execution of the block
// i.e. the part inside the block of the partial call.
options.data = createFrame(options.data);
options.data['partial-block'] = currentPartialBlock;
return fn(context, options);
};
if (fn.partials) {
options.partials = Utils.extend({}, options.partials, fn.partials);
}
}

Expand Down
7 changes: 7 additions & 0 deletions spec/partials.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,13 @@ describe('partials', function() {
true,
'success');
});
it('should be able to render the partial-block twice', function() {
shouldCompileToWithPartials(
'{{#> dude}}success{{/dude}}',
[{}, {}, {dude: '{{> @partial-block }} {{> @partial-block }}'}],
true,
'success success');
});
it('should render block from partial with context', function() {
shouldCompileToWithPartials(
'{{#> dude}}{{value}}{{/dude}}',
Expand Down

0 comments on commit 5a164d0

Please sign in to comment.