1 /*
2  *  This file is part of the KDE libraries
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003 Apple Computer, Inc.
5  *  Copyright (C) 2006, 2009, 2010 Maksim Orlovich (maksim@kde.org)
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include "kjs_events.h"
23 #include "kjs_events.lut.h"
24 
25 #include "kjs_data.h"
26 #include "kjs_window.h"
27 #include "kjs_views.h"
28 #include "kjs_proxy.h"
29 #include <xml/dom_nodeimpl.h>
30 #include <xml/dom_docimpl.h>
31 #include <xml/dom2_eventsimpl.h>
32 #include <rendering/render_object.h>
33 #include <rendering/render_canvas.h>
34 #include <khtml_part.h>
35 #ifdef KJS_DEBUGGER
36 #include "debugger/debugwindow.h"
37 #endif
38 #include "khtml_debug.h"
39 #include <kjs/scriptfunction.h>
40 #include <kjs/function_object.h>
41 
42 using namespace KJS;
43 using namespace KJSDebugger;
44 using namespace DOM;
45 
46 // -------------------------------------------------------------------------
47 
JSEventListener(JSObject * _listener,JSObject * _compareListenerImp,JSObject * _win,bool _html)48 JSEventListener::JSEventListener(JSObject *_listener, JSObject *_compareListenerImp, JSObject *_win, bool _html)
49     : listener(_listener), compareListenerImp(_compareListenerImp), html(_html), win(_win)
50 {
51     //fprintf(stderr,"JSEventListener::JSEventListener this=%p listener=%p\n",this,listener.imp());
52     if (compareListenerImp) {
53         static_cast<Window *>(win.get())->jsEventListeners.insert(QPair<void *, bool>(compareListenerImp.get(), html), this);
54     }
55 }
56 
~JSEventListener()57 JSEventListener::~JSEventListener()
58 {
59     if (compareListenerImp) {
60         static_cast<Window *>(win.get())->jsEventListeners.remove(QPair<void *, bool>(compareListenerImp.get(), html));
61     }
62     //fprintf(stderr,"JSEventListener::~JSEventListener this=%p listener=%p\n",this,listener.imp());
63 }
64 
handleEvent(DOM::Event & evt)65 void JSEventListener::handleEvent(DOM::Event &evt)
66 {
67     KHTMLPart *part = qobject_cast<KHTMLPart *>(static_cast<Window *>(win.get())->part());
68     KJSProxy *proxy = nullptr;
69     if (part) {
70         proxy = part->jScript();
71     }
72 
73     if (proxy && listener && listener->implementsCall()) {
74 #ifdef KJS_DEBUGGER
75         //### This is the wrong place to do this --- we need
76         // a more global/general stategy to prevent unwanted event loop recursion issues.
77         if (proxy->debugEnabled() && DebugWindow::window()->inSession()) {
78             return;
79         }
80 #endif
81         ref();
82 
83         KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
84         ExecState *exec = interpreter->globalExec();
85 
86         List args;
87         args.append(getDOMEvent(exec, evt.handle()));
88 
89         JSObject *thisObj = nullptr;
90         // Check whether handler is a function or an object with handleEvent method
91         if (listener == compareListenerImp) {
92             // Set "this" to the event's current target
93             thisObj = getEventTarget(exec, evt.handle()->currentTarget())->getObject();
94         } else {
95             thisObj = compareListenerImp;
96         }
97 
98         if (!thisObj) {
99             // ### can this still happen? eventTarget should be window on Window events now.
100             thisObj = win;
101         }
102 
103         Window *window = static_cast<Window *>(win.get());
104         // Set the event we're handling in the Window object
105         window->setCurrentEvent(evt.handle());
106         // ... and in the interpreter
107         interpreter->setCurrentEvent(&evt);
108 
109         interpreter->startCPUGuard();
110         JSValue *retval = listener->call(exec, thisObj, args);
111         interpreter->stopCPUGuard();
112 
113         window->setCurrentEvent(nullptr);
114         interpreter->setCurrentEvent(nullptr);
115         if (exec->hadException()) {
116             exec->clearException();
117         } else if (html) {
118             QVariant ret = ValueToVariant(exec, retval);
119             if (ret.type() == QVariant::Bool && ret.toBool() == false) {
120                 evt.preventDefault();
121             }
122         }
123         window->afterScriptExecution();
124         deref();
125     }
126 }
127 
eventListenerType()128 DOM::DOMString JSEventListener::eventListenerType()
129 {
130     if (html) {
131         return "_khtml_HTMLEventListener";
132     } else {
133         return "_khtml_JSEventListener";
134     }
135 }
136 
listenerObj() const137 JSObject *JSEventListener::listenerObj() const
138 {
139     return listener;
140 }
141 
JSLazyEventListener(const QString & _code,const QString & _url,int _lineNum,const QString & _name,JSObject * _win,DOM::NodeImpl * _originalNode,bool _svg)142 JSLazyEventListener::JSLazyEventListener(const QString &_code, const QString &_url, int _lineNum,
143         const QString &_name, JSObject *_win, DOM::NodeImpl *_originalNode, bool _svg)
144     : JSEventListener(nullptr, nullptr, _win, true), code(_code), url(_url), lineNum(_lineNum),
145       name(_name), parsed(false), svg(_svg)
146 {
147     // We don't retain the original node, because we assume it
148     // will stay alive as long as this handler object is around
149     // and we need to avoid a reference cycle. If JS transfers
150     // this handler to another node, parseCode will be called and
151     // then originalNode is no longer needed.
152 
153     originalNode = _originalNode;
154 }
155 
~JSLazyEventListener()156 JSLazyEventListener::~JSLazyEventListener()
157 {
158 }
159 
handleEvent(DOM::Event & evt)160 void JSLazyEventListener::handleEvent(DOM::Event &evt)
161 {
162     parseCode();
163     if (listener) {
164         JSEventListener::handleEvent(evt);
165     }
166 }
167 
listenerObj() const168 JSObject *JSLazyEventListener::listenerObj() const
169 {
170     parseCode();
171     return listener;
172 }
173 
parseCode() const174 void JSLazyEventListener::parseCode() const
175 {
176     if (!parsed) {
177         KHTMLPart *part = qobject_cast<KHTMLPart *>(static_cast<Window *>(win.get())->part());
178         KJSProxy *proxy = nullptr;
179         if (part) {
180             proxy = part->jScript();
181         }
182 
183         if (proxy) {
184             KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
185             ExecState *exec = interpreter->globalExec();
186 
187             //KJS::Constructor constr(KJS::Global::current().get("Function").imp());
188             KJS::FunctionObjectImp *constr = static_cast<KJS::FunctionObjectImp *>(interpreter->builtinFunction());
189             KJS::List args;
190 
191             if (svg) {
192                 args.append(jsString("evt"));
193             } else {
194                 args.append(jsString("event"));
195             }
196 
197             args.append(jsString(code));
198             listener = constr->construct(exec, args,
199                                          Identifier(UString(name)), url, lineNum); // ### is globalExec ok ?
200             compareListenerImp = listener;
201 
202             if (exec->hadException()) {
203                 exec->clearException();
204 
205                 // failed to parse, so let's just make this listener a no-op
206                 listener = nullptr;
207             } else if (!listener->inherits(&DeclaredFunctionImp::info)) {
208                 listener = nullptr;// Error creating function
209             } else {
210                 DeclaredFunctionImp *declFunc = static_cast<DeclaredFunctionImp *>(listener.get());
211 
212                 if (originalNode) {
213                     // Add the event's home element to the scope
214                     // (and the document, and the form - see KJS::HTMLElement::eventHandlerScope)
215                     ScopeChain scope = declFunc->scope();
216 
217                     JSObject *thisObj = getDOMNode(exec, originalNode)->getObject();
218 
219                     if (thisObj) {
220                         static_cast<DOMNode *>(thisObj)->pushEventHandlerScope(exec, scope);
221                         declFunc->setScope(scope);
222                     }
223                 }
224             }
225         }
226 
227         // no more need to keep the unparsed code around
228         code.clear();
229 
230         if (listener) {
231             static_cast<Window *>(win.get())->jsEventListeners.insert(QPair<void *, bool>(compareListenerImp.get(), true),
232                     (KJS::JSEventListener *)(this));
233         }
234 
235         parsed = true;
236     }
237 }
238 
239 // -------------------------------------------------------------------------
240 
241 const ClassInfo DOMEvent::info = { "Event", nullptr, &DOMEventTable, nullptr };
242 /*
243 @begin DOMEventTable 7
244   type      DOMEvent::Type      DontDelete|ReadOnly
245   target    DOMEvent::Target    DontDelete|ReadOnly
246   currentTarget DOMEvent::CurrentTarget DontDelete|ReadOnly
247   srcElement    DOMEvent::SrcElement    DontDelete|ReadOnly
248   eventPhase    DOMEvent::EventPhase    DontDelete|ReadOnly
249   bubbles   DOMEvent::Bubbles   DontDelete|ReadOnly
250   cancelable    DOMEvent::Cancelable    DontDelete|ReadOnly
251   timeStamp DOMEvent::TimeStamp DontDelete|ReadOnly
252   returnValue   DOMEvent::ReturnValue   DontDelete
253   cancelBubble  DOMEvent::CancelBubble  DontDelete
254 @end
255 @begin DOMEventProtoTable 3
256   stopPropagation   DOMEvent::StopPropagation   DontDelete|Function 0
257   preventDefault    DOMEvent::PreventDefault    DontDelete|Function 0
258   initEvent     DOMEvent::InitEvent     DontDelete|Function 3
259 @end
260 */
261 KJS_DEFINE_PROTOTYPE(DOMEventProto)
KJS_IMPLEMENT_PROTOFUNC(DOMEventProtoFunc)262 KJS_IMPLEMENT_PROTOFUNC(DOMEventProtoFunc)
263 KJS_IMPLEMENT_PROTOTYPE("DOMEvent", DOMEventProto, DOMEventProtoFunc, ObjectPrototype)
264 
265 DOMEvent::DOMEvent(ExecState *exec, DOM::EventImpl *e)
266     : m_impl(e)
267 {
268     setPrototype(DOMEventProto::self(exec));
269 }
270 
DOMEvent(JSObject * proto,DOM::EventImpl * e)271 DOMEvent::DOMEvent(JSObject *proto, DOM::EventImpl *e):
272     m_impl(e)
273 {
274     setPrototype(proto);
275 }
276 
~DOMEvent()277 DOMEvent::~DOMEvent()
278 {
279     ScriptInterpreter::forgetDOMObject(m_impl.get());
280 }
281 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)282 bool DOMEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
283 {
284 #ifdef KJS_VERBOSE
285     qCDebug(KHTML_LOG) << "KJS::DOMEvent::getOwnPropertySlot " << propertyName.qstring();
286 #endif
287 
288     return getStaticValueSlot<DOMEvent, DOMObject>(exec, &DOMEventTable, this, propertyName, slot);
289 }
290 
getValueProperty(ExecState * exec,int token) const291 JSValue *DOMEvent::getValueProperty(ExecState *exec, int token) const
292 {
293     DOM::EventImpl &event = *impl();
294     switch (token) {
295     case Type:
296         return jsString(event.type());
297     case Target:
298     case SrcElement: /*MSIE extension - "the object that fired the event"*/
299         return getEventTarget(exec, event.target());
300     case CurrentTarget:
301         return getEventTarget(exec, event.currentTarget());
302     case EventPhase:
303         return jsNumber((unsigned int)event.eventPhase());
304     case Bubbles:
305         return jsBoolean(event.bubbles());
306     case Cancelable:
307         return jsBoolean(event.cancelable());
308     case TimeStamp:
309         return jsNumber((long unsigned int)event.timeStamp()); // ### long long ?
310     case ReturnValue: // MSIE extension
311         // return false == cancel, so this returns the -opposite- of defaultPrevented
312         return jsBoolean(!event.defaultPrevented());
313     case CancelBubble: // MSIE extension
314         return jsBoolean(event.propagationStopped());
315     default:
316         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMEvent::getValueProperty : " << token;
317         return nullptr;
318     }
319 }
320 
defaultValue(ExecState * exec,KJS::JSType hint) const321 JSValue *DOMEvent::defaultValue(ExecState *exec, KJS::JSType hint) const
322 {
323     if (m_impl->id() == EventImpl::ERROR_EVENT && !m_impl->message().isNull()) {
324         return jsString(m_impl->message());
325     } else {
326         return DOMObject::defaultValue(exec, hint);
327     }
328 }
329 
put(ExecState * exec,const Identifier & propertyName,JSValue * value,int attr)330 void DOMEvent::put(ExecState *exec, const Identifier &propertyName,
331                    JSValue *value, int attr)
332 {
333     lookupPut<DOMEvent, DOMObject>(exec, propertyName, value, attr,
334                                    &DOMEventTable, this);
335 }
336 
putValueProperty(ExecState * exec,int token,JSValue * value,int)337 void DOMEvent::putValueProperty(ExecState *exec, int token, JSValue *value, int)
338 {
339     switch (token) {
340     case ReturnValue: // MSIE equivalent for "preventDefault" (but with a way to reset it)
341         // returnValue=false means "default action of the event on the source object is canceled",
342         // which means preventDefault(true). Hence the '!'.
343         m_impl->preventDefault(!value->toBoolean(exec));
344         break;
345     case CancelBubble: // MSIE equivalent for "stopPropagation" (but with a way to reset it)
346         m_impl->stopPropagation(value->toBoolean(exec));
347         break;
348     default:
349         break;
350     }
351 }
352 
callAsFunction(ExecState * exec,JSObject * thisObj,const List & args)353 JSValue *DOMEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
354 {
355     KJS_CHECK_THIS(KJS::DOMEvent, thisObj);
356     DOM::EventImpl &event = *static_cast<DOMEvent *>(thisObj)->impl();
357     switch (id) {
358     case DOMEvent::StopPropagation:
359         event.stopPropagation(true);
360         return jsUndefined();
361     case DOMEvent::PreventDefault:
362         event.preventDefault(true);
363         return jsUndefined();
364     case DOMEvent::InitEvent:
365         event.initEvent(args[0]->toString(exec).domString(), args[1]->toBoolean(exec), args[2]->toBoolean(exec));
366         return jsUndefined();
367     };
368     return jsUndefined();
369 }
370 
getDOMEvent(ExecState * exec,DOM::EventImpl * ei)371 JSValue *KJS::getDOMEvent(ExecState *exec, DOM::EventImpl *ei)
372 {
373     if (!ei) {
374         return jsNull();
375     }
376     ScriptInterpreter *interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
377     DOMObject *ret = interp->getDOMObject(ei);
378     if (!ret) {
379         if (ei->isTextInputEvent()) {
380             ret = new DOMTextEvent(exec, static_cast<DOM::TextEventImpl *>(ei));
381         } else if (ei->isKeyboardEvent()) {
382             ret = new DOMKeyboardEvent(exec, static_cast<DOM::KeyboardEventImpl *>(ei));
383         } else if (ei->isMouseEvent()) {
384             ret = new DOMMouseEvent(exec, static_cast<DOM::MouseEventImpl *>(ei));
385         } else if (ei->isUIEvent()) {
386             ret = new DOMUIEvent(exec, static_cast<DOM::UIEventImpl *>(ei));
387         } else if (ei->isMutationEvent()) {
388             ret = new DOMMutationEvent(exec, static_cast<DOM::MutationEventImpl *>(ei));
389         } else if (ei->isMessageEvent()) {
390             ret = new DOMMessageEvent(exec, static_cast<DOM::MessageEventImpl *>(ei));
391         } else if (ei->isHashChangeEvent()) {
392             ret = new DOMHashChangeEvent(exec, static_cast<DOM::HashChangeEventImpl *>(ei));
393         } else {
394             ret = new DOMEvent(exec, ei);
395         }
396 
397         interp->putDOMObject(ei, ret);
398     }
399 
400     return ret;
401 }
402 
toEvent(JSValue * val)403 DOM::EventImpl *KJS::toEvent(JSValue *val)
404 {
405     JSObject *obj = val->getObject();
406     if (!obj || !obj->inherits(&DOMEvent::info)) {
407         return nullptr;
408     }
409 
410     const DOMEvent *dobj = static_cast<const DOMEvent *>(obj);
411     return dobj->impl();
412 }
413 
414 // -------------------------------------------------------------------------
415 /*
416 @begin EventConstantsTable 23
417   CAPTURING_PHASE   DOM::Event::CAPTURING_PHASE DontDelete|ReadOnly
418   AT_TARGET     DOM::Event::AT_TARGET       DontDelete|ReadOnly
419   BUBBLING_PHASE    DOM::Event::BUBBLING_PHASE  DontDelete|ReadOnly
420 # Reverse-engineered from Netscape
421   MOUSEDOWN     1               DontDelete|ReadOnly
422   MOUSEUP       2               DontDelete|ReadOnly
423   MOUSEOVER     4               DontDelete|ReadOnly
424   MOUSEOUT      8               DontDelete|ReadOnly
425   MOUSEMOVE     16              DontDelete|ReadOnly
426   MOUSEDRAG     32              DontDelete|ReadOnly
427   CLICK         64              DontDelete|ReadOnly
428   DBLCLICK      128             DontDelete|ReadOnly
429   KEYDOWN       256             DontDelete|ReadOnly
430   KEYUP         512             DontDelete|ReadOnly
431   KEYPRESS      1024                DontDelete|ReadOnly
432   DRAGDROP      2048                DontDelete|ReadOnly
433   FOCUS         4096                DontDelete|ReadOnly
434   BLUR          8192                DontDelete|ReadOnly
435   SELECT        16384               DontDelete|ReadOnly
436   CHANGE        32768               DontDelete|ReadOnly
437 @end
438 */
439 DEFINE_CONSTANT_TABLE(EventConstants)
440 IMPLEMENT_CONSTANT_TABLE(EventConstants, "EventConstants")
441 
442 IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(EventConstructor, "EventConstructor", DOMEventProto, EventConstants)
443 // -------------------------------------------------------------------------
444 
445 const ClassInfo EventExceptionConstructor::info = { "EventExceptionConstructor", nullptr, &EventExceptionConstructorTable, nullptr };
446 /*
447 @begin EventExceptionConstructorTable 1
448   UNSPECIFIED_EVENT_TYPE_ERR    DOM::EventException::UNSPECIFIED_EVENT_TYPE_ERR DontDelete|ReadOnly
449 @end
450 */
EventExceptionConstructor(ExecState * exec)451 EventExceptionConstructor::EventExceptionConstructor(ExecState *exec)
452     : DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype())
453 {
454 }
455 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)456 bool EventExceptionConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
457 {
458     return getStaticValueSlot<EventExceptionConstructor, DOMObject>(exec, &EventExceptionConstructorTable, this, propertyName, slot);
459 }
460 
getValueProperty(ExecState *,int token) const461 JSValue *EventExceptionConstructor::getValueProperty(ExecState *, int token) const
462 {
463     // We use the token as the value to return directly
464     return jsNumber(token);
465 }
466 
getEventExceptionConstructor(ExecState * exec)467 JSValue *KJS::getEventExceptionConstructor(ExecState *exec)
468 {
469     return cacheGlobalObject<EventExceptionConstructor>(exec, "[[eventException.constructor]]");
470 }
471 
472 // -------------------------------------------------------------------------
473 
474 const ClassInfo DOMUIEvent::info = { "UIEvent", &DOMEvent::info, &DOMUIEventTable, nullptr };
475 /*
476 @begin DOMUIEventTable 7
477   view      DOMUIEvent::View    DontDelete|ReadOnly
478   detail    DOMUIEvent::Detail  DontDelete|ReadOnly
479   keyCode   DOMUIEvent::KeyCode DontDelete|ReadOnly
480   charCode  DOMUIEvent::CharCode    DontDelete|ReadOnly
481   layerX    DOMUIEvent::LayerX  DontDelete|ReadOnly
482   layerY    DOMUIEvent::LayerY  DontDelete|ReadOnly
483   pageX     DOMUIEvent::PageX   DontDelete|ReadOnly
484   pageY     DOMUIEvent::PageY   DontDelete|ReadOnly
485   which     DOMUIEvent::Which   DontDelete|ReadOnly
486 @end
487 @begin DOMUIEventProtoTable 1
488   initUIEvent   DOMUIEvent::InitUIEvent DontDelete|Function 5
489 @end
490 */
491 KJS_DEFINE_PROTOTYPE(DOMUIEventProto)
KJS_IMPLEMENT_PROTOFUNC(DOMUIEventProtoFunc)492 KJS_IMPLEMENT_PROTOFUNC(DOMUIEventProtoFunc)
493 KJS_IMPLEMENT_PROTOTYPE("DOMUIEvent", DOMUIEventProto, DOMUIEventProtoFunc, DOMEventProto)
494 
495 DOMUIEvent::DOMUIEvent(ExecState *exec, DOM::UIEventImpl *ue) :
496     DOMEvent(DOMUIEventProto::self(exec), ue) {}
497 
DOMUIEvent(JSObject * proto,DOM::UIEventImpl * ue)498 DOMUIEvent::DOMUIEvent(JSObject *proto, DOM::UIEventImpl *ue) :
499     DOMEvent(proto, ue) {}
500 
~DOMUIEvent()501 DOMUIEvent::~DOMUIEvent()
502 {
503 }
504 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)505 bool DOMUIEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
506 {
507     return getStaticValueSlot<DOMUIEvent, DOMEvent>(exec, &DOMUIEventTable, this, propertyName, slot);
508 }
509 
getValueProperty(ExecState * exec,int token) const510 JSValue *DOMUIEvent::getValueProperty(ExecState *exec, int token) const
511 {
512     DOM::UIEventImpl &event = *impl();
513     switch (token) {
514     case View:
515         return getDOMAbstractView(exec, event.view());
516     case Detail:
517         return jsNumber(event.detail());
518     case KeyCode:
519         // IE-compatibility
520         return jsNumber(event.keyCode());
521     case CharCode:
522         // IE-compatibility
523         return jsNumber(event.charCode());
524     case LayerX:
525         // NS-compatibility
526         return jsNumber(event.layerX());
527     case LayerY:
528         // NS-compatibility
529         return jsNumber(event.layerY());
530     case PageX:
531         // NS-compatibility
532         return jsNumber(event.pageX());
533     case PageY:
534         // NS-compatibility
535         return jsNumber(event.pageY());
536     case Which:
537         // NS-compatibility
538         return jsNumber(event.which());
539     default:
540         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMUIEvent::getValueProperty : " << token;
541         return jsUndefined();
542     }
543 }
544 
callAsFunction(ExecState * exec,JSObject * thisObj,const List & args)545 JSValue *DOMUIEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
546 {
547     KJS_CHECK_THIS(KJS::DOMUIEvent, thisObj);
548     DOM::UIEventImpl &uiEvent = *static_cast<DOMUIEvent *>(thisObj)->impl();
549     switch (id) {
550     case DOMUIEvent::InitUIEvent: {
551         DOM::AbstractViewImpl *v = toAbstractView(args[3]);
552         uiEvent.initUIEvent(args[0]->toString(exec).domString(),
553                             args[1]->toBoolean(exec),
554                             args[2]->toBoolean(exec),
555                             v,
556                             args[4]->toInteger(exec));
557     }
558     return jsUndefined();
559     }
560     return jsUndefined();
561 }
562 
563 // -------------------------------------------------------------------------
564 
565 const ClassInfo DOMMouseEvent::info = { "MouseEvent", &DOMUIEvent::info, &DOMMouseEventTable, nullptr };
566 
567 /*
568 @begin DOMMouseEventTable 2
569   screenX   DOMMouseEvent::ScreenX  DontDelete|ReadOnly
570   screenY   DOMMouseEvent::ScreenY  DontDelete|ReadOnly
571   clientX   DOMMouseEvent::ClientX  DontDelete|ReadOnly
572   x     DOMMouseEvent::X    DontDelete|ReadOnly
573   clientY   DOMMouseEvent::ClientY  DontDelete|ReadOnly
574   y     DOMMouseEvent::Y    DontDelete|ReadOnly
575   offsetX   DOMMouseEvent::OffsetX  DontDelete|ReadOnly
576   offsetY   DOMMouseEvent::OffsetY  DontDelete|ReadOnly
577   ctrlKey   DOMMouseEvent::CtrlKey  DontDelete|ReadOnly
578   shiftKey  DOMMouseEvent::ShiftKey DontDelete|ReadOnly
579   altKey    DOMMouseEvent::AltKey   DontDelete|ReadOnly
580   metaKey   DOMMouseEvent::MetaKey  DontDelete|ReadOnly
581   button    DOMMouseEvent::Button   DontDelete|ReadOnly
582   relatedTarget DOMMouseEvent::RelatedTarget DontDelete|ReadOnly
583   fromElement   DOMMouseEvent::FromElement DontDelete|ReadOnly
584   toElement DOMMouseEvent::ToElement    DontDelete|ReadOnly
585 @end
586 @begin DOMMouseEventProtoTable 1
587   initMouseEvent    DOMMouseEvent::InitMouseEvent   DontDelete|Function 15
588 @end
589 */
590 KJS_DEFINE_PROTOTYPE(DOMMouseEventProto)
KJS_IMPLEMENT_PROTOFUNC(DOMMouseEventProtoFunc)591 KJS_IMPLEMENT_PROTOFUNC(DOMMouseEventProtoFunc)
592 KJS_IMPLEMENT_PROTOTYPE("DOMMouseEvent", DOMMouseEventProto, DOMMouseEventProtoFunc, DOMUIEventProto)
593 
594 DOMMouseEvent::DOMMouseEvent(ExecState *exec, DOM::MouseEventImpl *me) :
595     DOMUIEvent(DOMMouseEventProto::self(exec), me) {}
596 
~DOMMouseEvent()597 DOMMouseEvent::~DOMMouseEvent()
598 {
599 }
600 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)601 bool DOMMouseEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
602 {
603 #ifdef KJS_VERBOSE
604     qCDebug(KHTML_LOG) << "DOMMouseEvent::getOwnPropertySlot " << propertyName.qstring();
605 #endif
606 
607     return getStaticValueSlot<DOMMouseEvent, DOMUIEvent>(exec, &DOMMouseEventTable, this, propertyName, slot);
608 }
609 
getValueProperty(ExecState * exec,int token) const610 JSValue *DOMMouseEvent::getValueProperty(ExecState *exec, int token) const
611 {
612     DOM::MouseEventImpl &event = *impl();
613     switch (token) {
614     case ScreenX:
615         return jsNumber(event.screenX());
616     case ScreenY:
617         return jsNumber(event.screenY());
618     case ClientX:
619     case X:
620         return jsNumber(event.clientX());
621     case ClientY:
622     case Y:
623         return jsNumber(event.clientY());
624     case OffsetX:
625     case OffsetY: { // MSIE extension
626         if (event.target()->eventTargetType() != EventTargetImpl::DOM_NODE) {
627             return jsUndefined();
628         }
629 
630         DOM::Node node = static_cast<NodeImpl *>(event.target());
631         khtml::RenderObject *rend = nullptr;
632         if (node.handle()) {
633             node.handle()->document()->updateRendering();
634             rend = node.handle()->renderer();
635         }
636         int x = event.clientX();
637         int y = event.clientY();
638         if (rend) {
639             int xPos, yPos;
640             if (rend->absolutePosition(xPos, yPos)) {
641                 //qCDebug(KHTML_LOG) << "DOMMouseEvent::getValueProperty rend=" << rend << "  xPos=" << xPos << "  yPos=" << yPos;
642                 x -= xPos;
643                 y -= yPos;
644             }
645             if (rend->canvas()) {
646                 int cYPos, cXPos;
647                 rend->canvas()->absolutePosition(cXPos,  cYPos,  true);
648                 x += cXPos;
649                 y += cYPos;
650             }
651         }
652         return jsNumber(token == OffsetX ? x : y);
653     }
654     case CtrlKey:
655         return jsBoolean(event.ctrlKey());
656     case ShiftKey:
657         return jsBoolean(event.shiftKey());
658     case AltKey:
659         return jsBoolean(event.altKey());
660     case MetaKey:
661         return jsBoolean(event.metaKey());
662     case Button: {
663         if (exec->dynamicInterpreter()->compatMode() == Interpreter::IECompat) {
664             // Tricky. The DOM (and khtml) use 0 for LMB, 1 for MMB and 2 for RMB
665             // but MSIE uses 1=LMB, 2=RMB, 4=MMB, as a bitfield
666             int domButton = event.button();
667             int button = domButton == 0 ? 1 : domButton == 1 ? 4 : domButton == 2 ? 2 : 0;
668             return jsNumber((unsigned int)button);
669         }
670         return jsNumber(event.button());
671     }
672     case ToElement:
673         // MSIE extension - "the object toward which the user is moving the mouse pointer"
674         if (event.id() == DOM::EventImpl::MOUSEOUT_EVENT) {
675             return getEventTarget(exec, event.relatedTarget());
676         }
677         return getEventTarget(exec, event.target());
678     case FromElement:
679         // MSIE extension - "object from which activation
680         // or the mouse pointer is exiting during the event" (huh?)
681         if (event.id() == DOM::EventImpl::MOUSEOUT_EVENT) {
682             return getEventTarget(exec, event.target());
683         }
684     /* fall through */
685     case RelatedTarget:
686         return getEventTarget(exec, event.relatedTarget());
687     default:
688         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMMouseEvent::getValueProperty : " << token;
689         return nullptr;
690     }
691 }
692 
callAsFunction(ExecState * exec,JSObject * thisObj,const List & args)693 JSValue *DOMMouseEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
694 {
695     KJS_CHECK_THIS(KJS::DOMMouseEvent, thisObj);
696     DOM::MouseEventImpl &mouseEvent = *static_cast<DOMMouseEvent *>(thisObj)->impl();
697     switch (id) {
698     case DOMMouseEvent::InitMouseEvent:
699         mouseEvent.initMouseEvent(args[0]->toString(exec).domString(), // typeArg
700                                   args[1]->toBoolean(exec), // canBubbleArg
701                                   args[2]->toBoolean(exec), // cancelableArg
702                                   toAbstractView(args[3]), // viewArg
703                                   args[4]->toInteger(exec), // detailArg
704                                   args[5]->toInteger(exec), // screenXArg
705                                   args[6]->toInteger(exec), // screenYArg
706                                   args[7]->toInteger(exec), // clientXArg
707                                   args[8]->toInteger(exec), // clientYArg
708                                   args[9]->toBoolean(exec), // ctrlKeyArg
709                                   args[10]->toBoolean(exec), // altKeyArg
710                                   args[11]->toBoolean(exec), // shiftKeyArg
711                                   args[12]->toBoolean(exec), // metaKeyArg
712                                   args[13]->toInteger(exec), // buttonArg
713                                   toNode(args[14])); // relatedTargetArg
714         return jsUndefined();
715     }
716     return jsUndefined();
717 }
718 
719 // -------------------------------------------------------------------------
720 
721 const ClassInfo DOMKeyEventBase::info = { "KeyEventBase", &DOMUIEvent::info, &DOMKeyEventBaseTable, nullptr };
722 
723 /*
724 @begin DOMKeyEventBaseTable 5
725   keyVal     DOMKeyEventBase::Key         DontDelete|ReadOnly
726   virtKeyVal     DOMKeyEventBase::VirtKey     DontDelete|ReadOnly
727   ctrlKey        DOMKeyEventBase::CtrlKey     DontDelete|ReadOnly
728   altKey         DOMKeyEventBase::AltKey      DontDelete|ReadOnly
729   shiftKey       DOMKeyEventBase::ShiftKey    DontDelete|ReadOnly
730   metaKey        DOMKeyEventBase::MetaKey     DontDelete|ReadOnly
731 @end
732 */
733 
DOMKeyEventBase(JSObject * proto,DOM::KeyEventBaseImpl * ke)734 DOMKeyEventBase::DOMKeyEventBase(JSObject *proto, DOM::KeyEventBaseImpl *ke) :
735     DOMUIEvent(proto, ke) {}
736 
~DOMKeyEventBase()737 DOMKeyEventBase::~DOMKeyEventBase()
738 {}
739 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)740 bool DOMKeyEventBase::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
741 {
742 #ifdef KJS_VERBOSE
743     qCDebug(KHTML_LOG) << "DOMKeyEventBase::getOwnPropertySlot " << propertyName.qstring();
744 #endif
745     return getStaticValueSlot<DOMKeyEventBase, DOMUIEvent>(exec, &DOMKeyEventBaseTable, this, propertyName, slot);
746 }
747 
getValueProperty(ExecState *,int token) const748 JSValue *DOMKeyEventBase::getValueProperty(ExecState *, int token) const
749 {
750     DOM::KeyEventBaseImpl *tevent = impl();
751     switch (token) {
752     case Key:
753         return jsNumber(tevent->keyVal());
754     case VirtKey:
755         return jsNumber(tevent->virtKeyVal());
756     // these modifier attributes actually belong into a KeyboardEvent interface,
757     // but we want them on "keypress" as well.
758     case CtrlKey:
759         return jsBoolean(tevent->ctrlKey());
760     case ShiftKey:
761         return jsBoolean(tevent->shiftKey());
762     case AltKey:
763         return jsBoolean(tevent->altKey());
764     case MetaKey:
765         return jsBoolean(tevent->metaKey());
766     default:
767         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMKeyEventBase::getValueProperty : " << token;
768         return jsUndefined();
769     }
770 }
771 
772 // -------------------------------------------------------------------------
773 const ClassInfo DOMTextEvent::info = { "TextEvent", &DOMKeyEventBase::info, &DOMTextEventTable, nullptr };
774 
775 /*
776 @begin DOMTextEventTable 1
777   data           DOMTextEvent::Data          DontDelete|ReadOnly
778 @end
779 @begin DOMTextEventProtoTable 1
780   initTextEvent DOMTextEvent::InitTextEvent DontDelete|Function 5
781   # Missing: initTextEventNS
782 @end
783 */
784 KJS_DEFINE_PROTOTYPE(DOMTextEventProto)
KJS_IMPLEMENT_PROTOFUNC(DOMTextEventProtoFunc)785 KJS_IMPLEMENT_PROTOFUNC(DOMTextEventProtoFunc)
786 KJS_IMPLEMENT_PROTOTYPE("DOMTextEvent", DOMTextEventProto, DOMTextEventProtoFunc, DOMUIEventProto) //Note: no proto in KeyBase
787 
788 DOMTextEvent::DOMTextEvent(ExecState *exec, DOM::TextEventImpl *ke) :
789     DOMKeyEventBase(DOMTextEventProto::self(exec), ke) {}
790 
~DOMTextEvent()791 DOMTextEvent::~DOMTextEvent()
792 {
793 }
794 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)795 bool DOMTextEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
796 {
797 #ifdef KJS_VERBOSE
798     qCDebug(KHTML_LOG) << "DOMTextEvent::getOwnPropertySlot " << propertyName.qstring();
799 #endif
800     return getStaticValueSlot<DOMTextEvent, DOMKeyEventBase>(exec, &DOMTextEventTable, this, propertyName, slot);
801 }
802 
getValueProperty(ExecState *,int token) const803 JSValue *DOMTextEvent::getValueProperty(ExecState *, int token) const
804 {
805     DOM::TextEventImpl &tevent = *impl();
806     switch (token) {
807     case Data:
808         return jsString(tevent.data());
809     default:
810         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token;
811         return jsUndefined();
812     }
813 }
814 
callAsFunction(ExecState * exec,JSObject * thisObj,const List & args)815 JSValue *DOMTextEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
816 {
817     KJS_CHECK_THIS(KJS::DOMTextEvent, thisObj);
818     DOM::TextEventImpl &keyEvent = *static_cast<DOMTextEvent *>(thisObj)->impl();
819     switch (id) {
820     case DOMTextEvent::InitTextEvent:
821 
822         keyEvent.initTextEvent(args[0]->toString(exec).domString(), // typeArg
823                                args[1]->toBoolean(exec), // canBubbleArg
824                                args[2]->toBoolean(exec), // cancelableArg
825                                toAbstractView(args[3]), // viewArg
826                                args[4]->toString(exec).domString()); // dataArg
827         return jsUndefined();
828     }
829     return jsUndefined();
830 }
831 // -------------------------------------------------------------------------
832 const ClassInfo DOMKeyboardEvent::info = { "KeyboardEvent", &DOMKeyEventBase::info, &DOMKeyboardEventTable, nullptr };
833 
834 /*
835 @begin DOMKeyboardEventTable 2
836   keyIdentifier  DOMKeyboardEvent::KeyIdentifier  DontDelete|ReadOnly
837   keyLocation    DOMKeyboardEvent::KeyLocation    DontDelete|ReadOnly
838 @end
839 @begin DOMKeyboardEventProtoTable 2
840   initKeyboardEvent DOMKeyboardEvent::InitKeyboardEvent DontDelete|Function 7
841   getModifierState      DOMKeyboardEvent::GetModifierState      DontDelete|Function 1
842 @end
843 */
844 KJS_DEFINE_PROTOTYPE(DOMKeyboardEventProto)
KJS_IMPLEMENT_PROTOFUNC(DOMKeyboardEventProtoFunc)845 KJS_IMPLEMENT_PROTOFUNC(DOMKeyboardEventProtoFunc)
846 KJS_IMPLEMENT_PROTOTYPE("DOMKeyboardEvent", DOMKeyboardEventProto, DOMKeyboardEventProtoFunc, DOMUIEventProto) //Note: no proto in KeyBase
847 
848 DOMKeyboardEvent::DOMKeyboardEvent(ExecState *exec, DOM::KeyboardEventImpl *ke) :
849     DOMKeyEventBase(DOMKeyboardEventProto::self(exec), ke) {}
850 
~DOMKeyboardEvent()851 DOMKeyboardEvent::~DOMKeyboardEvent()
852 {
853 }
854 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)855 bool DOMKeyboardEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
856 {
857 #ifdef KJS_VERBOSE
858     qCDebug(KHTML_LOG) << "DOMKeyboardEvent::getOwnPropertySlot " << propertyName.qstring();
859 #endif
860     return getStaticValueSlot<DOMKeyboardEvent, DOMKeyEventBase>(exec, &DOMKeyboardEventTable, this, propertyName, slot);
861 }
862 
getValueProperty(ExecState *,int token) const863 JSValue *DOMKeyboardEvent::getValueProperty(ExecState *, int token) const
864 {
865     DOM::KeyboardEventImpl *tevent = impl();
866     switch (token) {
867     case KeyIdentifier:
868         return jsString(tevent->keyIdentifier());
869     case KeyLocation:
870         return jsNumber(tevent->keyLocation());
871     default:
872         // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMKeyboardEvent::getValueProperty : " << token;
873         return jsUndefined();
874     }
875 }
876 
callAsFunction(ExecState * exec,JSObject * thisObj,const List & args)877 JSValue *DOMKeyboardEventProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
878 {
879     KJS_CHECK_THIS(KJS::DOMKeyboardEvent, thisObj);
880     DOM::KeyboardEventImpl *keyEvent = static_cast<DOMKeyboardEvent *>(thisObj)->impl();
881     switch (id) {
882     case DOMKeyboardEvent::InitKeyboardEvent:
883         keyEvent->initKeyboardEvent(args[0]->toString(exec).domString(), // typeArg
884                                     args[1]->toBoolean(exec), // canBubbleArg
885                                     args[2]->toBoolean(exec), // cancelableArg
886                                     toAbstractView(args[3]), // viewArg
887                                     args[4]->toString(exec).domString(), // keyIdentifierArg
888                                     args[5]->toInteger(exec),         // keyLocationArg
889                                     args[6]->toString(exec).domString()); //modifiersList
890         break;
891     case DOMKeyboardEvent::GetModifierState:
892         return jsBoolean(keyEvent->getModifierState(args[0]->toString(exec).domString()));
893     }
894     return jsUndefined();
895 }
896 
897 // -------------------------------------------------------------------------
898 const ClassInfo KeyboardEventConstructor::info = { "KeyboardEventConstructor", nullptr, &KeyboardEventConstructorTable, nullptr };
899 /*
900 @begin KeyboardEventConstructorTable 4
901   DOM_KEY_LOCATION_STANDARD  DOM::KeyboardEvent::DOM_KEY_LOCATION_STANDARD DontDelete|ReadOnly
902   DOM_KEY_LOCATION_LEFT      DOM::KeyboardEvent::DOM_KEY_LOCATION_LEFT     DontDelete|ReadOnly
903   DOM_KEY_LOCATION_RIGHT     DOM::KeyboardEvent::DOM_KEY_LOCATION_RIGHT    DontDelete|ReadOnly
904   DOM_KEY_LOCATION_NUMPAD    DOM::KeyboardEvent::DOM_KEY_LOCATION_NUMPAD   DontDelete|ReadOnly
905 @end
906 */
KeyboardEventConstructor(ExecState * exec)907 KeyboardEventConstructor::KeyboardEventConstructor(ExecState *exec)
908     : DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype())
909 {}
910 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)911 bool KeyboardEventConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
912 {
913 #ifdef KJS_VERBOSE
914     qCDebug(KHTML_LOG) << "DOMKeyboardEvent::getOwnPropertySlot " << propertyName.qstring();
915 #endif
916     return getStaticValueSlot<KeyboardEventConstructor, DOMObject>(exec, &KeyboardEventConstructorTable, this, propertyName, slot);
917 }
918 
getValueProperty(ExecState *,int token) const919 JSValue *KeyboardEventConstructor::getValueProperty(ExecState *, int token) const
920 {
921     // We use the token as the value to return directly
922     return jsNumber(token);
923 }
924 
getKeyboardEventConstructor(ExecState * exec)925 JSValue *KJS::getKeyboardEventConstructor(ExecState *exec)
926 {
927     return cacheGlobalObject<KeyboardEventConstructor>(exec, "[[keyboardEvent.constructor]]");
928 }
929 
930 // -------------------------------------------------------------------------
931 const ClassInfo MutationEventConstructor::info = { "MutationEventConstructor", nullptr, &MutationEventConstructorTable, nullptr };
932 /*
933 @begin MutationEventConstructorTable 3
934   MODIFICATION  DOM::MutationEvent::MODIFICATION    DontDelete|ReadOnly
935   ADDITION  DOM::MutationEvent::ADDITION        DontDelete|ReadOnly
936   REMOVAL   DOM::MutationEvent::REMOVAL     DontDelete|ReadOnly
937 @end
938 */
MutationEventConstructor(ExecState * exec)939 MutationEventConstructor::MutationEventConstructor(ExecState *exec)
940     : DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype())
941 {
942 }
943 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)944 bool MutationEventConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
945 {
946     return getStaticValueSlot<MutationEventConstructor, DOMObject>(exec, &MutationEventConstructorTable, this, propertyName, slot);
947 }
948 
getValueProperty(ExecState *,int token) const949 JSValue *MutationEventConstructor::getValueProperty(ExecState *, int token) const
950 {
951     // We use the token as the value to return directly
952     return jsNumber(token);
953 }
954 
getMutationEventConstructor(ExecState * exec)955 JSValue *KJS::getMutationEventConstructor(ExecState *exec)
956 {
957     return cacheGlobalObject<MutationEventConstructor>(exec, "[[mutationEvent.constructor]]");
958 }
959 
960 // -------------------------------------------------------------------------
961 
962 const ClassInfo DOMMutationEvent::info = { "MutationEvent", &DOMEvent::info, &DOMMutationEventTable, nullptr };
963 /*
964 @begin DOMMutationEventTable 5
965   relatedNode   DOMMutationEvent::RelatedNode   DontDelete|ReadOnly
966   prevValue DOMMutationEvent::PrevValue DontDelete|ReadOnly
967   newValue  DOMMutationEvent::NewValue  DontDelete|ReadOnly
968   attrName  DOMMutationEvent::AttrName  DontDelete|ReadOnly
969   attrChange    DOMMutationEvent::AttrChange    DontDelete|ReadOnly
970 @end
971 @begin DOMMutationEventProtoTable 1
972   initMutationEvent DOMMutationEvent::InitMutationEvent DontDelete|Function 8
973 @end
974 */
975 KJS_DEFINE_PROTOTYPE(DOMMutationEventProto)
KJS_IMPLEMENT_PROTOFUNC(DOMMutationEventProtoFunc)976 KJS_IMPLEMENT_PROTOFUNC(DOMMutationEventProtoFunc)
977 KJS_IMPLEMENT_PROTOTYPE("DOMMutationEvent", DOMMutationEventProto, DOMMutationEventProtoFunc, DOMEventProto)
978 
979 DOMMutationEvent::DOMMutationEvent(ExecState *exec, DOM::MutationEventImpl *me) :
980     DOMEvent(DOMMutationEventProto::self(exec), me) {}
981 
~DOMMutationEvent()982 DOMMutationEvent::~DOMMutationEvent()
983 {
984 }
985 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)986 bool DOMMutationEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
987 {
988     return getStaticValueSlot<DOMMutationEvent, DOMEvent>(exec, &DOMMutationEventTable, this, propertyName, slot);
989 }
990 
getValueProperty(ExecState * exec,int token) const991 JSValue *DOMMutationEvent::getValueProperty(ExecState *exec, int token) const
992 {
993     DOM::MutationEventImpl &event = *impl();
994     switch (token) {
995     case RelatedNode: {
996         DOM::Node relatedNode = event.relatedNode();
997         return getDOMNode(exec, relatedNode.handle());
998     }
999     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 
callAsFunction(ExecState * exec,JSObject * thisObj,const List & args)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)
KJS_IMPLEMENT_PROTOFUNC(DOMMessageEventProtoFunc)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 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)1053 bool DOMMessageEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1054 {
1055     return getStaticValueSlot<DOMMessageEvent, DOMEvent>(exec, &DOMMessageEventTable, this, propertyName, slot);
1056 }
1057 
getValueProperty(ExecState * exec,int token) const1058 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 
callAsFunction(ExecState * exec,JSObject * thisObj,const List & args)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)
KJS_IMPLEMENT_PROTOFUNC(DOMHashChangeEventProtoFunc)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 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)1138 bool DOMHashChangeEvent::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
1139 {
1140     return getStaticValueSlot<DOMHashChangeEvent, DOMEvent>(exec, &DOMHashChangeEventTable, this, propertyName, slot);
1141 }
1142 
getValueProperty(ExecState *,int token) const1143 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 
callAsFunction(ExecState * exec,JSObject * thisObj,const List & args)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 }
1173