aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@theqtcompany.com>2015-01-14 16:22:33 +0100
committerSimon Hausmann <simon.hausmann@digia.com>2015-01-21 18:22:52 +0100
commit8209f35b7961b7ea6867d7ebfb5288dcf40ecd71 (patch)
treef9e8b5083788574b75d7dba7f4ca1c60eded86fe
parentd8131513b07d3f0a6d749c9961b294fc955fed6d (diff)
Rework QJSValue internals
Use a flagged pointer to either store a pointer to a QV4::Value (from the persistent storage) or a pointer to a QVariant in QJSValue::d. Like this we don't need to malloc to create a QJSValue for most use cases. Significantly reduces the memory consumption of QJSValue and speeds it up a lot. Change-Id: I10902cc4b6cc3f43d3f816875dc6c4bbb6b4490f Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/imports/statemachine/signaltransition.cpp2
-rw-r--r--src/qml/jsapi/qjsengine.cpp34
-rw-r--r--src/qml/jsapi/qjsvalue.cpp413
-rw-r--r--src/qml/jsapi/qjsvalue.h3
-rw-r--r--src/qml/jsapi/qjsvalue_p.h133
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp16
-rw-r--r--src/qml/jsruntime/qv4engine.cpp5
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp4
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp4
-rw-r--r--src/qml/qml/v8/qv8engine.cpp12
11 files changed, 354 insertions, 274 deletions
diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp
index 41286d84c8..1b18444358 100644
--- a/src/imports/statemachine/signaltransition.cpp
+++ b/src/imports/statemachine/signaltransition.cpp
@@ -95,7 +95,7 @@ void SignalTransition::setSignal(const QJSValue &signal)
QV4::ExecutionEngine *jsEngine = QV8Engine::getV4(QQmlEngine::contextForObject(this)->engine());
QV4::Scope scope(jsEngine);
- QV4::Scoped<QV4::QObjectMethod> qobjectSignal(scope, QJSValuePrivate::get(m_signal)->getValue(jsEngine));
+ QV4::Scoped<QV4::QObjectMethod> qobjectSignal(scope, QJSValuePrivate::convertedToValue(jsEngine, m_signal));
Q_ASSERT(qobjectSignal);
QObject *sender = qobjectSignal->object();
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index e82849746f..413e0eedaf 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -250,12 +250,18 @@ void QJSEngine::collectGarbage()
*/
void QJSEngine::installTranslatorFunctions(const QJSValue &object)
{
- QV4::ExecutionEngine *v4 = d->m_v4Engine;
- QV4::Scope scope(v4);
- QJSValuePrivate *vp = QJSValuePrivate::get(object);
- QV4::ScopedObject obj(scope, vp->getValue(v4));
+ QV4::ExecutionEngine *otherEngine = QJSValuePrivate::engine(&object);
+ if (otherEngine && otherEngine != d->m_v4Engine) {
+ qWarning("QJSEngine: Trying to install a translator function from a different engine");
+ return;
+ }
+ QV4::Scope scope(d->m_v4Engine);
+ QV4::ScopedObject obj(scope);
+ QV4::Value *val = QJSValuePrivate::getValue(&object);
+ if (val)
+ obj = val;
if (!obj)
- obj = v4->globalObject();
+ obj = scope.engine->globalObject();
#ifndef QT_NO_TRANSLATION
obj->defineDefaultProperty(QStringLiteral("qsTranslate"), QV4::GlobalExtensions::method_qsTranslate);
obj->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), QV4::GlobalExtensions::method_qsTranslateNoOp);
@@ -265,7 +271,7 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object)
obj->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp);
// string prototype extension
- v4->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"),
+ scope.engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"),
QV4::GlobalExtensions::method_string_arg);
#endif
}
@@ -420,21 +426,21 @@ QJSValue QJSEngine::create(int type, const void *ptr)
*/
bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
{
- QJSValuePrivate *vp = QJSValuePrivate::get(value);
- QV4::ExecutionEngine *v4 = vp->engine();
+ QV4::ExecutionEngine *v4 = QJSValuePrivate::engine(&value);
QV4::Value scratch;
- QV4::Value *val = vp->valueForData(&scratch);
+ QV4::Value *val = QJSValuePrivate::valueForData(&value, &scratch);
if (v4) {
QV4::Scope scope(v4);
QV4::ScopedValue v(scope, *val);
return scope.engine->metaTypeFromJS(v, type, ptr);
}
- Q_ASSERT(vp->persistent.isEmpty());
-
if (!val) {
- if (vp->unboundData.userType() == QMetaType::QString) {
- QString string = vp->unboundData.toString();
+ QVariant *variant = QJSValuePrivate::getVariant(&value);
+ Q_ASSERT(variant);
+
+ if (variant->userType() == QMetaType::QString) {
+ QString string = variant->toString();
// have a string based value without engine. Do conversion manually
if (type == QMetaType::Bool) {
*reinterpret_cast<bool*>(ptr) = string.length() != 0;
@@ -483,7 +489,7 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
return false;
}
} else {
- return QMetaType::convert(&vp->unboundData.data_ptr(), vp->unboundData.userType(), ptr, type);
+ return QMetaType::convert(&variant->data_ptr(), variant->userType(), ptr, type);
}
}
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 479a2d0901..5310b56af1 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -48,53 +48,6 @@
#include <private/qv4mm_p.h>
#include <private/qv4scopedvalue_p.h>
-QV4::ReturnedValue QJSValuePrivate::getValue(QV4::ExecutionEngine *e)
-{
- QV4::ExecutionEngine *engine = persistent.engine();
- if (!engine) {
- persistent = QV4::PersistentValue(e, e->fromVariant(unboundData));
- unboundData.clear();
- engine = e;
- }
-
- if (engine != e) {
- qWarning("JSValue can't be reassigned to another engine.");
- return QV4::Encode::undefined();
- }
-
- return persistent.value();
-}
-
-QV4::Value QJSValuePrivate::primitiveValueForUnboundData() const
-{
- QV4::Value v = QV4::Primitive::emptyValue();
- switch ((int)unboundData.type()) {
- case QMetaType::UnknownType:
- case QMetaType::Void:
- v = QV4::Encode::undefined();
- break;
- case QMetaType::VoidStar:
- v = QV4::Encode::null();
- break;
- case QMetaType::Bool:
- v = QV4::Encode(unboundData.toBool());
- break;
- case QMetaType::Double:
- v = QV4::Encode(unboundData.toDouble());
- break;
- case QMetaType::Int:
- case QMetaType::Short:
- case QMetaType::UShort:
- case QMetaType::Char:
- case QMetaType::UChar:
- v = QV4::Encode(unboundData.toInt());
- break;
- case QMetaType::UInt:
- v = QV4::Encode(unboundData.toUInt());
- break;
- }
- return v;
-}
/*!
\since 5.0
@@ -168,66 +121,66 @@ using namespace QV4;
Constructs a new QJSValue with a boolean \a value.
*/
QJSValue::QJSValue(bool value)
- : d(new QJSValuePrivate(QVariant(value)))
{
+ QJSValuePrivate::setVariant(this, QVariant(value));
}
/*!
\internal
*/
QJSValue::QJSValue(ExecutionEngine *e, quint64 val)
- : d(new QJSValuePrivate(e, val))
{
+ QJSValuePrivate::setValue(this, e, val);
}
/*!
Constructs a new QJSValue with a number \a value.
*/
QJSValue::QJSValue(int value)
- : d(new QJSValuePrivate(QVariant((double)value)))
{
+ QJSValuePrivate::setVariant(this, QVariant(value));
}
/*!
Constructs a new QJSValue with a number \a value.
*/
QJSValue::QJSValue(uint value)
- : d(new QJSValuePrivate(QVariant((double)value)))
{
+ QJSValuePrivate::setVariant(this, QVariant((double)value));
}
/*!
Constructs a new QJSValue with a number \a value.
*/
QJSValue::QJSValue(double value)
- : d(new QJSValuePrivate(QVariant(value)))
{
+ QJSValuePrivate::setVariant(this, QVariant(value));
}
/*!
Constructs a new QJSValue with a string \a value.
*/
QJSValue::QJSValue(const QString& value)
- : d(new QJSValuePrivate(value))
{
+ QJSValuePrivate::setVariant(this, QVariant(value));
}
/*!
Constructs a new QJSValue with a special \a value.
*/
QJSValue::QJSValue(SpecialValue value)
- : d(new QJSValuePrivate)
+ : d(0)
{
if (value == NullValue)
- d->unboundData = QVariant(QMetaType::VoidStar, (void *)0);
+ QJSValuePrivate::setVariant(this, QVariant(QMetaType::VoidStar, (void *)0));
}
/*!
Constructs a new QJSValue with a string \a value.
*/
QJSValue::QJSValue(const QLatin1String &value)
- : d(new QJSValuePrivate(value))
{
+ QJSValuePrivate::setVariant(this, QVariant(value));
}
/*!
@@ -235,8 +188,8 @@ QJSValue::QJSValue(const QLatin1String &value)
*/
#ifndef QT_NO_CAST_FROM_ASCII
QJSValue::QJSValue(const char *value)
- : d(new QJSValuePrivate(QString::fromUtf8(value)))
{
+ QJSValuePrivate::setVariant(this, QVariant(QString::fromUtf8(value)));
}
#endif
@@ -248,9 +201,14 @@ QJSValue::QJSValue(const char *value)
the new script value (i.e., the object itself is not copied).
*/
QJSValue::QJSValue(const QJSValue& other)
- : d(other.d)
+ : d(0)
{
- d->ref();
+ QV4::Value *v = QJSValuePrivate::getValue(&other);
+ if (v) {
+ QJSValuePrivate::setValue(this, QJSValuePrivate::engine(&other), v);
+ } else if (QVariant *v = QJSValuePrivate::getVariant(&other)) {
+ QJSValuePrivate::setVariant(this, *v);
+ }
}
/*!
@@ -258,8 +216,7 @@ QJSValue::QJSValue(const QJSValue& other)
*/
QJSValue::~QJSValue()
{
- if (d)
- d->deref();
+ QJSValuePrivate::free(this);
}
/*!
@@ -270,9 +227,11 @@ QJSValue::~QJSValue()
*/
bool QJSValue::isBool() const
{
- if (d->persistent.valueRef())
- return d->persistent.valueRef()->isBoolean();
- return d->unboundData.type() == QVariant::Bool;
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (val)
+ return val->isBoolean();
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ return variant && variant->type() == QVariant::Bool;
}
/*!
@@ -283,9 +242,27 @@ bool QJSValue::isBool() const
*/
bool QJSValue::isNumber() const
{
- if (d->persistent.valueRef())
- return d->persistent.valueRef()->isNumber();
- return d->unboundData.type() == QVariant::Double;
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (val)
+ return val->isNumber();
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ if (!variant)
+ return false;
+
+ switch (variant->userType()) {
+ case QMetaType::Double:
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ case QMetaType::Long:
+ case QMetaType::ULong:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ return true;
+ default:
+ return false;
+ }
}
/*!
@@ -294,9 +271,11 @@ bool QJSValue::isNumber() const
*/
bool QJSValue::isNull() const
{
- if (d->persistent.valueRef())
- return d->persistent.valueRef()->isNull();
- return (int)d->unboundData.type() == QMetaType::VoidStar;
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (val)
+ return val->isNull();
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ return variant && variant->userType() == QMetaType::VoidStar;
}
/*!
@@ -307,9 +286,11 @@ bool QJSValue::isNull() const
*/
bool QJSValue::isString() const
{
- if (d->persistent.valueRef())
- return d->persistent.valueRef()->isString();
- return (int)d->unboundData.type() == QMetaType::QString;
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (val)
+ return val->isString();
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ return variant && variant->userType() == QMetaType::QString;
}
/*!
@@ -318,9 +299,11 @@ bool QJSValue::isString() const
*/
bool QJSValue::isUndefined() const
{
- if (d->persistent.valueRef())
- return d->persistent.valueRef()->isUndefined();
- return (int)d->unboundData.type() == QMetaType::UnknownType || (int)d->unboundData.type() == QMetaType::Void;
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (val)
+ return val->isUndefined();
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ return !variant || variant->userType() == QMetaType::UnknownType || variant->userType() == QMetaType::Void;
}
/*!
@@ -329,9 +312,10 @@ bool QJSValue::isUndefined() const
*/
bool QJSValue::isError() const
{
- if (d->persistent.isEmpty())
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (!val)
return false;
- Object *o = d->persistent.valueRef()->asObject();
+ Object *o = val->asObject();
return o && o->asErrorObject();
}
@@ -343,9 +327,10 @@ bool QJSValue::isError() const
*/
bool QJSValue::isArray() const
{
- if (d->persistent.isEmpty())
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (!val)
return false;
- return d->persistent.valueRef()->asArrayObject();
+ return val->asArrayObject();
}
/*!
@@ -359,9 +344,10 @@ bool QJSValue::isArray() const
*/
bool QJSValue::isObject() const
{
- if (d->persistent.isEmpty())
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (!val)
return false;
- return d->persistent.valueRef()->asObject();
+ return val->asObject();
}
/*!
@@ -372,9 +358,10 @@ bool QJSValue::isObject() const
*/
bool QJSValue::isCallable() const
{
- if (d->persistent.isEmpty())
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (!val)
return false;
- return d->persistent.valueRef()->asFunctionObject();
+ return val->asFunctionObject();
}
/*!
@@ -385,9 +372,10 @@ bool QJSValue::isCallable() const
*/
bool QJSValue::isVariant() const
{
- if (d->persistent.isEmpty())
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (!val)
return false;
- return d->persistent.valueRef()->as<QV4::VariantObject>();
+ return val->as<QV4::VariantObject>();
}
/*!
@@ -405,13 +393,15 @@ bool QJSValue::isVariant() const
QString QJSValue::toString() const
{
QV4::Value scratch;
- QV4::Value *val = d->valueForData(&scratch);
+ QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
if (!val) {
- if (d->unboundData.type() == QVariant::Map)
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ Q_ASSERT(variant);
+ if (variant->type() == QVariant::Map)
return QStringLiteral("[object Object]");
- else if (d->unboundData.type() == QVariant::List) {
- const QVariantList list = d->unboundData.toList();
+ else if (variant->type() == QVariant::List) {
+ const QVariantList list = variant->toList();
QString result;
for (int i = 0; i < list.count(); ++i) {
if (i > 0)
@@ -420,7 +410,7 @@ QString QJSValue::toString() const
}
return result;
}
- return d->unboundData.toString();
+ return variant->toString();
}
return val->toQStringNoThrow();
}
@@ -440,19 +430,22 @@ QString QJSValue::toString() const
double QJSValue::toNumber() const
{
QV4::Value scratch;
- QV4::Value *val = d->valueForData(&scratch);
+ QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
if (!val) {
- if (d->unboundData.type() == QVariant::String)
- return RuntimeHelpers::stringToNumber(d->unboundData.toString());
- else if (d->unboundData.canConvert<double>())
- return d->unboundData.value<double>();
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ Q_ASSERT(variant);
+
+ if (variant->type() == QVariant::String)
+ return RuntimeHelpers::stringToNumber(variant->toString());
+ else if (variant->canConvert<double>())
+ return variant->value<double>();
else
return std::numeric_limits<double>::quiet_NaN();
}
double dbl = val->toNumber();
- QV4::ExecutionEngine *engine = d->persistent.engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (engine && engine->hasException) {
engine->catchException();
return 0;
@@ -475,17 +468,18 @@ double QJSValue::toNumber() const
bool QJSValue::toBool() const
{
QV4::Value scratch;
- QV4::Value *val = d->valueForData(&scratch);
+ QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
if (!val) {
- if (d->unboundData.userType() == QMetaType::QString)
- return d->unboundData.toString().length() > 0;
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ if (variant->userType() == QMetaType::QString)
+ return variant->toString().length() > 0;
else
- return d->unboundData.toBool();
+ return variant->toBool();
}
bool b = val->toBoolean();
- QV4::ExecutionEngine *engine = d->persistent.engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (engine && engine->hasException) {
engine->catchException();
return false;
@@ -508,17 +502,18 @@ bool QJSValue::toBool() const
qint32 QJSValue::toInt() const
{
QV4::Value scratch;
- QV4::Value *val = d->valueForData(&scratch);
+ QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
if (!val) {
- if (d->unboundData.userType() == QMetaType::QString)
- return QV4::Primitive::toInt32(RuntimeHelpers::stringToNumber(d->unboundData.toString()));
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ if (variant->userType() == QMetaType::QString)
+ return QV4::Primitive::toInt32(RuntimeHelpers::stringToNumber(variant->toString()));
else
- return d->unboundData.toInt();
+ return variant->toInt();
}
qint32 i = val->toInt32();
- QV4::ExecutionEngine *engine = d->persistent.engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (engine && engine->hasException) {
engine->catchException();
return 0;
@@ -541,17 +536,18 @@ qint32 QJSValue::toInt() const
quint32 QJSValue::toUInt() const
{
QV4::Value scratch;
- QV4::Value *val = d->valueForData(&scratch);
+ QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
if (!val) {
- if (d->unboundData.userType() == QMetaType::QString)
- return QV4::Primitive::toUInt32(RuntimeHelpers::stringToNumber(d->unboundData.toString()));
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ if (variant->userType() == QMetaType::QString)
+ return QV4::Primitive::toUInt32(RuntimeHelpers::stringToNumber(variant->toString()));
else
- return d->unboundData.toUInt();
+ return variant->toUInt();
}
quint32 u = val->toUInt32();
- QV4::ExecutionEngine *engine = d->persistent.engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (engine && engine->hasException) {
engine->catchException();
return 0;
@@ -583,24 +579,29 @@ quint32 QJSValue::toUInt() const
*/
QVariant QJSValue::toVariant() const
{
- if (d->persistent.isEmpty())
- return d->unboundData;
-
- if (Object *o = d->persistent.valueRef()->asObject())
- return o->engine()->toVariant(*d->persistent.valueRef(), /*typeHint*/ -1, /*createJSValueForObjects*/ false);
-
- if (d->persistent.valueRef()->isString())
- return QVariant(d->persistent.valueRef()->stringValue()->toQString());
- if (d->persistent.valueRef()->isBoolean())
- return QVariant(d->persistent.valueRef()->booleanValue());
- if (d->persistent.valueRef()->isNumber()) {
- if (d->persistent.valueRef()->isInt32())
- return QVariant(d->persistent.valueRef()->integerValue());
- return QVariant(d->persistent.valueRef()->asDouble());
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ if (variant)
+ return *variant;
+
+ QV4::Value scratch;
+ QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
+ Q_ASSERT(val);
+
+ if (Object *o = val->asObject())
+ return o->engine()->toVariant(*val, /*typeHint*/ -1, /*createJSValueForObjects*/ false);
+
+ if (val->isString())
+ return QVariant(val->stringValue()->toQString());
+ if (val->isBoolean())
+ return QVariant(val->booleanValue());
+ if (val->isNumber()) {
+ if (val->isInt32())
+ return QVariant(val->integerValue());
+ return QVariant(val->asDouble());
}
- if (d->persistent.valueRef()->isNull())
+ if (val->isNull())
return QVariant(QMetaType::VoidStar, 0);
- Q_ASSERT(d->persistent.valueRef()->isUndefined());
+ Q_ASSERT(val->isUndefined());
return QVariant();
}
@@ -621,25 +622,26 @@ QVariant QJSValue::toVariant() const
*/
QJSValue QJSValue::call(const QJSValueList &args)
{
- if (d->persistent.isEmpty())
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (!val)
return QJSValue();
- FunctionObject *f = d->persistent.valueRef()->asFunctionObject();
+ FunctionObject *f = val->asFunctionObject();
if (!f)
return QJSValue();
- ExecutionEngine *engine = d->persistent.engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
Q_ASSERT(engine);
Scope scope(engine);
ScopedCallData callData(scope, args.length());
callData->thisObject = engine->globalObject()->asReturnedValue();
for (int i = 0; i < args.size(); ++i) {
- if (!args.at(i).d->checkEngine(engine)) {
+ if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
return QJSValue();
}
- callData->args[i] = args.at(i).d->getValue(engine);
+ callData->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i));
}
ScopedValue result(scope, f->call(callData));
@@ -671,30 +673,31 @@ QJSValue QJSValue::call(const QJSValueList &args)
*/
QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList &args)
{
- if (d->persistent.isEmpty())
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (!val)
return QJSValue();
- FunctionObject *f = d->persistent.valueRef()->asFunctionObject();
+ FunctionObject *f = val->asFunctionObject();
if (!f)
return QJSValue();
- ExecutionEngine *engine = d->persistent.engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
Q_ASSERT(engine);
Scope scope(engine);
- if (!instance.d->checkEngine(engine)) {
+ if (!QJSValuePrivate::checkEngine(engine, instance)) {
qWarning("QJSValue::call() failed: cannot call function with thisObject created in a different engine");
return QJSValue();
}
ScopedCallData callData(scope, args.size());
- callData->thisObject = instance.d->getValue(engine);
+ callData->thisObject = QJSValuePrivate::convertedToValue(engine, instance);
for (int i = 0; i < args.size(); ++i) {
- if (!args.at(i).d->checkEngine(engine)) {
+ if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
return QJSValue();
}
- callData->args[i] = args.at(i).d->getValue(engine);
+ callData->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i));
}
ScopedValue result(scope, f->call(callData));
@@ -724,24 +727,25 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
*/
QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
{
- if (d->persistent.isEmpty())
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (!val)
return QJSValue();
- FunctionObject *f = d->persistent.valueRef()->asFunctionObject();
+ FunctionObject *f = val->asFunctionObject();
if (!f)
return QJSValue();
- ExecutionEngine *engine = d->persistent.engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
Q_ASSERT(engine);
Scope scope(engine);
ScopedCallData callData(scope, args.size());
for (int i = 0; i < args.size(); ++i) {
- if (!args.at(i).d->checkEngine(engine)) {
+ if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
return QJSValue();
}
- callData->args[i] = args.at(i).d->getValue(engine);
+ callData->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i));
}
ScopedValue result(scope, f->construct(callData));
@@ -762,7 +766,7 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
*/
QJSEngine* QJSValue::engine() const
{
- QV4::ExecutionEngine *engine = d->persistent.engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (engine)
return engine->jsEngine();
return 0;
@@ -779,11 +783,11 @@ QJSEngine* QJSValue::engine() const
*/
QJSValue QJSValue::prototype() const
{
- QV4::ExecutionEngine *engine = d->persistent.engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (!engine)
return QJSValue();
QV4::Scope scope(engine);
- ScopedObject o(scope, d->persistent.valueRef()->asObject());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this)->asObject());
if (!o)
return QJSValue();
ScopedObject p(scope, o->prototype());
@@ -806,20 +810,23 @@ QJSValue QJSValue::prototype() const
*/
void QJSValue::setPrototype(const QJSValue& prototype)
{
- ExecutionEngine *v4 = d->persistent.engine();
- if (!v4)
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
+ if (!engine)
return;
- Scope scope(v4);
- ScopedObject o(scope, d->persistent.value());
+ Scope scope(engine);
+ ScopedObject o(scope, QJSValuePrivate::getValue(this));
if (!o)
return;
- prototype.d->getValue(v4);
- if (prototype.d->persistent.valueRef()->isNull()) {
+ QV4::Value scratch;
+ QV4::Value *val = QJSValuePrivate::valueForData(&prototype, &scratch);
+ if (!val)
+ return;
+ if (val->isNull()) {
o->setPrototype(0);
return;
}
- ScopedObject p(scope, prototype.d->persistent.value());
+ ScopedObject p(scope, val);
if (!p)
return;
if (o->engine() != p->engine()) {
@@ -839,10 +846,17 @@ void QJSValue::setPrototype(const QJSValue& prototype)
*/
QJSValue& QJSValue::operator=(const QJSValue& other)
{
- if (d != other.d) {
- d->deref();
- d = other.d;
- d->ref();
+ if (d == other.d)
+ return *this;
+
+ QJSValuePrivate::free(this);
+ d = 0;
+
+ QV4::Value *v = QJSValuePrivate::getValue(&other);
+ if (v) {
+ QJSValuePrivate::setValue(this, QJSValuePrivate::engine(&other), v);
+ } else if (QVariant *v = QJSValuePrivate::getVariant(&other)) {
+ QJSValuePrivate::setVariant(this, *v);
}
return *this;
}
@@ -890,15 +904,17 @@ static bool js_equal(const QString &string, QV4::ValueRef value)
bool QJSValue::equals(const QJSValue& other) const
{
QV4::Value s1, s2;
- QV4::Value *v = d->valueForData(&s1);
- QV4::Value *ov = other.d->valueForData(&s2);
+ QV4::Value *v = QJSValuePrivate::valueForData(this, &s1);
+ QV4::Value *ov = QJSValuePrivate::valueForData(&other, &s2);
if (!v) {
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ Q_ASSERT(variant);
if (!ov)
- return d->unboundData == other.d->unboundData;
- if (d->unboundData.type() == QVariant::Map || d->unboundData.type() == QVariant::List)
+ return *variant == *QJSValuePrivate::getVariant(&other);
+ if (variant->type() == QVariant::Map || variant->type() == QVariant::List)
return false;
- return js_equal(d->unboundData.toString(), *ov);
+ return js_equal(variant->toString(), *ov);
}
if (!ov)
return other.equals(*this);
@@ -931,16 +947,18 @@ bool QJSValue::equals(const QJSValue& other) const
bool QJSValue::strictlyEquals(const QJSValue& other) const
{
QV4::Value s1, s2;
- QV4::Value *v = d->valueForData(&s1);
- QV4::Value *ov = other.d->valueForData(&s2);
+ QV4::Value *v = QJSValuePrivate::valueForData(this, &s1);
+ QV4::Value *ov = QJSValuePrivate::valueForData(&other, &s2);
if (!v) {
+ QVariant *variant = QJSValuePrivate::getVariant(this);
+ Q_ASSERT(variant);
if (!ov)
- return d->unboundData == other.d->unboundData;
- if (d->unboundData.type() == QVariant::Map || d->unboundData.type() == QVariant::List)
+ return *variant == *QJSValuePrivate::getVariant(&other);
+ if (variant->type() == QVariant::Map || variant->type() == QVariant::List)
return false;
if (ov->isString())
- return d->unboundData.toString() == ov->stringValue()->toQString();
+ return variant->toString() == ov->stringValue()->toQString();
return false;
}
if (!ov)
@@ -964,12 +982,12 @@ bool QJSValue::strictlyEquals(const QJSValue& other) const
*/
QJSValue QJSValue::property(const QString& name) const
{
- ExecutionEngine *engine = d->engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (!engine)
return QJSValue();
QV4::Scope scope(engine);
- ScopedObject o(scope, d->persistent.value());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this));
if (!o)
return QJSValue();
@@ -1000,12 +1018,12 @@ QJSValue QJSValue::property(const QString& name) const
*/
QJSValue QJSValue::property(quint32 arrayIndex) const
{
- ExecutionEngine *engine = d->engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (!engine)
return QJSValue();
QV4::Scope scope(engine);
- ScopedObject o(scope, d->persistent.value());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this));
if (!o)
return QJSValue();
@@ -1028,16 +1046,16 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
*/
void QJSValue::setProperty(const QString& name, const QJSValue& value)
{
- ExecutionEngine *engine = d->engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (!engine)
return;
Scope scope(engine);
- ScopedObject o(scope, d->persistent.value());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this));
if (!o)
return;
- if (!value.d->checkEngine(o->engine())) {
+ if (!QJSValuePrivate::checkEngine(engine, value)) {
qWarning("QJSValue::setProperty(%s) failed: cannot set value created in a different engine", name.toUtf8().constData());
return;
}
@@ -1050,7 +1068,7 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value)
}
s->makeIdentifier(scope.engine);
- QV4::ScopedValue v(scope, value.d->getValue(engine));
+ QV4::ScopedValue v(scope, QJSValuePrivate::convertedToValue(engine, value));
o->put(s, v);
if (engine->hasException)
engine->catchException();
@@ -1070,16 +1088,21 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value)
*/
void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
{
- ExecutionEngine *engine = d->engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (!engine)
return;
Scope scope(engine);
- ScopedObject o(scope, d->persistent.value());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this));
if (!o)
return;
- QV4::ScopedValue v(scope, value.d->getValue(engine));
+ if (!QJSValuePrivate::checkEngine(engine, value)) {
+ qWarning("QJSValue::setProperty(%d) failed: cannot set value created in a different engine", arrayIndex);
+ return;
+ }
+
+ QV4::ScopedValue v(scope, QJSValuePrivate::convertedToValue(engine, value));
if (arrayIndex != UINT_MAX)
o->putIndexed(arrayIndex, v);
else
@@ -1110,9 +1133,9 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
*/
bool QJSValue::deleteProperty(const QString &name)
{
- ExecutionEngine *engine = d->engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
Scope scope(engine);
- ScopedObject o(scope, d->persistent.value());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this));
if (!o)
return false;
@@ -1131,12 +1154,12 @@ bool QJSValue::deleteProperty(const QString &name)
*/
bool QJSValue::hasProperty(const QString &name) const
{
- ExecutionEngine *engine = d->engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (!engine)
return false;
Scope scope(engine);
- ScopedObject o(scope, d->persistent.value());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this));
if (!o)
return false;
@@ -1152,12 +1175,12 @@ bool QJSValue::hasProperty(const QString &name) const
*/
bool QJSValue::hasOwnProperty(const QString &name) const
{
- ExecutionEngine *engine = d->engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (!engine)
return false;
Scope scope(engine);
- ScopedObject o(scope, d->persistent.value());
+ ScopedObject o(scope, QJSValuePrivate::getValue(this));
if (!o)
return false;
@@ -1177,11 +1200,11 @@ bool QJSValue::hasOwnProperty(const QString &name) const
*/
QObject *QJSValue::toQObject() const
{
- ExecutionEngine *engine = d->engine();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
if (!engine)
return 0;
QV4::Scope scope(engine);
- QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, d->persistent.value());
+ QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, QJSValuePrivate::getValue(this));
if (!wrapper)
return 0;
@@ -1197,8 +1220,9 @@ QObject *QJSValue::toQObject() const
*/
QDateTime QJSValue::toDateTime() const
{
- if (!d->persistent.isEmpty()) {
- QV4::DateObject *date = d->persistent.valueRef()->asDateObject();
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ if (val) {
+ QV4::DateObject *date = val->asDateObject();
if (date)
return date->toQDateTime();
}
@@ -1211,7 +1235,8 @@ QDateTime QJSValue::toDateTime() const
*/
bool QJSValue::isDate() const
{
- return !d->persistent.isEmpty() && d->persistent.valueRef()->asDateObject();
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ return val && val->asDateObject();
}
/*!
@@ -1220,7 +1245,8 @@ bool QJSValue::isDate() const
*/
bool QJSValue::isRegExp() const
{
- return !d->persistent.isEmpty() && d->persistent.valueRef()->as<RegExpObject>();
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ return val && val->as<RegExpObject>();
}
/*!
@@ -1234,7 +1260,8 @@ bool QJSValue::isRegExp() const
*/
bool QJSValue::isQObject() const
{
- return !d->persistent.isEmpty() && d->persistent.valueRef()->as<QV4::QObjectWrapper>() != 0;
+ QV4::Value *val = QJSValuePrivate::getValue(this);
+ return val && val->as<QV4::QObjectWrapper>() != 0;
}
QT_END_NAMESPACE
diff --git a/src/qml/jsapi/qjsvalue.h b/src/qml/jsapi/qjsvalue.h
index 4ff86b1edc..19736803c1 100644
--- a/src/qml/jsapi/qjsvalue.h
+++ b/src/qml/jsapi/qjsvalue.h
@@ -49,7 +49,6 @@ struct QMetaObject;
class QDateTime;
typedef QList<QJSValue> QJSValueList;
-class QJSValuePrivate;
namespace QV4 {
struct ExecutionEngine;
struct Value;
@@ -140,7 +139,7 @@ private:
// force compile error, prevent QJSValue(bool) to be called
QJSValue(void *) Q_DECL_EQ_DELETE;
- QJSValuePrivate *d;
+ mutable quintptr d;
};
QT_END_NAMESPACE
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index 3d7afdbd75..83dbe82f76 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -57,64 +57,117 @@
QT_BEGIN_NAMESPACE
-/*!
- \internal
- \class QJSValuePrivate
-*/
-class Q_QML_PRIVATE_EXPORT QJSValuePrivate
+class QJSValuePrivate
{
public:
- QJSValuePrivate()
- : refcount(1)
- {}
- QJSValuePrivate(QV4::ExecutionEngine *e, const QV4::ValueRef v)
- : refcount(1),
- persistent(e, v)
+ static inline QV4::Value *getValue(const QJSValue *jsval)
{
- Q_ASSERT(!v->isEmpty());
+ if (jsval->d & 3)
+ return 0;
+ return reinterpret_cast<QV4::Value *>(jsval->d);
}
- QJSValuePrivate(QV4::ExecutionEngine *e, QV4::ReturnedValue v)
- : refcount(1),
- persistent(e, v)
+
+ static inline QVariant *getVariant(const QJSValue *jsval)
{
+ if (jsval->d & 1)
+ return reinterpret_cast<QVariant *>(jsval->d & ~3);
+ return 0;
}
- explicit QJSValuePrivate(const QVariant &v)
- : refcount(1),
- unboundData(v)
- {
+
+ static inline void setVariant(QJSValue *jsval, const QVariant &v) {
+ QVariant *val = new QVariant(v);
+ jsval->d = reinterpret_cast<quintptr>(val) | 1;
}
- bool checkEngine(QV4::ExecutionEngine *e) {
- if (persistent.isEmpty())
- getValue(e);
- return persistent.engine() == e;
+ static inline void setValue(QJSValue *jsval, QV4::ExecutionEngine *engine, QV4::ValueRef v) {
+ QV4::Value *value = engine->memoryManager->m_persistentValues->allocate();
+ *value = v;
+ jsval->d = reinterpret_cast<quintptr>(value);
}
- QV4::ReturnedValue getValue(QV4::ExecutionEngine *e);
+ static inline void setValue(QJSValue *jsval, QV4::ExecutionEngine *engine, QV4::ReturnedValue v) {
+ QV4::Value *value = engine->memoryManager->m_persistentValues->allocate();
+ *value = v;
+ jsval->d = reinterpret_cast<quintptr>(value);
+ }
- static QJSValuePrivate *get(const QJSValue &v) { return v.d; }
- QV4::ExecutionEngine *engine() const { return persistent.engine(); }
+ static QV4::ReturnedValue convertedToValue(QV4::ExecutionEngine *e, const QJSValue &jsval)
+ {
+ QV4::Value *v = getValue(&jsval);
+ if (!v) {
+ QVariant *variant = getVariant(&jsval);
+ v = e->memoryManager->m_persistentValues->allocate();
+ *v = variant ? e->fromVariant(*variant) : QV4::Encode::undefined();
+ jsval.d = reinterpret_cast<quintptr>(v);
+ delete variant;
+ }
+
+ if (QV4::PersistentValueStorage::getEngine(v) != e) {
+ qWarning("JSValue can't be reassigned to another engine.");
+ return QV4::Encode::undefined();
+ }
- void ref() { ++refcount; }
- void deref() {
- if (!--refcount)
- delete this;
+ return v->asReturnedValue();
}
- QV4::Value *valueForData(QV4::Value *scratch) const {
- QV4::Value *v = persistent.valueRef();
+ static QV4::Value *valueForData(const QJSValue *jsval, QV4::Value *scratch)
+ {
+ QV4::Value *v = getValue(jsval);
if (v)
return v;
- *scratch = primitiveValueForUnboundData();
- return (scratch->isEmpty() ? 0 : scratch);
+ v = scratch;
+ QVariant *variant = getVariant(jsval);
+ if (!variant) {
+ *v = QV4::Encode::undefined();
+ return v;
+ }
+
+ switch (variant->userType()) {
+ case QMetaType::UnknownType:
+ case QMetaType::Void:
+ *v = QV4::Encode::undefined();
+ break;
+ case QMetaType::VoidStar:
+ *v = QV4::Encode::null();
+ break;
+ case QMetaType::Bool:
+ *v = QV4::Encode(variant->toBool());
+ break;
+ case QMetaType::Double:
+ *v = QV4::Encode(variant->toDouble());
+ break;
+ case QMetaType::Int:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ *v = QV4::Encode(variant->toInt());
+ break;
+ case QMetaType::UInt:
+ *v = QV4::Encode(variant->toUInt());
+ break;
+ default:
+ return 0;
+ }
+ return v;
+ }
+
+ static QV4::ExecutionEngine *engine(const QJSValue *jsval) {
+ QV4::Value *v = getValue(jsval);
+ return v ? QV4::PersistentValueStorage::getEngine(v) : 0;
}
- QV4::Value primitiveValueForUnboundData() const;
- int refcount;
- QV4::PersistentValue persistent;
- QVariant unboundData;
-private:
- QJSValuePrivate(QV4::ReturnedValue v) Q_DECL_EQ_DELETE;
+ static inline bool checkEngine(QV4::ExecutionEngine *e, const QJSValue &jsval) {
+ QV4::ExecutionEngine *v4 = engine(&jsval);
+ return !v4 || v4 == e;
+ }
+
+ static inline void free(QJSValue *jsval) {
+ if (QV4::Value *v = QJSValuePrivate::getValue(jsval))
+ QV4::PersistentValueStorage::free(v);
+ else if (QVariant *v = QJSValuePrivate::getVariant(jsval))
+ delete v;
+ }
};
QT_END_NAMESPACE
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index 2b27f655c8..6f78f71f48 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -45,13 +45,12 @@ QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
, currentIndex(UINT_MAX)
, nextIndex(UINT_MAX)
{
- QJSValuePrivate *jsp = QJSValuePrivate::get(value);
- QV4::ExecutionEngine *e = jsp->persistent.engine();
+ QV4::ExecutionEngine *e = QJSValuePrivate::engine(&v);
if (!e)
return;
QV4::Scope scope(e);
- QV4::ScopedObject o(scope, jsp->persistent.value());
+ QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&v));
iterator.set(e, e->newForEachIteratorObject(o));
currentName = (QV4::String *)0;
@@ -123,7 +122,7 @@ QJSValueIterator::~QJSValueIterator()
*/
bool QJSValueIterator::hasNext() const
{
- QV4::Value *val = QJSValuePrivate::get(d_ptr->value)->persistent.valueRef();
+ QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value);
if (!val || !val->isObject())
return false;
return !!d_ptr->nextName || d_ptr->nextIndex != UINT_MAX;
@@ -139,7 +138,7 @@ bool QJSValueIterator::hasNext() const
*/
bool QJSValueIterator::next()
{
- QV4::Value *val = QJSValuePrivate::get(d_ptr->value)->persistent.valueRef();
+ QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value);
if (!val || !val->isObject())
return false;
d_ptr->currentName = d_ptr->nextName;
@@ -166,7 +165,7 @@ bool QJSValueIterator::next()
*/
QString QJSValueIterator::name() const
{
- QV4::Value *val = QJSValuePrivate::get(d_ptr->value)->persistent.valueRef();
+ QV4::Value *val = QJSValuePrivate::getValue(&d_ptr->value);
if (!val || !val->isObject())
return QString();
if (!!d_ptr->currentName)
@@ -189,7 +188,7 @@ QJSValue QJSValueIterator::value() const
if (!engine)
return QJSValue();
QV4::Scope scope(engine);
- QV4::ScopedObject obj(scope, QJSValuePrivate::get(d_ptr->value)->persistent.value());
+ QV4::ScopedObject obj(scope, QJSValuePrivate::getValue(&d_ptr->value));
if (!obj)
return QJSValue();
@@ -223,9 +222,8 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
return *this;
}
- QJSValuePrivate *jsp = QJSValuePrivate::get(object);
QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, jsp->persistent.value());
+ QV4::ScopedObject o(scope, QJSValuePrivate::getValue(&object));
d_ptr->iterator.set(v4, v4->newForEachIteratorObject(o));
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it.flags = QV4::ObjectIterator::NoFlags;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 359b24d5ab..366e5c7603 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1433,8 +1433,7 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
}
} else if (type == qMetaTypeId<QJSValue>()) {
const QJSValue *value = reinterpret_cast<const QJSValue *>(ptr);
- QJSValuePrivate *valuep = QJSValuePrivate::get(*value);
- return valuep->getValue(this);
+ return QJSValuePrivate::convertedToValue(this, *value);
} else if (type == qMetaTypeId<QList<QObject *> >()) {
// XXX Can this be made more by using Array as a prototype and implementing
// directly against QList<QObject*>?
@@ -1586,7 +1585,7 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(data));
default:
if (type == qMetaTypeId<QJSValue>()) {
- return QJSValuePrivate::get(*reinterpret_cast<const QJSValue*>(data))->getValue(this);
+ return QJSValuePrivate::convertedToValue(this, *reinterpret_cast<const QJSValue*>(data));
} else {
QByteArray typeName = QMetaType::typeName(type);
if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 3bacba117e..9fb7ad96fa 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -194,7 +194,7 @@ static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object
} else if (property.propType == qMetaTypeId<QJSValue>()) {
QJSValue v;
ReadFunction(object, property, &v, notifier);
- return QJSValuePrivate::get(v)->getValue(v4);
+ return QJSValuePrivate::convertedToValue(v4, v);
} else if (property.isQVariant()) {
QVariant v;
ReadFunction(object, property, &v, notifier);
@@ -1680,7 +1680,7 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
QV4::Scope scope(engine);
if (type == qMetaTypeId<QJSValue>()) {
- return QJSValuePrivate::get(*qjsValuePtr)->getValue(scope.engine);
+ return QJSValuePrivate::convertedToValue(scope.engine, *qjsValuePtr);
} else if (type == QMetaType::Int) {
return QV4::Encode(int(intValue));
} else if (type == QMetaType::UInt) {
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 0c16ae18db..29f5152f77 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -416,7 +416,7 @@ ReturnedValue QmlContextWrapper::qmlSingletonWrapper(ExecutionEngine *v4, String
if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
return QV4::QObjectWrapper::wrap(engine(), qobjectSingleton);
- return QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(engine());
+ return QJSValuePrivate::convertedToValue(engine(), siinfo->scriptApi(e));
}
DEFINE_OBJECT_VTABLE(QQmlIdObjectsArray);
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 77d472e0c7..2c0972bced 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -168,7 +168,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
return QV4::QObjectWrapper::getQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
} else if (!siinfo->scriptApi(e).isUndefined()) {
// NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable.
- QV4::ScopedObject o(scope, QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(v4));
+ QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e)));
if (!!o)
return o->get(name);
}
@@ -254,7 +254,7 @@ void QmlTypeWrapper::put(Managed *m, String *name, const ValueRef value)
if (qobjectSingleton) {
QV4::QObjectWrapper::setQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
} else if (!siinfo->scriptApi(e).isUndefined()) {
- QV4::ScopedObject apiprivate(scope, QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(v4));
+ QV4::ScopedObject apiprivate(scope, QJSValuePrivate::convertedToValue(v4, siinfo->scriptApi(e)));
if (!apiprivate) {
QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"');
v4->throwError(error);
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index ce5d3c8370..73113be9ba 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -102,20 +102,18 @@ static void saveJSValue(QDataStream &stream, const void *data)
static void restoreJSValue(QDataStream &stream, void *data)
{
QJSValue *jsv = reinterpret_cast<QJSValue*>(data);
- QJSValuePrivate *d = QJSValuePrivate::get(*jsv);
quint32 isNullOrUndefined;
stream >> isNullOrUndefined;
- // ### Optimize for the common case where we have an valid persistent
- d->persistent.clear();
-
if (isNullOrUndefined & 0x1) {
- d->unboundData = QVariant(QMetaType::VoidStar, (void *)0);
+ *jsv = QJSValue(QJSValue::NullValue);
} else if (isNullOrUndefined & 0x2) {
- d->unboundData = QVariant();
+ *jsv = QJSValue();
} else {
- d->unboundData.load(stream);
+ QVariant v;
+ v.load(stream);
+ QJSValuePrivate::setVariant(jsv, v);
}
}