diff options
Diffstat (limited to 'khtml/ecma/kjs_traversal.cpp')
-rw-r--r-- | khtml/ecma/kjs_traversal.cpp | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/khtml/ecma/kjs_traversal.cpp b/khtml/ecma/kjs_traversal.cpp new file mode 100644 index 000000000..5b521b6d5 --- /dev/null +++ b/khtml/ecma/kjs_traversal.cpp @@ -0,0 +1,327 @@ +// -*- c-basic-offset: 2 -*- +/* + * This file is part of the KDE libraries + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "kjs_traversal.h" +#include "kjs_traversal.lut.h" +#include "kjs_proxy.h" +#include <dom/dom_node.h> +#include <xml/dom_nodeimpl.h> +#include <xml/dom_docimpl.h> +#include <khtmlview.h> +#include <khtml_part.h> +#include <kdebug.h> + +namespace KJS { + +// ------------------------------------------------------------------------- + +const ClassInfo DOMNodeIterator::info = { "NodeIterator", 0, &DOMNodeIteratorTable, 0 }; +/* +@begin DOMNodeIteratorTable 5 + root DOMNodeIterator::Root DontDelete|ReadOnly + whatToShow DOMNodeIterator::WhatToShow DontDelete|ReadOnly + filter DOMNodeIterator::Filter DontDelete|ReadOnly + expandEntityReferences DOMNodeIterator::ExpandEntityReferences DontDelete|ReadOnly +@end +@begin DOMNodeIteratorProtoTable 3 + nextNode DOMNodeIterator::NextNode DontDelete|Function 0 + previousNode DOMNodeIterator::PreviousNode DontDelete|Function 0 + detach DOMNodeIterator::Detach DontDelete|Function 0 +@end +*/ +KJS_DEFINE_PROTOTYPE(DOMNodeIteratorProto) +IMPLEMENT_PROTOFUNC_DOM(DOMNodeIteratorProtoFunc) +KJS_IMPLEMENT_PROTOTYPE("DOMNodeIterator", DOMNodeIteratorProto,DOMNodeIteratorProtoFunc) + +DOMNodeIterator::DOMNodeIterator(ExecState *exec, DOM::NodeIterator ni) + : DOMObject(DOMNodeIteratorProto::self(exec)), nodeIterator(ni) {} + +DOMNodeIterator::~DOMNodeIterator() +{ + ScriptInterpreter::forgetDOMObject(nodeIterator.handle()); +} + +Value DOMNodeIterator::tryGet(ExecState *exec, const Identifier &p) const +{ + return DOMObjectLookupGetValue<DOMNodeIterator,DOMObject>(exec,p,&DOMNodeIteratorTable,this); +} + +Value DOMNodeIterator::getValueProperty(ExecState *exec, int token) const +{ + DOM::NodeIterator ni(nodeIterator); + switch (token) { + case Root: + return getDOMNode(exec,ni.root()); + case WhatToShow: + return Number(ni.whatToShow()); + case Filter: + return getDOMNodeFilter(exec,ni.filter()); + case ExpandEntityReferences: + return Boolean(ni.expandEntityReferences()); + default: + kdDebug(6070) << "WARNING: Unhandled token in DOMNodeIterator::getValueProperty : " << token << endl; + return Value(); + } +} + +Value DOMNodeIteratorProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &) +{ + KJS_CHECK_THIS( KJS::DOMNodeIterator, thisObj ); + DOM::NodeIterator nodeIterator = static_cast<DOMNodeIterator *>(thisObj.imp())->toNodeIterator(); + switch (id) { + case DOMNodeIterator::PreviousNode: + return getDOMNode(exec,nodeIterator.previousNode()); + case DOMNodeIterator::NextNode: + return getDOMNode(exec,nodeIterator.nextNode()); + case DOMNodeIterator::Detach: + nodeIterator.detach(); + return Undefined(); + } + return Undefined(); +} + +Value getDOMNodeIterator(ExecState *exec, DOM::NodeIterator ni) +{ + return cacheDOMObject<DOM::NodeIterator, DOMNodeIterator>(exec, ni); +} + + +// ------------------------------------------------------------------------- + +const ClassInfo NodeFilterConstructor::info = { "NodeFilterConstructor", 0, &NodeFilterConstructorTable, 0 }; +/* +@begin NodeFilterConstructorTable 17 + FILTER_ACCEPT DOM::NodeFilter::FILTER_ACCEPT DontDelete|ReadOnly + FILTER_REJECT DOM::NodeFilter::FILTER_REJECT DontDelete|ReadOnly + FILTER_SKIP DOM::NodeFilter::FILTER_SKIP DontDelete|ReadOnly + SHOW_ALL DOM::NodeFilter::SHOW_ALL DontDelete|ReadOnly + SHOW_ELEMENT DOM::NodeFilter::SHOW_ELEMENT DontDelete|ReadOnly + SHOW_ATTRIBUTE DOM::NodeFilter::SHOW_ATTRIBUTE DontDelete|ReadOnly + SHOW_TEXT DOM::NodeFilter::SHOW_TEXT DontDelete|ReadOnly + SHOW_CDATA_SECTION DOM::NodeFilter::SHOW_CDATA_SECTION DontDelete|ReadOnly + SHOW_ENTITY_REFERENCE DOM::NodeFilter::SHOW_ENTITY_REFERENCE DontDelete|ReadOnly + SHOW_ENTITY DOM::NodeFilter::SHOW_ENTITY DontDelete|ReadOnly + SHOW_PROCESSING_INSTRUCTION DOM::NodeFilter::SHOW_PROCESSING_INSTRUCTION DontDelete|ReadOnly + SHOW_COMMENT DOM::NodeFilter::SHOW_COMMENT DontDelete|ReadOnly + SHOW_DOCUMENT DOM::NodeFilter::SHOW_DOCUMENT DontDelete|ReadOnly + SHOW_DOCUMENT_TYPE DOM::NodeFilter::SHOW_DOCUMENT_TYPE DontDelete|ReadOnly + SHOW_DOCUMENT_FRAGMENT DOM::NodeFilter::SHOW_DOCUMENT_FRAGMENT DontDelete|ReadOnly + SHOW_NOTATION DOM::NodeFilter::SHOW_NOTATION DontDelete|ReadOnly +@end +*/ + +NodeFilterConstructor::NodeFilterConstructor(ExecState* exec) + : DOMObject(exec->interpreter()->builtinObjectPrototype()) +{ +} + +Value NodeFilterConstructor::tryGet(ExecState *exec, const Identifier &p) const +{ + return DOMObjectLookupGetValue<NodeFilterConstructor,DOMObject>(exec,p,&NodeFilterConstructorTable,this); +} + +Value NodeFilterConstructor::getValueProperty(ExecState *, int token) const +{ + // We use the token as the value to return directly + return Number(token); +} + +Value getNodeFilterConstructor(ExecState *exec) +{ + return cacheGlobalObject<NodeFilterConstructor>(exec, "[[nodeFilter.constructor]]"); +} + +// ------------------------------------------------------------------------- + +const ClassInfo DOMNodeFilter::info = { "NodeFilter", 0, 0, 0 }; +/* +@begin DOMNodeFilterProtoTable 1 + acceptNode DOMNodeFilter::AcceptNode DontDelete|Function 0 +@end +*/ +KJS_DEFINE_PROTOTYPE(DOMNodeFilterProto) +IMPLEMENT_PROTOFUNC_DOM(DOMNodeFilterProtoFunc) +KJS_IMPLEMENT_PROTOTYPE("DOMNodeFilter",DOMNodeFilterProto,DOMNodeFilterProtoFunc) + +DOMNodeFilter::DOMNodeFilter(ExecState *exec, DOM::NodeFilter nf) + : DOMObject(DOMNodeFilterProto::self(exec)), nodeFilter(nf) {} + +DOMNodeFilter::~DOMNodeFilter() +{ + ScriptInterpreter::forgetDOMObject(nodeFilter.handle()); +} + +Value DOMNodeFilterProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) +{ + KJS_CHECK_THIS( KJS::DOMNodeFilter, thisObj ); + DOM::NodeFilter nodeFilter = static_cast<DOMNodeFilter *>(thisObj.imp())->toNodeFilter(); + switch (id) { + case DOMNodeFilter::AcceptNode: + return Number(nodeFilter.acceptNode(toNode(args[0]))); + } + return Undefined(); +} + +Value getDOMNodeFilter(ExecState *exec, DOM::NodeFilter nf) +{ + return cacheDOMObject<DOM::NodeFilter, DOMNodeFilter>(exec, nf); +} + +// ------------------------------------------------------------------------- + +const ClassInfo DOMTreeWalker::info = { "TreeWalker", 0, &DOMTreeWalkerTable, 0 }; +/* +@begin DOMTreeWalkerTable 5 + root DOMTreeWalker::Root DontDelete|ReadOnly + whatToShow DOMTreeWalker::WhatToShow DontDelete|ReadOnly + filter DOMTreeWalker::Filter DontDelete|ReadOnly + expandEntityReferences DOMTreeWalker::ExpandEntityReferences DontDelete|ReadOnly + currentNode DOMTreeWalker::CurrentNode DontDelete +@end +@begin DOMTreeWalkerProtoTable 7 + parentNode DOMTreeWalker::ParentNode DontDelete|Function 0 + firstChild DOMTreeWalker::FirstChild DontDelete|Function 0 + lastChild DOMTreeWalker::LastChild DontDelete|Function 0 + previousSibling DOMTreeWalker::PreviousSibling DontDelete|Function 0 + nextSibling DOMTreeWalker::NextSibling DontDelete|Function 0 + previousNode DOMTreeWalker::PreviousNode DontDelete|Function 0 + nextNode DOMTreeWalker::NextNode DontDelete|Function 0 +@end +*/ +KJS_DEFINE_PROTOTYPE(DOMTreeWalkerProto) +IMPLEMENT_PROTOFUNC_DOM(DOMTreeWalkerProtoFunc) +KJS_IMPLEMENT_PROTOTYPE("DOMTreeWalker", DOMTreeWalkerProto,DOMTreeWalkerProtoFunc) + +DOMTreeWalker::DOMTreeWalker(ExecState *exec, DOM::TreeWalker tw) + : DOMObject(DOMTreeWalkerProto::self(exec)), treeWalker(tw) {} + +DOMTreeWalker::~DOMTreeWalker() +{ + ScriptInterpreter::forgetDOMObject(treeWalker.handle()); +} + +Value DOMTreeWalker::tryGet(ExecState *exec, const Identifier &p) const +{ + return DOMObjectLookupGetValue<DOMTreeWalker,DOMObject>(exec,p,&DOMTreeWalkerTable,this); +} + +Value DOMTreeWalker::getValueProperty(ExecState *exec, int token) const +{ + DOM::TreeWalker tw(treeWalker); + switch (token) { + case Root: + return getDOMNode(exec,tw.root()); + case WhatToShow: + return Number(tw.whatToShow()); + case Filter: + return getDOMNodeFilter(exec,tw.filter()); + case ExpandEntityReferences: + return Boolean(tw.expandEntityReferences()); + case CurrentNode: + return getDOMNode(exec,tw.currentNode()); + default: + kdDebug(6070) << "WARNING: Unhandled token in DOMTreeWalker::getValueProperty : " << token << endl; + return Value(); + } +} + +void DOMTreeWalker::tryPut(ExecState *exec, const Identifier &propertyName, + const Value& value, int attr) +{ + if (propertyName == "currentNode") { + treeWalker.setCurrentNode(toNode(value)); + } + else + ObjectImp::put(exec, propertyName, value, attr); +} + +Value DOMTreeWalkerProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &) +{ + KJS_CHECK_THIS( KJS::DOMTreeWalker, thisObj ); + DOM::TreeWalker treeWalker = static_cast<DOMTreeWalker *>(thisObj.imp())->toTreeWalker(); + switch (id) { + case DOMTreeWalker::ParentNode: + return getDOMNode(exec,treeWalker.parentNode()); + case DOMTreeWalker::FirstChild: + return getDOMNode(exec,treeWalker.firstChild()); + case DOMTreeWalker::LastChild: + return getDOMNode(exec,treeWalker.lastChild()); + case DOMTreeWalker::PreviousSibling: + return getDOMNode(exec,treeWalker.previousSibling()); + case DOMTreeWalker::NextSibling: + return getDOMNode(exec,treeWalker.nextSibling()); + case DOMTreeWalker::PreviousNode: + return getDOMNode(exec,treeWalker.previousSibling()); + case DOMTreeWalker::NextNode: + return getDOMNode(exec,treeWalker.nextNode()); + } + return Undefined(); +} + +Value getDOMTreeWalker(ExecState *exec, DOM::TreeWalker tw) +{ + return cacheDOMObject<DOM::TreeWalker, DOMTreeWalker>(exec, tw); +} + +DOM::NodeFilter toNodeFilter(const Value& val) +{ + Object obj = Object::dynamicCast(val); + if (!obj.isValid() || !obj.inherits(&DOMNodeFilter::info)) + return DOM::NodeFilter(); + + const DOMNodeFilter *dobj = static_cast<const DOMNodeFilter*>(obj.imp()); + return dobj->toNodeFilter(); +} + +// ------------------------------------------------------------------------- + +JSNodeFilter::JSNodeFilter(Object & _filter) : DOM::CustomNodeFilter(), filter( _filter ) +{ +} + +JSNodeFilter::~JSNodeFilter() +{ +} + +short JSNodeFilter::acceptNode(const DOM::Node &n) +{ + KHTMLView *view = static_cast<DOM::DocumentImpl *>( n.handle()->docPtr() )->view(); + if (!view) + return DOM::NodeFilter::FILTER_REJECT; + + KHTMLPart *part = view->part(); + KJSProxy *proxy = part->jScript(); + if (proxy) { + ExecState *exec = proxy->interpreter()->globalExec(); + Object acceptNodeFunc = Object::dynamicCast( filter.get(exec, "acceptNode") ); + if (!acceptNodeFunc.isNull() && acceptNodeFunc.implementsCall()) { + List args; + args.append(getDOMNode(exec,n)); + Value result = acceptNodeFunc.call(exec,filter,args); + if (exec->hadException()) + exec->clearException(); + return result.toInteger(exec); + } + } + + return DOM::NodeFilter::FILTER_REJECT; +} + +} //namespace KJS |