7#include <private/qqmlabstractbinding_p.h>
8#include <private/qqmlboundsignal_p.h>
9#include <private/qqmlcontext_p.h>
10#include <private/qqmlnotifier_p.h>
11#include <private/qqmlpluginimporter_p.h>
12#include <private/qqmlprofiler_p.h>
13#include <private/qqmlscriptdata_p.h>
14#include <private/qqmlsourcecoordinate_p.h>
15#include <private/qqmltype_p.h>
16#include <private/qqmltypedata_p.h>
17#include <private/qqmlvmemetaobject_p.h>
18#include <private/qqmlcomponent_p.h>
20#include <private/qobject_p.h>
21#include <private/qthread_p.h>
23#include <QtQml/qqml.h>
24#include <QtQml/qqmlcomponent.h>
25#include <QtQml/qqmlcontext.h>
26#include <QtQml/qqmlincubator.h>
27#include <QtQml/qqmlscriptstring.h>
29#include <QtCore/qcoreapplication.h>
30#include <QtCore/qcryptographichash.h>
31#include <QtCore/qdir.h>
32#include <QtCore/qdiriterator.h>
33#include <QtCore/qmetaobject.h>
34#include <QtCore/qmutex.h>
35#include <QtCore/qstandardpaths.h>
36#include <QtCore/qstorageinfo.h>
37#include <QtCore/qthread.h>
39#if QT_CONFIG(qml_network)
40#include <QtQml/qqmlnetworkaccessmanagerfactory.h>
41#include <QtNetwork/qnetworkaccessmanager.h>
45# include <qt_windows.h>
47# include <QtCore/qlibrary.h>
49# define CSIDL_APPDATA 0x001a
59using namespace Qt::StringLiterals;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
119Q_CONSTINIT std::atomic<
bool> QQmlEnginePrivate::qml_debugging_enabled{
false};
120bool QQmlEnginePrivate::s_designerMode =
false;
122bool QQmlEnginePrivate::designerMode()
124 return s_designerMode;
127void QQmlEnginePrivate::activateDesignerMode()
129 s_designerMode =
true;
134
135
136
137
138
139
140
141
142
143
144
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
165
166
167
168
169
170
171
172
175
176
177
178
181
182
183
184
187QQmlImageProviderBase::QQmlImageProviderBase()
192QQmlImageProviderBase::~QQmlImageProviderBase()
196QQmlEnginePrivate::~QQmlEnginePrivate()
198 if (inProgressCreations)
199 qWarning() << QQmlEngine::tr(
"There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
201 if (incubationController) incubationController->d =
nullptr;
202 incubationController =
nullptr;
204#if QT_CONFIG(qml_debug)
209void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
211 QObjectPrivate *p = QObjectPrivate::get(o);
212 if (QQmlData *d = QQmlData::get(p)) {
213 const auto invalidate = [](QQmlContextData *c) {c->invalidate();};
215 d->ownContext->deepClearContextObject(o, invalidate, invalidate);
216 d->ownContext.reset();
217 d->context =
nullptr;
218 Q_ASSERT(!d->outerContext || d->outerContext->contextObject() != o);
219 }
else if (d->outerContext && d->outerContext->contextObject() == o) {
220 d->outerContext->deepClearContextObject(o, invalidate, invalidate);
223 if (d->hasVMEMetaObject || d->hasInterceptorMetaObject) {
236 static_cast<QQmlInterceptorMetaObject *>(p->metaObject)->invalidate();
237 d->hasVMEMetaObject = d->hasInterceptorMetaObject =
false;
242 QQmlData::markAsDeleted(o);
246QQmlData::QQmlData(Ownership ownership)
247 : ownMemory(ownership == OwnsMemory), indestructible(
true), explicitIndestructibleSet(
false),
248 hasTaintedV4Object(
false), isQueuedForDeletion(
false), rootObjectInCreation(
false),
249 hasInterceptorMetaObject(
false), hasVMEMetaObject(
false), hasConstWrapper(
false), dummy(0),
250 bindingBitsArraySize(InlineBindingArraySize)
252 memset(bindingBitsValue, 0,
sizeof(bindingBitsValue));
260void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
262 QQmlData *ddata =
static_cast<QQmlData *>(d);
276 QMetaMethod method = target->metaObject()->method(methodIndex);
277 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
278 int signalIndex = QMetaObjectPrivate::signalIndex(method);
279 QQmlData *ddata = QQmlData::get(target,
false);
280 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
281 if (ep) QQmlNotifier::emitNotify(ep, a);
289void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object,
int index,
void **a)
291 QQmlData *ddata = QQmlData::get(object,
false);
303 if (!ddata->notifyList.loadRelaxed())
306 auto objectThreadData = QObjectPrivate::get(object)->threadData.loadRelaxed();
307 if (QThread::currentThreadId() != objectThreadData->threadId.loadRelaxed()) {
308 if (!objectThreadData->thread.loadAcquire())
311 QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
312 QList<QByteArray> parameterTypes = m.parameterTypes();
314 QVarLengthArray<
const QtPrivate::QMetaTypeInterface *, 16> argTypes;
315 argTypes.reserve(1 + parameterTypes.size());
316 argTypes.emplace_back(
nullptr);
317 for (
const QByteArray &typeName: parameterTypes) {
319 if (typeName.endsWith(
'*'))
320 type = QMetaType(QMetaType::VoidStar);
322 type = QMetaType::fromName(typeName);
324 if (!type.isValid()) {
325 qWarning(
"QObject::connect: Cannot queue arguments of type '%s'\n"
326 "(Make sure '%s' is registered using qRegisterMetaType().)",
327 typeName.constData(), typeName.constData());
331 argTypes.emplace_back(type.iface());
334 auto ev = std::make_unique<QQueuedMetaCallEvent>(m.methodIndex(), 0,
nullptr, object, index,
335 argTypes.size(), argTypes.data(), a);
337 QQmlThreadNotifierProxyObject *mpo =
new QQmlThreadNotifierProxyObject;
338 mpo->target = object;
339 mpo->moveToThread(objectThreadData->thread.loadAcquire());
340 QCoreApplication::postEvent(mpo, ev.release());
343 QQmlNotifierEndpoint *ep = ddata->notify(index);
344 if (ep) QQmlNotifier::emitNotify(ep, a);
348int QQmlData::receivers(QAbstractDeclarativeData *d,
const QObject *,
int index)
350 QQmlData *ddata =
static_cast<QQmlData *>(d);
351 return ddata->endpointCount(index);
354bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d,
const QObject *,
int index)
356 QQmlData *ddata =
static_cast<QQmlData *>(d);
357 return ddata->signalHasEndpoint(index);
360int QQmlData::endpointCount(
int index)
363 QQmlNotifierEndpoint *ep = notify(index);
374void QQmlData::markAsDeleted(QObject *o)
376 QVarLengthArray<QObject *> workStack;
377 workStack.push_back(o);
378 while (!workStack.isEmpty()) {
379 auto currentObject = workStack.last();
380 workStack.pop_back();
381 QQmlData::setQueuedForDeletion(currentObject);
382 auto currentObjectPriv = QObjectPrivate::get(currentObject);
383 for (QObject *child: std::as_const(currentObjectPriv->children))
384 workStack.push_back(child);
388void QQmlData::setQueuedForDeletion(QObject *object)
391 if (QQmlData *ddata = QQmlData::get(object)) {
392 if (ddata->ownContext) {
393 Q_ASSERT(ddata->ownContext.data() == ddata->context);
394 ddata->ownContext->deepClearContextObject(object);
395 ddata->ownContext.reset();
396 ddata->context =
nullptr;
398 ddata->isQueuedForDeletion =
true;
405 ddata->disconnectNotifiers(DeleteNotifyList::No);
410void QQmlData::flushPendingBinding(
int coreIndex)
412 clearPendingBindingBit(coreIndex);
415 QQmlAbstractBinding *b = bindings;
416 while (b && (b->targetPropertyIndex().coreIndex() != coreIndex ||
417 b->targetPropertyIndex().hasValueTypeIndex()))
418 b = b->nextBinding();
420 if (b && b->targetPropertyIndex().coreIndex() == coreIndex &&
421 !b->targetPropertyIndex().hasValueTypeIndex())
422 b->setEnabled(
true, QQmlPropertyData::BypassInterceptor |
423 QQmlPropertyData::DontRemoveBinding);
426QQmlData::DeferredData::DeferredData() =
default;
427QQmlData::DeferredData::~DeferredData() =
default;
430int qmlRegisterType<
void>(
const char *uri,
int versionMajor,
int versionMinor,
const char *qmlName)
432 QQmlPrivate::RegisterType type = {
433 QQmlPrivate::RegisterType::CurrentVersion,
440 QTypeRevision::fromVersion(versionMajor, versionMinor),
451 QTypeRevision::zero(),
453 QQmlPrivate::ValueTypeCreationMethod::None,
456 return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
459bool QQmlEnginePrivate::baseModulesUninitialized =
true;
460void QQmlEnginePrivate::init()
464 if (baseModulesUninitialized) {
466 qml_register_types_QML();
469 static_assert(std::is_same_v<QStringList, QList<QString>>);
470 static_assert(std::is_same_v<QVariantList, QList<QVariant>>);
472 qRegisterMetaType<QQmlScriptString>();
473 qRegisterMetaType<QQmlComponent::Status>();
474 qRegisterMetaType<QList<QObject*> >();
475 qRegisterMetaType<QQmlBinding*>();
478 qmlProtectModule(
"QML", 1);
481 baseModulesUninitialized =
false;
484 q->handle()->setQmlEngine(q);
486 rootContext =
new QQmlContext(q,
true);
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
508
509
510QQmlEngine::QQmlEngine(QObject *parent)
511: QJSEngine(*
new QQmlEnginePrivate, parent)
515 QJSEnginePrivate::addToDebugServer(
this);
519
520
521QQmlEngine::QQmlEngine(QQmlEnginePrivate &dd, QObject *parent)
522: QJSEngine(dd, parent)
529
530
531
532
533
534
535
536
537QQmlEngine::~QQmlEngine()
541#if QT_CONFIG(qml_worker_script)
544 delete std::exchange(d->workerScriptEngine,
nullptr);
547 QV4::ExecutionEngine *v4 = handle();
548 v4->inShutdown =
true;
549 QJSEnginePrivate::removeFromDebugServer(
this);
554 QQmlContextPrivate::get(rootContext())->emitDestruction();
560 d->singletonInstances.clear();
562 delete d->rootContext;
563 d->rootContext =
nullptr;
565 v4->typeLoader()->invalidate();
568 qDeleteAll(d->cachedValueTypeInstances);
569 d->cachedValueTypeInstances.clear();
571 v4->resetQmlEngine();
575
576
577
578
581
582
583
584
585
586
590
591
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622void QQmlEngine::clearComponentCache()
627 qDeleteAll(std::exchange(d->cachedValueTypeInstances, {}));
631 QV4::MemoryManager *mm = handle()->memoryManager;
632 auto oldLimit = mm->gcStateMachine->timeLimit;
633 mm->setGCTimeLimit(-1);
635 mm->gcStateMachine->timeLimit = std::move(oldLimit);
637 QV4::ExecutionEngine *v4 = handle();
638 v4->trimCompilationUnits();
639 v4->typeLoader()->clearCache();
640 QQmlMetaType::freeUnusedTypesAndCaches();
644
645
646
647
648
649
650
651
652
653
654
655void QQmlEngine::trimComponentCache()
657 QV4::ExecutionEngine *v4 = handle();
658 v4->trimCompilationUnits();
659 v4->typeLoader()->trimCache();
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677void QQmlEngine::clearSingletons()
680 d->singletonInstances.clear();
684
685
686
687
688
689
690
691
692
693
694QQmlContext *QQmlEngine::rootContext()
const
696 Q_D(
const QQmlEngine);
697 return d->rootContext;
700#if QT_DEPRECATED_SINCE(6
, 0
)
702
703
704
705
706
707
708
709QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor()
const
711 return QQmlTypeLoader::get(
this)->urlInterceptors().last();
716
717
718
719
720
721
722
723
724void QQmlEngine::addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
726 QQmlTypeLoader::get(
this)->addUrlInterceptor(urlInterceptor);
730
731
732
733
734
735
736
737void QQmlEngine::removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
739 QQmlTypeLoader::get(
this)->removeUrlInterceptor(urlInterceptor);
743
744
745
746QUrl QQmlEngine::interceptUrl(
const QUrl &url, QQmlAbstractUrlInterceptor::DataType type)
const
748 return QQmlTypeLoader::get(
this)->interceptUrl(url, type);
752
753
754QList<QQmlAbstractUrlInterceptor *> QQmlEngine::urlInterceptors()
const
756 return QQmlTypeLoader::get(
this)->urlInterceptors();
759QSharedPointer<QQmlImageProviderBase> QQmlEnginePrivate::imageProvider(
const QString &providerId)
const
761 const QString providerIdLower = providerId.toLower();
762 QMutexLocker locker(&imageProviderMutex);
763 return imageProviders.value(providerIdLower);
766#if QT_CONFIG(qml_network)
768
769
770
771
772
773
774
775
776
777
778
779void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
781 QQmlTypeLoader::get(
this)->setNetworkAccessManagerFactory(factory);
784class QQmlEnginePublicAPIToken {};
787
788
789
790
791QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory()
const
793 return QQmlTypeLoader::get(
this)->networkAccessManagerFactory().get(QQmlEnginePublicAPIToken());
797
798
799
800
801
802
803
804
805
806
807
808QNetworkAccessManager *QQmlEngine::networkAccessManager()
const
810 return handle()->getNetworkAccessManager();
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829void QQmlEngine::addImageProvider(
const QString &providerId, QQmlImageProviderBase *provider)
832 QString providerIdLower = providerId.toLower();
833 QSharedPointer<QQmlImageProviderBase> sp(provider);
834 QMutexLocker locker(&d->imageProviderMutex);
835 d->imageProviders.insert(std::move(providerIdLower), std::move(sp));
839
840
841
842
843QQmlImageProviderBase *QQmlEngine::imageProvider(
const QString &providerId)
const
845 Q_D(
const QQmlEngine);
846 const QString providerIdLower = providerId.toLower();
847 QMutexLocker locker(&d->imageProviderMutex);
848 return d->imageProviders.value(providerIdLower).data();
852
853
854
855
856void QQmlEngine::removeImageProvider(
const QString &providerId)
859 const QString providerIdLower = providerId.toLower();
860 QMutexLocker locker(&d->imageProviderMutex);
861 d->imageProviders.take(providerIdLower);
865
866
867
868
869
870
871
872
873
874QUrl QQmlEngine::baseUrl()
const
876 Q_D(
const QQmlEngine);
877 if (d->baseUrl.isEmpty()) {
878 const QString currentPath = QDir::currentPath();
879 const QString rootPath = QDir::rootPath();
880 return QUrl::fromLocalFile((currentPath == rootPath) ? rootPath : (currentPath + QDir::separator()));
887
888
889
890
891void QQmlEngine::setBaseUrl(
const QUrl &url)
898
899
900
901
902
903bool QQmlEngine::outputWarningsToStandardError()
const
905 Q_D(
const QQmlEngine);
906 return d->outputWarningsToMsgLog;
910
911
912
913
914
915
916
917
918
919void QQmlEngine::setOutputWarningsToStandardError(
bool enabled)
922 d->outputWarningsToMsgLog = enabled;
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957void QQmlEngine::markCurrentFunctionAsTranslationBinding()
960 if (
auto propertyCapture = d->propertyCapture)
961 propertyCapture->captureTranslation();
965
966
967
968
969void QQmlEngine::captureProperty(QObject *object,
const QMetaProperty &property)
const
971 Q_D(
const QQmlEngine);
972 if (d->propertyCapture && !property.isConstant()) {
973 d->propertyCapture->captureProperty(
974 object, property.propertyIndex(),
975 QMetaObjectPrivate::signalIndex(property.notifySignal()));
980
981
982
983
984
985
986
987
988
989
990
991
992
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1025QJSValue QQmlEngine::singletonInstance<QJSValue>(
int qmlTypeId)
1028 QQmlType type = QQmlMetaType::qmlTypeById(qmlTypeId);
1030 if (!type.isValid() || !type.isSingleton())
1033 return d->singletonInstance<QJSValue>(type);
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1060QJSValue QQmlEngine::singletonInstance<QJSValue>(QAnyStringView uri, QAnyStringView typeName)
1064 auto loadHelper = QQml::makeRefPointer<LoadHelper>(
1065 QQmlTypeLoader::get(
this), uri, typeName, QQmlTypeLoader::Synchronous);
1066 const QQmlType type = loadHelper->type();
1068 if (!type.isSingleton())
1071 return d->singletonInstance<QJSValue>(type);
1075
1076
1077
1078
1079
1080
1081
1082
1083void QQmlEngine::retranslate()
1086 d->translationLanguage.notify();
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099QQmlContext *QQmlEngine::contextForObject(
const QObject *object)
1104 QQmlData *data = QQmlData::get(object);
1105 if (data && data->outerContext)
1106 return data->outerContext->asQQmlContext();
1112
1113
1114
1115
1116
1117
1118
1119void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
1121 if (!object || !context)
1124 QQmlData *data = QQmlData::get(object,
true);
1125 if (data->context) {
1126 qWarning(
"QQmlEngine::setContextForObject(): Object already has a QQmlContext");
1130 QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
1131 Q_ASSERT(data->context ==
nullptr);
1132 data->context = contextData.data();
1133 contextData->addOwnedObject(data);
1137
1138
1139bool QQmlEngine::event(QEvent *e)
1141 if (e->type() == QEvent::LanguageChange) {
1145 return QJSEngine::event(e);
1164void QQmlData::NotifyList::layout(QQmlNotifierEndpoint *endpoint)
1168 endpoint->prev =
nullptr;
1170 while (endpoint->next) {
1171 Q_ASSERT(
reinterpret_cast<QQmlNotifierEndpoint *>(endpoint->next->prev) == endpoint);
1172 endpoint = endpoint->next;
1176 QQmlNotifierEndpoint *ep = (QQmlNotifierEndpoint *) endpoint->prev;
1178 int index = endpoint->sourceSignal;
1179 index = qMin(index, 0xFFFF - 1);
1181 endpoint->next = notifies[index];
1182 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1183 endpoint->prev = ¬ifies[index];
1184 notifies[index] = endpoint;
1190void QQmlData::NotifyList::layout()
1192 Q_ASSERT(maximumTodoIndex >= notifiesSize);
1195 QQmlNotifierEndpoint **old = notifies;
1196 const int reallocSize = (maximumTodoIndex + 1) *
sizeof(QQmlNotifierEndpoint*);
1197 notifies = (QQmlNotifierEndpoint**)realloc(notifies, reallocSize);
1198 const int memsetSize = (maximumTodoIndex - notifiesSize + 1) *
1199 sizeof(QQmlNotifierEndpoint*);
1200 memset(notifies + notifiesSize, 0, memsetSize);
1202 if (notifies != old) {
1203 for (
int ii = 0; ii < notifiesSize; ++ii)
1205 notifies[ii]->prev = ¬ifies[ii];
1208 notifiesSize = maximumTodoIndex + 1;
1213 maximumTodoIndex = 0;
1217void QQmlData::deferData(
1218 int objectIndex,
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
1219 const QQmlRefPointer<QQmlContextData> &context,
const QString &inlineComponentName)
1221 QQmlData::DeferredData *deferData =
new QQmlData::DeferredData;
1222 deferData->deferredIdx = objectIndex;
1223 deferData->compilationUnit = compilationUnit;
1224 deferData->context = context;
1225 deferData->inlineComponentName = inlineComponentName;
1227 const QV4::CompiledData::Object *compiledObject = compilationUnit->objectAt(objectIndex);
1228 const QV4::CompiledData::BindingPropertyData *propertyData
1229 = compilationUnit->bindingPropertyDataPerObjectAt(objectIndex);
1231 const QV4::CompiledData::Binding *binding = compiledObject->bindingTable();
1232 for (quint32 i = 0; i < compiledObject->nBindings; ++i, ++binding) {
1233 const QQmlPropertyData *property = propertyData->at(i);
1234 if (binding->hasFlag(QV4::CompiledData::Binding::IsDeferredBinding))
1235 deferData->bindings.insert(property ? property->coreIndex() : -1, binding);
1238 deferredData.append(deferData);
1241void QQmlData::releaseDeferredData()
1243 auto it = deferredData.begin();
1244 while (it != deferredData.end()) {
1245 DeferredData *deferData = *it;
1246 if (deferData->bindings.isEmpty()) {
1248 it = deferredData.erase(it);
1255void QQmlData::addNotify(
int index, QQmlNotifierEndpoint *endpoint)
1259 NotifyList *list = notifyList.loadRelaxed();
1262 list =
new NotifyList;
1268 notifyList.storeRelaxed(list);
1271 Q_ASSERT(!endpoint->isConnected());
1273 index = qMin(index, 0xFFFF - 1);
1278 list->connectionMask.storeRelaxed(
1279 list->connectionMask.loadRelaxed() | (1ULL << quint64(index % 64)));
1281 if (index < list->notifiesSize) {
1282 endpoint->next = list->notifies[index];
1283 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1284 endpoint->prev = &list->notifies[index];
1285 list->notifies[index] = endpoint;
1287 list->maximumTodoIndex = qMax(
int(list->maximumTodoIndex), index);
1289 endpoint->next = list->todo;
1290 if (endpoint->next) endpoint->next->prev = &endpoint->next;
1291 endpoint->prev = &list->todo;
1292 list->todo = endpoint;
1296void QQmlData::disconnectNotifiers(QQmlData::DeleteNotifyList doDelete)
1299 if (NotifyList *list = notifyList.loadRelaxed()) {
1300 while (QQmlNotifierEndpoint *todo = list->todo)
1302 for (
int ii = 0; ii < list->notifiesSize; ++ii) {
1303 while (QQmlNotifierEndpoint *ep = list->notifies[ii])
1306 free(list->notifies);
1308 if (doDelete == DeleteNotifyList::Yes) {
1312 notifyList.storeRelaxed(
nullptr);
1318 list->connectionMask.storeRelaxed(0);
1319 list->maximumTodoIndex = 0;
1320 list->notifiesSize = 0;
1321 list->notifies =
nullptr;
1327QHash<QQmlAttachedPropertiesFunc, QObject *> *QQmlData::attachedProperties()
const
1329 if (!extendedData) extendedData =
new QQmlDataExtended;
1330 return &extendedData->attachedProperties;
1333void QQmlData::destroyed(QObject *object)
1335 if (nextContextObject)
1336 nextContextObject->prevContextObject = prevContextObject;
1337 if (prevContextObject)
1338 *prevContextObject = nextContextObject;
1339 else if (outerContext && outerContext->ownedObjects() ==
this)
1340 outerContext->setOwnedObjects(nextContextObject);
1342 QQmlAbstractBinding *binding = bindings;
1344 binding->setAddedToObject(
false);
1345 binding = binding->nextBinding();
1347 if (bindings && !bindings->ref.deref())
1350 compilationUnit.reset();
1352 qDeleteAll(deferredData);
1353 deferredData.clear();
1355 QQmlBoundSignal *signalHandler = signalHandlers;
1356 while (signalHandler) {
1357 if (signalHandler->isNotifying()) {
1362 QString locationString;
1363 QQmlBoundSignalExpression *expr = signalHandler->expression();
1365 QQmlSourceLocation location = expr->sourceLocation();
1366 if (location.sourceFile.isEmpty())
1367 location.sourceFile = QStringLiteral(
"<Unknown File>");
1368 locationString.append(location.sourceFile);
1369 locationString.append(QStringLiteral(
":%0: ").arg(location.line));
1370 QString source = expr->expression();
1371 if (source.size() > 100) {
1372 source.truncate(96);
1373 source.append(QLatin1String(
" ..."));
1375 locationString.append(source);
1377 locationString = QStringLiteral(
"<Unknown Location>");
1379 qFatal(
"Object %p destroyed while one of its QML signal handlers is in progress.\n"
1380 "Most likely the object was deleted synchronously (use QObject::deleteLater() "
1381 "instead), or the application is running a nested event loop.\n"
1382 "This behavior is NOT supported!\n"
1383 "%s", object, qPrintable(locationString));
1386 QQmlBoundSignal *next = signalHandler->m_nextSignal;
1387 signalHandler->m_prevSignal =
nullptr;
1388 signalHandler->m_nextSignal =
nullptr;
1389 delete signalHandler;
1390 signalHandler = next;
1393 if (bindingBitsArraySize > InlineBindingArraySize)
1397 propertyCache.reset();
1402 auto *guard = guards;
1403 guard->setObject(
nullptr);
1404 if (guard->objectDestroyed)
1405 guard->objectDestroyed(guard);
1408 disconnectNotifiers(DeleteNotifyList::Yes);
1411 delete extendedData;
1422QQmlData::BindingBitsType *QQmlData::growBits(QObject *obj,
int bit)
1424 BindingBitsType *bits = (bindingBitsArraySize == InlineBindingArraySize) ? bindingBitsValue : bindingBits;
1425 int props = QQmlMetaObject(obj).propertyCount();
1426 Q_ASSERT(bit < 2 * props);
1429 uint arraySize = (2 *
static_cast<uint>(props) + BitsPerType - 1) / BitsPerType;
1430 Q_ASSERT(arraySize > 1);
1431 Q_ASSERT(arraySize <= 0xffff);
1433 BindingBitsType *newBits =
static_cast<BindingBitsType *>(malloc(arraySize*
sizeof(BindingBitsType)));
1434 memcpy(newBits, bits, bindingBitsArraySize *
sizeof(BindingBitsType));
1435 memset(newBits + bindingBitsArraySize, 0,
sizeof(BindingBitsType) * (arraySize - bindingBitsArraySize));
1437 if (bindingBitsArraySize > InlineBindingArraySize)
1439 bindingBits = newBits;
1441 bindingBitsArraySize = arraySize;
1445QQmlData *QQmlData::createQQmlData(QObjectPrivate *priv)
1448 Q_ASSERT(!priv->isDeletingChildren);
1449 priv->declarativeData =
new QQmlData(OwnsMemory);
1450 return static_cast<QQmlData *>(priv->declarativeData);
1453QQmlPropertyCache::ConstPtr QQmlData::createPropertyCache(QObject *object)
1455 QQmlData *ddata = QQmlData::get(object,
true);
1456 ddata->propertyCache = QQmlMetaType::propertyCache(object, QTypeRevision {});
1457 return ddata->propertyCache;
1460void QQmlEnginePrivate::sendQuit()
1464 if (q->receivers(SIGNAL(quit())) == 0) {
1465 qWarning(
"Signal QQmlEngine::quit() emitted, but no receivers connected to handle it.");
1469void QQmlEnginePrivate::sendExit(
int retCode)
1472 if (q->receivers(SIGNAL(exit(
int))) == 0)
1473 qWarning(
"Signal QQmlEngine::exit() emitted, but no receivers connected to handle it.");
1474 emit q->exit(retCode);
1479 switch (error.messageType()) {
1481 QMessageLogger(error.url().toString().toLatin1().constData(),
1482 error.line(),
nullptr).debug().noquote().nospace()
1483 << error.toString();
1486 QMessageLogger(error.url().toString().toLatin1().constData(),
1487 error.line(),
nullptr).info().noquote().nospace()
1488 << error.toString();
1492 QMessageLogger(error.url().toString().toLatin1().constData(),
1493 error.line(),
nullptr).warning().noquote().nospace()
1494 << error.toString();
1497 QMessageLogger(error.url().toString().toLatin1().constData(),
1498 error.line(),
nullptr).critical().noquote().nospace()
1499 << error.toString();
1506 for (
int ii = 0; ii < errors.size(); ++ii)
1507 dumpwarning(errors.at(ii));
1510void QQmlEnginePrivate::warning(
const QQmlError &error)
1513 emit q->warnings(QList<QQmlError>({error}));
1514 if (outputWarningsToMsgLog)
1518void QQmlEnginePrivate::warning(
const QList<QQmlError> &errors)
1521 emit q->warnings(errors);
1522 if (outputWarningsToMsgLog)
1523 dumpwarning(errors);
1526void QQmlEnginePrivate::warning(QQmlEngine *engine,
const QQmlError &error)
1529 QQmlEnginePrivate::get(engine)->warning(error);
1534void QQmlEnginePrivate::warning(QQmlEngine *engine,
const QList<QQmlError> &error)
1537 QQmlEnginePrivate::get(engine)->warning(error);
1542void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine,
const QQmlError &error)
1545 engine->warning(error);
1550void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine,
const QList<QQmlError> &error)
1553 engine->warning(error);
1558QList<QQmlError> QQmlEnginePrivate::qmlErrorFromDiagnostics(
1559 const QString &fileName,
const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages)
1561 QList<QQmlError> errors;
1562 for (
const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {
1563 if (m.isWarning()) {
1564 qWarning(
"%s:%d : %s", qPrintable(fileName), m.loc.startLine, qPrintable(m.message));
1569 error.setUrl(QUrl(fileName));
1570 error.setDescription(m.message);
1571 error.setLine(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startLine));
1572 error.setColumn(qmlConvertSourceCoordinate<quint32,
int>(m.loc.startColumn));
1578void QQmlEnginePrivate::cleanupScarceResources()
1584 QV4::ExecutionEngine *engine = v4Engine.get();
1585 while (QV4::ExecutionEngine::ScarceResourceData *sr = engine->scarceResources.first()) {
1586 sr->data = QVariant();
1587 engine->scarceResources.remove(sr);
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607void QQmlEngine::addImportPath(
const QString& path)
1609 QQmlTypeLoader::get(
this)->addImportPath(path);
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627QStringList QQmlEngine::importPathList()
const
1629 return QQmlTypeLoader::get(
this)->importPathList();
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644void QQmlEngine::setImportPathList(
const QStringList &paths)
1646 QQmlTypeLoader::get(
this)->setImportPathList(paths);
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661void QQmlEngine::addPluginPath(
const QString& path)
1663 QQmlTypeLoader::get(
this)->addPluginPath(path);
1667
1668
1669
1670
1671
1672
1673
1674
1675QStringList QQmlEngine::pluginPathList()
const
1677 return QQmlTypeLoader::get(
this)->pluginPathList();
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690void QQmlEngine::setPluginPathList(
const QStringList &paths)
1692 QQmlTypeLoader::get(
this)->setPluginPathList(paths);
1695#if QT_CONFIG(library)
1696#if QT_DEPRECATED_SINCE(6
, 4
)
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711bool QQmlEngine::importPlugin(
const QString &filePath,
const QString &uri, QList<QQmlError> *errors)
1713 QQmlTypeLoaderQmldirContent qmldir;
1714 QQmlPluginImporter importer(uri, QTypeRevision(), &qmldir, QQmlTypeLoader::get(
this), errors);
1715 return importer.importDynamicPlugin(filePath, uri,
false).isValid();
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1740
1741
1742
1743
1745void QQmlEngine::setOfflineStoragePath(
const QString& dir)
1748 if (dir == d->offlineStoragePath)
1750 d->offlineStoragePath = dir;
1751 Q_EMIT offlineStoragePathChanged();
1754QString QQmlEngine::offlineStoragePath()
const
1756 Q_D(
const QQmlEngine);
1758 if (d->offlineStoragePath.isEmpty()) {
1759 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
1760 QQmlEnginePrivate *e =
const_cast<QQmlEnginePrivate *>(d);
1761 if (!dataLocation.isEmpty()) {
1762 e->offlineStoragePath = dataLocation.replace(QLatin1Char(
'/'), QDir::separator())
1763 + QDir::separator() + QLatin1String(
"QML")
1764 + QDir::separator() + QLatin1String(
"OfflineStorage");
1765 Q_EMIT e->q_func()->offlineStoragePathChanged();
1769 return d->offlineStoragePath;
1773
1774
1775
1776
1777
1778
1779QString QQmlEngine::offlineStorageDatabaseFilePath(
const QString &databaseName)
const
1781 Q_D(
const QQmlEngine);
1782 QCryptographicHash md5(QCryptographicHash::Md5);
1783 md5.addData(databaseName.toUtf8());
1784 return d->offlineStorageDatabaseDirectory() + QLatin1String(md5.result().toHex());
1787QString QQmlEnginePrivate::offlineStorageDatabaseDirectory()
const
1789 Q_Q(
const QQmlEngine);
1790 return q->offlineStoragePath() + QDir::separator() + QLatin1String(
"Databases") + QDir::separator();
1795 bool requiredPropertiesFound =
false;
1797 if (propertyCache) {
1798 for (
int idx = 0, count = propertyCache->propertyCount(); idx < count; ++idx)
1799 requiredPropertiesFound |= propertyCache->property(idx)->isRequired();
1801 return requiredPropertiesFound;
1805QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(
const QQmlType &type)
1809 QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
1810 Q_ASSERT(siinfo !=
nullptr);
1812 QJSValue value = singletonInstances.value(siinfo);
1813 if (!value.isUndefined())
1816 if (siinfo->scriptCallback) {
1817 value = siinfo->scriptCallback(q, q);
1818 if (value.isQObject()) {
1819 QObject *o = value.toQObject();
1822 q->setContextForObject(o,
new QQmlContext(q->rootContext(), q));
1824 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1826 }
else if (siinfo->qobjectCallback) {
1827 QObject *o = siinfo->qobjectCallback(q, q);
1830 error.setMessageType(QtMsgType::QtCriticalMsg);
1831 error.setDescription(QString::asprintf(
"qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.",
1832 qPrintable(QString::fromUtf8(type.typeName()))));
1835 type.createProxy(o);
1838 QQmlPropertyCache::ConstPtr propertyCache = QQmlData::ensurePropertyCache(o);
1839 if (Q_UNLIKELY(hasRequiredProperties(propertyCache))) {
1844 error.setMessageType(QtMsgType::QtCriticalMsg);
1845 error.setDescription(QString::asprintf(
"Singleton \"%s\" is not available because the type has unset required properties.",
1846 qPrintable(QString::fromUtf8(type.typeName()))));
1853 QQmlData *data = QQmlData::get(o,
true);
1854 if (!data->context) {
1855 auto contextData = QQmlContextData::get(
new QQmlContext(q->rootContext(), q));
1856 data->context = contextData.data();
1857 contextData->addOwnedObject(data);
1862 value = q->newQObject(o);
1863 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1864 }
else if (!siinfo->url.isEmpty()) {
1865 QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous);
1866 if (component.isError()) {
1867 warning(component.errors());
1868 v4Engine->throwError(
1869 QLatin1String(
"Due to the preceding error(s), "
1870 "Singleton \"%1\" could not be loaded.")
1871 .arg(QString::fromUtf8(type.typeName())));
1873 return QJSValue(QJSValue::UndefinedValue);
1875 QObject *o = component.beginCreate(q->rootContext());
1876 auto *compPriv = QQmlComponentPrivate::get(&component);
1877 if (compPriv->hasUnsetRequiredProperties()) {
1879
1880
1881
1882
1883
1885 const auto requiredProperties = compPriv->requiredProperties();
1886 QList<QQmlError> errors (requiredProperties->size());
1887 for (
const auto &reqProp: *requiredProperties)
1888 errors.push_back(QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(reqProp));
1890 v4Engine->throwError(
1891 QLatin1String(
"Due to the preceding error(s), "
1892 "Singleton \"%1\" could not be loaded.")
1893 .arg(QString::fromUtf8(type.typeName())));
1894 return QJSValue(QJSValue::UndefinedValue);
1897 value = q->newQObject(o);
1898 singletonInstances.convertAndInsert(v4Engine.get(), siinfo, &value);
1899 component.completeCreate();
1905void QQmlEnginePrivate::executeRuntimeFunction(
const QUrl &url, qsizetype functionIndex,
1906 QObject *thisObject,
int argc,
void **args,
1909 const auto unit = compilationUnitFromUrl(url);
1912 executeRuntimeFunction(unit, functionIndex, thisObject, argc, args, types);
1915void QQmlEnginePrivate::executeRuntimeFunction(
const QV4::ExecutableCompilationUnit *unit,
1916 qsizetype functionIndex, QObject *thisObject,
1917 int argc,
void **args, QMetaType *types)
1920 Q_ASSERT((functionIndex >= 0) && (functionIndex < unit->runtimeFunctions.size()));
1921 Q_ASSERT(thisObject);
1923 QQmlData *ddata = QQmlData::get(thisObject);
1924 Q_ASSERT(ddata && ddata->context);
1926 QV4::Function *function = unit->runtimeFunctions[functionIndex];
1928 Q_ASSERT(function->compiledFunction);
1930 QV4::ExecutionEngine *v4 = v4Engine.get();
1936 QV4::Scope scope(v4);
1937 QV4::ExecutionContext *ctx = v4->scriptContext();
1938 QV4::Scoped<QV4::ExecutionContext> callContext(scope,
1939 QV4::QmlContext::create(ctx, ddata->context, thisObject));
1941 if (
auto nested = function->nestedFunction()) {
1944 }
else if (function->isClosureWrapper()) {
1951 QV4::Scoped<QV4::JavaScriptFunctionObject> result(scope,
1952 v4->callInContext(function, thisObject, callContext, 0,
nullptr));
1953 Q_ASSERT(result->function());
1954 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
1957 function = result->function();
1958 callContext = QV4::Scoped<QV4::ExecutionContext>(scope, result->scope());
1961 v4->callInContext(function, thisObject, callContext, argc, args, types);
1964QV4::ExecutableCompilationUnit *QQmlEnginePrivate::compilationUnitFromUrl(
const QUrl &url)
1966 QV4::ExecutionEngine *v4 = v4Engine.get();
1967 if (
auto unit = v4->compilationUnitForUrl(url)) {
1968 if (!unit->runtimeStrings)
1973 auto unit = v4->typeLoader()->getType(url)->compilationUnit();
1977 auto executable = v4->executableCompilationUnit(std::move(unit));
1978 executable->populate();
1979 return executable.data();
1982QQmlRefPointer<QQmlContextData>
1983QQmlEnginePrivate::createInternalContext(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
1984 const QQmlRefPointer<QQmlContextData> &parentContext,
1985 int subComponentIndex,
bool isComponentRoot)
1989 QQmlRefPointer<QQmlContextData> context;
1990 context = QQmlContextData::createRefCounted(parentContext);
1991 context->setInternal(
true);
1992 context->setImports(unit->typeNameCache());
1993 context->initFromTypeCompilationUnit(unit, subComponentIndex);
1995 const auto *dependentScripts = unit->dependentScriptsPtr();
1996 const qsizetype dependentScriptsSize = dependentScripts->size();
1997 if (isComponentRoot && dependentScriptsSize) {
1998 QV4::ExecutionEngine *v4 = v4Engine.get();
2000 QV4::Scope scope(v4);
2002 QV4::ScopedObject scripts(scope, v4->newArrayObject(dependentScriptsSize));
2003 context->setImportedScripts(v4, scripts);
2004 QV4::ScopedValue v(scope);
2005 for (qsizetype i = 0; i < dependentScriptsSize; ++i)
2006 scripts->put(i, (v = dependentScripts->at(i)->scriptValueForContext(context)));
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2039 QQmlTypeLoader *loader, QAnyStringView uri, QAnyStringView typeName,
2040 QQmlTypeLoader::Mode mode)
2046 m_typeLoader->loadWithStaticData(
this, QByteArray(), m_mode);
2051 m_callback = callback;
2057 Q_ASSERT(callback == m_callback);
2058 m_callback =
nullptr;
2064 if (!couldFindModule()) {
2069 QQmlTypeModule *module = QQmlMetaType::typeModule(m_uri, QTypeRevision{});
2071 m_type = module->type(m_typeName, {});
2072 if (m_type.isValid()) {
2080 QTypeRevision versionReturn;
2081 QList<QQmlError> errors;
2082 QQmlImportNamespace *ns_return =
nullptr;
2083 m_importCache->resolveType(
2084 typeLoader(), m_typeName, &m_type, &versionReturn, &ns_return, &errors);
2090 QQmlTypeLoader::Blob::completed();
2093 m_callback->completeLoadFromModule(m_uri, m_typeName);
2094 m_callback =
nullptr;
2100 auto import = std::make_shared<PendingImport>();
2101 import->uri = m_uri;
2102 QList<QQmlError> errorList;
2103 if (!Blob::addImport(import, &errorList)) {
2104 qCDebug(lcQmlImport) <<
"LoadHelper: Errors loading " << m_uri << errorList;
2109bool LoadHelper::couldFindModule()
const
2111 if (m_uri.isEmpty())
2113 for (
const auto &import: std::as_const(m_unresolvedImports))
2114 if (import->priority == 0)
2121#include "moc_qqmlengine.cpp"
QHash< QQmlAttachedPropertiesFunc, QObject * > attachedProperties
QPointer< QObject > target
int qt_metacall(QMetaObject::Call, int methodIndex, void **a) override
static bool hasRequiredProperties(const QQmlPropertyCache::ConstPtr &propertyCache)
static void dumpwarning(const QQmlError &error)
void hasJsOwnershipIndicator(QQmlGuardImpl *)
void qml_register_types_QML()
int qmlRegisterType< void >(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
LoadHelper(QQmlTypeLoader *loader, QAnyStringView uri, QAnyStringView typeName, QQmlTypeLoader::Mode mode)
void dataReceived(const SourceCodeData &) final
Invoked when data for the blob is received.
void completed() final
Invoked on the main thread sometime after done() was called on the load thread.
void registerCallback(QQmlComponentPrivate *callback)
void unregisterCallback(QQmlComponentPrivate *callback)
void done() final
Invoked once data has either been received or a network error occurred, and all dependencies are comp...