diff options
48 files changed, 425 insertions, 327 deletions
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 211809e59c..bac76b0657 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -297,7 +297,8 @@ static ReturnedValue qmlsqldatabase_executeSql(SimpleCallContext *ctx) } if (query.exec()) { QQmlSqlDatabaseWrapper *rows = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine); - rows->setPrototype(databaseData(engine)->rowsProto.value().asObject()); + QV4::ScopedObject p(scope, databaseData(engine)->rowsProto.value()); + rows->setPrototype(p.getPointer()); rows->type = QQmlSqlDatabaseWrapper::Rows; rows->database = db; rows->sqlQuery = query; @@ -344,7 +345,8 @@ static ReturnedValue qmlsqldatabase_changeVersion(SimpleCallContext *ctx) V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->version)); QQmlSqlDatabaseWrapper *w = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine); - w->setPrototype(databaseData(engine)->queryProto.value().asObject()); + QV4::ScopedObject p(scope, databaseData(engine)->queryProto.value()); + w->setPrototype(p.getPointer()); w->type = QQmlSqlDatabaseWrapper::Query; w->database = db; w->version = r->version; @@ -401,7 +403,8 @@ static ReturnedValue qmlsqldatabase_transaction_shared(SimpleCallContext *ctx, b QSqlDatabase db = r->database; QQmlSqlDatabaseWrapper *w = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine); - w->setPrototype(databaseData(engine)->queryProto.value().asObject()); + QV4::ScopedObject p(scope, databaseData(engine)->queryProto.value()); + w->setPrototype(p.getPointer()); w->type = QQmlSqlDatabaseWrapper::Query; w->database = db; w->version = r->version; @@ -684,7 +687,8 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args) } QQmlSqlDatabaseWrapper *db = new (ctx->engine->memoryManager) QQmlSqlDatabaseWrapper(engine); - db->setPrototype(databaseData(engine)->databaseProto.value().asObject()); + QV4::ScopedObject p(scope, databaseData(engine)->databaseProto.value()); + db->setPrototype(p.getPointer()); db->database = database; db->version = version; diff --git a/src/particles/qquickv4particledata.cpp b/src/particles/qquickv4particledata.cpp index 9f95edff3b..8cbe42bdd3 100644 --- a/src/particles/qquickv4particledata.cpp +++ b/src/particles/qquickv4particledata.cpp @@ -512,9 +512,11 @@ QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData QV8ParticleDataDeletable *d = particleV8Data(engine); QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); - QV4::Object *o = new (v4->memoryManager) QV4ParticleData(v4, datum); - o->setPrototype(d->proto.value().asObject()); - m_v4Value = QV4::Value::fromObject(o); + QV4::Scope scope(v4); + QV4::ScopedObject o(scope, new (v4->memoryManager) QV4ParticleData(v4, datum)); + QV4::ScopedObject p(scope, d->proto.value()); + o->setPrototype(p.getPointer()); + m_v4Value = o; } QQuickV4ParticleData::~QQuickV4ParticleData() @@ -523,7 +525,7 @@ QQuickV4ParticleData::~QQuickV4ParticleData() QQmlV4Handle QQuickV4ParticleData::v4Value() { - return QQmlV4Handle(m_v4Value); + return QQmlV4Handle(QV4::Value::fromReturnedValue(m_v4Value.value())); } QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlenginedebugservice.cpp b/src/qml/debugger/qqmlenginedebugservice.cpp index 2b013129ce..5f3db9fb65 100644 --- a/src/qml/debugger/qqmlenginedebugservice.cpp +++ b/src/qml/debugger/qqmlenginedebugservice.cpp @@ -742,8 +742,10 @@ bool QQmlEngineDebugService::setMethodBody(int objectId, const QString &method, Q_ASSERT(vmeMetaObject); // the fact we found the property above should guarentee this int lineNumber = vmeMetaObject->vmeMethodLineNumber(prop->coreIndex); - vmeMetaObject->setVmeMethod(prop->coreIndex, - QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->url.toString(), lineNumber)); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine(object)->handle()); + QV4::Scope scope(v4); + QV4::ScopedValue v(scope, QQmlExpressionPrivate::evalFunction(contextData, object, jsfunction, contextData->url.toString(), lineNumber)); + vmeMetaObject->setVmeMethod(prop->coreIndex, v); return true; } diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index f99463256e..59a6a14e81 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -286,7 +286,9 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in */ QJSValue QJSEngine::newObject() { - return new QJSValuePrivate(d->m_v4Engine->newObject()->getPointer()); + QV4::Scope scope(d->m_v4Engine); + QV4::ScopedValue v(scope, d->m_v4Engine->newObject()); + return new QJSValuePrivate(d->m_v4Engine, v); } /*! @@ -301,7 +303,7 @@ QJSValue QJSEngine::newArray(uint length) if (length < 0x1000) array->arrayReserve(length); array->setArrayLengthUnchecked(length); - return new QJSValuePrivate(d->m_v4Engine, array.asValue()); + return new QJSValuePrivate(d->m_v4Engine, array); } /*! @@ -346,7 +348,10 @@ QJSValue QJSEngine::newQObject(QObject *object) */ QJSValue QJSEngine::globalObject() const { - return new QJSValuePrivate(d->m_v4Engine->globalObject); + Q_D(const QJSEngine); + QV4::Scope scope(d->m_v4Engine); + QV4::ScopedValue v(scope, d->m_v4Engine->globalObject); + return new QJSValuePrivate(d->m_v4Engine, v); } /*! @@ -356,7 +361,9 @@ QJSValue QJSEngine::globalObject() const QJSValue QJSEngine::create(int type, const void *ptr) { Q_D(QJSEngine); - return new QJSValuePrivate(d->m_v4Engine, QV4::Value::fromReturnedValue(d->metaTypeToJS(type, ptr))); + QV4::Scope scope(d->m_v4Engine); + QV4::ScopedValue v(scope, d->metaTypeToJS(type, ptr)); + return new QJSValuePrivate(d->m_v4Engine, v); } /*! diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index 56a01a584d..9c06f403b5 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -149,7 +149,7 @@ using namespace QV4; Constructs a new QJSValue with a boolean \a value. */ QJSValue::QJSValue(bool value) - : d(new QJSValuePrivate(0, Value::fromBoolean(value))) + : d(new QJSValuePrivate(Encode(value))) { } @@ -162,7 +162,7 @@ QJSValue::QJSValue(QJSValuePrivate *dd) Constructs a new QJSValue with a number \a value. */ QJSValue::QJSValue(int value) - : d(new QJSValuePrivate(0, Value::fromInt32(value))) + : d(new QJSValuePrivate(Encode(value))) { } @@ -170,7 +170,7 @@ QJSValue::QJSValue(int value) Constructs a new QJSValue with a number \a value. */ QJSValue::QJSValue(uint value) - : d(new QJSValuePrivate(0, Value::fromUInt32(value))) + : d(new QJSValuePrivate(Encode(value))) { } @@ -178,7 +178,7 @@ QJSValue::QJSValue(uint value) Constructs a new QJSValue with a number \a value. */ QJSValue::QJSValue(double value) - : d(new QJSValuePrivate(0, Value::fromDouble(value))) + : d(new QJSValuePrivate(Encode(value))) { } @@ -194,7 +194,7 @@ QJSValue::QJSValue(const QString& value) Constructs a new QJSValue with a special \a value. */ QJSValue::QJSValue(SpecialValue value) - : d(new QJSValuePrivate(0, value == UndefinedValue ? Value::undefinedValue() : Value::nullValue())) + : d(new QJSValuePrivate(value == UndefinedValue ? Encode::undefined() : Encode::null())) { } @@ -673,7 +673,7 @@ QJSValue QJSValue::prototype() const Scoped<Object> p(scope, o->prototype()); if (!p) return QJSValue(NullValue); - return new QJSValuePrivate(o->internalClass->engine, p.asValue()); + return new QJSValuePrivate(o->internalClass->engine, p); } /*! diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h index a0dfa010ab..ec3f61ef20 100644 --- a/src/qml/jsapi/qjsvalue_p.h +++ b/src/qml/jsapi/qjsvalue_p.h @@ -69,19 +69,18 @@ QT_BEGIN_NAMESPACE class Q_QML_PRIVATE_EXPORT QJSValuePrivate : public QV4::PersistentValuePrivate { public: - QJSValuePrivate(QV4::ExecutionEngine *engine, const QV4::Value &v) - : PersistentValuePrivate(v, engine) + QJSValuePrivate(QV4::ExecutionEngine *engine, const QV4::ValueRef v) + : PersistentValuePrivate(v.asReturnedValue(), engine) + { + Q_ASSERT(!value.isEmpty()); + } + QJSValuePrivate(QV4::ReturnedValue v) + : PersistentValuePrivate(v) { Q_ASSERT(!value.isEmpty()); } - QJSValuePrivate(QV4::Object *o) - : PersistentValuePrivate(QV4::Value::fromObject(o)) - { } - QJSValuePrivate(QV4::String *s) - : PersistentValuePrivate(QV4::Value::fromString(s)) - { } QJSValuePrivate(const QString &s) - : PersistentValuePrivate(QV4::Value::undefinedValue()) + : PersistentValuePrivate(QV4::Encode::undefined()) , string(0, s) { value = QV4::Value::fromString(&string); 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() { diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index a5e281dc56..a388178952 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -178,7 +178,7 @@ QQmlBinding::QQmlBinding(const QString &str, QObject *obj, v4function = qmlBinding(ctxt, obj, str, url, m_lineNumber); } -QQmlBinding::QQmlBinding(const QV4::Value &functionPtr, QObject *obj, QQmlContextData *ctxt, +QQmlBinding::QQmlBinding(const QV4::ValueRef functionPtr, QObject *obj, QQmlContextData *ctxt, const QString &url, quint16 lineNumber, quint16 columnNumber) : QQmlJavaScriptExpression(&QQmlBinding_jsvtable), QQmlAbstractBinding(Binding), m_url(url), m_lineNumber(lineNumber), m_columnNumber(columnNumber) @@ -250,7 +250,8 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) bool isUndefined = false; - QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), v4function.value(), &isUndefined)); + QV4::ScopedValue f(scope, v4function.value()); + QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined)); trace.event("writing binding result"); @@ -291,7 +292,8 @@ QVariant QQmlBinding::evaluate() bool isUndefined = false; - QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), v4function.value(), &isUndefined)); + QV4::ScopedValue f(scope, v4function.value()); + QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined)); ep->dereferenceScarceResources(); diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index ea703e8d38..e872482373 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -84,7 +84,7 @@ public: QQmlBinding(const QString &, QObject *, QQmlContextData *); QQmlBinding(const QString &, QObject *, QQmlContextData *, const QString &url, quint16 lineNumber, quint16 columnNumber); - QQmlBinding(const QV4::Value &, QObject *, QQmlContextData *, + QQmlBinding(const QV4::ValueRef, QObject *, QQmlContextData *, const QString &url, quint16 lineNumber, quint16 columnNumber); void setTarget(const QQmlProperty &); diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index 3a0d58d87c..cc2edb7b19 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -86,7 +86,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, m_expression = expression; } -QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, const QV4::PersistentValue &function) +QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, const QV4::ValueRef &function) : QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable), m_v8function(function), m_line(-1), @@ -128,7 +128,9 @@ QString QQmlBoundSignalExpression::expression() const { if (m_expressionFunctionValid) { Q_ASSERT (context() && engine()); - return m_v8function.value().toQStringNoThrow(); + QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine()); + QV4::ScopedValue v(scope, m_v8function.value()); + return v->toQStringNoThrow(); } else { return m_expression; } @@ -144,6 +146,7 @@ void QQmlBoundSignalExpression::evaluate(void **a) return; QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine()); + QV4::Scope scope(ep->v4engine()); ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation. { @@ -181,7 +184,7 @@ void QQmlBoundSignalExpression::evaluate(void **a) m_v8function = evalFunction(context(), scopeObject(), expression, m_fileName, m_line, &m_v8qmlscope); - if (m_v8function.isUndefined() || m_v8function.value().isNull()) { + if (m_v8function.isNullOrUndefined()) { ep->dereferenceScarceResources(); return; // could not evaluate function. Not valid. } @@ -223,7 +226,8 @@ void QQmlBoundSignalExpression::evaluate(void **a) } } - QQmlJavaScriptExpression::evaluate(context(), m_v8function.value(), argCount, args, 0); + QV4::ScopedValue f(scope, m_v8function.value()); + QQmlJavaScriptExpression::evaluate(context(), f, argCount, args, 0); } ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete. } diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h index 86e3dc20ea..feb79d5484 100644 --- a/src/qml/qml/qqmlboundsignal_p.h +++ b/src/qml/qml/qqmlboundsignal_p.h @@ -76,7 +76,7 @@ public: const QString ¶meterString = QString()); QQmlBoundSignalExpression(QObject *target, int index, - QQmlContextData *ctxt, QObject *scope, const QV4::PersistentValue &function); + QQmlContextData *ctxt, QObject *scope, const QV4::ValueRef &function); // "inherited" from QQmlJavaScriptExpression. diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index cf3493a590..cfda595438 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1123,7 +1123,7 @@ public: QV8Engine *v8; QPointer<QObject> parent; QV4::Value valuemap; - QV4::Value qmlGlobal; + QV4::SafeValue qmlGlobal; QV4::Value m_statusChanged; protected: virtual void statusChanged(Status); @@ -1244,7 +1244,8 @@ void QQmlComponent::createObject(QQmlV4Function *args) if (!valuemap.isUndefined()) { QQmlComponentExtension *e = componentExtension(v8engine); - QV4::ScopedValue f(scope, QV4::Script::evaluate(v4engine, QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal().asObject())); + QV4::ScopedObject qmlglobal(scope, args->qmlGlobal()); + QV4::ScopedValue f(scope, QV4::Script::evaluate(v4engine, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlglobal)); Q_ASSERT(f->asFunctionObject()); QV4::ScopedCallData callData(scope, 2); callData->thisObject = QV4::Value::fromObject(v4engine->globalObject); @@ -1329,9 +1330,11 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) Q_ASSERT(d->engine); Q_UNUSED(d); Q_ASSERT(args); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(args->engine()); + QV4::Scope scope(v4); QObject *parent = 0; - QV4::Value valuemap = QV4::Value::undefinedValue(); + QV4::ScopedValue valuemap(scope, QV4::Value::undefinedValue()); QQmlIncubator::IncubationMode mode = QQmlIncubator::Asynchronous; if (args->length() >= 1) { @@ -1340,9 +1343,9 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) } if (args->length() >= 2) { - QV4::Value v = (*args)[1]; - if (v.isNull()) { - } else if (!v.asObject() || v.asArrayObject()) { + QV4::ScopedValue v(scope, (*args)[1]); + if (v->isNull()) { + } else if (!v->asObject() || v->asArrayObject()) { qmlInfo(this) << tr("createObject: value is not an object"); args->setReturnValue(QV4::Value::nullValue()); return; @@ -1361,27 +1364,27 @@ void QQmlComponent::incubateObject(QQmlV4Function *args) QQmlComponentExtension *e = componentExtension(args->engine()); - QV4::ExecutionEngine *v4 = QV8Engine::getV4(args->engine()); - QmlIncubatorObject *r = new (v4->memoryManager) QmlIncubatorObject(args->engine(), mode); - r->setPrototype(e->incubationProto.value().asObject()); + QV4::Scoped<QmlIncubatorObject> r(scope, new (v4->memoryManager) QmlIncubatorObject(args->engine(), mode)); + QV4::ScopedObject p(scope, e->incubationProto.value()); + r->setPrototype(p.getPointer()); - if (!valuemap.isUndefined()) { + if (!valuemap->isUndefined()) { r->valuemap = valuemap; r->qmlGlobal = args->qmlGlobal(); } r->parent = parent; - create(*r, creationContext()); + create(*r.getPointer(), creationContext()); if (r->status() == QQmlIncubator::Null) { args->setReturnValue(QV4::Value::nullValue()); } else { - args->setReturnValue(QV4::Value::fromObject(r)); + args->setReturnValue(r.asValue()); } } // XXX used by QSGLoader -void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate) +void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::ValueRef qmlGlobal, const QV4::Value &valuemap, QObject *toCreate) { QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); QV8Engine *v8engine = ep->v8engine(); @@ -1393,8 +1396,9 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu if (!valuemap.isUndefined()) { QQmlComponentExtension *e = componentExtension(v8engine); + QV4::ScopedObject qmlGlobalObj(scope, qmlGlobal); QV4::Scoped<QV4::FunctionObject> f(scope, QV4::Script::evaluate(QV8Engine::getV4(v8engine), - QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal.asObject())); + QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobalObj)); QV4::ScopedCallData callData(scope, 2); callData->thisObject = QV4::Value::fromObject(v4engine->globalObject); callData->args[0] = object; @@ -1490,7 +1494,7 @@ void QmlIncubatorObject::setInitialState(QObject *o) QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8); QV4::Scope scope(v4); - QV4::Scoped<QV4::FunctionObject> f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal.asObject())); + QV4::Scoped<QV4::FunctionObject> f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobal)); QV4::ScopedCallData callData(scope, 2); callData->thisObject = QV4::Value::fromObject(v4->globalObject); callData->args[0] = QV4::Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, o)); diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index 08e4dcea7d..f2f81c8ab2 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -91,7 +91,7 @@ public: QObject *beginCreate(QQmlContextData *); void completeCreate(); - void initializeObjectWithInitialProperties(const QV4::Value &qmlGlobal, const QV4::Value &valuemap, QObject *toCreate); + void initializeObjectWithInitialProperties(const QV4::ValueRef qmlGlobal, const QV4::Value &valuemap, QObject *toCreate); QQmlTypeData *typeData; virtual void typeDataReady(QQmlTypeData *); diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp index 425c19a090..46ff821fff 100644 --- a/src/qml/qml/qqmlcontextwrapper.cpp +++ b/src/qml/qml/qqmlcontextwrapper.cpp @@ -188,7 +188,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, const StringRef name, bool *has if (r.scriptIndex != -1) { int index = r.scriptIndex; if (index < context->importedScripts.count()) - return context->importedScripts.at(index).value().asReturnedValue(); + return context->importedScripts.at(index).value(); else return QV4::Value::undefinedValue().asReturnedValue(); } else if (r.type) { @@ -318,13 +318,13 @@ void QmlContextWrapper::put(Managed *m, const StringRef name, const ValueRef val // Search scope object if (scopeObject && - QV4::QObjectWrapper::setQmlProperty(v4->current, context, scopeObject, name.getPointer(), QV4::QObjectWrapper::CheckRevision, *value)) + QV4::QObjectWrapper::setQmlProperty(v4->current, context, scopeObject, name.getPointer(), QV4::QObjectWrapper::CheckRevision, value)) return; scopeObject = 0; // Search context object if (context->contextObject && - QV4::QObjectWrapper::setQmlProperty(v4->current, context, context->contextObject, name.getPointer(), QV4::QObjectWrapper::CheckRevision, *value)) + QV4::QObjectWrapper::setQmlProperty(v4->current, context, context->contextObject, name.getPointer(), QV4::QObjectWrapper::CheckRevision, value)) return; context = context->parent; diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 2e77d8257b..2f873936e3 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1654,7 +1654,7 @@ void QQmlData::destroyed(QObject *object) delete extendedData; // Dispose the handle. - jsWrapper = QV4::Value::undefinedValue(); + jsWrapper.clear(); if (ownMemory) delete this; diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 76214c17a4..cdb5813221 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -262,12 +262,17 @@ void QQmlExpression::setExpression(const QString &expression) // Must be called with a valid handle scope QV4::ReturnedValue QQmlExpressionPrivate::v4value(bool *isUndefined) { + Q_Q(QQmlExpression); + if (!expressionFunctionValid) { function = qmlBinding(context(), scopeObject(), expression, url, line, &qmlscope); expressionFunctionValid = true; } - return evaluate(context(), function.value(), isUndefined); + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(q->engine())->v4engine(); + QV4::Scope scope(v4); + QV4::ScopedValue f(scope, function.value()); + return evaluate(context(), f, isUndefined); } QVariant QQmlExpressionPrivate::value(bool *isUndefined) diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp index b1184729d0..e08e8eebb7 100644 --- a/src/qml/qml/qqmljavascriptexpression.cpp +++ b/src/qml/qml/qqmljavascriptexpression.cpp @@ -321,7 +321,7 @@ void QQmlJavaScriptExpression::exceptionToError(const QV4::Exception &e, QQmlErr } } -QV4::PersistentValue +QV4::ReturnedValue QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObject, const QString &code, const QString &filename, quint16 line, QV4::PersistentValue *qmlscope) @@ -333,8 +333,8 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje QV4::ExecutionContext *ctx = v4->current; QV4::Scope scope(v4); - QV4::Scoped<QV4::Object> qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(ep->v8engine(), ctxt, scopeObject)); - QV4::Script script(v4, qmlScopeObject.getPointer(), code, filename, line); + QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(ep->v8engine(), ctxt, scopeObject)); + QV4::Script script(v4, qmlScopeObject, code, filename, line); QV4::ScopedValue result(scope); try { script.parse(); @@ -351,14 +351,14 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje error.setUrl(QUrl::fromLocalFile(filename)); error.setObject(scopeObject); ep->warning(error); - return QV4::PersistentValue(); + return QV4::Encode::undefined(); } if (qmlscope) - *qmlscope = qmlScopeObject.asValue(); + *qmlscope = qmlScopeObject; return result.asReturnedValue(); } -QV4::PersistentValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, QObject *qmlScope, +QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, QObject *qmlScope, const QString &code, const QString &filename, quint16 line, QV4::PersistentValue *qmlscope) { @@ -369,8 +369,8 @@ QV4::PersistentValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, QV4::ExecutionContext *ctx = v4->current; QV4::Scope scope(v4); - QV4::ScopedValue qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(ep->v8engine(), ctxt, qmlScope)); - QV4::Script script(v4, qmlScopeObject->asObject(), code, filename, line); + QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(ep->v8engine(), ctxt, qmlScope)); + QV4::Script script(v4, qmlScopeObject, code, filename, line); QV4::ScopedValue result(scope); try { script.parse(); @@ -387,7 +387,7 @@ QV4::PersistentValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, error.setUrl(QUrl::fromLocalFile(filename)); error.setObject(qmlScope); ep->warning(error); - return QV4::PersistentValue(); + return QV4::Encode::undefined(); } if (qmlscope) *qmlscope = qmlScopeObject; diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h index f08b3af6cf..c13e191216 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -146,12 +146,12 @@ public: QQmlDelayedError *delayedError(); static void exceptionToError(const QV4::Exception &e, QQmlError &); - static QV4::PersistentValue evalFunction(QQmlContextData *ctxt, QObject *scope, + static QV4::ReturnedValue evalFunction(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line, QV4::PersistentValue *qmlscope = 0); // doesn't require rewriting the expression - static QV4::PersistentValue qmlBinding(QQmlContextData *ctxt, QObject *scope, + static QV4::ReturnedValue qmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line, QV4::PersistentValue *qmlscope = 0); diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index c3c7d0282d..db949467d1 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -835,11 +835,13 @@ QV4::ReturnedValue QQmlLocale::locale(QV8Engine *v8engine, const QString &locale { QV8LocaleDataDeletable *d = localeV8Data(v8engine); QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine); - QQmlLocaleData *wrapper = new (engine->memoryManager) QQmlLocaleData(engine); + QV4::Scope scope(engine); + QV4::Scoped<QQmlLocaleData> wrapper(scope, new (engine->memoryManager) QQmlLocaleData(engine)); if (!locale.isEmpty()) wrapper->locale = QLocale(locale); - wrapper->setPrototype(d->prototype.value().asObject()); - return QV4::Value::fromObject(wrapper).asReturnedValue(); + QV4::ScopedObject p(scope, d->prototype.value()); + wrapper->setPrototype(p.getPointer()); + return wrapper.asReturnedValue(); } void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine) diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 601f4dbba0..2f4e782069 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1080,7 +1080,9 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI if (binding->type == QV4::CompiledData::Binding::Type_Script) { QV4::Function *runtimeFunction = jsUnit->runtimeFunctions[binding->value.compiledScriptIndex]; - QV4::Value function = QV4::Value::fromObject(QV4::FunctionObject::creatScriptFunction(_qmlContext, runtimeFunction)); + + QV4::Scope scope(_qmlContext); + QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::creatScriptFunction(_qmlContext, runtimeFunction)); if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) { int signalIndex = _propertyCache->methodIndexToSignalIndex(property->coreIndex); @@ -1194,6 +1196,8 @@ bool QmlObjectCreator::setPropertyValue(QQmlPropertyData *property, int bindingI void QmlObjectCreator::setupFunctions() { + QV4::Scope scope(_qmlContext); + QV4::ScopedValue function(scope); QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(_qobject); const quint32 *functionIdx = _compiledObject->functionOffsetTable(); @@ -1205,8 +1209,8 @@ void QmlObjectCreator::setupFunctions() if (!property->isVMEFunction()) continue; - QV4::FunctionObject *function = QV4::FunctionObject::creatScriptFunction(_qmlContext, runtimeFunction); - vme->setVmeMethod(property->coreIndex, QV4::Value::fromObject(function)); + function = QV4::FunctionObject::creatScriptFunction(_qmlContext, runtimeFunction); + vme->setVmeMethod(property->coreIndex, function); } } diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index f821687f63..bcecda9c57 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -1460,7 +1460,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, const QQmlPropertyData &core, QQmlContextData *context, QQmlJavaScriptExpression *expression, - const QV4::Value &result, bool isUndefined, + const QV4::ValueRef result, bool isUndefined, WriteFlags flags) { Q_ASSERT(object); @@ -1482,22 +1482,22 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, if (!isUndefined && !core.isValueTypeVirtual()) { switch (core.propType) { case QMetaType::Int: - if (result.isInteger()) - QUICK_STORE(int, result.integerValue()) - else if (result.isNumber()) - QUICK_STORE(int, qRound(result.doubleValue())) + if (result->isInteger()) + QUICK_STORE(int, result->integerValue()) + else if (result->isNumber()) + QUICK_STORE(int, qRound(result->doubleValue())) break; case QMetaType::Double: - if (result.isNumber()) - QUICK_STORE(double, result.asDouble()) + if (result->isNumber()) + QUICK_STORE(double, result->asDouble()) break; case QMetaType::Float: - if (result.isNumber()) - QUICK_STORE(float, result.asDouble()) + if (result->isNumber()) + QUICK_STORE(float, result->asDouble()) break; case QMetaType::QString: - if (result.isString()) - QUICK_STORE(QString, result.toQStringNoThrow()) + if (result->isString()) + QUICK_STORE(QString, result->toQStringNoThrow()) break; default: break; @@ -1514,19 +1514,19 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, if (isUndefined) { } else if (core.isQList()) { - value = v8engine->toVariant(result, qMetaTypeId<QList<QObject *> >()); - } else if (result.isNull() && core.isQObject()) { + 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()) { return false; } else if (isVarProperty) { - QV4::FunctionObject *f = result.asFunctionObject(); + QV4::FunctionObject *f = result->asFunctionObject(); if (f && f->bindingKeyFlag) { // we explicitly disallow this case to avoid confusion. Users can still store one // in an array in a var property if they need to, but the common case is user error. @@ -1537,14 +1537,14 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object); Q_ASSERT(vmemo); - vmemo->setVMEProperty(core.coreIndex, result); + vmemo->setVMEProperty(core.coreIndex, *result); } else if (isUndefined && core.isResettable()) { void *args[] = { 0 }; QMetaObject::metacall(object, QMetaObject::ResetProperty, core.coreIndex, args); } else if (isUndefined && type == qMetaTypeId<QVariant>()) { writeValueProperty(object, core, QVariant(), context, flags); } else if (type == qMetaTypeId<QJSValue>()) { - QV4::FunctionObject *f = result.asFunctionObject(); + QV4::FunctionObject *f = result->asFunctionObject(); if (f && f->bindingKeyFlag) { expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration.")); expression->delayedError()->setErrorObject(object); @@ -1562,7 +1562,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object, expression->delayedError()->setErrorDescription(errorStr); expression->delayedError()->setErrorObject(object); return false; - } else if (QV4::FunctionObject *f = result.asFunctionObject()) { + } else if (QV4::FunctionObject *f = result->asFunctionObject()) { if (f->bindingKeyFlag) expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration.")); else diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h index 9af091ad46..ce15061ba0 100644 --- a/src/qml/qml/qqmlproperty_p.h +++ b/src/qml/qml/qqmlproperty_p.h @@ -148,7 +148,7 @@ public: static bool writeBinding(QObject *, const QQmlPropertyData &, QQmlContextData *context, QQmlJavaScriptExpression *expression, - const QV4::Value &result, bool isUndefined, + const QV4::ValueRef result, bool isUndefined, WriteFlags flags); static int valueTypeCoreIndex(const QQmlProperty &that); static int bindingIndex(const QQmlProperty &that); diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index d5c0ed058c..13dad049c8 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -160,9 +160,8 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasPro // check for property. return QV4::QObjectWrapper::getQmlProperty(v4->current, context, qobjectSingleton, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, hasProperty); } else if (!siinfo->scriptApi(e).isUndefined()) { - QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine); // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable. - QV4::Scoped<Object> o(scope, QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(engine)); + QV4::ScopedObject o(scope, QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(v4)); if (!!o) return o->get(name); } @@ -203,7 +202,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, const StringRef name, bool *hasPro } else if (r.scriptIndex != -1) { int index = r.scriptIndex; if (index < context->importedScripts.count()) - return context->importedScripts.at(index).value().asReturnedValue(); + return context->importedScripts.at(index).value(); } else if (r.importNamespace) { return create(w->v8, object, context->imports, r.importNamespace); } @@ -231,6 +230,7 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value) if (!w) v4->current->throwTypeError(); + QV4::Scope scope(v4); QV8Engine *v8engine = v4->v8Engine; QQmlContextData *context = v8engine->callingContext(); @@ -239,7 +239,7 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value) QObject *object = w->object; QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object); if (ao) - QV4::QObjectWrapper::setQmlProperty(v4->current, context, ao, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, *value); + QV4::QObjectWrapper::setQmlProperty(v4->current, context, ao, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, value); } else if (type && type->isSingleton()) { QQmlEngine *e = v8engine->engine(); QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo(); @@ -247,9 +247,9 @@ void QmlTypeWrapper::put(Managed *m, const StringRef name, const ValueRef value) QObject *qobjectSingleton = siinfo->qobjectApi(e); if (qobjectSingleton) { - QV4::QObjectWrapper::setQmlProperty(v4->current, context, qobjectSingleton, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, *value); + QV4::QObjectWrapper::setQmlProperty(v4->current, context, qobjectSingleton, name.getPointer(), QV4::QObjectWrapper::IgnoreRevision, value); } else if (!siinfo->scriptApi(e).isUndefined()) { - QV4::Object *apiprivate = QJSValuePrivate::get(siinfo->scriptApi(e))->value.asObject(); + QV4::ScopedObject apiprivate(scope, QJSValuePrivate::get(siinfo->scriptApi(e))->value); if (!apiprivate) { QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"'); v4->current->throwError(error); diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index b27d99793f..f1d2f3a85c 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -372,7 +372,7 @@ void QmlValueTypeWrapper::put(Managed *m, const StringRef name, const ValueRef v QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame(); - newBinding = new QQmlBinding(*value, reference->object, context, + newBinding = new QQmlBinding(value, reference->object, context, frame.source, qmlSourceCoordinate(frame.line), qmlSourceCoordinate(frame.column)); newBinding->setTarget(reference->object, cacheData, context); newBinding->setEvaluateFlags(newBinding->evaluateFlags() | diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 1a6577d7ad..3b88e148c7 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -1087,7 +1087,7 @@ void QQmlScriptData::initialize(QQmlEngine *engine) // If compilation throws an error, a surrounding catch will record it. // pass 0 as the QML object, we set it later before calling run() - QV4::Script *program = new QV4::Script(v4, 0, m_programSource, urlString, 1); + QV4::Script *program = new QV4::Script(v4, QV4::ObjectRef::null(), m_programSource, urlString, 1); try { program->parse(); } catch (QV4::Exception &) { diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index d70df5175b..18f3dff39d 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -76,7 +76,7 @@ void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *) QV4::ExecutionEngine *v4 = m_target->varProperties.engine(); if (v4) { QV4::Scope scope(v4); - QV4::ScopedArrayObject a(scope, m_target->varProperties.value().asArrayObject()); + QV4::ScopedArrayObject a(scope, m_target->varProperties.value()); if (a) a->putIndexed(m_index - m_target->firstVarPropertyIndex, QV4::ScopedValue(scope, QV4::Value::nullValue())); } @@ -989,24 +989,30 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index) ctxt->urlString, data->lineNumber); } - return v8methods[index].value().asReturnedValue(); + return v8methods[index].value(); } QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id) { Q_ASSERT(id >= firstVarPropertyIndex); - if (ensureVarPropertiesAllocated()) - return varProperties.value().asObject()->getIndexed(id - firstVarPropertyIndex); + if (ensureVarPropertiesAllocated()) { + QV4::Scope scope(QQmlEnginePrivate::get(ctxt->engine)->v4engine()); + QV4::ScopedObject o(scope, varProperties.value()); + return o->getIndexed(id - firstVarPropertyIndex); + } return QV4::Value::undefinedValue().asReturnedValue(); } QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id) { if (id >= firstVarPropertyIndex) { - if (ensureVarPropertiesAllocated()) + 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(varProperties.value().asObject()->getIndexed(id - firstVarPropertyIndex)), -1); + QV4::Value::fromReturnedValue(o->getIndexed(id - firstVarPropertyIndex)), -1); + } return QVariant(); } else { if (data[id].dataType() == QMetaType::QObjectStar) { @@ -1026,7 +1032,8 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) QV4::Scope scope(varProperties.engine()); // Importantly, if the current value is a scarce resource, we need to ensure that it // gets automatically released by the engine if no other references to it exist. - QV4::Scoped<QV4::VariantObject> oldv(scope, varProperties.value().asObject()->getIndexed(id - firstVarPropertyIndex)); + QV4::ScopedObject vp(scope, varProperties.value()); + QV4::Scoped<QV4::VariantObject> oldv(scope, vp->getIndexed(id - firstVarPropertyIndex)); if (!!oldv) oldv->removeVmePropertyReference(); @@ -1057,7 +1064,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) } // Write the value and emit change signal as appropriate. - varProperties.value().asObject()->putIndexed(id - firstVarPropertyIndex, v); + vp->putIndexed(id - firstVarPropertyIndex, v); activate(object, methodOffset() + id, 0); } @@ -1071,7 +1078,8 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) // Importantly, if the current value is a scarce resource, we need to ensure that it // gets automatically released by the engine if no other references to it exist. - QV4::Scoped<QV4::VariantObject> oldv(scope, varProperties.value().asObject()->getIndexed(id - firstVarPropertyIndex)); + QV4::ScopedObject vp(scope, varProperties.value()); + QV4::Scoped<QV4::VariantObject> oldv(scope, vp->getIndexed(id - firstVarPropertyIndex)); if (!!oldv) oldv->removeVmePropertyReference(); @@ -1083,7 +1091,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) // Write the value and emit change signal as appropriate. QVariant currentValue = readPropertyAsVariant(id); - varProperties.value().asObject()->putIndexed(id - firstVarPropertyIndex, newv); + vp->putIndexed(id - firstVarPropertyIndex, newv); if ((currentValue.userType() != value.userType() || currentValue != value)) activate(object, methodOffset() + id, 0); } else { @@ -1169,7 +1177,7 @@ QV4::ReturnedValue QQmlVMEMetaObject::vmeMethod(int index) } // Used by debugger -void QQmlVMEMetaObject::setVmeMethod(int index, QV4::PersistentValue function) +void QQmlVMEMetaObject::setVmeMethod(int index, QV4::ValueRef function) { if (index < methodOffset()) { Q_ASSERT(parentVMEMetaObject()); diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 35592c4906..c9babc0492 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -166,7 +166,7 @@ public: void registerInterceptor(int index, int valueIndex, QQmlPropertyValueInterceptor *interceptor); QV4::ReturnedValue vmeMethod(int index); quint16 vmeMethodLineNumber(int index); - void setVmeMethod(int index, QV4::PersistentValue function); + void setVmeMethod(int index, QV4::ValueRef function); QV4::ReturnedValue vmeProperty(int index); void setVMEProperty(int index, const QV4::Value &v); diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 48072f53c8..10d407a48d 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -579,13 +579,14 @@ ReturnedValue NodePrototype::method_get_attributes(SimpleCallContext *ctx) Value NodePrototype::getProto(ExecutionEngine *v4) { + Scope scope(v4); QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine); if (d->nodePrototype.isUndefined()) { - Object *p = new (v4->memoryManager) NodePrototype(v4); - d->nodePrototype = Value::fromObject(p); - v4->v8Engine->freezeObject(d->nodePrototype.value()); + ScopedObject p(scope, new (v4->memoryManager) NodePrototype(v4)); + d->nodePrototype = p; + v4->v8Engine->freezeObject(p.asValue()); } - return d->nodePrototype.value(); + return Value::fromReturnedValue(d->nodePrototype.value()); } Value Node::create(QV8Engine *engine, NodeImpl *data) @@ -631,9 +632,9 @@ Value Element::prototype(ExecutionEngine *engine) p->setPrototype(NodePrototype::getProto(engine).asObject()); p->defineAccessorProperty(QStringLiteral("tagName"), NodePrototype::method_get_nodeName, 0); d->elementPrototype = p; - engine->v8Engine->freezeObject(d->elementPrototype.value()); + engine->v8Engine->freezeObject(p.asValue()); } - return d->elementPrototype.value(); + return Value::fromReturnedValue(d->elementPrototype.value()); } Value Attr::prototype(ExecutionEngine *engine) @@ -647,9 +648,9 @@ Value Attr::prototype(ExecutionEngine *engine) p->defineAccessorProperty(QStringLiteral("value"), method_value, 0); p->defineAccessorProperty(QStringLiteral("ownerElement"), method_ownerElement, 0); d->attrPrototype = p; - engine->v8Engine->freezeObject(d->attrPrototype.value()); + engine->v8Engine->freezeObject(p.asValue()); } - return d->attrPrototype.value(); + return Value::fromReturnedValue(d->attrPrototype.value()); } ReturnedValue Attr::method_name(SimpleCallContext *ctx) @@ -702,9 +703,9 @@ Value CharacterData::prototype(ExecutionEngine *v4) p->defineAccessorProperty(QStringLiteral("data"), NodePrototype::method_get_nodeValue, 0); p->defineAccessorProperty(QStringLiteral("length"), method_length, 0); d->characterDataPrototype = p; - v4->v8Engine->freezeObject(d->characterDataPrototype); + v4->v8Engine->freezeObject(p.asValue()); } - return d->characterDataPrototype.value(); + return Value::fromReturnedValue(d->characterDataPrototype.value()); } ReturnedValue Text::method_isElementContentWhitespace(SimpleCallContext *ctx) @@ -735,9 +736,9 @@ Value Text::prototype(ExecutionEngine *v4) p->defineAccessorProperty(QStringLiteral("isElementContentWhitespace"), method_isElementContentWhitespace, 0); p->defineAccessorProperty(QStringLiteral("wholeText"), method_wholeText, 0); d->textPrototype = p; - v4->v8Engine->freezeObject(d->textPrototype); + v4->v8Engine->freezeObject(p.asValue()); } - return d->textPrototype.value(); + return Value::fromReturnedValue(d->textPrototype.value()); } Value CDATA::prototype(ExecutionEngine *v4) @@ -749,9 +750,9 @@ Value CDATA::prototype(ExecutionEngine *v4) Scoped<Object> p(scope, v4->newObject()); p->setPrototype(Text::prototype(v4).asObject()); d->cdataPrototype = p; - v4->v8Engine->freezeObject(d->cdataPrototype); + v4->v8Engine->freezeObject(p.asValue()); } - return d->cdataPrototype.value(); + return Value::fromReturnedValue(d->cdataPrototype.value()); } Value Document::prototype(ExecutionEngine *v4) @@ -766,9 +767,9 @@ Value Document::prototype(ExecutionEngine *v4) p->defineAccessorProperty(QStringLiteral("xmlStandalone"), method_xmlStandalone, 0); p->defineAccessorProperty(QStringLiteral("documentElement"), method_documentElement, 0); d->documentPrototype = p; - v4->v8Engine->freezeObject(d->documentPrototype); + v4->v8Engine->freezeObject(p.asValue()); } - return d->documentPrototype.value(); + return Value::fromReturnedValue(d->documentPrototype.value()); } ReturnedValue Document::load(QV8Engine *engine, const QByteArray &data) @@ -1284,7 +1285,7 @@ ReturnedValue QQmlXMLHttpRequest::abort(const ValueRef me) ReturnedValue QQmlXMLHttpRequest::getMe() const { - return m_me.value().asReturnedValue(); + return m_me.value(); } void QQmlXMLHttpRequest::setMe(const ValueRef me) diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index b62e2150af..e8c84eee35 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -120,6 +120,8 @@ QV8Engine::~QV8Engine() QVariant QV8Engine::toVariant(const QV4::Value &value, int typeHint) { Q_ASSERT (!value.isEmpty()); + QV4::Scope scope(m_v4Engine); + QV4::ScopedValue v(scope, value); if (QV4::VariantObject *v = value.as<QV4::VariantObject>()) return v->data; @@ -131,7 +133,7 @@ QVariant QV8Engine::toVariant(const QV4::Value &value, int typeHint) return QVariant::fromValue(QV4::JsonObject::toJsonValue(value)); if (typeHint == qMetaTypeId<QJSValue>()) - return QVariant::fromValue(QJSValue(new QJSValuePrivate(m_v4Engine, value))); + return QVariant::fromValue(QJSValue(new QJSValuePrivate(m_v4Engine, v))); if (QV4::Object *object = value.asObject()) { if (typeHint == QMetaType::QJsonObject @@ -450,9 +452,9 @@ void QV8Engine::initializeGlobal() " }"\ "})" - QV4::Scoped<QV4::FunctionObject> result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), 0)); + QV4::Scoped<QV4::FunctionObject> result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), QV4::ObjectRef::null())); Q_ASSERT(!!result); - m_freezeObject = result.asValue(); + m_freezeObject = result; #undef FREEZE_SOURCE } } @@ -460,10 +462,11 @@ void QV8Engine::initializeGlobal() void QV8Engine::freezeObject(const QV4::Value &value) { QV4::Scope scope(m_v4Engine); + QV4::ScopedFunctionObject f(scope, m_freezeObject.value()); QV4::ScopedCallData callData(scope, 1); callData->args[0] = value; callData->thisObject = QV4::Value::fromObject(m_v4Engine->globalObject); - m_freezeObject.value().asFunctionObject()->call(callData); + f->call(callData); } void QV8Engine::gc() @@ -709,6 +712,8 @@ QV4::ReturnedValue QV8Engine::metaTypeToJS(int type, const void *data) // 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) { + QV4::Scope scope(QV8Engine::getV4(this)); + // check if it's one of the types we know switch (QMetaType::Type(type)) { case QMetaType::Bool: @@ -871,7 +876,7 @@ bool QV8Engine::metaTypeFromJS(const QV4::Value &value, int type, void *data) { *reinterpret_cast<void* *>(data) = 0; return true; } else if (type == qMetaTypeId<QJSValue>()) { - *reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(m_v4Engine, value)); + *reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(m_v4Engine, QV4::ScopedValue(scope, value))); return true; } diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 0fa0c73ae0..97aa3ec628 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -2390,11 +2390,13 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index) model->m_cacheMetaType->initializePrototype(); QV8Engine *v8 = model->m_cacheMetaType->v8Engine; QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8); - QV4::Object *o = new (v4->memoryManager) QQmlDelegateModelItemObject(v4, cacheItem); - o->setPrototype(model->m_cacheMetaType->modelItemProto.value().asObject()); + QV4::Scope scope(v4); + QV4::ScopedObject o(scope, new (v4->memoryManager) QQmlDelegateModelItemObject(v4, cacheItem)); + QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value()); + o->setPrototype(p.getPointer()); ++cacheItem->scriptRef; - return QQmlV4Handle(QV4::Value::fromObject(o)); + return QQmlV4Handle(o.asValue()); } bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::Value &value, int *index, Compositor::Group *group) const @@ -3158,7 +3160,8 @@ public: static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty) { QV4::ExecutionEngine *v4 = m->engine(); - QQmlDelegateModelGroupChangeArray *array = m->as<QQmlDelegateModelGroupChangeArray>(); + QV4::Scope scope(v4); + QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, m->as<QQmlDelegateModelGroupChangeArray>()); if (!array) v4->current->throwTypeError(); @@ -3170,14 +3173,14 @@ public: const QQmlChangeSet::Change &change = array->at(index); - QV4::Object *changeProto = engineData(v4->v8Engine)->changeProto.value().asObject(); - QQmlDelegateModelGroupChange *object = new (v4->memoryManager) QQmlDelegateModelGroupChange(v4); - object->setPrototype(changeProto); + QV4::ScopedObject changeProto(scope, engineData(v4->v8Engine)->changeProto.value()); + QV4::Scoped<QQmlDelegateModelGroupChange> object(scope, new (v4->memoryManager) QQmlDelegateModelGroupChange(v4)); + object->setPrototype(changeProto.getPointer()); object->change = change; if (hasProperty) *hasProperty = true; - return QV4::Value::fromObject(object).asReturnedValue(); + return object.asReturnedValue(); } static QV4::ReturnedValue get(QV4::Managed *m, const QV4::StringRef name, bool *hasProperty) diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index ef23a34db8..b955555a82 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -244,9 +244,13 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() // Requires handle and context scope QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id) { - QV4::FunctionObject *f = createsend.value().asFunctionObject(); - QV4::ExecutionContext *ctx = f->engine()->current; - QV4::Scope scope(ctx->engine); + QV4::ExecutionEngine *v4 = createsend.engine(); + if (!v4) + return QV4::Encode::undefined(); + + QV4::Scope scope(v4); + QV4::ScopedFunctionObject f(scope, createsend.value()); + QV4::ExecutionContext *ctx = v4->current; QV4::ScopedValue v(scope); try { @@ -315,12 +319,12 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *scri QV4::Scoped<QV4::Object> api(scope, v4->newObject()); api->put(QV4::ScopedString(scope, v4->newString("sendMessage")), QV4::ScopedValue(scope, workerEngine->sendFunction(script->id))); - script->object.value().asObject()->put(QV4::ScopedString(scope, v4->newString("WorkerScript")), api); + w->QV4::Object::put(QV4::ScopedString(scope, v4->newString("WorkerScript")), api); w->setReadOnly(true); } - return script->object.value().asReturnedValue(); + return script->object.value(); } bool QQuickWorkerScriptEnginePrivate::event(QEvent *event) @@ -351,9 +355,10 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d if (!script) return; - QV4::FunctionObject *f = workerEngine->onmessage.value().asFunctionObject(); - QV4::ExecutionContext *ctx = f->internalClass->engine->current; - QV4::Scope scope(ctx); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine); + QV4::Scope scope(v4); + QV4::ScopedFunctionObject f(scope, workerEngine->onmessage.value()); + QV4::ExecutionContext *ctx = v4->current; QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, workerEngine)); @@ -396,7 +401,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) if (!activation) return; - QV4::Script program(v4, activation.getPointer(), sourceCode, url.toString()); + QV4::Script program(v4, activation, sourceCode, url.toString()); QV4::ExecutionContext *ctx = v4->current; try { diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp index 7351e696c6..c4ba42c84a 100644 --- a/src/qml/util/qqmladaptormodel.cpp +++ b/src/qml/util/qqmladaptormodel.cpp @@ -228,7 +228,7 @@ public: p->setGetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::get_property)); p->setSetter(new (v4->memoryManager) QV4::IndexedBuiltinFunction(v4->rootContext, propertyId, QQmlDMCachedModelData::set_property)); } - prototype = proto.asValue(); + prototype = proto; } // QAbstractDynamicMetaObject @@ -424,12 +424,12 @@ public: QQmlAdaptorModelEngineData * const data = engineData(v4->v8Engine); type->initializeConstructor(data); } - QV4::Object *proto = type->prototype.value().asObject(); - QV4::Object *o = new (proto->engine()->memoryManager) QQmlDelegateModelItemObject(proto->engine(), this); - o->setPrototype(proto); - QV4::Value data = QV4::Value::fromObject(o); + QV4::Scope scope(v4); + QV4::ScopedObject proto(scope, type->prototype.value()); + QV4::ScopedObject o(scope, new (proto->engine()->memoryManager) QQmlDelegateModelItemObject(proto->engine(), this)); + o->setPrototype(proto.getPointer()); ++scriptRef; - return data.asReturnedValue(); + return o.asReturnedValue(); } }; @@ -599,11 +599,12 @@ public: QV4::ReturnedValue get() { QQmlAdaptorModelEngineData *data = engineData(v4->v8Engine); - QV4::Object *o = new (v4->memoryManager) QQmlDelegateModelItemObject(v4, this); - o->setPrototype(data->listItemProto.value().asObject()); - QV4::Value val = QV4::Value::fromObject(o); + QV4::Scope scope(v4); + QV4::ScopedObject o(scope, new (v4->memoryManager) QQmlDelegateModelItemObject(v4, this)); + QV4::ScopedObject p(scope, data->listItemProto.value()); + o->setPrototype(p.getPointer()); ++scriptRef; - return val.asReturnedValue(); + return o.asReturnedValue(); } void setValue(const QString &role, const QVariant &value) diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index f21abdab67..78369eb404 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -666,7 +666,7 @@ void QQuickCanvasItem::updatePolish() callData->thisObject = QV4::Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, this)); foreach (int key, animationCallbacks.keys()) { - QV4::FunctionObject *f = animationCallbacks.value(key).value().asFunctionObject(); + QV4::ScopedFunctionObject f(scope, animationCallbacks.value(key).value()); callData->args[0] = QV4::Value::fromUInt32(QDateTime::currentDateTimeUtc().toTime_t()); f->call(callData); } @@ -789,7 +789,9 @@ void QQuickCanvasItem::requestAnimationFrame(QQmlV4Function *args) static int id = 0; - d->animationCallbacks.insert(++id, QV4::PersistentValue((*args)[0])); + QV4::Scope scope(QV8Engine::getV4(args->engine())); + QV4::ScopedValue v(scope, (*args)[0]); + d->animationCallbacks.insert(++id, QV4::PersistentValue(v)); if (isVisible()) polish(); diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 1930fb69c9..ea3bd77509 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -915,8 +915,10 @@ static QV4::Value qt_create_image_data(qreal w, qreal h, QV8Engine* engine, cons { QQuickContext2DEngineData *ed = engineData(engine); QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); - QQuickJSContext2DPixelData *pixelData = new (v4->memoryManager) QQuickJSContext2DPixelData(v4); - pixelData->setPrototype(ed->pixelArrayProto.value().asObject()); + QV4::Scope scope(v4); + QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, new (v4->memoryManager) QQuickJSContext2DPixelData(v4)); + QV4::ScopedObject p(scope, ed->pixelArrayProto.value()); + pixelData->setPrototype(p.getPointer()); if (image.isNull()) { pixelData->image = QImage(w, h, QImage::Format_ARGB32); @@ -927,7 +929,7 @@ static QV4::Value qt_create_image_data(qreal w, qreal h, QV8Engine* engine, cons } QQuickJSContext2DImageData *imageData = new (v4->memoryManager) QQuickJSContext2DImageData(v4); - imageData->pixelData = QV4::Value::fromObject(pixelData); + imageData->pixelData = pixelData.asValue(); return QV4::Value::fromObject(imageData); } @@ -1362,7 +1364,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_fillStyle(QV4::SimpleCallContex QString str = QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString); return QV4::Value::fromString(ctx->engine->newString(str)).asReturnedValue(); } - return r->context->m_fillStyle.value().asReturnedValue(); + return r->context->m_fillStyle.value(); } QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::SimpleCallContext *ctx) @@ -1477,7 +1479,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_strokeStyle(QV4::SimpleCallCont QString str = QString::fromLatin1("rgba(%1, %2, %3, %4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(alphaString); return QV4::Value::fromString(ctx->engine->newString(str)).asReturnedValue(); } - return r->context->m_strokeStyle.value().asReturnedValue(); + return r->context->m_strokeStyle.value(); } QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::SimpleCallContext *ctx) @@ -1559,10 +1561,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4:: } QQuickContext2DEngineData *ed = engineData(engine); - QQuickContext2DStyle *gradient = new (v4->memoryManager) QQuickContext2DStyle(v4); - gradient->setPrototype(ed->gradientProto.value().asObject()); + QV4::Scoped<QQuickContext2DStyle> gradient(scope, new (v4->memoryManager) QQuickContext2DStyle(v4)); + QV4::ScopedObject p(scope, ed->gradientProto.value()); + gradient->setPrototype(p.getPointer()); gradient->brush = QLinearGradient(x0, y0, x1, y1); - return QV4::Value::fromObject(gradient).asReturnedValue(); + return gradient.asReturnedValue(); } return ctx->thisObject.asReturnedValue(); @@ -1613,10 +1616,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4:: QQuickContext2DEngineData *ed = engineData(engine); - QQuickContext2DStyle *gradient = new (v4->memoryManager) QQuickContext2DStyle(v4); - gradient->setPrototype(ed->gradientProto.value().asObject()); + QV4::Scoped<QQuickContext2DStyle> gradient(scope, new (v4->memoryManager) QQuickContext2DStyle(v4)); + QV4::ScopedObject p(scope, ed->gradientProto.value()); + gradient->setPrototype(p.getPointer()); gradient->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0)); - return QV4::Value::fromObject(gradient).asReturnedValue(); + return gradient.asReturnedValue(); } return ctx->thisObject.asReturnedValue(); @@ -1659,10 +1663,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4: QQuickContext2DEngineData *ed = engineData(engine); - QQuickContext2DStyle *gradient = new (v4->memoryManager) QQuickContext2DStyle(v4); - gradient->setPrototype(ed->gradientProto.value().asObject()); + QV4::Scoped<QQuickContext2DStyle> gradient(scope, new (v4->memoryManager) QQuickContext2DStyle(v4)); + QV4::ScopedObject p(scope, ed->gradientProto.value()); + gradient->setPrototype(p.getPointer()); gradient->brush = QConicalGradient(x, y, angle); - return QV4::Value::fromObject(gradient).asReturnedValue(); + return gradient.asReturnedValue(); } return ctx->thisObject.asReturnedValue(); @@ -2080,7 +2085,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_path(QV4::SimpleCallContext *ct QQuickJSContext2D *r = ctx->thisObject.as<QQuickJSContext2D>(); CHECK_CONTEXT(r) - return r->context->m_v4path.value().asReturnedValue(); + return r->context->m_v4path.value(); } QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::SimpleCallContext *ctx) @@ -4041,7 +4046,7 @@ QQuickContext2D::~QQuickContext2D() QV4::Value QQuickContext2D::v4value() const { - return m_v4value.value(); + return QV4::Value::fromReturnedValue(m_v4value.value()); } QStringList QQuickContext2D::contextNames() const @@ -4278,10 +4283,12 @@ void QQuickContext2D::setV8Engine(QV8Engine *engine) QQuickContext2DEngineData *ed = engineData(engine); QV4::ExecutionEngine *v4Engine = QV8Engine::getV4(engine); - QQuickJSContext2D *wrapper = new (v4Engine->memoryManager) QQuickJSContext2D(v4Engine); - wrapper->setPrototype(ed->contextPrototype.value().asObject()); + QV4::Scope scope(v4Engine); + QV4::Scoped<QQuickJSContext2D> wrapper(scope, new (v4Engine->memoryManager) QQuickJSContext2D(v4Engine)); + QV4::ScopedObject p(scope, ed->contextPrototype.value()); + wrapper->setPrototype(p.getPointer()); wrapper->context = this; - m_v4value = QV4::Value::fromObject(wrapper); + m_v4value = wrapper; } } diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 3dee563de2..63490ef2cc 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -577,8 +577,8 @@ void QQuickLoader::setSource(QQmlV4Function *args) QUrl sourceUrl = d->resolveSourceUrl(args); if (!ipv.isUndefined()) { d->disposeInitialPropertyValues(); - d->initialPropertyValues = ipv; - d->qmlGlobalForIpv = args->qmlGlobal(); + d->initialPropertyValues = ipv.asReturnedValue(); + d->qmlGlobalForIpv = args->qmlGlobal().asReturnedValue(); } setSource(sourceUrl, false); // already cleared and set ipv above. @@ -644,7 +644,11 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj) QQmlComponentPrivate *d = QQmlComponentPrivate::get(component); Q_ASSERT(d && d->engine); - d->initializeObjectWithInitialProperties(qmlGlobalForIpv.value(), initialPropertyValues.value(), obj); + QV4::ExecutionEngine *v4 = qmlGlobalForIpv.engine(); + Q_ASSERT(v4); + QV4::Scope scope(v4); + QV4::ScopedValue ipv(scope, initialPropertyValues.value()); + d->initializeObjectWithInitialProperties(qmlGlobalForIpv, ipv, obj); } void QQuickLoaderIncubator::statusChanged(Status status) diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index a77c300d49..cba0267b26 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -1233,13 +1233,13 @@ public: { QQmlData *ddata = QQmlData::get(this); assert(ddata); - QV4::QObjectWrapper *thisObject = ddata->jsWrapper.value().as<QV4::QObjectWrapper>(); + QV4::QObjectWrapper *thisObject = QV4::Value::fromReturnedValue(ddata->jsWrapper.value()).as<QV4::QObjectWrapper>(); assert(thisObject); QQmlData *otherDData = QQmlData::get(other); assert(otherDData); - thisObject->defineDefaultProperty(QStringLiteral("autoTestStrongRef"), otherDData->jsWrapper.value()); + thisObject->defineDefaultProperty(QStringLiteral("autoTestStrongRef"), QV4::Value::fromReturnedValue(otherDData->jsWrapper.value())); } void setEngine(QQmlEngine* declarativeEngine) diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index d85b974175..a5f30a01c2 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -3905,8 +3905,11 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) { if (qmlglobal.isUndefined()) continue; + QV4::Scope scope(QV8Engine::getV4((engine))); + QV4::ScopedValue qml(scope, qmlglobal.value()); - scriptContext = QV4::QmlContextWrapper::getContext(qmlglobal); + scriptContext = QV4::QmlContextWrapper::getContext(qml); + qml = QV4::Encode::undefined(); { QV4::Scope scope(QV8Engine::getV4((engine))); @@ -3915,7 +3918,8 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) { } engine->gc(); - newContext = QV4::QmlContextWrapper::getContext(qmlglobal); + qml = qmlglobal.value(); + newContext = QV4::QmlContextWrapper::getContext(qml); QVERIFY(scriptContext == newContext); } } @@ -4992,11 +4996,11 @@ void tst_qqmlecmascript::propertyVarInheritance() { // XXX NOTE: this is very implementation dependent. QDVMEMO->vmeProperty() is the only // public function which can return us a handle to something in the varProperties array. - QV4::Value tmp = QV4::Value::fromReturnedValue(icovmemo->vmeProperty(ico5->metaObject()->indexOfProperty("circ"))); + QV4::ReturnedValue tmp = icovmemo->vmeProperty(ico5->metaObject()->indexOfProperty("circ")); icoCanaryHandle = tmp; - tmp = QV4::Value::fromReturnedValue(ccovmemo->vmeProperty(cco5->metaObject()->indexOfProperty("circ"))); + tmp = ccovmemo->vmeProperty(cco5->metaObject()->indexOfProperty("circ")); ccoCanaryHandle = tmp; - tmp = QV4::Value::nullValue(); + tmp = QV4::Encode::null(); QVERIFY(!icoCanaryHandle.isUndefined()); QVERIFY(!ccoCanaryHandle.isUndefined()); gc(engine); @@ -5038,9 +5042,7 @@ void tst_qqmlecmascript::propertyVarInheritance2() QCOMPARE(childObject->property("textCanary").toInt(), 10); QV4::WeakValue childObjectVarArrayValueHandle; { - QV4::Value tmp = QV4::Value::fromReturnedValue(QQmlVMEMetaObject::get(childObject)->vmeProperty(childObject->metaObject()->indexOfProperty("vp"))); - childObjectVarArrayValueHandle = tmp; - tmp = QV4::Value::nullValue(); + childObjectVarArrayValueHandle = QQmlVMEMetaObject::get(childObject)->vmeProperty(childObject->metaObject()->indexOfProperty("vp")); QVERIFY(!childObjectVarArrayValueHandle.isUndefined()); gc(engine); QVERIFY(!childObjectVarArrayValueHandle.isUndefined()); // should not have been collected yet. |