Move more API over to use ValueRef

Change-Id: I372f1f3e3e78d45912a913f437e622e0acfc9646
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
Lars Knoll 2013-09-24 15:25:10 +02:00 committed by The Qt Project
parent 9062476491
commit 74807c0725
20 changed files with 206 additions and 201 deletions

View File

@ -270,12 +270,13 @@ static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx)
if (query.prepare(sql)) {
if (ctx->argumentCount > 1) {
Value values = ctx->arguments[1];
if (ArrayObject *array = values.asArrayObject()) {
ScopedValue values(scope, ctx->arguments[1]);
if (ArrayObject *array = values->asArrayObject()) {
quint32 size = array->arrayLength();
QV4::ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii)
query.bindValue(ii, engine->toVariant(QV4::Value::fromReturnedValue(array->getIndexed(ii)), -1));
} else if (Object *object = values.asObject()) {
query.bindValue(ii, engine->toVariant((v = array->getIndexed(ii)), -1));
} else if (Object *object = values->asObject()) {
ObjectIterator it(object, ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly);
ScopedValue key(scope);
while (1) {
@ -283,7 +284,8 @@ static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx)
key = it.nextPropertyName(&value);
if (key->isNull())
break;
QVariant v = engine->toVariant(value, -1);
QV4::ScopedValue val(scope, value);
QVariant v = engine->toVariant(val, -1);
if (key->isString()) {
query.bindValue(key->stringValue()->toQString(), v);
} else {

View File

@ -375,7 +375,9 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
QJSValuePrivate *vp = QJSValuePrivate::get(value);
QV8Engine *engine = vp->engine ? vp->engine->v8Engine : 0;
if (engine) {
return engine->metaTypeFromJS(QV4::Value::fromReturnedValue(vp->getValue(engine->m_v4Engine)), type, ptr);
QV4::Scope scope(engine->m_v4Engine);
QV4::ScopedValue v(scope, vp->getValue(engine->m_v4Engine));
return engine->metaTypeFromJS(v, type, ptr);
} else {
switch (type) {
case QMetaType::Bool:

View File

@ -1021,11 +1021,11 @@ bool QJSValue::hasOwnProperty(const QString &name) const
*/
QObject *QJSValue::toQObject() const
{
QV4::QObjectWrapper *o = d->value.as<QV4::QObjectWrapper>();
Returned<QV4::QObjectWrapper> *o = d->value.as<QV4::QObjectWrapper>();
if (!o)
return 0;
return o->object();
return o->getPointer()->object();
}
/*!

View File

@ -963,20 +963,20 @@ ReturnedValue JsonObject::fromJsonValue(ExecutionEngine *engine, const QJsonValu
return Encode::undefined();
}
QJsonValue JsonObject::toJsonValue(const QV4::Value &value,
QJsonValue JsonObject::toJsonValue(const ValueRef value,
V4ObjectSet &visitedObjects)
{
if (String *s = value.asString())
if (String *s = value->asString())
return QJsonValue(s->toQString());
else if (value.isNumber())
return QJsonValue(value.toNumber());
else if (value.isBoolean())
return QJsonValue((bool)value.booleanValue());
else if (ArrayObject *a = value.asArrayObject())
else if (value->isNumber())
return QJsonValue(value->toNumber());
else if (value->isBoolean())
return QJsonValue((bool)value->booleanValue());
else if (ArrayObject *a = value->asArrayObject())
return toJsonArray(a, visitedObjects);
else if (Object *o = value.asObject())
else if (Object *o = value->asObject())
return toJsonObject(o, visitedObjects);
else if (value.isNull())
else if (value->isNull())
return QJsonValue(QJsonValue::Null);
else
return QJsonValue(QJsonValue::Undefined);
@ -1020,9 +1020,11 @@ QJsonObject JsonObject::toJsonObject(QV4::Object *o, V4ObjectSet &visitedObjects
if (name->isNull())
break;
QV4::ScopedValue val(scope, v);
QString key = name->toQStringNoThrow();
if (!v.asFunctionObject())
result.insert(key, toJsonValue(v, visitedObjects));
if (!val->asFunctionObject())
result.insert(key, toJsonValue(val, visitedObjects));
}
visitedObjects.remove(o);
@ -1065,7 +1067,9 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
quint32 length = a->arrayLength();
for (quint32 i = 0; i < length; ++i) {
v = a->getIndexed(i);
result.append(toJsonValue(v->asFunctionObject() ? QV4::Value::nullValue() : v, visitedObjects));
if (v->asFunctionObject())
v = Encode::null();
result.append(toJsonValue(v, visitedObjects));
}
visitedObjects.remove(a);

View File

@ -63,7 +63,7 @@ public:
static ReturnedValue fromJsonObject(ExecutionEngine *engine, const QJsonObject &object);
static ReturnedValue fromJsonArray(ExecutionEngine *engine, const QJsonArray &array);
static inline QJsonValue toJsonValue(const QV4::Value &value)
static inline QJsonValue toJsonValue(const QV4::ValueRef value)
{ V4ObjectSet visitedObjects; return toJsonValue(value, visitedObjects); }
static inline QJsonObject toJsonObject(QV4::Object *o)
{ V4ObjectSet visitedObjects; return toJsonObject(o, visitedObjects); }
@ -71,7 +71,7 @@ public:
{ V4ObjectSet visitedObjects; return toJsonArray(a, visitedObjects); }
private:
static QJsonValue toJsonValue(const QV4::Value &value, V4ObjectSet &visitedObjects);
static QJsonValue toJsonValue(const QV4::ValueRef value, V4ObjectSet &visitedObjects);
static QJsonObject toJsonObject(QV4::Object *o, V4ObjectSet &visitedObjects);
static QJsonArray toJsonArray(QV4::ArrayObject *a, V4ObjectSet &visitedObjects);

View File

@ -378,10 +378,10 @@ void MemoryManager::mark()
for (PersistentValuePrivate *weak = m_weakValues; weak; weak = weak->next) {
if (!weak->refcount)
continue;
QObjectWrapper *qobjectWrapper = weak->value.as<QObjectWrapper>();
Returned<QObjectWrapper> *qobjectWrapper = weak->value.as<QObjectWrapper>();
if (!qobjectWrapper)
continue;
QObject *qobject = qobjectWrapper->object();
QObject *qobject = qobjectWrapper->getPointer()->object();
if (!qobject)
continue;
bool keepAlive = QQmlData::keepAliveDuringGarbageCollection(qobject);
@ -396,7 +396,7 @@ void MemoryManager::mark()
}
if (keepAlive)
qobjectWrapper->mark();
qobjectWrapper->getPointer()->mark();
}
}

View File

@ -513,9 +513,9 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
} else {
QVariant v;
if (result->isQList())
v = ctx->engine->v8Engine->toVariant(*value, qMetaTypeId<QList<QObject *> >());
v = ctx->engine->v8Engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
else
v = ctx->engine->v8Engine->toVariant(*value, result->propType);
v = ctx->engine->v8Engine->toVariant(value, result->propType);
QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->engine);
if (!QQmlPropertyPrivate::write(object, *result, v, callingQmlContext)) {
@ -980,7 +980,7 @@ struct CallArgument {
inline void *dataPtr();
inline void initAsType(int type);
inline void fromValue(int type, QV8Engine *, const QV4::Value&);
inline void fromValue(int type, QV8Engine *, const ValueRef);
inline ReturnedValue toValue(QV8Engine *);
private:
@ -1022,21 +1022,8 @@ private:
};
}
namespace {
struct CallArgs
{
CallArgs(int length, const QV4::Value *args) : _length(length), _args(args) {}
int Length() const { return _length; }
QV4::Value operator[](int idx) { return _args[idx]; }
private:
int _length;
const QV4::Value *_args;
};
}
static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType, int argCount,
int *argTypes, QV8Engine *engine, CallArgs &callArgs)
int *argTypes, QV8Engine *engine, QV4::CallData *callArgs)
{
if (argCount > 0) {
@ -1054,7 +1041,7 @@ static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType,
QVarLengthArray<CallArgument, 9> args(argCount + 1);
args[0].initAsType(returnType);
for (int ii = 0; ii < argCount; ++ii)
args[ii + 1].fromValue(argTypes[ii], engine, callArgs[ii]);
args[ii + 1].fromValue(argTypes[ii], engine, callArgs->args[ii]);
QVarLengthArray<void *, 9> argData(args.count());
for (int ii = 0; ii < args.count(); ++ii)
argData[ii] = args[ii].dataPtr();
@ -1093,9 +1080,9 @@ static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType,
The conversion table is copied out of the \l QScript::callQtMethod() function.
*/
static int MatchScore(const QV4::Value &actual, int conversionType)
static int MatchScore(const QV4::ValueRef actual, int conversionType)
{
if (actual.isNumber()) {
if (actual->isNumber()) {
switch (conversionType) {
case QMetaType::Double:
return 0;
@ -1122,7 +1109,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
} else if (actual.isString()) {
} else if (actual->isString()) {
switch (conversionType) {
case QMetaType::QString:
return 0;
@ -1131,7 +1118,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
} else if (actual.isBoolean()) {
} else if (actual->isBoolean()) {
switch (conversionType) {
case QMetaType::Bool:
return 0;
@ -1140,7 +1127,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
} else if (actual.asDateObject()) {
} else if (actual->asDateObject()) {
switch (conversionType) {
case QMetaType::QDateTime:
return 0;
@ -1151,14 +1138,14 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
} else if (actual.as<QV4::RegExpObject>()) {
} else if (actual->as<QV4::RegExpObject>()) {
switch (conversionType) {
case QMetaType::QRegExp:
return 0;
default:
return 10;
}
} else if (actual.asArrayObject()) {
} else if (actual->asArrayObject()) {
switch (conversionType) {
case QMetaType::QJsonArray:
return 3;
@ -1173,7 +1160,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
default:
return 10;
}
} else if (actual.isNull()) {
} else if (actual->isNull()) {
switch (conversionType) {
case QMetaType::VoidStar:
case QMetaType::QObjectStar:
@ -1187,7 +1174,7 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
return 10;
}
}
} else if (QV4::Object *obj = actual.asObject()) {
} else if (QV4::Object *obj = actual->asObject()) {
QV8Engine *engine = obj->engine()->v8Engine;
if (QV4::VariantObject *v = obj->as<QV4::VariantObject>()) {
@ -1279,7 +1266,7 @@ static const QQmlPropertyData * RelatedMethod(QObject *object,
}
static QV4::ReturnedValue CallPrecise(QObject *object, const QQmlPropertyData &data,
QV8Engine *engine, CallArgs &callArgs)
QV8Engine *engine, QV4::CallData *callArgs)
{
QByteArray unknownTypeError;
@ -1305,7 +1292,7 @@ static QV4::ReturnedValue CallPrecise(QObject *object, const QQmlPropertyData &d
QV8Engine::getV4(engine)->current->throwError(error);
}
if (args[0] > callArgs.Length()) {
if (args[0] > callArgs->argc) {
QString error = QLatin1String("Insufficient arguments");
QV8Engine::getV4(engine)->current->throwError(error);
}
@ -1333,9 +1320,9 @@ Resolve the overloaded method to call. The algorithm works conceptually like th
score is constructed by adding the matchScore() result for each of the parameters.
*/
static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData &data,
QV8Engine *engine, CallArgs &callArgs)
QV8Engine *engine, QV4::CallData *callArgs)
{
int argumentCount = callArgs.Length();
int argumentCount = callArgs->argc;
const QQmlPropertyData *best = 0;
int bestParameterScore = INT_MAX;
@ -1354,6 +1341,9 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData
QQmlPropertyData dummy;
const QQmlPropertyData *attempt = &data;
QV4::Scope scope(QV8Engine::getV4(engine));
QV4::ScopedValue v(scope);
do {
QVarLengthArray<int, 9> dummy;
int methodArgumentCount = 0;
@ -1377,7 +1367,7 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData
int methodMatchScore = 0;
for (int ii = 0; ii < methodArgumentCount; ++ii)
methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii]);
methodMatchScore += MatchScore((v = callArgs->args[ii]), methodArgTypes[ii]);
if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
best = attempt;
@ -1491,40 +1481,38 @@ void CallArgument::initAsType(int callType)
}
}
void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::Value &value)
void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRef value)
{
if (type != 0) { cleanup(); type = 0; }
if (callType == qMetaTypeId<QJSValue>()) {
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
QV4::ScopedValue v(scope, value);
qjsValuePtr = new (&allocData) QJSValue(new QJSValuePrivate(v4, v));
qjsValuePtr = new (&allocData) QJSValue(new QJSValuePrivate(v4, value));
type = qMetaTypeId<QJSValue>();
} else if (callType == QMetaType::Int) {
intValue = quint32(value.toInt32());
intValue = quint32(value->toInt32());
type = callType;
} else if (callType == QMetaType::UInt) {
intValue = quint32(value.toUInt32());
intValue = quint32(value->toUInt32());
type = callType;
} else if (callType == QMetaType::Bool) {
boolValue = value.toBoolean();
boolValue = value->toBoolean();
type = callType;
} else if (callType == QMetaType::Double) {
doubleValue = double(value.toNumber());
doubleValue = double(value->toNumber());
type = callType;
} else if (callType == QMetaType::Float) {
floatValue = float(value.toNumber());
floatValue = float(value->toNumber());
type = callType;
} else if (callType == QMetaType::QString) {
if (value.isNull() || value.isUndefined())
if (value->isNull() || value->isUndefined())
qstringPtr = new (&allocData) QString();
else
qstringPtr = new (&allocData) QString(value.toQStringNoThrow());
qstringPtr = new (&allocData) QString(value->toQStringNoThrow());
type = callType;
} else if (callType == QMetaType::QObjectStar) {
qobjectPtr = 0;
if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
if (QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>())
qobjectPtr = qobjectWrapper->object();
type = callType;
} else if (callType == qMetaTypeId<QVariant>()) {
@ -1532,7 +1520,7 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::Value &
type = callType;
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
qlistPtr = new (&allocData) QList<QObject *>();
if (QV4::ArrayObject *array = value.asArrayObject()) {
if (QV4::ArrayObject *array = value->asArrayObject()) {
QV4::Scope scope(array->engine());
Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
@ -1546,19 +1534,19 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::Value &
}
} else {
QObject *o = 0;
if (QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>())
if (QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>())
o = qobjectWrapper->object();
qlistPtr->append(o);
}
type = callType;
} else if (callType == qMetaTypeId<QQmlV4Handle>()) {
handlePtr = new (&allocData) QQmlV4Handle(value.asReturnedValue());
handlePtr = new (&allocData) QQmlV4Handle(value->asReturnedValue());
type = callType;
} else if (callType == QMetaType::QJsonArray) {
jsonArrayPtr = new (&allocData) QJsonArray(QV4::JsonObject::toJsonArray(value.asArrayObject()));
jsonArrayPtr = new (&allocData) QJsonArray(QV4::JsonObject::toJsonArray(value->asArrayObject()));
type = callType;
} else if (callType == QMetaType::QJsonObject) {
jsonObjectPtr = new (&allocData) QJsonObject(QV4::JsonObject::toJsonObject(value.asObject()));
jsonObjectPtr = new (&allocData) QJsonObject(QV4::JsonObject::toJsonObject(value->asObject()));
type = callType;
} else if (callType == QMetaType::QJsonValue) {
jsonValuePtr = new (&allocData) QJsonValue(QV4::JsonObject::toJsonValue(value));
@ -1771,11 +1759,10 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
return rv.asReturnedValue();
}
CallArgs callArgs(callData->argc, callData->args);
if (!method.isOverload()) {
return CallPrecise(object, method, v8Engine, callArgs);
return CallPrecise(object, method, v8Engine, callData);
} else {
return CallOverloaded(object, method, v8Engine, callArgs);
return CallOverloaded(object, method, v8Engine, callData);
}
}

View File

@ -624,15 +624,18 @@ QVariant SequencePrototype::toVariant(QV4::Object *object)
return QQml##ElementTypeName##List::toVariant(a); \
} else
QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, bool *succeeded)
QVariant SequencePrototype::toVariant(const QV4::ValueRef array, int typeHint, bool *succeeded)
{
*succeeded = true;
QV4::ArrayObject *a = array.asArrayObject();
if (!a) {
if (!array->asArrayObject()) {
*succeeded = false;
return QVariant();
}
QV4::Scope scope(array->engine());
// ### GC
QV4::ArrayObject *a = array->asArrayObject();
FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ *succeeded = false; return QVariant(); }
}

View File

@ -81,7 +81,7 @@ struct SequencePrototype : public QV4::Object
static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
static int metaTypeForSequence(QV4::Object *object);
static QVariant toVariant(QV4::Object *object);
static QVariant toVariant(const QV4::Value &array, int typeHint, bool *succeeded);
static QVariant toVariant(const ValueRef array, int typeHint, bool *succeeded);
};
}

View File

@ -391,7 +391,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
array->arrayDataLen = ii + 1;
}
array->setArrayLengthUnchecked(seqLength);
QVariant seqVariant = QV4::SequencePrototype::toVariant(array.asValue(), sequenceType, &succeeded);
QVariant seqVariant = QV4::SequencePrototype::toVariant(array, sequenceType, &succeeded);
return QV4::SequencePrototype::fromVariant(v4, seqVariant, &succeeded);
}
}

View File

@ -348,7 +348,7 @@ struct Q_QML_PRIVATE_EXPORT PersistentValuePrivate
{
PersistentValuePrivate(ReturnedValue v, ExecutionEngine *engine = 0, bool weak = false);
virtual ~PersistentValuePrivate();
Value value;
SafeValue value;
uint refcount;
bool weak;
QV4::ExecutionEngine *engine;

View File

@ -69,24 +69,25 @@ VariantObject::VariantObject(ExecutionEngine *engine, const QVariant &value)
internalClass->engine->scarceResources.insert(this);
}
QVariant VariantObject::toVariant(const QV4::Value &v)
QVariant VariantObject::toVariant(const QV4::ValueRef v)
{
if (Object *o = v.asObject())
return o->engine()->v8Engine->variantFromJS(v);
if (v->asObject())
return v->engine()->v8Engine->variantFromJS(v);
if (v.isString())
return QVariant(v.stringValue()->toQString());
if (v.isBoolean())
return QVariant(v.booleanValue());
if (v.isNumber()) {
QV4::Value val = v;
if (v->isString())
return QVariant(v->stringValue()->toQString());
if (v->isBoolean())
return QVariant(v->booleanValue());
if (v->isNumber()) {
QV4::SafeValue val;
val = v;
if (val.isInt32())
return QVariant(val.integerValue());
return QVariant(v.asDouble());
return QVariant(v->asDouble());
}
if (v.isNull())
if (v->isNull())
return QVariant(QMetaType::VoidStar, 0);
Q_ASSERT(v.isUndefined());
Q_ASSERT(v->isUndefined());
return QVariant();
}

View File

@ -71,7 +71,7 @@ public:
VariantObject(InternalClass *ic);
VariantObject(ExecutionEngine *engine, const QVariant &value);
static QVariant toVariant(const QV4::Value &v);
static QVariant toVariant(const ValueRef v);
void addVmePropertyReference();
void removeVmePropertyReference();

View File

@ -1514,13 +1514,13 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
if (isUndefined) {
} else if (core.isQList()) {
value = v8engine->toVariant(*result, qMetaTypeId<QList<QObject *> >());
value = v8engine->toVariant(result, qMetaTypeId<QList<QObject *> >());
} else if (result->isNull() && core.isQObject()) {
value = QVariant::fromValue((QObject *)0);
} else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
value = resolvedUrlSequence(v8engine->toVariant(*result, qMetaTypeId<QList<QUrl> >()), context);
value = resolvedUrlSequence(v8engine->toVariant(result, qMetaTypeId<QList<QUrl> >()), context);
} else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
value = v8engine->toVariant(*result, type);
value = v8engine->toVariant(result, type);
}
if (expression->hasError()) {

View File

@ -385,7 +385,7 @@ void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef v
oldBinding->destroy();
if (!f) {
QVariant v = r->v8->toVariant(*value, -1);
QVariant v = r->v8->toVariant(value, -1);
if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
v = v.toInt();
@ -409,7 +409,7 @@ void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef v
if (index == -1)
return;
QVariant v = r->v8->toVariant(*value, -1);
QVariant v = r->v8->toVariant(value, -1);
r->type->setValue(copy->value);
QMetaProperty p = r->type->metaObject()->property(index);

View File

@ -1010,8 +1010,8 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
if (ensureVarPropertiesAllocated()) {
QV4::Scope scope(QQmlEnginePrivate::get(ctxt->engine)->v4engine());
QV4::ScopedObject o(scope, varProperties.value());
return QQmlEnginePrivate::get(ctxt->engine)->v8engine()->toVariant(
QV4::Value::fromReturnedValue(o->getIndexed(id - firstVarPropertyIndex)), -1);
QV4::ScopedValue val(scope, o->getIndexed(id - firstVarPropertyIndex));
return QQmlEnginePrivate::get(ctxt->engine)->v8engine()->toVariant(val, -1);
}
return QVariant();
} else {

View File

@ -117,27 +117,27 @@ QV8Engine::~QV8Engine()
delete m_v4Engine;
}
QVariant QV8Engine::toVariant(const QV4::Value &value, int typeHint)
QVariant QV8Engine::toVariant(const QV4::ValueRef value, int typeHint)
{
Q_ASSERT (!value.isEmpty());
Q_ASSERT (!value->isEmpty());
QV4::Scope scope(m_v4Engine);
QV4::ScopedValue v(scope, value);
// QV4::ScopedValue v(scope, value);
if (QV4::VariantObject *v = value.as<QV4::VariantObject>())
if (QV4::VariantObject *v = value->as<QV4::VariantObject>())
return v->data;
if (typeHint == QVariant::Bool)
return QVariant(value.toBoolean());
return QVariant(value->toBoolean());
if (typeHint == QMetaType::QJsonValue)
return QVariant::fromValue(QV4::JsonObject::toJsonValue(value));
if (typeHint == qMetaTypeId<QJSValue>())
return QVariant::fromValue(QJSValue(new QJSValuePrivate(m_v4Engine, v)));
return QVariant::fromValue(QJSValue(new QJSValuePrivate(m_v4Engine, value)));
if (QV4::Object *object = value.asObject()) {
if (QV4::Object *object = value->asObject()) {
if (typeHint == QMetaType::QJsonObject
&& !value.asArrayObject() && !value.asFunctionObject()) {
&& !value->asArrayObject() && !value->asFunctionObject()) {
return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
} else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
return qVariantFromValue<QObject *>(wrapper->object());
@ -153,7 +153,7 @@ QVariant QV8Engine::toVariant(const QV4::Value &value, int typeHint)
return QV4::SequencePrototype::toVariant(object);
}
if (QV4::ArrayObject *a = value.asArrayObject()) {
if (QV4::ArrayObject *a = value->asArrayObject()) {
QV4::Scope scope(a->engine());
if (typeHint == qMetaTypeId<QList<QObject *> >()) {
QList<QObject *> list;
@ -373,27 +373,27 @@ QQmlContextData *QV8Engine::callingContext()
// Date -> QVariant(QDateTime)
// RegExp -> QVariant(QRegExp)
// [Any other object] -> QVariantMap(...)
QVariant QV8Engine::toBasicVariant(const QV4::Value &value)
QVariant QV8Engine::toBasicVariant(const QV4::ValueRef value)
{
if (value.isNull() || value.isUndefined())
if (value->isNullOrUndefined())
return QVariant();
if (value.isBoolean())
return value.booleanValue();
if (value.isInteger())
return value.integerValue();
if (value.isNumber())
return value.asDouble();
if (value.isString())
return value.stringValue()->toQString();
if (QV4::DateObject *d = value.asDateObject())
if (value->isBoolean())
return value->booleanValue();
if (value->isInteger())
return value->integerValue();
if (value->isNumber())
return value->asDouble();
if (value->isString())
return value->stringValue()->toQString();
if (QV4::DateObject *d = value->asDateObject())
return d->toQDateTime();
// NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
Q_ASSERT(value.isObject());
Q_ASSERT(value->isObject());
if (QV4::RegExpObject *re = value.as<QV4::RegExpObject>())
if (QV4::RegExpObject *re = value->as<QV4::RegExpObject>())
return re->toQRegExp();
if (QV4::ArrayObject *a = value.asArrayObject()) {
if (QV4::ArrayObject *a = value->asArrayObject()) {
QV4::Scope scope(a->engine());
QV4::ScopedValue v(scope);
QVariantList rv;
@ -405,8 +405,8 @@ QVariant QV8Engine::toBasicVariant(const QV4::Value &value)
}
return rv;
}
if (!value.asFunctionObject())
return variantMapFromJS(value.asObject());
if (!value->asFunctionObject())
return variantMapFromJS(value->asObject());
return QVariant();
}
@ -620,7 +620,8 @@ QVariantMap QV8Engine::variantMapFromJS(QV4::Object *o,
break;
QString key = name->toQStringNoThrow();
result.insert(key, variantFromJS(v, visitedObjects));
QV4::ScopedValue val(scope, v);
result.insert(key, variantFromJS(val, visitedObjects));
}
visitedObjects.remove(o);
@ -713,92 +714,93 @@ QV4::ReturnedValue QV8Engine::metaTypeToJS(int type, const void *data)
// Converts a JS value to a meta-type.
// data must point to a place that can store a value of the given type.
// Returns true if conversion succeeded, false otherwise.
bool QV8Engine::metaTypeFromJS(const QV4::Value &value, int type, void *data) {
bool QV8Engine::metaTypeFromJS(const QV4::ValueRef value, int type, void *data)
{
QV4::Scope scope(QV8Engine::getV4(this));
// check if it's one of the types we know
switch (QMetaType::Type(type)) {
case QMetaType::Bool:
*reinterpret_cast<bool*>(data) = value.toBoolean();
*reinterpret_cast<bool*>(data) = value->toBoolean();
return true;
case QMetaType::Int:
*reinterpret_cast<int*>(data) = value.toInt32();
*reinterpret_cast<int*>(data) = value->toInt32();
return true;
case QMetaType::UInt:
*reinterpret_cast<uint*>(data) = value.toUInt32();
*reinterpret_cast<uint*>(data) = value->toUInt32();
return true;
case QMetaType::LongLong:
*reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger());
*reinterpret_cast<qlonglong*>(data) = qlonglong(value->toInteger());
return true;
case QMetaType::ULongLong:
*reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger());
*reinterpret_cast<qulonglong*>(data) = qulonglong(value->toInteger());
return true;
case QMetaType::Double:
*reinterpret_cast<double*>(data) = value.toNumber();
*reinterpret_cast<double*>(data) = value->toNumber();
return true;
case QMetaType::QString:
if (value.isUndefined() || value.isNull())
if (value->isUndefined() || value->isNull())
*reinterpret_cast<QString*>(data) = QString();
else
*reinterpret_cast<QString*>(data) = value.toString(m_v4Engine->current)->toQString();
*reinterpret_cast<QString*>(data) = value->toString(m_v4Engine->current)->toQString();
return true;
case QMetaType::Float:
*reinterpret_cast<float*>(data) = value.toNumber();
*reinterpret_cast<float*>(data) = value->toNumber();
return true;
case QMetaType::Short:
*reinterpret_cast<short*>(data) = short(value.toInt32());
*reinterpret_cast<short*>(data) = short(value->toInt32());
return true;
case QMetaType::UShort:
*reinterpret_cast<unsigned short*>(data) = value.toUInt16();
*reinterpret_cast<unsigned short*>(data) = value->toUInt16();
return true;
case QMetaType::Char:
*reinterpret_cast<char*>(data) = char(value.toInt32());
*reinterpret_cast<char*>(data) = char(value->toInt32());
return true;
case QMetaType::UChar:
*reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32());
*reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->toInt32());
return true;
case QMetaType::QChar:
if (value.isString()) {
QString str = value.stringValue()->toQString();
if (value->isString()) {
QString str = value->stringValue()->toQString();
*reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
} else {
*reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16()));
*reinterpret_cast<QChar*>(data) = QChar(ushort(value->toUInt16()));
}
return true;
case QMetaType::QDateTime:
if (QV4::DateObject *d = value.asDateObject()) {
if (QV4::DateObject *d = value->asDateObject()) {
*reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
return true;
} break;
case QMetaType::QDate:
if (QV4::DateObject *d = value.asDateObject()) {
if (QV4::DateObject *d = value->asDateObject()) {
*reinterpret_cast<QDate *>(data) = d->toQDateTime().date();
return true;
} break;
case QMetaType::QRegExp:
if (QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
if (QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
*reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
return true;
} break;
case QMetaType::QObjectStar: {
QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>();
if (qobjectWrapper || value.isNull()) {
QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
if (qobjectWrapper || value->isNull()) {
*reinterpret_cast<QObject* *>(data) = qtObjectFromJS(value);
return true;
} break;
}
case QMetaType::QStringList:
if (QV4::ArrayObject *a = value.asArrayObject()) {
if (QV4::ArrayObject *a = value->asArrayObject()) {
*reinterpret_cast<QStringList *>(data) = a->toQStringList();
return true;
} break;
case QMetaType::QVariantList:
if (QV4::ArrayObject *a = value.asArrayObject()) {
if (QV4::ArrayObject *a = value->asArrayObject()) {
*reinterpret_cast<QVariantList *>(data) = variantListFromJS(a);
return true;
} break;
case QMetaType::QVariantMap:
if (QV4::Object *o = value.asObject()) {
if (QV4::Object *o = value->asObject()) {
*reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(o);
return true;
} break;
@ -809,10 +811,10 @@ bool QV8Engine::metaTypeFromJS(const QV4::Value &value, int type, void *data) {
*reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
return true;
case QMetaType::QJsonObject:
*reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value.asObject());
*reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value->asObject());
return true;
case QMetaType::QJsonArray:
*reinterpret_cast<QJsonArray *>(data) = QV4::JsonObject::toJsonArray(value.asArrayObject());
*reinterpret_cast<QJsonArray *>(data) = QV4::JsonObject::toJsonArray(value->asArrayObject());
return true;
default:
;
@ -842,14 +844,14 @@ bool QV8Engine::metaTypeFromJS(const QV4::Value &value, int type, void *data) {
QByteArray name = QMetaType::typeName(type);
if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(data)))
return true;
if (value.as<QV4::VariantObject>() && name.endsWith('*')) {
if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
QVariant &var = value.as<QV4::VariantObject>()->data;
QVariant &var = value->as<QV4::VariantObject>()->data;
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
return true;
} else if (QV4::Object *o = value.asObject()) {
} else if (QV4::Object *o = value->asObject()) {
// Look in the prototype chain.
QV4::Object *proto = o->prototype();
while (proto) {
@ -860,7 +862,8 @@ bool QV8Engine::metaTypeFromJS(const QV4::Value &value, int type, void *data) {
}
else if (proto->as<QV4::QObjectWrapper>()) {
QByteArray className = name.left(name.size()-1);
if (QObject *qobject = qtObjectFromJS(QV4::Value::fromObject(proto)))
QV4::ScopedObject p(scope, proto);
if (QObject *qobject = qtObjectFromJS(p))
canCast = qobject->qt_metacast(className) != 0;
}
if (canCast) {
@ -874,11 +877,11 @@ bool QV8Engine::metaTypeFromJS(const QV4::Value &value, int type, void *data) {
proto = proto->prototype();
}
}
} else if (value.isNull() && name.endsWith('*')) {
} else if (value->isNull() && name.endsWith('*')) {
*reinterpret_cast<void* *>(data) = 0;
return true;
} else if (type == qMetaTypeId<QJSValue>()) {
*reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(m_v4Engine, QV4::ScopedValue(scope, value)));
*reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(m_v4Engine, value));
return true;
}
@ -901,40 +904,40 @@ QV4::ReturnedValue QV8Engine::variantToJS(const QVariant &value)
// Date -> QVariant(QDateTime)
// RegExp -> QVariant(QRegExp)
// [Any other object] -> QVariantMap(...)
QVariant QV8Engine::variantFromJS(const QV4::Value &value,
QVariant QV8Engine::variantFromJS(const QV4::ValueRef value,
V8ObjectSet &visitedObjects)
{
Q_ASSERT(!value.isEmpty());
if (value.isUndefined())
Q_ASSERT(!value->isEmpty());
if (value->isUndefined())
return QVariant();
if (value.isNull())
if (value->isNull())
return QVariant(QMetaType::VoidStar, 0);
if (value.isBoolean())
return value.booleanValue();
if (value.isInteger())
return value.integerValue();
if (value.isNumber())
return value.asDouble();
if (value.isString())
return value.stringValue()->toQString();
Q_ASSERT(value.isObject());
if (QV4::ArrayObject *a = value.asArrayObject())
if (value->isBoolean())
return value->booleanValue();
if (value->isInteger())
return value->integerValue();
if (value->isNumber())
return value->asDouble();
if (value->isString())
return value->stringValue()->toQString();
Q_ASSERT(value->isObject());
if (QV4::ArrayObject *a = value->asArrayObject())
return variantListFromJS(a, visitedObjects);
if (QV4::DateObject *d = value.asDateObject())
if (QV4::DateObject *d = value->asDateObject())
return d->toQDateTime();
if (QV4::RegExpObject *re = value.as<QV4::RegExpObject>())
if (QV4::RegExpObject *re = value->as<QV4::RegExpObject>())
return re->toQRegExp();
if (QV4::VariantObject *v = value.as<QV4::VariantObject>())
if (QV4::VariantObject *v = value->as<QV4::VariantObject>())
return v->data;
if (value.as<QV4::QObjectWrapper>())
if (value->as<QV4::QObjectWrapper>())
return qVariantFromValue(qtObjectFromJS(value));
if (QV4::QmlValueTypeWrapper *v = value.as<QV4::QmlValueTypeWrapper>())
if (QV4::QmlValueTypeWrapper *v = value->as<QV4::QmlValueTypeWrapper>())
return v->toVariant();
return variantMapFromJS(value.asObject(), visitedObjects);
return variantMapFromJS(value->asObject(), visitedObjects);
}
bool QV8Engine::convertToNativeQObject(const QV4::Value &value, const QByteArray &targetType, void **result)
bool QV8Engine::convertToNativeQObject(const QV4::ValueRef value, const QByteArray &targetType, void **result)
{
if (!targetType.endsWith('*'))
return false;
@ -949,19 +952,21 @@ bool QV8Engine::convertToNativeQObject(const QV4::Value &value, const QByteArray
return false;
}
QObject *QV8Engine::qtObjectFromJS(const QV4::Value &value)
QObject *QV8Engine::qtObjectFromJS(const QV4::ValueRef value)
{
if (!value.isObject())
if (!value->isObject())
return 0;
QV4::Scope scope(m_v4Engine);
QV4::Scoped<QV4::VariantObject> v(scope, value);
if (QV4::VariantObject *v = value.as<QV4::VariantObject>()) {
if (v) {
QVariant variant = v->data;
int type = variant.userType();
if (type == QMetaType::QObjectStar)
return *reinterpret_cast<QObject* const *>(variant.constData());
}
QV4::QObjectWrapper *wrapper = value.as<QV4::QObjectWrapper>();
QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, value);
if (!wrapper)
return 0;
return wrapper->object();

View File

@ -205,7 +205,7 @@ public:
void freezeObject(const QV4::ValueRef value);
QVariant toVariant(const QV4::Value &value, int typeHint);
QVariant toVariant(const QV4::ValueRef value, int typeHint);
QV4::ReturnedValue fromVariant(const QVariant &);
// Return a JS string for the given QString \a string
@ -236,13 +236,13 @@ public:
{ V8ObjectSet visitedObjects; return variantMapFromJS(object, visitedObjects); }
QV4::ReturnedValue variantToJS(const QVariant &value);
inline QVariant variantFromJS(const QV4::Value &value)
inline QVariant variantFromJS(const QV4::ValueRef value)
{ V8ObjectSet visitedObjects; return variantFromJS(value, visitedObjects); }
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
bool metaTypeFromJS(const QV4::Value &value, int type, void *data);
bool metaTypeFromJS(const QV4::ValueRef value, int type, void *data);
bool convertToNativeQObject(const QV4::Value &value,
bool convertToNativeQObject(const QV4::ValueRef value,
const QByteArray &targetType,
void **result);
@ -253,7 +253,7 @@ public:
// used for console.count()
int consoleCountHelper(const QString &file, quint16 line, quint16 column);
QObject *qtObjectFromJS(const QV4::Value &value);
QObject *qtObjectFromJS(const QV4::ValueRef value);
protected:
QJSEngine* q;
@ -275,14 +275,14 @@ protected:
QHash<QString, quint32> m_consoleCount;
QVariant toBasicVariant(const QV4::Value &);
QVariant toBasicVariant(const QV4::ValueRef);
void initializeGlobal();
private:
QVariantList variantListFromJS(QV4::ArrayObject *array, V8ObjectSet &visitedObjects);
QVariantMap variantMapFromJS(QV4::Object *object, V8ObjectSet &visitedObjects);
QVariant variantFromJS(const QV4::Value &value, V8ObjectSet &visitedObjects);
QVariant variantFromJS(const QV4::ValueRef value, V8ObjectSet &visitedObjects);
Q_DISABLE_COPY(QV8Engine)
};

View File

@ -1561,7 +1561,8 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const
propertyName = it.nextPropertyNameAsString(&value);
if (propertyName->isNull())
break;
cacheItem->setValue(propertyName->toQStringNoThrow(), m_cacheMetaType->v8Engine->toVariant(value, QVariant::Invalid));
QV4::ScopedValue v(scope, value);
cacheItem->setValue(propertyName->toQStringNoThrow(), m_cacheMetaType->v8Engine->toVariant(v, QVariant::Invalid));
}
cacheItem->groups = groups | Compositor::UnresolvedFlag | Compositor::CacheFlag;

View File

@ -2287,7 +2287,7 @@ static inline bool evaluate_error(QV8Engine *engine, const QV4::Value &o, const
return false;
}
static inline bool evaluate_value(QV8Engine *engine, const QV4::Value &o,
static inline bool evaluate_value(QV8Engine *engine, const QV4::ValueRef o,
const char *source, const QV4::Value &result)
{
QString functionSource = QLatin1String("(function(object) { return ") +
@ -2424,8 +2424,8 @@ void tst_qqmlecmascript::callQtInvokables()
o->reset();
{
QV4::Value ret = EVALUATE("object.method_NoArgs_QPointF()");
QVERIFY(!ret.isUndefined());
QV4::ScopedValue ret(scope, EVALUATE("object.method_NoArgs_QPointF()"));
QVERIFY(!ret->isUndefined());
QCOMPARE(engine->toVariant(ret, -1), QVariant(QPointF(123, 4.5)));
QCOMPARE(o->error(), false);
QCOMPARE(o->invoked(), 3);
@ -2434,8 +2434,8 @@ void tst_qqmlecmascript::callQtInvokables()
o->reset();
{
QV4::Value ret = EVALUATE("object.method_NoArgs_QObject()");
QV4::QObjectWrapper *qobjectWrapper = ret.as<QV4::QObjectWrapper>();
QV4::ScopedValue ret(scope, EVALUATE("object.method_NoArgs_QObject()"));
QV4::QObjectWrapper *qobjectWrapper = ret->as<QV4::QObjectWrapper>();
QVERIFY(qobjectWrapper);
QCOMPARE(qobjectWrapper->object(), (QObject *)o);
QCOMPARE(o->error(), false);
@ -2460,7 +2460,7 @@ void tst_qqmlecmascript::callQtInvokables()
}
o->reset();
QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", engine->toString("QML rocks")));
QVERIFY(EVALUATE_VALUE("object.method_NoArgs_QVariant()", QV4::Value::fromReturnedValue(engine->toString("QML rocks"))));
QCOMPARE(o->error(), false);
QCOMPARE(o->invoked(), 7);
QCOMPARE(o->actuals().count(), 0);