Merge branch 'v8'
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v8 / qv8typewrapper.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qv8contextwrapper_p.h"
43 #include "qv8engine_p.h"
44
45 #include <private/qdeclarativeengine_p.h>
46 #include <private/qdeclarativecontext_p.h>
47
48 QT_BEGIN_NAMESPACE
49
50 class QV8TypeResource : public QV8ObjectResource
51 {
52     V8_RESOURCE_TYPE(TypeType);
53
54 public:
55     QV8TypeResource(QV8Engine *engine);
56     virtual ~QV8TypeResource();
57
58     QV8TypeWrapper::TypeNameMode mode;
59
60     QDeclarativeGuard<QObject> object;
61     QDeclarativeType *type;
62     QDeclarativeTypeNameCache *typeNamespace;
63 };
64
65 QV8TypeResource::QV8TypeResource(QV8Engine *engine)
66 : QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0)
67 {
68 }
69
70 QV8TypeResource::~QV8TypeResource()
71 {
72     if (typeNamespace) typeNamespace->release();
73 }
74
75 QV8TypeWrapper::QV8TypeWrapper()
76 : m_engine(0)
77 {
78 }
79
80 QV8TypeWrapper::~QV8TypeWrapper()
81 {
82 }
83
84 void QV8TypeWrapper::destroy()
85 {
86     qPersistentDispose(m_constructor);
87 }
88
89 void QV8TypeWrapper::init(QV8Engine *engine)
90 {
91     m_engine = engine;
92     v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
93     ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter);
94     ft->InstanceTemplate()->SetHasExternalResource(true);
95     m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
96 }
97
98 v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode)
99 {
100     Q_ASSERT(t);
101     // XXX NewInstance() should be optimized
102     v8::Local<v8::Object> rv = m_constructor->NewInstance(); 
103     QV8TypeResource *r = new QV8TypeResource(m_engine);
104     r->mode = mode; r->object = o; r->type = t;
105     rv->SetExternalResource(r);
106     return rv;
107 }
108
109 v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, TypeNameMode mode)
110 {
111     Q_ASSERT(t);
112     // XXX NewInstance() should be optimized
113     v8::Local<v8::Object> rv = m_constructor->NewInstance(); 
114     QV8TypeResource *r = new QV8TypeResource(m_engine);
115     t->addref();
116     r->mode = mode; r->object = o; r->typeNamespace = t;
117     rv->SetExternalResource(r);
118     return rv;
119 }
120
121 v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property, 
122                                              const v8::AccessorInfo &info)
123 {
124     v8::Object::ExternalResource *r = info.This()->GetExternalResource();
125     QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This());
126
127     if (!resource) 
128         return v8::Undefined();
129
130     QV8Engine *v8engine = resource->engine;
131     QObject *object = resource->object;
132
133     QHashedV8String propertystring(property);
134
135     if (resource->type) {
136         QDeclarativeType *type = resource->type;
137
138         if (QV8Engine::startsWithUpper(property)) {
139             if (resource->mode == IncludeEnums) {
140                 QString name = v8engine->toString(property);
141
142                 // ### Optimize
143                 QByteArray enumName = name.toUtf8();
144                 const QMetaObject *metaObject = type->baseMetaObject();
145                 for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
146                     QMetaEnum e = metaObject->enumerator(ii);
147                     int value = e.keyToValue(enumName.constData());
148                     if (value != -1) 
149                         return v8::Integer::New(value);
150                 }
151             } 
152
153             // Fall through to undefined
154
155         } else if (resource->object) {
156             QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
157             if (ao) 
158                 return v8engine->qobjectWrapper()->getProperty(ao, propertystring, 
159                                                                QV8QObjectWrapper::IgnoreRevision);
160
161             // Fall through to undefined
162         }
163
164         // Fall through to undefined
165
166     } else if (resource->typeNamespace) {
167
168         QDeclarativeTypeNameCache *typeNamespace = resource->typeNamespace;
169         QDeclarativeTypeNameCache::Data *d = typeNamespace->data(propertystring);
170         Q_ASSERT(!d || !d->typeNamespace); // Nested namespaces not supported
171
172         if (d && d->type) {
173             return v8engine->typeWrapper()->newObject(object, d->type, resource->mode);
174         } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = typeNamespace->moduleApi()) {
175             // XXX TODO: Currently module APIs are implemented against QScriptValues.  Consequently we
176             // can't do anything here until the QtScript/V8 binding is complete.
177             return v8::Undefined();
178
179         }
180
181         // Fall through to undefined
182
183     } else {
184         Q_ASSERT(!"Unreachable");
185     }
186     return v8::Undefined(); 
187 }
188
189 v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property, 
190                                              v8::Local<v8::Value> value,
191                                              const v8::AccessorInfo &info)
192 {
193     v8::Object::ExternalResource *r = info.This()->GetExternalResource();
194     QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This());
195
196     if (!resource) 
197         return value;
198
199     QV8Engine *v8engine = resource->engine;
200
201     // XXX TODO: Implement writes to module API objects
202
203     QHashedV8String propertystring(property);
204
205     if (resource->type && resource->object) {
206         QDeclarativeType *type = resource->type;
207         QObject *object = resource->object;
208         QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
209         if (ao) 
210             v8engine->qobjectWrapper()->setProperty(ao, propertystring, value, 
211                                                     QV8QObjectWrapper::IgnoreRevision);
212     }
213
214     return value;
215 }
216
217 QT_END_NAMESPACE