File indexing completed on 2024-04-28 15:23:20

0001 /*
0002  *  This file is part of the KDE libraries
0003  *  Copyright (C) 2010 Maksim Orlovich <maksim@kde.org>
0004  *
0005  *  This library is free software; you can redistribute it and/or
0006  *  modify it under the terms of the GNU Lesser General Public
0007  *  License as published by the Free Software Foundation; either
0008  *  version 2 of the License, or (at your option) any later version.
0009  *
0010  *  This library is distributed in the hope that it will be useful,
0011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  *  Lesser General Public License for more details.
0014  *
0015  *  You should have received a copy of the GNU Lesser General Public
0016  *  License along with this library; if not, write to the Free Software
0017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0018  */
0019 #include "kjs_xpath.h"
0020 #include "kjs_dom.h"
0021 
0022 #include "dom/dom3_xpath.h"
0023 
0024 using KJS::XPathResult;
0025 
0026 #include "kjs_xpath.lut.h"
0027 
0028 namespace KJS
0029 {
0030 
0031 // -------------------------------------------------------------------------
0032 /*
0033 @begin XPathResultConstantsTable  13
0034   ANY_TYPE                      DOM::XPath::ANY_TYPE      DontDelete|ReadOnly
0035   NUMBER_TYPE                   DOM::XPath::NUMBER_TYPE   DontDelete|ReadOnly
0036   STRING_TYPE                   DOM::XPath::STRING_TYPE   DontDelete|ReadOnly
0037   BOOLEAN_TYPE                  DOM::XPath::BOOLEAN_TYPE  DontDelete|ReadOnly
0038   UNORDERED_NODE_ITERATOR_TYPE  DOM::XPath::UNORDERED_NODE_ITERATOR_TYPE DontDelete|ReadOnly
0039   ORDERED_NODE_ITERATOR_TYPE    DOM::XPath::ORDERED_NODE_ITERATOR_TYPE   DontDelete|ReadOnly
0040   UNORDERED_NODE_SNAPSHOT_TYPE  DOM::XPath::UNORDERED_NODE_SNAPSHOT_TYPE DontDelete|ReadOnly
0041   ORDERED_NODE_SNAPSHOT_TYPE    DOM::XPath::ORDERED_NODE_SNAPSHOT_TYPE   DontDelete|ReadOnly
0042   ANY_UNORDERED_NODE_TYPE       DOM::XPath::ANY_UNORDERED_NODE_TYPE      DontDelete|ReadOnly
0043   FIRST_ORDERED_NODE_TYPE       DOM::XPath::FIRST_ORDERED_NODE_TYPE      DontDelete|ReadOnly
0044 @end
0045 */
0046 DEFINE_CONSTANT_TABLE(XPathResultConstants)
0047 IMPLEMENT_CONSTANT_TABLE(XPathResultConstants, "XPathResultConstants")
0048 // -------------------------------------------------------------------------
0049 /*
0050 @begin XPathResultProtoTable 3
0051   iterateNext   XPathResult::IterateNext   DontDelete|Function 0
0052   snapshotItem  XPathResult::SnapshotItem  DontDelete|Function 1
0053 @end
0054 */
0055 KJS_DEFINE_PROTOTYPE(XPathResultProto)
0056 KJS_IMPLEMENT_PROTOFUNC(XPathResultProtoFunc)
0057 KJS_IMPLEMENT_PROTOTYPE("XPathResult", XPathResultProto, XPathResultProtoFunc, XPathResultConstants)
0058 IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(XPathResultPseudoCtor, "XPathResult", XPathResultProto, XPathResultConstants)
0059 
0060 /*
0061 @begin XPathResultTable 11
0062     resultType   XPathResult::ResultType  DontDelete|ReadOnly
0063     numberValue  XPathResult::NumberValue DontDelete|ReadOnly
0064     stringValue  XPathResult::StringValue DontDelete|ReadOnly
0065     booleanValue XPathResult::BooleanValue DontDelete|ReadOnly
0066     singleNodeValue XPathResult::SingleNodeValue DontDelete|ReadOnly
0067     invalidIteratorState XPathResult::InvalidIteratorState DontDelete|ReadOnly
0068     snapshotLength  XPathResult::SnapshotLength DontDelete|ReadOnly
0069 @end
0070 */
0071 const ClassInfo XPathResult::info = { "XPathResult", nullptr, &XPathResultTable, nullptr };
0072 
0073 XPathResult::XPathResult(ExecState *exec, khtml::XPathResultImpl *impl):
0074     WrapperBase(XPathResultProto::self(exec), impl)
0075 {}
0076 
0077 JSValue *XPathResultProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0078 {
0079     KJS_CHECK_THIS(XPathResult, thisObj);
0080 
0081     khtml::XPathResultImpl *imp = static_cast<XPathResult *>(thisObj)->impl();
0082     DOMExceptionTranslator exception(exec);
0083 
0084     switch (id) {
0085     case XPathResult::IterateNext:
0086         return getDOMNode(exec, imp->iterateNext(exception));
0087     case XPathResult::SnapshotItem:
0088         return getDOMNode(exec, imp->snapshotItem(args[0]->toInt32(exec), exception));
0089     }
0090 
0091     return jsUndefined();
0092 }
0093 
0094 bool XPathResult::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot &slot)
0095 {
0096     return getStaticValueSlot<XPathResult, DOMObject>(exec, &XPathResultTable,
0097             this, p, slot);
0098 }
0099 
0100 JSValue *XPathResult::getValueProperty(ExecState *exec, int token) const
0101 {
0102     DOMExceptionTranslator exception(exec);
0103     switch (token) {
0104     case ResultType:
0105         return jsNumber(impl()->resultType());
0106     case NumberValue:
0107         return jsNumber(impl()->numberValue(exception));
0108     case StringValue:
0109         return jsString(impl()->stringValue(exception));
0110     case BooleanValue:
0111         return jsBoolean(impl()->booleanValue(exception));
0112     case SingleNodeValue:
0113         return getDOMNode(exec, impl()->singleNodeValue(exception));
0114     case InvalidIteratorState:
0115         return jsBoolean(impl()->invalidIteratorState());
0116     case SnapshotLength:
0117         return jsNumber(impl()->snapshotLength(exception));
0118     default:
0119         assert(0);
0120         return jsUndefined();
0121     }
0122 }
0123 
0124 // -------------------------------------------------------------------------
0125 /*
0126 @begin XPathExpressionProtoTable 3
0127   evaluate   XPathExpression::Evaluate   DontDelete|Function 2
0128 @end
0129 */
0130 KJS_DEFINE_PROTOTYPE(XPathExpressionProto)
0131 KJS_IMPLEMENT_PROTOFUNC(XPathExpressionProtoFunc)
0132 KJS_IMPLEMENT_PROTOTYPE("XPathExpression", XPathExpressionProto, XPathExpressionProtoFunc, ObjectPrototype)
0133 IMPLEMENT_PSEUDO_CONSTRUCTOR(XPathExpressionPseudoCtor, "XPathExpression", XPathExpressionProto)
0134 
0135 const ClassInfo XPathExpression::info = { "XPathExpression", nullptr, nullptr, nullptr };
0136 
0137 XPathExpression::XPathExpression(ExecState *exec, khtml::XPathExpressionImpl *impl):
0138     WrapperBase(XPathExpressionProto::self(exec), impl), jsResolver(nullptr)
0139 {}
0140 
0141 void XPathExpression::mark()
0142 {
0143     DOMObject::mark();
0144 
0145     if (jsResolver && !jsResolver->marked()) {
0146         jsResolver->mark();
0147     }
0148 }
0149 
0150 JSValue *XPathExpressionProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0151 {
0152     KJS_CHECK_THIS(XPathExpression, thisObj);
0153 
0154     khtml::XPathExpressionImpl *imp = static_cast<XPathExpression *>(thisObj)->impl();
0155     DOMExceptionTranslator exception(exec);
0156 
0157     switch (id) {
0158     case XPathExpression::Evaluate:
0159         return getWrapper<XPathResult>(exec, imp->evaluate(toNode(args[0]),
0160                                        args[1]->toInt32(exec),
0161                                        nullptr,
0162                                        exception));
0163     }
0164 
0165     return jsUndefined();
0166 }
0167 
0168 // -------------------------------------------------------------------------
0169 /*
0170 @begin XPathNSResolverProtoTable 3
0171   lookupNamespaceURI   XPathNSResolver::LookupNamespaceURI   DontDelete|Function 1
0172 @end
0173 */
0174 KJS_DEFINE_PROTOTYPE(XPathNSResolverProto)
0175 KJS_IMPLEMENT_PROTOFUNC(XPathNSResolverProtoFunc)
0176 KJS_IMPLEMENT_PROTOTYPE("XPathNSResolver", XPathNSResolverProto, XPathNSResolverProtoFunc, ObjectPrototype)
0177 IMPLEMENT_PSEUDO_CONSTRUCTOR(XPathNSResolverPseudoCtor, "XPathNSResolver", XPathNSResolverProto)
0178 
0179 const ClassInfo XPathNSResolver::info = { "XPathNSResolver", nullptr, nullptr, nullptr };
0180 
0181 XPathNSResolver::XPathNSResolver(ExecState *exec, khtml::XPathNSResolverImpl *impl):
0182     WrapperBase(XPathNSResolverProto::self(exec), impl)
0183 {}
0184 
0185 JSValue *XPathNSResolverProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
0186 {
0187     KJS_CHECK_THIS(XPathNSResolver, thisObj);
0188 
0189     khtml::XPathNSResolverImpl *imp = static_cast<XPathNSResolver *>(thisObj)->impl();
0190     DOMExceptionTranslator exception(exec);
0191 
0192     switch (id) {
0193     case XPathNSResolver::LookupNamespaceURI:
0194         return jsString(imp->lookupNamespaceURI(args[0]->toString(exec).qstring()));
0195     }
0196 
0197     return jsUndefined();
0198 }
0199 
0200 // -------------------------------------------------------------------------
0201 
0202 JSXPathNSResolver::JSXPathNSResolver(Interpreter *ctx, JSObject *impl): impl(impl), ctx(ctx)
0203 {}
0204 
0205 khtml::XPathNSResolverImpl::Type JSXPathNSResolver::type()
0206 {
0207     return XPathNSResolverImpl::JS;
0208 }
0209 
0210 DOM::DOMString JSXPathNSResolver::lookupNamespaceURI(const DOM::DOMString &prefix)
0211 {
0212     // ### this is "heavily inspired" by JSNodeFilter::acceptNode ---
0213     // gotta be a way of reducing the dupe. This one doesn't
0214     // propagate exceptions, however --- should it?
0215     ExecState *exec = ctx->globalExec();
0216 
0217     JSObject *function = nullptr;
0218     if (impl->implementsCall()) {
0219         function = impl;
0220     } else {
0221         // See if we have an object with a lookupNamespaceURI method.
0222         JSObject *cand = impl->get(exec, "lookupNamespaceURI")->getObject();
0223         if (cand && cand->implementsCall()) {
0224             function = cand;
0225         }
0226     }
0227 
0228     if (function) {
0229         List args;
0230         args.append(jsString(prefix));
0231 
0232         JSValue *result = function->call(exec, impl, args);
0233         if (!exec->hadException()) {
0234             if (result->isUndefinedOrNull()) {
0235                 return DOMString();
0236             } else {
0237                 return result->toString(exec).domString();
0238             }
0239         } else {
0240             exec->clearException();
0241         }
0242     }
0243 
0244     return DOM::DOMString();
0245 }
0246 
0247 // Convert JS -> DOM. Might make a new JSXPathNSResolver. It does not
0248 // protect the JS resolver from collection in any way.
0249 khtml::XPathNSResolverImpl *toResolver(ExecState *exec, JSValue *impl)
0250 {
0251     JSObject *o = impl->getObject();
0252     if (!o) {
0253         return nullptr;
0254     }
0255 
0256     // Wrapped native object -> unwrap
0257     if (o->inherits(&XPathNSResolver::info)) {
0258         return static_cast<XPathNSResolver *>(o)->impl();
0259     }
0260 
0261     // A JS object -> wrap it.
0262     return new JSXPathNSResolver(exec->dynamicInterpreter(), o);
0263 }
0264 
0265 } // namespace KJS
0266