File indexing completed on 2023-09-24 04:06:09
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 2000 Harri Porten (porten@kde.org) 0004 * Copyright (C) 2003 Apple Computer, Inc. 0005 * Copyright (C) 2010 Maksim Orlovich (maksim@kde.org) 0006 * 0007 * This library is free software; you can redistribute it and/or 0008 * modify it under the terms of the GNU Library General Public 0009 * License as published by the Free Software Foundation; either 0010 * version 2 of the License, or (at your option) any later version. 0011 * 0012 * This library is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Library General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Library General Public 0018 * License along with this library; if not, write to the Free Software 0019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0020 */ 0021 0022 #include "kjs_dom.h" 0023 #include "kjs_dom.lut.h" 0024 0025 #include <khtmlview.h> 0026 #include <xml/dom2_eventsimpl.h> 0027 #include <rendering/render_canvas.h> 0028 #include <rendering/render_layer.h> 0029 #include <xml/dom_nodeimpl.h> 0030 #include <xml/dom_docimpl.h> 0031 #include <xml/dom3_xpathimpl.h> 0032 #include <html/html_baseimpl.h> 0033 #include <html/html_documentimpl.h> 0034 #include <html/html_miscimpl.h> 0035 #include "HTMLAudioElement.h" 0036 #include "HTMLVideoElement.h" 0037 #include "JSHTMLAudioElement.h" 0038 #include "JSHTMLVideoElement.h" 0039 #include "khtml_debug.h" 0040 #include <khtml_part.h> 0041 #include <QList> 0042 0043 #include "kjs_html.h" 0044 #include "kjs_css.h" 0045 #include "kjs_range.h" 0046 #include "kjs_traversal.h" 0047 #include "kjs_events.h" 0048 #include "kjs_views.h" 0049 #include "kjs_window.h" 0050 #include "kjs_xpath.h" 0051 #include "kjs_clientrect.h" 0052 #include "xmlhttprequest.h" 0053 #include <kjs/PropertyNameArray.h> 0054 #include <dom/dom_exception.h> 0055 #include <dom/html_document.h> 0056 #include <khtmlpart_p.h> 0057 0058 // for win32, MinGW 0059 #undef FOCUS_EVENT 0060 #undef CreateEvent 0061 0062 using namespace KJS; 0063 using namespace khtml; 0064 using namespace DOM; 0065 0066 // ------------------------------------------------------------------------- 0067 /* Source for DOMNodeConstantsTable. 0068 @begin DOMNodeConstantsTable 21 0069 ELEMENT_NODE DOM::Node::ELEMENT_NODE DontDelete|ReadOnly 0070 ATTRIBUTE_NODE DOM::Node::ATTRIBUTE_NODE DontDelete|ReadOnly 0071 TEXT_NODE DOM::Node::TEXT_NODE DontDelete|ReadOnly 0072 CDATA_SECTION_NODE DOM::Node::CDATA_SECTION_NODE DontDelete|ReadOnly 0073 ENTITY_REFERENCE_NODE DOM::Node::ENTITY_REFERENCE_NODE DontDelete|ReadOnly 0074 ENTITY_NODE DOM::Node::ENTITY_NODE DontDelete|ReadOnly 0075 PROCESSING_INSTRUCTION_NODE DOM::Node::PROCESSING_INSTRUCTION_NODE DontDelete|ReadOnly 0076 COMMENT_NODE DOM::Node::COMMENT_NODE DontDelete|ReadOnly 0077 DOCUMENT_NODE DOM::Node::DOCUMENT_NODE DontDelete|ReadOnly 0078 DOCUMENT_TYPE_NODE DOM::Node::DOCUMENT_TYPE_NODE DontDelete|ReadOnly 0079 DOCUMENT_FRAGMENT_NODE DOM::Node::DOCUMENT_FRAGMENT_NODE DontDelete|ReadOnly 0080 NOTATION_NODE DOM::Node::NOTATION_NODE DontDelete|ReadOnly 0081 XPATH_NAMESPACE_NODE DOM::Node::XPATH_NAMESPACE_NODE DontDelete|ReadOnly 0082 DOCUMENT_POSITION_DISCONNECTED DOM::Node::DOCUMENT_POSITION_DISCONNECTED DontDelete|ReadOnly 0083 DOCUMENT_POSITION_PRECEDING DOM::Node::DOCUMENT_POSITION_PRECEDING DontDelete|ReadOnly 0084 DOCUMENT_POSITION_FOLLOWING DOM::Node::DOCUMENT_POSITION_FOLLOWING DontDelete|ReadOnly 0085 DOCUMENT_POSITION_CONTAINS DOM::Node::DOCUMENT_POSITION_CONTAINS DontDelete|ReadOnly 0086 DOCUMENT_POSITION_CONTAINED_BY DOM::Node::DOCUMENT_POSITION_CONTAINED_BY DontDelete|ReadOnly 0087 DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC DOM::Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC DontDelete|ReadOnly 0088 @end 0089 */ 0090 IMPLEMENT_CONSTANT_TABLE(DOMNodeConstants, "DOMNodeConstants") 0091 0092 // ------------------------------------------------------------------------- 0093 /* Source for DOMNodeProtoTable. 0094 @begin DOMNodeProtoTable 13 0095 insertBefore DOMNode::InsertBefore DontDelete|Function 2 0096 replaceChild DOMNode::ReplaceChild DontDelete|Function 2 0097 removeChild DOMNode::RemoveChild DontDelete|Function 1 0098 appendChild DOMNode::AppendChild DontDelete|Function 1 0099 hasAttributes DOMNode::HasAttributes DontDelete|Function 0 0100 hasChildNodes DOMNode::HasChildNodes DontDelete|Function 0 0101 cloneNode DOMNode::CloneNode DontDelete|Function 1 0102 # DOM2 0103 normalize DOMNode::Normalize DontDelete|Function 0 0104 isSupported DOMNode::IsSupported DontDelete|Function 2 0105 # DOM3 0106 compareDocumentPosition DOMNode::CompareDocumentPosition DontDelete|Function 1 0107 # from the EventTarget interface 0108 addEventListener DOMNode::AddEventListener DontDelete|Function 3 0109 removeEventListener DOMNode::RemoveEventListener DontDelete|Function 3 0110 dispatchEvent DOMNode::DispatchEvent DontDelete|Function 1 0111 # IE extensions 0112 contains DOMNode::Contains DontDelete|Function 1 0113 insertAdjacentHTML DOMNode::InsertAdjacentHTML DontDelete|Function 2 0114 @end 0115 */ 0116 KJS_IMPLEMENT_PROTOFUNC(DOMNodeProtoFunc) 0117 KJS_IMPLEMENT_PROTOTYPE_IMP("DOMNode", DOMNodeProto, DOMNodeProtoFunc, DOMNodeConstants) 0118 { 0119 // We need to setup the constructor property to the ctor here, but NodeConstructor::self 0120 // will try to make us again, since we're in the middle of cacheGlobalObject. 0121 // To workaround that, register ourselves so the re-entry of cacheGlobalObject 0122 // will pick us. NodeCtor ctor does the same already, to fix the problem 0123 // in the other direction. 0124 exec->lexicalInterpreter()->globalObject()->put(exec, *name(), this, KJS::Internal | KJS::DontEnum); 0125 putDirect(exec->propertyNames().constructor, NodeConstructor::self(exec), DontEnum); 0126 } 0127 0128 const ClassInfo DOMNode::info = { "Node", nullptr, &DOMNodeTable, nullptr }; 0129 0130 DOMNode::DOMNode(ExecState *exec, DOM::NodeImpl *n) 0131 : DOMObject(DOMNodeProto::self(exec)), m_impl(n) 0132 {} 0133 0134 DOMNode::DOMNode(JSObject *proto, DOM::NodeImpl *n) 0135 : DOMObject(proto), m_impl(n) 0136 {} 0137 0138 DOMNode::~DOMNode() 0139 { 0140 ScriptInterpreter::forgetDOMObject(m_impl.get()); 0141 } 0142 0143 bool DOMNode::toBoolean(ExecState *) const 0144 { 0145 return !m_impl.isNull(); 0146 } 0147 0148 /* Source for DOMNodeTable. 0149 @begin DOMNodeTable 53 0150 nodeName DOMNode::NodeName DontDelete|ReadOnly 0151 nodeValue DOMNode::NodeValue DontDelete 0152 nodeType DOMNode::NodeType DontDelete|ReadOnly 0153 parentNode DOMNode::ParentNode DontDelete|ReadOnly 0154 parentElement DOMNode::ParentElement DontDelete|ReadOnly 0155 childNodes DOMNode::ChildNodes DontDelete|ReadOnly 0156 firstChild DOMNode::FirstChild DontDelete|ReadOnly 0157 lastChild DOMNode::LastChild DontDelete|ReadOnly 0158 previousSibling DOMNode::PreviousSibling DontDelete|ReadOnly 0159 nextSibling DOMNode::NextSibling DontDelete|ReadOnly 0160 attributes DOMNode::Attributes DontDelete|ReadOnly 0161 namespaceURI DOMNode::NamespaceURI DontDelete|ReadOnly 0162 # DOM2 0163 prefix DOMNode::Prefix DontDelete 0164 localName DOMNode::LocalName DontDelete|ReadOnly 0165 ownerDocument DOMNode::OwnerDocument DontDelete|ReadOnly 0166 # DOM3 0167 textContent DOMNode::TextContent DontDelete 0168 # Event handlers 0169 # IE also has: onactivate, onbefore*, oncontextmenu, oncontrolselect, oncut, 0170 # ondeactivate, ondrag*, ondrop, onfocusin, onfocusout, onhelp, onmousewheel, 0171 # onmove*, onpaste, onpropertychange, onreadystatechange, onresizeend/start, 0172 # onselectionchange, onstop 0173 onabort DOMNode::OnAbort DontDelete 0174 onblur DOMNode::OnBlur DontDelete 0175 onchange DOMNode::OnChange DontDelete 0176 onclick DOMNode::OnClick DontDelete 0177 ondblclick DOMNode::OnDblClick DontDelete 0178 ondragdrop DOMNode::OnDragDrop DontDelete 0179 onerror DOMNode::OnError DontDelete 0180 onfocus DOMNode::OnFocus DontDelete 0181 onkeydown DOMNode::OnKeyDown DontDelete 0182 onkeypress DOMNode::OnKeyPress DontDelete 0183 onkeyup DOMNode::OnKeyUp DontDelete 0184 onload DOMNode::OnLoad DontDelete 0185 onmousedown DOMNode::OnMouseDown DontDelete 0186 onmousemove DOMNode::OnMouseMove DontDelete 0187 onmouseout DOMNode::OnMouseOut DontDelete 0188 onmouseover DOMNode::OnMouseOver DontDelete 0189 onmouseup DOMNode::OnMouseUp DontDelete 0190 onmove DOMNode::OnMove DontDelete 0191 onreset DOMNode::OnReset DontDelete 0192 onresize DOMNode::OnResize DontDelete 0193 onscroll DOMNode::OnScroll DontDelete 0194 onselect DOMNode::OnSelect DontDelete 0195 onsubmit DOMNode::OnSubmit DontDelete 0196 onunload DOMNode::OnUnload DontDelete 0197 # IE extensions 0198 offsetLeft DOMNode::OffsetLeft DontDelete|ReadOnly 0199 offsetTop DOMNode::OffsetTop DontDelete|ReadOnly 0200 offsetWidth DOMNode::OffsetWidth DontDelete|ReadOnly 0201 offsetHeight DOMNode::OffsetHeight DontDelete|ReadOnly 0202 offsetParent DOMNode::OffsetParent DontDelete|ReadOnly 0203 clientWidth DOMNode::ClientWidth DontDelete|ReadOnly 0204 clientHeight DOMNode::ClientHeight DontDelete|ReadOnly 0205 clientLeft DOMNode::ClientLeft DontDelete|ReadOnly 0206 clientTop DOMNode::ClientTop DontDelete|ReadOnly 0207 scrollLeft DOMNode::ScrollLeft DontDelete 0208 scrollTop DOMNode::ScrollTop DontDelete 0209 scrollWidth DOMNode::ScrollWidth DontDelete|ReadOnly 0210 scrollHeight DOMNode::ScrollHeight DontDelete|ReadOnly 0211 sourceIndex DOMNode::SourceIndex DontDelete|ReadOnly 0212 @end 0213 */ 0214 0215 bool DOMNode::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 0216 { 0217 #ifdef KJS_VERBOSE 0218 qCDebug(KHTML_LOG) << "DOMNode::getOwnPropertySlot " << propertyName.qstring(); 0219 #endif 0220 return getStaticValueSlot<DOMNode, DOMObject>(exec, &DOMNodeTable, this, propertyName, slot); 0221 } 0222 0223 static khtml::RenderObject *handleBodyRootQuirk(const DOM::NodeImpl *node, khtml::RenderObject *rend, int token) 0224 { 0225 //This emulates the quirks of various height/width properties on the viewport and root. Note that it 0226 //is (mostly) IE-compatible in quirks, and mozilla-compatible in strict. 0227 if (!rend) { 0228 return nullptr; 0229 } 0230 0231 bool quirksMode = rend->style() && rend->style()->htmlHacks(); 0232 0233 //There are a couple quirks here. One is that in quirks mode body is always forwarded to root... 0234 //This is relevant for even the scrollTop/scrollLeft type properties. 0235 if (quirksMode && node->id() == ID_BODY) { 0236 while (rend->parent() && !rend->isRoot()) { 0237 rend = rend->parent(); 0238 } 0239 } 0240 0241 //Also, some properties of the root are really done in terms of the viewport. 0242 //These are {offset/client}{Height/Width}. The offset versions do it only in 0243 //quirks mode, the client always. 0244 if (!rend->isRoot()) { 0245 return rend; //Don't care about non-root things here! 0246 } 0247 bool needViewport = false; 0248 0249 switch (token) { 0250 case DOMNode::OffsetHeight: 0251 case DOMNode::OffsetWidth: 0252 needViewport = quirksMode; 0253 break; 0254 case DOMNode::ClientHeight: 0255 case DOMNode::ClientWidth: 0256 case DOMNode::ClientLeft: 0257 case DOMNode::ClientTop: 0258 needViewport = true; 0259 break; 0260 } 0261 0262 if (needViewport) { 0263 //Scan up to find the new target 0264 while (rend->parent()) { 0265 rend = rend->parent(); 0266 } 0267 } 0268 return rend; 0269 } 0270 0271 JSValue *DOMNode::getValueProperty(ExecState *exec, int token) const 0272 { 0273 NodeImpl &node = *impl(); 0274 switch (token) { 0275 case NodeName: 0276 return jsString(node.nodeName()); 0277 case NodeValue: 0278 return ::getStringOrNull(node.nodeValue()); // initially null, per domts/level1/core/hc_documentcreateelement.html 0279 case NodeType: 0280 return jsNumber((unsigned int)node.nodeType()); 0281 case ParentNode: 0282 return getDOMNode(exec, node.parentNode()); 0283 case ParentElement: // IE only apparently 0284 return getDOMNode(exec, node.parentNode()); 0285 case ChildNodes: 0286 return getDOMNodeList(exec, node.childNodes().get()); 0287 case FirstChild: 0288 return getDOMNode(exec, node.firstChild()); 0289 case LastChild: 0290 return getDOMNode(exec, node.lastChild()); 0291 case PreviousSibling: 0292 return getDOMNode(exec, node.previousSibling()); 0293 case NextSibling: 0294 return getDOMNode(exec, node.nextSibling()); 0295 case Attributes: { 0296 DOM::NamedNodeMapImpl *attrs = nullptr; 0297 if (node.isElementNode()) { 0298 DOM::ElementImpl &el = static_cast<DOM::ElementImpl &>(node); 0299 attrs = el.attributes(); 0300 } 0301 return getDOMNamedNodeMap(exec, attrs); 0302 } 0303 case NamespaceURI: 0304 return ::getStringOrNull(node.namespaceURI()); // Moz returns null if not set (dom/namespaces.html) 0305 case Prefix: 0306 return ::getStringOrNull(node.prefix()); // Moz returns null if not set (dom/namespaces.html) 0307 case LocalName: 0308 return ::getStringOrNull(node.localName()); // Moz returns null if not set (dom/namespaces.html) 0309 case OwnerDocument: 0310 return getDOMNode(exec, node.ownerDocument()); 0311 case TextContent: 0312 return ::getStringOrNull(node.textContent()); 0313 case OnAbort: 0314 return getListener(DOM::EventImpl::ABORT_EVENT); 0315 case OnBlur: 0316 return getListener(DOM::EventImpl::BLUR_EVENT); 0317 case OnChange: 0318 return getListener(DOM::EventImpl::CHANGE_EVENT); 0319 case OnClick: 0320 return getListener(DOM::EventImpl::KHTML_ECMA_CLICK_EVENT); 0321 case OnDblClick: 0322 return getListener(DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT); 0323 case OnDragDrop: 0324 return getListener(DOM::EventImpl::KHTML_DRAGDROP_EVENT); 0325 case OnError: 0326 return getListener(DOM::EventImpl::ERROR_EVENT); 0327 case OnFocus: 0328 return getListener(DOM::EventImpl::FOCUS_EVENT); 0329 case OnKeyDown: 0330 return getListener(DOM::EventImpl::KEYDOWN_EVENT); 0331 case OnKeyPress: 0332 return getListener(DOM::EventImpl::KEYPRESS_EVENT); 0333 case OnKeyUp: 0334 return getListener(DOM::EventImpl::KEYUP_EVENT); 0335 case OnLoad: 0336 return getListener(DOM::EventImpl::LOAD_EVENT); 0337 case OnMouseDown: 0338 return getListener(DOM::EventImpl::MOUSEDOWN_EVENT); 0339 case OnMouseMove: 0340 return getListener(DOM::EventImpl::MOUSEMOVE_EVENT); 0341 case OnMouseOut: 0342 return getListener(DOM::EventImpl::MOUSEOUT_EVENT); 0343 case OnMouseOver: 0344 return getListener(DOM::EventImpl::MOUSEOVER_EVENT); 0345 case OnMouseUp: 0346 return getListener(DOM::EventImpl::MOUSEUP_EVENT); 0347 case OnMove: 0348 return getListener(DOM::EventImpl::KHTML_MOVE_EVENT); 0349 case OnReset: 0350 return getListener(DOM::EventImpl::RESET_EVENT); 0351 case OnResize: 0352 return getListener(DOM::EventImpl::RESIZE_EVENT); 0353 case OnScroll: 0354 return getListener(DOM::EventImpl::SCROLL_EVENT); 0355 case OnSelect: 0356 return getListener(DOM::EventImpl::SELECT_EVENT); 0357 case OnSubmit: 0358 return getListener(DOM::EventImpl::SUBMIT_EVENT); 0359 case OnUnload: 0360 return getListener(DOM::EventImpl::UNLOAD_EVENT); 0361 case SourceIndex: { 0362 // Retrieves the ordinal position of the object, in source order, as the object 0363 // appears in the document's all collection 0364 // i.e. document.all[n.sourceIndex] == n 0365 DOM::DocumentImpl *doc = node.document(); 0366 if (doc->isHTMLDocument()) { 0367 HTMLCollectionImpl all(doc, HTMLCollectionImpl::DOC_ALL); 0368 unsigned long i = 0; 0369 for (DOM::NodeImpl *n = all.firstItem(); n; n = all.nextItem()) { 0370 if (n == impl()) { 0371 return jsNumber(i); 0372 } 0373 ++i; 0374 } 0375 } 0376 return jsUndefined(); 0377 } 0378 default: 0379 // no DOM standard, found in IE only 0380 0381 // Make sure our layout is up to date before we allow a query on these attributes. 0382 DOM::DocumentImpl *docimpl = node.document(); 0383 if (docimpl) { 0384 docimpl->updateLayout(); 0385 } 0386 0387 khtml::RenderObject *rend = node.renderer(); 0388 0389 //In quirks mode, may need to forward if to body. 0390 rend = handleBodyRootQuirk(impl(), rend, token); 0391 0392 switch (token) { 0393 case OffsetLeft: 0394 return rend ? jsNumber(rend->offsetLeft()) : jsNumber(0); 0395 case OffsetTop: 0396 return rend ? jsNumber(rend->offsetTop()) : jsNumber(0); 0397 case OffsetWidth: 0398 return rend ? jsNumber(rend->offsetWidth()) : jsNumber(0); 0399 case OffsetHeight: 0400 return rend ? jsNumber(rend->offsetHeight()) : jsNumber(0); 0401 case OffsetParent: { 0402 khtml::RenderObject *par = rend ? rend->offsetParent() : nullptr; 0403 return getDOMNode(exec, par ? par->element() : nullptr); 0404 } 0405 case ClientWidth: 0406 return rend ? jsNumber(rend->clientWidth()) : jsNumber(0); 0407 case ClientHeight: 0408 return rend ? jsNumber(rend->clientHeight()) : jsNumber(0); 0409 case ClientLeft: 0410 return rend ? jsNumber(rend->clientLeft()) : jsNumber(0); 0411 case ClientTop: 0412 return rend ? jsNumber(rend->clientTop()) : jsNumber(0); 0413 case ScrollWidth: 0414 return rend ? jsNumber(rend->scrollWidth()) : jsNumber(0); 0415 case ScrollHeight: 0416 return rend ? jsNumber(rend->scrollHeight()) : jsNumber(0); 0417 case ScrollLeft: 0418 if (rend && rend->layer()) { 0419 if (rend->isRoot() && !rend->hasOverflowClip()) { 0420 return jsNumber(node.document()->view() ? node.document()->view()->contentsX() : 0); 0421 } 0422 return jsNumber(rend->hasOverflowClip() ? rend->layer()->scrollXOffset() : 0); 0423 } 0424 return jsNumber(0); 0425 case ScrollTop: 0426 if (rend && rend->layer()) { 0427 if (rend->isRoot() && !rend->hasOverflowClip()) { 0428 return jsNumber(node.document()->view() ? node.document()->view()->contentsY() : 0); 0429 } 0430 return jsNumber(rend->hasOverflowClip() ? rend->layer()->scrollYOffset() : 0); 0431 } 0432 return jsNumber(0); 0433 default: 0434 // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMNode::getValueProperty : " << token; 0435 break; 0436 } 0437 } 0438 return jsUndefined(); 0439 } 0440 0441 void DOMNode::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) 0442 { 0443 #ifdef KJS_VERBOSE 0444 qCDebug(KHTML_LOG) << "DOMNode::tryPut " << propertyName.qstring(); 0445 #endif 0446 lookupPut<DOMNode, DOMObject>(exec, propertyName, value, attr, 0447 &DOMNodeTable, this); 0448 } 0449 0450 void DOMNode::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/) 0451 { 0452 DOMExceptionTranslator exception(exec); 0453 NodeImpl &node = *impl(); 0454 0455 switch (token) { 0456 case NodeValue: 0457 node.setNodeValue(value->toString(exec).domString(), exception); 0458 break; 0459 case Prefix: 0460 node.setPrefix(value->toString(exec).domString(), exception); 0461 break; 0462 case TextContent: 0463 node.setTextContent(valueToStringWithNullCheck(exec, value), exception); 0464 break; 0465 case OnAbort: 0466 setListener(exec, DOM::EventImpl::ABORT_EVENT, value); 0467 break; 0468 case OnBlur: 0469 setListener(exec, DOM::EventImpl::BLUR_EVENT, value); 0470 break; 0471 case OnChange: 0472 setListener(exec, DOM::EventImpl::CHANGE_EVENT, value); 0473 break; 0474 case OnClick: 0475 setListener(exec, DOM::EventImpl::KHTML_ECMA_CLICK_EVENT, value); 0476 break; 0477 case OnDblClick: 0478 setListener(exec, DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT, value); 0479 break; 0480 case OnDragDrop: 0481 setListener(exec, DOM::EventImpl::KHTML_DRAGDROP_EVENT, value); 0482 break; 0483 case OnError: 0484 setListener(exec, DOM::EventImpl::ERROR_EVENT, value); 0485 break; 0486 case OnFocus: 0487 setListener(exec, DOM::EventImpl::FOCUS_EVENT, value); 0488 break; 0489 case OnKeyDown: 0490 setListener(exec, DOM::EventImpl::KEYDOWN_EVENT, value); 0491 break; 0492 case OnKeyPress: 0493 setListener(exec, DOM::EventImpl::KEYPRESS_EVENT, value); 0494 break; 0495 case OnKeyUp: 0496 setListener(exec, DOM::EventImpl::KEYUP_EVENT, value); 0497 break; 0498 case OnLoad: 0499 setListener(exec, DOM::EventImpl::LOAD_EVENT, value); 0500 break; 0501 case OnMouseDown: 0502 setListener(exec, DOM::EventImpl::MOUSEDOWN_EVENT, value); 0503 break; 0504 case OnMouseMove: 0505 setListener(exec, DOM::EventImpl::MOUSEMOVE_EVENT, value); 0506 break; 0507 case OnMouseOut: 0508 setListener(exec, DOM::EventImpl::MOUSEOUT_EVENT, value); 0509 break; 0510 case OnMouseOver: 0511 setListener(exec, DOM::EventImpl::MOUSEOVER_EVENT, value); 0512 break; 0513 case OnMouseUp: 0514 setListener(exec, DOM::EventImpl::MOUSEUP_EVENT, value); 0515 break; 0516 case OnMove: 0517 setListener(exec, DOM::EventImpl::KHTML_MOVE_EVENT, value); 0518 break; 0519 case OnReset: 0520 setListener(exec, DOM::EventImpl::RESET_EVENT, value); 0521 break; 0522 case OnResize: 0523 setListener(exec, DOM::EventImpl::RESIZE_EVENT, value); 0524 break; 0525 case OnScroll: 0526 setListener(exec, DOM::EventImpl::SCROLL_EVENT, value); 0527 break; 0528 case OnSelect: 0529 setListener(exec, DOM::EventImpl::SELECT_EVENT, value); 0530 break; 0531 case OnSubmit: 0532 setListener(exec, DOM::EventImpl::SUBMIT_EVENT, value); 0533 break; 0534 case OnUnload: 0535 setListener(exec, DOM::EventImpl::UNLOAD_EVENT, value); 0536 break; 0537 default: 0538 // Make sure our layout is up to date 0539 DOM::DocumentImpl *docimpl = node.document(); 0540 if (docimpl) { 0541 docimpl->updateLayout(); 0542 } 0543 0544 khtml::RenderObject *rend = node.renderer(); 0545 0546 //In quirks mode, may need to forward. 0547 rend = handleBodyRootQuirk(impl(), rend, token); 0548 0549 switch (token) { 0550 case ScrollLeft: 0551 if (rend && rend->layer()) { 0552 if (rend->hasOverflowClip()) { 0553 rend->layer()->scrollToXOffset(value->toInt32(exec)); 0554 } else if (rend->isRoot()) { 0555 KHTMLView *sview = node.document()->view(); 0556 if (sview) { 0557 sview->setContentsPos(value->toInt32(exec), sview->contentsY()); 0558 } 0559 } 0560 } 0561 break; 0562 case ScrollTop: 0563 if (rend && rend->layer()) { 0564 if (rend->hasOverflowClip()) { 0565 rend->layer()->scrollToYOffset(value->toInt32(exec)); 0566 } else if (rend->isRoot()) { 0567 KHTMLView *sview = node.document()->view(); 0568 if (sview) { 0569 sview->setContentsPos(sview->contentsX(), value->toInt32(exec)); 0570 } 0571 } 0572 } 0573 break; 0574 default: 0575 // qCDebug(KHTML_LOG) << "WARNING: DOMNode::putValueProperty unhandled token " << token; 0576 break; 0577 } 0578 } 0579 } 0580 0581 JSValue *DOMNode::toPrimitive(ExecState *exec, JSType /*preferred*/) const 0582 { 0583 if (m_impl.isNull()) { 0584 return jsNull(); 0585 } 0586 0587 return jsString(toString(exec)); 0588 } 0589 0590 UString DOMNode::toString(ExecState *) const 0591 { 0592 if (m_impl.isNull()) { 0593 return "null"; 0594 } 0595 return "[object " + className() + "]"; 0596 } 0597 0598 void DOMNode::setListener(ExecState *exec, int eventId, JSValue *func) const 0599 { 0600 m_impl->setHTMLEventListener(eventId, Window::retrieveActive(exec)->getJSEventListener(func, true)); 0601 } 0602 0603 JSValue *DOMNode::getListener(int eventId) const 0604 { 0605 DOM::EventListener *listener = m_impl->getHTMLEventListener(eventId); 0606 JSEventListener *jsListener = static_cast<JSEventListener *>(listener); 0607 if (jsListener && jsListener->listenerObj()) { 0608 return jsListener->listenerObj(); 0609 } else { 0610 return jsNull(); 0611 } 0612 } 0613 0614 void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const 0615 { 0616 } 0617 0618 JSValue *DOMNodeProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 0619 { 0620 KJS_CHECK_THIS(DOMNode, thisObj); 0621 DOMExceptionTranslator exception(exec); 0622 DOM::NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl(); 0623 switch (id) { 0624 case DOMNode::HasAttributes: 0625 return jsBoolean(node.hasAttributes()); 0626 case DOMNode::HasChildNodes: 0627 return jsBoolean(node.hasChildNodes()); 0628 case DOMNode::CloneNode: { 0629 RefPtr<NodeImpl> clone = node.cloneNode(args[0]->toBoolean(exec)); 0630 return getDOMNode(exec, clone.get()); 0631 } 0632 case DOMNode::Normalize: 0633 node.normalize(); 0634 return jsUndefined(); 0635 case DOMNode::IsSupported: 0636 return jsBoolean(node.isSupported(args[0]->toString(exec).domString(), args[1]->toString(exec).domString())); 0637 case DOMNode::AddEventListener: { 0638 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); 0639 EventName id = EventName::fromString(args[0]->toString(exec).domString()); 0640 node.addEventListener(id, listener, args[2]->toBoolean(exec)); 0641 return jsUndefined(); 0642 } 0643 case DOMNode::RemoveEventListener: { 0644 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); 0645 EventName id = EventName::fromString(args[0]->toString(exec).domString()); 0646 node.removeEventListener(id, listener, args[2]->toBoolean(exec)); 0647 return jsUndefined(); 0648 } 0649 case DOMNode::DispatchEvent: { 0650 SharedPtr<DOM::EventImpl> evt = toEvent(args[0]); 0651 if (!evt) { 0652 setDOMException(exec, DOMException::NOT_FOUND_ERR); 0653 return jsUndefined(); 0654 } 0655 node.dispatchEvent(evt.get(), exception); 0656 return jsBoolean(!evt->defaultPrevented()); 0657 } 0658 case DOMNode::AppendChild: 0659 return getDOMNode(exec, node.appendChild(toNode(args[0]), exception)); 0660 case DOMNode::RemoveChild: { 0661 SharedPtr<DOM::NodeImpl> oldKid = toNode(args[0]); 0662 node.removeChild(oldKid.get(), exception); 0663 return getDOMNode(exec, oldKid.get()); 0664 } 0665 case DOMNode::InsertBefore: 0666 return getDOMNode(exec, node.insertBefore(toNode(args[0]), toNode(args[1]), exception)); 0667 case DOMNode::ReplaceChild: { 0668 SharedPtr<DOM::NodeImpl> oldKid = toNode(args[1]); 0669 node.replaceChild(toNode(args[0]), oldKid.get(), exception); 0670 return getDOMNode(exec, oldKid.get()); 0671 } 0672 case DOMNode::Contains: { 0673 DOM::NodeImpl *other = toNode(args[0]); 0674 if (other && other->isElementNode()) { 0675 return jsBoolean(other->isAncestor(&node)); 0676 } 0677 setDOMException(exec, DOMException::TYPE_MISMATCH_ERR); // ### a guess 0678 return jsUndefined(); 0679 } 0680 case DOMNode::InsertAdjacentHTML: { 0681 // see http://www.faqts.com/knowledge_base/view.phtml/aid/5756 0682 // and http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/insertAdjacentHTML.asp 0683 SharedPtr<DOM::RangeImpl> range = node.document()->createRange(); 0684 0685 range->setStartBefore(&node, exception); 0686 if (exception.triggered()) { 0687 return jsUndefined(); 0688 } 0689 0690 SharedPtr<DOM::DocumentFragmentImpl> docFrag = 0691 static_cast<DOM::DocumentFragmentImpl *>(range->createContextualFragment(args[1]->toString(exec).domString(), exception).handle()); 0692 if (exception.triggered()) { 0693 return jsUndefined(); 0694 } 0695 0696 DOMString where = args[0]->toString(exec).domString().lower(); 0697 0698 if (where == "beforebegin") { 0699 node.parentNode()->insertBefore(docFrag.get(), &node, exception); 0700 } else if (where == "afterbegin") { 0701 node.insertBefore(docFrag.get(), node.firstChild(), exception); 0702 } else if (where == "beforeend") { 0703 return getDOMNode(exec, node.appendChild(docFrag.get(), exception)); 0704 } else if (where == "afterend") { 0705 if (node.nextSibling()) { 0706 node.parentNode()->insertBefore(docFrag.get(), node.nextSibling(), exception); 0707 } else { 0708 node.parentNode()->appendChild(docFrag.get(), exception); 0709 } 0710 } 0711 0712 return jsUndefined(); 0713 } 0714 case DOMNode::CompareDocumentPosition: { 0715 DOM::NodeImpl *other = toNode(args[0]); 0716 if (!other) { 0717 setDOMException(exec, DOMException::TYPE_MISMATCH_ERR); 0718 } else { 0719 return jsNumber(node.compareDocumentPosition(other)); 0720 } 0721 } 0722 } 0723 0724 return jsUndefined(); 0725 } 0726 0727 // ------------------------------------------------------------------------- 0728 0729 /* 0730 @begin DOMNodeListProtoTable 2 0731 item DOMNodeList::Item DontDelete|Function 1 0732 # IE extension (IE treats DOMNodeList like an HTMLCollection) 0733 namedItem DOMNodeList::NamedItem DontDelete|Function 1 0734 @end 0735 */ 0736 KJS_DEFINE_PROTOTYPE(DOMNodeListProto) 0737 KJS_IMPLEMENT_PROTOFUNC(DOMNodeListProtoFunc) 0738 KJS_IMPLEMENT_PROTOTYPE("DOMNodeList", DOMNodeListProto, DOMNodeListProtoFunc, ObjectPrototype) 0739 0740 IMPLEMENT_PSEUDO_CONSTRUCTOR(NodeListPseudoCtor, "NodeList", DOMNodeListProto) 0741 0742 const ClassInfo DOMNodeList::info = { "NodeList", nullptr, nullptr, nullptr }; 0743 0744 DOMNodeList::DOMNodeList(ExecState *exec, DOM::NodeListImpl *l) 0745 : DOMObject(DOMNodeListProto::self(exec)), m_impl(l) { } 0746 0747 DOMNodeList::~DOMNodeList() 0748 { 0749 ScriptInterpreter::forgetDOMObject(m_impl.get()); 0750 } 0751 0752 JSValue *DOMNodeList::indexGetter(ExecState *exec, unsigned index) 0753 { 0754 return getDOMNode(exec, m_impl->item(index)); 0755 } 0756 0757 JSValue *DOMNodeList::nameGetter(ExecState *exec, JSObject *, const Identifier &name, const PropertySlot &slot) 0758 { 0759 DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase()); 0760 return getDOMNode(exec, thisObj->getByName(name)); 0761 } 0762 0763 JSValue *DOMNodeList::lengthGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &slot) 0764 { 0765 DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase()); 0766 return jsNumber(thisObj->m_impl->length()); 0767 } 0768 0769 DOM::NodeImpl *DOMNodeList::getByName(const Identifier &name) 0770 { 0771 //### M.O.: I bet IE checks name only for some tags. 0772 DOMString domName = name.domString(); 0773 unsigned long l = m_impl->length(); 0774 for (unsigned long i = 0; i < l; i++) { 0775 DOM::NodeImpl *n = m_impl->item(i); 0776 if (n->isElementNode()) { 0777 DOM::ElementImpl *e = static_cast<DOM::ElementImpl *>(n); 0778 if (e->getAttribute(ATTR_ID) == domName || e->getAttribute(ATTR_NAME) == domName) { 0779 return n; 0780 } 0781 } 0782 } 0783 return nullptr; 0784 } 0785 0786 bool DOMNodeList::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 0787 { 0788 if (propertyName == exec->propertyNames().length) { 0789 slot.setCustom(this, lengthGetter); 0790 return true; 0791 } 0792 0793 //### this could benefit from further nodelist/collection consolidation, 0794 //including moving nameditem down to nodelists. 0795 0796 // Look in the prototype (for functions) before assuming it's an item's name 0797 JSObject *proto = prototype()->getObject(); 0798 if (proto && proto->hasProperty(exec, propertyName)) { 0799 return false; 0800 } 0801 0802 //May be it's an index? 0803 if (getIndexSlot(this, *m_impl, propertyName, slot)) { 0804 return true; 0805 } 0806 0807 //May be it's a name -- check by ID 0808 //Check by id 0809 if (getByName(propertyName)) { 0810 slot.setCustom(this, nameGetter); 0811 return true; 0812 } 0813 0814 return DOMObject::getOwnPropertySlot(exec, propertyName, slot); 0815 } 0816 0817 void DOMNodeList::getOwnPropertyNames(ExecState *exec, PropertyNameArray &propertyNames, PropertyMap::PropertyMode mode) 0818 { 0819 for (unsigned i = 0; i < m_impl->length(); ++i) { 0820 propertyNames.add(Identifier::from(i)); 0821 } 0822 0823 propertyNames.add(exec->propertyNames().length); 0824 0825 JSObject::getOwnPropertyNames(exec, propertyNames, mode); 0826 } 0827 0828 // Need to support both get and call, so that list[0] and list(0) work. 0829 JSValue *DOMNodeList::callAsFunction(ExecState *exec, JSObject *, const List &args) 0830 { 0831 // Do not use thisObj here. See HTMLCollection. 0832 UString s = args[0]->toString(exec); 0833 0834 // index-based lookup? 0835 bool ok; 0836 unsigned int u = s.qstring().toULong(&ok); 0837 if (ok) { 0838 return getDOMNode(exec, m_impl->item(u)); 0839 } 0840 0841 // try lookup by name 0842 // ### NodeList::namedItem() would be cool to have 0843 // ### do we need to support the same two arg overload as in HTMLCollection? 0844 JSValue *result = get(exec, Identifier(s)); 0845 0846 if (result) { 0847 return result; 0848 } 0849 0850 return jsUndefined(); 0851 } 0852 0853 JSValue *DOMNodeListProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 0854 { 0855 KJS_CHECK_THIS(KJS::DOMNodeList, thisObj); 0856 DOMNodeList *jsList = static_cast<DOMNodeList *>(thisObj); 0857 DOM::NodeListImpl &list = *jsList->impl(); 0858 switch (id) { 0859 case KJS::DOMNodeList::Item: 0860 return getDOMNode(exec, list.item(args[0]->toInt32(exec))); 0861 case KJS::DOMNodeList::NamedItem: 0862 return getDOMNode(exec, jsList->getByName(Identifier(args[0]->toString(exec)))); 0863 default: 0864 return jsUndefined(); 0865 } 0866 } 0867 0868 // ------------------------------------------------------------------------- 0869 0870 //### FIXME: link to the node prototype. 0871 const ClassInfo DOMAttr::info = { "Attr", &DOMNode::info, &DOMAttrTable, nullptr }; 0872 0873 /* Source for DOMAttrTable. 0874 @begin DOMAttrTable 5 0875 name DOMAttr::Name DontDelete|ReadOnly 0876 specified DOMAttr::Specified DontDelete|ReadOnly 0877 value DOMAttr::ValueProperty DontDelete 0878 ownerElement DOMAttr::OwnerElement DontDelete|ReadOnly 0879 @end 0880 */ 0881 bool DOMAttr::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 0882 { 0883 #ifdef KJS_VERBOSE 0884 qCDebug(KHTML_LOG) << "DOMAttr::tryGet " << propertyName.qstring(); 0885 #endif 0886 return getStaticValueSlot<DOMAttr, DOMNode>(exec, &DOMAttrTable, this, propertyName, slot); 0887 } 0888 0889 JSValue *DOMAttr::getValueProperty(ExecState *exec, int token) const 0890 { 0891 AttrImpl *attr = static_cast<AttrImpl *>(impl()); 0892 switch (token) { 0893 case Name: 0894 return jsString(attr->name()); 0895 case Specified: 0896 return jsBoolean(attr->specified()); 0897 case ValueProperty: 0898 return jsString(attr->nodeValue()); 0899 case OwnerElement: // DOM2 0900 return getDOMNode(exec, attr->ownerElement()); 0901 } 0902 return jsNull(); // not reached 0903 } 0904 0905 void DOMAttr::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) 0906 { 0907 #ifdef KJS_VERBOSE 0908 qCDebug(KHTML_LOG) << "DOMAttr::tryPut " << propertyName.qstring(); 0909 #endif 0910 lookupPut<DOMAttr, DOMNode>(exec, propertyName, value, attr, 0911 &DOMAttrTable, this); 0912 } 0913 0914 void DOMAttr::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/) 0915 { 0916 DOMExceptionTranslator exception(exec); 0917 switch (token) { 0918 case ValueProperty: 0919 static_cast<AttrImpl *>(impl())->setValue(value->toString(exec).domString(), exception); 0920 return; 0921 default: 0922 qCWarning(KHTML_LOG) << "DOMAttr::putValueProperty unhandled token " << token; 0923 } 0924 } 0925 0926 AttrImpl *toAttr(JSValue *val) 0927 { 0928 if (!val || !val->isObject(&DOMAttr::info)) { 0929 return nullptr; 0930 } 0931 return static_cast<AttrImpl *>(static_cast<DOMNode *>(val)->impl()); 0932 } 0933 0934 // ------------------------------------------------------------------------- 0935 0936 /* Source for DOMDocumentProtoTable. 0937 @begin DOMDocumentProtoTable 23 0938 createElement DOMDocument::CreateElement DontDelete|Function 1 0939 createDocumentFragment DOMDocument::CreateDocumentFragment DontDelete|Function 1 0940 createTextNode DOMDocument::CreateTextNode DontDelete|Function 1 0941 createComment DOMDocument::CreateComment DontDelete|Function 1 0942 createCDATASection DOMDocument::CreateCDATASection DontDelete|Function 1 0943 createProcessingInstruction DOMDocument::CreateProcessingInstruction DontDelete|Function 1 0944 createAttribute DOMDocument::CreateAttribute DontDelete|Function 1 0945 createEntityReference DOMDocument::CreateEntityReference DontDelete|Function 1 0946 getElementsByTagName DOMDocument::GetElementsByTagName DontDelete|Function 1 0947 importNode DOMDocument::ImportNode DontDelete|Function 2 0948 createElementNS DOMDocument::CreateElementNS DontDelete|Function 2 0949 createAttributeNS DOMDocument::CreateAttributeNS DontDelete|Function 2 0950 getElementsByTagNameNS DOMDocument::GetElementsByTagNameNS DontDelete|Function 2 0951 getElementById DOMDocument::GetElementById DontDelete|Function 1 0952 createRange DOMDocument::CreateRange DontDelete|Function 0 0953 createNodeIterator DOMDocument::CreateNodeIterator DontDelete|Function 3 0954 createTreeWalker DOMDocument::CreateTreeWalker DontDelete|Function 4 0955 createEvent DOMDocument::CreateEvent DontDelete|Function 1 0956 getOverrideStyle DOMDocument::GetOverrideStyle DontDelete|Function 2 0957 abort DOMDocument::Abort DontDelete|Function 0 0958 load DOMDocument::Load DontDelete|Function 1 0959 loadXML DOMDocument::LoadXML DontDelete|Function 2 0960 execCommand DOMDocument::ExecCommand DontDelete|Function 3 0961 queryCommandEnabled DOMDocument::QueryCommandEnabled DontDelete|Function 1 0962 queryCommandIndeterm DOMDocument::QueryCommandIndeterm DontDelete|Function 1 0963 queryCommandState DOMDocument::QueryCommandState DontDelete|Function 1 0964 queryCommandSupported DOMDocument::QueryCommandSupported DontDelete|Function 1 0965 queryCommandValue DOMDocument::QueryCommandValue DontDelete|Function 1 0966 getElementsByClassName DOMDocument::GetElementsByClassName DontDelete|Function 1 0967 querySelector DOMDocument::QuerySelector DontDelete|Function 1 0968 querySelectorAll DOMDocument::QuerySelectorAll DontDelete|Function 1 0969 createExpression DOMDocument::CreateExpression DontDelete|Function 2 0970 createNSResolver DOMDocument::CreateNSResolver DontDelete|Function 1 0971 evaluate DOMDocument::Evaluate DontDelete|Function 4 0972 @end 0973 */ 0974 0975 KJS_IMPLEMENT_PROTOFUNC(DOMDocumentProtoFunc) 0976 KJS_IMPLEMENT_PROTOTYPE("DOMDocument", DOMDocumentProto, DOMDocumentProtoFunc, DOMNodeProto) 0977 0978 IMPLEMENT_PSEUDO_CONSTRUCTOR(DocumentPseudoCtor, "Document", DOMDocumentProto) 0979 0980 const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, nullptr }; 0981 0982 /* Source for DOMDocumentTable. 0983 @begin DOMDocumentTable 4 0984 doctype DOMDocument::DocType DontDelete|ReadOnly 0985 implementation DOMDocument::Implementation DontDelete|ReadOnly 0986 characterSet DOMDocument::CharacterSet DontDelete|ReadOnly 0987 documentElement DOMDocument::DocumentElement DontDelete|ReadOnly 0988 styleSheets DOMDocument::StyleSheets DontDelete|ReadOnly 0989 preferredStylesheetSet DOMDocument::PreferredStylesheetSet DontDelete|ReadOnly 0990 selectedStylesheetSet DOMDocument::SelectedStylesheetSet DontDelete 0991 readyState DOMDocument::ReadyState DontDelete|ReadOnly 0992 defaultView DOMDocument::DefaultView DontDelete|ReadOnly 0993 async DOMDocument::Async DontDelete 0994 title DOMDocument::Title DontDelete 0995 @end 0996 */ 0997 0998 DOMDocument::DOMDocument(ExecState *exec, DOM::DocumentImpl *d) 0999 : DOMNode(exec, d) 1000 { 1001 setPrototype(DOMDocumentProto::self(exec)); 1002 } 1003 1004 DOMDocument::DOMDocument(JSObject *proto, DOM::DocumentImpl *d) 1005 : DOMNode(proto, d) 1006 {} 1007 1008 bool DOMDocument::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 1009 { 1010 #ifdef KJS_VERBOSE 1011 qCDebug(KHTML_LOG) << "DOMDocument::tryGet " << propertyName.qstring(); 1012 #endif 1013 return getStaticValueSlot<DOMDocument, DOMNode>( 1014 exec, &DOMDocumentTable, this, propertyName, slot); 1015 } 1016 1017 JSValue *DOMDocument::getValueProperty(ExecState *exec, int token) const 1018 { 1019 DOM::DocumentImpl &doc = *static_cast<DOM::DocumentImpl *>(m_impl.get()); 1020 1021 switch (token) { 1022 case DocType: 1023 return getDOMNode(exec, doc.doctype()); 1024 case Implementation: 1025 return getDOMDOMImplementation(exec, doc.implementation()); 1026 case DocumentElement: 1027 return getDOMNode(exec, doc.documentElement()); 1028 case CharacterSet: { 1029 if (doc.part()) { 1030 return jsString(doc.part()->encoding()); 1031 } else { 1032 return jsUndefined(); 1033 } 1034 } 1035 case StyleSheets: 1036 //qCDebug(KHTML_LOG) << "DOMDocument::StyleSheets, returning " << doc.styleSheets().length() << " stylesheets"; 1037 return getDOMStyleSheetList(exec, doc.styleSheets(), &doc); 1038 case DOMDocument::DefaultView: { // DOM2 1039 KHTMLPart *part = doc.part(); 1040 if (part) { 1041 return Window::retrieve(part); 1042 } 1043 return getDOMAbstractView(exec, doc.defaultView()); 1044 } 1045 case PreferredStylesheetSet: 1046 return jsString(doc.preferredStylesheetSet()); 1047 case SelectedStylesheetSet: 1048 return jsString(doc.selectedStylesheetSet()); 1049 case ReadyState: { 1050 if (KHTMLPart *part = doc.part()) { 1051 if (part->d->m_bComplete) { 1052 return jsString("complete"); 1053 } 1054 if (doc.parsing()) { 1055 return jsString("loading"); 1056 } 1057 return jsString("loaded"); 1058 // What does the interactive value mean ? 1059 // Missing support for "uninitialized" 1060 } 1061 return jsUndefined(); 1062 } 1063 case Async: 1064 return jsBoolean(doc.async()); 1065 case Title: 1066 return jsString(doc.title()); 1067 default: 1068 // qCDebug(KHTML_LOG) << "WARNING: DOMDocument::getValueProperty unhandled token " << token; 1069 return jsNull(); 1070 } 1071 } 1072 1073 void DOMDocument::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) 1074 { 1075 #ifdef KJS_VERBOSE 1076 qCDebug(KHTML_LOG) << "DOMDocument::tryPut " << propertyName.qstring(); 1077 #endif 1078 lookupPut<DOMDocument, DOMNode>(exec, propertyName, value, attr, &DOMDocumentTable, this); 1079 } 1080 1081 void DOMDocument::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/) 1082 { 1083 DOM::DocumentImpl &doc = *static_cast<DOM::DocumentImpl *>(impl()); 1084 switch (token) { 1085 case SelectedStylesheetSet: { 1086 doc.setSelectedStylesheetSet(value->toString(exec).domString()); 1087 break; 1088 } 1089 case Async: { 1090 doc.setAsync(value->toBoolean(exec)); 1091 break; 1092 } 1093 case Title: { 1094 DOM::DOMString val = value->toString(exec).domString(); 1095 if (doc.title() != val) { 1096 doc.setTitle(val); 1097 } 1098 break; 1099 } 1100 } 1101 } 1102 1103 JSValue *DOMDocumentProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 1104 { 1105 KJS_CHECK_THIS(KJS::DOMDocument, thisObj); 1106 DOMExceptionTranslator exception(exec); 1107 DOM::NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl(); 1108 DOM::DocumentImpl &doc = static_cast<DOM::DocumentImpl &>(node); 1109 1110 KJS::UString str = args[0]->toString(exec); 1111 1112 // we can do it fast, without copying the data 1113 if (id == DOMDocument::GetElementById) { 1114 #ifdef KJS_VERBOSE 1115 qCDebug(KHTML_LOG) << "DOMDocument::GetElementById looking for " << args[0]->toString(exec).qstring(); 1116 #endif 1117 // create DOMStringImpl without copying 1118 DOMStringImpl shallowCopy(DOMStringImpl::ShallowCopy, (QChar *)str.data(), str.size()); 1119 return getDOMNode(exec, doc.getElementById(DOMString(&shallowCopy))); 1120 } 1121 1122 DOM::DOMString s = str.domString(); 1123 1124 switch (id) { 1125 case DOMDocument::CreateElement: 1126 return getDOMNode(exec, doc.createElement(s, exception)); 1127 case DOMDocument::CreateDocumentFragment: 1128 return getDOMNode(exec, doc.createDocumentFragment()); 1129 case DOMDocument::CreateTextNode: 1130 return getDOMNode(exec, doc.createTextNode(s.implementation())); 1131 case DOMDocument::CreateComment: 1132 return getDOMNode(exec, doc.createComment(s.implementation())); 1133 case DOMDocument::CreateCDATASection: 1134 return getDOMNode(exec, doc.createCDATASection(s.implementation(), exception)); 1135 case DOMDocument::CreateProcessingInstruction: 1136 return getDOMNode(exec, doc.createProcessingInstruction(args[0]->toString(exec).domString(), 1137 args[1]->toString(exec).domString().implementation())); 1138 case DOMDocument::CreateAttribute: 1139 return getDOMNode(exec, doc.createAttribute(s, exception)); 1140 case DOMDocument::CreateEntityReference: 1141 return getDOMNode(exec, doc.createEntityReference(args[0]->toString(exec).domString(), exception)); 1142 case DOMDocument::GetElementsByTagName: 1143 return getDOMNodeList(exec, doc.getElementsByTagName(s)); 1144 case DOMDocument::ImportNode: // DOM2 1145 return getDOMNode(exec, doc.importNode(toNode(args[0]), args[1]->toBoolean(exec), exception)); 1146 case DOMDocument::CreateElementNS: // DOM2 1147 return getDOMNode(exec, doc.createElementNS(valueToStringWithNullCheck(exec, args[0]), args[1]->toString(exec).domString(), exception)); 1148 case DOMDocument::CreateAttributeNS: // DOM2 1149 return getDOMNode(exec, doc.createAttributeNS(valueToStringWithNullCheck(exec, args[0]), args[1]->toString(exec).domString(), exception)); 1150 case DOMDocument::GetElementsByTagNameNS: // DOM2 1151 return getDOMNodeList(exec, doc.getElementsByTagNameNS(args[0]->toString(exec).domString(), 1152 args[1]->toString(exec).domString())); 1153 case DOMDocument::CreateRange: 1154 return getDOMRange(exec, doc.createRange()); 1155 case DOMDocument::CreateNodeIterator: 1156 return getDOMNodeIterator(exec, 1157 doc.createNodeIterator(toNode(args[0]), 1158 (long unsigned int)(args[1]->toNumber(exec)), 1159 toNodeFilter(args[2]), args[3]->toBoolean(exec), exception)); 1160 case DOMDocument::CreateTreeWalker: 1161 return getDOMTreeWalker(exec, doc.createTreeWalker(toNode(args[0]), (long unsigned int)(args[1]->toNumber(exec)), 1162 toNodeFilter(args[2]), args[3]->toBoolean(exec), exception)); 1163 case DOMDocument::CreateEvent: 1164 return getDOMEvent(exec, doc.createEvent(s, exception)); 1165 case DOMDocument::GetOverrideStyle: { 1166 DOM::NodeImpl *arg0 = toNode(args[0]); 1167 if (!arg0 || !arg0->isElementNode()) { 1168 return jsUndefined(); // throw exception? 1169 } else { 1170 return getDOMCSSStyleDeclaration(exec, doc.getOverrideStyle(static_cast<DOM::ElementImpl *>(arg0), args[1]->toString(exec).domString().implementation())); 1171 } 1172 } 1173 case DOMDocument::Abort: 1174 doc.abort(); 1175 break; 1176 case DOMDocument::Load: { 1177 Window *active = Window::retrieveActive(exec); 1178 // Complete the URL using the "active part" (running interpreter). We do this for the security 1179 // check and to make sure we load exactly the same url as we have verified to be safe 1180 KHTMLPart *khtmlpart = qobject_cast<KHTMLPart *>(active->part()); 1181 if (khtmlpart) { 1182 // Security: only allow documents to be loaded from the same host 1183 QString dstUrl = khtmlpart->htmlDocument().completeURL(s).string(); 1184 KParts::ReadOnlyPart *part = static_cast<KJS::ScriptInterpreter *>(exec->dynamicInterpreter())->part(); 1185 if (part->url().host() == QUrl(dstUrl).host()) { 1186 // qCDebug(KHTML_LOG) << "JavaScript: access granted for document.load() of " << dstUrl; 1187 doc.load(dstUrl); 1188 } else { 1189 // qCDebug(KHTML_LOG) << "JavaScript: access denied for document.load() of " << dstUrl; 1190 } 1191 } 1192 break; 1193 } 1194 case DOMDocument::LoadXML: 1195 doc.loadXML(s); 1196 break; 1197 case DOMDocument::ExecCommand: { 1198 return jsBoolean(doc.execCommand(args[0]->toString(exec).domString(), args[1]->toBoolean(exec), args[2]->toString(exec).domString())); 1199 } 1200 case DOMDocument::QueryCommandEnabled: { 1201 return jsBoolean(doc.queryCommandEnabled(args[0]->toString(exec).domString())); 1202 } 1203 case DOMDocument::QueryCommandIndeterm: { 1204 return jsBoolean(doc.queryCommandIndeterm(args[0]->toString(exec).domString())); 1205 } 1206 case DOMDocument::QueryCommandState: { 1207 return jsBoolean(doc.queryCommandState(args[0]->toString(exec).domString())); 1208 } 1209 case DOMDocument::QueryCommandSupported: { 1210 return jsBoolean(doc.queryCommandSupported(args[0]->toString(exec).domString())); 1211 } 1212 case DOMDocument::QueryCommandValue: { 1213 DOM::DOMString commandValue(doc.queryCommandValue(args[0]->toString(exec).domString())); 1214 // Method returns null DOMString to signal command is unsupported. 1215 // Microsoft documentation for this method says: 1216 // "If not supported [for a command identifier], this method returns a Boolean set to false." 1217 if (commandValue.isNull()) { 1218 return jsBoolean(false); 1219 } else { 1220 return jsString(commandValue); 1221 } 1222 } 1223 case DOMDocument::GetElementsByClassName: 1224 return getDOMNodeList(exec, doc.getElementsByClassName(s)); 1225 case DOMDocument::QuerySelector: { 1226 RefPtr<DOM::ElementImpl> e = doc.querySelector(s, exception); 1227 return getDOMNode(exec, e.get()); 1228 } 1229 case DOMDocument::QuerySelectorAll: { 1230 RefPtr<DOM::NodeListImpl> l = doc.querySelectorAll(s, exception); 1231 return getDOMNodeList(exec, l.get()); 1232 } 1233 case DOMDocument::CreateExpression: { 1234 RefPtr<khtml::XPathNSResolverImpl> res = toResolver(exec, args[1]); 1235 RefPtr<khtml::XPathExpressionImpl> e = doc.createExpression(s, res.get(), exception); 1236 JSValue *wrapper = getWrapper<KJS::XPathExpression>(exec, e.get()); 1237 1238 // protect the resolver if needed 1239 if (!wrapper->isNull() && res && res->type() == khtml::XPathNSResolverImpl::JS) { 1240 static_cast<XPathExpression *>(wrapper)->setAssociatedResolver(static_cast<JSXPathNSResolver *>(res.get())->resolverObject()); 1241 } 1242 return wrapper; 1243 } 1244 case DOMDocument::CreateNSResolver: { 1245 DOM::NodeImpl *node = toNode(args[0]); 1246 return getWrapper<KJS::XPathNSResolver>(exec, doc.createNSResolver(node)); 1247 } 1248 case DOMDocument::Evaluate: { 1249 return getWrapper<KJS::XPathResult>(exec, 1250 doc.evaluate(s, // expression 1251 toNode(args[1]), // contextNode, 1252 toResolver(exec, args[2]), // resolver 1253 args[3]->toInt32(exec), // type 1254 nullptr, // result reuse, ignored 1255 exception)); 1256 } 1257 default: 1258 break; 1259 } 1260 1261 return jsUndefined(); 1262 } 1263 1264 // ------------------------------------------------------------------------- 1265 1266 /* Source for DOMElementProtoTable. 1267 @begin DOMElementProtoTable 17 1268 getAttribute DOMElement::GetAttribute DontDelete|Function 1 1269 setAttribute DOMElement::SetAttribute DontDelete|Function 2 1270 removeAttribute DOMElement::RemoveAttribute DontDelete|Function 1 1271 getAttributeNode DOMElement::GetAttributeNode DontDelete|Function 1 1272 setAttributeNode DOMElement::SetAttributeNode DontDelete|Function 2 1273 removeAttributeNode DOMElement::RemoveAttributeNode DontDelete|Function 1 1274 getElementsByTagName DOMElement::GetElementsByTagName DontDelete|Function 1 1275 hasAttribute DOMElement::HasAttribute DontDelete|Function 1 1276 getAttributeNS DOMElement::GetAttributeNS DontDelete|Function 2 1277 setAttributeNS DOMElement::SetAttributeNS DontDelete|Function 3 1278 removeAttributeNS DOMElement::RemoveAttributeNS DontDelete|Function 2 1279 getAttributeNodeNS DOMElement::GetAttributeNodeNS DontDelete|Function 2 1280 setAttributeNodeNS DOMElement::SetAttributeNodeNS DontDelete|Function 1 1281 getElementsByTagNameNS DOMElement::GetElementsByTagNameNS DontDelete|Function 2 1282 hasAttributeNS DOMElement::HasAttributeNS DontDelete|Function 2 1283 getElementsByClassName DOMElement::GetElementsByClassName DontDelete|Function 1 1284 # Extensions 1285 blur DOMElement::Blur DontDelete|Function 0 1286 focus DOMElement::Focus DontDelete|Function 0 1287 querySelector DOMElement::QuerySelector DontDelete|Function 1 1288 querySelectorAll DOMElement::QuerySelectorAll DontDelete|Function 1 1289 getClientRects DOMElement::GetClientRects DontDelete|Function 0 1290 getBoundingClientRect DOMElement::GetBoundingClientRect DontDelete|Function 0 1291 @end 1292 */ 1293 KJS_IMPLEMENT_PROTOFUNC(DOMElementProtoFunc) 1294 KJS_IMPLEMENT_PROTOTYPE("DOMElement", DOMElementProto, DOMElementProtoFunc, DOMNodeProto) 1295 1296 IMPLEMENT_PSEUDO_CONSTRUCTOR(ElementPseudoCtor, "Element", DOMElementProto) 1297 1298 const ClassInfo DOMElement::info = { "Element", &DOMNode::info, &DOMElementTable, nullptr }; 1299 /* Source for DOMElementTable. 1300 @begin DOMElementTable 7 1301 tagName DOMElement::TagName DontDelete|ReadOnly 1302 style DOMElement::Style DontDelete|ReadOnly 1303 # DOM 3 - ElementTraversal interface 1304 firstElementChild DOMElement::FirstElementChild DontDelete|ReadOnly 1305 lastElementChild DOMElement::LastElementChild DontDelete|ReadOnly 1306 previousElementSibling DOMElement::PreviousElementSibling DontDelete|ReadOnly 1307 nextElementSibling DOMElement::NextElementSibling DontDelete|ReadOnly 1308 childElementCount DOMElement::ChildElementCount DontDelete|ReadOnly 1309 @end 1310 */ 1311 DOMElement::DOMElement(ExecState *exec, DOM::ElementImpl *e) 1312 : DOMNode(exec, e) 1313 { 1314 setPrototype(DOMElementProto::self(exec)); 1315 } 1316 1317 DOMElement::DOMElement(JSObject *proto, DOM::ElementImpl *e) 1318 : DOMNode(proto, e) 1319 {} 1320 1321 JSValue *DOMElement::getValueProperty(ExecState *exec, int token) const 1322 { 1323 DOM::ElementImpl &element = static_cast<DOM::ElementImpl &>(*m_impl); 1324 switch (token) { 1325 case TagName: 1326 return jsString(element.tagName()); 1327 case Style: 1328 return getDOMCSSStyleDeclaration(exec, element.getInlineStyleDecls()); 1329 case FirstElementChild: 1330 return getDOMNode(exec, element.firstElementChild()); 1331 case LastElementChild: 1332 return getDOMNode(exec, element.lastElementChild()); 1333 case PreviousElementSibling: 1334 return getDOMNode(exec, element.previousElementSibling()); 1335 case NextElementSibling: 1336 return getDOMNode(exec, element.nextElementSibling()); 1337 case ChildElementCount: 1338 return jsNumber((unsigned int)element.childElementCount()); 1339 default: 1340 // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMElement::getValueProperty : " << token; 1341 return jsUndefined(); 1342 } 1343 } 1344 1345 bool DOMElement::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 1346 { 1347 #ifdef KJS_VERBOSE 1348 qCDebug(KHTML_LOG) << "DOMElement::getOwnPropertySlot " << propertyName.qstring(); 1349 #endif 1350 1351 //DOM::Element element = static_cast<DOM::Element>(node); 1352 if (getStaticOwnValueSlot(&DOMElementTable, this, propertyName, slot)) { 1353 return true; 1354 } 1355 1356 return DOMNode::getOwnPropertySlot(exec, propertyName, slot); 1357 } 1358 1359 JSValue *DOMElementProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 1360 { 1361 KJS_CHECK_THIS(KJS::DOMNode, thisObj); // node should be enough here, given the cast 1362 DOMExceptionTranslator exception(exec); 1363 DOM::NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl(); 1364 DOM::ElementImpl &element = static_cast<DOM::ElementImpl &>(node); 1365 1366 switch (id) { 1367 case DOMElement::GetAttribute: 1368 /** In theory, we should not return null here, as per DOM. In practice, that 1369 breaks websites */ 1370 return getStringOrNull(element.getAttribute(args[0]->toString(exec).domString())); 1371 case DOMElement::SetAttribute: 1372 element.setAttribute(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception); 1373 return jsUndefined(); 1374 case DOMElement::RemoveAttribute: 1375 element.removeAttribute(args[0]->toString(exec).domString(), exception); 1376 return jsUndefined(); 1377 case DOMElement::GetAttributeNode: 1378 return getDOMNode(exec, element.getAttributeNode(args[0]->toString(exec).domString())); 1379 case DOMElement::SetAttributeNode: { 1380 DOM::Attr ret = element.setAttributeNode(KJS::toAttr(args[0]), exception); 1381 return getDOMNode(exec, ret.handle()); 1382 } 1383 case DOMElement::RemoveAttributeNode: { 1384 DOM::Attr ret = element.removeAttributeNode(KJS::toAttr(args[0]), exception); 1385 return getDOMNode(exec, ret.handle()); 1386 } 1387 case DOMElement::GetElementsByTagName: 1388 return getDOMNodeList(exec, element.getElementsByTagName(args[0]->toString(exec).domString())); 1389 case DOMElement::HasAttribute: // DOM2 1390 return jsBoolean(element.hasAttribute(args[0]->toString(exec).domString())); 1391 case DOMElement::GetAttributeNS: // DOM2 1392 return jsString(element.getAttributeNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception)); 1393 case DOMElement::SetAttributeNS: // DOM2 1394 element.setAttributeNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), args[2]->toString(exec).domString(), exception); 1395 return jsUndefined(); 1396 case DOMElement::RemoveAttributeNS: // DOM2 1397 element.removeAttributeNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception); 1398 return jsUndefined(); 1399 case DOMElement::GetAttributeNodeNS: // DOM2 1400 return getDOMNode(exec, element.getAttributeNodeNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception)); 1401 case DOMElement::SetAttributeNodeNS: { 1402 DOM::Attr toRet = element.setAttributeNodeNS(KJS::toAttr(args[0]), exception); 1403 return getDOMNode(exec, toRet.handle()); 1404 } 1405 case DOMElement::GetElementsByTagNameNS: // DOM2 1406 return getDOMNodeList(exec, element.getElementsByTagNameNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString())); 1407 case DOMElement::HasAttributeNS: // DOM2 1408 return jsBoolean(element.hasAttributeNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString())); 1409 case DOMElement::GetElementsByClassName: // HTML 5 1410 return getDOMNodeList(exec, element.getElementsByClassName(args[0]->toString(exec).domString())); 1411 case DOMElement::QuerySelector: { // WA Selectors 1 1412 RefPtr<DOM::ElementImpl> e = element.querySelector(args[0]->toString(exec).domString(), exception); 1413 return getDOMNode(exec, e.get()); 1414 } 1415 case DOMElement::QuerySelectorAll: { // WA Selectors 1 1416 RefPtr<DOM::NodeListImpl> l = element.querySelectorAll(args[0]->toString(exec).domString(), exception); 1417 return getDOMNodeList(exec, l.get()); 1418 } 1419 case DOMElement::GetClientRects: { 1420 DOM::DocumentImpl *docimpl = node.document(); 1421 if (docimpl) { 1422 docimpl->updateLayout(); 1423 } 1424 1425 khtml::RenderObject *rend = node.renderer(); 1426 1427 if (!rend) { 1428 return new ClientRectList(exec); 1429 } 1430 1431 //In quirks mode, may need to forward it to body. 1432 rend = handleBodyRootQuirk(static_cast<DOMNode *>(thisObj)->impl(), rend, DOMNode::ClientTop); 1433 1434 return new ClientRectList(exec, rend->getClientRects()); 1435 } 1436 case DOMElement::GetBoundingClientRect: { 1437 DOM::DocumentImpl *docimpl = node.document(); 1438 if (docimpl) { 1439 docimpl->updateLayout(); 1440 } 1441 1442 khtml::RenderObject *rend = node.renderer(); 1443 1444 //In quirks mode, may need to forward it to body. 1445 rend = handleBodyRootQuirk(static_cast<DOMNode *>(thisObj)->impl(), rend, DOMNode::ClientTop); 1446 1447 if (!rend) { 1448 return new ClientRect(exec, 0, 0, 0, 0); 1449 } 1450 1451 QList<QRectF> list = rend->getClientRects(); 1452 if (list.isEmpty()) { 1453 return new ClientRect(exec, 0, 0, 0, 0); 1454 } else { 1455 QRectF rect = list.first(); 1456 for (int i = 1; i < list.length(); ++i) { 1457 rect = rect.united(list.at(i)); 1458 } 1459 return new ClientRect(exec, rect); 1460 } 1461 } 1462 1463 default: 1464 1465 // Make sure our layout is up to date before we call these 1466 DOM::DocumentImpl *docimpl = element.document(); 1467 if (docimpl) { 1468 docimpl->updateLayout(); 1469 } 1470 switch (id) { 1471 case DOMElement::Focus: 1472 element.focus(); 1473 return jsUndefined(); 1474 case DOMElement::Blur: 1475 element.blur(); 1476 return jsUndefined(); 1477 default: 1478 return jsUndefined(); 1479 } 1480 } 1481 } 1482 1483 DOM::ElementImpl *KJS::toElement(JSValue *v) 1484 { 1485 DOM::NodeImpl *node = toNode(v); 1486 if (node && node->isElementNode()) { 1487 return static_cast<DOM::ElementImpl *>(node); 1488 } 1489 return nullptr; 1490 } 1491 1492 DOM::AttrImpl *KJS::toAttr(JSValue *v) 1493 { 1494 DOM::NodeImpl *node = toNode(v); 1495 if (node && node->isAttributeNode()) { 1496 return static_cast<DOM::AttrImpl *>(node); 1497 } 1498 return nullptr; 1499 } 1500 1501 // ------------------------------------------------------------------------- 1502 1503 /* Source for DOMDOMImplementationProtoTable. 1504 @begin DOMDOMImplementationProtoTable 5 1505 hasFeature DOMDOMImplementation::HasFeature DontDelete|Function 2 1506 createCSSStyleSheet DOMDOMImplementation::CreateCSSStyleSheet DontDelete|Function 2 1507 # DOM2 1508 createDocumentType DOMDOMImplementation::CreateDocumentType DontDelete|Function 3 1509 createDocument DOMDOMImplementation::CreateDocument DontDelete|Function 3 1510 createHTMLDocument DOMDOMImplementation::CreateHTMLDocument DontDelete|Function 1 1511 @end 1512 */ 1513 KJS_DEFINE_PROTOTYPE(DOMDOMImplementationProto) 1514 KJS_IMPLEMENT_PROTOFUNC(DOMDOMImplementationProtoFunc) 1515 KJS_IMPLEMENT_PROTOTYPE("DOMImplementation", DOMDOMImplementationProto, DOMDOMImplementationProtoFunc, ObjectPrototype) 1516 1517 const ClassInfo DOMDOMImplementation::info = { "DOMImplementation", nullptr, nullptr, nullptr }; 1518 1519 DOMDOMImplementation::DOMDOMImplementation(ExecState *exec, DOM::DOMImplementationImpl *i) 1520 : DOMObject(DOMDOMImplementationProto::self(exec)), m_impl(i) { } 1521 1522 DOMDOMImplementation::~DOMDOMImplementation() 1523 { 1524 ScriptInterpreter::forgetDOMObject(m_impl.get()); 1525 } 1526 1527 JSValue *DOMDOMImplementationProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 1528 { 1529 KJS_CHECK_THIS(KJS::DOMDOMImplementation, thisObj); 1530 DOM::DOMImplementationImpl &implementation = *static_cast<DOMDOMImplementation *>(thisObj)->impl(); 1531 DOMExceptionTranslator exception(exec); 1532 1533 switch (id) { 1534 case DOMDOMImplementation::HasFeature: 1535 return jsBoolean(implementation.hasFeature(args[0]->toString(exec).domString(), 1536 valueToStringWithNullCheck(exec, args[1]))); 1537 case DOMDOMImplementation::CreateDocumentType: // DOM2 1538 return getDOMNode(exec, implementation.createDocumentType(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), args[2]->toString(exec).domString(), exception)); 1539 case DOMDOMImplementation::CreateDocument: { // DOM2 1540 // Initially set the URL to document of the creator... this is so that it resides in the same 1541 // host/domain for security checks. The URL will be updated if Document.load() is called. 1542 KHTMLPart *part = qobject_cast<KHTMLPart *>(static_cast<KJS::ScriptInterpreter *>(exec->dynamicInterpreter())->part()); 1543 if (part) { 1544 //### this should probably be pushed to the impl 1545 DOM::NodeImpl *supposedDocType = toNode(args[2]); 1546 if (supposedDocType && supposedDocType->nodeType() != DOM::Node::DOCUMENT_TYPE_NODE) { 1547 setDOMException(exec, DOMException::NOT_FOUND_ERR); 1548 return jsNull(); 1549 } 1550 1551 DOM::DocumentTypeImpl *docType = static_cast<DOM::DocumentTypeImpl *>(supposedDocType); 1552 1553 // ### no real leak but lifetime of part is not tied to document 1554 KHTMLPart *newPart = new KHTMLPart(part->view(), part); 1555 DOM::DocumentImpl *doc = implementation.createDocument(valueToStringWithNullCheck(exec, args[0]), 1556 valueToStringWithNullCheck(exec, args[1]), 1557 docType, 1558 newPart->view(), 1559 exception); 1560 if (!doc) { 1561 return jsNull(); 1562 } 1563 QUrl url = static_cast<DocumentImpl *>(part->document().handle())->URL(); 1564 doc->setURL(url.url()); 1565 return getDOMNode(exec, doc); 1566 } 1567 break; 1568 } 1569 case DOMDOMImplementation::CreateCSSStyleSheet: // DOM2 1570 return getDOMStyleSheet(exec, implementation.createCSSStyleSheet( 1571 args[0]->toString(exec).domString().implementation(), 1572 args[1]->toString(exec).domString().implementation(), exception)); 1573 case DOMDOMImplementation::CreateHTMLDocument: // DOM2-HTML 1574 return getDOMNode(exec, implementation.createHTMLDocument(args[0]->toString(exec).domString())); 1575 default: 1576 break; 1577 } 1578 return jsUndefined(); 1579 } 1580 1581 // ------------------------------------------------------------------------- 1582 1583 const ClassInfo DOMDocumentType::info = { "DocumentType", &DOMNode::info, &DOMDocumentTypeTable, nullptr }; 1584 1585 /* Source for DOMDocumentTypeTable. 1586 @begin DOMDocumentTypeTable 6 1587 name DOMDocumentType::Name DontDelete|ReadOnly 1588 entities DOMDocumentType::Entities DontDelete|ReadOnly 1589 notations DOMDocumentType::Notations DontDelete|ReadOnly 1590 # DOM2 1591 publicId DOMDocumentType::PublicId DontDelete|ReadOnly 1592 systemId DOMDocumentType::SystemId DontDelete|ReadOnly 1593 internalSubset DOMDocumentType::InternalSubset DontDelete|ReadOnly 1594 @end 1595 */ 1596 DOMDocumentType::DOMDocumentType(ExecState *exec, DOM::DocumentTypeImpl *dt) 1597 : DOMNode(/*### no proto yet*/exec, dt) { } 1598 1599 bool DOMDocumentType::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, KJS::PropertySlot &slot) 1600 { 1601 #ifdef KJS_VERBOSE 1602 qCDebug(KHTML_LOG) << "DOMDocumentType::getOwnPropertySlot " << propertyName.qstring(); 1603 #endif 1604 return getStaticValueSlot<DOMDocumentType, DOMNode>(exec, &DOMDocumentTypeTable, this, propertyName, slot); 1605 } 1606 1607 JSValue *DOMDocumentType::getValueProperty(ExecState *exec, int token) const 1608 { 1609 DOM::DocumentTypeImpl &type = static_cast<DOM::DocumentTypeImpl &>(*m_impl); 1610 switch (token) { 1611 case Name: 1612 return jsString(type.name()); 1613 case Entities: 1614 return getDOMNamedNodeMap(exec, type.entities()); 1615 case Notations: 1616 return getDOMNamedNodeMap(exec, type.notations()); 1617 case PublicId: // DOM2 1618 return jsString(type.publicId()); 1619 case SystemId: // DOM2 1620 return jsString(type.systemId()); 1621 case InternalSubset: // DOM2 1622 return ::getStringOrNull(type.internalSubset()); // can be null, see domts/level2/core/internalSubset01.html 1623 default: 1624 // qCDebug(KHTML_LOG) << "WARNING: DOMDocumentType::getValueProperty unhandled token " << token; 1625 return jsNull(); 1626 } 1627 } 1628 1629 // ------------------------------------------------------------------------- 1630 1631 /* Source for DOMNamedNodeMapProtoTable. 1632 @begin DOMNamedNodeMapProtoTable 7 1633 getNamedItem DOMNamedNodeMap::GetNamedItem DontDelete|Function 1 1634 setNamedItem DOMNamedNodeMap::SetNamedItem DontDelete|Function 1 1635 removeNamedItem DOMNamedNodeMap::RemoveNamedItem DontDelete|Function 1 1636 item DOMNamedNodeMap::Item DontDelete|Function 1 1637 # DOM2 1638 getNamedItemNS DOMNamedNodeMap::GetNamedItemNS DontDelete|Function 2 1639 setNamedItemNS DOMNamedNodeMap::SetNamedItemNS DontDelete|Function 1 1640 removeNamedItemNS DOMNamedNodeMap::RemoveNamedItemNS DontDelete|Function 2 1641 @end 1642 @begin DOMNamedNodeMapTable 7 1643 length DOMNamedNodeMap::Length DontDelete|Function 1 1644 @end 1645 */ 1646 KJS_DEFINE_PROTOTYPE(DOMNamedNodeMapProto) 1647 KJS_IMPLEMENT_PROTOFUNC(DOMNamedNodeMapProtoFunc) 1648 KJS_IMPLEMENT_PROTOTYPE("NamedNodeMap", DOMNamedNodeMapProto, DOMNamedNodeMapProtoFunc, ObjectPrototype) 1649 1650 const ClassInfo DOMNamedNodeMap::info = { "NamedNodeMap", nullptr, &DOMNamedNodeMapTable, nullptr }; 1651 1652 DOMNamedNodeMap::DOMNamedNodeMap(ExecState *exec, DOM::NamedNodeMapImpl *m) 1653 : DOMObject(DOMNamedNodeMapProto::self(exec)), m_impl(m) { } 1654 1655 DOMNamedNodeMap::~DOMNamedNodeMap() 1656 { 1657 ScriptInterpreter::forgetDOMObject(m_impl.get()); 1658 } 1659 1660 JSValue *DOMNamedNodeMap::indexGetter(ExecState *exec, unsigned index) 1661 { 1662 return getDOMNode(exec, m_impl->item(index)); 1663 } 1664 1665 JSValue *DOMNamedNodeMap::lengthGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &slot) 1666 { 1667 DOMNamedNodeMap *thisObj = static_cast<DOMNamedNodeMap *>(slot.slotBase()); 1668 return jsNumber(thisObj->m_impl->length()); 1669 } 1670 1671 bool DOMNamedNodeMap::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 1672 { 1673 if (propertyName == exec->propertyNames().length) { 1674 slot.setCustom(this, lengthGetter); 1675 return true; 1676 } 1677 1678 // See if it's an item name get 1679 DOM::NodeImpl *attr = impl()->getNamedItem(propertyName.ustring().domString()); 1680 if (attr) { 1681 return getImmediateValueSlot(this, getDOMNode(exec, attr), slot); 1682 } 1683 1684 //May be it's an index? 1685 if (getIndexSlot(this, *m_impl, propertyName, slot)) { 1686 return true; 1687 } 1688 1689 return DOMObject::getOwnPropertySlot(exec, propertyName, slot); 1690 } 1691 1692 JSValue *DOMNamedNodeMapProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 1693 { 1694 KJS_CHECK_THIS(KJS::DOMNamedNodeMap, thisObj); 1695 DOMExceptionTranslator exception(exec); 1696 DOM::NamedNodeMapImpl &map = *static_cast<DOMNamedNodeMap *>(thisObj)->impl(); 1697 1698 switch (id) { 1699 case DOMNamedNodeMap::GetNamedItem: 1700 return getDOMNode(exec, map.getNamedItem(args[0]->toString(exec).domString())); 1701 case DOMNamedNodeMap::SetNamedItem: { 1702 DOM::Node old = map.setNamedItem(toNode(args[0]), exception); 1703 return getDOMNode(exec, old.handle()); 1704 } 1705 case DOMNamedNodeMap::RemoveNamedItem: { 1706 DOM::Attr toRet = map.removeNamedItem(args[0]->toString(exec).domString(), exception); 1707 return getDOMNode(exec, toRet.handle()); 1708 } 1709 case DOMNamedNodeMap::Item: 1710 return getDOMNode(exec, map.item(args[0]->toInt32(exec))); 1711 case DOMNamedNodeMap::GetNamedItemNS: {// DOM2 1712 DOM::Node old = map.getNamedItemNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString()); 1713 return getDOMNode(exec, old.handle()); 1714 } 1715 case DOMNamedNodeMap::SetNamedItemNS: {// DOM2 1716 DOM::Node old = map.setNamedItemNS(toNode(args[0]), exception); 1717 return getDOMNode(exec, old.handle()); 1718 } 1719 case DOMNamedNodeMap::RemoveNamedItemNS: { // DOM2 1720 DOM::Node old = map.removeNamedItemNS(args[0]->toString(exec).domString(), args[1]->toString(exec).domString(), exception); 1721 return getDOMNode(exec, old.handle()); 1722 } 1723 default: 1724 break; 1725 } 1726 1727 return jsUndefined(); 1728 } 1729 1730 // ------------------------------------------------------------------------- 1731 //### FIXME: proto 1732 const ClassInfo DOMProcessingInstruction::info = { "ProcessingInstruction", &DOMNode::info, &DOMProcessingInstructionTable, nullptr }; 1733 1734 /* Source for DOMProcessingInstructionTable. 1735 @begin DOMProcessingInstructionTable 3 1736 target DOMProcessingInstruction::Target DontDelete|ReadOnly 1737 data DOMProcessingInstruction::Data DontDelete 1738 sheet DOMProcessingInstruction::Sheet DontDelete|ReadOnly 1739 @end 1740 */ 1741 bool DOMProcessingInstruction::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 1742 { 1743 return getStaticValueSlot<DOMProcessingInstruction, DOMNode>(exec, &DOMProcessingInstructionTable, this, propertyName, slot); 1744 } 1745 1746 JSValue *DOMProcessingInstruction::getValueProperty(ExecState *exec, int token) const 1747 { 1748 DOM::ProcessingInstructionImpl &pi = *static_cast<DOM::ProcessingInstructionImpl *>(m_impl.get()); 1749 switch (token) { 1750 case Target: 1751 return jsString(pi.target()); 1752 case Data: 1753 return jsString(pi.data()); 1754 case Sheet: 1755 return getDOMStyleSheet(exec, pi.sheet()); 1756 default: 1757 // qCDebug(KHTML_LOG) << "WARNING: DOMProcessingInstruction::getValueProperty unhandled token " << token; 1758 return jsNull(); 1759 } 1760 } 1761 1762 void DOMProcessingInstruction::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) 1763 { 1764 DOM::ProcessingInstructionImpl &pi = *static_cast<DOM::ProcessingInstructionImpl *>(m_impl.get()); 1765 // Not worth using the hashtable for this one ;) 1766 if (propertyName == "data") { 1767 DOMExceptionTranslator exception(exec); 1768 pi.setData(value->toString(exec).domString(), exception); 1769 } else { 1770 DOMNode::put(exec, propertyName, value, attr); 1771 } 1772 } 1773 1774 // ------------------------------------------------------------------------- 1775 1776 const ClassInfo DOMNotation::info = { "Notation", &DOMNode::info, &DOMNotationTable, nullptr }; 1777 1778 /* Source for DOMNotationTable. 1779 @begin DOMNotationTable 2 1780 publicId DOMNotation::PublicId DontDelete|ReadOnly 1781 systemId DOMNotation::SystemId DontDelete|ReadOnly 1782 @end 1783 */ 1784 bool DOMNotation::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 1785 { 1786 return getStaticValueSlot<DOMNotation, DOMNode>(exec, &DOMNotationTable, this, propertyName, slot); 1787 } 1788 1789 JSValue *DOMNotation::getValueProperty(ExecState *, int token) const 1790 { 1791 DOM::NotationImpl ¬a = *static_cast<DOM::NotationImpl *>(m_impl.get()); 1792 switch (token) { 1793 case PublicId: 1794 return jsString(nota.publicId()); 1795 case SystemId: 1796 return jsString(nota.systemId()); 1797 default: 1798 // qCDebug(KHTML_LOG) << "WARNING: DOMNotation::getValueProperty unhandled token " << token; 1799 return jsNull(); 1800 } 1801 } 1802 1803 // ------------------------------------------------------------------------- 1804 1805 const ClassInfo DOMEntity::info = { "Entity", &DOMNode::info, nullptr, nullptr }; 1806 1807 /* Source for DOMEntityTable. 1808 @begin DOMEntityTable 2 1809 publicId DOMEntity::PublicId DontDelete|ReadOnly 1810 systemId DOMEntity::SystemId DontDelete|ReadOnly 1811 notationName DOMEntity::NotationName DontDelete|ReadOnly 1812 @end 1813 */ 1814 bool DOMEntity::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 1815 { 1816 return getStaticValueSlot<DOMEntity, DOMNode>(exec, &DOMEntityTable, this, propertyName, slot); 1817 } 1818 1819 JSValue *DOMEntity::getValueProperty(ExecState *, int token) const 1820 { 1821 DOM::EntityImpl &entity = *static_cast<DOM::EntityImpl *>(m_impl.get()); 1822 switch (token) { 1823 case PublicId: 1824 return jsString(entity.publicId()); 1825 case SystemId: 1826 return jsString(entity.systemId()); 1827 case NotationName: 1828 return jsString(entity.notationName()); 1829 default: 1830 // qCDebug(KHTML_LOG) << "WARNING: DOMEntity::getValueProperty unhandled token " << token; 1831 return jsNull(); 1832 } 1833 } 1834 1835 // ------------------------------------------------------------------------- 1836 1837 bool KJS::checkNodeSecurity(ExecState *exec, const DOM::NodeImpl *n) 1838 { 1839 // Check to see if the currently executing interpreter is allowed to access the specified node 1840 if (!n) { 1841 return true; 1842 } 1843 KHTMLPart *part = n->document()->part(); 1844 Window *win = part ? Window::retrieveWindow(part) : nullptr; 1845 if (!win || !win->isSafeScript(exec)) { 1846 return false; 1847 } 1848 return true; 1849 } 1850 1851 // adopted from binding/JSHTMLElementFactory.cpp 1852 #define CREATE_WRAPPER_FUNCTION(name) \ 1853 static DOMObject* create##name##Wrapper(ExecState* exec, DOM::NodeImpl* n) \ 1854 { \ 1855 return new JSHTML##name##Element(exec, static_cast<HTML##name##Element*>(n)); \ 1856 } 1857 1858 CREATE_WRAPPER_FUNCTION(Audio) 1859 CREATE_WRAPPER_FUNCTION(Video) 1860 1861 JSValue *KJS::getEventTarget(ExecState *exec, DOM::EventTargetImpl *t) 1862 { 1863 if (!t) { 1864 return jsNull(); 1865 } 1866 if (t->eventTargetType() == EventTargetImpl::DOM_NODE) { 1867 return getDOMNode(exec, static_cast<DOM::NodeImpl *>(t)); 1868 } else if (t->eventTargetType() == EventTargetImpl::WINDOW) { 1869 Window *w = static_cast<WindowEventTargetImpl *>(t)->window(); 1870 return w ? w : jsNull(); 1871 } else { 1872 return static_cast<XMLHttpRequest *>(t); 1873 } 1874 } 1875 1876 JSValue *KJS::getDOMNode(ExecState *exec, DOM::NodeImpl *n) 1877 { 1878 DOMObject *ret = nullptr; 1879 if (!n) { 1880 return jsNull(); 1881 } 1882 ScriptInterpreter *interp = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter()); 1883 if ((ret = interp->getDOMObject(n))) { 1884 return ret; 1885 } 1886 1887 switch (n->nodeType()) { 1888 case DOM::Node::ELEMENT_NODE: 1889 switch (n->id()) { 1890 case ID_AUDIO: 1891 ret = createAudioWrapper(exec, n); 1892 break; 1893 case ID_VIDEO: 1894 ret = createVideoWrapper(exec, n); 1895 break; 1896 default: 1897 if (static_cast<DOM::ElementImpl *>(n)->isHTMLElement()) { 1898 ret = new HTMLElement(exec, static_cast<DOM::HTMLElementImpl *>(n)); 1899 } else { 1900 ret = new DOMElement(exec, static_cast<DOM::ElementImpl *>(n)); 1901 } 1902 break; 1903 } 1904 break; 1905 case DOM::Node::ATTRIBUTE_NODE: 1906 ret = new DOMAttr(exec, static_cast<DOM::AttrImpl *>(n)); 1907 break; 1908 case DOM::Node::TEXT_NODE: 1909 case DOM::Node::CDATA_SECTION_NODE: 1910 ret = new DOMText(exec, static_cast<DOM::TextImpl *>(n)); 1911 break; 1912 case DOM::Node::ENTITY_REFERENCE_NODE: 1913 ret = new DOMNode(exec, n); 1914 break; 1915 case DOM::Node::ENTITY_NODE: 1916 ret = new DOMEntity(exec, static_cast<DOM::EntityImpl *>(n)); 1917 break; 1918 case DOM::Node::PROCESSING_INSTRUCTION_NODE: 1919 ret = new DOMProcessingInstruction(exec, static_cast<DOM::ProcessingInstructionImpl *>(n)); 1920 break; 1921 case DOM::Node::COMMENT_NODE: 1922 ret = new DOMComment(exec, static_cast<DOM::CommentImpl *>(n)); 1923 break; 1924 case DOM::Node::DOCUMENT_NODE: 1925 if (static_cast<DOM::DocumentImpl *>(n)->isHTMLDocument()) { 1926 ret = new HTMLDocument(exec, static_cast<DOM::HTMLDocumentImpl *>(n)); 1927 } else { 1928 ret = new DOMDocument(exec, static_cast<DOM::DocumentImpl *>(n)); 1929 } 1930 break; 1931 case DOM::Node::DOCUMENT_TYPE_NODE: 1932 ret = new DOMDocumentType(exec, static_cast<DOM::DocumentTypeImpl *>(n)); 1933 break; 1934 case DOM::Node::DOCUMENT_FRAGMENT_NODE: 1935 ret = new DOMDocumentFragment(exec, static_cast<DOM::DocumentFragmentImpl *>(n)); 1936 break; 1937 case DOM::Node::NOTATION_NODE: 1938 ret = new DOMNotation(exec, static_cast<DOM::NotationImpl *>(n)); 1939 break; 1940 default: 1941 ret = new DOMNode(exec, n); 1942 } 1943 interp->putDOMObject(n, ret); 1944 1945 return ret; 1946 } 1947 1948 JSValue *KJS::getDOMNamedNodeMap(ExecState *exec, DOM::NamedNodeMapImpl *m) 1949 { 1950 return cacheDOMObject<DOM::NamedNodeMapImpl, KJS::DOMNamedNodeMap>(exec, m); 1951 } 1952 1953 JSValue *KJS::getDOMNodeList(ExecState *exec, DOM::NodeListImpl *l) 1954 { 1955 return cacheDOMObject<DOM::NodeListImpl, KJS::DOMNodeList>(exec, l); 1956 } 1957 1958 JSValue *KJS::getDOMDOMImplementation(ExecState *exec, DOM::DOMImplementationImpl *i) 1959 { 1960 return cacheDOMObject<DOM::DOMImplementationImpl, KJS::DOMDOMImplementation>(exec, i); 1961 } 1962 1963 // ------------------------------------------------------------------------- 1964 1965 IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(NodeConstructor, "NodeConstructor", DOMNodeProto, DOMNodeConstants) 1966 // ------------------------------------------------------------------------- 1967 1968 /* Source for DOMExceptionProtoTable. 1969 @begin DOMExceptionProtoTable 29 1970 INDEX_SIZE_ERR DOM::DOMException::INDEX_SIZE_ERR DontDelete|ReadOnly 1971 DOMSTRING_SIZE_ERR DOM::DOMException::DOMSTRING_SIZE_ERR DontDelete|ReadOnly 1972 HIERARCHY_REQUEST_ERR DOM::DOMException::HIERARCHY_REQUEST_ERR DontDelete|ReadOnly 1973 WRONG_DOCUMENT_ERR DOM::DOMException::WRONG_DOCUMENT_ERR DontDelete|ReadOnly 1974 INVALID_CHARACTER_ERR DOM::DOMException::INVALID_CHARACTER_ERR DontDelete|ReadOnly 1975 NO_DATA_ALLOWED_ERR DOM::DOMException::NO_DATA_ALLOWED_ERR DontDelete|ReadOnly 1976 NO_MODIFICATION_ALLOWED_ERR DOM::DOMException::NO_MODIFICATION_ALLOWED_ERR DontDelete|ReadOnly 1977 NOT_FOUND_ERR DOM::DOMException::NOT_FOUND_ERR DontDelete|ReadOnly 1978 NOT_SUPPORTED_ERR DOM::DOMException::NOT_SUPPORTED_ERR DontDelete|ReadOnly 1979 INUSE_ATTRIBUTE_ERR DOM::DOMException::INUSE_ATTRIBUTE_ERR DontDelete|ReadOnly 1980 INVALID_STATE_ERR DOM::DOMException::INVALID_STATE_ERR DontDelete|ReadOnly 1981 SYNTAX_ERR DOM::DOMException::SYNTAX_ERR DontDelete|ReadOnly 1982 INVALID_MODIFICATION_ERR DOM::DOMException::INVALID_MODIFICATION_ERR DontDelete|ReadOnly 1983 NAMESPACE_ERR DOM::DOMException::NAMESPACE_ERR DontDelete|ReadOnly 1984 INVALID_ACCESS_ERR DOM::DOMException::INVALID_ACCESS_ERR DontDelete|ReadOnly 1985 VALIDATION_ERR DOM::DOMException::VALIDATION_ERR DontDelete|ReadOnly 1986 TYPE_MISMATCH_ERR DOM::DOMException::TYPE_MISMATCH_ERR DontDelete|ReadOnly 1987 SECURITY_ERR DOM::DOMException::SECURITY_ERR DontDelete|ReadOnly 1988 NETWORK_ERR DOM::DOMException::NETWORK_ERR DontDelete|ReadOnly 1989 ABORT_ERR DOM::DOMException::ABORT_ERR DontDelete|ReadOnly 1990 URL_MISMATCH_ERR DOM::DOMException::URL_MISMATCH_ERR DontDelete|ReadOnly 1991 QUOTA_EXCEEDED_ERR DOM::DOMException::QUOTA_EXCEEDED_ERR DontDelete|ReadOnly 1992 TIMEOUT_ERR DOM::DOMException::TIMEOUT_ERR DontDelete|ReadOnly 1993 NOT_READABLE_ERR DOM::DOMException::NOT_READABLE_ERR DontDelete|ReadOnly 1994 DATA_CLONE_ERR DOM::DOMException::DATA_CLONE_ERR DontDelete|ReadOnly 1995 ENCODING_ERR DOM::DOMException::ENCODING_ERR DontDelete|ReadOnly 1996 @end 1997 */ 1998 1999 DEFINE_CONSTANT_TABLE(DOMExceptionProto) 2000 IMPLEMENT_CONSTANT_TABLE(DOMExceptionProto, "DOMException") 2001 2002 IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(DOMExceptionPseudoCtor, 2003 "DOMException", 2004 DOMExceptionProto, DOMExceptionProto) 2005 2006 JSDOMException::JSDOMException(ExecState *exec) 2007 : DOMObject(DOMExceptionProto::self(exec)) 2008 { 2009 } 2010 2011 const ClassInfo JSDOMException::info = { "DOMException", nullptr, nullptr, nullptr }; 2012 2013 JSObject *KJS::getDOMExceptionConstructor(ExecState *exec) 2014 { 2015 return DOMExceptionPseudoCtor::self(exec); 2016 } 2017 2018 // ------------------------------------------------------------------------- 2019 2020 /* Source for DOMNamedNodesCollection. 2021 @begin DOMNamedNodesCollectionTable 1 2022 length KJS::DOMNamedNodesCollection::Length DontDelete|ReadOnly 2023 @end 2024 */ 2025 const ClassInfo KJS::DOMNamedNodesCollection::info = { "DOMNamedNodesCollection", nullptr, &DOMNamedNodesCollectionTable, nullptr }; 2026 2027 // Such a collection is usually very short-lived, it only exists 2028 // for constructs like document.forms.<name>[1], 2029 // so it shouldn't be a problem that it's storing all the nodes (with the same name). (David) 2030 DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState *exec, const QList<SharedPtr<DOM::NodeImpl> > &nodes) 2031 : DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype()), 2032 m_nodes(nodes) 2033 { 2034 // Maybe we should ref (and deref in the dtor) the nodes, though ? 2035 } 2036 2037 JSValue *DOMNamedNodesCollection::indexGetter(ExecState *exec, unsigned index) 2038 { 2039 return getDOMNode(exec, m_nodes[index].get()); 2040 } 2041 2042 JSValue *DOMNamedNodesCollection::lengthGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &slot) 2043 { 2044 DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection *>(slot.slotBase()); 2045 return jsNumber(thisObj->m_nodes.size()); 2046 } 2047 2048 bool DOMNamedNodesCollection::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 2049 { 2050 // qCDebug(KHTML_LOG) << propertyName.ascii(); 2051 2052 if (propertyName == exec->propertyNames().length) { 2053 slot.setCustom(this, lengthGetter); 2054 return true; 2055 } 2056 2057 //May be it's an index? 2058 if (getIndexSlot(this, m_nodes.size(), propertyName, slot)) { 2059 return true; 2060 } 2061 2062 return DOMObject::getOwnPropertySlot(exec, propertyName, slot); 2063 } 2064 2065 // ------------------------------------------------------------------------- 2066 2067 const ClassInfo DOMCharacterData::info = { "CharacterImp", 2068 &DOMNode::info, &DOMCharacterDataTable, nullptr 2069 }; 2070 /* 2071 @begin DOMCharacterDataTable 2 2072 data DOMCharacterData::Data DontDelete 2073 length DOMCharacterData::Length DontDelete|ReadOnly 2074 @end 2075 @begin DOMCharacterDataProtoTable 7 2076 substringData DOMCharacterData::SubstringData DontDelete|Function 2 2077 appendData DOMCharacterData::AppendData DontDelete|Function 1 2078 insertData DOMCharacterData::InsertData DontDelete|Function 2 2079 deleteData DOMCharacterData::DeleteData DontDelete|Function 2 2080 replaceData DOMCharacterData::ReplaceData DontDelete|Function 2 2081 @end 2082 */ 2083 KJS_DEFINE_PROTOTYPE(DOMCharacterDataProto) 2084 KJS_IMPLEMENT_PROTOFUNC(DOMCharacterDataProtoFunc) 2085 KJS_IMPLEMENT_PROTOTYPE("DOMCharacterData", DOMCharacterDataProto, DOMCharacterDataProtoFunc, DOMNodeProto) 2086 2087 DOMCharacterData::DOMCharacterData(ExecState *exec, DOM::CharacterDataImpl *d) 2088 : DOMNode(exec, d) 2089 { 2090 setPrototype(DOMCharacterDataProto::self(exec)); 2091 } 2092 2093 bool DOMCharacterData::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 2094 { 2095 #ifdef KJS_VERBOSE 2096 qCDebug(KHTML_LOG) << "DOMCharacterData::tryGet " << propertyName.qstring(); 2097 #endif 2098 return getStaticValueSlot<DOMCharacterData, DOMNode>(exec, &DOMCharacterDataTable, this, propertyName, slot); 2099 } 2100 2101 JSValue *DOMCharacterData::getValueProperty(ExecState *, int token) const 2102 { 2103 DOM::CharacterDataImpl &data = *impl(); 2104 switch (token) { 2105 case Data: 2106 return jsString(data.data()); 2107 case Length: 2108 return jsNumber(data.length()); 2109 default: 2110 // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMCharacterData::getValueProperty : " << token; 2111 return jsNull(); 2112 } 2113 } 2114 2115 void DOMCharacterData::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) 2116 { 2117 if (propertyName == "data") { 2118 DOMExceptionTranslator exception(exec); 2119 impl()->setData(value->toString(exec).domString(), exception); 2120 } else { 2121 DOMNode::put(exec, propertyName, value, attr); 2122 } 2123 } 2124 2125 JSValue *DOMCharacterDataProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 2126 { 2127 KJS_CHECK_THIS(KJS::DOMCharacterData, thisObj); 2128 DOM::CharacterDataImpl &data = *static_cast<DOMCharacterData *>(thisObj)->impl(); 2129 DOMExceptionTranslator exception(exec); 2130 switch (id) { 2131 case DOMCharacterData::SubstringData: 2132 return jsString(data.substringData(args[0]->toInteger(exec), args[1]->toInteger(exec), exception)); 2133 case DOMCharacterData::AppendData: 2134 data.appendData(args[0]->toString(exec).domString(), exception); 2135 return jsUndefined(); 2136 break; 2137 case DOMCharacterData::InsertData: 2138 data.insertData(args[0]->toInteger(exec), args[1]->toString(exec).domString(), exception); 2139 return jsUndefined(); 2140 break; 2141 case DOMCharacterData::DeleteData: 2142 data.deleteData(args[0]->toInteger(exec), args[1]->toInteger(exec), exception); 2143 return jsUndefined(); 2144 break; 2145 case DOMCharacterData::ReplaceData: 2146 data.replaceData(args[0]->toInteger(exec), args[1]->toInteger(exec), args[2]->toString(exec).domString(), exception); 2147 return jsUndefined(); 2148 default: 2149 break; 2150 } 2151 return jsUndefined(); 2152 } 2153 2154 // ------------------------------------------------------------------------- 2155 2156 const ClassInfo DOMText::info = { "Text", &DOMCharacterData::info, 2157 &DOMTextTable, nullptr 2158 }; 2159 2160 /* 2161 @begin DOMTextTable 2 2162 wholeText DOMText::WholeText DontDelete|ReadOnly 2163 @end 2164 @begin DOMTextProtoTable 2 2165 splitText DOMText::SplitText DontDelete|Function 1 2166 replaceWholeText DOMText::ReplaceWholeText DontDelete|Function 1 2167 @end 2168 */ 2169 KJS_DEFINE_PROTOTYPE(DOMTextProto) 2170 KJS_IMPLEMENT_PROTOFUNC(DOMTextProtoFunc) 2171 KJS_IMPLEMENT_PROTOTYPE("DOMText", DOMTextProto, DOMTextProtoFunc, DOMCharacterDataProto) 2172 2173 DOMText::DOMText(ExecState *exec, DOM::TextImpl *t) 2174 : DOMCharacterData(exec, t) 2175 { 2176 setPrototype(DOMTextProto::self(exec)); 2177 } 2178 2179 bool DOMText::getOwnPropertySlot(ExecState *exec, 2180 const Identifier &propertyName, 2181 PropertySlot &slot) 2182 { 2183 return getStaticValueSlot<DOMText, DOMCharacterData>(exec, &DOMTextTable, this, propertyName, slot); 2184 } 2185 2186 JSValue *DOMText::getValueProperty(ExecState *, int token) const 2187 { 2188 TextImpl *text = static_cast<TextImpl *>(impl()); 2189 switch (token) { 2190 case WholeText: 2191 return jsString(text->wholeText()); 2192 } 2193 return jsNull(); // not reached 2194 } 2195 2196 JSValue *DOMTextProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 2197 { 2198 KJS_CHECK_THIS(KJS::DOMText, thisObj); 2199 DOM::TextImpl &text = *static_cast<DOMText *>(thisObj)->impl(); 2200 DOMExceptionTranslator exception(exec); 2201 switch (id) { 2202 case DOMText::SplitText: 2203 return getDOMNode(exec, text.splitText(args[0]->toInteger(exec), exception)); 2204 case DOMText::ReplaceWholeText: 2205 return getDOMNode(exec, text.replaceWholeText(args[0]->toString(exec).domString(), exception)); 2206 default: 2207 break; 2208 } 2209 return jsUndefined(); 2210 } 2211 2212 // ------------------------------------------------------------------------- 2213 2214 const ClassInfo DOMComment::info = { "Comment", 2215 &DOMCharacterData::info, nullptr, nullptr 2216 }; 2217 /* 2218 @begin DOMCommentProtoTable 1 2219 @end 2220 */ 2221 2222 KJS_DEFINE_PROTOTYPE(DOMCommentProto) 2223 KJS_IMPLEMENT_PROTOFUNC(DOMCommentProtoFunc) 2224 KJS_IMPLEMENT_PROTOTYPE("DOMComment", DOMCommentProto, DOMCommentProtoFunc, DOMCharacterDataProto) 2225 2226 DOMComment::DOMComment(ExecState *exec, DOM::CommentImpl *d) 2227 : DOMCharacterData(exec, d) 2228 { 2229 setPrototype(DOMCommentProto::self(exec)); 2230 } 2231 2232 JSValue *DOMCommentProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List & /*args*/) 2233 { 2234 KJS_CHECK_THIS(KJS::DOMComment, thisObj); 2235 return jsUndefined(); 2236 } 2237 2238 // ------------------------------------------------------------------------- 2239 2240 const ClassInfo DOMDocumentFragment::info = { "DocumentFragment", 2241 &DOMNode::info, nullptr, nullptr 2242 }; 2243 /* 2244 @begin DOMDocumentFragmentProtoTable 2 2245 querySelector DOMDocumentFragment::QuerySelector DontDelete|Function 1 2246 querySelectorAll DOMDocumentFragment::QuerySelectorAll DontDelete|Function 1 2247 @end 2248 */ 2249 2250 KJS_DEFINE_PROTOTYPE(DOMDocumentFragmentProto) 2251 KJS_IMPLEMENT_PROTOFUNC(DOMDocumentFragmentProtoFunc) 2252 KJS_IMPLEMENT_PROTOTYPE("DocumentFragment", DOMDocumentFragmentProto, 2253 DOMDocumentFragmentProtoFunc, DOMNodeProto) 2254 IMPLEMENT_PSEUDO_CONSTRUCTOR(DocumentFragmentPseudoCtor, "DocumentFragment", DOMDocumentFragmentProto) 2255 2256 DOMDocumentFragment::DOMDocumentFragment(ExecState *exec, DOM::DocumentFragmentImpl *i) 2257 : DOMNode(exec, i) 2258 { 2259 setPrototype(DOMDocumentFragmentProto::self(exec)); 2260 } 2261 2262 JSValue *DOMDocumentFragmentProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 2263 { 2264 KJS_CHECK_THIS(KJS::DOMDocumentFragment, thisObj); 2265 DOMExceptionTranslator exception(exec); 2266 2267 DOM::NodeImpl *n = static_cast<DOMDocumentFragment *>(thisObj)->impl(); 2268 DOM::DOMString s = args[0]->toString(exec).domString(); 2269 2270 switch (id) { 2271 case DOMDocumentFragment::QuerySelector: { 2272 RefPtr<DOM::ElementImpl> e = n->querySelector(s, exception); 2273 return getDOMNode(exec, e.get()); 2274 } 2275 case DOMDocumentFragment::QuerySelectorAll: { 2276 RefPtr<DOM::NodeListImpl> l = n->querySelectorAll(s, exception); 2277 return getDOMNodeList(exec, l.get()); 2278 } 2279 } 2280 return jsUndefined(); 2281 } 2282