Skip to content

Commit

Permalink
Merge pull request #45 from wthie/athenaDetachClient-fix-12
Browse files Browse the repository at this point in the history
Avoid missing children due to array modification during iteration while detaching widgets.

Author: wthie
Reviewer: mithrandi
  • Loading branch information
mithrandi committed Aug 12, 2014
2 parents b4a483d + e62cd13 commit 8dd62fa
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 8 deletions.
2 changes: 1 addition & 1 deletion nevow/athena.py
Original file line number Diff line number Diff line change
Expand Up @@ -1804,7 +1804,7 @@ def _athenaDetachServer(self):
"""
if self.fragmentParent is None:
raise OrphanedFragment(self)
for ch in self.liveFragmentChildren:
for ch in list(self.liveFragmentChildren):
ch._athenaDetachServer()
self.fragmentParent.liveFragmentChildren.remove(self)
self.fragmentParent = None
Expand Down
14 changes: 9 additions & 5 deletions nevow/js/Nevow/Athena/Tests/__init__.js
Original file line number Diff line number Diff line change
Expand Up @@ -755,27 +755,31 @@ Nevow.Athena.Tests.DynamicWidgetInstantiation.methods(

function _testDetachWithChildren(self, detach) {
var parent = null;
var child = null;
var result = self.callRemote('getAndSaveDynamicWidgetWithChild');
var child0 = null;
var child1 = null;
var result = self.callRemote('getAndSaveDynamicWidgetWithChildren');
result.addCallback(
function(widgetInfo) {
return self.addChildWidgetFromWidgetInfo(widgetInfo);
});
result.addCallback(
function(widget) {
parent = widget;
child = widget.childWidgets[0];
child0 = widget.childWidgets[0];
child1 = widget.childWidgets[1];
return widget.detach();
});
result.addCallback(
function(ignored) {
self.assertEqual(parent.childWidgets.length, 0);
self.assertEqual(parent.widgetParent, null);
self.assertEqual(child.widgetParent, null);
self.assertEqual(child0.widgetParent, null);
self.assertEqual(child1.widgetParent, null);

var widgets = Nevow.Athena.Widget._athenaWidgets;
self.failIf(parent.objectID in widgets);
self.failIf(child.objectID in widgets);
self.failIf(child0.objectID in widgets);
self.failIf(child1.objectID in widgets);
});
return result;
},
Expand Down
7 changes: 5 additions & 2 deletions nevow/js/Nevow/Athena/__init__.js
Original file line number Diff line number Diff line change
Expand Up @@ -1127,8 +1127,11 @@ Nevow.Athena.Widget.methods(
* tracking system.
*/
function _athenaDetachClient(self) {
for (var i = 0; i < self.childWidgets.length; ++i) {
self.childWidgets[i]._athenaDetachClient();
//copy of self.childWidgets for safe iteration by removeChildWidget
var childWidgets = self.childWidgets.slice();

for (var i = 0; i < childWidgets.length; ++i) {
childWidgets[i]._athenaDetachClient();
}
if (self.widgetParent !== null) {
self.widgetParent.removeChildWidget(self);
Expand Down

0 comments on commit 8dd62fa

Please sign in to comment.