Skip to content
This repository was archived by the owner on Apr 4, 2019. It is now read-only.

Commit b83e3ad

Browse files
committed
Fix issue with duplicate keys and last item.
We are using `renderState.handledMorphs` as a way to know if a given key is duplicated or not (if it is duplicated we use a binning strategy to prevent errors), but we were accidentally setting `handleMorphs[key]` to `null` when the given morph was the last item in the list. There is a slight disparity with how we use `handledMorphs` in `yieldItem` and the way it is used in `renderAndCleanup`. In `renderAndCleanup` we check via `if (key in handledMorphs) {}`, but in `yieldItem` we check `if (handledMorphs[key]) {}`. This difference combined with the other issue, meant that we were setting `handledMorphs[key] = null` which failed the duplicate check for subsequent renders. The fix is to update `handledMorphs` prior to changing `currentMorph`'s value.
1 parent 01da467 commit b83e3ad

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

packages/htmlbars-compiler/tests/diffing-test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,18 @@ test("Morph order is preserved when rerendering with duplicate keys", function()
8080
equalTokens(result.fragment, `<ul><li>B1</li><li>A2</li></ul>`);
8181
deepEqual(getNames(), ['B1', 'A1']);
8282
});
83+
84+
test("duplicate keys are allowed when duplicate is last morph", function() {
85+
var template = compile(`<ul>{{#each items as |item|}}<li>{{item.name}}</li>{{/each}}</ul>`);
86+
87+
let a1 = { key: "a", name: "A1" };
88+
let a2 = { key: "a", name: "A2" };
89+
90+
var result = template.render({ items: [ ] }, env);
91+
92+
result.rerender(env, { items: [ a1 ] });
93+
equalTokens(result.fragment, `<ul><li>A1</li></ul>`);
94+
95+
result.rerender(env, { items: [a1, a2] });
96+
equalTokens(result.fragment, `<ul><li>A1</li><li>A2</li></ul>`);
97+
});

packages/htmlbars-runtime/lib/hooks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,8 @@ function yieldItem(template, env, parentScope, morph, renderState, visitor) {
247247

248248
if (currentMorph && currentMorph.key === key) {
249249
yieldTemplate(template, env, parentScope, currentMorph, renderState, visitor)(blockArguments, self);
250-
currentMorph = currentMorph.nextMorph;
251250
handledMorphs[key] = currentMorph;
251+
currentMorph = currentMorph.nextMorph;
252252
} else if (morphMap[key] !== undefined) {
253253
let foundMorph = morphMap[key];
254254

0 commit comments

Comments
 (0)