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
55using namespace Qt::StringLiterals;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
78
79
80
81
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
115Q_CONSTINIT std::atomic<
bool> QQmlEnginePrivate::qml_debugging_enabled{
false};
116bool QQmlEnginePrivate::s_designerMode =
false;
118bool QQmlEnginePrivate::designerMode()
120 return s_designerMode;
123void QQmlEnginePrivate::activateDesignerMode()
125 s_designerMode =
true;
130
131
132
133
134
135
136
137
138
139
140
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
161
162
163
164
165
166
167
168
171
172
173
174
177
178
179
180
183QQmlImageProviderBase::QQmlImageProviderBase()
188QQmlImageProviderBase::~QQmlImageProviderBase()
192QQmlEnginePrivate::~QQmlEnginePrivate()
194 if (inProgressCreations)
195 qWarning() << QQmlEngine::tr(
"There are still \"%1\" items in the process of being created at engine destruction.").arg(inProgressCreations);
197 if (incubationController) incubationController->d =
nullptr;
198 incubationController =
nullptr;
200#if QT_CONFIG(qml_debug)
205void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
207 QObjectPrivate *p = QObjectPrivate::get(o);
208 if (QQmlData *d = QQmlData::get(p)) {
209 const auto invalidate = [](QQmlContextData *c) {c->invalidate();};
211 d->ownContext->deepClearContextObject(o, invalidate, invalidate);
212 d->ownContext.reset();
213 d->context =
nullptr;
214 Q_ASSERT(!d->outerContext || d->outerContext->contextObject() != o);
215 }
else if (d->outerContext && d->outerContext->contextObject() == o) {
216 d->outerContext->deepClearContextObject(o, invalidate, invalidate);
219 if (d->hasVMEMetaObject || d->hasInterceptorMetaObject) {
232 static_cast<QQmlInterceptorMetaObject *>(p->metaObject)->invalidate();
233 d->hasVMEMetaObject = d->hasInterceptorMetaObject =
false;
238 QQmlData::markAsDeleted(o);
242QQmlData::QQmlData(Ownership ownership)
243 : ownMemory(ownership == OwnsMemory), indestructible(
true), explicitIndestructibleSet(
false),
244 hasTaintedV4Object(
false), isQueuedForDeletion(
false), rootObjectInCreation(
false),
245 hasInterceptorMetaObject(
false), hasVMEMetaObject(
false), hasConstWrapper(
false), dummy(0),
246 bindingBitsArraySize(InlineBindingArraySize)
248 memset(bindingBitsValue, 0,
sizeof(bindingBitsValue));
256void QQmlData::destroyed(QAbstractDeclarativeData *d, QObject *o)
258 QQmlData *ddata =
static_cast<QQmlData *>(d);
272 QMetaMethod method = target->metaObject()->method(methodIndex);
273 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
274 int signalIndex = QMetaObjectPrivate::signalIndex(method);
275 QQmlData *ddata = QQmlData::get(target,
false);
276 QQmlNotifierEndpoint *ep = ddata->notify(signalIndex);
277 if (ep) QQmlNotifier::emitNotify(ep, a);
285void QQmlData::signalEmitted(QAbstractDeclarativeData *, QObject *object,
int index,
void **a)
287 QQmlData *ddata = QQmlData::get(object,
false);
299 if (!ddata->notifyList.loadRelaxed())
302 auto objectThreadData = QObjectPrivate::get(object)->threadData.loadRelaxed();
303 if (QThread::currentThreadId() != objectThreadData->threadId.loadRelaxed()) {
304 if (!objectThreadData->thread.loadAcquire())
307 QMetaMethod m = QMetaObjectPrivate::signal(object->metaObject(), index);
308 QList<QByteArray> parameterTypes = m.parameterTypes();
310 auto ev = std::make_unique<QMetaCallEvent>(m.methodIndex(), 0,
nullptr,
312 parameterTypes.size() + 1);
314 void **args = ev->args();
315 QMetaType *types = ev->types();
317 for (
int ii = 0; ii < parameterTypes.size(); ++ii) {
318 const QByteArray &typeName = parameterTypes.at(ii);
319 if (typeName.endsWith(
'*'))
320 types[ii + 1] = QMetaType(QMetaType::VoidStar);
322 types[ii + 1] = QMetaType::fromName(typeName);
324 if (!types[ii + 1].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 args[ii + 1] = types[ii + 1].create(a[ii + 1]);
334 QQmlThreadNotifierProxyObject *mpo =
new QQmlThreadNotifierProxyObject;
335 mpo->target = object;
336 mpo->moveToThread(objectThreadData->thread.loadAcquire());
337 QCoreApplication::postEvent(mpo, ev.release());
340 QQmlNotifierEndpoint *ep = ddata->notify(index);
341 if (ep) QQmlNotifier::emitNotify(ep, a);
345int QQmlData::receivers(QAbstractDeclarativeData *d,
const QObject *,
int index)
347 QQmlData *ddata =
static_cast<QQmlData *>(d);
348 return ddata->endpointCount(index);
351bool QQmlData::isSignalConnected(QAbstractDeclarativeData *d,
const QObject *,
int index)
353 QQmlData *ddata =
static_cast<QQmlData *>(d);
354 return ddata->signalHasEndpoint(index);
357int QQmlData::endpointCount(
int index)
360 QQmlNotifierEndpoint *ep = notify(index);
371void QQmlData::markAsDeleted(QObject *o)
373 QVarLengthArray<QObject *> workStack;
374 workStack.push_back(o);
375 while (!workStack.isEmpty()) {
376 auto currentObject = workStack.last();
377 workStack.pop_back();
378 QQmlData::setQueuedForDeletion(currentObject);
379 auto currentObjectPriv = QObjectPrivate::get(currentObject);
380 for (QObject *child: std::as_const(currentObjectPriv->children))
381 workStack.push_back(child);
385void QQmlData::setQueuedForDeletion(QObject *object)
388 if (QQmlData *ddata = QQmlData::get(object)) {
389 if (ddata->ownContext) {
390 Q_ASSERT(ddata->ownContext.data() == ddata->context);
391 ddata->ownContext->deepClearContextObject(object);
392 ddata->ownContext.reset();
393 ddata->context =
nullptr;
395 ddata->isQueuedForDeletion =
true;
402 ddata->disconnectNotifiers(DeleteNotifyList::No);
407void QQmlData::flushPendingBinding(
int coreIndex)
409 clearPendingBindingBit(coreIndex);
412 QQmlAbstractBinding *b = bindings;
413 while (b && (b->targetPropertyIndex().coreIndex() != coreIndex ||
414 b->targetPropertyIndex().hasValueTypeIndex()))
415 b = b->nextBinding();
417 if (b && b->targetPropertyIndex().coreIndex() == coreIndex &&
418 !b->targetPropertyIndex().hasValueTypeIndex())
419 b->setEnabled(
true, QQmlPropertyData::BypassInterceptor |
420 QQmlPropertyData::DontRemoveBinding);
423QQmlData::DeferredData::DeferredData() =
default;
424QQmlData::DeferredData::~DeferredData() =
default;
427int qmlRegisterType<
void>(
const char *uri,
int versionMajor,
int versionMinor,
const char *qmlName)
429 QQmlPrivate::RegisterType type = {
430 QQmlPrivate::RegisterType::CurrentVersion,
437 QTypeRevision::fromVersion(versionMajor, versionMinor),
448 QTypeRevision::zero(),
450 QQmlPrivate::ValueTypeCreationMethod::None,
453 return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
456bool QQmlEnginePrivate::baseModulesUninitialized =
true;
457void QQmlEnginePrivate::init()
461 if (baseModulesUninitialized) {
463 qml_register_types_QML();
466 static_assert(std::is_same_v<QStringList, QList<QString>>);
467 static_assert(std::is_same_v<QVariantList, QList<QVariant>>);
469 qRegisterMetaType<QQmlScriptString>();
470 qRegisterMetaType<QQmlComponent::Status>();
471 qRegisterMetaType<QList<QObject*> >();
472 qRegisterMetaType<QQmlBinding*>();
475 qmlProtectModule(
"QML", 1);
478 baseModulesUninitialized =
false;
481 q->handle()->setQmlEngine(q);
483 rootContext =
new QQmlContext(q,
true);
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
505
506
507QQmlEngine::QQmlEngine(QObject *parent)
508: QJSEngine(*
new QQmlEnginePrivate(
this), parent)
512 QJSEnginePrivate::addToDebugServer(
this);
516
517
518QQmlEngine::QQmlEngine(QQmlEnginePrivate &dd, QObject *parent)
519: QJSEngine(dd, parent)
526
527
528
529
530
531
532
533
534QQmlEngine::~QQmlEngine()
537 handle()->inShutdown =
true;
538 QJSEnginePrivate::removeFromDebugServer(
this);
543 QQmlContextPrivate::get(rootContext())->emitDestruction();
549 d->singletonInstances.clear();
551 delete d->rootContext;
552 d->rootContext =
nullptr;
554 d->typeLoader.invalidate();
557 qDeleteAll(d->cachedValueTypeInstances);
558 d->cachedValueTypeInstances.clear();
562
563
564
565
568
569
570
571
572
573
577
578
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609void QQmlEngine::clearComponentCache()
615 QV4::MemoryManager *mm = handle()->memoryManager;
616 auto oldLimit = mm->gcStateMachine->timeLimit;
617 mm->setGCTimeLimit(-1);
619 mm->gcStateMachine->timeLimit = std::move(oldLimit);
621 handle()->trimCompilationUnits();
622 d->typeLoader.clearCache();
623 QQmlMetaType::freeUnusedTypesAndCaches();
627
628
629
630
631
632
633
634
635
636
637
638void QQmlEngine::trimComponentCache()
641 handle()->trimCompilationUnits();
642 d->typeLoader.trimCache();
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660void QQmlEngine::clearSingletons()
663 d->singletonInstances.clear();
667
668
669
670
671
672
673
674
675
676
677QQmlContext *QQmlEngine::rootContext()
const
679 Q_D(
const QQmlEngine);
680 return d->rootContext;
683#if QT_DEPRECATED_SINCE(6
, 0
)
685
686
687
688
689
690
691
692QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor()
const
694 Q_D(
const QQmlEngine);
695 return d->typeLoader.urlInterceptors().last();
700
701
702
703
704
705
706
707
708void QQmlEngine::addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
711 d->typeLoader.addUrlInterceptor(urlInterceptor);
715
716
717
718
719
720
721
722void QQmlEngine::removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
725 d->typeLoader.removeUrlInterceptor(urlInterceptor);
729
730
731
732QUrl QQmlEngine::interceptUrl(
const QUrl &url, QQmlAbstractUrlInterceptor::DataType type)
const
734 Q_D(
const QQmlEngine);
735 return d->typeLoader.interceptUrl(url, type);
739
740
741QList<QQmlAbstractUrlInterceptor *> QQmlEngine::urlInterceptors()
const
743 Q_D(
const QQmlEngine);
744 return d->typeLoader.urlInterceptors();
747QSharedPointer<QQmlImageProviderBase> QQmlEnginePrivate::imageProvider(
const QString &providerId)
const
749 const QString providerIdLower = providerId.toLower();
750 QMutexLocker locker(&imageProviderMutex);
751 return imageProviders.value(providerIdLower);
754#if QT_CONFIG(qml_network)
756
757
758
759
760
761
762
763
764
765
766
767void QQmlEngine::setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *factory)
770 d->typeLoader.setNetworkAccessManagerFactory(factory);
773class QQmlEnginePublicAPIToken {};
776
777
778
779
780QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory()
const
782 Q_D(
const QQmlEngine);
783 return d->typeLoader.networkAccessManagerFactory().get(QQmlEnginePublicAPIToken());
786QNetworkAccessManager *QQmlEnginePrivate::getNetworkAccessManager()
789 if (!networkAccessManager)
790 networkAccessManager = typeLoader.createNetworkAccessManager(q);
791 return networkAccessManager;
795
796
797
798
799
800
801
802
803
804
805
806QNetworkAccessManager *QQmlEngine::networkAccessManager()
const
809 Q_D(
const QQmlEngine);
810 return const_cast<QQmlEnginePrivate *>(d)->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 &d->typeLoader, 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();
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)
1610 d->typeLoader.addImportPath(path);
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628QStringList QQmlEngine::importPathList()
const
1630 Q_D(
const QQmlEngine);
1631 return d->typeLoader.importPathList();
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646void QQmlEngine::setImportPathList(
const QStringList &paths)
1649 d->typeLoader.setImportPathList(paths);
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664void QQmlEngine::addPluginPath(
const QString& path)
1667 d->typeLoader.addPluginPath(path);
1671
1672
1673
1674
1675
1676
1677
1678
1679QStringList QQmlEngine::pluginPathList()
const
1681 Q_D(
const QQmlEngine);
1682 return d->typeLoader.pluginPathList();
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695void QQmlEngine::setPluginPathList(
const QStringList &paths)
1698 d->typeLoader.setPluginPathList(paths);
1701#if QT_CONFIG(library)
1702#if QT_DEPRECATED_SINCE(6
, 4
)
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717bool QQmlEngine::importPlugin(
const QString &filePath,
const QString &uri, QList<QQmlError> *errors)
1720 QQmlTypeLoaderQmldirContent qmldir;
1721 QQmlPluginImporter importer(uri, QTypeRevision(), &qmldir, &d->typeLoader, errors);
1722 return importer.importDynamicPlugin(filePath, uri,
false).isValid();
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1747
1748
1749
1750
1752void QQmlEngine::setOfflineStoragePath(
const QString& dir)
1755 if (dir == d->offlineStoragePath)
1757 d->offlineStoragePath = dir;
1758 Q_EMIT offlineStoragePathChanged();
1761QString QQmlEngine::offlineStoragePath()
const
1763 Q_D(
const QQmlEngine);
1765 if (d->offlineStoragePath.isEmpty()) {
1766 QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
1767 QQmlEnginePrivate *e =
const_cast<QQmlEnginePrivate *>(d);
1768 if (!dataLocation.isEmpty()) {
1769 e->offlineStoragePath = dataLocation.replace(QLatin1Char(
'/'), QDir::separator())
1770 + QDir::separator() + QLatin1String(
"QML")
1771 + QDir::separator() + QLatin1String(
"OfflineStorage");
1772 Q_EMIT e->q_func()->offlineStoragePathChanged();
1776 return d->offlineStoragePath;
1780
1781
1782
1783
1784
1785
1786QString QQmlEngine::offlineStorageDatabaseFilePath(
const QString &databaseName)
const
1788 Q_D(
const QQmlEngine);
1789 QCryptographicHash md5(QCryptographicHash::Md5);
1790 md5.addData(databaseName.toUtf8());
1791 return d->offlineStorageDatabaseDirectory() + QLatin1String(md5.result().toHex());
1794QString QQmlEnginePrivate::offlineStorageDatabaseDirectory()
const
1796 Q_Q(
const QQmlEngine);
1797 return q->offlineStoragePath() + QDir::separator() + QLatin1String(
"Databases") + QDir::separator();
1802 bool requiredPropertiesFound =
false;
1804 if (propertyCache) {
1805 for (
int idx = 0, count = propertyCache->propertyCount(); idx < count; ++idx)
1806 requiredPropertiesFound |= propertyCache->property(idx)->isRequired();
1808 return requiredPropertiesFound;
1812QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(
const QQmlType &type)
1816 QQmlType::SingletonInstanceInfo::ConstPtr siinfo = type.singletonInstanceInfo();
1817 Q_ASSERT(siinfo !=
nullptr);
1819 QJSValue value = singletonInstances.value(siinfo);
1820 if (!value.isUndefined())
1823 if (siinfo->scriptCallback) {
1824 value = siinfo->scriptCallback(q, q);
1825 if (value.isQObject()) {
1826 QObject *o = value.toQObject();
1829 q->setContextForObject(o,
new QQmlContext(q->rootContext(), q));
1831 singletonInstances.convertAndInsert(v4engine(), siinfo, &value);
1833 }
else if (siinfo->qobjectCallback) {
1834 QObject *o = siinfo->qobjectCallback(q, q);
1837 error.setMessageType(QtMsgType::QtCriticalMsg);
1838 error.setDescription(QString::asprintf(
"qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.",
1839 qPrintable(QString::fromUtf8(type.typeName()))));
1842 type.createProxy(o);
1845 QQmlPropertyCache::ConstPtr propertyCache = QQmlData::ensurePropertyCache(o);
1846 if (Q_UNLIKELY(hasRequiredProperties(propertyCache))) {
1851 error.setMessageType(QtMsgType::QtCriticalMsg);
1852 error.setDescription(QString::asprintf(
"Singleton \"%s\" is not available because the type has unset required properties.",
1853 qPrintable(QString::fromUtf8(type.typeName()))));
1860 QQmlData *data = QQmlData::get(o,
true);
1861 if (!data->context) {
1862 auto contextData = QQmlContextData::get(
new QQmlContext(q->rootContext(), q));
1863 data->context = contextData.data();
1864 contextData->addOwnedObject(data);
1869 value = q->newQObject(o);
1870 singletonInstances.convertAndInsert(v4engine(), siinfo, &value);
1871 }
else if (!siinfo->url.isEmpty()) {
1872 QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous);
1873 if (component.isError()) {
1874 warning(component.errors());
1875 v4engine()->throwError(QLatin1String(
"Due to the preceding error(s), Singleton \"%1\" could not be loaded.").arg(QString::fromUtf8(type.typeName())));
1877 return QJSValue(QJSValue::UndefinedValue);
1879 QObject *o = component.beginCreate(q->rootContext());
1880 auto *compPriv = QQmlComponentPrivate::get(&component);
1881 if (compPriv->hasUnsetRequiredProperties()) {
1883
1884
1885
1886
1887
1889 const auto requiredProperties = compPriv->requiredProperties();
1890 QList<QQmlError> errors (requiredProperties->size());
1891 for (
const auto &reqProp: *requiredProperties)
1892 errors.push_back(QQmlComponentPrivate::unsetRequiredPropertyToQQmlError(reqProp));
1894 v4engine()->throwError(QLatin1String(
"Due to the preceding error(s), Singleton \"%1\" could not be loaded.").arg(QString::fromUtf8(type.typeName())));
1895 return QJSValue(QJSValue::UndefinedValue);
1898 value = q->newQObject(o);
1899 singletonInstances.convertAndInsert(v4engine(), siinfo, &value);
1900 component.completeCreate();
1906bool QQmlEnginePrivate::isTypeLoaded(
const QUrl &url)
const
1908 return typeLoader.isTypeLoaded(url);
1911bool QQmlEnginePrivate::isScriptLoaded(
const QUrl &url)
const
1913 return typeLoader.isScriptLoaded(url);
1916void QQmlEnginePrivate::executeRuntimeFunction(
const QUrl &url, qsizetype functionIndex,
1917 QObject *thisObject,
int argc,
void **args,
1920 const auto unit = compilationUnitFromUrl(url);
1923 executeRuntimeFunction(unit, functionIndex, thisObject, argc, args, types);
1926void QQmlEnginePrivate::executeRuntimeFunction(
const QV4::ExecutableCompilationUnit *unit,
1927 qsizetype functionIndex, QObject *thisObject,
1928 int argc,
void **args, QMetaType *types)
1931 Q_ASSERT((functionIndex >= 0) && (functionIndex < unit->runtimeFunctions.size()));
1932 Q_ASSERT(thisObject);
1934 QQmlData *ddata = QQmlData::get(thisObject);
1935 Q_ASSERT(ddata && ddata->outerContext);
1937 QV4::Function *function = unit->runtimeFunctions[functionIndex];
1939 Q_ASSERT(function->compiledFunction);
1941 QV4::ExecutionEngine *v4 = v4engine();
1947 QV4::Scope scope(v4);
1948 QV4::ExecutionContext *ctx = v4->scriptContext();
1949 QV4::Scoped<QV4::ExecutionContext> callContext(scope,
1950 QV4::QmlContext::create(ctx, ddata->outerContext, thisObject));
1952 if (
auto nested = function->nestedFunction()) {
1955 }
else if (function->isClosureWrapper()) {
1962 QV4::Scoped<QV4::JavaScriptFunctionObject> result(scope,
1963 v4->callInContext(function, thisObject, callContext, 0,
nullptr));
1964 Q_ASSERT(result->function());
1965 Q_ASSERT(result->function()->compilationUnit == function->compilationUnit);
1968 function = result->function();
1969 callContext = QV4::Scoped<QV4::ExecutionContext>(scope, result->scope());
1972 v4->callInContext(function, thisObject, callContext, argc, args, types);
1975QV4::ExecutableCompilationUnit *QQmlEnginePrivate::compilationUnitFromUrl(
const QUrl &url)
1977 QV4::ExecutionEngine *v4 = v4engine();
1978 if (
auto unit = v4->compilationUnitForUrl(url)) {
1979 if (!unit->runtimeStrings)
1984 auto unit = typeLoader.getType(url)->compilationUnit();
1988 auto executable = v4->executableCompilationUnit(std::move(unit));
1989 executable->populate();
1990 return executable.data();
1993QQmlRefPointer<QQmlContextData>
1994QQmlEnginePrivate::createInternalContext(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
1995 const QQmlRefPointer<QQmlContextData> &parentContext,
1996 int subComponentIndex,
bool isComponentRoot)
2000 QQmlRefPointer<QQmlContextData> context;
2001 context = QQmlContextData::createRefCounted(parentContext);
2002 context->setInternal(
true);
2003 context->setImports(unit->typeNameCache());
2004 context->initFromTypeCompilationUnit(unit, subComponentIndex);
2006 const auto *dependentScripts = unit->dependentScriptsPtr();
2007 const qsizetype dependentScriptsSize = dependentScripts->size();
2008 if (isComponentRoot && dependentScriptsSize) {
2009 QV4::ExecutionEngine *v4 = v4engine();
2011 QV4::Scope scope(v4);
2013 QV4::ScopedObject scripts(scope, v4->newArrayObject(dependentScriptsSize));
2014 context->setImportedScripts(v4, scripts);
2015 QV4::ScopedValue v(scope);
2016 for (qsizetype i = 0; i < dependentScriptsSize; ++i)
2017 scripts->put(i, (v = dependentScripts->at(i)->scriptValueForContext(context)));
2023#if defined(Q_OS_WIN)
2027static inline QString shellNormalizeFileName(
const QString &name)
2029 const QString nativeSeparatorName(QDir::toNativeSeparators(name));
2030 const LPCTSTR nameC =
reinterpret_cast<LPCTSTR>(nativeSeparatorName.utf16());
2033#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3
)
2035 if (FAILED(SHParseDisplayName(nameC, NULL,
reinterpret_cast<LPITEMIDLIST>(&file), 0, NULL)))
2038 PIDLIST_ABSOLUTE file;
2039 if (FAILED(SHParseDisplayName(nameC, NULL, &file, 0, NULL)))
2042 TCHAR buffer[MAX_PATH];
2043 bool gotPath = SHGetPathFromIDList(file, buffer);
2049 QString canonicalName = QString::fromWCharArray(buffer);
2051 if (canonicalName.size() > 2 && canonicalName.at(1) == QLatin1Char(
':'))
2052 canonicalName[0] = canonicalName.at(0).toUpper();
2053 return QDir::cleanPath(canonicalName);
2059#if defined(Q_OS_DARWIN) || defined(Q_OS_WIN)
2060 QFileInfo info(fileName);
2061 const QString absolute = info.absoluteFilePath();
2064 if (absolute[0] == QLatin1Char(
':'))
2067#if defined(Q_OS_DARWIN)
2068 const QString canonical = info.canonicalFilePath();
2069 if (
const auto suffix = info.suffix();
2070 (suffix ==
"qml"_L1 || suffix ==
"dylib"_L1) && info.exists()) {
2078 if (pathconf(canonical.toUtf8().constData(), _PC_CASE_PRESERVING) != 1) {
2079 qCDebug(lcQmlImport) <<
"Detected QML file on non-case-preserving file system"
2080 << QStorageInfo(canonical) <<
"Verifying file case via directory listing";
2081 QDirIterator dirIterator(info.absolutePath(), { info.fileName() },
2082 QDir::Files | QDir::CaseSensitive, QDirIterator::FollowSymlinks);
2083 if (!dirIterator.hasNext())
2087#elif defined(Q_OS_WIN)
2088 const QString canonical = shellNormalizeFileName(absolute);
2091 const int absoluteLength = absolute.length();
2092 const int canonicalLength = canonical.length();
2094 int length = qMin(absoluteLength, canonicalLength);
2095 if (lengthIn >= 0) {
2096 length = qMin(lengthIn, length);
2100 int lastSlash = absolute.lastIndexOf(QLatin1Char(
'/'));
2102 lastSlash = absolute.lastIndexOf(QLatin1Char(
'\\'));
2103 if (lastSlash >= 0) {
2104 const int fileNameLength = absoluteLength - 1 - lastSlash;
2105 length = qMin(length, fileNameLength);
2109 for (
int ii = 0; ii < length; ++ii) {
2110 const QChar &a = absolute.at(absoluteLength - 1 - ii);
2111 const QChar &c = canonical.at(canonicalLength - 1 - ii);
2113 if (a.toLower() != c.toLower())
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2152 QQmlTypeLoader *loader, QAnyStringView uri, QAnyStringView typeName,
2153 QQmlTypeLoader::Mode mode)
2159 m_typeLoader->loadWithStaticData(
this, QByteArray(), m_mode);
2164 m_callback = callback;
2170 Q_ASSERT(callback == m_callback);
2171 m_callback =
nullptr;
2177 if (!couldFindModule()) {
2182 QQmlTypeModule *module = QQmlMetaType::typeModule(m_uri, QTypeRevision{});
2184 m_type = module->type(m_typeName, {});
2185 if (m_type.isValid()) {
2193 QTypeRevision versionReturn;
2194 QList<QQmlError> errors;
2195 QQmlImportNamespace *ns_return =
nullptr;
2196 m_importCache->resolveType(
2197 typeLoader(), m_typeName, &m_type, &versionReturn, &ns_return, &errors);
2203 QQmlTypeLoader::Blob::completed();
2206 m_callback->completeLoadFromModule(m_uri, m_typeName);
2207 m_callback =
nullptr;
2213 auto import = std::make_shared<PendingImport>();
2214 import->uri = m_uri;
2215 QList<QQmlError> errorList;
2216 if (!Blob::addImport(import, &errorList)) {
2217 qCDebug(lcQmlImport) <<
"LoadHelper: Errors loading " << m_uri << errorList;
2222bool LoadHelper::couldFindModule()
const
2224 if (m_uri.isEmpty())
2226 for (
const auto &import: std::as_const(m_unresolvedImports))
2227 if (import->priority == 0)
2234#include "moc_qqmlengine.cpp"
QHash< QQmlAttachedPropertiesFunc, QObject * > attachedProperties
QPointer< QObject > target
int qt_metacall(QMetaObject::Call, int methodIndex, void **a) override
Combined button and popup list for selecting options.
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)
bool QQml_isFileCaseCorrect(const QString &fileName, int length=-1)
Returns true if the case of fileName is equivalent to the file case of fileName on disk,...
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...