aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-09-23 15:52:10 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-26 09:05:16 +0200
commit12fd2ccd3fa2dc0133b5a3fb89f9fdf5cf721232 (patch)
tree880acb9c7c0d8289185b6aebe4339f439c707a0e /src/qml/jsruntime
parent2e4f66caa8a5f9e887dbdb4e3f2ae5c9be9a7005 (diff)
Fix Persistent/WeakValue API
Don't use unprotected Values in the API anymore. Change-Id: I8851628227fca374de24701bc8ee0908b5ae3923 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4engine.cpp4
-rw-r--r--src/qml/jsruntime/qv4engine_p.h2
-rw-r--r--src/qml/jsruntime/qv4exception.cpp3
-rw-r--r--src/qml/jsruntime/qv4exception_p.h3
-rw-r--r--src/qml/jsruntime/qv4include.cpp24
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp99
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h10
-rw-r--r--src/qml/jsruntime/qv4script.cpp14
-rw-r--r--src/qml/jsruntime/qv4script_p.h6
-rw-r--r--src/qml/jsruntime/qv4value.cpp73
-rw-r--r--src/qml/jsruntime/qv4value_p.h41
12 files changed, 153 insertions, 128 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 821e88ee61..363f0a45c0 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -101,6 +101,8 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
{
MemoryManager::GCBlocker gcBlocker(memoryManager);
+ exceptionValue = Encode::undefined();
+
if (!factory) {
#ifdef V4_ENABLE_JIT
@@ -735,6 +737,8 @@ void ExecutionEngine::markObjects()
typeErrorCtor.mark();
uRIErrorCtor.mark();
+ exceptionValue.mark();
+
thrower->mark();
if (m_qmlExtensions)
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index ec2c6f394d..90639d582c 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -236,6 +236,8 @@ struct Q_QML_EXPORT ExecutionEngine
RegExpCache *regExpCache;
+ SafeValue exceptionValue;
+
// Scarce resources are "exceptionally high cost" QVariant types where allowing the
// normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
// out-of-resource situations. When such a resource is passed into JavaScript we
diff --git a/src/qml/jsruntime/qv4exception.cpp b/src/qml/jsruntime/qv4exception.cpp
index 725a046b71..35a4f726e2 100644
--- a/src/qml/jsruntime/qv4exception.cpp
+++ b/src/qml/jsruntime/qv4exception.cpp
@@ -88,8 +88,8 @@ void Exception::throwException(ExecutionContext *context, const Value &value)
Exception::Exception(ExecutionContext *throwingContext, const Value &exceptionValue)
: e(throwingContext->engine)
- , exception(exceptionValue)
{
+ e->exceptionValue = exceptionValue;
this->throwingContext = throwingContext->engine->current;
accepted = false;
if (ErrorObject *error = exceptionValue.asErrorObject())
@@ -101,6 +101,7 @@ Exception::Exception(ExecutionContext *throwingContext, const Value &exceptionVa
Exception::~Exception()
{
assert(accepted);
+ e->exceptionValue = Value::undefinedValue();
}
void Exception::accept(ExecutionContext *catchingContext)
diff --git a/src/qml/jsruntime/qv4exception_p.h b/src/qml/jsruntime/qv4exception_p.h
index 75246fa147..eaeebf7abd 100644
--- a/src/qml/jsruntime/qv4exception_p.h
+++ b/src/qml/jsruntime/qv4exception_p.h
@@ -58,7 +58,7 @@ struct Q_QML_EXPORT Exception {
void partiallyUnwindContext(ExecutionContext *catchingContext);
- ReturnedValue value() const { return exception.value().asReturnedValue(); }
+ ReturnedValue value() const { return e->exceptionValue.asReturnedValue(); }
ExecutionEngine::StackTrace stackTrace() const { return m_stackTrace; }
ExecutionEngine *engine() const { return e; }
@@ -71,7 +71,6 @@ private:
ExecutionEngine *e;
ExecutionContext *throwingContext;
bool accepted;
- PersistentValue exception;
ExecutionEngine::StackTrace m_stackTrace;
static void throwInternal(ExecutionContext *throwingContext, const Value &exceptionValue);
};
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 681ae5990d..d6f01bf369 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -62,9 +62,9 @@ QV4Include::QV4Include(const QUrl &url, QV8Engine *engine, QQmlContextData *cont
const QV4::Value &qmlglobal, const QV4::Value &callback)
: v4(QV8Engine::getV4(engine)), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
{
- m_qmlglobal = qmlglobal;
+ m_qmlglobal = qmlglobal.asReturnedValue();
if (callback.asFunctionObject())
- m_callbackFunction = callback;
+ m_callbackFunction = callback.asReturnedValue();
m_resultObject = resultValue(v4);
@@ -119,7 +119,7 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
QV4::ReturnedValue QV4Include::result()
{
- return m_resultObject.value().asReturnedValue();
+ return m_resultObject.value();
}
#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15
@@ -143,32 +143,34 @@ void QV4Include::finished()
}
QV4::Scope scope(v4);
+ QV4::ScopedObject resultObj(scope, m_resultObject.value());
if (m_reply->error() == QNetworkReply::NoError) {
QByteArray data = m_reply->readAll();
QString code = QString::fromUtf8(data);
QQmlScript::Parser::extractPragmas(code);
- QV4::Script script(v4, m_qmlglobal.value().asObject(), code, m_url.toString());
+ QV4::ScopedObject qmlglobal(scope, m_qmlglobal.value());
+ QV4::Script script(v4, qmlglobal, code, m_url.toString());
QV4::ExecutionContext *ctx = v4->current;
- QV4::Scoped<QV4::Object> o(scope, m_resultObject.value());
QV4::ScopedString status(scope, v4->newString("status"));
try {
script.parse();
script.run();
- o->put(status, QV4::ScopedValue(scope, QV4::Value::fromInt32(Ok)));
+ resultObj->put(status, QV4::ScopedValue(scope, QV4::Value::fromInt32(Ok)));
} catch (QV4::Exception &e) {
e.accept(ctx);
- o->put(status, QV4::ScopedValue(scope, QV4::Value::fromInt32(Exception)));
+ resultObj->put(status, QV4::ScopedValue(scope, QV4::Value::fromInt32(Exception)));
QV4::ScopedValue ex(scope, e.value());
- o->put(QV4::ScopedString(scope, v4->newString("exception")), ex);
+ resultObj->put(QV4::ScopedString(scope, v4->newString("exception")), ex);
}
} else {
- m_resultObject.value().asObject()->put(QV4::ScopedString(scope, v4->newString("status")), QV4::ScopedValue(scope, QV4::Value::fromInt32(NetworkError)));
+ resultObj->put(QV4::ScopedString(scope, v4->newString("status")), QV4::ScopedValue(scope, QV4::Value::fromInt32(NetworkError)));
}
- callback(m_callbackFunction.value(), m_resultObject.value());
+ QV4::ScopedValue cb(scope, m_callbackFunction.value());
+ callback(cb, resultObj.asValue());
disconnect();
deleteLater();
@@ -216,7 +218,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::SimpleCallContext *ctx)
QString code = QString::fromUtf8(data);
QQmlScript::Parser::extractPragmas(code);
- QV4::Script script(v4, qmlcontextobject.getPointer(), code, url.toString());
+ QV4::Script script(v4, qmlcontextobject, code, url.toString());
QV4::ExecutionContext *ctx = v4->current;
try {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 7e31797627..c0c68bb6fd 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -400,11 +400,14 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
return wrapper->getQmlProperty(ctx, qmlContext, name, revisionMode, hasProperty);
}
-bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, const Value &value)
+bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name,
+ QObjectWrapper::RevisionMode revisionMode, const ValueRef value)
{
if (QQmlData::wasDeleted(object))
return false;
+ QV4::Scope scope(ctx);
+
QQmlPropertyData local;
QQmlPropertyData *result = 0;
{
@@ -427,7 +430,8 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
}
QQmlBinding *newBinding = 0;
- if (FunctionObject *f = value.asFunctionObject()) {
+ QV4::ScopedFunctionObject f(scope, value);
+ if (f) {
if (!f->bindingKeyFlag) {
if (!result->isVarProperty() && result->propType != qMetaTypeId<QJSValue>()) {
// assigning a JS function to a non var or QJSValue property or is not allowed.
@@ -461,7 +465,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
// allow assignment of "special" values (null, undefined, function) to var properties
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- vmemo->setVMEProperty(result->coreIndex, value);
+ vmemo->setVMEProperty(result->coreIndex, *value);
return true;
}
@@ -472,46 +476,46 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
void *argv[] = { &o, 0, &status, &flags }; \
QMetaObject::metacall(object, QMetaObject::WriteProperty, result->coreIndex, argv);
- if (value.isNull() && result->isQObject()) {
+ if (value->isNull() && result->isQObject()) {
PROPERTY_STORE(QObject*, 0);
- } else if (value.isUndefined() && result->isResettable()) {
+ } else if (value->isUndefined() && result->isResettable()) {
void *a[] = { 0 };
QMetaObject::metacall(object, QMetaObject::ResetProperty, result->coreIndex, a);
- } else if (value.isUndefined() && result->propType == qMetaTypeId<QVariant>()) {
+ } else if (value->isUndefined() && result->propType == qMetaTypeId<QVariant>()) {
PROPERTY_STORE(QVariant, QVariant());
- } else if (value.isUndefined() && result->propType == QMetaType::QJsonValue) {
+ } else if (value->isUndefined() && result->propType == QMetaType::QJsonValue) {
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
} else if (!newBinding && result->propType == qMetaTypeId<QJSValue>()) {
PROPERTY_STORE(QJSValue, new QJSValuePrivate(ctx->engine, value));
- } else if (value.isUndefined()) {
+ } else if (value->isUndefined()) {
QString error = QLatin1String("Cannot assign [undefined] to ");
if (!QMetaType::typeName(result->propType))
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(result->propType));
ctx->throwError(error);
- } else if (value.asFunctionObject()) {
+ } else if (value->asFunctionObject()) {
// this is handled by the binding creation above
- } else if (result->propType == QMetaType::Int && value.isNumber()) {
- PROPERTY_STORE(int, qRound(value.asDouble()));
- } else if (result->propType == QMetaType::QReal && value.isNumber()) {
- PROPERTY_STORE(qreal, qreal(value.asDouble()));
- } else if (result->propType == QMetaType::Float && value.isNumber()) {
- PROPERTY_STORE(float, float(value.asDouble()));
- } else if (result->propType == QMetaType::Double && value.isNumber()) {
- PROPERTY_STORE(double, double(value.asDouble()));
- } else if (result->propType == QMetaType::QString && value.isString()) {
- PROPERTY_STORE(QString, value.toQStringNoThrow());
+ } else if (result->propType == QMetaType::Int && value->isNumber()) {
+ PROPERTY_STORE(int, qRound(value->asDouble()));
+ } else if (result->propType == QMetaType::QReal && value->isNumber()) {
+ PROPERTY_STORE(qreal, qreal(value->asDouble()));
+ } else if (result->propType == QMetaType::Float && value->isNumber()) {
+ PROPERTY_STORE(float, float(value->asDouble()));
+ } else if (result->propType == QMetaType::Double && value->isNumber()) {
+ PROPERTY_STORE(double, double(value->asDouble()));
+ } else if (result->propType == QMetaType::QString && value->isString()) {
+ PROPERTY_STORE(QString, value->toQStringNoThrow());
} else if (result->isVarProperty()) {
QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
- vmemo->setVMEProperty(result->coreIndex, value);
+ vmemo->setVMEProperty(result->coreIndex, *value);
} 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)) {
@@ -547,7 +551,7 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
if (ddata->jsEngineId == engine->m_engineId && !ddata->jsWrapper.isUndefined()) {
// We own the JS object
- return ddata->jsWrapper.value().asReturnedValue();
+ return ddata->jsWrapper.value();
} else if (ddata->jsWrapper.isUndefined() &&
(ddata->jsEngineId == engine->m_engineId || // We own the QObject
ddata->jsEngineId == 0 || // No one owns the QObject
@@ -614,7 +618,7 @@ void QObjectWrapper::put(Managed *m, const StringRef name, const ValueRef value)
return;
QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
- if (!setQmlProperty(v4->current, qmlContext, that->m_object, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, *value)) {
+ if (!setQmlProperty(v4->current, qmlContext, that->m_object, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, value)) {
QString error = QLatin1String("Cannot assign to non-existent property \"") +
name->toQString() + QLatin1Char('\"');
v4->current->throwError(error);
@@ -697,13 +701,14 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
int argCount = argsTypes ? argsTypes[0]:0;
- QV4::FunctionObject *f = This->function.value().asFunctionObject();
- QV4::ExecutionEngine *v4 = f->internalClass->engine;
+ QV4::ExecutionEngine *v4 = This->function.engine();
+ Q_ASSERT(v4);
+ QV4::Scope scope(v4);
+ QV4::ScopedFunctionObject f(scope, This->function.value());
QV4::ExecutionContext *ctx = v4->current;
- Scope scope(v4);
QV4::ScopedCallData callData(scope, argCount);
- callData->thisObject = This->thisObject.isUndefined() ? Value::fromObject(v4->globalObject) : This->thisObject.value();
+ callData->thisObject = This->thisObject.isUndefined() ? Value::fromObject(v4->globalObject) : Value::fromReturnedValue(This->thisObject.value());
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
@@ -752,7 +757,8 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
if (connection->thisObject.isUndefined() == thisObject->isUndefined() &&
(connection->thisObject.isUndefined() || __qmljs_strict_equal(connection->thisObject, thisObject))) {
- QPair<QObject *, int> connectedFunctionData = extractQtMethod(connection->function.value().asFunctionObject());
+ QV4::ScopedFunctionObject f(scope, connection->function.value());
+ QPair<QObject *, int> connectedFunctionData = extractQtMethod(f.getPointer());
if (connectedFunctionData.first == receiverToDisconnect &&
connectedFunctionData.second == slotIndexToDisconnect) {
*ret = true;
@@ -798,22 +804,29 @@ ReturnedValue QObjectWrapper::method_connect(SimpleCallContext *ctx)
if (signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
V4THROW_ERROR("Function.prototype.connect: this object is not a signal");
- QV4::QObjectSlotDispatcher *slot = new QV4::QObjectSlotDispatcher;
- slot->signalIndex = signalIndex;
+ QV4::Scope scope(ctx);
+ QV4::ScopedFunctionObject f(scope);
+ QV4::ScopedValue thisObject (scope, QV4::Encode::undefined());
if (ctx->argumentCount == 1) {
- slot->function = ctx->arguments[0];
+ f = ctx->arguments[0];
} else if (ctx->argumentCount >= 2) {
- slot->thisObject = ctx->arguments[0];
- slot->function = ctx->arguments[1];
+ thisObject = ctx->arguments[0];
+ f = ctx->arguments[1];
}
- if (!slot->function.value().asFunctionObject())
+ if (!f)
V4THROW_ERROR("Function.prototype.connect: target is not a function");
- if (!slot->thisObject.isUndefined() && !slot->thisObject.value().isObject())
+ if (!thisObject->isUndefined() && !thisObject->isObject())
V4THROW_ERROR("Function.prototype.connect: target this is not an object");
+ QV4::QObjectSlotDispatcher *slot = new QV4::QObjectSlotDispatcher;
+ slot->signalIndex = signalIndex;
+
+ slot->thisObject = thisObject;
+ slot->function = f;
+
QObjectPrivate::connect(signalObject, signalIndex, slot, Qt::AutoConnection);
return Encode::undefined();
@@ -1483,7 +1496,10 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::Value &
if (type != 0) { cleanup(); type = 0; }
if (callType == qMetaTypeId<QJSValue>()) {
- qjsValuePtr = new (&allocData) QJSValue(new QJSValuePrivate(QV8Engine::getV4(engine), value));
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
+ QV4::Scope scope(v4);
+ QV4::ScopedValue v(scope, value);
+ qjsValuePtr = new (&allocData) QJSValue(new QJSValuePrivate(v4, v));
type = qMetaTypeId<QJSValue>();
} else if (callType == QMetaType::Int) {
intValue = quint32(value.toInt32());
@@ -1647,10 +1663,10 @@ QObjectMethod::QObjectMethod(ExecutionContext *scope, QObject *object, int index
: FunctionObject(scope)
, m_object(object)
, m_index(index)
- , m_qmlGlobal(qmlGlobal)
{
vtbl = &static_vtbl;
subtype = WrappedQtMethod;
+ m_qmlGlobal = qmlGlobal.asReturnedValue();
}
QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
@@ -1719,6 +1735,8 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
return Encode::undefined();
QV8Engine *v8Engine = context->engine->v8Engine;
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8Engine);
+ QV4::Scope scope(v4);
QQmlPropertyData method;
@@ -1741,8 +1759,9 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
if (method.isV4Function()) {
QV4::Value rv = QV4::Value::undefinedValue();
- QQmlV4Function func(callData->argc, callData->args, &rv, m_qmlGlobal.value(),
- QmlContextWrapper::getContext(m_qmlGlobal.value()),
+ QV4::ScopedValue qmlGlobal(scope, m_qmlGlobal.value());
+ QQmlV4Function func(callData->argc, callData->args, &rv, qmlGlobal,
+ QmlContextWrapper::getContext(qmlGlobal),
v8Engine);
QQmlV4Function *funcptr = &func;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 2fc0767bc8..ea2dccccbc 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -88,7 +88,7 @@ struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
static ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
- static bool setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
+ static bool setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const ValueRef value);
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object);
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 09851af091..f11a982b65 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -439,6 +439,10 @@ struct Referenced {
Referenced(const Scoped<T> &v)
: ptr(v.ptr) {}
Referenced(Safe<T> &v) { ptr = &v; }
+ Referenced(SafeValue &v) {
+ ptr = value_cast<T>(v) ? &v : 0;
+ }
+
Referenced &operator=(const Referenced &o)
{ *ptr = *o.ptr; return *this; }
Referenced &operator=(T *t)
@@ -465,7 +469,7 @@ struct Referenced {
T *getPointer() const {
return static_cast<T *>(ptr->managed());
}
- ReturnedValue asReturnedValue() const { return ptr->val; }
+ ReturnedValue asReturnedValue() const { return ptr ? ptr->val : Value::undefinedValue().asReturnedValue(); }
static Referenced null() { return Referenced(Null); }
bool isNull() const { return !ptr; }
@@ -643,7 +647,7 @@ PersistentValue::PersistentValue(Returned<T> *obj)
}
template<typename T>
-inline PersistentValue::PersistentValue(const Scoped<T> &obj)
+inline PersistentValue::PersistentValue(const Referenced<T> obj)
: d(new PersistentValuePrivate(*obj.ptr))
{
}
@@ -655,7 +659,7 @@ inline PersistentValue &PersistentValue::operator=(Returned<T> *obj)
}
template<typename T>
-inline PersistentValue &PersistentValue::operator=(const Scoped<T> &obj)
+inline PersistentValue &PersistentValue::operator=(const Referenced<T> obj)
{
return operator=(*obj.ptr);
}
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index 1aa9d80a2d..a6cb40fff8 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -201,7 +201,8 @@ void Script::parse()
isel->setUseFastLookups(false);
QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile();
vmFunction = compilationUnit->linkToEngine(v4);
- compilationUnitHolder = Value::fromObject(new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit));
+ ScopedValue holder(valueScope, Value::fromObject(new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)));
+ compilationUnitHolder = holder;
}
if (!vmFunction) {
@@ -256,7 +257,8 @@ ReturnedValue Script::run()
return result.asReturnedValue();
} else {
- FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qml.value().asObject());
+ ScopedObject qmlObj(valueScope, qml.value());
+ FunctionObject *f = new (engine->memoryManager) QmlBindingWrapper(scope, vmFunction, qmlObj.getPointer());
ScopedCallData callData(valueScope, 0);
callData->thisObject = Value::undefinedValue();
return f->call(callData);
@@ -274,11 +276,13 @@ ReturnedValue Script::qmlBinding()
{
if (!parsed)
parse();
- QV4::ExecutionEngine *v4 = scope->engine;
- return Value::fromObject(new (v4->memoryManager) QmlBindingWrapper(scope, vmFunction, qml.value().asObject())).asReturnedValue();
+ ExecutionEngine *v4 = scope->engine;
+ Scope valueScope(v4);
+ ScopedObject qmlObj(valueScope, qml.value());
+ return Value::fromObject(new (v4->memoryManager) QmlBindingWrapper(scope, vmFunction, qmlObj.getPointer())).asReturnedValue();
}
-QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject)
+QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &script, ObjectRef scopeObject)
{
QV4::Scope scope(engine);
QV4::Script qmlScript(engine, scopeObject, script, QString());
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 752cb2ac53..030622cf72 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -73,10 +73,10 @@ struct Q_QML_EXPORT Script {
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(scope), strictMode(false), inheritContext(false), parsed(false)
, vmFunction(0), parseAsBinding(false) {}
- Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
+ Script(ExecutionEngine *engine, ObjectRef qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
, scope(engine->rootContext), strictMode(false), inheritContext(true), parsed(false)
- , qml(Value::fromObject(qml)), vmFunction(0), parseAsBinding(true) {}
+ , qml(qml.asReturnedValue()), vmFunction(0), parseAsBinding(true) {}
~Script();
QString sourceFile;
int line;
@@ -98,7 +98,7 @@ struct Q_QML_EXPORT Script {
Function *function();
- static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject);
+ static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, ObjectRef scopeObject);
};
}
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 197b1c2ee5..51f7fba6d3 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -285,18 +285,13 @@ Object *Value::toObject(ExecutionContext *ctx) const
}
-PersistentValue::PersistentValue(const Value &val)
- : d(new PersistentValuePrivate(val))
-{
-}
-
-PersistentValue::PersistentValue(const ScopedValue &val)
- : d(new PersistentValuePrivate(*val.operator ->()))
+PersistentValue::PersistentValue(const ValueRef val)
+ : d(new PersistentValuePrivate(val.asReturnedValue()))
{
}
PersistentValue::PersistentValue(ReturnedValue val)
- : d(new PersistentValuePrivate(Value::fromReturnedValue(val)))
+ : d(new PersistentValuePrivate(val))
{
}
@@ -323,33 +318,23 @@ PersistentValue &PersistentValue::operator=(const PersistentValue &other)
return *this;
}
-PersistentValue &PersistentValue::operator =(const Value &other)
+PersistentValue &PersistentValue::operator =(const ValueRef other)
{
if (!d) {
- d = new PersistentValuePrivate(other);
+ d = new PersistentValuePrivate(other.asReturnedValue());
return *this;
}
- d = d->detach(other);
+ d = d->detach(other.asReturnedValue());
return *this;
}
-PersistentValue &PersistentValue::operator =(const ScopedValue &other)
-{
- return operator=(*other.operator ->());
-}
-
-PersistentValue &PersistentValue::operator =(const ValueRef other)
-{
- return operator=(*other.operator ->());
-}
-
-PersistentValue &PersistentValue::operator =(const ReturnedValue &other)
+PersistentValue &PersistentValue::operator =(ReturnedValue other)
{
if (!d) {
- d = new PersistentValuePrivate(Value::fromReturnedValue(other));
+ d = new PersistentValuePrivate(other);
return *this;
}
- d = d->detach(Value::fromReturnedValue(other));
+ d = d->detach(other);
return *this;
}
@@ -359,8 +344,8 @@ PersistentValue::~PersistentValue()
d->deref();
}
-WeakValue::WeakValue(const Value &val)
- : d(new PersistentValuePrivate(val, /*engine*/0, /*weak*/true))
+WeakValue::WeakValue(const ValueRef val)
+ : d(new PersistentValuePrivate(val.asReturnedValue(), /*engine*/0, /*weak*/true))
{
}
@@ -372,7 +357,7 @@ WeakValue::WeakValue(const WeakValue &other)
}
WeakValue::WeakValue(ReturnedValue val)
- : d(new PersistentValuePrivate(Value::fromReturnedValue(val), /*engine*/0, /*weak*/true))
+ : d(new PersistentValuePrivate(val, /*engine*/0, /*weak*/true))
{
}
@@ -392,23 +377,23 @@ WeakValue &WeakValue::operator=(const WeakValue &other)
return *this;
}
-WeakValue &WeakValue::operator =(const Value &other)
+WeakValue &WeakValue::operator =(const ValueRef other)
{
if (!d) {
- d = new PersistentValuePrivate(other, /*engine*/0, /*weak*/true);
+ d = new PersistentValuePrivate(other.asReturnedValue(), /*engine*/0, /*weak*/true);
return *this;
}
- d = d->detach(other, /*weak*/true);
+ d = d->detach(other.asReturnedValue(), /*weak*/true);
return *this;
}
WeakValue &WeakValue::operator =(const ReturnedValue &other)
{
if (!d) {
- d = new PersistentValuePrivate(Value::fromReturnedValue(other), /*engine*/0, /*weak*/true);
+ d = new PersistentValuePrivate(other, /*engine*/0, /*weak*/true);
return *this;
}
- d = d->detach(Value::fromReturnedValue(other), /*weak*/true);
+ d = d->detach(other, /*weak*/true);
return *this;
}
@@ -429,21 +414,27 @@ void WeakValue::markOnce()
m->mark();
}
-PersistentValuePrivate::PersistentValuePrivate(const Value &v, ExecutionEngine *e, bool weak)
- : value(v)
- , refcount(1)
+PersistentValuePrivate::PersistentValuePrivate(ReturnedValue v, ExecutionEngine *e, bool weak)
+ : refcount(1)
+ , weak(weak)
+ , engine(e)
, prev(0)
, next(0)
- , engine(e)
+{
+ value.val = v;
+ init();
+}
+
+void PersistentValuePrivate::init()
{
if (!engine) {
- Managed *m = v.asManaged();
+ Managed *m = value.asManaged();
if (!m)
return;
engine = m->engine();
}
- if (engine) {
+ if (engine && !prev) {
PersistentValuePrivate **listRoot = weak ? &engine->memoryManager->m_weakValues : &engine->memoryManager->m_persistentValues;
prev = listRoot;
@@ -479,10 +470,10 @@ void PersistentValuePrivate::deref()
}
}
-PersistentValuePrivate *PersistentValuePrivate::detach(const QV4::Value &value, bool weak)
+PersistentValuePrivate *PersistentValuePrivate::detach(const QV4::ReturnedValue val, bool weak)
{
if (refcount == 1) {
- this->value = value;
+ value.val = val;
Managed *m = value.asManaged();
if (!prev) {
@@ -503,6 +494,6 @@ PersistentValuePrivate *PersistentValuePrivate::detach(const QV4::Value &value,
return this;
}
--refcount;
- return new PersistentValuePrivate(value, engine, weak);
+ return new PersistentValuePrivate(val, engine, weak);
}
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index ad884b6380..598d30f1f0 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -346,18 +346,20 @@ inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m
struct Q_QML_PRIVATE_EXPORT PersistentValuePrivate
{
- PersistentValuePrivate(const Value &v, ExecutionEngine *engine = 0, bool weak = false);
+ PersistentValuePrivate(ReturnedValue v, ExecutionEngine *engine = 0, bool weak = false);
virtual ~PersistentValuePrivate();
Value value;
uint refcount;
+ bool weak;
QV4::ExecutionEngine *engine;
PersistentValuePrivate **prev;
PersistentValuePrivate *next;
+ void init();
void removeFromList();
void ref() { ++refcount; }
void deref();
- PersistentValuePrivate *detach(const QV4::Value &value, bool weak = false);
+ PersistentValuePrivate *detach(const ReturnedValue value, bool weak = false);
bool checkEngine(QV4::ExecutionEngine *otherEngine) {
if (!engine) {
@@ -372,39 +374,36 @@ class Q_QML_EXPORT PersistentValue
{
public:
PersistentValue() : d(0) {}
+ PersistentValue(const PersistentValue &other);
+ PersistentValue &operator=(const PersistentValue &other);
- PersistentValue(const Value &val);
- PersistentValue(const ScopedValue &val);
+ PersistentValue(const ValueRef val);
PersistentValue(ReturnedValue val);
template<typename T>
PersistentValue(Returned<T> *obj);
template<typename T>
- PersistentValue(const Scoped<T> &obj);
- PersistentValue(const PersistentValue &other);
- PersistentValue &operator=(const PersistentValue &other);
- PersistentValue &operator=(const Value &other);
- PersistentValue &operator=(const ScopedValue &other);
+ PersistentValue(const Referenced<T> obj);
PersistentValue &operator=(const ValueRef other);
- PersistentValue &operator =(const ReturnedValue &other);
+ PersistentValue &operator =(ReturnedValue other);
template<typename T>
PersistentValue &operator=(Returned<T> *obj);
template<typename T>
- PersistentValue &operator=(const Scoped<T> &obj);
+ PersistentValue &operator=(const Referenced<T> obj);
~PersistentValue();
- Value value() const {
- return d ? d->value : Value::undefinedValue();
+ ReturnedValue value() const {
+ return (d ? d->value : Value::undefinedValue()).asReturnedValue();
}
ExecutionEngine *engine() {
if (!d)
return 0;
+ if (d->engine)
+ return d->engine;
Managed *m = d->value.asManaged();
return m ? m->engine() : 0;
}
- operator Value() const { return value(); }
-
bool isUndefined() const { return !d || d->value.isUndefined(); }
bool isNullOrUndefined() const { return !d || d->value.isNullOrUndefined(); }
void clear() {
@@ -420,32 +419,32 @@ class Q_QML_EXPORT WeakValue
{
public:
WeakValue() : d(0) {}
- WeakValue(const Value &val);
+ WeakValue(const ValueRef val);
WeakValue(const WeakValue &other);
WeakValue(ReturnedValue val);
template<typename T>
WeakValue(Returned<T> *obj);
WeakValue &operator=(const WeakValue &other);
- WeakValue &operator=(const Value &other);
+ WeakValue &operator=(const ValueRef other);
WeakValue &operator =(const ReturnedValue &other);
template<typename T>
WeakValue &operator=(Returned<T> *obj);
~WeakValue();
- Value value() const {
- return d ? d->value : Value::undefinedValue();
+ ReturnedValue value() const {
+ return (d ? d->value : Value::undefinedValue()).asReturnedValue();
}
ExecutionEngine *engine() {
if (!d)
return 0;
+ if (d->engine)
+ return d->engine;
Managed *m = d->value.asManaged();
return m ? m->engine() : 0;
}
- operator Value() const { return value(); }
-
bool isUndefined() const { return !d || d->value.isUndefined(); }
bool isNullOrUndefined() const { return !d || d->value.isNullOrUndefined(); }
void clear() {