blob: cd57df3b999d812893154c0a746c70d0c3e68d9c [file] [log] [blame]
/*
* 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 Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "kjs_traversal.h"
#include "Document.h"
#include "Frame.h"
#include "JSNodeFilter.h"
#include "kjs_proxy.h"
#include "kjs_traversal.lut.h"
using namespace WebCore;
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
referenceNode DOMNodeIterator::ReferenceNode DontDelete|ReadOnly
pointerBeforeReferenceNode DOMNodeIterator::PointerBeforeReferenceNode 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)
KJS_IMPLEMENT_PROTOFUNC(DOMNodeIteratorProtoFunc)
KJS_IMPLEMENT_PROTOTYPE("DOMNodeIterator",DOMNodeIteratorProto,DOMNodeIteratorProtoFunc)
DOMNodeIterator::DOMNodeIterator(ExecState *exec, NodeIterator *ni)
: m_impl(ni)
{
setPrototype(DOMNodeIteratorProto::self(exec));
}
DOMNodeIterator::~DOMNodeIterator()
{
ScriptInterpreter::forgetDOMObject(m_impl.get());
}
void DOMNodeIterator::mark()
{
m_impl->filter()->mark();
DOMObject::mark();
}
bool DOMNodeIterator::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
{
return getStaticValueSlot<DOMNodeIterator, DOMObject>(exec, &DOMNodeIteratorTable, this, propertyName, slot);
}
JSValue *DOMNodeIterator::getValueProperty(ExecState *exec, int token) const
{
NodeIterator &ni = *m_impl;
switch (token) {
case Root:
return toJS(exec,ni.root());
case WhatToShow:
return jsNumber(ni.whatToShow());
case Filter:
return toJS(exec,ni.filter());
case ExpandEntityReferences:
return jsBoolean(ni.expandEntityReferences());
case ReferenceNode:
return toJS(exec,ni.referenceNode());
case PointerBeforeReferenceNode:
return jsBoolean(ni.pointerBeforeReferenceNode());
default:
return 0;
}
}
JSValue *DOMNodeIteratorProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &)
{
if (!thisObj->inherits(&KJS::DOMNodeIterator::info))
return throwError(exec, TypeError);
DOMExceptionTranslator exception(exec);
NodeIterator &nodeIterator = *static_cast<DOMNodeIterator *>(thisObj)->impl();
switch (id) {
case DOMNodeIterator::PreviousNode:
return toJS(exec,nodeIterator.previousNode(exception));
case DOMNodeIterator::NextNode:
return toJS(exec,nodeIterator.nextNode(exception));
case DOMNodeIterator::Detach:
nodeIterator.detach(exception);
return jsUndefined();
}
return jsUndefined();
}
JSValue *toJS(ExecState *exec, NodeIterator *ni)
{
return cacheDOMObject<NodeIterator, DOMNodeIterator>(exec, ni);
}
// -------------------------------------------------------------------------
const ClassInfo DOMNodeFilter::info = { "NodeFilter", 0, 0, 0 };
/*
@begin DOMNodeFilterProtoTable 1
acceptNode DOMNodeFilter::AcceptNode DontDelete|Function 0
@end
*/
KJS_DEFINE_PROTOTYPE(DOMNodeFilterProto)
KJS_IMPLEMENT_PROTOFUNC(DOMNodeFilterProtoFunc)
KJS_IMPLEMENT_PROTOTYPE("DOMNodeFilter",DOMNodeFilterProto,DOMNodeFilterProtoFunc)
DOMNodeFilter::DOMNodeFilter(ExecState *exec, NodeFilter *nf)
: m_impl(nf)
{
setPrototype(DOMNodeFilterProto::self(exec));
}
DOMNodeFilter::~DOMNodeFilter()
{
ScriptInterpreter::forgetDOMObject(m_impl.get());
}
void DOMNodeFilter::mark()
{
m_impl->mark();
DOMObject::mark();
}
JSValue *DOMNodeFilterProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
{
if (!thisObj->inherits(&KJS::DOMNodeFilter::info))
return throwError(exec, TypeError);
NodeFilter &nodeFilter = *static_cast<DOMNodeFilter *>(thisObj)->impl();
switch (id) {
case DOMNodeFilter::AcceptNode:
return jsNumber(nodeFilter.acceptNode(toNode(args[0])));
}
return jsUndefined();
}
JSValue *toJS(ExecState* exec, NodeFilter* nf)
{
return cacheDOMObject<NodeFilter, JSNodeFilter>(exec, nf);
}
PassRefPtr<NodeFilter> toNodeFilter(JSValue* val)
{
if (!val)
return 0;
if (!val->isObject())
return 0;
if (val->isObject(&DOMNodeFilter::info))
return static_cast<DOMNodeFilter *>(val)->impl();
JSObject* o = static_cast<JSObject*>(val);
if (o->implementsCall())
return new NodeFilter(new JSNodeFilterCondition(o));
return 0;
}
// -------------------------------------------------------------------------
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)
KJS_IMPLEMENT_PROTOFUNC(DOMTreeWalkerProtoFunc)
KJS_IMPLEMENT_PROTOTYPE("DOMTreeWalker",DOMTreeWalkerProto,DOMTreeWalkerProtoFunc)
DOMTreeWalker::DOMTreeWalker(ExecState *exec, TreeWalker *tw)
: m_impl(tw)
{
setPrototype(DOMTreeWalkerProto::self(exec));
}
DOMTreeWalker::~DOMTreeWalker()
{
ScriptInterpreter::forgetDOMObject(m_impl.get());
}
void DOMTreeWalker::mark()
{
m_impl->filter()->mark();
DOMObject::mark();
}
bool DOMTreeWalker::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
{
return getStaticValueSlot<DOMTreeWalker, DOMObject>(exec, &DOMTreeWalkerTable, this, propertyName, slot);
}
JSValue *DOMTreeWalker::getValueProperty(ExecState *exec, int token) const
{
TreeWalker &tw = *m_impl;
switch (token) {
case Root:
return toJS(exec,tw.root());
case WhatToShow:
return jsNumber(tw.whatToShow());
case Filter:
return toJS(exec,tw.filter());
case ExpandEntityReferences:
return jsBoolean(tw.expandEntityReferences());
case CurrentNode:
return toJS(exec,tw.currentNode());
default:
return 0;
}
}
void DOMTreeWalker::put(ExecState *exec, const Identifier &propertyName,
JSValue *value, int attr)
{
if (propertyName == "currentNode") {
DOMExceptionTranslator exception(exec);
m_impl->setCurrentNode(toNode(value), exception);
}
else
JSObject::put(exec, propertyName, value, attr);
}
JSValue *DOMTreeWalkerProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &)
{
if (!thisObj->inherits(&KJS::DOMTreeWalker::info))
return throwError(exec, TypeError);
TreeWalker &treeWalker = *static_cast<DOMTreeWalker *>(thisObj)->impl();
switch (id) {
case DOMTreeWalker::ParentNode:
return toJS(exec,treeWalker.parentNode());
case DOMTreeWalker::FirstChild:
return toJS(exec,treeWalker.firstChild());
case DOMTreeWalker::LastChild:
return toJS(exec,treeWalker.lastChild());
case DOMTreeWalker::PreviousSibling:
return toJS(exec,treeWalker.previousSibling());
case DOMTreeWalker::NextSibling:
return toJS(exec,treeWalker.nextSibling());
case DOMTreeWalker::PreviousNode:
return toJS(exec,treeWalker.previousNode());
case DOMTreeWalker::NextNode:
return toJS(exec,treeWalker.nextNode());
}
return jsUndefined();
}
JSValue *toJS(ExecState *exec, TreeWalker *tw)
{
return cacheDOMObject<TreeWalker, DOMTreeWalker>(exec, tw);
}
// -------------------------------------------------------------------------
JSNodeFilterCondition::JSNodeFilterCondition(JSObject * _filter)
: filter( _filter )
{
}
void JSNodeFilterCondition::mark()
{
filter->mark();
}
short JSNodeFilterCondition::acceptNode(WebCore::Node* filterNode) const
{
WebCore::Node *node = filterNode;
Frame *frame = node->document()->frame();
KJSProxy *proxy = frame->jScript();
if (proxy && filter->implementsCall()) {
JSLock lock;
ExecState *exec = proxy->interpreter()->globalExec();
List args;
args.append(toJS(exec, node));
JSObject *obj = filter;
JSValue *result = obj->call(exec, obj, args);
return result->toInt32(exec);
}
return NodeFilter::FILTER_REJECT;
}
} // namespace