[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: branches/KDE/4.0/kdelibs/khtml/ecma
From: Maks Orlovich <maksim () kde ! org>
Date: 2008-03-14 18:52:22
Message-ID: 1205520742.197590.27811.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 785693 by orlovich:
Apply a patch from Vyacheslav Tokarev (username tsjoker, hostname gmail, tld com)
that fixes multiple issues with event listeners:
1. Use the proper 'this' object for object-style event listeners.
2. Use the object, not function, for comparison of object-style
event listeners
3. Properly keep html-style and normal listener objects separate ---
they behave independent, even if they wrap the same function,
and of course have different event-cancellation semantics
BUG:147249
BUG:111568
BUG:128416
M +12 -8 kjs_events.cpp
M +2 -2 kjs_events.h
M +6 -6 kjs_window.cpp
M +1 -1 kjs_window.h
--- branches/KDE/4.0/kdelibs/khtml/ecma/kjs_events.cpp #785692:785693
@@ -48,14 +48,14 @@
{
//fprintf(stderr,"JSEventListener::JSEventListener this=%p \
listener=%p\n",this,listener.imp()); if (compareListenerImp) {
- static_cast<Window*>(win.get())->jsEventListeners.insert(compareListenerImp, \
this); + static_cast<Window*>(win.get())->jsEventListeners.insert(QPair<void*, \
bool>(compareListenerImp, html), this); }
}
JSEventListener::~JSEventListener()
{
if (compareListenerImp) {
- static_cast<Window*>(win.get())->jsEventListeners.remove(compareListenerImp);
+ static_cast<Window*>(win.get())->jsEventListeners.remove(QPair<void*, \
bool>(compareListenerImp, html)); }
//fprintf(stderr,"JSEventListener::~JSEventListener this=%p \
listener=%p\n",this,listener.imp()); }
@@ -82,8 +82,14 @@
List args;
args.append(getDOMEvent(exec,evt.handle()));
- // Set "this" to the event's current target
- JSObject *thisObj = getDOMNode(exec,evt.currentTarget().handle())->getObject();
+ JSObject *thisObj = 0;
+ // Check whether handler is a function or an object with handleEvent method
+ if (listener == compareListenerImp) {
+ // Set "this" to the event's current target
+ thisObj = getDOMNode(exec,evt.currentTarget().handle())->getObject();
+ } else {
+ thisObj = compareListenerImp;
+ }
if ( !thisObj ) {
// Window events (window.onload/window.onresize etc.) must have 'this' set to \
the window.
// DocumentImpl::defaultEventHandler sets currentTarget to 0 to mean 'window'.
@@ -144,9 +150,6 @@
JSLazyEventListener::~JSLazyEventListener()
{
- if (listener) {
- static_cast<Window*>(win.get())->jsEventListeners.remove(listener);
- }
}
void JSLazyEventListener::handleEvent(DOM::Event &evt)
@@ -186,6 +189,7 @@
args.append(jsString(code));
listener = constr->construct(exec, args,
Identifier(UString(name)), url, lineNum); // ### is globalExec ok ?
+ compareListenerImp = listener;
if (exec->hadException()) {
exec->clearException();
@@ -217,7 +221,7 @@
code.clear();
if (listener) {
- static_cast<Window*>(win.get())->jsEventListeners.insert(listener,
+ static_cast<Window*>(win.get())->jsEventListeners.insert(QPair<void*, \
bool>(compareListenerImp, true),
(KJS::JSEventListener *)(this));
}
--- branches/KDE/4.0/kdelibs/khtml/ecma/kjs_events.h #785692:785693
@@ -49,7 +49,7 @@
// for Window::clear(). This is a bad hack though. The JSEventListener might not \
get deleted
// if it was added to a DOM node in another frame (#61467). But calling \
removeEventListener on // all nodes we're listening to is quite difficult.
- void clear() { listener = 0; }
+ void clear() { listener = 0; compareListenerImp = 0; }
bool isHTMLEventListener() const { return html; }
protected:
@@ -64,7 +64,7 @@
// the imp() ptr of the 'passedListener' function _object_, as the \
implementation will
// call removeEventListener(.. [Object ..] on removal, and now we can \
successfully lookup
// the correct event listener, as well as the 'listener.handleEvent' function, \
we need to call.
- mutable JSObject *compareListenerImp;
+ mutable ProtectedPtr<JSObject> compareListenerImp;
bool html;
mutable ProtectedPtr<JSObject> win;
};
--- branches/KDE/4.0/kdelibs/khtml/ecma/kjs_window.cpp #785692:785693
@@ -1393,6 +1393,7 @@
// It's ObjectType, so it must be valid.
JSObject *listenerObject = val->getObject();
+ JSObject *thisObject = listenerObject;
// 'listener' is not a simple ecma function. (Always use sanity checks: Better \
safe than sorry!) if (!listenerObject->implementsCall() && part && part->jScript() \
&& part->jScript()->interpreter()) @@ -1405,20 +1406,19 @@
if(handleEventObject && handleEventObject->implementsCall())
{
+ thisObject = listenerObject;
listenerObject = handleEventObject;
}
}
- JSEventListener *existingListener = jsEventListeners[listenerObject];
+ JSEventListener *existingListener = jsEventListeners[QPair<void*, \
bool>(thisObject, html)]; if (existingListener) {
- if ( existingListener->isHTMLEventListener() != html )
- // The existingListener will have the wrong type, so onclick= will behave \
like addEventListener or vice versa.
- kWarning() << "getJSEventListener: event listener already found but with \
html=" << !html << " - please report this, we thought it would never happen"; + \
assert( existingListener->isHTMLEventListener() == html ); return existingListener;
}
// Note that the JSEventListener constructor adds it to our jsEventListeners list
- return new JSEventListener(listenerObject, listenerObject, this, html);
+ return new JSEventListener(listenerObject, thisObject, this, html);
}
JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, const \
QString& srcUrl, int line, @@ -1435,7 +1435,7 @@
clearProperties();
// Break the dependency between the listeners and their object
- QHashIterator<void*, JSEventListener*> it(jsEventListeners);
+ QHashIterator<const QPair<void*, bool>, JSEventListener*> it(jsEventListeners);
while ( it.hasNext() ) {
it.next();
it.value()->clear();
--- branches/KDE/4.0/kdelibs/khtml/ecma/kjs_window.h #785692:785693
@@ -135,7 +135,7 @@
// Set the current "event" object
void setCurrentEvent( DOM::EventImpl *evt );
- QHash<void*, JSEventListener*> jsEventListeners;
+ QHash<const QPair<void*, bool>, JSEventListener*> jsEventListeners;
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
enum { Closed, Crypto, DefaultStatus, Status, Document, Node, EventCtor, Range,
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic