File indexing completed on 2023-10-03 03:21:48
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 #include "static_binding.h" 0023 #include <kjs/interpreter.h> 0024 #include <kjs/function_object.h> 0025 #include <QDebug> 0026 0027 namespace KJSEmbed 0028 { 0029 static QHash<QString, const Constructor *> g_ctorHash; 0030 } 0031 0032 using namespace KJSEmbed; 0033 0034 StaticBinding::StaticBinding(KJS::ExecState *exec, const Method *method) 0035 : KJS::InternalFunctionImp(static_cast<KJS::FunctionPrototype *>(exec->lexicalInterpreter()->builtinFunctionPrototype()), 0036 method->name), 0037 m_method(method) 0038 { 0039 putDirect(exec->propertyNames().length, m_method->argc, LengthFlags); 0040 } 0041 0042 KJS::JSValue *StaticBinding::callAsFunction(KJS::ExecState *exec, KJS::JSObject *self, const KJS::List &args) 0043 { 0044 if (m_method->call == nullptr) { 0045 //throwError(exec, "Bad method id"); // NOTE: fix 0046 KJS::throwError(exec, KJS::GeneralError, "Bad method id"); 0047 return KJS::jsNull(); 0048 } 0049 0050 KJS::JSValue *retValue = (*m_method->call)(exec, self, args); 0051 0052 if (exec->hadException()) { 0053 return KJS::jsNull(); 0054 } 0055 return retValue; 0056 0057 } 0058 0059 void StaticBinding::publish(KJS::ExecState *exec, KJS::JSObject *object, const Method *methods) 0060 { 0061 int idx = 0; 0062 while (methods[idx].name != nullptr) { 0063 object->put(exec, methods[idx].name, new StaticBinding(exec, &methods[idx]), methods[idx].flags); 0064 idx++; 0065 } 0066 } 0067 0068 StaticConstructor::StaticConstructor(KJS::ExecState *exec, const Constructor *constructor) 0069 : KJS::InternalFunctionImp(static_cast<KJS::FunctionPrototype *>(exec->lexicalInterpreter()->builtinFunctionPrototype()), 0070 constructor->name), 0071 m_constructor(constructor) 0072 { 0073 putDirect(exec->propertyNames().length, m_constructor->argc, LengthFlags); 0074 m_default = KJS::jsNull(); 0075 } 0076 0077 KJS::JSObject *StaticConstructor::construct(KJS::ExecState *exec, const KJS::List &args) 0078 { 0079 return (*m_constructor->construct)(exec, args); 0080 } 0081 0082 void StaticConstructor::setDefaultValue(KJS::JSValue *value) 0083 { 0084 m_default = value; 0085 } 0086 0087 KJS::JSValue *StaticConstructor::defaultValue(KJS::ExecState *exec, KJS::JSType hint) const 0088 { 0089 Q_UNUSED(exec); 0090 Q_UNUSED(hint); 0091 return m_default; 0092 } 0093 0094 KJS::JSObject *StaticConstructor::add(KJS::ExecState *exec, KJS::JSObject *object, const Constructor *constructor) 0095 { 0096 KJS::JSObject *obj = new StaticConstructor(exec, constructor); 0097 object->put(exec, constructor->name, obj); 0098 if (constructor->staticMethods) { 0099 StaticBinding::publish(exec, obj, constructor->staticMethods); 0100 } 0101 /* crashes for some reason */ 0102 if (constructor->enumerators) { 0103 int idx = 0; 0104 while (constructor->enumerators[idx].name != nullptr) { 0105 obj->put(exec, constructor->enumerators[idx].name, 0106 KJS::jsNumber(constructor->enumerators[idx].value), KJS::DontDelete | KJS::ReadOnly); 0107 idx++; 0108 } 0109 } 0110 // publish methods 0111 KJSEmbed::g_ctorHash[constructor->name] = constructor; 0112 return obj; 0113 } 0114 0115 const Method *StaticConstructor::methods(const KJS::UString &className) 0116 { 0117 return KJSEmbed::g_ctorHash[toQString(className)]->methods; 0118 } 0119 0120 const Constructor *StaticConstructor::constructor(const KJS::UString &className) 0121 { 0122 return KJSEmbed::g_ctorHash[toQString(className)]; 0123 } 0124 0125 KJS::JSObject *StaticConstructor::bind(KJS::ExecState *exec, const QString &className, PointerBase &objPtr) 0126 { 0127 KJSEmbed::callBind mybind = KJSEmbed::g_ctorHash[className]->bind; 0128 // qDebug() << "StaticConstructor::bind() className=" << className << " mybind=" << mybind; 0129 if (mybind) { 0130 return (*mybind)(exec, objPtr); 0131 } 0132 0133 return nullptr; 0134 } 0135 0136 KJS::JSObject *StaticConstructor::construct(KJS::ExecState *exec, KJS::JSObject *parent, const KJS::UString &className, const KJS::List &args) 0137 { 0138 // qDebug("StaticConstructor::construct('%s')", className.ascii() ); 0139 if (parent->hasProperty(exec, className.ascii())) { 0140 KJS::JSObject *ctor = parent->get(exec, className.ascii())->toObject(exec); 0141 if (ctor) { 0142 return ctor->construct(exec, args); 0143 } 0144 } 0145 qDebug("cannot create '%s'", className.ascii()); 0146 return KJS::throwError(exec, KJS::TypeError, toUString(QString("Cannot create %1 objects from javascript.").arg(toQString(className)))); 0147 } 0148