← Back to team overview

divmod-dev team mailing list archive

Re: [Bug 927179] Re: _athenaDetachClient detaches only every other client

 

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 divmod-dev@xxxxxxxxxx

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();
},

-- 
You received this bug notification because you are a member of Divmod-
dev, which is the registrant for nevow.
https://bugs.launchpad.net/bugs/927179

Title:
  _athenaDetachClient detaches only every other client

Status in Divmod Nevow:
  New

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

To manage notifications about this bug go to:
https://bugs.launchpad.net/nevow/+bug/927179/+subscriptions


References