Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmlengine.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmlengine_p.h"
5#include "qqmlengine.h"
6
7#include "qqmlcontext_p.h"
8#include "qqml.h"
9#include "qqmlcontext.h"
10#include "qqmlscriptstring.h"
11#include "qqmlglobal_p.h"
12#include "qqmlnotifier_p.h"
13#include "qqmlincubator.h"
15
16#include <private/qqmldirparser_p.h>
17#include <private/qqmlboundsignal_p.h>
18#include <private/qqmljsdiagnosticmessage_p.h>
19#include <private/qqmltype_p_p.h>
20#include <private/qqmlpluginimporter_p.h>
21#include <QtCore/qstandardpaths.h>
22#include <QtCore/qmetaobject.h>
23#include <QDebug>
24#include <QtCore/qcoreapplication.h>
25#include <QtCore/qcryptographichash.h>
26#include <QtCore/qdir.h>
27#include <QtCore/qmutex.h>
28#include <QtCore/qthread.h>
29#include <private/qthread_p.h>
30#include <private/qqmlscriptdata_p.h>
31#include <QtQml/private/qqmlcomponentattached_p.h>
32#include <QtQml/private/qqmlsourcecoordinate_p.h>
33#include <QtQml/private/qqmlcomponent_p.h>
34
35#if QT_CONFIG(qml_network)
37#include <QNetworkAccessManager>
38#endif
39
40#include <private/qobject_p.h>
41#include <private/qmetaobject_p.h>
42#if QT_CONFIG(qml_locale)
43#include <private/qqmllocale_p.h>
44#endif
45#include <private/qqmlbind_p.h>
46#include <private/qqmlconnections_p.h>
47#if QT_CONFIG(qml_animation)
48#include <private/qqmltimer_p.h>
49#endif
50#include <private/qqmlplatform_p.h>
51#include <private/qqmlloggingcategory_p.h>
52#include <private/qv4sequenceobject_p.h>
53
54#ifdef Q_OS_WIN // for %APPDATA%
55# include <qt_windows.h>
56# include <shlobj.h>
57# include <qlibrary.h>
58# ifndef CSIDL_APPDATA
59# define CSIDL_APPDATA 0x001a // <username>\Application Data
60# endif
61#endif // Q_OS_WIN
62
64
66
123Q_CONSTINIT std::atomic<bool> QQmlEnginePrivate::qml_debugging_enabled{false};
124bool QQmlEnginePrivate::s_designerMode = false;
125
127{
128 return s_designerMode;
129}
130
132{
133 s_designerMode = true;
134}
135
136
191QQmlImageProviderBase::QQmlImageProviderBase()
192{
193}
194
199
201{
203 qWarning() << QQmlEngine::tr("There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
204
206 incubationController = nullptr;
207
209
210#if QT_CONFIG(qml_debug)
211 delete profiler;
212#endif
213 qDeleteAll(cachedValueTypeInstances);
214}
215
217{
219 if (QQmlData *d = QQmlData::get(p)) {
220 const auto invalidate = [](QQmlContextData *c) {c->invalidate();};
221 if (d->ownContext) {
222 d->ownContext->deepClearContextObject(o, invalidate, invalidate);
223 d->ownContext.reset();
224 d->context = nullptr;
225 Q_ASSERT(!d->outerContext || d->outerContext->contextObject() != o);
226 } else if (d->outerContext && d->outerContext->contextObject() == o) {
227 d->outerContext->deepClearContextObject(o, invalidate, invalidate);
228 }
229
230 if (d->hasVMEMetaObject || d->hasInterceptorMetaObject) {
231 // This is somewhat dangerous because another thread might concurrently
232 // try to resolve the dynamic metaobject. In practice this will then
233 // lead to either the code path that still returns the interceptor
234 // metaobject or the code path that returns the string casted one. Both
235 // is fine if you cannot actually touch the object itself. Since the
236 // other thread is obviously not synchronized to this one, it can't.
237 //
238 // In particular we do this when delivering the frameSwapped() signal
239 // in QQuickWindow. The handler for frameSwapped() is written in a way
240 // that is thread safe as long as QQuickWindow's dtor hasn't finished.
241 // QQuickWindow's dtor does synchronize with the render thread, but it
242 // runs _after_ qdeclarativeelement_destructor.
243 static_cast<QQmlInterceptorMetaObject *>(p->metaObject)->invalidate();
244 d->hasVMEMetaObject = d->hasInterceptorMetaObject = false;
245 }
246
247 // Mark this object as in the process of deletion to
248 // prevent it resolving in bindings
250 }
251}
252
254 : ownMemory(ownership == OwnsMemory), indestructible(true), explicitIndestructibleSet(false),
255 hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false),
256 hasInterceptorMetaObject(false), hasVMEMetaObject(false), hasConstWrapper(false), dummy(0),
257 bindingBitsArraySize(InlineBindingArraySize)
258{
259 memset(bindingBitsValue, 0, sizeof(bindingBitsValue));
260 init();
261}
262
266
268{
269 QQmlData *ddata = static_cast<QQmlData *>(d);
270 ddata->destroyed(o);
271}
272
273
275{
276public:
277 QPointer<QObject> target;
278
279 int qt_metacall(QMetaObject::Call, int methodIndex, void **a) override {
280 if (!target)
281 return -1;
282
283 QMetaMethod method = target->metaObject()->method(methodIndex);
284 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
286 QQmlData *ddata = QQmlData::get(target, false);
287 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
288 if (ep) QQmlNotifier::emitNotify(ep, a);
289
290 delete this;
291
292 return -1;
293 }
294};
295
297{
298 QQmlData *ddata = QQmlData::get(object, false);
299 if (!ddata) return; // Probably being deleted
300
301 // In general, QML only supports QObject's that live on the same thread as the QQmlEngine
302 // that they're exposed to. However, to make writing "worker objects" that calculate data
303 // in a separate thread easier, QML allows a QObject that lives in the same thread as the
304 // QQmlEngine to emit signals from a different thread. These signals are then automatically
305 // marshalled back onto the QObject's thread and handled by QML from there. This is tested
306 // by the qqmlecmascript::threadSignal() autotest.
307
308 // Relaxed semantics here. If we're on a different thread we might schedule a useless event,
309 // but that should be rare.
310 if (!ddata->notifyList.loadRelaxed())
311 return;
312
313 auto objectThreadData = QObjectPrivate::get(object)->threadData.loadRelaxed();
314 if (QThread::currentThreadId() != objectThreadData->threadId.loadRelaxed()) {
315 if (!objectThreadData->thread.loadAcquire())
316 return;
317
319 QList<QByteArray> parameterTypes = m.parameterTypes();
320
321 auto ev = std::make_unique<QMetaCallEvent>(m.methodIndex(), 0, nullptr,
322 object, index,
323 parameterTypes.size() + 1);
324
325 void **args = ev->args();
326 QMetaType *types = ev->types();
327
328 for (int ii = 0; ii < parameterTypes.size(); ++ii) {
329 const QByteArray &typeName = parameterTypes.at(ii);
330 if (typeName.endsWith('*'))
331 types[ii + 1] = QMetaType(QMetaType::VoidStar);
332 else
334
335 if (!types[ii + 1].isValid()) {
336 qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
337 "(Make sure '%s' is registered using qRegisterMetaType().)",
338 typeName.constData(), typeName.constData());
339 return;
340 }
341
342 args[ii + 1] = types[ii + 1].create(a[ii + 1]);
343 }
344
346 mpo->target = object;
347 mpo->moveToThread(objectThreadData->thread.loadAcquire());
348 QCoreApplication::postEvent(mpo, ev.release());
349
350 } else {
351 QQmlNotifierEndpoint *ep = ddata->notify(index);
352 if (ep) QQmlNotifier::emitNotify(ep, a);
353 }
354}
355
357{
358 QQmlData *ddata = static_cast<QQmlData *>(d);
359 return ddata->endpointCount(index);
360}
361
363{
364 QQmlData *ddata = static_cast<QQmlData *>(d);
365 return ddata->signalHasEndpoint(index);
366}
367
369{
370 int count = 0;
372 if (!ep)
373 return count;
374 ++count;
375 while (ep->next) {
376 ++count;
377 ep = ep->next;
378 }
379 return count;
380}
381
383{
384 QVarLengthArray<QObject *> workStack;
385 workStack.push_back(o);
386 while (!workStack.isEmpty()) {
387 auto currentObject = workStack.last();
388 workStack.pop_back();
389 QQmlData::setQueuedForDeletion(currentObject);
390 auto currentObjectPriv = QObjectPrivate::get(currentObject);
391 for (QObject *child: std::as_const(currentObjectPriv->children))
392 workStack.push_back(child);
393 }
394}
395
397{
398 if (object) {
399 if (QQmlData *ddata = QQmlData::get(object)) {
400 if (ddata->ownContext) {
401 Q_ASSERT(ddata->ownContext.data() == ddata->context);
402 ddata->ownContext->deepClearContextObject(object);
403 ddata->ownContext.reset();
404 ddata->context = nullptr;
405 }
406 ddata->isQueuedForDeletion = true;
407
408 // Disconnect the notifiers now - during object destruction this would be too late,
409 // since the disconnect call wouldn't be able to call disconnectNotify(), as it isn't
410 // possible to get the metaobject anymore.
411 // Also, there is no point in evaluating bindings in order to set properties on
412 // half-deleted objects.
413 ddata->disconnectNotifiers(DeleteNotifyList::No);
414 }
415 }
416}
417
419{
420 clearPendingBindingBit(coreIndex);
421
422 // Find the binding
424 while (b && (b->targetPropertyIndex().coreIndex() != coreIndex ||
425 b->targetPropertyIndex().hasValueTypeIndex()))
426 b = b->nextBinding();
427
428 if (b && b->targetPropertyIndex().coreIndex() == coreIndex &&
429 !b->targetPropertyIndex().hasValueTypeIndex())
432}
433
436
437template<>
438int qmlRegisterType<void>(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
439{
442 QMetaType(),
443 QMetaType(),
444 0, nullptr, nullptr,
445 QString(),
446 nullptr,
447 uri,
448 QTypeRevision::fromVersion(versionMajor, versionMinor),
449 qmlName,
450 nullptr,
451 nullptr,
452 nullptr,
453 -1,
454 -1,
455 -1,
456 nullptr,
457 nullptr,
458 nullptr,
460 -1,
462 };
463
465}
466
469{
470 Q_Q(QQmlEngine);
471
473 // Register builtins
475
476 // No need to specifically register those.
477 static_assert(std::is_same_v<QStringList, QList<QString>>);
478 static_assert(std::is_same_v<QVariantList, QList<QVariant>>);
479
480 qRegisterMetaType<QQmlScriptString>();
481 qRegisterMetaType<QQmlComponent::Status>();
482 qRegisterMetaType<QList<QObject*> >();
483 qRegisterMetaType<QQmlBinding*>();
484
485 // Protect the module: We don't want any URL interceptor to mess with the builtins.
486 qmlProtectModule("QML", 1);
487
490 }
491
492 q->handle()->setQmlEngine(q);
493
494 rootContext = new QQmlContext(q,true);
495}
496
519: QJSEngine(*new QQmlEnginePrivate(this), parent)
520{
521 Q_D(QQmlEngine);
522 d->init();
524}
525
530: QJSEngine(dd, parent)
531{
532 Q_D(QQmlEngine);
533 d->init();
534}
535
546{
547 Q_D(QQmlEngine);
548 handle()->inShutdown = true;
550
551 // Emit onDestruction signals for the root context before
552 // we destroy the contexts, engine, Singleton Types etc. that
553 // may be required to handle the destruction signal.
554 QQmlContextPrivate::get(rootContext())->emitDestruction();
555
556 // clean up all singleton type instances which we own.
557 // we do this here and not in the private dtor since otherwise a crash can
558 // occur (if we are the QObject parent of the QObject singleton instance)
559 // XXX TODO: performance -- store list of singleton types separately?
560 d->singletonInstances.clear();
561
562 delete d->rootContext;
563 d->rootContext = nullptr;
564
565 d->typeLoader.invalidate();
566}
567
615{
616 Q_D(QQmlEngine);
617
618 // Contexts can hold on to CUs but live on the JS heap.
619 // Use a non-incremental GC run to get rid of those.
621 auto oldLimit = mm->gcStateMachine->timeLimit;
622 mm->setGCTimeLimit(-1);
623 mm->runGC();
624 mm->gcStateMachine->timeLimit = std::move(oldLimit);
625
627 d->typeLoader.lock();
628 d->typeLoader.clearCache();
629 d->typeLoader.unlock();
631}
632
646{
647 Q_D(QQmlEngine);
649 d->typeLoader.trimCache();
650}
651
668{
669 Q_D(QQmlEngine);
670 d->singletonInstances.clear();
671}
672
685{
686 Q_D(const QQmlEngine);
687 return d->rootContext;
688}
689
690#if QT_DEPRECATED_SINCE(6, 0)
699QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor() const
700{
701 Q_D(const QQmlEngine);
702 return d->urlInterceptors.last();
703}
704#endif
705
716{
717 Q_D(QQmlEngine);
718 d->urlInterceptors.append(urlInterceptor);
719}
720
730{
731 Q_D(QQmlEngine);
732 d->urlInterceptors.removeOne(urlInterceptor);
733}
734
740{
741 Q_D(const QQmlEngine);
742 QUrl result = url;
743 for (QQmlAbstractUrlInterceptor *interceptor : d->urlInterceptors)
744 result = interceptor->intercept(result, type);
745 return result;
746}
747
751QList<QQmlAbstractUrlInterceptor *> QQmlEngine::urlInterceptors() const
752{
753 Q_D(const QQmlEngine);
754 return d->urlInterceptors;
755}
756
757QSharedPointer<QQmlImageProviderBase> QQmlEnginePrivate::imageProvider(const QString &providerId) const
758{
759 const QString providerIdLower = providerId.toLower();
761 return imageProviders.value(providerIdLower);
762}
763
764#if QT_CONFIG(qml_network)
777void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
778{
779 Q_D(QQmlEngine);
780 QMutexLocker locker(&d->networkAccessManagerMutex);
781 d->networkAccessManagerFactory = factory;
782}
783
789QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const
790{
791 Q_D(const QQmlEngine);
792 return d->networkAccessManagerFactory;
793}
794
795QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const
796{
799 if (networkAccessManagerFactory) {
800 nam = networkAccessManagerFactory->create(parent);
801 } else {
802 nam = new QNetworkAccessManager(parent);
803 }
804
805 return nam;
806}
807
808QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager() const
809{
810 Q_Q(const QQmlEngine);
811 if (!networkAccessManager)
812 networkAccessManager = createNetworkAccessManager(const_cast<QQmlEngine*>(q));
813 return networkAccessManager;
814}
815
828QNetworkAccessManager *QQmlEngine::networkAccessManager() const
829{
830 Q_D(const QQmlEngine);
831 return d->getNetworkAccessManager();
832}
833#endif // qml_network
834
851{
852 Q_D(QQmlEngine);
853 QString providerIdLower = providerId.toLower();
854 QSharedPointer<QQmlImageProviderBase> sp(provider);
855 QMutexLocker locker(&d->imageProviderMutex);
856 d->imageProviders.insert(std::move(providerIdLower), std::move(sp));
857}
858
865{
866 Q_D(const QQmlEngine);
867 const QString providerIdLower = providerId.toLower();
868 QMutexLocker locker(&d->imageProviderMutex);
869 return d->imageProviders.value(providerIdLower).data();
870}
871
878{
879 Q_D(QQmlEngine);
880 const QString providerIdLower = providerId.toLower();
881 QMutexLocker locker(&d->imageProviderMutex);
882 d->imageProviders.take(providerIdLower);
883}
884
896{
897 Q_D(const QQmlEngine);
898 if (d->baseUrl.isEmpty()) {
899 const QString currentPath = QDir::currentPath();
900 const QString rootPath = QDir::rootPath();
901 return QUrl::fromLocalFile((currentPath == rootPath) ? rootPath : (currentPath + QDir::separator()));
902 } else {
903 return d->baseUrl;
904 }
905}
906
913{
914 Q_D(QQmlEngine);
915 d->baseUrl = url;
916}
917
925{
926 Q_D(const QQmlEngine);
927 return d->outputWarningsToMsgLog;
928}
929
941{
942 Q_D(QQmlEngine);
943 d->outputWarningsToMsgLog = enabled;
944}
945
946
979{
980 Q_D(QQmlEngine);
981 if (auto propertyCapture = d->propertyCapture)
982 propertyCapture->captureTranslation();
983}
984
991{
992 Q_D(const QQmlEngine);
993 if (d->propertyCapture && !property.isConstant()) {
994 d->propertyCapture->captureProperty(
995 object, property.propertyIndex(),
997 }
998}
999
1045template<>
1046QJSValue QQmlEngine::singletonInstance<QJSValue>(int qmlTypeId)
1047{
1048 Q_D(QQmlEngine);
1050
1051 if (!type.isValid() || !type.isSingleton())
1052 return QJSValue();
1053
1054 return d->singletonInstance<QJSValue>(type);
1055}
1056
1057
1080template<>
1081QJSValue QQmlEngine::singletonInstance<QJSValue>(QAnyStringView uri, QAnyStringView typeName)
1082{
1083 Q_D(QQmlEngine);
1084
1085 auto loadHelper = QQml::makeRefPointer<LoadHelper>(&d->typeLoader, uri);
1086
1087 auto [moduleStatus, type] = loadHelper->resolveType(typeName);
1088
1090 return {};
1091 if (!type.isValid())
1092 return {};
1093 if (!type.isSingleton())
1094 return {};
1095
1096 return d->singletonInstance<QJSValue>(type);
1097}
1098
1109{
1110 Q_D(QQmlEngine);
1111 d->translationLanguage.notify();
1112}
1113
1125{
1126 if(!object)
1127 return nullptr;
1128
1129 QQmlData *data = QQmlData::get(object);
1130 if (data && data->outerContext)
1131 return data->outerContext->asQQmlContext();
1132
1133 return nullptr;
1134}
1135
1145{
1146 if (!object || !context)
1147 return;
1148
1149 QQmlData *data = QQmlData::get(object, true);
1150 if (data->context) {
1151 qWarning("QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1152 return;
1153 }
1154
1155 QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
1156 Q_ASSERT(data->context == nullptr);
1157 data->context = contextData.data();
1158 contextData->addOwnedObject(data);
1159}
1160
1165{
1166 if (e->type() == QEvent::LanguageChange) {
1167 retranslate();
1168 }
1169
1170 return QJSEngine::event(e);
1171}
1172
1174public:
1177
1178 QHash<QQmlAttachedPropertiesFunc, QObject *> attachedProperties;
1179};
1180
1184
1188
1190{
1191 // Add a temporary sentinel at beginning of list. This will be overwritten
1192 // when the end point is inserted into the notifies further down.
1193 endpoint->prev = nullptr;
1194
1195 while (endpoint->next) {
1196 Q_ASSERT(reinterpret_cast<QQmlNotifierEndpoint *>(endpoint->next->prev) == endpoint);
1197 endpoint = endpoint->next;
1198 }
1199
1200 while (endpoint) {
1201 QQmlNotifierEndpoint *ep = (QQmlNotifierEndpoint *) endpoint->prev;
1202
1203 int index = endpoint->sourceSignal;
1204 index = qMin(index, 0xFFFF - 1);
1205
1206 endpoint->next = notifies[index];
1207 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1208 endpoint->prev = &notifies[index];
1209 notifies[index] = endpoint;
1210
1211 endpoint = ep;
1212 }
1213}
1214
1216{
1217 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1218
1219 if (todo) {
1220 QQmlNotifierEndpoint **old = notifies;
1221 const int reallocSize = (maximumTodoIndex + 1) * sizeof(QQmlNotifierEndpoint*);
1222 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1223 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1224 sizeof(QQmlNotifierEndpoint*);
1225 memset(notifies + notifiesSize, 0, memsetSize);
1226
1227 if (notifies != old) {
1228 for (int ii = 0; ii < notifiesSize; ++ii)
1229 if (notifies[ii])
1230 notifies[ii]->prev = &notifies[ii];
1231 }
1232
1233 notifiesSize = maximumTodoIndex + 1;
1234
1235 layout(todo);
1236 }
1237
1238 maximumTodoIndex = 0;
1239 todo = nullptr;
1240}
1241
1243 int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
1244 const QQmlRefPointer<QQmlContextData> &context)
1245{
1247 deferData->deferredIdx = objectIndex;
1248 deferData->compilationUnit = compilationUnit;
1249 deferData->context = context;
1250
1251 const QV4::CompiledData::Object *compiledObject = compilationUnit->objectAt(objectIndex);
1252 const QV4::CompiledData::BindingPropertyData *propertyData
1254
1255 const QV4::CompiledData::Binding *binding = compiledObject->bindingTable();
1256 for (quint32 i = 0; i < compiledObject->nBindings; ++i, ++binding) {
1257 const QQmlPropertyData *property = propertyData->at(i);
1259 deferData->bindings.insert(property ? property->coreIndex() : -1, binding);
1260 }
1261
1262 deferredData.append(deferData);
1263}
1264
1266{
1267 auto it = deferredData.begin();
1268 while (it != deferredData.end()) {
1270 if (deferData->bindings.isEmpty()) {
1271 delete deferData;
1272 it = deferredData.erase(it);
1273 } else {
1274 ++it;
1275 }
1276 }
1277}
1278
1280{
1281 // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics.
1282
1283 NotifyList *list = notifyList.loadRelaxed();
1284
1285 if (!list) {
1286 list = new NotifyList;
1287 // We don't really care when this change takes effect on other threads. The notifyList can
1288 // only become non-null once in the life time of a QQmlData. It becomes null again when the
1289 // underlying QObject is deleted. At that point any interaction with the QQmlData is UB
1290 // anyway. So, for all intents and purposese, the list becomes non-null once and then stays
1291 // non-null "forever". We can apply relaxed semantics.
1292 notifyList.storeRelaxed(list);
1293 }
1294
1295 Q_ASSERT(!endpoint->isConnected());
1296
1297 index = qMin(index, 0xFFFF - 1);
1298
1299 // Likewise, we don't really care _when_ the change in the connectionMask is propagated to other
1300 // threads. Cross-thread event ordering is inherently nondeterministic. Therefore, when querying
1301 // the conenctionMask in the presence of concurrent modification, any result is correct.
1302 list->connectionMask.storeRelaxed(
1303 list->connectionMask.loadRelaxed() | (1ULL << quint64(index % 64)));
1304
1305 if (index < list->notifiesSize) {
1306 endpoint->next = list->notifies[index];
1307 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1308 endpoint->prev = &list->notifies[index];
1309 list->notifies[index] = endpoint;
1310 } else {
1311 list->maximumTodoIndex = qMax(int(list->maximumTodoIndex), index);
1312
1313 endpoint->next = list->todo;
1314 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1315 endpoint->prev = &list->todo;
1316 list->todo = endpoint;
1317 }
1318}
1319
1321{
1322 // Can only happen on "home" thread. We apply relaxed semantics when loading the atomics.
1323 if (NotifyList *list = notifyList.loadRelaxed()) {
1324 while (QQmlNotifierEndpoint *todo = list->todo)
1325 todo->disconnect();
1326 for (int ii = 0; ii < list->notifiesSize; ++ii) {
1327 while (QQmlNotifierEndpoint *ep = list->notifies[ii])
1328 ep->disconnect();
1329 }
1330 free(list->notifies);
1331
1332 if (doDelete == DeleteNotifyList::Yes) {
1333 // We can only get here from QQmlData::destroyed(), and that can only come from the
1334 // the QObject dtor. If you're still sending signals at that point you have UB already
1335 // without any threads. Therefore, it's enough to apply relaxed semantics.
1336 notifyList.storeRelaxed(nullptr);
1337 delete list;
1338 } else {
1339 // We can use relaxed semantics here. The worst thing that can happen is that some
1340 // signal is falsely reported as connected. Signal connectedness across threads
1341 // is not quite deterministic anyway.
1342 list->connectionMask.storeRelaxed(0);
1343 list->maximumTodoIndex = 0;
1344 list->notifiesSize = 0;
1345 list->notifies = nullptr;
1346
1347 }
1348 }
1349}
1350
1351QHash<QQmlAttachedPropertiesFunc, QObject *> *QQmlData::attachedProperties() const
1352{
1353 if (!extendedData) extendedData = new QQmlDataExtended;
1354 return &extendedData->attachedProperties;
1355}
1356
1358{
1363 else if (outerContext && outerContext->ownedObjects() == this)
1365
1366 QQmlAbstractBinding *binding = bindings;
1367 while (binding) {
1368 binding->setAddedToObject(false);
1369 binding = binding->nextBinding();
1370 }
1371 if (bindings && !bindings->ref.deref())
1372 delete bindings;
1373
1375
1377 deferredData.clear();
1378
1379 QQmlBoundSignal *signalHandler = signalHandlers;
1380 while (signalHandler) {
1381 if (signalHandler->isNotifying()) {
1382 // The object is being deleted during signal handler evaluation.
1383 // This will cause a crash due to invalid memory access when the
1384 // evaluation has completed.
1385 // Abort with a friendly message instead.
1386 QString locationString;
1387 QQmlBoundSignalExpression *expr = signalHandler->expression();
1388 if (expr) {
1390 if (location.sourceFile.isEmpty())
1391 location.sourceFile = QStringLiteral("<Unknown File>");
1392 locationString.append(location.sourceFile);
1393 locationString.append(QStringLiteral(":%0: ").arg(location.line));
1394 QString source = expr->expression();
1395 if (source.size() > 100) {
1396 source.truncate(96);
1397 source.append(QLatin1String(" ..."));
1398 }
1399 locationString.append(source);
1400 } else {
1401 locationString = QStringLiteral("<Unknown Location>");
1402 }
1403 qFatal("Object %p destroyed while one of its QML signal handlers is in progress.\n"
1404 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1405 "instead), or the application is running a nested event loop.\n"
1406 "This behavior is NOT supported!\n"
1407 "%s", object, qPrintable(locationString));
1408 }
1409
1410 QQmlBoundSignal *next = signalHandler->m_nextSignal;
1411 signalHandler->m_prevSignal = nullptr;
1412 signalHandler->m_nextSignal = nullptr;
1413 delete signalHandler;
1414 signalHandler = next;
1415 }
1416
1418 free(bindingBits);
1419
1420 if (propertyCache)
1422
1423 ownContext.reset();
1424
1425 while (guards) {
1426 auto *guard = guards;
1427 guard->setObject(nullptr);
1428 if (guard->objectDestroyed)
1429 guard->objectDestroyed(guard);
1430 }
1431
1433
1434 if (extendedData)
1435 delete extendedData;
1436
1437 // Dispose the handle.
1438 jsWrapper.clear();
1439
1440 if (ownMemory)
1441 delete this;
1442 else
1443 this->~QQmlData();
1444}
1445
1446QQmlData::BindingBitsType *QQmlData::growBits(QObject *obj, int bit)
1447{
1450 Q_ASSERT(bit < 2 * props);
1451 Q_UNUSED(bit); // .. for Q_NO_DEBUG mode when the assert above expands to empty
1452
1453 uint arraySize = (2 * static_cast<uint>(props) + BitsPerType - 1) / BitsPerType;
1454 Q_ASSERT(arraySize > 1);
1455 Q_ASSERT(arraySize <= 0xffff); // max for bindingBitsArraySize
1456
1457 BindingBitsType *newBits = static_cast<BindingBitsType *>(malloc(arraySize*sizeof(BindingBitsType)));
1458 memcpy(newBits, bits, bindingBitsArraySize * sizeof(BindingBitsType));
1459 memset(newBits + bindingBitsArraySize, 0, sizeof(BindingBitsType) * (arraySize - bindingBitsArraySize));
1460
1462 free(bits);
1463 bindingBits = newBits;
1464 bits = newBits;
1465 bindingBitsArraySize = arraySize;
1466 return bits;
1467}
1468
1469QQmlData *QQmlData::createQQmlData(QObjectPrivate *priv)
1470{
1471 Q_ASSERT(priv);
1472 Q_ASSERT(!priv->isDeletingChildren);
1473 priv->declarativeData = new QQmlData(OwnsMemory);
1474 return static_cast<QQmlData *>(priv->declarativeData);
1475}
1476
1477QQmlPropertyCache::ConstPtr QQmlData::createPropertyCache(QObject *object)
1478{
1479 QQmlData *ddata = QQmlData::get(object, /*create*/true);
1480 ddata->propertyCache = QQmlMetaType::propertyCache(object, QTypeRevision {});
1481 return ddata->propertyCache;
1482}
1483
1485{
1486 Q_Q(QQmlEngine);
1487 emit q->quit();
1488 if (q->receivers(SIGNAL(quit())) == 0) {
1489 qWarning("Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1490 }
1491}
1492
1494{
1495 Q_Q(QQmlEngine);
1496 if (q->receivers(SIGNAL(exit(int))) == 0)
1497 qWarning("Signal QQmlEngine::exit() emitted, but no receivers connected to handle it.");
1498 emit q->exit(retCode);
1499}
1500
1501static void dumpwarning(const QQmlError &error)
1502{
1503 switch (error.messageType()) {
1504 case QtDebugMsg:
1505 QMessageLogger(error.url().toString().toLatin1().constData(),
1506 error.line(), nullptr).debug().noquote().nospace()
1507 << error.toString();
1508 break;
1509 case QtInfoMsg:
1510 QMessageLogger(error.url().toString().toLatin1().constData(),
1511 error.line(), nullptr).info().noquote().nospace()
1512 << error.toString();
1513 break;
1514 case QtWarningMsg:
1515 case QtFatalMsg: // fatal does not support streaming, and furthermore, is actually fatal. Probably not desirable for QML.
1516 QMessageLogger(error.url().toString().toLatin1().constData(),
1517 error.line(), nullptr).warning().noquote().nospace()
1518 << error.toString();
1519 break;
1520 case QtCriticalMsg:
1521 QMessageLogger(error.url().toString().toLatin1().constData(),
1522 error.line(), nullptr).critical().noquote().nospace()
1523 << error.toString();
1524 break;
1525 }
1526}
1527
1528static void dumpwarning(const QList<QQmlError> &errors)
1529{
1530 for (int ii = 0; ii < errors.size(); ++ii)
1531 dumpwarning(errors.at(ii));
1532}
1533
1535{
1536 Q_Q(QQmlEngine);
1537 emit q->warnings(QList<QQmlError>({error}));
1538 if (outputWarningsToMsgLog)
1540}
1541
1542void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
1543{
1544 Q_Q(QQmlEngine);
1545 emit q->warnings(errors);
1546 if (outputWarningsToMsgLog)
1547 dumpwarning(errors);
1548}
1549
1551{
1552 if (engine)
1554 else
1556}
1557
1558void QQmlEnginePrivate::warning(QQmlEngine *engine, const QList<QQmlError> &error)
1559{
1560 if (engine)
1562 else
1564}
1565
1567{
1568 if (engine)
1569 engine->warning(error);
1570 else
1572}
1573
1575{
1576 if (engine)
1577 engine->warning(error);
1578 else
1580}
1581
1583 const QString &fileName, const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages)
1584{
1585 QList<QQmlError> errors;
1586 for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {
1587 if (m.isWarning()) {
1588 qWarning("%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message));
1589 continue;
1590 }
1591
1593 error.setUrl(QUrl(fileName));
1594 error.setDescription(m.message);
1595 error.setLine(qmlConvertSourceCoordinate<quint32, int>(m.loc.startLine));
1596 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(m.loc.startColumn));
1597 errors << error;
1598 }
1599 return errors;
1600}
1601
1602void QQmlEnginePrivate::cleanupScarceResources()
1603{
1604 // iterate through the list and release them all.
1605 // note that the actual SRD is owned by the JS engine,
1606 // so we cannot delete the SRD; but we can free the
1607 // memory used by the variant in the SRD.
1608 QV4::ExecutionEngine *engine = v4engine();
1609 while (QV4::ExecutionEngine::ScarceResourceData *sr = engine->scarceResources.first()) {
1610 sr->data = QVariant();
1611 engine->scarceResources.remove(sr);
1612 }
1613}
1614
1632{
1633 Q_D(QQmlEngine);
1634 d->importDatabase.addImportPath(path);
1635}
1636
1653{
1654 Q_D(const QQmlEngine);
1655 return d->importDatabase.importPathList();
1656}
1657
1671{
1672 Q_D(QQmlEngine);
1673 d->importDatabase.setImportPathList(paths);
1674}
1675
1676
1689{
1690 Q_D(QQmlEngine);
1691 d->importDatabase.addPluginPath(path);
1692}
1693
1704{
1705 Q_D(const QQmlEngine);
1706 return d->importDatabase.pluginPathList();
1707}
1708
1720{
1721 Q_D(QQmlEngine);
1722 d->importDatabase.setPluginPathList(paths);
1723}
1724
1725#if QT_CONFIG(library)
1726#if QT_DEPRECATED_SINCE(6, 4)
1741bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
1742{
1743 Q_D(QQmlEngine);
1745 QQmlPluginImporter importer(
1746 uri, QTypeRevision(), &d->importDatabase, &qmldir, &d->typeLoader, errors);
1747 return importer.importDynamicPlugin(filePath, uri, false).isValid();
1748}
1749#endif
1750#endif
1751
1778{
1779 Q_D(QQmlEngine);
1780 if (dir == d->offlineStoragePath)
1781 return;
1782 d->offlineStoragePath = dir;
1783 Q_EMIT offlineStoragePathChanged();
1784}
1785
1787{
1788 Q_D(const QQmlEngine);
1789
1790 if (d->offlineStoragePath.isEmpty()) {
1792 QQmlEnginePrivate *e = const_cast<QQmlEnginePrivate *>(d);
1793 if (!dataLocation.isEmpty()) {
1794 e->offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator())
1795 + QDir::separator() + QLatin1String("QML")
1796 + QDir::separator() + QLatin1String("OfflineStorage");
1797 Q_EMIT e->q_func()->offlineStoragePathChanged();
1798 }
1799 }
1800
1801 return d->offlineStoragePath;
1802}
1803
1812{
1813 Q_D(const QQmlEngine);
1815 md5.addData(databaseName.toUtf8());
1816 return d->offlineStorageDatabaseDirectory() + QLatin1String(md5.result().toHex());
1817}
1818
1820{
1821 Q_Q(const QQmlEngine);
1822 return q->offlineStoragePath() + QDir::separator() + QLatin1String("Databases") + QDir::separator();
1823}
1824
1825template<>
1826QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type)
1827{
1828 Q_Q(QQmlEngine);
1829
1830 QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
1831 Q_ASSERT(siinfo != nullptr);
1832
1833 QJSValue value = singletonInstances.value(siinfo);
1834 if (!value.isUndefined())
1835 return value;
1836
1837 if (siinfo->scriptCallback) {
1838 value = siinfo->scriptCallback(q, q);
1839 if (value.isQObject()) {
1840 QObject *o = value.toQObject();
1841 // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
1842 // should behave identically to QML singleton types.
1843 q->setContextForObject(o, new QQmlContext(q->rootContext(), q));
1844 }
1845 singletonInstances.convertAndInsert(v4engine(), siinfo, &value);
1846
1847 } else if (siinfo->qobjectCallback) {
1848 QObject *o = siinfo->qobjectCallback(q, q);
1849 if (!o) {
1851 error.setMessageType(QtMsgType::QtCriticalMsg);
1852 error.setDescription(QString::asprintf("qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.",
1853 qPrintable(QString::fromUtf8(type.typeName()))));
1854 warning(error);
1855 } else {
1856 type.createProxy(o);
1857
1858 // if this object can use a property cache, create it now
1860
1861 // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
1862 // should behave identically to QML singleton types. You can, however, manually
1863 // assign a context; and clearSingletons() retains the contexts, in which case
1864 // we don't want to see warnings about the object already having a context.
1865 QQmlData *data = QQmlData::get(o, true);
1866 if (!data->context) {
1867 auto contextData = QQmlContextData::get(new QQmlContext(q->rootContext(), q));
1868 data->context = contextData.data();
1869 contextData->addOwnedObject(data);
1870 }
1871 }
1872
1873 value = q->newQObject(o);
1874 singletonInstances.convertAndInsert(v4engine(), siinfo, &value);
1875 } else if (!siinfo->url.isEmpty()) {
1877 if (component.isError()) {
1878 warning(component.errors());
1879 v4engine()->throwError(QLatin1String("Due to the preceding error(s), Singleton \"%1\" could not be loaded.").arg(QString::fromUtf8(type.typeName())));
1880
1882 }
1883 QObject *o = component.beginCreate(q->rootContext());
1884 value = q->newQObject(o);
1885 singletonInstances.convertAndInsert(v4engine(), siinfo, &value);
1886 component.completeCreate();
1887 }
1888
1889 return value;
1890}
1891
1893{
1894 return typeLoader.isTypeLoaded(url);
1895}
1896
1898{
1899 return typeLoader.isScriptLoaded(url);
1900}
1901
1903 QObject *thisObject, int argc, void **args,
1905{
1906 const auto unit = compilationUnitFromUrl(url);
1907 if (!unit)
1908 return;
1909 executeRuntimeFunction(unit, functionIndex, thisObject, argc, args, types);
1910}
1911
1913 qsizetype functionIndex, QObject *thisObject,
1914 int argc, void **args, QMetaType *types)
1915{
1916 Q_ASSERT(unit);
1917 Q_ASSERT((functionIndex >= 0) && (functionIndex < unit->runtimeFunctions.size()));
1918 Q_ASSERT(thisObject);
1919
1920 QQmlData *ddata = QQmlData::get(thisObject);
1921 Q_ASSERT(ddata && ddata->outerContext);
1922
1923 QV4::Function *function = unit->runtimeFunctions[functionIndex];
1924 Q_ASSERT(function);
1925 Q_ASSERT(function->compiledFunction);
1926
1927 QV4::ExecutionEngine *v4 = v4engine();
1928
1929 // NB: always use scriptContext() by default as this method ignores whether
1930 // there's already a stack frame (except when dealing with closures). the
1931 // method is called from C++ (through QQmlEngine::executeRuntimeFunction())
1932 // and thus the caller must ensure correct setup
1933 QV4::Scope scope(v4);
1935 QV4::Scoped<QV4::ExecutionContext> callContext(scope,
1936 QV4::QmlContext::create(ctx, ddata->outerContext, thisObject));
1937
1938 if (auto nested = function->nestedFunction()) {
1939 // if a nested function is already known, call the closure directly
1940 function = nested;
1941 } else if (function->isClosureWrapper()) {
1942 // if there is a nested function, but we don't know it, we need to call
1943 // an outer function first and then the inner function. we fetch the
1944 // return value of a function call (that is a closure) by calling a
1945 // different version of ExecutionEngine::callInContext() that returns a
1946 // QV4::ReturnedValue with no arguments since they are not needed by the
1947 // outer function anyhow
1949 v4->callInContext(function, thisObject, callContext, 0, nullptr));
1950 Q_ASSERT(result->function());
1951 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
1952
1953 // overwrite the function and its context
1954 function = result->function();
1955 callContext = QV4::Scoped<QV4::ExecutionContext>(scope, result->scope());
1956 }
1957
1958 v4->callInContext(function, thisObject, callContext, argc, args, types);
1959}
1960
1962{
1963 QV4::ExecutionEngine *v4 = v4engine();
1964 if (auto unit = v4->compilationUnitForUrl(url)) {
1965 if (!unit->runtimeStrings)
1966 unit->populate();
1967 return unit.data();
1968 }
1969
1970 auto unit = typeLoader.getType(url)->compilationUnit();
1971 if (!unit)
1972 return nullptr;
1973
1974 auto executable = v4->executableCompilationUnit(std::move(unit));
1975 executable->populate();
1976 return executable.data();
1977}
1978
1979QQmlRefPointer<QQmlContextData>
1980QQmlEnginePrivate::createInternalContext(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
1981 const QQmlRefPointer<QQmlContextData> &parentContext,
1982 int subComponentIndex, bool isComponentRoot)
1983{
1984 Q_ASSERT(unit);
1985
1986 QQmlRefPointer<QQmlContextData> context;
1988 context->setInternal(true);
1989 context->setImports(unit->typeNameCache());
1990 context->initFromTypeCompilationUnit(unit, subComponentIndex);
1991
1992 const auto *dependentScripts = unit->dependentScriptsPtr();
1993 const qsizetype dependentScriptsSize = dependentScripts->size();
1994 if (isComponentRoot && dependentScriptsSize) {
1995 QV4::ExecutionEngine *v4 = v4engine();
1996 Q_ASSERT(v4);
1997 QV4::Scope scope(v4);
1998
1999 QV4::ScopedObject scripts(scope, v4->newArrayObject(dependentScriptsSize));
2001 QV4::ScopedValue v(scope);
2002 for (qsizetype i = 0; i < dependentScriptsSize; ++i)
2003 scripts->put(i, (v = dependentScripts->at(i)->scriptValueForContext(context)));
2004 }
2005
2006 return context;
2007}
2008
2009#if defined(Q_OS_WIN)
2010// Normalize a file name using Shell API. As opposed to converting it
2011// to a short 8.3 name and back, this also works for drives where 8.3 notation
2012// is disabled (see 8dot3name options of fsutil.exe).
2013static inline QString shellNormalizeFileName(const QString &name)
2014{
2015 const QString nativeSeparatorName(QDir::toNativeSeparators(name));
2016 const LPCTSTR nameC = reinterpret_cast<LPCTSTR>(nativeSeparatorName.utf16());
2017// The correct declaration of the SHGetPathFromIDList symbol is
2018// being used in mingw-w64 as of r6215, which is a v3 snapshot.
2019#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
2020 ITEMIDLIST *file;
2021 if (FAILED(SHParseDisplayName(nameC, NULL, reinterpret_cast<LPITEMIDLIST>(&file), 0, NULL)))
2022 return name;
2023#else
2024 PIDLIST_ABSOLUTE file;
2025 if (FAILED(SHParseDisplayName(nameC, NULL, &file, 0, NULL)))
2026 return name;
2027#endif
2028 TCHAR buffer[MAX_PATH];
2029 bool gotPath = SHGetPathFromIDList(file, buffer);
2030 ILFree(file);
2031
2032 if (!gotPath)
2033 return name;
2034
2035 QString canonicalName = QString::fromWCharArray(buffer);
2036 // Upper case drive letter
2037 if (canonicalName.size() > 2 && canonicalName.at(1) == QLatin1Char(':'))
2038 canonicalName[0] = canonicalName.at(0).toUpper();
2039 return QDir::cleanPath(canonicalName);
2040}
2041#endif // Q_OS_WIN
2042
2043bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn /* = -1 */)
2044{
2045#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
2047 const QString absolute = info.absoluteFilePath();
2048
2049#if defined(Q_OS_DARWIN)
2050 const QString canonical = info.canonicalFilePath();
2051#elif defined(Q_OS_WIN)
2052 // No difference if the path is qrc based
2053 if (absolute[0] == QLatin1Char(':'))
2054 return true;
2055 const QString canonical = shellNormalizeFileName(absolute);
2056#endif
2057
2058 const int absoluteLength = absolute.length();
2059 const int canonicalLength = canonical.length();
2060
2061 int length = qMin(absoluteLength, canonicalLength);
2062 if (lengthIn >= 0) {
2063 length = qMin(lengthIn, length);
2064 } else {
2065 // No length given: Limit to file name. Do not trigger
2066 // on drive letters or folder names.
2067 int lastSlash = absolute.lastIndexOf(QLatin1Char('/'));
2068 if (lastSlash < 0)
2069 lastSlash = absolute.lastIndexOf(QLatin1Char('\\'));
2070 if (lastSlash >= 0) {
2071 const int fileNameLength = absoluteLength - 1 - lastSlash;
2072 length = qMin(length, fileNameLength);
2073 }
2074 }
2075
2076 for (int ii = 0; ii < length; ++ii) {
2077 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2078 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2079
2080 if (a.toLower() != c.toLower())
2081 return true;
2082 if (a != c)
2083 return false;
2084 }
2085#else
2086 Q_UNUSED(lengthIn);
2088#endif
2089 return true;
2090}
2091
2117
2119 : QQmlTypeLoader::Blob({}, QQmlDataBlob::QmlFile, loader)
2120 , m_uri(uri.toString())
2121
2122{
2123 auto import = std::make_shared<PendingImport>();
2124 import->uri = m_uri;
2125 QList<QQmlError> errorList;
2126 if (!Blob::addImport(import, &errorList)) {
2127 qCDebug(lcQmlImport) << "LoadHelper: Errors loading " << m_uri << errorList;
2128 m_uri.clear(); // reset m_uri to remember the failure
2129 }
2130}
2131
2133{
2134 QQmlType type;
2135 if (!couldFindModule())
2137 QQmlTypeModule *module = QQmlMetaType::typeModule(m_uri, QTypeRevision{});
2138 if (module) {
2139 type = module->type(typeName.toString(), {});
2140 if (type.isValid())
2142 }
2143 // The module exists (see check above), but there is no QQmlTypeModule
2144 // ==> pure QML module, attempt resolveType
2145 QTypeRevision versionReturn;
2146 QList<QQmlError> errors;
2147 QQmlImportNamespace *ns_return = nullptr;
2149 typeLoader(), typeName.toString(), &type, &versionReturn, &ns_return, &errors);
2151}
2152
2153bool LoadHelper::couldFindModule() const
2154{
2155 if (m_uri.isEmpty())
2156 return false;
2157 for (const auto &import: std::as_const(m_unresolvedImports))
2158 if (import->priority == 0) // compare QQmlTypeData::allDependenciesDone
2159 return false;
2160 return true;
2161}
2162
2164
2165#include "moc_qqmlengine.cpp"
static bool(* isSignalConnected)(QAbstractDeclarativeData *, const QObject *, int)
Definition qobject_p.h:69
static int(* receivers)(QAbstractDeclarativeData *, const QObject *, int)
Definition qobject_p.h:68
static void(* destroyed)(QAbstractDeclarativeData *, QObject *)
Definition qobject_p.h:66
static void(* signalEmitted)(QAbstractDeclarativeData *, QObject *, int, void **)
Definition qobject_p.h:67
\inmodule QtCore
\inmodule QtCore
Definition qbytearray.h:57
QByteArray toHex(char separator='\0') const
Returns a hex encoded copy of the byte array.
\inmodule QtCore
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
void addData(QByteArrayView data) noexcept
Adds the characters in bytes to the cryptographic hash.
QByteArray result() const
Returns the final hash value.
static QChar separator()
Returns the native directory separator: "/" under Unix and "\\" under Windows.
Definition qdir.h:209
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
Definition qdir.cpp:2398
static QString toNativeSeparators(const QString &pathName)
Definition qdir.cpp:929
static QString currentPath()
Returns the absolute path of the application's current directory.
Definition qdir.cpp:2054
static QString rootPath()
Returns the absolute path of the root directory.
Definition qdir.cpp:2159
\inmodule QtCore
Definition qcoreevent.h:45
@ LanguageChange
Definition qcoreevent.h:123
Type type() const
Returns the event type.
Definition qcoreevent.h:304
T value(const Key &key) const noexcept
Definition qhash.h:1054
static void addToDebugServer(QJSEngine *q)
static void removeFromDebugServer(QJSEngine *q)
The QJSEngine class provides an environment for evaluating JavaScript code.
Definition qjsengine.h:26
QV4::ExecutionEngine * handle() const
Definition qjsengine.h:298
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
@ UndefinedValue
Definition qjsvalue.h:35
\inmodule QtCore
Definition qlogging.h:72
void void Q_DECL_COLD_FUNCTION void warning(const char *msg,...) const Q_ATTRIBUTE_FORMAT_PRINTF(2
Logs a warning message specified with format msg.
Definition qlogging.cpp:625
void void Q_DECL_COLD_FUNCTION void Q_DECL_COLD_FUNCTION void critical(const char *msg,...) const Q_ATTRIBUTE_FORMAT_PRINTF(2
Logs a critical message specified with format msg.
Definition qlogging.cpp:727
void void void info(const QLoggingCategory &cat, const char *msg,...) const Q_ATTRIBUTE_FORMAT_PRINTF(3
Logs an informational message specified with format msg for the context cat.
Definition qlogging.cpp:536
void debug(const char *msg,...) const Q_ATTRIBUTE_FORMAT_PRINTF(2
Logs a debug message specified with format msg.
Definition qlogging.cpp:389
\inmodule QtCore
Definition qmetaobject.h:19
\inmodule QtCore
\inmodule QtCore
Definition qmetatype.h:341
static QMetaType fromName(QByteArrayView name)
Returns a QMetaType matching typeName.
\inmodule QtCore
Definition qmutex.h:313
The QNetworkAccessManager class allows the application to send network requests and receive replies.
QObject * parent
Definition qobject.h:73
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:150
\inmodule QtCore
Definition qobject.h:103
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition qobject.cpp:1389
bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL)
Changes the thread affinity for this object and its children and returns true on success.
Definition qobject.cpp:1643
QQmlAbstractBinding * nextBinding() const
virtual void setEnabled(bool e, QQmlPropertyData::WriteFlags f=QQmlPropertyData::DontRemoveBinding)=0
DataType
Specifies where URL interception is taking place.
QQmlBoundSignalExpression * expression() const
Returns the signal expression.
The QQmlComponent class encapsulates a QML component definition.
void setOwnedObjects(QQmlData *ownedObjects)
void setInternal(bool isInternal)
static QQmlRefPointer< QQmlContextData > get(QQmlContext *context)
QQmlData * ownedObjects() const
void initFromTypeCompilationUnit(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &unit, int subComponentIndex)
void setImportedScripts(const QV4::PersistentValue &scripts)
void setImports(const QQmlRefPointer< QQmlTypeNameCache > &imports)
static QQmlRefPointer< QQmlContextData > createRefCounted(const QQmlRefPointer< QQmlContextData > &parent)
static QQmlContextPrivate * get(QQmlContext *context)
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
QList< QQmlError > errors() const
Return the errors on this blob.
QQmlTypeLoader * typeLoader() const
Type type() const
Returns the type provided to the constructor.
QHash< QQmlAttachedPropertiesFunc, QObject * > attachedProperties
static void init()
Definition qqmldata_p.h:63
QHash< QQmlAttachedPropertiesFunc, QObject * > * attachedProperties() const
static void flushPendingBinding(QObject *object, int coreIndex)
Definition qqmldata_p.h:413
static void markAsDeleted(QObject *)
QV4::WeakValue jsWrapper
Definition qqmldata_p.h:193
static QQmlPropertyCache::ConstPtr ensurePropertyCache(QObject *object)
Definition qqmldata_p.h:252
QVector< DeferredData * > deferredData
Definition qqmldata_p.h:187
QQmlRefPointer< QV4::ExecutableCompilationUnit > compilationUnit
Definition qqmldata_p.h:186
void addNotify(int index, QQmlNotifierEndpoint *)
QQmlPropertyCache::ConstPtr propertyCache
Definition qqmldata_p.h:195
QQmlData(Ownership ownership)
bool signalHasEndpoint(int index) const
Definition qqmldata_p.h:352
QQmlRefPointer< QQmlContextData > ownContext
Definition qqmldata_p.h:150
void releaseDeferredData()
BindingBitsType bindingBitsValue[InlineBindingArraySize]
Definition qqmldata_p.h:123
static void destroyed(QAbstractDeclarativeData *, QObject *)
void disconnectNotifiers(DeleteNotifyList doDelete)
QQmlBoundSignal * signalHandlers
Definition qqmldata_p.h:153
QQmlContextData * context
Definition qqmldata_p.h:147
QQmlData ** prevContextObject
Definition qqmldata_p.h:158
BindingBitsType * bindingBits
Definition qqmldata_p.h:122
quint32 bindingBitsArraySize
Definition qqmldata_p.h:115
QAtomicPointer< NotifyList > notifyList
Definition qqmldata_p.h:136
void clearPendingBindingBit(int)
Definition qqmldata_p.h:406
static QQmlData * get(QObjectPrivate *priv, bool create)
Definition qqmldata_p.h:199
void deferData(int objectIndex, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &, const QQmlRefPointer< QQmlContextData > &)
int endpointCount(int index)
QQmlGuardImpl * guards
Definition qqmldata_p.h:197
quint32 ownMemory
Definition qqmldata_p.h:87
QQmlData * nextContextObject
Definition qqmldata_p.h:157
static void setQueuedForDeletion(QObject *)
@ InlineBindingArraySize
Definition qqmldata_p.h:119
quintptr BindingBitsType
Definition qqmldata_p.h:116
QQmlNotifierEndpoint * notify(int index) const
Definition qqmldata_p.h:326
QQmlContextData * outerContext
Definition qqmldata_p.h:149
QQmlAbstractBinding * bindings
Definition qqmldata_p.h:152
static void activateDesignerMode()
QHash< QString, QSharedPointer< QQmlImageProviderBase > > imageProviders
QMutex networkAccessManagerMutex
QSharedPointer< QQmlImageProviderBase > imageProvider(const QString &providerId) const
QV4::ExecutableCompilationUnit * compilationUnitFromUrl(const QUrl &url)
void sendExit(int retCode=0)
void warning(const QQmlError &)
void executeRuntimeFunction(const QUrl &url, qsizetype functionIndex, QObject *thisObject, int argc=0, void **args=nullptr, QMetaType *types=nullptr)
static bool baseModulesUninitialized
static std::atomic< bool > qml_debugging_enabled
\qmltype QtObject \instantiates QObject \inqmlmodule QtQml
static QList< QQmlError > qmlErrorFromDiagnostics(const QString &fileName, const QList< QQmlJS::DiagnosticMessage > &diagnosticMessages)
~QQmlEnginePrivate() override
bool isTypeLoaded(const QUrl &url) const
static QQmlEnginePrivate * get(QQmlEngine *e)
QQmlContext * rootContext
QString offlineStorageDatabaseDirectory() const
bool isScriptLoaded(const QUrl &url) const
QQmlIncubationController * incubationController
static const quintptr profiler
QString offlineStoragePath
QRecursiveMutex imageProviderMutex
static bool designerMode()
QQmlRefPointer< QQmlContextData > createInternalContext(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &unit, const QQmlRefPointer< QQmlContextData > &parentContext, int subComponentIndex, bool isComponentRoot)
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
static QQmlContext * contextForObject(const QObject *)
Returns the QQmlContext for the object, or nullptr if no context has been set.
void addPluginPath(const QString &dir)
Adds path as a directory where the engine searches for native plugins for imported modules (reference...
void removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
Remove a urlInterceptor that was previously added using \l addUrlInterceptor.
QQmlEngine(QObject *p=nullptr)
Create a new QQmlEngine with the given parent.
void setImportPathList(const QStringList &paths)
Sets paths as the list of directories where the engine searches for installed modules in a URL-based ...
QStringList importPathList() const
Returns the list of directories where the engine searches for installed modules in a URL-based direct...
QList< QQmlAbstractUrlInterceptor * > urlInterceptors() const
Returns the list of currently active URL interceptors.
bool outputWarningsToStandardError() const
Returns true if warning messages will be output to stderr in addition to being emitted by the warning...
static void setContextForObject(QObject *, QQmlContext *)
Sets the QQmlContext for the object to context.
void addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
Adds a urlInterceptor to be used when resolving URLs in QML.
void setOfflineStoragePath(const QString &dir)
QQmlImageProviderBase * imageProvider(const QString &id) const
Returns the image provider set for providerId if found; otherwise returns \nullptr.
QQmlContext * rootContext() const
Returns the engine's root context.
QUrl baseUrl() const
Return the base URL for this engine.
void captureProperty(QObject *object, const QMetaProperty &property) const
QString offlineStoragePath
the directory for storing offline user data
Definition qqmlengine.h:58
bool event(QEvent *) override
\reimp
void setOutputWarningsToStandardError(bool)
Set whether warning messages will be output to stderr to enabled.
void trimComponentCache()
Trims the engine's internal component cache.
QStringList pluginPathList() const
Returns the list of directories where the engine searches for native plugins for imported modules (re...
void setPluginPathList(const QStringList &paths)
Sets the list of directories where the engine searches for native plugins for imported modules (refer...
void clearSingletons()
Clears all singletons the engine owns.
void setBaseUrl(const QUrl &)
Set the base URL for this engine to url.
void addImportPath(const QString &dir)
Adds path as a directory where the engine searches for installed modules in a URL-based directory str...
void markCurrentFunctionAsTranslationBinding()
QString offlineStorageDatabaseFilePath(const QString &databaseName) const
Returns the file path where a \l{QtQuick.LocalStorage}{Local Storage} database with the identifier da...
void clearComponentCache()
Clears the engine's internal component cache.
void addImageProvider(const QString &id, QQmlImageProviderBase *)
Sets the provider to use for images requested via the image: url scheme, with host providerId.
QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const
Run the current URL interceptors on the given url of the given type and return the result.
void retranslate()
Refreshes all binding expressions that use strings marked for translation.
~QQmlEngine() override
Destroys the QQmlEngine.
void removeImageProvider(const QString &id)
Removes the image provider for providerId.
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
void setObject(QObject *g)
The QQmlImageProviderBase class is used to register image providers in the QML engine.
Definition qqmlengine.h:18
virtual ~QQmlImageProviderBase()
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type, QQmlType *type_return, QTypeRevision *version_return, QQmlImportNamespace **ns_return, QList< QQmlError > *errors=nullptr, QQmlType::RegistrationType registrationType=QQmlType::AnyRegistrationType, bool *typeRecursionDetected=nullptr) const
virtual QQmlSourceLocation sourceLocation() const
int propertyCount() const
static QQmlType qmlTypeById(int qmlTypeId)
Returns the type (if any) that corresponds to qmlTypeId.
static QQmlPropertyCache::ConstPtr propertyCache(QObject *object, QTypeRevision version=QTypeRevision())
Returns a QQmlPropertyCache for obj if one is available.
static void freeUnusedTypesAndCaches()
bool isNotifying() const
Returns true if a notify is in progress.
void reset(T *t=nullptr)
int qt_metacall(QMetaObject::Call, int methodIndex, void **a) override
QPointer< QObject > target
QVector< PendingImportPtr > m_unresolvedImports
QQmlRefPointer< QQmlImports > m_importCache
The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
static QString writableLocation(StandardLocation type)
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:296
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3824
void truncate(qsizetype pos)
Truncates the string at the given position index.
Definition qstring.cpp:6319
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1226
QString toLower() const &
Definition qstring.h:435
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
Definition qstring.h:1309
QByteArray toUtf8() const &
Definition qstring.h:634
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Definition qstring.cpp:7263
qsizetype length() const noexcept
Returns the number of characters in this string.
Definition qstring.h:191
static Qt::HANDLE currentThreadId() noexcept Q_DECL_PURE_FUNCTION
Definition qthread.h:149
\inmodule QtCore
static constexpr QTypeRevision fromVersion(Major majorVersion, Minor minorVersion)
Produces a QTypeRevision from the given majorVersion and minorVersion, both of which need to be a val...
static constexpr QTypeRevision zero()
Produces a QTypeRevision with major and minor version {0}.
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3368
const CompiledObject * objectAt(int index) const
const CompiledData::BindingPropertyData * bindingPropertyDataPerObjectAt(qsizetype objectIndex) const
std::unique_ptr< GCStateMachine > gcStateMachine
Definition qv4mm_p.h:414
void setGCTimeLimit(int timeMs)
Definition qv4mm.cpp:1108
\inmodule QtCore
Definition qvariant.h:65
EGLContext ctx
#define this
Definition dialogs.cpp:9
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
auto signalIndex
short next
Definition keywords.cpp:445
void Q_QML_EXPORT qdeclarativeelement_destructor(QObject *)
int Q_QML_EXPORT qmlregister(RegistrationType, void *)
Definition qqml.cpp:771
Combined button and popup list for selecting options.
QVector< const QQmlPropertyData * > BindingPropertyData
static void * context
DBusConnection const char DBusError * error
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
@ QtCriticalMsg
Definition qlogging.h:32
@ QtInfoMsg
Definition qlogging.h:34
@ QtWarningMsg
Definition qlogging.h:31
@ QtFatalMsg
Definition qlogging.h:33
@ QtDebugMsg
Definition qlogging.h:30
#define qWarning
Definition qlogging.h:166
#define qFatal
Definition qlogging.h:168
#define qCDebug(category,...)
static const QMetaObjectPrivate * priv(const uint *data)
const char * typeName
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLint location
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLsizei GLenum GLenum * types
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLuint object
[3]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLenum GLuint buffer
GLenum type
GLsizei const GLuint * paths
GLenum target
GLenum GLuint GLsizei const GLenum * props
GLuint name
GLsizei GLsizei GLchar * source
GLhandleARB obj
[2]
const GLubyte * c
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
static qreal component(const QPointF &point, unsigned int i)
bool qmlProtectModule(const char *uri, int majVersion)
Definition qqml.cpp:238
int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
Definition qqml.cpp:357
QT_BEGIN_NAMESPACE void qml_register_types_QML()
static void dumpwarning(const QQmlError &error)
void hasJsOwnershipIndicator(QQmlGuardImpl *)
bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn)
Returns true if the case of fileName is equivalent to the file case of fileName on disk,...
int qmlRegisterType< void >(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
const QLoggingCategory & lcQmlImport()
QDebug warning(QAnyStringView fileName, int lineNumber)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define MAX_PATH
SSL_CTX int void * arg
#define qPrintable(string)
Definition qstring.h:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define sp
#define Q_EMIT
#define emit
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
unsigned long long quint64
Definition qtypes.h:61
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
#define enabled
const char property[13]
Definition qwizard.cpp:101
QList< int > list
[14]
if(qFloatDistance(a, b)<(1<< 7))
[0]
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
QVBoxLayout * layout
QString dir
[11]
QItemEditorFactory * factory
QLayoutItem * child
[0]
QHostInfo info
[0]
QJSValueList args
QJSEngine engine
[0]
LoadHelper(QQmlTypeLoader *loader, QAnyStringView uri)
ResolveTypeResult resolveType(QAnyStringView typeName)
\inmodule QtCore \reentrant
Definition qchar.h:18
static Q_CORE_EXPORT QMetaMethod signal(const QMetaObject *m, int signal_index)
static Q_CORE_EXPORT int signalIndex(const QMetaMethod &m)
unsigned int deferredIdx
Definition qqmldata_p.h:176
QQmlNotifierEndpoint ** notifies
Definition qqmldata_p.h:129
bool hasFlag(Flag flag) const
const Binding * bindingTable() const
MemoryManager * memoryManager
QQmlRefPointer< ExecutableCompilationUnit > compilationUnitForUrl(const QUrl &url) const
ExecutionContext * scriptContext() const
Heap::ArrayObject * newArrayObject(int count=0)
QQmlRefPointer< ExecutableCompilationUnit > executableCompilationUnit(QQmlRefPointer< QV4::CompiledData::CompilationUnit > &&unit)
void callInContext(QV4::Function *function, QObject *self, QV4::ExecutionContext *ctxt, int argc, void **args, QMetaType *types)
bool put(StringOrSymbol *name, const Value &v, Value *receiver=nullptr)
static Heap::QmlContext * create(QV4::ExecutionContext *parent, QQmlRefPointer< QQmlContextData > context, QObject *scopeObject)
QML_NEARLY_ALWAYS_INLINE ReturnedValue asReturnedValue() const