kjs_dom.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
00005  *  Copyright (C) 2003 Apple Computer, Inc.
00006  *
00007  *  This library is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU Library General Public
00009  *  License as published by the Free Software Foundation; either
00010  *  version 2 of the License, or (at your option) any later version.
00011  *
00012  *  This library is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  Library General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public
00018  *  License along with this library; if not, write to the Free Software
00019  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 #include <khtmlview.h>
00023 #include "xml/dom2_eventsimpl.h"
00024 #include "rendering/render_canvas.h"
00025 #include "rendering/render_layer.h"
00026 #include "xml/dom_nodeimpl.h"
00027 #include "xml/dom_docimpl.h"
00028 #include "misc/htmltags.h" // ID_*
00029 #include "misc/htmlattrs.h" // ATTR_*
00030 #include "html/html_baseimpl.h"
00031 #include <kdebug.h>
00032 #include <khtml_part.h>
00033 
00034 #include "kjs_dom.h"
00035 #include "kjs_html.h"
00036 #include "kjs_css.h"
00037 #include "kjs_range.h"
00038 #include "kjs_traversal.h"
00039 #include "kjs_events.h"
00040 #include "kjs_views.h"
00041 #include "kjs_window.h"
00042 #include "dom/dom_exception.h"
00043 #include "kjs_dom.lut.h"
00044 #include "khtmlpart_p.h"
00045 
00046 using namespace KJS;
00047 
00048 // -------------------------------------------------------------------------
00049 /* Source for DOMNodeProtoTable.
00050 @begin DOMNodeProtoTable 13
00051   insertBefore  DOMNode::InsertBefore   DontDelete|Function 2
00052   replaceChild  DOMNode::ReplaceChild   DontDelete|Function 2
00053   removeChild   DOMNode::RemoveChild    DontDelete|Function 1
00054   appendChild   DOMNode::AppendChild    DontDelete|Function 1
00055   hasAttributes DOMNode::HasAttributes  DontDelete|Function 0
00056   hasChildNodes DOMNode::HasChildNodes  DontDelete|Function 0
00057   cloneNode DOMNode::CloneNode  DontDelete|Function 1
00058 # DOM2
00059   normalize DOMNode::Normalize  DontDelete|Function 0
00060   isSupported   DOMNode::IsSupported    DontDelete|Function 2
00061 # from the EventTarget interface
00062   addEventListener  DOMNode::AddEventListener   DontDelete|Function 3
00063   removeEventListener   DOMNode::RemoveEventListener    DontDelete|Function 3
00064   dispatchEvent     DOMNode::DispatchEvent  DontDelete|Function 1
00065 # IE extensions
00066   contains  DOMNode::Contains       DontDelete|Function 1
00067   insertAdjacentHTML    DOMNode::InsertAdjacentHTML DontDelete|Function 2
00068 # "DOM level 0" (from Gecko DOM reference; also in WinIE)
00069   item          DOMNode::Item           DontDelete|Function 1
00070 @end
00071 */
00072 DEFINE_PROTOTYPE("DOMNode",DOMNodeProto)
00073 IMPLEMENT_PROTOFUNC_DOM(DOMNodeProtoFunc)
00074 IMPLEMENT_PROTOTYPE(DOMNodeProto,DOMNodeProtoFunc)
00075 
00076 const ClassInfo DOMNode::info = { "Node", 0, &DOMNodeTable, 0 };
00077 
00078 DOMNode::DOMNode(ExecState *exec, const DOM::Node& n)
00079   : DOMObject(DOMNodeProto::self(exec)), node(n)
00080 {
00081 }
00082 
00083 DOMNode::DOMNode(const Object& proto, const DOM::Node& n)
00084   : DOMObject(proto), node(n)
00085 {
00086 }
00087 
00088 DOMNode::~DOMNode()
00089 {
00090   ScriptInterpreter::forgetDOMObject(node.handle());
00091 }
00092 
00093 bool DOMNode::toBoolean(ExecState *) const
00094 {
00095     return !node.isNull();
00096 }
00097 
00098 /* Source for DOMNodeTable.
00099 @begin DOMNodeTable 53
00100   nodeName  DOMNode::NodeName   DontDelete|ReadOnly
00101   nodeValue DOMNode::NodeValue  DontDelete
00102   nodeType  DOMNode::NodeType   DontDelete|ReadOnly
00103   parentNode    DOMNode::ParentNode DontDelete|ReadOnly
00104   parentElement DOMNode::ParentElement  DontDelete|ReadOnly
00105   childNodes    DOMNode::ChildNodes DontDelete|ReadOnly
00106   firstChild    DOMNode::FirstChild DontDelete|ReadOnly
00107   lastChild DOMNode::LastChild  DontDelete|ReadOnly
00108   previousSibling  DOMNode::PreviousSibling DontDelete|ReadOnly
00109   nextSibling   DOMNode::NextSibling    DontDelete|ReadOnly
00110   attributes    DOMNode::Attributes DontDelete|ReadOnly
00111   namespaceURI  DOMNode::NamespaceURI   DontDelete|ReadOnly
00112 # DOM2
00113   prefix    DOMNode::Prefix     DontDelete
00114   localName DOMNode::LocalName  DontDelete|ReadOnly
00115   ownerDocument DOMNode::OwnerDocument  DontDelete|ReadOnly
00116 # Event handlers
00117 # IE also has: onactivate, onbefore*, oncontextmenu, oncontrolselect, oncut,
00118 # ondeactivate, ondrag*, ondrop, onfocusin, onfocusout, onhelp, onmousewheel,
00119 # onmove*, onpaste, onpropertychange, onreadystatechange, onresizeend/start,
00120 # onselectionchange, onstop
00121   onabort   DOMNode::OnAbort        DontDelete
00122   onblur    DOMNode::OnBlur         DontDelete
00123   onchange  DOMNode::OnChange       DontDelete
00124   onclick   DOMNode::OnClick        DontDelete
00125   ondblclick    DOMNode::OnDblClick     DontDelete
00126   ondragdrop    DOMNode::OnDragDrop     DontDelete
00127   onerror   DOMNode::OnError        DontDelete
00128   onfocus   DOMNode::OnFocus            DontDelete
00129   onkeydown DOMNode::OnKeyDown      DontDelete
00130   onkeypress    DOMNode::OnKeyPress     DontDelete
00131   onkeyup   DOMNode::OnKeyUp        DontDelete
00132   onload    DOMNode::OnLoad         DontDelete
00133   onmousedown   DOMNode::OnMouseDown        DontDelete
00134   onmousemove   DOMNode::OnMouseMove        DontDelete
00135   onmouseout    DOMNode::OnMouseOut     DontDelete
00136   onmouseover   DOMNode::OnMouseOver        DontDelete
00137   onmouseup DOMNode::OnMouseUp      DontDelete
00138   onmove    DOMNode::OnMove         DontDelete
00139   onreset   DOMNode::OnReset        DontDelete
00140   onresize  DOMNode::OnResize       DontDelete
00141   onselect  DOMNode::OnSelect       DontDelete
00142   onsubmit  DOMNode::OnSubmit       DontDelete
00143   onunload  DOMNode::OnUnload       DontDelete
00144 # IE extensions
00145   offsetLeft    DOMNode::OffsetLeft     DontDelete|ReadOnly
00146   offsetTop DOMNode::OffsetTop      DontDelete|ReadOnly
00147   offsetWidth   DOMNode::OffsetWidth        DontDelete|ReadOnly
00148   offsetHeight  DOMNode::OffsetHeight       DontDelete|ReadOnly
00149   offsetParent  DOMNode::OffsetParent       DontDelete|ReadOnly
00150   clientWidth   DOMNode::ClientWidth        DontDelete|ReadOnly
00151   clientHeight  DOMNode::ClientHeight       DontDelete|ReadOnly
00152   scrollLeft    DOMNode::ScrollLeft     DontDelete
00153   scrollTop DOMNode::ScrollTop      DontDelete
00154   scrollWidth   DOMNode::ScrollWidth            DontDelete|ReadOnly
00155   scrollHeight  DOMNode::ScrollHeight           DontDelete|ReadOnly
00156   sourceIndex   DOMNode::SourceIndex        DontDelete|ReadOnly
00157 @end
00158 */
00159 Value DOMNode::tryGet(ExecState *exec, const Identifier &propertyName) const
00160 {
00161 #ifdef KJS_VERBOSE
00162   kdDebug(6070) << "DOMNode::tryGet " << propertyName.qstring() << endl;
00163 #endif
00164   return DOMObjectLookupGetValue<DOMNode, DOMObject>(exec, propertyName, &DOMNodeTable, this);
00165 }
00166 
00167 Value DOMNode::getValueProperty(ExecState *exec, int token) const
00168 {
00169   switch (token) {
00170   case NodeName:
00171     return String(node.nodeName());
00172   case NodeValue:
00173     return getString(node.nodeValue()); // initially null, per domts/level1/core/hc_documentcreateelement.html
00174   case NodeType:
00175     return Number((unsigned int)node.nodeType());
00176   case ParentNode:
00177     return getDOMNode(exec,node.parentNode());
00178   case ParentElement: // IE only apparently
00179     return getDOMNode(exec,node.parentNode());
00180   case ChildNodes:
00181     return getDOMNodeList(exec,node.childNodes());
00182   case FirstChild:
00183     return getDOMNode(exec,node.firstChild());
00184   case LastChild:
00185     return getDOMNode(exec,node.lastChild());
00186   case PreviousSibling:
00187     return getDOMNode(exec,node.previousSibling());
00188   case NextSibling:
00189     return getDOMNode(exec,node.nextSibling());
00190   case Attributes:
00191     return getDOMNamedNodeMap(exec,node.attributes());
00192   case NamespaceURI:
00193     return getString(node.namespaceURI()); // Moz returns null if not set (dom/namespaces.html)
00194   case Prefix:
00195     return getString(node.prefix());  // Moz returns null if not set (dom/namespaces.html)
00196   case LocalName:
00197     return getString(node.localName());  // Moz returns null if not set (dom/namespaces.html)
00198   case OwnerDocument:
00199     return getDOMNode(exec,node.ownerDocument());
00200   case OnAbort:
00201     return getListener(DOM::EventImpl::ABORT_EVENT);
00202   case OnBlur:
00203     return getListener(DOM::EventImpl::BLUR_EVENT);
00204   case OnChange:
00205     return getListener(DOM::EventImpl::CHANGE_EVENT);
00206   case OnClick:
00207     return getListener(DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
00208   case OnDblClick:
00209     return getListener(DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
00210   case OnDragDrop:
00211     return getListener(DOM::EventImpl::KHTML_DRAGDROP_EVENT);
00212   case OnError:
00213     return getListener(DOM::EventImpl::ERROR_EVENT);
00214   case OnFocus:
00215     return getListener(DOM::EventImpl::FOCUS_EVENT);
00216   case OnKeyDown:
00217     return getListener(DOM::EventImpl::KEYDOWN_EVENT);
00218   case OnKeyPress:
00219     return getListener(DOM::EventImpl::KEYPRESS_EVENT);
00220   case OnKeyUp:
00221     return getListener(DOM::EventImpl::KEYUP_EVENT);
00222   case OnLoad:
00223     return getListener(DOM::EventImpl::LOAD_EVENT);
00224   case OnMouseDown:
00225     return getListener(DOM::EventImpl::MOUSEDOWN_EVENT);
00226   case OnMouseMove:
00227     return getListener(DOM::EventImpl::MOUSEMOVE_EVENT);
00228   case OnMouseOut:
00229     return getListener(DOM::EventImpl::MOUSEOUT_EVENT);
00230   case OnMouseOver:
00231     return getListener(DOM::EventImpl::MOUSEOVER_EVENT);
00232   case OnMouseUp:
00233     return getListener(DOM::EventImpl::MOUSEUP_EVENT);
00234   case OnMove:
00235     return getListener(DOM::EventImpl::KHTML_MOVE_EVENT);
00236   case OnReset:
00237     return getListener(DOM::EventImpl::RESET_EVENT);
00238   case OnResize:
00239     return getListener(DOM::EventImpl::RESIZE_EVENT);
00240   case OnSelect:
00241     return getListener(DOM::EventImpl::SELECT_EVENT);
00242   case OnSubmit:
00243     return getListener(DOM::EventImpl::SUBMIT_EVENT);
00244   case OnUnload:
00245     return getListener(DOM::EventImpl::UNLOAD_EVENT);
00246   case SourceIndex: {
00247     // Retrieves the ordinal position of the object, in source order, as the object
00248     // appears in the document's all collection
00249     // i.e. document.all[n.sourceIndex] == n
00250     DOM::Document doc = node.ownerDocument();
00251     if (doc.isHTMLDocument()) {
00252       DOM::HTMLCollection all = static_cast<DOM::HTMLDocument>(doc).all();
00253       unsigned long i = 0;
00254       DOM::Node n = all.firstItem();
00255       for ( ; !n.isNull() && n != node; n = all.nextItem() )
00256         ++i;
00257       Q_ASSERT( !n.isNull() ); // node not in document.all !?
00258       return Number(i);
00259     }
00260   }
00261   default:
00262     // no DOM standard, found in IE only
00263 
00264     // Make sure our layout is up to date before we allow a query on these attributes.
00265     DOM::DocumentImpl* docimpl = node.handle()->getDocument();
00266     if (docimpl) {
00267       docimpl->updateLayout();
00268     }
00269 
00270     khtml::RenderObject *rend = node.handle()->renderer();
00271 
00272     switch (token) {
00273     case OffsetLeft:
00274       return rend ? static_cast<Value>( Number( rend->offsetLeft() ) ) : Undefined();
00275     case OffsetTop:
00276       return rend ? static_cast<Value>(  Number( rend->offsetTop() ) ) : Undefined();
00277     case OffsetWidth:
00278       return rend ? static_cast<Value>(  Number( rend->offsetWidth() ) ) : Undefined();
00279     case OffsetHeight:
00280       return rend ? static_cast<Value>(  Number( rend->offsetHeight() ) ) : Undefined();
00281     case OffsetParent:
00282     {
00283       khtml::RenderObject* par = rend ? rend->offsetParent() : 0;
00284       return getDOMNode( exec, par ? par->element() : 0 );
00285     }
00286     case ClientWidth:
00287       return rend ? static_cast<Value>( Number( rend->clientWidth() ) ) : Undefined();
00288     case ClientHeight:
00289       return rend ? static_cast<Value>( Number( rend->clientHeight() ) ) : Undefined();
00290     case ScrollWidth:
00291       return rend ? static_cast<Value>( Number(rend->scrollWidth()) ) : Undefined();
00292     case ScrollHeight:
00293       return rend ? static_cast<Value>( Number(rend->scrollHeight()) ) : Undefined();
00294     case ScrollLeft:
00295       if (rend && rend->layer()) {
00296           if (rend->isRoot() && !rend->style()->hidesOverflow())
00297               return Number( node.ownerDocument().view() ? node.ownerDocument().view()->contentsX() : 0);
00298           return Number( rend->layer()->scrollXOffset() );
00299       }
00300       return Number( 0 );
00301     case ScrollTop:
00302       if (rend && rend->layer()) {
00303           if (rend->isRoot() && !rend->style()->hidesOverflow())
00304               return Number( node.ownerDocument().view() ? node.ownerDocument().view()->contentsY() : 0);
00305           return Number( rend->layer()->scrollYOffset() );
00306       }
00307       return Number( 0 );
00308     default:
00309       kdDebug(6070) << "WARNING: Unhandled token in DOMNode::getValueProperty : " << token << endl;
00310       break;
00311     }
00312   }
00313   return Undefined();
00314 }
00315 
00316 
00317 void DOMNode::tryPut(ExecState *exec, const Identifier& propertyName, const Value& value, int attr)
00318 {
00319 #ifdef KJS_VERBOSE
00320   kdDebug(6070) << "DOMNode::tryPut " << propertyName.qstring() << endl;
00321 #endif
00322   DOMObjectLookupPut<DOMNode,DOMObject>(exec, propertyName, value, attr,
00323                                         &DOMNodeTable, this );
00324 }
00325 
00326 void DOMNode::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
00327 {
00328   switch (token) {
00329   case NodeValue:
00330     node.setNodeValue(value.toString(exec).string());
00331     break;
00332   case Prefix:
00333     node.setPrefix(value.toString(exec).string());
00334     break;
00335   case OnAbort:
00336     setListener(exec,DOM::EventImpl::ABORT_EVENT,value);
00337     break;
00338   case OnBlur:
00339     setListener(exec,DOM::EventImpl::BLUR_EVENT,value);
00340     break;
00341   case OnChange:
00342     setListener(exec,DOM::EventImpl::CHANGE_EVENT,value);
00343     break;
00344   case OnClick:
00345     setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
00346     break;
00347   case OnDblClick:
00348     setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
00349     break;
00350   case OnDragDrop:
00351     setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
00352     break;
00353   case OnError:
00354     setListener(exec,DOM::EventImpl::ERROR_EVENT,value);
00355     break;
00356   case OnFocus:
00357     setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
00358     break;
00359   case OnKeyDown:
00360     setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
00361     break;
00362   case OnKeyPress:
00363     setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
00364     break;
00365   case OnKeyUp:
00366     setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
00367     break;
00368   case OnLoad:
00369     setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
00370     break;
00371   case OnMouseDown:
00372     setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
00373     break;
00374   case OnMouseMove:
00375     setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
00376     break;
00377   case OnMouseOut:
00378     setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
00379     break;
00380   case OnMouseOver:
00381     setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
00382     break;
00383   case OnMouseUp:
00384     setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
00385     break;
00386   case OnMove:
00387     setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
00388     break;
00389   case OnReset:
00390     setListener(exec,DOM::EventImpl::RESET_EVENT,value);
00391     break;
00392   case OnResize:
00393     setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
00394     break;
00395   case OnSelect:
00396     setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
00397     break;
00398   case OnSubmit:
00399     setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
00400     break;
00401   case OnUnload:
00402     setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
00403     break;
00404   default:
00405     // Make sure our layout is up to date 
00406     DOM::DocumentImpl* docimpl = node.handle()->getDocument();
00407     if (docimpl)
00408       docimpl->updateLayout();
00409 
00410     khtml::RenderObject *rend = node.handle() ? node.handle()->renderer() : 0L;
00411 
00412     switch (token) {
00413       case ScrollLeft:
00414         if (rend && rend->layer()) {
00415           if (rend->style()->hidesOverflow())
00416             rend->layer()->scrollToXOffset(value.toInt32(exec));
00417           else if (rend->isRoot()) {
00418             QScrollView* sview = node.ownerDocument().view();
00419             if (sview)
00420               sview->setContentsPos(value.toInt32(exec), sview->contentsY());
00421           }
00422         }
00423         break;
00424       case ScrollTop:
00425         if (rend && rend->layer()) {
00426           if (rend->style()->hidesOverflow())
00427             rend->layer()->scrollToYOffset(value.toInt32(exec));
00428           else if (rend->isRoot()) {
00429             QScrollView* sview = node.ownerDocument().view();
00430             if (sview)
00431               sview->setContentsPos(sview->contentsX(), value.toInt32(exec));
00432           }
00433         }
00434         break;
00435       default:
00436       kdDebug(6070) << "WARNING: DOMNode::putValueProperty unhandled token " << token << endl;
00437     }
00438   }
00439 }
00440 
00441 Value DOMNode::toPrimitive(ExecState *exec, Type /*preferred*/) const
00442 {
00443   if (node.isNull())
00444     return Null();
00445 
00446   return String(toString(exec));
00447 }
00448 
00449 UString DOMNode::toString(ExecState *) const
00450 {
00451   if (node.isNull())
00452     return "null";
00453   UString s;
00454 
00455   DOM::Element e = node;
00456   if ( !e.isNull() ) {
00457     s = e.nodeName().string();
00458   } else
00459     s = className(); // fallback
00460 
00461   return "[object " + s + "]";
00462 }
00463 
00464 void DOMNode::setListener(ExecState *exec, int eventId, const Value& func) const
00465 {
00466   node.handle()->setHTMLEventListener(eventId,Window::retrieveActive(exec)->getJSEventListener(func,true));
00467 }
00468 
00469 Value DOMNode::getListener(int eventId) const
00470 {
00471   DOM::EventListener *listener = node.handle()->getHTMLEventListener(eventId);
00472   JSEventListener *jsListener = static_cast<JSEventListener*>(listener);
00473   if ( jsListener && jsListener->listenerObjImp() )
00474     return jsListener->listenerObj();
00475   else
00476     return Null();
00477 }
00478 
00479 void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const
00480 {
00481 }
00482 
00483 Value DOMNodeProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00484 {
00485   KJS_CHECK_THIS( DOMNode, thisObj );
00486   DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
00487   switch (id) {
00488     case DOMNode::HasAttributes:
00489       return Boolean(node.hasAttributes());
00490     case DOMNode::HasChildNodes:
00491       return Boolean(node.hasChildNodes());
00492     case DOMNode::CloneNode:
00493       return getDOMNode(exec,node.cloneNode(args[0].toBoolean(exec)));
00494     case DOMNode::Normalize:
00495       node.normalize();
00496       return Undefined();
00497     case DOMNode::IsSupported:
00498       return Boolean(node.isSupported(args[0].toString(exec).string(),args[1].toString(exec).string()));
00499     case DOMNode::AddEventListener: {
00500         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
00501         node.addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
00502         return Undefined();
00503     }
00504     case DOMNode::RemoveEventListener: {
00505         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
00506         node.removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
00507         return Undefined();
00508     }
00509     case DOMNode::DispatchEvent:
00510       return Boolean(node.dispatchEvent(toEvent(args[0])));
00511     case DOMNode::AppendChild:
00512       return getDOMNode(exec,node.appendChild(toNode(args[0])));
00513     case DOMNode::RemoveChild:
00514       return getDOMNode(exec,node.removeChild(toNode(args[0])));
00515     case DOMNode::InsertBefore:
00516       return getDOMNode(exec,node.insertBefore(toNode(args[0]), toNode(args[1])));
00517     case DOMNode::ReplaceChild:
00518       return getDOMNode(exec,node.replaceChild(toNode(args[0]), toNode(args[1])));
00519     case DOMNode::Contains:
00520     {
00521     DOM::Node other = toNode(args[0]);
00522     if (!other.isNull() && node.nodeType()==DOM::Node::ELEMENT_NODE)
00523     {
00524         DOM::NodeBaseImpl *impl = static_cast<DOM::NodeBaseImpl *>(node.handle());
00525         bool retval = other.handle()->isAncestor(impl);
00526         return Boolean(retval);
00527     }
00528         return Undefined();
00529     }
00530     case DOMNode::InsertAdjacentHTML:
00531     {
00532       // see http://www.faqts.com/knowledge_base/view.phtml/aid/5756
00533       // and http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/insertAdjacentHTML.asp
00534       Range range = node.ownerDocument().createRange();
00535 
00536       range.setStartBefore(node);
00537 
00538       DocumentFragment docFrag = range.createContextualFragment(args[1].toString(exec).string());
00539 
00540       DOMString where = args[0].toString(exec).string();
00541 
00542       if (where == "beforeBegin" || where == "BeforeBegin")
00543         node.parentNode().insertBefore(docFrag, node);
00544       else if (where == "afterBegin" || where == "AfterBegin")
00545         node.insertBefore(docFrag, node.firstChild());
00546       else if (where == "beforeEnd" || where == "BeforeEnd")
00547         return getDOMNode(exec, node.appendChild(docFrag));
00548       else if (where == "afterEnd" || where == "AfterEnd")
00549         if (!node.nextSibling().isNull())
00550       node.parentNode().insertBefore(docFrag, node.nextSibling());
00551     else
00552       node.parentNode().appendChild(docFrag);
00553 
00554       return Undefined();
00555     }
00556     case DOMNode::Item:
00557       return getDOMNode(exec, node.childNodes().item(static_cast<unsigned long>(args[0].toNumber(exec))));
00558   }
00559 
00560   return Undefined();
00561 }
00562 
00563 // -------------------------------------------------------------------------
00564 
00565 /*
00566 @begin DOMNodeListProtoTable 2
00567   item      DOMNodeList::Item       DontDelete|Function 1
00568 # IE extension (IE treats DOMNodeList like an HTMLCollection)
00569   namedItem DOMNodeList::NamedItem      DontDelete|Function 1
00570 @end
00571 */
00572 DEFINE_PROTOTYPE("DOMNodeList", DOMNodeListProto)
00573 IMPLEMENT_PROTOFUNC_DOM(DOMNodeListProtoFunc)
00574 IMPLEMENT_PROTOTYPE(DOMNodeListProto,DOMNodeListProtoFunc)
00575 
00576 const ClassInfo DOMNodeList::info = { "NodeList", 0, 0, 0 };
00577 
00578 DOMNodeList::DOMNodeList(ExecState *exec, const DOM::NodeList& l)
00579  : DOMObject(DOMNodeListProto::self(exec)), list(l) { }
00580 
00581 DOMNodeList::~DOMNodeList()
00582 {
00583   ScriptInterpreter::forgetDOMObject(list.handle());
00584 }
00585 
00586 // We have to implement hasProperty since we don't use a hashtable for 'length'
00587 // ## this breaks "for (..in..)" though.
00588 bool DOMNodeList::hasProperty(ExecState *exec, const Identifier &p) const
00589 {
00590   if (p == lengthPropertyName)
00591     return true;
00592 
00593   if (ObjectImp::hasProperty(exec, p))
00594     return true;
00595 
00596   bool ok;
00597   unsigned long pos = p.toULong(&ok);
00598   if (ok && pos < list.length())
00599     return true;
00600 
00601   // ## missing: accept p if item id...
00602   return false;
00603 }
00604 
00605 Value DOMNodeList::tryGet(ExecState *exec, const Identifier &p) const
00606 {
00607 #ifdef KJS_VERBOSE
00608   kdDebug(6070) << "DOMNodeList::tryGet " << p.ascii() << endl;
00609 #endif
00610   if (p == lengthPropertyName)
00611     return Number(list.length());
00612 
00613   // Look in the prototype (for functions) before assuming it's an item's name
00614   Object proto = Object::dynamicCast(prototype());
00615   if (proto.isValid() && proto.hasProperty(exec,p))
00616     return proto.get(exec,p);
00617 
00618   Value result;
00619 
00620   // array index ?
00621   bool ok;
00622   long unsigned int idx = p.toULong(&ok);
00623   if (ok)
00624     result = getDOMNode(exec,list.item(idx));
00625   else {
00626     // Find by ID
00627     DOM::HTMLElement e;
00628     unsigned long l = list.length();
00629     bool found = false;
00630 
00631     for ( unsigned long i = 0; i < l; i++ )
00632       if ( ( e = list.item( i ) ).id() == p.string() ) {
00633         result = getDOMNode(exec, list.item( i ) );
00634         found = true;
00635         break;
00636       }
00637 
00638     if ( !found )
00639       result = ObjectImp::get(exec, p);
00640   }
00641 
00642   return result;
00643 }
00644 
00645 ReferenceList DOMNodeList::propList(ExecState *exec, bool recursive)
00646 {
00647   ReferenceList properties = ObjectImp::propList(exec,recursive);
00648 
00649   for (unsigned i = 0; i < list.length(); ++i) {
00650     if (!ObjectImp::hasProperty(exec,Identifier::from(i))) {
00651       properties.append(Reference(this, i));
00652     }
00653   }
00654 
00655   if (!ObjectImp::hasProperty(exec, lengthPropertyName))
00656     properties.append(Reference(this, lengthPropertyName));
00657 
00658   return properties;
00659 }
00660 
00661 // Need to support both get and call, so that list[0] and list(0) work.
00662 Value DOMNodeList::call(ExecState *exec, Object &thisObj, const List &args)
00663 {
00664   // This code duplication is necessary, DOMNodeList isn't a DOMFunction
00665   Value val;
00666   try {
00667     val = tryCall(exec, thisObj, args);
00668   }
00669   // pity there's no way to distinguish between these in JS code
00670   catch (...) {
00671     Object err = Error::create(exec, GeneralError, "Exception from DOMNodeList");
00672     exec->setException(err);
00673   }
00674   return val;
00675 }
00676 
00677 Value DOMNodeList::tryCall(ExecState *exec, Object &, const List &args)
00678 {
00679   // Do not use thisObj here. See HTMLCollection.
00680   UString s = args[0].toString(exec);
00681 
00682   // index-based lookup?
00683   bool ok;
00684   unsigned int u = s.toULong(&ok);
00685   if (ok)
00686     return getDOMNode(exec,list.item(u));
00687 
00688   // try lookup by name
00689   // ### NodeList::namedItem() would be cool to have
00690   // ### do we need to support the same two arg overload as in HTMLCollection?
00691   Value result = tryGet(exec, Identifier(s));
00692 
00693   if (result.isValid())
00694     return result;
00695 
00696   return Undefined();
00697 }
00698 
00699 // Not a prototype class currently, but should probably be converted to one
00700 Value DOMNodeListProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00701 {
00702   KJS_CHECK_THIS( KJS::DOMNodeList, thisObj );
00703   DOM::NodeList list = static_cast<DOMNodeList *>(thisObj.imp())->nodeList();
00704   switch (id) {
00705   case KJS::DOMNodeList::Item:
00706     return getDOMNode(exec, list.item(args[0].toInt32(exec)));
00707   case KJS::DOMNodeList::NamedItem:
00708   {
00709     // Not a real namedItem implementation like the one HTMLCollection has.
00710     // This is only an IE extension...
00711     DOM::HTMLElement e;
00712     unsigned long len = list.length();
00713     DOM::DOMString s = args[0].toString(exec).string();
00714 
00715     for ( unsigned long i = 0; i < len; i++ )
00716     {
00717       e = list.item( i );
00718       if ( !e.isNull() && (
00719              e.id() == s || static_cast<ElementImpl *>(e.handle())->getAttribute(ATTR_NAME) == s )
00720       )
00721       {
00722         return getDOMNode(exec, e );
00723       }
00724     }
00725     return Null(); // see HTMLCollection::NamedItem implementation
00726   }
00727   default:
00728     return Undefined();
00729   }
00730 }
00731 
00732 // -------------------------------------------------------------------------
00733 
00734 const ClassInfo DOMAttr::info = { "Attr", &DOMNode::info, &DOMAttrTable, 0 };
00735 
00736 /* Source for DOMAttrTable.
00737 @begin DOMAttrTable 5
00738   name      DOMAttr::Name       DontDelete|ReadOnly
00739   specified DOMAttr::Specified  DontDelete|ReadOnly
00740   value     DOMAttr::ValueProperty  DontDelete
00741   ownerElement  DOMAttr::OwnerElement   DontDelete|ReadOnly
00742 @end
00743 */
00744 Value DOMAttr::tryGet(ExecState *exec, const Identifier &propertyName) const
00745 {
00746 #ifdef KJS_VERBOSE
00747   kdDebug(6070) << "DOMAttr::tryGet " << propertyName.qstring() << endl;
00748 #endif
00749   return DOMObjectLookupGetValue<DOMAttr,DOMNode>(exec, propertyName,
00750                                                   &DOMAttrTable, this );
00751 }
00752 
00753 Value DOMAttr::getValueProperty(ExecState *exec, int token) const
00754 {
00755   switch (token) {
00756   case Name:
00757     return String(static_cast<DOM::Attr>(node).name());
00758   case Specified:
00759     return Boolean(static_cast<DOM::Attr>(node).specified());
00760   case ValueProperty:
00761     return String(static_cast<DOM::Attr>(node).value());
00762   case OwnerElement: // DOM2
00763     return getDOMNode(exec,static_cast<DOM::Attr>(node).ownerElement());
00764   }
00765   return Value(); // not reached
00766 }
00767 
00768 void DOMAttr::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
00769 {
00770 #ifdef KJS_VERBOSE
00771   kdDebug(6070) << "DOMAttr::tryPut " << propertyName.qstring() << endl;
00772 #endif
00773   DOMObjectLookupPut<DOMAttr,DOMNode>(exec, propertyName, value, attr,
00774                                       &DOMAttrTable, this );
00775 }
00776 
00777 void DOMAttr::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
00778 {
00779   switch (token) {
00780   case ValueProperty:
00781     static_cast<DOM::Attr>(node).setValue(value.toString(exec).string());
00782     return;
00783   default:
00784     kdDebug(6070) << "WARNING: DOMAttr::putValueProperty unhandled token " << token << endl;
00785   }
00786 }
00787 
00788 // -------------------------------------------------------------------------
00789 
00790 /* Source for DOMDocumentProtoTable.
00791 @begin DOMDocumentProtoTable 23
00792   createElement   DOMDocument::CreateElement                   DontDelete|Function 1
00793   createDocumentFragment DOMDocument::CreateDocumentFragment   DontDelete|Function 1
00794   createTextNode  DOMDocument::CreateTextNode                  DontDelete|Function 1
00795   createComment   DOMDocument::CreateComment                   DontDelete|Function 1
00796   createCDATASection DOMDocument::CreateCDATASection           DontDelete|Function 1
00797   createProcessingInstruction DOMDocument::CreateProcessingInstruction DontDelete|Function 1
00798   createAttribute DOMDocument::CreateAttribute                 DontDelete|Function 1
00799   createEntityReference DOMDocument::CreateEntityReference     DontDelete|Function 1
00800   getElementsByTagName  DOMDocument::GetElementsByTagName      DontDelete|Function 1
00801   importNode           DOMDocument::ImportNode                 DontDelete|Function 2
00802   createElementNS      DOMDocument::CreateElementNS            DontDelete|Function 2
00803   createAttributeNS    DOMDocument::CreateAttributeNS          DontDelete|Function 2
00804   getElementsByTagNameNS  DOMDocument::GetElementsByTagNameNS  DontDelete|Function 2
00805   getElementById     DOMDocument::GetElementById               DontDelete|Function 1
00806   createRange        DOMDocument::CreateRange                  DontDelete|Function 0
00807   createNodeIterator DOMDocument::CreateNodeIterator           DontDelete|Function 3
00808   createTreeWalker   DOMDocument::CreateTreeWalker             DontDelete|Function 4
00809   createEvent        DOMDocument::CreateEvent                  DontDelete|Function 1
00810   getOverrideStyle   DOMDocument::GetOverrideStyle             DontDelete|Function 2
00811   abort              DOMDocument::Abort                        DontDelete|Function 0
00812   load               DOMDocument::Load                         DontDelete|Function 1
00813   loadXML            DOMDocument::LoadXML                      DontDelete|Function 2
00814 @end
00815 */
00816 DEFINE_PROTOTYPE("DOMDocument", DOMDocumentProto)
00817 IMPLEMENT_PROTOFUNC_DOM(DOMDocumentProtoFunc)
00818 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMDocumentProto, DOMDocumentProtoFunc, DOMNodeProto)
00819 
00820 const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, 0 };
00821 
00822 /* Source for DOMDocumentTable.
00823 @begin DOMDocumentTable 4
00824   doctype         DOMDocument::DocType                         DontDelete|ReadOnly
00825   implementation  DOMDocument::Implementation                  DontDelete|ReadOnly
00826   documentElement DOMDocument::DocumentElement                 DontDelete|ReadOnly
00827   styleSheets     DOMDocument::StyleSheets                     DontDelete|ReadOnly
00828   preferredStylesheetSet  DOMDocument::PreferredStylesheetSet  DontDelete|ReadOnly
00829   selectedStylesheetSet  DOMDocument::SelectedStylesheetSet    DontDelete
00830   readyState      DOMDocument::ReadyState                      DontDelete|ReadOnly
00831   defaultView     DOMDocument::DefaultView                     DontDelete|ReadOnly
00832   async           DOMDocument::Async                           DontDelete
00833 @end
00834 */
00835 
00836 DOMDocument::DOMDocument(ExecState *exec, const DOM::Document& d)
00837   : DOMNode(DOMDocumentProto::self(exec), d) { }
00838 
00839 DOMDocument::DOMDocument(const Object& proto, const DOM::Document& d)
00840   : DOMNode(proto, d) { }
00841 
00842 DOMDocument::~DOMDocument()
00843 {
00844   ScriptInterpreter::forgetDOMObject(node.handle());
00845 }
00846 
00847 Value DOMDocument::tryGet(ExecState *exec, const Identifier &propertyName) const
00848 {
00849 #ifdef KJS_VERBOSE
00850   kdDebug(6070) << "DOMDocument::tryGet " << propertyName.qstring() << endl;
00851 #endif
00852   return DOMObjectLookupGetValue<DOMDocument, DOMNode>(
00853     exec, propertyName, &DOMDocumentTable, this);
00854 }
00855 
00856 Value DOMDocument::getValueProperty(ExecState *exec, int token) const
00857 {
00858   DOM::Document doc = static_cast<DOM::Document>(node);
00859 
00860   switch(token) {
00861   case DocType:
00862     return getDOMNode(exec,doc.doctype());
00863   case Implementation:
00864     return getDOMDOMImplementation(exec,doc.implementation());
00865   case DocumentElement:
00866     return getDOMNode(exec,doc.documentElement());
00867   case StyleSheets:
00868     //kdDebug() << "DOMDocument::StyleSheets, returning " << doc.styleSheets().length() << " stylesheets" << endl;
00869     return getDOMStyleSheetList(exec, doc.styleSheets(), doc);
00870   case DOMDocument::DefaultView: // DOM2
00871     {
00872     KHTMLView *view = node.handle()->getDocument()->view();
00873     if (view)
00874         return Window::retrieve(view->part());
00875     return getDOMAbstractView(exec, doc.defaultView());
00876     }
00877   case PreferredStylesheetSet:
00878     return String(doc.preferredStylesheetSet());
00879   case SelectedStylesheetSet:
00880     return String(doc.selectedStylesheetSet());
00881   case ReadyState:
00882     {
00883     DOM::DocumentImpl* docimpl = node.handle()->getDocument();
00884     if ( docimpl && docimpl->view() )
00885     {
00886       KHTMLPart* part = docimpl->view()->part();
00887       if ( part ) {
00888         if (part->d->m_bComplete) return String("complete");
00889         if (docimpl->parsing()) return String("loading");
00890         return String("loaded");
00891         // What does the interactive value mean ?
00892         // Missing support for "uninitialized"
00893       }
00894     }
00895     return Undefined();
00896     }
00897   case Async:
00898     return Boolean(doc.async());
00899   default:
00900     kdDebug(6070) << "WARNING: DOMDocument::getValueProperty unhandled token " << token << endl;
00901     return Value();
00902   }
00903 }
00904 
00905 void DOMDocument::tryPut(ExecState *exec, const Identifier& propertyName, const Value& value, int attr)
00906 {
00907 #ifdef KJS_VERBOSE
00908   kdDebug(6070) << "DOMDocument::tryPut " << propertyName.qstring() << endl;
00909 #endif
00910   DOMObjectLookupPut<DOMDocument,DOMNode>(exec, propertyName, value, attr, &DOMDocumentTable, this );
00911 }
00912 
00913 void DOMDocument::putValueProperty(ExecState *exec, int token, const Value& value, int /*attr*/)
00914 {
00915   DOM::Document doc = static_cast<DOM::Document>(node);
00916   switch (token) {
00917     case SelectedStylesheetSet: {
00918       doc.setSelectedStylesheetSet(value.toString(exec).string());
00919       break;
00920     }
00921     case Async: {
00922       doc.setAsync(value.toBoolean(exec));
00923       break;
00924     }
00925   }
00926 }
00927 
00928 Value DOMDocumentProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00929 {
00930   KJS_CHECK_THIS( KJS::DOMDocument, thisObj );
00931   DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
00932   DOM::Document doc = static_cast<DOM::Document>(node);
00933   String str = args[0].toString(exec);
00934   DOM::DOMString s = str.value().string();
00935 
00936   switch(id) {
00937   case DOMDocument::CreateElement:
00938     return getDOMNode(exec,doc.createElement(s));
00939   case DOMDocument::CreateDocumentFragment:
00940     return getDOMNode(exec,doc.createDocumentFragment());
00941   case DOMDocument::CreateTextNode:
00942     return getDOMNode(exec,doc.createTextNode(s));
00943   case DOMDocument::CreateComment:
00944     return getDOMNode(exec,doc.createComment(s));
00945   case DOMDocument::CreateCDATASection:
00946     return getDOMNode(exec,doc.createCDATASection(s));  /* TODO: okay ? */
00947   case DOMDocument::CreateProcessingInstruction:
00948     return getDOMNode(exec,doc.createProcessingInstruction(args[0].toString(exec).string(),
00949                                                                  args[1].toString(exec).string()));
00950   case DOMDocument::CreateAttribute:
00951     return getDOMNode(exec,doc.createAttribute(s));
00952   case DOMDocument::CreateEntityReference:
00953     return getDOMNode(exec,doc.createEntityReference(args[0].toString(exec).string()));
00954   case DOMDocument::GetElementsByTagName:
00955     return getDOMNodeList(exec,doc.getElementsByTagName(s));
00956   case DOMDocument::ImportNode: // DOM2
00957     return getDOMNode(exec,doc.importNode(toNode(args[0]), args[1].toBoolean(exec)));
00958   case DOMDocument::CreateElementNS: // DOM2
00959     return getDOMNode(exec,doc.createElementNS(args[0].toString(exec).string(), args[1].toString(exec).string()));
00960   case DOMDocument::CreateAttributeNS: // DOM2
00961     return getDOMNode(exec,doc.createAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
00962   case DOMDocument::GetElementsByTagNameNS: // DOM2
00963     return getDOMNodeList(exec,doc.getElementsByTagNameNS(args[0].toString(exec).string(),
00964                                                           args[1].toString(exec).string()));
00965   case DOMDocument::GetElementById:
00966 #ifdef KJS_VERBOSE
00967   kdDebug(6070) << "DOMDocument::GetElementById looking for " << args[0].toString(exec).string() << endl;
00968 #endif
00969     return getDOMNode(exec,doc.getElementById(args[0].toString(exec).string()));
00970   case DOMDocument::CreateRange:
00971     return getDOMRange(exec,doc.createRange());
00972   case DOMDocument::CreateNodeIterator:
00973     if (args[2].isA(NullType)) {
00974         DOM::NodeFilter filter;
00975         return getDOMNodeIterator(exec,
00976                                   doc.createNodeIterator(toNode(args[0]),
00977                                                          (long unsigned int)(args[1].toNumber(exec)),
00978                                                          filter,args[3].toBoolean(exec)));
00979     }
00980     else {
00981       Object obj = Object::dynamicCast(args[2]);
00982       if (obj.isValid())
00983       {
00984         DOM::CustomNodeFilter *customFilter = new JSNodeFilter(obj);
00985         DOM::NodeFilter filter = DOM::NodeFilter::createCustom(customFilter);
00986         return getDOMNodeIterator(exec,
00987           doc.createNodeIterator(
00988             toNode(args[0]),(long unsigned int)(args[1].toNumber(exec)),
00989             filter,args[3].toBoolean(exec)));
00990       }// else?
00991     }
00992   case DOMDocument::CreateTreeWalker:
00993     return getDOMTreeWalker(exec,doc.createTreeWalker(toNode(args[0]),(long unsigned int)(args[1].toNumber(exec)),
00994              toNodeFilter(args[2]),args[3].toBoolean(exec)));
00995   case DOMDocument::CreateEvent:
00996     return getDOMEvent(exec,doc.createEvent(s));
00997   case DOMDocument::GetOverrideStyle: {
00998     DOM::Node arg0 = toNode(args[0]);
00999     if (arg0.nodeType() != DOM::Node::ELEMENT_NODE)
01000       return Undefined(); // throw exception?
01001     else
01002       return getDOMCSSStyleDeclaration(exec,doc.getOverrideStyle(static_cast<DOM::Element>(arg0),args[1].toString(exec).string()));
01003   }
01004   case DOMDocument::Abort:
01005     doc.abort();
01006     break;
01007   case DOMDocument::Load: {
01008     Window* active = Window::retrieveActive(exec);
01009     // Complete the URL using the "active part" (running interpreter). We do this for the security
01010     // check and to make sure we load exactly the same url as we have verified to be safe
01011     KHTMLPart *khtmlpart = ::qt_cast<KHTMLPart *>(active->part());
01012     if (khtmlpart) {
01013       // Security: only allow documents to be loaded from the same host
01014       QString dstUrl = khtmlpart->htmlDocument().completeURL(s).string();
01015       KParts::ReadOnlyPart *part = static_cast<KJS::ScriptInterpreter*>(exec->interpreter())->part();
01016       if (part->url().host() == KURL(dstUrl).host()) {
01017     kdDebug(6070) << "JavaScript: access granted for document.load() of " << dstUrl << endl;
01018     doc.load(dstUrl);
01019       }
01020       else {
01021     kdDebug(6070) << "JavaScript: access denied for document.load() of " << dstUrl << endl;
01022       }
01023     }
01024     break;
01025   }
01026   case DOMDocument::LoadXML:
01027     doc.loadXML(s);
01028     break;
01029   default:
01030     break;
01031   }
01032 
01033   return Undefined();
01034 }
01035 
01036 // -------------------------------------------------------------------------
01037 
01038 /* Source for DOMElementProtoTable.
01039 @begin DOMElementProtoTable 17
01040   getAttribute      DOMElement::GetAttribute    DontDelete|Function 1
01041   setAttribute      DOMElement::SetAttribute    DontDelete|Function 2
01042   removeAttribute   DOMElement::RemoveAttribute DontDelete|Function 1
01043   getAttributeNode  DOMElement::GetAttributeNode    DontDelete|Function 1
01044   setAttributeNode  DOMElement::SetAttributeNode    DontDelete|Function 2
01045   removeAttributeNode   DOMElement::RemoveAttributeNode DontDelete|Function 1
01046   getElementsByTagName  DOMElement::GetElementsByTagName    DontDelete|Function 1
01047   hasAttribute      DOMElement::HasAttribute    DontDelete|Function 1
01048   getAttributeNS    DOMElement::GetAttributeNS  DontDelete|Function 2
01049   setAttributeNS    DOMElement::SetAttributeNS  DontDelete|Function 3
01050   removeAttributeNS DOMElement::RemoveAttributeNS   DontDelete|Function 2
01051   getAttributeNodeNS    DOMElement::GetAttributeNodeNS  DontDelete|Function 2
01052   setAttributeNodeNS    DOMElement::SetAttributeNodeNS  DontDelete|Function 1
01053   getElementsByTagNameNS DOMElement::GetElementsByTagNameNS DontDelete|Function 2
01054   hasAttributeNS    DOMElement::HasAttributeNS  DontDelete|Function 2
01055 @end
01056 */
01057 DEFINE_PROTOTYPE("DOMElement",DOMElementProto)
01058 IMPLEMENT_PROTOFUNC_DOM(DOMElementProtoFunc)
01059 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMElementProto,DOMElementProtoFunc,DOMNodeProto)
01060 
01061 const ClassInfo DOMElement::info = { "Element", &DOMNode::info, &DOMElementTable, 0 };
01062 /* Source for DOMElementTable.
01063 @begin DOMElementTable 3
01064   tagName   DOMElement::TagName                         DontDelete|ReadOnly
01065   style     DOMElement::Style                           DontDelete|ReadOnly
01066 @end
01067 */
01068 DOMElement::DOMElement(ExecState *exec, const DOM::Element& e)
01069   : DOMNode(DOMElementProto::self(exec), e) { }
01070 
01071 DOMElement::DOMElement(const Object& proto, const DOM::Element& e)
01072   : DOMNode(proto, e) { }
01073 
01074 Value DOMElement::tryGet(ExecState *exec, const Identifier &propertyName) const
01075 {
01076 #ifdef KJS_VERBOSE
01077   kdDebug(6070) << "DOMElement::tryGet " << propertyName.qstring() << endl;
01078 #endif
01079   DOM::Element element = static_cast<DOM::Element>(node);
01080 
01081   const HashEntry* entry = Lookup::findEntry(&DOMElementTable, propertyName);
01082   if (entry)
01083   {
01084     switch( entry->value ) {
01085     case TagName:
01086       return String(element.tagName());
01087     case Style:
01088       return getDOMCSSStyleDeclaration(exec,element.style());
01089     default:
01090       kdDebug(6070) << "WARNING: Unhandled token in DOMElement::tryGet : " << entry->value << endl;
01091       break;
01092     }
01093   }
01094   // We have to check in DOMNode before giving access to attributes, otherwise
01095   // onload="..." would make onload return the string (attribute value) instead of
01096   // the listener object (function).
01097   if (DOMNode::hasProperty(exec, propertyName))
01098     return DOMNode::tryGet(exec, propertyName);
01099 
01100   DOM::DOMString attr = element.getAttribute( propertyName.string() );
01101   // Give access to attributes
01102   if ( !attr.isNull() )
01103     return String( attr );
01104 
01105   return Undefined();
01106 }
01107 
01108 Value DOMElementProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01109 {
01110   KJS_CHECK_THIS( KJS::DOMNode, thisObj ); // node should be enough here, given the cast
01111   DOM::Node node = static_cast<DOMNode *>( thisObj.imp() )->toNode();
01112   DOM::Element element = static_cast<DOM::Element>(node);
01113 
01114   switch(id) {
01115     case DOMElement::GetAttribute:
01119       return getString(element.getAttribute(args[0].toString(exec).string()));
01120     case DOMElement::SetAttribute:
01121       element.setAttribute(args[0].toString(exec).string(),args[1].toString(exec).string());
01122       return Undefined();
01123     case DOMElement::RemoveAttribute:
01124       element.removeAttribute(args[0].toString(exec).string());
01125       return Undefined();
01126     case DOMElement::GetAttributeNode:
01127       return getDOMNode(exec,element.getAttributeNode(args[0].toString(exec).string()));
01128     case DOMElement::SetAttributeNode:
01129       return getDOMNode(exec,element.setAttributeNode((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
01130     case DOMElement::RemoveAttributeNode:
01131       return getDOMNode(exec,element.removeAttributeNode((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
01132     case DOMElement::GetElementsByTagName:
01133       return getDOMNodeList(exec,element.getElementsByTagName(args[0].toString(exec).string()));
01134     case DOMElement::HasAttribute: // DOM2
01135       return Boolean(element.hasAttribute(args[0].toString(exec).string()));
01136     case DOMElement::GetAttributeNS: // DOM2
01137       return String(element.getAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01138     case DOMElement::SetAttributeNS: // DOM2
01139       element.setAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string(),args[2].toString(exec).string());
01140       return Undefined();
01141     case DOMElement::RemoveAttributeNS: // DOM2
01142       element.removeAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string());
01143       return Undefined();
01144     case DOMElement::GetAttributeNodeNS: // DOM2
01145       return getDOMNode(exec,element.getAttributeNodeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01146     case DOMElement::SetAttributeNodeNS: // DOM2
01147       return getDOMNode(exec,element.setAttributeNodeNS((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
01148     case DOMElement::GetElementsByTagNameNS: // DOM2
01149       return getDOMNodeList(exec,element.getElementsByTagNameNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01150     case DOMElement::HasAttributeNS: // DOM2
01151       return Boolean(element.hasAttributeNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01152   default:
01153     return Undefined();
01154   }
01155 }
01156 
01157 // -------------------------------------------------------------------------
01158 
01159 /* Source for DOMDOMImplementationProtoTable.
01160 @begin DOMDOMImplementationProtoTable 5
01161   hasFeature        DOMDOMImplementation::HasFeature        DontDelete|Function 2
01162   createCSSStyleSheet   DOMDOMImplementation::CreateCSSStyleSheet   DontDelete|Function 2
01163 # DOM2
01164   createDocumentType    DOMDOMImplementation::CreateDocumentType    DontDelete|Function 3
01165   createDocument    DOMDOMImplementation::CreateDocument        DontDelete|Function 3
01166   createHTMLDocument    DOMDOMImplementation::CreateHTMLDocument        DontDelete|Function 1
01167 @end
01168 */
01169 DEFINE_PROTOTYPE("DOMImplementation",DOMDOMImplementationProto)
01170 IMPLEMENT_PROTOFUNC_DOM(DOMDOMImplementationProtoFunc)
01171 IMPLEMENT_PROTOTYPE(DOMDOMImplementationProto,DOMDOMImplementationProtoFunc)
01172 
01173 const ClassInfo DOMDOMImplementation::info = { "DOMImplementation", 0, 0, 0 };
01174 
01175 DOMDOMImplementation::DOMDOMImplementation(ExecState *exec, const DOM::DOMImplementation& i)
01176   : DOMObject(DOMDOMImplementationProto::self(exec)), implementation(i) { }
01177 
01178 DOMDOMImplementation::~DOMDOMImplementation()
01179 {
01180   ScriptInterpreter::forgetDOMObject(implementation.handle());
01181 }
01182 
01183 Value DOMDOMImplementationProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01184 {
01185   KJS_CHECK_THIS( KJS::DOMDOMImplementation, thisObj );
01186   DOM::DOMImplementation implementation = static_cast<DOMDOMImplementation *>( thisObj.imp() )->toImplementation();
01187 
01188   switch(id) {
01189   case DOMDOMImplementation::HasFeature:
01190     return Boolean(implementation.hasFeature(args[0].toString(exec).string(),args[1].toString(exec).string()));
01191   case DOMDOMImplementation::CreateDocumentType: // DOM2
01192     return getDOMNode(exec,implementation.createDocumentType(args[0].toString(exec).string(),args[1].toString(exec).string(),args[2].toString(exec).string()));
01193   case DOMDOMImplementation::CreateDocument: { // DOM2
01194     // Initially set the URL to document of the creator... this is so that it resides in the same
01195     // host/domain for security checks. The URL will be updated if Document.load() is called.
01196     KHTMLPart *part = ::qt_cast<KHTMLPart*>(static_cast<KJS::ScriptInterpreter*>(exec->interpreter())->part());
01197     if (part) {
01198       Document doc = implementation.createDocument(args[0].toString(exec).string(),args[1].toString(exec).string(),toNode(args[2]));
01199       KURL url = static_cast<DocumentImpl*>(part->document().handle())->URL();
01200       static_cast<DocumentImpl*>(doc.handle())->setURL(url.url());
01201       return getDOMNode(exec,doc);
01202     }
01203     break;
01204   }
01205   case DOMDOMImplementation::CreateCSSStyleSheet: // DOM2
01206     return getDOMStyleSheet(exec,implementation.createCSSStyleSheet(args[0].toString(exec).string(),args[1].toString(exec).string()));
01207   case DOMDOMImplementation::CreateHTMLDocument: // DOM2-HTML
01208     return getDOMNode(exec, implementation.createHTMLDocument(args[0].toString(exec).string()));
01209   default:
01210     break;
01211   }
01212   return Undefined();
01213 }
01214 
01215 // -------------------------------------------------------------------------
01216 
01217 const ClassInfo DOMDocumentType::info = { "DocumentType", &DOMNode::info, &DOMDocumentTypeTable, 0 };
01218 
01219 /* Source for DOMDocumentTypeTable.
01220 @begin DOMDocumentTypeTable 6
01221   name          DOMDocumentType::Name       DontDelete|ReadOnly
01222   entities      DOMDocumentType::Entities   DontDelete|ReadOnly
01223   notations     DOMDocumentType::Notations  DontDelete|ReadOnly
01224 # DOM2
01225   publicId      DOMDocumentType::PublicId   DontDelete|ReadOnly
01226   systemId      DOMDocumentType::SystemId   DontDelete|ReadOnly
01227   internalSubset    DOMDocumentType::InternalSubset DontDelete|ReadOnly
01228 @end
01229 */
01230 DOMDocumentType::DOMDocumentType(ExecState *exec, const DOM::DocumentType& dt)
01231   : DOMNode( /*### no proto yet*/exec, dt ) { }
01232 
01233 Value DOMDocumentType::tryGet(ExecState *exec, const Identifier &propertyName) const
01234 {
01235 #ifdef KJS_VERBOSE
01236   kdDebug(6070) << "DOMDocumentType::tryGet " << propertyName.qstring() << endl;
01237 #endif
01238   return DOMObjectLookupGetValue<DOMDocumentType, DOMNode>(exec, propertyName, &DOMDocumentTypeTable, this);
01239 }
01240 
01241 Value DOMDocumentType::getValueProperty(ExecState *exec, int token) const
01242 {
01243   DOM::DocumentType type = static_cast<DOM::DocumentType>(node);
01244   switch (token) {
01245   case Name:
01246     return String(type.name());
01247   case Entities:
01248     return getDOMNamedNodeMap(exec,type.entities());
01249   case Notations:
01250     return getDOMNamedNodeMap(exec,type.notations());
01251   case PublicId: // DOM2
01252     return String(type.publicId());
01253   case SystemId: // DOM2
01254     return String(type.systemId());
01255   case InternalSubset: // DOM2
01256     return getString(type.internalSubset()); // can be null, see domts/level2/core/internalSubset01.html
01257   default:
01258     kdDebug(6070) << "WARNING: DOMDocumentType::getValueProperty unhandled token " << token << endl;
01259     return Value();
01260   }
01261 }
01262 
01263 // -------------------------------------------------------------------------
01264 
01265 /* Source for DOMNamedNodeMapProtoTable.
01266 @begin DOMNamedNodeMapProtoTable 7
01267   getNamedItem      DOMNamedNodeMap::GetNamedItem       DontDelete|Function 1
01268   setNamedItem      DOMNamedNodeMap::SetNamedItem       DontDelete|Function 1
01269   removeNamedItem   DOMNamedNodeMap::RemoveNamedItem    DontDelete|Function 1
01270   item          DOMNamedNodeMap::Item           DontDelete|Function 1
01271 # DOM2
01272   getNamedItemNS    DOMNamedNodeMap::GetNamedItemNS     DontDelete|Function 2
01273   setNamedItemNS    DOMNamedNodeMap::SetNamedItemNS     DontDelete|Function 1
01274   removeNamedItemNS DOMNamedNodeMap::RemoveNamedItemNS  DontDelete|Function 2
01275 @end
01276 @begin DOMNamedNodeMapTable 7
01277   length        DOMNamedNodeMap::Length         DontDelete|Function 1
01278 @end
01279 */
01280 DEFINE_PROTOTYPE("NamedNodeMap", DOMNamedNodeMapProto)
01281 IMPLEMENT_PROTOFUNC_DOM(DOMNamedNodeMapProtoFunc)
01282 IMPLEMENT_PROTOTYPE(DOMNamedNodeMapProto,DOMNamedNodeMapProtoFunc)
01283 
01284 const ClassInfo DOMNamedNodeMap::info = { "NamedNodeMap", 0, &DOMNamedNodeMapTable, 0 };
01285 
01286 DOMNamedNodeMap::DOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap& m)
01287   : DOMObject(DOMNamedNodeMapProto::self(exec)), map(m) { }
01288 
01289 DOMNamedNodeMap::~DOMNamedNodeMap()
01290 {
01291   ScriptInterpreter::forgetDOMObject(map.handle());
01292 }
01293 
01294 bool DOMNamedNodeMap::hasProperty(ExecState *exec, const Identifier &p) const
01295 {
01296   // ## missing? array index
01297   return DOMObject::hasProperty(exec, p);
01298 }
01299 
01300 Value DOMNamedNodeMap::tryGet(ExecState* exec, const Identifier &p) const
01301 {
01302   if (p == lengthPropertyName)
01303     return Number(map.length());
01304 
01305   // array index ?
01306   bool ok;
01307   long unsigned int idx = p.toULong(&ok);
01308   if (ok)
01309     return getDOMNode(exec,map.item(idx));
01310 
01311   // Anything else (including functions, defined in the prototype)
01312   return DOMObject::tryGet(exec, p);
01313 }
01314 
01315 Value DOMNamedNodeMapProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01316 {
01317   KJS_CHECK_THIS( KJS::DOMNamedNodeMap, thisObj );
01318   DOM::NamedNodeMap map = static_cast<DOMNamedNodeMap *>(thisObj.imp())->toMap();
01319 
01320   switch(id) {
01321     case DOMNamedNodeMap::GetNamedItem:
01322       return getDOMNode(exec, map.getNamedItem(args[0].toString(exec).string()));
01323     case DOMNamedNodeMap::SetNamedItem:
01324       return getDOMNode(exec, map.setNamedItem((new DOMNode(exec,KJS::toNode(args[0])))->toNode()));
01325     case DOMNamedNodeMap::RemoveNamedItem:
01326       return getDOMNode(exec, map.removeNamedItem(args[0].toString(exec).string()));
01327     case DOMNamedNodeMap::Item:
01328       return getDOMNode(exec, map.item(args[0].toInt32(exec)));
01329     case DOMNamedNodeMap::GetNamedItemNS: // DOM2
01330       return getDOMNode(exec, map.getNamedItemNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01331     case DOMNamedNodeMap::SetNamedItemNS: // DOM2
01332       return getDOMNode(exec, map.setNamedItemNS(toNode(args[0])));
01333     case DOMNamedNodeMap::RemoveNamedItemNS: // DOM2
01334       return getDOMNode(exec, map.removeNamedItemNS(args[0].toString(exec).string(),args[1].toString(exec).string()));
01335     default:
01336       break;
01337   }
01338 
01339   return Undefined();
01340 }
01341 
01342 // -------------------------------------------------------------------------
01343 
01344 const ClassInfo DOMProcessingInstruction::info = { "ProcessingInstruction", &DOMNode::info, &DOMProcessingInstructionTable, 0 };
01345 
01346 /* Source for DOMProcessingInstructionTable.
01347 @begin DOMProcessingInstructionTable 3
01348   target    DOMProcessingInstruction::Target    DontDelete|ReadOnly
01349   data      DOMProcessingInstruction::Data      DontDelete
01350   sheet     DOMProcessingInstruction::Sheet     DontDelete|ReadOnly
01351 @end
01352 */
01353 Value DOMProcessingInstruction::tryGet(ExecState *exec, const Identifier &propertyName) const
01354 {
01355   return DOMObjectLookupGetValue<DOMProcessingInstruction, DOMNode>(exec, propertyName, &DOMProcessingInstructionTable, this);
01356 }
01357 
01358 Value DOMProcessingInstruction::getValueProperty(ExecState *exec, int token) const
01359 {
01360   switch (token) {
01361   case Target:
01362     return String(static_cast<DOM::ProcessingInstruction>(node).target());
01363   case Data:
01364     return String(static_cast<DOM::ProcessingInstruction>(node).data());
01365   case Sheet:
01366     return getDOMStyleSheet(exec,static_cast<DOM::ProcessingInstruction>(node).sheet());
01367   default:
01368     kdDebug(6070) << "WARNING: DOMProcessingInstruction::getValueProperty unhandled token " << token << endl;
01369     return Value();
01370   }
01371 }
01372 
01373 void DOMProcessingInstruction::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
01374 {
01375   // Not worth using the hashtable for this one ;)
01376   if (propertyName == "data")
01377     static_cast<DOM::ProcessingInstruction>(node).setData(value.toString(exec).string());
01378   else
01379     DOMNode::tryPut(exec, propertyName,value,attr);
01380 }
01381 
01382 // -------------------------------------------------------------------------
01383 
01384 const ClassInfo DOMNotation::info = { "Notation", &DOMNode::info, &DOMNotationTable, 0 };
01385 
01386 /* Source for DOMNotationTable.
01387 @begin DOMNotationTable 2
01388   publicId      DOMNotation::PublicId   DontDelete|ReadOnly
01389   systemId      DOMNotation::SystemId   DontDelete|ReadOnly
01390 @end
01391 */
01392 Value DOMNotation::tryGet(ExecState *exec, const Identifier &propertyName) const
01393 {
01394   return DOMObjectLookupGetValue<DOMNotation, DOMNode>(exec, propertyName, &DOMNotationTable, this);
01395 }
01396 
01397 Value DOMNotation::getValueProperty(ExecState *, int token) const
01398 {
01399   switch (token) {
01400   case PublicId:
01401     return String(static_cast<DOM::Notation>(node).publicId());
01402   case SystemId:
01403     return String(static_cast<DOM::Notation>(node).systemId());
01404   default:
01405     kdDebug(6070) << "WARNING: DOMNotation::getValueProperty unhandled token " << token << endl;
01406     return Value();
01407   }
01408 }
01409 
01410 // -------------------------------------------------------------------------
01411 
01412 const ClassInfo DOMEntity::info = { "Entity", &DOMNode::info, 0, 0 };
01413 
01414 /* Source for DOMEntityTable.
01415 @begin DOMEntityTable 2
01416   publicId      DOMEntity::PublicId     DontDelete|ReadOnly
01417   systemId      DOMEntity::SystemId     DontDelete|ReadOnly
01418   notationName      DOMEntity::NotationName DontDelete|ReadOnly
01419 @end
01420 */
01421 Value DOMEntity::tryGet(ExecState *exec, const Identifier &propertyName) const
01422 {
01423   return DOMObjectLookupGetValue<DOMEntity, DOMNode>(exec, propertyName, &DOMEntityTable, this);
01424 }
01425 
01426 Value DOMEntity::getValueProperty(ExecState *, int token) const
01427 {
01428   switch (token) {
01429   case PublicId:
01430     return String(static_cast<DOM::Entity>(node).publicId());
01431   case SystemId:
01432     return String(static_cast<DOM::Entity>(node).systemId());
01433   case NotationName:
01434     return String(static_cast<DOM::Entity>(node).notationName());
01435   default:
01436     kdDebug(6070) << "WARNING: DOMEntity::getValueProperty unhandled token " << token << endl;
01437     return Value();
01438   }
01439 }
01440 
01441 // -------------------------------------------------------------------------
01442 
01443 bool KJS::checkNodeSecurity(ExecState *exec, const DOM::Node& n)
01444 {
01445   // Check to see if the currently executing interpreter is allowed to access the specified node
01446   if (n.isNull())
01447     return true;
01448   KHTMLView *view = n.handle()->getDocument()->view();
01449   Window* win = view && view->part() ? Window::retrieveWindow(view->part()) : 0L;
01450   if ( !win || !win->isSafeScript(exec) )
01451     return false;
01452   return true;
01453 }
01454 
01455 Value KJS::getDOMNode(ExecState *exec, const DOM::Node& n)
01456 {
01457   DOMObject *ret = 0;
01458   if (n.isNull())
01459     return Null();
01460   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
01461   if ((ret = interp->getDOMObject(n.handle())))
01462     return Value(ret);
01463 
01464   switch (n.nodeType()) {
01465     case DOM::Node::ELEMENT_NODE:
01466       if (static_cast<DOM::Element>(n).isHTMLElement())
01467         ret = new HTMLElement(exec, static_cast<DOM::HTMLElement>(n));
01468       else
01469         ret = new DOMElement(exec, static_cast<DOM::Element>(n));
01470       break;
01471     case DOM::Node::ATTRIBUTE_NODE:
01472       ret = new DOMAttr(exec, static_cast<DOM::Attr>(n));
01473       break;
01474     case DOM::Node::TEXT_NODE:
01475     case DOM::Node::CDATA_SECTION_NODE:
01476       ret = new DOMText(exec, static_cast<DOM::Text>(n));
01477       break;
01478     case DOM::Node::ENTITY_REFERENCE_NODE:
01479       ret = new DOMNode(exec, n);
01480       break;
01481     case DOM::Node::ENTITY_NODE:
01482       ret = new DOMEntity(exec, static_cast<DOM::Entity>(n));
01483       break;
01484     case DOM::Node::PROCESSING_INSTRUCTION_NODE:
01485       ret = new DOMProcessingInstruction(exec, static_cast<DOM::ProcessingInstruction>(n));
01486       break;
01487     case DOM::Node::COMMENT_NODE:
01488       ret = new DOMCharacterData(exec, static_cast<DOM::CharacterData>(n));
01489       break;
01490     case DOM::Node::DOCUMENT_NODE:
01491       if (static_cast<DOM::Document>(n).isHTMLDocument())
01492         ret = new HTMLDocument(exec, static_cast<DOM::HTMLDocument>(n));
01493       else
01494         ret = new DOMDocument(exec, static_cast<DOM::Document>(n));
01495       break;
01496     case DOM::Node::DOCUMENT_TYPE_NODE:
01497       ret = new DOMDocumentType(exec, static_cast<DOM::DocumentType>(n));
01498       break;
01499     case DOM::Node::DOCUMENT_FRAGMENT_NODE:
01500       ret = new DOMNode(exec, n);
01501       break;
01502     case DOM::Node::NOTATION_NODE:
01503       ret = new DOMNotation(exec, static_cast<DOM::Notation>(n));
01504       break;
01505     default:
01506       ret = new DOMNode(exec, n);
01507   }
01508   interp->putDOMObject(n.handle(),ret);
01509 
01510   return Value(ret);
01511 }
01512 
01513 Value KJS::getDOMNamedNodeMap(ExecState *exec, const DOM::NamedNodeMap& m)
01514 {
01515   return Value(cacheDOMObject<DOM::NamedNodeMap, KJS::DOMNamedNodeMap>(exec, m));
01516 }
01517 
01518 Value KJS::getDOMNodeList(ExecState *exec, const DOM::NodeList& l)
01519 {
01520   return Value(cacheDOMObject<DOM::NodeList, KJS::DOMNodeList>(exec, l));
01521 }
01522 
01523 Value KJS::getDOMDOMImplementation(ExecState *exec, const DOM::DOMImplementation& i)
01524 {
01525   return Value(cacheDOMObject<DOM::DOMImplementation, KJS::DOMDOMImplementation>(exec, i));
01526 }
01527 
01528 // -------------------------------------------------------------------------
01529 
01530 const ClassInfo NodeConstructor::info = { "NodeConstructor", 0, &NodeConstructorTable, 0 };
01531 /* Source for NodeConstructorTable.
01532 @begin NodeConstructorTable 11
01533   ELEMENT_NODE      DOM::Node::ELEMENT_NODE     DontDelete|ReadOnly
01534   ATTRIBUTE_NODE    DOM::Node::ATTRIBUTE_NODE       DontDelete|ReadOnly
01535   TEXT_NODE     DOM::Node::TEXT_NODE        DontDelete|ReadOnly
01536   CDATA_SECTION_NODE    DOM::Node::CDATA_SECTION_NODE   DontDelete|ReadOnly
01537   ENTITY_REFERENCE_NODE DOM::Node::ENTITY_REFERENCE_NODE    DontDelete|ReadOnly
01538   ENTITY_NODE       DOM::Node::ENTITY_NODE      DontDelete|ReadOnly
01539   PROCESSING_INSTRUCTION_NODE DOM::Node::PROCESSING_INSTRUCTION_NODE DontDelete|ReadOnly
01540   COMMENT_NODE      DOM::Node::COMMENT_NODE     DontDelete|ReadOnly
01541   DOCUMENT_NODE     DOM::Node::DOCUMENT_NODE        DontDelete|ReadOnly
01542   DOCUMENT_TYPE_NODE    DOM::Node::DOCUMENT_TYPE_NODE   DontDelete|ReadOnly
01543   DOCUMENT_FRAGMENT_NODE DOM::Node::DOCUMENT_FRAGMENT_NODE  DontDelete|ReadOnly
01544   NOTATION_NODE     DOM::Node::NOTATION_NODE        DontDelete|ReadOnly
01545 @end
01546 */
01547 
01548 NodeConstructor::NodeConstructor(ExecState *exec)
01549   : DOMObject(exec->interpreter()->builtinObjectPrototype())
01550 {
01551 }
01552 
01553 Value NodeConstructor::tryGet(ExecState *exec, const Identifier &propertyName) const
01554 {
01555   return DOMObjectLookupGetValue<NodeConstructor, DOMObject>(exec, propertyName, &NodeConstructorTable, this);
01556 }
01557 
01558 Value NodeConstructor::getValueProperty(ExecState *, int token) const
01559 {
01560   // We use the token as the value to return directly
01561   return Number((unsigned int)token);
01562 #if 0
01563   switch (token) {
01564   case ELEMENT_NODE:
01565     return Number((unsigned int)DOM::Node::ELEMENT_NODE);
01566   case ATTRIBUTE_NODE:
01567     return Number((unsigned int)DOM::Node::ATTRIBUTE_NODE);
01568   case TEXT_NODE:
01569     return Number((unsigned int)DOM::Node::TEXT_NODE);
01570   case CDATA_SECTION_NODE:
01571     return Number((unsigned int)DOM::Node::CDATA_SECTION_NODE);
01572   case ENTITY_REFERENCE_NODE:
01573     return Number((unsigned int)DOM::Node::ENTITY_REFERENCE_NODE);
01574   case ENTITY_NODE:
01575     return Number((unsigned int)DOM::Node::ENTITY_NODE);
01576   case PROCESSING_INSTRUCTION_NODE:
01577     return Number((unsigned int)DOM::Node::PROCESSING_INSTRUCTION_NODE);
01578   case COMMENT_NODE:
01579     return Number((unsigned int)DOM::Node::COMMENT_NODE);
01580   case DOCUMENT_NODE:
01581     return Number((unsigned int)DOM::Node::DOCUMENT_NODE);
01582   case DOCUMENT_TYPE_NODE:
01583     return Number((unsigned int)DOM::Node::DOCUMENT_TYPE_NODE);
01584   case DOCUMENT_FRAGMENT_NODE:
01585     return Number((unsigned int)DOM::Node::DOCUMENT_FRAGMENT_NODE);
01586   case NOTATION_NODE:
01587     return Number((unsigned int)DOM::Node::NOTATION_NODE);
01588   default:
01589     kdDebug(6070) << "WARNING: NodeConstructor::getValueProperty unhandled token " << token << endl;
01590     return Value();
01591   }
01592 #endif
01593 }
01594 
01595 Object KJS::getNodeConstructor(ExecState *exec)
01596 {
01597   return Object(cacheGlobalObject<NodeConstructor>(exec, "[[node.constructor]]"));
01598 }
01599 
01600 // -------------------------------------------------------------------------
01601 
01602 const ClassInfo DOMExceptionConstructor::info = { "DOMExceptionConstructor", 0, 0, 0 };
01603 
01604 /* Source for DOMExceptionConstructorTable.
01605 @begin DOMExceptionConstructorTable 15
01606   INDEX_SIZE_ERR        DOM::DOMException::INDEX_SIZE_ERR       DontDelete|ReadOnly
01607   DOMSTRING_SIZE_ERR        DOM::DOMException::DOMSTRING_SIZE_ERR   DontDelete|ReadOnly
01608   HIERARCHY_REQUEST_ERR     DOM::DOMException::HIERARCHY_REQUEST_ERR    DontDelete|ReadOnly
01609   WRONG_DOCUMENT_ERR        DOM::DOMException::WRONG_DOCUMENT_ERR   DontDelete|ReadOnly
01610   INVALID_CHARACTER_ERR     DOM::DOMException::INVALID_CHARACTER_ERR    DontDelete|ReadOnly
01611   NO_DATA_ALLOWED_ERR       DOM::DOMException::NO_DATA_ALLOWED_ERR  DontDelete|ReadOnly
01612   NO_MODIFICATION_ALLOWED_ERR   DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR  DontDelete|ReadOnly
01613   NOT_FOUND_ERR         DOM::DOMException::NOT_FOUND_ERR        DontDelete|ReadOnly
01614   NOT_SUPPORTED_ERR     DOM::DOMException::NOT_SUPPORTED_ERR    DontDelete|ReadOnly
01615   INUSE_ATTRIBUTE_ERR       DOM::DOMException::INUSE_ATTRIBUTE_ERR  DontDelete|ReadOnly
01616   INVALID_STATE_ERR     DOM::DOMException::INVALID_STATE_ERR    DontDelete|ReadOnly
01617   SYNTAX_ERR            DOM::DOMException::SYNTAX_ERR       DontDelete|ReadOnly
01618   INVALID_MODIFICATION_ERR  DOM::DOMException::INVALID_MODIFICATION_ERR DontDelete|ReadOnly
01619   NAMESPACE_ERR         DOM::DOMException::NAMESPACE_ERR        DontDelete|ReadOnly
01620   INVALID_ACCESS_ERR        DOM::DOMException::INVALID_ACCESS_ERR   DontDelete|ReadOnly
01621 @end
01622 */
01623 
01624 DOMExceptionConstructor::DOMExceptionConstructor(ExecState* exec)
01625   : DOMObject(exec->interpreter()->builtinObjectPrototype())
01626 {
01627 }
01628 
01629 Value DOMExceptionConstructor::tryGet(ExecState *exec, const Identifier &propertyName) const
01630 {
01631   return DOMObjectLookupGetValue<DOMExceptionConstructor, DOMObject>(exec, propertyName, &DOMExceptionConstructorTable, this);
01632 }
01633 
01634 Value DOMExceptionConstructor::getValueProperty(ExecState *, int token) const
01635 {
01636   // We use the token as the value to return directly
01637   return Number((unsigned int)token);
01638 #if 0
01639   switch (token) {
01640   case INDEX_SIZE_ERR:
01641     return Number((unsigned int)DOM::DOMException::INDEX_SIZE_ERR);
01642   case DOMSTRING_SIZE_ERR:
01643     return Number((unsigned int)DOM::DOMException::DOMSTRING_SIZE_ERR);
01644   case HIERARCHY_REQUEST_ERR:
01645     return Number((unsigned int)DOM::DOMException::HIERARCHY_REQUEST_ERR);
01646   case WRONG_DOCUMENT_ERR:
01647     return Number((unsigned int)DOM::DOMException::WRONG_DOCUMENT_ERR);
01648   case INVALID_CHARACTER_ERR:
01649     return Number((unsigned int)DOM::DOMException::INVALID_CHARACTER_ERR);
01650   case NO_DATA_ALLOWED_ERR:
01651     return Number((unsigned int)DOM::DOMException::NO_DATA_ALLOWED_ERR);
01652   case NO_MODIFICATION_ALLOWED_ERR:
01653     return Number((unsigned int)DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR);
01654   case NOT_FOUND_ERR:
01655     return Number((unsigned int)DOM::DOMException::NOT_FOUND_ERR);
01656   case NOT_SUPPORTED_ERR:
01657     return Number((unsigned int)DOM::DOMException::NOT_SUPPORTED_ERR);
01658   case INUSE_ATTRIBUTE_ERR:
01659     return Number((unsigned int)DOM::DOMException::INUSE_ATTRIBUTE_ERR);
01660   case INVALID_STATE_ERR:
01661     return Number((unsigned int)DOM::DOMException::INVALID_STATE_ERR);
01662   case SYNTAX_ERR:
01663     return Number((unsigned int)DOM::DOMException::SYNTAX_ERR);
01664   case INVALID_MODIFICATION_ERR:
01665     return Number((unsigned int)DOM::DOMException::INVALID_MODIFICATION_ERR);
01666   case NAMESPACE_ERR:
01667     return Number((unsigned int)DOM::DOMException::NAMESPACE_ERR);
01668   case INVALID_ACCESS_ERR:
01669     return Number((unsigned int)DOM::DOMException::INVALID_ACCESS_ERR);
01670   default:
01671     kdDebug(6070) << "WARNING: DOMExceptionConstructor::getValueProperty unhandled token " << token << endl;
01672     return Value();
01673   }
01674 #endif
01675 }
01676 
01677 Object KJS::getDOMExceptionConstructor(ExecState *exec)
01678 {
01679   return cacheGlobalObject<DOMExceptionConstructor>(exec, "[[DOMException.constructor]]");
01680 }
01681 
01682 // -------------------------------------------------------------------------
01683 
01684 /* Source for DOMNamedNodesCollection.
01685 @begin DOMNamedNodesCollectionTable 1
01686   length        KJS::DOMNamedNodesCollection::Length        DontDelete|ReadOnly
01687 @end
01688 */
01689 const ClassInfo KJS::DOMNamedNodesCollection::info = { "DOMNamedNodesCollection", 0, &DOMNamedNodesCollectionTable, 0 };
01690 
01691 // Such a collection is usually very short-lived, it only exists
01692 // for constructs like document.forms.<name>[1],
01693 // so it shouldn't be a problem that it's storing all the nodes (with the same name). (David)
01694 DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState *exec, const QValueList<DOM::Node>& nodes )
01695   : DOMObject(exec->interpreter()->builtinObjectPrototype()),
01696   m_nodes(nodes)
01697 {
01698   // Maybe we should ref (and deref in the dtor) the nodes, though ?
01699 }
01700 
01701 Value DOMNamedNodesCollection::tryGet(ExecState *exec, const Identifier &propertyName) const
01702 {
01703   kdDebug(6070) << k_funcinfo << propertyName.ascii() << endl;
01704   if (propertyName == lengthPropertyName)
01705     return Number(m_nodes.count());
01706   // index?
01707   bool ok;
01708   unsigned int u = propertyName.toULong(&ok);
01709   if (ok && u < m_nodes.count()) {
01710     DOM::Node node = m_nodes[u];
01711     return getDOMNode(exec,node);
01712   }
01713   return DOMObject::tryGet(exec,propertyName);
01714 }
01715 
01716 // -------------------------------------------------------------------------
01717 
01718 const ClassInfo DOMCharacterData::info = { "CharacterImp",
01719                       &DOMNode::info, &DOMCharacterDataTable, 0 };
01720 /*
01721 @begin DOMCharacterDataTable 2
01722   data      DOMCharacterData::Data      DontDelete
01723   length    DOMCharacterData::Length    DontDelete|ReadOnly
01724 @end
01725 @begin DOMCharacterDataProtoTable 7
01726   substringData DOMCharacterData::SubstringData DontDelete|Function 2
01727   appendData    DOMCharacterData::AppendData    DontDelete|Function 1
01728   insertData    DOMCharacterData::InsertData    DontDelete|Function 2
01729   deleteData    DOMCharacterData::DeleteData    DontDelete|Function 2
01730   replaceData   DOMCharacterData::ReplaceData   DontDelete|Function 2
01731 @end
01732 */
01733 DEFINE_PROTOTYPE("DOMCharacterData",DOMCharacterDataProto)
01734 IMPLEMENT_PROTOFUNC_DOM(DOMCharacterDataProtoFunc)
01735 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMCharacterDataProto,DOMCharacterDataProtoFunc, DOMNodeProto)
01736 
01737 DOMCharacterData::DOMCharacterData(ExecState *exec, const DOM::CharacterData& d)
01738  : DOMNode(DOMCharacterDataProto::self(exec), d) {}
01739 
01740 DOMCharacterData::DOMCharacterData(const Object& proto, const DOM::CharacterData& d)
01741  : DOMNode(proto, d) {}
01742 
01743 Value DOMCharacterData::tryGet(ExecState *exec, const Identifier &p) const
01744 {
01745 #ifdef KJS_VERBOSE
01746   kdDebug(6070)<<"DOMCharacterData::tryGet "<<p.string().string()<<endl;
01747 #endif
01748   return DOMObjectLookupGetValue<DOMCharacterData,DOMNode>(exec,p,&DOMCharacterDataTable,this);
01749 }
01750 
01751 Value DOMCharacterData::getValueProperty(ExecState *, int token) const
01752 {
01753   DOM::CharacterData data = static_cast<DOM::CharacterData>(node);
01754   switch (token) {
01755   case Data:
01756     return String(data.data());
01757   case Length:
01758     return Number(data.length());
01759  default:
01760    kdDebug(6070) << "WARNING: Unhandled token in DOMCharacterData::getValueProperty : " << token << endl;
01761    return Value();
01762   }
01763 }
01764 
01765 void DOMCharacterData::tryPut(ExecState *exec, const Identifier &propertyName, const Value& value, int attr)
01766 {
01767   if (propertyName == "data")
01768     static_cast<DOM::CharacterData>(node).setData(value.toString(exec).string());
01769   else
01770     DOMNode::tryPut(exec, propertyName,value,attr);
01771 }
01772 
01773 Value DOMCharacterDataProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01774 {
01775   KJS_CHECK_THIS( KJS::DOMCharacterData, thisObj );
01776   DOM::CharacterData data = static_cast<DOMCharacterData *>(thisObj.imp())->toData();
01777   switch(id) {
01778     case DOMCharacterData::SubstringData:
01779       return String(data.substringData(args[0].toInteger(exec),args[1].toInteger(exec)));
01780     case DOMCharacterData::AppendData:
01781       data.appendData(args[0].toString(exec).string());
01782       return Undefined();
01783       break;
01784     case DOMCharacterData::InsertData:
01785       data.insertData(args[0].toInteger(exec),args[1].toString(exec).string());
01786       return  Undefined();
01787       break;
01788     case DOMCharacterData::DeleteData:
01789       data.deleteData(args[0].toInteger(exec),args[1].toInteger(exec));
01790       return  Undefined();
01791       break;
01792     case DOMCharacterData::ReplaceData:
01793       data.replaceData(args[0].toInteger(exec),args[1].toInteger(exec),args[2].toString(exec).string());
01794       return Undefined();
01795     default:
01796       break;
01797   }
01798   return Undefined();
01799 }
01800 
01801 // -------------------------------------------------------------------------
01802 
01803 const ClassInfo DOMText::info = { "Text",
01804                  &DOMCharacterData::info, 0, 0 };
01805 /*
01806 @begin DOMTextProtoTable 1
01807   splitText DOMText::SplitText  DontDelete|Function 1
01808 @end
01809 */
01810 DEFINE_PROTOTYPE("DOMText",DOMTextProto)
01811 IMPLEMENT_PROTOFUNC_DOM(DOMTextProtoFunc)
01812 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMTextProto,DOMTextProtoFunc,DOMCharacterDataProto)
01813 
01814 DOMText::DOMText(ExecState *exec, const DOM::Text& t)
01815   : DOMCharacterData(DOMTextProto::self(exec), t) { }
01816 
01817 Value DOMText::tryGet(ExecState *exec, const Identifier &p) const
01818 {
01819   if (p.isEmpty())
01820     return Undefined(); // ### TODO
01821   else
01822     return DOMCharacterData::tryGet(exec, p);
01823 }
01824 
01825 Value DOMTextProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01826 {
01827   KJS_CHECK_THIS( KJS::DOMText, thisObj );
01828   DOM::Text text = static_cast<DOMText *>(thisObj.imp())->toText();
01829   switch(id) {
01830     case DOMText::SplitText:
01831       return getDOMNode(exec,text.splitText(args[0].toInteger(exec)));
01832     default:
01833       break;
01834   }
01835   return Undefined();
01836 }
KDE Home | KDE Accessibility Home | Description of Access Keys