aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-02-26 16:04:23 +0100
committerUlf Hermann <ulf.hermann@qt.io>2020-03-23 12:00:33 +0100
commitd51c007ecc8aa6256cb95cf3992e5ac34a70fa3f (patch)
tree80f90690d29ab48a128c075b6c982cea7256a150 /src/qml/qml
parentc83a39fd460d1787d1c17391413543bf7ca4c330 (diff)
Encapsulate QQmlContextData
This class is not a private detail of QQmlContext. And it is incredibly hard to see who owns what in there. Let's add some civilization ... We enforce refcounting for QQmlContextData across the code base, with two exceptions: 1. QQmlContextPrivate may or may not own its QQmlContextData. 2. We may request a QQmlContextData owned by its parent QQmlContextData. For these two cases we keep flags in QQmlContextData and when the respective field (m_parent or m_publicContext) is reset, we release() once. Furthermore, QQmlContextData and QQmlGuardedContextData are moved to their own files, in order to de-spaghettify qqmlcontext_p.h and qqmlcontext.cpp. When the QQmlEngine is deleted, any QQmlComponents drop their object creators now, in order to release any context data held by those. Before, the context data would be deleted, but the object creators would retain the dangling pointer. [ChangeLog][QML][Important Behavior Changes] QQmlContext::baseUrl() does what the documentation says now: It prefers explicitly set baseUrls over compilation unit URLs. Only if no baseUrl is set, the CU's URL is returned. It used to prefer the CU's URL. Change-Id: Ieeb5dcb07b45d891526191321386d5443b8f5738 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml')
-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
42 files changed, 1538 insertions, 1197 deletions
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('.'));