if (current != null)
if (current.depth > 0)
  public final boolean dispatchEvent(Event event)    throws EventException  {    DomEvent e = (DomEvent) event;    DomNode[] ancestors = null;    int ancestorMax = 0;    boolean haveDispatchDataLock = false;        if (e.type == null)      {        throw new DomEventException();      }    e.doDefault = true;    e.target = this;        //    // Typical case:  one nonrecursive dispatchEvent call at a time    // for this class.  If that's our case, we can avoid allocating    // garbage, which is overall a big win.  Even with advanced GCs    // that deal well with short-lived garbage, and wayfast allocators,    // it still helps.    //    // Remember -- EVERY mutation goes though here at least once.    //    // When populating a DOM tree, trying to send mutation events is    // the primary cost; this dominates the critical path.    //    try      {        DomNode current;        int index;        boolean haveAncestorRegistrations = false;        ListenerRecord[] notificationSet;        int ancestorLen;                synchronized (lockNode)          {            if (!dispatchDataLock)              {                haveDispatchDataLock = dispatchDataLock = true;                notificationSet = DomNode.notificationSet;                ancestors = DomNode.ancestors;              }            else              {                notificationSet = new ListenerRecord[NOTIFICATIONS_INIT];                ancestors = new DomNode[ANCESTORS_INIT];              }            ancestorLen = ancestors.length;          }                // XXX autogrow ancestors ... based on statistics                // Climb to the top of this subtree and handle capture, letting        // each node (from the top down) capture until one stops it or        // until we get to this one.                for (index = 0, current = parent;             current != null && index < ancestorLen;             index++, current = current.parent)          {            if (current.nListeners != 0)              {                haveAncestorRegistrations = true;              }            ancestors [index] = current;          }        if (current != null)          {            throw new RuntimeException("dispatchEvent capture stack size");          }                ancestorMax = index;        e.stop = false;                if (haveAncestorRegistrations)          {            e.eventPhase = Event.CAPTURING_PHASE;            while (!e.stop && index-- > 0)              {                current = ancestors [index];                if (current.nListeners != 0)                  {                    notifyNode(e, current, true, notificationSet);                  }              }          }                // Always deliver events to the target node (this)        // unless stopPropagation was called.  If we saw        // no registrations yet (typical!), we never will.        if (!e.stop && nListeners != 0)          {            e.eventPhase = Event.AT_TARGET;            notifyNode (e, this, false, notificationSet);          }        else if (!haveAncestorRegistrations)          {            e.stop = true;          }                // If the event bubbles and propagation wasn't halted,        // walk back up the ancestor list.  Stop bubbling when        // any bubbled event handler stops it.                if (!e.stop && e.bubbles)          {            e.eventPhase = Event.BUBBLING_PHASE;            for (index = 0;                 !e.stop                 && index < ancestorMax                 && (current = ancestors[index]) != null;                 index++)              {                if (current.nListeners != 0)                  {                    notifyNode(e, current, false, notificationSet);                  }              }          }        e.eventPhase = 0;                // Caller chooses whether to perform the default        // action based on return from this method.        return e.doDefault;              }    finally      {        if (haveDispatchDataLock)          {            // synchronize to force write ordering            synchronized (lockNode)              {                // null out refs to ensure they'll be GC'd                for (int i = 0; i < ancestorMax; i++)                  {                    ancestors [i] = null;                  }                // notificationSet handled by notifyNode                                dispatchDataLock = false;              }          }      }  }