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 "Completion.h"
25#include "Strong.h"
26#include "runtime_method.h"
27
28#include <qbytearray.h>
29#include <qmetaobject.h>
30#include <qpointer.h>
31#include <qvariant.h>
32
33namespace JSC {
34namespace Bindings {
35
36class QtInstance;
37
38class QtField : public Field {
39public:
40
41    typedef enum {
42        MetaProperty,
43#ifndef QT_NO_PROPERTIES
44        DynamicProperty,
45#endif
46        ChildObject
47    } QtFieldType;
48
49    QtField(const QMetaProperty &p)
50        : m_type(MetaProperty), m_property(p)
51        {}
52
53#ifndef QT_NO_PROPERTIES
54    QtField(const QByteArray &b)
55        : m_type(DynamicProperty), m_dynamicProperty(b)
56        {}
57#endif
58
59    QtField(QObject *child)
60        : m_type(ChildObject), m_childObject(child)
61        {}
62
63    virtual JSValue valueFromInstance(ExecState*, const Instance*) const;
64    virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const;
65    QByteArray name() const;
66    QtFieldType fieldType() const {return m_type;}
67private:
68    QtFieldType m_type;
69    QByteArray m_dynamicProperty;
70    QMetaProperty m_property;
71    QPointer<QObject> m_childObject;
72};
73
74
75class QtMethod : public Method
76{
77public:
78    QtMethod(const QMetaObject *mo, int i, const QByteArray &ident, int numParameters)
79        : m_metaObject(mo),
80          m_index(i),
81          m_identifier(ident),
82          m_nParams(numParameters)
83        { }
84
85    virtual const char* name() const { return m_identifier.constData(); }
86    virtual int numParameters() const { return m_nParams; }
87
88private:
89    friend class QtInstance;
90    const QMetaObject *m_metaObject;
91    int m_index;
92    QByteArray m_identifier;
93    int m_nParams;
94};
95
96
97template <typename T> class QtArray : public Array
98{
99public:
100    QtArray(QList<T> list, QMetaType::Type type, PassRefPtr<RootObject>);
101    virtual ~QtArray();
102
103    RootObject* rootObject() const;
104
105    virtual void setValueAt(ExecState*, unsigned index, JSValue) const;
106    virtual JSValue valueAt(ExecState*, unsigned index) const;
107    virtual unsigned int getLength() const {return m_length;}
108
109private:
110    mutable QList<T> m_list; // setValueAt is const!
111    unsigned int m_length;
112    QMetaType::Type m_type;
113};
114
115// Based on RuntimeMethod
116
117// Extra data classes (to avoid the CELL_SIZE limit on JS objects)
118
119class QtRuntimeMethodData {
120    public:
121        virtual ~QtRuntimeMethodData();
122        RefPtr<QtInstance> m_instance;
123};
124
125class QtRuntimeConnectionMethod;
126class QtRuntimeMetaMethodData : public QtRuntimeMethodData {
127    public:
128        ~QtRuntimeMetaMethodData();
129        QByteArray m_signature;
130        bool m_allowPrivate;
131        int m_index;
132        WriteBarrier<QtRuntimeConnectionMethod> m_connect;
133        WriteBarrier<QtRuntimeConnectionMethod> m_disconnect;
134};
135
136class QtRuntimeConnectionMethodData : public QtRuntimeMethodData {
137    public:
138        ~QtRuntimeConnectionMethodData();
139        QByteArray m_signature;
140        int m_index;
141        bool m_isConnect;
142};
143
144// Common base class (doesn't really do anything interesting)
145class QtRuntimeMethod : public InternalFunction {
146public:
147    virtual ~QtRuntimeMethod();
148
149    static const ClassInfo s_info;
150
151    static FunctionPrototype* createPrototype(ExecState*, JSGlobalObject* globalObject)
152    {
153        return globalObject->functionPrototype();
154    }
155
156    static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
157    {
158        return Structure::create(globalData, prototype, TypeInfo(ObjectType,  StructureFlags), AnonymousSlotCount, &s_info);
159    }
160
161protected:
162    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | InternalFunction::StructureFlags | OverridesMarkChildren;
163
164    QtRuntimeMethodData *d_func() const {return d_ptr;}
165    QtRuntimeMethod(QtRuntimeMethodData *dd, ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst);
166    QtRuntimeMethodData *d_ptr;
167};
168
169class QtRuntimeMetaMethod : public QtRuntimeMethod
170{
171public:
172    QtRuntimeMetaMethod(ExecState *exec, const Identifier &n, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature, bool allowPrivate);
173
174    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
175    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
176    virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
177
178    virtual void markChildren(MarkStack& markStack);
179
180protected:
181    QtRuntimeMetaMethodData* d_func() const {return reinterpret_cast<QtRuntimeMetaMethodData*>(d_ptr);}
182
183private:
184    virtual CallType getCallData(CallData&);
185    static EncodedJSValue JSC_HOST_CALL call(ExecState* exec);
186    static JSValue lengthGetter(ExecState*, JSValue, const Identifier&);
187    static JSValue connectGetter(ExecState*, JSValue, const Identifier&);
188    static JSValue disconnectGetter(ExecState*, JSValue, const Identifier&);
189};
190
191class QtConnectionObject;
192class QtRuntimeConnectionMethod : public QtRuntimeMethod
193{
194public:
195    QtRuntimeConnectionMethod(ExecState *exec, const Identifier &n, bool isConnect, PassRefPtr<QtInstance> inst, int index, const QByteArray& signature );
196
197    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
198    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
199    virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
200
201protected:
202    QtRuntimeConnectionMethodData* d_func() const {return reinterpret_cast<QtRuntimeConnectionMethodData*>(d_ptr);}
203
204private:
205    virtual CallType getCallData(CallData&);
206    static EncodedJSValue JSC_HOST_CALL call(ExecState* exec);
207    static JSValue lengthGetter(ExecState*, JSValue, const Identifier&);
208    static QMultiMap<QObject *, QtConnectionObject *> connections;
209    friend class QtConnectionObject;
210};
211
212class QtConnectionObject: public QObject
213{
214public:
215    QtConnectionObject(JSGlobalData&, PassRefPtr<QtInstance> instance, int signalIndex, JSObject* thisObject, JSObject* funcObject);
216    ~QtConnectionObject();
217
218    static const QMetaObject staticMetaObject;
219    virtual const QMetaObject *metaObject() const;
220    virtual void *qt_metacast(const char *);
221    virtual int qt_metacall(QMetaObject::Call, int, void **argv);
222
223    bool match(QObject *sender, int signalIndex, JSObject* thisObject, JSObject *funcObject);
224
225    // actual slot:
226    void execute(void **argv);
227
228private:
229    RefPtr<QtInstance> m_instance;
230    int m_signalIndex;
231    QObject* m_originalObject; // only used as a key, not dereferenced
232    Strong<JSObject> m_thisObject;
233    Strong<JSObject> m_funcObject;
234};
235
236QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type hint, int *distance);
237JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& variant);
238
239} // namespace Bindings
240} // namespace JSC
241
242#endif
243