2011-05-11 07:20:40 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2013-01-02 11:17:46 +00:00
|
|
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
2012-09-20 05:21:40 +00:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
2011-05-11 07:20:40 +00:00
|
|
|
**
|
2012-02-16 04:43:03 +00:00
|
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
2011-05-11 07:20:40 +00:00
|
|
|
**
|
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
2012-09-20 05:21:40 +00:00
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
|
|
|
**
|
2011-05-11 07:20:40 +00:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-09-20 05:21:40 +00:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
**
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2011-05-11 07:20:40 +00:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
2011-08-04 06:20:18 +00:00
|
|
|
** GNU General Public License Usage
|
2012-09-20 05:21:40 +00:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 3.0 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU General Public License version 3.0 requirements will be
|
|
|
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
2011-05-11 07:20:40 +00:00
|
|
|
**
|
2012-01-24 03:37:23 +00:00
|
|
|
**
|
2011-05-11 07:20:40 +00:00
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
2013-05-20 09:13:48 +00:00
|
|
|
#include "qv4serialize_p.h"
|
2011-05-11 07:20:40 +00:00
|
|
|
|
2013-05-20 09:13:48 +00:00
|
|
|
#include <private/qv8engine_p.h>
|
2013-01-10 22:07:37 +00:00
|
|
|
#include <private/qqmllistmodel_p.h>
|
|
|
|
#include <private/qqmllistmodelworkeragent_p.h>
|
2011-06-07 06:54:09 +00:00
|
|
|
|
2013-04-27 14:28:51 +00:00
|
|
|
#include <private/qv4value_p.h>
|
2013-05-16 10:17:22 +00:00
|
|
|
#include <private/qv4dateobject_p.h>
|
|
|
|
#include <private/qv4regexpobject_p.h>
|
2013-05-31 14:06:42 +00:00
|
|
|
#include <private/qv4sequenceobject_p.h>
|
|
|
|
#include <private/qv4objectproto_p.h>
|
2013-04-27 14:28:51 +00:00
|
|
|
|
2011-05-11 07:20:40 +00:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2013-05-20 09:13:48 +00:00
|
|
|
using namespace QV4;
|
|
|
|
|
2011-05-11 07:20:40 +00:00
|
|
|
// We allow the following JavaScript types to be passed between the main and
|
|
|
|
// the secondary thread:
|
|
|
|
// + undefined
|
|
|
|
// + null
|
|
|
|
// + Boolean
|
|
|
|
// + String
|
|
|
|
// + Function
|
|
|
|
// + Array
|
|
|
|
// + "Simple" Objects
|
|
|
|
// + Number
|
|
|
|
// + Date
|
|
|
|
// + RegExp
|
|
|
|
// <quint8 type><quint24 size><data>
|
|
|
|
|
|
|
|
enum Type {
|
|
|
|
WorkerUndefined,
|
|
|
|
WorkerNull,
|
|
|
|
WorkerTrue,
|
|
|
|
WorkerFalse,
|
|
|
|
WorkerString,
|
|
|
|
WorkerFunction,
|
|
|
|
WorkerArray,
|
|
|
|
WorkerObject,
|
|
|
|
WorkerInt32,
|
|
|
|
WorkerUint32,
|
|
|
|
WorkerNumber,
|
|
|
|
WorkerDate,
|
2011-06-07 06:54:09 +00:00
|
|
|
WorkerRegexp,
|
Add support for more sequence types
This commit adds support for more sequence types by adding a sequence
wrapper. This class enables conversion between v8::Array and C++
sequences of various types (currently just QList<int>, QList<qreal>,
QList<bool>, QList<QString>, QList<QUrl> and QStringList), but more
types can be added later if required).
When a JavaScript object is created from such a sequence, its
prototype object is set to the v8::Array prototype object. The
indexed setter, indexed getter, length and toString methods are
implemented directly or in terms of the underlying sequence resource.
Note that currently, sequences of ValueTypes are NOT supported, due to
the fact that operations like:
someObj.someValueTypeSequence[i].x = 5;
would not behave as required.
Task-number: QTBUG-20826
Task-number: QTBUG-21770
Change-Id: I36deb448fb0e87a32084a900e70a2604ff369309
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
2011-10-03 00:52:38 +00:00
|
|
|
WorkerListModel,
|
|
|
|
WorkerSequence
|
2011-05-11 07:20:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static inline quint32 valueheader(Type type, quint32 size = 0)
|
|
|
|
{
|
|
|
|
return quint8(type) << 24 | (size & 0xFFFFFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Type headertype(quint32 header)
|
|
|
|
{
|
|
|
|
return (Type)(header >> 24);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline quint32 headersize(quint32 header)
|
|
|
|
{
|
|
|
|
return header & 0xFFFFFF;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void push(QByteArray &data, quint32 value)
|
|
|
|
{
|
|
|
|
data.append((const char *)&value, sizeof(quint32));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void push(QByteArray &data, double value)
|
|
|
|
{
|
|
|
|
data.append((const char *)&value, sizeof(double));
|
|
|
|
}
|
|
|
|
|
2011-06-07 06:54:09 +00:00
|
|
|
static inline void push(QByteArray &data, void *ptr)
|
|
|
|
{
|
|
|
|
data.append((const char *)&ptr, sizeof(void *));
|
|
|
|
}
|
|
|
|
|
2011-05-11 07:20:40 +00:00
|
|
|
static inline void reserve(QByteArray &data, int extra)
|
|
|
|
{
|
|
|
|
data.reserve(data.size() + extra);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline quint32 popUint32(const char *&data)
|
|
|
|
{
|
|
|
|
quint32 rv = *((quint32 *)data);
|
|
|
|
data += sizeof(quint32);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline double popDouble(const char *&data)
|
|
|
|
{
|
|
|
|
double rv = *((double *)data);
|
|
|
|
data += sizeof(double);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2011-06-07 06:54:09 +00:00
|
|
|
static inline void *popPtr(const char *&data)
|
|
|
|
{
|
|
|
|
void *rv = *((void **)data);
|
|
|
|
data += sizeof(void *);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2011-06-09 04:40:44 +00:00
|
|
|
// XXX TODO: Check that worker script is exception safe in the case of
|
|
|
|
// serialization/deserialization failures
|
2011-05-11 07:20:40 +00:00
|
|
|
|
|
|
|
#define ALIGN(size) (((size) + 3) & ~3)
|
2013-05-20 09:13:48 +00:00
|
|
|
void Serialize::serialize(QByteArray &data, const QV4::Value &v, QV8Engine *engine)
|
2011-05-11 07:20:40 +00:00
|
|
|
{
|
2013-05-14 16:58:34 +00:00
|
|
|
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
|
2013-09-11 14:28:17 +00:00
|
|
|
QV4::Scope scope(v4);
|
|
|
|
|
2013-05-16 10:17:22 +00:00
|
|
|
if (v.isEmpty()) {
|
|
|
|
} else if (v.isUndefined()) {
|
2011-05-11 07:20:40 +00:00
|
|
|
push(data, valueheader(WorkerUndefined));
|
2013-05-16 10:17:22 +00:00
|
|
|
} else if (v.isNull()) {
|
2011-05-11 07:20:40 +00:00
|
|
|
push(data, valueheader(WorkerNull));
|
2013-05-16 10:17:22 +00:00
|
|
|
} else if (v.isBoolean()) {
|
|
|
|
push(data, valueheader(v.booleanValue() == true ? WorkerTrue : WorkerFalse));
|
|
|
|
} else if (QV4::String *s = v.asString()) {
|
|
|
|
const QString &qstr = s->toQString();
|
|
|
|
int length = qstr.length();
|
2011-05-11 07:20:40 +00:00
|
|
|
if (length > 0xFFFFFF) {
|
|
|
|
push(data, valueheader(WorkerUndefined));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int utf16size = ALIGN(length * sizeof(uint16_t));
|
|
|
|
|
|
|
|
reserve(data, utf16size + sizeof(quint32));
|
|
|
|
push(data, valueheader(WorkerString, length));
|
|
|
|
|
|
|
|
int offset = data.size();
|
|
|
|
data.resize(data.size() + utf16size);
|
|
|
|
char *buffer = data.data() + offset;
|
|
|
|
|
2013-05-16 10:17:22 +00:00
|
|
|
memcpy(buffer, qstr.constData(), length*sizeof(QChar));
|
|
|
|
} else if (v.asFunctionObject()) {
|
2011-06-09 04:40:44 +00:00
|
|
|
// XXX TODO: Implement passing function objects between the main and
|
|
|
|
// worker scripts
|
2011-05-11 07:20:40 +00:00
|
|
|
push(data, valueheader(WorkerUndefined));
|
2013-05-16 10:17:22 +00:00
|
|
|
} else if (QV4::ArrayObject *array = v.asArrayObject()) {
|
|
|
|
uint32_t length = array->arrayLength();
|
2011-05-11 07:20:40 +00:00
|
|
|
if (length > 0xFFFFFF) {
|
|
|
|
push(data, valueheader(WorkerUndefined));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
reserve(data, sizeof(quint32) + length * sizeof(quint32));
|
|
|
|
push(data, valueheader(WorkerArray, length));
|
|
|
|
for (uint32_t ii = 0; ii < length; ++ii)
|
2013-09-11 19:48:23 +00:00
|
|
|
serialize(data, QV4::Value::fromReturnedValue(array->getIndexed(ii)), engine);
|
2013-05-16 10:17:22 +00:00
|
|
|
} else if (v.isInteger()) {
|
2011-05-11 07:20:40 +00:00
|
|
|
reserve(data, 2 * sizeof(quint32));
|
|
|
|
push(data, valueheader(WorkerInt32));
|
2013-05-16 10:17:22 +00:00
|
|
|
push(data, (quint32)v.integerValue());
|
|
|
|
// } else if (v->IsUint32()) {
|
|
|
|
// reserve(data, 2 * sizeof(quint32));
|
|
|
|
// push(data, valueheader(WorkerUint32));
|
|
|
|
// push(data, v->Uint32Value());
|
|
|
|
} else if (v.isNumber()) {
|
2011-05-11 07:20:40 +00:00
|
|
|
reserve(data, sizeof(quint32) + sizeof(double));
|
|
|
|
push(data, valueheader(WorkerNumber));
|
2013-05-16 10:17:22 +00:00
|
|
|
push(data, v.asDouble());
|
|
|
|
} else if (QV4::DateObject *d = v.asDateObject()) {
|
2011-05-11 07:20:40 +00:00
|
|
|
reserve(data, sizeof(quint32) + sizeof(double));
|
|
|
|
push(data, valueheader(WorkerDate));
|
2013-05-16 10:17:22 +00:00
|
|
|
push(data, d->value.asDouble());
|
2013-05-31 12:02:15 +00:00
|
|
|
} else if (QV4::RegExpObject *re = v.as<RegExpObject>()) {
|
2013-05-16 10:17:22 +00:00
|
|
|
quint32 flags = re->flags();
|
|
|
|
QString pattern = re->source();
|
|
|
|
int length = pattern.length() + 1;
|
2011-05-11 07:20:40 +00:00
|
|
|
if (length > 0xFFFFFF) {
|
|
|
|
push(data, valueheader(WorkerUndefined));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int utf16size = ALIGN(length * sizeof(uint16_t));
|
|
|
|
|
|
|
|
reserve(data, sizeof(quint32) + utf16size);
|
|
|
|
push(data, valueheader(WorkerRegexp, flags));
|
|
|
|
push(data, (quint32)length);
|
2013-05-16 10:17:22 +00:00
|
|
|
|
2011-05-11 07:20:40 +00:00
|
|
|
int offset = data.size();
|
|
|
|
data.resize(data.size() + utf16size);
|
|
|
|
char *buffer = data.data() + offset;
|
|
|
|
|
2013-05-16 10:17:22 +00:00
|
|
|
memcpy(buffer, pattern.constData(), length*sizeof(QChar));
|
2013-06-03 13:23:20 +00:00
|
|
|
} else if (QV4::QObjectWrapper *qobjectWrapper = v.as<QV4::QObjectWrapper>()) {
|
2013-05-16 10:17:22 +00:00
|
|
|
// XXX TODO: Generalize passing objects between the main thread and worker scripts so
|
2011-06-09 04:40:44 +00:00
|
|
|
// that others can trivially plug in their elements.
|
2013-06-03 13:51:45 +00:00
|
|
|
QQmlListModel *lm = qobject_cast<QQmlListModel *>(qobjectWrapper->object());
|
2011-06-07 06:54:09 +00:00
|
|
|
if (lm && lm->agent()) {
|
2013-01-10 22:07:37 +00:00
|
|
|
QQmlListModelWorkerAgent *agent = lm->agent();
|
2011-06-07 06:54:09 +00:00
|
|
|
agent->addref();
|
|
|
|
push(data, valueheader(WorkerListModel));
|
|
|
|
push(data, (void *)agent);
|
|
|
|
return;
|
2013-05-16 10:17:22 +00:00
|
|
|
}
|
2011-06-07 06:54:09 +00:00
|
|
|
// No other QObject's are allowed to be sent
|
|
|
|
push(data, valueheader(WorkerUndefined));
|
2013-05-16 10:17:22 +00:00
|
|
|
} else if (QV4::Object *o = v.asObject()) {
|
2013-05-14 16:58:34 +00:00
|
|
|
|
|
|
|
if (o->isListType()) {
|
|
|
|
// valid sequence. we generate a length (sequence length + 1 for the sequence type)
|
2013-09-11 14:28:17 +00:00
|
|
|
uint32_t seqLength = ScopedValue(scope, o->get(v4->id_length))->toUInt32();
|
2013-05-14 16:58:34 +00:00
|
|
|
uint32_t length = seqLength + 1;
|
|
|
|
if (length > 0xFFFFFF) {
|
|
|
|
push(data, valueheader(WorkerUndefined));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
reserve(data, sizeof(quint32) + length * sizeof(quint32));
|
|
|
|
push(data, valueheader(WorkerSequence, length));
|
2013-05-21 15:06:36 +00:00
|
|
|
serialize(data, QV4::Value::fromInt32(QV4::SequencePrototype::metaTypeForSequence(o)), engine); // sequence type
|
2013-05-14 16:58:34 +00:00
|
|
|
for (uint32_t ii = 0; ii < seqLength; ++ii)
|
2013-09-11 19:48:23 +00:00
|
|
|
serialize(data, QV4::Value::fromReturnedValue(o->getIndexed(ii)), engine); // sequence elements
|
2013-05-14 16:58:34 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-05-16 10:17:22 +00:00
|
|
|
// regular object
|
2013-05-31 14:06:42 +00:00
|
|
|
QV4::ArrayObject *properties = QV4::ObjectPrototype::getOwnPropertyNames(v4, v);
|
2013-05-16 10:17:22 +00:00
|
|
|
quint32 length = properties->arrayLength();
|
|
|
|
if (length > 0xFFFFFF) {
|
|
|
|
push(data, valueheader(WorkerUndefined));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
push(data, valueheader(WorkerObject, length));
|
|
|
|
|
2013-09-11 14:28:17 +00:00
|
|
|
QV4::ScopedValue val(scope);
|
2013-09-11 19:48:23 +00:00
|
|
|
QV4::ScopedValue s(scope);
|
2013-05-16 10:17:22 +00:00
|
|
|
for (quint32 ii = 0; ii < length; ++ii) {
|
2013-09-11 19:48:23 +00:00
|
|
|
s = properties->getIndexed(ii);
|
|
|
|
serialize(data, s, engine);
|
2013-05-16 10:17:22 +00:00
|
|
|
|
|
|
|
QV4::ExecutionContext *ctx = v4->current;
|
|
|
|
try {
|
2013-09-11 19:48:23 +00:00
|
|
|
val = o->get(s->asString());
|
2013-05-16 10:17:22 +00:00
|
|
|
} catch (QV4::Exception &e) {
|
|
|
|
e.accept(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
serialize(data, val, engine);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
} else {
|
2011-05-11 07:20:40 +00:00
|
|
|
push(data, valueheader(WorkerUndefined));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-12 20:37:41 +00:00
|
|
|
ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
|
2011-05-11 07:20:40 +00:00
|
|
|
{
|
|
|
|
quint32 header = popUint32(data);
|
|
|
|
Type type = headertype(header);
|
|
|
|
|
2013-05-16 10:17:22 +00:00
|
|
|
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
|
2013-09-12 20:37:41 +00:00
|
|
|
Scope scope(v4);
|
2013-05-16 10:17:22 +00:00
|
|
|
|
2011-05-11 07:20:40 +00:00
|
|
|
switch (type) {
|
|
|
|
case WorkerUndefined:
|
2013-09-12 20:37:41 +00:00
|
|
|
return QV4::Encode::undefined();
|
2011-05-11 07:20:40 +00:00
|
|
|
case WorkerNull:
|
2013-09-12 20:37:41 +00:00
|
|
|
return QV4::Encode::null();
|
2011-05-11 07:20:40 +00:00
|
|
|
case WorkerTrue:
|
2013-09-12 20:37:41 +00:00
|
|
|
return QV4::Encode(true);
|
2011-05-11 07:20:40 +00:00
|
|
|
case WorkerFalse:
|
2013-09-12 20:37:41 +00:00
|
|
|
return QV4::Encode(false);
|
2011-05-11 07:20:40 +00:00
|
|
|
case WorkerString:
|
|
|
|
{
|
|
|
|
quint32 size = headersize(header);
|
2013-05-16 10:17:22 +00:00
|
|
|
QString qstr((QChar *)data, size);
|
2011-05-11 07:20:40 +00:00
|
|
|
data += ALIGN(size * sizeof(uint16_t));
|
2013-09-12 20:37:41 +00:00
|
|
|
return QV4::Value::fromString(v4->newString(qstr)).asReturnedValue();
|
2011-05-11 07:20:40 +00:00
|
|
|
}
|
|
|
|
case WorkerFunction:
|
|
|
|
Q_ASSERT(!"Unreachable");
|
|
|
|
break;
|
|
|
|
case WorkerArray:
|
|
|
|
{
|
|
|
|
quint32 size = headersize(header);
|
2013-09-14 09:25:02 +00:00
|
|
|
Scoped<ArrayObject> a(scope, v4->newArrayObject());
|
2013-09-12 20:37:41 +00:00
|
|
|
ScopedValue v(scope);
|
2011-05-11 07:20:40 +00:00
|
|
|
for (quint32 ii = 0; ii < size; ++ii) {
|
2013-09-12 20:37:41 +00:00
|
|
|
v = deserialize(data, engine);
|
|
|
|
a->putIndexed(ii, v);
|
2011-05-11 07:20:40 +00:00
|
|
|
}
|
2013-09-14 09:25:02 +00:00
|
|
|
return a.asReturnedValue();
|
2011-05-11 07:20:40 +00:00
|
|
|
}
|
|
|
|
case WorkerObject:
|
|
|
|
{
|
|
|
|
quint32 size = headersize(header);
|
2013-09-16 20:02:27 +00:00
|
|
|
Scoped<Object> o(scope, v4->newObject());
|
2013-09-12 20:37:41 +00:00
|
|
|
ScopedValue name(scope);
|
|
|
|
ScopedValue value(scope);
|
2011-05-11 07:20:40 +00:00
|
|
|
for (quint32 ii = 0; ii < size; ++ii) {
|
2013-09-12 20:37:41 +00:00
|
|
|
name = deserialize(data, engine);
|
|
|
|
value = deserialize(data, engine);
|
|
|
|
o->put(name->asString(), value);
|
2011-05-11 07:20:40 +00:00
|
|
|
}
|
2013-09-16 20:02:27 +00:00
|
|
|
return o.asReturnedValue();
|
2011-05-11 07:20:40 +00:00
|
|
|
}
|
|
|
|
case WorkerInt32:
|
2013-09-12 20:37:41 +00:00
|
|
|
return QV4::Encode((qint32)popUint32(data));
|
2011-05-11 07:20:40 +00:00
|
|
|
case WorkerUint32:
|
2013-09-12 20:37:41 +00:00
|
|
|
return QV4::Encode(popUint32(data));
|
2011-05-11 07:20:40 +00:00
|
|
|
case WorkerNumber:
|
2013-09-12 20:37:41 +00:00
|
|
|
return QV4::Encode(popDouble(data));
|
2011-05-11 07:20:40 +00:00
|
|
|
case WorkerDate:
|
2013-09-13 15:07:44 +00:00
|
|
|
return QV4::Encode(v4->newDateObject(QV4::Value::fromDouble(popDouble(data))));
|
2011-05-11 07:20:40 +00:00
|
|
|
case WorkerRegexp:
|
|
|
|
{
|
|
|
|
quint32 flags = headersize(header);
|
|
|
|
quint32 length = popUint32(data);
|
2013-05-16 10:17:22 +00:00
|
|
|
QString pattern = QString((QChar *)data, length - 1);
|
2011-05-11 07:20:40 +00:00
|
|
|
data += ALIGN(length * sizeof(uint16_t));
|
2013-09-13 15:07:44 +00:00
|
|
|
return Encode(v4->newRegExpObject(pattern, flags));
|
2011-05-11 07:20:40 +00:00
|
|
|
}
|
2011-06-07 06:54:09 +00:00
|
|
|
case WorkerListModel:
|
|
|
|
{
|
|
|
|
void *ptr = popPtr(data);
|
2013-01-10 22:07:37 +00:00
|
|
|
QQmlListModelWorkerAgent *agent = (QQmlListModelWorkerAgent *)ptr;
|
2013-09-12 20:37:41 +00:00
|
|
|
QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(v4, agent));
|
2013-05-24 12:50:03 +00:00
|
|
|
// ### Find a better solution then the ugly property
|
|
|
|
QQmlListModelWorkerAgent::VariantRef ref(agent);
|
|
|
|
QVariant var = qVariantFromValue(ref);
|
2013-09-12 20:37:41 +00:00
|
|
|
QV4::ScopedValue v(scope, engine->fromVariant((var)));
|
|
|
|
rv->asObject()->defineReadonlyProperty(v4->newString("__qml:hidden:ref"), v);
|
2013-05-24 12:50:03 +00:00
|
|
|
|
2011-06-07 06:54:09 +00:00
|
|
|
agent->release();
|
|
|
|
agent->setV8Engine(engine);
|
2013-09-12 20:37:41 +00:00
|
|
|
return rv.asReturnedValue();
|
2011-06-07 06:54:09 +00:00
|
|
|
}
|
Add support for more sequence types
This commit adds support for more sequence types by adding a sequence
wrapper. This class enables conversion between v8::Array and C++
sequences of various types (currently just QList<int>, QList<qreal>,
QList<bool>, QList<QString>, QList<QUrl> and QStringList), but more
types can be added later if required).
When a JavaScript object is created from such a sequence, its
prototype object is set to the v8::Array prototype object. The
indexed setter, indexed getter, length and toString methods are
implemented directly or in terms of the underlying sequence resource.
Note that currently, sequences of ValueTypes are NOT supported, due to
the fact that operations like:
someObj.someValueTypeSequence[i].x = 5;
would not behave as required.
Task-number: QTBUG-20826
Task-number: QTBUG-21770
Change-Id: I36deb448fb0e87a32084a900e70a2604ff369309
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
2011-10-03 00:52:38 +00:00
|
|
|
case WorkerSequence:
|
|
|
|
{
|
2013-09-12 20:37:41 +00:00
|
|
|
ScopedValue value(scope);
|
Add support for more sequence types
This commit adds support for more sequence types by adding a sequence
wrapper. This class enables conversion between v8::Array and C++
sequences of various types (currently just QList<int>, QList<qreal>,
QList<bool>, QList<QString>, QList<QUrl> and QStringList), but more
types can be added later if required).
When a JavaScript object is created from such a sequence, its
prototype object is set to the v8::Array prototype object. The
indexed setter, indexed getter, length and toString methods are
implemented directly or in terms of the underlying sequence resource.
Note that currently, sequences of ValueTypes are NOT supported, due to
the fact that operations like:
someObj.someValueTypeSequence[i].x = 5;
would not behave as required.
Task-number: QTBUG-20826
Task-number: QTBUG-21770
Change-Id: I36deb448fb0e87a32084a900e70a2604ff369309
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
2011-10-03 00:52:38 +00:00
|
|
|
bool succeeded = false;
|
|
|
|
quint32 length = headersize(header);
|
|
|
|
quint32 seqLength = length - 1;
|
2013-09-12 20:37:41 +00:00
|
|
|
value = deserialize(data, engine);
|
|
|
|
int sequenceType = value->integerValue();
|
2013-09-14 09:25:02 +00:00
|
|
|
Scoped<ArrayObject> array(scope, v4->newArrayObject());
|
2013-05-14 16:58:34 +00:00
|
|
|
array->arrayReserve(seqLength);
|
2013-07-01 03:49:26 +00:00
|
|
|
array->arrayDataLen = seqLength;
|
2013-09-12 20:37:41 +00:00
|
|
|
for (quint32 ii = 0; ii < seqLength; ++ii) {
|
|
|
|
value = deserialize(data, engine);
|
|
|
|
array->arrayData[ii].value = value;
|
|
|
|
}
|
2013-05-14 16:58:34 +00:00
|
|
|
array->setArrayLengthUnchecked(seqLength);
|
2013-09-14 09:25:02 +00:00
|
|
|
QVariant seqVariant = QV4::SequencePrototype::toVariant(array.asValue(), sequenceType, &succeeded);
|
2013-05-21 15:06:36 +00:00
|
|
|
return QV4::SequencePrototype::fromVariant(v4, seqVariant, &succeeded);
|
Add support for more sequence types
This commit adds support for more sequence types by adding a sequence
wrapper. This class enables conversion between v8::Array and C++
sequences of various types (currently just QList<int>, QList<qreal>,
QList<bool>, QList<QString>, QList<QUrl> and QStringList), but more
types can be added later if required).
When a JavaScript object is created from such a sequence, its
prototype object is set to the v8::Array prototype object. The
indexed setter, indexed getter, length and toString methods are
implemented directly or in terms of the underlying sequence resource.
Note that currently, sequences of ValueTypes are NOT supported, due to
the fact that operations like:
someObj.someValueTypeSequence[i].x = 5;
would not behave as required.
Task-number: QTBUG-20826
Task-number: QTBUG-21770
Change-Id: I36deb448fb0e87a32084a900e70a2604ff369309
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
2011-10-03 00:52:38 +00:00
|
|
|
}
|
2011-05-11 07:20:40 +00:00
|
|
|
}
|
|
|
|
Q_ASSERT(!"Unreachable");
|
2013-09-12 20:37:41 +00:00
|
|
|
return QV4::Encode::undefined();
|
2011-05-11 07:20:40 +00:00
|
|
|
}
|
|
|
|
|
2013-05-20 09:13:48 +00:00
|
|
|
QByteArray Serialize::serialize(const QV4::Value &value, QV8Engine *engine)
|
2011-05-11 07:20:40 +00:00
|
|
|
{
|
|
|
|
QByteArray rv;
|
|
|
|
serialize(rv, value, engine);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2013-09-12 20:37:41 +00:00
|
|
|
ReturnedValue Serialize::deserialize(const QByteArray &data, QV8Engine *engine)
|
2011-05-11 07:20:40 +00:00
|
|
|
{
|
|
|
|
const char *stream = data.constData();
|
|
|
|
return deserialize(stream, engine);
|
|
|
|
}
|
|
|
|
|
|
|
|
QT_END_NAMESPACE
|
|
|
|
|