• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KJS-API

kjsprototype.cpp

Go to the documentation of this file.
00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (C) 2008 Harri Porten (porten@kde.org)
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License as published by the Free Software Foundation; either
00008  *  version 2 of the License, or (at your option) any later version.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Library General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Library General Public License
00016  *  along with this library; see the file COPYING.LIB.  If not, write to
00017  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  *  Boston, MA 02110-1301, USA.
00019  *
00020  */
00021 
00022 #include "kjsprototype.h"
00023 #include "kjsinterpreter.h"
00024 #include "kjsarguments.h"
00025 #include "kjsprivate.h"
00026 
00027 #include "kjs/object.h"
00028 #include "kjs/JSVariableObject.h"
00029 #include "kjs/context.h"
00030 #include "kjs/interpreter.h"
00031 
00032 #include <QMap>
00033 
00034 using namespace KJS;
00035 
00036 class KJSCustomProperty
00037 {
00038 public:
00039     KJSCustomProperty(KJSPrototype::PropertyGetter g,
00040                       KJSPrototype::PropertySetter s)
00041         : getter(g), setter(s)
00042     {
00043     }
00044 
00045     JSValue* read(ExecState* exec, void* object);
00046     void write(ExecState* exec, void* object, JSValue* value);
00047 
00048 private:
00049     KJSPrototype::PropertyGetter getter;
00050     KJSPrototype::PropertySetter setter;
00051 };
00052 
00053 class CustomObjectInfo {
00054 public:
00055     CustomObjectInfo(void* v): iv(v) {}
00056     virtual ~CustomObjectInfo() {} 
00057     void* internalValue() { return iv; }
00058 protected:
00059     void* iv;
00060 };
00061 
00062 template<class Base>
00063 class CustomObject : public Base, public CustomObjectInfo {
00064 public:
00065     CustomObject(JSValue* proto, void* v)
00066         : Base(proto),
00067           CustomObjectInfo(v)
00068     {}
00069 
00070     using Base::put;
00071     void put(ExecState* exec, const Identifier& id,
00072              JSValue *value, int attr = None);
00073 
00074 
00075     // rtti
00076     static const ClassInfo info;
00077     const ClassInfo* classInfo() const { return &info; }
00078 };
00079 
00080 template<>
00081 const ClassInfo CustomObject<JSObject>::info = { "CustomObject", 0, 0, 0 };
00082 
00083 template<>
00084 const ClassInfo CustomObject<JSGlobalObject>::info = { "CustomGlobalObject", 0, 0, 0 };
00085 
00086 class KJSCustomFunction : public JSObject {
00087 public:
00088     KJSCustomFunction(ExecState* exec, KJSPrototype::FunctionCall f)
00089         : callback(f)
00090     {
00091         setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
00092     }
00093 
00094     JSValue* callAsFunction(ExecState* exec, JSObject* thisObj,
00095                             const List &args);
00096     bool implementsCall() const { return true; }
00097 
00098 private:
00099     KJSPrototype::FunctionCall callback;
00100 };
00101 
00102 JSValue* KJSCustomFunction::callAsFunction(ExecState* exec, JSObject* thisObj,
00103                                            const List &args)
00104 {
00105     // FIXME: does not protect against mixing custom objects
00106     CustomObjectInfo* inf = dynamic_cast<CustomObjectInfo*>(thisObj);
00107 
00108     if (!inf) {
00109         const char* errMsg = "Attempt at calling a function with an invalid receiver";
00110         KJS::JSObject *err = KJS::Error::create(exec, KJS::TypeError, errMsg);
00111         exec->setException(err);
00112         return err;
00113     }
00114 
00115     void* thisValue = inf->internalValue();
00116 
00117     KJSContext ctx(EXECSTATE_HANDLE(exec));
00118     KJSArguments a(LIST_HANDLE(&args));
00119     KJSObject res = (*callback)(&ctx, thisValue, a);
00120     return JSVALUE(&res);
00121 }
00122 
00123 JSValue* KJSCustomProperty::read(ExecState* exec, void* object)
00124 {
00125     assert(getter);
00126     
00127     KJSContext ctx(EXECSTATE_HANDLE(exec));
00128     KJSObject res = (*getter)(&ctx, object);
00129     return JSVALUE(&res);
00130 }
00131 
00132 void KJSCustomProperty::write(ExecState* exec, void* object, JSValue* value)
00133 {
00134     KJSContext ctx(EXECSTATE_HANDLE(exec));
00135 
00136     if (setter) {
00137         KJSObject vo(JSVALUE_HANDLE(value));
00138         (*setter)(&ctx, object, vo);
00139     } else {
00140         JSObject *e = Error::create(exec, GeneralError,
00141                                     "Property is read-only");
00142         exec->setException(e);
00143     }
00144 }
00145 
00146 static JSValue* getPropertyValue(ExecState* exec, JSObject *originalObject,
00147                                  const Identifier&, const PropertySlot& sl)
00148 {
00149     CustomObjectInfo* inf = dynamic_cast<CustomObjectInfo*>(originalObject);
00150     if (!inf)
00151         return jsUndefined();
00152 
00153     KJSCustomProperty* p =
00154         reinterpret_cast<KJSCustomProperty*>(sl.customValue());
00155 
00156     return p->read(exec, inf->internalValue());
00157 }
00158 
00159 // FIXME: or use Identifier?
00160 // FIXME: use values
00161 typedef QMap<UString, KJSCustomProperty*> CustomPropertyMap;
00162 
00163 class CustomPrototype : public JSObject {
00164 public:
00165     CustomPrototype()
00166     {
00167     }
00168     ~CustomPrototype()
00169     {
00170         qDeleteAll(properties);
00171     }
00172 
00173     using KJS::JSObject::getOwnPropertySlot;
00174     bool getOwnPropertySlot(ExecState *exec, const Identifier& id,
00175                             PropertySlot& sl)
00176     {
00177         CustomPropertyMap::iterator it = properties.find(id.ustring());
00178         if (it == properties.end())
00179             return JSObject::getOwnPropertySlot(exec, id, sl);
00180         
00181         sl.setCustomValue(0, *it, getPropertyValue);
00182 
00183         return true;
00184     }
00185 
00186     void registerProperty(const QString& name,
00187                           KJSPrototype::PropertyGetter g,
00188                           KJSPrototype::PropertySetter s)
00189     {
00190         properties.insert(toUString(name), new KJSCustomProperty(g, s));
00191     }
00192 
00193     void registerFunction(ExecState* exec,
00194                           const QString& name, KJSPrototype::FunctionCall f)
00195     {
00196         putDirect(toIdentifier(name), new KJSCustomFunction(exec, f));
00197     }
00198 
00199     template<typename Base>
00200     bool setProperty(ExecState* exec, CustomObject<Base>* obj,
00201                      const Identifier& id, JSValue* value)
00202     {
00203         CustomPropertyMap::iterator it = properties.find(id.ustring());
00204         if (it == properties.end())
00205             return false;
00206 
00207         (*it)->write(exec, obj->internalValue(), value);
00208         
00209         return true;
00210     }
00211 
00212 private:
00213     CustomPropertyMap properties;
00214 };
00215 
00216 template<class Base>
00217 void CustomObject<Base>::put(ExecState* exec, const Identifier& id,
00218                        JSValue* value, int attr)
00219 {
00220     CustomPrototype* p = static_cast<CustomPrototype*>(this->prototype());
00221 
00222     if (!p->setProperty(exec, this, id, value))
00223         Base::put(exec, id, value, attr);
00224 }
00225 
00226 KJSPrototype::KJSPrototype()
00227 {
00228     CustomPrototype* p = new CustomPrototype;
00229     gcProtect(p);
00230 
00231     hnd = PROTOTYPE_HANDLE(p);
00232 }
00233 
00234 KJSPrototype::~KJSPrototype()
00235 {
00236     gcUnprotect(PROTOTYPE(this));
00237 }
00238 
00239 void KJSPrototype::defineConstant(const QString& name, double value)
00240 {
00241     CustomPrototype* p = PROTOTYPE(this);
00242 
00243     p->putDirect(toIdentifier(name), jsNumber(value),
00244                  DontEnum|DontDelete|ReadOnly);
00245 }
00246 
00247 void KJSPrototype::defineConstant(const QString& name, const QString& value)
00248 {
00249     CustomPrototype* p = PROTOTYPE(this);
00250 
00251     p->putDirect(toIdentifier(name), jsString(toUString(value)),
00252                  DontEnum|DontDelete|ReadOnly);
00253 }
00254 
00255 void KJSPrototype::defineConstant(const QString& name, const KJSObject& value)
00256 {
00257     CustomPrototype* p = PROTOTYPE(this);
00258 
00259     p->putDirect(toIdentifier(name), JSVALUE(&value),
00260                  DontEnum|DontDelete|ReadOnly);
00261 }
00262 
00263 KJSObject KJSPrototype::constructObject(KJSContext* ctx, void *internalValue)
00264 {
00265     CustomPrototype* p = PROTOTYPE(this);
00266 
00267     if (ctx && !p->prototype()) {
00268         ExecState* exec = EXECSTATE(ctx);
00269         KJS::Interpreter* i = exec->lexicalInterpreter();
00270         JSObject* objectProto = i->builtinObjectPrototype();
00271         p->setPrototype(objectProto);
00272     }
00273 
00274     CustomObject<JSObject>* newObj = new CustomObject<JSObject>(p, internalValue);
00275     return KJSObject(JSVALUE_HANDLE(newObj));
00276 }
00277 
00278 KJSGlobalObject KJSPrototype::constructGlobalObject(void *internalValue)
00279 {
00280     CustomPrototype* p = PROTOTYPE(this);
00281 
00282     CustomObject<JSGlobalObject>* newObj = new CustomObject<JSGlobalObject>(p, internalValue);
00283     return KJSGlobalObject(JSVALUE_HANDLE(newObj));
00284 }
00285 
00286 void KJSPrototype::defineProperty(KJSContext* ctx,
00287                                   const QString& name,
00288                                   PropertyGetter getter,
00289                                   PropertySetter setter)
00290 {
00291     Q_UNUSED(ctx);
00292     assert(getter);
00293 
00294     CustomPrototype* p = PROTOTYPE(this);
00295 
00296     p->registerProperty(name, getter, setter);
00297 }
00298 
00299 void KJSPrototype::defineFunction(KJSContext* ctx,
00300                                   const QString& name, FunctionCall callback)
00301 {
00302     assert(callback);
00303 
00304     CustomPrototype* p = PROTOTYPE(this);
00305     ExecState* exec = EXECSTATE(ctx);
00306 
00307     p->registerFunction(exec, name, callback);
00308 }
00309 
00310 
00311 // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;

KJS-API

Skip menu "KJS-API"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal