• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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     void put(ExecState* exec, const Identifier& id,
00071              JSValue *value, int attr = None);
00072 
00073 
00074     // rtti
00075     static const ClassInfo info;
00076     const ClassInfo* classInfo() const { return &info; }
00077 };
00078 
00079 template<>
00080 const ClassInfo CustomObject<JSObject>::info = { "CustomObject", 0, 0, 0 };
00081 
00082 template<>
00083 const ClassInfo CustomObject<JSGlobalObject>::info = { "CustomGlobalObject", 0, 0, 0 };
00084 
00085 class KJSCustomFunction : public JSObject {
00086 public:
00087     KJSCustomFunction(ExecState* exec, KJSPrototype::FunctionCall f)
00088         : callback(f)
00089     {
00090         setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
00091     }
00092 
00093     JSValue* callAsFunction(ExecState* exec, JSObject* thisObj,
00094                             const List &args);
00095     bool implementsCall() const { return true; }
00096 
00097 private:
00098     KJSPrototype::FunctionCall callback;
00099 };
00100 
00101 JSValue* KJSCustomFunction::callAsFunction(ExecState* exec, JSObject* thisObj,
00102                                            const List &args)
00103 {
00104     // FIXME: does not protect against mixing custom objects
00105     CustomObjectInfo* inf = dynamic_cast<CustomObjectInfo*>(thisObj);
00106 
00107     if (!inf) {
00108         const char* errMsg = "Attempt at calling a function with an invalid receiver";
00109         KJS::JSObject *err = KJS::Error::create(exec, KJS::TypeError, errMsg);
00110         exec->setException(err);
00111         return err;
00112     }
00113 
00114     void* thisValue = inf->internalValue();
00115 
00116     KJSContext ctx(EXECSTATE_HANDLE(exec));
00117     KJSArguments a(LIST_HANDLE(&args));
00118     KJSObject res = (*callback)(&ctx, thisValue, a);
00119     return JSVALUE(&res);
00120 }
00121 
00122 JSValue* KJSCustomProperty::read(ExecState* exec, void* object)
00123 {
00124     assert(getter);
00125     
00126     KJSContext ctx(EXECSTATE_HANDLE(exec));
00127     KJSObject res = (*getter)(&ctx, object);
00128     return JSVALUE(&res);
00129 }
00130 
00131 void KJSCustomProperty::write(ExecState* exec, void* object, JSValue* value)
00132 {
00133     KJSContext ctx(EXECSTATE_HANDLE(exec));
00134 
00135     if (setter) {
00136         KJSObject vo(JSVALUE_HANDLE(value));
00137         (*setter)(&ctx, object, vo);
00138     } else {
00139         JSObject *e = Error::create(exec, GeneralError,
00140                                     "Property is read-only");
00141         exec->setException(e);
00142     }
00143 }
00144 
00145 static JSValue* getPropertyValue(ExecState* exec, JSObject *originalObject,
00146                                  const Identifier&, const PropertySlot& sl)
00147 {
00148     CustomObjectInfo* inf = dynamic_cast<CustomObjectInfo*>(originalObject);
00149     if (!inf)
00150         return jsUndefined();
00151 
00152     KJSCustomProperty* p =
00153         reinterpret_cast<KJSCustomProperty*>(sl.customValue());
00154 
00155     return p->read(exec, inf->internalValue());
00156 }
00157 
00158 // FIXME: or use Identifier?
00159 // FIXME: use values
00160 typedef QMap<UString, KJSCustomProperty*> CustomPropertyMap;
00161 
00162 class CustomPrototype : public JSObject {
00163 public:
00164     CustomPrototype()
00165     {
00166     }
00167     ~CustomPrototype()
00168     {
00169         qDeleteAll(properties);
00170     }
00171 
00172     bool getOwnPropertySlot(ExecState *exec, const Identifier& id,
00173                             PropertySlot& sl)
00174     {
00175         CustomPropertyMap::iterator it = properties.find(id.ustring());
00176         if (it == properties.end())
00177             return JSObject::getOwnPropertySlot(exec, id, sl);
00178         
00179         sl.setCustomValue(0, *it, getPropertyValue);
00180 
00181         return true;
00182     }
00183 
00184     void registerProperty(const QString& name,
00185                           KJSPrototype::PropertyGetter g,
00186                           KJSPrototype::PropertySetter s)
00187     {
00188         properties.insert(toUString(name), new KJSCustomProperty(g, s));
00189     }
00190 
00191     void registerFunction(ExecState* exec,
00192                           const QString& name, KJSPrototype::FunctionCall f)
00193     {
00194         putDirect(toIdentifier(name), new KJSCustomFunction(exec, f));
00195     }
00196 
00197     template<typename Base>
00198     bool setProperty(ExecState* exec, CustomObject<Base>* obj,
00199                      const Identifier& id, JSValue* value)
00200     {
00201         CustomPropertyMap::iterator it = properties.find(id.ustring());
00202         if (it == properties.end())
00203             return false;
00204 
00205         (*it)->write(exec, obj->internalValue(), value);
00206         
00207         return true;
00208     }
00209 
00210 private:
00211     CustomPropertyMap properties;
00212 };
00213 
00214 template<class Base>
00215 void CustomObject<Base>::put(ExecState* exec, const Identifier& id,
00216                        JSValue* value, int attr)
00217 {
00218     CustomPrototype* p = static_cast<CustomPrototype*>(this->prototype());
00219 
00220     if (!p->setProperty(exec, this, id, value))
00221         Base::put(exec, id, value, attr);
00222 }
00223 
00224 KJSPrototype::KJSPrototype()
00225 {
00226     CustomPrototype* p = new CustomPrototype;
00227     gcProtect(p);
00228 
00229     hnd = PROTOTYPE_HANDLE(p);
00230 }
00231 
00232 KJSPrototype::~KJSPrototype()
00233 {
00234     gcUnprotect(PROTOTYPE(this));
00235 }
00236 
00237 void KJSPrototype::defineConstant(const QString& name, double value)
00238 {
00239     CustomPrototype* p = PROTOTYPE(this);
00240 
00241     p->putDirect(toIdentifier(name), jsNumber(value),
00242                  DontEnum|DontDelete|ReadOnly);
00243 }
00244 
00245 void KJSPrototype::defineConstant(const QString& name, const QString& value)
00246 {
00247     CustomPrototype* p = PROTOTYPE(this);
00248 
00249     p->putDirect(toIdentifier(name), jsString(toUString(value)),
00250                  DontEnum|DontDelete|ReadOnly);
00251 }
00252 
00253 void KJSPrototype::defineConstant(const QString& name, const KJSObject& value)
00254 {
00255     CustomPrototype* p = PROTOTYPE(this);
00256 
00257     p->putDirect(toIdentifier(name), JSVALUE(&value),
00258                  DontEnum|DontDelete|ReadOnly);
00259 }
00260 
00261 KJSObject KJSPrototype::constructObject(KJSContext* ctx, void *internalValue)
00262 {
00263     CustomPrototype* p = PROTOTYPE(this);
00264 
00265     if (ctx && !p->prototype()) {
00266         ExecState* exec = EXECSTATE(ctx);
00267         KJS::Interpreter* i = exec->lexicalInterpreter();
00268         JSObject* objectProto = i->builtinObjectPrototype();
00269         p->setPrototype(objectProto);
00270     }
00271 
00272     CustomObject<JSObject>* newObj = new CustomObject<JSObject>(p, internalValue);
00273     return KJSObject(JSVALUE_HANDLE(newObj));
00274 }
00275 
00276 KJSGlobalObject KJSPrototype::constructGlobalObject(void *internalValue)
00277 {
00278     CustomPrototype* p = PROTOTYPE(this);
00279 
00280     CustomObject<JSGlobalObject>* newObj = new CustomObject<JSGlobalObject>(p, internalValue);
00281     return KJSGlobalObject(JSVALUE_HANDLE(newObj));
00282 }
00283 
00284 void KJSPrototype::defineProperty(KJSContext* ctx,
00285                                   const QString& name,
00286                                   PropertyGetter getter,
00287                                   PropertySetter setter)
00288 {
00289     assert(getter);
00290 
00291     CustomPrototype* p = PROTOTYPE(this);
00292 
00293     p->registerProperty(name, getter, setter);
00294 }
00295 
00296 void KJSPrototype::defineFunction(KJSContext* ctx,
00297                                   const QString& name, FunctionCall callback)
00298 {
00299     assert(callback);
00300 
00301     CustomPrototype* p = PROTOTYPE(this);
00302     ExecState* exec = EXECSTATE(ctx);
00303 
00304     p->registerFunction(exec, name, callback);
00305 }
00306 
00307 
00308 // 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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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