diff --git a/packages/@glimmer/runtime/lib/syntax/functions.ts b/packages/@glimmer/runtime/lib/syntax/functions.ts index ad4368f76c..4d7fa36aac 100644 --- a/packages/@glimmer/runtime/lib/syntax/functions.ts +++ b/packages/@glimmer/runtime/lib/syntax/functions.ts @@ -5,6 +5,7 @@ import { } from '@glimmer/reference'; import { assert, + assign, Dict, dict, EMPTY_ARRAY, @@ -259,14 +260,18 @@ export class PartialInvoker implements DynamicInvoker { let partial = unwrap(_partial); let partialSymbols = partial.symbolTable.symbols; let outerScope = vm.scope(); + let outerEvalScope = outerScope.getEvalScope(); let partialScope = vm.pushRootScope(partialSymbols.length, false); partialScope.bindCallerScope(outerScope.getCallerScope()); - partialScope.bindEvalScope(outerScope.getEvalScope()); + partialScope.bindEvalScope(outerEvalScope); partialScope.bindSelf(outerScope.getSelf()); let { evalInfo, outerSymbols } = this; - let locals = dict>(); + let locals = outerScope.getPartialMap(); + if (locals === null) { + locals = dict>(); + } for (let i = 0; i < evalInfo.length; i++) { let slot = evalInfo[i]; @@ -275,12 +280,16 @@ export class PartialInvoker implements DynamicInvoker { locals[name] = ref; } - let evalScope = outerScope.getEvalScope()!; + if (outerEvalScope === null) { + outerEvalScope = {}; + } + + let mergedScope = assign(outerEvalScope, locals); for (let i = 0; i < partialSymbols.length; i++) { let name = partialSymbols[i]; let symbol = i + 1; - let value = evalScope[name]; + let value = mergedScope[name]; if (value !== undefined) partialScope.bind(symbol, value); } diff --git a/packages/@glimmer/runtime/test/partial-test.ts b/packages/@glimmer/runtime/test/partial-test.ts index 44a36270cb..b05ec3d6b9 100644 --- a/packages/@glimmer/runtime/test/partial-test.ts +++ b/packages/@glimmer/runtime/test/partial-test.ts @@ -324,6 +324,53 @@ QUnit.test('nested dynamic partial with dynamic content', () => { equalTokens(root, `Before
Testing wat are
Nested you doing?
After`); }); +QUnit.test('nested partials within nested `{{#with}}` blocks', () => { + let template = compile(`Hi {{person1}}. {{#with 'Sophie' as |person1|}}Hi {{person1}} (aged {{age}}), {{person2}}, {{person3}} and {{person4}}. {{partial 'person2-partial'}}{{/with}}`); + + env.registerPartial('person2-partial', `{{#with 'Ben' as |person2|}}Hi {{person1}} (aged {{age}}), {{person2}}, {{person3}} and {{person4}}. {{partial 'person3-partial'}}{{/with}}`); + env.registerPartial('person3-partial', `{{#with 'Alex' as |person3|}}Hi {{person1}} (aged {{age}}), {{person2}}, {{person3}} and {{person4}}. {{partial 'person4-partial'}}{{/with}}`); + env.registerPartial('person4-partial', `{{#with 'Sarah' as |person4|}}Hi {{person1}} (aged {{age}}), {{person2}}, {{person3}} and {{person4}}.{{/with}}`); + + render(template, { + person1: 'Context1', + person2: 'Context2', + person3: 'Context3', + person4: 'Context4', + age: 0 + }); + + equalTokens(root, `Hi Context1. Hi Sophie (aged 0), Context2, Context3 and Context4. Hi Sophie (aged 0), Ben, Context3 and Context4. Hi Sophie (aged 0), Ben, Alex and Context4. Hi Sophie (aged 0), Ben, Alex and Sarah.`); + + rerender({person1: 'Context1', + person2: 'Context2', + person3: 'Context3', + person4: 'Context4', + age: 0 + }, { assertStable: true }); + + equalTokens(root, `Hi Context1. Hi Sophie (aged 0), Context2, Context3 and Context4. Hi Sophie (aged 0), Ben, Context3 and Context4. Hi Sophie (aged 0), Ben, Alex and Context4. Hi Sophie (aged 0), Ben, Alex and Sarah.`); + + rerender({ + person1: 'UpdatedContext1', + person2: 'UpdatedContext2', + person3: 'UpdatedContext3', + person4: 'UpdatedContext4', + age: 1 + }); + + equalTokens(root, `Hi UpdatedContext1. Hi Sophie (aged 1), UpdatedContext2, UpdatedContext3 and UpdatedContext4. Hi Sophie (aged 1), Ben, UpdatedContext3 and UpdatedContext4. Hi Sophie (aged 1), Ben, Alex and UpdatedContext4. Hi Sophie (aged 1), Ben, Alex and Sarah.`); + + rerender({ + person1: 'Context1', + person2: 'Context2', + person3: 'Context3', + person4: 'Context4', + age: 0 + }); + + equalTokens(root, `Hi Context1. Hi Sophie (aged 0), Context2, Context3 and Context4. Hi Sophie (aged 0), Ben, Context3 and Context4. Hi Sophie (aged 0), Ben, Alex and Context4. Hi Sophie (aged 0), Ben, Alex and Sarah.`); +}); + QUnit.test('dynamic partial with falsy value does not render', () => { let template = compile(`Before {{partial name}} After`);