KHtml

kjs_traversal.cpp
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (C) 2001 Peter Kelly ([email protected])
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include "kjs_traversal.h"
21 #include "kjs_traversal.lut.h"
22 #include "kjs_proxy.h"
23 #include <dom/dom_node.h>
24 #include <xml/dom_nodeimpl.h>
25 #include <xml/dom_docimpl.h>
26 #include <khtmlview.h>
27 #include <khtml_part.h>
28 #include "khtml_debug.h"
29 
30 using namespace KJS;
31 
32 namespace KJS
33 {
34 
35 class TraversalExceptionForwarder
36 {
37 public:
38  explicit TraversalExceptionForwarder(ExecState *exec) : m_exec(exec), m_code(nullptr) { }
39  ~TraversalExceptionForwarder()
40  {
41  if (m_code) {
42  m_exec->setException(static_cast<JSValue *>(m_code));
43  }
44  }
45  operator void *&()
46  {
47  return m_code;
48  }
49 private:
50  ExecState *m_exec;
51  void *m_code;
52 };
53 
54 }
55 // -------------------------------------------------------------------------
56 
57 const ClassInfo DOMNodeIterator::info = { "NodeIterator", nullptr, &DOMNodeIteratorTable, nullptr };
58 /*
59 @begin DOMNodeIteratorTable 5
60  root DOMNodeIterator::Root DontDelete|ReadOnly
61  whatToShow DOMNodeIterator::WhatToShow DontDelete|ReadOnly
62  filter DOMNodeIterator::Filter DontDelete|ReadOnly
63  expandEntityReferences DOMNodeIterator::ExpandEntityReferences DontDelete|ReadOnly
64 @end
65 @begin DOMNodeIteratorProtoTable 3
66  nextNode DOMNodeIterator::NextNode DontDelete|Function 0
67  previousNode DOMNodeIterator::PreviousNode DontDelete|Function 0
68  detach DOMNodeIterator::Detach DontDelete|Function 0
69 @end
70 */
71 KJS_DEFINE_PROTOTYPE(DOMNodeIteratorProto)
72 KJS_IMPLEMENT_PROTOFUNC(DOMNodeIteratorProtoFunc)
73 KJS_IMPLEMENT_PROTOTYPE("DOMNodeIterator", DOMNodeIteratorProto, DOMNodeIteratorProtoFunc, ObjectPrototype)
74 
75 DOMNodeIterator::DOMNodeIterator(ExecState *exec, DOM::NodeIteratorImpl *ni)
76  : DOMObject(DOMNodeIteratorProto::self(exec)), m_impl(ni) {}
77 
78 DOMNodeIterator::~DOMNodeIterator()
79 {
80  ScriptInterpreter::forgetDOMObject(m_impl.get());
81 }
82 
83 bool DOMNodeIterator::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
84 {
85  return getStaticValueSlot<DOMNodeIterator, DOMObject>(exec, &DOMNodeIteratorTable, this, propertyName, slot);
86 }
87 
88 JSValue *DOMNodeIterator::getValueProperty(ExecState *exec, int token) const
89 {
90  DOM::NodeIteratorImpl &ni = *impl();
91  switch (token) {
92  case Root:
93  return getDOMNode(exec, ni.root());
94  case WhatToShow:
95  return jsNumber(ni.whatToShow());
96  case Filter:
97  return getDOMNodeFilter(exec, ni.filter());
98  case ExpandEntityReferences:
99  return jsBoolean(ni.expandEntityReferences());
100  default:
101  // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMNodeIterator::getValueProperty : " << token;
102  return nullptr;
103  }
104 }
105 
106 JSValue *DOMNodeIteratorProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &)
107 {
108  KJS_CHECK_THIS(KJS::DOMNodeIterator, thisObj);
109  DOMExceptionTranslator exception(exec);
110  TraversalExceptionForwarder filterException(exec);
111  DOM::NodeIteratorImpl &nodeIterator = *static_cast<DOMNodeIterator *>(thisObj)->impl();
112  switch (id) {
113  case DOMNodeIterator::PreviousNode: {
114  SharedPtr<DOM::NodeImpl> node = nodeIterator.previousNode(exception, filterException);
115  if (!filterException) {
116  return getDOMNode(exec, node.get());
117  }
118  break;
119  }
120  case DOMNodeIterator::NextNode: {
121  SharedPtr<DOM::NodeImpl> node = nodeIterator.nextNode(exception, filterException);
122  if (!filterException) {
123  return getDOMNode(exec, node.get());
124  }
125  break;
126  }
127  case DOMNodeIterator::Detach:
128  nodeIterator.detach(exception);
129  return jsUndefined();
130  }
131  return jsUndefined();
132 }
133 
134 JSValue *KJS::getDOMNodeIterator(ExecState *exec, DOM::NodeIteratorImpl *ni)
135 {
136  return cacheDOMObject<DOM::NodeIteratorImpl, DOMNodeIterator>(exec, ni);
137 }
138 
139 // -------------------------------------------------------------------------
140 
141 const ClassInfo NodeFilterConstructor::info = { "NodeFilterConstructor", nullptr, &NodeFilterConstructorTable, nullptr };
142 /*
143 @begin NodeFilterConstructorTable 17
144  FILTER_ACCEPT DOM::NodeFilter::FILTER_ACCEPT DontDelete|ReadOnly
145  FILTER_REJECT DOM::NodeFilter::FILTER_REJECT DontDelete|ReadOnly
146  FILTER_SKIP DOM::NodeFilter::FILTER_SKIP DontDelete|ReadOnly
147  SHOW_ALL DOM::NodeFilter::SHOW_ALL DontDelete|ReadOnly
148  SHOW_ELEMENT DOM::NodeFilter::SHOW_ELEMENT DontDelete|ReadOnly
149  SHOW_ATTRIBUTE DOM::NodeFilter::SHOW_ATTRIBUTE DontDelete|ReadOnly
150  SHOW_TEXT DOM::NodeFilter::SHOW_TEXT DontDelete|ReadOnly
151  SHOW_CDATA_SECTION DOM::NodeFilter::SHOW_CDATA_SECTION DontDelete|ReadOnly
152  SHOW_ENTITY_REFERENCE DOM::NodeFilter::SHOW_ENTITY_REFERENCE DontDelete|ReadOnly
153  SHOW_ENTITY DOM::NodeFilter::SHOW_ENTITY DontDelete|ReadOnly
154  SHOW_PROCESSING_INSTRUCTION DOM::NodeFilter::SHOW_PROCESSING_INSTRUCTION DontDelete|ReadOnly
155  SHOW_COMMENT DOM::NodeFilter::SHOW_COMMENT DontDelete|ReadOnly
156  SHOW_DOCUMENT DOM::NodeFilter::SHOW_DOCUMENT DontDelete|ReadOnly
157  SHOW_DOCUMENT_TYPE DOM::NodeFilter::SHOW_DOCUMENT_TYPE DontDelete|ReadOnly
158  SHOW_DOCUMENT_FRAGMENT DOM::NodeFilter::SHOW_DOCUMENT_FRAGMENT DontDelete|ReadOnly
159  SHOW_NOTATION DOM::NodeFilter::SHOW_NOTATION DontDelete|ReadOnly
160 @end
161 */
162 
163 NodeFilterConstructor::NodeFilterConstructor(ExecState *exec)
164  : DOMObject(exec->lexicalInterpreter()->builtinObjectPrototype())
165 {
166 }
167 
168 bool NodeFilterConstructor::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
169 {
170  return getStaticValueSlot<NodeFilterConstructor, DOMObject>(exec, &NodeFilterConstructorTable, this, propertyName, slot);
171 }
172 
173 JSValue *NodeFilterConstructor::getValueProperty(ExecState *, int token) const
174 {
175  // We use the token as the value to return directly
176  return jsNumber(token);
177 }
178 
179 JSValue *KJS::getNodeFilterConstructor(ExecState *exec)
180 {
181  return cacheGlobalObject<NodeFilterConstructor>(exec, "[[nodeFilter.constructor]]");
182 }
183 
184 // -------------------------------------------------------------------------
185 
186 const ClassInfo DOMTreeWalker::info = { "TreeWalker", nullptr, &DOMTreeWalkerTable, nullptr };
187 /*
188 @begin DOMTreeWalkerTable 5
189  root DOMTreeWalker::Root DontDelete|ReadOnly
190  whatToShow DOMTreeWalker::WhatToShow DontDelete|ReadOnly
191  filter DOMTreeWalker::Filter DontDelete|ReadOnly
192  expandEntityReferences DOMTreeWalker::ExpandEntityReferences DontDelete|ReadOnly
193  currentNode DOMTreeWalker::CurrentNode DontDelete
194 @end
195 @begin DOMTreeWalkerProtoTable 7
196  parentNode DOMTreeWalker::ParentNode DontDelete|Function 0
197  firstChild DOMTreeWalker::FirstChild DontDelete|Function 0
198  lastChild DOMTreeWalker::LastChild DontDelete|Function 0
199  previousSibling DOMTreeWalker::PreviousSibling DontDelete|Function 0
200  nextSibling DOMTreeWalker::NextSibling DontDelete|Function 0
201  previousNode DOMTreeWalker::PreviousNode DontDelete|Function 0
202  nextNode DOMTreeWalker::NextNode DontDelete|Function 0
203 @end
204 */
205 KJS_DEFINE_PROTOTYPE(DOMTreeWalkerProto)
206 KJS_IMPLEMENT_PROTOFUNC(DOMTreeWalkerProtoFunc)
207 KJS_IMPLEMENT_PROTOTYPE("DOMTreeWalker", DOMTreeWalkerProto, DOMTreeWalkerProtoFunc, ObjectPrototype)
208 
209 DOMTreeWalker::DOMTreeWalker(ExecState *exec, DOM::TreeWalkerImpl *tw)
210  : m_impl(tw)
211 {
212  setPrototype(DOMTreeWalkerProto::self(exec));
213 }
214 
215 DOMTreeWalker::~DOMTreeWalker()
216 {
217  ScriptInterpreter::forgetDOMObject(m_impl.get());
218 }
219 
220 void DOMTreeWalker::mark()
221 {
222  JSObject::mark();
223  JSNodeFilter *filt = JSNodeFilter::fromDOMFilter(impl()->getFilter());
224  if (filt) {
225  filt->mark();
226  }
227 }
228 
229 bool DOMTreeWalker::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
230 {
231  return getStaticValueSlot<DOMTreeWalker, DOMObject>(exec, &DOMTreeWalkerTable, this, propertyName, slot);
232 }
233 
234 JSValue *DOMTreeWalker::getValueProperty(ExecState *exec, int token) const
235 {
236  DOM::TreeWalkerImpl &tw = *impl();
237  switch (token) {
238  case Root:
239  return getDOMNode(exec, tw.getRoot());
240  case WhatToShow:
241  return jsNumber(tw.getWhatToShow());
242  case Filter:
243  return getDOMNodeFilter(exec, tw.getFilter());
244  case ExpandEntityReferences:
245  return jsBoolean(tw.getExpandEntityReferences());
246  case CurrentNode:
247  return getDOMNode(exec, tw.getCurrentNode());
248  default:
249  // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in DOMTreeWalker::getValueProperty : " << token;
250  return nullptr;
251  }
252 }
253 
254 void DOMTreeWalker::put(ExecState *exec, const Identifier &propertyName,
255  JSValue *value, int attr)
256 {
257  DOMExceptionTranslator exception(exec);
258  if (propertyName == "currentNode") {
259  m_impl->setCurrentNode(toNode(value), exception);
260  } else {
261  JSObject::put(exec, propertyName, value, attr);
262  }
263 }
264 
265 JSValue *DOMTreeWalkerProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &)
266 {
267  KJS_CHECK_THIS(KJS::DOMTreeWalker, thisObj);
268  DOM::TreeWalkerImpl &treeWalker = *static_cast<DOMTreeWalker *>(thisObj)->impl();
269  TraversalExceptionForwarder filterException(exec);
270  switch (id) {
271  case DOMTreeWalker::ParentNode:
272  return getDOMNode(exec, treeWalker.parentNode(filterException));
273  case DOMTreeWalker::FirstChild:
274  return getDOMNode(exec, treeWalker.firstChild(filterException));
275  case DOMTreeWalker::LastChild:
276  return getDOMNode(exec, treeWalker.lastChild(filterException));
277  case DOMTreeWalker::PreviousSibling:
278  return getDOMNode(exec, treeWalker.previousSibling(filterException));
279  case DOMTreeWalker::NextSibling:
280  return getDOMNode(exec, treeWalker.nextSibling(filterException));
281  case DOMTreeWalker::PreviousNode:
282  return getDOMNode(exec, treeWalker.previousNode(filterException));
283  case DOMTreeWalker::NextNode:
284  return getDOMNode(exec, treeWalker.nextNode(filterException));
285  }
286  return jsUndefined();
287 }
288 
289 JSValue *KJS::getDOMTreeWalker(ExecState *exec, DOM::TreeWalkerImpl *tw)
290 {
291  return cacheDOMObject<DOM::TreeWalkerImpl, DOMTreeWalker>(exec, tw);
292 }
293 
294 // -------------------------------------------------------------------------
295 
296 DOM::NodeFilterImpl *KJS::toNodeFilter(JSValue *val)
297 {
298  JSObject *obj = val->getObject();
299  if (!obj) {
300  return nullptr;
301  }
302 
303  return new JSNodeFilter(obj);
304 }
305 
306 JSValue *KJS::getDOMNodeFilter(ExecState *exec, DOM::NodeFilterImpl *nf)
307 {
308  Q_UNUSED(exec);
309  if (nf && nf->isJSFilter()) {
310  return static_cast<JSNodeFilter *>(nf)->filter();
311  }
312 
313  return jsNull();
314 }
315 
316 JSNodeFilter::JSNodeFilter(JSObject *_filter) : m_filter(_filter)
317 {}
318 
319 JSNodeFilter::~JSNodeFilter()
320 {}
321 
322 void JSNodeFilter::mark()
323 {
324  if (!m_filter->marked()) {
325  m_filter->mark();
326  }
327 }
328 
329 bool JSNodeFilter::isJSFilter() const
330 {
331  return true;
332 }
333 
334 JSNodeFilter *JSNodeFilter::fromDOMFilter(DOM::NodeFilterImpl *nf)
335 {
336  if (!nf || !nf->isJSFilter()) {
337  return nullptr;
338  }
339 
340  return static_cast<JSNodeFilter *>(nf);
341 }
342 
343 short JSNodeFilter::acceptNode(const DOM::Node &n, void *&bindingsException)
344 {
345  KHTMLPart *part = n.handle()->document()->part();
346  if (!part) {
347  return DOM::NodeFilter::FILTER_REJECT;
348  }
349 
350  KJSProxy *proxy = part->jScript();
351  if (proxy) {
352  ExecState *exec = proxy->interpreter()->globalExec();
353  JSObject *fn = nullptr;
354 
355  // Use a function given directly, or extract it from the acceptNode field
356  if (m_filter->implementsCall()) {
357  fn = m_filter;
358  } else {
359  JSObject *acceptNodeFunc = m_filter->get(exec, "acceptNode")->getObject();
360  if (acceptNodeFunc && acceptNodeFunc->implementsCall()) {
361  fn = acceptNodeFunc;
362  }
363  }
364 
365  if (fn) {
366  List args;
367  args.append(getDOMNode(exec, n.handle()));
368  JSValue *result = fn->call(exec, m_filter, args);
369  if (exec->hadException()) {
370  bindingsException = exec->exception();
371  exec->clearException();
372  return DOM::NodeFilter::FILTER_REJECT; // throw '1' isn't accept :-)
373  }
374  return result->toInteger(exec);
375  }
376  }
377 
378  return DOM::NodeFilter::FILTER_REJECT;
379 }
The Node interface is the primary datatype for the entire Document Object Model.
Definition: dom_node.h:278
virtual ExecState * globalExec()
Base class for all objects in this binding.
Definition: kjs_binding.h:78
void append(JSValue *val)
Proxy class serving as interface when being dlopen&#39;ed.
Definition: kjs_proxy.h:61
This class is khtml&#39;s main class.
Definition: khtml_part.h:208
JSValue * exception() const
bool hadException() const
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
This library provides a full-featured HTML parser and widget.
void clearException()
NodeImpl * handle() const
Definition: dom_node.h:936
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 16 2021 22:47:57 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.