kjs_binding.h

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
00005  *  Copyright (C) 2003 Apple Computer, Inc.
00006  *
00007  *  This library is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU Library General Public
00009  *  License as published by the Free Software Foundation; either
00010  *  version 2 of the License, or (at your option) any later version.
00011  *
00012  *  This library is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  Library General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public
00018  *  License along with this library; if not, write to the Free Software
00019  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 #ifndef _KJS_BINDING_H_
00023 #define _KJS_BINDING_H_
00024 
00025 #include <kjs/interpreter.h>
00026 #include <kjs/function_object.h> 
00027 
00028 #include <dom/dom_node.h>
00029 #include <qvariant.h>
00030 #include <qptrdict.h>
00031 #include <kurl.h>
00032 #include <kjs/lookup.h>
00033 
00034 namespace KParts {
00035   class ReadOnlyPart;
00036   class LiveConnectExtension;
00037 }
00038 
00039 namespace khtml {
00040   class ChildFrame;
00041 }
00042 
00043 namespace KJS {
00044 
00050   class DOMObject : public ObjectImp {
00051   public:
00052     DOMObject(const Object &proto) : ObjectImp(proto) {}
00053     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00054     virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const
00055       { return ObjectImp::get(exec, propertyName); }
00056 
00057     virtual void put(ExecState *exec, const Identifier &propertyName,
00058                      const Value &value, int attr = None);
00059     virtual void tryPut(ExecState *exec, const Identifier &propertyName,
00060                         const Value& value, int attr = None);
00061 
00062     virtual UString toString(ExecState *exec) const;
00063   };
00064 
00070   class DOMFunction : public InternalFunctionImp {
00071   public:
00072     DOMFunction(ExecState* exec) : InternalFunctionImp(
00073       static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
00074       ) {}
00075     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00076     virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const
00077       { return ObjectImp::get(exec, propertyName); }
00078 
00079     virtual bool implementsCall() const { return true; }
00080     virtual Value call(ExecState *exec, Object &thisObj, const List &args);
00081 
00082     virtual Value tryCall(ExecState *exec, Object &thisObj, const List&args)
00083       { return ObjectImp::call(exec, thisObj, args); }
00084     virtual bool toBoolean(ExecState *) const { return true; }
00085   };
00086 
00092   class KDE_EXPORT ScriptInterpreter : public Interpreter
00093   {
00094   public:
00095     ScriptInterpreter( const Object &global, khtml::ChildFrame* frame );
00096     virtual ~ScriptInterpreter();
00097 
00098     DOMObject* getDOMObject( void* objectHandle ) const {
00099       return m_domObjects[objectHandle];
00100     }
00101     void putDOMObject( void* objectHandle, DOMObject* obj ) {
00102       m_domObjects.insert( objectHandle, obj );
00103     }
00104     void customizedDOMObject( DOMObject* obj ) {
00105       m_customizedDomObjects.replace( obj, this );
00106     }
00107     bool deleteDOMObject( void* objectHandle ) {
00108       DOMObject* obj = m_domObjects.take( objectHandle );
00109       if (obj) {
00110         m_customizedDomObjects.remove( obj );
00111         return true;
00112       }
00113       else
00114         return false;
00115     }
00116     void clear() {
00117       m_customizedDomObjects.clear();
00118       m_domObjects.clear();
00119     }
00123     static void forgetDOMObject( void* objectHandle );
00124 
00128     virtual void mark();
00129     KParts::ReadOnlyPart* part() const;
00130 
00131     virtual int rtti() { return 1; }
00132 
00136     void setCurrentEvent( DOM::Event *evt ) { m_evt = evt; }
00137     void setInlineCode( bool inlineCode ) { m_inlineCode = inlineCode; }
00138     void setProcessingTimerCallback( bool timerCallback ) { m_timerCallback = timerCallback; }
00142     bool isWindowOpenAllowed() const;
00143 
00144   private:
00145     khtml::ChildFrame* m_frame;
00146     QPtrDict<DOMObject> m_domObjects;
00147     QPtrDict<void> m_customizedDomObjects; //Objects which had custom properties set,
00148                                            //and should not be GC'd. key is DOMObject*
00149     DOM::Event *m_evt;
00150     bool m_inlineCode;
00151     bool m_timerCallback;
00152   };
00156   template<class DOMObj, class KJSDOMObj>
00157   inline Value cacheDOMObject(ExecState *exec, DOMObj domObj)
00158   {
00159     DOMObject *ret;
00160     if (domObj.isNull())
00161       return Null();
00162     ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
00163     if ((ret = interp->getDOMObject(domObj.handle())))
00164       return Value(ret);
00165     else {
00166       ret = new KJSDOMObj(exec, domObj);
00167       interp->putDOMObject(domObj.handle(),ret);
00168       return Value(ret);
00169     }
00170   }
00171 
00175   DOM::Node toNode(const Value&);
00179   Value getString(DOM::DOMString s);
00180 
00184   QVariant ValueToVariant(ExecState* exec, const Value& val);
00185 
00190   template <class FuncImp, class ThisImp, class ParentImp>
00191   inline Value DOMObjectLookupGet(ExecState *exec, const Identifier &propertyName,
00192                                   const HashTable* table, const ThisImp* thisObj)
00193   {
00194     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00195 
00196     if (!entry) // not found, forward to parent
00197       return thisObj->ParentImp::tryGet(exec, propertyName);
00198 
00199     if (entry->attr & Function) {
00200       return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
00201     }
00202     return thisObj->getValueProperty(exec, entry->value);
00203   }
00204 
00209   template <class ThisImp, class ParentImp>
00210   inline Value DOMObjectLookupGetValue(ExecState *exec, const Identifier &propertyName,
00211                                        const HashTable* table, const ThisImp* thisObj)
00212   {
00213     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00214 
00215     if (!entry) // not found, forward to parent
00216       return thisObj->ParentImp::tryGet(exec, propertyName);
00217 
00218     if (entry->attr & Function)
00219       fprintf(stderr, "Function bit set! Shouldn't happen in lookupValue!\n" );
00220     return thisObj->getValueProperty(exec, entry->value);
00221   }
00222 
00227   template <class ThisImp, class ParentImp>
00228   inline void DOMObjectLookupPut(ExecState *exec, const Identifier &propertyName,
00229                                  const Value& value, int attr,
00230                                  const HashTable* table, ThisImp* thisObj)
00231   {
00232     const HashEntry* entry = Lookup::findEntry(table, propertyName);
00233 
00234     if (!entry) // not found: forward to parent
00235       thisObj->ParentImp::tryPut(exec, propertyName, value, attr);
00236     else if (entry->attr & Function) // function: put as override property
00237       thisObj->ObjectImp::put(exec, propertyName, value, attr);
00238     else if (entry->attr & ReadOnly) // readonly! Can't put!
00239 #ifdef KJS_VERBOSE
00240       fprintf(stderr,"WARNING: Attempt to change value of readonly property '%s'\n",propertyName.ascii());
00241 #else
00242     ; // do nothing
00243 #endif
00244     else
00245       thisObj->putValueProperty(exec, entry->value, value, attr);
00246   }
00247 
00248   // Modified version of IMPLEMENT_PROTOFUNC, to use DOMFunction and tryCall
00249 #define IMPLEMENT_PROTOFUNC_DOM(ClassFunc) \
00250   namespace KJS { \
00251   class ClassFunc : public DOMFunction { \
00252   public: \
00253     ClassFunc(ExecState *exec, int i, int len) \
00254        : DOMFunction( exec ), id(i) { \
00255        Value protect(this); \
00256        put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum); \
00257     } \
00258  \
00259     virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args); \
00260   private: \
00261     int id; \
00262   }; \
00263   }
00264 
00265   Value getLiveConnectValue(KParts::LiveConnectExtension *lc, const QString & name, const int type, const QString & value, int id);
00266 
00267 
00268 // This is used to create pseudo-constructor objects, like Mozillaish
00269 // Element, HTMLDocument, etc., which do not act like real constructors,
00270 // but do have the prototype property pointing to prototype of "instances"
00271 #define DEFINE_PSEUDO_CONSTRUCTOR(ClassName) \
00272   class ClassName : public DOMObject { \
00273       public: \
00274           ClassName(ExecState *); \
00275           virtual const ClassInfo* classInfo() const { return &info; } \
00276           static const ClassInfo info; \
00277           static Object self(ExecState *exec); \
00278   };
00279 
00280 #define IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,ParentProto) \
00281     const ClassInfo Class::info = { ClassName, 0, 0, 0 }; \
00282     Class::Class(ExecState* exec): DOMObject(ParentProto) {\
00283         Object proto = ProtoClass::self(exec); \
00284         putDirect(prototypePropertyName, proto.imp(), DontDelete|ReadOnly); \
00285     }\
00286     Object Class::self(ExecState *exec) { \
00287         return Object(cacheGlobalObject<Class>(exec, "[[" ClassName ".constructor]]")); \
00288     }
00289 
00290 #define IMPLEMENT_PSEUDO_CONSTRUCTOR(Class,ClassName,ProtoClass) \
00291     IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,exec->lexicalInterpreter()->builtinObjectPrototype())
00292 
00293 #define IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(Class,ClassName,ProtoClass,ParentProtoClass) \
00294     IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,ParentProtoClass::self(exec))
00295 
00296 // This is used to implement a constant table. Can be used as a prototype
00297 #define CREATE_CONSTANT_TABLE(Class,ClassName) \
00298    class Class : public DOMObject { \
00299    public: \
00300      Class(ExecState *exec): DOMObject(exec->interpreter()->builtinObjectPrototype()) {} \
00301      virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const { \
00302         return DOMObjectLookupGetValue<Class, DOMObject>(exec, propertyName, &Class##Table, this);\
00303      } \
00304      Value getValueProperty(ExecState * /*exec*/, int token) const { \
00305         /* We use the token as the value to return directly*/ \
00306         return Number((unsigned int)token); \
00307      }  \
00308      virtual const ClassInfo* classInfo() const { return &info; } \
00309      static const ClassInfo info; \
00310      static Object self(ExecState *exec) { \
00311         return Object(cacheGlobalObject<Class>(exec, "[[" ClassName ".constant_table]]")); \
00312      } \
00313    }; \
00314    const ClassInfo Class::info = { ClassName, 0, &Class##Table, 0 };
00315 
00316 } // namespace
00317 
00318 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys