Reviewed by Hyatt.
[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, 2005, 2006 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 "CDATASectionImpl.h"
25 #include "CommentImpl.h"
26 #include "DOMImplementationImpl.h"
27 #include "DocumentFragmentImpl.h"
28 #include "DocumentTypeImpl.h"
29 #include "ExceptionCode.h"
30 #include "EventNames.h"
31 #include "Frame.h"
32 #include "JSAttr.h"
33 #include "JSCharacterData.h"
34 #include "JSDOMImplementation.h"
35 #include "JSDocumentType.h"
36 #include "JSEntity.h"
37 #include "JSNotation.h"
38 #include "JSProcessingInstruction.h"
39 #include "JSText.h"
40 #include "css_ruleimpl.h"
41 #include "css_stylesheetimpl.h"
42 #include "dom2_eventsimpl.h"
43 #include "dom2_rangeimpl.h"
44 #include "dom2_viewsimpl.h"
45 #include "dom_xmlimpl.h"
46 #include "html_documentimpl.h"
47 #include "html_objectimpl.h"
48 #include "htmlnames.h"
49 #include "khtml_settings.h"
50 #include "kjs_css.h"
51 #include "kjs_events.h"
52 #include "kjs_html.h"
53 #include "kjs_range.h"
54 #include "kjs_traversal.h"
55 #include "kjs_views.h"
56 #include "kjs_window.h"
57 #include "render_canvas.h"
58
59 #if __APPLE__
60 #include <JavaScriptCore/runtime_object.h>
61 #endif
62
63 using namespace WebCore;
64 using namespace HTMLNames;
65 using namespace EventNames;
66
67 #include "kjs_dom.lut.h"
68
69 namespace KJS {
70
71 // -------------------------------------------------------------------------
72 /* Source for DOMNodeProtoTable. Use "make hashtables" to regenerate.
73 @begin DOMNodeProtoTable 18
74   insertBefore  DOMNode::InsertBefore   DontDelete|Function 2
75   replaceChild  DOMNode::ReplaceChild   DontDelete|Function 2
76   removeChild   DOMNode::RemoveChild    DontDelete|Function 1
77   appendChild   DOMNode::AppendChild    DontDelete|Function 1
78   hasAttributes DOMNode::HasAttributes  DontDelete|Function 0
79   hasChildNodes DOMNode::HasChildNodes  DontDelete|Function 0
80   cloneNode     DOMNode::CloneNode      DontDelete|Function 1
81 # DOM2
82   normalize     DOMNode::Normalize      DontDelete|Function 0
83   isSupported   DOMNode::IsSupported    DontDelete|Function 2
84 # DOM3
85   isSameNode    DOMNode::IsSameNode     DontDelete|Function 1
86   isEqualNode   DOMNode::IsEqualNode    DontDelete|Function 1
87   isDefaultNamespace    DOMNode::IsDefaultNamespace DontDelete|Function 1
88   lookupNamespaceURI    DOMNode::LookupNamespaceURI DontDelete|Function 1
89   lookupPrefix  DOMNode::LookupPrefix   DontDelete|Function 1
90 # from the EventTarget interface
91   addEventListener  DOMNode::AddEventListener   DontDelete|Function 3
92   removeEventListener   DOMNode::RemoveEventListener    DontDelete|Function 3
93   dispatchEvent DOMNode::DispatchEvent  DontDelete|Function 1
94   contains      DOMNode::Contains       DontDelete|Function 1
95 # "DOM level 0" (from Gecko DOM reference; also in WinIE)
96   item          DOMNode::Item           DontDelete|Function 1
97 @end
98 */
99 KJS_IMPLEMENT_PROTOFUNC(DOMNodeProtoFunc)
100 KJS_IMPLEMENT_PROTOTYPE("DOMNode", DOMNodeProto, DOMNodeProtoFunc)
101
102 const ClassInfo DOMNode::info = { "Node", 0, &DOMNodeTable, 0 };
103
104 DOMNode::DOMNode(ExecState *exec, NodeImpl *n)
105   : m_impl(n)
106 {
107   setPrototype(DOMNodeProto::self(exec));
108 }
109
110 DOMNode::DOMNode(NodeImpl *n)
111   : m_impl(n)
112 {
113 }
114
115 DOMNode::~DOMNode()
116 {
117   ScriptInterpreter::forgetDOMNodeForDocument(m_impl->getDocument(), m_impl.get());
118 }
119
120 void DOMNode::mark()
121 {
122   assert(!marked());
123
124   NodeImpl *node = m_impl.get();
125
126   // Nodes in the document are kept alive by ScriptInterpreter::mark,
127   // so we have no special responsibilities and can just call the base class here.
128   if (node->inDocument()) {
129     DOMObject::mark();
130     return;
131   }
132
133   // This is a node outside the document, so find the root of the tree it is in,
134   // and start marking from there.
135   NodeImpl *root = node;
136   for (NodeImpl *current = m_impl.get(); current; current = current->parentNode()) {
137     root = current;
138   }
139
140   static HashSet<NodeImpl*> markingRoots;
141
142   // If we're already marking this tree, then we can simply mark this wrapper
143   // by calling the base class; our caller is iterating the tree.
144   if (markingRoots.contains(root)) {
145     DOMObject::mark();
146     return;
147   }
148
149   DocumentImpl *document = m_impl->getDocument();
150
151   // Mark the whole tree; use the global set of roots to avoid reentering.
152   markingRoots.add(root);
153   for (NodeImpl *nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) {
154     DOMNode *wrapper = ScriptInterpreter::getDOMNodeForDocument(document, nodeToMark);
155     if (wrapper) {
156       if (!wrapper->marked())
157         wrapper->mark();
158     } else if (nodeToMark == node) {
159       // This is the case where the map from the document to wrappers has
160       // been cleared out, but a wrapper is being marked. For now, we'll
161       // let the rest of the tree of wrappers get collected, because we have
162       // no good way of finding them. Later we should test behavior of other
163       // browsers and see if we need to preserve other wrappers in this case.
164       if (!marked())
165         mark();
166     }
167   }
168   markingRoots.remove(root);
169
170   // Double check that we actually ended up marked. This assert caught problems in the past.
171   assert(marked());
172 }
173
174 bool DOMNode::toBoolean(ExecState *) const
175 {
176     return m_impl;
177 }
178
179 /* Source for DOMNodeTable. Use "make hashtables" to regenerate.
180 @begin DOMNodeTable 69
181   nodeName      DOMNode::NodeName       DontDelete|ReadOnly
182   nodeValue     DOMNode::NodeValue      DontDelete
183   nodeType      DOMNode::NodeType       DontDelete|ReadOnly
184   parentNode    DOMNode::ParentNode     DontDelete|ReadOnly
185   parentElement DOMNode::ParentElement  DontDelete|ReadOnly
186   childNodes    DOMNode::ChildNodes     DontDelete|ReadOnly
187   firstChild    DOMNode::FirstChild     DontDelete|ReadOnly
188   lastChild     DOMNode::LastChild      DontDelete|ReadOnly
189   previousSibling  DOMNode::PreviousSibling DontDelete|ReadOnly
190   nextSibling   DOMNode::NextSibling    DontDelete|ReadOnly
191   attributes    DOMNode::Attributes     DontDelete|ReadOnly
192   namespaceURI  DOMNode::NamespaceURI   DontDelete|ReadOnly
193 # DOM2
194   prefix        DOMNode::Prefix         DontDelete
195   localName     DOMNode::LocalName      DontDelete|ReadOnly
196   ownerDocument DOMNode::OwnerDocument  DontDelete|ReadOnly
197 # DOM3
198   textContent   DOMNode::TextContent    DontDelete
199 #
200   onabort       DOMNode::OnAbort                DontDelete
201   onblur        DOMNode::OnBlur                 DontDelete
202   onchange      DOMNode::OnChange               DontDelete
203   onclick       DOMNode::OnClick                DontDelete
204   oncontextmenu DOMNode::OnContextMenu          DontDelete
205   ondblclick    DOMNode::OnDblClick             DontDelete
206   onbeforecut   DOMNode::OnBeforeCut            DontDelete
207   oncut         DOMNode::OnCut                  DontDelete
208   onbeforecopy  DOMNode::OnBeforeCopy           DontDelete
209   oncopy        DOMNode::OnCopy                 DontDelete
210   onbeforepaste DOMNode::OnBeforePaste          DontDelete
211   onpaste       DOMNode::OnPaste                DontDelete
212   ondrag        DOMNode::OnDrag                 DontDelete
213   ondragdrop    DOMNode::OnDragDrop             DontDelete
214   ondragend     DOMNode::OnDragEnd              DontDelete
215   ondragenter   DOMNode::OnDragEnter            DontDelete
216   ondragleave   DOMNode::OnDragLeave            DontDelete
217   ondragover    DOMNode::OnDragOver             DontDelete
218   ondragstart   DOMNode::OnDragStart            DontDelete
219   ondrop        DOMNode::OnDrop                 DontDelete
220   onerror       DOMNode::OnError                DontDelete
221   onfocus       DOMNode::OnFocus                DontDelete
222   oninput       DOMNode::OnInput                DontDelete
223   onkeydown     DOMNode::OnKeyDown              DontDelete
224   onkeypress    DOMNode::OnKeyPress             DontDelete
225   onkeyup       DOMNode::OnKeyUp                DontDelete
226   onload        DOMNode::OnLoad                 DontDelete
227   onmousedown   DOMNode::OnMouseDown            DontDelete
228   onmousemove   DOMNode::OnMouseMove            DontDelete
229   onmouseout    DOMNode::OnMouseOut             DontDelete
230   onmouseover   DOMNode::OnMouseOver            DontDelete
231   onmouseup     DOMNode::OnMouseUp              DontDelete
232   onmousewheel  DOMNode::OnMouseWheel           DontDelete
233   onmove        DOMNode::OnMove                 DontDelete
234   onreset       DOMNode::OnReset                DontDelete
235   onresize      DOMNode::OnResize               DontDelete
236   onscroll      DOMNode::OnScroll               DontDelete
237   onsearch      DOMNode::OnSearch               DontDelete
238   onselect      DOMNode::OnSelect               DontDelete
239   onselectstart DOMNode::OnSelectStart          DontDelete
240   onsubmit      DOMNode::OnSubmit               DontDelete
241   onunload      DOMNode::OnUnload               DontDelete
242 # IE extensions
243   offsetLeft    DOMNode::OffsetLeft             DontDelete|ReadOnly
244   offsetTop     DOMNode::OffsetTop              DontDelete|ReadOnly
245   offsetWidth   DOMNode::OffsetWidth            DontDelete|ReadOnly
246   offsetHeight  DOMNode::OffsetHeight           DontDelete|ReadOnly
247   offsetParent  DOMNode::OffsetParent           DontDelete|ReadOnly
248   clientWidth   DOMNode::ClientWidth            DontDelete|ReadOnly
249   clientHeight  DOMNode::ClientHeight           DontDelete|ReadOnly
250   scrollLeft    DOMNode::ScrollLeft             DontDelete
251   scrollTop     DOMNode::ScrollTop              DontDelete
252   scrollWidth   DOMNode::ScrollWidth            DontDelete|ReadOnly
253   scrollHeight  DOMNode::ScrollHeight           DontDelete|ReadOnly
254 @end
255 */
256 bool DOMNode::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
257 {
258   return getStaticValueSlot<DOMNode, DOMObject>(exec, &DOMNodeTable, this, propertyName, slot);
259 }
260
261 JSValue *DOMNode::getValueProperty(ExecState *exec, int token) const
262 {
263   NodeImpl &node = *m_impl;
264   switch (token) {
265   case NodeName:
266     return jsStringOrNull(node.nodeName());
267   case NodeValue:
268     return jsStringOrNull(node.nodeValue());
269   case NodeType:
270     return jsNumber(node.nodeType());
271   case ParentNode:
272   case ParentElement: // IE only apparently
273     return toJS(exec,node.parentNode());
274   case ChildNodes:
275     return toJS(exec,node.childNodes().get());
276   case FirstChild:
277     return toJS(exec,node.firstChild());
278   case LastChild:
279     return toJS(exec,node.lastChild());
280   case PreviousSibling:
281     return toJS(exec,node.previousSibling());
282   case NextSibling:
283     return toJS(exec,node.nextSibling());
284   case Attributes:
285     return toJS(exec,node.attributes());
286   case NamespaceURI:
287     return jsStringOrNull(node.namespaceURI());
288   case Prefix:
289     return jsStringOrNull(node.prefix());
290   case LocalName:
291     return jsStringOrNull(node.localName());
292   case OwnerDocument:
293     return toJS(exec,node.ownerDocument());
294   case TextContent:
295     return jsStringOrNull(node.textContent());
296   case OnAbort:
297     return getListener(abortEvent);
298   case OnBlur:
299     return getListener(blurEvent);
300   case OnChange:
301     return getListener(changeEvent);
302   case OnClick:
303     return getListener(clickEvent);
304   case OnContextMenu:
305     return getListener(contextmenuEvent);
306   case OnDblClick:
307     return getListener(dblclickEvent);
308   case OnDragDrop:
309     return getListener(khtmlDragdropEvent);
310   case OnError:
311     return getListener(khtmlErrorEvent);
312   case OnFocus:
313     return getListener(focusEvent);
314   case OnInput:
315     return getListener(inputEvent);
316   case OnKeyDown:
317     return getListener(keydownEvent);
318   case OnKeyPress:
319     return getListener(keypressEvent);
320   case OnKeyUp:
321     return getListener(keyupEvent);
322   case OnLoad:
323     return getListener(loadEvent);
324   case OnMouseDown:
325     return getListener(mousedownEvent);
326   case OnMouseMove:
327     return getListener(mousemoveEvent);
328   case OnMouseOut:
329     return getListener(mouseoutEvent);
330   case OnMouseOver:
331     return getListener(mouseoverEvent);
332   case OnMouseUp:
333     return getListener(mouseupEvent);      
334   case OnMouseWheel:
335     return getListener(mousewheelEvent);      
336   case OnBeforeCut:
337     return getListener(beforecutEvent);
338   case OnCut:
339     return getListener(cutEvent);
340   case OnBeforeCopy:
341     return getListener(beforecopyEvent);
342   case OnCopy:
343     return getListener(copyEvent);
344   case OnBeforePaste:
345     return getListener(beforepasteEvent);
346   case OnPaste:
347     return getListener(pasteEvent);
348   case OnDragEnter:
349     return getListener(dragenterEvent);
350   case OnDragOver:
351     return getListener(dragoverEvent);
352   case OnDragLeave:
353     return getListener(dragleaveEvent);
354   case OnDrop:
355     return getListener(dropEvent);
356   case OnDragStart:
357     return getListener(dragstartEvent);
358   case OnDrag:
359     return getListener(dragEvent);
360   case OnDragEnd:
361     return getListener(dragendEvent);
362   case OnMove:
363     return getListener(khtmlMoveEvent);
364   case OnReset:
365     return getListener(resetEvent);
366   case OnResize:
367     return getListener(resizeEvent);
368   case OnScroll:
369     return getListener(scrollEvent);
370   case OnSearch:
371     return getListener(searchEvent);
372   case OnSelect:
373     return getListener(selectEvent);
374   case OnSelectStart:
375     return getListener(selectstartEvent);
376   case OnSubmit:
377     return getListener(submitEvent);
378   case OnUnload:
379     return getListener(unloadEvent);
380   default:
381     // no DOM standard, found in IE only
382
383     // Make sure our layout is up to date before we allow a query on these attributes.
384     DOM::DocumentImpl* docimpl = node.getDocument();
385     if (docimpl) {
386       docimpl->updateLayoutIgnorePendingStylesheets();
387     }
388
389     RenderObject *rend = node.renderer();
390
391     switch (token) {
392     case OffsetLeft:
393       return rend ? jsNumber(rend->offsetLeft()) : static_cast<JSValue *>(jsUndefined());
394     case OffsetTop:
395       return rend ? jsNumber(rend->offsetTop()) : static_cast<JSValue *>(jsUndefined());
396     case OffsetWidth:
397       return rend ? jsNumber(rend->offsetWidth()) : static_cast<JSValue *>(jsUndefined());
398     case OffsetHeight:
399       return rend ? jsNumber(rend->offsetHeight()) : static_cast<JSValue *>(jsUndefined());
400     case OffsetParent: {
401       RenderObject* par = rend ? rend->offsetParent() : 0;
402       return toJS(exec, par ? par->element() : 0);
403     }
404     case ClientWidth:
405       return rend ? jsNumber(rend->clientWidth()) : static_cast<JSValue *>(jsUndefined());
406     case ClientHeight:
407       return rend ? jsNumber(rend->clientHeight()) : static_cast<JSValue *>(jsUndefined());
408     case ScrollWidth:
409         return rend ? jsNumber(rend->scrollWidth()) : static_cast<JSValue *>(jsUndefined());
410     case ScrollHeight:
411         return rend ? jsNumber(rend->scrollHeight()) : static_cast<JSValue *>(jsUndefined());
412     case ScrollLeft:
413       return jsNumber(rend && rend->layer() ? rend->layer()->scrollXOffset() : 0);
414     case ScrollTop:
415       return jsNumber(rend && rend->layer() ? rend->layer()->scrollYOffset() : 0);
416     default:
417       break;
418     }
419   }
420
421   return NULL;
422 }
423
424 void DOMNode::put(ExecState *exec, const Identifier& propertyName, JSValue *value, int attr)
425 {
426     lookupPut<DOMNode,DOMObject>(exec, propertyName, value, attr, &DOMNodeTable, this);
427 }
428
429 void DOMNode::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/)
430 {
431   DOMExceptionTranslator exception(exec);
432   NodeImpl &node = *m_impl;
433   switch (token) {
434   case NodeValue:
435     node.setNodeValue(value->toString(exec).domString(), exception);
436     break;
437   case Prefix:
438     node.setPrefix(value->toString(exec).domString().impl(), exception);
439     break;
440   case TextContent:
441     node.setTextContent(valueToStringWithNullCheck(exec, value), exception);
442     break;
443   case OnAbort:
444     setListener(exec,abortEvent,value);
445     break;
446   case OnBlur:
447     setListener(exec,blurEvent,value);
448     break;
449   case OnChange:
450     setListener(exec,changeEvent,value);
451     break;
452   case OnClick:
453     setListener(exec,clickEvent,value);
454     break;
455   case OnContextMenu:
456     setListener(exec,contextmenuEvent,value);
457     break;
458   case OnDblClick:
459     setListener(exec,dblclickEvent,value);
460     break;
461   case OnDragDrop:
462     setListener(exec,khtmlDragdropEvent,value);
463     break;
464   case OnError:
465     setListener(exec,khtmlErrorEvent,value);
466     break;
467   case OnFocus:
468     setListener(exec,focusEvent,value);
469     break;
470   case OnInput:
471     setListener(exec,inputEvent,value);
472     break;
473   case OnKeyDown:
474     setListener(exec,keydownEvent,value);
475     break;
476   case OnKeyPress:
477     setListener(exec,keypressEvent,value);
478     break;
479   case OnKeyUp:
480     setListener(exec,keyupEvent,value);
481     break;
482   case OnLoad:
483     setListener(exec,loadEvent,value);
484     break;
485   case OnMouseDown:
486     setListener(exec,mousedownEvent,value);
487     break;
488   case OnMouseMove:
489     setListener(exec,mousemoveEvent,value);
490     break;
491   case OnMouseOut:
492     setListener(exec,mouseoutEvent,value);
493     break;
494   case OnMouseOver:
495     setListener(exec,mouseoverEvent,value);
496     break;
497   case OnMouseUp:
498     setListener(exec,mouseupEvent,value);
499     break;
500   case OnMouseWheel:
501     setListener(exec,mousewheelEvent,value);
502     break;
503   case OnBeforeCut:
504     setListener(exec,beforecutEvent,value);
505     break;
506   case OnCut:
507     setListener(exec,cutEvent,value);
508     break;
509   case OnBeforeCopy:
510     setListener(exec,beforecopyEvent,value);
511     break;
512   case OnCopy:
513     setListener(exec,copyEvent,value);
514     break;
515   case OnBeforePaste:
516     setListener(exec,beforepasteEvent,value);
517     break;
518   case OnPaste:
519     setListener(exec,pasteEvent,value);
520     break;
521   case OnDragEnter:
522     setListener(exec,dragenterEvent,value);
523     break;
524   case OnDragOver:
525     setListener(exec,dragoverEvent,value);
526     break;
527   case OnDragLeave:
528     setListener(exec,dragleaveEvent,value);
529     break;
530   case OnDrop:
531     setListener(exec,dropEvent,value);
532     break;
533   case OnDragStart:
534     setListener(exec,dragstartEvent,value);
535     break;
536   case OnDrag:
537     setListener(exec,dragEvent,value);
538     break;
539   case OnDragEnd:
540     setListener(exec,dragendEvent,value);
541     break;
542   case OnMove:
543     setListener(exec,khtmlMoveEvent,value);
544     break;
545   case OnReset:
546     setListener(exec,resetEvent,value);
547     break;
548   case OnResize:
549     setListener(exec,resizeEvent,value);
550     break;
551   case OnScroll:
552     setListener(exec,scrollEvent,value);
553     break;
554   case OnSearch:
555     setListener(exec,searchEvent,value);
556     break;
557   case OnSelect:
558     setListener(exec,selectEvent,value);
559     break;
560   case OnSelectStart:
561     setListener(exec,selectstartEvent,value);
562     break;
563   case OnSubmit:
564     setListener(exec,submitEvent,value);
565     break;
566   case OnUnload:
567     setListener(exec, unloadEvent, value);
568     break;
569   case ScrollTop: {
570     RenderObject *rend = node.renderer();
571     if (rend && rend->hasOverflowClip())
572         rend->layer()->scrollToYOffset(value->toInt32(exec));
573     break;
574   }
575   case ScrollLeft: {
576     RenderObject *rend = node.renderer();
577     if (rend && rend->hasOverflowClip())
578       rend->layer()->scrollToXOffset(value->toInt32(exec));
579     break;
580   }
581   }
582 }
583
584 JSValue *DOMNode::toPrimitive(ExecState *exec, JSType) const
585 {
586   if (!m_impl)
587     return jsNull();
588
589   return jsString(toString(exec));
590 }
591
592 UString DOMNode::toString(ExecState *) const
593 {
594   if (!m_impl)
595     return "null";
596   return "[object " + (m_impl->isElementNode() ? m_impl->nodeName() : className()) + "]";
597 }
598
599 void DOMNode::setListener(ExecState *exec, const AtomicString &eventType, JSValue *func) const
600 {
601   m_impl->setHTMLEventListener(eventType, Window::retrieveActive(exec)->getJSEventListener(func, true));
602 }
603
604 JSValue *DOMNode::getListener(const AtomicString &eventType) const
605 {
606     DOM::EventListener *listener = m_impl->getHTMLEventListener(eventType);
607     JSEventListener *jsListener = static_cast<JSEventListener*>(listener);
608     if (jsListener && jsListener->listenerObj())
609         return jsListener->listenerObj();
610     else
611         return jsNull();
612 }
613
614 void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const
615 {
616 }
617
618 JSValue *DOMNodeProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
619 {
620   if (!thisObj->inherits(&DOMNode::info))
621     return throwError(exec, TypeError);
622   DOMExceptionTranslator exception(exec);
623   NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl();
624   switch (id) {
625     case DOMNode::HasAttributes:
626       return jsBoolean(node.hasAttributes());
627     case DOMNode::HasChildNodes:
628       return jsBoolean(node.hasChildNodes());
629     case DOMNode::CloneNode:
630       return toJS(exec,node.cloneNode(args[0]->toBoolean(exec)));
631     case DOMNode::Normalize:
632       node.normalize();
633       return jsUndefined();
634     case DOMNode::IsSupported:
635         return jsBoolean(node.isSupported(args[0]->toString(exec).domString(),
636                                           valueToStringWithNullCheck(exec, args[1])));
637     case DOMNode::IsSameNode:
638         return jsBoolean(node.isSameNode(toNode(args[0])));
639     case DOMNode::IsEqualNode:
640         return jsBoolean(node.isEqualNode(toNode(args[0])));
641     case DOMNode::IsDefaultNamespace:
642         return jsBoolean(node.isDefaultNamespace(valueToStringWithNullCheck(exec, args[0])));
643     case DOMNode::LookupNamespaceURI:
644         return jsStringOrNull(node.lookupNamespaceURI(valueToStringWithNullCheck(exec, args[0])));
645     case DOMNode::LookupPrefix:
646         return jsStringOrNull(node.lookupPrefix(valueToStringWithNullCheck(exec, args[0])));
647     case DOMNode::AddEventListener: {
648         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
649         if (listener)
650             node.addEventListener(AtomicString(args[0]->toString(exec).domString()), listener,args[2]->toBoolean(exec));
651         return jsUndefined();
652     }
653     case DOMNode::RemoveEventListener: {
654         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
655         if (listener)
656             node.removeEventListener(AtomicString(args[0]->toString(exec).domString()), listener,args[2]->toBoolean(exec));
657         return jsUndefined();
658     }
659     case DOMNode::DispatchEvent:
660       return jsBoolean(node.dispatchEvent(toEvent(args[0]), exception));
661     case DOMNode::AppendChild:
662       if (node.appendChild(toNode(args[0]), exception))
663         return args[0];
664       return jsNull();
665     case DOMNode::RemoveChild:
666       if (node.removeChild(toNode(args[0]), exception))
667         return args[0];
668       return jsNull();
669     case DOMNode::InsertBefore:
670       if (node.insertBefore(toNode(args[0]), toNode(args[1]), exception))
671         return args[0];
672       return jsNull();
673     case DOMNode::ReplaceChild:
674      if (node.replaceChild(toNode(args[0]), toNode(args[1]), exception))
675         return args[1];
676       return jsNull();
677     case DOMNode::Contains:
678       if (node.isElementNode())
679         if (NodeImpl *node0 = toNode(args[0]))
680           return jsBoolean(node.isAncestor(node0));
681       // FIXME: Is there a good reason to return undefined rather than false
682       // when the parameter is not a node? When the object is not an element?
683       return jsUndefined();
684     case DOMNode::Item:
685       return thisObj->get(exec, args[0]->toInt32(exec));
686   }
687
688   return jsUndefined();
689 }
690
691 NodeImpl *toNode(JSValue *val)
692 {
693     if (!val || !val->isObject(&DOMNode::info))
694         return 0;
695     return static_cast<DOMNode *>(val)->impl();
696 }
697
698 // -------------------------------------------------------------------------
699
700 /*
701 @begin DOMNodeListTable 2
702   length        DOMNodeList::Length     DontDelete|ReadOnly
703   item          DOMNodeList::Item               DontDelete|Function 1
704 @end
705 */
706
707 KJS_IMPLEMENT_PROTOFUNC(DOMNodeListFunc)
708
709 const ClassInfo DOMNodeList::info = { "NodeList", 0, &DOMNodeListTable, 0 };
710
711 DOMNodeList::~DOMNodeList()
712 {
713   ScriptInterpreter::forgetDOMObject(m_impl.get());
714 }
715
716 JSValue *DOMNodeList::toPrimitive(ExecState *exec, JSType) const
717 {
718   if (!m_impl)
719     return jsNull();
720
721   return jsString(toString(exec));
722 }
723
724 JSValue *DOMNodeList::getValueProperty(ExecState *exec, int token) const
725 {
726   assert(token == Length);
727   return jsNumber(m_impl->length());
728 }
729
730 JSValue *DOMNodeList::indexGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
731 {
732   DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
733   return toJS(exec, thisObj->m_impl->item(slot.index()));
734 }
735
736 JSValue *DOMNodeList::nameGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
737 {
738   DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
739   return toJS(exec, thisObj->m_impl->itemById(propertyName.domString().impl()));
740 }
741
742 bool DOMNodeList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
743 {
744   const HashEntry* entry = Lookup::findEntry(&DOMNodeListTable, propertyName);
745
746   if (entry) {
747     if (entry->attr & Function)
748       slot.setStaticEntry(this, entry, staticFunctionGetter<DOMNodeListFunc>);
749     else
750       slot.setStaticEntry(this, entry, staticValueGetter<DOMNodeList>);
751     return true;
752   }
753
754   NodeListImpl &list = *m_impl;
755
756   // array index ?
757   bool ok;
758   unsigned idx = propertyName.toUInt32(&ok);
759   if (ok && idx < list.length()) {
760     slot.setCustomIndex(this, idx, indexGetter);
761     return true;
762   } else if (list.itemById(propertyName.domString().impl())) {
763     slot.setCustom(this, nameGetter);
764     return true;
765   }
766
767   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
768 }
769
770 // Need to support both get and call, so that list[0] and list(0) work.
771 JSValue *DOMNodeList::callAsFunction(ExecState *exec, JSObject *, const List &args)
772 {
773   // Do not use thisObj here. See HTMLCollection.
774   UString s = args[0]->toString(exec);
775   bool ok;
776   unsigned int u = s.toUInt32(&ok);
777   if (ok)
778     return toJS(exec, m_impl->item(u));
779
780   return jsUndefined();
781 }
782
783 // Not a prototype class currently, but should probably be converted to one
784 JSValue *DOMNodeListFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
785 {
786   if (!thisObj->inherits(&KJS::DOMNodeList::info))
787     return throwError(exec, TypeError);
788   DOM::NodeListImpl &list = *static_cast<DOMNodeList *>(thisObj)->impl();
789
790   if (id == DOMNodeList::Item)
791     return toJS(exec, list.item(args[0]->toInt32(exec)));
792
793   return jsUndefined();
794 }
795
796 AttrImpl *toAttr(JSValue *val)
797 {
798     if (!val || !val->isObject(&JSAttr::info))
799         return 0;
800     return static_cast<AttrImpl *>(static_cast<DOMNode *>(val)->impl());
801 }
802
803 // -------------------------------------------------------------------------
804
805 /* Source for DOMDocumentProtoTable. Use "make hashtables" to regenerate.
806 @begin DOMDocumentProtoTable 29
807   adoptNode       DOMDocument::AdoptNode                       DontDelete|Function 1
808   createElement   DOMDocument::CreateElement                   DontDelete|Function 1
809   createDocumentFragment DOMDocument::CreateDocumentFragment   DontDelete|Function 1
810   createTextNode  DOMDocument::CreateTextNode                  DontDelete|Function 1
811   createComment   DOMDocument::CreateComment                   DontDelete|Function 1
812   createCDATASection DOMDocument::CreateCDATASection           DontDelete|Function 1
813   createProcessingInstruction DOMDocument::CreateProcessingInstruction DontDelete|Function 1
814   createAttribute DOMDocument::CreateAttribute                 DontDelete|Function 1
815   createEntityReference DOMDocument::CreateEntityReference     DontDelete|Function 1
816   elementFromPoint     DOMDocument::ElementFromPoint           DontDelete|Function 1
817   getElementsByTagName  DOMDocument::GetElementsByTagName      DontDelete|Function 1
818   importNode           DOMDocument::ImportNode                 DontDelete|Function 2
819   createElementNS      DOMDocument::CreateElementNS            DontDelete|Function 2
820   createAttributeNS    DOMDocument::CreateAttributeNS          DontDelete|Function 2
821   getElementsByTagNameNS  DOMDocument::GetElementsByTagNameNS  DontDelete|Function 2
822   getElementById     DOMDocument::GetElementById               DontDelete|Function 1
823   createRange        DOMDocument::CreateRange                  DontDelete|Function 0
824   createNodeIterator DOMDocument::CreateNodeIterator           DontDelete|Function 3
825   createTreeWalker   DOMDocument::CreateTreeWalker             DontDelete|Function 4
826   createEvent        DOMDocument::CreateEvent                  DontDelete|Function 1
827   getOverrideStyle   DOMDocument::GetOverrideStyle             DontDelete|Function 2
828   execCommand        DOMDocument::ExecCommand                  DontDelete|Function 3
829   queryCommandEnabled DOMDocument::QueryCommandEnabled         DontDelete|Function 1
830   queryCommandIndeterm DOMDocument::QueryCommandIndeterm       DontDelete|Function 1
831   queryCommandState DOMDocument::QueryCommandState             DontDelete|Function 1
832   queryCommandSupported DOMDocument::QueryCommandSupported     DontDelete|Function 1
833   queryCommandValue DOMDocument::QueryCommandValue             DontDelete|Function 1
834 @end
835 */
836 KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMDocumentProto, DOMNodeProto)
837 KJS_IMPLEMENT_PROTOFUNC(DOMDocumentProtoFunc)
838 KJS_IMPLEMENT_PROTOTYPE("DOMDocument", DOMDocumentProto, DOMDocumentProtoFunc)
839
840 const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, 0 };
841
842 /* Source for DOMDocumentTable. Use "make hashtables" to regenerate.
843 @begin DOMDocumentTable 4
844   doctype         DOMDocument::DocType                         DontDelete|ReadOnly
845   implementation  DOMDocument::Implementation                  DontDelete|ReadOnly
846   documentElement DOMDocument::DocumentElement                 DontDelete|ReadOnly
847   charset         DOMDocument::Charset                         DontDelete
848   defaultCharset  DOMDocument::DefaultCharset                  DontDelete|ReadOnly
849   characterSet    DOMDocument::CharacterSet                    DontDelete|ReadOnly
850   actualEncoding  DOMDocument::ActualEncoding                  DontDelete|ReadOnly
851   inputEncoding   DOMDocument::InputEncoding                   DontDelete|ReadOnly
852   styleSheets     DOMDocument::StyleSheets                     DontDelete|ReadOnly
853   preferredStylesheetSet  DOMDocument::PreferredStylesheetSet  DontDelete|ReadOnly
854   selectedStylesheetSet  DOMDocument::SelectedStylesheetSet    DontDelete
855   readyState      DOMDocument::ReadyState                      DontDelete|ReadOnly
856   defaultView        DOMDocument::DefaultView                  DontDelete|ReadOnly
857 @end
858 */
859
860 DOMDocument::DOMDocument(ExecState *exec, DocumentImpl *d)
861   : DOMNode(d) 
862
863   setPrototype(DOMDocumentProto::self(exec));
864 }
865
866 DOMDocument::DOMDocument(DocumentImpl *d)
867   : DOMNode(d) 
868
869 }
870
871 DOMDocument::~DOMDocument()
872 {
873   ScriptInterpreter::forgetDOMObject(static_cast<DocumentImpl *>(m_impl.get()));
874 }
875
876 bool DOMDocument::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
877 {
878   return getStaticValueSlot<DOMDocument, DOMNode>(exec, &DOMDocumentTable, this, propertyName, slot);
879 }
880
881 JSValue *DOMDocument::getValueProperty(ExecState *exec, int token) const
882 {
883   DocumentImpl &doc = *static_cast<DocumentImpl *>(impl());
884
885   switch(token) {
886   case DocType:
887     return toJS(exec,doc.doctype());
888   case Implementation:
889     return toJS(exec, doc.implementation());
890   case DocumentElement:
891     return toJS(exec,doc.documentElement());
892   case Charset:
893   case CharacterSet:
894   case ActualEncoding:
895   case InputEncoding:
896     if (Decoder* decoder = doc.decoder())
897       return jsString(decoder->encodingName());
898     return jsNull();
899   case DefaultCharset:
900     if (Frame *frame = doc.frame())
901         return jsString(frame->settings()->encoding());
902     return jsUndefined();
903   case StyleSheets:
904     //kdDebug() << "DOMDocument::StyleSheets, returning " << doc.styleSheets().length() << " stylesheets" << endl;
905     return getDOMStyleSheetList(exec, doc.styleSheets(), &doc);
906   case PreferredStylesheetSet:
907     return jsStringOrNull(doc.preferredStylesheetSet());
908   case SelectedStylesheetSet:
909     return jsStringOrNull(doc.selectedStylesheetSet());
910   case ReadyState:
911     if (Frame *frame = doc.frame()) {
912       if (frame->isComplete()) return jsString("complete");
913       if (doc.parsing()) return jsString("loading");
914       return jsString("loaded");
915       // What does the interactive value mean ?
916       // Missing support for "uninitialized"
917     }
918     return jsUndefined();
919   case DOMDocument::DefaultView: // DOM2
920     return toJS(exec,doc.defaultView());
921   default:
922     return NULL;
923   }
924 }
925
926 void DOMDocument::put(ExecState *exec, const Identifier& propertyName, JSValue *value, int attr)
927 {
928     lookupPut<DOMDocument,DOMNode>(exec, propertyName, value, attr, &DOMDocumentTable, this);
929 }
930
931 void DOMDocument::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/)
932 {
933   DocumentImpl &doc = *static_cast<DocumentImpl *>(impl());
934   switch (token) {
935     case SelectedStylesheetSet:
936       doc.setSelectedStylesheetSet(value->toString(exec).domString());
937       break;
938     case Charset:
939       doc.decoder()->setEncodingName(value->toString(exec).cstring().c_str(), Decoder::UserChosenEncoding);
940       break;
941   }
942 }
943
944 JSValue *DOMDocumentProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
945 {
946   if (!thisObj->inherits(&KJS::DOMNode::info))
947     return throwError(exec, TypeError);
948   DOMExceptionTranslator exception(exec);
949   NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl();
950   DocumentImpl &doc = static_cast<DocumentImpl &>(node);
951   UString str = args[0]->toString(exec);
952   DOM::DOMString s = str.domString();
953
954   switch(id) {
955   case DOMDocument::AdoptNode:
956     return toJS(exec,doc.adoptNode(toNode(args[0]),exception));
957   case DOMDocument::CreateElement:
958     return toJS(exec,doc.createElement(s, exception));
959   case DOMDocument::CreateDocumentFragment:
960     return toJS(exec,doc.createDocumentFragment());
961   case DOMDocument::CreateTextNode:
962     return toJS(exec,doc.createTextNode(s));
963   case DOMDocument::CreateComment:
964     return toJS(exec,doc.createComment(s));
965   case DOMDocument::CreateCDATASection:
966     return toJS(exec, doc.createCDATASection(s, exception));
967   case DOMDocument::CreateProcessingInstruction:
968     return toJS(exec, doc.createProcessingInstruction(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception));
969   case DOMDocument::CreateAttribute:
970     return toJS(exec,doc.createAttribute(s, exception));
971   case DOMDocument::CreateEntityReference:
972     return toJS(exec, doc.createEntityReference(s, exception));
973   case DOMDocument::ElementFromPoint:
974     return toJS(exec,doc.elementFromPoint((int)args[0]->toNumber(exec), (int)args[1]->toNumber(exec)));
975   case DOMDocument::GetElementsByTagName:
976     return toJS(exec,doc.getElementsByTagName(s).get());
977   case DOMDocument::ImportNode: // DOM2
978     return toJS(exec,doc.importNode(toNode(args[0]), args[1]->toBoolean(exec), exception));
979   case DOMDocument::CreateElementNS: // DOM2
980     return toJS(exec,doc.createElementNS(s, args[1]->toString(exec).domString(), exception));
981   case DOMDocument::CreateAttributeNS: // DOM2
982     return toJS(exec,doc.createAttributeNS(s, args[1]->toString(exec).domString(), exception));
983   case DOMDocument::GetElementsByTagNameNS: // DOM2
984     return toJS(exec,doc.getElementsByTagNameNS(s, args[1]->toString(exec).domString()).get());
985   case DOMDocument::GetElementById:
986     return toJS(exec,doc.getElementById(args[0]->toString(exec).domString().impl()));
987   case DOMDocument::CreateRange:
988     return toJS(exec, doc.createRange().get());
989   case DOMDocument::CreateNodeIterator: {
990     RefPtr<NodeFilterImpl> filter;
991     JSValue* arg2 = args[2];
992     if (arg2->isObject()) {
993       JSObject* o(static_cast<JSObject*>(arg2));
994       filter = new NodeFilterImpl(new JSNodeFilterCondition(o));
995     }
996     return toJS(exec, doc.createNodeIterator(toNode(args[0]), args[1]->toUInt32(exec),
997         filter.release(), args[3]->toBoolean(exec), exception).get());
998   }
999   case DOMDocument::CreateTreeWalker: {
1000     RefPtr<NodeFilterImpl> filter;
1001     JSValue* arg2 = args[2];
1002     if (arg2->isObject()) {
1003       JSObject* o(static_cast<JSObject *>(arg2));
1004       filter = new NodeFilterImpl(new JSNodeFilterCondition(o));
1005     }
1006     return toJS(exec, doc.createTreeWalker(toNode(args[0]), args[1]->toUInt32(exec),
1007         filter.release(), args[3]->toBoolean(exec), exception).get());
1008   }
1009   case DOMDocument::CreateEvent:
1010     return toJS(exec, doc.createEvent(s, exception).get());
1011   case DOMDocument::GetOverrideStyle:
1012     if (ElementImpl *element0 = toElement(args[0]))
1013         return toJS(exec,doc.getOverrideStyle(element0, args[1]->toString(exec).domString()));
1014     // FIXME: Is undefined right here, or should we raise an exception?
1015     return jsUndefined();
1016   case DOMDocument::ExecCommand: {
1017     return jsBoolean(doc.execCommand(args[0]->toString(exec).domString(), args[1]->toBoolean(exec), args[2]->toString(exec).domString()));
1018   }
1019   case DOMDocument::QueryCommandEnabled: {
1020     return jsBoolean(doc.queryCommandEnabled(args[0]->toString(exec).domString()));
1021   }
1022   case DOMDocument::QueryCommandIndeterm: {
1023     return jsBoolean(doc.queryCommandIndeterm(args[0]->toString(exec).domString()));
1024   }
1025   case DOMDocument::QueryCommandState: {
1026     return jsBoolean(doc.queryCommandState(args[0]->toString(exec).domString()));
1027   }
1028   case DOMDocument::QueryCommandSupported: {
1029     return jsBoolean(doc.queryCommandSupported(args[0]->toString(exec).domString()));
1030   }
1031   case DOMDocument::QueryCommandValue: {
1032     DOM::DOMString commandValue(doc.queryCommandValue(args[0]->toString(exec).domString()));
1033     // Method returns null DOMString to signal command is unsupported.
1034     // Microsoft documentation for this method says:
1035     // "If not supported [for a command identifier], this method returns a Boolean set to false."
1036     if (commandValue.isNull())
1037         return jsBoolean(false);
1038     else 
1039         return jsString(commandValue);
1040   }
1041   default:
1042     break;
1043   }
1044
1045   return jsUndefined();
1046 }
1047
1048 // -------------------------------------------------------------------------
1049
1050 /* Source for DOMElementProtoTable. Use "make hashtables" to regenerate.
1051 @begin DOMElementProtoTable 17
1052   scrollIntoView        DOMElement::ScrollIntoView      DontDelete|Function 1
1053   scrollIntoViewIfNeeded        DOMElement::ScrollIntoViewIfNeeded      DontDelete|Function 1
1054
1055 # extension for Safari RSS
1056   scrollByLines         DOMElement::ScrollByLines       DontDelete|Function 1
1057   scrollByPages         DOMElement::ScrollByPages       DontDelete|Function 1
1058
1059 @end
1060 */
1061 KJS_IMPLEMENT_PROTOFUNC(DOMElementProtoFunc)
1062 KJS_IMPLEMENT_PROTOTYPE("DOMElement", DOMElementProto, DOMElementProtoFunc)
1063
1064 const ClassInfo DOMElement::info = { "Element", &DOMNode::info, &DOMElementTable, 0 };
1065 /* Source for DOMElementTable. Use "make hashtables" to regenerate.
1066 @begin DOMElementTable 3
1067   tagName       DOMElement::TagName                         DontDelete|ReadOnly
1068 @end
1069 */
1070 DOMElement::DOMElement(ExecState *exec, ElementImpl *e)
1071   : DOMNode(e) 
1072 {
1073   setPrototype(DOMElementProto::self(exec));
1074 }
1075
1076 DOMElement::DOMElement(ElementImpl *e)
1077   : DOMNode(e) 
1078
1079 }
1080
1081 JSValue *DOMElement::getValueProperty(ExecState *exec, int token) const
1082 {
1083   ElementImpl *element = static_cast<ElementImpl *>(impl());
1084   switch (token) {
1085   case TagName:
1086     return jsStringOrNull(element->nodeName());
1087   default:
1088     assert(0);
1089     return jsUndefined();
1090   }
1091 }
1092
1093 JSValue *DOMElement::attributeGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
1094 {
1095   DOMElement *thisObj = static_cast<DOMElement *>(slot.slotBase());
1096
1097   ElementImpl *element = static_cast<ElementImpl *>(thisObj->impl());
1098   DOM::DOMString attr = element->getAttribute(propertyName.domString());
1099   return jsStringOrNull(attr);
1100 }
1101
1102 bool DOMElement::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1103 {
1104   const HashEntry* entry = Lookup::findEntry(&DOMElementTable, propertyName);
1105   if (entry) {
1106     slot.setStaticEntry(this, entry, staticValueGetter<DOMElement>);
1107     return true;
1108   }
1109
1110   // We have to check in DOMNode before giving access to attributes, otherwise
1111   // onload="..." would make onload return the string (attribute value) instead of
1112   // the listener object (function).
1113   if (DOMNode::getOwnPropertySlot(exec, propertyName, slot))
1114     return true;
1115
1116   JSValue *proto = prototype();
1117   if (proto->isObject() && static_cast<JSObject *>(proto)->hasProperty(exec, propertyName))
1118     return false;
1119
1120   ElementImpl &element = *static_cast<ElementImpl *>(impl());
1121
1122   // FIXME: do we really want to do this attribute lookup thing? Mozilla doesn't do it,
1123   // and it seems like it could interfere with XBL.
1124   DOM::DOMString attr = element.getAttribute(propertyName.domString());
1125   if (!attr.isNull()) {
1126     slot.setCustom(this, attributeGetter);
1127     return true;
1128   }
1129
1130   return false;
1131 }
1132
1133 JSValue *DOMElementProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
1134 {
1135   if (!thisObj->inherits(&KJS::DOMNode::info))
1136     return throwError(exec, TypeError);
1137   DOMExceptionTranslator exception(exec);
1138   NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl();
1139   ElementImpl &element = static_cast<ElementImpl &>(node);
1140
1141   switch(id) {
1142       case DOMElement::ScrollIntoView: 
1143         element.scrollIntoView(args[0]->isUndefinedOrNull() || args[0]->toBoolean(exec));
1144         return jsUndefined();
1145       case DOMElement::ScrollIntoViewIfNeeded: 
1146         element.scrollIntoViewIfNeeded(args[0]->isUndefinedOrNull() || args[0]->toBoolean(exec));
1147         return jsUndefined();
1148       case DOMElement::ScrollByLines:
1149       case DOMElement::ScrollByPages:
1150       if (DocumentImpl* doc = element.getDocument()) {
1151         doc->updateLayoutIgnorePendingStylesheets();
1152         if (RenderObject *rend = element.renderer())
1153           if (rend->hasOverflowClip()) {
1154             KWQScrollDirection direction = KWQScrollDown;
1155             int multiplier = args[0]->toInt32(exec);
1156             if (multiplier < 0) {
1157                 direction = KWQScrollUp;
1158                 multiplier = -multiplier;
1159             }
1160             KWQScrollGranularity granularity = id == DOMElement::ScrollByLines ? KWQScrollLine : KWQScrollPage;
1161             rend->layer()->scroll(direction, granularity, multiplier);
1162           }
1163       }
1164       return jsUndefined();
1165     default:
1166       return jsUndefined();
1167     }
1168 }
1169
1170 ElementImpl *toElement(JSValue *val)
1171 {
1172     if (!val || !val->isObject(&DOMElement::info))
1173         return 0;
1174     return static_cast<ElementImpl *>(static_cast<DOMElement *>(val)->impl());
1175 }
1176
1177 DocumentTypeImpl *toDocumentType(JSValue *val)
1178 {
1179     if (!val || !val->isObject(&JSDocumentType::info))
1180         return 0;
1181     return static_cast<DocumentTypeImpl *>(static_cast<DOMNode *>(val)->impl());
1182 }
1183
1184 // -------------------------------------------------------------------------
1185
1186 /* Source for DOMNamedNodeMapProtoTable. Use "make hashtables" to regenerate.
1187 @begin DOMNamedNodeMapProtoTable 7
1188   getNamedItem          DOMNamedNodeMap::GetNamedItem           DontDelete|Function 1
1189   setNamedItem          DOMNamedNodeMap::SetNamedItem           DontDelete|Function 1
1190   removeNamedItem       DOMNamedNodeMap::RemoveNamedItem        DontDelete|Function 1
1191   item                  DOMNamedNodeMap::Item                   DontDelete|Function 1
1192 # DOM2
1193   getNamedItemNS        DOMNamedNodeMap::GetNamedItemNS         DontDelete|Function 2
1194   setNamedItemNS        DOMNamedNodeMap::SetNamedItemNS         DontDelete|Function 1
1195   removeNamedItemNS     DOMNamedNodeMap::RemoveNamedItemNS      DontDelete|Function 2
1196 @end
1197 */
1198 KJS_DEFINE_PROTOTYPE(DOMNamedNodeMapProto)
1199 KJS_IMPLEMENT_PROTOFUNC(DOMNamedNodeMapProtoFunc)
1200 KJS_IMPLEMENT_PROTOTYPE("NamedNodeMap",DOMNamedNodeMapProto,DOMNamedNodeMapProtoFunc)
1201
1202 const ClassInfo DOMNamedNodeMap::info = { "NamedNodeMap", 0, 0, 0 };
1203
1204 DOMNamedNodeMap::DOMNamedNodeMap(ExecState *exec, NamedNodeMapImpl *m)
1205   : m_impl(m) 
1206
1207   setPrototype(DOMNamedNodeMapProto::self(exec));
1208 }
1209
1210 DOMNamedNodeMap::~DOMNamedNodeMap()
1211 {
1212   ScriptInterpreter::forgetDOMObject(m_impl.get());
1213 }
1214
1215 JSValue *DOMNamedNodeMap::lengthGetter(ExecState* exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
1216 {
1217   DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
1218   return jsNumber(thisObj->m_impl->length());
1219 }
1220
1221 JSValue *DOMNamedNodeMap::indexGetter(ExecState* exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
1222 {
1223   DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
1224   return toJS(exec, thisObj->m_impl->item(slot.index()));
1225 }
1226
1227 JSValue *DOMNamedNodeMap::nameGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
1228 {
1229   DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
1230   return toJS(exec, thisObj->m_impl->getNamedItem(propertyName.domString()));
1231 }
1232
1233 bool DOMNamedNodeMap::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
1234 {
1235   if (propertyName == lengthPropertyName) {
1236       slot.setCustom(this, lengthGetter);
1237       return true;
1238   } else {
1239     // Look in the prototype (for functions) before assuming it's an item's name
1240     JSValue *proto = prototype();
1241     if (proto->isObject() && static_cast<JSObject *>(proto)->hasProperty(exec, propertyName))
1242       return false;
1243
1244     // name or index ?
1245     bool ok;
1246     unsigned idx = propertyName.toUInt32(&ok);
1247     if (ok && idx < m_impl->length()) {
1248       slot.setCustomIndex(this, idx, indexGetter);
1249       return true;
1250     }
1251
1252     if (m_impl->getNamedItem(propertyName.domString())) {
1253       slot.setCustom(this, nameGetter);
1254       return true;
1255     }
1256   }
1257
1258   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
1259 }
1260
1261 JSValue *DOMNamedNodeMapProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
1262 {
1263   if (!thisObj->inherits(&KJS::DOMNamedNodeMap::info))
1264     return throwError(exec, TypeError);
1265   DOMExceptionTranslator exception(exec);
1266   NamedNodeMapImpl &map = *static_cast<DOMNamedNodeMap *>(thisObj)->impl();
1267   switch (id) {
1268     case DOMNamedNodeMap::GetNamedItem:
1269       return toJS(exec, map.getNamedItem(args[0]->toString(exec).domString()));
1270     case DOMNamedNodeMap::SetNamedItem:
1271       return toJS(exec, map.setNamedItem(toNode(args[0]), exception).get());
1272     case DOMNamedNodeMap::RemoveNamedItem:
1273       return toJS(exec, map.removeNamedItem(args[0]->toString(exec).domString(), exception).get());
1274     case DOMNamedNodeMap::Item:
1275       return toJS(exec, map.item(args[0]->toInt32(exec)));
1276     case DOMNamedNodeMap::GetNamedItemNS: // DOM2
1277       return toJS(exec, map.getNamedItemNS(valueToStringWithNullCheck(exec, args[0]), args[1]->toString(exec).domString()));
1278     case DOMNamedNodeMap::SetNamedItemNS: // DOM2
1279       return toJS(exec, map.setNamedItemNS(toNode(args[0]), exception).get());
1280     case DOMNamedNodeMap::RemoveNamedItemNS: // DOM2
1281       return toJS(exec, map.removeNamedItemNS(valueToStringWithNullCheck(exec, args[0]), args[1]->toString(exec).domString(), exception).get());
1282   }
1283   return jsUndefined();
1284 }
1285
1286 // -------------------------------------------------------------------------
1287
1288 JSValue* toJS(ExecState *exec, DocumentImpl *n)
1289 {
1290   if (!n)
1291     return jsNull();
1292
1293   DOMDocument *ret = 0;
1294   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
1295
1296   if ((ret = static_cast<DOMDocument *>(interp->getDOMObject(n))))
1297     return ret;
1298
1299   if (n->isHTMLDocument())
1300     ret = new HTMLDocument(exec, static_cast<HTMLDocumentImpl *>(n));
1301   else
1302     ret = new DOMDocument(exec, n);
1303
1304   // Make sure the document is kept around by the window object, and works right with the
1305   // back/forward cache.
1306   if (n->frame())
1307     Window::retrieveWindow(n->frame())->putDirect("document", ret, DontDelete|ReadOnly);
1308
1309   interp->putDOMObject(n, ret);
1310
1311   return ret;
1312 }
1313
1314 bool checkNodeSecurity(ExecState *exec, NodeImpl *n)
1315 {
1316   if (!n) 
1317     return false;
1318
1319   // Check to see if the currently executing interpreter is allowed to access the specified node
1320   Frame *frame = n->getDocument()->frame();
1321   if (!frame)
1322     return false;
1323   Window *win = Window::retrieveWindow(frame);
1324   return win && win->isSafeScript(exec);
1325 }
1326
1327 JSValue *toJS(ExecState *exec, PassRefPtr<NodeImpl> node)
1328 {
1329   NodeImpl* n = node.get();
1330   DOMNode *ret = 0;
1331   if (!n)
1332     return jsNull();
1333   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
1334   DocumentImpl *doc = n->getDocument();
1335
1336   if ((ret = interp->getDOMNodeForDocument(doc, n)))
1337     return ret;
1338
1339   switch (n->nodeType()) {
1340     case WebCore::NodeImpl::ELEMENT_NODE:
1341       if (n->isHTMLElement())
1342         ret = new HTMLElement(exec, static_cast<HTMLElementImpl *>(n));
1343       else
1344         ret = new JSElement(exec, static_cast<ElementImpl *>(n));
1345       break;
1346     case WebCore::NodeImpl::ATTRIBUTE_NODE:
1347       ret = new JSAttr(exec, static_cast<AttrImpl *>(n));
1348       break;
1349     case WebCore::NodeImpl::TEXT_NODE:
1350     case WebCore::NodeImpl::CDATA_SECTION_NODE:
1351       ret = new JSText(exec, static_cast<TextImpl *>(n));
1352       break;
1353     case WebCore::NodeImpl::ENTITY_NODE:
1354       ret = new JSEntity(exec, static_cast<EntityImpl *>(n));
1355       break;
1356     case WebCore::NodeImpl::PROCESSING_INSTRUCTION_NODE:
1357       ret = new JSProcessingInstruction(exec, static_cast<ProcessingInstructionImpl *>(n));
1358       break;
1359     case WebCore::NodeImpl::COMMENT_NODE:
1360       ret = new JSCharacterData(exec, static_cast<CharacterDataImpl *>(n));
1361       break;
1362     case WebCore::NodeImpl::DOCUMENT_NODE:
1363       // we don't want to cache the document itself in the per-document dictionary
1364       return toJS(exec, static_cast<DocumentImpl *>(n));
1365     case WebCore::NodeImpl::DOCUMENT_TYPE_NODE:
1366       ret = new JSDocumentType(exec, static_cast<DocumentTypeImpl *>(n));
1367       break;
1368     case WebCore::NodeImpl::NOTATION_NODE:
1369       ret = new JSNotation(exec, static_cast<NotationImpl *>(n));
1370       break;
1371     case WebCore::NodeImpl::DOCUMENT_FRAGMENT_NODE:
1372     case WebCore::NodeImpl::ENTITY_REFERENCE_NODE:
1373     default:
1374       ret = new DOMNode(exec, n);
1375   }
1376
1377   interp->putDOMNodeForDocument(doc, n, ret);
1378
1379   return ret;
1380 }
1381
1382 JSValue *toJS(ExecState *exec, NamedNodeMapImpl *m)
1383 {
1384   return cacheDOMObject<NamedNodeMapImpl, DOMNamedNodeMap>(exec, m);
1385 }
1386
1387 JSValue *getRuntimeObject(ExecState *exec, NodeImpl *n)
1388 {
1389     if (!n)
1390         return 0;
1391
1392 #if __APPLE__
1393     if (n->hasTagName(appletTag)) {
1394         HTMLAppletElementImpl *appletElement = static_cast<HTMLAppletElementImpl *>(n);
1395         if (appletElement->getAppletInstance())
1396             // The instance is owned by the applet element.
1397             return new RuntimeObjectImp(appletElement->getAppletInstance());
1398     }
1399     else if (n->hasTagName(embedTag)) {
1400         HTMLEmbedElementImpl *embedElement = static_cast<HTMLEmbedElementImpl *>(n);
1401         if (embedElement->getEmbedInstance())
1402             return new RuntimeObjectImp(embedElement->getEmbedInstance());
1403     }
1404     else if (n->hasTagName(objectTag)) {
1405         HTMLObjectElementImpl *objectElement = static_cast<HTMLObjectElementImpl *>(n);
1406         if (objectElement->getObjectInstance())
1407             return new RuntimeObjectImp(objectElement->getObjectInstance());
1408     }
1409 #endif
1410
1411     // If we don't have a runtime object return 0.
1412     return 0;
1413 }
1414
1415 JSValue *toJS(ExecState *exec, PassRefPtr<NodeListImpl> l)
1416 {
1417   return cacheDOMObject<NodeListImpl, DOMNodeList>(exec, l.get());
1418 }
1419
1420 // -------------------------------------------------------------------------
1421
1422 const ClassInfo NodeConstructor::info = { "NodeConstructor", 0, &NodeConstructorTable, 0 };
1423 /* Source for NodeConstructorTable. Use "make hashtables" to regenerate.
1424 @begin NodeConstructorTable 11
1425   ELEMENT_NODE          WebCore::NodeImpl::ELEMENT_NODE         DontDelete|ReadOnly
1426   ATTRIBUTE_NODE        WebCore::NodeImpl::ATTRIBUTE_NODE               DontDelete|ReadOnly
1427   TEXT_NODE             WebCore::NodeImpl::TEXT_NODE            DontDelete|ReadOnly
1428   CDATA_SECTION_NODE    WebCore::NodeImpl::CDATA_SECTION_NODE   DontDelete|ReadOnly
1429   ENTITY_REFERENCE_NODE WebCore::NodeImpl::ENTITY_REFERENCE_NODE        DontDelete|ReadOnly
1430   ENTITY_NODE           WebCore::NodeImpl::ENTITY_NODE          DontDelete|ReadOnly
1431   PROCESSING_INSTRUCTION_NODE WebCore::NodeImpl::PROCESSING_INSTRUCTION_NODE DontDelete|ReadOnly
1432   COMMENT_NODE          WebCore::NodeImpl::COMMENT_NODE         DontDelete|ReadOnly
1433   DOCUMENT_NODE         WebCore::NodeImpl::DOCUMENT_NODE                DontDelete|ReadOnly
1434   DOCUMENT_TYPE_NODE    WebCore::NodeImpl::DOCUMENT_TYPE_NODE   DontDelete|ReadOnly
1435   DOCUMENT_FRAGMENT_NODE WebCore::NodeImpl::DOCUMENT_FRAGMENT_NODE      DontDelete|ReadOnly
1436   NOTATION_NODE         WebCore::NodeImpl::NOTATION_NODE                DontDelete|ReadOnly
1437 @end
1438 */
1439 bool NodeConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1440 {
1441   return getStaticValueSlot<NodeConstructor, DOMObject>(exec, &NodeConstructorTable, this, propertyName, slot);
1442 }
1443
1444 JSValue *NodeConstructor::getValueProperty(ExecState *, int token) const
1445 {
1446   // We use the token as the value to return directly
1447   return jsNumber(token);
1448 }
1449
1450 JSObject *getNodeConstructor(ExecState *exec)
1451 {
1452   return cacheGlobalObject<NodeConstructor>(exec, "[[node.constructor]]");
1453 }
1454
1455 // -------------------------------------------------------------------------
1456
1457 const ClassInfo DOMExceptionConstructor::info = { "DOMExceptionConstructor", 0, 0, 0 };
1458
1459 /* Source for DOMExceptionConstructorTable. Use "make hashtables" to regenerate.
1460 @begin DOMExceptionConstructorTable 15
1461   INDEX_SIZE_ERR                WebCore::INDEX_SIZE_ERR               DontDelete|ReadOnly
1462   DOMSTRING_SIZE_ERR            WebCore::DOMSTRING_SIZE_ERR   DontDelete|ReadOnly
1463   HIERARCHY_REQUEST_ERR         WebCore::HIERARCHY_REQUEST_ERR        DontDelete|ReadOnly
1464   WRONG_DOCUMENT_ERR            WebCore::WRONG_DOCUMENT_ERR   DontDelete|ReadOnly
1465   INVALID_CHARACTER_ERR         WebCore::INVALID_CHARACTER_ERR        DontDelete|ReadOnly
1466   NO_DATA_ALLOWED_ERR           WebCore::NO_DATA_ALLOWED_ERR  DontDelete|ReadOnly
1467   NO_MODIFICATION_ALLOWED_ERR   WebCore::NO_MODIFICATION_ALLOWED_ERR  DontDelete|ReadOnly
1468   NOT_FOUND_ERR                 WebCore::NOT_FOUND_ERR                DontDelete|ReadOnly
1469   NOT_SUPPORTED_ERR             WebCore::NOT_SUPPORTED_ERR    DontDelete|ReadOnly
1470   INUSE_ATTRIBUTE_ERR           WebCore::INUSE_ATTRIBUTE_ERR  DontDelete|ReadOnly
1471   INVALID_STATE_ERR             WebCore::INVALID_STATE_ERR    DontDelete|ReadOnly
1472   SYNTAX_ERR                    WebCore::SYNTAX_ERR           DontDelete|ReadOnly
1473   INVALID_MODIFICATION_ERR      WebCore::INVALID_MODIFICATION_ERR     DontDelete|ReadOnly
1474   NAMESPACE_ERR                 WebCore::NAMESPACE_ERR                DontDelete|ReadOnly
1475   INVALID_ACCESS_ERR            WebCore::INVALID_ACCESS_ERR   DontDelete|ReadOnly
1476 @end
1477 */
1478
1479 bool DOMExceptionConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1480 {
1481   return getStaticValueSlot<DOMExceptionConstructor, DOMObject>(exec, &DOMExceptionConstructorTable, this, propertyName, slot);
1482 }
1483
1484 JSValue *DOMExceptionConstructor::getValueProperty(ExecState *, int token) const
1485 {
1486   // We use the token as the value to return directly
1487   return jsNumber(token);
1488 }
1489
1490 JSObject *getDOMExceptionConstructor(ExecState *exec)
1491 {
1492   return cacheGlobalObject<DOMExceptionConstructor>(exec, "[[DOMException.constructor]]");
1493 }
1494
1495 // -------------------------------------------------------------------------
1496
1497 // Such a collection is usually very short-lived, it only exists
1498 // for constructs like document.forms.<name>[1],
1499 // so it shouldn't be a problem that it's storing all the nodes (with the same name). (David)
1500 DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState *, const QValueList< RefPtr<NodeImpl> >& nodes )
1501   : m_nodes(nodes)
1502 {
1503 }
1504
1505 JSValue *DOMNamedNodesCollection::lengthGetter(ExecState* exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
1506 {
1507   DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection *>(slot.slotBase());
1508   return jsNumber(thisObj->m_nodes.count());
1509 }
1510
1511 JSValue *DOMNamedNodesCollection::indexGetter(ExecState* exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
1512 {
1513   DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection *>(slot.slotBase());
1514   return toJS(exec, thisObj->m_nodes[slot.index()].get());
1515 }
1516
1517 bool DOMNamedNodesCollection::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1518 {
1519   if (propertyName == lengthPropertyName) {
1520     slot.setCustom(this, lengthGetter);
1521     return true;
1522   }
1523
1524   // array index ?
1525   bool ok;
1526   unsigned idx = propertyName.toUInt32(&ok);
1527   if (ok && idx < m_nodes.count()) {
1528     slot.setCustomIndex(this, idx, indexGetter);
1529     return true;
1530   }
1531
1532   // For IE compatibility, we need to be able to look up elements in a
1533   // document.formName.name result by id as well as be index.
1534
1535   QValueListConstIterator< RefPtr<NodeImpl> > end = m_nodes.end();
1536   int i = 0;
1537   for (QValueListConstIterator< RefPtr<NodeImpl> > it = m_nodes.begin(); it != end; ++it, ++i) {
1538     NodeImpl *node = (*it).get();
1539     if (node->hasAttributes() &&
1540         node->attributes()->id() == propertyName.domString()) {
1541       slot.setCustomIndex(this, i, indexGetter);
1542       return true;
1543     }
1544   }
1545
1546   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
1547 }
1548
1549 // -------------------------------------------------------------------------
1550
1551
1552 } // namespace