aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlengine_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmlengine_p.h')
-rw-r--r--src/qml/qml/qqmlengine_p.h363
1 files changed, 139 insertions, 224 deletions
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 04ed50b2ee..7c820679ba 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QQMLENGINE_P_H
#define QQMLENGINE_P_H
@@ -53,63 +17,46 @@
#include "qqmlengine.h"
-#include "qqmltypeloader_p.h"
-#include "qqmlimport_p.h"
-#include <private/qpodvector_p.h>
-#include "qqml.h"
-#include "qqmlvaluetype_p.h"
-#include "qqmlcontext.h"
-#include "qqmlcontextdata_p.h"
-#include "qqmlexpression.h"
-#include "qqmlproperty_p.h"
-#include "qqmlmetatype_p.h"
+#include <private/qfieldlist_p.h>
#include <private/qintrusivelist_p.h>
+#include <private/qjsengine_p.h>
+#include <private/qjsvalue_p.h>
+#include <private/qpodvector_p.h>
+#include <private/qqmldirparser_p.h>
+#include <private/qqmlimport_p.h>
+#include <private/qqmlmetatype_p.h>
+#include <private/qqmlnotifier_p.h>
+#include <private/qqmlproperty_p.h>
+#include <private/qqmltypeloader_p.h>
+#include <private/qqmlvaluetype_p.h>
#include <private/qrecyclepool_p.h>
-#include <private/qfieldlist_p.h>
#include <private/qv4engine_p.h>
-#include <private/qjsvalue_p.h>
+
+#include <QtQml/qqml.h>
+#include <QtQml/qqmlcontext.h>
#include <QtCore/qlist.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qmutex.h>
#include <QtCore/qpair.h>
+#include <QtCore/qpointer.h>
+#include <QtCore/qproperty.h>
#include <QtCore/qstack.h>
-#include <QtCore/qmutex.h>
#include <QtCore/qstring.h>
#include <QtCore/qthread.h>
-#include <private/qobject_p.h>
-
-#include <private/qjsengine_p.h>
-#include <private/qqmldirparser_p.h>
-
-#include <qproperty.h>
+#include <atomic>
QT_BEGIN_NAMESPACE
-class QQmlContext;
-class QQmlEngine;
-class QQmlContextPrivate;
-class QQmlExpression;
-class QQmlImportDatabase;
-class QNetworkReply;
class QNetworkAccessManager;
-class QQmlNetworkAccessManagerFactory;
-class QQmlTypeNameCache;
-class QQmlComponentAttached;
class QQmlDelayedError;
-class QQmlObjectCreator;
-class QDir;
class QQmlIncubator;
+class QQmlMetaObject;
+class QQmlNetworkAccessManagerFactory;
+class QQmlObjectCreator;
class QQmlProfiler;
class QQmlPropertyCapture;
-class QQmlMetaObject;
-
-struct QObjectForeign {
- Q_GADGET
- QML_FOREIGN(QObject)
- QML_NAMED_ELEMENT(QtObject)
- QML_ADDED_IN_VERSION(2, 0)
- Q_CLASSINFO("QML.Root", "QML")
-};
// This needs to be declared here so that the pool for it can live in QQmlEnginePrivate.
// The inline method definitions are in qqmljavascriptexpression_p.h
@@ -127,11 +74,20 @@ public:
};
struct QPropertyChangeTrigger : QPropertyObserver {
- QPropertyChangeTrigger(QQmlJavaScriptExpression *expression) : QPropertyObserver(&QPropertyChangeTrigger::trigger), m_expression(expression) {}
- QQmlJavaScriptExpression * m_expression;
- QObject *target = nullptr;
+ Q_DISABLE_COPY_MOVE(QPropertyChangeTrigger)
+
+ QPropertyChangeTrigger(QQmlJavaScriptExpression *expression)
+ : QPropertyObserver(&QPropertyChangeTrigger::trigger)
+ , m_expression(expression)
+ {
+ }
+
+ QPointer<QObject> target;
+ QQmlJavaScriptExpression *m_expression;
int propertyIndex = 0;
static void trigger(QPropertyObserver *, QUntypedPropertyData *);
+
+ QMetaProperty property() const;
};
struct TriggerList : QPropertyChangeTrigger {
@@ -141,11 +97,11 @@ struct TriggerList : QPropertyChangeTrigger {
TriggerList *next = nullptr;
};
-class Q_QML_PRIVATE_EXPORT QQmlEnginePrivate : public QJSEnginePrivate
+class Q_QML_EXPORT QQmlEnginePrivate : public QJSEnginePrivate
{
Q_DECLARE_PUBLIC(QQmlEngine)
public:
- QQmlEnginePrivate(QQmlEngine *);
+ explicit QQmlEnginePrivate(QQmlEngine *q) : importDatabase(q), typeLoader(q) {}
~QQmlEnginePrivate() override;
void init();
@@ -153,49 +109,48 @@ public:
// is just qmlClearTypeRegistrations (which can't be called while an engine exists)
static bool baseModulesUninitialized;
- QQmlPropertyCapture *propertyCapture;
+ QQmlPropertyCapture *propertyCapture = nullptr;
QRecyclePool<QQmlJavaScriptExpressionGuard> jsExpressionGuardPool;
QRecyclePool<TriggerList> qPropertyTriggerPool;
- QQmlContext *rootContext;
+ QQmlContext *rootContext = nullptr;
+ Q_OBJECT_BINDABLE_PROPERTY(QQmlEnginePrivate, QString, translationLanguage);
#if !QT_CONFIG(qml_debug)
static const quintptr profiler = 0;
#else
- QQmlProfiler *profiler;
+ QQmlProfiler *profiler = nullptr;
#endif
- bool outputWarningsToMsgLog;
+ bool outputWarningsToMsgLog = true;
// Bindings that have had errors during startup
- QQmlDelayedError *erroredBindings;
- int inProgressCreations;
+ QQmlDelayedError *erroredBindings = nullptr;
+ int inProgressCreations = 0;
QV4::ExecutionEngine *v4engine() const { return q_func()->handle(); }
#if QT_CONFIG(qml_worker_script)
- QThread *workerScriptEngine;
+ QThread *workerScriptEngine = nullptr;
#endif
QUrl baseUrl;
- typedef QPair<QPointer<QObject>,int> FinalizeCallback;
- void registerFinalizeCallback(QObject *obj, int index);
-
- QQmlObjectCreator *activeObjectCreator;
+ QQmlObjectCreator *activeObjectCreator = nullptr;
#if QT_CONFIG(qml_network)
QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
QNetworkAccessManager *getNetworkAccessManager() const;
- mutable QNetworkAccessManager *networkAccessManager;
- mutable QQmlNetworkAccessManagerFactory *networkAccessManagerFactory;
+ mutable QNetworkAccessManager *networkAccessManager = nullptr;
+ mutable QQmlNetworkAccessManagerFactory *networkAccessManagerFactory = nullptr;
#endif
+ mutable QRecursiveMutex imageProviderMutex;
QHash<QString,QSharedPointer<QQmlImageProviderBase> > imageProviders;
QSharedPointer<QQmlImageProviderBase> imageProvider(const QString &providerId) const;
QList<QQmlAbstractUrlInterceptor *> urlInterceptors;
- int scarceResourcesRefCount;
+ int scarceResourcesRefCount = 0;
void referenceScarceResources();
void dereferenceScarceResources();
@@ -204,52 +159,24 @@ public:
QString offlineStoragePath;
- mutable quint32 uniqueId;
- inline quint32 getUniqueId() const {
- return uniqueId++;
- }
-
// Unfortunate workaround to avoid a circular dependency between
// qqmlengine_p.h and qqmlincubator_p.h
- struct Incubator : public QSharedData {
+ struct Incubator {
QIntrusiveListNode next;
- // Unfortunate workaround for MSVC
- QIntrusiveListNode nextWaitingFor;
};
QIntrusiveList<Incubator, &Incubator::next> incubatorList;
- unsigned int incubatorCount;
- QQmlIncubationController *incubationController;
+ unsigned int incubatorCount = 0;
+ QQmlIncubationController *incubationController = nullptr;
void incubate(QQmlIncubator &, const QQmlRefPointer<QQmlContextData> &);
// These methods may be called from any thread
- inline bool isEngineThread() const;
- inline static bool isEngineThread(const QQmlEngine *);
- template<typename T>
- inline void deleteInEngineThread(T *);
- template<typename T>
- inline static void deleteInEngineThread(QQmlEnginePrivate *, T *);
QString offlineStorageDatabaseDirectory() const;
- // These methods may be called from the loader thread
- inline QQmlPropertyCache *cache(const QQmlType &, QTypeRevision version);
- using QJSEnginePrivate::cache;
-
- // These methods may be called from the loader thread
- QQmlMetaObject rawMetaObjectForType(int) const;
- QQmlMetaObject metaObjectForType(int) const;
- QQmlPropertyCache *propertyCacheForType(int);
- QQmlPropertyCache *rawPropertyCacheForType(int);
- QQmlPropertyCache *rawPropertyCacheForType(int, QTypeRevision version);
- void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
- void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
- QV4::ExecutableCompilationUnit *obtainExecutableCompilationUnit(int typeId);
-
bool isTypeLoaded(const QUrl &url) const;
bool isScriptLoaded(const QUrl &url) const;
template <typename T>
T singletonInstance(const QQmlType &type);
- void destroySingletonInstance(const QQmlType &type);
void sendQuit();
void sendExit(int retCode = 0);
@@ -270,24 +197,22 @@ public:
static QList<QQmlError> qmlErrorFromDiagnostics(const QString &fileName, const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages);
- static void defineModule();
-
static bool designerMode();
static void activateDesignerMode();
- static bool qml_debugging_enabled;
+ static std::atomic<bool> qml_debugging_enabled;
mutable QMutex networkAccessManagerMutex;
QQmlGadgetPtrWrapper *valueTypeInstance(QMetaType type)
{
int typeIndex = type.id();
- auto it = cachedValueTypeInstances.find(typeIndex);
- if (it != cachedValueTypeInstances.end())
+ auto it = cachedValueTypeInstances.constFind(typeIndex);
+ if (it != cachedValueTypeInstances.cend())
return *it;
if (QQmlValueType *valueType = QQmlMetaType::valueType(type)) {
- QQmlGadgetPtrWrapper *instance = new QQmlGadgetPtrWrapper(valueType, q_func());
+ QQmlGadgetPtrWrapper *instance = new QQmlGadgetPtrWrapper(valueType);
cachedValueTypeInstances.insert(typeIndex, instance);
return instance;
}
@@ -295,38 +220,81 @@ public:
return nullptr;
}
- QJSValue executeRuntimeFunction(const QUrl &url, qsizetype functionIndex, QObject *thisObject,
- int arcg=0, void **args = nullptr, QMetaType *types = nullptr);
+ void executeRuntimeFunction(const QUrl &url, qsizetype functionIndex, QObject *thisObject,
+ int argc = 0, void **args = nullptr, QMetaType *types = nullptr);
+ void executeRuntimeFunction(const QV4::ExecutableCompilationUnit *unit, qsizetype functionIndex,
+ QObject *thisObject, int argc = 0, void **args = nullptr,
+ QMetaType *types = nullptr);
+ QV4::ExecutableCompilationUnit *compilationUnitFromUrl(const QUrl &url);
+ QQmlRefPointer<QQmlContextData>
+ createInternalContext(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
+ const QQmlRefPointer<QQmlContextData> &parentContext,
+ int subComponentIndex, bool isComponentRoot);
+ static void setInternalContext(QObject *This, const QQmlRefPointer<QQmlContextData> &context,
+ QQmlContextData::QmlObjectKind kind)
+ {
+ Q_ASSERT(This);
+ QQmlData *ddata = QQmlData::get(This, /*create*/ true);
+ // NB: copied from QQmlObjectCreator::createInstance()
+ //
+ // the if-statement logic to determine the kind is:
+ // if (static_cast<quint32>(index) == 0 || ddata->rootObjectInCreation || isInlineComponent)
+ // then QQmlContextData::DocumentRoot. here, we pass this through qmltc
+ context->installContext(ddata, kind);
+ Q_ASSERT(qmlEngine(This));
+ }
private:
- class SingletonInstances : private QHash<QQmlType, QJSValue>
+ class SingletonInstances : private QHash<QQmlType::SingletonInstanceInfo::ConstPtr, QJSValue>
{
public:
- void convertAndInsert(QV4::ExecutionEngine *engine, const QQmlType &type, QJSValue *value)
+ void convertAndInsert(
+ QV4::ExecutionEngine *engine, const QQmlType::SingletonInstanceInfo::ConstPtr &type,
+ QJSValue *value)
{
QJSValuePrivate::manageStringOnV4Heap(engine, value);
insert(type, *value);
}
- using QHash<QQmlType, QJSValue>::value;
- using QHash<QQmlType, QJSValue>::take;
+ void clear()
+ {
+ const auto canDelete = [](QObject *instance, const auto &siinfo) -> bool {
+ if (!instance)
+ return false;
+
+ if (!siinfo->url.isEmpty())
+ return true;
+
+ const auto *ddata = QQmlData::get(instance, false);
+ return !(ddata && ddata->indestructible && ddata->explicitIndestructibleSet);
+ };
+
+ for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
+ auto *instance = it.value().toQObject();
+ if (canDelete(instance, it.key()))
+ QQmlData::markAsDeleted(instance);
+ }
+
+ for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
+ QObject *instance = it.value().toQObject();
+
+ if (canDelete(instance, it.key()))
+ delete instance;
+ }
+
+ QHash<QQmlType::SingletonInstanceInfo::ConstPtr, QJSValue>::clear();
+ }
+
+ using QHash<QQmlType::SingletonInstanceInfo::ConstPtr, QJSValue>::value;
+ using QHash<QQmlType::SingletonInstanceInfo::ConstPtr, QJSValue>::take;
};
SingletonInstances singletonInstances;
QHash<int, QQmlGadgetPtrWrapper *> cachedValueTypeInstances;
- // These members must be protected by a QQmlEnginePrivate::Locker as they are required by
- // the threaded loader. Only access them through their respective accessor methods.
- QHash<int, QV4::ExecutableCompilationUnit *> m_compositeTypes;
static bool s_designerMode;
- // These members is protected by the full QQmlEnginePrivate::mutex mutex
- struct Deletable { Deletable():next(nullptr) {} virtual ~Deletable() {} Deletable *next; };
- QFieldList<Deletable, &Deletable::next> toDeleteInEngineThread;
- void doDeleteInEngineThread();
-
void cleanupScarceResources();
- QQmlPropertyCache *findPropertyCacheInCompositeTypes(int t) const;
};
/*
@@ -359,81 +327,6 @@ inline void QQmlEnginePrivate::dereferenceScarceResources()
}
}
-/*!
-Returns true if the calling thread is the QQmlEngine thread.
-*/
-bool QQmlEnginePrivate::isEngineThread() const
-{
-
- return QThread::currentThread() == q_ptr->thread();
-}
-
-/*!
-Returns true if the calling thread is the QQmlEngine \a engine thread.
-*/
-bool QQmlEnginePrivate::isEngineThread(const QQmlEngine *engine)
-{
- Q_ASSERT(engine);
- return QQmlEnginePrivate::get(engine)->isEngineThread();
-}
-
-/*!
-Delete \a value in the engine thread. If the calling thread is the engine
-thread, \a value will be deleted immediately.
-
-This method should be used for *any* type that has resources that need to
-be freed in the engine thread. This is generally types that use V8 handles.
-As there is some small overhead in checking the current thread, it is best
-practice to check if any V8 handles actually need to be freed and delete
-the instance directly if not.
-*/
-template<typename T>
-void QQmlEnginePrivate::deleteInEngineThread(T *value)
-{
- Q_ASSERT(value);
- if (isEngineThread()) {
- delete value;
- } else {
- struct I : public Deletable {
- I(T *value) : value(value) {}
- ~I() override { delete value; }
- T *value;
- };
- I *i = new I(value);
- mutex.lock();
- bool wasEmpty = toDeleteInEngineThread.isEmpty();
- toDeleteInEngineThread.append(i);
- mutex.unlock();
- if (wasEmpty)
- QCoreApplication::postEvent(q_ptr, new QEvent(QEvent::User));
- }
-}
-
-/*!
-Delete \a value in the \a engine thread. If the calling thread is the engine
-thread, \a value will be deleted immediately.
-*/
-template<typename T>
-void QQmlEnginePrivate::deleteInEngineThread(QQmlEnginePrivate *engine, T *value)
-{
- Q_ASSERT(engine);
- engine->deleteInEngineThread<T>(value);
-}
-
-/*!
-Returns a QQmlPropertyCache for \a type with \a minorVersion.
-
-The returned cache is not referenced, so if it is to be stored, call addref().
-*/
-QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, QTypeRevision version)
-{
- Q_ASSERT(type.isValid());
- Q_ASSERT(type.containsRevisionedAttributes());
-
- Locker locker(this);
- return QQmlMetaType::propertyCache(type, version);
-}
-
QV4::ExecutionEngine *QQmlEnginePrivate::getV4Engine(QQmlEngine *e)
{
Q_ASSERT(e);
@@ -491,13 +384,35 @@ QQmlEnginePrivate *QQmlEnginePrivate::get(QV4::ExecutionEngine *e)
}
template<>
-Q_QML_PRIVATE_EXPORT QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type);
+Q_QML_EXPORT QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type);
template<typename T>
T QQmlEnginePrivate::singletonInstance(const QQmlType &type) {
return qobject_cast<T>(singletonInstance<QJSValue>(type).toQObject());
}
+struct LoadHelper final : QQmlTypeLoader::Blob
+{
+ LoadHelper(QQmlTypeLoader *loader, QAnyStringView uri);
+
+ struct ResolveTypeResult
+ {
+ enum Status { NoSuchModule, ModuleFound } status;
+ QQmlType type;
+ };
+
+ ResolveTypeResult resolveType(QAnyStringView typeName);
+
+protected:
+ void dataReceived(const SourceCodeData &) final { Q_UNREACHABLE(); }
+ void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *) final { Q_UNREACHABLE(); }
+
+private:
+ bool couldFindModule() const;
+ QString m_uri;
+};
+
+
QT_END_NAMESPACE
#endif // QQMLENGINE_P_H