diff options
author | Ulf Hermann <[email protected]> | 2025-06-03 14:35:29 +0200 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2025-06-17 07:00:33 +0200 |
commit | d2bc4a4330254c0c68a0ade51b59a71c4b67b470 (patch) | |
tree | 8345312f50df0be783618fd75a1d7e52c2ca65d7 | |
parent | 8e0810c19c791386fd5f2cefc6b992f45be21750 (diff) |
QtQml: Hold QQmlTypeLoader in QV4::ExecutionEngine
... rather than QQmlEngine. This paves the way for having the type
loader attached to ExecutionEngine rather than QQmlEngine.
Also, reference the execution engine in the type loader, in turn.
Task-number: QTBUG-19407
Change-Id: I04e571c5c6ac5bce5e82537cb96c6940c7186f3a
Reviewed-by: Fabian Kosmale <[email protected]>
47 files changed, 283 insertions, 301 deletions
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp index 614890a8fd..c84ba7269a 100644 --- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp +++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp @@ -92,11 +92,11 @@ void QQmlProfilerServiceImpl::engineAboutToBeAdded(QJSEngine *engine) QMutexLocker lock(&m_configMutex); if (QQmlEngine *qmlEngine = qobject_cast<QQmlEngine *>(engine)) { - QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(qmlEngine); - QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, enginePrivate); + QQmlProfilerAdapter *qmlAdapter + = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(qmlEngine)); addEngineProfiler(qmlAdapter, engine); QQmlProfilerAdapter *compileAdapter - = new QQmlProfilerAdapter(this, &(enginePrivate->typeLoader)); + = new QQmlProfilerAdapter(this, QQmlTypeLoader::get(engine)); addEngineProfiler(compileAdapter, engine); } QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, engine->handle()); diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h index 0ab893d02a..c1f7895549 100644 --- a/src/qml/jsapi/qjsengine_p.h +++ b/src/qml/jsapi/qjsengine_p.h @@ -35,9 +35,11 @@ class Q_QML_EXPORT QJSEnginePrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QJSEngine) public: - static QJSEnginePrivate* get(QJSEngine*e) { return e->d_func(); } + static QJSEnginePrivate *get(QJSEngine*e) { return e->d_func(); } static const QJSEnginePrivate* get(const QJSEngine*e) { return e->d_func(); } - static QJSEnginePrivate* get(QV4::ExecutionEngine *e); + static QJSEngine *get(QJSEnginePrivate *e) { return e->q_func(); } + static const QJSEngine *get(const QJSEnginePrivate *e) { return e->q_func(); } + static QJSEnginePrivate *get(QV4::ExecutionEngine *e); QJSEnginePrivate() = default; ~QJSEnginePrivate() override; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 82e653a645..1f27ca1f1e 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -856,6 +856,10 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) ExecutionEngine::~ExecutionEngine() { +#if QT_CONFIG(qml_network) + delete networkAccessManager; +#endif + m_typeLoader.reset(); qDeleteAll(m_extensionData); delete m_multiplyWrappedQObjects; m_multiplyWrappedQObjects = nullptr; @@ -884,6 +888,15 @@ ExecutionEngine::~ExecutionEngine() #endif } +#if QT_CONFIG(qml_network) +QNetworkAccessManager *ExecutionEngine::getNetworkAccessManager() +{ + if (!networkAccessManager) + networkAccessManager = typeLoader()->createNetworkAccessManager(nullptr); + return networkAccessManager; +} +#endif + #if QT_CONFIG(qml_debug) void ExecutionEngine::setDebugger(Debugging::Debugger *debugger) { @@ -2194,13 +2207,10 @@ ExecutionEngine::Module ExecutionEngine::registerNativeModule( return Module(); QQmlRefPointer<CompiledData::CompilationUnit> cu; - if (m_qmlEngine) { - // Make sure the type loader doesn't try to resolve the module anymore. - // If some other code requests that same module, we need to produce the same CU. - cu = QQmlEnginePrivate::get(m_qmlEngine)->typeLoader.injectModule(url, unit); - } else { - cu = QQml::makeRefPointer<CompiledData::CompilationUnit>(unit); - } + + // Make sure the type loader doesn't try to resolve the module anymore. + // If some other code requests that same module, we need to produce the same CU. + cu = typeLoader()->injectModule(url, unit); QQmlRefPointer<ExecutableCompilationUnit> newModule = insertCompilationUnit(std::move(cu)); @@ -2956,11 +2966,4 @@ int ExecutionEngine::registerExtension() return registrationData()->extensionCount++; } -#if QT_CONFIG(qml_network) -QNetworkAccessManager *QV4::detail::getNetworkAccessManager(ExecutionEngine *engine) -{ - return engine->qmlEngine()->networkAccessManager(); -} -#endif // qml_network - QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 764a796f9d..8c1c12e543 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -57,16 +57,8 @@ QT_BEGIN_NAMESPACE #if QT_CONFIG(qml_network) class QNetworkAccessManager; - -namespace QV4 { -struct QObjectMethod; -namespace detail { -QNetworkAccessManager *getNetworkAccessManager(ExecutionEngine *engine); -} -} -#else -namespace QV4 { struct QObjectMethod; } #endif // qml_network +namespace QV4 { struct QObjectMethod; } // Used to allow a QObject method take and return raw V4 handles without having to expose // 48 in the public API. @@ -176,9 +168,9 @@ public: template<typename TypeLoader = QQmlTypeLoader> TypeLoader *typeLoader() { - if (m_qmlEngine) - return TypeLoader::get(m_qmlEngine); - return nullptr; + if (!m_typeLoader) + m_typeLoader = std::make_unique<TypeLoader>(this); + return m_typeLoader.get(); } enum JSObjects { @@ -359,7 +351,8 @@ public: FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); } #if QT_CONFIG(qml_network) - QNetworkAccessManager* (*networkAccessManager)(ExecutionEngine*) = detail::getNetworkAccessManager; + QNetworkAccessManager *getNetworkAccessManager(); + QNetworkAccessManager *networkAccessManager = nullptr; #endif enum JSStrings { @@ -866,6 +859,7 @@ private: void *m_xmlHttpRequestData = nullptr; #endif + std::unique_ptr<QQmlTypeLoader> m_typeLoader; QQmlEngine *m_qmlEngine = nullptr; QQmlDelayedCallQueue m_delayedCallQueue; diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index baef0b4864..4d29d6b890 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -201,7 +201,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r if (context->imports() && (name->startsWithUpper() || context->valueTypesAreAddressable())) { // Search for attached properties, enums and imported scripts QQmlTypeNameCache::Result r = context->imports()->query<QQmlImport::AllowRecursion>( - name, QQmlTypeLoader::get(ep)); + name, v4->typeLoader()); if (r.isValid()) { if (hasProperty) diff --git a/src/qml/qml/ftw/qqmlthread_impl.cpp b/src/qml/qml/ftw/qqmlthread_impl.cpp index 7a5e40e995..1114e71e29 100644 --- a/src/qml/qml/ftw/qqmlthread_impl.cpp +++ b/src/qml/qml/ftw/qqmlthread_impl.cpp @@ -224,6 +224,12 @@ bool QQmlThread::isThisThread() const return d->isCurrentThread(); } +bool QQmlThread::isParentThread() const +{ + // The thread() of the QQmlThread is its parent thread. + return d->thread()->isCurrentThread(); +} + QThread *QQmlThread::thread() const { return const_cast<QThread *>(static_cast<const QThread *>(d)); diff --git a/src/qml/qml/ftw/qqmlthread_p.h b/src/qml/qml/ftw/qqmlthread_p.h index 75d2efca4d..b373ee988d 100644 --- a/src/qml/qml/ftw/qqmlthread_p.h +++ b/src/qml/qml/ftw/qqmlthread_p.h @@ -38,6 +38,7 @@ public: void wait(); bool isThisThread() const; + bool isParentThread() const; // Synchronously invoke a method in the thread template<typename Method, typename ...Args> diff --git a/src/qml/qml/ftw/qqmlthread_stub.cpp b/src/qml/qml/ftw/qqmlthread_stub.cpp index d65ebc7db6..0c30bce848 100644 --- a/src/qml/qml/ftw/qqmlthread_stub.cpp +++ b/src/qml/qml/ftw/qqmlthread_stub.cpp @@ -71,6 +71,11 @@ bool QQmlThread::isThisThread() const return d->thread()->isCurrentThread(); } +bool QQmlThread::isParentThread() const +{ + return d->thread()->isCurrentThread(); +} + void QQmlThread::internalCallMethodInThread(Message *message) { internalCallMethodInMain(message); diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index c55064c600..c12e64b7ce 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -116,8 +116,8 @@ QQmlAttachedPropertiesFunc qmlAttachedPropertiesFunction(QObject *object, const QMetaObject *attachedMetaObject) { QQmlEngine *engine = object ? qmlEngine(object) : nullptr; - return QQmlMetaType::attachedPropertiesFunc(engine ? QQmlEnginePrivate::get(engine) : nullptr, - attachedMetaObject); + return QQmlMetaType::attachedPropertiesFunc( + engine ? QQmlTypeLoader::get(engine) : nullptr, attachedMetaObject); } QObject *qmlAttachedPropertiesObject(QObject *object, QQmlAttachedPropertiesFunc func, bool create) @@ -507,7 +507,7 @@ int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *q Types; internal code should use QQmlMetaType API. */ QQmlEngine engine; - QQmlTypeLoader *typeLoader = &QQmlEnginePrivate::get(&engine)->typeLoader; + QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(&engine); auto loadHelper = QQml::makeRefPointer<LoadHelper>( typeLoader, uri, qmlName, QQmlTypeLoader::Synchronous); const QQmlType type = loadHelper->type(); @@ -2615,8 +2615,7 @@ bool AOTCompiledContext::loadAttachedLookup(uint index, QObject *object, void *t QV4::Scoped<QV4::QQmlTypeWrapper> wrapper(scope, lookup->qmlTypeLookup.qmlTypeWrapper); Q_ASSERT(wrapper); *static_cast<QObject **>(target) = qmlAttachedPropertiesObject( - object, wrapper->d()->type().attachedPropertiesFunction( - QQmlEnginePrivate::get(qmlEngine()))); + object, wrapper->d()->type().attachedPropertiesFunction(scope.engine->typeLoader())); return true; } diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp index 221153b7f1..108312a859 100644 --- a/src/qml/qml/qqmlapplicationengine.cpp +++ b/src/qml/qml/qqmlapplicationengine.cpp @@ -15,8 +15,8 @@ using namespace Qt::Literals::StringLiterals; QT_BEGIN_NAMESPACE -QQmlApplicationEnginePrivate::QQmlApplicationEnginePrivate(QQmlEngine *e) - : QQmlEnginePrivate(e) +QQmlApplicationEnginePrivate::QQmlApplicationEnginePrivate() + : QQmlEnginePrivate() { uiLanguage = QLocale().bcp47Name(); } @@ -126,7 +126,7 @@ void QQmlApplicationEnginePrivate::startLoad(QAnyStringView uri, QAnyStringView const QQmlType type = componentPriv->loadHelperType(); if (type.sourceUrl().isValid()) { - const auto qmlDirData = typeLoader.getQmldir(type.sourceUrl()); + const auto qmlDirData = QQmlTypeLoader::get(q)->getQmldir(type.sourceUrl()); const QUrl url = qmlDirData->finalUrl(); // A QRC URL coming from a qmldir cannot contain a relative path Q_ASSERT(url.scheme() != "qrc"_L1 || url.path().startsWith('/'_L1)); @@ -296,7 +296,7 @@ void QQmlApplicationEnginePrivate::updateTranslationDirectory(const QUrl &url) order to load a QML file. */ QQmlApplicationEngine::QQmlApplicationEngine(QObject *parent) -: QQmlEngine(*(new QQmlApplicationEnginePrivate(this)), parent) +: QQmlEngine(*(new QQmlApplicationEnginePrivate), parent) { QJSEnginePrivate::addToDebugServer(this); } diff --git a/src/qml/qml/qqmlapplicationengine_p.h b/src/qml/qml/qqmlapplicationengine_p.h index fa74de876f..45107deb43 100644 --- a/src/qml/qml/qqmlapplicationengine_p.h +++ b/src/qml/qml/qqmlapplicationengine_p.h @@ -28,7 +28,7 @@ class Q_QML_EXPORT QQmlApplicationEnginePrivate : public QQmlEnginePrivate { Q_DECLARE_PUBLIC(QQmlApplicationEngine) public: - QQmlApplicationEnginePrivate(QQmlEngine *e); + QQmlApplicationEnginePrivate(); ~QQmlApplicationEnginePrivate(); void ensureInitialized(); void init(); diff --git a/src/qml/qml/qqmlbuiltinfunctions.cpp b/src/qml/qml/qqmlbuiltinfunctions.cpp index d0a30e7113..9b2bbd8dd0 100644 --- a/src/qml/qml/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/qqmlbuiltinfunctions.cpp @@ -1374,7 +1374,7 @@ QObject *QtObject::createQmlObject(const QString &qml, QObject *parent, const QU return nullptr; } - QQmlRefPointer<QQmlTypeData> typeData = QQmlEnginePrivate::get(engine)->typeLoader.getType( + QQmlRefPointer<QQmlTypeData> typeData = v4Engine()->typeLoader()->getType( qml.toUtf8(), resolvedUrl, QQmlTypeLoader::Synchronous); if (!typeData->isCompleteOrError()) { @@ -1738,10 +1738,10 @@ QVariant QtObject::enumStringToValue(QJSValue enumType, QJSValue string) QQmlType type = enumWrapper->d()->type(); int enumIndex = enumWrapper->d()->enumIndex; QString keyString = string.toString(); - auto &typeLoader = QQmlEnginePrivate::get(m_engine->qmlEngine())->typeLoader; + auto *typeLoader = m_engine->typeLoader(); int value = enumWrapper->d()->scoped - ? type.scopedEnumValue(&typeLoader, enumIndex, keyString, &ok) - : type.unscopedEnumValue(&typeLoader, enumIndex, keyString, &ok); + ? type.scopedEnumValue(typeLoader, enumIndex, keyString, &ok) + : type.unscopedEnumValue(typeLoader, enumIndex, keyString, &ok); if (ok) return value; @@ -1773,10 +1773,10 @@ QVariant QtObject::enumValueToString(QJSValue enumType, QJSValue value) QQmlType type = enumWrapper->d()->type(); int enumIndex = enumWrapper->d()->enumIndex; int keyValue = value.toInt(); - auto &typeLoader = QQmlEnginePrivate::get(m_engine->qmlEngine())->typeLoader; + auto *typeLoader = m_engine->typeLoader(); QString key = enumWrapper->d()->scoped - ? type.scopedEnumKey(&typeLoader, enumIndex, keyValue, &ok) - : type.unscopedEnumKey(&typeLoader, enumIndex, keyValue, &ok); + ? type.scopedEnumKey(typeLoader, enumIndex, keyValue, &ok) + : type.unscopedEnumKey(typeLoader, enumIndex, keyValue, &ok); if (ok) return key; @@ -1805,11 +1805,11 @@ QVariant QtObject::enumValueToStrings(QJSValue enumType, QJSValue value) QQmlType type = enumWrapper->d()->type(); int enumIndex = enumWrapper->d()->enumIndex; int keyValue = value.toInt(); - auto &typeLoader = QQmlEnginePrivate::get(m_engine->qmlEngine())->typeLoader; + auto *typeLoader = m_engine->typeLoader(); Scope scope(m_engine); QStringList keys = enumWrapper->d()->scoped - ? type.scopedEnumKeys(&typeLoader, enumIndex, keyValue, &ok) - : type.unscopedEnumKeys(&typeLoader, enumIndex, keyValue, &ok); + ? type.scopedEnumKeys(typeLoader, enumIndex, keyValue, &ok) + : type.unscopedEnumKeys(typeLoader, enumIndex, keyValue, &ok); if (ok) return keys; diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 1dc73b9321..6ba59fad9e 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -467,8 +467,7 @@ QQmlComponent::~QQmlComponent() if (d->m_engine && !d->m_typeData->isCompleteOrError()) { // In this case we have to send it to the type loader thread to be dropped. It will // manipulate its "waiting" lists that other blobs may be using concurrently. - QQmlEnginePrivate::get(d->m_engine)->typeLoader.drop( - QQmlDataBlob::Ptr(d->m_typeData.data())); + QQmlTypeLoader::get(d->m_engine)->drop(QQmlDataBlob::Ptr(d->m_typeData.data())); } d->m_typeData.reset(); } @@ -725,7 +724,7 @@ void QQmlComponent::setData(const QByteArray &data, const QUrl &url) d->m_url = url; - QQmlRefPointer<QQmlTypeData> typeData = QQmlEnginePrivate::get(d->m_engine)->typeLoader.getType(data, url); + QQmlRefPointer<QQmlTypeData> typeData = QQmlTypeLoader::get(d->m_engine)->getType(data, url); if (typeData->isCompleteOrError()) { d->fromTypeData(typeData); @@ -824,8 +823,7 @@ void QQmlComponentPrivate::loadUrl(const QUrl &newUrl, QQmlComponent::Compilatio QQmlTypeLoader::Mode loaderMode = (mode == QQmlComponent::Asynchronous) ? QQmlTypeLoader::Asynchronous : QQmlTypeLoader::PreferSynchronous; - QQmlRefPointer<QQmlTypeData> data - = QQmlEnginePrivate::get(m_engine)->typeLoader.getType(m_url, loaderMode); + QQmlRefPointer<QQmlTypeData> data = QQmlTypeLoader::get(m_engine)->getType(m_url, loaderMode); if (data->isCompleteOrError()) { fromTypeData(data); @@ -1420,9 +1418,8 @@ void QQmlComponentPrivate::prepareLoadFromModule( if (m_loadHelper) m_loadHelper->unregisterCallback(this); - QQmlTypeLoader *typeLoader = &QQmlEnginePrivate::get(m_engine)->typeLoader; // LoadHelper must be on the Heap as it derives from QQmlRefCount - m_loadHelper = QQml::makeRefPointer<LoadHelper>(typeLoader, uri, typeName, mode); + m_loadHelper = QQml::makeRefPointer<LoadHelper>(QQmlTypeLoader::get(m_engine), uri, typeName, mode); } void QQmlComponentPrivate::completeLoadFromModule(QAnyStringView uri, QAnyStringView typeName) diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 39dacb80f4..f7d1c95292 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -453,8 +453,9 @@ QJSValue QQmlContext::importedScript(const QString &name) const { Q_D(const QQmlContext); - QQmlTypeNameCache::Result r = d->m_data->imports()->query(name, QQmlTypeLoader::get(engine())); - QV4::Scope scope(engine()->handle()); + QV4::ExecutionEngine *v4 = engine()->handle(); + QQmlTypeNameCache::Result r = d->m_data->imports()->query(name, v4->typeLoader()); + QV4::Scope scope(v4); QV4::ScopedObject scripts(scope, d->m_data->importedScripts()); return scripts ? QJSValuePrivate::fromReturnedValue(scripts->get(r.scriptIndex)) : QJSValue(QJSValue::UndefinedValue); diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index c16d4911ae..6eddb07b41 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -221,7 +221,7 @@ QQmlTypeLoader *QQmlCustomParser::typeLoader() const if (!engine && !validator) return nullptr; - return validator ? validator->typeLoader() : &engine->typeLoader; + return validator ? validator->typeLoader() : QQmlTypeLoader::get(engine); } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmldatablob_p.h b/src/qml/qml/qqmldatablob_p.h index 8874c2c395..82e430eb2d 100644 --- a/src/qml/qml/qqmldatablob_p.h +++ b/src/qml/qml/qqmldatablob_p.h @@ -60,6 +60,7 @@ public: void startLoading(); QQmlTypeLoader *typeLoader() const { return m_typeLoader; } + void resetTypeLoader() { m_typeLoader = nullptr; } Type type() const; @@ -116,10 +117,17 @@ public: } template<typename Loader = QQmlTypeLoader> + void assertEngineThreadIfRunning() const + { + const Loader *loader = m_typeLoader; + Q_ASSERT(!loader || !loader->thread() || loader->thread()->isParentThread()); + } + + template<typename Loader = QQmlTypeLoader> void assertEngineThread() const { const Loader *loader = m_typeLoader; - Q_ASSERT(loader && loader->engine() && loader->engine()->thread()->isCurrentThread()); + Q_ASSERT(loader && loader->thread() && loader->thread()->isParentThread()); } protected: diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index cc13b5006d..f4c3cfb1f2 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -509,7 +509,7 @@ void QQmlEnginePrivate::init() Create a new QQmlEngine with the given \a parent. */ QQmlEngine::QQmlEngine(QObject *parent) -: QJSEngine(*new QQmlEnginePrivate(this), parent) +: QJSEngine(*new QQmlEnginePrivate, parent) { Q_D(QQmlEngine); d->init(); @@ -538,7 +538,15 @@ QQmlEngine::QQmlEngine(QQmlEnginePrivate &dd, QObject *parent) QQmlEngine::~QQmlEngine() { Q_D(QQmlEngine); - handle()->inShutdown = true; + +#if QT_CONFIG(qml_worker_script) + // Delete the workerscript engine early + // so that it won't be able to use the type loader anymore. + delete std::exchange(d->workerScriptEngine, nullptr); +#endif + + QV4::ExecutionEngine *v4 = handle(); + v4->inShutdown = true; QJSEnginePrivate::removeFromDebugServer(this); // Emit onDestruction signals for the root context before @@ -555,7 +563,7 @@ QQmlEngine::~QQmlEngine() delete d->rootContext; d->rootContext = nullptr; - d->typeLoader.invalidate(); + v4->typeLoader()->invalidate(); // QQmlGadgetPtrWrapper can have QQmlData with various references. qDeleteAll(d->cachedValueTypeInstances); @@ -612,8 +620,6 @@ QQmlEngine::~QQmlEngine() */ void QQmlEngine::clearComponentCache() { - Q_D(QQmlEngine); - // Contexts can hold on to CUs but live on the JS heap. // Use a non-incremental GC run to get rid of those. QV4::MemoryManager *mm = handle()->memoryManager; @@ -622,8 +628,9 @@ void QQmlEngine::clearComponentCache() mm->runGC(); mm->gcStateMachine->timeLimit = std::move(oldLimit); - handle()->trimCompilationUnits(); - d->typeLoader.clearCache(); + QV4::ExecutionEngine *v4 = handle(); + v4->trimCompilationUnits(); + v4->typeLoader()->clearCache(); QQmlMetaType::freeUnusedTypesAndCaches(); } @@ -641,9 +648,9 @@ void QQmlEngine::clearComponentCache() */ void QQmlEngine::trimComponentCache() { - Q_D(QQmlEngine); - handle()->trimCompilationUnits(); - d->typeLoader.trimCache(); + QV4::ExecutionEngine *v4 = handle(); + v4->trimCompilationUnits(); + v4->typeLoader()->trimCache(); } /*! @@ -695,8 +702,7 @@ QQmlContext *QQmlEngine::rootContext() const */ QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor() const { - Q_D(const QQmlEngine); - return d->typeLoader.urlInterceptors().last(); + return QQmlTypeLoader::get(this)->urlInterceptors().last(); } #endif @@ -711,8 +717,7 @@ QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor() const */ void QQmlEngine::addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor) { - Q_D(QQmlEngine); - d->typeLoader.addUrlInterceptor(urlInterceptor); + QQmlTypeLoader::get(this)->addUrlInterceptor(urlInterceptor); } /*! @@ -725,8 +730,7 @@ void QQmlEngine::addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor) */ void QQmlEngine::removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor) { - Q_D(QQmlEngine); - d->typeLoader.removeUrlInterceptor(urlInterceptor); + QQmlTypeLoader::get(this)->removeUrlInterceptor(urlInterceptor); } /*! @@ -735,8 +739,7 @@ void QQmlEngine::removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor */ QUrl QQmlEngine::interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const { - Q_D(const QQmlEngine); - return d->typeLoader.interceptUrl(url, type); + return QQmlTypeLoader::get(this)->interceptUrl(url, type); } /*! @@ -744,8 +747,7 @@ QUrl QQmlEngine::interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataT */ QList<QQmlAbstractUrlInterceptor *> QQmlEngine::urlInterceptors() const { - Q_D(const QQmlEngine); - return d->typeLoader.urlInterceptors(); + return QQmlTypeLoader::get(this)->urlInterceptors(); } QSharedPointer<QQmlImageProviderBase> QQmlEnginePrivate::imageProvider(const QString &providerId) const @@ -770,8 +772,7 @@ QSharedPointer<QQmlImageProviderBase> QQmlEnginePrivate::imageProvider(const QSt */ void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory) { - Q_D(QQmlEngine); - d->typeLoader.setNetworkAccessManagerFactory(factory); + QQmlTypeLoader::get(this)->setNetworkAccessManagerFactory(factory); } class QQmlEnginePublicAPIToken {}; @@ -783,16 +784,7 @@ class QQmlEnginePublicAPIToken {}; */ QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const { - Q_D(const QQmlEngine); - return d->typeLoader.networkAccessManagerFactory().get(QQmlEnginePublicAPIToken()); -} - -QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() -{ - Q_Q(QQmlEngine); - if (!networkAccessManager) - networkAccessManager = typeLoader.createNetworkAccessManager(q); - return networkAccessManager; + return QQmlTypeLoader::get(this)->networkAccessManagerFactory().get(QQmlEnginePublicAPIToken()); } /*! @@ -809,9 +801,7 @@ QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() */ QNetworkAccessManager *QQmlEngine::networkAccessManager() const { - // ### Qt7: This method is clearly not const since it _creates_ the network access manager. - Q_D(const QQmlEngine); - return const_cast<QQmlEnginePrivate *>(d)->getNetworkAccessManager(); + return handle()->getNetworkAccessManager(); } #endif // qml_network @@ -1066,7 +1056,7 @@ QJSValue QQmlEngine::singletonInstance<QJSValue>(QAnyStringView uri, QAnyStringV Q_D(QQmlEngine); auto loadHelper = QQml::makeRefPointer<LoadHelper>( - &d->typeLoader, uri, typeName, QQmlTypeLoader::Synchronous); + QQmlTypeLoader::get(this), uri, typeName, QQmlTypeLoader::Synchronous); const QQmlType type = loadHelper->type(); if (!type.isSingleton()) @@ -1610,8 +1600,7 @@ void QQmlEnginePrivate::cleanupScarceResources() */ void QQmlEngine::addImportPath(const QString& path) { - Q_D(QQmlEngine); - d->typeLoader.addImportPath(path); + QQmlTypeLoader::get(this)->addImportPath(path); } /*! @@ -1631,8 +1620,7 @@ void QQmlEngine::addImportPath(const QString& path) */ QStringList QQmlEngine::importPathList() const { - Q_D(const QQmlEngine); - return d->typeLoader.importPathList(); + return QQmlTypeLoader::get(this)->importPathList(); } /*! @@ -1649,8 +1637,7 @@ QStringList QQmlEngine::importPathList() const */ void QQmlEngine::setImportPathList(const QStringList &paths) { - Q_D(QQmlEngine); - d->typeLoader.setImportPathList(paths); + QQmlTypeLoader::get(this)->setImportPathList(paths); } @@ -1667,8 +1654,7 @@ void QQmlEngine::setImportPathList(const QStringList &paths) */ void QQmlEngine::addPluginPath(const QString& path) { - Q_D(QQmlEngine); - d->typeLoader.addPluginPath(path); + QQmlTypeLoader::get(this)->addPluginPath(path); } /*! @@ -1682,8 +1668,7 @@ void QQmlEngine::addPluginPath(const QString& path) */ QStringList QQmlEngine::pluginPathList() const { - Q_D(const QQmlEngine); - return d->typeLoader.pluginPathList(); + return QQmlTypeLoader::get(this)->pluginPathList(); } /*! @@ -1698,8 +1683,7 @@ QStringList QQmlEngine::pluginPathList() const */ void QQmlEngine::setPluginPathList(const QStringList &paths) { - Q_D(QQmlEngine); - d->typeLoader.setPluginPathList(paths); + QQmlTypeLoader::get(this)->setPluginPathList(paths); } #if QT_CONFIG(library) @@ -1720,9 +1704,8 @@ void QQmlEngine::setPluginPathList(const QStringList &paths) */ bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors) { - Q_D(QQmlEngine); QQmlTypeLoaderQmldirContent qmldir; - QQmlPluginImporter importer(uri, QTypeRevision(), &qmldir, &d->typeLoader, errors); + QQmlPluginImporter importer(uri, QTypeRevision(), &qmldir, QQmlTypeLoader::get(this), errors); return importer.importDynamicPlugin(filePath, uri, false).isValid(); } #endif @@ -1907,16 +1890,6 @@ QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type) return value; } -bool QQmlEnginePrivate::isTypeLoaded(const QUrl &url) const -{ - return typeLoader.isTypeLoaded(url); -} - -bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const -{ - return typeLoader.isScriptLoaded(url); -} - void QQmlEnginePrivate::executeRuntimeFunction(const QUrl &url, qsizetype functionIndex, QObject *thisObject, int argc, void **args, QMetaType *types) @@ -1985,7 +1958,7 @@ QV4::ExecutableCompilationUnit *QQmlEnginePrivate::compilationUnitFromUrl(const return unit.data(); } - auto unit = typeLoader.getType(url)->compilationUnit(); + auto unit = v4->typeLoader()->getType(url)->compilationUnit(); if (!unit) return nullptr; diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 322f4d6812..4d923c983f 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -100,7 +100,6 @@ class Q_QML_EXPORT QQmlEnginePrivate : public QJSEnginePrivate { Q_DECLARE_PUBLIC(QQmlEngine) public: - explicit QQmlEnginePrivate(QQmlEngine *q) : typeLoader(q) {} ~QQmlEnginePrivate() override; void init(); @@ -137,10 +136,7 @@ public: QUrl baseUrl; QQmlObjectCreator *activeObjectCreator = nullptr; -#if QT_CONFIG(qml_network) - QNetworkAccessManager *getNetworkAccessManager(); - QNetworkAccessManager *networkAccessManager = nullptr; -#endif + mutable QRecursiveMutex imageProviderMutex; QHash<QString,QSharedPointer<QQmlImageProviderBase> > imageProviders; QSharedPointer<QQmlImageProviderBase> imageProvider(const QString &providerId) const; @@ -149,8 +145,6 @@ public: void referenceScarceResources(); void dereferenceScarceResources(); - QQmlTypeLoader typeLoader; - QString offlineStoragePath; // Unfortunate workaround to avoid a circular dependency between @@ -166,9 +160,6 @@ public: // These methods may be called from any thread QString offlineStorageDatabaseDirectory() const; - bool isTypeLoaded(const QUrl &url) const; - bool isScriptLoaded(const QUrl &url) const; - template <typename T> T singletonInstance(const QQmlType &type); @@ -181,14 +172,15 @@ public: static void warning(QQmlEnginePrivate *, const QQmlError &); static void warning(QQmlEnginePrivate *, const QList<QQmlError> &); - inline static QV4::ExecutionEngine *getV4Engine(QQmlEngine *e); inline static QQmlEnginePrivate *get(QQmlEngine *e); inline static const QQmlEnginePrivate *get(const QQmlEngine *e); - inline static QQmlEnginePrivate *get(QQmlContext *c); - inline static QQmlEnginePrivate *get(const QQmlRefPointer<QQmlContextData> &c); inline static QQmlEngine *get(QQmlEnginePrivate *p); + inline static const QQmlEngine *get(const QQmlEnginePrivate *p); inline static QQmlEnginePrivate *get(QV4::ExecutionEngine *e); + inline static QQmlEnginePrivate *get(QQmlContext *c); + inline static QQmlEnginePrivate *get(const QQmlRefPointer<QQmlContextData> &c); + static QList<QQmlError> qmlErrorFromDiagnostics(const QString &fileName, const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages); static bool designerMode(); @@ -319,13 +311,6 @@ inline void QQmlEnginePrivate::dereferenceScarceResources() } } -QV4::ExecutionEngine *QQmlEnginePrivate::getV4Engine(QQmlEngine *e) -{ - Q_ASSERT(e); - - return e->handle(); -} - QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlEngine *e) { Q_ASSERT(e); diff --git a/src/qml/qml/qqmlfileselector.cpp b/src/qml/qml/qqmlfileselector.cpp index 903f67637f..4bd54fa95c 100644 --- a/src/qml/qml/qqmlfileselector.cpp +++ b/src/qml/qml/qqmlfileselector.cpp @@ -167,7 +167,7 @@ QQmlFileSelector* QQmlFileSelector::get(QQmlEngine* engine) } const QUrl nonEmptyInvalid(QLatin1String(":")); - const auto interceptors = enginePrivate->typeLoader.urlInterceptors(); + const auto interceptors = QQmlTypeLoader::get(engine)->urlInterceptors(); for (QQmlAbstractUrlInterceptor *interceptor : interceptors) { const QUrl result = interceptor->intercept( nonEmptyInvalid, QQmlAbstractUrlInterceptor::UrlString); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 7491ce90e1..4a37c446e8 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1154,13 +1154,13 @@ QMetaType QQmlMetaType::listValueType(QMetaType metaType) return QMetaType {}; } -QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFunc(QQmlEnginePrivate *engine, - const QMetaObject *mo) +QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFunc( + QQmlTypeLoader *typeLoader, const QMetaObject *mo) { QQmlMetaTypeDataPtr data; QQmlType type(data->metaObjectToType.value(mo)); - return type.attachedPropertiesFunction(engine); + return type.attachedPropertiesFunction(typeLoader); } QMetaProperty QQmlMetaType::defaultProperty(const QMetaObject *metaObject) diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 9e5a79630c..01ce721781 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -178,8 +178,8 @@ public: static QObject *toQObject(const QVariant &, bool *ok = nullptr); static QMetaType listValueType(QMetaType type); - static QQmlAttachedPropertiesFunc attachedPropertiesFunc(QQmlEnginePrivate *, - const QMetaObject *); + static QQmlAttachedPropertiesFunc attachedPropertiesFunc( + QQmlTypeLoader *typeLoader, const QMetaObject *); static bool isInterface(QMetaType type); static const char *interfaceIId(QMetaType type); static bool isList(QMetaType type); diff --git a/src/qml/qml/qqmlnotifyingblob.cpp b/src/qml/qml/qqmlnotifyingblob.cpp index fc46ae942f..f3581b6b5c 100644 --- a/src/qml/qml/qqmlnotifyingblob.cpp +++ b/src/qml/qml/qqmlnotifyingblob.cpp @@ -19,7 +19,7 @@ void QQmlNotifyingBlob::registerCallback(Callback *callback) void QQmlNotifyingBlob::unregisterCallback(Callback *callback) { - assertEngineThread(); + assertEngineThreadIfRunning(); Q_ASSERT(m_callbacks.contains(callback)); m_callbacks.removeOne(callback); Q_ASSERT(!m_callbacks.contains(callback)); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 5da9c3118d..0c69d48c33 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -840,10 +840,10 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex); Q_ASSERT(tr); QQmlType attachedType = tr->type(); - QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine); + QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine); if (!attachedType.isValid()) { - QQmlTypeNameCache::Result res = context->imports()->query( - stringAt(binding->propertyNameIndex), QQmlTypeLoader::get(enginePrivate)); + QQmlTypeNameCache::Result res + = context->imports()->query(stringAt(binding->propertyNameIndex), typeLoader); if (res.isValid()) attachedType = res.type; else @@ -856,7 +856,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper context->url())); QObject *qmlObject = qmlAttachedPropertiesObject( - _qobject, attachedType.attachedPropertiesFunction(enginePrivate)); + _qobject, attachedType.attachedPropertiesFunction(typeLoader)); if (!qmlObject) { recordError(binding->location, QStringLiteral("Could not create attached properties object '%1'") @@ -866,7 +866,8 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper const size_t objectIndex = sharedState->allCreatedObjects.size(); sharedState->allCreatedObjects.push_back(qmlObject); - const QQmlType attachedObjectType = QQmlMetaType::qmlType(attachedType.attachedPropertiesType(QQmlEnginePrivate::get((engine)))); + const QQmlType attachedObjectType + = QQmlMetaType::qmlType(attachedType.attachedPropertiesType(typeLoader)); const int parserStatusCast = attachedObjectType.parserStatusCast(); QQmlParserStatus *parserStatus = nullptr; if (parserStatusCast != -1) diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index 3fc8fac6c5..51b73bb3f6 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -248,12 +248,11 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name, // Types must begin with an uppercase letter (see checkRegistration() // in qqmlmetatype.cpp for the enforcement of this). if (typeNameCache && !pathName.isEmpty() && pathName.at(0).isUpper()) { - QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine); - QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(enginePrivate); + QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(engine.data()); QQmlTypeNameCache::Result r = typeNameCache->query(pathName, typeLoader); if (r.isValid()) { if (r.type.isValid()) { - QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate); + QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(typeLoader); if (!func) return; // Not an attachable type currentObject = qmlAttachedPropertiesObject(currentObject, func); @@ -269,7 +268,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name, if (!r.type.isValid()) return; // Invalid type in namespace - QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(enginePrivate); + QQmlAttachedPropertiesFunc func = r.type.attachedPropertiesFunction(typeLoader); if (!func) return; // Not an attachable type diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp index aa7327ffa0..89f9df7078 100644 --- a/src/qml/qml/qqmltype.cpp +++ b/src/qml/qml/qqmltype.cpp @@ -710,12 +710,6 @@ QTypeRevision QQmlType::metaObjectRevision() const return d ? d->revision : QTypeRevision(); } -QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction( - QQmlEnginePrivate *enginePrivate) const -{ - return attachedPropertiesFunction(&enginePrivate->typeLoader); -} - QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlTypeLoader *typeLoader) const { if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(typeLoader) : nullptr) @@ -723,11 +717,6 @@ QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlTypeLoader * return nullptr; } -const QMetaObject *QQmlType::attachedPropertiesType(QQmlEnginePrivate *enginePrivate) const -{ - return attachedPropertiesType(&enginePrivate->typeLoader); -} - const QMetaObject *QQmlType::attachedPropertiesType(QQmlTypeLoader *typeLoader) const { if (const QQmlTypePrivate *base = d ? d->attachedPropertiesBase(typeLoader) : nullptr) diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h index 70155637d1..c1108581b1 100644 --- a/src/qml/qml/qqmltype_p.h +++ b/src/qml/qml/qqmltype_p.h @@ -108,10 +108,7 @@ public: QTypeRevision metaObjectRevision() const; bool containsRevisionedAttributes() const; - QQmlAttachedPropertiesFunc attachedPropertiesFunction(QQmlEnginePrivate *enginePrivate) const; QQmlAttachedPropertiesFunc attachedPropertiesFunction(QQmlTypeLoader *typeLoader) const; - - const QMetaObject *attachedPropertiesType(QQmlEnginePrivate *enginePrivate) const; const QMetaObject *attachedPropertiesType(QQmlTypeLoader *typeLoader) const; int parserStatusCast() const; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index a3b1e84e05..d4d711332b 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -35,8 +35,10 @@ #include <functional> -#define ASSERT_LOADTHREAD() Q_ASSERT(thread() && thread()->isThisThread()) -#define ASSERT_ENGINETHREAD() Q_ASSERT(engine()->thread()->isCurrentThread()) +#define ASSERT_LOADTHREAD() \ + Q_ASSERT(thread() && thread()->isThisThread()) +#define ASSERT_ENGINETHREAD() \ + Q_ASSERT(!engine()->jsEngine() || engine()->jsEngine()->thread()->isCurrentThread()) QT_BEGIN_NAMESPACE @@ -413,7 +415,7 @@ void doInitializeEngine( if (thread && thread->isThisThread()) thread->initializeEngine(iface, uri); else - iface->initializeEngine(data->engine(), uri); + iface->initializeEngine(data->engine()->qmlEngine(), uri); } void QQmlTypeLoader::initializeEngine(QQmlEngineExtensionInterface *iface, const char *uri) @@ -647,11 +649,10 @@ void QQmlTypeLoader::clearQmldirInfo() } static void initializeConfiguredData( - const QQmlTypeLoaderConfiguredDataPtr &data, QQmlEngine *engine) + const QQmlTypeLoaderConfiguredDataPtr &data, QV4::ExecutionEngine *engine) { - QV4::ExecutionEngine *v4 = engine->handle(); - data->diskCacheOptions = v4->diskCacheOptions(); - data->isDebugging = v4->debugger() != nullptr; + data->diskCacheOptions = engine->diskCacheOptions(); + data->isDebugging = engine->debugger() != nullptr; data->initialized = true; } @@ -1201,7 +1202,7 @@ static QStringList parseEnvPath(const QString &envImportPath) /*! Constructs a new type loader that uses the given \a engine. */ -QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine) +QQmlTypeLoader::QQmlTypeLoader(QV4::ExecutionEngine *engine) : m_data(engine) { QQmlTypeLoaderConfiguredDataPtr data(&m_data); @@ -1724,6 +1725,15 @@ void QQmlTypeLoader::setQmldirContent(const QString &url, const QString &content qmldir->setContent(url, content); } +template<typename Blob> +void clearBlobs(QHash<QUrl, QQmlRefPointer<Blob>> *blobs) +{ + std::for_each(blobs->cbegin(), blobs->cend(), [](const QQmlRefPointer<Blob> &blob) { + blob->resetTypeLoader(); + }); + blobs->clear(); +} + /*! Clears cached information about loaded files, including any type data, scripts and qmldir information. @@ -1745,10 +1755,10 @@ void QQmlTypeLoader::clearCache() threadData->importQmlDirCache.clear(); QQmlTypeLoaderSharedDataPtr data(&m_data); - data->typeCache.clear(); + clearBlobs(&data->typeCache); + clearBlobs(&data->scriptCache); + clearBlobs(&data->qmldirCache); data->typeCacheTrimThreshold = QQmlTypeLoaderSharedData::MinimumTypeCacheTrimThreshold; - data->scriptCache.clear(); - data->qmldirCache.clear(); data->importDirCache.clear(); // The thread will auto-restart next time we need it. diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 757c5412bc..d207acdf34 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -129,24 +129,24 @@ public: QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus = QQmlMetaType::CachedUnitLookupError::NoError; }; - QQmlTypeLoader(QQmlEngine *); + QQmlTypeLoader(QV4::ExecutionEngine *engine); ~QQmlTypeLoader(); template< typename Engine, typename EnginePrivate = QQmlEnginePrivate, - typename = std::enable_if_t<std::is_same_v<Engine, QQmlEngine>>> + typename = std::enable_if_t<std::is_base_of_v<QJSEngine, Engine>>> static QQmlTypeLoader *get(Engine *engine) { - return get(EnginePrivate::get(engine)); + return engine->handle()->typeLoader(); } template< typename Engine, - typename = std::enable_if_t<std::is_same_v<Engine, QQmlEnginePrivate>>> + typename = std::enable_if_t<std::is_base_of_v<QJSEnginePrivate, Engine>>> static QQmlTypeLoader *get(Engine *engine) { - return &engine->typeLoader; + return Engine::get(engine)->handle()->typeLoader(); } static void sanitizeUNCPath(QString *path) @@ -298,7 +298,7 @@ private: }; QQmlTypeLoaderThread *thread() const { return m_data.thread(); } - QQmlEngine *engine() const { return m_data.engine(); } + QV4::ExecutionEngine *engine() const { return m_data.engine(); } void startThread(); void shutdownThread(); diff --git a/src/qml/qml/qqmltypeloaderdata.cpp b/src/qml/qml/qqmltypeloaderdata.cpp index 4fcece621c..6743cc4d41 100644 --- a/src/qml/qml/qqmltypeloaderdata.cpp +++ b/src/qml/qml/qqmltypeloaderdata.cpp @@ -10,9 +10,8 @@ QT_BEGIN_NAMESPACE -QQmlTypeLoaderLockedData::QQmlTypeLoaderLockedData(QQmlEngine *engine) +QQmlTypeLoaderLockedData::QQmlTypeLoaderLockedData(QV4::ExecutionEngine *engine) : m_engine(engine) -{ -} +{} QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypeloaderdata_p.h b/src/qml/qml/qqmltypeloaderdata_p.h index fa63a81003..dc2cf7f549 100644 --- a/src/qml/qml/qqmltypeloaderdata_p.h +++ b/src/qml/qml/qqmltypeloaderdata_p.h @@ -148,20 +148,20 @@ class QQmlTypeLoaderLockedData Q_DISABLE_COPY_MOVE(QQmlTypeLoaderLockedData) public: - QQmlTypeLoaderLockedData(QQmlEngine *engine); + QQmlTypeLoaderLockedData(QV4::ExecutionEngine *engine); QQmlTypeLoaderThread *thread() const { return m_thread; } void createThread(QQmlTypeLoader *loader) { - Q_ASSERT(m_engine->thread()->isCurrentThread()); + Q_ASSERT(isCurrentJsEngineThread()); m_thread = new QQmlTypeLoaderThread(loader); m_thread->startup(); } void deleteThread() { - Q_ASSERT(m_engine->thread()->isCurrentThread()); + Q_ASSERT(isCurrentJsEngineThread()); Q_ASSERT(m_thread); // Shut it down first, then set it to nullptr, then delete it. @@ -171,13 +171,23 @@ public: delete std::exchange(m_thread, nullptr); } - QQmlEngine *engine() const + QV4::ExecutionEngine *engine() const { - Q_ASSERT(m_engine->thread()->isCurrentThread()); + Q_ASSERT(isCurrentJsEngineThread()); return m_engine; } private: + bool isCurrentJsEngineThread() const + { + if (QJSEngine *jsEngine = m_engine->jsEngine()) + return jsEngine->thread()->isCurrentThread(); + + // If we can't determine the thread, assume it's the right one + return true; + } + + QQmlTypeLoaderSharedData m_sharedData; QQmlTypeLoaderThreadData m_threadData; QQmlTypeLoaderConfiguredData m_configuredData; @@ -185,7 +195,7 @@ private: QQmlTypeLoaderNetworkAccessManagerData m_networkAccessManagerData; #endif - QQmlEngine *m_engine = nullptr; + QV4::ExecutionEngine *m_engine = nullptr; QQmlTypeLoaderThread *m_thread = nullptr; }; diff --git a/src/qml/qml/qqmltypeloaderthread.cpp b/src/qml/qml/qqmltypeloaderthread.cpp index 39a88de0c8..0fe5bf83b9 100644 --- a/src/qml/qml/qqmltypeloaderthread.cpp +++ b/src/qml/qml/qqmltypeloaderthread.cpp @@ -141,8 +141,8 @@ void QQmlTypeLoaderThread::initializeExtensionMain(QQmlExtensionInterface *iface const char *uri) { // We can use m_engine because we're on the engine thread. - QQmlEngine *engine = m_loader->engine(); - Q_ASSERT(engine->thread() == QThread::currentThread()); + QQmlEngine *engine = m_loader->engine()->qmlEngine(); + Q_ASSERT(engine && engine->thread() == QThread::currentThread()); iface->initializeEngine(engine, uri); } @@ -150,8 +150,8 @@ void QQmlTypeLoaderThread::initializeEngineExtensionMain(QQmlEngineExtensionInte const char *uri) { // We can use m_engine because we're on the engine thread. - QQmlEngine *engine = m_loader->engine(); - Q_ASSERT(engine->thread() == QThread::currentThread()); + QQmlEngine *engine = m_loader->engine()->qmlEngine(); + Q_ASSERT(engine && engine->thread() == QThread::currentThread()); iface->initializeEngine(engine, uri); } diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index c56ed6e59d..826748dca1 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -82,12 +82,12 @@ QQmlType Heap::QQmlTypeWrapper::type() const } QQmlTypeNameCache::Result Heap::QQmlTypeWrapper::queryNamespace( - const QV4::String *name, QQmlEnginePrivate *enginePrivate) const + const QV4::String *name, QV4::ExecutionEngine *engine) const { Q_ASSERT(kind() == Namespace); Q_ASSERT(n.typeNamespace); Q_ASSERT(n.importNamespace); - return n.typeNamespace->query(name, n.importNamespace, QQmlTypeLoader::get(enginePrivate)); + return n.typeNamespace->query(name, n.importNamespace, engine->typeLoader()); } @@ -155,7 +155,7 @@ const QMetaObject *QQmlTypeWrapper::metaObject() const return metaObjectCandidate; } - return type.attachedPropertiesType(QQmlEnginePrivate::get(engine()->qmlEngine())); + return type.attachedPropertiesType(engine()->typeLoader()); } QObject *QQmlTypeWrapper::object() const @@ -164,13 +164,12 @@ QObject *QQmlTypeWrapper::object() const if (!type.isValid()) return nullptr; - QQmlEnginePrivate *qmlEngine = QQmlEnginePrivate::get(engine()->qmlEngine()); if (type.isSingleton()) - return qmlEngine->singletonInstance<QObject *>(type); + return QQmlEnginePrivate::get(engine()->qmlEngine())->singletonInstance<QObject *>(type); return qmlAttachedPropertiesObject( d()->object, - type.attachedPropertiesFunction(qmlEngine)); + type.attachedPropertiesFunction(engine()->typeLoader())); } QObject* QQmlTypeWrapper::singletonObject() const @@ -184,14 +183,14 @@ QObject* QQmlTypeWrapper::singletonObject() const QVariant QQmlTypeWrapper::toVariant() const { - QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine()->qmlEngine()); const QQmlType type = d()->type(); if (!isSingleton()) { return QVariant::fromValue(qmlAttachedPropertiesObject( - d()->object, type.attachedPropertiesFunction(e))); + d()->object, type.attachedPropertiesFunction(engine()->typeLoader()))); } + QQmlEnginePrivate *e = QQmlEnginePrivate::get(engine()->qmlEngine()); if (type.isQJSValueSingleton()) return QVariant::fromValue<QJSValue>(e->singletonInstance<QJSValue>(type)); @@ -323,15 +322,15 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons = w->d()->typeNameMode() == Heap::QQmlTypeWrapper::IncludeEnums; if (includeEnums && name->startsWithUpper()) { bool ok = false; - int value = enumForSingleton(&enginePrivate->typeLoader, name, type, &ok); + int value = enumForSingleton(v4->typeLoader(), name, type, &ok); if (ok) return QV4::Value::fromInt32(value).asReturnedValue(); - value = type.scopedEnumIndex(&enginePrivate->typeLoader, name, &ok); + value = type.scopedEnumIndex(v4->typeLoader(), name, &ok); if (ok) return createEnumWrapper(v4, scope, type, value, true); - value = type.unscopedEnumIndex(&enginePrivate->typeLoader, name, &ok); + value = type.unscopedEnumIndex(v4->typeLoader(), name, &ok); if (ok) return createEnumWrapper(v4, scope, type, value, false); } @@ -362,15 +361,15 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons if (name->startsWithUpper()) { bool ok = false; - int value = type.enumValue(&enginePrivate->typeLoader, name, &ok); + int value = type.enumValue(v4->typeLoader(), name, &ok); if (ok) return QV4::Value::fromInt32(value).asReturnedValue(); - value = type.scopedEnumIndex(&enginePrivate->typeLoader, name, &ok); + value = type.scopedEnumIndex(v4->typeLoader(), name, &ok); if (ok) return createEnumWrapper(v4, scope, type, value, true); - value = type.unscopedEnumIndex(&enginePrivate->typeLoader, name, &ok); + value = type.unscopedEnumIndex(v4->typeLoader(), name, &ok); if (ok) return createEnumWrapper(v4, scope, type, value, false); @@ -378,8 +377,7 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons } else if (w->d()->object) { QObject *ao = qmlAttachedPropertiesObject( - object, - type.attachedPropertiesFunction(QQmlEnginePrivate::get(v4->qmlEngine()))); + object, type.attachedPropertiesFunction(v4->typeLoader())); if (ao) return QV4::QObjectWrapper::getQmlProperty( v4, context, w->d(), ao, name, QV4::QObjectWrapper::AttachMethods, @@ -394,7 +392,7 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons // Fall through to base implementation } else if (w->d()->kind() == Heap::QQmlTypeWrapper::Namespace) { - const QQmlTypeNameCache::Result r = w->d()->queryNamespace(name, enginePrivate); + const QQmlTypeNameCache::Result r = w->d()->queryNamespace(name, v4); if (r.isValid()) { if (r.type.isValid()) { return create(scope.engine, object, r.type, w->d()->typeNameMode()); @@ -442,9 +440,8 @@ bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value, QQmlType type = w->d()->type(); if (type.isValid() && !type.isSingleton() && w->d()->object) { QObject *object = w->d()->object; - QQmlEngine *e = scope.engine->qmlEngine(); QObject *ao = qmlAttachedPropertiesObject( - object, type.attachedPropertiesFunction(QQmlEnginePrivate::get(e))); + object, type.attachedPropertiesFunction(scope.engine->typeLoader())); if (ao) return QV4::QObjectWrapper::setQmlProperty( scope.engine, context, ao, name, QV4::QObjectWrapper::NoFlag, value); @@ -521,8 +518,8 @@ static ReturnedValue instanceOfQObject( if (!theirDData->compilationUnit) return Encode(false); - QQmlEnginePrivate *qenginepriv = QQmlEnginePrivate::get(engine->qmlEngine()); - QQmlRefPointer<QQmlTypeData> td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl()); + QQmlRefPointer<QQmlTypeData> td + = engine->typeLoader()->getType(typeWrapper->d()->type().sourceUrl()); if (CompiledData::CompilationUnit *cu = td->compilationUnit()) myQmlType = QQmlMetaType::metaObjectForType(cu->metaType()); else @@ -663,7 +660,7 @@ ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(const Object *object, if (name->startsWithUpper()) { bool ok = false; - QQmlTypeLoader *typeLoader = &QQmlEnginePrivate::get(engine->qmlEngine())->typeLoader; + QQmlTypeLoader *typeLoader = engine->typeLoader(); int value = type.enumValue(typeLoader, name, &ok); if (ok) { lookup->qmlEnumValueLookup.ic.set(engine, This->internalClass()); @@ -698,8 +695,7 @@ ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(const Object *object, // Fall through to base implementation } else if (w->d()->object) { QObject *ao = qmlAttachedPropertiesObject( - w->d()->object, - type.attachedPropertiesFunction(QQmlEnginePrivate::get(engine->qmlEngine()))); + w->d()->object, type.attachedPropertiesFunction(engine->typeLoader())); if (ao) { // ### QTBUG-126877: Optimize this case lookup->call = QV4::Lookup::Call::GetterQObjectPropertyFallback; @@ -876,7 +872,7 @@ ReturnedValue QQmlEnumWrapper::virtualGet(const Managed *m, PropertyKey id, cons int index = resource->d()->enumIndex; bool ok = false; - auto *typeLoader = &QQmlEnginePrivate::get(v4->qmlEngine())->typeLoader; + auto *typeLoader = v4->typeLoader(); int value = resource->d()->scoped ? type.scopedEnumValue(typeLoader, index, name, &ok) : type.unscopedEnumValue(typeLoader, index, name, &ok); if (hasProperty) diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index 454bcf7584..9e20be17ac 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -72,7 +72,7 @@ struct QQmlTypeWrapper : FunctionObject { void warnIfUncreatable() const; QQmlTypeNameCache::Result queryNamespace( - const QV4::String *name, QQmlEnginePrivate *enginePrivate) const; + const QV4::String *name, QV4::ExecutionEngine *engine) const; QV4QPointer<QObject> object; diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index d2d663bfc3..f5eb50449d 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1670,7 +1670,8 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject Scope scope(f->engine()); const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f); - QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->networkAccessManager(scope.engine), scope.engine); + QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest( + scope.engine->getNetworkAccessManager(), scope.engine); Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r)); ScopedObject proto(scope, ctor->d()->proto); w->setPrototypeUnchecked(proto); diff --git a/src/qmlmeta/types/qqmlbind.cpp b/src/qmlmeta/types/qqmlbind.cpp index 0902778fe7..f82fb2d938 100644 --- a/src/qmlmeta/types/qqmlbind.cpp +++ b/src/qmlmeta/types/qqmlbind.cpp @@ -1000,8 +1000,7 @@ void QQmlBindPrivate::decodeBinding( QQmlContext *context = qmlContext(q); QObject *attachedObject = qmlAttachedPropertiesObject( - q, attachedType.attachedPropertiesFunction( - QQmlEnginePrivate::get(context->engine()))); + q, attachedType.attachedPropertiesFunction(QQmlTypeLoader::get(context->engine()))); if (!attachedObject) { qmlWarning(q).nospace() <<"Could not create attached properties object '" << attachedType.typeName() << "'"; diff --git a/src/qmlworkerscript/qquickworkerscript.cpp b/src/qmlworkerscript/qquickworkerscript.cpp index dbb8281a99..14cd783c32 100644 --- a/src/qmlworkerscript/qquickworkerscript.cpp +++ b/src/qmlworkerscript/qquickworkerscript.cpp @@ -105,7 +105,11 @@ public: WorkerDestroyEvent() : QEvent(QEvent::Type(WorkerEventType::Destroy)) {} }; -struct WorkerScript : public QV4::ExecutionEngine::Deletable +struct WorkerScript + : public QV4::ExecutionEngine::Deletable +#if QT_CONFIG(qml_network) + , public QQmlNetworkAccessManagerFactory +#endif { WorkerScript(QV4::ExecutionEngine *); ~WorkerScript() = default; @@ -113,7 +117,7 @@ struct WorkerScript : public QV4::ExecutionEngine::Deletable QQuickWorkerScriptEnginePrivate *p = nullptr; QQuickWorkerScript *owner = nullptr; #if QT_CONFIG(qml_network) - QScopedPointer<QNetworkAccessManager> scriptLocalNAM; + QNetworkAccessManager *create(QObject *parent) final; #endif }; @@ -222,6 +226,10 @@ QV4::ExecutionEngine *QQuickWorkerScriptEnginePrivate::workerEngine(int id) WorkerScript *script = workerScriptExtension(engine); script->owner = owner; script->p = this; +#if QT_CONFIG(qml_network) + // Eagerly create a network access manager that can outlive the parent engine. + engine->getNetworkAccessManager(); +#endif *it = engine; return engine; } @@ -305,7 +313,7 @@ void QQuickWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script QQuickWorkerScriptEngine::QQuickWorkerScriptEngine(QQmlEngine *parent) : QThread(parent) - , d(new QQuickWorkerScriptEnginePrivate(&QQmlEnginePrivate::get(parent)->typeLoader)) + , d(new QQuickWorkerScriptEnginePrivate(QQmlTypeLoader::get(parent))) { connect(d, SIGNAL(stopThread()), this, SLOT(quit()), Qt::DirectConnection); QMutexLocker locker(&d->m_lock); @@ -348,17 +356,17 @@ WorkerScript::WorkerScript(QV4::ExecutionEngine *engine) engine->globalObject->put(workerScriptName, api); #if QT_CONFIG(qml_network) - engine->networkAccessManager = [](QV4::ExecutionEngine *engine) { - WorkerScript *workerScript = workerScriptExtension(engine); - if (!workerScript->scriptLocalNAM) { - workerScript->scriptLocalNAM.reset( - workerScript->p->m_typeLoader->createNetworkAccessManager(workerScript->p)); - } - return workerScript->scriptLocalNAM.get(); - }; + engine->typeLoader()->setNetworkAccessManagerFactory(this); #endif // qml_network } +#if QT_CONFIG(qml_network) +QNetworkAccessManager *WorkerScript::create(QObject *parent) +{ + return p->m_typeLoader->createNetworkAccessManager(parent); +} +#endif + int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner) { const int id = d->m_nextId++; diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index 347e0e3936..3f412bf84a 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -443,7 +443,7 @@ QNetworkAccessManager *QQuickPixmapReader::networkAccessManager() { if (!accessManager) { Q_ASSERT(readerThreadExecutionEnforcer()); - accessManager = QQmlEnginePrivate::get(engine)->typeLoader.createNetworkAccessManager( + accessManager = QQmlTypeLoader::get(engine)->createNetworkAccessManager( readerThreadExecutionEnforcer()); } return accessManager; diff --git a/src/quicktemplates/qquickspinbox.cpp b/src/quicktemplates/qquickspinbox.cpp index 8b8f1c4d51..ececf39883 100644 --- a/src/quicktemplates/qquickspinbox.cpp +++ b/src/quicktemplates/qquickspinbox.cpp @@ -432,9 +432,8 @@ QString QQuickSpinBoxPrivate::evaluateTextFromValue(int val) const if (engine && textFromValue.isCallable()) { QJSValue loc; #if QT_CONFIG(qml_locale) - QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); loc = QJSValuePrivate::fromReturnedValue( - v4->fromData(QMetaType::fromType<QLocale>(), &locale)); + engine->handle()->fromData(QMetaType::fromType<QLocale>(), &locale)); #endif text = textFromValue.call(QJSValueList() << val << loc).toString(); } else { @@ -451,9 +450,8 @@ int QQuickSpinBoxPrivate::evaluateValueFromText(const QString &text) const if (engine && valueFromText.isCallable()) { QJSValue loc; #if QT_CONFIG(qml_locale) - QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); loc = QJSValuePrivate::fromReturnedValue( - v4->fromData(QMetaType::fromType<QLocale>(), &locale)); + engine->handle()->fromData(QMetaType::fromType<QLocale>(), &locale)); #endif value = valueFromText.call(QJSValueList() << text << loc).toInt(); } else { diff --git a/src/quicktemplates/qquickstackelement.cpp b/src/quicktemplates/qquickstackelement.cpp index 141fa1819d..04f1d92d8d 100644 --- a/src/quicktemplates/qquickstackelement.cpp +++ b/src/quicktemplates/qquickstackelement.cpp @@ -207,14 +207,13 @@ void QQuickStackElement::initialize(RequiredProperties *requiredProperties) if (!properties.isUndefined()) { QQmlEngine *engine = qmlEngine(view); Q_ASSERT(engine); - QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); - Q_ASSERT(v4); - QV4::Scope scope(v4); + QV4::Scope scope(engine->handle()); + Q_ASSERT(scope.engine); QV4::ScopedValue ipv(scope, properties.value()); QV4::Scoped<QV4::QmlContext> qmlContext(scope, qmlCallingContext.value()); - QV4::ScopedValue qmlObject(scope, QV4::QObjectWrapper::wrap(v4, item)); + QV4::ScopedValue qmlObject(scope, QV4::QObjectWrapper::wrap(scope.engine, item)); QQmlComponentPrivate::setInitialProperties( - v4, qmlContext, qmlObject, ipv, requiredProperties, item, + scope.engine, qmlContext, qmlObject, ipv, requiredProperties, item, component ? QQmlComponentPrivate::get(component)->creator() : nullptr); properties.clear(); } diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 86de5c3f32..0d83f9a33c 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -461,12 +461,14 @@ public: Q_INVOKABLE bool isTypeLoaded(QString file) { - return QQmlEnginePrivate::get(engine)->isTypeLoaded(tst_qqmlengine::instance()->testFileUrl(file)); + return QQmlTypeLoader::get(engine) + ->isTypeLoaded(tst_qqmlengine::instance()->testFileUrl(file)); } Q_INVOKABLE bool isScriptLoaded(QString file) { - return QQmlEnginePrivate::get(engine)->isScriptLoaded(tst_qqmlengine::instance()->testFileUrl(file)); + return QQmlTypeLoader::get(engine) + ->isScriptLoaded(tst_qqmlengine::instance()->testFileUrl(file)); } Q_INVOKABLE void beginIncubation() @@ -1113,22 +1115,22 @@ void tst_qqmlengine::componentFromEval() void tst_qqmlengine::qrcUrls() { QQmlEngine engine; - QQmlEnginePrivate *pEngine = QQmlEnginePrivate::get(&engine); + QQmlTypeLoader *typeLoader = QQmlTypeLoader::get(&engine); { - QQmlRefPointer<QQmlTypeData> oneQml(pEngine->typeLoader.getType(QUrl("qrc:/qrcurls.qml"))); + QQmlRefPointer<QQmlTypeData> oneQml(typeLoader->getType(QUrl("qrc:/qrcurls.qml"))); QVERIFY(oneQml.data() != nullptr); QVERIFY(!oneQml->backupSourceCode().isValid()); - QQmlRefPointer<QQmlTypeData> twoQml(pEngine->typeLoader.getType(QUrl("qrc:///qrcurls.qml"))); + QQmlRefPointer<QQmlTypeData> twoQml(typeLoader->getType(QUrl("qrc:///qrcurls.qml"))); QVERIFY(twoQml.data() != nullptr); QCOMPARE(oneQml.data(), twoQml.data()); } { - QQmlRefPointer<QQmlTypeData> oneJS(pEngine->typeLoader.getType(QUrl("qrc:/qrcurls.js"))); + QQmlRefPointer<QQmlTypeData> oneJS(typeLoader->getType(QUrl("qrc:/qrcurls.js"))); QVERIFY(oneJS.data() != nullptr); QVERIFY(!oneJS->backupSourceCode().isValid()); - QQmlRefPointer<QQmlTypeData> twoJS(pEngine->typeLoader.getType(QUrl("qrc:///qrcurls.js"))); + QQmlRefPointer<QQmlTypeData> twoJS(typeLoader->getType(QUrl("qrc:///qrcurls.js"))); QVERIFY(twoJS.data() != nullptr); QCOMPARE(oneJS.data(), twoJS.data()); } diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp index 25275a4028..0f1956c0cd 100644 --- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp +++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp @@ -104,7 +104,7 @@ void tst_QQmlImport::envResourceImportPath() qputenv("QML_IMPORT_PATH", envPaths.join(QDir::listSeparator()).toUtf8()); QQmlEngine engine; - const QStringList importPaths = QQmlEnginePrivate::get(&engine)->typeLoader.importPathList(); + const QStringList importPaths = QQmlTypeLoader::get(&engine)->importPathList(); for (const QString &path : envPaths) QVERIFY((importPaths.contains(path.startsWith(u':') ? QLatin1String("qrc") + path : path))); diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp index b1e1a8c8db..2197a1b372 100644 --- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp +++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp @@ -1161,7 +1161,7 @@ void tst_qqmlincubator::garbageCollection() // turn the last strong reference to the incubator into a weak one and collect QV4::WeakValue weakIncubatorRef; - weakIncubatorRef.set(QQmlEnginePrivate::getV4Engine(&engine), QJSValuePrivate::asReturnedValue(&strongRef)); + weakIncubatorRef.set(engine.handle(), QJSValuePrivate::asReturnedValue(&strongRef)); strongRef = QJSValue(); incubatorVariant.clear(); diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 09c7e75966..f8081b697e 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -2755,8 +2755,7 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode() QUrl url = testFileUrl("scriptString7.qml"); QScopedPointer<const QV4::CompiledData::Unit, FreeUnitData> readOnlyQmlUnit; { - QQmlEnginePrivate *eng = QQmlEnginePrivate::get(&engine); - QQmlRefPointer<QQmlTypeData> td = eng->typeLoader.getType(url); + QQmlRefPointer<QQmlTypeData> td = QQmlTypeLoader::get(&engine)->getType(url); Q_ASSERT(td); QVERIFY(!td->backupSourceCode().isValid()); diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp index c0fa508acf..e7356cc2b0 100644 --- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp +++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp @@ -602,7 +602,7 @@ void tst_qqmlmetatype::unregisterAttachedProperties() const QQmlType attachedType = QQmlMetaType::qmlType("QtQuick/KeyNavigation", QTypeRevision::fromVersion(2, 2)); - QCOMPARE(attachedType.attachedPropertiesType(QQmlEnginePrivate::get(&e)), + QCOMPARE(attachedType.attachedPropertiesType(QQmlTypeLoader::get(&e)), attachedType.metaObject()); QScopedPointer<QObject> obj(c.create()); diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp index 69dbd6179b..40c7b5d519 100644 --- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp +++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp @@ -57,8 +57,8 @@ void tst_qqmltranslation::translation() if (verifyCompiledData) { QQmlContext *context = qmlContext(object.get()); - QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine()); - QQmlRefPointer<QQmlTypeData> typeData = engine->typeLoader.getType(context->baseUrl()); + QQmlRefPointer<QQmlTypeData> typeData + = QQmlTypeLoader::get(context->engine())->getType(context->baseUrl()); QVERIFY(!typeData->backupSourceCode().isValid()); QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit(); QVERIFY(compilationUnit); @@ -122,8 +122,8 @@ void tst_qqmltranslation::idTranslation() { QQmlContext *context = qmlContext(object.get()); - QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine()); - QQmlRefPointer<QQmlTypeData> typeData = engine->typeLoader.getType(context->baseUrl()); + QQmlRefPointer<QQmlTypeData> typeData + = QQmlTypeLoader::get(context->engine())->getType(context->baseUrl()); QVERIFY(!typeData->backupSourceCode().isValid()); QV4::CompiledData::CompilationUnit *compilationUnit = typeData->compilationUnit(); QVERIFY(compilationUnit); diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp index 02435f7cdd..995867ea9f 100644 --- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp +++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp @@ -109,14 +109,14 @@ void tst_QQMLTypeLoader::loadComponentSynchronously() void tst_QQMLTypeLoader::trimCache() { QQmlEngine engine; - QQmlTypeLoader &loader = QQmlEnginePrivate::get(&engine)->typeLoader; + QQmlTypeLoader *loader = QQmlTypeLoader::get(&engine); QVector<QQmlTypeData *> releaseLater; QVector<QV4::CompiledData::CompilationUnit *> releaseCompilationUnitLater; for (int i = 0; i < 256; ++i) { QUrl url = testFileUrl("trim_cache.qml"); url.setQuery(QString::number(i)); - QQmlTypeData *data = loader.getType(url).take(); + QQmlTypeData *data = loader->getType(url).take(); // Backup source code should be dropped right after loading, even without cache trimming. QVERIFY(!data->backupSourceCode().isValid()); @@ -142,9 +142,9 @@ void tst_QQMLTypeLoader::trimCache() QUrl url = testFileUrl("trim_cache.qml"); url.setQuery(QString::number(i)); if (i % 5 == 0) - QVERIFY(loader.isTypeLoaded(url)); + QVERIFY(loader->isTypeLoaded(url)); else if (i < 128) - QVERIFY(!loader.isTypeLoaded(url)); + QVERIFY(!loader->isTypeLoaded(url)); // The cache is free to keep the others. } @@ -159,13 +159,13 @@ void tst_QQMLTypeLoader::trimCache2() { QScopedPointer<QQuickView> window(new QQuickView()); window->setSource(testFileUrl("trim_cache2.qml")); - QQmlTypeLoader &loader = QQmlEnginePrivate::get(window->engine())->typeLoader; + QQmlTypeLoader *loader = QQmlTypeLoader::get(window->engine()); // in theory if gc has already run this could be false // QCOMPARE(loader.isTypeLoaded(testFileUrl("MyComponent2.qml")), true); window->engine()->collectGarbage(); QTest::qWait(1); // force event loop window->engine()->trimComponentCache(); - QCOMPARE(loader.isTypeLoaded(testFileUrl("MyComponent2.qml")), false); + QCOMPARE(loader->isTypeLoaded(testFileUrl("MyComponent2.qml")), false); } // test trimming the cache of an item that contains sub-items created via incubation @@ -173,8 +173,8 @@ void tst_QQMLTypeLoader::trimCache3() { QScopedPointer<QQuickView> window(new QQuickView()); window->setSource(testFileUrl("trim_cache3.qml")); - QQmlTypeLoader &loader = QQmlEnginePrivate::get(window->engine())->typeLoader; - QCOMPARE(loader.isTypeLoaded(testFileUrl("ComponentWithIncubator.qml")), true); + QQmlTypeLoader *loader = QQmlTypeLoader::get(window->engine()); + QCOMPARE(loader->isTypeLoaded(testFileUrl("ComponentWithIncubator.qml")), true); QQmlProperty::write(window->rootObject(), "source", QString()); @@ -185,7 +185,7 @@ void tst_QQMLTypeLoader::trimCache3() window->engine()->trimComponentCache(); - QCOMPARE(loader.isTypeLoaded(testFileUrl("ComponentWithIncubator.qml")), false); + QCOMPARE(loader->isTypeLoaded(testFileUrl("ComponentWithIncubator.qml")), false); } void tst_QQMLTypeLoader::checkSingleton(const QString &dataDirectory) @@ -739,8 +739,8 @@ static void getCompilationUnitAndRuntimeInfo(QQmlRefPointer<QV4::ExecutableCompi QList<int> &runtimeFunctionIndices, const QUrl &url, QQmlEngine *engine) { - QQmlTypeLoader &loader = QQmlEnginePrivate::get(engine)->typeLoader; - auto typeData = loader.getType(url); + QQmlTypeLoader *loader = QQmlTypeLoader::get(engine); + auto typeData = loader->getType(url); QVERIFY(typeData); QVERIFY(!typeData->backupSourceCode().isValid()); diff --git a/tools/qmlplugindump/main.cpp b/tools/qmlplugindump/main.cpp index c6c96dcd90..36907a7edf 100644 --- a/tools/qmlplugindump/main.cpp +++ b/tools/qmlplugindump/main.cpp @@ -142,12 +142,13 @@ void collectReachableMetaObjects(QObject *object, QSet<const QMetaObject *> *met } } -void collectReachableMetaObjects(QQmlEnginePrivate *engine, const QQmlType &ty, QSet<const QMetaObject *> *metas, const QmlVersionInfo& info) +void collectReachableMetaObjects( + QQmlTypeLoader *typeLoader, const QQmlType &ty, QSet<const QMetaObject *> *metas, + const QmlVersionInfo& info) { collectReachableMetaObjects(ty.baseMetaObject(), metas, info, ty.isExtendedType()); - if (ty.attachedPropertiesType(engine) && matchingImportUri(ty, info)) { - collectReachableMetaObjects(ty.attachedPropertiesType(engine), metas, info); - } + if (ty.attachedPropertiesType(typeLoader) && matchingImportUri(ty, info)) + collectReachableMetaObjects(ty.attachedPropertiesType(typeLoader), metas, info); } /* When we dump a QMetaObject, we want to list all the types it is exported as. @@ -197,13 +198,14 @@ QByteArray convertToId(const QMetaObject *mo) // Collect all metaobjects for types registered with qmlRegisterType() without parameters -void collectReachableMetaObjectsWithoutQmlName(QQmlEnginePrivate *engine, QSet<const QMetaObject *>& metas, - QMap<QString, QList<QQmlType>> &compositeTypes, const QmlVersionInfo &info) { +void collectReachableMetaObjectsWithoutQmlName( + QQmlTypeLoader *typeLoader, QSet<const QMetaObject *>& metas, + QMap<QString, QList<QQmlType>> &compositeTypes, const QmlVersionInfo &info) { const auto qmlAllTypes = QQmlMetaType::qmlAllTypes(); for (const QQmlType &ty : qmlAllTypes) { if (!metas.contains(ty.baseMetaObject())) { if (!ty.isComposite()) { - collectReachableMetaObjects(engine, ty, &metas, info); + collectReachableMetaObjects(typeLoader, ty, &metas, info); } else if (matchingImportUri(ty, info)) { compositeTypes[ty.elementName()].append(ty); } @@ -211,13 +213,10 @@ void collectReachableMetaObjectsWithoutQmlName(QQmlEnginePrivate *engine, QSet<c } } -QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, - QSet<const QMetaObject *> &noncreatables, - QSet<const QMetaObject *> &singletons, - QMap<QString, QList<QQmlType>> &compositeTypes, - const QmlVersionInfo &info, - const QList<QQmlType> &skip = QList<QQmlType>() - ) +QSet<const QMetaObject *> collectReachableMetaObjects( + QQmlEngine *engine, QSet<const QMetaObject *> &noncreatables, + QSet<const QMetaObject *> &singletons, QMap<QString, QList<QQmlType>> &compositeTypes, + const QmlVersionInfo &info, const QList<QQmlType> &skip = QList<QQmlType>()) { QSet<const QMetaObject *> metas; metas.insert(&Qt::staticMetaObject); @@ -233,7 +232,7 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, if (!ty.isComposite()) { if (const QMetaObject *mo = ty.baseMetaObject()) qmlTypesByCppName[mo->className()].insert(ty); - collectReachableMetaObjects(QQmlEnginePrivate::get(engine), ty, &metas, info); + collectReachableMetaObjects(QQmlTypeLoader::get(engine), ty, &metas, info); } else { compositeTypes[ty.elementName()].append(ty); } @@ -302,7 +301,7 @@ QSet<const QMetaObject *> collectReachableMetaObjects(QQmlEngine *engine, } } - collectReachableMetaObjectsWithoutQmlName(QQmlEnginePrivate::get(engine), metas, compositeTypes, info); + collectReachableMetaObjectsWithoutQmlName(QQmlTypeLoader::get(engine), metas, compositeTypes, info); return metas; } @@ -535,7 +534,8 @@ public: QByteArray attachedTypeId; }; - void dump(QQmlEnginePrivate *engine, const QMetaObject *meta, bool isUncreatable, bool isSingleton) + void dump(QQmlTypeLoader *typeLoader, const QMetaObject *meta, + bool isUncreatable, bool isSingleton) { qml->writeStartObject("Component"); @@ -548,7 +548,7 @@ public: for (const QQmlType &type : types) { const QMetaObject *extendedObject = type.extensionFunction() ? type.metaObject() : nullptr; QByteArray attachedTypeId; - if (const QMetaObject *attachedType = type.attachedPropertiesType(engine)) { + if (const QMetaObject *attachedType = type.attachedPropertiesType(typeLoader)) { // Can happen when a type is registered that returns itself as attachedPropertiesType() // because there is no creatable type to attach to. if (attachedType != meta) @@ -1355,7 +1355,8 @@ int main(int argc, char *argv[]) if (relocatable) dumper.setRelocatableModuleUri(pluginImportUri); for (const QMetaObject *meta : std::as_const(nameToMeta)) { - dumper.dump(QQmlEnginePrivate::get(&engine), meta, uncreatableMetas.contains(meta), singletonMetas.contains(meta)); + dumper.dump(QQmlTypeLoader::get(&engine), meta, uncreatableMetas.contains(meta), + singletonMetas.contains(meta)); } QMap<QString, QList<QQmlType>>::const_iterator iter = compositeTypes.constBegin(); |