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 class KHTMLPart;
00035
00036 namespace KJS {
00037
00043 class DOMObject : public ObjectImp {
00044 public:
00045 DOMObject(const Object &proto) : ObjectImp(proto) {}
00046 virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00047 virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const
00048 { return ObjectImp::get(exec, propertyName); }
00049
00050 virtual void put(ExecState *exec, const Identifier &propertyName,
00051 const Value &value, int attr = None);
00052 virtual void tryPut(ExecState *exec, const Identifier &propertyName,
00053 const Value& value, int attr = None)
00054 { ObjectImp::put(exec,propertyName,value,attr); }
00055
00056 virtual UString toString(ExecState *exec) const;
00057 };
00058
00064 class DOMFunction : public InternalFunctionImp {
00065 public:
00066 DOMFunction(ExecState* exec) : InternalFunctionImp(
00067 static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp())
00068 ) {}
00069 virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00070 virtual Value tryGet(ExecState *exec, const Identifier &propertyName) const
00071 { return ObjectImp::get(exec, propertyName); }
00072
00073 virtual bool implementsCall() const { return true; }
00074 virtual Value call(ExecState *exec, Object &thisObj, const List &args);
00075
00076 virtual Value tryCall(ExecState *exec, Object &thisObj, const List&args)
00077 { return ObjectImp::call(exec, thisObj, args); }
00078 virtual bool toBoolean(ExecState *) const { return true; }
00079 };
00080
00086 class ScriptInterpreter : public Interpreter
00087 {
00088 public:
00089 ScriptInterpreter( const Object &global, KHTMLPart* part );
00090 virtual ~ScriptInterpreter();
00091
00092 DOMObject* getDOMObject( void* objectHandle ) const {
00093 return m_domObjects[objectHandle];
00094 }
00095 void putDOMObject( void* objectHandle, DOMObject* obj ) {
00096 m_domObjects.insert( objectHandle, obj );
00097 }
00098 bool deleteDOMObject( void* objectHandle ) {
00099 return m_domObjects.remove( objectHandle );
00100 }
00101 void clear() {
00102 m_domObjects.clear();
00103 }
00107 static void forgetDOMObject( void* objectHandle );
00108
00112 virtual void mark();
00113 KHTMLPart* part() const { return m_part; }
00114
00115 virtual int rtti() { return 1; }
00116
00120 void setCurrentEvent( DOM::Event *evt ) { m_evt = evt; }
00121 void setInlineCode( bool inlineCode ) { m_inlineCode = inlineCode; }
00122 void setProcessingTimerCallback( bool timerCallback ) { m_timerCallback = timerCallback; }
00126 bool isWindowOpenAllowed() const;
00127
00128 private:
00129 KHTMLPart* m_part;
00130 QPtrDict<DOMObject> m_domObjects;
00131 DOM::Event *m_evt;
00132 bool m_inlineCode;
00133 bool m_timerCallback;
00134 };
00138 template<class DOMObj, class KJSDOMObj>
00139 inline Value cacheDOMObject(ExecState *exec, DOMObj domObj)
00140 {
00141 DOMObject *ret;
00142 if (domObj.isNull())
00143 return Null();
00144 ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
00145 if ((ret = interp->getDOMObject(domObj.handle())))
00146 return Value(ret);
00147 else {
00148 ret = new KJSDOMObj(exec, domObj);
00149 interp->putDOMObject(domObj.handle(),ret);
00150 return Value(ret);
00151 }
00152 }
00153
00157 DOM::Node toNode(const Value&);
00161 Value getString(DOM::DOMString s);
00162
00166 QVariant ValueToVariant(ExecState* exec, const Value& val);
00167
00172 template <class FuncImp, class ThisImp, class ParentImp>
00173 inline Value DOMObjectLookupGet(ExecState *exec, const Identifier &propertyName,
00174 const HashTable* table, const ThisImp* thisObj)
00175 {
00176 const HashEntry* entry = Lookup::findEntry(table, propertyName);
00177
00178 if (!entry)
00179 return thisObj->ParentImp::tryGet(exec, propertyName);
00180
00181 if (entry->attr & Function) {
00182 return lookupOrCreateFunction<FuncImp>(exec, propertyName, thisObj, entry->value, entry->params, entry->attr);
00183 }
00184 return thisObj->getValueProperty(exec, entry->value);
00185 }
00186
00191 template <class ThisImp, class ParentImp>
00192 inline Value DOMObjectLookupGetValue(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 fprintf(stderr, "Function bit set! Shouldn't happen in lookupValue!\n" );
00202 return thisObj->getValueProperty(exec, entry->value);
00203 }
00204
00209 template <class ThisImp, class ParentImp>
00210 inline void DOMObjectLookupPut(ExecState *exec, const Identifier &propertyName,
00211 const Value& value, int attr,
00212 const HashTable* table, ThisImp* thisObj)
00213 {
00214 const HashEntry* entry = Lookup::findEntry(table, propertyName);
00215
00216 if (!entry)
00217 thisObj->ParentImp::tryPut(exec, propertyName, value, attr);
00218 else if (entry->attr & Function)
00219 thisObj->ObjectImp::put(exec, propertyName, value, attr);
00220 else if (entry->attr & ReadOnly)
00221 #ifdef KJS_VERBOSE
00222 fprintf(stderr,"WARNING: Attempt to change value of readonly property '%s'\n",propertyName.ascii());
00223 #else
00224 ;
00225 #endif
00226 else
00227 thisObj->putValueProperty(exec, entry->value, value, attr);
00228 }
00229
00230
00231 #define IMPLEMENT_PROTOFUNC_DOM(ClassFunc) \
00232 namespace KJS { \
00233 class ClassFunc : public DOMFunction { \
00234 public: \
00235 ClassFunc(ExecState *exec, int i, int len) \
00236 : DOMFunction( exec ), id(i) { \
00237 Value protect(this); \
00238 put(exec,lengthPropertyName,Number(len),DontDelete|ReadOnly|DontEnum); \
00239 } \
00240 \
00241 virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args); \
00242 private: \
00243 int id; \
00244 }; \
00245 }
00246
00247 }
00248
00249 #endif