b2fd66d43653ab56d2697296b61098437d03087e
[WebKit-https.git] / Source / WebCore / bridge / qt / qt_runtime.h
1 /*
2  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  */
19
20 #ifndef BINDINGS_QT_RUNTIME_H_
21 #define BINDINGS_QT_RUNTIME_H_
22
23 #include "BridgeJSC.h"
24 #include "JSDOMBinding.h"
25 #include "JavaScript.h"
26 #include "Weak.h"
27 #include "qt_instance.h"
28 #include "runtime_method.h"
29
30 #include <QPointer>
31
32 #include <qbytearray.h>
33 #include <qmetaobject.h>
34 #include <qvariant.h>
35
36 namespace WebCore {
37 class JSDOMGlobalObject;
38 }
39
40 namespace JSC {
41 namespace Bindings {
42
43 class QtField : public Field {
44 public:
45
46     typedef enum {
47         MetaProperty,
48 #ifndef QT_NO_PROPERTIES
49         DynamicProperty,
50 #endif
51         ChildObject
52     } QtFieldType;
53
54     QtField(const QMetaProperty &p)
55         : m_type(MetaProperty), m_property(p)
56         {}
57
58 #ifndef QT_NO_PROPERTIES
59     QtField(const QByteArray &b)
60         : m_type(DynamicProperty), m_dynamicProperty(b)
61         {}
62 #endif
63
64     QtField(QObject *child)
65         : m_type(ChildObject), m_childObject(child)
66         {}
67
68     virtual JSValue valueFromInstance(ExecState*, const Instance*) const;
69     virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const;
70     QByteArray name() const;
71     QtFieldType fieldType() const {return m_type;}
72 private:
73     QtFieldType m_type;
74     QByteArray m_dynamicProperty;
75     QMetaProperty m_property;
76     QPointer<QObject> m_childObject;
77 };
78
79
80 template <typename T> class QtArray : public Array
81 {
82 public:
83     QtArray(QList<T> list, QMetaType::Type type, PassRefPtr<RootObject>);
84     virtual ~QtArray();
85
86     RootObject* rootObject() const;
87
88     virtual void setValueAt(ExecState*, unsigned index, JSValue) const;
89     virtual JSValue valueAt(ExecState*, unsigned index) const;
90     virtual unsigned int getLength() const {return m_length;}
91
92 private:
93     mutable QList<T> m_list; // setValueAt is const!
94     unsigned int m_length;
95     QMetaType::Type m_type;
96 };
97
98 // Based on RuntimeMethod
99
100 // Extra data classes (to avoid the CELL_SIZE limit on JS objects)
101 class QtRuntimeMethod;
102 class QtRuntimeMethodData : public WeakHandleOwner {
103     public:
104         virtual ~QtRuntimeMethodData();
105         RefPtr<QtInstance> m_instance;
106         Weak<QtRuntimeMethod> m_finalizer;
107
108     private:
109         void finalize(Handle<Unknown>, void*);
110 };
111
112 class QtRuntimeConnectionMethod;
113 class QtRuntimeMetaMethodData : public QtRuntimeMethodData {
114     public:
115         ~QtRuntimeMetaMethodData();
116         QByteArray m_signature;
117         bool m_allowPrivate;
118         int m_index;
119         WriteBarrier<QtRuntimeConnectionMethod> m_connect;
120         WriteBarrier<QtRuntimeConnectionMethod> m_disconnect;
121 };
122
123 class QtRuntimeConnectionMethodData : public QtRuntimeMethodData {
124     public:
125         ~QtRuntimeConnectionMethodData();
126         QByteArray m_signature;
127         int m_index;
128         bool m_isConnect;
129 };
130
131 // Common base class (doesn't really do anything interesting)
132 class QtRuntimeMethod : public InternalFunction {
133 public:
134     typedef InternalFunction Base;
135
136     ~QtRuntimeMethod();
137     static void destroy(JSCell*);
138
139     static const ClassInfo s_info;
140
141     static FunctionPrototype* createPrototype(ExecState*, JSGlobalObject* globalObject)
142     {
143         return globalObject->functionPrototype();
144     }
145
146     static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
147     {
148         return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType,  StructureFlags), &s_info);
149     }
150
151 protected:
152     void finishCreation(ExecState*, const UString&, PassRefPtr<QtInstance>);
153     static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | InternalFunction::StructureFlags | OverridesVisitChildren;
154
155     QtRuntimeMethodData *d_func() const {return d_ptr;}
156     QtRuntimeMethod(QtRuntimeMethodData *dd, ExecState *, Structure*, const UString& name);
157     QtRuntimeMethodData *d_ptr;
158 };
159
160 class QtRuntimeMetaMethod : public QtRuntimeMethod {
161 public:
162     typedef QtRuntimeMethod Base;
163
164     static QtRuntimeMetaMethod* create(ExecState* exec, const UString& name, PassRefPtr<QtInstance> instance, int index, const QByteArray& signature, bool allowPrivate)
165     {
166         Structure* domStructure = WebCore::deprecatedGetDOMStructure<QtRuntimeMetaMethod>(exec);
167         QtRuntimeMetaMethod* method = new (allocateCell<QtRuntimeMetaMethod>(*exec->heap())) QtRuntimeMetaMethod(exec, domStructure, name);
168         method->finishCreation(exec, name, instance, index, signature, allowPrivate);
169         return method;
170     }
171
172     static bool getOwnPropertySlot(JSCell*, ExecState *, PropertyName, PropertySlot&);
173     static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
174     static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
175
176     static void visitChildren(JSCell*, SlotVisitor&);
177     
178     static const ClassInfo s_info;
179
180     static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
181     {
182         return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType,  StructureFlags), &s_info);
183     }
184
185 protected:
186     QtRuntimeMetaMethodData* d_func() const {return reinterpret_cast<QtRuntimeMetaMethodData*>(d_ptr);}
187
188 private:
189     QtRuntimeMetaMethod(ExecState*, Structure*, const UString&);
190     void finishCreation(ExecState*, const UString&, PassRefPtr<QtInstance>, int index, const QByteArray& signature, bool allowPrivate);
191
192     static CallType getCallData(JSCell*, CallData&);
193     static EncodedJSValue JSC_HOST_CALL call(ExecState* exec);
194     static JSValue lengthGetter(ExecState*, JSValue, PropertyName);
195     static JSValue connectGetter(ExecState*, JSValue, PropertyName);
196     static JSValue disconnectGetter(ExecState*, JSValue, PropertyName);
197 };
198
199 class QtConnectionObject;
200 class QtRuntimeConnectionMethod : public QtRuntimeMethod {
201 public:
202     typedef QtRuntimeMethod Base;
203
204     static QtRuntimeConnectionMethod* create(ExecState* exec, const UString& name, bool isConnect, PassRefPtr<QtInstance> instance, int index, const QByteArray& signature)
205     {
206         Structure* domStructure = WebCore::deprecatedGetDOMStructure<QtRuntimeConnectionMethod>(exec);
207         QtRuntimeConnectionMethod* method = new (allocateCell<QtRuntimeConnectionMethod>(*exec->heap())) QtRuntimeConnectionMethod(exec, domStructure, name);
208         method->finishCreation(exec, name, isConnect, instance, index, signature);
209         return method;
210     }
211
212     static bool getOwnPropertySlot(JSCell*, ExecState *, PropertyName, PropertySlot&);
213     static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
214     static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
215  
216     static const ClassInfo s_info;
217
218     static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
219     {
220         return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType,  StructureFlags), &s_info);
221     }
222
223 protected:
224     QtRuntimeConnectionMethodData* d_func() const {return reinterpret_cast<QtRuntimeConnectionMethodData*>(d_ptr);}
225
226 private:
227     QtRuntimeConnectionMethod(ExecState*, Structure*, const UString&);
228     void finishCreation(ExecState*, const UString&, bool isConnect, PassRefPtr<QtInstance>, int index, const QByteArray& signature);
229
230     static CallType getCallData(JSCell*, CallData&);
231     static EncodedJSValue JSC_HOST_CALL call(ExecState* exec);
232     static JSValue lengthGetter(ExecState*, JSValue, PropertyName);
233     static QMultiMap<QObject *, QtConnectionObject *> connections;
234     friend class QtConnectionObject;
235 };
236
237 // A QtConnectionObject represents a connection created inside JS. It will connect its own execute() slot
238 // with the appropriate signal of 'sender'. When execute() is called, it will call JS 'receiverFunction'.
239 class QtConnectionObject : public QObject
240 {
241     Q_OBJECT_FAKE
242 public:
243     QtConnectionObject(JSContextRef, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObjectRef receiver, JSObjectRef receiverFunction);
244     ~QtConnectionObject();
245
246     void execute(void **argv);
247
248     bool match(JSContextRef, QObject* sender, int signalIndex, JSObjectRef thisObject, JSObjectRef funcObject);
249
250     // Note: for callers using JSC internals, remove once we don't need anymore.
251     static QtConnectionObject* createWithInternalJSC(ExecState*, PassRefPtr<QtInstance> senderInstance, int signalIndex, JSObject* receiver, JSObject* receiverFunction);
252
253 private:
254     JSGlobalContextRef m_context;
255     RefPtr<QtInstance> m_senderInstance;
256
257     // We use this as key in active connections multimap.
258     QObject* m_originalSender;
259
260     int m_signalIndex;
261     JSObjectRef m_receiver;
262     JSObjectRef m_receiverFunction;
263 };
264
265
266 typedef QVariant (*ConvertToVariantFunction)(JSObject* object, int *distance, HashSet<JSObject*>* visitedObjects);
267 typedef JSValue (*ConvertToJSValueFunction)(ExecState* exec, WebCore::JSDOMGlobalObject* globalObject, const QVariant& variant);
268
269 void registerCustomType(int qtMetaTypeId, ConvertToVariantFunction, ConvertToJSValueFunction);
270
271 QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance);
272 JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant);
273
274 void setException(JSContextRef, JSValueRef* exception, const QString& text);
275
276 } // namespace Bindings
277 } // namespace JSC
278
279 #endif