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

[BUGFIX] Cleanup morph of each else section #442

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions packages/htmlbars-compiler/tests/dirtying-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ function commonSetup() {
}
});

registerHelper('each', function(params) {
registerHelper('each', function(params, hash, blocks) {
var list = params[0];

if(list.length !== 0) {
for (var i=0, l=list.length; i<l; i++) {
var item = list[i];
if (this.arity > 0) {
Expand All @@ -47,6 +47,9 @@ function commonSetup() {
this.yieldItem(item.key, undefined, item);
}
}
} else if (blocks.inverse.yield) {
blocks.inverse.yield();
}
});

}
Expand Down Expand Up @@ -490,6 +493,27 @@ test("MorphLists in childNodes are properly cleared", function() {
strictEqual(destroyedRenderNodeCount, 6, "cleanup hook was invoked again");
});

test("MorphLists in each else are properly cleared", function() {
var template = compile(`{{#each items as |item|}}<div>{{item.name}}</div>{{else}}<div>{{noItems}}</div>{{/each}}`);

let a1 = { key: "a", name: "A1" };
let a2 = { key: "a", name: "A2" };
var object = {items: [], noItems: "items not found"};

var result = template.render(object , env);
equalTokens(result.fragment, `<div>items not found</div>`);

object.items.push(a1);
object.items.push(a2);
result.rerender(env, object);

equalTokens(result.fragment, "<div>A1</div><div>A2</div>");
strictEqual(destroyedRenderNodeCount, 1, "cleanup hook was invoked for else morph");

result.rerender(env, { items: [] });
strictEqual(destroyedRenderNodeCount, 5, "cleanup hook was invoked for each morph");
});

test("Pruned render nodes invoke a cleanup hook when cleared", function() {
var object = { condition: true, value: 'hello world' };
var template = compile('<div>{{#if condition}}<p>{{value}}</p>{{/if}}</div>');
Expand Down
6 changes: 6 additions & 0 deletions packages/htmlbars-runtime/lib/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createChildMorph } from "./render";
import { keyLength, shallowCopy } from "../htmlbars-util/object-utils";
import { validateChildMorphs } from "../htmlbars-util/morph-utils";
import { RenderState, clearMorph, clearMorphList, renderAndCleanup } from "../htmlbars-util/template-utils";
import { visitChildren } from "../htmlbars-util/morph-utils";
import { linkParams } from "../htmlbars-util/morph-utils";

/**
Expand Down Expand Up @@ -258,6 +259,11 @@ function yieldItem(template, env, parentScope, morph, renderState, visitor) {
handledMorphs[foundMorph.key] = foundMorph;
yieldTemplate(template, env, parentScope, foundMorph, renderState, visitor)(blockArguments, self);
} else {
if(morph.childNodes){
visitChildren(morph.childNodes, function (node) {
clearMorph(node, env, true);
});
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can someone explain the logic of this change? I don't see how clearing all the morphs when adding a new item is the right thing to do.

var childMorph = createChildMorph(env.dom, morph);
childMorph.key = key;
morphMap[key] = handledMorphs[key] = childMorph;
Expand Down