[webkit-changes] cvs commit: WebCore/kwq KWQKHTMLPart.h KWQKHTMLPart.mm KWQObject.h KWQObject.mm KWQPageState.h KWQPageState.mm KWQTimer.h KWQTimer.mm WebCoreBridge.mm

Darin darin at opensource.apple.com
Sat Dec 10 09:14:42 PST 2005


darin       05/12/10 09:14:42

  Modified:    .        ChangeLog
               khtml/ecma kjs_window.cpp kjs_window.h
               kwq      KWQKHTMLPart.h KWQKHTMLPart.mm KWQObject.h
                        KWQObject.mm KWQPageState.h KWQPageState.mm
                        KWQTimer.h KWQTimer.mm WebCoreBridge.mm
  Log:
          Reviewed by Eric and Tim Omernick.
  
          - speed up timers by using CFTimerRunLoopRef instead of NSTimer
            http://bugzilla.opendarwin.org/show_bug.cgi?id=5677
  
          * kwq/KWQObject.h: Removed pauseTimer, resumeTimers, and _addTimer, added timerIntervals and
          restartTimer. Made KWQObjectSenderScope functions be inline.
          * kwq/KWQObject.mm:
          (timerFired): Added. Function called when the CFRunLoopTimerRef fires. Puts the timer into the
          deferred timer array if timers are deferred, otherwise makes a QTimerEvent and calls timerEvent
          on the target.
          (QObject::startTimer): Moved most of the code inside restartTimer. This now just picks a new
          timer ID and calls restartTimer.
          (QObject::restartTimer): Added. Creates a KWQObjectTimer and puts it in a timers dictionary.
          That includes creating a CFRunLoopTimer and scheduling it on the current run loop.
          (QObject::timerIntervals): Added. Looks up a timer and returns the intervals for next time to
          fire and the "fire again" interval.
          (deleteTimer): Added. Invalidates and then removes a timer.
          (QObject::killTimer): Changed to use deleteTimer to do most of its work.
          (deleteOneTimer): Added. Calls deleteTimer.
          (QObject::killTimers): Changed to use deleteOneTimer to do most of its work.
          (sendDeferredTimerEvent): Added. Creates a QTimerEvent and calls timerEvent on the target.
          (sendDeferredTimerEvents): Added. Calls sendDeferredTimerEvent in a loop on all the deferred timers.
          (QObject::setDefersTimers): Updated to call sendDeferredTimerEvents as needed.
  
          * kwq/KWQTimer.h:
          (QTimer::QTimer): Made constructor inline and removed the optional parameter.
          (QTimer::isActive): Made inline.
          (QTimer::fireDate): Added. Inline function.
          Got rid of the NSTimer and added a CFRunLoopTimer.
          * kwq/KWQTimer.mm:
          (timerFired): Added. Calls fire on the QTimer object.
          (QTimer::start): Changed to create a CFRunLoopTimer.
          (QTimer::stop): Changed to use CFRunLoopTimer functions.
          (QTimer::fire): Ditto.
  
          * khtml/ecma/kjs_window.h: Added PausedTimeouts class. Moved WindowQObject class up in the
          file so it can be used inline in the implementation of the Window class, and changed to
          use the PausedTimeouts class intead of a QMap to store the paused timeouts.
          * khtml/ecma/kjs_window.cpp:
          (KJS::ScheduledAction::execute): Put a check for nil part at the start; this replaces
          a check in the caller and a check partway down this function (after the part was
          already dereferenced). Fixed message handling so the message is not converted to ascii
          and back. Added an isObject() check so we won't crash if the passed function is a value
          that's not an object. Changed check for function vs. script to check for a function
          of nil instead of using a separate boolean.
          (KJS::WindowQObject::pauseTimeouts): Updated to create the new PausedTimeouts object,
          using the new QObject::timerIntervals function rather than the old QObject::pauseTimer
          function. This means that the paused timers are entirely stored in the PausedTimeouts
          object instead of being half in a QMap and the other half inside the QObject itself.
          (KJS::WindowQObject::resumeTimeouts): Ditto, using the new QObject::restartTimer function.
          (KJS::PausedTimeouts::~PausedTimeouts): Added. Deletes the stored timeouts, including
          the scheduled actions, unless the timeouts have already been resumed (in which case the
          m_array field will be 0).
  
          * kwq/KWQKHTMLPart.h: Renamed pause/resumeActions to pause/resumeTimeouts and made them
          use the PausedTimeouts class and no longer take a key parameter.
          * kwq/KWQKHTMLPart.mm:
          (KWQKHTMLPart::redirectionTimerStartedOrStopped): Use the new fireDate() function rathe than
          the old getNSTimer() function to get the fire date.
          (KWQKHTMLPart::pauseTimeouts): Remove the call to hasTimeouts and the key parameter.
          (KWQKHTMLPart::resumeTimeouts): Remove the key parameter.
          (KWQKHTMLPart::openURLFromPageCache): Change the timeout handling to use PausedTimeouts instead
          of a QMap for the paused timeouts.
  
          * kwq/KWQPageState.h: Changed to use PausedTimeouts instead of a QMap for timeouts.
          Added a pausedTimeouts parameter to the initializer and removed the setPausedActions: method.
          * kwq/KWQPageState.mm:
          (-[KWQPageState initWithDocument:URL:windowProperties:locationProperties:interpreterBuiltins:pausedTimeouts:]):
          Added code where it sets the pausedTimouts.
          (-[KWQPageState pausedTimeouts]): Added.
          (-[KWQPageState clear]): Added code to delete the pausedTimeouts and to deref mousePressNode.
          (-[KWQPageState invalidate]): Fixed bug where document would not be deref'd if the view was 0.
          (-[KWQPageState dealloc]): Removed code to deref mousePressNode since that's now handled in the clear method.
          (-[KWQPageState finalize]): Set document to 0 after deref for consistency.
  
          * kwq/WebCoreBridge.mm: (-[WebCoreBridge saveDocumentToPageCache]): Changed to pass in the
          paused timeouts using the new pauseTimeouts function.
  
  Revision  Changes    Path
  1.498     +81 -0     WebCore/ChangeLog
  
  Index: ChangeLog
  ===================================================================
  RCS file: /cvs/root/WebCore/ChangeLog,v
  retrieving revision 1.497
  retrieving revision 1.498
  diff -u -r1.497 -r1.498
  --- ChangeLog	10 Dec 2005 02:59:25 -0000	1.497
  +++ ChangeLog	10 Dec 2005 17:14:32 -0000	1.498
  @@ -1,3 +1,84 @@
  +2005-12-10  Darin Adler  <darin at apple.com>
  +
  +        Reviewed by Eric and Tim Omernick.
  +
  +        - speed up timers by using CFTimerRunLoopRef instead of NSTimer
  +          http://bugzilla.opendarwin.org/show_bug.cgi?id=5677
  +
  +        * kwq/KWQObject.h: Removed pauseTimer, resumeTimers, and _addTimer, added timerIntervals and
  +        restartTimer. Made KWQObjectSenderScope functions be inline.
  +        * kwq/KWQObject.mm:
  +        (timerFired): Added. Function called when the CFRunLoopTimerRef fires. Puts the timer into the
  +        deferred timer array if timers are deferred, otherwise makes a QTimerEvent and calls timerEvent
  +        on the target.
  +        (QObject::startTimer): Moved most of the code inside restartTimer. This now just picks a new
  +        timer ID and calls restartTimer.
  +        (QObject::restartTimer): Added. Creates a KWQObjectTimer and puts it in a timers dictionary.
  +        That includes creating a CFRunLoopTimer and scheduling it on the current run loop.
  +        (QObject::timerIntervals): Added. Looks up a timer and returns the intervals for next time to
  +        fire and the "fire again" interval.
  +        (deleteTimer): Added. Invalidates and then removes a timer.
  +        (QObject::killTimer): Changed to use deleteTimer to do most of its work.
  +        (deleteOneTimer): Added. Calls deleteTimer.
  +        (QObject::killTimers): Changed to use deleteOneTimer to do most of its work.
  +        (sendDeferredTimerEvent): Added. Creates a QTimerEvent and calls timerEvent on the target.
  +        (sendDeferredTimerEvents): Added. Calls sendDeferredTimerEvent in a loop on all the deferred timers.
  +        (QObject::setDefersTimers): Updated to call sendDeferredTimerEvents as needed.
  +
  +        * kwq/KWQTimer.h:
  +        (QTimer::QTimer): Made constructor inline and removed the optional parameter.
  +        (QTimer::isActive): Made inline.
  +        (QTimer::fireDate): Added. Inline function.
  +        Got rid of the NSTimer and added a CFRunLoopTimer.
  +        * kwq/KWQTimer.mm:
  +        (timerFired): Added. Calls fire on the QTimer object.
  +        (QTimer::start): Changed to create a CFRunLoopTimer.
  +        (QTimer::stop): Changed to use CFRunLoopTimer functions.
  +        (QTimer::fire): Ditto.
  +
  +        * khtml/ecma/kjs_window.h: Added PausedTimeouts class. Moved WindowQObject class up in the
  +        file so it can be used inline in the implementation of the Window class, and changed to
  +        use the PausedTimeouts class intead of a QMap to store the paused timeouts.
  +        * khtml/ecma/kjs_window.cpp:
  +        (KJS::ScheduledAction::execute): Put a check for nil part at the start; this replaces
  +        a check in the caller and a check partway down this function (after the part was
  +        already dereferenced). Fixed message handling so the message is not converted to ascii
  +        and back. Added an isObject() check so we won't crash if the passed function is a value
  +        that's not an object. Changed check for function vs. script to check for a function
  +        of nil instead of using a separate boolean.
  +        (KJS::WindowQObject::pauseTimeouts): Updated to create the new PausedTimeouts object,
  +        using the new QObject::timerIntervals function rather than the old QObject::pauseTimer
  +        function. This means that the paused timers are entirely stored in the PausedTimeouts
  +        object instead of being half in a QMap and the other half inside the QObject itself.
  +        (KJS::WindowQObject::resumeTimeouts): Ditto, using the new QObject::restartTimer function.
  +        (KJS::PausedTimeouts::~PausedTimeouts): Added. Deletes the stored timeouts, including
  +        the scheduled actions, unless the timeouts have already been resumed (in which case the
  +        m_array field will be 0).
  +
  +        * kwq/KWQKHTMLPart.h: Renamed pause/resumeActions to pause/resumeTimeouts and made them
  +        use the PausedTimeouts class and no longer take a key parameter.
  +        * kwq/KWQKHTMLPart.mm:
  +        (KWQKHTMLPart::redirectionTimerStartedOrStopped): Use the new fireDate() function rathe than
  +        the old getNSTimer() function to get the fire date.
  +        (KWQKHTMLPart::pauseTimeouts): Remove the call to hasTimeouts and the key parameter.
  +        (KWQKHTMLPart::resumeTimeouts): Remove the key parameter.
  +        (KWQKHTMLPart::openURLFromPageCache): Change the timeout handling to use PausedTimeouts instead
  +        of a QMap for the paused timeouts.
  +
  +        * kwq/KWQPageState.h: Changed to use PausedTimeouts instead of a QMap for timeouts.
  +        Added a pausedTimeouts parameter to the initializer and removed the setPausedActions: method.
  +        * kwq/KWQPageState.mm:
  +        (-[KWQPageState initWithDocument:URL:windowProperties:locationProperties:interpreterBuiltins:pausedTimeouts:]):
  +        Added code where it sets the pausedTimouts.
  +        (-[KWQPageState pausedTimeouts]): Added.
  +        (-[KWQPageState clear]): Added code to delete the pausedTimeouts and to deref mousePressNode.
  +        (-[KWQPageState invalidate]): Fixed bug where document would not be deref'd if the view was 0.
  +        (-[KWQPageState dealloc]): Removed code to deref mousePressNode since that's now handled in the clear method.
  +        (-[KWQPageState finalize]): Set document to 0 after deref for consistency.
  +
  +        * kwq/WebCoreBridge.mm: (-[WebCoreBridge saveDocumentToPageCache]): Changed to pass in the
  +        paused timeouts using the new pauseTimeouts function.
  +
   2005-12-09  Justin Garcia  <justin.garcia at apple.com>
   
           <rdar://problem/4370209> Reproducible crash when pasting over whitespace:pre text
  
  
  
  1.194     +109 -191  WebCore/khtml/ecma/kjs_window.cpp
  
  Index: kjs_window.cpp
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/ecma/kjs_window.cpp,v
  retrieving revision 1.193
  retrieving revision 1.194
  diff -u -r1.193 -r1.194
  --- kjs_window.cpp	4 Dec 2005 00:32:34 -0000	1.193
  +++ kjs_window.cpp	10 Dec 2005 17:14:36 -0000	1.194
  @@ -78,30 +78,25 @@
   // <cmath> and <math.h> the macros necessary for functions like
   // isnan are not defined.
   #include <cmath>
  +using std::isnan;
   
  -using namespace DOM::EventNames;
  +using namespace DOM;
  +using namespace EventNames;
   
  -using DOM::AtomicString;
  -using DOM::DocumentImpl;
  -using DOM::DOMString;
  -using DOM::ElementImpl;
  -using DOM::EventImpl;
  -using DOM::HTMLCollectionImpl;
  -using DOM::HTMLDocumentImpl;
  -using DOM::HTMLElementImpl;
  -using DOM::NodeImpl;
  -using DOM::Position;
  -
  -using khtml::TypingCommand;
  -
  -using KParts::ReadOnlyPart;
  -using KParts::URLArgs;
  -using KParts::WindowArgs;
  +using namespace khtml;
   
  -using std::isnan;
  +using namespace KParts;
   
   namespace KJS {
   
  +class PausedTimeout {
  +public:
  +    int timerId;
  +    int nextFireInterval;
  +    int repeatInterval;
  +    ScheduledAction *action;
  +};
  +
   ////////////////////// History Object ////////////////////////
   
     class History : public ObjectImp {
  @@ -1226,36 +1221,6 @@
     return !m_part.isNull();
   }
   
  -int Window::installTimeout(const UString &handler, int t, bool singleShot)
  -{
  -  return winq->installTimeout(handler, t, singleShot);
  -}
  -
  -int Window::installTimeout(ValueImp *function, List &args, int t, bool singleShot)
  -{
  -  return winq->installTimeout(function, args, t, singleShot);
  -}
  -
  -void Window::clearTimeout(int timerId)
  -{
  -  winq->clearTimeout(timerId);
  -}
  -
  -bool Window::hasTimeouts()
  -{
  -    return winq->hasTimeouts();
  -}
  -
  -QMap<int, ScheduledAction*> *Window::pauseTimeouts(const void *key)
  -{
  -    return winq->pauseTimeouts(key);
  -}
  -
  -void Window::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
  -{
  -    return winq->resumeTimeouts(sa, key);
  -}
  -
   void Window::scheduleClose()
   {
     kdDebug(6070) << "Window::scheduleClose window.close() " << m_part << endl;
  @@ -1906,199 +1871,142 @@
       docimpl->updateLayoutIgnorePendingStylesheets();
   }
   
  -
   ////////////////////// ScheduledAction ////////////////////////
   
  -ScheduledAction::ScheduledAction(ObjectImp *_func, List _args, bool _singleShot)
  +void ScheduledAction::execute(Window *window)
   {
  -  //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
  -  func = _func;
  -  args = _args;
  -  isFunction = true;
  -  singleShot = _singleShot;
  -}
  -
  -ScheduledAction::ScheduledAction(const QString &_code, bool _singleShot)
  -{
  -  //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
  -  //func = 0;
  -  //args = 0;
  -  code = _code;
  -  isFunction = false;
  -  singleShot = _singleShot;
  -}
  +    if (!window->m_part)
  +        return;
   
  +    ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
   
  -void ScheduledAction::execute(Window *window)
  -{
  -  ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
  +    interpreter->setProcessingTimerCallback(true);
     
  -  interpreter->setProcessingTimerCallback(true);
  -  
  -  //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
  -  if (isFunction) {
  -    if (func->implementsCall()) {
  -      // #### check this
  -      Q_ASSERT(window->m_part);
  -      if (window->m_part) {
  -        Interpreter *interpreter = KJSProxy::proxy(window->m_part)->interpreter();
  -        ExecState *exec = interpreter->globalExec();
  -        Q_ASSERT(window == interpreter->globalObject());
  -        ObjectImp *obj(window);
  -	JSLock lock;
  -        func->call(exec, obj, args); // note that call() creates its own execution state for the func call
  -	if (exec->hadException()) {
  -          char *message = exec->exception()->toObject(exec)->get(exec, messagePropertyName)->toString(exec).ascii();
  -          int lineNumber = exec->exception()->toObject(exec)->get(exec, "line")->toInt32(exec);
  -	  if (Interpreter::shouldPrintExceptions()) {
  -	    printf("(timer):%s\n", message);
  -            
  -            KWQ(window->m_part)->addMessageToConsole(message, lineNumber, QString());
  -          }
  -	  exec->clearException();
  +    if (ValueImp* func = m_func.get()) {
  +        if (func->isObject() && static_cast<ObjectImp *>(func)->implementsCall()) {
  +            ExecState *exec = interpreter->globalExec();
  +            assert(window == interpreter->globalObject());
  +            JSLock lock;
  +            static_cast<ObjectImp *>(func)->call(exec, window, m_args);
  +            if (exec->hadException()) {
  +                ObjectImp* exception = exec->exception()->toObject(exec);
  +                exec->clearException();
  +                QString message = exception->get(exec, messagePropertyName)->toString(exec).qstring();
  +                int lineNumber = exception->get(exec, "line")->toInt32(exec);
  +                if (Interpreter::shouldPrintExceptions())
  +                    printf("(timer):%s\n", message.local8Bit().data());
  +                KWQ(window->m_part)->addMessageToConsole(message, lineNumber, QString());
  +            }
           }
  -      }
  -    }
  -  } else
  -    window->m_part->executeScript(code);
  +    } else
  +        window->m_part->executeScript(m_code);
     
  -  // Update our document's rendering following the execution of the timeout callback.
  -  if (DocumentImpl *doc = window->m_part->xmlDocImpl())
  -    doc->updateRendering();
  +    // Update our document's rendering following the execution of the timeout callback.
  +    // FIXME: Why? Why not other documents, for example?
  +    DocumentImpl *doc = window->m_part->xmlDocImpl();
  +    if (doc)
  +        doc->updateRendering();
     
  -  interpreter->setProcessingTimerCallback(false);
  +    interpreter->setProcessingTimerCallback(false);
   }
   
   ////////////////////// WindowQObject ////////////////////////
   
   WindowQObject::WindowQObject(Window *w)
  -  : parent(w)
  -{
  -  //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
  -  part = parent->m_part;
  -  connect( parent->m_part, SIGNAL( destroyed() ),
  -           this, SLOT( parentDestroyed() ) );
  -}
  -
  -WindowQObject::~WindowQObject()
  +    : m_parent(w)
   {
  -  //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
  -  parentDestroyed(); // reuse same code
  +    connect(w->m_part, SIGNAL(destroyed()), this, SLOT(parentDestroyed()));
   }
   
   void WindowQObject::parentDestroyed()
   {
  -  //kdDebug(6070) << "WindowQObject::parentDestroyed " << this << " we have " << scheduledActions.count() << " actions in the map" << endl;
  -  killTimers();
  -  QMapIterator<int,ScheduledAction*> it;
  -  for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
  -    ScheduledAction *action = *it;
  -    //kdDebug(6070) << "WindowQObject::parentDestroyed deleting action " << action << endl;
  -    delete action;
  -  }
  -  scheduledActions.clear();
  +    killTimers();
  +    for (QMapIterator<int, ScheduledAction *> it = m_timeouts.begin(); it != m_timeouts.end(); ++it)
  +        delete *it;
  +    m_timeouts.clear();
   }
   
  -int WindowQObject::installTimeout(const UString &handler, int t, bool singleShot)
  +int WindowQObject::installTimeout(const UString& handler, int t, bool singleShot)
   {
  -  //kdDebug(6070) << "WindowQObject::installTimeout " << this << " " << handler.ascii() << endl;
  -  int id = startTimer(t);
  -  ScheduledAction *action = new ScheduledAction(handler.qstring(),singleShot);
  -  scheduledActions.insert(id, action);
  -  //kdDebug(6070) << this << " got id=" << id << " action=" << action << " - now having " << scheduledActions.count() << " actions"<<endl;
  -  return id;
  +    int id = startTimer(t);
  +    ScheduledAction *action = new ScheduledAction(handler.qstring(), singleShot);
  +    m_timeouts.insert(id, action);
  +    return id;
   }
   
  -int WindowQObject::installTimeout(ValueImp *func, List args, int t, bool singleShot)
  +int WindowQObject::installTimeout(ValueImp *func, const List& args, int t, bool singleShot)
   {
  -  ObjectImp *objFunc = static_cast<ObjectImp *>(func);
  -  int id = startTimer(t);
  -  scheduledActions.insert(id, new ScheduledAction(objFunc,args,singleShot));
  -  return id;
  +    int id = startTimer(t);
  +    m_timeouts.insert(id, new ScheduledAction(func, args, singleShot));
  +    return id;
   }
   
  -QMap<int, ScheduledAction*> *WindowQObject::pauseTimeouts(const void *key)
  +PausedTimeouts *WindowQObject::pauseTimeouts()
   {
  -    QMapIterator<int,ScheduledAction*> it;
  -
  -    QMap<int, ScheduledAction*>*pausedActions = new QMap<int, ScheduledAction*>;
  -    for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
  +    size_t count = m_timeouts.count();
  +    if (count == 0)
  +        return 0;
  +    PausedTimeout *t = new PausedTimeout [count];
  +    PausedTimeouts *result = new PausedTimeouts(t, count);
  +    for (QMapIterator<int, ScheduledAction *> it = m_timeouts.begin(); it != m_timeouts.end(); ++it) {
           int timerId = it.key();
  -        pauseTimer (timerId, key);
  -        pausedActions->insert(timerId, it.data());
  +        timerIntervals(timerId, t->nextFireInterval, t->repeatInterval);
  +        t->timerId = timerId;
  +        t->action = it.data();
  +        ++t;
  +        killTimer(timerId);
       }
  -    scheduledActions.clear();
  -    return pausedActions;
  +    m_timeouts.clear();
  +    return result;
   }
   
  -void WindowQObject::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
  +void WindowQObject::resumeTimeouts(PausedTimeouts *timeouts)
   {
  -    QMapIterator<int,ScheduledAction*> it;
  -    for (it = sa->begin(); it != sa->end(); ++it) {
  -        int timerId = it.key();
  -        scheduledActions.insert(timerId, it.data());
  +    if (!timeouts)
  +        return;
  +    size_t count = timeouts->numTimeouts();
  +    PausedTimeout *array = timeouts->takeTimeouts();
  +    for (size_t i = 0; i != count; ++i) {
  +        int timerId = array[i].timerId;
  +        m_timeouts.insert(timerId, array[i].action);
  +        restartTimer(timerId, array[i].nextFireInterval, array[i].repeatInterval);
       }
  -    sa->clear();
  -    resumeTimers (key, this);
  +    delete [] array;
   }
   
   void WindowQObject::clearTimeout(int timerId, bool delAction)
   {
  -  //kdDebug(6070) << "WindowQObject::clearTimeout " << this << " timerId=" << timerId << " delAction=" << delAction << endl;
  -  killTimer(timerId);
  -  if (delAction) {
  -    QMapIterator<int,ScheduledAction*> it = scheduledActions.find(timerId);
  -    if (it != scheduledActions.end()) {
  -      ScheduledAction *action = *it;
  -      scheduledActions.remove(it);
  -      delete action;
  +    killTimer(timerId);
  +    if (delAction) {
  +        QMapIterator<int, ScheduledAction *> it = m_timeouts.find(timerId);
  +        if (it != m_timeouts.end()) {
  +            delete *it;
  +            m_timeouts.remove(it);
  +        }
       }
  -  }
   }
   
   void WindowQObject::timerEvent(QTimerEvent *e)
   {
  -  QMapIterator<int,ScheduledAction*> it = scheduledActions.find(e->timerId());
  -  if (it != scheduledActions.end()) {
  +    QMapIterator<int, ScheduledAction *> it = m_timeouts.find(e->timerId());
       ScheduledAction *action = *it;
  -    bool singleShot = action->singleShot;
  -    //kdDebug(6070) << "WindowQObject::timerEvent " << this << " action=" << action << " singleShot:" << singleShot << endl;
  +    bool singleShot = action->singleShot();
   
  -    // remove single shots installed by setTimeout()
  -    if (singleShot)
  -    {
  -      clearTimeout(e->timerId(),false);
  -      scheduledActions.remove(it);
  +    // remove single shots before executing
  +    if (singleShot) {
  +        clearTimeout(e->timerId(), false);
  +        m_timeouts.remove(it);
       }
  -        
  -    if (!parent->part().isNull())
  -      action->execute(parent);
   
  -    // It is important to test singleShot and not action->singleShot here - the
  -    // action could have been deleted already if not single shot and if the
  +    action->execute(m_parent);
  +
  +    // It is important not to use action->singleShot here.
  +    // The action could have been deleted already if not single shot the
       // JS code called by execute() calls clearTimeout().
       if (singleShot)
  -      delete action;
  -  } else
  -    kdWarning(6070) << "WindowQObject::timerEvent this=" << this << " timer " << e->timerId()
  -                    << " not found (" << scheduledActions.count() << " actions in map)" << endl;
  -}
  -
  -void WindowQObject::timeoutClose()
  -{
  -  if (!parent->part().isNull())
  -  {
  -    //kdDebug(6070) << "WindowQObject::timeoutClose -> closing window" << endl;
  -    delete parent->m_part;
  -  }
  -}
  -
  -bool WindowQObject::hasTimeouts()
  -{
  -    return scheduledActions.count();
  +        delete action;
   }
   
  -
   const ClassInfo FrameArray::info = { "FrameArray", 0, &FrameArrayTable, 0 };
   
   /*
  @@ -2108,7 +2016,6 @@
   @end
   */
   
  -
   ValueImp *FrameArray::getValueProperty(ExecState *exec, int token)
   {
     switch (token) {
  @@ -2675,6 +2582,17 @@
   
   /////////////////////////////////////////////////////////////////////////////
   
  +PausedTimeouts::~PausedTimeouts()
  +{
  +    PausedTimeout *array = m_array;
  +    if (!array)
  +        return;
  +    size_t count = m_length;
  +    for (size_t i = 0; i != count; ++i)
  +        delete array[i].action;
  +    delete [] array;
  +}
  +
   } // namespace KJS
   
   #include "kjs_window.moc"
  
  
  
  1.59      +73 -54    WebCore/khtml/ecma/kjs_window.h
  
  Index: kjs_window.h
  ===================================================================
  RCS file: /cvs/root/WebCore/khtml/ecma/kjs_window.h,v
  retrieving revision 1.58
  retrieving revision 1.59
  diff -u -r1.58 -r1.59
  --- kjs_window.h	21 Nov 2005 01:19:57 -0000	1.58
  +++ kjs_window.h	10 Dec 2005 17:14:36 -0000	1.59
  @@ -40,17 +40,57 @@
   
   namespace KJS {
   
  -  class WindowFunc;
  -  class WindowQObject;
  -  class Location;
  -  class Selection;
  -  class BarInfo;
  -  class History;
  -  class FrameArray;
  -  class JSEventListener;
  -  class JSUnprotectedEventListener;
  -  class JSLazyEventListener;
  -  class ScheduledAction;
  +    class BarInfo;
  +    class FrameArray;
  +    class History;
  +    class JSEventListener;
  +    class JSLazyEventListener;
  +    class JSUnprotectedEventListener;
  +    class Location;
  +    class PausedTimeout;
  +    class ScheduledAction;
  +    class Selection;
  +    class Window;
  +    class WindowFunc;
  +
  +    class PausedTimeouts {
  +    public:
  +        PausedTimeouts(PausedTimeout *a, size_t length) : m_array(a), m_length(length) { }
  +        ~PausedTimeouts();
  +
  +        size_t numTimeouts() const { return m_length; }
  +        PausedTimeout *takeTimeouts()
  +            { PausedTimeout *a = m_array; m_array = 0; return a; }
  +
  +    private:
  +        PausedTimeout *m_array;
  +        size_t m_length;
  +
  +        PausedTimeouts(const PausedTimeouts&);
  +        PausedTimeouts& operator=(const PausedTimeouts&);
  +    };
  +
  +    class WindowQObject : public QObject {
  +        Q_OBJECT
  +    public:
  +        WindowQObject(Window *);
  +        ~WindowQObject() { parentDestroyed(); }
  +
  +        int installTimeout(const UString &handler, int interval, bool singleShot);
  +        int installTimeout(ValueImp *function, const List &, int interval, bool singleShot);
  +        void clearTimeout(int timerId, bool delAction = true);
  +
  +        PausedTimeouts *pauseTimeouts();
  +        void resumeTimeouts(PausedTimeouts *);
  +
  +    private slots:
  +        void parentDestroyed();
  +    private:
  +        virtual void timerEvent(QTimerEvent *);
  +
  +        Window *m_parent;
  +        QMap<int, ScheduledAction *> m_timeouts;
  +  };
   
     class Screen : public ObjectImp {
     public:
  @@ -98,19 +138,19 @@
       ValueImp *getValueProperty(ExecState *exec, int token) const;
       virtual void put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr = None);
       virtual bool toBoolean(ExecState *exec) const;
  -    int installTimeout(const UString &handler, int t, bool singleShot);
  -    int installTimeout(ValueImp *function, List &args, int t, bool singleShot);
  -    void clearTimeout(int timerId);
  -    bool hasTimeouts();
  -    QMap<int, ScheduledAction*> *pauseTimeouts(const void *key);
  -    void resumeTimeouts(QMap<int, ScheduledAction*>*sa, const void *key);
  +
  +    int installTimeout(const UString& handler, int t, bool singleShot) { return winq->installTimeout(handler, t, singleShot); }
  +    int installTimeout(ValueImp* function, List& args, int t, bool singleShot) { return winq->installTimeout(function, args, t, singleShot); }
  +    void clearTimeout(int timerId) { winq->clearTimeout(timerId); }
  +    PausedTimeouts* pauseTimeouts() { return winq->pauseTimeouts(); }
  +    void resumeTimeouts(PausedTimeouts* t) { winq->resumeTimeouts(t); }
       
       KJS::Interpreter *interpreter() const;
   
  -    static bool isSafeScript (const KJS::ScriptInterpreter *origin, const KJS::ScriptInterpreter *target);
       void scheduleClose();
           
       bool isSafeScript(ExecState *exec) const;
  +    static bool isSafeScript(const ScriptInterpreter *origin, const ScriptInterpreter *target);
       Location *location() const;
       Selection *selection() const;
       BarInfo *locationbar(ExecState *exec) const;
  @@ -184,42 +224,21 @@
      * time interval, either once or repeatedly. Used for window.setTimeout()
      * and window.setInterval()
      */
  -  class ScheduledAction {
  -  public:
  -    ScheduledAction(ObjectImp *_func, List _args, bool _singleShot);
  -    ScheduledAction(const QString &_code, bool _singleShot);
  -    void execute(Window *window);
  -
  -    ProtectedPtr<ObjectImp> func;
  -    List args;
  -    QString code;
  -    bool isFunction;
  -    bool singleShot;
  -  };
  -
  -  class WindowQObject : public QObject {
  -    Q_OBJECT
  -  public:
  -    WindowQObject(Window *w);
  -    ~WindowQObject();
  -    int installTimeout(const UString &handler, int t, bool singleShot);
  -    int installTimeout(ValueImp *func, List args, int t, bool singleShot);
  -    void clearTimeout(int timerId, bool delAction = true);
  -    bool hasTimeouts();
  -    QMap<int, ScheduledAction*> *WindowQObject::pauseTimeouts(const void *key);
  -    void WindowQObject::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key);
  -
  -  public slots:
  -    void timeoutClose();
  -  protected slots:
  -    void parentDestroyed();
  -  protected:
  -    void timerEvent(QTimerEvent *e);
  -  private:
  -    Window *parent;
  -    KHTMLPart *part;   		// not guarded, may be dangling
  -    QMap<int, ScheduledAction*> scheduledActions;
  -  };
  +    class ScheduledAction {
  +    public:
  +        ScheduledAction(ValueImp *func, const List& args, bool singleShot)
  +            : m_func(func), m_args(args), m_singleShot(singleShot) { }
  +        ScheduledAction(const QString& code, bool singleShot)
  +            : m_code(code), m_singleShot(singleShot) { }
  +        void execute(Window *);
  +        bool singleShot() const { return m_singleShot; }
  +
  +    private:
  +        ProtectedPtr<ValueImp> m_func;
  +        List m_args;
  +        QString m_code;
  +        bool m_singleShot;
  +    };
   
     class Location : public ObjectImp {
     public:
  
  
  
  1.237     +3 -2      WebCore/kwq/KWQKHTMLPart.h
  
  Index: KWQKHTMLPart.h
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQKHTMLPart.h,v
  retrieving revision 1.236
  retrieving revision 1.237
  diff -u -r1.236 -r1.237
  --- KWQKHTMLPart.h	6 Dec 2005 00:23:45 -0000	1.236
  +++ KWQKHTMLPart.h	10 Dec 2005 17:14:37 -0000	1.237
  @@ -61,6 +61,7 @@
   }
   
   namespace KJS {
  +    class PausedTimeouts;
       class SavedProperties;
       class SavedBuiltins;
       class ScheduledAction;
  @@ -159,8 +160,8 @@
   
       void unfocusWindow();
   
  -    QMap<int, KJS::ScheduledAction*> *pauseActions(const void *key);
  -    void resumeActions(QMap<int, KJS::ScheduledAction*> *actions, const void *key);
  +    KJS::PausedTimeouts *pauseTimeouts();
  +    void resumeTimeouts(KJS::PausedTimeouts *);
       
       bool canCachePage();
       void saveWindowProperties(KJS::SavedProperties *windowProperties);
  
  
  
  1.700     +27 -81    WebCore/kwq/KWQKHTMLPart.mm
  
  Index: KWQKHTMLPart.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQKHTMLPart.mm,v
  retrieving revision 1.699
  retrieving revision 1.700
  diff -u -r1.699 -r1.700
  --- KWQKHTMLPart.mm	9 Dec 2005 02:10:02 -0000	1.699
  +++ KWQKHTMLPart.mm	10 Dec 2005 17:14:37 -0000	1.700
  @@ -92,63 +92,14 @@
   using namespace EventNames;
   using namespace HTMLNames;
   
  -using khtml::Cache;
  -using khtml::CharacterIterator;
  -using khtml::ChildFrame;
  -using khtml::Decoder;
  -using khtml::DashboardRegionValue;
  -using khtml::EditCommandPtr;
  -using khtml::endOfWord;
  -using khtml::findPlainText;
  -using khtml::FocusState;
  -using khtml::InlineTextBox;
  -using khtml::LeftWordIfOnBoundary;
  -using khtml::MouseDoubleClickEvent;
  -using khtml::MouseMoveEvent;
  -using khtml::MousePressEvent;
  -using khtml::MouseReleaseEvent;
  -using khtml::parseURL;
  -using khtml::PRE;
  -using khtml::RenderCanvas;
  -using khtml::RenderImage;
  -using khtml::RenderLayer;
  -using khtml::RenderListItem;
  -using khtml::RenderObject;
  -using khtml::RenderStyle;
  -using khtml::RenderTableCell;
  -using khtml::RenderText;
  -using khtml::theme;
  -using khtml::RenderWidget;
  -using khtml::RightWordIfOnBoundary;
  -using khtml::SelectionController;
  -using khtml::SELECT_IGNORE;
  -using khtml::setEnd;
  -using khtml::setStart;
  -using khtml::ShadowData;
  -using khtml::startOfWord;
  -using khtml::startVisiblePosition;
  -using khtml::StyleDashboardRegion;
  -using khtml::TextIterator;
  -using khtml::DOWNSTREAM;
  -using khtml::VP_UPSTREAM_IF_POSSIBLE;
  -using khtml::VISIBLE;
  -using khtml::VisiblePosition;
  -using khtml::WordAwareIterator;
  -
  -using KIO::Job;
  -
  -using KJS::Interpreter;
  -using KJS::JSLock;
  -using KJS::Location;
  -using KJS::SavedBuiltins;
  -using KJS::SavedProperties;
  -using KJS::ScheduledAction;
  -using KJS::Window;
  +using namespace KJS;
  +using namespace Bindings;
   
  -using KJS::Bindings::Instance;
  +using namespace khtml;
   
  -using KParts::ReadOnlyPart;
  -using KParts::URLArgs;
  +using namespace KIO;
  +
  +using namespace KParts;
   
   NSEvent *KWQKHTMLPart::_currentEvent = nil;
   
  @@ -1127,11 +1078,13 @@
       
       KWQ_BLOCK_EXCEPTIONS;
       if (d->m_redirectionTimer.isActive()) {
  +        NSDate *fireDate = [[NSDate alloc] initWithTimeIntervalSinceReferenceDate:d->m_redirectionTimer.fireDate()];
           [_bridge reportClientRedirectToURL:KURL(d->m_redirectURL).getNSURL()
                                        delay:d->m_delayRedirect
  -                                  fireDate:[d->m_redirectionTimer.getNSTimer() fireDate]
  +                                  fireDate:fireDate
                                  lockHistory:d->m_redirectLockHistory
                                  isJavaScriptFormAction:d->m_executingJavaScriptFormAction];
  +        [fireDate release];
       } else {
           [_bridge reportClientRedirectCancelled:d->m_cancelWithLoadInProgress];
       }
  @@ -1462,24 +1415,22 @@
       [_bridge windowObjectCleared];
   }
   
  -QMap<int, ScheduledAction*> *KWQKHTMLPart::pauseActions(const void *key)
  +PausedTimeouts *KWQKHTMLPart::pauseTimeouts()
   {
       if (d->m_doc && d->m_jscript) {
           Window *w = Window::retrieveWindow(this);
  -        if (w && w->hasTimeouts()) {
  -            return w->pauseTimeouts(key);
  -        }
  +        if (w)
  +            return w->pauseTimeouts();
       }
       return 0;
   }
   
  -void KWQKHTMLPart::resumeActions(QMap<int, ScheduledAction*> *actions, const void *key)
  +void KWQKHTMLPart::resumeTimeouts(PausedTimeouts *t)
   {
       if (d->m_doc && d->m_jscript && d->m_bJScriptEnabled) {
           Window *w = Window::retrieveWindow(this);
  -        if (w) {
  -            w->resumeTimeouts(actions, key);
  -        }
  +        if (w)
  +            w->resumeTimeouts(t);
       }
   }
   
  @@ -1562,14 +1513,13 @@
       SavedProperties *windowProperties = [state windowProperties];
       SavedProperties *locationProperties = [state locationProperties];
       SavedBuiltins *interpreterBuiltins = [state interpreterBuiltins];
  -    QMap<int, ScheduledAction*> *actions = [state pausedActions];
  +    PausedTimeouts *timeouts = [state pausedTimeouts];
       
       cancelRedirection();
   
       // We still have to close the previous part page.
  -    if (!d->m_restored){
  +    if (!d->m_restored)
           closeURL();
  -    }
               
       d->m_bComplete = false;
       
  @@ -1577,13 +1527,12 @@
       d->m_bLoadEventEmitted = true;
       
       // delete old status bar msg's from kjs (if it _was_ activated on last URL)
  -    if( d->m_bJScriptEnabled )
  -    {
  +    if (d->m_bJScriptEnabled) {
           d->m_kjsStatusBarText = QString::null;
           d->m_kjsDefaultStatusBarText = QString::null;
       }
   
  -    ASSERT (url);
  +    ASSERT(url);
       
       m_url = *url;
       
  @@ -1617,27 +1566,24 @@
       d->m_mousePressNode = mousePressNode;
       
       Decoder *decoder = doc->decoder();
  -    if (decoder) {
  +    if (decoder)
           decoder->ref();
  -    }
  -    if (d->m_decoder) {
  +    if (d->m_decoder)
           d->m_decoder->deref();
  -    }
       d->m_decoder = decoder;
   
  -    doc->setParseMode ([state parseMode]);
  +    doc->setParseMode([state parseMode]);
       
       updatePolicyBaseURL();
   
       { // scope the lock
           JSLock lock;
  -        restoreWindowProperties (windowProperties);
  -        restoreLocationProperties (locationProperties);
  -        restoreInterpreterBuiltins (*interpreterBuiltins);
  +        restoreWindowProperties(windowProperties);
  +        restoreLocationProperties(locationProperties);
  +        restoreInterpreterBuiltins(*interpreterBuiltins);
       }
   
  -    if (actions)
  -        resumeActions (actions, state);
  +    resumeTimeouts(timeouts);
       
       checkCompleted();
   }
  @@ -4249,7 +4195,7 @@
       int exception = 0;
   
       ASSERT(!range || range->startContainer(exception) == range->endContainer(exception));
  -    ASSERT(!range || range->collapsed(exception) || range->startContainer(exception)->nodeType() == Node::TEXT_NODE);
  +    ASSERT(!range || range->collapsed(exception) || range->startContainer(exception)->nodeType() == DOM::Node::TEXT_NODE);
   
       if (attributes == nil) {
           m_markedTextUsesUnderlines = false;
  
  
  
  1.39      +20 -33    WebCore/kwq/KWQObject.h
  
  Index: KWQObject.h
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQObject.h,v
  retrieving revision 1.38
  retrieving revision 1.39
  diff -u -r1.38 -r1.39
  --- KWQObject.h	9 Nov 2005 02:46:29 -0000	1.38
  +++ KWQObject.h	10 Dec 2005 17:14:38 -0000	1.39
  @@ -26,14 +26,10 @@
   #ifndef QOBJECT_H_
   #define QOBJECT_H_
   
  -#include "KWQDef.h"
  -#include "KWQSignal.h"
  -
  -#include "KWQNamespace.h"
  -#include "KWQString.h"
   #include "KWQEvent.h"
  -#include "KWQStringList.h"
   #include "KWQPtrList.h"
  +#include "KWQSignal.h"
  +#include "KWQStringList.h"
   
   #define slots : public
   #define SLOT(x) "SLOT:" #x
  @@ -43,36 +39,30 @@
   #define Q_OBJECT
   #define Q_PROPERTY(text)
   
  +class QBitmap;
  +class QBrush;
  +class QColor;
  +class QColorGroup;
   class QEvent;
  +class QFont;
  +class QFontMetrics;
  +class QImage;
  +class QMovie;
   class QPaintDevice;
   class QPaintDeviceMetrics;
  -class QWidget;
  -class QColor;
  -class QColorGroup;
  -class QPalette;
   class QPainter;
  +class QPalette;
  +class QRect;
   class QRegion;
   class QSize;
   class QSizePolicy;
  -class QRect;
  -class QFont;
  -class QFontMetrics;
  -class QBrush;
  -class QBitmap;
  -class QMovie;
   class QTimer;
  -class QImage;
   class QVariant;
  +class QWidget;
   
   class KWQGuardedPtrBase;
   class KWQSignal;
   
  -#ifdef __OBJC__
  - at class NSTimer;
  -#else
  -class NSTimer;
  -#endif
  -
   class QObject : public Qt {
   public:
       QObject(QObject *parent = 0, const char *name = 0);
  @@ -85,12 +75,11 @@
   
       bool inherits(const char *className) const;
   
  -    int startTimer(int);
  -    void killTimer(int);
  +    int startTimer(int interval);
  +    void killTimer(int timerId);
       void killTimers();
  -    void pauseTimer(int _timerId, const void *key);
  -    void resumeTimers(const void *key, QObject *target);
  -    static void clearPausedTimers (const void *key);
  +    void timerIntervals(int timerId, int& nextFireInterval, int& repeatInterval) const;
  +    void restartTimer(int timerId, int nextFireInterval, int repeatInterval);
       
       virtual void timerEvent(QTimerEvent *);
   
  @@ -117,8 +106,6 @@
       virtual bool isQScrollView() const;
   
   private:
  -    void _addTimer(NSTimer *timer, int _timerId);
  -
       // no copying or assignment
       QObject(const QObject &);
       QObject &operator=(const QObject &);
  @@ -145,11 +132,11 @@
   class KWQObjectSenderScope
   {
   public:
  -    KWQObjectSenderScope(const QObject *);
  -    ~KWQObjectSenderScope();
  +    KWQObjectSenderScope(const QObject *o) : m_savedSender(QObject::_sender) { QObject::_sender = o; }
  +    ~KWQObjectSenderScope() { QObject::_sender = m_savedSender; }
   
   private:
  -    const QObject *_savedSender;
  +    const QObject *m_savedSender;
   };
   
   #endif
  
  
  
  1.52      +147 -226  WebCore/kwq/KWQObject.mm
  
  Index: KWQObject.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQObject.mm,v
  retrieving revision 1.51
  retrieving revision 1.52
  diff -u -r1.51 -r1.52
  --- KWQObject.mm	9 Nov 2005 02:46:29 -0000	1.51
  +++ KWQObject.mm	10 Dec 2005 17:14:38 -0000	1.52
  @@ -1,5 +1,5 @@
   /*
  - * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
  + * Copyright (C) 2004, 2005 Apple Computer, Inc.  All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
  @@ -26,50 +26,53 @@
   #include "config.h"
   #import "KWQObject.h"
   
  -#import "KWQVariant.h"
   #import <kxmlcore/Assertions.h>
  +#import <kxmlcore/FastMalloc.h>
   
  -// The Foundation-level Cocoa calls here (NSTimer, NSDate, NSArray,
  -// NSDictionary) should be exception-free, so no need to block
  -// exceptions.
  +struct KWQObjectTimer {
  +    QObject *target;
  +    int timerId;
  +    CFRunLoopTimerRef runLoopTimer; // non-0 for running timers
  +    bool deferred; // true if timer is in the deferredTimers array
  +    bool deleted;
  +};
   
   const QObject *QObject::_sender;
   bool QObject::_defersTimers;
   
   static CFMutableDictionaryRef timerDictionaries;
  -static CFMutableDictionaryRef allPausedTimers;
  -static NSMutableArray *deferredTimers;
  -static bool deferringTimers;
  +static CFMutableArrayRef deferredTimers;
  +static CFRunLoopTimerRef sendDeferredTimerEventsTimer;
  +static int lastTimerIdUsed;
   
  - at interface KWQObjectTimerTarget : NSObject
  +QObject::QObject(QObject *parent, const char *name)
  +    : _signalListHead(0), _signalsBlocked(false)
  +    , _destroyed(this, SIGNAL(destroyed()))
  +    , _eventFilterObject(0)
   {
  - at public
  -    QObject *target;
  -    int timerId;
  -    NSTimeInterval remainingTime;
  +    _guardedPtrDummyList.append(this);
   }
   
  -- initWithQObject:(QObject *)object timerId:(int)timerId;
  -- (void)timerFired;
  -
  - at end
  +QObject::~QObject()
  +{
  +    _destroyed.call();
  +    ASSERT(_signalListHead == &_destroyed);
  +    killTimers();
  +}
   
   KWQSignal *QObject::findSignal(const char *signalName) const
   {
  -    for (KWQSignal *signal = _signalListHead; signal; signal = signal->_next) {
  -        if (KWQNamesMatch(signalName, signal->_name)) {
  +    for (KWQSignal *signal = _signalListHead; signal; signal = signal->_next)
  +        if (KWQNamesMatch(signalName, signal->_name))
               return signal;
  -        }
  -    }
       return 0;
   }
   
   void QObject::connect(const QObject *sender, const char *signalName, const QObject *receiver, const char *member)
   {
  -    // FIXME: Assert that sender is not NULL rather than doing the if statement.
  -    if (!sender) {
  +    // FIXME: Assert that sender is not 0 rather than doing the if statement, then fix callers who call with 0.
  +    if (!sender)
           return;
  -    }
       
       KWQSignal *signal = sender->findSignal(signalName);
       if (!signal) {
  @@ -83,7 +86,7 @@
               && !KWQNamesMatch(member, SLOT(slotShowDocument(const QString &, const QString &)))
               && !KWQNamesMatch(member, SLOT(slotViewCleared())) // FIXME: Should implement this one!
               )
  -	ERROR("connecting member %s to signal %s, but that signal was not found", member, signalName);
  +        ERROR("connecting member %s to signal %s, but that signal was not found", member, signalName);
   #endif
           return;
       }
  @@ -92,274 +95,192 @@
   
   void QObject::disconnect(const QObject *sender, const char *signalName, const QObject *receiver, const char *member)
   {
  -    // FIXME: Assert that sender is not NULL rather than doing the if statement.
  +    // FIXME: Assert that sender is not 0 rather than doing the if statement, then fix callers who call with 0.
       if (!sender)
           return;
       
       KWQSignal *signal = sender->findSignal(signalName);
       if (!signal) {
  -        // FIXME: ERROR
  +        // FIXME: Put a call to ERROR here and clean up callers who do this.
           return;
       }
       signal->disconnect(KWQSlot(const_cast<QObject *>(receiver), member));
   }
   
  -KWQObjectSenderScope::KWQObjectSenderScope(const QObject *o)
  -    : _savedSender(QObject::_sender)
  -{
  -    QObject::_sender = o;
  -}
  -
  -KWQObjectSenderScope::~KWQObjectSenderScope()
  +void QObject::timerEvent(QTimerEvent *)
   {
  -    QObject::_sender = _savedSender;
   }
   
  -QObject::QObject(QObject *parent, const char *name)
  -    : _signalListHead(0), _signalsBlocked(false)
  -    , _destroyed(this, SIGNAL(destroyed()))
  -    , _eventFilterObject(0)
  +bool QObject::event(QEvent *)
   {
  -    _guardedPtrDummyList.append(this);
  +    return false;
   }
   
  -QObject::~QObject()
  +static void timerFired(CFRunLoopTimerRef runLoopTimer, void *info)
   {
  -    _destroyed.call();
  -    ASSERT(_signalListHead == &_destroyed);
  -    killTimers();
  +    KWQObjectTimer *timer = static_cast<KWQObjectTimer *>(info);
  +    if (QObject::defersTimers()) {
  +        if (!timer->deferred) {
  +            if (!deferredTimers)
  +                deferredTimers = CFArrayCreateMutable(0, 0, 0);
  +            CFArrayAppendValue(deferredTimers, timer);
  +            timer->deferred = true;
  +        }
  +    } else {
  +        QTimerEvent event(timer->timerId);
  +        timer->target->timerEvent(&event);
  +    }
   }
   
  -void QObject::timerEvent(QTimerEvent *te)
  +int QObject::startTimer(int interval)
   {
  +    int timerId = ++lastTimerIdUsed;
  +    restartTimer(timerId, interval, interval);
  +    return timerId;
   }
   
  -bool QObject::event(QEvent *)
  +void QObject::restartTimer(int timerId, int nextFireInterval, int repeatInterval)
   {
  -    return false;
  -}
  +    ASSERT(timerId > 0);
  +    ASSERT(timerId <= lastTimerIdUsed);
   
  -void QObject::pauseTimer (int _timerId, const void *key)
  -{
  -    NSMutableDictionary *timers = (NSMutableDictionary *)CFDictionaryGetValue(timerDictionaries, this);
  -    NSNumber *timerId = [NSNumber numberWithInt:_timerId];
  -    NSTimer *timer = (NSTimer *)[timers objectForKey:timerId];
  -
  -    if ([timer isValid]){
  -        KWQObjectTimerTarget *target = (KWQObjectTimerTarget *)[timer userInfo];
  -
  -        if (target){
  -            NSDate *fireDate = [timer fireDate];
  -            NSTimeInterval remainingTime = [fireDate timeIntervalSinceDate: [NSDate date]];
  -        
  -            if (remainingTime < 0)
  -                remainingTime = DBL_EPSILON;
  -            
  -            if (allPausedTimers == NULL) {
  -                // The global targets dictionary itself leaks, but the contents are removed
  -                // when each timer fires or is killed.
  -                allPausedTimers = CFDictionaryCreateMutable(NULL, 0, NULL, &kCFTypeDictionaryValueCallBacks);
  -            }
  -    
  -            NSMutableArray *pausedTimers = (NSMutableArray *)CFDictionaryGetValue(allPausedTimers, key);
  -            if (pausedTimers == nil) {
  -                pausedTimers = [[NSMutableArray alloc] init];
  -                CFDictionarySetValue(allPausedTimers, key, pausedTimers);
  -                [pausedTimers release];
  -            }
  -            
  -            target->remainingTime = remainingTime;
  -            [pausedTimers addObject:target];
  -                    
  -            [timer invalidate];
  -            [timers removeObjectForKey:timerId];
  -        }
  -    }
  -}
  +    if (!timerDictionaries)
  +        timerDictionaries = CFDictionaryCreateMutable(0, 0, 0, &kCFTypeDictionaryValueCallBacks);
   
  -void QObject::_addTimer(NSTimer *timer, int _timerId)
  -{
  -    NSMutableDictionary *timers = (NSMutableDictionary *)CFDictionaryGetValue(timerDictionaries, this);
  -    if (timers == nil) {
  -        timers = [[NSMutableDictionary alloc] init];
  +    CFMutableDictionaryRef timers = (CFMutableDictionaryRef)CFDictionaryGetValue(timerDictionaries, this);
  +    if (!timers) {
  +        timers = CFDictionaryCreateMutable(0, 0, 0, 0);
           CFDictionarySetValue(timerDictionaries, this, timers);
  -        [timers release];
  +        CFRelease(timers);
       }
  -    [timers setObject:timer forKey:[NSNumber numberWithInt:_timerId]];
  -}
   
  -static int nextTimerID = 1;
  +    ASSERT(!CFDictionaryGetValue(timers, reinterpret_cast<void *>(timerId)));
   
  -void QObject::clearPausedTimers (const void *key)
  -{
  -    if (allPausedTimers)
  -        CFDictionaryRemoveValue(allPausedTimers, key);
  +    KWQObjectTimer *timer = static_cast<KWQObjectTimer *>(fastMalloc(sizeof(KWQObjectTimer)));
  +    timer->target = this;
  +    timer->timerId = timerId;
  +    CFRunLoopTimerContext context = { 0, timer, 0, 0, 0 };
  +    CFRunLoopTimerRef runLoopTimer = CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent() + nextFireInterval * 0.001,
  +        repeatInterval * 0.001, 0, 0, timerFired, &context);
  +    timer->runLoopTimer = runLoopTimer;
  +    timer->deferred = false;
  +    timer->deleted = false;
  +
  +    CFDictionarySetValue(timers, reinterpret_cast<void *>(timerId), timer);
  +
  +    CFRunLoopAddTimer(CFRunLoopGetCurrent(), runLoopTimer, kCFRunLoopDefaultMode);
   }
   
  -void QObject::resumeTimers (const void *key, QObject *_target)
  +void QObject::timerIntervals(int timerId, int& nextFireInterval, int& repeatInterval) const
   {
  -    if (allPausedTimers == NULL) {
  +    nextFireInterval = -1;
  +    repeatInterval = -1;
  +    if (!timerDictionaries)
           return;
  -    }
  -    
  -    int maxId = MAX(0, nextTimerID);
  -        
  -    NSMutableArray *pausedTimers = (NSMutableArray *)CFDictionaryGetValue(allPausedTimers, key);
  -    if (pausedTimers == nil)
  -        return;
  -
  -    int count = [pausedTimers count];
  -    while (count--){
  -        KWQObjectTimerTarget *target = [pausedTimers objectAtIndex: count];
  -        target->target = _target;
  -        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:target->remainingTime
  -            target:target
  -            selector:@selector(timerFired)
  -            userInfo:target
  -            repeats:YES];
  -        [pausedTimers removeLastObject];
  -
  -        maxId = MAX (maxId, target->timerId);
  -                        
  -        _addTimer (timer, target->timerId);
  -    }
  -    nextTimerID = maxId+1;
  -    
  -    CFDictionaryRemoveValue(allPausedTimers, key);
  +    CFMutableDictionaryRef timers = (CFMutableDictionaryRef)CFDictionaryGetValue(timerDictionaries, this);
  +    if (!timers)
  +        return;
  +    KWQObjectTimer *timer = (KWQObjectTimer *)CFDictionaryGetValue(timers, reinterpret_cast<void *>(timerId));
  +    if (!timer)
  +        return;
  +    nextFireInterval = (int)((CFRunLoopTimerGetNextFireDate(timer->runLoopTimer) - CFAbsoluteTimeGetCurrent()) * 1000);
  +    repeatInterval = (int)(CFRunLoopTimerGetInterval(timer->runLoopTimer) * 1000);
   }
   
  -int QObject::startTimer(int milliseconds)
  +static void deleteTimer(KWQObjectTimer *timer)
   {
  -    if (timerDictionaries == NULL) {
  -        // The global timers dictionary itself lives forever, but the contents are removed
  -        // when each timer fires or is killed.
  -        timerDictionaries = CFDictionaryCreateMutable(NULL, 0, NULL, &kCFTypeDictionaryValueCallBacks);
  -    }
  -    
  -    NSMutableDictionary *timers = (NSMutableDictionary *)CFDictionaryGetValue(timerDictionaries, this);
  -    if (timers == nil) {
  -        timers = [[NSMutableDictionary alloc] init];
  -        CFDictionarySetValue(timerDictionaries, this, timers);
  -        [timers release];
  -    }
  +    CFRunLoopTimerInvalidate(timer->runLoopTimer);
  +    CFRelease(timer->runLoopTimer);
   
  -    KWQObjectTimerTarget *target = [[KWQObjectTimerTarget alloc] initWithQObject:this timerId:nextTimerID];
  -    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:milliseconds / 1000.0
  -          target:target
  -        selector:@selector(timerFired)
  -        userInfo:target
  -         repeats:YES];
  -    [target release];
  -    
  -    _addTimer (timer, nextTimerID);
  -    
  -    return nextTimerID++;    
  +    if (timer->deferred)
  +        timer->deleted = true;
  +    else
  +        fastFree(timer);
   }
   
  -void QObject::killTimer(int _timerId)
  +void QObject::killTimer(int timerId)
   {
  -    if (_timerId == 0) {
  +    if (!timerDictionaries)
           return;
  -    }
  -    if (timerDictionaries == NULL) {
  +    CFMutableDictionaryRef timers = (CFMutableDictionaryRef)CFDictionaryGetValue(timerDictionaries, this);
  +    if (!timers)
           return;
  -    }
  -    NSMutableDictionary *timers = (NSMutableDictionary *)CFDictionaryGetValue(timerDictionaries, this);
  -    NSNumber *timerId = [NSNumber numberWithInt:_timerId];
  -    NSTimer *timer = (NSTimer *)[timers objectForKey:timerId];
  -    // Only try to remove the timer is it hasn't fired (and is therefore valid).  It is NOT
  -    // permissible to reference a timer's userInfo if it is invalid.
  -    if ([timer isValid]){
  -        [deferredTimers removeObject:(KWQObjectTimerTarget *)[timer userInfo]];
  -        [timer invalidate];
  -    }
  -    [timers removeObjectForKey:timerId];
  +    KWQObjectTimer *timer = (KWQObjectTimer *)CFDictionaryGetValue(timers, reinterpret_cast<void *>(timerId));
  +    if (!timer)
  +        return;
  +    deleteTimer(timer);
  +    CFDictionaryRemoveValue(timers, reinterpret_cast<void *>(timerId));
  +}
  +
  +static void deleteOneTimer(const void *key, const void *value, void *context)
  +{
  +    deleteTimer((KWQObjectTimer *)value);
   }
   
   void QObject::killTimers()
   {
  -    if (timerDictionaries == NULL) {
  +    if (!timerDictionaries)
           return;
  -    }
  -    NSMutableDictionary *timers = (NSMutableDictionary *)CFDictionaryGetValue(timerDictionaries, this);
  -    if (timers == nil) {
  +    CFMutableDictionaryRef timers = (CFMutableDictionaryRef)CFDictionaryGetValue(timerDictionaries, this);
  +    if (!timers)
           return;
  -    }
  -    NSEnumerator *e = [timers keyEnumerator];
  -    NSNumber *timerId;
  -    while ((timerId = [e nextObject]) != nil) {
  -	killTimer([timerId intValue]);
  -    }
  -
  +    CFDictionaryApplyFunction(timers, deleteOneTimer, 0);
       CFDictionaryRemoveValue(timerDictionaries, this);
   }
   
  -void QObject::setDefersTimers(bool defers)
  +static void sendDeferredTimerEvent(const void *value, void *context)
   {
  -    if (defers) {
  -        _defersTimers = true;
  -        deferringTimers = true;
  -        [NSObject cancelPreviousPerformRequestsWithTarget:[KWQObjectTimerTarget class]];
  +    KWQObjectTimer *timer = (KWQObjectTimer *)value;
  +    if (!timer)
  +        return;
  +    if (timer->deleted) {
  +        fastFree(timer);
           return;
       }
  -    
  -    if (_defersTimers) {
  -        _defersTimers = false;
  -        if (deferringTimers) {
  -            [KWQObjectTimerTarget performSelector:@selector(stopDeferringTimers) withObject:nil afterDelay:0];
  -        }
  +    QTimerEvent event(timer->timerId);
  +    timer->target->timerEvent(&event);
  +    if (timer->deleted) {
  +        fastFree(timer);
  +        return;
       }
  +    timer->deferred = false;
   }
   
  - at implementation KWQObjectTimerTarget
  -
  -- initWithQObject:(QObject *)qo timerId:(int)t
  +static void sendDeferredTimerEvents(CFRunLoopTimerRef, void *)
   {
  -    [super init];
  -    target = qo;
  -    timerId = t;
  -    return self;
  -}
  +    CFRelease(sendDeferredTimerEventsTimer);
  +    sendDeferredTimerEventsTimer = 0;
   
  -- (void)sendTimerEvent
  -{
  -    QTimerEvent event(timerId);
  -    target->timerEvent(&event);
  -}
  +    CFArrayRef timers = deferredTimers;
  +    deferredTimers = 0;
   
  -- (void)timerFired
  -{
  -    if (deferringTimers) {
  -        if (deferredTimers == nil) {
  -            deferredTimers = [[NSMutableArray alloc] init];
  -        }
  -	if (![deferredTimers containsObject:self]) {
  -	    [deferredTimers addObject:self];
  -	}
  -    } else {
  -        [self sendTimerEvent];
  +    if (timers) {
  +        CFArrayApplyFunction(timers, CFRangeMake(0, CFArrayGetCount(timers)), sendDeferredTimerEvent, 0);
  +        CFRelease(timers);
       }
   }
   
  -+ (void)stopDeferringTimers
  +void QObject::setDefersTimers(bool defers)
   {
  -    ASSERT(deferringTimers);
  -    while ([deferredTimers count] != 0) {
  -	// remove before sending the timer event, in case the timer
  -	// callback cancels the timer - we don't want to remove too
  -	// much in that case.
  -	KWQObjectTimerTarget *timerTarget = [deferredTimers objectAtIndex:0];
  -	[timerTarget retain];
  -	[deferredTimers removeObjectAtIndex:0];
  -        [timerTarget sendTimerEvent];
  -	[timerTarget release];
  +    if (defers) {
  +        _defersTimers = true;
  +        if (sendDeferredTimerEventsTimer) {
  +            CFRunLoopTimerInvalidate(sendDeferredTimerEventsTimer);
  +            CFRelease(sendDeferredTimerEventsTimer);
  +            sendDeferredTimerEventsTimer = 0;
  +        }
  +        return;
  +    }
  +    
  +    if (_defersTimers) {
  +        _defersTimers = false;
  +        ASSERT(!sendDeferredTimerEventsTimer);
  +        sendDeferredTimerEventsTimer = CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent(),
  +            0, 0, 0, sendDeferredTimerEvents, 0);
  +        CFRunLoopAddTimer(CFRunLoopGetCurrent(), sendDeferredTimerEventsTimer, kCFRunLoopDefaultMode);
       }
  -
  -    deferringTimers = false;
   }
   
  - at end
  -
   bool QObject::inherits(const char *className) const
   {
       if (strcmp(className, "KHTMLPart") == 0) {
  
  
  
  1.10      +6 -14     WebCore/kwq/KWQPageState.h
  
  Index: KWQPageState.h
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQPageState.h,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- KWQPageState.h	9 Nov 2005 02:46:29 -0000	1.9
  +++ KWQPageState.h	10 Dec 2005 17:14:38 -0000	1.10
  @@ -25,19 +25,12 @@
   
   #import <Foundation/Foundation.h>
   
  -#include <qmap.h>
  -
  -#include "kjs_window.h"
  -#include "dom_docimpl.h"
  -
  -class KURL;
  -
  -namespace DOM {
  -    class DocumentImpl;
  -}
  +#import "dom_docimpl.h"
   
   namespace KJS {
  +    class SavedBuiltins;
       class SavedProperties;
  +    class PausedTimeouts;
   }
   
   @interface KWQPageState : NSObject
  @@ -48,11 +41,11 @@
       KJS::SavedProperties *windowProperties;
       KJS::SavedProperties *locationProperties;
       KJS::SavedBuiltins *interpreterBuiltins;
  -    QMap<int, KJS::ScheduledAction*> *pausedActions;
  +    KJS::PausedTimeouts *pausedTimeouts;
       DOM::DocumentImpl::ParseMode parseMode;
   }
   
  -- initWithDocument:(DOM::DocumentImpl *)doc URL:(const KURL &)u windowProperties:(KJS::SavedProperties *)wp locationProperties:(KJS::SavedProperties *)lp interpreterBuiltins:(KJS::SavedBuiltins *)ib;
  +- initWithDocument:(DOM::DocumentImpl *)doc URL:(const KURL &)u windowProperties:(KJS::SavedProperties *)wp locationProperties:(KJS::SavedProperties *)lp interpreterBuiltins:(KJS::SavedBuiltins *)ib pausedTimeouts:(KJS::PausedTimeouts *)pt;
   
   - (DOM::DocumentImpl *)document;
   - (DOM::DocumentImpl::ParseMode)parseMode;
  @@ -61,8 +54,7 @@
   - (KJS::SavedProperties *)windowProperties;
   - (KJS::SavedProperties *)locationProperties;
   - (KJS::SavedBuiltins *)interpreterBuiltins;
  -- (void)setPausedActions: (QMap<int, KJS::ScheduledAction*> *)pa;
  -- (QMap<int, KJS::ScheduledAction*> *)pausedActions;
  +- (KJS::PausedTimeouts *)pausedTimeouts;
   - (void)invalidate;
   
   @end
  
  
  
  1.25      +31 -44    WebCore/kwq/KWQPageState.mm
  
  Index: KWQPageState.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQPageState.mm,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- KWQPageState.mm	27 Nov 2005 07:54:53 -0000	1.24
  +++ KWQPageState.mm	10 Dec 2005 17:14:38 -0000	1.25
  @@ -23,7 +23,7 @@
    * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    */
   
  -#include "config.h"
  +#import "config.h"
   #import "KWQPageState.h"
   
   #import <JavaScriptCore/interpreter.h>
  @@ -37,65 +37,50 @@
   #import "KWQFoundationExtras.h"
   #import "KWQKHTMLPart.h"
   
  -using DOM::DocumentImpl;
  +using namespace DOM;
   
  -using khtml::RenderObject;
  +using namespace khtml;
   
  -using KJS::Interpreter;
  -using KJS::JSLock;
  -using KJS::SavedProperties;
  -using KJS::SavedBuiltins;
  +using namespace KJS;
   
   @implementation KWQPageState
   
  -- initWithDocument:(DocumentImpl *)doc URL:(const KURL &)u windowProperties:(SavedProperties *)wp locationProperties:(SavedProperties *)lp interpreterBuiltins:(SavedBuiltins *)ib
  +- initWithDocument:(DocumentImpl *)doc URL:(const KURL &)u windowProperties:(SavedProperties *)wp locationProperties:(SavedProperties *)lp interpreterBuiltins:(SavedBuiltins *)ib pausedTimeouts:(PausedTimeouts *)pt
   {
       [super init];
  +
       doc->ref();
       document = doc;
  -    document->setInPageCache(YES);
  -    parseMode = document->parseMode();
  -    document->view()->ref();
  -    mousePressNode = static_cast<KWQKHTMLPart *>(document->part())->mousePressNode();
  -    if (mousePressNode) {
  +    doc->setInPageCache(YES);
  +    mousePressNode = static_cast<KWQKHTMLPart *>(doc->part())->mousePressNode();
  +    if (mousePressNode)
           mousePressNode->ref();
  -    }
       URL = new KURL(u);
       windowProperties = wp;
       locationProperties = lp;
       interpreterBuiltins = ib;
  -    return self;
  -}
  +    pausedTimeouts = pt;
  +    parseMode = doc->parseMode();
   
  -- (DOM::DocumentImpl::ParseMode)parseMode { return parseMode; }
  +    doc->view()->ref();
   
  -- (void)setPausedActions: (QMap<int, KJS::ScheduledAction*> *)pa
  -{
  -    pausedActions = pa;
  +    return self;
   }
   
  -- (QMap<int, KJS::ScheduledAction*> *)pausedActions
  +- (DocumentImpl::ParseMode)parseMode
   {
  -    return pausedActions;
  +    return parseMode;
   }
   
  -- (void)_cleanupPausedActions
  +- (PausedTimeouts *)pausedTimeouts
   {
  -    if (pausedActions){
  -        QMapIterator<int,KJS::ScheduledAction*> it;
  -        for (it = pausedActions->begin(); it != pausedActions->end(); ++it) {
  -            KJS::ScheduledAction *action = *it;
  -            delete action;
  -        }
  -        delete pausedActions;
  -        pausedActions = 0;
  -    }
  -    QObject::clearPausedTimers(self);
  +    return pausedTimeouts;
   }
   
   - (void)clear
   {
  -    document = 0;
  +    if (mousePressNode)
  +        mousePressNode->deref();        
       mousePressNode = 0;
   
       delete URL;
  @@ -110,7 +95,8 @@
       delete interpreterBuiltins;
       interpreterBuiltins = 0;
   
  -    [self _cleanupPausedActions];
  +    delete pausedTimeouts;
  +    pausedTimeouts = 0;
   }
   
   - (void)invalidate
  @@ -120,19 +106,22 @@
       ASSERT(document->view());
       ASSERT(!document->inPageCache());
   
  -    if (document && document->view()) {
  -        document->view()->deref();
  +    if (document) {
  +        KHTMLView *view = document->view();
  +        if (view)
  +            view->deref();
           document->deref();
  +        document = 0;
       }
  -    
  +
       [self clear];
   }
   
   - (void)dealloc
   {
       if (document) {
  -        ASSERT(document->inPageCache());
           ASSERT(document->view());
  +        ASSERT(document->inPageCache());
   
           KHTMLView *view = document->view();
   
  @@ -145,10 +134,7 @@
               document->removeAllEventListenersFromAllNodes();
           }
           document->deref();
  -        
  -        if (mousePressNode) {
  -            mousePressNode->deref();
  -        }
  +        document = 0;
           
           if (view) {
               view->clearPart();
  @@ -181,6 +167,7 @@
               document->removeAllEventListenersFromAllNodes();
           }
           document->deref();
  +        document = 0;
           
           if (view) {
               view->clearPart();
  @@ -198,7 +185,7 @@
       return document;
   }
   
  -- (DOM::NodeImpl *)mousePressNode
  +- (NodeImpl *)mousePressNode
   {
       return mousePressNode;
   }
  
  
  
  1.16      +11 -14    WebCore/kwq/KWQTimer.h
  
  Index: KWQTimer.h
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQTimer.h,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- KWQTimer.h	5 Dec 2005 22:19:10 -0000	1.15
  +++ KWQTimer.h	10 Dec 2005 17:14:38 -0000	1.16
  @@ -1,5 +1,5 @@
   /*
  - * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
  + * Copyright (C) 2003, 2005 Apple Computer, Inc.  All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
  @@ -27,37 +27,34 @@
   #define QTIMER_H_
   
   #include "KWQObject.h"
  -#include "KWQSignal.h"
  -
  -#ifdef __OBJC__
  - at class NSTimer;
  -#else
  -class NSTimer;
  -#endif
   
   class QTimer : public QObject {
   public:
  -    QTimer(QObject *parent = 0);
  +    QTimer() : m_runLoopTimer(0), m_monitorFunction(0), m_timeoutSignal(this, SIGNAL(timeout())) { }
       ~QTimer() { stop(); }
       
  -    bool isActive() const;
  +    bool isActive() const { return m_runLoopTimer; }
       void start(int msec, bool singleShot = false);
       void stop();
       void fire();
       
       static void singleShot(int msec, QObject *receiver, const char *member);
  -    
  +
       // This is just a hack used by KWQKHTMLPart. The monitor function
       // gets called when the timer starts and when it is stopped before firing,
       // but not when the timer fires.
       void setMonitor(void (*monitorFunction)(void *context), void *context);
  -    NSTimer *getNSTimer() { return m_timer; }
   
  -private:    
  -    NSTimer *m_timer;
  +    CFAbsoluteTime fireDate() const { return CFRunLoopTimerGetNextFireDate(m_runLoopTimer); }
  +
  +private:
  +    CFRunLoopTimerRef m_runLoopTimer;
       void (*m_monitorFunction)(void *context);
       void *m_monitorFunctionContext;
       KWQSignal m_timeoutSignal;
  +
  +    QTimer(const QTimer&);
  +    QTimer& operator=(const QTimer&);
   };
   
   #endif
  
  
  
  1.23      +20 -104   WebCore/kwq/KWQTimer.mm
  
  Index: KWQTimer.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/KWQTimer.mm,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- KWQTimer.mm	5 Dec 2005 22:19:10 -0000	1.22
  +++ KWQTimer.mm	10 Dec 2005 17:14:38 -0000	1.23
  @@ -1,5 +1,5 @@
   /*
  - * Copyright (C) 2003 Apple Computer, Inc.  All rights reserved.
  + * Copyright (C) 2003, 2005 Apple Computer, Inc.  All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
  @@ -27,111 +27,37 @@
   #import "KWQTimer.h"
   
   #import <kxmlcore/Assertions.h>
  -#import "KWQLogging.h"
  -#import "KWQFoundationExtras.h"
   
  -// We know the Cocoa calls in this file are safe because they are all
  -// to the simple ObjC class defined here, or simple NSTimer calls that
  -// can't throw.
  -
  - at interface KWQTimerTarget : NSObject
  -{
  -    QTimer *timer;
  -}
  -+ (KWQTimerTarget *)targetWithQTimer:(QTimer *)timer;
  -- (void)timerFired:(id)userInfo;
  - at end
  -
  - at interface KWQSingleShotTimerTarget : NSObject
  -{
  -    KWQSlot *slot;
  -}
  -+ (KWQSingleShotTimerTarget *)targetWithQObject:(QObject *)object member:(const char *)member;
  -- (void)timerFired:(id)userInfo;
  - at end
  -
  - at implementation KWQTimerTarget
  -
  -+ (KWQTimerTarget *)targetWithQTimer:(QTimer *)t
  -{
  -    KWQTimerTarget *target = [[[self alloc] init] autorelease];
  -    target->timer = t;
  -    return target;
  -}
  -
  -- (void)timerFired:(id)userInfo
  +static void timerFired(CFRunLoopTimerRef, void *info)
   {
  -    timer->fire();
  -}
  -
  - at end
  -
  - at implementation KWQSingleShotTimerTarget
  -
  -+ (KWQSingleShotTimerTarget *)targetWithQObject:(QObject *)object member:(const char *)member
  -{
  -    KWQSingleShotTimerTarget *target = [[[self alloc] init] autorelease];
  -    target->slot = new KWQSlot(object, member);
  -    return target;
  -}
  -
  -- (void)dealloc
  -{
  -    delete slot;
  -    [super dealloc];
  -}
  -
  -- (void)finalize
  -{
  -    delete slot;
  -    [super finalize];
  -}
  -
  -- (void)timerFired:(id)userInfo
  -{
  -    slot->call();
  -}
  -
  - at end
  -
  -QTimer::QTimer(QObject *parent)
  -    : m_timer(nil), m_monitorFunction(0), m_timeoutSignal(this, SIGNAL(timeout()))
  -{
  -    if (parent) LOG(NotYetImplemented, "Parent pointer ignored.  QTimer will be leaked and may fire after parent dealloc causing crash.");
  -}
  -
  -bool QTimer::isActive() const
  -{
  -    return m_timer;
  +    ((QTimer *)info)->fire();
   }
   
   void QTimer::start(int msec, bool singleShot)
   {
       stop();
  -    m_timer = KWQRetain([NSTimer scheduledTimerWithTimeInterval:(msec / 1000.0)
  -                                                target:[KWQTimerTarget targetWithQTimer:this]
  -                                              selector:@selector(timerFired:)
  -                                              userInfo:nil
  -                                               repeats:!singleShot]);
   
  -    if (m_monitorFunction) {
  +    CFTimeInterval interval = msec * 0.001;
  +    CFRunLoopTimerContext context = { 0, this, 0, 0, 0 };
  +    m_runLoopTimer = CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent() + interval,
  +        singleShot ? 0 : interval, 0, 0, timerFired, &context);
  +    CFRunLoopAddTimer(CFRunLoopGetCurrent(), m_runLoopTimer, kCFRunLoopDefaultMode);
  +
  +    if (m_monitorFunction)
           m_monitorFunction(m_monitorFunctionContext);
  -    }
   }
   
   void QTimer::stop()
   {
  -    if (m_timer == nil) {
  +    if (!m_runLoopTimer)
           return;
  -    }
       
  -    [m_timer invalidate];
  -    KWQRelease(m_timer);
  -    m_timer = nil;
  +    CFRunLoopTimerInvalidate(m_runLoopTimer);
  +    CFRelease(m_runLoopTimer);
  +    m_runLoopTimer = 0;
   
  -    if (m_monitorFunction) {
  +    if (m_monitorFunction)
           m_monitorFunction(m_monitorFunctionContext);
  -    }
   }
   
   void QTimer::setMonitor(void (*monitorFunction)(void *context), void *context)
  @@ -143,22 +69,12 @@
   
   void QTimer::fire()
   {
  -    // Ensure that m_timer is kept around for duration of callback.
  -    // Final reference will eventually be released in stop(), which may be called 
  -    // in this frame, hence the need to ensure the timer is kept around until
  -    // the pool is released. 
  -    [[m_timer retain] autorelease];
  +    if (m_runLoopTimer && !CFRunLoopTimerIsValid(m_runLoopTimer)) {
  +        CFRunLoopTimerInvalidate(m_runLoopTimer);
  +        CFRelease(m_runLoopTimer);
  +        m_runLoopTimer = 0;
  +    }
   
       // Note: This call may destroy the QTimer, so be sure not to touch any fields afterward.
       m_timeoutSignal.call();
   }
  -
  -void QTimer::singleShot(int msec, QObject *receiver, const char *member)
  -{
  -    [NSTimer scheduledTimerWithTimeInterval:(msec / 1000.0)
  -                                     target:[KWQSingleShotTimerTarget targetWithQObject:receiver member:member]
  -                                   selector:@selector(timerFired:)
  -                                   userInfo:nil
  -                                    repeats:NO];
  -}
  -
  
  
  
  1.440     +14 -12    WebCore/kwq/WebCoreBridge.mm
  
  Index: WebCoreBridge.mm
  ===================================================================
  RCS file: /cvs/root/WebCore/kwq/WebCoreBridge.mm,v
  retrieving revision 1.439
  retrieving revision 1.440
  diff -u -r1.439 -r1.440
  --- WebCoreBridge.mm	8 Dec 2005 08:40:27 -0000	1.439
  +++ WebCoreBridge.mm	10 Dec 2005 17:14:38 -0000	1.440
  @@ -476,13 +476,11 @@
   - (BOOL)saveDocumentToPageCache
   {
       DocumentImpl *doc = _part->xmlDocImpl();
  -    if (!doc) {
  +    if (!doc)
           return NO;
  -    }
  -    
  -    if (!doc->view()) {
  +    if (!doc->view())
           return NO;
  -    }
  +
       _part->clearTimers();
   
       JSLock lock;
  @@ -496,14 +494,18 @@
       SavedBuiltins *interpreterBuiltins = new SavedBuiltins;
       _part->saveInterpreterBuiltins(*interpreterBuiltins);
   
  -    KWQPageState *pageState = [[[KWQPageState alloc] initWithDocument:doc
  -                                                                  URL:_part->m_url
  -                                                     windowProperties:windowProperties
  -                                                   locationProperties:locationProperties
  -				                  interpreterBuiltins:interpreterBuiltins] autorelease];
  -    [pageState setPausedActions: _part->pauseActions((const void *)pageState)];
  +    KWQPageState *pageState = [[KWQPageState alloc] initWithDocument:doc
  +                                                                 URL:_part->m_url
  +                                                    windowProperties:windowProperties
  +                                                  locationProperties:locationProperties
  +                                                 interpreterBuiltins:interpreterBuiltins
  +                                                      pausedTimeouts:_part->pauseTimeouts()];
  +
  +    BOOL result = [self saveDocumentToPageCache:pageState];
  +
  +    [pageState release];
   
  -    return [self saveDocumentToPageCache:pageState];
  +    return result;
   }
   
   - (BOOL)canCachePage
  
  
  



More information about the webkit-changes mailing list