LayoutTests:
[WebKit-https.git] / WebCore / bindings / js / 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) 2006 Jon Shier (jshier@iastate.edu)
5  *  Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "kjs_dom.h"
24
25 #include "CDATASection.h"
26 #include "Comment.h"
27 #include "DOMImplementation.h"
28 #include "DocumentFragment.h"
29 #include "DocumentType.h"
30 #include "ExceptionCode.h"
31 #include "EventNames.h"
32 #include "Frame.h"
33 #include "JSAttr.h"
34 #include "JSElement.h"
35 #include "JSCharacterData.h"
36 #include "JSDOMImplementation.h"
37 #include "JSDocumentType.h"
38 #include "JSEntity.h"
39 #include "JSNotation.h"
40 #include "JSProcessingInstruction.h"
41 #include "JSRange.h"
42 #include "JSText.h"
43 #include "css_ruleimpl.h"
44 #include "css_stylesheetimpl.h"
45 #include "dom2_eventsimpl.h"
46 #include "Range.h"
47 #include "dom_xmlimpl.h"
48 #include "HTMLDocument.h"
49 #include "html_objectimpl.h"
50 #include "JSHTMLElementWrapperFactory.h"
51 #include "HTMLNames.h"
52 #include "KWQKHTMLSettings.h"
53 #include "kjs_css.h"
54 #include "kjs_events.h"
55 #include "kjs_traversal.h"
56 #include "kjs_window.h"
57 #include "RenderCanvas.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 25
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 # "DOM level 0" (from Gecko DOM reference; also in WinIE)
91   item          DOMNode::Item           DontDelete|Function 1
92 @end
93 */
94 KJS_IMPLEMENT_PROTOFUNC(DOMNodeProtoFunc)
95 KJS_IMPLEMENT_PROTOTYPE("DOMNode", DOMNodeProto, DOMNodeProtoFunc)
96
97 const ClassInfo DOMNode::info = { "Node", 0, &DOMNodeTable, 0 };
98
99 DOMNode::DOMNode(ExecState *exec, WebCore::Node* n)
100   : m_impl(n)
101 {
102   setPrototype(DOMNodeProto::self(exec));
103 }
104
105 DOMNode::DOMNode(WebCore::Node* n)
106   : m_impl(n)
107 {
108 }
109
110 DOMNode::~DOMNode()
111 {
112   ScriptInterpreter::forgetDOMNodeForDocument(m_impl->document(), m_impl.get());
113 }
114
115 void DOMNode::mark()
116 {
117   assert(!marked());
118
119   WebCore::Node* node = m_impl.get();
120
121   // Nodes in the document are kept alive by ScriptInterpreter::mark,
122   // so we have no special responsibilities and can just call the base class here.
123   if (node->inDocument()) {
124     DOMObject::mark();
125     return;
126   }
127
128   // This is a node outside the document, so find the root of the tree it is in,
129   // and start marking from there.
130   WebCore::Node* root = node;
131   for (WebCore::Node* current = m_impl.get(); current; current = current->parentNode()) {
132     root = current;
133   }
134
135   static HashSet<WebCore::Node*> markingRoots;
136
137   // If we're already marking this tree, then we can simply mark this wrapper
138   // by calling the base class; our caller is iterating the tree.
139   if (markingRoots.contains(root)) {
140     DOMObject::mark();
141     return;
142   }
143
144   // Mark the whole tree; use the global set of roots to avoid reentering.
145   markingRoots.add(root);
146   for (WebCore::Node* nodeToMark = root; nodeToMark; nodeToMark = nodeToMark->traverseNextNode()) {
147     DOMNode *wrapper = ScriptInterpreter::getDOMNodeForDocument(m_impl->document(), nodeToMark);
148     if (wrapper) {
149       if (!wrapper->marked())
150         wrapper->mark();
151     } else if (nodeToMark == node) {
152       // This is the case where the map from the document to wrappers has
153       // been cleared out, but a wrapper is being marked. For now, we'll
154       // let the rest of the tree of wrappers get collected, because we have
155       // no good way of finding them. Later we should test behavior of other
156       // browsers and see if we need to preserve other wrappers in this case.
157       if (!marked())
158         mark();
159     }
160   }
161   markingRoots.remove(root);
162
163   // Double check that we actually ended up marked. This assert caught problems in the past.
164   assert(marked());
165 }
166
167 bool DOMNode::toBoolean(ExecState *) const
168 {
169     return m_impl;
170 }
171
172 /* Source for DOMNodeTable. Use "make hashtables" to regenerate.
173 @begin DOMNodeTable 25
174   nodeName      DOMNode::NodeName       DontDelete|ReadOnly
175   nodeValue     DOMNode::NodeValue      DontDelete
176   nodeType      DOMNode::NodeType       DontDelete|ReadOnly
177   parentNode    DOMNode::ParentNode     DontDelete|ReadOnly
178   parentElement DOMNode::ParentElement  DontDelete|ReadOnly
179   childNodes    DOMNode::ChildNodes     DontDelete|ReadOnly
180   firstChild    DOMNode::FirstChild     DontDelete|ReadOnly
181   lastChild     DOMNode::LastChild      DontDelete|ReadOnly
182   previousSibling  DOMNode::PreviousSibling DontDelete|ReadOnly
183   nextSibling   DOMNode::NextSibling    DontDelete|ReadOnly
184   attributes    DOMNode::Attributes     DontDelete|ReadOnly
185   namespaceURI  DOMNode::NamespaceURI   DontDelete|ReadOnly
186 # DOM2
187   prefix        DOMNode::Prefix         DontDelete
188   localName     DOMNode::LocalName      DontDelete|ReadOnly
189   ownerDocument DOMNode::OwnerDocument  DontDelete|ReadOnly
190 # DOM3
191   textContent   DOMNode::TextContent    DontDelete
192 @end
193 */
194 bool DOMNode::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
195 {
196   return getStaticValueSlot<DOMNode, DOMObject>(exec, &DOMNodeTable, this, propertyName, slot);
197 }
198
199 JSValue *DOMNode::getValueProperty(ExecState *exec, int token) const
200 {
201   WebCore::Node& node = *m_impl;
202   switch (token) {
203   case NodeName:
204     return jsStringOrNull(node.nodeName());
205   case NodeValue:
206     return jsStringOrNull(node.nodeValue());
207   case NodeType:
208     return jsNumber(node.nodeType());
209   case ParentNode:
210   case ParentElement: // IE only apparently
211     return toJS(exec,node.parentNode());
212   case ChildNodes:
213     return toJS(exec,node.childNodes().get());
214   case FirstChild:
215     return toJS(exec,node.firstChild());
216   case LastChild:
217     return toJS(exec,node.lastChild());
218   case PreviousSibling:
219     return toJS(exec,node.previousSibling());
220   case NextSibling:
221     return toJS(exec,node.nextSibling());
222   case Attributes:
223     return toJS(exec,node.attributes());
224   case NamespaceURI:
225     return jsStringOrNull(node.namespaceURI());
226   case Prefix:
227     return jsStringOrNull(node.prefix());
228   case LocalName:
229     return jsStringOrNull(node.localName());
230   case OwnerDocument:
231     return toJS(exec,node.ownerDocument());
232   case TextContent:
233     return jsStringOrNull(node.textContent());
234   }
235
236   return jsUndefined();
237 }
238
239 void DOMNode::put(ExecState *exec, const Identifier& propertyName, JSValue *value, int attr)
240 {
241     lookupPut<DOMNode,DOMObject>(exec, propertyName, value, attr, &DOMNodeTable, this);
242 }
243
244 void DOMNode::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/)
245 {
246   DOMExceptionTranslator exception(exec);
247   WebCore::Node& node = *m_impl;
248   switch (token) {
249   case NodeValue:
250     node.setNodeValue(value->toString(exec), exception);
251     break;
252   case Prefix:
253     node.setPrefix(value->toString(exec), exception);
254     break;
255   case TextContent:
256     node.setTextContent(valueToStringWithNullCheck(exec, value), exception);
257     break;
258   }
259 }
260
261 JSValue *DOMNode::toPrimitive(ExecState *exec, JSType) const
262 {
263   if (!m_impl)
264     return jsNull();
265
266   return jsString(toString(exec));
267 }
268
269 UString DOMNode::toString(ExecState *) const
270 {
271   if (!m_impl)
272     return "null";
273   return "[object " + (m_impl->isElementNode() ? UString(m_impl->nodeName()) : className()) + "]";
274 }
275
276 JSValue *DOMNodeProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
277 {
278   if (!thisObj->inherits(&DOMNode::info))
279     return throwError(exec, TypeError);
280   DOMExceptionTranslator exception(exec);
281   WebCore::Node& node = *static_cast<DOMNode*>(thisObj)->impl();
282   switch (id) {
283     case DOMNode::HasAttributes:
284       return jsBoolean(node.hasAttributes());
285     case DOMNode::HasChildNodes:
286       return jsBoolean(node.hasChildNodes());
287     case DOMNode::CloneNode:
288       return toJS(exec,node.cloneNode(args[0]->toBoolean(exec)));
289     case DOMNode::Normalize:
290       node.normalize();
291       return jsUndefined();
292     case DOMNode::IsSupported:
293         return jsBoolean(node.isSupported(args[0]->toString(exec),
294                                           valueToStringWithNullCheck(exec, args[1])));
295     case DOMNode::IsSameNode:
296         return jsBoolean(node.isSameNode(toNode(args[0])));
297     case DOMNode::IsEqualNode:
298         return jsBoolean(node.isEqualNode(toNode(args[0])));
299     case DOMNode::IsDefaultNamespace:
300         return jsBoolean(node.isDefaultNamespace(valueToStringWithNullCheck(exec, args[0])));
301     case DOMNode::LookupNamespaceURI:
302         return jsStringOrNull(node.lookupNamespaceURI(valueToStringWithNullCheck(exec, args[0])));
303     case DOMNode::LookupPrefix:
304         return jsStringOrNull(node.lookupPrefix(valueToStringWithNullCheck(exec, args[0])));
305     case DOMNode::AppendChild:
306       if (node.appendChild(toNode(args[0]), exception))
307         return args[0];
308       return jsNull();
309     case DOMNode::RemoveChild:
310       if (node.removeChild(toNode(args[0]), exception))
311         return args[0];
312       return jsNull();
313     case DOMNode::InsertBefore:
314       if (node.insertBefore(toNode(args[0]), toNode(args[1]), exception))
315         return args[0];
316       return jsNull();
317     case DOMNode::ReplaceChild:
318      if (node.replaceChild(toNode(args[0]), toNode(args[1]), exception))
319         return args[1];
320       return jsNull();
321     case DOMNode::Item:
322       return thisObj->get(exec, args[0]->toInt32(exec));
323   }
324
325   return jsUndefined();
326 }
327
328 EventTargetNode *toEventTargetNode(JSValue *val)
329 {
330     if (!val || !val->isObject(&DOMEventTargetNode::info))
331         return 0;
332     return static_cast<EventTargetNode*>(static_cast<DOMEventTargetNode *>(val)->impl());
333 }
334
335 WebCore::Node* toNode(JSValue* val)
336 {
337     if (!val || !val->isObject(&DOMNode::info))
338         return 0;
339     return static_cast<DOMNode *>(val)->impl();
340 }
341
342 // -------------------------------------------------------------------------
343
344 /* Source for DOMEventTargetNodeTable
345 @begin DOMEventTargetNodeTable 50
346 onabort       DOMEventTargetNode::OnAbort                DontDelete
347 onblur        DOMEventTargetNode::OnBlur                 DontDelete
348 onchange      DOMEventTargetNode::OnChange               DontDelete
349 onclick       DOMEventTargetNode::OnClick                DontDelete
350 oncontextmenu DOMEventTargetNode::OnContextMenu          DontDelete
351 ondblclick    DOMEventTargetNode::OnDblClick             DontDelete
352 onbeforecut   DOMEventTargetNode::OnBeforeCut            DontDelete
353 oncut         DOMEventTargetNode::OnCut                  DontDelete
354 onbeforecopy  DOMEventTargetNode::OnBeforeCopy           DontDelete
355 oncopy        DOMEventTargetNode::OnCopy                 DontDelete
356 onbeforepaste DOMEventTargetNode::OnBeforePaste          DontDelete
357 onpaste       DOMEventTargetNode::OnPaste                DontDelete
358 ondrag        DOMEventTargetNode::OnDrag                 DontDelete
359 ondragdrop    DOMEventTargetNode::OnDragDrop             DontDelete
360 ondragend     DOMEventTargetNode::OnDragEnd              DontDelete
361 ondragenter   DOMEventTargetNode::OnDragEnter            DontDelete
362 ondragleave   DOMEventTargetNode::OnDragLeave            DontDelete
363 ondragover    DOMEventTargetNode::OnDragOver             DontDelete
364 ondragstart   DOMEventTargetNode::OnDragStart            DontDelete
365 ondrop        DOMEventTargetNode::OnDrop                 DontDelete
366 onerror       DOMEventTargetNode::OnError                DontDelete
367 onfocus       DOMEventTargetNode::OnFocus                DontDelete
368 oninput       DOMEventTargetNode::OnInput                DontDelete
369 onkeydown     DOMEventTargetNode::OnKeyDown              DontDelete
370 onkeypress    DOMEventTargetNode::OnKeyPress             DontDelete
371 onkeyup       DOMEventTargetNode::OnKeyUp                DontDelete
372 onload        DOMEventTargetNode::OnLoad                 DontDelete
373 onmousedown   DOMEventTargetNode::OnMouseDown            DontDelete
374 onmousemove   DOMEventTargetNode::OnMouseMove            DontDelete
375 onmouseout    DOMEventTargetNode::OnMouseOut             DontDelete
376 onmouseover   DOMEventTargetNode::OnMouseOver            DontDelete
377 onmouseup     DOMEventTargetNode::OnMouseUp              DontDelete
378 onmousewheel  DOMEventTargetNode::OnMouseWheel           DontDelete
379 onmove        DOMEventTargetNode::OnMove                 DontDelete
380 onreset       DOMEventTargetNode::OnReset                DontDelete
381 onresize      DOMEventTargetNode::OnResize               DontDelete
382 onscroll      DOMEventTargetNode::OnScroll               DontDelete
383 onsearch      DOMEventTargetNode::OnSearch               DontDelete
384 onselect      DOMEventTargetNode::OnSelect               DontDelete
385 onselectstart DOMEventTargetNode::OnSelectStart          DontDelete
386 onsubmit      DOMEventTargetNode::OnSubmit               DontDelete
387 onunload      DOMEventTargetNode::OnUnload               DontDelete
388 @end
389 */
390
391 DOMEventTargetNode::DOMEventTargetNode(WebCore::Node* n)
392     : DOMNode(n)
393 {
394 }
395
396 DOMEventTargetNode::DOMEventTargetNode(ExecState* exec, WebCore::Node* n)
397     : DOMNode(n)
398 {
399     setPrototype(DOMEventTargetNodeProto::self(exec));
400 }
401
402 bool DOMEventTargetNode::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
403 {
404     return getStaticValueSlot<DOMEventTargetNode, DOMNode>(exec, &DOMEventTargetNodeTable, this, propertyName, slot);
405 }
406
407 JSValue *DOMEventTargetNode::getValueProperty(ExecState *exec, int token) const
408 {
409     switch (token) {
410         case OnAbort:
411             return getListener(abortEvent);
412         case OnBlur:
413             return getListener(blurEvent);
414         case OnChange:
415             return getListener(changeEvent);
416         case OnClick:
417             return getListener(clickEvent);
418         case OnContextMenu:
419             return getListener(contextmenuEvent);
420         case OnDblClick:
421             return getListener(dblclickEvent);
422         case OnDragDrop:
423             return getListener(khtmlDragdropEvent);
424         case OnError:
425             return getListener(errorEvent);
426         case OnFocus:
427             return getListener(focusEvent);
428         case OnInput:
429             return getListener(inputEvent);
430         case OnKeyDown:
431             return getListener(keydownEvent);
432         case OnKeyPress:
433             return getListener(keypressEvent);
434         case OnKeyUp:
435             return getListener(keyupEvent);
436         case OnLoad:
437             return getListener(loadEvent);
438         case OnMouseDown:
439             return getListener(mousedownEvent);
440         case OnMouseMove:
441             return getListener(mousemoveEvent);
442         case OnMouseOut:
443             return getListener(mouseoutEvent);
444         case OnMouseOver:
445             return getListener(mouseoverEvent);
446         case OnMouseUp:
447             return getListener(mouseupEvent);      
448         case OnMouseWheel:
449             return getListener(mousewheelEvent);      
450         case OnBeforeCut:
451             return getListener(beforecutEvent);
452         case OnCut:
453             return getListener(cutEvent);
454         case OnBeforeCopy:
455             return getListener(beforecopyEvent);
456         case OnCopy:
457             return getListener(copyEvent);
458         case OnBeforePaste:
459             return getListener(beforepasteEvent);
460         case OnPaste:
461             return getListener(pasteEvent);
462         case OnDragEnter:
463             return getListener(dragenterEvent);
464         case OnDragOver:
465             return getListener(dragoverEvent);
466         case OnDragLeave:
467             return getListener(dragleaveEvent);
468         case OnDrop:
469             return getListener(dropEvent);
470         case OnDragStart:
471             return getListener(dragstartEvent);
472         case OnDrag:
473             return getListener(dragEvent);
474         case OnDragEnd:
475             return getListener(dragendEvent);
476         case OnMove:
477             return getListener(khtmlMoveEvent);
478         case OnReset:
479             return getListener(resetEvent);
480         case OnResize:
481             return getListener(resizeEvent);
482         case OnScroll:
483             return getListener(scrollEvent);
484         case OnSearch:
485             return getListener(searchEvent);
486         case OnSelect:
487             return getListener(selectEvent);
488         case OnSelectStart:
489             return getListener(selectstartEvent);
490         case OnSubmit:
491             return getListener(submitEvent);
492         case OnUnload:
493             return getListener(unloadEvent);
494     }
495     
496     return jsUndefined();
497 }
498
499 void DOMEventTargetNode::put(ExecState *exec, const Identifier& propertyName, JSValue *value, int attr)
500 {
501     lookupPut<DOMEventTargetNode, DOMNode>(exec, propertyName, value, attr, &DOMEventTargetNodeTable, this);
502 }
503
504 void DOMEventTargetNode::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/)
505 {
506     switch (token) {
507         case OnAbort:
508             setListener(exec, abortEvent, value);
509             break;
510         case OnBlur:
511             setListener(exec, blurEvent, value);
512             break;
513         case OnChange:
514             setListener(exec, changeEvent, value);
515             break;
516         case OnClick:
517             setListener(exec, clickEvent, value);
518             break;
519         case OnContextMenu:
520             setListener(exec, contextmenuEvent, value);
521             break;
522         case OnDblClick:
523             setListener(exec, dblclickEvent, value);
524             break;
525         case OnDragDrop:
526             setListener(exec, khtmlDragdropEvent, value);
527             break;
528         case OnError:
529             setListener(exec, errorEvent, value);
530             break;
531         case OnFocus:
532             setListener(exec, focusEvent, value);
533             break;
534         case OnInput:
535             setListener(exec, inputEvent, value);
536             break;
537         case OnKeyDown:
538             setListener(exec, keydownEvent, value);
539             break;
540         case OnKeyPress:
541             setListener(exec, keypressEvent, value);
542             break;
543         case OnKeyUp:
544             setListener(exec, keyupEvent, value);
545             break;
546         case OnLoad:
547             setListener(exec, loadEvent, value);
548             break;
549         case OnMouseDown:
550             setListener(exec, mousedownEvent, value);
551             break;
552         case OnMouseMove:
553             setListener(exec, mousemoveEvent, value);
554             break;
555         case OnMouseOut:
556             setListener(exec, mouseoutEvent, value);
557             break;
558         case OnMouseOver:
559             setListener(exec, mouseoverEvent, value);
560             break;
561         case OnMouseUp:
562             setListener(exec, mouseupEvent, value);
563             break;
564         case OnMouseWheel:
565             setListener(exec, mousewheelEvent, value);
566             break;
567         case OnBeforeCut:
568             setListener(exec, beforecutEvent, value);
569             break;
570         case OnCut:
571             setListener(exec, cutEvent, value);
572             break;
573         case OnBeforeCopy:
574             setListener(exec, beforecopyEvent, value);
575             break;
576         case OnCopy:
577             setListener(exec, copyEvent, value);
578             break;
579         case OnBeforePaste:
580             setListener(exec, beforepasteEvent, value);
581             break;
582         case OnPaste:
583             setListener(exec, pasteEvent, value);
584             break;
585         case OnDragEnter:
586             setListener(exec, dragenterEvent, value);
587             break;
588         case OnDragOver:
589             setListener(exec, dragoverEvent, value);
590             break;
591         case OnDragLeave:
592             setListener(exec, dragleaveEvent, value);
593             break;
594         case OnDrop:
595             setListener(exec, dropEvent, value);
596             break;
597         case OnDragStart:
598             setListener(exec, dragstartEvent, value);
599             break;
600         case OnDrag:
601             setListener(exec, dragEvent, value);
602             break;
603         case OnDragEnd:
604             setListener(exec, dragendEvent, value);
605             break;
606         case OnMove:
607             setListener(exec, khtmlMoveEvent, value);
608             break;
609         case OnReset:
610             setListener(exec, resetEvent, value);
611             break;
612         case OnResize:
613             setListener(exec, resizeEvent, value);
614             break;
615         case OnScroll:
616             setListener(exec, scrollEvent, value);
617             break;
618         case OnSearch:
619             setListener(exec, searchEvent, value);
620             break;
621         case OnSelect:
622             setListener(exec, selectEvent, value);
623             break;
624         case OnSelectStart:
625             setListener(exec, selectstartEvent, value);
626             break;
627         case OnSubmit:
628             setListener(exec, submitEvent, value);
629             break;
630         case OnUnload:
631             setListener(exec, unloadEvent, value);
632             break;
633     }
634 }
635
636 void DOMEventTargetNode::setListener(ExecState *exec, const AtomicString &eventType, JSValue *func) const
637 {
638     EventTargetNodeCast(impl())->setHTMLEventListener(eventType, Window::retrieveActive(exec)->getJSEventListener(func, true));
639 }
640
641 JSValue *DOMEventTargetNode::getListener(const AtomicString &eventType) const
642 {
643     WebCore::EventListener *listener = EventTargetNodeCast(impl())->getHTMLEventListener(eventType);
644     JSEventListener *jsListener = static_cast<JSEventListener*>(listener);
645     if (jsListener && jsListener->listenerObj())
646         return jsListener->listenerObj();
647     else
648         return jsNull();
649 }
650
651 void DOMEventTargetNode::pushEventHandlerScope(ExecState *, ScopeChain &) const
652 {
653 }
654
655 /*
656 @begin DOMEventTargetNodeProtoTable 5
657 # from the EventTarget interface
658 addEventListener        DOMEventTargetNode::AddEventListener   DontDelete|Function 3
659 removeEventListener     DOMEventTargetNode::RemoveEventListener    DontDelete|Function 3
660 dispatchEvent           DOMEventTargetNode::DispatchEvent  DontDelete|Function 1
661 @end
662 */
663
664 KJS_IMPLEMENT_PROTOFUNC(DOMEventTargetNodeProtoFunc)
665 KJS_IMPLEMENT_PROTOTYPE("DOMEventTargetNode", DOMEventTargetNodeProto, DOMEventTargetNodeProtoFunc)
666
667 JSValue *DOMEventTargetNodeProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
668 {
669     if (!thisObj->inherits(&DOMEventTargetNode::info))
670         return throwError(exec, TypeError);
671     DOMExceptionTranslator exception(exec);
672     DOMEventTargetNode* DOMNode = static_cast<DOMEventTargetNode*>(thisObj);
673     EventTargetNode* node = static_cast<EventTargetNode*>(DOMNode->impl());
674     switch (id) {
675         case DOMEventTargetNode::AddEventListener: {
676             JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
677             if (listener)
678                 node->addEventListener(args[0]->toString(exec), listener,args[2]->toBoolean(exec));
679             return jsUndefined();
680         }
681         case DOMEventTargetNode::RemoveEventListener: {
682             JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
683             if (listener)
684                 node->removeEventListener(args[0]->toString(exec), listener,args[2]->toBoolean(exec));
685             return jsUndefined();
686         }
687         case DOMEventTargetNode::DispatchEvent:
688             return jsBoolean(node->dispatchEvent(toEvent(args[0]), exception));
689     }
690     
691     return jsUndefined();
692 }
693
694 // -------------------------------------------------------------------------
695
696 /*
697 @begin DOMNodeListTable 2
698   length        DOMNodeList::Length     DontDelete|ReadOnly
699   item          DOMNodeList::Item               DontDelete|Function 1
700 @end
701 */
702
703 KJS_IMPLEMENT_PROTOFUNC(DOMNodeListFunc)
704
705 const ClassInfo DOMNodeList::info = { "NodeList", 0, &DOMNodeListTable, 0 };
706
707 DOMNodeList::~DOMNodeList()
708 {
709   ScriptInterpreter::forgetDOMObject(m_impl.get());
710 }
711
712 JSValue *DOMNodeList::toPrimitive(ExecState *exec, JSType) const
713 {
714   if (!m_impl)
715     return jsNull();
716
717   return jsString(toString(exec));
718 }
719
720 JSValue *DOMNodeList::getValueProperty(ExecState *exec, int token) const
721 {
722   assert(token == Length);
723   return jsNumber(m_impl->length());
724 }
725
726 JSValue *DOMNodeList::indexGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
727 {
728   DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
729   return toJS(exec, thisObj->m_impl->item(slot.index()));
730 }
731
732 JSValue *DOMNodeList::nameGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
733 {
734   DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
735   return toJS(exec, thisObj->m_impl->itemById(propertyName));
736 }
737
738 bool DOMNodeList::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
739 {
740   const HashEntry* entry = Lookup::findEntry(&DOMNodeListTable, propertyName);
741
742   if (entry) {
743     if (entry->attr & Function)
744       slot.setStaticEntry(this, entry, staticFunctionGetter<DOMNodeListFunc>);
745     else
746       slot.setStaticEntry(this, entry, staticValueGetter<DOMNodeList>);
747     return true;
748   }
749
750   NodeList &list = *m_impl;
751
752   // array index ?
753   bool ok;
754   unsigned idx = propertyName.toUInt32(&ok);
755   if (ok && idx < list.length()) {
756     slot.setCustomIndex(this, idx, indexGetter);
757     return true;
758   } else if (list.itemById(String(propertyName).impl())) {
759     slot.setCustom(this, nameGetter);
760     return true;
761   }
762
763   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
764 }
765
766 // Need to support both get and call, so that list[0] and list(0) work.
767 JSValue *DOMNodeList::callAsFunction(ExecState *exec, JSObject *, const List &args)
768 {
769   // Do not use thisObj here. See JSHTMLCollection.
770   UString s = args[0]->toString(exec);
771   bool ok;
772   unsigned int u = s.toUInt32(&ok);
773   if (ok)
774     return toJS(exec, m_impl->item(u));
775
776   return jsUndefined();
777 }
778
779 // Not a prototype class currently, but should probably be converted to one
780 JSValue *DOMNodeListFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
781 {
782   if (!thisObj->inherits(&KJS::DOMNodeList::info))
783     return throwError(exec, TypeError);
784   WebCore::NodeList &list = *static_cast<DOMNodeList *>(thisObj)->impl();
785
786   if (id == DOMNodeList::Item)
787     return toJS(exec, list.item(args[0]->toInt32(exec)));
788
789   return jsUndefined();
790 }
791
792 Attr* toAttr(JSValue* val, bool& ok)
793 {
794     if (!val || !val->isObject(&JSAttr::info)) {
795         ok = false;
796         return 0;
797     }
798
799     ok = true;
800     return static_cast<Attr *>(static_cast<DOMNode *>(val)->impl());
801 }
802
803 Element *toElement(JSValue *val)
804 {
805     if (!val || !val->isObject(&JSElement::info))
806         return 0;
807     return static_cast<Element *>(static_cast<JSElement *>(val)->impl());
808 }
809
810 DocumentType *toDocumentType(JSValue *val)
811 {
812     if (!val || !val->isObject(&JSDocumentType::info))
813         return 0;
814     return static_cast<DocumentType *>(static_cast<DOMNode *>(val)->impl());
815 }
816
817 // -------------------------------------------------------------------------
818
819 /* Source for DOMNamedNodeMapProtoTable. Use "make hashtables" to regenerate.
820 @begin DOMNamedNodeMapProtoTable 10
821   getNamedItem          DOMNamedNodeMap::GetNamedItem           DontDelete|Function 1
822   setNamedItem          DOMNamedNodeMap::SetNamedItem           DontDelete|Function 1
823   removeNamedItem       DOMNamedNodeMap::RemoveNamedItem        DontDelete|Function 1
824   item                  DOMNamedNodeMap::Item                   DontDelete|Function 1
825 # DOM2
826   getNamedItemNS        DOMNamedNodeMap::GetNamedItemNS         DontDelete|Function 2
827   setNamedItemNS        DOMNamedNodeMap::SetNamedItemNS         DontDelete|Function 1
828   removeNamedItemNS     DOMNamedNodeMap::RemoveNamedItemNS      DontDelete|Function 2
829 @end
830 */
831 KJS_DEFINE_PROTOTYPE(DOMNamedNodeMapProto)
832 KJS_IMPLEMENT_PROTOFUNC(DOMNamedNodeMapProtoFunc)
833 KJS_IMPLEMENT_PROTOTYPE("NamedNodeMap",DOMNamedNodeMapProto,DOMNamedNodeMapProtoFunc)
834
835 const ClassInfo DOMNamedNodeMap::info = { "NamedNodeMap", 0, 0, 0 };
836
837 DOMNamedNodeMap::DOMNamedNodeMap(ExecState *exec, NamedNodeMap *m)
838   : m_impl(m) 
839
840   setPrototype(DOMNamedNodeMapProto::self(exec));
841 }
842
843 DOMNamedNodeMap::~DOMNamedNodeMap()
844 {
845   ScriptInterpreter::forgetDOMObject(m_impl.get());
846 }
847
848 JSValue *DOMNamedNodeMap::lengthGetter(ExecState* exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
849 {
850   DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
851   return jsNumber(thisObj->m_impl->length());
852 }
853
854 JSValue *DOMNamedNodeMap::indexGetter(ExecState* exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
855 {
856   DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
857   return toJS(exec, thisObj->m_impl->item(slot.index()));
858 }
859
860 JSValue *DOMNamedNodeMap::nameGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
861 {
862   DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase());
863   return toJS(exec, thisObj->m_impl->getNamedItem(propertyName));
864 }
865
866 bool DOMNamedNodeMap::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
867 {
868   if (propertyName == lengthPropertyName) {
869       slot.setCustom(this, lengthGetter);
870       return true;
871   } else {
872     // Look in the prototype (for functions) before assuming it's an item's name
873     JSValue *proto = prototype();
874     if (proto->isObject() && static_cast<JSObject *>(proto)->hasProperty(exec, propertyName))
875       return false;
876
877     // name or index ?
878     bool ok;
879     unsigned idx = propertyName.toUInt32(&ok);
880     if (ok && idx < m_impl->length()) {
881       slot.setCustomIndex(this, idx, indexGetter);
882       return true;
883     }
884
885     if (m_impl->getNamedItem(propertyName)) {
886       slot.setCustom(this, nameGetter);
887       return true;
888     }
889   }
890
891   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
892 }
893
894 JSValue *DOMNamedNodeMapProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
895 {
896   if (!thisObj->inherits(&KJS::DOMNamedNodeMap::info))
897     return throwError(exec, TypeError);
898   DOMExceptionTranslator exception(exec);
899   NamedNodeMap &map = *static_cast<DOMNamedNodeMap *>(thisObj)->impl();
900   switch (id) {
901     case DOMNamedNodeMap::GetNamedItem:
902       return toJS(exec, map.getNamedItem(args[0]->toString(exec)));
903     case DOMNamedNodeMap::SetNamedItem:
904       return toJS(exec, map.setNamedItem(toNode(args[0]), exception).get());
905     case DOMNamedNodeMap::RemoveNamedItem:
906       return toJS(exec, map.removeNamedItem(args[0]->toString(exec), exception).get());
907     case DOMNamedNodeMap::Item:
908       return toJS(exec, map.item(args[0]->toInt32(exec)));
909     case DOMNamedNodeMap::GetNamedItemNS: // DOM2
910       return toJS(exec, map.getNamedItemNS(valueToStringWithNullCheck(exec, args[0]), args[1]->toString(exec)));
911     case DOMNamedNodeMap::SetNamedItemNS: // DOM2
912       return toJS(exec, map.setNamedItemNS(toNode(args[0]), exception).get());
913     case DOMNamedNodeMap::RemoveNamedItemNS: // DOM2
914       return toJS(exec, map.removeNamedItemNS(valueToStringWithNullCheck(exec, args[0]), args[1]->toString(exec), exception).get());
915   }
916   return jsUndefined();
917 }
918
919 // -------------------------------------------------------------------------
920
921 JSValue* toJS(ExecState *exec, Document *n)
922 {
923   if (!n)
924     return jsNull();
925
926   JSDocument *ret = 0;
927   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
928
929   if ((ret = static_cast<JSDocument *>(interp->getDOMObject(n))))
930     return ret;
931
932   if (n->isHTMLDocument())
933     ret = new JSHTMLDocument(exec, static_cast<HTMLDocument *>(n));
934   else
935     ret = new JSDocument(exec, n);
936
937   // Make sure the document is kept around by the window object, and works right with the
938   // back/forward cache.
939   if (n->frame())
940     Window::retrieveWindow(n->frame())->putDirect("document", ret, DontDelete|ReadOnly);
941
942   interp->putDOMObject(n, ret);
943
944   return ret;
945 }
946
947 bool checkNodeSecurity(ExecState* exec, WebCore::Node* n)
948 {
949   if (!n) 
950     return false;
951
952   // Check to see if the currently executing interpreter is allowed to access the specified node
953   Window *win = Window::retrieveWindow(n->document()->frame());
954   return win && win->isSafeScript(exec);
955 }
956
957 JSValue* toJS(ExecState *exec, PassRefPtr<WebCore::Node> node)
958 {
959   WebCore::Node* n = node.get();
960   DOMNode *ret = 0;
961   if (!n)
962     return jsNull();
963   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter());
964   Document *doc = n->document();
965
966   if ((ret = interp->getDOMNodeForDocument(doc, n)))
967     return ret;
968
969   switch (n->nodeType()) {
970     case WebCore::Node::ELEMENT_NODE:
971       if (n->isHTMLElement())
972         ret = createJSWrapper(exec, static_pointer_cast<WebCore::HTMLElement>(node));
973       else
974         ret = new JSElement(exec, static_cast<Element *>(n));
975       break;
976     case WebCore::Node::ATTRIBUTE_NODE:
977       ret = new JSAttr(exec, static_cast<Attr *>(n));
978       break;
979     case WebCore::Node::TEXT_NODE:
980     case WebCore::Node::CDATA_SECTION_NODE:
981       ret = new JSText(exec, static_cast<Text *>(n));
982       break;
983     case WebCore::Node::ENTITY_NODE:
984       ret = new JSEntity(exec, static_cast<Entity *>(n));
985       break;
986     case WebCore::Node::PROCESSING_INSTRUCTION_NODE:
987       ret = new JSProcessingInstruction(exec, static_cast<ProcessingInstruction *>(n));
988       break;
989     case WebCore::Node::COMMENT_NODE:
990       ret = new JSCharacterData(exec, static_cast<CharacterData *>(n));
991       break;
992     case WebCore::Node::DOCUMENT_NODE:
993       // we don't want to cache the document itself in the per-document dictionary
994       return toJS(exec, static_cast<Document *>(n));
995     case WebCore::Node::DOCUMENT_TYPE_NODE:
996       ret = new JSDocumentType(exec, static_cast<DocumentType *>(n));
997       break;
998     case WebCore::Node::NOTATION_NODE:
999       ret = new JSNotation(exec, static_cast<Notation *>(n));
1000       break;
1001     case WebCore::Node::DOCUMENT_FRAGMENT_NODE:
1002     case WebCore::Node::ENTITY_REFERENCE_NODE:
1003     default:
1004       ret = new DOMNode(exec, n);
1005   }
1006
1007   interp->putDOMNodeForDocument(doc, n, ret);
1008
1009   return ret;
1010 }
1011
1012 JSValue *toJS(ExecState *exec, NamedNodeMap *m)
1013 {
1014   return cacheDOMObject<NamedNodeMap, DOMNamedNodeMap>(exec, m);
1015 }
1016
1017 JSValue *getRuntimeObject(ExecState* exec, WebCore::Node* n)
1018 {
1019     if (!n)
1020         return 0;
1021
1022 #if __APPLE__
1023     if (n->hasTagName(objectTag) || n->hasTagName(embedTag) || n->hasTagName(appletTag)) {
1024         HTMLPlugInElement *plugInElement = static_cast<HTMLPlugInElement *>(n);
1025         if (plugInElement->getInstance())
1026             // The instance is owned by the PlugIn element.
1027             return new RuntimeObjectImp(plugInElement->getInstance());
1028     }
1029 #endif
1030
1031     // If we don't have a runtime object return 0.
1032     return 0;
1033 }
1034
1035 JSValue *toJS(ExecState *exec, PassRefPtr<NodeList> l)
1036 {
1037   return cacheDOMObject<NodeList, DOMNodeList>(exec, l.get());
1038 }
1039
1040 // -------------------------------------------------------------------------
1041
1042 const ClassInfo NodeConstructor::info = { "NodeConstructor", 0, &NodeConstructorTable, 0 };
1043 /* Source for NodeConstructorTable. Use "make hashtables" to regenerate.
1044 @begin NodeConstructorTable 11
1045   ELEMENT_NODE          WebCore::Node::ELEMENT_NODE         DontDelete|ReadOnly
1046   ATTRIBUTE_NODE        WebCore::Node::ATTRIBUTE_NODE               DontDelete|ReadOnly
1047   TEXT_NODE             WebCore::Node::TEXT_NODE            DontDelete|ReadOnly
1048   CDATA_SECTION_NODE    WebCore::Node::CDATA_SECTION_NODE   DontDelete|ReadOnly
1049   ENTITY_REFERENCE_NODE WebCore::Node::ENTITY_REFERENCE_NODE        DontDelete|ReadOnly
1050   ENTITY_NODE           WebCore::Node::ENTITY_NODE          DontDelete|ReadOnly
1051   PROCESSING_INSTRUCTION_NODE WebCore::Node::PROCESSING_INSTRUCTION_NODE DontDelete|ReadOnly
1052   COMMENT_NODE          WebCore::Node::COMMENT_NODE         DontDelete|ReadOnly
1053   DOCUMENT_NODE         WebCore::Node::DOCUMENT_NODE                DontDelete|ReadOnly
1054   DOCUMENT_TYPE_NODE    WebCore::Node::DOCUMENT_TYPE_NODE   DontDelete|ReadOnly
1055   DOCUMENT_FRAGMENT_NODE WebCore::Node::DOCUMENT_FRAGMENT_NODE      DontDelete|ReadOnly
1056   NOTATION_NODE         WebCore::Node::NOTATION_NODE                DontDelete|ReadOnly
1057 @end
1058 */
1059 bool NodeConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1060 {
1061   return getStaticValueSlot<NodeConstructor, DOMObject>(exec, &NodeConstructorTable, this, propertyName, slot);
1062 }
1063
1064 JSValue *NodeConstructor::getValueProperty(ExecState *, int token) const
1065 {
1066   // We use the token as the value to return directly
1067   return jsNumber(token);
1068 }
1069
1070 JSObject *getNodeConstructor(ExecState *exec)
1071 {
1072   return cacheGlobalObject<NodeConstructor>(exec, "[[node.constructor]]");
1073 }
1074
1075 // -------------------------------------------------------------------------
1076
1077 const ClassInfo DOMExceptionConstructor::info = { "DOMExceptionConstructor", 0, 0, 0 };
1078
1079 /* Source for DOMExceptionConstructorTable. Use "make hashtables" to regenerate.
1080 @begin DOMExceptionConstructorTable 15
1081   INDEX_SIZE_ERR                WebCore::INDEX_SIZE_ERR               DontDelete|ReadOnly
1082   DOMSTRING_SIZE_ERR            WebCore::DOMSTRING_SIZE_ERR   DontDelete|ReadOnly
1083   HIERARCHY_REQUEST_ERR         WebCore::HIERARCHY_REQUEST_ERR        DontDelete|ReadOnly
1084   WRONG_DOCUMENT_ERR            WebCore::WRONG_DOCUMENT_ERR   DontDelete|ReadOnly
1085   INVALID_CHARACTER_ERR         WebCore::INVALID_CHARACTER_ERR        DontDelete|ReadOnly
1086   NO_DATA_ALLOWED_ERR           WebCore::NO_DATA_ALLOWED_ERR  DontDelete|ReadOnly
1087   NO_MODIFICATION_ALLOWED_ERR   WebCore::NO_MODIFICATION_ALLOWED_ERR  DontDelete|ReadOnly
1088   NOT_FOUND_ERR                 WebCore::NOT_FOUND_ERR                DontDelete|ReadOnly
1089   NOT_SUPPORTED_ERR             WebCore::NOT_SUPPORTED_ERR    DontDelete|ReadOnly
1090   INUSE_ATTRIBUTE_ERR           WebCore::INUSE_ATTRIBUTE_ERR  DontDelete|ReadOnly
1091   INVALID_STATE_ERR             WebCore::INVALID_STATE_ERR    DontDelete|ReadOnly
1092   SYNTAX_ERR                    WebCore::SYNTAX_ERR           DontDelete|ReadOnly
1093   INVALID_MODIFICATION_ERR      WebCore::INVALID_MODIFICATION_ERR     DontDelete|ReadOnly
1094   NAMESPACE_ERR                 WebCore::NAMESPACE_ERR                DontDelete|ReadOnly
1095   INVALID_ACCESS_ERR            WebCore::INVALID_ACCESS_ERR   DontDelete|ReadOnly
1096 @end
1097 */
1098
1099 bool DOMExceptionConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1100 {
1101   return getStaticValueSlot<DOMExceptionConstructor, DOMObject>(exec, &DOMExceptionConstructorTable, this, propertyName, slot);
1102 }
1103
1104 JSValue *DOMExceptionConstructor::getValueProperty(ExecState *, int token) const
1105 {
1106   // We use the token as the value to return directly
1107   return jsNumber(token);
1108 }
1109
1110 JSObject *getDOMExceptionConstructor(ExecState *exec)
1111 {
1112   return cacheGlobalObject<DOMExceptionConstructor>(exec, "[[DOMException.constructor]]");
1113 }
1114
1115 // -------------------------------------------------------------------------
1116
1117 // Such a collection is usually very short-lived, it only exists
1118 // for constructs like document.forms.<name>[1],
1119 // so it shouldn't be a problem that it's storing all the nodes (with the same name). (David)
1120 DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState *, const DeprecatedValueList< RefPtr<WebCore::Node> >& nodes )
1121   : m_nodes(nodes)
1122 {
1123 }
1124
1125 JSValue *DOMNamedNodesCollection::lengthGetter(ExecState* exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
1126 {
1127   DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection *>(slot.slotBase());
1128   return jsNumber(thisObj->m_nodes.count());
1129 }
1130
1131 JSValue *DOMNamedNodesCollection::indexGetter(ExecState* exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)
1132 {
1133   DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection *>(slot.slotBase());
1134   return toJS(exec, thisObj->m_nodes[slot.index()].get());
1135 }
1136
1137 bool DOMNamedNodesCollection::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
1138 {
1139   if (propertyName == lengthPropertyName) {
1140     slot.setCustom(this, lengthGetter);
1141     return true;
1142   }
1143
1144   // array index ?
1145   bool ok;
1146   unsigned idx = propertyName.toUInt32(&ok);
1147   if (ok && idx < m_nodes.count()) {
1148     slot.setCustomIndex(this, idx, indexGetter);
1149     return true;
1150   }
1151
1152   // For IE compatibility, we need to be able to look up elements in a
1153   // document.formName.name result by id as well as be index.
1154
1155   AtomicString atomicPropertyName = propertyName;
1156   DeprecatedValueListConstIterator< RefPtr<WebCore::Node> > end = m_nodes.end();
1157   int i = 0;
1158   for (DeprecatedValueListConstIterator< RefPtr<WebCore::Node> > it = m_nodes.begin(); it != end; ++it, ++i) {
1159     WebCore::Node* node = (*it).get();
1160     if (node->hasAttributes() && node->attributes()->id() == atomicPropertyName) {
1161       slot.setCustomIndex(this, i, indexGetter);
1162       return true;
1163     }
1164   }
1165
1166   return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
1167 }
1168
1169 // -------------------------------------------------------------------------
1170
1171
1172 } // namespace