File indexing completed on 2024-12-01 12:37:38
0001 /* This file is part of the KDE libraries 0002 Copyright (C) 2005, 2006 Ian Reinhart Geiser <geiseri@kde.org> 0003 Copyright (C) 2005, 2006 Matt Broadstone <mbroadst@gmail.com> 0004 Copyright (C) 2005, 2006 Richard J. Moore <rich@kde.org> 0005 Copyright (C) 2005, 2006 Erik L. Bunce <kde@bunce.us> 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 0023 #ifndef OBJECT_BINDING_H 0024 #define OBJECT_BINDING_H 0025 0026 #include "static_binding.h" 0027 #include "variant_binding.h" 0028 #include "pointer.h" 0029 #include "kjseglobal.h" 0030 0031 /** 0032 * A simple pointer style method. 0033 * This will extract the pointer, cast it to the native type and place it in "value". 0034 * Any data that should be returned from this method should be placed into "result"; 0035 * 0036 */ 0037 #define START_OBJECT_METHOD( METHODNAME, TYPE) \ 0038 KJS::JSValue *METHODNAME( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args ) \ 0039 { \ 0040 Q_UNUSED(exec);\ 0041 Q_UNUSED(self);\ 0042 Q_UNUSED(args);\ 0043 KJS::JSValue *result = KJS::jsNull(); \ 0044 KJSEmbed::ObjectBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::ObjectBinding>(exec, self ); \ 0045 if( imp ) \ 0046 { \ 0047 TYPE *object = imp->object<TYPE>(); \ 0048 if( object ) \ 0049 { 0050 0051 /** 0052 * End a variant method started by START_OBJECT_METHOD 0053 */ 0054 #define END_OBJECT_METHOD \ 0055 } \ 0056 else \ 0057 KJS::throwError(exec, KJS::ReferenceError, QString("O: The internal object died."));\ 0058 } \ 0059 else \ 0060 KJS::throwError(exec, KJS::GeneralError, QString("Object cast failed."));\ 0061 return result; \ 0062 } 0063 0064 #define START_STATIC_OBJECT_METHOD( METHODNAME ) \ 0065 KJS::JSValue *METHODNAME( KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args ) \ 0066 {\ 0067 Q_UNUSED(exec);\ 0068 Q_UNUSED(self);\ 0069 Q_UNUSED(args);\ 0070 KJS::JSValue *result = KJS::jsNull(); \ 0071 0072 #define END_STATIC_OBJECT_METHOD \ 0073 return result; \ 0074 } 0075 0076 namespace KJSEmbed 0077 { 0078 class KJSEMBED_EXPORT ObjectFactory 0079 { 0080 public: 0081 static const Method ObjectMethods[]; 0082 static const Method *methods() 0083 { 0084 return ObjectMethods; 0085 } 0086 }; 0087 0088 class KJSEMBED_EXPORT ObjectBinding : public ProxyBinding 0089 { 0090 public: 0091 enum Ownership { CPPOwned, QObjOwned, JSOwned }; 0092 static const KJS::ClassInfo info; 0093 0094 private: 0095 const char *m_name; 0096 mutable PointerBase *m_value; 0097 Ownership m_owner; 0098 0099 public: 0100 template <typename T> 0101 ObjectBinding(KJS::ExecState *exec, const char *typeName, T *ptr) 0102 : ProxyBinding(exec), 0103 m_name(typeName) 0104 { 0105 StaticBinding::publish(exec, this, ObjectFactory::methods()); 0106 0107 m_owner = CPPOwned; 0108 m_value = new Pointer<T>(ptr); 0109 } 0110 0111 ~ObjectBinding() override; 0112 0113 const char *typeName() const; 0114 0115 /** 0116 * \return the internal object as a pointer of type T 0117 */ 0118 template <typename T> 0119 T *object() const 0120 { 0121 if (m_value) { 0122 return pointer_cast<T>(m_value); 0123 } else { 0124 return nullptr; 0125 } 0126 } 0127 0128 void *voidStar() const 0129 { 0130 return m_value->voidStar(); 0131 } 0132 0133 template <typename T> 0134 void setObject(T *ptr) 0135 { 0136 if (m_owner == JSOwned) { 0137 //qDebug("object cleans up"); 0138 m_value->cleanup(); 0139 } 0140 delete m_value; 0141 m_value = new Pointer<T>(ptr); 0142 } 0143 0144 KJS::UString toString(KJS::ExecState *exec) const override; 0145 KJS::UString className() const override; 0146 KJS::JSType type() const override; 0147 0148 Ownership ownership() const; 0149 void setOwnership(Ownership owner); 0150 0151 }; 0152 0153 /** 0154 * Extracts a pointer based type from an ObjectBinding object. Care should be taken that this method 0155 * is not used with KJSEmbed::ObjectBinding objects because the cast will fail. 0156 */ 0157 template< typename T> 0158 T *extractObject(KJS::ExecState *exec, KJS::JSValue *arg, T *defaultValue) 0159 { 0160 if (!arg) { 0161 return defaultValue; 0162 } else { 0163 T *returnValue = nullptr; 0164 KJSEmbed::ObjectBinding *imp = KJSEmbed::extractBindingImp<KJSEmbed::ObjectBinding>(exec, arg); 0165 if (imp) { 0166 // GCC 3.3 has problems calling template functions in another class from a template class. 0167 // returnValue = imp->object<T>(); 0168 0169 returnValue = (T *)imp->voidStar(); 0170 } 0171 if (returnValue) { 0172 return returnValue; 0173 } else { 0174 return defaultValue; 0175 } 0176 } 0177 } 0178 0179 /** 0180 * Extracts a pointer from a KJS::List of KJS::JSValues. If the argument is out of range the default value 0181 * is returned. 0182 */ 0183 template< typename T> 0184 T *extractObject(KJS::ExecState *exec, const KJS::List &args, int idx, T *defaultValue = nullptr) 0185 { 0186 if (args.size() > idx) { 0187 return extractObject<T>(exec, args[idx], defaultValue); 0188 } else { 0189 return defaultValue; 0190 } 0191 } 0192 0193 /** 0194 * Can create any known KJSEmbed::ObjectBinding object and set the value. 0195 * On failure a KJS::jsNull will be returned and the exception set. 0196 */ 0197 template< typename T> 0198 KJS::JSValue *createObject(KJS::ExecState *exec, const KJS::UString &className, const T *value, KJSEmbed::ObjectBinding::Ownership owner = KJSEmbed::ObjectBinding::JSOwned) 0199 { 0200 if (nullptr == value) { 0201 return KJS::jsNull(); 0202 } 0203 0204 KJS::JSObject *parent = exec->dynamicInterpreter()->globalObject(); 0205 KJS::JSObject *returnValue = StaticConstructor::construct(exec, parent, className); 0206 if (returnValue) { 0207 // If it is a value type setValue 0208 KJSEmbed::ObjectBinding *imp = extractBindingImp<KJSEmbed::ObjectBinding>(exec, returnValue); 0209 if (imp) { 0210 imp->setOwnership(KJSEmbed::ObjectBinding::JSOwned); 0211 imp->setObject(value); 0212 imp->setOwnership(owner); 0213 } else { 0214 throwError(exec, KJS::TypeError, i18n("%1 is not an Object type", className.ascii())); 0215 return KJS::jsNull(); 0216 } 0217 } else { 0218 throwError(exec, KJS::GeneralError, "Could not construct value"); 0219 //throwError(exec, "Could not construct value" ); 0220 return KJS::jsNull(); 0221 } 0222 0223 return returnValue; 0224 } 0225 0226 template< typename T > 0227 T extractParameter(KJS::ExecState *exec, KJS::JSValue *arg, const T &defaultValue) 0228 { 0229 if (!arg) { 0230 return defaultValue; 0231 } else { 0232 switch (arg->type()) { 0233 case KJS::NumberType: 0234 return extractInt(exec, arg, defaultValue); 0235 break; 0236 case KJS::BooleanType: 0237 return extractBool(exec, arg, 0); 0238 break; 0239 case KJS::UnspecifiedType: 0240 case KJS::UndefinedType: 0241 case KJS::NullType: 0242 case KJS::GetterSetterType: 0243 case KJS::StringType: 0244 return defaultValue; 0245 break; 0246 } 0247 0248 KJS::JSObject *object = arg->toObject(exec); 0249 if (object->inherits(&VariantBinding::info)) { 0250 return extractVariant<T>(exec, arg, defaultValue); 0251 } else if (object->inherits(&ObjectBinding::info)) { 0252 return extractObject<T>(exec, arg, defaultValue); 0253 } else { 0254 return defaultValue; 0255 } 0256 } 0257 } 0258 } 0259 #endif 0260