JavaScriptCore:
[WebKit-https.git] / WebCore / khtml / ecma / kjs_dom.cpp
1 /*
2  *  This file is part of the KDE libraries
3  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2004 Apple Computer, Inc.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22 #include "kjs_dom.h"
23
24 #include <kdebug.h>
25 #include <khtml_part.h>
26 #include <khtmlview.h>
27 #include "xml/dom2_eventsimpl.h"
28 #include "xml/dom2_viewsimpl.h"
29 #include "rendering/render_canvas.h"
30 #include "xml/dom_nodeimpl.h"
31 #include "xml/dom_docimpl.h"
32 #include "xml/dom_textimpl.h"
33 #include "xml/EventNames.h"
34 #include "xml/dom_xmlimpl.h"
35 #include "html/html_documentimpl.h"
36 #include "css/css_ruleimpl.h"
37 #include "css/css_stylesheetimpl.h"
38
39 #include "kjs_html.h"
40 #include "kjs_css.h"
41 #include "kjs_range.h"
42 #include "kjs_traversal.h"
43 #include "kjs_events.h"
44 #include "kjs_views.h"
45 #include "kjs_window.h"
46 #include "dom/dom_exception.h"
47 #include "khtmlpart_p.h"
48
49 #include "html_objectimpl.h"
50
51 #include <JavaScriptCore/runtime_object.h>
52
53 using namespace DOM::HTMLNames;
54
55 using DOM::AtomicString;
56 using DOM::AttrImpl;
57 using DOM::CharacterDataImpl;
58 using DOM::DocumentImpl;
59 using DOM::DocumentTypeImpl;
60 using DOM::DOMException;
61 using DOM::DOMImplementationImpl;
62 using DOM::DOMString;
63 using DOM::ElementImpl;
64 using DOM::EntityImpl;
65 using DOM::EventImpl;
66 using namespace DOM::EventNames;
67 using DOM::HTMLAppletElementImpl;
68 using DOM::HTMLDocumentImpl;
69 using DOM::HTMLElementImpl;
70 using DOM::HTMLEmbedElementImpl;
71 using DOM::HTMLObjectElementImpl;
72 using DOM::NamedNodeMapImpl;
73 using DOM::Node;
74 using DOM::NodeFilterImpl;
75 using DOM::NodeImpl;
76 using DOM::NodeListImpl;
77 using DOM::NotationImpl;
78 using DOM::ProcessingInstructionImpl;
79 using DOM::TextImpl;
80
81 using namespace khtml;
82
83 #include "kjs_dom.lut.h"
84
85 namespace KJS {
86
87 // -------------------------------------------------------------------------
88 /* Source for DOMNodeProtoTable. Use "make hashtables" to regenerate.
89 @begin DOMNodeProtoTable 18
90   insertBefore  DOMNode::InsertBefore   DontDelete|Function 2
91   replaceChild  DOMNode::ReplaceChild   DontDelete|Function 2
92   removeChild   DOMNode::RemoveChild    DontDelete|Function 1
93   appendChild   DOMNode::AppendChild    DontDelete|Function 1
94   hasAttributes DOMNode::HasAttributes  DontDelete|Function 0
95   hasChildNodes DOMNode::HasChildNodes  DontDelete|Function 0
96   cloneNode     DOMNode::CloneNode      DontDelete|Function 1
97 # DOM2
98   normalize     DOMNode::Normalize      DontDelete|Function 0
99   isSupported   DOMNode::IsSupported    DontDelete|Function 2
100 # DOM3
101   isSameNode    DOMNode::IsSameNode     DontDelete|Function 1
102   isEqualNode   DOMNode::IsEqualNode    DontDelete|Function 1
103   isDefaultNamespace    DOMNode::IsDefaultNamespace DontDelete|Function 1
104   lookupNamespaceURI    DOMNode::LookupNamespaceURI DontDelete|Function 1
105   lookupPrefix  DOMNode::LookupPrefix   DontDelete|Function 1
106 # from the EventTarget interface
107   addEventListener      DOMNode::AddEventListener       DontDelete|Function 3
108   removeEventListener   DOMNode::RemoveEventListener    DontDelete|Function 3
109   dispatchEvent         DOMNode::DispatchEvent  DontDelete|Function 1
110   contains      DOMNode::Contains               DontDelete|Function 1
111 # "DOM level 0" (from Gecko DOM reference; also in WinIE)
112   item          DOMNode::Item           DontDelete|Function 1
113 @end
114 */
115 DEFINE_PROTOTYPE("DOMNode",DOMNodeProto)
116 IMPLEMENT_PROTOFUNC(DOMNodeProtoFunc)
117 IMPLEMENT_PROTOTYPE(DOMNodeProto,DOMNodeProtoFunc)
118
119 const ClassInfo DOMNode::info = { "Node", 0, &DOMNodeTable, 0 };
120
121 DOMNode::DOMNode(ExecState *exec, NodeImpl *n)
122   : m_impl(n)
123 {
124   setPrototype(DOMNodeProto::self(exec));
125 }
126
127 DOMNode::DOMNode(NodeImpl *n)
128   : m_impl(n)
129 {
130 }
131
132 DOMNode::~DOMNode()
133 {
134   ScriptInterpreter::forgetDOMNodeForDocument(m_impl->getDocument(), m_impl.get());
135 }
136
137 void DOMNode::mark()
138 {
139   assert(!marked());
140
141   NodeImpl *node = m_impl.get();
142
143   // Nodes in the document are kept alive by ScriptInterpreter::mark,
144   // so we have no special responsibilities and can just call the base class here.
145   if (node->inDocument()) {
146     DOMObject::mark();
147     return;
148   }
149
150   // This is a node outside the document, so find the root of the tree it is in,
151   // and start marking from there.
152   NodeImpl *root = node;
153   for (NodeImpl *current = m_impl.get(); current; current = current->parentNode()) {
154     root = current;
155   }
156
157   static QPtrDict<NodeImpl> markingRoots;
158
159   // If we're already marking this tree, then we can simply mark this wrapper
160   // by calling the base class; our caller is iterating the tree.
161   if (markingRoots.find(root)) {
162     DOMObject::mark();
163     return;
164   }
165
166   DocumentImpl *document = m_impl->getDocument();
167
168   // Mark the whole tree; use the global set of roots to avoid reentering.
169   markingRoots.insert(root, root);
170   for (NodeImpl *nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) {
171     DOMNode *wrapper = ScriptInterpreter::getDOMNodeForDocument(document, nodeToMark);
172     if (wrapper) {
173       if (!wrapper->marked())
174         wrapper->mark();
175     } else if (nodeToMark == node) {
176       // This is the case where the map from the document to wrappers has
177       // been cleared out, but a wrapper is being marked. For now, we'll
178       // let the rest of the tree of wrappers get collected, because we have
179       // no good way of finding them. Later we should test behavior of other
180       // browsers and see if we need to preserve other wrappers in this case.
181       if (!marked())
182         mark();
183     }
184   }
185   markingRoots.remove(root);
186
187   // Double check that we actually ended up marked. This assert caught problems in the past.
188   assert(marked());
189 }
190
191 bool DOMNode::toBoolean(ExecState *) const
192 {
193     return m_impl;
194 }
195
196 /* Source for DOMNodeTable. Use "make hashtables" to regenerate.
197 @begin DOMNodeTable 69
198   nodeName      DOMNode::NodeName       DontDelete|ReadOnly
199   nodeValue     DOMNode::NodeValue      DontDelete
200   nodeType      DOMNode::NodeType       DontDelete|ReadOnly
201   parentNode    DOMNode::ParentNode     DontDelete|ReadOnly
202   parentElement DOMNode::ParentElement  DontDelete|ReadOnly
203   childNodes    DOMNode::ChildNodes     DontDelete|ReadOnly
204   firstChild    DOMNode::FirstChild     DontDelete|ReadOnly
205   lastChild     DOMNode::LastChild      DontDelete|ReadOnly
206   previousSibling  DOMNode::PreviousSibling DontDelete|ReadOnly
207   nextSibling   DOMNode::NextSibling    DontDelete|ReadOnly
208   attributes    DOMNode::Attributes     DontDelete|ReadOnly
209   namespaceURI  DOMNode::NamespaceURI   DontDelete|ReadOnly
210 # DOM2
211   prefix        DOMNode::Prefix         DontDelete
212   localName     DOMNode::LocalName      DontDelete|ReadOnly
213   ownerDocument DOMNode::OwnerDocument  DontDelete|ReadOnly
214 # DOM3
215   textContent   DOMNode::TextContent    DontDelete
216 #
217   onabort       DOMNode::OnAbort                DontDelete
218   onblur        DOMNode::OnBlur                 DontDelete
219   onchange      DOMNode::OnChange               DontDelete
220   onclick       DOMNode::OnClick                DontDelete
221   oncontextmenu DOMNode::OnContextMenu          DontDelete
222   ondblclick    DOMNode::OnDblClick             DontDelete
223   onbeforecut   DOMNode::OnBeforeCut            DontDelete
224   oncut         DOMNode::OnCut                  DontDelete
225   onbeforecopy  DOMNode::OnBeforeCopy           DontDelete
226   oncopy        DOMNode::OnCopy                 DontDelete
227   onbeforepaste DOMNode::OnBeforePaste          DontDelete
228   onpaste       DOMNode::OnPaste                DontDelete
229   ondrag        DOMNode::OnDrag                 DontDelete
230   ondragdrop    DOMNode::OnDragDrop             DontDelete
231   ondragend     DOMNode::OnDragEnd              DontDelete
232   ondragenter   DOMNode::OnDragEnter            DontDelete
233   ondragleave   DOMNode::OnDragLeave            DontDelete
234   ondragover    DOMNode::OnDragOver             DontDelete
235   ondragstart   DOMNode::OnDragStart            DontDelete
236   ondrop        DOMNode::OnDrop                 DontDelete
237   onerror       DOMNode::OnError                DontDelete
238   onfocus       DOMNode::OnFocus                DontDelete
239   oninput       DOMNode::OnInput                DontDelete
240   onkeydown     DOMNode::OnKeyDown              DontDelete
241   onkeypress    DOMNode::OnKeyPress             DontDelete
242   onkeyup       DOMNode::OnKeyUp                DontDelete
243   onload        DOMNode::OnLoad                 DontDelete
244   onmousedown   DOMNode::OnMouseDown            DontDelete
245   onmousemove   DOMNode::OnMouseMove            DontDelete
246   onmouseout    DOMNode::OnMouseOut             DontDelete
247   onmouseover   DOMNode::OnMouseOver            DontDelete
248   onmouseup     DOMNode::OnMouseUp              DontDelete
249   onmousewheel  DOMNode::OnMouseWheel           DontDelete
250   onmove        DOMNode::OnMove                 DontDelete
251   onreset       DOMNode::OnReset                DontDelete
252   onresize      DOMNode::OnResize               DontDelete
253   onscroll      DOMNode::OnScroll               DontDelete
254   onsearch      DOMNode::OnSearch               DontDelete
255   onselect      DOMNode::OnSelect               DontDelete
256   onselectstart DOMNode::OnSelectStart          DontDelete
257   onsubmit      DOMNode::OnSubmit               DontDelete
258   onunload      DOMNode::OnUnload               DontDelete
259 # IE extensions
260   offsetLeft    DOMNode::OffsetLeft             DontDelete|ReadOnly
261   offsetTop     DOMNode::OffsetTop              DontDelete|ReadOnly
262   offsetWidth   DOMNode::OffsetWidth            DontDelete|ReadOnly
263   offsetHeight  DOMNode::OffsetHeight           DontDelete|ReadOnly
264   offsetParent  DOMNode::OffsetParent           DontDelete|ReadOnly
265   clientWidth   DOMNode::ClientWidth            DontDelete|ReadOnly
266   clientHeight  DOMNode::ClientHeight           DontDelete|ReadOnly
267   scrollLeft    DOMNode::ScrollLeft             DontDelete
268   scrollTop     DOMNode::ScrollTop              DontDelete
269   scrollWidth   DOMNode::ScrollWidth            DontDelete|ReadOnly
270   scrollHeight  DOMNode::ScrollHeight           DontDelete|ReadOnly
271 @end
272 */
273 bool DOMNode::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
274 {
275   return getStaticValueSlot<DOMNode, DOMObject>(exec, &DOMNodeTable, this, propertyName, slot);
276 }
277
278 ValueImp *DOMNode::getValueProperty(ExecState *exec, int token) const
279 {
280   NodeImpl &node = *m_impl;
281   switch (token) {
282   case NodeName:
283     return jsStringOrNull(node.nodeName());
284   case NodeValue:
285     return jsStringOrNull(node.nodeValue());
286   case NodeType:
287     return jsNumber(node.nodeType());
288   case ParentNode:
289   case ParentElement: // IE only apparently
290     return getDOMNode(exec,node.parentNode());
291   case ChildNodes:
292     return getDOMNodeList(exec,node.childNodes().get());
293   case FirstChild:
294     return getDOMNode(exec,node.firstChild());
295   case LastChild:
296     return getDOMNode(exec,node.lastChild());
297   case PreviousSibling:
298     return getDOMNode(exec,node.previousSibling());
299   case NextSibling:
300     return getDOMNode(exec,node.nextSibling());
301   case Attributes:
302     return getDOMNamedNodeMap(exec,node.attributes());
303   case NamespaceURI:
304     return jsStringOrNull(node.namespaceURI());
305   case Prefix:
306     return jsStringOrNull(node.prefix());
307   case LocalName:
308     return jsStringOrNull(node.localName());
309   case OwnerDocument:
310     return getDOMNode(exec,node.ownerDocument());
311   case TextContent:
312     return jsStringOrNull(node.textContent());
313   case OnAbort:
314     return getListener(abortEvent);
315   case OnBlur:
316     return getListener(blurEvent);
317   case OnChange:
318     return getListener(changeEvent);
319   case OnClick:
320     return getListener(clickEvent);
321   case OnContextMenu:
322     return getListener(contextmenuEvent);
323   case OnDblClick:
324     return getListener(khtmlDblclickEvent);
325   case OnDragDrop:
326     return getListener(khtmlDragdropEvent);
327   case OnError:
328     return getListener(khtmlErrorEvent);
329   case OnFocus:
330     return getListener(focusEvent);
331   case OnInput:
332     return getListener(inputEvent);
333   case OnKeyDown:
334     return getListener(keydownEvent);
335   case OnKeyPress:
336     return getListener(keypressEvent);
337   case OnKeyUp:
338     return getListener(keyupEvent);
339   case OnLoad:
340     return getListener(loadEvent);
341   case OnMouseDown:
342     return getListener(mousedownEvent);
343   case OnMouseMove:
344     return getListener(mousemoveEvent);
345   case OnMouseOut:
346     return getListener(mouseoutEvent);
347   case OnMouseOver:
348     return getListener(mouseoverEvent);
349   case OnMouseUp:
350     return getListener(mouseupEvent);      
351   case OnMouseWheel:
352     return getListener(mousewheelEvent);      
353   case OnBeforeCut:
354     return getListener(beforecutEvent);
355   case OnCut:
356     return getListener(cutEvent);
357   case OnBeforeCopy:
358     return getListener(beforecopyEvent);
359   case OnCopy:
360     return getListener(copyEvent);
361   case OnBeforePaste:
362     return getListener(beforepasteEvent);
363   case OnPaste:
364     return getListener(pasteEvent);
365   case OnDragEnter:
366     return getListener(dragenterEvent);
367   case OnDragOver:
368     return getListener(dragoverEvent);
369   case OnDragLeave:
370     return getListener(dragleaveEvent);
371   case OnDrop:
372     return getListener(dropEvent);
373   case OnDragStart:
374     return getListener(dragstartEvent);
375   case OnDrag:
376     return getListener(dragEvent);
377   case OnDragEnd:
378     return getListener(dragendEvent);
379   case OnMove:
380     return getListener(khtmlMoveEvent);
381   case OnReset:
382     return getListener(resetEvent);
383   case OnResize:
384     return getListener(resizeEvent);
385   case OnScroll:
386     return getListener(scrollEvent);
387   case OnSearch:
388     return getListener(searchEvent);
389   case OnSelect:
390     return getListener(selectEvent);
391   case OnSelectStart:
392     return getListener(selectstartEvent);
393   case OnSubmit:
394     return getListener(submitEvent);
395   case OnUnload:
396     return getListener(scrollEvent);
397   default:
398     // no DOM standard, found in IE only
399
400     // Make sure our layout is up to date before we allow a query on these attributes.
401     DOM::DocumentImpl* docimpl = node.getDocument();
402     if (docimpl) {
403       docimpl->updateLayoutIgnorePendingStylesheets();
404     }
405
406     RenderObject *rend = node.renderer();
407
408     switch (token) {
409     case OffsetLeft:
410       return rend ? jsNumber(rend->offsetLeft()) : static_cast<ValueImp *>(jsUndefined());
411     case OffsetTop:
412       return rend ? jsNumber(rend->offsetTop()) : static_cast<ValueImp *>(jsUndefined());
413     case OffsetWidth:
414       return rend ? jsNumber(rend->offsetWidth()) : static_cast<ValueImp *>(jsUndefined());
415     case OffsetHeight:
416       return rend ? jsNumber(rend->offsetHeight()) : static_cast<ValueImp *>(jsUndefined());
417     case OffsetParent: {
418       RenderObject* par = rend ? rend->offsetParent() : 0;
419       return getDOMNode(exec, par ? par->element() : 0);
420     }
421     case ClientWidth:
422       return rend ? jsNumber(rend->clientWidth()) : static_cast<ValueImp *>(jsUndefined());
423     case ClientHeight:
424       return rend ? jsNumber(rend->clientHeight()) : static_cast<ValueImp *>(jsUndefined());
425     case ScrollWidth:
426         return rend ? jsNumber(rend->scrollWidth()) : static_cast<ValueImp *>(jsUndefined());
427     case ScrollHeight:
428         return rend ? jsNumber(rend->scrollHeight()) : static_cast<ValueImp *>(jsUndefined());
429     case ScrollLeft:
430       return jsNumber(rend && rend->layer() ? rend->layer()->scrollXOffset() : 0);
431     case ScrollTop:
432       return jsNumber(rend && rend->layer() ? rend->layer()->scrollYOffset() : 0);
433     default:
434       kdWarning() << "Unhandled token in DOMNode::getValueProperty : " << token << endl;
435       break;
436     }
437   }
438
439   return NULL;
440 }
441
442 void DOMNode::put(ExecState *exec, const Identifier& propertyName, ValueImp *value, int attr)
443 {
444 #ifdef KJS_VERBOSE
445   kdDebug(6070) << "DOMNode::put " << propertyName.qstring() << endl;
446 #endif
447   lookupPut<DOMNode,DOMObject>(exec, propertyName, value, attr,
448                                         &DOMNodeTable, this );
449 }
450
451 void DOMNode::putValueProperty(ExecState *exec, int token, ValueImp *value, int /*attr*/)
452 {
453   DOMExceptionTranslator exception(exec);
454   NodeImpl &node = *m_impl;
455   switch (token) {
456   case NodeValue:
457     node.setNodeValue(value->toString(exec).domString(), exception);
458     break;
459   case Prefix:
460     node.setPrefix(value->toString(exec).domString().impl(), exception);
461     break;
462   case TextContent:
463     node.setTextContent(valueToStringWithNullCheck(exec, value), exception);
464     break;
465   case OnAbort:
466     setListener(exec,abortEvent,value);
467     break;
468   case OnBlur:
469     setListener(exec,blurEvent,value);
470     break;
471   case OnChange:
472     setListener(exec,changeEvent,value);
473     break;
474   case OnClick:
475     setListener(exec,clickEvent,value);
476     break;
477   case OnContextMenu:
478     setListener(exec,contextmenuEvent,value);
479     break;
480   case OnDblClick:
481     setListener(exec,khtmlDblclickEvent,value);
482     break;
483   case OnDragDrop:
484     setListener(exec,khtmlDragdropEvent,value);
485     break;
486   case OnError:
487     setListener(exec,khtmlErrorEvent,value);
488     break;
489   case OnFocus:
490     setListener(exec,focusEvent,value);
491     break;
492   case OnInput:
493     setListener(exec,inputEvent,value);
494     break;
495   case OnKeyDown:
496     setListener(exec,keydownEvent,value);
497     break;
498   case OnKeyPress:
499     setListener(exec,keypressEvent,value);
500     break;
501   case OnKeyUp:
502     setListener(exec,keyupEvent,value);
503     break;
504   case OnLoad:
505     setListener(exec,loadEvent,value);
506     break;
507   case OnMouseDown:
508     setListener(exec,mousedownEvent,value);
509     break;
510   case OnMouseMove:
511     setListener(exec,mousemoveEvent,value);
512     break;
513   case OnMouseOut:
514     setListener(exec,mouseoutEvent,value);
515     break;
516   case OnMouseOver:
517     setListener(exec,mouseoverEvent,value);
518     break;
519   case OnMouseUp:
520     setListener(exec,mouseupEvent,value);
521     break;
522   case OnMouseWheel:
523     setListener(exec,mousewheelEvent,value);
524     break;
525   case OnBeforeCut:
526     setListener(exec,beforecutEvent,value);
527     break;
528   case OnCut:
529     setListener(exec,cutEvent,value);
530     break;
531   case OnBeforeCopy:
532     setListener(exec,beforecopyEvent,value);
533     break;
534   case OnCopy:
535     setListener(exec,copyEvent,value);
536     break;
537   case OnBeforePaste:
538     setListener(exec,beforepasteEvent,value);
539     break;
540   case OnPaste:
541     setListener(exec,pasteEvent,value);
542     break;
543   case OnDragEnter:
544     setListener(exec,dragenterEvent,value);
545     break;
546   case OnDragOver:
547     setListener(exec,dragoverEvent,value);
548     break;
549   case OnDragLeave:
550     setListener(exec,dragleaveEvent,value);
551     break;
552   case OnDrop:
553     setListener(exec,dropEvent,value);
554     break;
555   case OnDragStart:
556     setListener(exec,dragstartEvent,value);
557     break;
558   case OnDrag:
559     setListener(exec,dragEvent,value);
560     break;
561   case OnDragEnd:
562     setListener(exec,dragendEvent,value);
563     break;
564   case OnMove:
565     setListener(exec,khtmlMoveEvent,value);
566     break;
567   case OnReset:
568     setListener(exec,resetEvent,value);
569     break;
570   case OnResize:
571     setListener(exec,resizeEvent,value);
572     break;
573   case OnScroll:
574     setListener(exec,scrollEvent,value);
575     break;
576   case OnSearch:
577     setListener(exec,searchEvent,value);
578     break;
579   case OnSelect:
580     setListener(exec,selectEvent,value);
581     break;
582   case OnSelectStart:
583     setListener(exec,selectstartEvent,value);
584     break;
585   case OnSubmit:
586     setListener(exec,submitEvent,value);
587     break;
588   case OnUnload:
589     setListener(exec,scrollEvent,value);
590     break;
591   case ScrollTop: {
592     RenderObject *rend = node.renderer();
593     if (rend && rend->hasOverflowClip())
594         rend->layer()->scrollToYOffset(value->toInt32(exec));
595     break;
596   }
597   case ScrollLeft: {
598     RenderObject *rend = node.renderer();
599     if (rend && rend->hasOverflowClip())
600       rend->layer()->scrollToXOffset(value->toInt32(exec));
601     break;
602   }
603   default:
604     kdWarning() << "DOMNode::putValueProperty unhandled token " << token << endl;
605   }
606 }
607
608 ValueImp *DOMNode::toPrimitive(ExecState *exec, Type /*preferred*/) const
609 {
610   if (!m_impl)
611     return jsNull();
612
613   return jsString(toString(exec));
614 }
615
616 UString DOMNode::toString(ExecState *) const
617 {
618   if (!m_impl)
619     return "null";
620   return "[object " + (m_impl->isElementNode() ? m_impl->nodeName() : className()) + "]";
621 }
622
623 void DOMNode::setListener(ExecState *exec, const AtomicString &eventType, ValueImp *func) const
624 {
625   m_impl->setHTMLEventListener(eventType, Window::retrieveActive(exec)->getJSEventListener(func, true));
626 }
627
628 ValueImp *DOMNode::getListener(const AtomicString &eventType) const
629 {
630     DOM::EventListener *listener = m_impl->getHTMLEventListener(eventType);
631     JSEventListener *jsListener = static_cast<JSEventListener*>(listener);
632     if ( jsListener && jsListener->listenerObjImp() )
633         return jsListener->listenerObj();
634     else
635         return jsNull();
636 }
637
638 void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const
639 {
640 }
641
642 ValueImp *DOMNodeProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
643 {
644   if (!thisObj->inherits(&DOMNode::info))
645     return throwError(exec, TypeError);
646   DOMExceptionTranslator exception(exec);
647   NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl();
648   switch (id) {
649     case DOMNode::HasAttributes:
650       return jsBoolean(node.hasAttributes());
651     case DOMNode::HasChildNodes:
652       return jsBoolean(node.hasChildNodes());
653     case DOMNode::CloneNode:
654       return getDOMNode(exec,node.cloneNode(args[0]->toBoolean(exec)));
655     case DOMNode::Normalize:
656       node.normalize();
657       return jsUndefined();
658     case DOMNode::IsSupported:
659         return jsBoolean(node.isSupported(args[0]->toString(exec).domString(),
660             args[1]->isUndefinedOrNull() ? DOMString() : args[1]->toString(exec).domString()));
661     case DOMNode::IsSameNode:
662         return jsBoolean(node.isSameNode(toNode(args[0])));
663     case DOMNode::IsEqualNode:
664         return jsBoolean(node.isEqualNode(toNode(args[0])));
665     case DOMNode::IsDefaultNamespace:
666         return jsBoolean(node.isDefaultNamespace(valueToStringWithNullCheck(exec, args[0])));
667     case DOMNode::LookupNamespaceURI:
668         return jsStringOrNull(node.lookupNamespaceURI(valueToStringWithNullCheck(exec, args[0])));
669     case DOMNode::LookupPrefix:
670         return jsStringOrNull(node.lookupPrefix(valueToStringWithNullCheck(exec, args[0])));
671     case DOMNode::AddEventListener: {
672         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
673         if (listener)
674             node.addEventListener(AtomicString(args[0]->toString(exec).domString()), listener,args[2]->toBoolean(exec));
675         return jsUndefined();
676     }
677     case DOMNode::RemoveEventListener: {
678         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
679         if (listener)
680             node.removeEventListener(AtomicString(args[0]->toString(exec).domString()), listener,args[2]->toBoolean(exec));
681         return jsUndefined();
682     }
683     case DOMNode::DispatchEvent:
684       return jsBoolean(node.dispatchEvent(toEvent(args[0]), exception));
685     case DOMNode::AppendChild:
686       return getDOMNode(exec,node.appendChild(toNode(args[0]), exception));
687     case DOMNode::RemoveChild:
688       return getDOMNode(exec,node.removeChild(toNode(args[0]), exception));
689     case DOMNode::InsertBefore:
690       return getDOMNode(exec,node.insertBefore(toNode(args[0]), toNode(args[1]), exception));
691     case DOMNode::ReplaceChild:
692       return getDOMNode(exec,node.replaceChild(toNode(args[0]), toNode(args[1]), exception));
693     case DOMNode::Contains:
694       if (node.isElementNode())
695         if (NodeImpl *node0 = toNode(args[0]))
696           return jsBoolean(node.isAncestor(node0));
697       // FIXME: Is there a good reason to return undefined rather than false
698       // when the parameter is not a node? When the object is not an element?
699       return jsUndefined();
700     case DOMNode::Item:
701       return thisObj->get(exec, args[0]->toInt32(exec));
702   }
703
704   return jsUndefined();
705 }
706
707 NodeImpl *toNode(ValueImp *val)
708 {
709     if (!val || !val->isObject(&DOMNode::info))
710         return 0;
711     return static_cast<DOMNode *>(val)->impl();
712 }
713
714 // -------------------------------------------------------------------------
715
716 /*
717 @begin DOMNodeListTable 2
718   length        DOMNodeList::Length     DontDelete|ReadOnly
719   item          DOMNodeList::Item               DontDelete|Function 1
720 @end
721 */
722
723 IMPLEMENT_PROTOFUNC(DOMNodeListFunc)
724
725 const ClassInfo DOMNodeList::info = { "NodeList", 0, &DOMNodeListTable, 0 };
726
727 DOMNodeList::~DOMNodeList()
728 {
729   ScriptInterpreter::forgetDOMObject(m_impl.get());
730 }
731
732 ValueImp *DOMNodeList::toPrimitive(ExecState *exec, Type /*preferred*/) const
733 {
734   if (!m_impl)
735     return jsNull();
736
737   return jsString(toString(exec));
738 }
739
740 ValueImp *DOMNodeList::getValueProperty(ExecState *exec, int token) const
741 {
742   assert(token == Length);
743   return jsNumber(m_impl->length());
744 }
745
746 ValueImp *DOMNodeList::indexGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
747 {
748   DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
749   return getDOMNode(exec, thisObj->m_impl->item(slot.index()));
750 }
751
752 ValueImp *DOMNodeList::nameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
753 {
754   DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
755   return getDOMNode(exec, thisObj->m_impl->itemById(propertyName.domString()));
756 }
757
758 bool DOMNodeList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
759 {
760   const HashEntry* entry = Lookup::findEntry(&DOMNodeListTable, propertyName);
761
762   if (entry) {
763     if (entry->attr & Function)
764       slot.setStaticEntry(this, entry, staticFunctionGetter<DOMNodeListFunc>);
765     else
766       slot.setStaticEntry(this, entry, staticValueGetter<DOMNodeList>);
767     return true;
768   }
769
770   NodeListImpl &list = *m_impl;
771
772   // array index ?
773   bool ok;
774   unsigned idx = propertyName.toUInt32(&ok);
775   if (ok && idx < list.length()) {
776     slot.setCustomIndex(this, idx, indexGetter);
777     return true;
778   } else if (list.itemById(propertyName.domString())) {
779     slot.setCustom(this, nameGetter);
780     return true;
781   }
782
783   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
784 }
785
786 // Need to support both get and call, so that list[0] and list(0) work.
787 ValueImp *DOMNodeList::callAsFunction(ExecState *exec, ObjectImp *, const List &args)
788 {
789   // Do not use thisObj here. See HTMLCollection.
790   UString s = args[0]->toString(exec);
791   bool ok;
792   unsigned int u = s.toUInt32(&ok);
793   if (ok)
794     return getDOMNode(exec, m_impl->item(u));
795
796   return jsUndefined();
797 }
798
799 // Not a prototype class currently, but should probably be converted to one
800 ValueImp *DOMNodeListFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
801 {
802   if (!thisObj->inherits(&KJS::DOMNodeList::info))
803     return throwError(exec, TypeError);
804   DOM::NodeListImpl &list = *static_cast<DOMNodeList *>(thisObj)->impl();
805
806   if (id == DOMNodeList::Item)
807     return getDOMNode(exec, list.item(args[0]->toInt32(exec)));
808
809   return jsUndefined();
810 }
811
812 // -------------------------------------------------------------------------
813
814 const ClassInfo DOMAttr::info = { "Attr", &DOMNode::info, &DOMAttrTable, 0 };
815
816 /* Source for DOMAttrTable. Use "make hashtables" to regenerate.
817 @begin DOMAttrTable 5
818   name          DOMAttr::Name           DontDelete|ReadOnly
819   specified     DOMAttr::Specified      DontDelete|ReadOnly
820   value         DOMAttr::ValueProperty  DontDelete
821   ownerElement  DOMAttr::OwnerElement   DontDelete|ReadOnly
822 @end
823 */
824
825 DOMAttr::DOMAttr(ExecState *exec, AttrImpl *a)
826   : DOMNode(exec, a)
827 {
828 }
829
830 bool DOMAttr::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
831 {
832   return getStaticValueSlot<DOMAttr, DOMNode>(exec, &DOMAttrTable, this, propertyName, slot);
833 }
834
835 ValueImp *DOMAttr::getValueProperty(ExecState *exec, int token) const
836 {
837   AttrImpl *attr = static_cast<AttrImpl *>(impl());
838   switch (token) {
839   case Name:
840     return jsStringOrNull(attr->name());
841   case Specified:
842     return jsBoolean(attr->specified());
843   case ValueProperty:
844     return jsStringOrNull(attr->value());
845   case OwnerElement: // DOM2
846     return getDOMNode(exec, attr->ownerElement());
847   }
848   return NULL; // not reached
849 }
850
851 void DOMAttr::put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr)
852 {
853 #ifdef KJS_VERBOSE
854   kdDebug(6070) << "DOMAttr::put " << propertyName.qstring() << endl;
855 #endif
856   lookupPut<DOMAttr,DOMNode>(exec, propertyName, value, attr,
857                                       &DOMAttrTable, this );
858 }
859
860 void DOMAttr::putValueProperty(ExecState *exec, int token, ValueImp *value, int /*attr*/)
861 {
862   DOMExceptionTranslator exception(exec);
863   switch (token) {
864   case ValueProperty:
865     static_cast<AttrImpl *>(impl())->setValue(value->toString(exec).domString(), exception);
866     return;
867   default:
868     kdWarning() << "DOMAttr::putValueProperty unhandled token " << token << endl;
869   }
870 }
871
872 AttrImpl *toAttr(ValueImp *val)
873 {
874     if (!val || !val->isObject(&DOMAttr::info))
875         return 0;
876     return static_cast<AttrImpl *>(static_cast<DOMNode *>(val)->impl());
877 }
878
879 // -------------------------------------------------------------------------
880
881 /* Source for DOMDocumentProtoTable. Use "make hashtables" to regenerate.
882 @begin DOMDocumentProtoTable 29
883   adoptNode       DOMDocument::AdoptNode                       DontDelete|Function 1
884   createElement   DOMDocument::CreateElement                   DontDelete|Function 1
885   createDocumentFragment DOMDocument::CreateDocumentFragment   DontDelete|Function 1
886   createTextNode  DOMDocument::CreateTextNode                  DontDelete|Function 1
887   createComment   DOMDocument::CreateComment                   DontDelete|Function 1
888   createCDATASection DOMDocument::CreateCDATASection           DontDelete|Function 1
889   createProcessingInstruction DOMDocument::CreateProcessingInstruction DontDelete|Function 1
890   createAttribute DOMDocument::CreateAttribute                 DontDelete|Function 1
891   createEntityReference DOMDocument::CreateEntityReference     DontDelete|Function 1
892   elementFromPoint     DOMDocument::ElementFromPoint           DontDelete|Function 1
893   getElementsByTagName  DOMDocument::GetElementsByTagName      DontDelete|Function 1
894   importNode           DOMDocument::ImportNode                 DontDelete|Function 2
895   createElementNS      DOMDocument::CreateElementNS            DontDelete|Function 2
896   createAttributeNS    DOMDocument::CreateAttributeNS          DontDelete|Function 2
897   getElementsByTagNameNS  DOMDocument::GetElementsByTagNameNS  DontDelete|Function 2
898   getElementById     DOMDocument::GetElementById               DontDelete|Function 1
899   createRange        DOMDocument::CreateRange                  DontDelete|Function 0
900   createNodeIterator DOMDocument::CreateNodeIterator           DontDelete|Function 3
901   createTreeWalker   DOMDocument::CreateTreeWalker             DontDelete|Function 4
902   createEvent        DOMDocument::CreateEvent                  DontDelete|Function 1
903   getOverrideStyle   DOMDocument::GetOverrideStyle             DontDelete|Function 2
904   execCommand        DOMDocument::ExecCommand                  DontDelete|Function 3
905   queryCommandEnabled DOMDocument::QueryCommandEnabled         DontDelete|Function 1
906   queryCommandIndeterm DOMDocument::QueryCommandIndeterm       DontDelete|Function 1
907   queryCommandState DOMDocument::QueryCommandState             DontDelete|Function 1
908   queryCommandSupported DOMDocument::QueryCommandSupported     DontDelete|Function 1
909   queryCommandValue DOMDocument::QueryCommandValue             DontDelete|Function 1
910 @end
911 */
912 DEFINE_PROTOTYPE("DOMDocument", DOMDocumentProto)
913 IMPLEMENT_PROTOFUNC(DOMDocumentProtoFunc)
914 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMDocumentProto, DOMDocumentProtoFunc, DOMNodeProto)
915
916 const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, 0 };
917
918 /* Source for DOMDocumentTable. Use "make hashtables" to regenerate.
919 @begin DOMDocumentTable 4
920   doctype         DOMDocument::DocType                         DontDelete|ReadOnly
921   implementation  DOMDocument::Implementation                  DontDelete|ReadOnly
922   documentElement DOMDocument::DocumentElement                 DontDelete|ReadOnly
923   charset         DOMDocument::Charset                         DontDelete
924   defaultCharset  DOMDocument::DefaultCharset                  DontDelete|ReadOnly
925   characterSet    DOMDocument::CharacterSet                    DontDelete|ReadOnly
926   actualEncoding  DOMDocument::ActualEncoding                  DontDelete|ReadOnly
927   inputEncoding   DOMDocument::InputEncoding                   DontDelete|ReadOnly
928   styleSheets     DOMDocument::StyleSheets                     DontDelete|ReadOnly
929   preferredStylesheetSet  DOMDocument::PreferredStylesheetSet  DontDelete|ReadOnly
930   selectedStylesheetSet  DOMDocument::SelectedStylesheetSet    DontDelete
931   readyState      DOMDocument::ReadyState                      DontDelete|ReadOnly
932   defaultView        DOMDocument::DefaultView                  DontDelete|ReadOnly
933 @end
934 */
935
936 DOMDocument::DOMDocument(ExecState *exec, DocumentImpl *d)
937   : DOMNode(d) 
938
939   setPrototype(DOMDocumentProto::self(exec));
940 }
941
942 DOMDocument::DOMDocument(DocumentImpl *d)
943   : DOMNode(d) 
944
945 }
946
947 DOMDocument::~DOMDocument()
948 {
949   ScriptInterpreter::forgetDOMObject(static_cast<DocumentImpl *>(m_impl.get()));
950 }
951
952 bool DOMDocument::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
953 {
954   return getStaticValueSlot<DOMDocument, DOMNode>(exec, &DOMDocumentTable, this, propertyName, slot);
955 }
956
957 ValueImp *DOMDocument::getValueProperty(ExecState *exec, int token) const
958 {
959   DocumentImpl &doc = *static_cast<DocumentImpl *>(impl());
960
961   switch(token) {
962   case DocType:
963     return getDOMNode(exec,doc.doctype());
964   case Implementation:
965     return getDOMDOMImplementation(exec, doc.implementation());
966   case DocumentElement:
967     return getDOMNode(exec,doc.documentElement());
968   case Charset:
969   case CharacterSet:
970   case ActualEncoding:
971   case InputEncoding:
972     if (Decoder* decoder = doc.decoder())
973       return jsString(decoder->encoding());
974     return jsNull();
975   case DefaultCharset:
976     if (KHTMLPart* part = doc.part())
977         return jsString(part->settings()->encoding());
978     return jsUndefined();
979   case StyleSheets:
980     //kdDebug() << "DOMDocument::StyleSheets, returning " << doc.styleSheets().length() << " stylesheets" << endl;
981     return getDOMStyleSheetList(exec, doc.styleSheets(), &doc);
982   case PreferredStylesheetSet:
983     return jsStringOrNull(doc.preferredStylesheetSet());
984   case SelectedStylesheetSet:
985     return jsStringOrNull(doc.selectedStylesheetSet());
986   case ReadyState:
987     if (KHTMLPart* part = doc.part()) {
988       if (part->d->m_bComplete) return jsString("complete");
989       if (doc.parsing()) return jsString("loading");
990       return jsString("loaded");
991       // What does the interactive value mean ?
992       // Missing support for "uninitialized"
993     }
994     return jsUndefined();
995   case DOMDocument::DefaultView: // DOM2
996     return getDOMAbstractView(exec,doc.defaultView());
997   default:
998     kdWarning() << "DOMDocument::getValueProperty unhandled token " << token << endl;
999     return NULL;
1000   }
1001 }
1002
1003 void DOMDocument::put(ExecState *exec, const Identifier& propertyName, ValueImp *value, int attr)
1004 {
1005 #ifdef KJS_VERBOSE
1006   kdDebug(6070) << "DOMDocument::put " << propertyName.qstring() << endl;
1007 #endif
1008   lookupPut<DOMDocument,DOMNode>(exec, propertyName, value, attr, &DOMDocumentTable, this );
1009 }
1010
1011 void DOMDocument::putValueProperty(ExecState *exec, int token, ValueImp *value, int /*attr*/)
1012 {
1013   DocumentImpl &doc = *static_cast<DocumentImpl *>(impl());
1014   switch (token) {
1015     case SelectedStylesheetSet:
1016       doc.setSelectedStylesheetSet(value->toString(exec).domString());
1017       break;
1018     case Charset:
1019       doc.decoder()->setEncoding(value->toString(exec).cstring().c_str(), Decoder::UserChosenEncoding);
1020       break;
1021   }
1022 }
1023
1024 ValueImp *DOMDocumentProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
1025 {
1026   if (!thisObj->inherits(&KJS::DOMNode::info))
1027     return throwError(exec, TypeError);
1028   DOMExceptionTranslator exception(exec);
1029   NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl();
1030   DocumentImpl &doc = static_cast<DocumentImpl &>(node);
1031   UString str = args[0]->toString(exec);
1032   DOM::DOMString s = str.domString();
1033
1034   switch(id) {
1035   case DOMDocument::AdoptNode:
1036     return getDOMNode(exec,doc.adoptNode(toNode(args[0]),exception));
1037   case DOMDocument::CreateElement:
1038     return getDOMNode(exec,doc.createElement(s, exception));
1039   case DOMDocument::CreateDocumentFragment:
1040     return getDOMNode(exec,doc.createDocumentFragment());
1041   case DOMDocument::CreateTextNode:
1042     return getDOMNode(exec,doc.createTextNode(s));
1043   case DOMDocument::CreateComment:
1044     return getDOMNode(exec,doc.createComment(s));
1045   case DOMDocument::CreateCDATASection:
1046     return getDOMNode(exec, doc.createCDATASection(s, exception));
1047   case DOMDocument::CreateProcessingInstruction:
1048     return getDOMNode(exec, doc.createProcessingInstruction(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception));
1049   case DOMDocument::CreateAttribute:
1050     return getDOMNode(exec,doc.createAttribute(s, exception));
1051   case DOMDocument::CreateEntityReference:
1052     return getDOMNode(exec, doc.createEntityReference(s, exception));
1053   case DOMDocument::ElementFromPoint:
1054     return getDOMNode(exec,doc.elementFromPoint((int)args[0]->toNumber(exec), (int)args[1]->toNumber(exec)));
1055   case DOMDocument::GetElementsByTagName:
1056     return getDOMNodeList(exec,doc.getElementsByTagName(s).get());
1057   case DOMDocument::ImportNode: // DOM2
1058     return getDOMNode(exec,doc.importNode(toNode(args[0]), args[1]->toBoolean(exec), exception));
1059   case DOMDocument::CreateElementNS: // DOM2
1060     return getDOMNode(exec,doc.createElementNS(s, args[1]->toString(exec).domString(), exception));
1061   case DOMDocument::CreateAttributeNS: // DOM2
1062     return getDOMNode(exec,doc.createAttributeNS(s, args[1]->toString(exec).domString(), exception));
1063   case DOMDocument::GetElementsByTagNameNS: // DOM2
1064     return getDOMNodeList(exec,doc.getElementsByTagNameNS(s, args[1]->toString(exec).domString()).get());
1065   case DOMDocument::GetElementById:
1066     return getDOMNode(exec,doc.getElementById(args[0]->toString(exec).domString()));
1067   case DOMDocument::CreateRange:
1068     return getDOMRange(exec,doc.createRange());
1069   case DOMDocument::CreateNodeIterator: {
1070     NodeFilterImpl *filter = 0;
1071     ValueImp *arg2 = args[2];
1072     if (arg2->isObject()) {
1073       ObjectImp *o(static_cast<ObjectImp *>(arg2));
1074       filter = new NodeFilterImpl(new JSNodeFilterCondition(o));
1075     }
1076     return getDOMNodeIterator(exec,doc.createNodeIterator(toNode(args[0]), args[1]->toUInt32(exec),
1077         filter, args[3]->toBoolean(exec), exception));
1078   }
1079   case DOMDocument::CreateTreeWalker: {
1080     NodeFilterImpl *filter = 0;
1081     ValueImp *arg2 = args[2];
1082     if (arg2->isObject()) {
1083       ObjectImp *o(static_cast<ObjectImp *>(arg2));
1084       filter = new NodeFilterImpl(new JSNodeFilterCondition(o));
1085     }
1086     return getDOMTreeWalker(exec,doc.createTreeWalker(toNode(args[0]), args[1]->toUInt32(exec),
1087         filter, args[3]->toBoolean(exec), exception));
1088   }
1089   case DOMDocument::CreateEvent:
1090     return getDOMEvent(exec,doc.createEvent(s, exception));
1091   case DOMDocument::GetOverrideStyle:
1092     if (ElementImpl *element0 = toElement(args[0]))
1093         return getDOMCSSStyleDeclaration(exec,doc.getOverrideStyle(element0, args[1]->toString(exec).domString()));
1094     // FIXME: Is undefined right here, or should we raise an exception?
1095     return jsUndefined();
1096   case DOMDocument::ExecCommand: {
1097     return jsBoolean(doc.execCommand(args[0]->toString(exec).domString(), args[1]->toBoolean(exec), args[2]->toString(exec).domString()));
1098   }
1099   case DOMDocument::QueryCommandEnabled: {
1100     return jsBoolean(doc.queryCommandEnabled(args[0]->toString(exec).domString()));
1101   }
1102   case DOMDocument::QueryCommandIndeterm: {
1103     return jsBoolean(doc.queryCommandIndeterm(args[0]->toString(exec).domString()));
1104   }
1105   case DOMDocument::QueryCommandState: {
1106     return jsBoolean(doc.queryCommandState(args[0]->toString(exec).domString()));
1107   }
1108   case DOMDocument::QueryCommandSupported: {
1109     return jsBoolean(doc.queryCommandSupported(args[0]->toString(exec).domString()));
1110   }
1111   case DOMDocument::QueryCommandValue: {
1112     DOM::DOMString commandValue(doc.queryCommandValue(args[0]->toString(exec).domString()));
1113     // Method returns null DOMString to signal command is unsupported.
1114     // Microsoft documentation for this method says:
1115     // "If not supported [for a command identifier], this method returns a Boolean set to false."
1116     if (commandValue.isNull())
1117         return jsBoolean(false);
1118     else 
1119         return jsString(commandValue);
1120   }
1121   default:
1122     break;
1123   }
1124
1125   return jsUndefined();
1126 }
1127
1128 // -------------------------------------------------------------------------
1129
1130 /* Source for DOMElementProtoTable. Use "make hashtables" to regenerate.
1131 @begin DOMElementProtoTable 17
1132   getAttribute          DOMElement::GetAttribute        DontDelete|Function 1
1133   setAttribute          DOMElement::SetAttribute        DontDelete|Function 2
1134   removeAttribute       DOMElement::RemoveAttribute     DontDelete|Function 1
1135   getAttributeNode      DOMElement::GetAttributeNode    DontDelete|Function 1
1136   setAttributeNode      DOMElement::SetAttributeNode    DontDelete|Function 2
1137   removeAttributeNode   DOMElement::RemoveAttributeNode DontDelete|Function 1
1138   getElementsByTagName  DOMElement::GetElementsByTagName        DontDelete|Function 1
1139   hasAttribute          DOMElement::HasAttribute        DontDelete|Function 1
1140   getAttributeNS        DOMElement::GetAttributeNS      DontDelete|Function 2
1141   setAttributeNS        DOMElement::SetAttributeNS      DontDelete|Function 3
1142   removeAttributeNS     DOMElement::RemoveAttributeNS   DontDelete|Function 2
1143   getAttributeNodeNS    DOMElement::GetAttributeNodeNS  DontDelete|Function 2
1144   setAttributeNodeNS    DOMElement::SetAttributeNodeNS  DontDelete|Function 1
1145   getElementsByTagNameNS DOMElement::GetElementsByTagNameNS     DontDelete|Function 2
1146   hasAttributeNS        DOMElement::HasAttributeNS      DontDelete|Function 2
1147   scrollIntoView        DOMElement::ScrollIntoView      DontDelete|Function 1
1148   focus                 DOMElement::ElementFocus        DontDelete|Function 0
1149   blur                  DOMElement::ElementBlur         DontDelete|Function 0
1150
1151 # extension for Safari RSS
1152   scrollByLines         DOMElement::ScrollByLines       DontDelete|Function 1
1153   scrollByPages         DOMElement::ScrollByPages       DontDelete|Function 1
1154
1155 @end
1156 */
1157 DEFINE_PROTOTYPE("DOMElement",DOMElementProto)
1158 IMPLEMENT_PROTOFUNC(DOMElementProtoFunc)
1159 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMElementProto,DOMElementProtoFunc,DOMNodeProto)
1160
1161 const ClassInfo DOMElement::info = { "Element", &DOMNode::info, &DOMElementTable, 0 };
1162 /* Source for DOMElementTable. Use "make hashtables" to regenerate.
1163 @begin DOMElementTable 3
1164   tagName       DOMElement::TagName                         DontDelete|ReadOnly
1165   style         DOMElement::Style                           DontDelete|ReadOnly
1166 @end
1167 */
1168 DOMElement::DOMElement(ExecState *exec, ElementImpl *e)
1169   : DOMNode(e) 
1170 {
1171   setPrototype(DOMElementProto::self(exec));
1172 }
1173
1174 DOMElement::DOMElement(ElementImpl *e)
1175   : DOMNode(e) 
1176
1177 }
1178
1179 ValueImp *DOMElement::getValueProperty(ExecState *exec, int token) const
1180 {
1181   ElementImpl *element = static_cast<ElementImpl *>(impl());
1182   switch (token) {
1183   case TagName:
1184     return jsStringOrNull(element->nodeName());
1185   case Style:
1186     return getDOMCSSStyleDeclaration(exec, element->style());
1187   default:
1188     assert(0);
1189     return jsUndefined();
1190   }
1191 }
1192
1193 ValueImp *DOMElement::attributeGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
1194 {
1195   DOMElement *thisObj = static_cast<DOMElement *>(slot.slotBase());
1196
1197   ElementImpl *element = static_cast<ElementImpl *>(thisObj->impl());
1198   DOM::DOMString attr = element->getAttribute(propertyName.domString());
1199   return jsStringOrNull(attr);
1200 }
1201
1202 bool DOMElement::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1203 {
1204   const HashEntry* entry = Lookup::findEntry(&DOMElementTable, propertyName);
1205   if (entry) {
1206     slot.setStaticEntry(this, entry, staticValueGetter<DOMElement>);
1207     return true;
1208   }
1209
1210   // We have to check in DOMNode before giving access to attributes, otherwise
1211   // onload="..." would make onload return the string (attribute value) instead of
1212   // the listener object (function).
1213   if (DOMNode::getOwnPropertySlot(exec, propertyName, slot))
1214     return true;
1215
1216   ValueImp *proto = prototype();
1217   if (proto->isObject() && static_cast<ObjectImp *>(proto)->hasProperty(exec, propertyName))
1218     return false;
1219
1220   ElementImpl &element = *static_cast<ElementImpl *>(impl());
1221
1222   // FIXME: do we really want to do this attribute lookup thing? Mozilla doesn't do it,
1223   // and it seems like it could interfere with XBL.
1224   DOM::DOMString attr = element.getAttribute(propertyName.domString());
1225   if (!attr.isNull()) {
1226     slot.setCustom(this, attributeGetter);
1227     return true;
1228   }
1229
1230   return false;
1231 }
1232
1233 ValueImp *DOMElementProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
1234 {
1235   if (!thisObj->inherits(&KJS::DOMNode::info))
1236     return throwError(exec, TypeError);
1237   DOMExceptionTranslator exception(exec);
1238   NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl();
1239   ElementImpl &element = static_cast<ElementImpl &>(node);
1240
1241   switch(id) {
1242     case DOMElement::GetAttribute:
1243       // jsStringOrNull should be used here, since if the attribute isn't present at all, you should
1244       // return null and not "".
1245       return jsStringOrNull(element.getAttribute(args[0]->toString(exec).domString()));
1246     case DOMElement::SetAttribute:
1247       element.setAttribute(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception);
1248       return jsUndefined();
1249     case DOMElement::RemoveAttribute:
1250       element.removeAttribute(args[0]->toString(exec).domString(), exception);
1251       return jsUndefined();
1252     case DOMElement::GetAttributeNode:
1253       return getDOMNode(exec,element.getAttributeNode(args[0]->toString(exec).domString()));
1254     case DOMElement::SetAttributeNode:
1255       return getDOMNode(exec,element.setAttributeNode(toAttr(args[0]), exception).get());
1256     case DOMElement::RemoveAttributeNode:
1257       return getDOMNode(exec,element.removeAttributeNode(toAttr(args[0]), exception).get());
1258     case DOMElement::GetElementsByTagName:
1259       return getDOMNodeList(exec, element.getElementsByTagName(args[0]->toString(exec).domString()).get());
1260     case DOMElement::HasAttribute: // DOM2
1261       return jsBoolean(element.hasAttribute(args[0]->toString(exec).domString()));
1262     case DOMElement::GetAttributeNS: // DOM2
1263       return jsString(element.getAttributeNS(args[0]->toString(exec).domString(),args[1]->toString(exec).domString()).domString());
1264     case DOMElement::SetAttributeNS: // DOM2
1265       element.setAttributeNS(valueToStringWithNullCheck(exec, args[0]), args[1]->toString(exec).domString(), args[2]->toString(exec).domString(), exception);
1266       return jsUndefined();
1267     case DOMElement::RemoveAttributeNS: // DOM2
1268       element.removeAttributeNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception);
1269       return jsUndefined();
1270     case DOMElement::GetAttributeNodeNS: // DOM2
1271       return getDOMNode(exec,element.getAttributeNodeNS(args[0]->toString(exec).domString(),args[1]->toString(exec).domString()));
1272     case DOMElement::SetAttributeNodeNS: // DOM2
1273       return getDOMNode(exec, element.setAttributeNodeNS(toAttr(args[0]), exception).get());
1274     case DOMElement::GetElementsByTagNameNS: // DOM2
1275       return getDOMNodeList(exec, element.getElementsByTagNameNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString()).get());
1276     case DOMElement::HasAttributeNS: // DOM2
1277       return jsBoolean(element.hasAttributeNS(args[0]->toString(exec).domString(),args[1]->toString(exec).domString()));
1278     case DOMElement::ScrollIntoView: 
1279         element.scrollIntoView(args[0]->isUndefinedOrNull() || args[0]->toBoolean(exec));
1280         return jsUndefined();
1281     case DOMElement::ScrollByLines:
1282     case DOMElement::ScrollByPages:
1283       if (DocumentImpl* doc = element.getDocument()) {
1284         doc->updateLayoutIgnorePendingStylesheets();
1285         if (RenderObject *rend = element.renderer())
1286           if (rend->hasOverflowClip()) {
1287             KWQScrollDirection direction = KWQScrollDown;
1288             int multiplier = args[0]->toInt32(exec);
1289             if (multiplier < 0) {
1290                 direction = KWQScrollUp;
1291                 multiplier = -multiplier;
1292             }
1293             KWQScrollGranularity granularity = id == DOMElement::ScrollByLines ? KWQScrollLine : KWQScrollPage;
1294             rend->layer()->scroll(direction, granularity, multiplier);
1295           }
1296       }
1297       return jsUndefined();
1298     case DOMElement::ElementFocus:
1299         element.focus();
1300         return jsUndefined();
1301     case DOMElement::ElementBlur:
1302         element.blur();
1303         return jsUndefined();
1304     default:
1305       return jsUndefined();
1306     }
1307 }
1308
1309 ElementImpl *toElement(ValueImp *val)
1310 {
1311     if (!val || !val->isObject(&DOMElement::info))
1312         return 0;
1313     return static_cast<ElementImpl *>(static_cast<DOMElement *>(val)->impl());
1314 }
1315
1316 // -------------------------------------------------------------------------
1317
1318 /* Source for DOMDOMImplementationProtoTable. Use "make hashtables" to regenerate.
1319 @begin DOMDOMImplementationProtoTable 5
1320   hasFeature            DOMDOMImplementation::HasFeature                DontDelete|Function 2
1321 # DOM2
1322   createCSSStyleSheet   DOMDOMImplementation::CreateCSSStyleSheet       DontDelete|Function 2
1323   createDocumentType    DOMDOMImplementation::CreateDocumentType        DontDelete|Function 3
1324   createDocument        DOMDOMImplementation::CreateDocument            DontDelete|Function 3
1325   createHTMLDocument    DOMDOMImplementation::CreateHTMLDocument        DontDelete|Function 1
1326 @end
1327 */
1328 DEFINE_PROTOTYPE("DOMImplementation",DOMDOMImplementationProto)
1329 IMPLEMENT_PROTOFUNC(DOMDOMImplementationProtoFunc)
1330 IMPLEMENT_PROTOTYPE(DOMDOMImplementationProto,DOMDOMImplementationProtoFunc)
1331
1332 const ClassInfo DOMDOMImplementation::info = { "DOMImplementation", 0, 0, 0 };
1333
1334 DOMDOMImplementation::DOMDOMImplementation(ExecState *exec, DOMImplementationImpl *i)
1335   : m_impl(i) 
1336
1337   setPrototype(DOMDOMImplementationProto::self(exec));
1338 }
1339
1340 DOMDOMImplementation::~DOMDOMImplementation()
1341 {
1342   ScriptInterpreter::forgetDOMObject(m_impl.get());
1343 }
1344
1345 ValueImp *DOMDOMImplementationProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
1346 {
1347   if (!thisObj->inherits(&KJS::DOMDOMImplementation::info))
1348     return throwError(exec, TypeError);
1349   DOMExceptionTranslator exception(exec);
1350   DOMImplementationImpl &implementation = *static_cast<DOMDOMImplementation *>(thisObj)->impl();
1351
1352   switch(id) {
1353   case DOMDOMImplementation::HasFeature:
1354     return jsBoolean(implementation.hasFeature(args[0]->toString(exec).domString(),
1355         args[1]->isUndefinedOrNull() ? DOMString() : args[1]->toString(exec).domString()));
1356   case DOMDOMImplementation::CreateDocumentType: // DOM2
1357     return getDOMNode(exec, implementation.createDocumentType(args[0]->toString(exec).domString(),
1358         args[1]->toString(exec).domString(), args[2]->toString(exec).domString(), exception));
1359   case DOMDOMImplementation::CreateDocument: // DOM2
1360     return getDOMNode(exec, implementation.createDocument(args[0]->toString(exec).domString(),
1361         args[1]->toString(exec).domString(), toDocumentType(args[2]), exception));
1362   case DOMDOMImplementation::CreateCSSStyleSheet: // DOM2
1363     return getDOMStyleSheet(exec, implementation.createCSSStyleSheet(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception));
1364   case DOMDOMImplementation::CreateHTMLDocument: // DOM2-HTML
1365     return getDOMNode(exec, implementation.createHTMLDocument(args[0]->toString(exec).domString()));
1366   default:
1367     break;
1368   }
1369   return jsUndefined();
1370 }
1371
1372 // -------------------------------------------------------------------------
1373
1374 const ClassInfo DOMDocumentType::info = { "DocumentType", &DOMNode::info, &DOMDocumentTypeTable, 0 };
1375
1376 /* Source for DOMDocumentTypeTable. Use "make hashtables" to regenerate.
1377 @begin DOMDocumentTypeTable 6
1378   name                  DOMDocumentType::Name           DontDelete|ReadOnly
1379   entities              DOMDocumentType::Entities       DontDelete|ReadOnly
1380   notations             DOMDocumentType::Notations      DontDelete|ReadOnly
1381 # DOM2
1382   publicId              DOMDocumentType::PublicId       DontDelete|ReadOnly
1383   systemId              DOMDocumentType::SystemId       DontDelete|ReadOnly
1384   internalSubset        DOMDocumentType::InternalSubset DontDelete|ReadOnly
1385 @end
1386 */
1387 DOMDocumentType::DOMDocumentType(ExecState *exec, DocumentTypeImpl *dt)
1388   : DOMNode( /*### no proto yet*/exec, dt ) { }
1389
1390 bool DOMDocumentType::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1391 {
1392   return getStaticValueSlot<DOMDocumentType, DOMNode>(exec, &DOMDocumentTypeTable, this, propertyName, slot);
1393 }
1394
1395 ValueImp *DOMDocumentType::getValueProperty(ExecState *exec, int token) const
1396 {
1397   DocumentTypeImpl &type = *static_cast<DocumentTypeImpl *>(impl());
1398   switch (token) {
1399   case Name:
1400     return jsStringOrNull(type.name());
1401   case Entities:
1402     return getDOMNamedNodeMap(exec,type.entities());
1403   case Notations:
1404     return getDOMNamedNodeMap(exec,type.notations());
1405   case PublicId: // DOM2
1406     return jsStringOrNull(type.publicId());
1407   case SystemId: // DOM2
1408     return jsStringOrNull(type.systemId());
1409   case InternalSubset: // DOM2
1410     return jsStringOrNull(type.internalSubset());
1411   default:
1412     kdWarning() << "DOMDocumentType::getValueProperty unhandled token " << token << endl;
1413     return NULL;
1414   }
1415 }
1416
1417 DocumentTypeImpl *toDocumentType(ValueImp *val)
1418 {
1419     if (!val || !val->isObject(&DOMDocumentType::info))
1420         return 0;
1421     return static_cast<DocumentTypeImpl *>(static_cast<DOMNode *>(val)->impl());
1422 }
1423
1424 // -------------------------------------------------------------------------
1425
1426 /* Source for DOMNamedNodeMapProtoTable. Use "make hashtables" to regenerate.
1427 @begin DOMNamedNodeMapProtoTable 7
1428   getNamedItem          DOMNamedNodeMap::GetNamedItem           DontDelete|Function 1
1429   setNamedItem          DOMNamedNodeMap::SetNamedItem           DontDelete|Function 1
1430   removeNamedItem       DOMNamedNodeMap::RemoveNamedItem        DontDelete|Function 1
1431   item                  DOMNamedNodeMap::Item                   DontDelete|Function 1
1432 # DOM2
1433   getNamedItemNS        DOMNamedNodeMap::GetNamedItemNS         DontDelete|Function 2
1434   setNamedItemNS        DOMNamedNodeMap::SetNamedItemNS         DontDelete|Function 1
1435   removeNamedItemNS     DOMNamedNodeMap::RemoveNamedItemNS      DontDelete|Function 2
1436 @end
1437 */
1438 DEFINE_PROTOTYPE("NamedNodeMap", DOMNamedNodeMapProto)
1439 IMPLEMENT_PROTOFUNC(DOMNamedNodeMapProtoFunc)
1440 IMPLEMENT_PROTOTYPE(DOMNamedNodeMapProto,DOMNamedNodeMapProtoFunc)
1441
1442 const ClassInfo DOMNamedNodeMap::info = { "NamedNodeMap", 0, 0, 0 };
1443
1444 DOMNamedNodeMap::DOMNamedNodeMap(ExecState *exec, NamedNodeMapImpl *m)
1445   : m_impl(m) 
1446
1447   setPrototype(DOMNamedNodeMapProto::self(exec));
1448 }
1449
1450 DOMNamedNodeMap::~DOMNamedNodeMap()
1451 {
1452   ScriptInterpreter::forgetDOMObject(m_impl.get());
1453 }
1454
1455 ValueImp *DOMNamedNodeMap::lengthGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
1456 {
1457   DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
1458   return jsNumber(thisObj->m_impl->length());
1459 }
1460
1461 ValueImp *DOMNamedNodeMap::indexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
1462 {
1463   DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
1464   return getDOMNode(exec, thisObj->m_impl->item(slot.index()));
1465 }
1466
1467 ValueImp *DOMNamedNodeMap::nameGetter(ExecState *exec, const Identifier& propertyName, const PropertySlot& slot)
1468 {
1469   DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
1470   return getDOMNode(exec, thisObj->m_impl->getNamedItem(propertyName.domString()));
1471 }
1472
1473 bool DOMNamedNodeMap::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
1474 {
1475   if (propertyName == lengthPropertyName) {
1476       slot.setCustom(this, lengthGetter);
1477       return true;
1478   } else {
1479     // Look in the prototype (for functions) before assuming it's an item's name
1480     ValueImp *proto = prototype();
1481     if (proto->isObject() && static_cast<ObjectImp *>(proto)->hasProperty(exec, propertyName))
1482       return false;
1483
1484     // name or index ?
1485     bool ok;
1486     unsigned idx = propertyName.toUInt32(&ok);
1487     if (ok && idx < m_impl->length()) {
1488       slot.setCustomIndex(this, idx, indexGetter);
1489       return true;
1490     }
1491
1492     if (m_impl->getNamedItem(propertyName.domString())) {
1493       slot.setCustom(this, nameGetter);
1494       return true;
1495     }
1496   }
1497
1498   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
1499 }
1500
1501 ValueImp *DOMNamedNodeMapProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
1502 {
1503   if (!thisObj->inherits(&KJS::DOMNamedNodeMap::info))
1504     return throwError(exec, TypeError);
1505   DOMExceptionTranslator exception(exec);
1506   NamedNodeMapImpl &map = *static_cast<DOMNamedNodeMap *>(thisObj)->impl();
1507
1508   switch(id) {
1509     case DOMNamedNodeMap::GetNamedItem:
1510       return getDOMNode(exec, map.getNamedItem(args[0]->toString(exec).domString()));
1511     case DOMNamedNodeMap::SetNamedItem:
1512       return getDOMNode(exec, map.setNamedItem(toNode(args[0]), exception).get());
1513     case DOMNamedNodeMap::RemoveNamedItem:
1514       return getDOMNode(exec, map.removeNamedItem(args[0]->toString(exec).domString(), exception).get());
1515     case DOMNamedNodeMap::Item:
1516       return getDOMNode(exec, map.item(args[0]->toInt32(exec)));
1517     case DOMNamedNodeMap::GetNamedItemNS: // DOM2
1518       return getDOMNode(exec, map.getNamedItemNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString()));
1519     case DOMNamedNodeMap::SetNamedItemNS: // DOM2
1520       return getDOMNode(exec, map.setNamedItemNS(toNode(args[0]), exception).get());
1521     case DOMNamedNodeMap::RemoveNamedItemNS: // DOM2
1522       return getDOMNode(exec, map.removeNamedItemNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception).get());
1523     default:
1524       break;
1525   }
1526
1527   return jsUndefined();
1528 }
1529
1530 // -------------------------------------------------------------------------
1531
1532 const ClassInfo DOMProcessingInstruction::info = { "ProcessingInstruction", &DOMNode::info, &DOMProcessingInstructionTable, 0 };
1533
1534 /* Source for DOMProcessingInstructionTable. Use "make hashtables" to regenerate.
1535 @begin DOMProcessingInstructionTable 3
1536   target        DOMProcessingInstruction::Target        DontDelete|ReadOnly
1537   data          DOMProcessingInstruction::Data          DontDelete
1538   sheet         DOMProcessingInstruction::Sheet         DontDelete|ReadOnly
1539 @end
1540 */
1541
1542 DOMProcessingInstruction::DOMProcessingInstruction(ExecState *exec, ProcessingInstructionImpl *i)
1543   : DOMNode(exec, i)
1544 {
1545 }
1546
1547 bool DOMProcessingInstruction::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1548 {
1549   return getStaticValueSlot<DOMProcessingInstruction, DOMNode>(exec, &DOMProcessingInstructionTable, this, propertyName, slot);
1550 }
1551
1552 ValueImp *DOMProcessingInstruction::getValueProperty(ExecState *exec, int token) const
1553 {
1554   ProcessingInstructionImpl *pi = static_cast<ProcessingInstructionImpl *>(impl());
1555   switch (token) {
1556   case Target:
1557     return jsStringOrNull(pi->target());
1558   case Data:
1559     return jsStringOrNull(pi->data());
1560   case Sheet:
1561     return getDOMStyleSheet(exec,pi->sheet());
1562   default:
1563     kdWarning() << "DOMProcessingInstruction::getValueProperty unhandled token " << token << endl;
1564     return NULL;
1565   }
1566 }
1567
1568 void DOMProcessingInstruction::put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr)
1569 {
1570   ProcessingInstructionImpl *pi = static_cast<ProcessingInstructionImpl *>(impl());
1571   DOMExceptionTranslator exception(exec);
1572   // Not worth using the hashtable for this one ;)
1573   if (propertyName == "data")
1574     pi->setData(value->toString(exec).domString(), exception);
1575   else
1576     DOMNode::put(exec, propertyName, value, attr);
1577 }
1578
1579 // -------------------------------------------------------------------------
1580
1581 const ClassInfo DOMNotation::info = { "Notation", &DOMNode::info, &DOMNotationTable, 0 };
1582
1583 /* Source for DOMNotationTable. Use "make hashtables" to regenerate.
1584 @begin DOMNotationTable 2
1585   publicId              DOMNotation::PublicId   DontDelete|ReadOnly
1586   systemId              DOMNotation::SystemId   DontDelete|ReadOnly
1587 @end
1588 */
1589
1590 DOMNotation::DOMNotation(ExecState *exec, NotationImpl *n)
1591   : DOMNode(exec, n)
1592 {
1593 }
1594
1595 bool DOMNotation::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1596 {
1597   return getStaticValueSlot<DOMNotation, DOMNode>(exec, &DOMNotationTable, this, propertyName, slot);
1598 }
1599
1600 ValueImp *DOMNotation::getValueProperty(ExecState *, int token) const
1601 {
1602   switch (token) {
1603   case PublicId:
1604     return jsStringOrNull(static_cast<NotationImpl *>(impl())->publicId());
1605   case SystemId:
1606     return jsStringOrNull(static_cast<NotationImpl *>(impl())->systemId());
1607   default:
1608     kdWarning() << "DOMNotation::getValueProperty unhandled token " << token << endl;
1609     return NULL;
1610   }
1611 }
1612
1613 // -------------------------------------------------------------------------
1614
1615 const ClassInfo DOMEntity::info = { "Entity", &DOMNode::info, 0, 0 };
1616
1617 /* Source for DOMEntityTable. Use "make hashtables" to regenerate.
1618 @begin DOMEntityTable 2
1619   publicId              DOMEntity::PublicId             DontDelete|ReadOnly
1620   systemId              DOMEntity::SystemId             DontDelete|ReadOnly
1621   notationName          DOMEntity::NotationName DontDelete|ReadOnly
1622 @end
1623 */
1624
1625 DOMEntity::DOMEntity(ExecState *exec, EntityImpl *e)
1626   : DOMNode(exec, e)
1627 {
1628 }
1629
1630 bool DOMEntity::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1631 {
1632   return getStaticValueSlot<DOMEntity, DOMNode>(exec, &DOMEntityTable, this, propertyName, slot);
1633 }
1634
1635 ValueImp *DOMEntity::getValueProperty(ExecState *, int token) const
1636 {
1637   switch (token) {
1638   case PublicId:
1639     return jsStringOrNull(static_cast<EntityImpl *>(impl())->publicId());
1640   case SystemId:
1641     return jsStringOrNull(static_cast<EntityImpl *>(impl())->systemId());
1642   case NotationName:
1643     return jsStringOrNull(static_cast<EntityImpl *>(impl())->notationName());
1644   default:
1645     kdWarning() << "DOMEntity::getValueProperty unhandled token " << token << endl;
1646     return NULL;
1647   }
1648 }
1649
1650 // -------------------------------------------------------------------------
1651
1652 ValueImp *getDOMDocumentNode(ExecState *exec, DocumentImpl *n)
1653 {
1654   DOMDocument *ret = 0;
1655   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
1656
1657   if ((ret = static_cast<DOMDocument *>(interp->getDOMObject(n))))
1658     return ret;
1659
1660   if (n->isHTMLDocument())
1661     ret = new HTMLDocument(exec, static_cast<HTMLDocumentImpl *>(n));
1662   else
1663     ret = new DOMDocument(exec, n);
1664
1665   // Make sure the document is kept around by the window object, and works right with the
1666   // back/forward cache.
1667   if (n->view())
1668     Window::retrieveWindow(n->view()->part())->putDirect("document", ret, DontDelete|ReadOnly);
1669
1670   interp->putDOMObject(n, ret);
1671
1672   return ret;
1673 }
1674
1675 bool checkNodeSecurity(ExecState *exec, NodeImpl *n)
1676 {
1677   if (!n) 
1678     return false;
1679
1680   // Check to see if the currently executing interpreter is allowed to access the specified node
1681   KHTMLPart *part = n->getDocument()->part();
1682   if (!part)
1683     return false;
1684   Window *win = Window::retrieveWindow(part);
1685   return win && win->isSafeScript(exec);
1686 }
1687
1688 ValueImp *getDOMNode(ExecState *exec, NodeImpl *n)
1689 {
1690   DOMNode *ret = 0;
1691   if (!n)
1692     return jsNull();
1693   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
1694   DocumentImpl *doc = n->getDocument();
1695
1696   if ((ret = interp->getDOMNodeForDocument(doc, n)))
1697     return ret;
1698
1699   switch (n->nodeType()) {
1700     case DOM::Node::ELEMENT_NODE:
1701       if (n->isHTMLElement())
1702         ret = new HTMLElement(exec, static_cast<HTMLElementImpl *>(n));
1703       else
1704         ret = new DOMElement(exec, static_cast<ElementImpl *>(n));
1705       break;
1706     case DOM::Node::ATTRIBUTE_NODE:
1707       ret = new DOMAttr(exec, static_cast<AttrImpl *>(n));
1708       break;
1709     case DOM::Node::TEXT_NODE:
1710     case DOM::Node::CDATA_SECTION_NODE:
1711       ret = new DOMText(exec, static_cast<TextImpl *>(n));
1712       break;
1713     case DOM::Node::ENTITY_NODE:
1714       ret = new DOMEntity(exec, static_cast<EntityImpl *>(n));
1715       break;
1716     case DOM::Node::PROCESSING_INSTRUCTION_NODE:
1717       ret = new DOMProcessingInstruction(exec, static_cast<ProcessingInstructionImpl *>(n));
1718       break;
1719     case DOM::Node::COMMENT_NODE:
1720       ret = new DOMCharacterData(exec, static_cast<CharacterDataImpl *>(n));
1721       break;
1722     case DOM::Node::DOCUMENT_NODE:
1723       // we don't want to cache the document itself in the per-document dictionary
1724       return getDOMDocumentNode(exec, static_cast<DocumentImpl *>(n));
1725     case DOM::Node::DOCUMENT_TYPE_NODE:
1726       ret = new DOMDocumentType(exec, static_cast<DocumentTypeImpl *>(n));
1727       break;
1728     case DOM::Node::NOTATION_NODE:
1729       ret = new DOMNotation(exec, static_cast<NotationImpl *>(n));
1730       break;
1731     case DOM::Node::DOCUMENT_FRAGMENT_NODE:
1732     case DOM::Node::ENTITY_REFERENCE_NODE:
1733     default:
1734       ret = new DOMNode(exec, n);
1735   }
1736
1737   interp->putDOMNodeForDocument(doc, n, ret);
1738
1739   return ret;
1740 }
1741
1742 ValueImp *getDOMNamedNodeMap(ExecState *exec, NamedNodeMapImpl *m)
1743 {
1744   return cacheDOMObject<NamedNodeMapImpl, DOMNamedNodeMap>(exec, m);
1745 }
1746
1747 ValueImp *getRuntimeObject(ExecState *exec, NodeImpl *n)
1748 {
1749     if (!n)
1750         return 0;
1751
1752     if (n->hasTagName(appletTag)) {
1753         HTMLAppletElementImpl *appletElement = static_cast<HTMLAppletElementImpl *>(n);
1754         if (appletElement->getAppletInstance())
1755             // The instance is owned by the applet element.
1756             return new RuntimeObjectImp(appletElement->getAppletInstance(), false);
1757     }
1758     else if (n->hasTagName(embedTag)) {
1759         HTMLEmbedElementImpl *embedElement = static_cast<HTMLEmbedElementImpl *>(n);
1760         if (embedElement->getEmbedInstance())
1761             return new RuntimeObjectImp(embedElement->getEmbedInstance(), false);
1762     }
1763     else if (n->hasTagName(objectTag)) {
1764         HTMLObjectElementImpl *objectElement = static_cast<HTMLObjectElementImpl *>(n);
1765         if (objectElement->getObjectInstance())
1766             return new RuntimeObjectImp(objectElement->getObjectInstance(), false);
1767     }
1768     
1769     // If we don't have a runtime object return 0.
1770     return 0;
1771 }
1772
1773 ValueImp *getDOMNodeList(ExecState *exec, NodeListImpl *l)
1774 {
1775   return cacheDOMObject<NodeListImpl, DOMNodeList>(exec, l);
1776 }
1777
1778 ValueImp *getDOMDOMImplementation(ExecState *exec, DOMImplementationImpl *i)
1779 {
1780   return cacheDOMObject<DOMImplementationImpl, DOMDOMImplementation>(exec, i);
1781 }
1782
1783 // -------------------------------------------------------------------------
1784
1785 const ClassInfo NodeConstructor::info = { "NodeConstructor", 0, &NodeConstructorTable, 0 };
1786 /* Source for NodeConstructorTable. Use "make hashtables" to regenerate.
1787 @begin NodeConstructorTable 11
1788   ELEMENT_NODE          DOM::Node::ELEMENT_NODE         DontDelete|ReadOnly
1789   ATTRIBUTE_NODE        DOM::Node::ATTRIBUTE_NODE               DontDelete|ReadOnly
1790   TEXT_NODE             DOM::Node::TEXT_NODE            DontDelete|ReadOnly
1791   CDATA_SECTION_NODE    DOM::Node::CDATA_SECTION_NODE   DontDelete|ReadOnly
1792   ENTITY_REFERENCE_NODE DOM::Node::ENTITY_REFERENCE_NODE        DontDelete|ReadOnly
1793   ENTITY_NODE           DOM::Node::ENTITY_NODE          DontDelete|ReadOnly
1794   PROCESSING_INSTRUCTION_NODE DOM::Node::PROCESSING_INSTRUCTION_NODE DontDelete|ReadOnly
1795   COMMENT_NODE          DOM::Node::COMMENT_NODE         DontDelete|ReadOnly
1796   DOCUMENT_NODE         DOM::Node::DOCUMENT_NODE                DontDelete|ReadOnly
1797   DOCUMENT_TYPE_NODE    DOM::Node::DOCUMENT_TYPE_NODE   DontDelete|ReadOnly
1798   DOCUMENT_FRAGMENT_NODE DOM::Node::DOCUMENT_FRAGMENT_NODE      DontDelete|ReadOnly
1799   NOTATION_NODE         DOM::Node::NOTATION_NODE                DontDelete|ReadOnly
1800 @end
1801 */
1802 bool NodeConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1803 {
1804   return getStaticValueSlot<NodeConstructor, DOMObject>(exec, &NodeConstructorTable, this, propertyName, slot);
1805 }
1806
1807 ValueImp *NodeConstructor::getValueProperty(ExecState *, int token) const
1808 {
1809   // We use the token as the value to return directly
1810   return jsNumber(token);
1811 }
1812
1813 ObjectImp *getNodeConstructor(ExecState *exec)
1814 {
1815   return cacheGlobalObject<NodeConstructor>(exec, "[[node.constructor]]");
1816 }
1817
1818 // -------------------------------------------------------------------------
1819
1820 const ClassInfo DOMExceptionConstructor::info = { "DOMExceptionConstructor", 0, 0, 0 };
1821
1822 /* Source for DOMExceptionConstructorTable. Use "make hashtables" to regenerate.
1823 @begin DOMExceptionConstructorTable 15
1824   INDEX_SIZE_ERR                DOM::DOMException::INDEX_SIZE_ERR               DontDelete|ReadOnly
1825   DOMSTRING_SIZE_ERR            DOM::DOMException::DOMSTRING_SIZE_ERR   DontDelete|ReadOnly
1826   HIERARCHY_REQUEST_ERR         DOM::DOMException::HIERARCHY_REQUEST_ERR        DontDelete|ReadOnly
1827   WRONG_DOCUMENT_ERR            DOM::DOMException::WRONG_DOCUMENT_ERR   DontDelete|ReadOnly
1828   INVALID_CHARACTER_ERR         DOM::DOMException::INVALID_CHARACTER_ERR        DontDelete|ReadOnly
1829   NO_DATA_ALLOWED_ERR           DOM::DOMException::NO_DATA_ALLOWED_ERR  DontDelete|ReadOnly
1830   NO_MODIFICATION_ALLOWED_ERR   DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR  DontDelete|ReadOnly
1831   NOT_FOUND_ERR                 DOM::DOMException::NOT_FOUND_ERR                DontDelete|ReadOnly
1832   NOT_SUPPORTED_ERR             DOM::DOMException::NOT_SUPPORTED_ERR    DontDelete|ReadOnly
1833   INUSE_ATTRIBUTE_ERR           DOM::DOMException::INUSE_ATTRIBUTE_ERR  DontDelete|ReadOnly
1834   INVALID_STATE_ERR             DOM::DOMException::INVALID_STATE_ERR    DontDelete|ReadOnly
1835   SYNTAX_ERR                    DOM::DOMException::SYNTAX_ERR           DontDelete|ReadOnly
1836   INVALID_MODIFICATION_ERR      DOM::DOMException::INVALID_MODIFICATION_ERR     DontDelete|ReadOnly
1837   NAMESPACE_ERR                 DOM::DOMException::NAMESPACE_ERR                DontDelete|ReadOnly
1838   INVALID_ACCESS_ERR            DOM::DOMException::INVALID_ACCESS_ERR   DontDelete|ReadOnly
1839 @end
1840 */
1841
1842 bool DOMExceptionConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1843 {
1844   return getStaticValueSlot<DOMExceptionConstructor, DOMObject>(exec, &DOMExceptionConstructorTable, this, propertyName, slot);
1845 }
1846
1847 ValueImp *DOMExceptionConstructor::getValueProperty(ExecState *, int token) const
1848 {
1849   // We use the token as the value to return directly
1850   return jsNumber(token);
1851 }
1852
1853 ObjectImp *getDOMExceptionConstructor(ExecState *exec)
1854 {
1855   return cacheGlobalObject<DOMExceptionConstructor>(exec, "[[DOMException.constructor]]");
1856 }
1857
1858 // -------------------------------------------------------------------------
1859
1860 // Such a collection is usually very short-lived, it only exists
1861 // for constructs like document.forms.<name>[1],
1862 // so it shouldn't be a problem that it's storing all the nodes (with the same name). (David)
1863 DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState *, const QValueList< RefPtr<NodeImpl> >& nodes )
1864   : m_nodes(nodes)
1865 {
1866 }
1867
1868 ValueImp *DOMNamedNodesCollection::lengthGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
1869 {
1870   DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection *>(slot.slotBase());
1871   return jsNumber(thisObj->m_nodes.count());
1872 }
1873
1874 ValueImp *DOMNamedNodesCollection::indexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
1875 {
1876   DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection *>(slot.slotBase());
1877   return getDOMNode(exec, thisObj->m_nodes[slot.index()].get());
1878 }
1879
1880 bool DOMNamedNodesCollection::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1881 {
1882   if (propertyName == lengthPropertyName) {
1883     slot.setCustom(this, lengthGetter);
1884     return true;
1885   }
1886
1887   // array index ?
1888   bool ok;
1889   unsigned idx = propertyName.toUInt32(&ok);
1890   if (ok && idx < m_nodes.count()) {
1891     slot.setCustomIndex(this, idx, indexGetter);
1892     return true;
1893   }
1894
1895   // For IE compatibility, we need to be able to look up elements in a
1896   // document.formName.name result by id as well as be index.
1897
1898   QValueListConstIterator< RefPtr<NodeImpl> > end = m_nodes.end();
1899   int i = 0;
1900   for (QValueListConstIterator< RefPtr<NodeImpl> > it = m_nodes.begin(); it != end; ++it, ++i) {
1901     NodeImpl *node = (*it).get();
1902     if (node->hasAttributes() &&
1903         node->attributes()->id() == propertyName.domString()) {
1904       slot.setCustomIndex(this, i, indexGetter);
1905       return true;
1906     }
1907   }
1908
1909   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
1910 }
1911
1912 // -------------------------------------------------------------------------
1913
1914 const ClassInfo DOMCharacterData::info = { "CharacterImp",
1915                                           &DOMNode::info, &DOMCharacterDataTable, 0 };
1916 /*
1917 @begin DOMCharacterDataTable 2
1918   data          DOMCharacterData::Data          DontDelete
1919   length        DOMCharacterData::Length        DontDelete|ReadOnly
1920 @end
1921 @begin DOMCharacterDataProtoTable 7
1922   substringData DOMCharacterData::SubstringData DontDelete|Function 2
1923   appendData    DOMCharacterData::AppendData    DontDelete|Function 1
1924   insertData    DOMCharacterData::InsertData    DontDelete|Function 2
1925   deleteData    DOMCharacterData::DeleteData    DontDelete|Function 2
1926   replaceData   DOMCharacterData::ReplaceData   DontDelete|Function 2
1927 @end
1928 */
1929 DEFINE_PROTOTYPE("DOMCharacterData",DOMCharacterDataProto)
1930 IMPLEMENT_PROTOFUNC(DOMCharacterDataProtoFunc)
1931 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMCharacterDataProto,DOMCharacterDataProtoFunc, DOMNodeProto)
1932
1933 DOMCharacterData::DOMCharacterData(ExecState *exec, CharacterDataImpl *d)
1934  : DOMNode(d) 
1935 {
1936   setPrototype(DOMCharacterDataProto::self(exec));
1937 }
1938
1939 DOMCharacterData::DOMCharacterData(CharacterDataImpl *d)
1940  : DOMNode(d) 
1941 {
1942 }
1943
1944 bool DOMCharacterData::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1945 {
1946   return getStaticValueSlot<DOMCharacterData, DOMNode>(exec, &DOMCharacterDataTable, this, propertyName, slot);
1947 }
1948
1949 ValueImp *DOMCharacterData::getValueProperty(ExecState *, int token) const
1950 {
1951   CharacterDataImpl &data = *static_cast<CharacterDataImpl *>(impl());
1952   switch (token) {
1953   case Data:
1954     return jsString(data.data());
1955   case Length:
1956     return jsNumber(data.length());
1957   default:
1958     kdWarning() << "Unhandled token in DOMCharacterData::getValueProperty : " << token << endl;
1959     return NULL;
1960   }
1961 }
1962
1963 void DOMCharacterData::put(ExecState *exec, const Identifier &propertyName, ValueImp *value, int attr)
1964 {
1965   DOMExceptionTranslator exception(exec);
1966   if (propertyName == "data")
1967     static_cast<CharacterDataImpl *>(impl())->setData(value->toString(exec).domString(), exception);
1968   else
1969     DOMNode::put(exec, propertyName,value,attr);
1970 }
1971
1972 ValueImp *DOMCharacterDataProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
1973 {
1974   if (!thisObj->inherits(&KJS::DOMCharacterData::info))
1975     return throwError(exec, TypeError);
1976   DOMExceptionTranslator exception(exec);
1977   CharacterDataImpl &data = *static_cast<CharacterDataImpl *>(static_cast<DOMCharacterData *>(thisObj)->impl());
1978   switch(id) {
1979     case DOMCharacterData::SubstringData: {
1980       const int count = args[1]->toInt32(exec);
1981       if (count < 0)
1982         setDOMException(exec, DOMException::INDEX_SIZE_ERR);
1983       else
1984         return jsStringOrNull(data.substringData(args[0]->toInt32(exec), count, exception));
1985     }
1986     case DOMCharacterData::AppendData:
1987       data.appendData(args[0]->toString(exec).domString(), exception);
1988       return jsUndefined();
1989     case DOMCharacterData::InsertData:
1990       data.insertData(args[0]->toInt32(exec), args[1]->toString(exec).domString(), exception);
1991       return jsUndefined();
1992     case DOMCharacterData::DeleteData: {
1993       const int count = args[1]->toInt32(exec);
1994       if (count < 0)
1995         setDOMException(exec, DOMException::INDEX_SIZE_ERR);
1996       else
1997         data.deleteData(args[0]->toInt32(exec), count, exception);
1998       return jsUndefined();
1999     }
2000     case DOMCharacterData::ReplaceData: {
2001       const int count = args[1]->toInt32(exec);
2002       if (count < 0)
2003         setDOMException(exec, DOMException::INDEX_SIZE_ERR);
2004       else
2005         data.replaceData(args[0]->toInt32(exec), count, args[2]->toString(exec).domString(), exception);
2006       return jsUndefined();
2007     }
2008     default:
2009       return jsUndefined();
2010   }
2011 }
2012
2013 // -------------------------------------------------------------------------
2014
2015 const ClassInfo DOMText::info = { "Text",
2016                                  &DOMCharacterData::info, 0, 0 };
2017 /*
2018 @begin DOMTextProtoTable 1
2019   splitText     DOMText::SplitText      DontDelete|Function 1
2020 @end
2021 */
2022 DEFINE_PROTOTYPE("DOMText",DOMTextProto)
2023 IMPLEMENT_PROTOFUNC(DOMTextProtoFunc)
2024 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMTextProto,DOMTextProtoFunc,DOMCharacterDataProto)
2025
2026 DOMText::DOMText(ExecState *exec, TextImpl *t)
2027   : DOMCharacterData(t) 
2028
2029   setPrototype(DOMTextProto::self(exec));
2030 }
2031
2032 ValueImp *DOMTextProtoFunc::callAsFunction(ExecState *exec, ObjectImp *thisObj, const List &args)
2033 {
2034   if (!thisObj->inherits(&KJS::DOMText::info))
2035     return throwError(exec, TypeError);
2036   DOMExceptionTranslator exception(exec);
2037   TextImpl &text = *static_cast<TextImpl *>(static_cast<DOMText *>(thisObj)->impl());
2038   switch(id) {
2039     case DOMText::SplitText:
2040       return getDOMNode(exec, text.splitText(args[0]->toInt32(exec), exception));
2041   }
2042   return jsUndefined();
2043 }
2044
2045 } // namespace