aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2016-05-11 15:22:51 +0200
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2016-05-18 10:08:30 +0000
commit72515ebe5a63c201fde09471bc646dbe15110a6b (patch)
tree22588014a613d0c2d72b909e28b1667a1c5dc9ec /src
parent74628af12aa8f72a56635bf27e7361861c50f796 (diff)
Fix crashes when incubating objects asynchronously with initial properties
This is a regression from commit 94e337fa95425d259e81b4d21f4d0853108553bd where we accidentally ended up not having a calling QML context set anymore when initializing the properties on newly incubated objects as provided by the caller. The QML context is necessary as for example when we set a URL property, the URL can be relative and it will be resolved to the base url of the context when written, such as in in QQmlPropertyPrivate::write. Change-Id: I1d896381fc92f653a7d76f4d82174bca48828f5e Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/jsruntime/qv4context_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp23
-rw-r--r--src/qml/qml/qqmlcomponent_p.h2
-rw-r--r--src/quick/items/qquickloader.cpp4
-rw-r--r--src/quick/items/qquickloader_p_p.h1
6 files changed, 24 insertions, 10 deletions
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 6c360e7dda..c0c89a5c3d 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -241,7 +241,7 @@ struct WithContext : public ExecutionContext
V4_MANAGED(WithContext, ExecutionContext)
};
-struct QmlContext : public ExecutionContext
+struct Q_QML_EXPORT QmlContext : public ExecutionContext
{
V4_MANAGED(QmlContext, ExecutionContext)
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 49b6dce697..fefc5b6308 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -693,7 +693,7 @@ Heap::QmlContext *ExecutionEngine::qmlContext() const
if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer)
ctx = parentContext(currentContext)->d();
- if (!ctx->outer)
+ if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !ctx->outer)
return 0;
while (ctx->outer && ctx->outer->type != Heap::ExecutionContext::Type_GlobalContext)
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 9b52a951af..24abf52e38 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1071,6 +1071,7 @@ struct QmlIncubatorObject : Object {
QPointer<QObject> parent;
QV4::Value valuemap;
QV4::Value statusChanged;
+ Pointer<Heap::QmlContext> qmlContext;
};
}
@@ -1185,7 +1186,7 @@ static void QQmlComponent_setQmlParent(QObject *me, QObject *parent)
*/
-static void setInitialProperties(QV4::ExecutionEngine *engine, const QV4::Value &o, const QV4::Value &v)
+static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v)
{
QV4::Scope scope(engine);
QV4::ScopedObject object(scope);
@@ -1196,6 +1197,9 @@ static void setInitialProperties(QV4::ExecutionEngine *engine, const QV4::Value
if (engine->hasException)
return;
+ QV4::ExecutionContextSaver saver(scope);
+ engine->pushContext(qmlContext);
+
while (1) {
name = it.nextPropertyNameAsString(val);
if (!name)
@@ -1269,8 +1273,10 @@ void QQmlComponent::createObject(QQmlV4Function *args)
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4, rv));
Q_ASSERT(object->isObject());
- if (!valuemap->isUndefined())
- setInitialProperties(v4, object, valuemap);
+ if (!valuemap->isUndefined()) {
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, v4->qmlContext());
+ setInitialProperties(v4, qmlContext, object, valuemap);
+ }
d->completeCreate();
@@ -1387,6 +1393,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
if (!valuemap->isUndefined())
r->d()->valuemap = valuemap;
+ r->d()->qmlContext = v4->qmlContext();
r->d()->parent = parent;
QQmlIncubator *incubator = r->d()->incubator.data();
@@ -1400,7 +1407,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
}
// XXX used by QSGLoader
-void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate)
+void QQmlComponentPrivate::initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate)
{
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4engine = QV8Engine::getV4(ep->v8engine());
@@ -1410,7 +1417,7 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu
Q_ASSERT(object->as<QV4::Object>());
if (!valuemap.isUndefined())
- setInitialProperties(v4engine, object, valuemap);
+ setInitialProperties(v4engine, qmlContext, object, valuemap);
}
QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4)
@@ -1487,6 +1494,7 @@ QQmlComponentExtension::~QQmlComponentExtension()
QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(QQmlIncubator::IncubationMode m)
: valuemap(QV4::Primitive::undefinedValue())
, statusChanged(QV4::Primitive::undefinedValue())
+ , qmlContext(0)
{
incubator.reset(new QQmlComponentIncubator(this, m));
}
@@ -1499,7 +1507,8 @@ void QV4::QmlIncubatorObject::setInitialState(QObject *o)
QV4::ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
QV4::ScopedObject obj(scope, QV4::QObjectWrapper::wrap(v4, o));
- setInitialProperties(v4, obj, d()->valuemap);
+ QV4::Scoped<QV4::QmlContext> qmlCtxt(scope, d()->qmlContext);
+ setInitialProperties(v4, qmlCtxt, obj, d()->valuemap);
}
}
@@ -1508,6 +1517,8 @@ void QV4::QmlIncubatorObject::markObjects(QV4::Heap::Base *that, QV4::ExecutionE
QmlIncubatorObject::Data *o = static_cast<QmlIncubatorObject::Data *>(that);
o->valuemap.mark(e);
o->statusChanged.mark(e);
+ if (o->qmlContext)
+ o->qmlContext->mark(e);
Object::markObjects(that, e);
}
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 15ec88dd52..ff6969fcdc 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -82,7 +82,7 @@ public:
QObject *beginCreate(QQmlContextData *);
void completeCreate();
- void initializeObjectWithInitialProperties(const QV4::Value &valuemap, QObject *toCreate);
+ void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate);
QQmlTypeData *typeData;
virtual void typeDataReady(QQmlTypeData *);
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 456eedd0be..7cac79bd46 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -577,6 +577,7 @@ void QQuickLoader::setSource(QQmlV4Function *args)
d->disposeInitialPropertyValues();
d->initialPropertyValues.set(args->v4engine(), ipv);
}
+ d->qmlCallingContext.set(scope.engine, scope.engine->qmlContext());
setSource(sourceUrl, false); // already cleared and set ipv above.
}
@@ -645,7 +646,8 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
Q_ASSERT(v4);
QV4::Scope scope(v4);
QV4::ScopedValue ipv(scope, initialPropertyValues.value());
- d->initializeObjectWithInitialProperties(ipv, obj);
+ QV4::Scoped<QV4::QmlContext> qmlContext(scope, qmlCallingContext.value());
+ d->initializeObjectWithInitialProperties(qmlContext, ipv, obj);
}
void QQuickLoaderIncubator::statusChanged(Status status)
diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index 9677318b58..26a74be9d9 100644
--- a/src/quick/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
@@ -102,6 +102,7 @@ public:
QQmlContext *itemContext;
QQuickLoaderIncubator *incubator;
QV4::PersistentValue initialPropertyValues;
+ QV4::PersistentValue qmlCallingContext;
bool updatingSize: 1;
bool active : 1;
bool loadingFromSource : 1;