File indexing completed on 2024-05-26 11:45:01

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