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 <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2025-06-03 14:35:29 +02:00
parent 8e0810c19c
commit d2bc4a4330
47 changed files with 283 additions and 301 deletions

View File

@ -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());

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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));

View File

@ -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>

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -60,6 +60,7 @@ public:
void startLoading();
QQmlTypeLoader *typeLoader() const { return m_typeLoader; }
void resetTypeLoader() { m_typeLoader = nullptr; }
Type type() const;
@ -115,11 +116,18 @@ public:
Q_ASSERT(loader && loader->thread() && loader->thread()->isThisThread());
}
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:

View File

@ -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;

View File

@ -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,13 +172,14 @@ 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 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);
inline static QQmlEngine *get(QQmlEnginePrivate *p);
inline static QQmlEnginePrivate *get(QV4::ExecutionEngine *e);
static QList<QQmlError> qmlErrorFromDiagnostics(const QString &fileName, const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages);
@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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));

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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.

View File

@ -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();

View File

@ -10,9 +10,8 @@
QT_BEGIN_NAMESPACE
QQmlTypeLoaderLockedData::QQmlTypeLoaderLockedData(QQmlEngine *engine)
QQmlTypeLoaderLockedData::QQmlTypeLoaderLockedData(QV4::ExecutionEngine *engine)
: m_engine(engine)
{
}
{}
QT_END_NAMESPACE

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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() << "'";

View File

@ -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++;

View File

@ -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;

View File

@ -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 {

View File

@ -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();
}

View File

@ -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());
}

View File

@ -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)));

View File

@ -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();

View File

@ -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());

View File

@ -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());

View File

@ -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);

View File

@ -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());

View File

@ -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();