Merge the QJSEngine and QJSValue development branch into master.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v8 / qv8variantwrapper.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 "qv8variantwrapper_p.h"
43 #include "qv8engine_p.h"
44 #include "qdeclarativeengine_p.h"
45
46 QT_BEGIN_NAMESPACE
47
48 class QV8VariantResource : public QV8ObjectResource, 
49                            public QDeclarativeEnginePrivate::ScarceResourceData
50 {
51     V8_RESOURCE_TYPE(VariantType);
52 public:
53     QV8VariantResource(QV8Engine *engine, const QVariant &data);
54 };
55
56 QV8VariantResource::QV8VariantResource(QV8Engine *engine, const QVariant &data)
57 : QV8ObjectResource(engine), QDeclarativeEnginePrivate::ScarceResourceData(data)
58 {
59 }
60
61 QV8VariantWrapper::QV8VariantWrapper()
62 : m_engine(0)
63 {
64 }
65
66 QV8VariantWrapper::~QV8VariantWrapper()
67 {
68 }
69
70 void QV8VariantWrapper::init(QV8Engine *engine)
71 {
72     m_engine = engine;
73     m_toString = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ToString)->GetFunction());
74     m_valueOf = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ValueOf)->GetFunction());
75
76     {
77     v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
78     ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
79     ft->InstanceTemplate()->SetHasExternalResource(true);
80     ft->InstanceTemplate()->MarkAsUseUserObjectComparison();
81     ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0, 
82                                         m_toString, v8::DEFAULT, 
83                                         v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
84     ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0,
85                                         m_valueOf, v8::DEFAULT,
86                                         v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
87     m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
88     }
89     {
90     m_preserve = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(Preserve)->GetFunction());
91     m_destroy = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(Destroy)->GetFunction());
92     v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
93     ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
94     ft->InstanceTemplate()->SetHasExternalResource(true);
95     ft->InstanceTemplate()->MarkAsUseUserObjectComparison();
96     ft->InstanceTemplate()->SetAccessor(v8::String::New("preserve"), PreserveGetter, 0, 
97                                         m_preserve, v8::DEFAULT, 
98                                         v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
99     ft->InstanceTemplate()->SetAccessor(v8::String::New("destroy"), DestroyGetter, 0, 
100                                         m_destroy, v8::DEFAULT, 
101                                         v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
102     ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0, 
103                                         m_toString, v8::DEFAULT, 
104                                         v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
105     ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0,
106                                         m_valueOf, v8::DEFAULT,
107                                         v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
108     m_scarceConstructor = qPersistentNew<v8::Function>(ft->GetFunction());
109     }
110
111 }
112
113 void QV8VariantWrapper::destroy()
114 {
115     qPersistentDispose(m_valueOf);
116     qPersistentDispose(m_toString);
117     qPersistentDispose(m_destroy);
118     qPersistentDispose(m_preserve);
119     qPersistentDispose(m_scarceConstructor);
120     qPersistentDispose(m_constructor);
121 }
122
123 v8::Local<v8::Object> QV8VariantWrapper::newVariant(const QVariant &value)
124 {
125     bool scarceResource = value.type() == QVariant::Pixmap ||
126                           value.type() == QVariant::Image;
127
128     // XXX NewInstance() should be optimized
129     v8::Local<v8::Object> rv;
130     QV8VariantResource *r = new QV8VariantResource(m_engine, value);
131
132     if (scarceResource) {
133         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_engine->engine());
134         Q_ASSERT(ep->scarceResourcesRefCount);
135         rv = m_scarceConstructor->NewInstance();
136         ep->scarceResources.insert(r);
137     } else {
138         rv = m_constructor->NewInstance();
139     }
140
141     rv->SetExternalResource(r);
142     return rv;
143 }
144
145 bool QV8VariantWrapper::isVariant(v8::Handle<v8::Value> value)
146 {
147     return value->IsObject() && v8_resource_cast<QV8VariantResource>(value->ToObject());
148 }
149
150 QVariant QV8VariantWrapper::toVariant(v8::Handle<v8::Object> obj)
151 {
152     QV8VariantResource *r =  v8_resource_cast<QV8VariantResource>(obj);
153     return r?r->data:QVariant();
154 }
155
156 QVariant QV8VariantWrapper::toVariant(QV8ObjectResource *r)
157 {
158     Q_ASSERT(r->resourceType() == QV8ObjectResource::VariantType);
159     return static_cast<QV8VariantResource *>(r)->data;
160 }
161
162 v8::Handle<v8::Value> QV8VariantWrapper::Getter(v8::Local<v8::String> property, 
163                                                 const v8::AccessorInfo &info)
164 {
165     return v8::Undefined();
166 }
167
168 v8::Handle<v8::Value> QV8VariantWrapper::Setter(v8::Local<v8::String> property, 
169                                                 v8::Local<v8::Value> value,
170                                                 const v8::AccessorInfo &info)
171 {
172     return v8::Undefined();
173 }
174
175 v8::Handle<v8::Value> QV8VariantWrapper::PreserveGetter(v8::Local<v8::String> property, 
176                                                         const v8::AccessorInfo &info)
177 {
178     Q_UNUSED(property);
179     return info.Data();
180 }
181
182 v8::Handle<v8::Value> QV8VariantWrapper::DestroyGetter(v8::Local<v8::String> property, 
183                                                        const v8::AccessorInfo &info)
184 {
185     Q_UNUSED(property);
186     return info.Data();
187 }
188
189 v8::Handle<v8::Value> QV8VariantWrapper::ToStringGetter(v8::Local<v8::String> property, 
190                                                         const v8::AccessorInfo &info)
191 {
192     Q_UNUSED(property);
193     return info.Data();
194 }
195
196 v8::Handle<v8::Value> QV8VariantWrapper::ValueOfGetter(v8::Local<v8::String> property,
197                                                        const v8::AccessorInfo &info)
198 {
199     Q_UNUSED(property);
200     return info.Data();
201 }
202
203 v8::Handle<v8::Value> QV8VariantWrapper::Preserve(const v8::Arguments &args)
204 {
205     QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
206     if (resource) {
207         resource->node.remove();
208     }
209     return v8::Undefined();
210 }
211
212 v8::Handle<v8::Value> QV8VariantWrapper::Destroy(const v8::Arguments &args)
213 {
214     QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
215     if (resource) {
216         resource->data = QVariant();
217         resource->node.remove();
218     }
219     return v8::Undefined();
220 }
221
222 v8::Handle<v8::Value> QV8VariantWrapper::ToString(const v8::Arguments &args)
223 {
224     QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
225     if (resource) {
226         QString result = resource->data.toString();
227         if (result.isEmpty() && !resource->data.canConvert(QVariant::String))
228             result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(resource->data.typeName()));
229         return resource->engine->toString(result);
230     } else {
231         return v8::Undefined();
232     }
233 }
234
235 v8::Handle<v8::Value> QV8VariantWrapper::ValueOf(const v8::Arguments &args)
236 {
237     QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
238     if (resource) {
239         QVariant v = resource->data;
240         switch (v.type()) {
241         case QVariant::Invalid:
242             return v8::Undefined();
243         case QVariant::String:
244             return resource->engine->toString(v.toString());
245         case QVariant::Int:
246         case QVariant::Double:
247         case QVariant::UInt:
248             return v8::Number::New(v.toDouble());
249         case QVariant::Bool:
250             return v8::Boolean::New(v.toBool());
251         default:
252             break;
253         }
254     }
255     return args.This();
256 }
257
258 QT_END_NAMESPACE