KHtml

kjs_dom.cpp
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (C) 2000 Harri Porten ([email protected])
4  * Copyright (C) 2003 Apple Computer, Inc.
5  * Copyright (C) 2010 Maksim Orlovich ([email protected])
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "kjs_dom.h"
23 #include "kjs_dom.lut.h"
24 
25 #include <khtmlview.h>
26 #include <xml/dom2_eventsimpl.h>
27 #include <rendering/render_canvas.h>
28 #include <rendering/render_layer.h>
29 #include <xml/dom_nodeimpl.h>
30 #include <xml/dom_docimpl.h>
31 #include <xml/dom3_xpathimpl.h>
32 #include <html/html_baseimpl.h>
33 #include <html/html_documentimpl.h>
34 #include <html/html_miscimpl.h>
35 #include "HTMLAudioElement.h"
36 #include "HTMLVideoElement.h"
37 #include "JSHTMLAudioElement.h"
38 #include "JSHTMLVideoElement.h"
39 #include "khtml_debug.h"
40 #include <khtml_part.h>
41 #include <QList>
42 
43 #include "kjs_html.h"
44 #include "kjs_css.h"
45 #include "kjs_range.h"
46 #include "kjs_traversal.h"
47 #include "kjs_events.h"
48 #include "kjs_views.h"
49 #include "kjs_window.h"
50 #include "kjs_xpath.h"
51 #include "kjs_clientrect.h"
52 #include "xmlhttprequest.h"
53 #include <kjs/PropertyNameArray.h>
54 #include <dom/dom_exception.h>
55 #include <dom/html_document.h>
56 #include <khtmlpart_p.h>
57 
58 // for win32, MinGW
59 #undef FOCUS_EVENT
60 #undef CreateEvent
61 
62 using namespace KJS;
63 using namespace khtml;
64 using namespace DOM;
65 
66 // -------------------------------------------------------------------------
67 /* Source for DOMNodeConstantsTable.
68 @begin DOMNodeConstantsTable 21
69  ELEMENT_NODE DOM::Node::ELEMENT_NODE DontDelete|ReadOnly
70  ATTRIBUTE_NODE DOM::Node::ATTRIBUTE_NODE DontDelete|ReadOnly
71  TEXT_NODE DOM::Node::TEXT_NODE DontDelete|ReadOnly
72  CDATA_SECTION_NODE DOM::Node::CDATA_SECTION_NODE DontDelete|ReadOnly
73  ENTITY_REFERENCE_NODE DOM::Node::ENTITY_REFERENCE_NODE DontDelete|ReadOnly
74  ENTITY_NODE DOM::Node::ENTITY_NODE DontDelete|ReadOnly
75  PROCESSING_INSTRUCTION_NODE DOM::Node::PROCESSING_INSTRUCTION_NODE DontDelete|ReadOnly
76  COMMENT_NODE DOM::Node::COMMENT_NODE DontDelete|ReadOnly
77  DOCUMENT_NODE DOM::Node::DOCUMENT_NODE DontDelete|ReadOnly
78  DOCUMENT_TYPE_NODE DOM::Node::DOCUMENT_TYPE_NODE DontDelete|ReadOnly
79  DOCUMENT_FRAGMENT_NODE DOM::Node::DOCUMENT_FRAGMENT_NODE DontDelete|ReadOnly
80  NOTATION_NODE DOM::Node::NOTATION_NODE DontDelete|ReadOnly
81  XPATH_NAMESPACE_NODE DOM::Node::XPATH_NAMESPACE_NODE DontDelete|ReadOnly
82  DOCUMENT_POSITION_DISCONNECTED DOM::Node::DOCUMENT_POSITION_DISCONNECTED DontDelete|ReadOnly
83  DOCUMENT_POSITION_PRECEDING DOM::Node::DOCUMENT_POSITION_PRECEDING DontDelete|ReadOnly
84  DOCUMENT_POSITION_FOLLOWING DOM::Node::DOCUMENT_POSITION_FOLLOWING DontDelete|ReadOnly
85  DOCUMENT_POSITION_CONTAINS DOM::Node::DOCUMENT_POSITION_CONTAINS DontDelete|ReadOnly
86  DOCUMENT_POSITION_CONTAINED_BY DOM::Node::DOCUMENT_POSITION_CONTAINED_BY DontDelete|ReadOnly
87  DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC DOM::Node::DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC DontDelete|ReadOnly
88 @end
89 */
90 IMPLEMENT_CONSTANT_TABLE(DOMNodeConstants, "DOMNodeConstants")
91 
92 // -------------------------------------------------------------------------
93 /* Source for DOMNodeProtoTable.
94 @begin DOMNodeProtoTable 13
95  insertBefore DOMNode::InsertBefore DontDelete|Function 2
96  replaceChild DOMNode::ReplaceChild DontDelete|Function 2
97  removeChild DOMNode::RemoveChild DontDelete|Function 1
98  appendChild DOMNode::AppendChild DontDelete|Function 1
99  hasAttributes DOMNode::HasAttributes DontDelete|Function 0
100  hasChildNodes DOMNode::HasChildNodes DontDelete|Function 0
101  cloneNode DOMNode::CloneNode DontDelete|Function 1
102 # DOM2
103  normalize DOMNode::Normalize DontDelete|Function 0
104  isSupported DOMNode::IsSupported DontDelete|Function 2
105 # DOM3
106  compareDocumentPosition DOMNode::CompareDocumentPosition DontDelete|Function 1
107 # from the EventTarget interface
108  addEventListener DOMNode::AddEventListener DontDelete|Function 3
109  removeEventListener DOMNode::RemoveEventListener DontDelete|Function 3
110  dispatchEvent DOMNode::DispatchEvent DontDelete|Function 1
111 # IE extensions
112  contains DOMNode::Contains DontDelete|Function 1
113  insertAdjacentHTML DOMNode::InsertAdjacentHTML DontDelete|Function 2
114 @end
115 */
116 KJS_IMPLEMENT_PROTOFUNC(DOMNodeProtoFunc)
117 KJS_IMPLEMENT_PROTOTYPE_IMP("DOMNode", DOMNodeProto, DOMNodeProtoFunc, DOMNodeConstants)
118 {
119  // We need to setup the constructor property to the ctor here, but NodeConstructor::self
120  // will try to make us again, since we're in the middle of cacheGlobalObject.
121  // To workaround that, register ourselves so the re-entry of cacheGlobalObject
122  // will pick us. NodeCtor ctor does the same already, to fix the problem
123  // in the other direction.
124  exec->lexicalInterpreter()->globalObject()->put(exec, *name(), this, KJS::Internal | KJS::DontEnum);
125  putDirect(exec->propertyNames().constructor, NodeConstructor::self(exec), DontEnum);
126 }
127 
128 const ClassInfo DOMNode::info = { "Node", nullptr, &DOMNodeTable, nullptr };
129 
130 DOMNode::DOMNode(ExecState *exec, DOM::NodeImpl *n)
131  : DOMObject(DOMNodeProto::self(exec)), m_impl(n)
132 {}
133 
134 DOMNode::DOMNode(JSObject *proto, DOM::NodeImpl *n)
135  : DOMObject(proto), m_impl(n)
136 {}
137 
138 DOMNode::~DOMNode()
139 {
140  ScriptInterpreter::forgetDOMObject(m_impl.get());
141 }
142 
143 bool DOMNode::toBoolean(ExecState *) const
144 {
145  return !m_impl.isNull();
146 }
147 
148 /* Source for DOMNodeTable.
149 @begin DOMNodeTable 53
150  nodeName DOMNode::NodeName DontDelete|ReadOnly
151  nodeValue DOMNode::NodeValue DontDelete
152  nodeType DOMNode::NodeType DontDelete|ReadOnly
153  parentNode DOMNode::ParentNode DontDelete|ReadOnly
154  parentElement DOMNode::ParentElement DontDelete|ReadOnly
155  childNodes DOMNode::ChildNodes DontDelete|ReadOnly
156  firstChild DOMNode::FirstChild DontDelete|ReadOnly
157  lastChild DOMNode::LastChild DontDelete|ReadOnly
158  previousSibling DOMNode::PreviousSibling DontDelete|ReadOnly
159  nextSibling DOMNode::NextSibling DontDelete|ReadOnly
160  attributes DOMNode::Attributes DontDelete|ReadOnly
161  namespaceURI DOMNode::NamespaceURI DontDelete|ReadOnly
162 # DOM2
163  prefix DOMNode::Prefix DontDelete
164  localName DOMNode::LocalName DontDelete|ReadOnly
165  ownerDocument DOMNode::OwnerDocument DontDelete|ReadOnly
166 # DOM3
167  textContent DOMNode::TextContent DontDelete
168 # Event handlers
169 # IE also has: onactivate, onbefore*, oncontextmenu, oncontrolselect, oncut,
170 # ondeactivate, ondrag*, ondrop, onfocusin, onfocusout, onhelp, onmousewheel,
171 # onmove*, onpaste, onpropertychange, onreadystatechange, onresizeend/start,
172 # onselectionchange, onstop
173  onabort DOMNode::OnAbort DontDelete
174  onblur DOMNode::OnBlur DontDelete
175  onchange DOMNode::OnChange DontDelete
176  onclick DOMNode::OnClick DontDelete
177  ondblclick DOMNode::OnDblClick DontDelete
178  ondragdrop DOMNode::OnDragDrop DontDelete
179  onerror DOMNode::OnError DontDelete
180  onfocus DOMNode::OnFocus DontDelete
181  onkeydown DOMNode::OnKeyDown DontDelete
182  onkeypress DOMNode::OnKeyPress DontDelete
183  onkeyup DOMNode::OnKeyUp DontDelete
184  onload DOMNode::OnLoad DontDelete
185  onmousedown DOMNode::OnMouseDown DontDelete
186  onmousemove DOMNode::OnMouseMove DontDelete
187  onmouseout DOMNode::OnMouseOut DontDelete
188  onmouseover DOMNode::OnMouseOver DontDelete
189  onmouseup DOMNode::OnMouseUp DontDelete
190  onmove DOMNode::OnMove DontDelete
191  onreset DOMNode::OnReset DontDelete
192  onresize DOMNode::OnResize DontDelete
193  onscroll DOMNode::OnScroll DontDelete
194  onselect DOMNode::OnSelect DontDelete
195  onsubmit DOMNode::OnSubmit DontDelete
196  onunload DOMNode::OnUnload DontDelete
197 # IE extensions
198  offsetLeft DOMNode::OffsetLeft DontDelete|ReadOnly
199  offsetTop DOMNode::OffsetTop DontDelete|ReadOnly
200  offsetWidth DOMNode::OffsetWidth DontDelete|ReadOnly
201  offsetHeight DOMNode::OffsetHeight DontDelete|ReadOnly
202  offsetParent DOMNode::OffsetParent DontDelete|ReadOnly
203  clientWidth DOMNode::ClientWidth DontDelete|ReadOnly
204  clientHeight DOMNode::ClientHeight DontDelete|ReadOnly
205  clientLeft DOMNode::ClientLeft DontDelete|ReadOnly
206  clientTop DOMNode::ClientTop DontDelete|ReadOnly
207  scrollLeft DOMNode::ScrollLeft DontDelete
208  scrollTop DOMNode::ScrollTop DontDelete
209  scrollWidth DOMNode::ScrollWidth DontDelete|ReadOnly
210  scrollHeight DOMNode::ScrollHeight DontDelete|ReadOnly
211  sourceIndex DOMNode::SourceIndex DontDelete|ReadOnly
212 @end
213 */
214 
215 bool DOMNode::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
216 {
217 #ifdef KJS_VERBOSE
218  qCDebug(KHTML_LOG) << "DOMNode::getOwnPropertySlot " << propertyName.qstring();
219 #endif
220  return getStaticValueSlot<DOMNode, DOMObject>(exec, &DOMNodeTable, this, propertyName, slot);
221 }
222 
223 static khtml::RenderObject *handleBodyRootQuirk(const DOM::NodeImpl *node, khtml::RenderObject *rend, int token)
224 {
225  //This emulates the quirks of various height/width properties on the viewport and root. Note that it
226  //is (mostly) IE-compatible in quirks, and mozilla-compatible in strict.
227  if (!rend) {
228  return nullptr;
229  }
230 
231  bool quirksMode = rend->style() && rend->style()->htmlHacks();
232 
233  //There are a couple quirks here. One is that in quirks mode body is always forwarded to root...
234  //This is relevant for even the scrollTop/scrollLeft type properties.
235  if (quirksMode && node->id() == ID_BODY) {
236  while (rend->parent() && !rend->isRoot()) {
237  rend = rend->parent();
238  }
239  }
240 
241  //Also, some properties of the root are really done in terms of the viewport.
242  //These are {offset/client}{Height/Width}. The offset versions do it only in
243  //quirks mode, the client always.
244  if (!rend->isRoot()) {
245  return rend; //Don't care about non-root things here!
246  }
247  bool needViewport = false;
248 
249  switch (token) {
250  case DOMNode::OffsetHeight:
251  case DOMNode::OffsetWidth:
252  needViewport = quirksMode;
253  break;
254  case DOMNode::ClientHeight:
255  case DOMNode::ClientWidth:
256  case DOMNode::ClientLeft:
257  case DOMNode::ClientTop:
258  needViewport = true;
259  break;
260  }
261 
262  if (needViewport) {
263  //Scan up to find the new target
264  while (rend->parent()) {
265  rend = rend->parent();
266  }
267  }
268  return rend;
269 }
270 
271 JSValue *DOMNode::getValueProperty(ExecState *exec, int token) const
272 {
273  NodeImpl &node = *impl();
274  switch (token) {
275  case NodeName:
276  return jsString(node.nodeName());
277  case NodeValue:
278  return ::getStringOrNull(node.nodeValue()); // initially null, per domts/level1/core/hc_documentcreateelement.html
279  case NodeType:
280  return jsNumber((unsigned int)node.nodeType());
281  case ParentNode:
282  return getDOMNode(exec, node.parentNode());
283  case ParentElement: // IE only apparently
284  return getDOMNode(exec, node.parentNode());
285  case ChildNodes:
286  return getDOMNodeList(exec, node.childNodes().get());
287  case FirstChild:
288  return getDOMNode(exec, node.firstChild());
289  case LastChild:
290  return getDOMNode(exec, node.lastChild());
291  case PreviousSibling:
292  return getDOMNode(exec, node.previousSibling());
293  case NextSibling:
294  return getDOMNode(exec, node.nextSibling());
295  case Attributes: {
296  DOM::NamedNodeMapImpl *attrs = nullptr;
297  if (node.isElementNode()) {
298  DOM::ElementImpl &el = static_cast<DOM::ElementImpl &>(node);
299  attrs = el.attributes();
300  }
301  return getDOMNamedNodeMap(exec, attrs);
302  }
303  case NamespaceURI:
304  return ::getStringOrNull(node.namespaceURI()); // Moz returns null if not set (dom/namespaces.html)
305  case Prefix:
306  return ::getStringOrNull(node.prefix()); // Moz returns null if not set (dom/namespaces.html)
307  case LocalName:
308  return ::getStringOrNull(node.localName()); // Moz returns null if not set (dom/namespaces.html)
309  case OwnerDocument:
310  return getDOMNode(exec, node.ownerDocument());
311  case TextContent:
312  return ::getStringOrNull(node.textContent());
313  case OnAbort:
314  return getListener(DOM::EventImpl::ABORT_EVENT);
315  case OnBlur:
316  return getListener(DOM::EventImpl::BLUR_EVENT);
317  case OnChange:
318  return getListener(DOM::EventImpl::CHANGE_EVENT);
319  case OnClick:
320  return getListener(DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
321  case OnDblClick:
322  return getListener(DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
323  case OnDragDrop:
324  return getListener(DOM::EventImpl::KHTML_DRAGDROP_EVENT);
325  case OnError:
326  return getListener(DOM::EventImpl::ERROR_EVENT);
327  case OnFocus:
328  return getListener(DOM::EventImpl::FOCUS_EVENT);
329  case OnKeyDown:
330  return getListener(DOM::EventImpl::KEYDOWN_EVENT);
331  case OnKeyPress:
332  return getListener(DOM::EventImpl::KEYPRESS_EVENT);
333  case OnKeyUp:
334  return getListener(DOM::EventImpl::KEYUP_EVENT);
335  case OnLoad:
336  return getListener(DOM::EventImpl::LOAD_EVENT);
337  case OnMouseDown:
338  return getListener(DOM::EventImpl::MOUSEDOWN_EVENT);
339  case OnMouseMove:
340  return getListener(DOM::EventImpl::MOUSEMOVE_EVENT);
341  case OnMouseOut:
342  return getListener(DOM::EventImpl::MOUSEOUT_EVENT);
343  case OnMouseOver:
344  return getListener(DOM::EventImpl::MOUSEOVER_EVENT);
345  case OnMouseUp:
346  return getListener(DOM::EventImpl::MOUSEUP_EVENT);
347  case OnMove:
348  return getListener(DOM::EventImpl::KHTML_MOVE_EVENT);
349  case OnReset:
350  return getListener(DOM::EventImpl::RESET_EVENT);
351  case OnResize:
352  return getListener(DOM::EventImpl::RESIZE_EVENT);
353  case OnScroll:
354  return getListener(DOM::EventImpl::SCROLL_EVENT);
355  case OnSelect:
356  return getListener(DOM::EventImpl::SELECT_EVENT);
357  case OnSubmit:
358  return getListener(DOM::EventImpl::SUBMIT_EVENT);
359  case OnUnload:
360  return getListener(DOM::EventImpl::UNLOAD_EVENT);
361  case SourceIndex: {
362  // Retrieves the ordinal position of the object, in source order, as the object
363  // appears in the document's all collection
364  // i.e. document.all[n.sourceIndex] == n
365  DOM::DocumentImpl *doc = node.document();
366  if (doc->isHTMLDocument()) {
367  HTMLCollectionImpl all(doc, HTMLCollectionImpl::DOC_ALL);
368  unsigned long i = 0;
369  for (DOM::NodeImpl *n = all.firstItem(); n; n = all.nextItem()) {
370  if (n == impl()) {
371  return jsNumber(i);
372  }
373  ++i;
374  }
375  }
376  return jsUndefined();
377  }
378  default:
379  // no DOM standard, found in IE only
380 
381  // Make sure our layout is up to date before we allow a query on these attributes.
382  DOM::DocumentImpl *docimpl = node.document();
383  if (docimpl) {
384  docimpl->updateLayout();
385  }
386 
387  khtml::RenderObject *rend = node.renderer();
388 
389  //In quirks mode, may need to forward if to body.
390  rend = handleBodyRootQuirk(impl(), rend, token);
391 
392  switch (token) {
393  case OffsetLeft:
394  return rend ? jsNumber(rend->offsetLeft()) : jsNumber(0);
395  case OffsetTop:
396  return rend ? jsNumber(rend->offsetTop()) : jsNumber(0);
397  case OffsetWidth:
398  return rend ? jsNumber(rend->offsetWidth()) : jsNumber(0);
399  case OffsetHeight:
400  return rend ? jsNumber(rend->offsetHeight()) : jsNumber(0);
401  case OffsetParent: {
402  khtml::RenderObject *par = rend ? rend->offsetParent() : nullptr;
403  return getDOMNode(exec, par ? par->element() : nullptr);
404  }
405  case ClientWidth:
406  return rend ? jsNumber(rend->clientWidth()) : jsNumber(0);
407  case ClientHeight:
408  return rend ? jsNumber(rend->clientHeight()) : jsNumber(0);
409  case ClientLeft:
410  return rend ? jsNumber(rend->clientLeft()) : jsNumber(0);
411  case ClientTop:
412  return rend ? jsNumber(rend->clientTop()) : jsNumber(0);
413  case ScrollWidth:
414  return rend ? jsNumber(rend->scrollWidth()) : jsNumber(0);
415  case ScrollHeight:
416  return rend ? jsNumber(rend->scrollHeight()) : jsNumber(0);
417  case ScrollLeft:
418  if (rend && rend->layer()) {
419  if (rend->isRoot() && !rend->hasOverflowClip()) {
420  return jsNumber(node.document()->view() ? node.document()->view()->contentsX() : 0);
421  }
422  return jsNumber(rend->hasOverflowClip() ? rend->layer()->scrollXOffset() : 0);
423  }
424  return jsNumber(0);
425  case ScrollTop:
426  if (rend && rend->layer()) {
427  if (rend->isRoot() && !rend->hasOverflowClip()) {
428  return jsNumber(node.document()->view() ? node.document()->view()->contentsY() : 0);
429  }
430  return jsNumber(rend->hasOverflowClip() ? rend->layer()->scrollYOffset() : 0);
431  }
432  return jsNumber(0);
433  default:
434  // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMNode::getValueProperty : " << token;
435  break;
436  }
437  }
438  return jsUndefined();
439 }
440 
441 void DOMNode::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
442 {
443 #ifdef KJS_VERBOSE
444  qCDebug(KHTML_LOG) << "DOMNode::tryPut " << propertyName.qstring();
445 #endif
446  lookupPut<DOMNode, DOMObject>(exec, propertyName, value, attr,
447  &DOMNodeTable, this);
448 }
449 
450 void DOMNode::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/)
451 {
452  DOMExceptionTranslator exception(exec);
453  NodeImpl &node = *impl();
454 
455  switch (token) {
456  case NodeValue:
457  node.setNodeValue(value->toString(exec).domString(), exception);
458  break;
459  case Prefix:
460  node.setPrefix(value->toString(exec).domString(), exception);
461  break;
462  case TextContent:
463  node.setTextContent(valueToStringWithNullCheck(exec, value), exception);
464  break;
465  case OnAbort:
466  setListener(exec, DOM::EventImpl::ABORT_EVENT, value);
467  break;
468  case OnBlur:
469  setListener(exec, DOM::EventImpl::BLUR_EVENT, value);
470  break;
471  case OnChange:
472  setListener(exec, DOM::EventImpl::CHANGE_EVENT, value);
473  break;
474  case OnClick:
475  setListener(exec, DOM::EventImpl::KHTML_ECMA_CLICK_EVENT, value);
476  break;
477  case OnDblClick:
478  setListener(exec, DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT, value);
479  break;
480  case OnDragDrop:
481  setListener(exec, DOM::EventImpl::KHTML_DRAGDROP_EVENT, value);
482  break;
483  case OnError:
484  setListener(exec, DOM::EventImpl::ERROR_EVENT, value);
485  break;
486  case OnFocus:
487  setListener(exec, DOM::EventImpl::FOCUS_EVENT, value);
488  break;
489  case OnKeyDown:
490  setListener(exec, DOM::EventImpl::KEYDOWN_EVENT, value);
491  break;
492  case OnKeyPress:
493  setListener(exec, DOM::EventImpl::KEYPRESS_EVENT, value);
494  break;
495  case OnKeyUp:
496  setListener(exec, DOM::EventImpl::KEYUP_EVENT, value);
497  break;
498  case OnLoad:
499  setListener(exec, DOM::EventImpl::LOAD_EVENT, value);
500  break;
501  case OnMouseDown:
502  setListener(exec, DOM::EventImpl::MOUSEDOWN_EVENT, value);
503  break;
504  case OnMouseMove:
505  setListener(exec, DOM::EventImpl::MOUSEMOVE_EVENT, value);
506  break;
507  case OnMouseOut:
508  setListener(exec, DOM::EventImpl::MOUSEOUT_EVENT, value);
509  break;
510  case OnMouseOver:
511  setListener(exec, DOM::EventImpl::MOUSEOVER_EVENT, value);
512  break;
513  case OnMouseUp:
514  setListener(exec, DOM::EventImpl::MOUSEUP_EVENT, value);
515  break;
516  case OnMove:
517  setListener(exec, DOM::EventImpl::KHTML_MOVE_EVENT, value);
518  break;
519  case OnReset:
520  setListener(exec, DOM::EventImpl::RESET_EVENT, value);
521  break;
522  case OnResize:
523  setListener(exec, DOM::EventImpl::RESIZE_EVENT, value);
524  break;
525  case OnScroll:
526  setListener(exec, DOM::EventImpl::SCROLL_EVENT, value);
527  break;
528  case OnSelect:
529  setListener(exec, DOM::EventImpl::SELECT_EVENT, value);
530  break;
531  case OnSubmit:
532  setListener(exec, DOM::EventImpl::SUBMIT_EVENT, value);
533  break;
534  case OnUnload:
535  setListener(exec, DOM::EventImpl::UNLOAD_EVENT, value);
536  break;
537  default:
538  // Make sure our layout is up to date
539  DOM::DocumentImpl *docimpl = node.document();
540  if (docimpl) {
541  docimpl->updateLayout();
542  }
543 
544  khtml::RenderObject *rend = node.renderer();
545 
546  //In quirks mode, may need to forward.
547  rend = handleBodyRootQuirk(impl(), rend, token);
548 
549  switch (token) {
550  case ScrollLeft:
551  if (rend && rend->layer()) {
552  if (rend->hasOverflowClip()) {
553  rend->layer()->scrollToXOffset(value->toInt32(exec));
554  } else if (rend->isRoot()) {
555  KHTMLView *sview = node.document()->view();
556  if (sview) {
557  sview->setContentsPos(value->toInt32(exec), sview->contentsY());
558  }
559  }
560  }
561  break;
562  case ScrollTop:
563  if (rend && rend->layer()) {
564  if (rend->hasOverflowClip()) {
565  rend->layer()->scrollToYOffset(value->toInt32(exec));
566  } else if (rend->isRoot()) {
567  KHTMLView *sview = node.document()->view();
568  if (sview) {
569  sview->setContentsPos(sview->contentsX(), value->toInt32(exec));
570  }
571  }
572  }
573  break;
574  default:
575  // qCDebug(KHTML_LOG) << "WARNING: DOMNode::putValueProperty unhandled token " << token;
576  break;
577  }
578  }
579 }
580 
581 JSValue *DOMNode::toPrimitive(ExecState *exec, JSType /*preferred*/) const
582 {
583  if (m_impl.isNull()) {
584  return jsNull();
585  }
586 
587  return jsString(toString(exec));
588 }
589 
590 UString DOMNode::toString(ExecState *) const
591 {
592  if (m_impl.isNull()) {
593  return "null";
594  }
595  return "[object " + className() + "]";
596 }
597 
598 void DOMNode::setListener(ExecState *exec, int eventId, JSValue *func) const
599 {
600  m_impl->setHTMLEventListener(eventId, Window::retrieveActive(exec)->getJSEventListener(func, true));
601 }
602 
603 JSValue *DOMNode::getListener(int eventId) const
604 {
605  DOM::EventListener *listener = m_impl->getHTMLEventListener(eventId);
606  JSEventListener *jsListener = static_cast<JSEventListener *>(listener);
607  if (jsListener && jsListener->listenerObj()) {
608  return jsListener->listenerObj();
609  } else {
610  return jsNull();
611  }
612 }
613 
614 void DOMNode::pushEventHandlerScope(ExecState *, ScopeChain &) const
615 {
616 }
617 
618 JSValue *DOMNodeProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
619 {
620  KJS_CHECK_THIS(DOMNode, thisObj);
621  DOMExceptionTranslator exception(exec);
622  DOM::NodeImpl &node = *static_cast<DOMNode *>(thisObj)->impl();
623  switch (id) {
624  case DOMNode::HasAttributes:
625  return jsBoolean(node.hasAttributes());
626  case DOMNode::HasChildNodes:
627  return jsBoolean(node.hasChildNodes());
628  case DOMNode::CloneNode: {
629  RefPtr<NodeImpl> clone = node.cloneNode(args[0]->toBoolean(exec));
630  return getDOMNode(exec, clone.get());
631  }
632  case DOMNode::Normalize:
633  node.normalize();
634  return jsUndefined();
635  case DOMNode::IsSupported:
636  return jsBoolean(node.isSupported(args[0]->toString(exec).domString(), args[1]->toString(exec).domString()));
637  case DOMNode::AddEventListener: {
638  JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
639  EventName id = EventName::fromString(args[0]->toString(exec).domString());
640  node.addEventListener(id, listener, args[2]->toBoolean(exec));
641  return jsUndefined();
642  }
643  case DOMNode::RemoveEventListener: {
644  JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
645  EventName id = EventName::fromString(args[0]->toString(exec).domString());
646  node.removeEventListener(id, listener, args[2]->toBoolean(exec));
647  return jsUndefined();
648  }
649  case DOMNode::DispatchEvent: {
650  SharedPtr<DOM::EventImpl> evt = toEvent(args[0]);
651  if (!evt) {
652  setDOMException(exec, DOMException::NOT_FOUND_ERR);
653  return jsUndefined();
654  }
655  node.dispatchEvent(evt.get(), exception);
656  return jsBoolean(!evt->defaultPrevented());
657  }
658  case DOMNode::AppendChild:
659  return getDOMNode(exec, node.appendChild(toNode(args[0]), exception));
660  case DOMNode::RemoveChild: {
661  SharedPtr<DOM::NodeImpl> oldKid = toNode(args[0]);
662  node.removeChild(oldKid.get(), exception);
663  return getDOMNode(exec, oldKid.get());
664  }
665  case DOMNode::InsertBefore:
666  return getDOMNode(exec, node.insertBefore(toNode(args[0]), toNode(args[1]), exception));
667  case DOMNode::ReplaceChild: {
668  SharedPtr<DOM::NodeImpl> oldKid = toNode(args[1]);
669  node.replaceChild(toNode(args[0]), oldKid.get(), exception);
670  return getDOMNode(exec, oldKid.get());
671  }
672  case DOMNode::Contains: {
673  DOM::NodeImpl *other = toNode(args[0]);
674  if (other && other->isElementNode()) {
675  return jsBoolean(other->isAncestor(&node));
676  }
677  setDOMException(exec, DOMException::TYPE_MISMATCH_ERR); // ### a guess
678  return jsUndefined();
679  }
680  case DOMNode::InsertAdjacentHTML: {
681  // see http://www.faqts.com/knowledge_base/view.phtml/aid/5756
682  // and http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/insertAdjacentHTML.asp
683  SharedPtr<DOM::RangeImpl> range = node.document()->createRange();
684 
685  range->setStartBefore(&node, exception);
686  if (exception.triggered()) {
687  return jsUndefined();
688  }
689 
690  SharedPtr<DOM::DocumentFragmentImpl> docFrag =
691  static_cast<DOM::DocumentFragmentImpl *>(range->createContextualFragment(args[1]->toString(exec).domString(), exception).handle());
692  if (exception.triggered()) {
693  return jsUndefined();
694  }
695 
696  DOMString where = args[0]->toString(exec).domString().lower();
697 
698  if (where == "beforebegin") {
699  node.parentNode()->insertBefore(docFrag.get(), &node, exception);
700  } else if (where == "afterbegin") {
701  node.insertBefore(docFrag.get(), node.firstChild(), exception);
702  } else if (where == "beforeend") {
703  return getDOMNode(exec, node.appendChild(docFrag.get(), exception));
704  } else if (where == "afterend") {
705  if (node.nextSibling()) {
706  node.parentNode()->insertBefore(docFrag.get(), node.nextSibling(), exception);
707  } else {
708  node.parentNode()->appendChild(docFrag.get(), exception);
709  }
710  }
711 
712  return jsUndefined();
713  }
714  case DOMNode::CompareDocumentPosition: {
715  DOM::NodeImpl *other = toNode(args[0]);
716  if (!other) {
717  setDOMException(exec, DOMException::TYPE_MISMATCH_ERR);
718  } else {
719  return jsNumber(node.compareDocumentPosition(other));
720  }
721  }
722  }
723 
724  return jsUndefined();
725 }
726 
727 // -------------------------------------------------------------------------
728 
729 /*
730 @begin DOMNodeListProtoTable 2
731  item DOMNodeList::Item DontDelete|Function 1
732 # IE extension (IE treats DOMNodeList like an HTMLCollection)
733  namedItem DOMNodeList::NamedItem DontDelete|Function 1
734 @end
735 */
736 KJS_DEFINE_PROTOTYPE(DOMNodeListProto)
737 KJS_IMPLEMENT_PROTOFUNC(DOMNodeListProtoFunc)
738 KJS_IMPLEMENT_PROTOTYPE("DOMNodeList", DOMNodeListProto, DOMNodeListProtoFunc, ObjectPrototype)
739 
740 IMPLEMENT_PSEUDO_CONSTRUCTOR(NodeListPseudoCtor, "NodeList", DOMNodeListProto)
741 
742 const ClassInfo DOMNodeList::info = { "NodeList", nullptr, nullptr, nullptr };
743 
744 DOMNodeList::DOMNodeList(ExecState *exec, DOM::NodeListImpl *l)
745  : DOMObject(DOMNodeListProto::self(exec)), m_impl(l) { }
746 
747 DOMNodeList::~DOMNodeList()
748 {
749  ScriptInterpreter::forgetDOMObject(m_impl.get());
750 }
751 
752 JSValue *DOMNodeList::indexGetter(ExecState *exec, unsigned index)
753 {
754  return getDOMNode(exec, m_impl->item(index));
755 }
756 
757 JSValue *DOMNodeList::nameGetter(ExecState *exec, JSObject *, const Identifier &name, const PropertySlot &slot)
758 {
759  DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
760  return getDOMNode(exec, thisObj->getByName(name));
761 }
762 
763 JSValue *DOMNodeList::lengthGetter(ExecState *, JSObject *, const Identifier &, const PropertySlot &slot)
764 {
765  DOMNodeList *thisObj = static_cast<DOMNodeList *>(slot.slotBase());
766  return jsNumber(thisObj->m_impl->length());
767 }
768 
769 DOM::NodeImpl *DOMNodeList::getByName(const Identifier &name)
770 {
771  //### M.O.: I bet IE checks name only for some tags.
772  DOMString domName = name.domString();
773  unsigned long l = m_impl->length();
774  for (unsigned long i = 0; i < l; i++) {
775  DOM::NodeImpl *n = m_impl->item(i);
776  if (n->isElementNode()) {
777  DOM::ElementImpl *e = static_cast<DOM::ElementImpl *>(n);
778  if (e->getAttribute(ATTR_ID) == domName || e->getAttribute(ATTR_NAME) == domName) {
779  return n;
780  }
781  }
782  }
783  return nullptr;
784 }
785 
786 bool DOMNodeList::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
787 {
788  if (propertyName == exec->propertyNames().length) {
789  slot.setCustom(this, lengthGetter);
790  return true;
791  }
792 
793  //### this could benefit from further nodelist/collection consolidation,
794  //including moving nameditem down to nodelists.
795 
796  // Look in the prototype (for functions) before assuming it's an item's name
797  JSObject *proto = prototype()->getObject();
798  if (proto && proto->hasProperty(exec, propertyName)) {
799  return false;
800  }
801 
802  //May be it's an index?
803  if (getIndexSlot(this, *m_impl, propertyName, slot)) {
804  return true;
805  }
806 
807  //May be it's a name -- check by ID
808  //Check by id
809  if (getByName(propertyName)) {
810  slot.setCustom(this, nameGetter);
811  return true;
812  }
813 
814  return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
815 }
816 
817 void DOMNodeList::getOwnPropertyNames(ExecState *exec, PropertyNameArray &propertyNames, PropertyMap::PropertyMode mode)
818 {
819  for (unsigned i = 0; i < m_impl->length(); ++i) {
820  propertyNames.add(Identifier::from(i));
821  }
822 
823  propertyNames.add(exec->propertyNames().length);
824 
825  JSObject::getOwnPropertyNames(exec, propertyNames, mode);
826 }
827 
828 // Need to support both get and call, so that list[0] and list(0) work.
829 JSValue *DOMNodeList::callAsFunction(ExecState *exec, JSObject *, const List &args)
830 {
831  // Do not use thisObj here. See HTMLCollection.
832  UString s = args[0]->toString(exec);
833 
834  // index-based lookup?
835  bool ok;
836  unsigned int u = s.qstring().toULong(&ok);
837  if (ok) {
838  return getDOMNode(exec, m_impl->item(u));
839  }
840 
841  // try lookup by name
842  // ### NodeList::namedItem() would be cool to have
843  // ### do we need to support the same two arg overload as in HTMLCollection?
844  JSValue *result = get(exec, Identifier(s));
845 
846  if (result) {
847  return result;
848  }
849 
850  return jsUndefined();
851 }
852 
853 JSValue *DOMNodeListProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
854 {
855  KJS_CHECK_THIS(KJS::DOMNodeList, thisObj);
856  DOMNodeList *jsList = static_cast<DOMNodeList *>(thisObj);
857  DOM::NodeListImpl &list = *jsList->impl();
858  switch (id) {
859  case KJS::DOMNodeList::Item:
860  return getDOMNode(exec, list.item(args[0]->toInt32(exec)));
861  case KJS::DOMNodeList::NamedItem:
862  return getDOMNode(exec, jsList->getByName(Identifier(args[0]->toString(exec))));
863  default:
864  return jsUndefined();
865  }
866 }
867 
868 // -------------------------------------------------------------------------
869 
870 //### FIXME: link to the node prototype.
871 const ClassInfo DOMAttr::info = { "Attr", &DOMNode::info, &DOMAttrTable, nullptr };
872 
873 /* Source for DOMAttrTable.
874 @begin DOMAttrTable 5
875  name DOMAttr::Name DontDelete|ReadOnly
876  specified DOMAttr::Specified DontDelete|ReadOnly
877  value DOMAttr::ValueProperty DontDelete
878  ownerElement DOMAttr::OwnerElement DontDelete|ReadOnly
879 @end
880 */
881 bool DOMAttr::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
882 {
883 #ifdef KJS_VERBOSE
884  qCDebug(KHTML_LOG) << "DOMAttr::tryGet " << propertyName.qstring();
885 #endif
886  return getStaticValueSlot<DOMAttr, DOMNode>(exec, &DOMAttrTable, this, propertyName, slot);
887 }
888 
889 JSValue *DOMAttr::getValueProperty(ExecState *exec, int token) const
890 {
891  AttrImpl *attr = static_cast<AttrImpl *>(impl());
892  switch (token) {
893  case Name:
894  return jsString(attr->name());
895  case Specified:
896  return jsBoolean(attr->specified());
897  case ValueProperty:
898  return jsString(attr->nodeValue());
899  case OwnerElement: // DOM2
900  return getDOMNode(exec, attr->ownerElement());
901  }
902  return jsNull(); // not reached
903 }
904 
905 void DOMAttr::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr)
906 {
907 #ifdef KJS_VERBOSE
908  qCDebug(KHTML_LOG) << "DOMAttr::tryPut " << propertyName.qstring();
909 #endif
910  lookupPut<DOMAttr, DOMNode>(exec, propertyName, value, attr,
911  &DOMAttrTable, this);
912 }
913 
914 void DOMAttr::putValueProperty(ExecState *exec, int token, JSValue *value, int /*attr*/)
915 {
916  DOMExceptionTranslator exception(exec);
917  switch (token) {
918  case ValueProperty:
919  static_cast<AttrImpl *>(impl())->setValue(value->toString(exec).domString(), exception);
920  return;
921  default:
922  qCWarning(KHTML_LOG) << "DOMAttr::putValueProperty unhandled token " << token;
923  }
924 }
925 
926 AttrImpl *toAttr(JSValue *val)
927 {
928  if (!val || !val->isObject(&DOMAttr::info)) {
929  return nullptr;
930  }
931  return static_cast<AttrImpl *>(static_cast<DOMNode *>(val)->impl());
932 }
933 
934 // -------------------------------------------------------------------------
935 
936 /* Source for DOMDocumentProtoTable.
937 @begin DOMDocumentProtoTable 23
938  createElement DOMDocument::CreateElement DontDelete|Function 1
939  createDocumentFragment DOMDocument::CreateDocumentFragment DontDelete|Function 1
940  createTextNode DOMDocument::CreateTextNode DontDelete|Function 1
941  createComment DOMDocument::CreateComment DontDelete|Function 1
942  createCDATASection DOMDocument::CreateCDATASection DontDelete|Function 1
943  createProcessingInstruction DOMDocument::CreateProcessingInstruction DontDelete|Function 1
944  createAttribute DOMDocument::CreateAttribute DontDelete|Function 1
945  createEntityReference DOMDocument::CreateEntityReference DontDelete|Function 1
946  getElementsByTagName DOMDocument::GetElementsByTagName DontDelete|Function 1
947  importNode DOMDocument::ImportNode DontDelete|Function 2
948  createElementNS DOMDocument::CreateElementNS DontDelete|Function 2
949  createAttributeNS DOMDocument::CreateAttributeNS DontDelete|Function 2
950  getElementsByTagNameNS DOMDocument::GetElementsByTagNameNS DontDelete|Function 2
951  getElementById DOMDocument::GetElementById DontDelete|Function 1
952  createRange DOMDocument::CreateRange DontDelete|Function 0
953  createNodeIterator DOMDocument::CreateNodeIterator DontDelete|Function 3
954  createTreeWalker DOMDocument::CreateTreeWalker DontDelete|Function 4
955  createEvent DOMDocument::CreateEvent DontDelete|Function 1
956  getOverrideStyle DOMDocument::GetOverrideStyle DontDelete|Function 2
957  abort DOMDocument::Abort DontDelete|Function 0
958  load DOMDocument::Load DontDelete|Function 1
959  loadXML DOMDocument::LoadXML DontDelete|Function 2
960  execCommand DOMDocument::ExecCommand DontDelete|Function 3
961  queryCommandEnabled DOMDocument::QueryCommandEnabled DontDelete|Function 1
962  queryCommandIndeterm DOMDocument::QueryCommandIndeterm DontDelete|Function 1
963  queryCommandState DOMDocument::QueryCommandState DontDelete|Function 1
964  queryCommandSupported DOMDocument::QueryCommandSupported DontDelete|Function 1
965  queryCommandValue DOMDocument::QueryCommandValue DontDelete|Function 1
966  getElementsByClassName DOMDocument::GetElementsByClassName DontDelete|Function 1
967  querySelector DOMDocument::QuerySelector DontDelete|Function 1
968  querySelectorAll DOMDocument::QuerySelectorAll DontDelete|Function 1
969  createExpression DOMDocument::CreateExpression DontDelete|Function 2
970  createNSResolver DOMDocument::CreateNSResolver DontDelete|Function 1
971  evaluate DOMDocument::Evaluate DontDelete|Function 4
972 @end
973 */
974 
975 KJS_IMPLEMENT_PROTOFUNC(DOMDocumentProtoFunc)
976 KJS_IMPLEMENT_PROTOTYPE("DOMDocument", DOMDocumentProto, DOMDocumentProtoFunc, DOMNodeProto)
977 
978 IMPLEMENT_PSEUDO_CONSTRUCTOR(DocumentPseudoCtor, "Document", DOMDocumentProto)
979 
980 const ClassInfo DOMDocument::info = { "Document", &DOMNode::info, &DOMDocumentTable, nullptr };
981 
982 /* Source for DOMDocumentTable.
983 @begin DOMDocumentTable 4
984  doctype DOMDocument::DocType DontDelete|ReadOnly
985  implementation DOMDocument::Implementation DontDelete|ReadOnly
986  characterSet DOMDocument::CharacterSet DontDelete|ReadOnly
987  documentElement DOMDocument::DocumentElement DontDelete|ReadOnly
988  styleSheets DOMDocument::StyleSheets DontDelete|ReadOnly
989  preferredStylesheetSet DOMDocument::PreferredStylesheetSet DontDelete|ReadOnly
990  selectedStylesheetSet DOMDocument::SelectedStylesheetSet DontDelete
991  readyState DOMDocument::ReadyState DontDelete|ReadOnly
992  defaultView DOMDocument::DefaultView DontDelete|ReadOnly
993  async DOMDocument::Async DontDelete
994  title DOMDocument::Title DontDelete
995 @end
996 */
997 
998 DOMDocument::DOMDocument(ExecState *exec, DOM::DocumentImpl *d)
999  : 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 &nota = *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 
QString url(QUrl::FormattingOptions options) const const
ulong toULong(bool *ok, int base) const const
KJS_EXTERNAL_EXPORT QString qstring() const
The Node interface is the primary datatype for the entire Document Object Model.
Definition: dom_node.h:278
QString name(const QVariant &location)
Base class for all objects in this binding.
Definition: kjs_binding.h:78
Interpreter * dynamicInterpreter() const
KJOBWIDGETS_EXPORT QWidget * window(KJob *job)
An HTMLDocument is the root of the HTML hierarchy and holds the entire content.
Definition: html_document.h:74
KJS_EXTERNAL_EXPORT QString qstring() const
int size() const
int length() const const
This file is part of the HTML rendering engine for KDE.
int contentsY() const
Returns the y coordinate of the contents area point that is currently located at the top left in the ...
Definition: khtmlview.cpp:714
const T & at(int i) const const
QString host(QUrl::ComponentFormattingOptions options) const const
This class is khtml&#39;s main class.
Definition: khtml_part.h:208
The DOMImplementation interface provides a number of methods for performing operations that are indep...
Definition: dom_doc.h:78
DocumentFragment is a "lightweight" or "minimal" Document object.
Definition: dom_doc.h:1042
Renders and displays HTML in a QScrollArea.
Definition: khtmlview.h:97
void setContentsPos(int x, int y)
Place the contents area point x/y at the top left of the viewport.
Definition: khtmlview.cpp:751
DOM operations only raise exceptions in "exceptional" circumstances, i.e., when an operation is impos...
Definition: dom_exception.h:58
KHTMLView * view() const
Returns a pointer to the HTML document&#39;s view.
Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can b...
Definition: dom_node.h:64
DOMString completeURL(const DOMString &url) const
not part of the DOM
We inherit from Interpreter, to save a pointer to the HTML part that the interpreter runs for...
Definition: kjs_binding.h:96
By far the vast majority of objects (apart from text) that authors encounter when traversing a docume...
Definition: dom_element.h:212
Type type(const QSqlDatabase &db)
The Attr interface represents an attribute in an Element object.
Definition: dom_element.h:89
bool isEmpty() const const
This class implements the basic string we use in the DOM.
Definition: dom_string.h:44
The Document interface represents the entire HTML or XML document.
Definition: dom_doc.h:246
T & first()
QRectF united(const QRectF &rectangle) const const
const UString & ustring() const
The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented.
Definition: dom_node.h:976
Introduced in DOM Level 2.
Definition: dom2_events.h:69
This library provides a full-featured HTML parser and widget.
char * toString(const T &value)
int contentsX() const
Returns the x coordinate of the contents area point that is currently located at the top left in the ...
Definition: khtmlview.cpp:709
Base Class for all rendering tree objects.
JSObject * builtinObjectPrototype() const
DOM::HTMLDocument htmlDocument() const
Returns a reference to the DOM HTML document (for non-HTML documents, returns null) ...
Title
DOM::Document document() const
Returns a reference to the DOM document.
QUrl url() const
NodeImpl * handle() const
Definition: dom_node.h:936
QFuture< void > map(Sequence &sequence, MapFunctor function)
Window
Definition: kjs_window.h:393
All HTML element interfaces derive from this class.
Definition: html_element.h:70
const UChar * data() const
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
KJS_EXTERNAL_EXPORT DOM::DOMString domString() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:05 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.