00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 virtual bool implementsHasInstance() const { return true; }
00057 virtual Boolean hasInstance(ExecState *exec, const Value &value);
00058 virtual void put(ExecState *exec, const Identifier &propertyName,
00059 const Value &value, int attr = None);
00060 virtual void tryPut(ExecState *exec, const Identifier &propertyName,
00061 const Value& value, int attr = None);
00062
00063 virtual UString toString(ExecState *exec) const;
00064 };
00065
00071 class DOMFunction : public InternalFunctionImp {
00072 public:
00073 DOMFunction(ExecState* exec) : InternalFunctionImp(
00074 static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
00075 ) {}
00076 virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00077 virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const
00078 { return ObjectImp::get(exec, propertyName); }
00079
00080 virtual bool implementsCall() const { return true; }
00081 virtual Value call(ExecState *exec, Object &thisObj, const List &args);
00082
00083 virtual Value tryCall(ExecState *exec, Object &thisObj, const List&args)
00084 { return ObjectImp::call(exec, thisObj, args); }
00085 virtual bool toBoolean(ExecState *) const { return true; }
00086 };
00087
00093 class KDE_EXPORT ScriptInterpreter : public Interpreter
00094 {
00095 public:
00096 ScriptInterpreter( const Object &global, khtml::ChildFrame* frame );
00097 virtual ~ScriptInterpreter();
00098
00099 DOMObject* getDOMObject( void* objectHandle ) const {
00100 return m_domObjects[objectHandle];
00101 }
00102 void putDOMObject( void* objectHandle, DOMObject* obj ) {
00103 m_domObjects.insert( objectHandle, obj );
00104 }
00105 void customizedDOMObject( DOMObject* obj ) {
00106 m_customizedDomObjects.replace( obj, this );
00107 }
00108 bool deleteDOMObject( void* objectHandle ) {
00109 DOMObject* obj = m_domObjects.take( objectHandle );
00110 if (obj) {
00111 m_customizedDomObjects.remove( obj );
00112 return true;
00113 }
00114 else
00115 return false;
00116 }
00117 void clear() {
00118 m_customizedDomObjects.clear();
00119 m_domObjects.clear();
00120 }
00124 static void forgetDOMObject( void* objectHandle );
00125
00129 virtual void mark();
00130 KParts::ReadOnlyPart* part() const;
00131
00132 virtual int rtti() { return 1; }
00133
00137 void setCurrentEvent( DOM::Event *evt ) { m_evt = evt; }
00138 void setInlineCode( bool inlineCode ) { m_inlineCode = inlineCode; }
00139 void setProcessingTimerCallback( bool timerCallback ) { m_timerCallback = timerCallback; }
00143 bool isWindowOpenAllowed() const;
00144
00145 private:
00146 khtml::ChildFrame* m_frame;
00147 QPtrDict<DOMObject> m_domObjects;
00148 QPtrDict<void> m_customizedDomObjects;
00149
00150 DOM::Event *m_evt;
00151 bool m_inlineCode;
00152 bool m_timerCallback;
00153 };
00157 template<class DOMObj, class KJSDOMObj>
00158 inline Value cacheDOMObject(ExecState *exec, DOMObj domObj)
00159 {
00160 DOMObject *ret;
00161 if (domObj.isNull())
00162 return Null();
00163 ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
00164 if ((ret = interp->getDOMObject(domObj.handle())))
00165 return Value(ret);
00166 else {
00167 ret = new KJSDOMObj(exec, domObj);
00168 interp->putDOMObject(domObj.handle(),ret);
00169 return Value(ret);
00170 }
00171 }
00172
00176 DOM::Node toNode(const Value&);
00180 Value getString(DOM::DOMString s);
00181
00185 QVariant ValueToVariant(ExecState* exec, const Value& val);
00186
00191 template <class FuncImp, class ThisImp, class ParentImp>
00192 inline Value DOMObjectLookupGet(ExecState *exec, const Identifier &propertyName,
00193 const HashTable* table, const ThisImp* thisObj)
00194 {
00195 const HashEntry* entry = Lookup::findEntry(table, propertyName);
00196
00197 if (!entry)
00198 return thisObj->ParentImp::tryGet(exec, propertyName);
00199
00200 if (entry->attr & Function) {
00201 return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
00202 }
00203 return thisObj->getValueProperty(exec, entry->value);
00204 }
00205
00210 template <class ThisImp, class ParentImp>
00211 inline Value DOMObjectLookupGetValue(ExecState *exec, const Identifier &propertyName,
00212 const HashTable* table, const ThisImp* thisObj)
00213 {
00214 const HashEntry* entry = Lookup::findEntry(table, propertyName);
00215
00216 if (!entry)
00217 return thisObj->ParentImp::tryGet(exec, propertyName);
00218
00219 if (entry->attr & Function)
00220 fprintf(stderr, "Function bit set! Shouldn't happen in lookupValue!\n" );
00221 return thisObj->getValueProperty(exec, entry->value);
00222 }
00223
00228 template <class ThisImp, class ParentImp>
00229 inline void DOMObjectLookupPut(ExecState *exec, const Identifier &propertyName,
00230 const Value& value, int attr,
00231 const HashTable* table, ThisImp* thisObj)
00232 {
00233 const HashEntry* entry = Lookup::findEntry(table, propertyName);
00234
00235 if (!entry)
00236 thisObj->ParentImp::tryPut(exec, propertyName, value, attr);
00237 else if (entry->attr & Function)
00238 thisObj->ObjectImp::put(exec, propertyName, value, attr);
00239 else if (entry->attr & ReadOnly)
00240 #ifdef KJS_VERBOSE
00241 fprintf(stderr,"WARNING: Attempt to change value of readonly property '%s'\n",propertyName.ascii());
00242 #else
00243 ;
00244 #endif
00245 else
00246 thisObj->putValueProperty(exec, entry->value, value, attr);
00247 }
00248
00249
00250 #define IMPLEMENT_PROTOFUNC_DOM(ClassFunc) \
00251 namespace KJS { \
00252 class ClassFunc : public DOMFunction { \
00253 public: \
00254 ClassFunc(ExecState *exec, int i, int len) \
00255 : DOMFunction( exec ), id(i) { \
00256 Value protect(this); \
00257 put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum); \
00258 } \
00259 \
00260 virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args); \
00261 private: \
00262 int id; \
00263 }; \
00264 }
00265
00266 Value getLiveConnectValue(KParts::LiveConnectExtension *lc, const QString & name, const int type, const QString & value, int id);
00267
00268
00269
00270
00271
00272 #define DEFINE_PSEUDO_CONSTRUCTOR(ClassName) \
00273 class ClassName : public DOMObject { \
00274 public: \
00275 ClassName(ExecState *); \
00276 virtual const ClassInfo* classInfo() const { return &info; } \
00277 static const ClassInfo info; \
00278 static Object self(ExecState *exec); \
00279 };
00280
00281 #define IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,ParentProto) \
00282 const ClassInfo Class::info = { ClassName, 0, 0, 0 }; \
00283 Class::Class(ExecState* exec): DOMObject(ParentProto) {\
00284 Object proto = ProtoClass::self(exec); \
00285 putDirect(prototypePropertyName, proto.imp(), DontDelete|ReadOnly); \
00286 }\
00287 Object Class::self(ExecState *exec) { \
00288 return Object(cacheGlobalObject<Class>(exec, "[[" ClassName ".constructor]]")); \
00289 }
00290
00291 #define IMPLEMENT_PSEUDO_CONSTRUCTOR(Class,ClassName,ProtoClass) \
00292 IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,exec->lexicalInterpreter()->builtinObjectPrototype())
00293
00294 #define IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(Class,ClassName,ProtoClass,ParentProtoClass) \
00295 IMPLEMENT_PSEUDO_CONSTRUCTOR_IMP(Class,ClassName,ProtoClass,ParentProtoClass::self(exec))
00296
00297
00298 #define CREATE_CONSTANT_TABLE(Class,ClassName) \
00299 class Class : public DOMObject { \
00300 public: \
00301 Class(ExecState *exec): DOMObject(exec->interpreter()->builtinObjectPrototype()) {} \
00302 virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const { \
00303 return DOMObjectLookupGetValue<Class, DOMObject>(exec, propertyName, &Class##Table, this);\
00304 } \
00305 Value getValueProperty(ExecState * , int token) const { \
00306 \
00307 return Number((unsigned int)token); \
00308 } \
00309 virtual const ClassInfo* classInfo() const { return &info; } \
00310 static const ClassInfo info; \
00311 static Object self(ExecState *exec) { \
00312 return Object(cacheGlobalObject<Class>(exec, "[[" ClassName ".constant_table]]")); \
00313 } \
00314 }; \
00315 const ClassInfo Class::info = { ClassName, 0, &Class##Table, 0 };
00316
00317 }
00318
00319 #endif