[webkit-changes] cvs commit: WebCore/kwq KWQKHTMLPart.h
KWQKHTMLPart.mm KWQObject.h KWQObject.mm KWQPageState.h
KWQPageState.mm KWQTimer.h KWQTimer.mm WebCoreBridge.mm
Tim
tomernic at opensource.apple.com
Tue Nov 8 18:46:34 PST 2005
tomernic 05/11/08 18:46:33
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:
<http://bugzilla.opendarwin.org/show_bug.cgi?id=5665> (REGRESSION: Crash in deleteTimer)
Rolled back Darin's timer changes from 2005-11-07, as they caused a couple of regressions.
Revision Changes Path
1.348 +6 -0 WebCore/ChangeLog
Index: ChangeLog
===================================================================
RCS file: /cvs/root/WebCore/ChangeLog,v
retrieving revision 1.347
retrieving revision 1.348
diff -u -r1.347 -r1.348
--- ChangeLog 8 Nov 2005 21:54:17 -0000 1.347
+++ ChangeLog 9 Nov 2005 02:46:21 -0000 1.348
@@ -1,3 +1,9 @@
+2005-11-08 Tim Omernick <timo at apple.com>
+
+ <http://bugzilla.opendarwin.org/show_bug.cgi?id=5665> (REGRESSION: Crash in deleteTimer)
+
+ Rolled back Darin's timer changes from 2005-11-07, as they caused a couple of regressions.
+
2005-11-08 Adele Peterson <adele at apple.com>
Reviewed by Darin.
1.187 +199 -109 WebCore/khtml/ecma/kjs_window.cpp
Index: kjs_window.cpp
===================================================================
RCS file: /cvs/root/WebCore/khtml/ecma/kjs_window.cpp,v
retrieving revision 1.186
retrieving revision 1.187
diff -u -r1.186 -r1.187
--- kjs_window.cpp 7 Nov 2005 20:52:09 -0000 1.186
+++ kjs_window.cpp 9 Nov 2005 02:46:27 -0000 1.187
@@ -80,25 +80,30 @@
// <cmath> and <math.h> the macros necessary for functions like
// isnan are not defined.
#include <cmath>
-using std::isnan;
-using namespace DOM;
-using namespace EventNames;
+using namespace DOM::EventNames;
-using namespace khtml;
+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 KParts;
+using std::isnan;
namespace KJS {
-class PausedTimeout {
-public:
- int timerId;
- int nextFireInterval;
- int repeatInterval;
- ScheduledAction *action;
-};
-
////////////////////// History Object ////////////////////////
class History : public ObjectImp {
@@ -1257,11 +1262,47 @@
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);
+}
+
+#if APPLE_CHANGES
+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);
+}
+#endif
+
void Window::scheduleClose()
{
kdDebug(6070) << "Window::scheduleClose window.close() " << m_part << endl;
Q_ASSERT(winq);
+#if APPLE_CHANGES
KWQ(m_part)->scheduleClose();
+#else
+ QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
+#endif
}
static bool shouldLoadAsEmptyDocument(const KURL &url)
@@ -1986,141 +2027,200 @@
docimpl->updateLayoutIgnorePendingStylesheets();
}
+
////////////////////// ScheduledAction ////////////////////////
-void ScheduledAction::execute(Window *window)
+ScheduledAction::ScheduledAction(ObjectImp *_func, List _args, bool _singleShot)
{
- if (!window->m_part)
- return;
+ //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;
+}
- ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
- interpreter->setProcessingTimerCallback(true);
+void ScheduledAction::execute(Window *window)
+{
+ ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
- if (m_func) {
- if (m_func->isObject() && static_cast<ObjectImp *>(m_func.get())->implementsCall()) {
- ExecState *exec = interpreter->globalExec();
- assert(window == interpreter->globalObject());
- InterpreterLock lock;
- static_cast<ObjectImp *>(m_func.get())->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.utf8().data());
- KWQ(window->m_part)->addMessageToConsole(message, lineNumber, QString());
- }
+ 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);
+ InterpreterLock 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();
}
- } else
- window->m_part->executeScript(m_code);
+ }
+ }
+ } else
+ window->m_part->executeScript(code);
- // 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();
+ // Update our document's rendering following the execution of the timeout callback.
+ if (DocumentImpl *doc = window->m_part->xmlDocImpl())
+ doc->updateRendering();
- interpreter->setProcessingTimerCallback(false);
+ interpreter->setProcessingTimerCallback(false);
}
////////////////////// WindowQObject ////////////////////////
WindowQObject::WindowQObject(Window *w)
- : m_parent(w)
+ : parent(w)
{
- connect(w->m_part, SIGNAL(destroyed()), this, SLOT(parentDestroyed()));
+ //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
+ part = parent->m_part;
+ connect( parent->m_part, SIGNAL( destroyed() ),
+ this, SLOT( parentDestroyed() ) );
+}
+
+WindowQObject::~WindowQObject()
+{
+ //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
+ parentDestroyed(); // reuse same code
}
void WindowQObject::parentDestroyed()
{
- killTimers();
- for (QMapIterator<int, ScheduledAction *> it = m_timeouts.begin(); it != m_timeouts.end(); ++it)
- delete *it;
- m_timeouts.clear();
+ //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();
}
-int WindowQObject::installTimeout(const UString& handler, int t, bool singleShot)
+int WindowQObject::installTimeout(const UString &handler, int t, bool singleShot)
{
- int id = startTimer(t);
- ScheduledAction *action = new ScheduledAction(handler.qstring(), singleShot);
- m_timeouts.insert(id, action);
- return id;
+ //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 WindowQObject::installTimeout(ValueImp *func, const List& args, int t, bool singleShot)
+int WindowQObject::installTimeout(ValueImp *func, List args, int t, bool singleShot)
{
- int id = startTimer(t);
- m_timeouts.insert(id, new ScheduledAction(func, args, singleShot));
- return id;
+ ObjectImp *objFunc = static_cast<ObjectImp *>(func);
+ int id = startTimer(t);
+ scheduledActions.insert(id, new ScheduledAction(objFunc,args,singleShot));
+ return id;
}
-PausedTimeouts *WindowQObject::pauseTimeouts()
+QMap<int, ScheduledAction*> *WindowQObject::pauseTimeouts(const void *key)
{
- 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) {
+ QMapIterator<int,ScheduledAction*> it;
+
+ QMap<int, ScheduledAction*>*pausedActions = new QMap<int, ScheduledAction*>;
+ for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
int timerId = it.key();
- timerIntervals(timerId, t->nextFireInterval, t->repeatInterval);
- t->timerId = timerId;
- t->action = it.data();
- ++t;
- killTimer(timerId);
+ pauseTimer (timerId, key);
+ pausedActions->insert(timerId, it.data());
}
- m_timeouts.clear();
- return result;
+ scheduledActions.clear();
+ return pausedActions;
}
-void WindowQObject::resumeTimeouts(PausedTimeouts *timeouts)
+void WindowQObject::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
{
- 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);
+ QMapIterator<int,ScheduledAction*> it;
+ for (it = sa->begin(); it != sa->end(); ++it) {
+ int timerId = it.key();
+ scheduledActions.insert(timerId, it.data());
}
- delete [] array;
+ sa->clear();
+ resumeTimers (key, this);
}
void WindowQObject::clearTimeout(int timerId, bool delAction)
{
- killTimer(timerId);
- if (delAction) {
- QMapIterator<int, ScheduledAction *> it = m_timeouts.find(timerId);
- if (it != m_timeouts.end()) {
- delete *it;
- m_timeouts.remove(it);
- }
+ //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;
}
+ }
}
void WindowQObject::timerEvent(QTimerEvent *e)
{
- QMapIterator<int, ScheduledAction *> it = m_timeouts.find(e->timerId());
+ QMapIterator<int,ScheduledAction*> it = scheduledActions.find(e->timerId());
+ if (it != scheduledActions.end()) {
ScheduledAction *action = *it;
- bool singleShot = action->singleShot();
+ bool singleShot = action->singleShot;
+ //kdDebug(6070) << "WindowQObject::timerEvent " << this << " action=" << action << " singleShot:" << singleShot << endl;
- // remove single shots before executing
- if (singleShot) {
- clearTimeout(e->timerId(), false);
- m_timeouts.remove(it);
+ // remove single shots installed by setTimeout()
+ if (singleShot)
+ {
+ clearTimeout(e->timerId(),false);
+ scheduledActions.remove(it);
}
+
+ if (!parent->part().isNull())
+ action->execute(parent);
- 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
+ // 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
// JS code called by execute() calls clearTimeout().
if (singleShot)
- delete action;
+ 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;
+ }
+}
+
+#if APPLE_CHANGES
+bool WindowQObject::hasTimeouts()
+{
+ return scheduledActions.count();
}
+#endif
+
const ClassInfo FrameArray::info = { "FrameArray", 0, &FrameArrayTable, 0 };
@@ -2131,6 +2231,7 @@
@end
*/
+
ValueImp *FrameArray::getValueProperty(ExecState *exec, int token)
{
switch (token) {
@@ -2707,17 +2808,6 @@
/////////////////////////////////////////////////////////////////////////////
-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.56 +58 -73 WebCore/khtml/ecma/kjs_window.h
Index: kjs_window.h
===================================================================
RCS file: /cvs/root/WebCore/khtml/ecma/kjs_window.h,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- kjs_window.h 7 Nov 2005 20:52:09 -0000 1.55
+++ kjs_window.h 9 Nov 2005 02:46:27 -0000 1.56
@@ -40,57 +40,17 @@
namespace KJS {
- 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 WindowFunc;
+ class WindowQObject;
+ class Location;
+ class Selection;
+ class BarInfo;
+ class History;
+ class FrameArray;
+ class JSEventListener;
+ class JSUnprotectedEventListener;
+ class JSLazyEventListener;
+ class ScheduledAction;
class Screen : public ObjectImp {
public:
@@ -138,19 +98,21 @@
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) { 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); }
+ int installTimeout(const UString &handler, int t, bool singleShot);
+ int installTimeout(ValueImp *function, List &args, int t, bool singleShot);
+ void clearTimeout(int timerId);
+#ifdef APPLE_CHANGES
+ bool hasTimeouts();
+ QMap<int, ScheduledAction*> *pauseTimeouts(const void *key);
+ void resumeTimeouts(QMap<int, ScheduledAction*>*sa, const void *key);
KJS::Interpreter *interpreter() const;
+ static bool isSafeScript (const KJS::ScriptInterpreter *origin, const KJS::ScriptInterpreter *target);
+#endif
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;
@@ -224,21 +186,44 @@
* time interval, either once or repeatedly. Used for window.setTimeout()
* and window.setInterval()
*/
- 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 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);
+#ifdef APPLE_CHANGES
+ bool hasTimeouts();
+ QMap<int, ScheduledAction*> *WindowQObject::pauseTimeouts(const void *key);
+ void WindowQObject::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key);
+#endif
+
+ 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 Location : public ObjectImp {
public:
1.232 +2 -3 WebCore/kwq/KWQKHTMLPart.h
Index: KWQKHTMLPart.h
===================================================================
RCS file: /cvs/root/WebCore/kwq/KWQKHTMLPart.h,v
retrieving revision 1.231
retrieving revision 1.232
diff -u -r1.231 -r1.232
--- KWQKHTMLPart.h 7 Nov 2005 20:52:10 -0000 1.231
+++ KWQKHTMLPart.h 9 Nov 2005 02:46:28 -0000 1.232
@@ -61,7 +61,6 @@
}
namespace KJS {
- class PausedTimeouts;
class SavedProperties;
class SavedBuiltins;
class ScheduledAction;
@@ -161,8 +160,8 @@
void unfocusWindow();
- KJS::PausedTimeouts *pauseTimeouts();
- void resumeTimeouts(KJS::PausedTimeouts *);
+ QMap<int, KJS::ScheduledAction*> *pauseActions(const void *key);
+ void resumeActions(QMap<int, KJS::ScheduledAction*> *actions, const void *key);
bool canCachePage();
void saveWindowProperties(KJS::SavedProperties *windowProperties);
1.686 +104 -30 WebCore/kwq/KWQKHTMLPart.mm
Index: KWQKHTMLPart.mm
===================================================================
RCS file: /cvs/root/WebCore/kwq/KWQKHTMLPart.mm,v
retrieving revision 1.685
retrieving revision 1.686
diff -u -r1.685 -r1.686
--- KWQKHTMLPart.mm 7 Nov 2005 20:52:10 -0000 1.685
+++ KWQKHTMLPart.mm 9 Nov 2005 02:46:28 -0000 1.686
@@ -88,18 +88,87 @@
#undef _KWQ_TIMING
-using namespace DOM;
-using namespace EventNames;
-using namespace HTMLNames;
+using namespace DOM::EventNames;
+using namespace DOM::HTMLNames;
-using namespace KJS;
-using namespace Bindings;
+using DOM::AtomicString;
+using DOM::ClipboardEventImpl;
+using DOM::DocumentFragmentImpl;
+using DOM::DocumentImpl;
+using DOM::DocumentMarker;
+using DOM::DOMString;
+using DOM::ElementImpl;
+using DOM::EventImpl;
+using DOM::HTMLDocumentImpl;
+using DOM::HTMLElementImpl;
+using DOM::HTMLFormElementImpl;
+using DOM::HTMLFrameElementImpl;
+using DOM::HTMLGenericFormElementImpl;
+using DOM::HTMLTableCellElementImpl;
+using DOM::Node;
+using DOM::NodeImpl;
+using DOM::Position;
+using DOM::Range;
+using DOM::RangeImpl;
+using DOM::TextImpl;
+
+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::InterpreterLock;
+using KJS::Location;
+using KJS::SavedBuiltins;
+using KJS::SavedProperties;
+using KJS::ScheduledAction;
+using KJS::Window;
-using namespace khtml;
+using KJS::Bindings::Instance;
-using namespace KIO;
-
-using namespace KParts;
+using KParts::ReadOnlyPart;
+using KParts::URLArgs;
NSEvent *KWQKHTMLPart::_currentEvent = nil;
@@ -1078,13 +1147,11 @@
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:fireDate
+ fireDate:[d->m_redirectionTimer.getNSTimer() fireDate]
lockHistory:d->m_redirectLockHistory
isJavaScriptFormAction:d->m_executingJavaScriptFormAction];
- [fireDate release];
} else {
[_bridge reportClientRedirectCancelled:d->m_cancelWithLoadInProgress];
}
@@ -1405,22 +1472,24 @@
[_bridge windowObjectCleared];
}
-PausedTimeouts *KWQKHTMLPart::pauseTimeouts()
+QMap<int, ScheduledAction*> *KWQKHTMLPart::pauseActions(const void *key)
{
if (d->m_doc && d->m_jscript) {
Window *w = Window::retrieveWindow(this);
- if (w)
- return w->pauseTimeouts();
+ if (w && w->hasTimeouts()) {
+ return w->pauseTimeouts(key);
+ }
}
return 0;
}
-void KWQKHTMLPart::resumeTimeouts(PausedTimeouts *t)
+void KWQKHTMLPart::resumeActions(QMap<int, ScheduledAction*> *actions, const void *key)
{
if (d->m_doc && d->m_jscript && d->m_bJScriptEnabled) {
Window *w = Window::retrieveWindow(this);
- if (w)
- w->resumeTimeouts(t);
+ if (w) {
+ w->resumeTimeouts(actions, key);
+ }
}
}
@@ -1503,13 +1572,14 @@
SavedProperties *windowProperties = [state windowProperties];
SavedProperties *locationProperties = [state locationProperties];
SavedBuiltins *interpreterBuiltins = [state interpreterBuiltins];
- PausedTimeouts *timeouts = [state pausedTimeouts];
+ QMap<int, ScheduledAction*> *actions = [state pausedActions];
cancelRedirection();
// We still have to close the previous part page.
- if (!d->m_restored)
+ if (!d->m_restored){
closeURL();
+ }
d->m_bComplete = false;
@@ -1517,12 +1587,13 @@
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;
@@ -1556,24 +1627,27 @@
d->m_mousePressNode.reset(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
InterpreterLock lock;
- restoreWindowProperties(windowProperties);
- restoreLocationProperties(locationProperties);
- restoreInterpreterBuiltins(*interpreterBuiltins);
+ restoreWindowProperties (windowProperties);
+ restoreLocationProperties (locationProperties);
+ restoreInterpreterBuiltins (*interpreterBuiltins);
}
- resumeTimeouts(timeouts);
+ if (actions)
+ resumeActions (actions, state);
checkCompleted();
}
@@ -4158,7 +4232,7 @@
int exception = 0;
ASSERT(!range || range->startContainer(exception) == range->endContainer(exception));
- ASSERT(!range || range->collapsed(exception) || range->startContainer(exception)->nodeType() == DOM::Node::TEXT_NODE);
+ ASSERT(!range || range->collapsed(exception) || range->startContainer(exception)->nodeType() == Node::TEXT_NODE);
if (attributes == nil) {
m_markedTextUsesUnderlines = false;
1.38 +33 -20 WebCore/kwq/KWQObject.h
Index: KWQObject.h
===================================================================
RCS file: /cvs/root/WebCore/kwq/KWQObject.h,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- KWQObject.h 7 Nov 2005 20:52:11 -0000 1.37
+++ KWQObject.h 9 Nov 2005 02:46:29 -0000 1.38
@@ -26,10 +26,14 @@
#ifndef QOBJECT_H_
#define QOBJECT_H_
-#include "KWQEvent.h"
-#include "KWQPtrList.h"
+#include "KWQDef.h"
#include "KWQSignal.h"
+
+#include "KWQNamespace.h"
+#include "KWQString.h"
+#include "KWQEvent.h"
#include "KWQStringList.h"
+#include "KWQPtrList.h"
#define slots : public
#define SLOT(x) "SLOT:" #x
@@ -39,30 +43,36 @@
#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 QPainter;
+class QWidget;
+class QColor;
+class QColorGroup;
class QPalette;
-class QRect;
+class QPainter;
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);
@@ -75,11 +85,12 @@
bool inherits(const char *className) const;
- int startTimer(int interval);
- void killTimer(int timerId);
+ int startTimer(int);
+ void killTimer(int);
void killTimers();
- void timerIntervals(int timerId, int& nextFireInterval, int& repeatInterval) const;
- void restartTimer(int timerId, int nextFireInterval, int repeatInterval);
+ void pauseTimer(int _timerId, const void *key);
+ void resumeTimers(const void *key, QObject *target);
+ static void clearPausedTimers (const void *key);
virtual void timerEvent(QTimerEvent *);
@@ -106,6 +117,8 @@
virtual bool isQScrollView() const;
private:
+ void _addTimer(NSTimer *timer, int _timerId);
+
// no copying or assignment
QObject(const QObject &);
QObject &operator=(const QObject &);
@@ -132,11 +145,11 @@
class KWQObjectSenderScope
{
public:
- KWQObjectSenderScope(const QObject *o) : m_savedSender(QObject::_sender) { QObject::_sender = o; }
- ~KWQObjectSenderScope() { QObject::_sender = m_savedSender; }
+ KWQObjectSenderScope(const QObject *);
+ ~KWQObjectSenderScope();
private:
- const QObject *m_savedSender;
+ const QObject *_savedSender;
};
#endif
1.51 +224 -140 WebCore/kwq/KWQObject.mm
Index: KWQObject.mm
===================================================================
RCS file: /cvs/root/WebCore/kwq/KWQObject.mm,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -r1.50 -r1.51
--- KWQObject.mm 8 Nov 2005 21:54:23 -0000 1.50
+++ KWQObject.mm 9 Nov 2005 02:46:29 -0000 1.51
@@ -28,53 +28,48 @@
#import "KWQVariant.h"
#import <kxmlcore/Assertions.h>
-#import <kxmlcore/FastMalloc.h>
-struct KWQObjectTimer {
- QObject *target;
- int timerId;
- CFRunLoopTimerRef runLoopTimer; // non-0 for running timers
- CFIndex deferredTimerArrayIndex; // kCFNotFound if not deferred
-};
+// The Foundation-level Cocoa calls here (NSTimer, NSDate, NSArray,
+// NSDictionary) should be exception-free, so no need to block
+// exceptions.
const QObject *QObject::_sender;
bool QObject::_defersTimers;
static CFMutableDictionaryRef timerDictionaries;
-static CFMutableArrayRef deferredTimers;
+static CFMutableDictionaryRef allPausedTimers;
+static NSMutableArray *deferredTimers;
static bool deferringTimers;
-static CFRunLoopTimerRef sendDeferredTimerEventsTimer;
-static int lastTimerIdUsed;
-
-QObject::QObject(QObject *parent, const char *name)
- : _signalListHead(0), _signalsBlocked(false)
- , _destroyed(this, SIGNAL(destroyed()))
- , _eventFilterObject(0)
+ at interface KWQObjectTimerTarget : NSObject
{
- _guardedPtrDummyList.append(this);
+ at public
+ QObject *target;
+ int timerId;
+ NSTimeInterval remainingTime;
}
-QObject::~QObject()
-{
- _destroyed.call();
- ASSERT(_signalListHead == &_destroyed);
- killTimers();
-}
+- initWithQObject:(QObject *)object timerId:(int)timerId;
+- (void)timerFired;
+
+ at end
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 0 rather than doing the if statement, then fix callers who call with 0.
- if (!sender)
+ // FIXME: Assert that sender is not NULL rather than doing the if statement.
+ if (!sender) {
return;
+ }
KWQSignal *signal = sender->findSignal(signalName);
if (!signal) {
@@ -88,7 +83,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;
}
@@ -97,160 +92,206 @@
void QObject::disconnect(const QObject *sender, const char *signalName, const QObject *receiver, const char *member)
{
- // FIXME: Assert that sender is not 0 rather than doing the if statement, then fix callers who call with 0.
+ // FIXME: Assert that sender is not NULL rather than doing the if statement.
if (!sender)
return;
KWQSignal *signal = sender->findSignal(signalName);
if (!signal) {
- // FIXME: Put a call to ERROR here and clean up callers who do this.
+ // FIXME: ERROR
return;
}
signal->disconnect(KWQSlot(const_cast<QObject *>(receiver), member));
}
-void QObject::timerEvent(QTimerEvent *)
+KWQObjectSenderScope::KWQObjectSenderScope(const QObject *o)
+ : _savedSender(QObject::_sender)
{
+ QObject::_sender = o;
}
-bool QObject::event(QEvent *)
+KWQObjectSenderScope::~KWQObjectSenderScope()
{
- return false;
+ QObject::_sender = _savedSender;
}
-static void timerFired(CFRunLoopTimerRef runLoopTimer, void *info)
+QObject::QObject(QObject *parent, const char *name)
+ : _signalListHead(0), _signalsBlocked(false)
+ , _destroyed(this, SIGNAL(destroyed()))
+ , _eventFilterObject(0)
{
- KWQObjectTimer *timer = static_cast<KWQObjectTimer *>(info);
- if (deferringTimers) {
- if (timer->deferredTimerArrayIndex == kCFNotFound) {
- if (!deferredTimers)
- deferredTimers = CFArrayCreateMutable(0, 0, 0);
- timer->deferredTimerArrayIndex = CFArrayGetCount(deferredTimers);
- CFArrayAppendValue(deferredTimers, timer);
- }
- } else {
- QTimerEvent event(timer->timerId);
- timer->target->timerEvent(&event);
- }
+ _guardedPtrDummyList.append(this);
}
-int QObject::startTimer(int interval)
+QObject::~QObject()
{
- int timerId = ++lastTimerIdUsed;
- restartTimer(timerId, interval, interval);
- return timerId;
+ _destroyed.call();
+ ASSERT(_signalListHead == &_destroyed);
+ killTimers();
}
-void QObject::restartTimer(int timerId, int nextFireInterval, int repeatInterval)
+void QObject::timerEvent(QTimerEvent *te)
{
- ASSERT(timerId > 0);
- ASSERT(timerId <= lastTimerIdUsed);
-
- if (!timerDictionaries)
- timerDictionaries = CFDictionaryCreateMutable(0, 0, 0, &kCFTypeDictionaryValueCallBacks);
-
- CFMutableDictionaryRef timers = (CFMutableDictionaryRef)CFDictionaryGetValue(timerDictionaries, this);
- if (!timers) {
- timers = CFDictionaryCreateMutable(0, 0, 0, 0);
- CFDictionarySetValue(timerDictionaries, this, timers);
- CFRelease(timers);
- }
-
- ASSERT(!CFDictionaryGetValue(timers, reinterpret_cast<void *>(timerId)));
-
- 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->deferredTimerArrayIndex = kCFNotFound;
-
- CFDictionarySetValue(timers, reinterpret_cast<void *>(timerId), timer);
+}
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), runLoopTimer, kCFRunLoopDefaultMode);
+bool QObject::event(QEvent *)
+{
+ return false;
}
-void QObject::timerIntervals(int timerId, int& nextFireInterval, int& repeatInterval) const
+void QObject::pauseTimer (int _timerId, const void *key)
{
- nextFireInterval = -1;
- repeatInterval = -1;
- if (!timerDictionaries)
- return;
- 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);
+ 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];
+ }
+ }
}
-static void deleteTimer(KWQObjectTimer *timer)
+void QObject::_addTimer(NSTimer *timer, int _timerId)
{
- CFRunLoopTimerInvalidate(timer->runLoopTimer);
- CFRelease(timer->runLoopTimer);
+ NSMutableDictionary *timers = (NSMutableDictionary *)CFDictionaryGetValue(timerDictionaries, this);
+ if (timers == nil) {
+ timers = [[NSMutableDictionary alloc] init];
+ CFDictionarySetValue(timerDictionaries, this, timers);
+ [timers release];
+ }
+ [timers setObject:timer forKey:[NSNumber numberWithInt:_timerId]];
+}
- CFIndex i = timer->deferredTimerArrayIndex;
- if (i != kCFNotFound)
- CFArraySetValueAtIndex(deferredTimers, i, 0);
+static int nextTimerID = 1;
- fastFree(timer);
+void QObject::clearPausedTimers (const void *key)
+{
+ if (allPausedTimers)
+ CFDictionaryRemoveValue(allPausedTimers, key);
}
-void QObject::killTimer(int timerId)
+void QObject::resumeTimers (const void *key, QObject *_target)
{
- if (!timerDictionaries)
- return;
- CFMutableDictionaryRef timers = (CFMutableDictionaryRef)CFDictionaryGetValue(timerDictionaries, this);
- if (!timers)
+ if (allPausedTimers == NULL) {
return;
- KWQObjectTimer *timer = (KWQObjectTimer *)CFDictionaryGetValue(timers, reinterpret_cast<void *>(timerId));
- if (!timer)
- return;
- deleteTimer(timer);
- CFDictionaryRemoveValue(timers, reinterpret_cast<void *>(timerId));
+ }
+
+ 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);
}
-static void deleteOneTimer(const void *key, const void *value, void *context)
+int QObject::startTimer(int milliseconds)
{
- deleteTimer((KWQObjectTimer *)value);
+ 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];
+ }
+
+ 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++;
}
-void QObject::killTimers()
+void QObject::killTimer(int _timerId)
{
- if (!timerDictionaries)
+ if (_timerId == 0) {
return;
- CFMutableDictionaryRef timers = (CFMutableDictionaryRef)CFDictionaryGetValue(timerDictionaries, this);
- if (!timers)
+ }
+ if (timerDictionaries == NULL) {
return;
- CFDictionaryApplyFunction(timers, deleteOneTimer, 0);
- CFDictionaryRemoveValue(timerDictionaries, this);
+ }
+ 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];
}
-static void sendDeferredTimerEvent(const void *value, void *context)
+void QObject::killTimers()
{
- KWQObjectTimer *timer = (KWQObjectTimer *)value;
- if (!timer)
+ if (timerDictionaries == NULL) {
return;
- QTimerEvent event(timer->timerId);
- timer->target->timerEvent(&event);
-}
-
-static void sendDeferredTimerEvents(CFRunLoopTimerRef, void *)
-{
- CFRelease(sendDeferredTimerEventsTimer);
- sendDeferredTimerEventsTimer = 0;
-
- CFArrayRef timers = deferredTimers;
- deferredTimers = 0;
-
- if (timers) {
- CFArrayApplyFunction(timers, CFRangeMake(0, CFArrayGetCount(timers)), sendDeferredTimerEvent, 0);
- CFRelease(timers);
}
+ NSMutableDictionary *timers = (NSMutableDictionary *)CFDictionaryGetValue(timerDictionaries, this);
+ if (timers == nil) {
+ return;
+ }
+ NSEnumerator *e = [timers keyEnumerator];
+ NSNumber *timerId;
+ while ((timerId = [e nextObject]) != nil) {
+ killTimer([timerId intValue]);
+ }
+
+ CFDictionaryRemoveValue(timerDictionaries, this);
}
void QObject::setDefersTimers(bool defers)
@@ -258,24 +299,67 @@
if (defers) {
_defersTimers = true;
deferringTimers = true;
- if (sendDeferredTimerEventsTimer) {
- CFRunLoopTimerInvalidate(sendDeferredTimerEventsTimer);
- CFRelease(sendDeferredTimerEventsTimer);
- sendDeferredTimerEventsTimer = 0;
- }
+ [NSObject cancelPreviousPerformRequestsWithTarget:[KWQObjectTimerTarget class]];
return;
}
if (_defersTimers) {
_defersTimers = false;
if (deferringTimers) {
- sendDeferredTimerEventsTimer = CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent(),
- 0, 0, 0, sendDeferredTimerEvents, 0);
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), sendDeferredTimerEventsTimer, kCFRunLoopDefaultMode);
+ [KWQObjectTimerTarget performSelector:@selector(stopDeferringTimers) withObject:nil afterDelay:0];
+ }
+ }
+}
+
+ at implementation KWQObjectTimerTarget
+
+- initWithQObject:(QObject *)qo timerId:(int)t
+{
+ [super init];
+ target = qo;
+ timerId = t;
+ return self;
+}
+
+- (void)sendTimerEvent
+{
+ QTimerEvent event(timerId);
+ target->timerEvent(&event);
+}
+
+- (void)timerFired
+{
+ if (deferringTimers) {
+ if (deferredTimers == nil) {
+ deferredTimers = [[NSMutableArray alloc] init];
}
+ if (![deferredTimers containsObject:self]) {
+ [deferredTimers addObject:self];
+ }
+ } else {
+ [self sendTimerEvent];
}
}
++ (void)stopDeferringTimers
+{
+ 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];
+ }
+
+ deferringTimers = false;
+}
+
+ at end
+
bool QObject::inherits(const char *className) const
{
if (strcmp(className, "KHTMLPart") == 0) {
1.9 +14 -6 WebCore/kwq/KWQPageState.h
Index: KWQPageState.h
===================================================================
RCS file: /cvs/root/WebCore/kwq/KWQPageState.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- KWQPageState.h 7 Nov 2005 20:52:11 -0000 1.8
+++ KWQPageState.h 9 Nov 2005 02:46:29 -0000 1.9
@@ -25,12 +25,19 @@
#import <Foundation/Foundation.h>
-#import "dom_docimpl.h"
+#include <qmap.h>
+
+#include "kjs_window.h"
+#include "dom_docimpl.h"
+
+class KURL;
+
+namespace DOM {
+ class DocumentImpl;
+}
namespace KJS {
- class SavedBuiltins;
class SavedProperties;
- class PausedTimeouts;
}
@interface KWQPageState : NSObject
@@ -41,11 +48,11 @@
KJS::SavedProperties *windowProperties;
KJS::SavedProperties *locationProperties;
KJS::SavedBuiltins *interpreterBuiltins;
- KJS::PausedTimeouts *pausedTimeouts;
+ QMap<int, KJS::ScheduledAction*> *pausedActions;
DOM::DocumentImpl::ParseMode parseMode;
}
-- initWithDocument:(DOM::DocumentImpl *)doc URL:(const KURL &)u windowProperties:(KJS::SavedProperties *)wp locationProperties:(KJS::SavedProperties *)lp interpreterBuiltins:(KJS::SavedBuiltins *)ib pausedTimeouts:(KJS::PausedTimeouts *)pt;
+- initWithDocument:(DOM::DocumentImpl *)doc URL:(const KURL &)u windowProperties:(KJS::SavedProperties *)wp locationProperties:(KJS::SavedProperties *)lp interpreterBuiltins:(KJS::SavedBuiltins *)ib;
- (DOM::DocumentImpl *)document;
- (DOM::DocumentImpl::ParseMode)parseMode;
@@ -54,7 +61,8 @@
- (KJS::SavedProperties *)windowProperties;
- (KJS::SavedProperties *)locationProperties;
- (KJS::SavedBuiltins *)interpreterBuiltins;
-- (KJS::PausedTimeouts *)pausedTimeouts;
+- (void)setPausedActions: (QMap<int, KJS::ScheduledAction*> *)pa;
+- (QMap<int, KJS::ScheduledAction*> *)pausedActions;
- (void)invalidate;
@end
1.23 +44 -31 WebCore/kwq/KWQPageState.mm
Index: KWQPageState.mm
===================================================================
RCS file: /cvs/root/WebCore/kwq/KWQPageState.mm,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- KWQPageState.mm 7 Nov 2005 20:52:11 -0000 1.22
+++ KWQPageState.mm 9 Nov 2005 02:46:29 -0000 1.23
@@ -23,7 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#import "config.h"
+#include "config.h"
#import "KWQPageState.h"
#import <JavaScriptCore/interpreter.h>
@@ -37,50 +37,65 @@
#import "KWQFoundationExtras.h"
#import "KWQKHTMLPart.h"
-using namespace DOM;
+using DOM::DocumentImpl;
-using namespace khtml;
+using khtml::RenderObject;
-using namespace KJS;
+using KJS::Interpreter;
+using KJS::InterpreterLock;
+using KJS::SavedProperties;
+using KJS::SavedBuiltins;
@implementation KWQPageState
-- initWithDocument:(DocumentImpl *)doc URL:(const KURL &)u windowProperties:(SavedProperties *)wp locationProperties:(SavedProperties *)lp interpreterBuiltins:(SavedBuiltins *)ib pausedTimeouts:(PausedTimeouts *)pt
+- initWithDocument:(DocumentImpl *)doc URL:(const KURL &)u windowProperties:(SavedProperties *)wp locationProperties:(SavedProperties *)lp interpreterBuiltins:(SavedBuiltins *)ib
{
[super init];
-
doc->ref();
document = doc;
- doc->setInPageCache(YES);
- mousePressNode = static_cast<KWQKHTMLPart *>(doc->part())->mousePressNode();
- if (mousePressNode)
+ document->setInPageCache(YES);
+ parseMode = document->parseMode();
+ document->view()->ref();
+ mousePressNode = static_cast<KWQKHTMLPart *>(document->part())->mousePressNode();
+ if (mousePressNode) {
mousePressNode->ref();
+ }
URL = new KURL(u);
windowProperties = wp;
locationProperties = lp;
interpreterBuiltins = ib;
- pausedTimeouts = pt;
- parseMode = doc->parseMode();
+ return self;
+}
- doc->view()->ref();
+- (DOM::DocumentImpl::ParseMode)parseMode { return parseMode; }
- return self;
+- (void)setPausedActions: (QMap<int, KJS::ScheduledAction*> *)pa
+{
+ pausedActions = pa;
}
-- (DocumentImpl::ParseMode)parseMode
+- (QMap<int, KJS::ScheduledAction*> *)pausedActions
{
- return parseMode;
+ return pausedActions;
}
-- (PausedTimeouts *)pausedTimeouts
+- (void)_cleanupPausedActions
{
- return 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);
}
- (void)clear
{
- if (mousePressNode)
- mousePressNode->deref();
+ document = 0;
mousePressNode = 0;
delete URL;
@@ -95,8 +110,7 @@
delete interpreterBuiltins;
interpreterBuiltins = 0;
- delete pausedTimeouts;
- pausedTimeouts = 0;
+ [self _cleanupPausedActions];
}
- (void)invalidate
@@ -106,22 +120,19 @@
ASSERT(document->view());
ASSERT(!document->inPageCache());
- if (document) {
- KHTMLView *view = document->view();
- if (view)
- view->deref();
+ if (document && document->view()) {
+ document->view()->deref();
document->deref();
- document = 0;
}
-
+
[self clear];
}
- (void)dealloc
{
if (document) {
- ASSERT(document->view());
ASSERT(document->inPageCache());
+ ASSERT(document->view());
KHTMLView *view = document->view();
@@ -134,7 +145,10 @@
document->removeAllEventListenersFromAllNodes();
}
document->deref();
- document = 0;
+
+ if (mousePressNode) {
+ mousePressNode->deref();
+ }
if (view) {
view->clearPart();
@@ -167,7 +181,6 @@
document->removeAllEventListenersFromAllNodes();
}
document->deref();
- document = 0;
if (view) {
view->clearPart();
@@ -185,7 +198,7 @@
return document;
}
-- (NodeImpl *)mousePressNode
+- (DOM::NodeImpl *)mousePressNode
{
return mousePressNode;
}
1.14 +15 -10 WebCore/kwq/KWQTimer.h
Index: KWQTimer.h
===================================================================
RCS file: /cvs/root/WebCore/kwq/KWQTimer.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- KWQTimer.h 7 Nov 2005 20:52:11 -0000 1.13
+++ KWQTimer.h 9 Nov 2005 02:46:29 -0000 1.14
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003 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,34 +27,39 @@
#define QTIMER_H_
#include "KWQObject.h"
+#include "KWQSignal.h"
+
+#ifdef __OBJC__
+ at class NSTimer;
+#else
+class NSTimer;
+#endif
class QTimer : public QObject {
public:
- QTimer() : m_runLoopTimer(0), m_monitorFunction(0), m_timeoutSignal(this, SIGNAL(timeout())) { }
+ QTimer(QObject *parent = 0);
~QTimer() { stop(); }
- bool isActive() const { return m_runLoopTimer; }
+ bool isActive() const;
void start(int msec, bool singleShot = false);
void stop();
void fire();
static void singleShot(int msec, QObject *receiver, const char *member);
+
+ static void immediateSingleShotOnMainThread(void (*func)());
// 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; }
- CFAbsoluteTime fireDate() const { return CFRunLoopTimerGetNextFireDate(m_runLoopTimer); }
-
-private:
- CFRunLoopTimerRef m_runLoopTimer;
+private:
+ NSTimer *m_timer;
void (*m_monitorFunction)(void *context);
void *m_monitorFunctionContext;
KWQSignal m_timeoutSignal;
-
- QTimer(const QTimer&);
- QTimer& operator=(const QTimer&);
};
#endif
1.21 +125 -30 WebCore/kwq/KWQTimer.mm
Index: KWQTimer.mm
===================================================================
RCS file: /cvs/root/WebCore/kwq/KWQTimer.mm,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- KWQTimer.mm 7 Nov 2005 20:52:11 -0000 1.20
+++ KWQTimer.mm 9 Nov 2005 02:46:29 -0000 1.21
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003, 2005 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2003 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,111 @@
#import "KWQTimer.h"
#import <kxmlcore/Assertions.h>
+#import "KWQLogging.h"
+#import "KWQFoundationExtras.h"
-static void timerFired(CFRunLoopTimerRef, void *info)
+// 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
+{
+ 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
{
- ((QTimer *)info)->fire();
+ 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;
}
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]);
- 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)
+ if (m_monitorFunction) {
m_monitorFunction(m_monitorFunctionContext);
+ }
}
void QTimer::stop()
{
- if (!m_runLoopTimer)
+ if (m_timer == nil) {
return;
+ }
- CFRunLoopTimerInvalidate(m_runLoopTimer);
- CFRelease(m_runLoopTimer);
- m_runLoopTimer = 0;
+ [m_timer invalidate];
+ KWQRelease(m_timer);
+ m_timer = nil;
- if (m_monitorFunction)
+ if (m_monitorFunction) {
m_monitorFunction(m_monitorFunctionContext);
+ }
}
void QTimer::setMonitor(void (*monitorFunction)(void *context), void *context)
@@ -69,31 +143,52 @@
void QTimer::fire()
{
- if (m_runLoopTimer && !CFRunLoopTimerIsValid(m_runLoopTimer)) {
- CFRunLoopTimerInvalidate(m_runLoopTimer);
- CFRelease(m_runLoopTimer);
- m_runLoopTimer = 0;
- }
+ // 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];
// Note: This call may destroy the QTimer, so be sure not to touch any fields afterward.
m_timeoutSignal.call();
}
-static void deleteKWQSlot(const void *info)
+void QTimer::singleShot(int msec, QObject *receiver, const char *member)
{
- delete (KWQSlot *)info;
+ [NSTimer scheduledTimerWithTimeInterval:(msec / 1000.0)
+ target:[KWQSingleShotTimerTarget targetWithQObject:receiver member:member]
+ selector:@selector(timerFired:)
+ userInfo:nil
+ repeats:NO];
}
-static void singleShotTimerFired(CFRunLoopTimerRef, void *info)
+ at interface KWQMainThreadPerformTarget : NSObject
{
- ((KWQSlot *)info)->call();
+ void (*_func)();
}
-void QTimer::singleShot(int msec, QObject *receiver, const char *member)
+- (id)initWithFunction:(void (*)())func;
+- (void)callFunction:(id)ignore;
+ at end
+
+ at implementation KWQMainThreadPerformTarget
+- (id)initWithFunction:(void (*)())func
+{
+ if ((self = [super init])) {
+ _func = func;
+ }
+ return self;
+}
+
+- (void)callFunction:(id)ignore
+{
+ _func();
+}
+
+ at end
+
+void QTimer::immediateSingleShotOnMainThread(void (*func)())
{
- CFRunLoopTimerContext context = { 0, new KWQSlot(receiver, member), 0, deleteKWQSlot, 0 };
- CFRunLoopTimerRef timer = CFRunLoopTimerCreate(0, CFAbsoluteTimeGetCurrent() + msec * 0.001,
- 0, 0, 0, singleShotTimerFired, &context);
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode);
- CFRelease(timer);
+ [[[KWQMainThreadPerformTarget alloc] initWithFunction:func] performSelectorOnMainThread:@selector(callFunction) withObject:nil waitUntilDone:NO];
}
+
1.426 +12 -14 WebCore/kwq/WebCoreBridge.mm
Index: WebCoreBridge.mm
===================================================================
RCS file: /cvs/root/WebCore/kwq/WebCoreBridge.mm,v
retrieving revision 1.425
retrieving revision 1.426
diff -u -r1.425 -r1.426
--- WebCoreBridge.mm 7 Nov 2005 20:52:11 -0000 1.425
+++ WebCoreBridge.mm 9 Nov 2005 02:46:29 -0000 1.426
@@ -476,11 +476,13 @@
- (BOOL)saveDocumentToPageCache
{
DocumentImpl *doc = _part->xmlDocImpl();
- if (!doc)
+ if (!doc) {
return NO;
- if (!doc->view())
+ }
+
+ if (!doc->view()) {
return NO;
-
+ }
_part->clearTimers();
InterpreterLock lock;
@@ -494,18 +496,14 @@
SavedBuiltins *interpreterBuiltins = new SavedBuiltins;
_part->saveInterpreterBuiltins(*interpreterBuiltins);
- 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];
+ KWQPageState *pageState = [[[KWQPageState alloc] initWithDocument:doc
+ URL:_part->m_url
+ windowProperties:windowProperties
+ locationProperties:locationProperties
+ interpreterBuiltins:interpreterBuiltins] autorelease];
+ [pageState setPausedActions: _part->pauseActions((const void *)pageState)];
- return result;
+ return [self saveDocumentToPageCache:pageState];
}
- (BOOL)canCachePage
More information about the webkit-changes
mailing list