aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/statemachine/signaltransition.cpp5
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp29
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp8
-rw-r--r--src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.h3
-rw-r--r--src/qml/CMakeLists.txt2
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces_p.h6
-rw-r--r--src/qml/jsruntime/qv4engine.cpp4
-rw-r--r--src/qml/jsruntime/qv4engine_p.h2
-rw-r--r--src/qml/jsruntime/qv4include.cpp4
-rw-r--r--src/qml/jsruntime/qv4include_p.h4
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp114
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h18
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp51
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h26
-rw-r--r--src/qml/qml/qml.pri3
-rw-r--r--src/qml/qml/qqmlbinding.cpp56
-rw-r--r--src/qml/qml/qqmlbinding_p.h21
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp22
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h19
-rw-r--r--src/qml/qml/qqmlcomponent.cpp52
-rw-r--r--src/qml/qml/qqmlcomponent_p.h7
-rw-r--r--src/qml/qml/qqmlcomponentattached_p.h29
-rw-r--r--src/qml/qml/qqmlcontext.cpp547
-rw-r--r--src/qml/qml/qqmlcontext.h2
-rw-r--r--src/qml/qml/qqmlcontext_p.h335
-rw-r--r--src/qml/qml/qqmlcontextdata.cpp366
-rw-r--r--src/qml/qml/qqmlcontextdata_p.h427
-rw-r--r--src/qml/qml/qqmldata_p.h45
-rw-r--r--src/qml/qml/qqmlengine.cpp47
-rw-r--r--src/qml/qml/qqmlengine_p.h22
-rw-r--r--src/qml/qml/qqmlexpression.cpp41
-rw-r--r--src/qml/qml/qqmlexpression.h2
-rw-r--r--src/qml/qml/qqmlexpression_p.h4
-rw-r--r--src/qml/qml/qqmlguardedcontextdata_p.h131
-rw-r--r--src/qml/qml/qqmlincubator.cpp21
-rw-r--r--src/qml/qml/qqmlincubator_p.h2
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp37
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h34
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp142
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h31
-rw-r--r--src/qml/qml/qqmlproperty.cpp59
-rw-r--r--src/qml/qml/qqmlproperty_p.h25
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp22
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h18
-rw-r--r--src/qml/qml/qqmlpropertyresolver.cpp1
-rw-r--r--src/qml/qml/qqmlscriptblob.cpp1
-rw-r--r--src/qml/qml/qqmlscriptdata.cpp70
-rw-r--r--src/qml/qml/qqmlscriptdata_p.h5
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp10
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp2
-rw-r--r--src/qml/qml/qqmlvme.cpp2
-rw-r--r--src/qml/qml/qqmlvme_p.h2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp32
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h7
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp18
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp16
-rw-r--r--src/qml/types/qqmlconnections.cpp6
-rw-r--r--src/qmlmodels/qqmldelegatemodel.cpp43
-rw-r--r--src/qmlmodels/qqmldelegatemodel_p_p.h4
-rw-r--r--src/qmlmodels/qqmltableinstancemodel.cpp8
-rw-r--r--src/quick/designer/qquickdesignersupport.cpp6
-rw-r--r--src/quick/items/qquickloader.cpp7
-rw-r--r--src/quick/items/qquickwindowmodule.cpp6
-rw-r--r--src/quick/util/qquickpropertychanges.cpp9
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp7
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp2
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp46
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp58
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp2
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp7
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp1
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp3
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp12
75 files changed, 1812 insertions, 1432 deletions
diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp
index 51b2501a7b..c70a824fb6 100644
--- a/src/imports/statemachine/signaltransition.cpp
+++ b/src/imports/statemachine/signaltransition.cpp
@@ -69,8 +69,7 @@ bool SignalTransition::eventTest(QEvent *event)
QQmlContext *outerContext = QQmlEngine::contextForObject(this);
QQmlContext context(outerContext);
- QQmlContextData::get(outerContext)->imports->addref();
- QQmlContextData::get(&context)->imports = QQmlContextData::get(outerContext)->imports;
+ QQmlContextData::get(&context)->setImports(QQmlContextData::get(outerContext)->imports());
QStateMachine::SignalEvent *e = static_cast<QStateMachine::SignalEvent*>(event);
@@ -163,7 +162,7 @@ void SignalTransition::connectTriggered()
QObject *target = senderObject();
QQmlData *ddata = QQmlData::get(this);
- QQmlContextData *ctxtdata = ddata ? ddata->outerContext : nullptr;
+ QQmlRefPointer<QQmlContextData> ctxtdata = ddata ? ddata->outerContext : nullptr;
Q_ASSERT(m_bindings.count() == 1);
const QV4::CompiledData::Binding *binding = m_bindings.at(0);
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index d435e82390..1aa24ea3a4 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -389,7 +389,7 @@ void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message,
if (!ctxt->isValid())
return;
- QQmlContextData *p = QQmlContextData::get(ctxt);
+ QQmlRefPointer<QQmlContextData> p = QQmlContextData::get(ctxt);
QString ctxtName = ctxt->objectName();
int ctxtId = QQmlDebugService::idForObject(ctxt);
@@ -400,31 +400,31 @@ void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message,
int count = 0;
- QQmlContextData *child = p->childContexts;
+ QQmlRefPointer<QQmlContextData> child = p->childContexts();
while (child) {
++count;
- child = child->nextChild;
+ child = child->nextChild();
}
message << count;
- child = p->childContexts;
+ child = p->childContexts();
while (child) {
buildObjectList(message, child->asQQmlContext(), instances);
- child = child->nextChild;
+ child = child->nextChild();
}
count = 0;
for (int ii = 0; ii < instances.count(); ++ii) {
QQmlData *data = QQmlData::get(instances.at(ii));
- if (data->context == p)
+ if (data->context == p.data())
count ++;
}
message << count;
for (int ii = 0; ii < instances.count(); ++ii) {
QQmlData *data = QQmlData::get(instances.at(ii));
- if (data->context == p)
+ if (data->context == p.data())
message << objectData(instances.at(ii));
}
}
@@ -522,16 +522,11 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message)
if (engine) {
QQmlContext *rootContext = engine->rootContext();
- // Clean deleted objects
QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(rootContext);
- for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
- if (!ctxtPriv->instances.at(ii)) {
- ctxtPriv->instances.removeAt(ii);
- --ii;
- }
- }
- buildObjectList(rs, rootContext, ctxtPriv->instances);
- buildStatesList(true, ctxtPriv->instances);
+ ctxtPriv->cleanInstances(); // Clean deleted objects
+ const QList<QPointer<QObject>> instances = ctxtPriv->instances();
+ buildObjectList(rs, rootContext, instances);
+ buildStatesList(true, instances);
}
} else if (type == "FETCH_OBJECT") {
@@ -783,7 +778,7 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth
QQmlContext *context = qmlContext(object);
if (!object || !context || !context->isValid())
return false;
- QQmlContextData *contextData = QQmlContextData::get(context);
+ QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
QQmlPropertyData dummy;
QQmlPropertyData *prop =
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
index 333ce4b26f..a70941682b 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
@@ -88,10 +88,10 @@ void JavaScriptJob::run()
QV4::ScopedObject withContext(scope, engine->newObject());
QV4::ScopedString k(scope);
QV4::ScopedValue v(scope);
- for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) {
- QObject *object = ctxtPriv->instances.at(ii);
- if (QQmlContext *context = qmlContext(object)) {
- if (QQmlContextData *cdata = QQmlContextData::get(context)) {
+ const QList<QPointer<QObject>> instances = ctxtPriv->instances();
+ for (const QPointer<QObject> &object : instances) {
+ if (QQmlContext *context = qmlContext(object.data())) {
+ if (QQmlRefPointer<QQmlContextData> cdata = QQmlContextData::get(context)) {
v = QV4::QObjectWrapper::wrap(engine, object);
k = engine->newString(cdata->findObjectId(object));
withContext->put(k, v);
diff --git a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
index 012730902b..301db59952 100644
--- a/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
+++ b/src/plugins/qmltooling/qmldbg_inspector/globalinspector.cpp
@@ -298,7 +298,7 @@ QString GlobalInspector::idStringForObject(QObject *obj) const
{
QQmlContext *context = qmlContext(obj);
if (context) {
- QQmlContextData *cdata = QQmlContextData::get(context);
+ QQmlRefPointer<QQmlContextData> cdata = QQmlContextData::get(context);
if (cdata)
return cdata->findObjectId(obj);
}
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.cpp
index 1561777202..5da26e9610 100644
--- a/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.cpp
@@ -58,7 +58,9 @@ QString QQmlDebugTranslationServiceImpl::foundElidedText(QObject *textObject, co
return elideText;
}
-void QQmlDebugTranslationServiceImpl::foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject, QQmlContextData *contextData)
+void QQmlDebugTranslationServiceImpl::foundTranslationBinding(
+ QQmlTranslationBinding *binding, QObject *scopeObject,
+ const QQmlRefPointer<QQmlContextData> &contextData)
{
Q_UNUSED(binding)
Q_UNUSED(scopeObject)
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.h b/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.h
index a337a937a5..802f21ecce 100644
--- a/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.h
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.h
@@ -78,7 +78,8 @@ public:
QQmlDebugTranslationServiceImpl(QObject *parent = 0);
QString foundElidedText(QObject *textObject, const QString &layoutText, const QString &elideText) override;
- void foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject, QQmlContextData *contextData) override;
+ void foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject,
+ const QQmlRefPointer<QQmlContextData> &contextData) override;
void messageReceived(const QByteArray &message) override;
};
diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt
index 3240e48092..3a6f75a58b 100644
--- a/src/qml/CMakeLists.txt
+++ b/src/qml/CMakeLists.txt
@@ -191,6 +191,7 @@ qt_add_module(Qml
qml/qqmlcomponent.cpp qml/qqmlcomponent.h qml/qqmlcomponent_p.h
qml/qqmlcomponentattached_p.h
qml/qqmlcontext.cpp qml/qqmlcontext.h qml/qqmlcontext_p.h
+ qml/qqmlcontextdata.cpp qml/qqmlcontextdata_p.h
qml/qqmlcustomparser.cpp qml/qqmlcustomparser_p.h
qml/qqmldata_p.h
qml/qqmldatablob.cpp qml/qqmldatablob_p.h
@@ -207,6 +208,7 @@ qt_add_module(Qml
qml/qqmlfileselector.cpp qml/qqmlfileselector.h qml/qqmlfileselector_p.h
qml/qqmlglobal.cpp qml/qqmlglobal_p.h
qml/qqmlguard_p.h
+ qml/qqmlguardedcontextdata_p.h
qml/qqmlimport.cpp qml/qqmlimport_p.h
qml/qqmlincubator.cpp qml/qqmlincubator.h qml/qqmlincubator_p.h
qml/qqmlinfo.cpp qml/qqmlinfo.h
diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
index b259e047a1..df1ed68c7b 100644
--- a/src/qml/debugger/qqmldebugserviceinterfaces_p.h
+++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
@@ -107,7 +107,8 @@ class QQmlNativeDebugService {};
class QQmlDebugTranslationService {
public:
virtual QString foundElidedText(QObject *, const QString &, const QString &) {return {};}
- virtual void foundTranslationBinding(QQmlTranslationBinding *, QObject *, QQmlContextData *) {}
+ virtual void foundTranslationBinding(QQmlTranslationBinding *, QObject *,
+ const QQmlRefPointer<QQmlContextData> &) {}
};
#else
@@ -175,7 +176,8 @@ public:
static const QString s_key;
virtual QString foundElidedText(QObject *qQuickTextObject, const QString &layoutText, const QString &elideText) = 0;
- virtual void foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject, QQmlContextData *contextData) = 0;
+ virtual void foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject,
+ const QQmlRefPointer<QQmlContextData> &contextData) = 0;
protected:
friend class QQmlDebugConnector;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index d4725ce7c2..5edf2fdea7 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -1198,13 +1198,13 @@ QObject *ExecutionEngine::qmlScopeObject() const
return ctx->qml()->scopeObject;
}
-QQmlContextData *ExecutionEngine::callingQmlContext() const
+QQmlRefPointer<QQmlContextData> ExecutionEngine::callingQmlContext() const
{
Heap::QmlContext *ctx = qmlContext();
if (!ctx)
return nullptr;
- return ctx->qml()->context->contextData();
+ return ctx->qml()->context;
}
StackTrace ExecutionEngine::stackTrace(int frameLimit) const
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 21971c1c23..9d734a16a0 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -609,7 +609,7 @@ public:
Heap::QmlContext *qmlContext() const;
QObject *qmlScopeObject() const;
- QQmlContextData *callingQmlContext() const;
+ QQmlRefPointer<QQmlContextData> callingQmlContext() const;
StackTrace stackTrace(int frameLimit = -1) const;
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 745ffab0cd..17512cf4ff 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -208,9 +208,9 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons
if (!argc)
RETURN_UNDEFINED();
- QQmlContextData *context = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
- if ((!context || !context->isJSContext) && scope.engine->qmlEngine())
+ if ((!context || !context->isJSContext()) && scope.engine->qmlEngine())
RETURN_RESULT(scope.engine->throwError(QString::fromUtf8("Qt.include(): Can only be called from JavaScript files")));
QV4::ScopedValue callbackFunction(scope, QV4::Value::undefinedValue());
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 70ccfbf223..9d0a17a5cc 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -53,11 +53,11 @@
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
-
-#include <private/qqmlcontext_p.h>
+#include <QtCore/qpointer.h>
#include <private/qv4value_p.h>
#include <private/qv4context_p.h>
+#include <private/qv4persistent_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 4538900d21..9863edead0 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -64,23 +64,25 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QQmlContextWrapper);
DEFINE_MANAGED_VTABLE(QmlContext);
-void Heap::QQmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject)
+void Heap::QQmlContextWrapper::init(QQmlRefPointer<QQmlContextData> context, QObject *scopeObject)
{
Object::init();
- this->context = new QQmlContextDataRef(context);
+ this->context = context.take();
this->scopeObject.init(scopeObject);
}
void Heap::QQmlContextWrapper::destroy()
{
- delete context;
+ context->release();
+ context = nullptr;
scopeObject.destroy();
Object::destroy();
}
-static OptionalReturnedValue searchContextProperties(QV4::ExecutionEngine *v4, QQmlContextData *context, String *name,
- bool *hasProperty, Value *base, QV4::Lookup *lookup,
- QV4::Lookup *originalLookup, QQmlEnginePrivate *ep)
+static OptionalReturnedValue searchContextProperties(
+ QV4::ExecutionEngine *v4, const QQmlRefPointer<QQmlContextData> &context, String *name,
+ bool *hasProperty, Value *base, QV4::Lookup *lookup, QV4::Lookup *originalLookup,
+ QQmlEnginePrivate *ep)
{
const QV4::IdentifierHash &properties = context->propertyNames();
if (properties.count() == 0)
@@ -91,7 +93,7 @@ static OptionalReturnedValue searchContextProperties(QV4::ExecutionEngine *v4, Q
if (propertyIdx == -1)
return OptionalReturnedValue();
- if (propertyIdx < context->idValueCount) {
+ if (propertyIdx < context->numIdValues()) {
if (hasProperty)
*hasProperty = true;
@@ -104,16 +106,16 @@ static OptionalReturnedValue searchContextProperties(QV4::ExecutionEngine *v4, Q
}
if (ep->propertyCapture)
- ep->propertyCapture->captureProperty(&context->idValues[propertyIdx].bindings);
- return OptionalReturnedValue(QV4::QObjectWrapper::wrap(v4, context->idValues[propertyIdx]));
+ ep->propertyCapture->captureProperty(context->idValueBindings(propertyIdx));
+ return OptionalReturnedValue(QV4::QObjectWrapper::wrap(v4, context->idValue(propertyIdx)));
}
QQmlContextPrivate *cp = context->asQQmlContextPrivate();
if (ep->propertyCapture)
- ep->propertyCapture->captureProperty(context->asQQmlContext(), -1, propertyIdx + cp->notifyIndex);
+ ep->propertyCapture->captureProperty(context->asQQmlContext(), -1, propertyIdx + cp->notifyIndex());
- const QVariant &value = cp->propertyValues.at(propertyIdx);
+ const QVariant &value = cp->propertyValue(propertyIdx);
if (hasProperty)
*hasProperty = true;
if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
@@ -122,7 +124,7 @@ static OptionalReturnedValue searchContextProperties(QV4::ExecutionEngine *v4, Q
QQmlContextPrivate::context_at);
return OptionalReturnedValue(QmlListWrapper::create(v4, prop, qMetaTypeId<QQmlListProperty<QObject> >()));
}
- return OptionalReturnedValue(v4->fromVariant(cp->propertyValues.at(propertyIdx)));
+ return OptionalReturnedValue(v4->fromVariant(cp->propertyValue(propertyIdx)));
}
ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *resource, PropertyKey id, const Value *receiver, bool *hasProperty, Value *base, Lookup *lookup)
@@ -133,7 +135,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
QV4::ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
- if (v4->callingQmlContext() != *resource->d()->context) {
+ if (v4->callingQmlContext().data() != resource->d()->context) {
if (resource->d()->module) {
Scoped<Module> module(scope, resource->d()->module);
bool hasProp = false;
@@ -158,8 +160,8 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
// It's possible we could delay the calculation of the "actual" context (in the case
// of sub contexts) until it is definitely needed.
- QQmlContextData *context = resource->getContext();
- QQmlContextData *expressionContext = context;
+ QQmlRefPointer<QQmlContextData> context = resource->getContext();
+ QQmlRefPointer<QQmlContextData> expressionContext = context;
if (!context) {
if (hasProperty)
@@ -211,9 +213,9 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
return result->asReturnedValue();
}
- if (context->imports && name->startsWithUpper()) {
+ if (context->imports() && name->startsWithUpper()) {
// Search for attached properties, enums and imported scripts
- QQmlTypeNameCache::Result r = context->imports->query(name, QQmlImport::AllowRecursion);
+ QQmlTypeNameCache::Result r = context->imports()->query(name, QQmlImport::AllowRecursion);
if (r.isValid()) {
if (hasProperty)
@@ -224,7 +226,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupScript;
return lookup->qmlContextPropertyGetter(lookup, v4, base);
}
- QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
+ QV4::ScopedObject scripts(scope, context->importedScripts().valueRef());
if (scripts)
return scripts->get(r.scriptIndex);
return QV4::Encode::null();
@@ -250,7 +252,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
}
result = QQmlTypeWrapper::create(v4, scopeObject, r.type);
} else if (r.importNamespace) {
- result = QQmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace);
+ result = QQmlTypeWrapper::create(v4, scopeObject, context->imports(), r.importNamespace);
}
if (lookup) {
lookup->qmlTypeLookup.qmlTypeWrapper = static_cast<Heap::Object*>(result->heapObject());
@@ -268,7 +270,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
decltype(lookup->qmlContextPropertyGetter) contextGetterFunction = QQmlContextWrapper::lookupContextObjectProperty;
// minor optimization so we don't potentially try two property lookups on the same object
- if (scopeObject == context->contextObject) {
+ if (scopeObject == context->contextObject()) {
scopeObject = nullptr;
contextGetterFunction = QQmlContextWrapper::lookupScopeObjectProperty;
}
@@ -310,22 +312,24 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
// Search context object
- if (context->contextObject) {
+ if (QObject *contextObject = context->contextObject()) {
bool hasProp = false;
QQmlPropertyData *propertyData = nullptr;
- result = QV4::QObjectWrapper::getQmlProperty(v4, context, context->contextObject,
- name, QV4::QObjectWrapper::CheckRevision, &hasProp, &propertyData);
+ result = QV4::QObjectWrapper::getQmlProperty(v4, context, contextObject,
+ name, QV4::QObjectWrapper::CheckRevision,
+ &hasProp, &propertyData);
if (hasProp) {
if (hasProperty)
*hasProperty = true;
if (base)
- *base = QV4::QObjectWrapper::wrap(v4, context->contextObject);
+ *base = QV4::QObjectWrapper::wrap(v4, contextObject);
if (propertyData) {
if (lookup) {
- QQmlData *ddata = QQmlData::get(context->contextObject, false);
+ QQmlData *ddata = QQmlData::get(contextObject, false);
if (ddata && ddata->propertyCache) {
- ScopedValue val(scope, base ? *base : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, context->contextObject)));
+ ScopedValue val(scope, base ? *base
+ : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, contextObject)));
const QObjectWrapper *That = static_cast<const QObjectWrapper *>(val->objectValue());
lookup->qobjectLookup.ic = That->internalClass();
lookup->qobjectLookup.propertyCache = ddata->propertyCache;
@@ -342,7 +346,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
}
}
- context = context->parent;
+ context = context->parent();
// As the hierarchy of contexts is not stable, we can't do accelerated lookups beyond
// the immediate QML context (of the .qml file).
@@ -370,7 +374,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
return result->asReturnedValue();
}
- expressionContext->unresolvedNames = true;
+ expressionContext->setUnresolvedNames(true);
return Encode::undefined();
}
@@ -402,8 +406,8 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val
// It's possible we could delay the calculation of the "actual" context (in the case
// of sub contexts) until it is definitely needed.
- QQmlContextData *context = wrapper->getContext();
- QQmlContextData *expressionContext = context;
+ QQmlRefPointer<QQmlContextData> context = wrapper->getContext();
+ QQmlRefPointer<QQmlContextData> expressionContext = context;
if (!context)
return false;
@@ -419,7 +423,7 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val
if (properties.count()) {
const int propertyIndex = properties.value(name);
if (propertyIndex != -1) {
- if (propertyIndex < context->idValueCount) {
+ if (propertyIndex < context->numIdValues()) {
v4->throwError(QLatin1String("left-hand side of assignment operator is not an lvalue"));
return false;
}
@@ -434,14 +438,15 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val
scopeObject = nullptr;
// Search context object
- if (context->contextObject &&
- QV4::QObjectWrapper::setQmlProperty(v4, context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, value))
+ if (context->contextObject() &&
+ QV4::QObjectWrapper::setQmlProperty(v4, context, context->contextObject(), name,
+ QV4::QObjectWrapper::CheckRevision, value))
return true;
- context = context->parent;
+ context = context->parent();
}
- expressionContext->unresolvedNames = true;
+ expressionContext->setUnresolvedNames(true);
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
@@ -502,11 +507,11 @@ ReturnedValue QQmlContextWrapper::lookupScript(Lookup *l, ExecutionEngine *engin
if (!qmlContext)
return QV4::Encode::null();
- QQmlContextData *context = qmlContext->qmlContext();
+ QQmlRefPointer<QQmlContextData> context = qmlContext->qmlContext();
if (!context)
return QV4::Encode::null();
- QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
+ QV4::ScopedObject scripts(scope, context->importedScripts().valueRef());
if (!scripts)
return QV4::Encode::null();
return scripts->get(l->qmlContextScriptLookup.scriptIndex);
@@ -527,7 +532,7 @@ ReturnedValue QQmlContextWrapper::lookupIdObject(Lookup *l, ExecutionEngine *eng
if (!qmlContext)
return QV4::Encode::null();
- QQmlContextData *context = qmlContext->qmlContext();
+ QQmlRefPointer<QQmlContextData> context = qmlContext->qmlContext();
if (!context)
return QV4::Encode::null();
@@ -535,9 +540,9 @@ ReturnedValue QQmlContextWrapper::lookupIdObject(Lookup *l, ExecutionEngine *eng
const int objectId = l->qmlContextIdObjectLookup.objectId;
if (qmlEngine->propertyCapture)
- qmlEngine->propertyCapture->captureProperty(&context->idValues[objectId].bindings);
+ qmlEngine->propertyCapture->captureProperty(context->idValueBindings(objectId));
- return QV4::QObjectWrapper::wrap(engine, context->idValues[objectId]);
+ return QV4::QObjectWrapper::wrap(engine, context->idValue(objectId));
}
ReturnedValue QQmlContextWrapper::lookupScopeObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base)
@@ -576,11 +581,11 @@ ReturnedValue QQmlContextWrapper::lookupContextObjectProperty(Lookup *l, Executi
if (!qmlContext)
return QV4::Encode::undefined();
- QQmlContextData *context = qmlContext->qmlContext();
+ QQmlRefPointer<QQmlContextData> context = qmlContext->qmlContext();
if (!context)
return QV4::Encode::undefined();
- QObject *contextObject = context->contextObject;
+ QObject *contextObject = context->contextObject();
if (!contextObject)
return QV4::Encode::undefined();
@@ -621,11 +626,11 @@ ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, Exec
if (!qmlContext)
return QV4::Encode::undefined();
- QQmlContextData *context = qmlContext->qmlContext();
+ QQmlRefPointer<QQmlContextData> context = qmlContext->qmlContext();
if (!context)
return QV4::Encode::undefined();
- QQmlContextData *expressionContext = context;
+ QQmlRefPointer<QQmlContextData> expressionContext = context;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->qmlEngine());
@@ -635,18 +640,19 @@ ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, Exec
ScopedValue result(scope);
- for (context = context->parent; context; context = context->parent) {
+ for (context = context->parent(); context; context = context->parent()) {
if (auto property = searchContextProperties(engine, context, name, nullptr, base, nullptr, nullptr, ep))
return *property;
// Search context object
- if (context->contextObject) {
+ if (QObject *contextObject = context->contextObject()) {
bool hasProp = false;
- result = QV4::QObjectWrapper::getQmlProperty(engine, context, context->contextObject,
- name, QV4::QObjectWrapper::CheckRevision, &hasProp);
+ result = QV4::QObjectWrapper::getQmlProperty(
+ engine, context, contextObject, name,
+ QV4::QObjectWrapper::CheckRevision, &hasProp);
if (hasProp) {
if (base)
- *base = QV4::QObjectWrapper::wrap(engine, context->contextObject);
+ *base = QV4::QObjectWrapper::wrap(engine, contextObject);
return result->asReturnedValue();
}
@@ -658,7 +664,7 @@ ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, Exec
if (hasProp)
return result->asReturnedValue();
- expressionContext->unresolvedNames = true;
+ expressionContext->setUnresolvedNames(true);
return Encode::undefined();
}
@@ -692,11 +698,15 @@ void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContex
this->activation.set(internalClass->engine, qml->d());
}
-Heap::QmlContext *QmlContext::create(ExecutionContext *parent, QQmlContextData *context, QObject *scopeObject)
+Heap::QmlContext *QmlContext::create(
+ ExecutionContext *parent, QQmlRefPointer<QQmlContextData> context,
+ QObject *scopeObject)
{
Scope scope(parent);
- Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocate<QQmlContextWrapper>(context, scopeObject));
+ Scoped<QQmlContextWrapper> qml(
+ scope, scope.engine->memoryManager->allocate<QQmlContextWrapper>(
+ std::move(context), scopeObject));
Heap::QmlContext *c = scope.engine->memoryManager->alloc<QmlContext>(parent, qml);
Q_ASSERT(c->vtable() == staticVTable());
return c;
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index e3e7239fe5..ba7c5da146 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -56,7 +56,7 @@
#include <private/qv4object_p.h>
#include <private/qv4context_p.h>
-#include <private/qqmlcontext_p.h>
+#include <private/qqmlcontextdata_p.h>
QT_BEGIN_NAMESPACE
@@ -72,10 +72,11 @@ namespace Heap {
DECLARE_HEAP_OBJECT(QQmlContextWrapper, Object) {
DECLARE_MARKOBJECTS(QQmlContextWrapper);
- void init(QQmlContextData *context, QObject *scopeObject);
+ void init(QQmlRefPointer<QQmlContextData> context, QObject *scopeObject);
void destroy();
- QQmlContextDataRef *context;
+ // This has to be a plain pointer because object needs to be a POD type.
+ QQmlContextData *context;
QQmlQPointer<QObject> scopeObject;
};
@@ -97,7 +98,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
V4_INTERNALCLASS(QmlContextWrapper)
inline QObject *getScopeObject() const { return d()->scopeObject; }
- inline QQmlContextData *getContext() const { return *d()->context; }
+ inline QQmlRefPointer<QQmlContextData> getContext() const { return d()->context; }
static ReturnedValue getPropertyAndBase(const QQmlContextWrapper *resource, PropertyKey id, const Value *receiver,
bool *hasProperty, Value *base, Lookup *lookup = nullptr);
@@ -120,13 +121,16 @@ struct Q_QML_EXPORT QmlContext : public ExecutionContext
V4_MANAGED(QmlContext, ExecutionContext)
V4_INTERNALCLASS(QmlContext)
- static Heap::QmlContext *create(QV4::ExecutionContext *parent, QQmlContextData *context, QObject *scopeObject);
+ static Heap::QmlContext *create(
+ QV4::ExecutionContext *parent, QQmlRefPointer<QQmlContextData> context,
+ QObject *scopeObject);
QObject *qmlScope() const {
return d()->qml()->scopeObject;
}
- QQmlContextData *qmlContext() const {
- return *d()->qml()->context;
+
+ QQmlRefPointer<QQmlContextData> qmlContext() const {
+ return d()->qml()->context;
}
};
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index a924fa2975..4e387d0380 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -212,13 +212,17 @@ void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
engine->functionPrototype()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
}
-QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const
+QQmlPropertyData *QObjectWrapper::findProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext, String *name,
+ RevisionMode revisionMode, QQmlPropertyData *local) const
{
QObject *o = d()->object();
return findProperty(engine, o, qmlContext, name, revisionMode, local);
}
-QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QObject *o, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local)
+QQmlPropertyData *QObjectWrapper::findProperty(
+ ExecutionEngine *engine, QObject *o, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ String *name, RevisionMode revisionMode, QQmlPropertyData *local)
{
Q_UNUSED(revisionMode);
@@ -285,13 +289,14 @@ static OptionalReturnedValue getDestroyOrToStringMethod(ExecutionEngine *v4, Str
return OptionalReturnedValue(QV4::QObjectMethod::create(global, qobj, index));
}
-static OptionalReturnedValue getPropertyFromImports(ExecutionEngine *v4, String *name, QQmlContextData *qmlContext, QObject *qobj,
- bool *hasProperty = nullptr)
+static OptionalReturnedValue getPropertyFromImports(
+ ExecutionEngine *v4, String *name, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ QObject *qobj, bool *hasProperty = nullptr)
{
- if (!qmlContext || !qmlContext->imports)
+ if (!qmlContext || !qmlContext->imports())
return OptionalReturnedValue();
- QQmlTypeNameCache::Result r = qmlContext->imports->query(name);
+ QQmlTypeNameCache::Result r = qmlContext->imports()->query(name);
if (hasProperty)
*hasProperty = true;
@@ -304,15 +309,17 @@ static OptionalReturnedValue getPropertyFromImports(ExecutionEngine *v4, String
} else if (r.type.isValid()) {
return OptionalReturnedValue(QQmlTypeWrapper::create(v4, qobj,r.type, Heap::QQmlTypeWrapper::ExcludeEnums));
} else if (r.importNamespace) {
- return OptionalReturnedValue(QQmlTypeWrapper::create(v4, qobj, qmlContext->imports, r.importNamespace,
- Heap::QQmlTypeWrapper::ExcludeEnums));
+ return OptionalReturnedValue(QQmlTypeWrapper::create(
+ v4, qobj, qmlContext->imports(), r.importNamespace,
+ Heap::QQmlTypeWrapper::ExcludeEnums));
}
Q_UNREACHABLE();
return OptionalReturnedValue();
}
-ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode,
- bool *hasProperty, bool includeImports) const
+ReturnedValue QObjectWrapper::getQmlProperty(
+ const QQmlRefPointer<QQmlContextData> &qmlContext, String *name,
+ QObjectWrapper::RevisionMode revisionMode, bool *hasProperty, bool includeImports) const
{
// Keep this code in sync with ::virtualResolveLookupGetter
@@ -355,7 +362,10 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
return getProperty(v4, d()->object(), result);
}
-ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty, QQmlPropertyData **property)
+ReturnedValue QObjectWrapper::getQmlProperty(
+ QV4::ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty,
+ QQmlPropertyData **property)
{
if (QQmlData::wasDeleted(object)) {
if (hasProperty)
@@ -415,8 +425,9 @@ ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlC
}
-bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name,
- QObjectWrapper::RevisionMode revisionMode, const Value &value)
+bool QObjectWrapper::setQmlProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext, QObject *object,
+ String *name, QObjectWrapper::RevisionMode revisionMode, const Value &value)
{
if (QQmlData::wasDeleted(object))
return false;
@@ -462,7 +473,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
}
} else {
// binding assignment.
- QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> callingQmlContext = scope.engine->callingQmlContext();
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
@@ -561,7 +572,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
else
v = scope.engine->toVariant(value, property->propType());
- QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
const char *valueType = (v.userType() == QMetaType::UnknownType)
? "an unknown type"
@@ -702,7 +713,7 @@ QV4::ReturnedValue QObjectWrapper::virtualGet(const Managed *m, PropertyKey id,
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
Scope scope(that);
ScopedString n(scope, id.asStringOrSymbol());
- QQmlContextData *qmlContext = that->engine()->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = that->engine()->callingQmlContext();
return that->getQmlProperty(qmlContext, n, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
@@ -718,7 +729,7 @@ bool QObjectWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value,
if (scope.engine->hasException || QQmlData::wasDeleted(that->d()->object()))
return false;
- QQmlContextData *qmlContext = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = scope.engine->callingQmlContext();
if (!setQmlProperty(scope.engine, qmlContext, that->d()->object(), name, QV4::QObjectWrapper::IgnoreRevision, value)) {
QQmlData *ddata = QQmlData::get(that->d()->object());
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
@@ -744,7 +755,7 @@ PropertyAttributes QObjectWrapper::virtualGetOwnProperty(const Managed *m, Prope
if (!QQmlData::wasDeleted(thatObject)) {
Scope scope(m);
ScopedString n(scope, id.asStringOrSymbol());
- QQmlContextData *qmlContext = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = scope.engine->callingQmlContext();
QQmlPropertyData local;
if (that->findProperty(scope.engine, qmlContext, n, IgnoreRevision, &local)
|| n->equals(scope.engine->id_destroy()) || n->equals(scope.engine->id_toString())) {
@@ -848,7 +859,7 @@ ReturnedValue QObjectWrapper::virtualResolveLookupGetter(const Object *object, E
const QObjectWrapper *This = static_cast<const QObjectWrapper *>(object);
ScopedString name(scope, id.asStringOrSymbol());
- QQmlContextData *qmlContext = engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = engine->callingQmlContext();
QObject * const qobj = This->d()->object();
@@ -1168,7 +1179,7 @@ void QObjectWrapper::destroyObject(bool lastCall)
if (ddata) {
if (!h->object()->parent() && !ddata->indestructible) {
if (ddata && ddata->ownContext) {
- Q_ASSERT(ddata->ownContext == ddata->context);
+ Q_ASSERT(ddata->ownContext.data() == ddata->context);
ddata->ownContext->emitDestruction();
ddata->ownContext = nullptr;
ddata->context = nullptr;
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index ac9cad2bdb..6d12271eb8 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -165,10 +165,19 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
QObject *object() const { return d()->object(); }
- ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = nullptr, bool includeImports = false) const;
- static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = nullptr, QQmlPropertyData **property = nullptr);
-
- static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
+ ReturnedValue getQmlProperty(
+ const QQmlRefPointer<QQmlContextData> &qmlContext, String *name,
+ RevisionMode revisionMode, bool *hasProperty = nullptr,
+ bool includeImports = false) const;
+ \
+ static ReturnedValue getQmlProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = nullptr,
+ QQmlPropertyData **property = nullptr);
+
+ static bool setQmlProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ QObject *object, String *name, RevisionMode revisionMode, const Value &value);
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object);
static void markWrapper(QObject *object, MarkStack *markStack);
@@ -193,8 +202,13 @@ protected:
static bool virtualIsEqualTo(Managed *that, Managed *o);
static ReturnedValue create(ExecutionEngine *engine, QObject *object);
- static QQmlPropertyData *findProperty(ExecutionEngine *engine, QObject *o, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local);
- QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
+ static QQmlPropertyData *findProperty(
+ ExecutionEngine *engine, QObject *o, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ String *name, RevisionMode revisionMode, QQmlPropertyData *local);
+
+ QQmlPropertyData *findProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index a16f3d4167..f937d4d0b3 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -17,6 +17,7 @@ SOURCES += \
$$PWD/qqmlcomponent.cpp \
$$PWD/qqmlincubator.cpp \
$$PWD/qqmlcontext.cpp \
+ $$PWD/qqmlcontextdata.cpp \
$$PWD/qqmlcustomparser.cpp \
$$PWD/qqmlpropertyvaluesource.cpp \
$$PWD/qqmlpropertyvalueinterceptor.cpp \
@@ -112,6 +113,8 @@ HEADERS += \
$$PWD/qqmlinfo.h \
$$PWD/qqmlproperty_p.h \
$$PWD/qqmlcontext_p.h \
+ $$PWD/qqmlcontextdata_p.h \
+ $$PWD/qqmlguardedcontextdata_p.h \
$$PWD/qqmltypeloader_p.h \
$$PWD/qqmllist.h \
$$PWD/qqmllist_p.h \
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 59f2759c81..e8e57eb725 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -81,19 +81,19 @@ QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QQmlScr
QString url;
QV4::Function *runtimeFunction = nullptr;
- QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context);
+ QQmlRefPointer<QQmlContextData> ctxtdata = QQmlContextData::get(scriptPrivate->context);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine());
- if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit) {
+ if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit()) {
url = ctxtdata->urlString();
if (scriptPrivate->bindingId != QQmlBinding::Invalid)
- runtimeFunction = ctxtdata->typeCompilationUnit->runtimeFunctions.at(scriptPrivate->bindingId);
+ runtimeFunction = ctxtdata->typeCompilationUnit()->runtimeFunctions.at(scriptPrivate->bindingId);
}
b->setNotifyOnValueChanged(true);
b->QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
b->setScopeObject(obj ? obj : scriptPrivate->scope);
- QV4::ExecutionEngine *v4 = b->context()->engine->handle();
+ QV4::ExecutionEngine *v4 = b->engine()->handle();
if (runtimeFunction) {
QV4::Scope scope(v4);
QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(v4->rootContext(), ctxtdata, b->scopeObject()));
@@ -121,8 +121,9 @@ void QQmlBinding::setSourceLocation(const QQmlSourceLocation &location)
}
-QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString &str, QObject *obj,
- QQmlContextData *ctxt, const QString &url, quint16 lineNumber)
+QQmlBinding *QQmlBinding::create(
+ const QQmlPropertyData *property, const QString &str, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt, const QString &url, quint16 lineNumber)
{
QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
@@ -135,8 +136,9 @@ QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString
return b;
}
-QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, QV4::Function *function,
- QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope)
+QQmlBinding *QQmlBinding::create(
+ const QQmlPropertyData *property, QV4::Function *function, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt, QV4::ExecutionContext *scope)
{
QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
@@ -162,7 +164,7 @@ void QQmlBinding::setNotifyOnValueChanged(bool v)
void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
{
- if (!enabledFlag() || !context() || !context()->isValid())
+ if (!enabledFlag() || !hasValidContext())
return;
// Check that the target has not been deleted
@@ -183,15 +185,15 @@ void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
DeleteWatcher watcher(this);
- QQmlEngine *engine = context()->engine;
- QV4::Scope scope(engine->handle());
+ QQmlEngine *qmlEngine = engine();
+ QV4::Scope scope(qmlEngine->handle());
if (canUseAccessor())
flags.setFlag(QQmlPropertyData::BypassInterceptor);
Q_TRACE_SCOPE(QQmlBinding, engine, function() ? function()->name()->toQString() : QString(),
sourceLocation().sourceFile, sourceLocation().line, sourceLocation().column);
- QQmlBindingProfiler prof(QQmlEnginePrivate::get(engine)->profiler, function());
+ QQmlBindingProfiler prof(QQmlEnginePrivate::get(qmlEngine)->profiler, function());
doUpdate(watcher, flags, scope);
if (!watcher.wasDeleted())
@@ -200,7 +202,7 @@ void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
QV4::ReturnedValue QQmlBinding::evaluate(bool *isUndefined)
{
- QV4::ExecutionEngine *v4 = context()->engine->handle();
+ QV4::ExecutionEngine *v4 = engine()->handle();
int argc = 0;
const QV4::Value *argv = nullptr;
const QV4::Value *thisObject = nullptr;
@@ -266,7 +268,7 @@ protected:
}
if (hasError()) {
- if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
+ if (!delayedError()->addError(ep)) ep->warning(this->error(engine()));
} else {
clearError();
}
@@ -389,7 +391,10 @@ private:
const QV4::CompiledData::Binding *m_binding;
};
-QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
+QQmlBinding *QQmlBinding::createTranslationBinding(
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
+ const QV4::CompiledData::Binding *binding, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt)
{
QQmlTranslationBinding *b = new QQmlTranslationBinding(unit, binding);
@@ -410,8 +415,8 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
const QV4::Value &result,
bool isUndefined, QQmlPropertyData::WriteFlags flags)
{
- QQmlEngine *engine = context()->engine;
- QV4::ExecutionEngine *v4engine = engine->handle();
+ QQmlEngine *qmlEngine = engine();
+ QV4::ExecutionEngine *v4engine = qmlEngine->handle();
int type = valueTypeData.isValid() ? valueTypeData.propType() : core.propType();
@@ -486,7 +491,7 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
if (QObject *o = *(QObject *const *)value.constData()) {
valueType = o->metaObject()->className();
- QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
+ QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate::get(qmlEngine), type);
if (!propertyMetaObject.isNull())
propertyType = propertyMetaObject.className();
}
@@ -516,13 +521,13 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
QVariant QQmlBinding::evaluate()
{
- QQmlEngine *engine = context()->engine;
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
+ QQmlEngine *qmlEngine = engine();
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine);
ep->referenceScarceResources();
bool isUndefined = false;
- QV4::Scope scope(engine->handle());
+ QV4::Scope scope(qmlEngine->handle());
QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
ep->dereferenceScarceResources();
@@ -620,7 +625,7 @@ bool QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, const
QQmlData *data = QQmlData::get(*m_target, true);
if (!data->propertyCache) {
- data->propertyCache = QQmlEnginePrivate::get(context()->engine)->cache(m_target->metaObject());
+ data->propertyCache = QQmlEnginePrivate::get(engine())->cache(m_target->metaObject());
data->propertyCache->addref();
}
@@ -635,7 +640,7 @@ void QQmlBinding::getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyD
Q_ASSERT(data);
if (Q_UNLIKELY(!data->propertyCache)) {
- data->propertyCache = QQmlEnginePrivate::get(context()->engine)->cache(m_target->metaObject());
+ data->propertyCache = QQmlEnginePrivate::get(engine())->cache(m_target->metaObject());
data->propertyCache->addref();
}
@@ -722,8 +727,9 @@ protected:
}
} else if (auto variant = result.as<QV4::VariantObject>()) {
QVariant value = variant->d()->data();
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context());
- resultMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, value.userType());
+ QQmlEngine *qmlEngine = engine();
+ resultMo = QQmlPropertyPrivate::rawMetaObjectForType(
+ qmlEngine ? QQmlEnginePrivate::get(qmlEngine) : nullptr, value.userType());
if (resultMo.isNull())
return slowWrite(*pd, vtpd, result, isUndefined, flags);
resultObject = *static_cast<QObject *const *>(value.constData());
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 7f96b4df9f..5c9a15bec3 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -76,12 +76,21 @@ public:
typedef QExplicitlySharedDataPointer<QQmlBinding> Ptr;
static QQmlBinding *create(const QQmlPropertyData *, const QQmlScriptString &, QObject *, QQmlContext *);
- static QQmlBinding *create(const QQmlPropertyData *, const QString &, QObject *, QQmlContextData *,
- const QString &url = QString(), quint16 lineNumber = 0);
- static QQmlBinding *create(const QQmlPropertyData *property, QV4::Function *function,
- QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope);
- static QQmlBinding *createTranslationBinding(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, const QV4::CompiledData::Binding *binding,
- QObject *obj, QQmlContextData *ctxt);
+
+ static QQmlBinding *create(
+ const QQmlPropertyData *, const QString &, QObject *,
+ const QQmlRefPointer<QQmlContextData> &, const QString &url = QString(),
+ quint16 lineNumber = 0);
+
+ static QQmlBinding *create(
+ const QQmlPropertyData *property, QV4::Function *function, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt, QV4::ExecutionContext *scope);
+
+ static QQmlBinding *createTranslationBinding(
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
+ const QV4::CompiledData::Binding *binding, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt);
+
~QQmlBinding() override;
void setTarget(const QQmlProperty &);
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 6de4ef153e..6272979e92 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -64,11 +64,10 @@
QT_BEGIN_NAMESPACE
-QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
- QQmlContextData *ctxt, QObject *scope, const QString &expression,
- const QString &fileName, quint16 line, quint16 column,
- const QString &handlerName,
- const QString &parameterString)
+QQmlBoundSignalExpression::QQmlBoundSignalExpression(
+ QObject *target, int index, const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope,
+ const QString &expression, const QString &fileName, quint16 line, quint16 column,
+ const QString &handlerName, const QString &parameterString)
: QQmlJavaScriptExpression(),
m_index(index),
m_target(target)
@@ -105,8 +104,9 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
setupFunction(context, f->function());
}
-QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scopeObject,
- QV4::Function *function, QV4::ExecutionContext *scope)
+QQmlBoundSignalExpression::QQmlBoundSignalExpression(
+ QObject *target, int index, const QQmlRefPointer<QQmlContextData> &ctxt,
+ QObject *scopeObject, QV4::Function *function, QV4::ExecutionContext *scope)
: QQmlJavaScriptExpression(),
m_index(index),
m_target(target)
@@ -114,7 +114,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
// It's important to call init first, because m_index gets remapped in case of cloned signals.
init(ctxt, scopeObject);
- QV4::ExecutionEngine *engine = ctxt->engine->handle();
+ QV4::ExecutionEngine *engine = ctxt->engine()->handle();
// If the function is marked as having a nested function, then the user wrote:
// onSomeSignal: function() { /*....*/ }
@@ -141,7 +141,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
setupFunction(qmlContext, function);
}
-void QQmlBoundSignalExpression::init(QQmlContextData *ctxt, QObject *scope)
+void QQmlBoundSignalExpression::init(const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope)
{
setNotifyOnValueChanged(false);
setContext(ctxt);
@@ -177,7 +177,7 @@ QString QQmlBoundSignalExpression::expression() const
// Changes made here may need to be made there and vice versa.
void QQmlBoundSignalExpression::evaluate(void **a)
{
- Q_ASSERT (context() && engine());
+ Q_ASSERT (engine());
if (!expressionFunctionValid())
return;
@@ -225,7 +225,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
void QQmlBoundSignalExpression::evaluate(const QList<QVariant> &args)
{
- Q_ASSERT (context() && engine());
+ Q_ASSERT (engine());
if (!expressionFunctionValid())
return;
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index d1ec67210e..4a0fa6d4e7 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -66,15 +66,14 @@ QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlJavaScriptExpression, public QQmlRefCount
{
public:
- QQmlBoundSignalExpression(QObject *target, int index,
- QQmlContextData *ctxt, QObject *scope, const QString &expression,
- const QString &fileName, quint16 line, quint16 column,
- const QString &handlerName = QString(),
- const QString &parameterString = QString());
+ QQmlBoundSignalExpression(
+ QObject *target, int index, const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope,
+ const QString &expression, const QString &fileName, quint16 line, quint16 column,
+ const QString &handlerName = QString(), const QString &parameterString = QString());
- QQmlBoundSignalExpression(QObject *target, int index,
- QQmlContextData *ctxt, QObject *scopeObject, QV4::Function *function,
- QV4::ExecutionContext *scope = nullptr);
+ QQmlBoundSignalExpression(
+ QObject *target, int index, const QQmlRefPointer<QQmlContextData> &ctxt,
+ QObject *scopeObject, QV4::Function *function, QV4::ExecutionContext *scope = nullptr);
// inherited from QQmlJavaScriptExpression.
QString expressionIdentifier() const override;
@@ -87,12 +86,10 @@ public:
QString expression() const;
QObject *target() const { return m_target; }
- QQmlEngine *engine() const { return context() ? context()->engine : nullptr; }
-
private:
~QQmlBoundSignalExpression() override;
- void init(QQmlContextData *ctxt, QObject *scope);
+ void init(const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope);
bool expressionFunctionValid() const { return function() != nullptr; }
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 9ee4fdbe41..64e2c9a90e 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -521,6 +521,10 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, QObject *parent)
{
Q_D(QQmlComponent);
d->engine = engine;
+ QObject::connect(engine, &QObject::destroyed, this, [d]() {
+ d->state.creator.reset();
+ d->engine = nullptr;
+ });
}
/*!
@@ -635,7 +639,7 @@ void QQmlComponent::setData(const QByteArray &data, const QUrl &url)
QQmlContext *QQmlComponent::creationContext() const
{
Q_D(const QQmlComponent);
- if(d->creationContext)
+ if (!d->creationContext.isNull())
return d->creationContext->asQQmlContext();
return qmlContext(this);
@@ -879,15 +883,11 @@ QObject *QQmlComponent::createWithInitialProperties(const QVariantMap& initialPr
QObject *QQmlComponent::beginCreate(QQmlContext *publicContext)
{
Q_D(QQmlComponent);
-
Q_ASSERT(publicContext);
- QQmlContextData *context = QQmlContextData::get(publicContext);
-
- return d->beginCreate(context);
+ return d->beginCreate(QQmlContextData::get(publicContext));
}
-QObject *
-QQmlComponentPrivate::beginCreate(QQmlContextData *context)
+QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> context)
{
Q_Q(QQmlComponent);
if (!context) {
@@ -900,7 +900,7 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
return nullptr;
}
- if (context->engine != engine) {
+ if (context->engine() != engine) {
qWarning("QQmlComponent: Must create component in context from the same QQmlEngine");
return nullptr;
}
@@ -930,7 +930,7 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
enginePriv->referenceScarceResources();
QObject *rv = nullptr;
- state.creator.reset(new QQmlObjectCreator(context, compilationUnit, creationContext));
+ state.creator.reset(new QQmlObjectCreator(std::move(context), compilationUnit, creationContext));
rv = state.creator->create(start);
if (!rv)
state.errors = state.creator->errors;
@@ -963,8 +963,9 @@ void QQmlComponentPrivate::beginDeferred(QQmlEnginePrivate *enginePriv,
ConstructionState *state = new ConstructionState;
state->completePending = true;
- QQmlContextData *creationContext = nullptr;
- state->creator.reset(new QQmlObjectCreator(deferredData->context->parent, deferredData->compilationUnit, creationContext));
+ state->creator.reset(new QQmlObjectCreator(
+ deferredData->context->parent(), deferredData->compilationUnit,
+ QQmlRefPointer<QQmlContextData>()));
if (!state->creator->populateDeferredProperties(object, deferredData))
state->errors << state->creator->errors;
@@ -1082,16 +1083,16 @@ void QQmlComponentPrivate::completeCreate()
}
QQmlComponentAttached::QQmlComponentAttached(QObject *parent)
-: QObject(parent), prev(nullptr), next(nullptr)
+: QObject(parent), m_prev(nullptr), m_next(nullptr)
{
}
QQmlComponentAttached::~QQmlComponentAttached()
{
- if (prev) *prev = next;
- if (next) next->prev = prev;
- prev = nullptr;
- next = nullptr;
+ if (m_prev) *m_prev = m_next;
+ if (m_next) m_next->m_prev = m_prev;
+ m_prev = nullptr;
+ m_next = nullptr;
}
/*!
@@ -1107,12 +1108,12 @@ QQmlComponentAttached *QQmlComponent::qmlAttachedProperties(QObject *obj)
QQmlEnginePrivate *p = QQmlEnginePrivate::get(engine);
if (p->activeObjectCreator) { // XXX should only be allowed during begin
- a->add(p->activeObjectCreator->componentAttachment());
+ a->insertIntoList(p->activeObjectCreator->componentAttachment());
} else {
QQmlData *d = QQmlData::get(obj);
Q_ASSERT(d);
Q_ASSERT(d->context);
- a->add(&d->context->componentAttached);
+ d->context->addComponentAttached(a);
}
return a;
@@ -1138,24 +1139,23 @@ QQmlComponentAttached *QQmlComponent::qmlAttachedProperties(QObject *obj)
\sa QQmlIncubator
*/
-void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
- QQmlContext *forContext)
+void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context, QQmlContext *forContext)
{
Q_D(QQmlComponent);
if (!context)
context = d->engine->rootContext();
- QQmlContextData *contextData = QQmlContextData::get(context);
- QQmlContextData *forContextData = contextData;
- if (forContext) forContextData = QQmlContextData::get(forContext);
+ QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
+ QQmlRefPointer<QQmlContextData> forContextData =
+ forContext ? QQmlContextData::get(forContext) : contextData;
if (!contextData->isValid()) {
qWarning("QQmlComponent: Cannot create a component in an invalid context");
return;
}
- if (contextData->engine != d->engine) {
+ if (contextData->engine() != d->engine) {
qWarning("QQmlComponent: Must create component in context from the same QQmlEngine");
return;
}
@@ -1209,8 +1209,8 @@ void QQmlComponentPrivate::incubateObject(
QQmlIncubator *incubationTask,
QQmlComponent *component,
QQmlEngine *engine,
- QQmlContextData *context,
- QQmlContextData *forContext)
+ const QQmlRefPointer<QQmlContextData> &context,
+ const QQmlRefPointer<QQmlContextData> &forContext)
{
QQmlIncubatorPrivate *incubatorPriv = QQmlIncubatorPrivate::get(incubationTask);
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index a919eb45c0..cc938371a1 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -61,6 +61,7 @@
#include "qqml.h"
#include <private/qqmlobjectcreator_p.h>
#include <private/qqmltypedata_p.h>
+#include <private/qqmlguardedcontextdata_p.h>
#include <QtCore/QString>
#include <QtCore/QStringList>
@@ -84,7 +85,7 @@ public:
void loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous);
- QObject *beginCreate(QQmlContextData *);
+ QObject *beginCreate(QQmlRefPointer<QQmlContextData>);
void completeCreate();
void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate, RequiredProperties &requiredProperties);
static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v, RequiredProperties &requiredProperties, QObject *createdComponent);
@@ -94,8 +95,8 @@ public:
QQmlIncubator *incubationTask,
QQmlComponent *component,
QQmlEngine *engine,
- QQmlContextData *context,
- QQmlContextData *forContext);
+ const QQmlRefPointer<QQmlContextData> &context,
+ const QQmlRefPointer<QQmlContextData> &forContext);
QQmlRefPointer<QQmlTypeData> typeData;
void typeDataReady(QQmlTypeData *) override;
diff --git a/src/qml/qml/qqmlcomponentattached_p.h b/src/qml/qml/qqmlcomponentattached_p.h
index eb6d35652b..b94d474d1f 100644
--- a/src/qml/qml/qqmlcomponentattached_p.h
+++ b/src/qml/qml/qqmlcomponentattached_p.h
@@ -71,24 +71,33 @@ public:
QQmlComponentAttached(QObject *parent = nullptr);
~QQmlComponentAttached();
- void add(QQmlComponentAttached **a) {
- prev = a; next = *a; *a = this;
- if (next) next->prev = &next;
+ void insertIntoList(QQmlComponentAttached **listHead)
+ {
+ m_prev = listHead;
+ m_next = *listHead;
+ *listHead = this;
+ if (m_next)
+ m_next->m_prev = &m_next;
}
- void rem() {
- if (next) next->prev = prev;
- *prev = next;
- next = nullptr; prev = nullptr;
+
+ void removeFromList()
+ {
+ *m_prev = m_next;
+ if (m_next)
+ m_next->m_prev = m_prev;
+ m_next = nullptr;
+ m_prev = nullptr;
}
- QQmlComponentAttached **prev;
- QQmlComponentAttached *next;
+
+ QQmlComponentAttached *next() const { return m_next; }
Q_SIGNALS:
void completed();
void destruction();
private:
- friend class QQmlContextData;
+ QQmlComponentAttached **m_prev;
+ QQmlComponentAttached *m_next;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index abd379a320..a67eeeecc9 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -55,11 +55,6 @@
QT_BEGIN_NAMESPACE
-QQmlContextPrivate::QQmlContextPrivate()
-: data(nullptr), notifyIndex(-1)
-{
-}
-
/*!
\class QQmlContext
\brief The QQmlContext class defines a context within a QML engine.
@@ -157,13 +152,8 @@ QQmlContextPrivate::QQmlContextPrivate()
/*! \internal */
QQmlContext::QQmlContext(QQmlEngine *e, bool)
-: QObject(*(new QQmlContextPrivate))
+ : QObject(*(new QQmlContextPrivate(this, nullptr, e)))
{
- Q_D(QQmlContext);
- d->data = new QQmlContextData(this);
- ++d->data->refCount;
-
- d->data->engine = e;
}
/*!
@@ -171,13 +161,10 @@ QQmlContext::QQmlContext(QQmlEngine *e, bool)
QObject \a parent.
*/
QQmlContext::QQmlContext(QQmlEngine *engine, QObject *parent)
-: QObject(*(new QQmlContextPrivate), parent)
+ : QObject(*(new QQmlContextPrivate(
+ this, engine ? QQmlContextData::get(engine->rootContext()).data() : nullptr)),
+ parent)
{
- Q_D(QQmlContext);
- d->data = new QQmlContextData(this);
- ++d->data->refCount;
-
- d->data->setParent(engine?QQmlContextData::get(engine->rootContext()):nullptr);
}
/*!
@@ -185,24 +172,18 @@ QQmlContext::QQmlContext(QQmlEngine *engine, QObject *parent)
QObject \a parent.
*/
QQmlContext::QQmlContext(QQmlContext *parentContext, QObject *parent)
-: QObject(*(new QQmlContextPrivate), parent)
+ : QObject(*(new QQmlContextPrivate(
+ this, parentContext ? QQmlContextData::get(parentContext).data() : nullptr)),
+ parent)
{
- Q_D(QQmlContext);
- d->data = new QQmlContextData(this);
- ++d->data->refCount;
-
- d->data->setParent(parentContext?QQmlContextData::get(parentContext):nullptr);
}
/*!
\internal
*/
-QQmlContext::QQmlContext(QQmlContextData *data)
-: QObject(*(new QQmlContextPrivate), nullptr)
+QQmlContext::QQmlContext(QQmlContextPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
{
- Q_D(QQmlContext);
- d->data = data;
- // don't add a refcount here, as the data owns this context
}
/*!
@@ -215,10 +196,7 @@ QQmlContext::QQmlContext(QQmlContextData *data)
QQmlContext::~QQmlContext()
{
Q_D(QQmlContext);
-
- d->data->publicContext = nullptr;
- if (!--d->data->refCount)
- d->data->destroy();
+ d->m_data->clearPublicContext();
}
/*!
@@ -230,7 +208,7 @@ QQmlContext::~QQmlContext()
bool QQmlContext::isValid() const
{
Q_D(const QQmlContext);
- return d->data && d->data->isValid();
+ return d->m_data->isValid();
}
/*!
@@ -240,7 +218,7 @@ bool QQmlContext::isValid() const
QQmlEngine *QQmlContext::engine() const
{
Q_D(const QQmlContext);
- return d->data->engine;
+ return d->m_data->engine();
}
/*!
@@ -250,7 +228,10 @@ QQmlEngine *QQmlContext::engine() const
QQmlContext *QQmlContext::parentContext() const
{
Q_D(const QQmlContext);
- return d->data->parent?d->data->parent->asQQmlContext():nullptr;
+
+ if (QQmlRefPointer<QQmlContextData> parent = d->m_data->parent())
+ return parent->asQQmlContext();
+ return nullptr;
}
/*!
@@ -259,7 +240,7 @@ QQmlContext *QQmlContext::parentContext() const
QObject *QQmlContext::contextObject() const
{
Q_D(const QQmlContext);
- return d->data->contextObject;
+ return d->m_data->contextObject();
}
/*!
@@ -269,19 +250,19 @@ void QQmlContext::setContextObject(QObject *object)
{
Q_D(QQmlContext);
- QQmlContextData *data = d->data;
+ QQmlRefPointer<QQmlContextData> data = d->m_data;
- if (data->isInternal) {
+ if (data->isInternal()) {
qWarning("QQmlContext: Cannot set context object for internal context.");
return;
}
- if (!isValid()) {
+ if (!data->isValid()) {
qWarning("QQmlContext: Cannot set context object on invalid context.");
return;
}
- data->contextObject = object;
+ data->setContextObject(object);
data->refreshExpressions();
}
@@ -291,31 +272,30 @@ void QQmlContext::setContextObject(QObject *object)
void QQmlContext::setContextProperty(const QString &name, const QVariant &value)
{
Q_D(QQmlContext);
- if (d->notifyIndex == -1)
- d->notifyIndex = QMetaObjectPrivate::absoluteSignalCount(&QQmlContext::staticMetaObject);
+ if (d->notifyIndex() == -1)
+ d->setNotifyIndex(QMetaObjectPrivate::absoluteSignalCount(&QQmlContext::staticMetaObject));
- QQmlContextData *data = d->data;
+ QQmlRefPointer<QQmlContextData> data = d->m_data;
- if (data->isInternal) {
+ if (data->isInternal()) {
qWarning("QQmlContext: Cannot set property on internal context.");
return;
}
- if (!isValid()) {
+ if (!data->isValid()) {
qWarning("QQmlContext: Cannot set property on invalid context.");
return;
}
- QV4::IdentifierHash &properties = data->detachedPropertyNames();
- int idx = properties.value(name);
+ QV4::IdentifierHash *properties = data->detachedPropertyNames();
+ int idx = properties->value(name);
if (idx == -1) {
- properties.add(name, data->idValueCount + d->propertyValues.count());
- d->propertyValues.append(value);
-
+ properties->add(name, data->numIdValues() + d->numPropertyValues());
+ d->appendPropertyValue(value);
data->refreshExpressions();
} else {
- d->propertyValues[idx] = value;
- QMetaObject::activate(this, d->notifyIndex, idx, nullptr);
+ d->setPropertyValue(idx, value);
+ QMetaObject::activate(this, d->notifyIndex(), idx, nullptr);
}
if (auto *obj = qvariant_cast<QObject *>(value)) {
@@ -350,20 +330,15 @@ void QQmlContext::setContextProperties(const QVector<PropertyPair> &properties)
{
Q_D(const QQmlContext);
- QQmlContextData *data = d->data;
-
- QQmlJavaScriptExpression *expressions = data->expressions;
- QQmlContextData *childContexts = data->childContexts;
-
- data->expressions = nullptr;
- data->childContexts = nullptr;
+ QQmlRefPointer<QQmlContextData> data = d->m_data;
+ QQmlJavaScriptExpression *expressions = data->takeExpressions();
+ QQmlRefPointer<QQmlContextData> childContexts = data->takeChildContexts();
for (const auto &property : properties)
setContextProperty(property.name, property.value);
- data->expressions = expressions;
- data->childContexts = childContexts;
-
+ data->setExpressions(expressions);
+ data->setChildContexts(childContexts);
data->refreshExpressions();
}
@@ -389,28 +364,27 @@ QVariant QQmlContext::contextProperty(const QString &name) const
QVariant value;
int idx = -1;
- QQmlContextData *data = d->data;
+ QQmlRefPointer<QQmlContextData> data = d->m_data;
- const QV4::IdentifierHash &properties = data->propertyNames();
+ const QV4::IdentifierHash properties = data->propertyNames();
if (properties.count())
idx = properties.value(name);
if (idx == -1) {
- if (data->contextObject) {
- QObject *obj = data->contextObject;
+ if (QObject *obj = data->contextObject()) {
QQmlPropertyData local;
QQmlPropertyData *property =
- QQmlPropertyCache::property(data->engine, obj, name, data, local);
+ QQmlPropertyCache::property(data->engine(), obj, name, data, local);
if (property) value = obj->metaObject()->property(property->coreIndex()).read(obj);
}
if (!value.isValid() && parentContext())
value = parentContext()->contextProperty(name);
} else {
- if (idx >= d->propertyValues.count())
- value = QVariant::fromValue(data->idValues[idx - d->propertyValues.count()].data());
+ if (idx >= d->numPropertyValues())
+ value = QVariant::fromValue(data->idValue(idx - d->numPropertyValues()));
else
- value = d->propertyValues[idx];
+ value = d->propertyValue(idx);
}
return value;
@@ -427,7 +401,7 @@ QString QQmlContext::nameForObject(QObject *object) const
{
Q_D(const QQmlContext);
- return d->data->findObjectId(object);
+ return d->m_data->findObjectId(object);
}
/*!
@@ -439,37 +413,9 @@ QString QQmlContext::nameForObject(QObject *object) const
QUrl QQmlContext::resolvedUrl(const QUrl &src)
{
Q_D(QQmlContext);
- return d->data->resolvedUrl(src);
-}
-
-QUrl QQmlContextData::resolvedUrl(const QUrl &src)
-{
- QUrl resolved;
- if (src.isRelative() && !src.isEmpty()) {
- QQmlContextData *ctxt = this;
- do {
- if (ctxt->url().isValid())
- break;
- else
- ctxt = ctxt->parent;
- } while (ctxt);
-
- if (ctxt)
- resolved = ctxt->url().resolved(src);
- else if (engine)
- resolved = engine->baseUrl().resolved(src);
- } else {
- resolved = src;
- }
-
- if (resolved.isEmpty()) //relative but no ctxt
- return resolved;
-
- return engine ? engine->interceptUrl(resolved, QQmlAbstractUrlInterceptor::UrlString)
- : resolved;
+ return d->m_data->resolvedUrl(src);
}
-
/*!
Explicitly sets the url resolvedUrl() will use for relative references to \a baseUrl.
@@ -481,9 +427,8 @@ QUrl QQmlContextData::resolvedUrl(const QUrl &src)
void QQmlContext::setBaseUrl(const QUrl &baseUrl)
{
Q_D(QQmlContext);
-
- d->data->baseUrl = baseUrl;
- d->data->baseUrlString = baseUrl.toString();
+ d->m_data->setBaseUrl(baseUrl);
+ d->m_data->setBaseUrlString(baseUrl.toString());
}
/*!
@@ -493,14 +438,7 @@ void QQmlContext::setBaseUrl(const QUrl &baseUrl)
QUrl QQmlContext::baseUrl() const
{
Q_D(const QQmlContext);
- const QQmlContextData* data = d->data;
- while (data && data->url().isEmpty())
- data = data->parent;
-
- if (data)
- return data->url();
- else
- return QUrl();
+ return d->m_data->baseUrl();
}
int QQmlContextPrivate::context_count(QQmlListProperty<QObject> *prop)
@@ -509,11 +447,10 @@ int QQmlContextPrivate::context_count(QQmlListProperty<QObject> *prop)
QQmlContextPrivate *d = QQmlContextPrivate::get(context);
int contextProperty = (int)(quintptr)prop->data;
- if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) {
+ if (d->propertyValue(contextProperty).userType() != qMetaTypeId<QList<QObject*> >())
return 0;
- } else {
- return ((const QList<QObject> *)d->propertyValues.at(contextProperty).constData())->count();
- }
+ else
+ return ((const QList<QObject> *)d->propertyValue(contextProperty).constData())->count();
}
QObject *QQmlContextPrivate::context_at(QQmlListProperty<QObject> *prop, int index)
@@ -522,384 +459,40 @@ QObject *QQmlContextPrivate::context_at(QQmlListProperty<QObject> *prop, int ind
QQmlContextPrivate *d = QQmlContextPrivate::get(context);
int contextProperty = (int)(quintptr)prop->data;
- if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) {
+ if (d->propertyValue(contextProperty).userType() != qMetaTypeId<QList<QObject*> >())
return nullptr;
- } else {
- return ((const QList<QObject*> *)d->propertyValues.at(contextProperty).constData())->at(index);
- }
+ else
+ return ((const QList<QObject*> *)d->propertyValue(contextProperty).constData())->at(index);
}
void QQmlContextPrivate::dropDestroyedQObject(const QString &name, QObject *destroyed)
{
- if (!data->isValid())
+ if (!m_data->isValid())
return;
- const int idx = data->propertyNames().value(name);
+ const int idx = m_data->propertyNames().value(name);
Q_ASSERT(idx >= 0);
- if (qvariant_cast<QObject *>(propertyValues[idx]) != destroyed)
+ if (qvariant_cast<QObject *>(propertyValue(idx)) != destroyed)
return;
- propertyValues[idx] = QVariant::fromValue<QObject *>(nullptr);
- QMetaObject::activate(q_func(), notifyIndex, idx, nullptr);
-}
-
-
-QQmlContextData::QQmlContextData()
- : QQmlContextData(nullptr)
-{
-}
-
-QQmlContextData::QQmlContextData(QQmlContext *ctxt)
- : engine(nullptr), isInternal(false), isJSContext(false),
- isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
- stronglyReferencedByParent(false), hasExtraObject(false), publicContext(ctxt), incubator(nullptr), componentObjectIndex(-1),
- contextObject(nullptr), nextChild(nullptr), prevChild(nullptr),
- expressions(nullptr), contextObjects(nullptr), idValues(nullptr), idValueCount(0),
- componentAttached(nullptr)
-{
-}
-
-void QQmlContextData::emitDestruction()
-{
- if (!hasEmittedDestruction) {
- hasEmittedDestruction = true;
-
- // Emit the destruction signal - must be emitted before invalidate so that the
- // context is still valid if bindings or resultant expression evaluation requires it
- if (engine) {
- while (componentAttached) {
- QQmlComponentAttached *a = componentAttached;
- componentAttached = a->next;
- if (componentAttached) componentAttached->prev = &componentAttached;
-
- a->next = nullptr;
- a->prev = nullptr;
-
- emit a->destruction();
- }
-
- QQmlContextData * child = childContexts;
- while (child) {
- child->emitDestruction();
- child = child->nextChild;
- }
- }
- }
-}
-
-void QQmlContextData::invalidate()
-{
- emitDestruction();
-
- while (childContexts) {
- Q_ASSERT(childContexts != this);
- if (childContexts->stronglyReferencedByParent && !--childContexts->refCount)
- childContexts->destroy();
- else
- childContexts->invalidate();
- }
-
- if (prevChild) {
- *prevChild = nextChild;
- if (nextChild) nextChild->prevChild = prevChild;
- nextChild = nullptr;
- prevChild = nullptr;
- }
-
- importedScripts.clear();
-
- engine = nullptr;
- parent = nullptr;
-}
-
-void QQmlContextData::clearContextRecursively()
-{
- clearContext();
-
- for (auto ctxIt = childContexts; ctxIt; ctxIt = ctxIt->nextChild)
- ctxIt->clearContextRecursively();
-}
-
-void QQmlContextData::clearContext()
-{
- emitDestruction();
-
- QQmlJavaScriptExpression *expression = expressions;
- while (expression) {
- QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
-
- expression->m_prevExpression = nullptr;
- expression->m_nextExpression = nullptr;
-
- expression->setContext(nullptr);
-
- expression = nextExpression;
- }
- expressions = nullptr;
-}
-
-void QQmlContextData::destroy()
-{
- Q_ASSERT(refCount == 0);
- linkedContext = nullptr;
-
- // avoid recursion
- ++refCount;
- if (engine)
- invalidate();
-
- Q_ASSERT(refCount == 1);
- clearContext();
- Q_ASSERT(refCount == 1);
-
- while (contextObjects) {
- QQmlData *co = contextObjects;
- contextObjects = contextObjects->nextContextObject;
-
- if (co->context == this)
- co->context = nullptr;
- co->outerContext = nullptr;
- co->nextContextObject = nullptr;
- co->prevContextObject = nullptr;
- }
- Q_ASSERT(refCount == 1);
-
- QQmlGuardedContextData *contextGuard = contextGuards;
- while (contextGuard) {
- QQmlGuardedContextData *next = contextGuard->m_next;
- contextGuard->m_next = nullptr;
- contextGuard->m_prev = nullptr;
- contextGuard->m_contextData = nullptr;
- contextGuard = next;
- }
- contextGuards = nullptr;
- Q_ASSERT(refCount == 1);
-
- delete [] idValues;
- idValues = nullptr;
-
- Q_ASSERT(refCount == 1);
- if (publicContext) {
- // the QQmlContext destructor will remove one ref again
- ++refCount;
- delete publicContext;
- }
-
- Q_ASSERT(refCount == 1);
- --refCount;
- Q_ASSERT(refCount == 0);
-
- delete this;
-}
-
-void QQmlContextData::setParent(QQmlContextData *p, bool stronglyReferencedByParent)
-{
- if (p == parent)
- return;
- if (p) {
- Q_ASSERT(!parent);
- parent = p;
- this->stronglyReferencedByParent = stronglyReferencedByParent;
- if (stronglyReferencedByParent)
- ++refCount; // balanced in QQmlContextData::invalidate()
- engine = p->engine;
- nextChild = p->childContexts;
- if (nextChild) nextChild->prevChild = &nextChild;
- prevChild = &p->childContexts;
- p->childContexts = this;
- }
-}
-
-void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
-{
- QQmlJavaScriptExpression::DeleteWatcher w(expression);
-
- if (expression->m_nextExpression)
- refreshExpressionsRecursive(expression->m_nextExpression);
-
- if (!w.wasDeleted())
- expression->refresh();
-}
-
-QQmlContextData::~QQmlContextData()
-{
-}
-
-static inline bool expressions_to_run(QQmlContextData *ctxt, bool isGlobalRefresh)
-{
- return ctxt->expressions && (!isGlobalRefresh || ctxt->unresolvedNames);
-}
-
-void QQmlContextData::refreshExpressionsRecursive(bool isGlobal)
-{
- // For efficiency, we try and minimize the number of guards we have to create
- if (expressions_to_run(this, isGlobal) && (nextChild || childContexts)) {
- QQmlGuardedContextData guard(this);
-
- if (childContexts)
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- if (guard.isNull()) return;
-
- if (nextChild)
- nextChild->refreshExpressionsRecursive(isGlobal);
-
- if (guard.isNull()) return;
-
- if (expressions_to_run(this, isGlobal))
- refreshExpressionsRecursive(expressions);
-
- } else if (expressions_to_run(this, isGlobal)) {
-
- refreshExpressionsRecursive(expressions);
-
- } else if (nextChild && childContexts) {
-
- QQmlGuardedContextData guard(this);
-
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- if (!guard.isNull() && nextChild)
- nextChild->refreshExpressionsRecursive(isGlobal);
-
- } else if (nextChild) {
-
- nextChild->refreshExpressionsRecursive(isGlobal);
-
- } else if (childContexts) {
-
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- }
-}
-
-// Refreshes all expressions that could possibly depend on this context. Refreshing flushes all
-// context-tree dependent caches in the expressions, and should occur every time the context tree
-// *structure* (not values) changes.
-void QQmlContextData::refreshExpressions()
-{
- bool isGlobal = (parent == nullptr);
-
- // For efficiency, we try and minimize the number of guards we have to create
- if (expressions_to_run(this, isGlobal) && childContexts) {
- QQmlGuardedContextData guard(this);
-
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- if (!guard.isNull() && expressions_to_run(this, isGlobal))
- refreshExpressionsRecursive(expressions);
-
- } else if (expressions_to_run(this, isGlobal)) {
-
- refreshExpressionsRecursive(expressions);
-
- } else if (childContexts) {
-
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- }
-}
-
-void QQmlContextData::addObject(QQmlData *data)
-{
- if (data->outerContext) {
- if (data->nextContextObject)
- data->nextContextObject->prevContextObject = data->prevContextObject;
- if (data->prevContextObject)
- *data->prevContextObject = data->nextContextObject;
- else if (data->outerContext->contextObjects == data)
- data->outerContext->contextObjects = data->nextContextObject;
- }
-
- data->outerContext = this;
-
- data->nextContextObject = contextObjects;
- if (data->nextContextObject)
- data->nextContextObject->prevContextObject = &data->nextContextObject;
- data->prevContextObject = &contextObjects;
- contextObjects = data;
-}
-
-void QQmlContextData::setIdProperty(int idx, QObject *obj)
-{
- idValues[idx] = obj;
- idValues[idx].context = this;
-}
-
-QString QQmlContextData::findObjectId(const QObject *obj) const
-{
- const QV4::IdentifierHash &properties = propertyNames();
- if (propertyNameCache.isEmpty())
- return QString();
-
- for (int ii = 0; ii < idValueCount; ii++) {
- if (idValues[ii] == obj)
- return properties.findId(ii);
- }
-
- if (publicContext) {
- QQmlContextPrivate *p = QQmlContextPrivate::get(publicContext);
- for (int ii = 0; ii < p->propertyValues.count(); ++ii)
- if (p->propertyValues.at(ii) == QVariant::fromValue(const_cast<QObject *>(obj)))
- return properties.findId(ii);
- }
-
- if (linkedContext)
- return linkedContext->findObjectId(obj);
- return QString();
-}
-
-QQmlContext *QQmlContextData::asQQmlContext()
-{
- if (!publicContext)
- publicContext = new QQmlContext(this);
- return publicContext;
-}
-
-QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
-{
- return QQmlContextPrivate::get(asQQmlContext());
-}
-
-void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int subComponentIndex)
-{
- typeCompilationUnit = unit;
- componentObjectIndex = subComponentIndex == -1 ? /*root object*/0 : subComponentIndex;
- Q_ASSERT(!idValues);
- idValueCount = typeCompilationUnit->objectAt(componentObjectIndex)->nNamedObjectsInComponent;
- idValues = new ContextGuard[idValueCount];
-}
-
-const QV4::IdentifierHash &QQmlContextData::propertyNames() const
-{
- if (propertyNameCache.isEmpty()) {
- if (typeCompilationUnit)
- propertyNameCache = typeCompilationUnit->namedObjectsPerComponent(componentObjectIndex);
- else
- propertyNameCache = QV4::IdentifierHash(engine->handle());
- }
- return propertyNameCache;
-}
-
-QV4::IdentifierHash &QQmlContextData::detachedPropertyNames()
-{
- propertyNames();
- propertyNameCache.detach();
- return propertyNameCache;
+ setPropertyValue(idx, QVariant::fromValue<QObject *>(nullptr));
+ QMetaObject::activate(q_func(), notifyIndex(), idx, nullptr);
}
-QUrl QQmlContextData::url() const
+void QQmlContextPrivate::emitDestruction()
{
- if (typeCompilationUnit)
- return typeCompilationUnit->finalUrl();
- return baseUrl;
+ m_data->emitDestruction();
}
-QString QQmlContextData::urlString() const
+// m_data is owned by the public context. When the public context is reset to nullptr, it will be
+// deref'd. It's OK to pass a half-created publicContext here. We will not dereference it during
+// construction.
+QQmlContextPrivate::QQmlContextPrivate(
+ QQmlContext *publicContext, QQmlContextData *parent, QQmlEngine *engine) :
+ m_data(new QQmlContextData(QQmlContextData::OwnedByPublicContext, publicContext,
+ parent, engine))
{
- if (typeCompilationUnit)
- return typeCompilationUnit->finalUrlString();
- return baseUrlString;
+ Q_ASSERT(publicContext != nullptr);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h
index 7ed70c7619..f12a94ef9d 100644
--- a/src/qml/qml/qqmlcontext.h
+++ b/src/qml/qml/qqmlcontext.h
@@ -100,7 +100,7 @@ private:
friend class QQmlComponentPrivate;
friend class QQmlScriptPrivate;
friend class QQmlContextData;
- QQmlContext(QQmlContextData *);
+ QQmlContext(QQmlContextPrivate &dd, QObject *parent = nullptr);
QQmlContext(QQmlEngine *, bool);
Q_DISABLE_COPY(QQmlContext)
};
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index f93393a11b..ca49cbf963 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -51,342 +51,73 @@
// We mean it.
//
-#include "qqmlcontext.h"
+#include <QtCore/qlist.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qpointer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmllist.h>
-#include "qqmldata_p.h"
-#include "qqmltypenamecache_p.h"
-#include "qqmlnotifier_p.h"
-#include "qqmllist.h"
-
-#include <QtCore/qhash.h>
-#include <QtQml/qjsvalue.h>
-#include <QtCore/qset.h>
-
-#include <private/qobject_p.h>
-#include <private/qflagpointer_p.h>
-#include <private/qqmlguard_p.h>
-
-#include <private/qv4executablecompilationunit_p.h>
-#include <private/qv4identifier_p.h>
+#include <QtCore/private/qobject_p.h>
+#include <QtQml/private/qqmlrefcount_p.h>
QT_BEGIN_NAMESPACE
-class QQmlContext;
-class QQmlExpression;
-class QQmlEngine;
-class QQmlExpression;
-class QQmlExpressionPrivate;
-class QQmlJavaScriptExpression;
class QQmlContextData;
-class QQmlGuardedContextData;
-class QQmlIncubatorPrivate;
class QQmlContextPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQmlContext)
public:
- QQmlContextPrivate();
-
- QQmlContextData *data;
-
- QList<QVariant> propertyValues;
- int notifyIndex;
-
static QQmlContextPrivate *get(QQmlContext *context) {
return static_cast<QQmlContextPrivate *>(QObjectPrivate::get(context));
}
+
static QQmlContext *get(QQmlContextPrivate *context) {
return static_cast<QQmlContext *>(context->q_func());
}
- // Only used for debugging
- QList<QPointer<QObject> > instances;
-
static int context_count(QQmlListProperty<QObject> *);
static QObject *context_at(QQmlListProperty<QObject> *, int);
void dropDestroyedQObject(const QString &name, QObject *destroyed);
-};
-
-class QQmlComponentAttached;
-
-class Q_QML_PRIVATE_EXPORT QQmlContextData
-{
-public:
- QQmlContextData();
- QQmlContextData(QQmlContext *);
- void emitDestruction();
- void clearContext();
- void clearContextRecursively();
- void invalidate();
-
- inline bool isValid() const {
- return engine && (!isInternal || !contextObject || !QObjectPrivate::get(contextObject)->wasDeleted);
- }
-
- // My parent context and engine
- QQmlContextData *parent = nullptr;
- QQmlEngine *engine;
-
- void setParent(QQmlContextData *, bool stronglyReferencedByParent = false);
- void refreshExpressions();
-
- void addObject(QQmlData *data);
-
- QUrl resolvedUrl(const QUrl &);
-
- // My containing QQmlContext. If isInternal is true this owns publicContext.
- // If internal is false publicContext owns this.
- QQmlContext *asQQmlContext();
- QQmlContextPrivate *asQQmlContextPrivate();
- quint32 refCount = 0;
- quint32 isInternal:1;
- quint32 isJSContext:1;
- quint32 isPragmaLibraryContext:1;
- quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name
- quint32 hasEmittedDestruction:1;
- quint32 isRootObjectInCreation:1;
- quint32 stronglyReferencedByParent:1;
- quint32 hasExtraObject:1; // used in QQmlDelegateModelItem::dataForObject to find the corresponding QQmlDelegateModelItem of an object
- quint32 dummy:24;
- QQmlContext *publicContext;
- union {
- // The incubator that is constructing this context if any
- QQmlIncubatorPrivate *incubator;
- // a pointer to extra data, currently only used in QQmlDelegateModel
- QObject *extraObject;
- };
+ int notifyIndex() const { return m_notifyIndex; }
+ void setNotifyIndex(int notifyIndex) { m_notifyIndex = notifyIndex; }
- // Compilation unit for contexts that belong to a compiled type.
- QQmlRefPointer<QV4::ExecutableCompilationUnit> typeCompilationUnit;
+ int numPropertyValues() const { return m_propertyValues.count(); }
+ void appendPropertyValue(const QVariant &value) { m_propertyValues.append(value); }
+ void setPropertyValue(int index, const QVariant &value) { m_propertyValues[index] = value; }
+ QVariant propertyValue(int index) const { return m_propertyValues[index]; }
- // object index in CompiledData::Unit to component that created this context
- int componentObjectIndex;
-
- void initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int subComponentIndex);
-
- // flag indicates whether the context owns the cache (after mutation) or not.
- mutable QV4::IdentifierHash propertyNameCache;
- const QV4::IdentifierHash &propertyNames() const;
- QV4::IdentifierHash &detachedPropertyNames();
-
- // Context object
- QObject *contextObject;
-
- // Any script blocks that exist on this context
- QV4::PersistentValue importedScripts; // This is a JS Array
-
- QUrl baseUrl;
- QString baseUrlString;
-
- QUrl url() const;
- QString urlString() const;
-
- // List of imports that apply to this context
- QQmlRefPointer<QQmlTypeNameCache> imports;
-
- // My children
- QQmlContextData *childContexts = nullptr;
-
- // My peers in parent's childContexts list
- QQmlContextData *nextChild;
- QQmlContextData **prevChild;
-
- // Expressions that use this context
- QQmlJavaScriptExpression *expressions;
-
- // Doubly-linked list of objects that are owned by this context
- QQmlData *contextObjects;
-
- // Doubly-linked list of context guards (XXX merge with contextObjects)
- QQmlGuardedContextData *contextGuards = nullptr;
-
- // id guards
- struct ContextGuard : public QQmlGuard<QObject>
+ QList<QPointer<QObject>> instances() const { return m_instances; }
+ void appendInstance(QObject *instance) { m_instances.append(instance); }
+ void cleanInstances()
{
- inline ContextGuard();
- inline ContextGuard &operator=(QObject *obj);
- inline void objectDestroyed(QObject *) override;
-
- inline bool wasSet() const;
-
- QFlagPointer<QQmlContextData> context;
- QQmlNotifier bindings;
- };
- ContextGuard *idValues;
- int idValueCount;
- void setIdProperty(int, QObject *);
-
- // Linked contexts. this owns linkedContext.
- QQmlContextDataRef linkedContext;
-
- // Linked list of uses of the Component attached property in this
- // context
- QQmlComponentAttached *componentAttached;
-
- // Return the outermost id for obj, if any.
- QString findObjectId(const QObject *obj) const;
-
- static QQmlContextData *get(QQmlContext *context) {
- return QQmlContextPrivate::get(context)->data;
+ for (auto it = m_instances.begin(); it != m_instances.end();
+ it->isNull() ? (it = m_instances.erase(it)) : ++it) {}
}
-private:
- friend class QQmlContextDataRef;
- friend class QQmlContext; // needs to do manual refcounting :/
- void refreshExpressionsRecursive(bool isGlobal);
- void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
- ~QQmlContextData();
- void destroy();
-};
-
-
-class QQmlGuardedContextData
-{
-public:
- inline QQmlGuardedContextData() = default;
- inline QQmlGuardedContextData(QQmlContextData *data)
- { setContextData(data); }
- inline ~QQmlGuardedContextData()
- { clear(); }
-
- inline QQmlContextData *contextData() const
- { return m_contextData; }
- inline void setContextData(QQmlContextData *);
-
- inline bool isNull() const { return !m_contextData; }
-
- inline operator QQmlContextData*() const { return m_contextData; }
- inline QQmlContextData* operator->() const { return m_contextData; }
- inline QQmlGuardedContextData &operator=(QQmlContextData *d) {
- setContextData(d); return *this;
- }
+ void emitDestruction();
private:
- QQmlGuardedContextData &operator=(const QQmlGuardedContextData &) = delete;
- QQmlGuardedContextData(const QQmlGuardedContextData &) = delete;
friend class QQmlContextData;
- inline void clear();
-
- QQmlContextData *m_contextData = nullptr;
- QQmlGuardedContextData *m_next = nullptr;
- QQmlGuardedContextData **m_prev = nullptr;
-};
-
-
-void QQmlGuardedContextData::setContextData(QQmlContextData *contextData)
- {
- if (m_contextData == contextData)
- return;
- clear();
-
- if (contextData) {
- m_contextData = contextData;
- m_next = contextData->contextGuards;
- if (m_next) m_next->m_prev = &m_next;
- m_prev = &contextData->contextGuards;
- contextData->contextGuards = this;
- }
-}
-
-void QQmlGuardedContextData::clear()
-{
- if (m_prev) {
- *m_prev = m_next;
- if (m_next) m_next->m_prev = m_prev;
- m_contextData = nullptr;
- m_next = nullptr;
- m_prev = nullptr;
- }
-}
-
-QQmlContextDataRef::QQmlContextDataRef()
- : m_contextData(nullptr)
-{
-}
-
-QQmlContextDataRef::QQmlContextDataRef(const QQmlContextDataRef &other)
- : m_contextData(other.m_contextData)
-{
- if (m_contextData)
- ++m_contextData->refCount;
-}
-
-QQmlContextDataRef::QQmlContextDataRef(QQmlContextData *data)
- : m_contextData(data)
-{
- if (m_contextData)
- ++m_contextData->refCount;
-}
-
-QQmlContextDataRef::~QQmlContextDataRef()
-{
- clear();
-}
-
-void QQmlContextDataRef::setContextData(QQmlContextData *contextData)
-{
- if (m_contextData == contextData)
- return;
- clear();
-
- if (contextData) {
- m_contextData = contextData;
- ++m_contextData->refCount;
- }
-}
-
-QQmlContextData *QQmlContextDataRef::contextData() const
-{
- return m_contextData;
-}
-
-void QQmlContextDataRef::clear()
-{
- if (m_contextData && !--m_contextData->refCount)
- m_contextData->destroy();
- m_contextData = nullptr;
-}
+ QQmlContextPrivate(QQmlContextData *data) : m_data(data) {}
+ QQmlContextPrivate(QQmlContext *publicContext, QQmlContextData *parent,
+ QQmlEngine *engine = nullptr);
-QQmlContextDataRef &
-QQmlContextDataRef::operator=(QQmlContextData *d)
-{
- setContextData(d);
- return *this;
-}
-
-QQmlContextDataRef &
-QQmlContextDataRef::operator=(const QQmlContextDataRef &other)
-{
- setContextData(other.m_contextData);
- return *this;
-}
+ // Intentionally a bare pointer. QQmlContextData knows whether it owns QQmlContext or vice
+ // versa. If QQmlContext is the owner, QQmlContextData keeps an extra ref for its publicContext.
+ // The publicContext ref is released when doing QQmlContextData::setPublicContext(nullptr).
+ QQmlContextData *m_data;
-QQmlContextData::ContextGuard::ContextGuard()
-: context(nullptr)
-{
-}
-
-QQmlContextData::ContextGuard &QQmlContextData::ContextGuard::operator=(QObject *obj)
-{
- QQmlGuard<QObject>::operator=(obj);
- context.setFlag();
- bindings.notify(); // For alias connections
- return *this;
-}
+ QList<QVariant> m_propertyValues;
+ int m_notifyIndex = -1;
-void QQmlContextData::ContextGuard::objectDestroyed(QObject *)
-{
- if (context->contextObject && !QObjectPrivate::get(context->contextObject)->wasDeleted)
- bindings.notify();
-}
-
-bool QQmlContextData::ContextGuard::wasSet() const
-{
- return context.flag();
-}
+ // Only used for debugging
+ QList<QPointer<QObject>> m_instances;
+};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontextdata.cpp b/src/qml/qml/qqmlcontextdata.cpp
new file mode 100644
index 0000000000..33be23b14d
--- /dev/null
+++ b/src/qml/qml/qqmlcontextdata.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlcontextdata_p.h"
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/private/qqmlcomponentattached_p.h>
+#include <QtQml/private/qqmljavascriptexpression_p.h>
+#include <QtQml/private/qqmlguardedcontextdata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QUrl QQmlContextData::resolvedUrl(const QUrl &src)
+{
+ QUrl resolved;
+ if (src.isRelative() && !src.isEmpty()) {
+ QQmlRefPointer<QQmlContextData> ctxt = this;
+ do {
+ if (ctxt->url().isValid())
+ break;
+ else
+ ctxt = ctxt->parent();
+ } while (ctxt);
+
+ if (ctxt)
+ resolved = ctxt->url().resolved(src);
+ else if (m_engine)
+ resolved = m_engine->baseUrl().resolved(src);
+ } else {
+ resolved = src;
+ }
+
+ if (resolved.isEmpty()) //relative but no ctxt
+ return resolved;
+
+ return m_engine ? m_engine->interceptUrl(resolved, QQmlAbstractUrlInterceptor::UrlString)
+ : resolved;
+}
+
+void QQmlContextData::emitDestruction()
+{
+ if (!m_hasEmittedDestruction) {
+ m_hasEmittedDestruction = true;
+
+ // Emit the destruction signal - must be emitted before invalidate so that the
+ // context is still valid if bindings or resultant expression evaluation requires it
+ if (m_engine) {
+ while (m_componentAttacheds) {
+ QQmlComponentAttached *attached = m_componentAttacheds;
+ attached->removeFromList();
+ emit attached->destruction();
+ }
+
+ for (QQmlContextData *child = m_childContexts; child; child = child->m_nextChild)
+ child->emitDestruction();
+ }
+ }
+}
+
+void QQmlContextData::invalidate()
+{
+ emitDestruction();
+
+ while (m_childContexts) {
+ Q_ASSERT(m_childContexts != this);
+ m_childContexts->invalidate();
+ }
+
+ if (m_prevChild) {
+ *m_prevChild = m_nextChild;
+ if (m_nextChild) m_nextChild->m_prevChild = m_prevChild;
+ m_nextChild = nullptr;
+ m_prevChild = nullptr;
+ }
+
+ m_importedScripts.clear();
+
+ m_engine = nullptr;
+ clearParent();
+}
+
+void QQmlContextData::clearContextRecursively()
+{
+ clearContext();
+
+ for (auto ctxIt = m_childContexts; ctxIt; ctxIt = ctxIt->m_nextChild)
+ ctxIt->clearContextRecursively();
+}
+
+void QQmlContextData::clearContext()
+{
+ emitDestruction();
+
+ QQmlJavaScriptExpression *expression = m_expressions;
+ while (expression) {
+ QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
+
+ expression->m_prevExpression = nullptr;
+ expression->m_nextExpression = nullptr;
+
+ expression->setContext(nullptr);
+
+ expression = nextExpression;
+ }
+ m_expressions = nullptr;
+}
+
+QQmlContextData::~QQmlContextData()
+{
+ Q_ASSERT(refCount() == 0);
+ m_linkedContext = nullptr;
+
+ // avoid recursion
+ addref();
+ if (m_engine)
+ invalidate();
+
+ Q_ASSERT(refCount() == 1);
+ clearContext();
+ Q_ASSERT(refCount() == 1);
+
+ while (m_ownedObjects) {
+ QQmlData *co = m_ownedObjects;
+ m_ownedObjects = m_ownedObjects->nextContextObject;
+
+ if (co->context == this)
+ co->context = nullptr;
+ co->outerContext = nullptr;
+ co->nextContextObject = nullptr;
+ co->prevContextObject = nullptr;
+ }
+ Q_ASSERT(refCount() == 1);
+
+ QQmlGuardedContextData *contextGuard = m_contextGuards;
+ while (contextGuard) {
+ QQmlGuardedContextData *next = contextGuard->next();
+ next->reset();
+ contextGuard = next;
+ }
+ m_contextGuards = nullptr;
+ Q_ASSERT(refCount() == 1);
+
+ delete [] m_idValues;
+ m_idValues = nullptr;
+
+ Q_ASSERT(refCount() == 1);
+ if (m_publicContext)
+ delete m_publicContext;
+
+ Q_ASSERT(refCount() == 1);
+}
+
+void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
+{
+ QQmlJavaScriptExpression::DeleteWatcher w(expression);
+
+ if (expression->m_nextExpression)
+ refreshExpressionsRecursive(expression->m_nextExpression);
+
+ if (!w.wasDeleted())
+ expression->refresh();
+}
+
+void QQmlContextData::refreshExpressionsRecursive(bool isGlobal)
+{
+ // For efficiency, we try and minimize the number of guards we have to create
+ if (hasExpressionsToRun(isGlobal) && (m_nextChild || m_childContexts)) {
+ QQmlGuardedContextData guard(this);
+
+ if (m_childContexts)
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+
+ if (guard.isNull()) return;
+
+ if (m_nextChild)
+ m_nextChild->refreshExpressionsRecursive(isGlobal);
+
+ if (guard.isNull()) return;
+
+ if (hasExpressionsToRun(isGlobal))
+ refreshExpressionsRecursive(m_expressions);
+
+ } else if (hasExpressionsToRun(isGlobal)) {
+ refreshExpressionsRecursive(m_expressions);
+ } else if (m_nextChild && m_childContexts) {
+ QQmlGuardedContextData guard(this);
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+ if (!guard.isNull() && m_nextChild)
+ m_nextChild->refreshExpressionsRecursive(isGlobal);
+ } else if (m_nextChild) {
+ m_nextChild->refreshExpressionsRecursive(isGlobal);
+ } else if (m_childContexts) {
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+ }
+}
+
+// Refreshes all expressions that could possibly depend on this context. Refreshing flushes all
+// context-tree dependent caches in the expressions, and should occur every time the context tree
+// *structure* (not values) changes.
+void QQmlContextData::refreshExpressions()
+{
+ bool isGlobal = (m_parent == nullptr);
+
+ // For efficiency, we try and minimize the number of guards we have to create
+ if (hasExpressionsToRun(isGlobal) && m_childContexts) {
+ QQmlGuardedContextData guard(this);
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+ if (!guard.isNull() && hasExpressionsToRun(isGlobal))
+ refreshExpressionsRecursive(m_expressions);
+ } else if (hasExpressionsToRun(isGlobal)) {
+ refreshExpressionsRecursive(m_expressions);
+ } else if (m_childContexts) {
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+ }
+}
+
+void QQmlContextData::addOwnedObject(QQmlData *data)
+{
+ if (data->outerContext) {
+ if (data->nextContextObject)
+ data->nextContextObject->prevContextObject = data->prevContextObject;
+ if (data->prevContextObject)
+ *data->prevContextObject = data->nextContextObject;
+ else if (data->outerContext->m_ownedObjects == data)
+ data->outerContext->m_ownedObjects = data->nextContextObject;
+ }
+
+ data->outerContext = this;
+
+ data->nextContextObject = m_ownedObjects;
+ if (data->nextContextObject)
+ data->nextContextObject->prevContextObject = &data->nextContextObject;
+ data->prevContextObject = &m_ownedObjects;
+ m_ownedObjects = data;
+}
+
+void QQmlContextData::setIdValue(int idx, QObject *obj)
+{
+ m_idValues[idx] = obj;
+ m_idValues[idx].setContext(this);
+}
+
+QString QQmlContextData::findObjectId(const QObject *obj) const
+{
+ const QV4::IdentifierHash &properties = propertyNames();
+ if (m_propertyNameCache.isEmpty())
+ return QString();
+
+ for (int ii = 0; ii < m_idValueCount; ii++) {
+ if (m_idValues[ii] == obj)
+ return properties.findId(ii);
+ }
+
+ if (m_publicContext) {
+ QQmlContextPrivate *p = QQmlContextPrivate::get(m_publicContext);
+ for (int ii = 0; ii < p->numPropertyValues(); ++ii)
+ if (p->propertyValue(ii) == QVariant::fromValue(const_cast<QObject *>(obj)))
+ return properties.findId(ii);
+ }
+
+ if (m_linkedContext)
+ return m_linkedContext->findObjectId(obj);
+ return QString();
+}
+
+QQmlContext *QQmlContextData::asQQmlContext()
+{
+ if (!m_publicContext)
+ m_publicContext = new QQmlContext(*new QQmlContextPrivate(this));
+ return m_publicContext;
+}
+
+QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
+{
+ return QQmlContextPrivate::get(asQQmlContext());
+}
+
+void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int subComponentIndex)
+{
+ m_typeCompilationUnit = unit;
+ m_componentObjectIndex = subComponentIndex == -1 ? /*root object*/0 : subComponentIndex;
+ Q_ASSERT(!m_idValues);
+ m_idValueCount = m_typeCompilationUnit->objectAt(m_componentObjectIndex)
+ ->nNamedObjectsInComponent;
+ m_idValues = new ContextGuard[m_idValueCount];
+}
+
+void QQmlContextData::addComponentAttached(QQmlComponentAttached *attached)
+{
+ attached->insertIntoList(&m_componentAttacheds);
+}
+
+void QQmlContextData::addExpression(QQmlJavaScriptExpression *expression)
+{
+ expression->insertIntoList(&m_expressions);
+}
+
+QV4::IdentifierHash QQmlContextData::propertyNames() const
+{
+ if (m_propertyNameCache.isEmpty()) {
+ if (m_typeCompilationUnit)
+ m_propertyNameCache = m_typeCompilationUnit->namedObjectsPerComponent(m_componentObjectIndex);
+ else
+ m_propertyNameCache = QV4::IdentifierHash(m_engine->handle());
+ }
+ return m_propertyNameCache;
+}
+
+QV4::IdentifierHash *QQmlContextData::detachedPropertyNames()
+{
+ propertyNames();
+ m_propertyNameCache.detach();
+ return &m_propertyNameCache;
+}
+
+QUrl QQmlContextData::url() const
+{
+ if (m_typeCompilationUnit)
+ return m_typeCompilationUnit->finalUrl();
+ return m_baseUrl;
+}
+
+QString QQmlContextData::urlString() const
+{
+ if (m_typeCompilationUnit)
+ return m_typeCompilationUnit->finalUrlString();
+ return m_baseUrlString;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontextdata_p.h b/src/qml/qml/qqmlcontextdata_p.h
new file mode 100644
index 0000000000..e31a45dea4
--- /dev/null
+++ b/src/qml/qml/qqmlcontextdata_p.h
@@ -0,0 +1,427 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLCONTEXTDATA_P_H
+#define QQMLCONTEXTDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/private/qqmlglobal_p.h>
+#include <QtQml/private/qqmlcontext_p.h>
+#include <QtQml/private/qqmlguard_p.h>
+#include <QtQml/private/qqmltypenamecache_p.h>
+#include <QtQml/private/qv4identifier_p.h>
+#include <QtQml/private/qv4executablecompilationunit_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlComponentAttached;
+class QQmlGuardedContextData;
+class QQmlJavaScriptExpression;
+class QQmlIncubatorPrivate;
+
+class Q_QML_PRIVATE_EXPORT QQmlContextData
+{
+public:
+ static QQmlRefPointer<QQmlContextData> createRefCounted(
+ const QQmlRefPointer<QQmlContextData> &parent)
+ {
+ return QQmlRefPointer<QQmlContextData>(new QQmlContextData(RefCounted, nullptr, parent),
+ QQmlRefPointer<QQmlContextData>::Adopt);
+ }
+
+ // Owned by the parent. When the parent is reset to nullptr, it will be deref'd.
+ static QQmlRefPointer<QQmlContextData> createChild(
+ const QQmlRefPointer<QQmlContextData> &parent)
+ {
+ Q_ASSERT(!parent.isNull());
+ return QQmlRefPointer<QQmlContextData>(new QQmlContextData(OwnedByParent, nullptr, parent));
+ }
+
+ void addref() const { ++m_refCount; }
+ void release() const { if (--m_refCount == 0) delete this; }
+ int count() const { return m_refCount; }
+ int refCount() const { return m_refCount; }
+
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> typeCompilationUnit() const
+ {
+ return m_typeCompilationUnit;
+ }
+ void initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
+ int subComponentIndex);
+
+ static QQmlRefPointer<QQmlContextData> get(QQmlContext *context) {
+ return QQmlContextPrivate::get(context)->m_data;
+ }
+
+ void emitDestruction();
+ void clearContext();
+ void clearContextRecursively();
+ void invalidate();
+
+ bool isValid() const
+ {
+ return m_engine && (!m_isInternal || !m_contextObject
+ || !QObjectPrivate::get(m_contextObject)->wasDeleted);
+ }
+
+ bool isInternal() const { return m_isInternal; }
+ void setInternal(bool isInternal) { m_isInternal = isInternal; }
+
+ bool isJSContext() const { return m_isJSContext; }
+ void setJSContext(bool isJSContext) { m_isJSContext = isJSContext; }
+
+ bool isPragmaLibraryContext() const { return m_isPragmaLibraryContext; }
+ void setPragmaLibraryContext(bool library) { m_isPragmaLibraryContext = library; }
+
+ QQmlRefPointer<QQmlContextData> parent() const { return m_parent; }
+ void clearParent()
+ {
+ if (!m_parent)
+ return;
+
+ m_parent = nullptr;
+ if (m_ownedByParent) {
+ m_ownedByParent = false;
+ release();
+ }
+ }
+
+ void refreshExpressions();
+
+ void addOwnedObject(QQmlData *ownedObject);
+ QQmlData *ownedObjects() const { return m_ownedObjects; }
+ void setOwnedObjects(QQmlData *ownedObjects) { m_ownedObjects = ownedObjects; }
+
+ QUrl resolvedUrl(const QUrl &);
+
+ // My containing QQmlContext. If isInternal is true this owns publicContext.
+ // If internal is false publicContext owns this.
+ QQmlContext *asQQmlContext();
+ QQmlContextPrivate *asQQmlContextPrivate();
+
+ QObject *contextObject() const { return m_contextObject; }
+ void setContextObject(QObject *contextObject) { m_contextObject = contextObject; }
+
+ QQmlEngine *engine() const { return m_engine; }
+ void setEngine(QQmlEngine *engine) { m_engine = engine; }
+
+ QQmlContext *publicContext() const { return m_publicContext; }
+ void clearPublicContext()
+ {
+ if (!m_publicContext)
+ return;
+
+ m_publicContext = nullptr;
+ if (m_ownedByPublicContext) {
+ m_ownedByPublicContext = false;
+ release();
+ }
+ }
+
+ QV4::IdentifierHash propertyNames() const;
+ QV4::IdentifierHash *detachedPropertyNames();
+
+ void setExpressions(QQmlJavaScriptExpression *expressions) { m_expressions = expressions; }
+ QQmlJavaScriptExpression *takeExpressions()
+ {
+ QQmlJavaScriptExpression *expressions = m_expressions;
+ m_expressions = nullptr;
+ return expressions;
+ }
+
+ void setChildContexts(const QQmlRefPointer<QQmlContextData> &childContexts)
+ {
+ m_childContexts = childContexts.data();
+ }
+ QQmlRefPointer<QQmlContextData> childContexts() const { return m_childContexts; }
+ QQmlRefPointer<QQmlContextData> takeChildContexts()
+ {
+ QQmlRefPointer<QQmlContextData> childContexts = m_childContexts;
+ m_childContexts = nullptr;
+ return childContexts;
+ }
+ QQmlRefPointer<QQmlContextData> nextChild() const { return m_nextChild; }
+
+ int numIdValues() const { return m_idValueCount; }
+ void setIdValue(int index, QObject *idValue);
+ bool isIdValueSet(int index) const { return m_idValues[index].wasSet(); }
+ QQmlNotifier *idValueBindings(int index) const { return m_idValues[index].bindings(); }
+ QObject *idValue(int index) const { return m_idValues[index].data(); }
+
+ // Return the outermost id for obj, if any.
+ QString findObjectId(const QObject *obj) const;
+
+ // url() and urlString() prefer the CU's URL over explicitly set baseUrls. They
+ // don't search the context hierarchy.
+ // baseUrl() and baseUrlString() search the context hierarchy and prefer explicit
+ // base URLs over CU Urls.
+
+ QUrl url() const;
+ QString urlString() const;
+
+ void setBaseUrlString(const QString &baseUrlString) { m_baseUrlString = baseUrlString; }
+ QString baseUrlString() const
+ {
+ for (const QQmlContextData *data = this; data; data = data->m_parent) {
+ if (!data->m_baseUrlString.isEmpty())
+ return data->m_baseUrlString;
+ if (data->m_typeCompilationUnit)
+ return data->m_typeCompilationUnit->finalUrlString();
+ }
+ return QString();
+ }
+
+ void setBaseUrl(const QUrl &baseUrl) { m_baseUrl = baseUrl; }
+ QUrl baseUrl() const
+ {
+ for (const QQmlContextData *data = this; data; data = data->m_parent) {
+ if (!data->m_baseUrl.isEmpty())
+ return data->m_baseUrl;
+ if (data->m_typeCompilationUnit)
+ return data->m_typeCompilationUnit->finalUrl();
+ }
+ return QUrl();
+ }
+
+ QQmlRefPointer<QQmlTypeNameCache> imports() const { return m_imports; }
+ void setImports(const QQmlRefPointer<QQmlTypeNameCache> &imports) { m_imports = imports; }
+
+ QQmlIncubatorPrivate *incubator() const { return m_hasExtraObject ? nullptr : m_incubator; }
+ void setIncubator(QQmlIncubatorPrivate *incubator)
+ {
+ Q_ASSERT(!m_hasExtraObject || m_extraObject == nullptr);
+ m_hasExtraObject = false;
+ m_incubator = incubator;
+ }
+
+ QObject *extraObject() const { return m_hasExtraObject ? m_extraObject : nullptr; }
+ void setExtraObject(QObject *extraObject)
+ {
+ Q_ASSERT(m_hasExtraObject || m_incubator == nullptr);
+ m_hasExtraObject = true;
+ m_extraObject = extraObject;
+ }
+
+ bool isRootObjectInCreation() const { return m_isRootObjectInCreation; }
+ void setRootObjectInCreation(bool rootInCreation) { m_isRootObjectInCreation = rootInCreation; }
+
+ QV4::PersistentValue importedScripts() const { return m_importedScripts; }
+ void setImportedScripts(const QV4::PersistentValue &scripts) { m_importedScripts = scripts; }
+
+ QQmlRefPointer<QQmlContextData> linkedContext() const { return m_linkedContext; }
+ void setLinkedContext(const QQmlRefPointer<QQmlContextData> &context) { m_linkedContext = context; }
+
+ bool hasUnresolvedNames() const { return m_unresolvedNames; }
+ void setUnresolvedNames(bool hasUnresolvedNames) { m_unresolvedNames = hasUnresolvedNames; }
+
+ QQmlComponentAttached *componentAttacheds() const { return m_componentAttacheds; }
+ void addComponentAttached(QQmlComponentAttached *attached);
+
+ void addExpression(QQmlJavaScriptExpression *expression);
+
+private:
+ friend class QQmlGuardedContextData;
+ friend class QQmlContextPrivate;
+
+ enum Ownership {
+ RefCounted,
+ OwnedByParent,
+ OwnedByPublicContext
+ };
+
+ // id guards
+ struct ContextGuard : public QQmlGuard<QObject>
+ {
+ inline ContextGuard() : m_context(nullptr) {}
+ inline ContextGuard &operator=(QObject *obj);
+ inline void objectDestroyed(QObject *) override;
+
+ inline bool wasSet() const;
+
+ QQmlNotifier *bindings() { return &m_bindings; }
+ void setContext(const QQmlRefPointer<QQmlContextData> &context)
+ {
+ m_context = context.data();
+ }
+
+ private:
+ // Not refcounted, as it always belongs to the QQmlContextData.
+ QFlagPointer<QQmlContextData> m_context;
+ QQmlNotifier m_bindings;
+ };
+
+ // It's OK to pass a half-created publicContext here. We will not dereference it during
+ // construction.
+ QQmlContextData(
+ Ownership ownership, QQmlContext *publicContext,
+ const QQmlRefPointer<QQmlContextData> &parent, QQmlEngine *engine = nullptr)
+ : m_parent(parent.data()),
+ m_engine(engine ? engine : (parent.isNull() ? nullptr : parent->engine())),
+ m_isInternal(false), m_isJSContext(false), m_isPragmaLibraryContext(false),
+ m_unresolvedNames(false), m_hasEmittedDestruction(false), m_isRootObjectInCreation(false),
+ m_ownedByParent(ownership == OwnedByParent),
+ m_ownedByPublicContext(ownership == OwnedByPublicContext), m_hasExtraObject(false),
+ m_dummy(0), m_publicContext(publicContext), m_incubator(nullptr)
+ {
+ Q_ASSERT(!m_ownedByParent || !m_ownedByPublicContext);
+ if (!m_parent)
+ return;
+
+ m_nextChild = m_parent->m_childContexts;
+ if (m_nextChild)
+ m_nextChild->m_prevChild = &m_nextChild;
+ m_prevChild = &m_parent->m_childContexts;
+ m_parent->m_childContexts = this;
+ }
+
+ ~QQmlContextData();
+
+ bool hasExpressionsToRun(bool isGlobalRefresh) const
+ {
+ return m_expressions && (!isGlobalRefresh || m_unresolvedNames);
+ }
+
+ void refreshExpressionsRecursive(bool isGlobal);
+ void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
+
+ // My parent context and engine
+ QQmlContextData *m_parent = nullptr;
+ QQmlEngine *m_engine = nullptr;
+
+ mutable quint32 m_refCount = 1;
+ quint32 m_isInternal:1;
+ quint32 m_isJSContext:1;
+ quint32 m_isPragmaLibraryContext:1;
+ quint32 m_unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name
+ quint32 m_hasEmittedDestruction:1;
+ quint32 m_isRootObjectInCreation:1;
+ quint32 m_ownedByParent:1;
+ quint32 m_ownedByPublicContext:1;
+ quint32 m_hasExtraObject:1; // used in QQmlDelegateModelItem::dataForObject to find the corresponding QQmlDelegateModelItem of an object
+ quint32 m_dummy:23;
+ QQmlContext *m_publicContext = nullptr;
+
+ union {
+ // The incubator that is constructing this context if any
+ QQmlIncubatorPrivate *m_incubator;
+ // a pointer to extra data, currently only used in QQmlDelegateModel
+ QObject *m_extraObject;
+ };
+
+ // Compilation unit for contexts that belong to a compiled type.
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> m_typeCompilationUnit;
+
+ // object index in CompiledData::Unit to component that created this context
+ int m_componentObjectIndex = -1;
+
+ // flag indicates whether the context owns the cache (after mutation) or not.
+ mutable QV4::IdentifierHash m_propertyNameCache;
+
+ // Context object
+ QObject *m_contextObject = nullptr;
+
+ // Any script blocks that exist on this context
+ QV4::PersistentValue m_importedScripts; // This is a JS Array
+
+ QUrl m_baseUrl;
+ QString m_baseUrlString;
+
+ // List of imports that apply to this context
+ QQmlRefPointer<QQmlTypeNameCache> m_imports;
+
+ // My children, not refcounted as that would create cyclic references
+ QQmlContextData *m_childContexts = nullptr;
+
+ // My peers in parent's childContexts list; not refcounted
+ QQmlContextData *m_nextChild = nullptr;
+ QQmlContextData **m_prevChild = nullptr;
+
+ // Expressions that use this context
+ QQmlJavaScriptExpression *m_expressions = nullptr;
+
+ // Doubly-linked list of objects that are owned by this context
+ QQmlData *m_ownedObjects = nullptr;
+
+ // Doubly-linked list of context guards (XXX merge with contextObjects)
+ QQmlGuardedContextData *m_contextGuards = nullptr;
+
+ ContextGuard *m_idValues = nullptr;
+ int m_idValueCount = 0;
+
+ // Linked contexts. this owns linkedContext.
+ QQmlRefPointer<QQmlContextData> m_linkedContext;
+
+ // Linked list of uses of the Component attached property in this context
+ QQmlComponentAttached *m_componentAttacheds = nullptr;
+};
+
+QQmlContextData::ContextGuard &QQmlContextData::ContextGuard::operator=(QObject *obj)
+{
+ QQmlGuard<QObject>::operator=(obj);
+ m_context.setFlag();
+ m_bindings.notify(); // For alias connections
+ return *this;
+}
+
+void QQmlContextData::ContextGuard::objectDestroyed(QObject *)
+{
+ if (QObject *contextObject = m_context->contextObject()) {
+ if (!QObjectPrivate::get(contextObject)->wasDeleted)
+ m_bindings.notify();
+ }
+}
+
+bool QQmlContextData::ContextGuard::wasSet() const
+{
+ return m_context.flag();
+}
+
+QT_END_NAMESPACE
+
+#endif // QQMLCONTEXTDATA_P_H
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index ee31cb38d9..1c238767d8 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -82,34 +82,6 @@ struct Binding;
}
}
-// This is declared here because QQmlData below needs it and this file
-// in turn is included from qqmlcontext_p.h.
-class QQmlContextData;
-class Q_QML_PRIVATE_EXPORT QQmlContextDataRef
-{
-public:
- inline QQmlContextDataRef();
- inline QQmlContextDataRef(QQmlContextData *);
- inline QQmlContextDataRef(const QQmlContextDataRef &);
- inline ~QQmlContextDataRef();
-
- inline QQmlContextData *contextData() const;
- inline void setContextData(QQmlContextData *);
-
- inline bool isNull() const { return !m_contextData; }
-
- inline operator QQmlContextData*() const { return m_contextData; }
- inline QQmlContextData* operator->() const { return m_contextData; }
- inline QQmlContextDataRef &operator=(QQmlContextData *d);
- inline QQmlContextDataRef &operator=(const QQmlContextDataRef &other);
-
-private:
-
- inline void clear();
-
- QQmlContextData *m_contextData;
-};
-
// This class is structured in such a way, that simply zero'ing it is the
// default state for elemental object allocations. This is crucial in the
// workings of the QQmlInstruction::CreateSimpleObject instruction.
@@ -195,11 +167,11 @@ public:
bool signalHasEndpoint(int index) const;
void disconnectNotifiers();
- // The context that created the C++ object
+ // The context that created the C++ object; not refcounted to prevent cycles
QQmlContextData *context = nullptr;
- // The outermost context in which this object lives
+ // The outermost context in which this object lives; not refcounted to prevent cycles
QQmlContextData *outerContext = nullptr;
- QQmlContextDataRef ownContext;
+ QQmlRefPointer<QQmlContextData> ownContext;
QQmlAbstractBinding *bindings;
QQmlBoundSignal *signalHandlers;
@@ -226,14 +198,19 @@ public:
~DeferredData();
unsigned int deferredIdx;
QMultiHash<int, const QV4::CompiledData::Binding *> bindings;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;//Not always the same as the other compilation unit
- QQmlContextData *context;//Could be either context or outerContext
+
+ // Not always the same as the other compilation unit
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
+
+ // Could be either context or outerContext
+ QQmlRefPointer<QQmlContextData> context;
Q_DISABLE_COPY(DeferredData);
};
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
QVector<DeferredData *> deferredData;
- void deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, QQmlContextData *);
+ void deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &,
+ const QQmlRefPointer<QQmlContextData> &);
void releaseDeferredData();
QV4::WeakValue jsWrapper;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 0d9326b9a9..eb23b6e256 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -665,20 +665,21 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
{
if (QQmlData *d = QQmlData::get(o)) {
if (d->ownContext) {
- for (QQmlContextData *lc = d->ownContext->linkedContext; lc; lc = lc->linkedContext) {
+ for (QQmlRefPointer<QQmlContextData> lc = d->ownContext->linkedContext().data(); lc;
+ lc = lc->linkedContext()) {
lc->invalidate();
- if (lc->contextObject == o)
- lc->contextObject = nullptr;
+ if (lc->contextObject() == o)
+ lc->setContextObject(nullptr);
}
d->ownContext->invalidate();
- if (d->ownContext->contextObject == o)
- d->ownContext->contextObject = nullptr;
+ if (d->ownContext->contextObject() == o)
+ d->ownContext->setContextObject(nullptr);
d->ownContext = nullptr;
d->context = nullptr;
}
- if (d->outerContext && d->outerContext->contextObject == o)
- d->outerContext->contextObject = nullptr;
+ if (d->outerContext && d->outerContext->contextObject() == o)
+ d->outerContext->setContextObject(nullptr);
// Mark this object as in the process of deletion to
// prevent it resolving in bindings
@@ -849,10 +850,10 @@ void QQmlData::setQueuedForDeletion(QObject *object)
if (object) {
if (QQmlData *ddata = QQmlData::get(object)) {
if (ddata->ownContext) {
- Q_ASSERT(ddata->ownContext == ddata->context);
+ Q_ASSERT(ddata->ownContext.data() == ddata->context);
ddata->context->emitDestruction();
- if (ddata->ownContext->contextObject == object)
- ddata->ownContext->contextObject = nullptr;
+ if (ddata->ownContext->contextObject() == object)
+ ddata->ownContext->setContextObject(nullptr);
ddata->ownContext = nullptr;
ddata->context = nullptr;
}
@@ -982,7 +983,7 @@ QQmlEngine::~QQmlEngine()
// Emit onDestruction signals for the root context before
// we destroy the contexts, engine, Singleton Types etc. that
// may be required to handle the destruction signal.
- QQmlContextData::get(rootContext())->emitDestruction();
+ QQmlContextPrivate::get(rootContext())->emitDestruction();
// clean up all singleton type instances which we own.
// we do this here and not in the private dtor since otherwise a crash can
@@ -1422,10 +1423,10 @@ QJSValue QQmlEngine::singletonInstance<QJSValue>(int qmlTypeId)
void QQmlEngine::retranslate()
{
Q_D(QQmlEngine);
- QQmlContextData *context = QQmlContextData::get(d->rootContext)->childContexts;
- while (context) {
+ for (QQmlRefPointer<QQmlContextData> context
+ = QQmlContextData::get(d->rootContext)->childContexts();
+ context; context = context->nextChild()) {
context->refreshExpressions();
- context = context->nextChild;
}
}
@@ -1469,10 +1470,10 @@ void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
return;
}
- QQmlContextData *contextData = QQmlContextData::get(context);
+ QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
Q_ASSERT(data->context == nullptr);
- data->context = contextData;
- contextData->addObject(data);
+ data->context = contextData.data();
+ contextData->addOwnedObject(data);
}
/*!
@@ -1576,7 +1577,7 @@ void qmlExecuteDeferred(QObject *object)
QQmlData *data = QQmlData::get(object);
if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object)) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
QQmlComponentPrivate::DeferredState state;
QQmlComponentPrivate::beginDeferred(ep, object, &state);
@@ -1598,7 +1599,7 @@ QQmlEngine *qmlEngine(const QObject *obj)
QQmlData *data = QQmlData::get(obj, false);
if (!data || !data->context)
return nullptr;
- return data->context->engine;
+ return data->context->engine();
}
static QObject *resolveAttachedProperties(QQmlAttachedPropertiesFunc pf, QQmlData *data,
@@ -1786,7 +1787,9 @@ void QQmlData::NotifyList::layout()
todo = nullptr;
}
-void QQmlData::deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *context)
+void QQmlData::deferData(
+ int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QQmlRefPointer<QQmlContextData> &context)
{
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
deferData->deferredIdx = objectIndex;
@@ -1880,8 +1883,8 @@ void QQmlData::destroyed(QObject *object)
nextContextObject->prevContextObject = prevContextObject;
if (prevContextObject)
*prevContextObject = nextContextObject;
- else if (outerContext && outerContext->contextObjects == this)
- outerContext->contextObjects = nextContextObject;
+ else if (outerContext && outerContext->ownedObjects() == this)
+ outerContext->setOwnedObjects(nextContextObject);
QQmlAbstractBinding *binding = bindings;
while (binding) {
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 23c69651ed..f8b8b187a5 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -59,7 +59,7 @@
#include "qqml.h"
#include "qqmlvaluetype_p.h"
#include "qqmlcontext.h"
-#include "qqmlcontext_p.h"
+#include "qqmlcontextdata_p.h"
#include "qqmlexpression.h"
#include "qqmlproperty_p.h"
#include "qqmlmetatype_p.h"
@@ -205,7 +205,7 @@ public:
QIntrusiveList<Incubator, &Incubator::next> incubatorList;
unsigned int incubatorCount;
QQmlIncubationController *incubationController;
- void incubate(QQmlIncubator &, QQmlContextData *);
+ void incubate(QQmlIncubator &, const QQmlRefPointer<QQmlContextData> &);
// These methods may be called from any thread
inline bool isEngineThread() const;
@@ -255,7 +255,7 @@ public:
inline static QQmlEnginePrivate *get(QQmlEngine *e);
inline static const QQmlEnginePrivate *get(const QQmlEngine *e);
inline static QQmlEnginePrivate *get(QQmlContext *c);
- inline static QQmlEnginePrivate *get(QQmlContextData *c);
+ inline static QQmlEnginePrivate *get(const QQmlRefPointer<QQmlContextData> &c);
inline static QQmlEngine *get(QQmlEnginePrivate *p);
inline static QQmlEnginePrivate *get(QV4::ExecutionEngine *e);
@@ -442,14 +442,24 @@ const QQmlEnginePrivate *QQmlEnginePrivate::get(const QQmlEngine *e)
return e ? e->d_func() : nullptr;
}
+template<typename Context>
+QQmlEnginePrivate *contextEngine(const Context &context)
+{
+ if (!context)
+ return nullptr;
+ if (QQmlEngine *engine = context->engine())
+ return QQmlEnginePrivate::get(engine);
+ return nullptr;
+}
+
QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContext *c)
{
- return (c && c->engine()) ? QQmlEnginePrivate::get(c->engine()) : nullptr;
+ return contextEngine(c);
}
-QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContextData *c)
+QQmlEnginePrivate *QQmlEnginePrivate::get(const QQmlRefPointer<QQmlContextData> &c)
{
- return (c && c->engine) ? QQmlEnginePrivate::get(c->engine) : nullptr;
+ return contextEngine(c);
}
QQmlEngine *QQmlEnginePrivate::get(QQmlEnginePrivate *p)
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index f6a5afb891..5864c3245c 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -63,7 +63,8 @@ QQmlExpressionPrivate::~QQmlExpressionPrivate()
{
}
-void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QObject *me)
+void QQmlExpressionPrivate::init(const QQmlRefPointer<QQmlContextData> &ctxt, const QString &expr,
+ QObject *me)
{
expression = expr;
@@ -72,10 +73,11 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QOb
expressionFunctionValid = false;
}
-void QQmlExpressionPrivate::init(QQmlContextData *ctxt, QV4::Function *runtimeFunction, QObject *me)
+void QQmlExpressionPrivate::init(const QQmlRefPointer<QQmlContextData> &ctxt,
+ QV4::Function *runtimeFunction, QObject *me)
{
expressionFunctionValid = true;
- QV4::ExecutionEngine *engine = ctxt->engine->handle();
+ QV4::ExecutionEngine *engine = ctxt->engine()->handle();
QV4::Scope scope(engine);
QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(engine->rootContext(), ctxt, me));
setupFunction(qmlContext, runtimeFunction);
@@ -144,20 +146,24 @@ QQmlExpression::QQmlExpression(const QQmlScriptString &script, QQmlContext *ctxt
if (!ctxt && (!scriptPrivate->context || !scriptPrivate->context->isValid()))
return;
- QQmlContextData *evalCtxtData = QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context);
+ QQmlRefPointer<QQmlContextData> evalCtxtData
+ = QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context);
QObject *scopeObject = scope ? scope : scriptPrivate->scope;
QV4::Function *runtimeFunction = nullptr;
if (scriptPrivate->context) {
- QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context);
+ QQmlRefPointer<QQmlContextData> ctxtdata = QQmlContextData::get(scriptPrivate->context);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine());
- if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit) {
+ if (engine
+ && ctxtdata
+ && !ctxtdata->urlString().isEmpty()
+ && ctxtdata->typeCompilationUnit()) {
d->url = ctxtdata->urlString();
d->line = scriptPrivate->lineNumber;
d->column = scriptPrivate->columnNumber;
if (scriptPrivate->bindingId != QQmlBinding::Invalid)
- runtimeFunction = ctxtdata->typeCompilationUnit->runtimeFunctions.at(scriptPrivate->bindingId);
+ runtimeFunction = ctxtdata->typeCompilationUnit()->runtimeFunctions.at(scriptPrivate->bindingId);
}
}
@@ -175,10 +181,8 @@ QQmlExpression::QQmlExpression(const QQmlScriptString &script, QQmlContext *ctxt
If specified, the \a scope object's properties will also be in scope during
the expression's execution.
*/
-QQmlExpression::QQmlExpression(QQmlContext *ctxt,
- QObject *scope,
- const QString &expression,
- QObject *parent)
+QQmlExpression::QQmlExpression(QQmlContext *ctxt, QObject *scope, const QString &expression,
+ QObject *parent)
: QObject(*new QQmlExpressionPrivate, parent)
{
Q_D(QQmlExpression);
@@ -188,12 +192,10 @@ QQmlExpression::QQmlExpression(QQmlContext *ctxt,
/*!
\internal
*/
-QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope,
- const QString &expression)
-: QObject(*new QQmlExpressionPrivate, nullptr)
+QQmlExpression::QQmlExpression(QQmlExpressionPrivate &dd, QObject *parent) : QObject(dd, parent)
{
- Q_D(QQmlExpression);
- d->init(ctxt, expression, scope);
+// Q_D(QQmlExpression);
+// d->init(QQmlContextData::get(ctxt), expression, scope);
}
/*!
@@ -210,7 +212,7 @@ QQmlExpression::~QQmlExpression()
QQmlEngine *QQmlExpression::engine() const
{
Q_D(const QQmlExpression);
- return d->context()?d->context()->engine:nullptr;
+ return d->engine();
}
/*!
@@ -220,8 +222,7 @@ QQmlEngine *QQmlExpression::engine() const
QQmlContext *QQmlExpression::context() const
{
Q_D(const QQmlExpression);
- QQmlContextData *data = d->context();
- return data?data->asQQmlContext():nullptr;
+ return d->publicContext();
}
/*!
@@ -265,7 +266,7 @@ QVariant QQmlExpressionPrivate::value(bool *isUndefined)
{
Q_Q(QQmlExpression);
- if (!context() || !context()->isValid()) {
+ if (!hasValidContext()) {
qWarning("QQmlExpression: Attempted to evaluate an expression in an invalid context");
return QVariant();
}
diff --git a/src/qml/qml/qqmlexpression.h b/src/qml/qml/qqmlexpression.h
index 0eceeb12e1..c9719aec52 100644
--- a/src/qml/qml/qqmlexpression.h
+++ b/src/qml/qml/qqmlexpression.h
@@ -90,7 +90,7 @@ Q_SIGNALS:
void valueChanged();
private:
- QQmlExpression(QQmlContextData *, QObject *, const QString &);
+ QQmlExpression(QQmlExpressionPrivate &dd, QObject *parent);
Q_DISABLE_COPY(QQmlExpression)
Q_DECLARE_PRIVATE(QQmlExpression)
diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h
index da10b31b2c..3df839a6a2 100644
--- a/src/qml/qml/qqmlexpression_p.h
+++ b/src/qml/qml/qqmlexpression_p.h
@@ -70,8 +70,8 @@ public:
QQmlExpressionPrivate();
~QQmlExpressionPrivate() override;
- void init(QQmlContextData *, const QString &, QObject *);
- void init(QQmlContextData *, QV4::Function *runtimeFunction, QObject *);
+ void init(const QQmlRefPointer<QQmlContextData> &, const QString &, QObject *);
+ void init(const QQmlRefPointer<QQmlContextData> &, QV4::Function *runtimeFunction, QObject *);
QVariant value(bool *isUndefined = nullptr);
diff --git a/src/qml/qml/qqmlguardedcontextdata_p.h b/src/qml/qml/qqmlguardedcontextdata_p.h
new file mode 100644
index 0000000000..0b24c04305
--- /dev/null
+++ b/src/qml/qml/qqmlguardedcontextdata_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLGUARDEDCONTEXTDATA_P_H
+#define QQMLGUARDEDCONTEXTDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/private/qqmlglobal_p.h>
+#include <QtQml/private/qqmlcontextdata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlGuardedContextData
+{
+ Q_DISABLE_COPY(QQmlGuardedContextData);
+public:
+ QQmlGuardedContextData() = default;
+ ~QQmlGuardedContextData() { unlink(); }
+
+ QQmlGuardedContextData(QQmlGuardedContextData &&) = default;
+ QQmlGuardedContextData &operator=(QQmlGuardedContextData &&) = default;
+
+ QQmlGuardedContextData(QQmlRefPointer<QQmlContextData> data)
+ {
+ setContextData(std::move(data));
+ }
+
+ QQmlGuardedContextData &operator=(QQmlRefPointer<QQmlContextData> d)
+ {
+ setContextData(std::move(d));
+ return *this;
+ }
+
+ QQmlRefPointer<QQmlContextData> contextData() const { return m_contextData; }
+ void setContextData(QQmlRefPointer<QQmlContextData> contextData)
+ {
+ if (m_contextData.data() == contextData.data())
+ return;
+ unlink();
+
+ if (contextData) {
+ m_contextData = std::move(contextData);
+ m_next = m_contextData->m_contextGuards;
+ if (m_next)
+ m_next->m_prev = &m_next;
+
+ m_contextData->m_contextGuards = this;
+ m_prev = &m_contextData->m_contextGuards;
+ }
+ }
+
+ bool isNull() const { return !m_contextData; }
+
+ operator const QQmlRefPointer<QQmlContextData> &() const { return m_contextData; }
+ QQmlContextData &operator*() const { return m_contextData.operator*(); }
+ QQmlContextData *operator->() const { return m_contextData.operator->(); }
+
+ QQmlGuardedContextData *next() const { return m_next; }
+
+ void reset()
+ {
+ m_contextData = nullptr;
+ m_next = nullptr;
+ m_prev = nullptr;
+ }
+
+private:
+ void unlink()
+ {
+ if (m_prev) {
+ *m_prev = m_next;
+ if (m_next)
+ m_next->m_prev = m_prev;
+ reset();
+ }
+ }
+
+ QQmlRefPointer<QQmlContextData> m_contextData;
+ QQmlGuardedContextData *m_next = nullptr;
+ QQmlGuardedContextData **m_prev = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLGUARDEDCONTEXTDATA_P_H
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index 0ad013e90b..1f41934c3c 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -45,7 +45,8 @@
#include "qqmlobjectcreator_p.h"
#include <private/qqmlcomponent_p.h>
-void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
+void QQmlEnginePrivate::incubate(
+ QQmlIncubator &i, const QQmlRefPointer<QQmlContextData> &forContext)
{
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> p(i.d);
@@ -59,13 +60,13 @@ void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
// Need to find the first constructing context and see if it is asynchronous
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> parentIncubator;
- QQmlContextData *cctxt = forContext;
+ QQmlRefPointer<QQmlContextData> cctxt = forContext;
while (cctxt) {
- if (!cctxt->hasExtraObject && cctxt->incubator) {
- parentIncubator = cctxt->incubator;
+ if (QQmlIncubatorPrivate *incubator = cctxt->incubator()) {
+ parentIncubator = incubator;
break;
}
- cctxt = cctxt->parent;
+ cctxt = cctxt->parent();
}
if (parentIncubator && parentIncubator->isAsynchronous) {
@@ -149,8 +150,8 @@ void QQmlIncubatorPrivate::clear()
}
enginePriv = nullptr;
if (!rootContext.isNull()) {
- if (!rootContext->hasExtraObject)
- rootContext->incubator = nullptr;
+ if (rootContext->incubator())
+ rootContext->setIncubator(nullptr);
rootContext = nullptr;
}
@@ -360,10 +361,8 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
if (watcher.hasRecursed())
return;
- QQmlContextData *ctxt = nullptr;
- ctxt = creator->finalize(i);
- if (ctxt) {
- rootContext = ctxt;
+ if (creator->finalize(i)) {
+ rootContext = creator->rootContext();
progress = QQmlIncubatorPrivate::Completed;
goto finishIncubate;
}
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index a674ff274f..b178c6aa29 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -46,7 +46,7 @@
#include <private/qqmlvme_p.h>
#include <private/qrecursionwatcher_p.h>
#include <private/qqmlengine_p.h>
-#include <private/qqmlcontext_p.h>
+#include <private/qqmlguardedcontextdata_p.h>
//
// W A R N I N G
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 6a9ef06159..93af2d7c52 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -134,7 +134,7 @@ QQmlSourceLocation QQmlJavaScriptExpression::sourceLocation() const
return QQmlSourceLocation();
}
-void QQmlJavaScriptExpression::setContext(QQmlContextData *context)
+void QQmlJavaScriptExpression::setContext(const QQmlRefPointer<QQmlContextData> &context)
{
if (m_prevExpression) {
*m_prevExpression = m_nextExpression;
@@ -144,15 +144,10 @@ void QQmlJavaScriptExpression::setContext(QQmlContextData *context)
m_nextExpression = nullptr;
}
- m_context = context;
+ m_context = context.data();
- if (context) {
- m_nextExpression = context->expressions;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = &m_nextExpression;
- m_prevExpression = &context->expressions;
- context->expressions = this;
- }
+ if (context)
+ context->addExpression(this);
}
QV4::Function *QQmlJavaScriptExpression::function() const
@@ -166,7 +161,7 @@ void QQmlJavaScriptExpression::refresh()
QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
{
- QV4::ExecutionEngine *v4 = m_context->engine->handle();
+ QV4::ExecutionEngine *v4 = m_context->engine()->handle();
QV4::Scope scope(v4);
QV4::JSCallData jsCall(scope);
@@ -175,7 +170,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined)
{
- Q_ASSERT(m_context && m_context->engine);
+ Q_ASSERT(m_context && m_context->engine());
QV4::Function *v4Function = function();
if (!v4Function) {
@@ -184,14 +179,14 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
return QV4::Encode::undefined();
}
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine());
// All code that follows must check with watcher before it accesses data members
// incase we have been deleted.
DeleteWatcher watcher(this);
Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty());
- QQmlPropertyCapture capture(m_context->engine, this, &watcher);
+ QQmlPropertyCapture capture(m_context->engine(), this, &watcher);
QQmlPropertyCapture *lastPropertyCapture = ep->propertyCapture;
ep->propertyCapture = notifyOnValueChanged() ? &capture : nullptr;
@@ -200,7 +195,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
if (notifyOnValueChanged())
capture.guards.copyAndClearPrepend(activeGuards);
- QV4::ExecutionEngine *v4 = m_context->engine->handle();
+ QV4::ExecutionEngine *v4 = m_context->engine()->handle();
callData->thisObject = v4->globalObject;
if (scopeObject()) {
QV4::ReturnedValue scope = QV4::QObjectWrapper::wrap(v4, scopeObject());
@@ -337,10 +332,11 @@ QQmlDelayedError *QQmlJavaScriptExpression::delayedError()
}
QV4::ReturnedValue
-QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObject,
- const QString &code, const QString &filename, quint16 line)
+QQmlJavaScriptExpression::evalFunction(
+ const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scopeObject,
+ const QString &code, const QString &filename, quint16 line)
{
- QQmlEngine *engine = ctxt->engine;
+ QQmlEngine *engine = ctxt->engine();
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4 = engine->handle();
@@ -367,10 +363,11 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
return result->asReturnedValue();
}
-void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject *qmlScope,
- const QString &code, const QString &filename, quint16 line)
+void QQmlJavaScriptExpression::createQmlBinding(
+ const QQmlRefPointer<QQmlContextData> &ctxt, QObject *qmlScope, const QString &code,
+ const QString &filename, quint16 line)
{
- QQmlEngine *engine = ctxt->engine;
+ QQmlEngine *engine = ctxt->engine();
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4 = engine->handle();
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index eecee08062..6e904f15f5 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -118,10 +118,21 @@ public:
virtual QQmlSourceLocation sourceLocation() const;
- bool isValid() const { return context() != nullptr; }
-
- QQmlContextData *context() const { return m_context; }
- void setContext(QQmlContextData *context);
+ bool hasContext() const { return m_context != nullptr; }
+ bool hasValidContext() const { return m_context && m_context->isValid(); }
+ QQmlContext *publicContext() const { return m_context ? m_context->asQQmlContext() : nullptr; }
+
+ QQmlRefPointer<QQmlContextData> context() const { return m_context; }
+ void setContext(const QQmlRefPointer<QQmlContextData> &context);
+
+ void insertIntoList(QQmlJavaScriptExpression **listHead)
+ {
+ m_nextExpression = *listHead;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = &m_nextExpression;
+ m_prevExpression = listHead;
+ *listHead = this;
+ }
QV4::Function *function() const;
@@ -146,11 +157,16 @@ public:
void clearActiveGuards();
QQmlDelayedError *delayedError();
- static QV4::ReturnedValue evalFunction(QQmlContextData *ctxt, QObject *scope,
- const QString &code, const QString &filename,
- quint16 line);
+ static QV4::ReturnedValue evalFunction(
+ const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope, const QString &code,
+ const QString &filename, quint16 line);
+
+ QQmlEngine *engine() const { return m_context ? m_context->engine() : nullptr; }
+ bool hasUnresolvedNames() const { return m_context && m_context->hasUnresolvedNames(); }
+
protected:
- void createQmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line);
+ void createQmlBinding(const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope,
+ const QString &code, const QString &filename, quint16 line);
void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f);
void setCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit);
@@ -173,7 +189,9 @@ private:
// m_error:flag1 translationsCapturedDuringEvaluation
QFlagPointer<QQmlDelayedError> m_error;
+ // Not refcounted as the context will clear the expressions when destructed.
QQmlContextData *m_context;
+
QQmlJavaScriptExpression **m_prevExpression;
QQmlJavaScriptExpression *m_nextExpression;
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index e0187eb75a..8f209311fa 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -67,8 +67,11 @@
QT_USE_NAMESPACE
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *creationContext,
- QQmlIncubatorPrivate *incubator)
+QQmlObjectCreator::QQmlObjectCreator(
+ QQmlRefPointer<QQmlContextData> parentContext,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QQmlRefPointer<QQmlContextData> &creationContext,
+ QQmlIncubatorPrivate *incubator)
: phase(Startup)
, compilationUnit(compilationUnit)
, propertyCaches(&compilationUnit->propertyCaches)
@@ -76,7 +79,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
, topLevelCreator(true)
, incubator(incubator)
{
- init(parentContext);
+ init(std::move(parentContext));
sharedState->componentAttached = nullptr;
sharedState->allCreatedBindings.allocate(compilationUnit->totalBindingsCount());
@@ -95,7 +98,10 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
}
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
+QQmlObjectCreator::QQmlObjectCreator(
+ QQmlRefPointer<QQmlContextData> parentContext,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ QQmlObjectCreatorSharedState *inheritedSharedState)
: phase(Startup)
, compilationUnit(compilationUnit)
, propertyCaches(&compilationUnit->propertyCaches)
@@ -103,13 +109,13 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
, topLevelCreator(false)
, incubator(nullptr)
{
- init(parentContext);
+ init(std::move(parentContext));
}
-void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
+void QQmlObjectCreator::init(QQmlRefPointer<QQmlContextData> providedParentContext)
{
- parentContext = providedParentContext;
- engine = parentContext->engine;
+ parentContext = std::move(providedParentContext);
+ engine = parentContext->engine();
v4 = engine->handle();
if (compilationUnit && !compilationUnit->engine)
@@ -142,7 +148,7 @@ QQmlObjectCreator::~QQmlObjectCreator()
}
while (sharedState->componentAttached) {
QQmlComponentAttached *a = sharedState->componentAttached;
- a->rem();
+ a->removeFromList();
}
}
}
@@ -151,7 +157,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
{
if (phase == CreatingObjectsPhase2) {
phase = ObjectsCreated;
- return context->contextObject;
+ return context->contextObject();
}
Q_ASSERT(phase == Startup);
phase = CreatingObjects;
@@ -171,16 +177,15 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
}
}
- context = new QQmlContextData;
- context->isInternal = true;
- context->imports = compilationUnit->typeNameCache;
+ context = QQmlContextData::createRefCounted(parentContext);
+ context->setInternal(true);
+ context->setImports(compilationUnit->typeNameCache);
context->initFromTypeCompilationUnit(compilationUnit, subComponentIndex);
- context->setParent(parentContext);
if (!sharedState->rootContext) {
sharedState->rootContext = context;
- sharedState->rootContext->incubator = incubator;
- sharedState->rootContext->isRootObjectInCreation = true;
+ sharedState->rootContext->setIncubator(incubator);
+ sharedState->rootContext->setRootObjectInCreation(true);
}
QV4::Scope scope(v4);
@@ -191,14 +196,14 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
if (subComponentIndex == -1 && compilationUnit->dependentScripts.count()) {
QV4::ScopedObject scripts(scope, v4->newArrayObject(compilationUnit->dependentScripts.count()));
- context->importedScripts.set(v4, scripts);
+ context->setImportedScripts(QV4::PersistentValue(v4, scripts.asReturnedValue()));
QV4::ScopedValue v(scope);
for (int i = 0; i < compilationUnit->dependentScripts.count(); ++i) {
QQmlRefPointer<QQmlScriptData> s = compilationUnit->dependentScripts.at(i);
scripts->put(i, (v = s->scriptValueForContext(context)));
}
} else if (sharedState->creationContext) {
- context->importedScripts = sharedState->creationContext->importedScripts;
+ context->setImportedScripts(sharedState->creationContext->importedScripts());
}
QObject *instance = createInstance(objectToCreate, parent, /*isContextObject*/true);
@@ -221,18 +226,18 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
if (instance) {
if (QQmlEngineDebugService *service
= QQmlDebugConnector::service<QQmlEngineDebugService>()) {
- if (!parentContext->isInternal)
- parentContext->asQQmlContextPrivate()->instances.append(instance);
+ if (!parentContext->isInternal())
+ parentContext->asQQmlContextPrivate()->appendInstance(instance);
service->objectCreated(engine, instance);
- } else if (!parentContext->isInternal && QQmlDebugConnector::service<QV4DebugService>()) {
- parentContext->asQQmlContextPrivate()->instances.append(instance);
+ } else if (!parentContext->isInternal() && QQmlDebugConnector::service<QV4DebugService>()) {
+ parentContext->asQQmlContextPrivate()->appendInstance(instance);
}
}
return instance;
}
-void QQmlObjectCreator::beginPopulateDeferred(QQmlContextData *newContext)
+void QQmlObjectCreator::beginPopulateDeferred(const QQmlRefPointer<QQmlContextData> &newContext)
{
context = newContext;
sharedState->rootContext = newContext;
@@ -741,7 +746,10 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
- QQmlPropertyData *property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
+ QQmlPropertyData *property = binding->propertyNameIndex != 0
+ ? _propertyCache->property(stringAt(binding->propertyNameIndex),
+ _qobject, context)
+ : defaultProperty;
if (property)
bindingSkipList |= (1 << property->coreIndex());
}
@@ -809,7 +817,8 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
Q_ASSERT(tr);
QQmlType attachedType = tr->type;
if (!attachedType.isValid()) {
- QQmlTypeNameCache::Result res = context->imports->query(stringAt(binding->propertyNameIndex));
+ QQmlTypeNameCache::Result res = context->imports()->query(
+ stringAt(binding->propertyNameIndex));
if (res.isValid())
attachedType = res.type;
else
@@ -902,8 +911,9 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex());
QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
- QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex,
- context, _scopeObject, runtimeFunction, currentQmlContext());
+ QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(
+ _bindingTarget, signalIndex, context,
+ _scopeObject, runtimeFunction, currentQmlContext());
bs->takeExpression(expr);
} else {
@@ -920,10 +930,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
subprop = bindingProperty;
}
if (binding->isTranslationBinding()) {
- qmlBinding = QQmlBinding::createTranslationBinding(compilationUnit, binding, _scopeObject, context);
+ qmlBinding = QQmlBinding::createTranslationBinding(
+ compilationUnit, binding, _scopeObject, context);
} else {
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
- qmlBinding = QQmlBinding::create(targetProperty, runtimeFunction, _scopeObject, context, currentQmlContext());
+ qmlBinding = QQmlBinding::create(targetProperty, runtimeFunction, _scopeObject,
+ context, currentQmlContext());
}
auto bindingTarget = _bindingTarget;
@@ -965,10 +977,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
QObject *target = createdSubObject->parent();
QQmlProperty prop;
- if (_valueTypeProperty)
- prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, bindingProperty, context);
- else
+ if (_valueTypeProperty) {
+ prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty,
+ bindingProperty, context);
+ } else {
prop = QQmlPropertyPrivate::restore(target, *bindingProperty, nullptr, context);
+ }
vs->setTarget(prop);
return true;
}
@@ -990,15 +1004,19 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
// we can't have aliasses on subproperties of value types, so:
QQmlPropertyData targetPropertyData = *data->propertyCache->property(propIndex.coreIndex());
- auto prop = QQmlPropertyPrivate::restore(target, targetPropertyData, nullptr, context);
+ auto prop = QQmlPropertyPrivate::restore(
+ target, targetPropertyData, nullptr, context);
vi->setTarget(prop);
propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
} else {
QQmlProperty prop;
- if (_valueTypeProperty)
- prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, bindingProperty, context);
- else
- prop = QQmlPropertyPrivate::restore(target, *bindingProperty, nullptr, context);
+ if (_valueTypeProperty) {
+ prop = QQmlPropertyPrivate::restore(
+ target, *_valueTypeProperty, bindingProperty, context);
+ } else {
+ prop = QQmlPropertyPrivate::restore(
+ target, *bindingProperty, nullptr, context);
+ }
vi->setTarget(prop);
propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
}
@@ -1144,7 +1162,7 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location,
void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const
{
if (object->id >= 0)
- context->setIdProperty(object->id, instance);
+ context->setIdValue(object->id, instance);
}
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
@@ -1200,10 +1218,10 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
customParser = type.customParser();
- if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation) {
+ if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation()) {
QQmlData *ddata = QQmlData::get(instance, /*create*/true);
ddata->rootObjectInCreation = true;
- sharedState->rootContext->isRootObjectInCreation = false;
+ sharedState->rootContext->setRootObjectInCreation(false);
}
sharedState->allCreatedObjects.push(instance);
@@ -1264,21 +1282,22 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
const bool isInlineComponent = obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot;
if (static_cast<quint32>(index) == /*root object*/0 || ddata->rootObjectInCreation || isInlineComponent) {
if (ddata->context) {
- Q_ASSERT(ddata->context != context);
+ Q_ASSERT(ddata->context != context.data());
Q_ASSERT(ddata->outerContext);
- Q_ASSERT(ddata->outerContext != context);
- QQmlContextData *c = ddata->context;
- while (c->linkedContext) c = c->linkedContext;
- c->linkedContext = context;
+ Q_ASSERT(ddata->outerContext != context.data());
+ QQmlRefPointer<QQmlContextData> c = ddata->context;
+ while (QQmlRefPointer<QQmlContextData> linked = c->linkedContext())
+ c = linked;
+ c->setLinkedContext(context);
} else {
- ddata->context = context;
+ ddata->context = context.data();
}
ddata->ownContext = ddata->context;
} else if (!ddata->context) {
- ddata->context = context;
+ ddata->context = context.data();
}
- context->addObject(ddata);
+ context->addOwnedObject(ddata);
if (parserStatus) {
parserStatus->classBegin();
@@ -1292,7 +1311,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
// Register the context object in the context early on in order for pending binding
// initialization to find it available.
if (isContextObject)
- context->contextObject = instance;
+ context->setContextObject(instance);
if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
customParser->engine = QQmlEnginePrivate::get(engine);
@@ -1367,7 +1386,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
return ok ? instance : nullptr;
}
-QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
+bool QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
{
Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
phase = Finalizing;
@@ -1389,12 +1408,13 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
if (!b->isValueTypeProxy()) {
QQmlBinding *binding = static_cast<QQmlBinding*>(b.data());
if (!binding->hasError() && !binding->hasDependencies()
- && binding->context() && !binding->context()->unresolvedNames)
+ && binding->hasContext() && !binding->hasUnresolvedNames()) {
b->removeFromObject();
+ }
}
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return nullptr;
+ return false;
}
if (QQmlVME::componentCompleteEnabled()) { // the qml designer does the component complete later
@@ -1408,7 +1428,7 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
}
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return nullptr;
+ return false;
}
}
@@ -1420,27 +1440,27 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
}
if (watcher.hasRecursed())
- return nullptr;
+ return false;
}
sharedState->finalizeCallbacks.clear();
while (sharedState->componentAttached) {
QQmlComponentAttached *a = sharedState->componentAttached;
- a->rem();
+ a->removeFromList();
QQmlData *d = QQmlData::get(a->parent());
Q_ASSERT(d);
Q_ASSERT(d->context);
- a->add(&d->context->componentAttached);
+ d->context->addComponentAttached(a);
if (QQmlVME::componentCompleteEnabled())
emit a->completed();
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return nullptr;
+ return false;
}
phase = Done;
- return sharedState->rootContext;
+ return true;
}
void QQmlObjectCreator::clear()
@@ -1458,7 +1478,7 @@ void QQmlObjectCreator::clear()
while (sharedState->componentAttached) {
QQmlComponentAttached *a = sharedState->componentAttached;
- a->rem();
+ a->removeFromList();
}
phase = Done;
@@ -1553,9 +1573,9 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
while (alias->aliasToLocalAlias)
alias = _compiledObject->aliasesBegin() + alias->localAliasIndex;
Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
- if (!context->idValues->wasSet())
+ if (!context->isIdValueSet(0)) // TODO: Do we really want 0 here?
continue;
- QObject *target = context->idValues[alias->targetObjectId].data();
+ QObject *target = context->idValue(alias->targetObjectId);
if (!target)
continue;
QQmlData *targetDData = QQmlData::get(target, /*create*/false);
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 50ce8d5909..0b14ec6603 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -57,6 +57,7 @@
#include <private/qrecursionwatcher_p.h>
#include <private/qqmlprofiler_p.h>
#include <private/qv4qmlcontext_p.h>
+#include <private/qqmlguardedcontextdata_p.h>
#include <qpointer.h>
@@ -90,8 +91,8 @@ class RequiredProperties : public QHash<QQmlPropertyData*, RequiredPropertyInfo>
struct QQmlObjectCreatorSharedState : public QSharedData
{
- QQmlContextData *rootContext;
- QQmlContextData *creationContext;
+ QQmlRefPointer<QQmlContextData> rootContext;
+ QQmlRefPointer<QQmlContextData> creationContext;
QFiniteStack<QQmlAbstractBinding::Ptr> allCreatedBindings;
QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
QFiniteStack<QPointer<QObject> > allCreatedObjects;
@@ -108,38 +109,48 @@ class Q_QML_PRIVATE_EXPORT QQmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
public:
- QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr);
+ QQmlObjectCreator(QQmlRefPointer<QQmlContextData> parentContext,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QQmlRefPointer<QQmlContextData> &creationContext,
+ QQmlIncubatorPrivate *incubator = nullptr);
~QQmlObjectCreator();
enum CreationFlags { NormalObject = 1, InlineComponent = 2 };
- QObject *create(int subComponentIndex = -1, QObject *parent = nullptr, QQmlInstantiationInterrupt *interrupt = nullptr, int flags = NormalObject);
+ QObject *create(int subComponentIndex = -1, QObject *parent = nullptr,
+ QQmlInstantiationInterrupt *interrupt = nullptr, int flags = NormalObject);
bool populateDeferredProperties(QObject *instance, const QQmlData::DeferredData *deferredData);
- void beginPopulateDeferred(QQmlContextData *context);
+ void beginPopulateDeferred(const QQmlRefPointer<QQmlContextData> &context);
void populateDeferredBinding(const QQmlProperty &qmlProperty, int deferredIndex,
const QV4::CompiledData::Binding *binding);
void finalizePopulateDeferred();
- QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt);
+ bool finalize(QQmlInstantiationInterrupt &interrupt);
void clear();
+ QQmlRefPointer<QQmlContextData> rootContext() const { return sharedState->rootContext; }
QQmlComponentAttached **componentAttachment() { return &sharedState->componentAttached; }
QList<QQmlEnginePrivate::FinalizeCallback> *finalizeCallbacks() { return &sharedState->finalizeCallbacks; }
QList<QQmlError> errors;
- QQmlContextData *parentContextData() const { return parentContext.contextData(); }
+ QQmlRefPointer<QQmlContextData> parentContextData() const
+ {
+ return parentContext.contextData();
+ }
QFiniteStack<QPointer<QObject> > &allCreatedObjects() { return sharedState->allCreatedObjects; }
RequiredProperties &requiredProperties() {return sharedState->requiredProperties;}
bool componentHadRequiredProperties() const {return sharedState->hadRequiredProperties;}
private:
- QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
+ QQmlObjectCreator(QQmlRefPointer<QQmlContextData> contextData,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ QQmlObjectCreatorSharedState *inheritedSharedState);
- void init(QQmlContextData *parentContext);
+ void init(QQmlRefPointer<QQmlContextData> parentContext);
QObject *createInstance(int index, QObject *parent = nullptr, bool isContextObject = false);
@@ -181,7 +192,7 @@ private:
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
const QV4::CompiledData::Unit *qmlUnit;
QQmlGuardedContextData parentContext;
- QQmlContextData *context;
+ QQmlRefPointer<QQmlContextData> context;
const QQmlPropertyCacheVector *propertyCaches;
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
bool topLevelCreator;
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 8521de6ab3..3824a7fb6d 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -163,7 +163,6 @@ QQmlProperty::QQmlProperty(QObject *obj, QQmlContext *ctxt)
QQmlProperty::QQmlProperty(QObject *obj, QQmlEngine *engine)
: d(new QQmlPropertyPrivate)
{
- d->context = nullptr;
d->engine = engine;
d->initDefault(obj);
}
@@ -205,7 +204,11 @@ QQmlProperty::QQmlProperty(QObject *obj, const QString &name, QQmlContext *ctxt)
d->context = ctxt?QQmlContextData::get(ctxt):nullptr;
d->engine = ctxt?ctxt->engine():nullptr;
d->initProperty(obj, name);
- if (!isValid()) { d->object = nullptr; d->context = nullptr; d->engine = nullptr; }
+ if (!isValid()) {
+ d->object = nullptr;
+ d->context = nullptr;
+ d->engine = nullptr;
+ }
}
/*!
@@ -216,19 +219,23 @@ QQmlProperty::QQmlProperty(QObject *obj, const QString &name, QQmlContext *ctxt)
QQmlProperty::QQmlProperty(QObject *obj, const QString &name, QQmlEngine *engine)
: d(new QQmlPropertyPrivate)
{
- d->context = nullptr;
d->engine = engine;
d->initProperty(obj, name);
- if (!isValid()) { d->object = nullptr; d->context = nullptr; d->engine = nullptr; }
+ if (!isValid()) {
+ d->object = nullptr;
+ d->context = nullptr;
+ d->engine = nullptr;
+ }
}
-QQmlProperty QQmlPropertyPrivate::create(QObject *target, const QString &propertyName, QQmlContextData *context)
+QQmlProperty QQmlPropertyPrivate::create(QObject *target, const QString &propertyName,
+ const QQmlRefPointer<QQmlContextData> &context)
{
QQmlProperty result;
auto d = new QQmlPropertyPrivate;
result.d = d;
d->context = context;
- d->engine = context ? context->engine : nullptr;
+ d->engine = context ? context->engine() : nullptr;
d->initProperty(target, propertyName);
if (!result.isValid()) {
d->object = nullptr;
@@ -238,23 +245,21 @@ QQmlProperty QQmlPropertyPrivate::create(QObject *target, const QString &propert
return result;
}
-QQmlPropertyPrivate::QQmlPropertyPrivate()
-: context(nullptr), engine(nullptr), object(nullptr), isNameCached(false)
+QQmlRefPointer<QQmlContextData> QQmlPropertyPrivate::effectiveContext() const
{
-}
-
-QQmlContextData *QQmlPropertyPrivate::effectiveContext() const
-{
- if (context) return context;
- else if (engine) return QQmlContextData::get(engine->rootContext());
- else return nullptr;
+ if (context)
+ return context;
+ else if (engine)
+ return QQmlContextData::get(engine->rootContext());
+ else
+ return nullptr;
}
void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
{
if (!obj) return;
- QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context?context->imports:nullptr;
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context ? context->imports() : nullptr;
QObject *currentObject = obj;
QVector<QStringRef> path;
@@ -974,7 +979,7 @@ void QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
if (expr) {
int signalIndex = QQmlPropertyPrivate::get(that)->signalIndex();
QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, signalIndex, that.d->object,
- expr->context()->engine);
+ expr->engine());
signal->takeExpression(expr);
}
}
@@ -1097,7 +1102,8 @@ QVariant QQmlPropertyPrivate::readValueProperty()
}
// helper function to allow assignment / binding to QList<QUrl> properties.
-QVariant QQmlPropertyPrivate::resolvedUrlSequence(const QVariant &value, QQmlContextData *context)
+QVariant QQmlPropertyPrivate::resolvedUrlSequence(
+ const QVariant &value, const QQmlRefPointer<QQmlContextData> &context)
{
QList<QUrl> urls;
if (value.userType() == qMetaTypeId<QUrl>()) {
@@ -1186,7 +1192,8 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
const QVariant &value,
- QQmlContextData *context,QQmlPropertyData::WriteFlags flags)
+ const QQmlRefPointer<QQmlContextData> &context,
+ QQmlPropertyData::WriteFlags flags)
{
// Remove any existing bindings on this property
if (!(flags & QQmlPropertyData::DontRemoveBinding) && object)
@@ -1201,7 +1208,7 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
};
QQmlGadgetPtrWrapper *wrapper = context
- ? QQmlGadgetPtrWrapper::instance(context->engine, core.propType())
+ ? QQmlGadgetPtrWrapper::instance(context->engine(), core.propType())
: nullptr;
if (wrapper) {
doWrite(wrapper);
@@ -1217,10 +1224,9 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
return rv;
}
-bool QQmlPropertyPrivate::write(QObject *object,
- const QQmlPropertyData &property,
- const QVariant &value, QQmlContextData *context,
- QQmlPropertyData::WriteFlags flags)
+bool QQmlPropertyPrivate::write(
+ QObject *object, const QQmlPropertyData &property, const QVariant &value,
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
{
const int propertyType = property.propType();
const int variantType = value.userType();
@@ -1647,14 +1653,15 @@ QQmlPropertyIndex QQmlPropertyPrivate::propertyIndex(const QQmlProperty &that)
QQmlProperty
QQmlPropertyPrivate::restore(QObject *object, const QQmlPropertyData &data,
- const QQmlPropertyData *valueTypeData, QQmlContextData *ctxt)
+ const QQmlPropertyData *valueTypeData,
+ const QQmlRefPointer<QQmlContextData> &ctxt)
{
QQmlProperty prop;
prop.d = new QQmlPropertyPrivate;
prop.d->object = object;
prop.d->context = ctxt;
- prop.d->engine = ctxt ? ctxt->engine : nullptr;
+ prop.d->engine = ctxt ? ctxt->engine() : nullptr;
prop.d->core = data;
if (valueTypeData)
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index 8abd83d7b4..5e357d77c0 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -57,9 +57,10 @@
#include <private/qobject_p.h>
#include <private/qtqmlglobal_p.h>
#include <private/qqmlrefcount_p.h>
-#include <private/qqmlcontext_p.h>
+#include <private/qqmlcontextdata_p.h>
#include <private/qqmlboundsignalexpressionpointer_p.h>
#include <private/qqmlpropertydata_p.h>
+#include <private/qqmlpropertyindex_p.h>
QT_BEGIN_NAMESPACE
@@ -67,11 +68,12 @@ class QQmlContext;
class QQmlEnginePrivate;
class QQmlJavaScriptExpression;
class QQmlMetaObject;
+class QQmlAbstractBinding;
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
{
public:
- QQmlContextData *context;
+ QQmlRefPointer<QQmlContextData> context;
QPointer<QQmlEngine> engine;
QPointer<QObject> object;
@@ -81,14 +83,14 @@ public:
bool isNameCached:1;
QString nameCache;
- QQmlPropertyPrivate();
+ QQmlPropertyPrivate() : isNameCached(false) {}
QQmlPropertyIndex encodedIndex() const
{ return encodedIndex(core, valueTypeData); }
static QQmlPropertyIndex encodedIndex(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData)
{ return QQmlPropertyIndex(core.coreIndex(), valueTypeData.coreIndex()); }
- inline QQmlContextData *effectiveContext() const;
+ QQmlRefPointer<QQmlContextData> effectiveContext() const;
void initProperty(QObject *obj, const QString &name);
void initDefault(QObject *obj);
@@ -106,10 +108,11 @@ public:
const QVariant &value, int flags);
static bool writeValueProperty(QObject *,
const QQmlPropertyData &, const QQmlPropertyData &valueTypeData,
- const QVariant &, QQmlContextData *,
+ const QVariant &, const QQmlRefPointer<QQmlContextData> &,
QQmlPropertyData::WriteFlags flags = {});
static bool write(QObject *, const QQmlPropertyData &, const QVariant &,
- QQmlContextData *, QQmlPropertyData::WriteFlags flags = {});
+ const QQmlRefPointer<QQmlContextData> &,
+ QQmlPropertyData::WriteFlags flags = {});
static void findAliasTarget(QObject *, QQmlPropertyIndex, QObject **, QQmlPropertyIndex *);
enum BindingFlag {
@@ -126,7 +129,8 @@ public:
static void removeBinding(QQmlAbstractBinding *b);
static QQmlAbstractBinding *binding(QObject *, QQmlPropertyIndex index);
- static QQmlProperty restore(QObject *, const QQmlPropertyData &, const QQmlPropertyData *, QQmlContextData *);
+ static QQmlProperty restore(QObject *, const QQmlPropertyData &, const QQmlPropertyData *,
+ const QQmlRefPointer<QQmlContextData> &);
int signalIndex() const;
@@ -146,8 +150,11 @@ public:
int type = 0, int *types = nullptr);
static void flushSignal(const QObject *sender, int signal_index);
- static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context);
- static QQmlProperty create(QObject *target, const QString &propertyName, QQmlContextData *context);
+ static QVariant resolvedUrlSequence(
+ const QVariant &value, const QQmlRefPointer<QQmlContextData> &context);
+ static QQmlProperty create(
+ QObject *target, const QString &propertyName,
+ const QQmlRefPointer<QQmlContextData> &context);
};
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index aa171c1c29..4b17760f8e 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -753,7 +753,9 @@ void QQmlPropertyCache::invalidate(const QMetaObject *metaObject)
}
}
-QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it, QObject *object, QQmlContextData *context) const
+QQmlPropertyData *QQmlPropertyCache::findProperty(
+ StringCache::ConstIterator it, QObject *object,
+ const QQmlRefPointer<QQmlContextData> &context) const
{
QQmlData *data = (object ? QQmlData::get(object) : nullptr);
const QQmlVMEMetaObject *vmemo = nullptr;
@@ -766,11 +768,11 @@ QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it,
namespace {
-inline bool contextHasNoExtensions(QQmlContextData *context)
+inline bool contextHasNoExtensions(const QQmlRefPointer<QQmlContextData> &context)
{
// This context has no extension if its parent is the engine's rootContext,
// which has children but no imports
- return (!context->parent || !context->parent->imports);
+ return (!context->parent() || !context->parent()->imports());
}
inline int maximumIndexForProperty(QQmlPropertyData *prop, const int methodCount, const int signalCount, const int propertyCount)
@@ -782,7 +784,9 @@ inline int maximumIndexForProperty(QQmlPropertyData *prop, const int methodCount
}
-QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *vmemo, QQmlContextData *context) const
+QQmlPropertyData *QQmlPropertyCache::findProperty(
+ StringCache::ConstIterator it, const QQmlVMEMetaObject *vmemo,
+ const QQmlRefPointer<QQmlContextData> &context) const
{
StringCache::ConstIterator end = stringCache.end();
@@ -796,7 +800,7 @@ QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it,
if (vmemo && context && !contextHasNoExtensions(context)) {
// Find the meta-object that corresponds to the supplied context
do {
- if (vmemo->ctxt == context)
+ if (vmemo->ctxt.contextData().data() == context.data())
break;
vmemo = vmemo->parentVMEMetaObject();
@@ -1007,7 +1011,7 @@ static inline QByteArray qQmlPropertyCacheToString(const QV4::String *string)
template<typename T>
QQmlPropertyData *
qQmlPropertyCacheProperty(QJSEngine *engine, QObject *obj, T name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData &local)
{
QQmlPropertyCache *cache = nullptr;
@@ -1040,21 +1044,21 @@ qQmlPropertyCacheProperty(QJSEngine *engine, QObject *obj, T name,
QQmlPropertyData *
QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QV4::String *name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData &local)
{
return qQmlPropertyCacheProperty<const QV4::String *>(engine, obj, name, context, local);
}
QQmlPropertyData *
QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QStringRef &name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData &local)
{
return qQmlPropertyCacheProperty<const QStringRef &>(engine, obj, name, context, local);
}
QQmlPropertyData *
QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QLatin1String &name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData &local)
{
return qQmlPropertyCacheProperty<const QLatin1String &>(engine, obj, name, context, local);
}
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 6038056991..43ffb0fb36 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -114,7 +114,8 @@ public:
const QMetaObject *firstCppMetaObject() const;
template<typename K>
- QQmlPropertyData *property(const K &key, QObject *object, QQmlContextData *context) const
+ QQmlPropertyData *property(const K &key, QObject *object,
+ const QQmlRefPointer<QQmlContextData> &context) const
{
return findProperty(stringCache.find(key), object, context);
}
@@ -136,14 +137,15 @@ public:
inline bool isAllowedInRevision(QQmlPropertyData *) const;
static QQmlPropertyData *property(QJSEngine *, QObject *, const QStringRef &,
- QQmlContextData *, QQmlPropertyData &);
+ const QQmlRefPointer<QQmlContextData> &, QQmlPropertyData &);
static QQmlPropertyData *property(QJSEngine *, QObject *, const QLatin1String &,
- QQmlContextData *, QQmlPropertyData &);
+ const QQmlRefPointer<QQmlContextData> &, QQmlPropertyData &);
static QQmlPropertyData *property(QJSEngine *, QObject *, const QV4::String *,
- QQmlContextData *, QQmlPropertyData &);
+ const QQmlRefPointer<QQmlContextData> &, QQmlPropertyData &);
static QQmlPropertyData *property(QJSEngine *engine, QObject *obj, const QString &name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context,
+ QQmlPropertyData &local)
{
return property(engine, obj, QStringRef(&name), context, local);
}
@@ -200,8 +202,10 @@ private:
typedef QLinkedStringMultiHash<QPair<int, QQmlPropertyData *> > StringCache;
typedef QVector<QTypeRevision> AllowedRevisionCache;
- QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *, QQmlContextData *) const;
- QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *, QQmlContextData *) const;
+ QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *,
+ const QQmlRefPointer<QQmlContextData> &) const;
+ QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *,
+ const QQmlRefPointer<QQmlContextData> &) const;
QQmlPropertyData *ensureResolved(QQmlPropertyData*) const;
diff --git a/src/qml/qml/qqmlpropertyresolver.cpp b/src/qml/qml/qqmlpropertyresolver.cpp
index 90eaca0b90..396f2876b9 100644
--- a/src/qml/qml/qqmlpropertyresolver.cpp
+++ b/src/qml/qml/qqmlpropertyresolver.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qqmlpropertyresolver_p.h"
+#include <private/qqmlcontextdata_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlscriptblob.cpp b/src/qml/qml/qqmlscriptblob.cpp
index dac21f7ee7..14ed501131 100644
--- a/src/qml/qml/qqmlscriptblob.cpp
+++ b/src/qml/qml/qqmlscriptblob.cpp
@@ -42,6 +42,7 @@
#include <private/qqmlscriptblob_p.h>
#include <private/qqmlscriptdata_p.h>
#include <private/qqmlsourcecoordinate_p.h>
+#include <private/qqmlcontextdata_p.h>
#include <private/qv4runtimecodegen_p.h>
#include <private/qv4script_p.h>
diff --git a/src/qml/qml/qqmlscriptdata.cpp b/src/qml/qml/qqmlscriptdata.cpp
index ae268ca904..50ec0e20cd 100644
--- a/src/qml/qml/qqmlscriptdata.cpp
+++ b/src/qml/qml/qqmlscriptdata.cpp
@@ -55,78 +55,82 @@ QQmlScriptData::QQmlScriptData()
{
}
-QQmlContextData *QQmlScriptData::qmlContextDataForContext(QQmlContextData *parentQmlContextData)
+QQmlRefPointer<QQmlContextData> QQmlScriptData::qmlContextDataForContext(
+ const QQmlRefPointer<QQmlContextData> &parentQmlContextData)
{
- Q_ASSERT(parentQmlContextData && parentQmlContextData->engine);
+ Q_ASSERT(parentQmlContextData && parentQmlContextData->engine());
if (m_precompiledScript->isESModule())
return nullptr;
- auto qmlContextData = new QQmlContextData();
+ QQmlRefPointer<QQmlContextData> qmlContextData = m_precompiledScript->isSharedLibrary()
+ ? QQmlContextData::createRefCounted(QQmlRefPointer<QQmlContextData>())
+ : QQmlContextData::createRefCounted(parentQmlContextData);
- qmlContextData->isInternal = true;
- qmlContextData->isJSContext = true;
+ qmlContextData->setInternal(true);
+ qmlContextData->setJSContext(true);
if (m_precompiledScript->isSharedLibrary())
- qmlContextData->isPragmaLibraryContext = true;
+ qmlContextData->setPragmaLibraryContext(true);
else
- qmlContextData->isPragmaLibraryContext = parentQmlContextData->isPragmaLibraryContext;
- qmlContextData->baseUrl = url;
- qmlContextData->baseUrlString = urlString;
+ qmlContextData->setPragmaLibraryContext(parentQmlContextData->isPragmaLibraryContext());
+ qmlContextData->setBaseUrl(url);
+ qmlContextData->setBaseUrlString(urlString);
// For backward compatibility, if there are no imports, we need to use the
// imports from the parent context. See QTBUG-17518.
if (!typeNameCache->isEmpty()) {
- qmlContextData->imports = typeNameCache;
+ qmlContextData->setImports(typeNameCache);
} else if (!m_precompiledScript->isSharedLibrary()) {
- qmlContextData->imports = parentQmlContextData->imports;
- qmlContextData->importedScripts = parentQmlContextData->importedScripts;
+ qmlContextData->setImports(parentQmlContextData->imports());
+ qmlContextData->setImportedScripts(parentQmlContextData->importedScripts());
}
- if (!m_precompiledScript->isSharedLibrary()) {
- qmlContextData->setParent(parentQmlContextData);
- } else {
- qmlContextData->engine = parentQmlContextData->engine; // Fix for QTBUG-21620
- }
+ if (m_precompiledScript->isSharedLibrary())
+ qmlContextData->setEngine(parentQmlContextData->engine()); // Fix for QTBUG-21620
- QV4::ExecutionEngine *v4 = parentQmlContextData->engine->handle();
+ QV4::ExecutionEngine *v4 = parentQmlContextData->engine()->handle();
QV4::Scope scope(v4);
QV4::ScopedObject scriptsArray(scope);
- if (qmlContextData->importedScripts.isNullOrUndefined()) {
+ if (qmlContextData->importedScripts().isNullOrUndefined()) {
scriptsArray = v4->newArrayObject(scripts.count());
- qmlContextData->importedScripts.set(v4, scriptsArray);
+ qmlContextData->setImportedScripts(
+ QV4::PersistentValue(v4, scriptsArray.asReturnedValue()));
} else {
- scriptsArray = qmlContextData->importedScripts.valueRef();
+ scriptsArray = qmlContextData->importedScripts().valueRef();
}
QV4::ScopedValue v(scope);
- for (int ii = 0; ii < scripts.count(); ++ii)
- scriptsArray->put(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(qmlContextData)));
+ for (int ii = 0; ii < scripts.count(); ++ii) {
+ v = scripts.at(ii)->scriptData()->scriptValueForContext(qmlContextData.data());
+ scriptsArray->put(ii, v);
+ }
return qmlContextData;
}
-QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentQmlContextData)
+QV4::ReturnedValue QQmlScriptData::scriptValueForContext(
+ const QQmlRefPointer<QQmlContextData> &parentQmlContextData)
{
if (m_loaded)
return m_value.value();
- Q_ASSERT(parentQmlContextData && parentQmlContextData->engine);
- QV4::ExecutionEngine *v4 = parentQmlContextData->engine->handle();
+ Q_ASSERT(parentQmlContextData && parentQmlContextData->engine());
+ QV4::ExecutionEngine *v4 = parentQmlContextData->engine()->handle();
QV4::Scope scope(v4);
if (!hasEngine()) {
- addToEngine(parentQmlContextData->engine);
+ addToEngine(parentQmlContextData->engine());
addref();
}
- QQmlContextDataRef qmlContextData = qmlContextDataForContext(parentQmlContextData);
QV4::Scoped<QV4::QmlContext> qmlExecutionContext(scope);
- if (qmlContextData)
- qmlExecutionContext =
- QV4::QmlContext::create(v4->rootContext(), qmlContextData, /* scopeObject: */ nullptr);
+ if (auto qmlContextData = qmlContextDataForContext(parentQmlContextData)) {
+ qmlExecutionContext = QV4::QmlContext::create(v4->rootContext(), std::move(qmlContextData),
+ /* scopeObject: */ nullptr);
+ }
QV4::Scoped<QV4::Module> module(scope, m_precompiledScript->instantiate(v4));
if (module) {
- if (qmlContextData) {
+ if (qmlExecutionContext) {
module->d()->scope->outer.set(v4, qmlExecutionContext->d());
qmlExecutionContext->d()->qml()->module.set(v4, module->d());
}
@@ -141,7 +145,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
}
QV4::ScopedValue value(scope);
- if (qmlContextData)
+ if (qmlExecutionContext)
value = qmlExecutionContext->d()->qml();
else if (module)
value = module->d();
diff --git a/src/qml/qml/qqmlscriptdata_p.h b/src/qml/qml/qqmlscriptdata_p.h
index 80b65b699c..abbafc33c2 100644
--- a/src/qml/qml/qqmlscriptdata_p.h
+++ b/src/qml/qml/qqmlscriptdata_p.h
@@ -85,7 +85,7 @@ public:
QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
QVector<QQmlRefPointer<QQmlScriptBlob>> scripts;
- QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
+ QV4::ReturnedValue scriptValueForContext(const QQmlRefPointer<QQmlContextData> &parentCtxt);
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit() const { return m_precompiledScript; }
@@ -96,7 +96,8 @@ private:
friend class QQmlScriptBlob;
void initialize(QQmlEngine *);
- QQmlContextData *qmlContextDataForContext(QQmlContextData *parentQmlContextData);
+ QQmlRefPointer<QQmlContextData> qmlContextDataForContext(
+ const QQmlRefPointer<QQmlContextData> &parentQmlContextData);
bool m_loaded;
QQmlRefPointer<QV4::ExecutableCompilationUnit> m_precompiledScript;
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index c787d4092e..da76659ef4 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -183,7 +183,7 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons
if (hasProperty)
*hasProperty = true;
- QQmlContextData *context = v4->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = v4->callingQmlContext();
QObject *object = w->d()->object;
QQmlType type = w->d()->type();
@@ -283,10 +283,10 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons
if (r.type.isValid()) {
return create(scope.engine, object, r.type, w->d()->mode);
} else if (r.scriptIndex != -1) {
- QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
+ QV4::ScopedObject scripts(scope, context->importedScripts().valueRef());
return scripts->get(r.scriptIndex);
} else if (r.importNamespace) {
- return create(scope.engine, object, context->imports, r.importNamespace);
+ return create(scope.engine, object, context->imports(), r.importNamespace);
}
return QV4::Encode::undefined();
@@ -329,7 +329,7 @@ bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value,
return false;
ScopedString name(scope, id.asStringOrSymbol());
- QQmlContextData *context = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
QQmlType type = w->d()->type();
if (type.isValid() && !type.isSingleton() && w->d()->object) {
@@ -440,7 +440,7 @@ ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(const Object *object,
const QQmlTypeWrapper *This = static_cast<const QQmlTypeWrapper *>(object);
ScopedString name(scope, id.asStringOrSymbol());
- QQmlContextData *qmlContext = engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = engine->callingQmlContext();
Scoped<QQmlTypeWrapper> w(scope, static_cast<const QQmlTypeWrapper *>(This));
QQmlType type = w->d()->type();
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index aa7e28add0..d367edad1b 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -569,7 +569,7 @@ bool QQmlValueTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &v
return false;
}
- QQmlContextData *context = v4->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = v4->callingQmlContext();
QQmlPropertyData cacheData;
cacheData.setWritable(true);
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 018769948d..38e9fad2b6 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -138,7 +138,7 @@ bool QQmlVMEGuard::isOK() const
return false;
for (int ii = 0; ii < m_contextCount; ++ii)
- if (m_contexts[ii].isNull() || !m_contexts[ii]->engine)
+ if (m_contexts[ii].isNull() || !m_contexts[ii]->engine())
return false;
return true;
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index 05a78a17fe..784df5d7ef 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -87,7 +87,7 @@ namespace QQmlVMETypes {
State() : flags(0), context(nullptr), instructionStream(nullptr) {}
quint32 flags;
- QQmlContextData *context;
+ QQmlRefPointer<QQmlContextData> context;
const char *instructionStream;
QBitField bindingSkipList;
};
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index aa9f4bc1bd..c107f22df5 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -230,8 +230,8 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
} else {
const QV4::CompiledData::Alias *aliasData = &metaObject->compiledObject->aliasTable()[aliasId];
if (!aliasData->isObjectAlias()) {
- QQmlContextData *ctxt = metaObject->ctxt;
- QObject *target = ctxt->idValues[aliasData->targetObjectId].data();
+ QQmlRefPointer<QQmlContextData> ctxt = metaObject->ctxt;
+ QObject *target = ctxt->idValue(aliasData->targetObjectId);
if (!target)
return;
@@ -255,7 +255,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
return;
if (pd->notifyIndex() != -1)
- connect(target, pd->notifyIndex(), ctxt->engine);
+ connect(target, pd->notifyIndex(), ctxt->engine());
}
metaObject.setFlag();
@@ -321,7 +321,7 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
if (type != QMetaType::UnknownType) {
if (valueIndex != -1) {
QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance(
- data->context->engine, type);
+ data->context->engine(), type);
Q_ASSERT(valueType);
//
@@ -694,7 +694,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
const QV4::CompiledData::BuiltinType t = property.builtinType();
// the context can be null if accessing var properties from cpp after re-parenting an item.
- QQmlEnginePrivate *ep = (ctxt == nullptr || ctxt->engine == nullptr) ? nullptr : QQmlEnginePrivate::get(ctxt->engine);
+ QQmlEnginePrivate *ep = (ctxt.isNull() || ctxt->engine() == nullptr)
+ ? nullptr
+ : QQmlEnginePrivate::get(ctxt->engine());
const int fallbackMetaType = QQmlPropertyCacheCreatorBase::metaTypeForPropertyType(t);
@@ -891,15 +893,13 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if ((aliasData->flags & QV4::CompiledData::Alias::AliasPointsToPointerObject) && c == QMetaObject::ReadProperty)
*reinterpret_cast<void **>(a[0]) = nullptr;
- if (!ctxt) return -1;
+ if (ctxt.isNull())
+ return -1;
while (aliasData->aliasToLocalAlias)
aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
- QQmlContext *context = ctxt->asQQmlContext();
- QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
-
- QObject *target = ctxtPriv->data->idValues[aliasData->targetObjectId].data();
+ QObject *target = ctxt->idValue(aliasData->targetObjectId);
if (!target)
return -1;
@@ -934,7 +934,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
// Value type property or deep alias
QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance(
- ctxt->engine, pd->propType());
+ ctxt->engine(), pd->propType());
if (valueType) {
valueType->read(target, coreIndex);
int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a);
@@ -973,7 +973,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
id -= plainSignals;
if (id < methodCount) {
- QQmlEngine *engine = ctxt->engine;
+ QQmlEngine *engine = ctxt->engine();
if (!engine)
return -1; // We can't run the method
@@ -1050,7 +1050,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
QV4::ReturnedValue QQmlVMEMetaObject::method(int index) const
{
- if (!ctxt || !ctxt->isValid() || !compiledObject) {
+ if (ctxt.isNull() || !ctxt->isValid() || !compiledObject) {
qWarning("QQmlVMEMetaObject: Internal error - attempted to evaluate a function in an invalid context");
return QV4::Encode::undefined();
}
@@ -1255,14 +1255,14 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
*coreIndex = -1;
*valueTypeIndex = -1;
- if (!ctxt)
+ if (ctxt.isNull())
return false;
const int aliasId = index - propOffset() - compiledObject->nProperties;
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId];
while (aliasData->aliasToLocalAlias)
aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
- *target = ctxt->idValues[aliasData->targetObjectId].data();
+ *target = ctxt->idValue(aliasData->targetObjectId);
if (!*target)
return false;
@@ -1290,7 +1290,7 @@ void QQmlVMEMetaObject::connectAlias(int aliasId)
}
endpoint->metaObject = this;
- endpoint->connect(&ctxt->idValues[aliasData->targetObjectId].bindings);
+ endpoint->connect(ctxt->idValueBindings(aliasData->targetObjectId));
endpoint->tryConnect();
}
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index e17701a968..10fa0d89a2 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -64,8 +64,8 @@
#include <private/qobject_p.h>
#include "qqmlguard_p.h"
-#include "qqmlcontext_p.h"
+#include <private/qqmlguardedcontextdata_p.h>
#include <private/qflagpointer_p.h>
#include <private/qv4object_p.h>
@@ -144,7 +144,10 @@ class QQmlVMEMetaObjectEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
{
public:
- QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlCompilationUnit, int qmlObjectId);
+ QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj,
+ const QQmlRefPointer<QQmlPropertyCache> &cache,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlCompilationUnit,
+ int qmlObjectId);
~QQmlVMEMetaObject() override;
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 61070113cc..179d5314a8 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1020,7 +1020,8 @@ public:
QString replyStatusText() const;
ReturnedValue open(Object *thisObject, const QString &, const QUrl &, LoadType);
- ReturnedValue send(Object *thisObject, QQmlContextData *context, const QByteArray &);
+ ReturnedValue send(Object *thisObject, const QQmlRefPointer<QQmlContextData> &context,
+ const QByteArray &);
ReturnedValue abort(Object *thisObject);
void addHeader(const QString &, const QString &);
@@ -1068,7 +1069,7 @@ private:
void readEncoding();
PersistentValue m_thisObject;
- QQmlContextDataRef m_qmlContext;
+ QQmlRefPointer<QQmlContextData> m_qmlContext;
bool m_wasConstructedWithQmlContext = true;
void dispatchCallbackNow(Object *thisObj);
@@ -1095,7 +1096,7 @@ QQmlXMLHttpRequest::QQmlXMLHttpRequest(QNetworkAccessManager *manager, QV4::Exec
, m_responseType()
, m_parsedDocument()
{
- m_wasConstructedWithQmlContext = v4->callingQmlContext() != nullptr;
+ m_wasConstructedWithQmlContext = !v4->callingQmlContext().isNull();
}
QQmlXMLHttpRequest::~QQmlXMLHttpRequest()
@@ -1297,7 +1298,8 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
}
}
-ReturnedValue QQmlXMLHttpRequest::send(Object *thisObject, QQmlContextData *context, const QByteArray &data)
+ReturnedValue QQmlXMLHttpRequest::send(
+ Object *thisObject, const QQmlRefPointer<QQmlContextData> &context, const QByteArray &data)
{
m_errorFlag = false;
m_sendFlag = true;
@@ -1462,7 +1464,7 @@ void QQmlXMLHttpRequest::finished()
dispatchCallbackSafely();
m_thisObject.clear();
- m_qmlContext.setContextData(nullptr);
+ m_qmlContext = nullptr;
}
@@ -1615,12 +1617,13 @@ void QQmlXMLHttpRequest::dispatchCallbackNow(Object *thisObj, bool done, bool er
void QQmlXMLHttpRequest::dispatchCallbackSafely()
{
- if (m_wasConstructedWithQmlContext && !m_qmlContext.contextData())
+ if (m_wasConstructedWithQmlContext && m_qmlContext.isNull()) {
// if the calling context object is no longer valid, then it has been
// deleted explicitly (e.g., by a Loader deleting the itemContext when
// the source is changed). We do nothing in this case, as the evaluation
// cannot succeed.
return;
+ }
dispatchCallbackNow(m_thisObject.as<Object>());
}
@@ -1791,8 +1794,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(const FunctionObject *b, const
QUrl url = QUrl(argv[1].toQStringNoThrow());
if (url.isRelative()) {
- QQmlContextData *qmlContextData = scope.engine->callingQmlContext();
- if (qmlContextData)
+ if (QQmlRefPointer<QQmlContextData> qmlContextData = scope.engine->callingQmlContext())
url = qmlContextData->resolvedUrl(url);
else
url = scope.engine->resolvedUrl(url.url());
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 4e5ab9b899..10932a0091 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -988,8 +988,7 @@ ReturnedValue QtObject::method_resolvedUrl(const FunctionObject *b, const Value
QQmlEnginePrivate *p = nullptr;
if (e) p = QQmlEnginePrivate::get(e);
if (p) {
- QQmlContextData *ctxt = scope.engine->callingQmlContext();
- if (ctxt)
+ if (QQmlRefPointer<QQmlContextData> ctxt = scope.engine->callingQmlContext())
return Encode(scope.engine->newString(ctxt->resolvedUrl(url).toString()));
else
return Encode(scope.engine->newString(url.toString()));
@@ -1156,7 +1155,7 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
QQmlEngine *engine = scope.engine->qmlEngine();
- QQmlContextData *context = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
if (!context) {
QQmlEngine *qmlEngine = scope.engine->qmlEngine();
if (qmlEngine)
@@ -1164,7 +1163,7 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
}
Q_ASSERT(context);
QQmlContext *effectiveContext = nullptr;
- if (context->isPragmaLibraryContext)
+ if (context->isPragmaLibraryContext())
effectiveContext = engine->rootContext();
else
effectiveContext = context->asQQmlContext();
@@ -1288,16 +1287,15 @@ ReturnedValue QtObject::method_createComponent(const FunctionObject *b, const Va
QQmlEngine *engine = scope.engine->qmlEngine();
- QQmlContextData *context = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
if (!context) {
QQmlEngine *qmlEngine = scope.engine->qmlEngine();
if (qmlEngine)
context = QQmlContextData::get(QQmlEnginePrivate::get(qmlEngine)->rootContext);
}
Q_ASSERT(context);
- QQmlContextData *effectiveContext = context;
- if (context->isPragmaLibraryContext)
- effectiveContext = nullptr;
+ QQmlRefPointer<QQmlContextData> effectiveContext
+ = context->isPragmaLibraryContext() ? nullptr : context;
QString arg = argv[0].toQStringNoThrow();
if (arg.isEmpty())
@@ -2044,7 +2042,7 @@ ReturnedValue GlobalExtensions::method_qsTr(const FunctionObject *b, const Value
}
if (context.isEmpty()) {
- if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) {
+ if (QQmlRefPointer<QQmlContextData> ctxt = scope.engine->callingQmlContext()) {
QString path = ctxt->urlString();
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
int lastDot = path.lastIndexOf(QLatin1Char('.'));
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 4c44bba43e..29946b1da4 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -292,9 +292,9 @@ void QQmlConnections::connectSignalsToMethods()
if (!ddata)
return;
- QV4::ExecutionEngine *engine = ddata->context->engine->handle();
+ QV4::ExecutionEngine *engine = ddata->context->engine()->handle();
- QQmlContextData *ctxtdata = ddata->outerContext;
+ QQmlRefPointer<QQmlContextData> ctxtdata = ddata->outerContext;
for (int i = ddata->propertyCache->methodOffset(),
end = ddata->propertyCache->methodOffset() + ddata->propertyCache->methodCount();
i < end;
@@ -344,7 +344,7 @@ void QQmlConnections::connectSignalsToBindings()
Q_D(QQmlConnections);
QObject *target = this->target();
QQmlData *ddata = QQmlData::get(this);
- QQmlContextData *ctxtdata = ddata ? ddata->outerContext : nullptr;
+ QQmlRefPointer<QQmlContextData> ctxtdata = ddata ? ddata->outerContext : nullptr;
for (const QV4::CompiledData::Binding *binding : qAsConst(d->bindings)) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script);
diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp
index 08c91d172e..710cc359b4 100644
--- a/src/qmlmodels/qqmldelegatemodel.cpp
+++ b/src/qmlmodels/qqmldelegatemodel.cpp
@@ -267,7 +267,6 @@ QQmlDelegateModel::~QQmlDelegateModel()
cacheItem->object = nullptr;
cacheItem->contextData->invalidate();
- Q_ASSERT(cacheItem->contextData->refCount == 1);
cacheItem->contextData = nullptr;
cacheItem->scriptRef -= 1;
}
@@ -957,10 +956,8 @@ void QQDMIncubationTask::initializeRequiredProperties(QQmlDelegateModelItem *mod
if (incubatorPriv->hadRequiredProperties()) {
QQmlData *d = QQmlData::get(object);
auto contextData = d ? d->context : nullptr;
- if (contextData) {
- contextData->hasExtraObject = true;
- contextData->extraObject = modelItemToIncubate;
- }
+ if (contextData)
+ contextData->setExtraObject(modelItemToIncubate);
if (incubatorPriv->requiredProperties().empty())
return;
@@ -1022,9 +1019,9 @@ void QQDMIncubationTask::initializeRequiredProperties(QQmlDelegateModelItem *mod
}
}
} else {
- modelItemToIncubate->contextData->contextObject = modelItemToIncubate;
+ modelItemToIncubate->contextData->setContextObject(modelItemToIncubate);
if (proxiedObject)
- proxyContext->contextObject = proxiedObject;
+ proxyContext->setContextObject(proxiedObject);
}
}
@@ -1039,7 +1036,7 @@ void QQDMIncubationTask::statusChanged(Status status)
incubating->object = nullptr;
if (incubating->contextData) {
incubating->contextData->invalidate();
- Q_ASSERT(incubating->contextData->refCount == 1);
+ Q_ASSERT(incubating->contextData->refCount() == 1);
incubating->contextData = nullptr;
}
incubating->scriptRef = 0;
@@ -1174,7 +1171,7 @@ void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incuba
cacheItem->scriptRef -= 1;
if (cacheItem->contextData) {
cacheItem->contextData->invalidate();
- Q_ASSERT(cacheItem->contextData->refCount == 1);
+ Q_ASSERT(cacheItem->contextData->refCount() == 1);
}
cacheItem->contextData = nullptr;
@@ -1269,15 +1266,14 @@ QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQ
for (int i = 1; i < m_groupCount; ++i)
cacheItem->incubationTask->index[i] = it.index[i];
- QQmlContextData *ctxt = new QQmlContextData;
- ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_context.data()));
+ QQmlRefPointer<QQmlContextData> ctxt = QQmlContextData::createRefCounted(
+ QQmlContextData::get(creationContext ? creationContext : m_context.data()));
cacheItem->contextData = ctxt;
if (m_adaptorModel.hasProxyObject()) {
if (QQmlAdaptorModelProxyInterface *proxy
= qobject_cast<QQmlAdaptorModelProxyInterface *>(cacheItem)) {
- ctxt = new QQmlContextData;
- ctxt->setParent(cacheItem->contextData, /*stronglyReferencedByParent*/true);
+ ctxt = QQmlContextData::createChild(cacheItem->contextData);
QObject *proxied = proxy->proxiedObject();
cacheItem->incubationTask->proxiedObject = proxied;
cacheItem->incubationTask->proxyContext = ctxt;
@@ -2252,9 +2248,10 @@ void QQmlDelegateModelItem::childContextObjectDestroyed(QObject *childContextObj
if (!contextData)
return;
- for (QQmlContextData *ctxt = contextData->childContexts; ctxt; ctxt = ctxt->nextChild) {
- if (ctxt->contextObject == childContextObject)
- ctxt->contextObject = nullptr;
+ for (QQmlRefPointer<QQmlContextData> ctxt = contextData->childContexts(); ctxt;
+ ctxt = ctxt->nextChild()) {
+ if (ctxt->contextObject() == childContextObject)
+ ctxt->setContextObject(nullptr);
}
}
@@ -2359,8 +2356,8 @@ void QQmlDelegateModelItem::destroyObject()
Q_ASSERT(data);
if (data->ownContext) {
data->ownContext->clearContext();
- if (data->ownContext->contextObject == object)
- data->ownContext->contextObject = nullptr;
+ if (data->ownContext->contextObject() == object)
+ data->ownContext->setContextObject(nullptr);
data->ownContext = nullptr;
data->context = nullptr;
}
@@ -2379,12 +2376,12 @@ void QQmlDelegateModelItem::destroyObject()
QQmlDelegateModelItem *QQmlDelegateModelItem::dataForObject(QObject *object)
{
QQmlData *d = QQmlData::get(object);
- QQmlContextData *context = d ? d->context : nullptr;
- if (context && context->hasExtraObject)
- return qobject_cast<QQmlDelegateModelItem *>(context->extraObject);
- for (context = context ? context->parent : nullptr; context; context = context->parent) {
+ QQmlRefPointer<QQmlContextData> context = d ? d->context : nullptr;
+ if (QObject *extraObject = context ? context->extraObject() : nullptr)
+ return qobject_cast<QQmlDelegateModelItem *>(extraObject);
+ for (context = context ? context->parent() : nullptr; context; context = context->parent()) {
if (QQmlDelegateModelItem *cacheItem = qobject_cast<QQmlDelegateModelItem *>(
- context->contextObject)) {
+ context->contextObject())) {
return cacheItem;
}
}
diff --git a/src/qmlmodels/qqmldelegatemodel_p_p.h b/src/qmlmodels/qqmldelegatemodel_p_p.h
index 8684439508..20fb47f021 100644
--- a/src/qmlmodels/qqmldelegatemodel_p_p.h
+++ b/src/qmlmodels/qqmldelegatemodel_p_p.h
@@ -149,7 +149,7 @@ public:
QV4::ExecutionEngine *v4;
QQmlRefPointer<QQmlDelegateModelItemMetaType> const metaType;
- QQmlContextDataRef contextData;
+ QQmlRefPointer<QQmlContextData> contextData;
QPointer<QObject> object;
QPointer<QQmlDelegateModelAttached> attached;
QQDMIncubationTask *incubationTask;
@@ -222,7 +222,7 @@ public:
QQmlDelegateModelItem *incubating = nullptr;
QQmlDelegateModelPrivate *vdm = nullptr;
- QQmlContextData *proxyContext = nullptr;
+ QQmlRefPointer<QQmlContextData> proxyContext;
QPointer<QObject> proxiedObject = nullptr; // the proxied object might disapear, so we use a QPointer instead of a raw one
int index[QQmlListCompositor::MaximumGroupCount];
};
diff --git a/src/qmlmodels/qqmltableinstancemodel.cpp b/src/qmlmodels/qqmltableinstancemodel.cpp
index 8c034356f3..4152cbe3ea 100644
--- a/src/qmlmodels/qqmltableinstancemodel.cpp
+++ b/src/qmlmodels/qqmltableinstancemodel.cpp
@@ -68,7 +68,7 @@ void QQmlTableInstanceModel::deleteModelItemLater(QQmlDelegateModelItem *modelIt
if (modelItem->contextData) {
modelItem->contextData->invalidate();
- Q_ASSERT(modelItem->contextData->refCount == 1);
+ Q_ASSERT(modelItem->contextData->refCount() == 1);
modelItem->contextData = nullptr;
}
@@ -325,10 +325,10 @@ void QQmlTableInstanceModel::incubateModelItem(QQmlDelegateModelItem *modelItem,
} else {
modelItem->incubationTask = new QQmlTableInstanceModelIncubationTask(this, modelItem, incubationMode);
- QQmlContextData *ctxt = new QQmlContextData;
QQmlContext *creationContext = modelItem->delegate->creationContext();
- ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_qmlContext.data()));
- ctxt->contextObject = modelItem;
+ QQmlRefPointer<QQmlContextData> ctxt = QQmlContextData::createRefCounted(
+ QQmlContextData::get(creationContext ? creationContext : m_qmlContext.data()));
+ ctxt->setContextObject(modelItem);
modelItem->contextData = ctxt;
QQmlComponentPrivate::get(modelItem->delegate)->incubateObject(
diff --git a/src/quick/designer/qquickdesignersupport.cpp b/src/quick/designer/qquickdesignersupport.cpp
index 70b568800d..48b6b9733b 100644
--- a/src/quick/designer/qquickdesignersupport.cpp
+++ b/src/quick/designer/qquickdesignersupport.cpp
@@ -390,13 +390,13 @@ void QQuickDesignerSupport::emitComponentCompleteSignalForAttachedProperty(QObje
QQmlData *data = QQmlData::get(object);
if (data && data->context) {
- QQmlComponentAttached *componentAttached = data->context->componentAttached;
+ QQmlComponentAttached *componentAttached = data->context->componentAttacheds();
while (componentAttached) {
if (componentAttached->parent())
if (componentAttached->parent() == object)
emit componentAttached->completed();
- componentAttached = componentAttached->next;
+ componentAttached = componentAttached->next();
}
}
}
@@ -429,7 +429,7 @@ int QQuickDesignerSupport::borderWidth(QQuickItem *item)
void QQuickDesignerSupport::refreshExpressions(QQmlContext *context)
{
- QQmlContextPrivate::get(context)->data->refreshExpressions();
+ QQmlContextData::get(context)->refreshExpressions();
}
void QQuickDesignerSupport::setRootItem(QQuickView *view, QQuickItem *item)
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index e1d533f092..bf868fd449 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -962,12 +962,7 @@ QUrl QQuickLoaderPrivate::resolveSourceUrl(QQmlV4Function *args)
QV4::Scope scope(args->v4engine());
QV4::ScopedValue v(scope, (*args)[0]);
QString arg = v->toQString();
- if (arg.isEmpty())
- return QUrl();
-
- QQmlContextData *context = scope.engine->callingQmlContext();
- Q_ASSERT(context);
- return context->resolvedUrl(QUrl(arg));
+ return arg.isEmpty() ? QUrl() : scope.engine->callingQmlContext()->resolvedUrl(QUrl(arg));
}
QV4::ReturnedValue QQuickLoaderPrivate::extractInitialPropertyValues(QQmlV4Function *args, QObject *loader, bool *error)
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index 593181ee61..6100d1466a 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -154,9 +154,9 @@ void QQuickWindowQmlImpl::setWindowVisibility()
QQmlError error;
error.setObject(this);
- const QQmlContextData* urlContext = data->context;
+ QQmlRefPointer<QQmlContextData> urlContext = data->context;
while (urlContext && urlContext->url().isEmpty())
- urlContext = urlContext->parent;
+ urlContext = urlContext->parent();
error.setUrl(urlContext ? urlContext->url() : QUrl());
QString objectId = data->context->findObjectId(this);
@@ -167,7 +167,7 @@ void QQuickWindowQmlImpl::setWindowVisibility()
error.setDescription(QCoreApplication::translate("QQuickWindowQmlImpl",
"Conflicting properties 'visible' and 'visibility'"));
- QQmlEnginePrivate::get(data->context->engine)->warning(error);
+ QQmlEnginePrivate::get(data->context->engine())->warning(error);
}
if (d->visibility == AutomaticVisibility) {
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index 1cb30f5a8d..74e8d056c5 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -411,10 +411,9 @@ QQmlProperty
QQuickPropertyChangesPrivate::property(const QString &property)
{
Q_Q(QQuickPropertyChanges);
- QQmlContextData *context = nullptr;
- if (QQmlData *ddata = QQmlData::get(q))
- context = ddata->outerContext;
- QQmlProperty prop = QQmlPropertyPrivate::create(object, property, context);
+ QQmlData *ddata = QQmlData::get(q);
+ QQmlProperty prop = QQmlPropertyPrivate::create(
+ object, property, ddata ? ddata->outerContext : QQmlRefPointer<QQmlContextData>());
if (!prop.isValid()) {
qmlWarning(q) << QQuickPropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property);
return QQmlProperty();
@@ -469,7 +468,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
a.specifiedObject = d->object;
a.specifiedProperty = property;
- QQmlContextData *context = QQmlContextData::get(qmlContext(this));
+ QQmlRefPointer<QQmlContextData> context = QQmlContextData::get(qmlContext(this));
QQmlBinding *newBinding = nullptr;
if (e.binding && e.binding->isTranslationBinding()) {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index 12befeb1ec..3ae40bf687 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -1395,17 +1395,14 @@ void tst_QQmlEngineDebugService::invalidContexts()
QQmlContext context(m_engine);
getContexts();
QCOMPARE(m_dbg->rootContext().contexts.count(), base + 1);
- QQmlContextData *contextData = QQmlContextData::get(&context);
+ QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(&context);
contextData->invalidate();
getContexts();
QCOMPARE(m_dbg->rootContext().contexts.count(), base);
- QQmlContextData *rootData = QQmlContextData::get(m_engine->rootContext());
+ QQmlRefPointer<QQmlContextData> rootData = QQmlContextData::get(m_engine->rootContext());
rootData->invalidate();
getContexts();
QCOMPARE(m_dbg->rootContext().contexts.count(), 0);
- contextData->setParent(rootData); // makes context valid again, but not root.
- getContexts();
- QCOMPARE(m_dbg->rootContext().contexts.count(), 0);
}
void tst_QQmlEngineDebugService::createObjectOnDestruction()
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index 43cbd93396..79014a4450 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -35,7 +35,7 @@
#include <QtQuick>
#include <QtQuick/private/qquickrectangle_p.h>
#include <QtQuick/private/qquickmousearea_p.h>
-#include <private/qqmlcontext_p.h>
+#include <private/qqmlguardedcontextdata_p.h>
#include <private/qv4qmlcontext_p.h>
#include <private/qv4scopedvalue_p.h>
#include <private/qv4qmlcontext_p.h>
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
index 6754f22049..7b62469003 100644
--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
+++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
@@ -34,6 +34,7 @@
#include <QQmlComponent>
#include <QQmlExpression>
#include <private/qqmlcontext_p.h>
+#include <private/qqmlguardedcontextdata_p.h>
#include <private/qv4qmlcontext_p.h>
#include <private/qv4object_p.h>
#include "../../shared/util.h"
@@ -737,7 +738,7 @@ void tst_qqmlcontext::qobjectDerived()
// the engine
QQmlContext context(engine.rootContext());
- QObject *o1 = component.create(&context);
+ QScopedPointer<QObject> o1(component.create(&context));
Q_UNUSED(o1);
QCOMPARE(command.count, 2);
@@ -800,32 +801,33 @@ void tst_qqmlcontext::contextLeak()
QQmlData *ddata = QQmlData::get(obj.data());
QVERIFY(ddata);
- QQmlContextData *context = ddata->context;
+ QQmlRefPointer<QQmlContextData> context = ddata->context;
QVERIFY(context);
- QVERIFY(!context->importedScripts.isNullOrUndefined());
- QCOMPARE(int(context->importedScripts.valueRef()->as<QV4::Object>()->getLength()), 1);
-
- {
- QV4::Scope scope(ddata->jsWrapper.engine());
- QV4::ScopedValue scriptContextWrapper(scope);
- scriptContextWrapper = context->importedScripts.valueRef()->as<QV4::Object>()->get(uint(0));
- scriptContext = scriptContextWrapper->as<QV4::QQmlContextWrapper>()->getContext();
- }
+ QVERIFY(!context->importedScripts().isNullOrUndefined());
+ QCOMPARE(int(context->importedScripts().valueRef()->as<QV4::Object>()->getLength()), 1);
+
+ QV4::Scope scope(ddata->jsWrapper.engine());
+ QV4::ScopedValue scriptContextWrapper(scope);
+ scriptContextWrapper = context->importedScripts().valueRef()
+ ->as<QV4::Object>()->get(uint(0));
+ scriptContext = scriptContextWrapper->as<QV4::QQmlContextWrapper>()->getContext();
}
engine.collectGarbage();
// Each time a JS file (non-pragma-shared) is imported, we create a QQmlContext(Data) for it.
// Make sure that context does not leak.
- QVERIFY(scriptContext.isNull());
+ // The QQmlGuardedContextData also holds a reference. Therefore, the refCount is still 1.
+ // All other references should be gone by now.
+ QCOMPARE(scriptContext->refCount(), 1);
}
static bool buildObjectList(QQmlContext *ctxt)
{
static QHash<QObject *, QString> deletedObjects;
- QQmlContextData *p = QQmlContextData::get(ctxt);
- QObject *object = p->contextObject;
+ QQmlRefPointer<QQmlContextData> p = QQmlContextData::get(ctxt);
+ QObject *object = p->contextObject();
if (object) {
// If the object was actually deleted this is likely to crash in one way or another.
// Either the memory is still intact, then we will probably find the objectName, or it is
@@ -838,11 +840,11 @@ static bool buildObjectList(QQmlContext *ctxt)
});
}
- QQmlContextData *child = p->childContexts;
+ QQmlRefPointer<QQmlContextData> child = p->childContexts();
while (child) {
if (!buildObjectList(child->asQQmlContext()))
return false;
- child = child->nextChild;
+ child = child->nextChild();
}
return true;
@@ -878,10 +880,14 @@ void tst_qqmlcontext::outerContextObject()
void tst_qqmlcontext::contextObjectHierarchy()
{
QQmlEngine engine;
- QQmlComponent component(&engine);
- component.loadUrl(testFileUrl("contextObjectHierarchy.qml"));
- QVERIFY(component.isReady());
- QScopedPointer<QObject> root(component.create());
+ QScopedPointer<QObject> root;
+ {
+ // Drop the component after create(), to release the root context.
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("contextObjectHierarchy.qml"));
+ QVERIFY(component.isReady());
+ root.reset(component.create());
+ }
QVERIFY(!root.isNull());
for (const QObject *child : root->children())
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index cfbc329198..b3e4296a13 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -386,7 +386,7 @@ private slots:
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
- static void verifyContextLifetime(QQmlContextData *ctxt);
+ static void verifyContextLifetime(const QQmlRefPointer<QQmlContextData> &ctxt);
// When calling into JavaScript, the specific type of the return value can differ if that return
// value is a number. This is not only the case for non-integral numbers, or numbers that do not
@@ -4289,16 +4289,16 @@ void tst_qqmlecmascript::singletonTypeResolution()
delete object;
}
-void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
- QQmlContextData *childCtxt = ctxt->childContexts;
+void tst_qqmlecmascript::verifyContextLifetime(const QQmlRefPointer<QQmlContextData> &ctxt) {
+ QQmlRefPointer<QQmlContextData> childCtxt = ctxt->childContexts();
- if (!ctxt->importedScripts.isNullOrUndefined()) {
- QV4::ExecutionEngine *v4 = ctxt->engine->handle();
+ if (!ctxt->importedScripts().isNullOrUndefined()) {
+ QV4::ExecutionEngine *v4 = ctxt->engine()->handle();
QV4::Scope scope(v4);
- QV4::ScopedArrayObject scripts(scope, ctxt->importedScripts.value());
+ QV4::ScopedArrayObject scripts(scope, ctxt->importedScripts().value());
QV4::Scoped<QV4::QQmlContextWrapper> qml(scope);
for (quint32 i = 0; i < scripts->getLength(); ++i) {
- QQmlContextData *scriptContext, *newContext;
+ QQmlRefPointer<QQmlContextData> scriptContext, newContext;
qml = scripts->get(i);
scriptContext = qml ? qml->getContext() : nullptr;
@@ -4310,17 +4310,16 @@ void tst_qqmlecmascript::verifyContextLifetime(QQmlContextData *ctxt) {
Q_UNUSED(temporaryScope)
}
- ctxt->engine->collectGarbage();
+ ctxt->engine()->collectGarbage();
qml = scripts->get(i);
newContext = qml ? qml->getContext() : nullptr;
- QCOMPARE(scriptContext, newContext);
+ QCOMPARE(scriptContext.data(), newContext.data());
}
}
while (childCtxt) {
verifyContextLifetime(childCtxt);
-
- childCtxt = childCtxt->nextChild;
+ childCtxt = childCtxt->nextChild();
}
}
@@ -4592,9 +4591,7 @@ void tst_qqmlecmascript::importScripts()
QVERIFY(!object);
} else {
QVERIFY(object != nullptr);
-
- QQmlContextData *ctxt = QQmlContextData::get(engine.rootContext());
- tst_qqmlecmascript::verifyContextLifetime(ctxt);
+ tst_qqmlecmascript::verifyContextLifetime(QQmlContextData::get(engine.rootContext()));
for (int i = 0; i < propertyNames.size(); ++i)
QCOMPARE(object->property(propertyNames.at(i).toLatin1().constData()), propertyValues.at(i));
@@ -6138,24 +6135,22 @@ void tst_qqmlecmascript::nullObjectInitializer()
// Test that bindings don't evaluate once the engine has been destroyed
void tst_qqmlecmascript::deletedEngine()
{
- QQmlEngine *engine = new QQmlEngine;
- QQmlComponent component(engine, testFileUrl("deletedEngine.qml"));
+ QScopedPointer<QQmlEngine> engine(new QQmlEngine);
+ QQmlComponent component(engine.data(), testFileUrl("deletedEngine.qml"));
+ QScopedPointer<QObject> object(component.create());
- QObject *object = component.create();
QVERIFY(object != nullptr);
QCOMPARE(object->property("a").toInt(), 39);
object->setProperty("b", QVariant(9));
QCOMPARE(object->property("a").toInt(), 117);
- delete engine;
+ engine.reset(); // This drops the engine's context hierarchy and the object gets notified.
QCOMPARE(object->property("a").toInt(), 0);
object->setProperty("b", QVariant(10));
object->setProperty("b", QVariant());
QCOMPARE(object->property("a").toInt(), 0);
-
- delete object;
}
// Test the crashing part of QTBUG-9705
@@ -6217,25 +6212,30 @@ void tst_qqmlecmascript::variants()
void tst_qqmlecmascript::qtbug_9792()
{
QQmlEngine engine;
- QQmlComponent component(&engine, testFileUrl("qtbug_9792.qml"));
- QQmlContext *context = new QQmlContext(engine.rootContext());
+ QScopedPointer<QQmlContext> context(new QQmlContext(engine.rootContext()));
+ QScopedPointer<QObject> object;
- MyQmlObject *object = qobject_cast<MyQmlObject*>(component.create(context));
- QVERIFY(object != nullptr);
+ MyQmlObject *myQmlObject = nullptr;
+ {
+ // Drop the component after creation as that holds a strong reference
+ // to the root QQmlContextData. We want the context data to be destroyed.
+ QQmlComponent component(&engine, testFileUrl("qtbug_9792.qml"));
+ object.reset(component.create(context.data()));
+ myQmlObject = qobject_cast<MyQmlObject*>(object.data());
+ }
+ QVERIFY(myQmlObject != nullptr);
QTest::ignoreMessage(QtDebugMsg, "Hello world!");
- object->basicSignal();
+ myQmlObject->basicSignal();
- delete context;
+ context.reset();
QQmlTestMessageHandler messageHandler;
- object->basicSignal();
+ myQmlObject->basicSignal();
QVERIFY2(messageHandler.messages().isEmpty(), qPrintable(messageHandler.messageString()));
-
- delete object;
}
// Verifies that QPointer<>s used in the vmemetaobject are cleaned correctly
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index 31a4135d89..2c0e5f1d8c 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -149,7 +149,7 @@ void CustomBinding::componentComplete()
int bindingId = binding->value.compiledScriptIndex;
- QQmlContextData *context = QQmlContextData::get(qmlContext(this));
+ QQmlRefPointer<QQmlContextData> context = QQmlContextData::get(qmlContext(this));
QQmlProperty property(m_target, name, qmlContext(this));
QV4::Scope scope(qmlEngine(this)->handle());
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 6d932c2665..f2fa301565 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -4871,8 +4871,9 @@ static void beginDeferredOnce(QQmlEnginePrivate *enginePriv,
QQmlComponentPrivate::ConstructionState *state = new QQmlComponentPrivate::ConstructionState;
state->completePending = true;
- QQmlContextData *creationContext = nullptr;
- state->creator.reset(new QQmlObjectCreator(deferData->context->parent, deferData->compilationUnit, creationContext));
+ state->creator.reset(new QQmlObjectCreator(
+ deferData->context->parent(), deferData->compilationUnit,
+ QQmlRefPointer<QQmlContextData>()));
enginePriv->inProgressCreations++;
@@ -4904,7 +4905,7 @@ static void testExecuteDeferredOnce(const QQmlProperty &property)
QObject *object = property.object();
QQmlData *data = QQmlData::get(object);
if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object)) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
QQmlComponentPrivate::DeferredState state;
beginDeferredOnce(ep, property, &state);
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index 2e040eec18..956759668e 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -32,6 +32,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlcomponent.h>
#include <private/qmetaobjectbuilder_p.h>
+#include <private/qqmlcontextdata_p.h>
#include <QCryptographicHash>
#include "../../shared/util.h"
diff --git a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
index 33b8742170..1ede8968a4 100644
--- a/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
+++ b/tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp
@@ -1148,8 +1148,7 @@ void tst_QQuickRepeater::contextProperties()
while (!items.isEmpty()) {
QQuickItem *item = items.dequeue();
- QQmlContextData *data = QQmlContextData::get(qmlContext(item));
- QVERIFY(!data->hasExtraObject);
+ QVERIFY(!QQmlContextData::get(qmlContext(item))->extraObject());
for (QQuickItem *child : item->childItems())
items.enqueue(child);
}
diff --git a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
index 66069c48cb..d5ac20cafc 100644
--- a/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
+++ b/tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp
@@ -4219,11 +4219,15 @@ void tst_qquickvisualdatamodel::invalidContext()
engine.rootContext()->setContextProperty("myModel", &model);
QScopedPointer<QQmlContext> context(new QQmlContext(engine.rootContext()));
+ QScopedPointer<QObject> obj;
+ {
+ // The component keeps a reference to the root context as long as the engine lives.
+ // In order to drop the root context we need to drop the component first.
+ QQmlComponent c(&engine, testFileUrl("visualdatamodel.qml"));
+ obj.reset(c.create(context.data()));
+ }
- QQmlComponent c(&engine, testFileUrl("visualdatamodel.qml"));
-
-
- QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel*>(c.create(context.data()));
+ QQmlDelegateModel *visualModel = qobject_cast<QQmlDelegateModel *>(obj.get());
QVERIFY(visualModel);
QQuickItem *item = qobject_cast<QQuickItem*>(visualModel->object(4));