_athenaDetachClient detaches only every other client

Bug #927179 reported by Werner Thie
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
nevow
New
Undecided
Unassigned

Bug Description

The code in Athena/__init__.js at line 1130 detaches only every other client

for (var i = 0; i < self.childWidgets.length; ++i) {
    self.childWidgets[i]._athenaDetachClient();

Possible fix by creating a copy of the widgets list could be:

        var childWidgets = self.childWidgets.slice(); //copy self.childWidgets, it will be modified by removeChildWidget

        for (var i = 0; i < self.childWidgets.length; ++i) {
            childWidgets[i] = self.childWidgets[i];
        }
        for (var i = 0; i < childWidgets.length; ++i) {
            childWidgets[i]._athenaDetachClient();

This is a bug for which I submitted the above fix and necessary test when divmod.org was still active
How do I proceed?

Thxs, Werner

Revision history for this message
Jean-Paul Calderone (exarkun) wrote :

Do you happen to know the divmod.org bug number?

Revision history for this message
Werner Thie (werner-thieprojects) wrote : Re: [Bug 927179] Re: _athenaDetachClient detaches only every other client

Hello Jean-Paul

no, AFAIR I didn't open a ticket, it was at the very end of divmod and I
prepared everything to be ready, knowing that test code would be asked
for :-)

Werner

On 05.02.2012 18:16, Jean-Paul Calderone wrote:
> Do you happen to know the divmod.org bug number?
>

Revision history for this message
Werner Thie (werner-thieprojects) wrote :

On 05.02.2012 18:16, Jean-Paul Calderone wrote:
> Do you happen to know the divmod.org bug number?

Found the original mail, no ticket was filed.

Werner

---- original sent to <email address hidden>

Attaching/Detaching LiveElements is a lot of fun but while ensuring that
everything got detached I stumbled over the problem that out of 36
fragments only 18 (the even numbered ones) received a detach call. This
pattern smelled a lot like there is an iteration over a list happening
while somewhere in the code items are removed from the list. A quick
debugging session confirmed that this is in fact so. Consider the
original code on the server in nevow/athena for:

def _athenaDetachServer(self):
   """
   Locally remove this from its parent.

   @raise OrphanedFragment: if not attached to a parent.
   """
   if self.fragmentParent is None:
     raise OrphanedFragment(self)
   for ch in self.liveFragmentChildren:
     ch._athenaDetachServer()
   self.fragmentParent.liveFragmentChildren.remove(self)
   self.fragmentParent = None
   self.page = None
   self.detached()
expose(_athenaDetachServer)

which detaches every other liveFragmentChildren, whereas the code below
detaches all liveFragmentChildren, working with a copy of the list while
iterating:

def _athenaDetachServer(self):
   """
   Locally remove this from its parent.

   @raise OrphanedFragment: if not attached to a parent.
   """
   if self.fragmentParent is None:
     raise OrphanedFragment(self)
   #need a copy the children's list for undisturbed cleanup
   for ch in list(self.liveFragmentChildren):
     ch._athenaDetachServer()
   self.fragmentParent.liveFragmentChildren.remove(self)
   self.fragmentParent = None
   self.page = None
   self.detached()
expose(_athenaDetachServer)

The same holds true for the client code in nevow/js/__init__.js, where

function _athenaDetachClient(self) {
   for (var i = 0; i < self.childWidgets.length; ++i) {
     self.childWidgets[i]._athenaDetachClient();
   }
   if (self.widgetParent !== null) {
     self.widgetParent.removeChildWidget(self);
   }
   delete Nevow.Athena.Widget._athenaWidgets[self.objectID];
   self.detached();
},

becomes

function _athenaDetachClient(self) {
   var childWidgets = [];
   //need a copy the children's list for undisturbed cleanup
   for (var i = 0; i < self.childWidgets.length; ++i) {
     childWidgets[i] = self.childWidgets[i];
   }
   for (var i = 0; i < childWidgets.length; ++i) {
     childWidgets[i]._athenaDetachClient();
   }
   if (self.widgetParent !== null) {
     self.widgetParent.removeChildWidget(self);
   }
   delete Nevow.Athena.Widget._athenaWidgets[self.objectID];
         self.detached();
},

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.