1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtDeclarative/qdeclarative.h>
44 #include "qv8sequencewrapper_p.h"
45 #include "qv8sequencewrapper_p_p.h"
46 #include "qv8engine_p.h"
50 QV8SequenceWrapper::QV8SequenceWrapper()
55 QV8SequenceWrapper::~QV8SequenceWrapper()
59 #define REGISTER_QML_SEQUENCE_METATYPE(unused, unused2, SequenceType, unused3) qRegisterMetaType<SequenceType>();
60 void QV8SequenceWrapper::init(QV8Engine *engine)
62 FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
65 m_toString = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ToString)->GetFunction());
66 m_valueOf = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ValueOf)->GetFunction());
67 v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
68 ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
69 ft->InstanceTemplate()->SetIndexedPropertyHandler(IndexedGetter, IndexedSetter, 0, IndexedDeleter, IndexedEnumerator);
70 ft->InstanceTemplate()->SetAccessor(v8::String::New("length"), LengthGetter, LengthSetter,
71 v8::Handle<v8::Value>(), v8::DEFAULT,
72 v8::PropertyAttribute(v8::DontDelete | v8::DontEnum));
73 ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0,
74 m_toString, v8::DEFAULT,
75 v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete | v8::DontEnum));
76 ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0,
77 m_valueOf, v8::DEFAULT,
78 v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete | v8::DontEnum));
79 ft->InstanceTemplate()->SetHasExternalResource(true);
80 ft->InstanceTemplate()->MarkAsUseUserObjectComparison();
81 m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
83 #undef REGISTER_QML_SEQUENCE_METATYPE
85 void QV8SequenceWrapper::destroy()
87 qPersistentDispose(m_toString);
88 qPersistentDispose(m_valueOf);
89 qPersistentDispose(m_constructor);
92 bool QV8SequenceWrapper::isEqual(QV8ObjectResource *lhs, QV8ObjectResource *rhs)
94 Q_ASSERT(lhs && rhs && lhs->resourceType() == QV8ObjectResource::SequenceType && rhs->resourceType() == QV8ObjectResource::SequenceType);
95 QV8SequenceResource *lr = static_cast<QV8SequenceResource *>(lhs);
96 QV8SequenceResource *rr = static_cast<QV8SequenceResource *>(rhs);
97 return lr->isEqual(rr);
100 quint32 QV8SequenceWrapper::sequenceLength(QV8ObjectResource *r)
102 Q_ASSERT(r->resourceType() == QV8ObjectResource::SequenceType);
103 QV8SequenceResource *sr = static_cast<QV8SequenceResource *>(r);
105 return sr->lengthGetter();
108 #define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
109 if (sequenceType == qMetaTypeId<SequenceType>()) { \
110 r = new QV8##ElementTypeName##SequenceResource(m_engine, object, propertyIndex); \
113 v8::Local<v8::Object> QV8SequenceWrapper::newSequence(int sequenceType, QObject *object, int propertyIndex, bool *succeeded)
115 // This function is called when the property is a QObject Q_PROPERTY of
116 // the given sequence type. Internally we store a typed-sequence
117 // (as well as object ptr + property index for updated-read and write-back)
118 // and so access/mutate avoids variant conversion.
120 QV8SequenceResource *r = 0;
121 FOREACH_QML_SEQUENCE_TYPE(NEW_REFERENCE_SEQUENCE) { /* else */ *succeeded = false; return v8::Local<v8::Object>(); }
123 v8::Local<v8::Object> rv = m_constructor->NewInstance();
124 rv->SetExternalResource(r);
125 rv->SetPrototype(v8::Array::New(1)->GetPrototype());
128 #undef NEW_REFERENCE_SEQUENCE
130 #define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
131 if (sequenceType == qMetaTypeId<SequenceType>()) { \
132 r = new QV8##ElementTypeName##SequenceResource(m_engine, v.value<SequenceType>()); \
135 v8::Local<v8::Object> QV8SequenceWrapper::fromVariant(const QVariant& v, bool *succeeded)
137 // This function is called when assigning a sequence value to a normal JS var
138 // in a JS block. Internally, we store a sequence of the specified type.
139 // Access and mutation is extremely fast since it will not need to modify any
141 int sequenceType = v.userType();
143 QV8SequenceResource *r = 0;
144 FOREACH_QML_SEQUENCE_TYPE(NEW_COPY_SEQUENCE) { /* else */ *succeeded = false; return v8::Local<v8::Object>(); }
146 v8::Local<v8::Object> rv = m_constructor->NewInstance();
147 rv->SetExternalResource(r);
148 rv->SetPrototype(v8::Array::New(1)->GetPrototype());
151 #undef NEW_COPY_SEQUENCE
153 QVariant QV8SequenceWrapper::toVariant(QV8ObjectResource *r)
155 Q_ASSERT(r->resourceType() == QV8ObjectResource::SequenceType);
156 QV8SequenceResource *resource = static_cast<QV8SequenceResource *>(r);
157 return resource->toVariant();
160 #define SEQUENCE_TO_VARIANT(ElementType, ElementTypeName, SequenceType, unused) \
161 if (typeHint == qMetaTypeId<SequenceType>()) { \
162 return QV8##ElementTypeName##SequenceResource::toVariant(m_engine, array, length, succeeded); \
165 QVariant QV8SequenceWrapper::toVariant(v8::Handle<v8::Array> array, int typeHint, bool *succeeded)
168 uint32_t length = array->Length();
169 FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ *succeeded = false; return QVariant(); }
171 #undef SEQUENCE_TO_VARIANT
173 v8::Handle<v8::Value> QV8SequenceWrapper::IndexedSetter(quint32 index, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
175 QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This());
177 return sr->indexedSetter(index, value);
180 v8::Handle<v8::Value> QV8SequenceWrapper::IndexedGetter(quint32 index, const v8::AccessorInfo &info)
182 QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This());
184 return sr->indexedGetter(index);
187 v8::Handle<v8::Boolean> QV8SequenceWrapper::IndexedDeleter(quint32 index, const v8::AccessorInfo &info)
189 QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This());
191 return sr->indexedDeleter(index);
194 v8::Handle<v8::Array> QV8SequenceWrapper::IndexedEnumerator(const v8::AccessorInfo &info)
196 QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This());
198 return sr->indexedEnumerator();
201 v8::Handle<v8::Value> QV8SequenceWrapper::LengthGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info)
204 QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This());
206 return v8::Integer::NewFromUnsigned(sr->lengthGetter());
209 void QV8SequenceWrapper::LengthSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo &info)
212 QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This());
214 sr->lengthSetter(value);
217 v8::Handle<v8::Value> QV8SequenceWrapper::ToStringGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info)
223 v8::Handle<v8::Value> QV8SequenceWrapper::ValueOfGetter(v8::Local<v8::String> property,
224 const v8::AccessorInfo &info)
230 v8::Handle<v8::Value> QV8SequenceWrapper::ToString(const v8::Arguments &args)
232 QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(args.This());
234 return sr->toString();
237 v8::Handle<v8::Value> QV8SequenceWrapper::ValueOf(const v8::Arguments &args)
239 QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(args.This());
241 v8::Handle<v8::Value> tostringValue = sr->toString();
242 if (!tostringValue.IsEmpty())
243 return tostringValue;
244 return v8::Integer::NewFromUnsigned(sr->lengthGetter());
247 v8::Handle<v8::Value> QV8SequenceWrapper::Getter(v8::Local<v8::String> property,
248 const v8::AccessorInfo &info)
252 return v8::Handle<v8::Value>();
255 v8::Handle<v8::Value> QV8SequenceWrapper::Setter(v8::Local<v8::String> property,
256 v8::Local<v8::Value> value,
257 const v8::AccessorInfo &info)