File indexing completed on 2024-04-28 15:23:12

0001 /*
0002  *  This file is part of the KDE libraries
0003  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
0004  *  Copyright (C) 2003 Apple Computer, Inc.
0005  *  Copyright (C) 2006, 2009, 2010 Maksim Orlovich (maksim@kde.org)
0006  *
0007  *  This library is free software; you can redistribute it and/or
0008  *  modify it under the terms of the GNU Library General Public
0009  *  License as published by the Free Software Foundation; either
0010  *  version 2 of the License, or (at your option) any later version.
0011  *
0012  *  This library is distributed in the hope that it will be useful,
0013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  *  Library General Public License for more details.
0016  *
0017  *  You should have received a copy of the GNU Library General Public
0018  *  License along with this library; if not, write to the Free Software
0019  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0020  */
0021 
0022 #include "kjs_events.h"
0023 #include "kjs_events.lut.h"
0024 
0025 #include "kjs_data.h"
0026 #include "kjs_window.h"
0027 #include "kjs_views.h"
0028 #include "kjs_proxy.h"
0029 #include <xml/dom_nodeimpl.h>
0030 #include <xml/dom_docimpl.h>
0031 #include <xml/dom2_eventsimpl.h>
0032 #include <rendering/render_object.h>
0033 #include <rendering/render_canvas.h>
0034 #include <khtml_part.h>
0035 #ifdef KJS_DEBUGGER
0036 #include "debugger/debugwindow.h"
0037 #endif
0038 #include "khtml_debug.h"
0039 #include <kjs/scriptfunction.h>
0040 #include <kjs/function_object.h>
0041 
0042 using namespace KJS;
0043 using namespace KJSDebugger;
0044 using namespace DOM;
0045 
0046 // -------------------------------------------------------------------------
0047 
0048 JSEventListener::JSEventListener(JSObject *_listener, JSObject *_compareListenerImp, JSObject *_win, bool _html)
0049     : listener(_listener), compareListenerImp(_compareListenerImp), html(_html), win(_win)
0050 {
0051     //fprintf(stderr,"JSEventListener::JSEventListener this=%p listener=%p\n",this,listener.imp());
0052     if (compareListenerImp) {
0053         static_cast<Window *>(win.get())->jsEventListeners.insert(QPair<void *, bool>(compareListenerImp.get(), html), this);
0054     }
0055 }
0056 
0057 JSEventListener::~JSEventListener()
0058 {
0059     if (compareListenerImp) {
0060         static_cast<Window *>(win.get())->jsEventListeners.remove(QPair<void *, bool>(compareListenerImp.get(), html));
0061     }
0062     //fprintf(stderr,"JSEventListener::~JSEventListener this=%p listener=%p\n",this,listener.imp());
0063 }
0064 
0065 void JSEventListener::handleEvent(DOM::Event &evt)
0066 {
0067     KHTMLPart *part = qobject_cast<KHTMLPart *>(static_cast<Window *>(win.get())->part());
0068     KJSProxy *proxy = nullptr;
0069     if (part) {
0070         proxy = part->jScript();
0071     }
0072 
0073     if (proxy && listener && listener->implementsCall()) {
0074 #ifdef KJS_DEBUGGER
0075         //### This is the wrong place to do this --- we need
0076         // a more global/general stategy to prevent unwanted event loop recursion issues.
0077         if (proxy->debugEnabled() && DebugWindow::window()->inSession()) {
0078             return;
0079         }
0080 #endif
0081         ref();
0082 
0083         KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
0084         ExecState *exec = interpreter->globalExec();
0085 
0086         List args;
0087         args.append(getDOMEvent(exec, evt.handle()));
0088 
0089         JSObject *thisObj = nullptr;
0090         // Check whether handler is a function or an object with handleEvent method
0091         if (listener == compareListenerImp) {
0092             // Set "this" to the event's current target
0093             thisObj = getEventTarget(exec, evt.handle()->currentTarget())->getObject();
0094         } else {
0095             thisObj = compareListenerImp;
0096         }
0097 
0098         if (!thisObj) {
0099             // ### can this still happen? eventTarget should be window on Window events now.
0100             thisObj = win;
0101         }
0102 
0103         Window *window = static_cast<Window *>(win.get());
0104         // Set the event we're handling in the Window object
0105         window->setCurrentEvent(evt.handle());
0106         // ... and in the interpreter
0107         interpreter->setCurrentEvent(&evt);
0108 
0109         interpreter->startCPUGuard();
0110         JSValue *retval = listener->call(exec, thisObj, args);
0111         interpreter->stopCPUGuard();
0112 
0113         window->setCurrentEvent(nullptr);
0114         interpreter->setCurrentEvent(nullptr);
0115         if (exec->hadException()) {
0116             exec->clearException();
0117         } else if (html) {
0118             QVariant ret = ValueToVariant(exec, retval);
0119             if (ret.type() == QVariant::Bool && ret.toBool() == false) {
0120                 evt.preventDefault();
0121             }
0122         }
0123         window->afterScriptExecution();
0124         deref();
0125     }
0126 }
0127 
0128 DOM::DOMString JSEventListener::eventListenerType()
0129 {
0130     if (html) {
0131         return "_khtml_HTMLEventListener";
0132     } else {
0133         return "_khtml_JSEventListener";
0134     }
0135 }
0136 
0137 JSObject *JSEventListener::listenerObj() const
0138 {
0139     return listener;
0140 }
0141 
0142 JSLazyEventListener::JSLazyEventListener(const QString &_code, const QString &_url, int _lineNum,
0143         const QString &_name, JSObject *_win, DOM::NodeImpl *_originalNode, bool _svg)
0144     : JSEventListener(nullptr, nullptr, _win, true), code(_code), url(_url), lineNum(_lineNum),
0145       name(_name), parsed(false), svg(_svg)
0146 {
0147     // We don't retain the original node, because we assume it
0148     // will stay alive as long as this handler object is around
0149     // and we need to avoid a reference cycle. If JS transfers
0150     // this handler to another node, parseCode will be called and
0151     // then originalNode is no longer needed.
0152 
0153     originalNode = _originalNode;
0154 }
0155 
0156 JSLazyEventListener::~JSLazyEventListener()
0157 {
0158 }
0159 
0160 void JSLazyEventListener::handleEvent(DOM::Event &evt)
0161 {
0162     parseCode();
0163     if (listener) {
0164         JSEventListener::handleEvent(evt);
0165     }
0166 }
0167 
0168 JSObject *JSLazyEventListener::listenerObj() const
0169 {
0170     parseCode();
0171     return listener;
0172 }
0173 
0174 void JSLazyEventListener::parseCode() const
0175 {
0176     if (!parsed) {
0177         KHTMLPart *part = qobject_cast<KHTMLPart *>(static_cast<Window *>(win.get())->part());
0178         KJSProxy *proxy = nullptr;
0179         if (part) {
0180             proxy = part->jScript();
0181         }
0182 
0183         if (proxy) {
0184             KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
0185             ExecState *exec = interpreter->globalExec();
0186 
0187             //KJS::Constructor constr(KJS::Global::current().get("Function").imp());
0188             KJS::FunctionObjectImp *constr = static_cast<KJS::FunctionObjectImp *>(interpreter->builtinFunction());
0189             KJS::List args;
0190 
0191             if (svg) {
0192                 args.append(jsString("evt"));
0193             } else {
0194                 args.append(jsString("event"));
0195             }
0196 
0197             args.append(jsString(code));
0198             listener = constr->construct(exec, args,
0199                                          Identifier(UString(name)), url, lineNum); // ### is globalExec ok ?
0200             compareListenerImp = listener;
0201 
0202             if (exec->hadException()) {
0203                 exec->clearException();
0204 
0205                 // failed to parse, so let's just make this listener a no-op
0206                 listener = nullptr;
0207             } else if (!listener->inherits(&DeclaredFunctionImp::info)) {
0208                 listener = nullptr;// Error creating function
0209             } else {
0210                 DeclaredFunctionImp *declFunc = static_cast<DeclaredFunctionImp *>(listener.get());
0211 
0212                 if (originalNode) {
0213                     // Add the event's home element to the scope
0214                     // (and the document, and the form - see KJS::HTMLElement::eventHandlerScope)
0215                     ScopeChain scope = declFunc->scope();
0216 
0217                     JSObject *thisObj = getDOMNode(exec, originalNode)->getObject();
0218 
0219                     if (thisObj) {
0220                         static_cast<DOMNode *>(thisObj)->pushEventHandlerScope(exec, scope);
0221                         declFunc->setScope(scope);
0222                     }
0223                 }
0224             }
0225         }
0226 
0227         // no more need to keep the unparsed code around
0228         code.clear();
0229 
0230         if (listener) {
0231             static_cast<Window *>(win.get())->jsEventListeners.insert(QPair<void *, bool>(compareListenerImp.get(), true),
0232                     (KJS::JSEventListener *)(this));
0233         }
0234 
0235         parsed = true;
0236     }
0237 }
0238 
0239 // -------------------------------------------------------------------------
0240 
0241 const ClassInfo DOMEvent::info = { "Event", nullptr, &DOMEventTable, nullptr };
0242 /*
0243 @begin DOMEventTable 7
0244   type      DOMEvent::Type      DontDelete|ReadOnly
0245   target    DOMEvent::Target    DontDelete|ReadOnly
0246   currentTarget DOMEvent::CurrentTarget DontDelete|ReadOnly
0247   srcElement    DOMEvent::SrcElement    DontDelete|ReadOnly
0248   eventPhase    DOMEvent::EventPhase    DontDelete|ReadOnly
0249   bubbles   DOMEvent::Bubbles   DontDelete|ReadOnly
0250   cancelable    DOMEvent::Cancelable    DontDelete|ReadOnly
0251   timeStamp DOMEvent::TimeStamp DontDelete|ReadOnly
0252   returnValue   DOMEvent::ReturnValue   DontDelete
0253   cancelBubble  DOMEvent::CancelBubble  DontDelete
0254 @end
0255 @begin DOMEventProtoTable 3
0256   stopPropagation   DOMEvent::StopPropagation   DontDelete|Function 0
0257   preventDefault    DOMEvent::PreventDefault    DontDelete|Function 0
0258   initEvent     DOMEvent::InitEvent     DontDelete|Function 3
0259 @end
0260 */
0261 KJS_DEFINE_PROTOTYPE(DOMEventProto)
0262 KJS_IMPLEMENT_PROTOFUNC(DOMEventProtoFunc)
0263 KJS_IMPLEMENT_PROTOTYPE("DOMEvent", DOMEventProto, DOMEventProtoFunc, ObjectPrototype)
0264 
0265 DOMEvent::DOMEvent(ExecState *exec, DOM::EventImpl *e)
0266     : m_impl(e)
0267 {
0268     setPrototype(DOMEventProto::self(exec));
0269 }
0270 
0271 DOMEvent::DOMEvent(JSObject *proto, DOM::EventImpl *e):
0272     m_impl(e)
0273 {
0274     setPrototype(proto);
0275 }
0276 
0277 DOMEvent::~DOMEvent()
0278 {
0279     ScriptInterpreter::forgetDOMObject(m_impl.get());
0280 }
0281 
0282 bool DOMEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0283 {
0284 #ifdef KJS_VERBOSE
0285     qCDebug(KHTML_LOG) << "KJS::DOMEvent::getOwnPropertySlot " << propertyName.qstring();
0286 #endif
0287 
0288     return getStaticValueSlot<DOMEvent, DOMObject>(exec, &DOMEventTable, this, propertyName, slot);
0289 }
0290 
0291 JSValue *DOMEvent::getValueProperty(ExecState *exec, int token) const
0292 {
0293     DOM::EventImpl &event = *impl();
0294     switch (token) {
0295     case Type:
0296         return jsString(event.type());
0297     case Target:
0298     case SrcElement: /*MSIE extension - "the object that fired the event"*/
0299         return getEventTarget(exec, event.target());
0300     case CurrentTarget:
0301         return getEventTarget(exec, event.currentTarget());
0302     case EventPhase:
0303         return jsNumber((unsigned int)event.eventPhase());
0304     case Bubbles:
0305         return jsBoolean(event.bubbles());
0306     case Cancelable:
0307         return jsBoolean(event.cancelable());
0308     case TimeStamp:
0309         return jsNumber((long unsigned int)event.timeStamp()); // ### long long ?
0310     case ReturnValue: // MSIE extension
0311         // return false == cancel, so this returns the -opposite- of defaultPrevented
0312         return jsBoolean(!event.defaultPrevented());
0313     case CancelBubble: // MSIE extension
0314         return jsBoolean(event.propagationStopped());
0315     default:
0316         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMEvent::getValueProperty : " << token;
0317         return nullptr;
0318     }
0319 }
0320 
0321 JSValue *DOMEvent::defaultValue(ExecState *exec, KJS::JSType hint) const
0322 {
0323     if (m_impl->id() == EventImpl::ERROR_EVENT && !m_impl->message().isNull()) {
0324         return jsString(m_impl->message());
0325     } else {
0326         return DOMObject::defaultValue(exec, hint);
0327     }
0328 }
0329 
0330 void DOMEvent::put(ExecState *exec, const Identifier &propertyName,
0331                    JSValue *value, int attr)
0332 {
0333     lookupPut<DOMEvent, DOMObject>(exec, propertyName, value, attr,
0334                                    &DOMEventTable, this);
0335 }
0336 
0337 void DOMEvent::putValueProperty(ExecState *exec, int token, JSValue *value, int)
0338 {
0339     switch (token) {
0340     case ReturnValue: // MSIE equivalent for "preventDefault" (but with a way to reset it)
0341         // returnValue=false means "default action of the event on the source object is canceled",
0342         // which means preventDefault(true). Hence the '!'.
0343         m_impl->preventDefault(!value->toBoolean(exec));
0344         break;
0345     case CancelBubble: // MSIE equivalent for "stopPropagation" (but with a way to reset it)
0346         m_impl->stopPropagation(value->toBoolean(exec));
0347         break;
0348     default:
0349         break;
0350     }
0351 }
0352 
0353 JSValue *DOMEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0354 {
0355     KJS_CHECK_THIS(KJS::DOMEvent, thisObj);
0356     DOM::EventImpl &event = *static_cast<DOMEvent *>(thisObj)->impl();
0357     switch (id) {
0358     case DOMEvent::StopPropagation:
0359         event.stopPropagation(true);
0360         return jsUndefined();
0361     case DOMEvent::PreventDefault:
0362         event.preventDefault(true);
0363         return jsUndefined();
0364     case DOMEvent::InitEvent:
0365         event.initEvent(args[0]->toString(exec).domString(), args[1]->toBoolean(exec), args[2]->toBoolean(exec));
0366         return jsUndefined();
0367     };
0368     return jsUndefined();
0369 }
0370 
0371 JSValue *KJS::getDOMEvent(ExecState *exec, DOM::EventImpl *ei)
0372 {
0373     if (!ei) {
0374         return jsNull();
0375     }
0376     ScriptInterpreter *interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
0377     DOMObject *ret = interp->getDOMObject(ei);
0378     if (!ret) {
0379         if (ei->isTextInputEvent()) {
0380             ret = new DOMTextEvent(exec, static_cast<DOM::TextEventImpl *>(ei));
0381         } else if (ei->isKeyboardEvent()) {
0382             ret = new DOMKeyboardEvent(exec, static_cast<DOM::KeyboardEventImpl *>(ei));
0383         } else if (ei->isMouseEvent()) {
0384             ret = new DOMMouseEvent(exec, static_cast<DOM::MouseEventImpl *>(ei));
0385         } else if (ei->isUIEvent()) {
0386             ret = new DOMUIEvent(exec, static_cast<DOM::UIEventImpl *>(ei));
0387         } else if (ei->isMutationEvent()) {
0388             ret = new DOMMutationEvent(exec, static_cast<DOM::MutationEventImpl *>(ei));
0389         } else if (ei->isMessageEvent()) {
0390             ret = new DOMMessageEvent(exec, static_cast<DOM::MessageEventImpl *>(ei));
0391         } else if (ei->isHashChangeEvent()) {
0392             ret = new DOMHashChangeEvent(exec, static_cast<DOM::HashChangeEventImpl *>(ei));
0393         } else {
0394             ret = new DOMEvent(exec, ei);
0395         }
0396 
0397         interp->putDOMObject(ei, ret);
0398     }
0399 
0400     return ret;
0401 }
0402 
0403 DOM::EventImpl *KJS::toEvent(JSValue *val)
0404 {
0405     JSObject *obj = val->getObject();
0406     if (!obj || !obj->inherits(&DOMEvent::info)) {
0407         return nullptr;
0408     }
0409 
0410     const DOMEvent *dobj = static_cast<const DOMEvent *>(obj);
0411     return dobj->impl();
0412 }
0413 
0414 // -------------------------------------------------------------------------
0415 /*
0416 @begin EventConstantsTable 23
0417   CAPTURING_PHASE   DOM::Event::CAPTURING_PHASE DontDelete|ReadOnly
0418   AT_TARGET     DOM::Event::AT_TARGET       DontDelete|ReadOnly
0419   BUBBLING_PHASE    DOM::Event::BUBBLING_PHASE  DontDelete|ReadOnly
0420 # Reverse-engineered from Netscape
0421   MOUSEDOWN     1               DontDelete|ReadOnly
0422   MOUSEUP       2               DontDelete|ReadOnly
0423   MOUSEOVER     4               DontDelete|ReadOnly
0424   MOUSEOUT      8               DontDelete|ReadOnly
0425   MOUSEMOVE     16              DontDelete|ReadOnly
0426   MOUSEDRAG     32              DontDelete|ReadOnly
0427   CLICK         64              DontDelete|ReadOnly
0428   DBLCLICK      128             DontDelete|ReadOnly
0429   KEYDOWN       256             DontDelete|ReadOnly
0430   KEYUP         512             DontDelete|ReadOnly
0431   KEYPRESS      1024                DontDelete|ReadOnly
0432   DRAGDROP      2048                DontDelete|ReadOnly
0433   FOCUS         4096                DontDelete|ReadOnly
0434   BLUR          8192                DontDelete|ReadOnly
0435   SELECT        16384               DontDelete|ReadOnly
0436   CHANGE        32768               DontDelete|ReadOnly
0437 @end
0438 */
0439 DEFINE_CONSTANT_TABLE(EventConstants)
0440 IMPLEMENT_CONSTANT_TABLE(EventConstants, "EventConstants")
0441 
0442 IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(EventConstructor, "EventConstructor", DOMEventProto, EventConstants)
0443 // -------------------------------------------------------------------------
0444 
0445 const ClassInfo EventExceptionConstructor::info = { "EventExceptionConstructor", nullptr, &EventExceptionConstructorTable, nullptr };
0446 /*
0447 @begin EventExceptionConstructorTable 1
0448   UNSPECIFIED_EVENT_TYPE_ERR    DOM::EventException::UNSPECIFIED_EVENT_TYPE_ERR DontDelete|ReadOnly
0449 @end
0450 */
0451 EventExceptionConstructor::EventExceptionConstructor(ExecState *exec)
0452     : DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype())
0453 {
0454 }
0455 
0456 bool EventExceptionConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0457 {
0458     return getStaticValueSlot<EventExceptionConstructor, DOMObject>(exec, &EventExceptionConstructorTable, this, propertyName, slot);
0459 }
0460 
0461 JSValue *EventExceptionConstructor::getValueProperty(ExecState *, int token) const
0462 {
0463     // We use the token as the value to return directly
0464     return jsNumber(token);
0465 }
0466 
0467 JSValue *KJS::getEventExceptionConstructor(ExecState *exec)
0468 {
0469     return cacheGlobalObject<EventExceptionConstructor>(exec, "[[eventException.constructor]]");
0470 }
0471 
0472 // -------------------------------------------------------------------------
0473 
0474 const ClassInfo DOMUIEvent::info = { "UIEvent", &DOMEvent::info, &DOMUIEventTable, nullptr };
0475 /*
0476 @begin DOMUIEventTable 7
0477   view      DOMUIEvent::View    DontDelete|ReadOnly
0478   detail    DOMUIEvent::Detail  DontDelete|ReadOnly
0479   keyCode   DOMUIEvent::KeyCode DontDelete|ReadOnly
0480   charCode  DOMUIEvent::CharCode    DontDelete|ReadOnly
0481   layerX    DOMUIEvent::LayerX  DontDelete|ReadOnly
0482   layerY    DOMUIEvent::LayerY  DontDelete|ReadOnly
0483   pageX     DOMUIEvent::PageX   DontDelete|ReadOnly
0484   pageY     DOMUIEvent::PageY   DontDelete|ReadOnly
0485   which     DOMUIEvent::Which   DontDelete|ReadOnly
0486 @end
0487 @begin DOMUIEventProtoTable 1
0488   initUIEvent   DOMUIEvent::InitUIEvent DontDelete|Function 5
0489 @end
0490 */
0491 KJS_DEFINE_PROTOTYPE(DOMUIEventProto)
0492 KJS_IMPLEMENT_PROTOFUNC(DOMUIEventProtoFunc)
0493 KJS_IMPLEMENT_PROTOTYPE("DOMUIEvent", DOMUIEventProto, DOMUIEventProtoFunc, DOMEventProto)
0494 
0495 DOMUIEvent::DOMUIEvent(ExecState *exec, DOM::UIEventImpl *ue) :
0496     DOMEvent(DOMUIEventProto::self(exec), ue) {}
0497 
0498 DOMUIEvent::DOMUIEvent(JSObject *proto, DOM::UIEventImpl *ue) :
0499     DOMEvent(proto, ue) {}
0500 
0501 DOMUIEvent::~DOMUIEvent()
0502 {
0503 }
0504 
0505 bool DOMUIEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0506 {
0507     return getStaticValueSlot<DOMUIEvent, DOMEvent>(exec, &DOMUIEventTable, this, propertyName, slot);
0508 }
0509 
0510 JSValue *DOMUIEvent::getValueProperty(ExecState *exec, int token) const
0511 {
0512     DOM::UIEventImpl &event = *impl();
0513     switch (token) {
0514     case View:
0515         return getDOMAbstractView(exec, event.view());
0516     case Detail:
0517         return jsNumber(event.detail());
0518     case KeyCode:
0519         // IE-compatibility
0520         return jsNumber(event.keyCode());
0521     case CharCode:
0522         // IE-compatibility
0523         return jsNumber(event.charCode());
0524     case LayerX:
0525         // NS-compatibility
0526         return jsNumber(event.layerX());
0527     case LayerY:
0528         // NS-compatibility
0529         return jsNumber(event.layerY());
0530     case PageX:
0531         // NS-compatibility
0532         return jsNumber(event.pageX());
0533     case PageY:
0534         // NS-compatibility
0535         return jsNumber(event.pageY());
0536     case Which:
0537         // NS-compatibility
0538         return jsNumber(event.which());
0539     default:
0540         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMUIEvent::getValueProperty : " << token;
0541         return jsUndefined();
0542     }
0543 }
0544 
0545 JSValue *DOMUIEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0546 {
0547     KJS_CHECK_THIS(KJS::DOMUIEvent, thisObj);
0548     DOM::UIEventImpl &uiEvent = *static_cast<DOMUIEvent *>(thisObj)->impl();
0549     switch (id) {
0550     case DOMUIEvent::InitUIEvent: {
0551         DOM::AbstractViewImpl *v = toAbstractView(args[3]);
0552         uiEvent.initUIEvent(args[0]->toString(exec).domString(),
0553                             args[1]->toBoolean(exec),
0554                             args[2]->toBoolean(exec),
0555                             v,
0556                             args[4]->toInteger(exec));
0557     }
0558     return jsUndefined();
0559     }
0560     return jsUndefined();
0561 }
0562 
0563 // -------------------------------------------------------------------------
0564 
0565 const ClassInfo DOMMouseEvent::info = { "MouseEvent", &DOMUIEvent::info, &DOMMouseEventTable, nullptr };
0566 
0567 /*
0568 @begin DOMMouseEventTable 2
0569   screenX   DOMMouseEvent::ScreenX  DontDelete|ReadOnly
0570   screenY   DOMMouseEvent::ScreenY  DontDelete|ReadOnly
0571   clientX   DOMMouseEvent::ClientX  DontDelete|ReadOnly
0572   x     DOMMouseEvent::X    DontDelete|ReadOnly
0573   clientY   DOMMouseEvent::ClientY  DontDelete|ReadOnly
0574   y     DOMMouseEvent::Y    DontDelete|ReadOnly
0575   offsetX   DOMMouseEvent::OffsetX  DontDelete|ReadOnly
0576   offsetY   DOMMouseEvent::OffsetY  DontDelete|ReadOnly
0577   ctrlKey   DOMMouseEvent::CtrlKey  DontDelete|ReadOnly
0578   shiftKey  DOMMouseEvent::ShiftKey DontDelete|ReadOnly
0579   altKey    DOMMouseEvent::AltKey   DontDelete|ReadOnly
0580   metaKey   DOMMouseEvent::MetaKey  DontDelete|ReadOnly
0581   button    DOMMouseEvent::Button   DontDelete|ReadOnly
0582   relatedTarget DOMMouseEvent::RelatedTarget DontDelete|ReadOnly
0583   fromElement   DOMMouseEvent::FromElement DontDelete|ReadOnly
0584   toElement DOMMouseEvent::ToElement    DontDelete|ReadOnly
0585 @end
0586 @begin DOMMouseEventProtoTable 1
0587   initMouseEvent    DOMMouseEvent::InitMouseEvent   DontDelete|Function 15
0588 @end
0589 */
0590 KJS_DEFINE_PROTOTYPE(DOMMouseEventProto)
0591 KJS_IMPLEMENT_PROTOFUNC(DOMMouseEventProtoFunc)
0592 KJS_IMPLEMENT_PROTOTYPE("DOMMouseEvent", DOMMouseEventProto, DOMMouseEventProtoFunc, DOMUIEventProto)
0593 
0594 DOMMouseEvent::DOMMouseEvent(ExecState *exec, DOM::MouseEventImpl *me) :
0595     DOMUIEvent(DOMMouseEventProto::self(exec), me) {}
0596 
0597 DOMMouseEvent::~DOMMouseEvent()
0598 {
0599 }
0600 
0601 bool DOMMouseEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0602 {
0603 #ifdef KJS_VERBOSE
0604     qCDebug(KHTML_LOG) << "DOMMouseEvent::getOwnPropertySlot " << propertyName.qstring();
0605 #endif
0606 
0607     return getStaticValueSlot<DOMMouseEvent, DOMUIEvent>(exec, &DOMMouseEventTable, this, propertyName, slot);
0608 }
0609 
0610 JSValue *DOMMouseEvent::getValueProperty(ExecState *exec, int token) const
0611 {
0612     DOM::MouseEventImpl &event = *impl();
0613     switch (token) {
0614     case ScreenX:
0615         return jsNumber(event.screenX());
0616     case ScreenY:
0617         return jsNumber(event.screenY());
0618     case ClientX:
0619     case X:
0620         return jsNumber(event.clientX());
0621     case ClientY:
0622     case Y:
0623         return jsNumber(event.clientY());
0624     case OffsetX:
0625     case OffsetY: { // MSIE extension
0626         if (event.target()->eventTargetType() != EventTargetImpl::DOM_NODE) {
0627             return jsUndefined();
0628         }
0629 
0630         DOM::Node node = static_cast<NodeImpl *>(event.target());
0631         khtml::RenderObject *rend = nullptr;
0632         if (node.handle()) {
0633             node.handle()->document()->updateRendering();
0634             rend = node.handle()->renderer();
0635         }
0636         int x = event.clientX();
0637         int y = event.clientY();
0638         if (rend) {
0639             int xPos, yPos;
0640             if (rend->absolutePosition(xPos, yPos)) {
0641                 //qCDebug(KHTML_LOG) << "DOMMouseEvent::getValueProperty rend=" << rend << "  xPos=" << xPos << "  yPos=" << yPos;
0642                 x -= xPos;
0643                 y -= yPos;
0644             }
0645             if (rend->canvas()) {
0646                 int cYPos, cXPos;
0647                 rend->canvas()->absolutePosition(cXPos,  cYPos,  true);
0648                 x += cXPos;
0649                 y += cYPos;
0650             }
0651         }
0652         return jsNumber(token == OffsetX ? x : y);
0653     }
0654     case CtrlKey:
0655         return jsBoolean(event.ctrlKey());
0656     case ShiftKey:
0657         return jsBoolean(event.shiftKey());
0658     case AltKey:
0659         return jsBoolean(event.altKey());
0660     case MetaKey:
0661         return jsBoolean(event.metaKey());
0662     case Button: {
0663         if (exec->dynamicInterpreter()->compatMode() == Interpreter::IECompat) {
0664             // Tricky. The DOM (and khtml) use 0 for LMB, 1 for MMB and 2 for RMB
0665             // but MSIE uses 1=LMB, 2=RMB, 4=MMB, as a bitfield
0666             int domButton = event.button();
0667             int button = domButton == 0 ? 1 : domButton == 1 ? 4 : domButton == 2 ? 2 : 0;
0668             return jsNumber((unsigned int)button);
0669         }
0670         return jsNumber(event.button());
0671     }
0672     case ToElement:
0673         // MSIE extension - "the object toward which the user is moving the mouse pointer"
0674         if (event.id() == DOM::EventImpl::MOUSEOUT_EVENT) {
0675             return getEventTarget(exec, event.relatedTarget());
0676         }
0677         return getEventTarget(exec, event.target());
0678     case FromElement:
0679         // MSIE extension - "object from which activation
0680         // or the mouse pointer is exiting during the event" (huh?)
0681         if (event.id() == DOM::EventImpl::MOUSEOUT_EVENT) {
0682             return getEventTarget(exec, event.target());
0683         }
0684     /* fall through */
0685     case RelatedTarget:
0686         return getEventTarget(exec, event.relatedTarget());
0687     default:
0688         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMMouseEvent::getValueProperty : " << token;
0689         return nullptr;
0690     }
0691 }
0692 
0693 JSValue *DOMMouseEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0694 {
0695     KJS_CHECK_THIS(KJS::DOMMouseEvent, thisObj);
0696     DOM::MouseEventImpl &mouseEvent = *static_cast<DOMMouseEvent *>(thisObj)->impl();
0697     switch (id) {
0698     case DOMMouseEvent::InitMouseEvent:
0699         mouseEvent.initMouseEvent(args[0]->toString(exec).domString(), // typeArg
0700                                   args[1]->toBoolean(exec), // canBubbleArg
0701                                   args[2]->toBoolean(exec), // cancelableArg
0702                                   toAbstractView(args[3]), // viewArg
0703                                   args[4]->toInteger(exec), // detailArg
0704                                   args[5]->toInteger(exec), // screenXArg
0705                                   args[6]->toInteger(exec), // screenYArg
0706                                   args[7]->toInteger(exec), // clientXArg
0707                                   args[8]->toInteger(exec), // clientYArg
0708                                   args[9]->toBoolean(exec), // ctrlKeyArg
0709                                   args[10]->toBoolean(exec), // altKeyArg
0710                                   args[11]->toBoolean(exec), // shiftKeyArg
0711                                   args[12]->toBoolean(exec), // metaKeyArg
0712                                   args[13]->toInteger(exec), // buttonArg
0713                                   toNode(args[14])); // relatedTargetArg
0714         return jsUndefined();
0715     }
0716     return jsUndefined();
0717 }
0718 
0719 // -------------------------------------------------------------------------
0720 
0721 const ClassInfo DOMKeyEventBase::info = { "KeyEventBase", &DOMUIEvent::info, &DOMKeyEventBaseTable, nullptr };
0722 
0723 /*
0724 @begin DOMKeyEventBaseTable 5
0725   keyVal     DOMKeyEventBase::Key         DontDelete|ReadOnly
0726   virtKeyVal     DOMKeyEventBase::VirtKey     DontDelete|ReadOnly
0727   ctrlKey        DOMKeyEventBase::CtrlKey     DontDelete|ReadOnly
0728   altKey         DOMKeyEventBase::AltKey      DontDelete|ReadOnly
0729   shiftKey       DOMKeyEventBase::ShiftKey    DontDelete|ReadOnly
0730   metaKey        DOMKeyEventBase::MetaKey     DontDelete|ReadOnly
0731 @end
0732 */
0733 
0734 DOMKeyEventBase::DOMKeyEventBase(JSObject *proto, DOM::KeyEventBaseImpl *ke) :
0735     DOMUIEvent(proto, ke) {}
0736 
0737 DOMKeyEventBase::~DOMKeyEventBase()
0738 {}
0739 
0740 bool DOMKeyEventBase::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0741 {
0742 #ifdef KJS_VERBOSE
0743     qCDebug(KHTML_LOG) << "DOMKeyEventBase::getOwnPropertySlot " << propertyName.qstring();
0744 #endif
0745     return getStaticValueSlot<DOMKeyEventBase, DOMUIEvent>(exec, &DOMKeyEventBaseTable, this, propertyName, slot);
0746 }
0747 
0748 JSValue *DOMKeyEventBase::getValueProperty(ExecState *, int token) const
0749 {
0750     DOM::KeyEventBaseImpl *tevent = impl();
0751     switch (token) {
0752     case Key:
0753         return jsNumber(tevent->keyVal());
0754     case VirtKey:
0755         return jsNumber(tevent->virtKeyVal());
0756     // these modifier attributes actually belong into a KeyboardEvent interface,
0757     // but we want them on "keypress" as well.
0758     case CtrlKey:
0759         return jsBoolean(tevent->ctrlKey());
0760     case ShiftKey:
0761         return jsBoolean(tevent->shiftKey());
0762     case AltKey:
0763         return jsBoolean(tevent->altKey());
0764     case MetaKey:
0765         return jsBoolean(tevent->metaKey());
0766     default:
0767         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMKeyEventBase::getValueProperty : " << token;
0768         return jsUndefined();
0769     }
0770 }
0771 
0772 // -------------------------------------------------------------------------
0773 const ClassInfo DOMTextEvent::info = { "TextEvent", &DOMKeyEventBase::info, &DOMTextEventTable, nullptr };
0774 
0775 /*
0776 @begin DOMTextEventTable 1
0777   data           DOMTextEvent::Data          DontDelete|ReadOnly
0778 @end
0779 @begin DOMTextEventProtoTable 1
0780   initTextEvent DOMTextEvent::InitTextEvent DontDelete|Function 5
0781   # Missing: initTextEventNS
0782 @end
0783 */
0784 KJS_DEFINE_PROTOTYPE(DOMTextEventProto)
0785 KJS_IMPLEMENT_PROTOFUNC(DOMTextEventProtoFunc)
0786 KJS_IMPLEMENT_PROTOTYPE("DOMTextEvent", DOMTextEventProto, DOMTextEventProtoFunc, DOMUIEventProto) //Note: no proto in KeyBase
0787 
0788 DOMTextEvent::DOMTextEvent(ExecState *exec, DOM::TextEventImpl *ke) :
0789     DOMKeyEventBase(DOMTextEventProto::self(exec), ke) {}
0790 
0791 DOMTextEvent::~DOMTextEvent()
0792 {
0793 }
0794 
0795 bool DOMTextEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0796 {
0797 #ifdef KJS_VERBOSE
0798     qCDebug(KHTML_LOG) << "DOMTextEvent::getOwnPropertySlot " << propertyName.qstring();
0799 #endif
0800     return getStaticValueSlot<DOMTextEvent, DOMKeyEventBase>(exec, &DOMTextEventTable, this, propertyName, slot);
0801 }
0802 
0803 JSValue *DOMTextEvent::getValueProperty(ExecState *, int token) const
0804 {
0805     DOM::TextEventImpl &tevent = *impl();
0806     switch (token) {
0807     case Data:
0808         return jsString(tevent.data());
0809     default:
0810         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token;
0811         return jsUndefined();
0812     }
0813 }
0814 
0815 JSValue *DOMTextEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0816 {
0817     KJS_CHECK_THIS(KJS::DOMTextEvent, thisObj);
0818     DOM::TextEventImpl &keyEvent = *static_cast<DOMTextEvent *>(thisObj)->impl();
0819     switch (id) {
0820     case DOMTextEvent::InitTextEvent:
0821 
0822         keyEvent.initTextEvent(args[0]->toString(exec).domString(), // typeArg
0823                                args[1]->toBoolean(exec), // canBubbleArg
0824                                args[2]->toBoolean(exec), // cancelableArg
0825                                toAbstractView(args[3]), // viewArg
0826                                args[4]->toString(exec).domString()); // dataArg
0827         return jsUndefined();
0828     }
0829     return jsUndefined();
0830 }
0831 // -------------------------------------------------------------------------
0832 const ClassInfo DOMKeyboardEvent::info = { "KeyboardEvent", &DOMKeyEventBase::info, &DOMKeyboardEventTable, nullptr };
0833 
0834 /*
0835 @begin DOMKeyboardEventTable 2
0836   keyIdentifier  DOMKeyboardEvent::KeyIdentifier  DontDelete|ReadOnly
0837   keyLocation    DOMKeyboardEvent::KeyLocation    DontDelete|ReadOnly
0838 @end
0839 @begin DOMKeyboardEventProtoTable 2
0840   initKeyboardEvent DOMKeyboardEvent::InitKeyboardEvent DontDelete|Function 7
0841   getModifierState      DOMKeyboardEvent::GetModifierState      DontDelete|Function 1
0842 @end
0843 */
0844 KJS_DEFINE_PROTOTYPE(DOMKeyboardEventProto)
0845 KJS_IMPLEMENT_PROTOFUNC(DOMKeyboardEventProtoFunc)
0846 KJS_IMPLEMENT_PROTOTYPE("DOMKeyboardEvent", DOMKeyboardEventProto, DOMKeyboardEventProtoFunc, DOMUIEventProto) //Note: no proto in KeyBase
0847 
0848 DOMKeyboardEvent::DOMKeyboardEvent(ExecState *exec, DOM::KeyboardEventImpl *ke) :
0849     DOMKeyEventBase(DOMKeyboardEventProto::self(exec), ke) {}
0850 
0851 DOMKeyboardEvent::~DOMKeyboardEvent()
0852 {
0853 }
0854 
0855 bool DOMKeyboardEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0856 {
0857 #ifdef KJS_VERBOSE
0858     qCDebug(KHTML_LOG) << "DOMKeyboardEvent::getOwnPropertySlot " << propertyName.qstring();
0859 #endif
0860     return getStaticValueSlot<DOMKeyboardEvent, DOMKeyEventBase>(exec, &DOMKeyboardEventTable, this, propertyName, slot);
0861 }
0862 
0863 JSValue *DOMKeyboardEvent::getValueProperty(ExecState *, int token) const
0864 {
0865     DOM::KeyboardEventImpl *tevent = impl();
0866     switch (token) {
0867     case KeyIdentifier:
0868         return jsString(tevent->keyIdentifier());
0869     case KeyLocation:
0870         return jsNumber(tevent->keyLocation());
0871     default:
0872         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMKeyboardEvent::getValueProperty : " << token;
0873         return jsUndefined();
0874     }
0875 }
0876 
0877 JSValue *DOMKeyboardEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0878 {
0879     KJS_CHECK_THIS(KJS::DOMKeyboardEvent, thisObj);
0880     DOM::KeyboardEventImpl *keyEvent = static_cast<DOMKeyboardEvent *>(thisObj)->impl();
0881     switch (id) {
0882     case DOMKeyboardEvent::InitKeyboardEvent:
0883         keyEvent->initKeyboardEvent(args[0]->toString(exec).domString(), // typeArg
0884                                     args[1]->toBoolean(exec), // canBubbleArg
0885                                     args[2]->toBoolean(exec), // cancelableArg
0886                                     toAbstractView(args[3]), // viewArg
0887                                     args[4]->toString(exec).domString(), // keyIdentifierArg
0888                                     args[5]->toInteger(exec),         // keyLocationArg
0889                                     args[6]->toString(exec).domString()); //modifiersList
0890         break;
0891     case DOMKeyboardEvent::GetModifierState:
0892         return jsBoolean(keyEvent->getModifierState(args[0]->toString(exec).domString()));
0893     }
0894     return jsUndefined();
0895 }
0896 
0897 // -------------------------------------------------------------------------
0898 const ClassInfo KeyboardEventConstructor::info = { "KeyboardEventConstructor", nullptr, &KeyboardEventConstructorTable, nullptr };
0899 /*
0900 @begin KeyboardEventConstructorTable 4
0901   DOM_KEY_LOCATION_STANDARD  DOM::KeyboardEvent::DOM_KEY_LOCATION_STANDARD DontDelete|ReadOnly
0902   DOM_KEY_LOCATION_LEFT      DOM::KeyboardEvent::DOM_KEY_LOCATION_LEFT     DontDelete|ReadOnly
0903   DOM_KEY_LOCATION_RIGHT     DOM::KeyboardEvent::DOM_KEY_LOCATION_RIGHT    DontDelete|ReadOnly
0904   DOM_KEY_LOCATION_NUMPAD    DOM::KeyboardEvent::DOM_KEY_LOCATION_NUMPAD   DontDelete|ReadOnly
0905 @end
0906 */
0907 KeyboardEventConstructor::KeyboardEventConstructor(ExecState *exec)
0908     : DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype())
0909 {}
0910 
0911 bool KeyboardEventConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0912 {
0913 #ifdef KJS_VERBOSE
0914     qCDebug(KHTML_LOG) << "DOMKeyboardEvent::getOwnPropertySlot " << propertyName.qstring();
0915 #endif
0916     return getStaticValueSlot<KeyboardEventConstructor, DOMObject>(exec, &KeyboardEventConstructorTable, this, propertyName, slot);
0917 }
0918 
0919 JSValue *KeyboardEventConstructor::getValueProperty(ExecState *, int token) const
0920 {
0921     // We use the token as the value to return directly
0922     return jsNumber(token);
0923 }
0924 
0925 JSValue *KJS::getKeyboardEventConstructor(ExecState *exec)
0926 {
0927     return cacheGlobalObject<KeyboardEventConstructor>(exec, "[[keyboardEvent.constructor]]");
0928 }
0929 
0930 // -------------------------------------------------------------------------
0931 const ClassInfo MutationEventConstructor::info = { "MutationEventConstructor", nullptr, &MutationEventConstructorTable, nullptr };
0932 /*
0933 @begin MutationEventConstructorTable 3
0934   MODIFICATION  DOM::MutationEvent::MODIFICATION    DontDelete|ReadOnly
0935   ADDITION  DOM::MutationEvent::ADDITION        DontDelete|ReadOnly
0936   REMOVAL   DOM::MutationEvent::REMOVAL     DontDelete|ReadOnly
0937 @end
0938 */
0939 MutationEventConstructor::MutationEventConstructor(ExecState *exec)
0940     : DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype())
0941 {
0942 }
0943 
0944 bool MutationEventConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0945 {
0946     return getStaticValueSlot<MutationEventConstructor, DOMObject>(exec, &MutationEventConstructorTable, this, propertyName, slot);
0947 }
0948 
0949 JSValue *MutationEventConstructor::getValueProperty(ExecState *, int token) const
0950 {
0951     // We use the token as the value to return directly
0952     return jsNumber(token);
0953 }
0954 
0955 JSValue *KJS::getMutationEventConstructor(ExecState *exec)
0956 {
0957     return cacheGlobalObject<MutationEventConstructor>(exec, "[[mutationEvent.constructor]]");
0958 }
0959 
0960 // -------------------------------------------------------------------------
0961 
0962 const ClassInfo DOMMutationEvent::info = { "MutationEvent", &DOMEvent::info, &DOMMutationEventTable, nullptr };
0963 /*
0964 @begin DOMMutationEventTable 5
0965   relatedNode   DOMMutationEvent::RelatedNode   DontDelete|ReadOnly
0966   prevValue DOMMutationEvent::PrevValue DontDelete|ReadOnly
0967   newValue  DOMMutationEvent::NewValue  DontDelete|ReadOnly
0968   attrName  DOMMutationEvent::AttrName  DontDelete|ReadOnly
0969   attrChange    DOMMutationEvent::AttrChange    DontDelete|ReadOnly
0970 @end
0971 @begin DOMMutationEventProtoTable 1
0972   initMutationEvent DOMMutationEvent::InitMutationEvent DontDelete|Function 8
0973 @end
0974 */
0975 KJS_DEFINE_PROTOTYPE(DOMMutationEventProto)
0976 KJS_IMPLEMENT_PROTOFUNC(DOMMutationEventProtoFunc)
0977 KJS_IMPLEMENT_PROTOTYPE("DOMMutationEvent", DOMMutationEventProto, DOMMutationEventProtoFunc, DOMEventProto)
0978 
0979 DOMMutationEvent::DOMMutationEvent(ExecState *exec, DOM::MutationEventImpl *me) :
0980     DOMEvent(DOMMutationEventProto::self(exec), me) {}
0981 
0982 DOMMutationEvent::~DOMMutationEvent()
0983 {
0984 }
0985 
0986 bool DOMMutationEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
0987 {
0988     return getStaticValueSlot<DOMMutationEvent, DOMEvent>(exec, &DOMMutationEventTable, this, propertyName, slot);
0989 }
0990 
0991 JSValue *DOMMutationEvent::getValueProperty(ExecState *exec, int token) const
0992 {
0993     DOM::MutationEventImpl &event = *impl();
0994     switch (token) {
0995     case RelatedNode: {
0996         DOM::Node relatedNode = event.relatedNode();
0997         return getDOMNode(exec, relatedNode.handle());
0998     }
0999     case PrevValue:
1000         return jsString(event.prevValue());
1001     case NewValue:
1002         return jsString(event.newValue());
1003     case AttrName:
1004         return jsString(event.attrName());
1005     case AttrChange:
1006         return jsNumber((unsigned int)event.attrChange());
1007     default:
1008         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMMutationEvent::getValueProperty : " << token;
1009         return nullptr;
1010     }
1011 }
1012 
1013 JSValue *DOMMutationEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
1014 {
1015     KJS_CHECK_THIS(KJS::DOMMutationEvent, thisObj);
1016     DOM::MutationEventImpl &mutationEvent = *static_cast<DOMMutationEvent *>(thisObj)->impl();
1017     switch (id) {
1018     case DOMMutationEvent::InitMutationEvent:
1019         mutationEvent.initMutationEvent(args[0]->toString(exec).domString(), // typeArg,
1020                                         args[1]->toBoolean(exec), // canBubbleArg
1021                                         args[2]->toBoolean(exec), // cancelableArg
1022                                         toNode(args[3]), // relatedNodeArg
1023                                         args[4]->toString(exec).domString(), // prevValueArg
1024                                         args[5]->toString(exec).domString(), // newValueArg
1025                                         args[6]->toString(exec).domString(), // attrNameArg
1026                                         args[7]->toInteger(exec)); // attrChangeArg
1027         return jsUndefined();
1028     }
1029     return jsUndefined();
1030 }
1031 // -------------------------------------------------------------------------
1032 
1033 const ClassInfo DOMMessageEvent::info = { "MessageEvent", &DOMEvent::info, &DOMMessageEventTable, nullptr };
1034 /*
1035 @begin DOMMessageEventTable 5
1036   data     DOMMessageEvent::Data     DontDelete|ReadOnly
1037   origin   DOMMessageEvent::Origin   DontDelete|ReadOnly
1038   source   DOMMessageEvent::Source   DontDelete|ReadOnly
1039   lastEventId  DOMMessageEvent::LastEventId   DontDelete|ReadOnly
1040 @end
1041 @begin DOMMessageEventProtoTable 1
1042   initMessageEvent     DOMMessageEvent::InitMessageEvent     DontDelete|Function 7
1043 @end
1044 */
1045 KJS_DEFINE_PROTOTYPE(DOMMessageEventProto)
1046 KJS_IMPLEMENT_PROTOFUNC(DOMMessageEventProtoFunc)
1047 KJS_IMPLEMENT_PROTOTYPE("DOMMessageEvent", DOMMessageEventProto, DOMMessageEventProtoFunc, DOMEventProto)
1048 IMPLEMENT_PSEUDO_CONSTRUCTOR(MessageEventPseudoCtor, "DOMMessageEvent", DOMMessageEventProto)
1049 
1050 DOMMessageEvent::DOMMessageEvent(ExecState *exec, DOM::MessageEventImpl *me) :
1051     DOMEvent(DOMMessageEventProto::self(exec), me) {}
1052 
1053 bool DOMMessageEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1054 {
1055     return getStaticValueSlot<DOMMessageEvent, DOMEvent>(exec, &DOMMessageEventTable, this, propertyName, slot);
1056 }
1057 
1058 JSValue *DOMMessageEvent::getValueProperty(ExecState *exec, int token) const
1059 {
1060     DOM::MessageEventImpl &event = *impl();
1061     switch (token) {
1062     case Data:
1063         return getMessageEventData(exec, event.data().get());
1064     case Origin:
1065         return jsString(event.origin());
1066     case LastEventId:
1067         return jsString(event.lastEventId());
1068     case Source:
1069         if (KHTMLPart *p = event.source()) {
1070             return Window::retrieve(p);
1071         } else {
1072             return jsNull();
1073         }
1074     default:
1075         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMMessageEvent::getValueProperty : " << token;
1076         return nullptr;
1077     }
1078 }
1079 
1080 JSValue *DOMMessageEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
1081 {
1082     KJS_CHECK_THIS(KJS::DOMMessageEvent, thisObj);
1083     DOM::MessageEventImpl &messageEvent = *static_cast<DOMMessageEvent *>(thisObj)->impl();
1084     switch (id) {
1085     case DOMMessageEvent::InitMessageEvent: {
1086         JSObject *sourceObj = args[3]->getObject();
1087 
1088         Window *sourceWin = nullptr;
1089         if (sourceObj && sourceObj->inherits(&Window::info)) {
1090             sourceWin = static_cast<Window *>(sourceObj);
1091         }
1092 
1093         KHTMLPart *part = nullptr;
1094         if (sourceWin) {
1095             part = qobject_cast<KHTMLPart *>(sourceWin->part());
1096         }
1097 
1098         if (!part) {
1099             setDOMException(exec, DOM::DOMException::TYPE_MISMATCH_ERR);
1100             return jsUndefined();
1101         }
1102 
1103         messageEvent.initMessageEvent(args[0]->toString(exec).domString(), // typeArg,
1104                                       args[1]->toBoolean(exec), // canBubbleArg
1105                                       args[2]->toBoolean(exec), // cancelableArg
1106                                       encapsulateMessageEventData(
1107                                           exec, exec->dynamicInterpreter(), args[3]), // dataArg
1108                                       args[4]->toString(exec).domString(), // originArg
1109                                       args[5]->toString(exec).domString(), // lastEventIdArg
1110                                       part); // sourceArg
1111         return jsUndefined();
1112     }
1113     }
1114     return jsUndefined();
1115 }
1116 
1117 // -------------------------------------------------------------------------
1118 
1119 const ClassInfo DOMHashChangeEvent::info = { "HashChangeEvent", &DOMEvent::info, &DOMHashChangeEventTable, nullptr };
1120 /*
1121 @begin DOMHashChangeEventTable 2
1122   oldURL   DOMHashChangeEvent::OldUrl DontDelete|ReadOnly
1123   newURL   DOMHashChangeEvent::NewUrl DontDelete|ReadOnly
1124 @end
1125 @begin DOMHashChangeEventProtoTable 1
1126   initHashChangeEvent     DOMHashChangeEvent::InitHashChangeEvent     DontDelete|Function 5
1127 @end
1128 */
1129 KJS_DEFINE_PROTOTYPE(DOMHashChangeEventProto)
1130 KJS_IMPLEMENT_PROTOFUNC(DOMHashChangeEventProtoFunc)
1131 KJS_IMPLEMENT_PROTOTYPE("DOMHashChangeEvent", DOMHashChangeEventProto, DOMHashChangeEventProtoFunc, DOMEventProto)
1132 IMPLEMENT_PSEUDO_CONSTRUCTOR(HashChangeEventPseudoCtor, "DOMHashChangeEvent", DOMHashChangeEventProto)
1133 
1134 DOMHashChangeEvent::DOMHashChangeEvent(ExecState *exec, HashChangeEventImpl *me) :
1135     DOMEvent(DOMHashChangeEventProto::self(exec), me)
1136 {}
1137 
1138 bool DOMHashChangeEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1139 {
1140     return getStaticValueSlot<DOMHashChangeEvent, DOMEvent>(exec, &DOMHashChangeEventTable, this, propertyName, slot);
1141 }
1142 
1143 JSValue *DOMHashChangeEvent::getValueProperty(ExecState * /*exec*/, int token) const
1144 {
1145     DOM::HashChangeEventImpl &event = *impl();
1146     switch (token) {
1147     case NewUrl:
1148         return jsString(event.newUrl());
1149     case OldUrl:
1150         return jsString(event.oldUrl());
1151     default:
1152         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMHashChangeEvent::getValueProperty : " << token;
1153         return jsUndefined();
1154     }
1155 }
1156 
1157 JSValue *DOMHashChangeEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
1158 {
1159     KJS_CHECK_THIS(KJS::DOMHashChangeEvent, thisObj);
1160     DOM::HashChangeEventImpl &hashChangeEvent = *static_cast<DOMHashChangeEvent *>(thisObj)->impl();
1161     switch (id) {
1162     case DOMHashChangeEvent::InitHashChangeEvent: {
1163         hashChangeEvent.initHashChangeEvent(args[0]->toString(exec).domString(), // typeArg,
1164                                             args[1]->toBoolean(exec), // canBubbleArg
1165                                             args[2]->toBoolean(exec), // cancelableArg
1166                                             args[3]->toString(exec).domString(), // oldURL
1167                                             args[4]->toString(exec).domString()); // newURL
1168         return jsUndefined();
1169     }
1170     }
1171     return jsUndefined();
1172 }