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#ifndef QQMLPRIVATE_H
5#define QQMLPRIVATE_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtQml/qtqmlglobal.h>
19#include <QtQml/qqmlparserstatus.h>
20#include <QtQml/qqmllist.h>
21#include <QtQml/qqmlpropertyvaluesource.h>
22#include <QtQml/qjsvalue.h>
23
24#include <QtCore/qglobal.h>
25#include <QtCore/qvariant.h>
26#include <QtCore/qurl.h>
27#include <QtCore/qpointer.h>
28#include <QtCore/qversionnumber.h>
29
30#include <QtCore/qmetaobject.h>
31#include <QtCore/qmetacontainer.h>
32#include <QtCore/qdebug.h>
33
34#include <functional>
35#include <type_traits>
36#include <limits>
37
38QT_BEGIN_NAMESPACE
39
40class QQmlPropertyValueInterceptor;
41class QQmlContextData;
42class QQmlFinalizerHook;
43
44namespace QQmlPrivate {
45struct CachedQmlUnit;
46template<typename A>
47using QQmlAttachedPropertiesFunc = A *(*)(QObject *);
48}
49
50namespace QV4 {
51struct ExecutionEngine;
52class ExecutableCompilationUnit;
53namespace CompiledData {
54struct Unit;
55}
56}
57namespace QmlIR {
58struct Document;
59typedef void (*IRLoaderFunction)(Document *, const QQmlPrivate::CachedQmlUnit *);
60}
61
62using QQmlAttachedPropertiesFunc = QQmlPrivate::QQmlAttachedPropertiesFunc<QObject>;
63
64inline size_t qHash(QQmlAttachedPropertiesFunc func, size_t seed = 0)
65{
66 return qHash(key: quintptr(func), seed);
67}
68
69template <typename TYPE>
70class QQmlTypeInfo
71{
72public:
73 enum {
74 hasAttachedProperties = 0
75 };
76};
77
78
79class QJSEngine;
80class QQmlEngine;
81class QQmlCustomParser;
82class QQmlTypeNotAvailable;
83
84template<class T>
85QQmlCustomParser *qmlCreateCustomParser()
86{
87 return nullptr;
88}
89
90namespace QQmlPrivate
91{
92 void Q_QML_EXPORT qdeclarativeelement_destructor(QObject *);
93 template<typename T>
94 class QQmlElement final : public T
95 {
96 public:
97 ~QQmlElement() override {
98 QQmlPrivate::qdeclarativeelement_destructor(this);
99 }
100 static void operator delete(void *ptr) {
101 // We allocate memory from this class in QQmlType::create
102 // along with some additional memory.
103 // So we override the operator delete in order to avoid the
104 // sized operator delete to be called with a different size than
105 // the size that was allocated.
106 ::operator delete (ptr);
107 }
108#ifdef Q_CC_MSVC
109 static void operator delete(void *, void *) {
110 // Deliberately empty placement delete operator.
111 // Silences MSVC warning C4291: no matching operator delete found
112 // On MinGW it causes -Wmismatched-new-delete, though.
113 }
114#endif
115 };
116
117 enum class SingletonConstructionMode
118 {
119 None,
120 Constructor,
121 Factory,
122 FactoryWrapper
123 };
124
125 template<typename T, typename WrapperT = T, typename = std::void_t<>>
126 struct HasSingletonFactory
127 {
128 static constexpr bool value = false;
129 };
130
131 template<typename T, typename WrapperT>
132 struct HasSingletonFactory<T, WrapperT, std::void_t<decltype(WrapperT::create(
133 static_cast<QQmlEngine *>(nullptr),
134 static_cast<QJSEngine *>(nullptr)))>>
135 {
136 static constexpr bool value = std::is_same_v<
137 decltype(WrapperT::create(static_cast<QQmlEngine *>(nullptr),
138 static_cast<QJSEngine *>(nullptr))), T *>;
139 };
140
141 template<typename T, typename WrapperT>
142 constexpr SingletonConstructionMode singletonConstructionMode()
143 {
144 if constexpr (!std::is_base_of<QObject, T>::value)
145 return SingletonConstructionMode::None;
146 if constexpr (!std::is_same_v<T, WrapperT> && HasSingletonFactory<T, WrapperT>::value)
147 return SingletonConstructionMode::FactoryWrapper;
148 if constexpr (std::is_default_constructible<T>::value)
149 return SingletonConstructionMode::Constructor;
150 if constexpr (HasSingletonFactory<T>::value)
151 return SingletonConstructionMode::Factory;
152
153 return SingletonConstructionMode::None;
154 }
155
156 template<typename>
157 struct QmlMarkerFunction;
158
159 template<typename Ret, typename Class>
160 struct QmlMarkerFunction<Ret (Class::*)()>
161 {
162 using ClassType = Class;
163 };
164
165 template<typename T, typename Marker>
166 using QmlTypeHasMarker = std::is_same<T, typename QmlMarkerFunction<Marker>::ClassType>;
167
168 template<typename T>
169 void createInto(void *memory, void *) { new (memory) QQmlElement<T>; }
170
171 template<typename T, typename WrapperT, SingletonConstructionMode Mode>
172 QObject *createSingletonInstance(QQmlEngine *q, QJSEngine *j)
173 {
174 Q_UNUSED(q);
175 Q_UNUSED(j);
176 if constexpr (Mode == SingletonConstructionMode::Constructor)
177 return new T;
178 else if constexpr (Mode == SingletonConstructionMode::Factory)
179 return T::create(q, j);
180 else if constexpr (Mode == SingletonConstructionMode::FactoryWrapper)
181 return WrapperT::create(q, j);
182 else
183 return nullptr;
184 }
185
186 template<typename T>
187 QObject *createParent(QObject *p) { return new T(p); }
188
189 using CreateIntoFunction = void (*)(void *, void *);
190 using CreateSingletonFunction = QObject *(*)(QQmlEngine *, QJSEngine *);
191 using CreateParentFunction = QObject *(*)(QObject *);
192 using CreateValueTypeFunction = QVariant (*)(const QJSValue &);
193
194 template<typename T, typename WrapperT = T,
195 SingletonConstructionMode Mode = singletonConstructionMode<T, WrapperT>()>
196 struct Constructors;
197
198 template<typename T, typename WrapperT>
199 struct Constructors<T, WrapperT, SingletonConstructionMode::Constructor>
200 {
201 static constexpr CreateIntoFunction createInto
202 = QQmlPrivate::createInto<T>;
203 static constexpr CreateSingletonFunction createSingletonInstance
204 = QQmlPrivate::createSingletonInstance<
205 T, WrapperT, SingletonConstructionMode::Constructor>;
206 };
207
208 template<typename T, typename WrapperT>
209 struct Constructors<T, WrapperT, SingletonConstructionMode::None>
210 {
211 static constexpr CreateIntoFunction createInto = nullptr;
212 static constexpr CreateSingletonFunction createSingletonInstance = nullptr;
213 };
214
215 template<typename T, typename WrapperT>
216 struct Constructors<T, WrapperT, SingletonConstructionMode::Factory>
217 {
218 static constexpr CreateIntoFunction createInto = nullptr;
219 static constexpr CreateSingletonFunction createSingletonInstance
220 = QQmlPrivate::createSingletonInstance<
221 T, WrapperT, SingletonConstructionMode::Factory>;
222 };
223
224 template<typename T, typename WrapperT>
225 struct Constructors<T, WrapperT, SingletonConstructionMode::FactoryWrapper>
226 {
227 static constexpr CreateIntoFunction createInto = nullptr;
228 static constexpr CreateSingletonFunction createSingletonInstance
229 = QQmlPrivate::createSingletonInstance<
230 T, WrapperT, SingletonConstructionMode::FactoryWrapper>;
231 };
232
233 template<typename T,
234 bool IsObject = std::is_base_of<QObject, T>::value,
235 bool IsGadget = QtPrivate::IsGadgetHelper<T>::IsRealGadget>
236 struct ExtendedType;
237
238 template<typename T>
239 struct ExtendedType<T, false, false>
240 {
241 static constexpr const CreateParentFunction createParent = nullptr;
242 static const QMetaObject *staticMetaObject() { return nullptr; }
243 };
244
245 // If it's a QObject, we actually want an error if the ctor or the metaobject is missing.
246 template<typename T>
247 struct ExtendedType<T, true, false>
248 {
249 static constexpr const CreateParentFunction createParent = QQmlPrivate::createParent<T>;
250 static const QMetaObject *staticMetaObject() { return &T::staticMetaObject; }
251 };
252
253 // If it's a Q_GADGET, we don't want the ctor.
254 template<typename T>
255 struct ExtendedType<T, false, true>
256 {
257 static constexpr const CreateParentFunction createParent = nullptr;
258 static const QMetaObject *staticMetaObject() { return &T::staticMetaObject; }
259 };
260
261 template<typename F, typename Result = void>
262 struct ValueTypeFactory
263 {
264 static constexpr const Result (*create)(const QJSValue &) = nullptr;
265 };
266
267 template<typename F>
268 struct ValueTypeFactory<F, std::void_t<decltype(F::create(QJSValue()))>>
269 {
270 static decltype(F::create(QJSValue())) create(const QJSValue &params)
271 {
272 return F::create(params);
273 }
274 };
275
276 template<typename T, typename F,
277 bool HasCtor = std::is_constructible_v<T, QJSValue>,
278 bool HasFactory = std::is_constructible_v<
279 QVariant, decltype(ValueTypeFactory<F>::create(QJSValue()))>>
280 struct ValueType;
281
282 template<typename T, typename F>
283 struct ValueType<T, F, false, false>
284 {
285 static constexpr const CreateValueTypeFunction create = nullptr;
286 };
287
288 template<typename T, typename F, bool HasCtor>
289 struct ValueType<T, F, HasCtor, true>
290 {
291 static QVariant create(const QJSValue &params)
292 {
293 return F::create(params);
294 }
295 };
296
297 template<typename T, typename F>
298 struct ValueType<T, F, true, false>
299 {
300 static QVariant create(const QJSValue &params)
301 {
302 return QVariant::fromValue(T(params));
303 }
304 };
305
306 template<class From, class To, int N>
307 struct StaticCastSelectorClass
308 {
309 static inline int cast() { return -1; }
310 };
311
312 template<class From, class To>
313 struct StaticCastSelectorClass<From, To, sizeof(int)>
314 {
315 static inline int cast() { return int(reinterpret_cast<quintptr>(static_cast<To *>(reinterpret_cast<From *>(0x10000000)))) - 0x10000000; }
316 };
317
318 template<class From, class To>
319 struct StaticCastSelector
320 {
321 typedef int yes_type;
322 typedef char no_type;
323
324 static yes_type checkType(To *);
325 static no_type checkType(...);
326
327 static inline int cast()
328 {
329 return StaticCastSelectorClass<From, To, sizeof(checkType(reinterpret_cast<From *>(0)))>::cast();
330 }
331 };
332
333 // You can prevent subclasses from using the same attached type by specialzing this.
334 // This is reserved for internal types, though.
335 template<class T, class A>
336 struct OverridableAttachedType
337 {
338 using Type = A;
339 };
340
341 template<class T, class = std::void_t<>, bool OldStyle = QQmlTypeInfo<T>::hasAttachedProperties>
342 struct QmlAttached
343 {
344 using Type = void;
345 using Func = QQmlAttachedPropertiesFunc<QObject>;
346 static const QMetaObject *staticMetaObject() { return nullptr; }
347 static Func attachedPropertiesFunc() { return nullptr; }
348 };
349
350 // Defined inline via QML_ATTACHED
351 template<class T>
352 struct QmlAttached<T, std::void_t<typename OverridableAttachedType<T, typename T::QmlAttachedType>::Type>, false>
353 {
354 // Normal attached properties
355 template <typename Parent, typename Attached>
356 struct Properties
357 {
358 using Func = QQmlAttachedPropertiesFunc<Attached>;
359 static const QMetaObject *staticMetaObject() { return &Attached::staticMetaObject; }
360 static Func attachedPropertiesFunc() { return Parent::qmlAttachedProperties; }
361 };
362
363 // Disabled via OverridableAttachedType
364 template<typename Parent>
365 struct Properties<Parent, void>
366 {
367 using Func = QQmlAttachedPropertiesFunc<QObject>;
368 static const QMetaObject *staticMetaObject() { return nullptr; };
369 static Func attachedPropertiesFunc() { return nullptr; };
370 };
371
372 using Type = typename std::conditional<
373 QmlTypeHasMarker<T, decltype(&T::qt_qmlMarker_attached)>::value,
374 typename OverridableAttachedType<T, typename T::QmlAttachedType>::Type, void>::type;
375 using Func = typename Properties<T, Type>::Func;
376
377 static const QMetaObject *staticMetaObject()
378 {
379 return Properties<T, Type>::staticMetaObject();
380 }
381
382 static Func attachedPropertiesFunc()
383 {
384 return Properties<T, Type>::attachedPropertiesFunc();
385 }
386 };
387
388 // Separately defined via QQmlTypeInfo
389 template<class T>
390 struct QmlAttached<T, std::void_t<decltype(T::qmlAttachedProperties)>, true>
391 {
392 using Type = typename std::remove_pointer<decltype(T::qmlAttachedProperties(nullptr))>::type;
393 using Func = QQmlAttachedPropertiesFunc<Type>;
394
395 static const QMetaObject *staticMetaObject() { return &Type::staticMetaObject; }
396 static Func attachedPropertiesFunc() { return T::qmlAttachedProperties; }
397 };
398
399 // This is necessary because both the type containing a default template parameter and the type
400 // instantiating the template need to have access to the default template parameter type. In
401 // this case that's T::QmlAttachedType. The QML_FOREIGN macro needs to befriend specific other
402 // types. Therefore we need some kind of "accessor". Because of compiler bugs in gcc and clang,
403 // we cannot befriend attachedPropertiesFunc() directly. Wrapping the actual access into another
404 // struct "fixes" that. For convenience we still want the free standing functions in addition.
405 template<class T>
406 struct QmlAttachedAccessor
407 {
408 static QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunc()
409 {
410 return QQmlAttachedPropertiesFunc<QObject>(QmlAttached<T>::attachedPropertiesFunc());
411 }
412
413 static const QMetaObject *staticMetaObject()
414 {
415 return QmlAttached<T>::staticMetaObject();
416 }
417 };
418
419 template<typename T>
420 inline QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunc()
421 {
422 return QmlAttachedAccessor<T>::attachedPropertiesFunc();
423 }
424
425 template<typename T>
426 inline const QMetaObject *attachedPropertiesMetaObject()
427 {
428 return QmlAttachedAccessor<T>::staticMetaObject();
429 }
430
431 enum AutoParentResult { Parented, IncompatibleObject, IncompatibleParent };
432 typedef AutoParentResult (*AutoParentFunction)(QObject *object, QObject *parent);
433
434 enum class ValueTypeCreationMethod { None, Construct, Structured };
435
436 struct RegisterType {
437 enum StructVersion: int {
438 Base = 0,
439 FinalizerCast = 1,
440 CreationMethod = 2,
441 CurrentVersion = CreationMethod,
442 };
443
444 bool has(StructVersion v) const { return structVersion >= int(v); }
445
446 int structVersion;
447
448 QMetaType typeId;
449 QMetaType listId;
450 int objectSize;
451 // The second parameter of create is for userdata
452 void (*create)(void *, void *);
453 void *userdata;
454 QString noCreationReason;
455
456 // ### Qt7: Get rid of this. It can be covered by creationMethod below.
457 QVariant (*createValueType)(const QJSValue &);
458
459 const char *uri;
460 QTypeRevision version;
461 const char *elementName;
462 const QMetaObject *metaObject;
463
464 QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunction;
465 const QMetaObject *attachedPropertiesMetaObject;
466
467 int parserStatusCast;
468 int valueSourceCast;
469 int valueInterceptorCast;
470
471 QObject *(*extensionObjectCreate)(QObject *);
472 const QMetaObject *extensionMetaObject;
473
474 QQmlCustomParser *customParser;
475
476 QTypeRevision revision;
477 int finalizerCast;
478
479 ValueTypeCreationMethod creationMethod;
480 // If this is extended ensure "version" is bumped!!!
481 };
482
483 struct RegisterTypeAndRevisions {
484 int structVersion;
485
486 QMetaType typeId;
487 QMetaType listId;
488 int objectSize;
489 void (*create)(void *, void *);
490 void *userdata;
491
492 QVariant (*createValueType)(const QJSValue &);
493
494 const char *uri;
495 QTypeRevision version;
496
497 const QMetaObject *metaObject;
498 const QMetaObject *classInfoMetaObject;
499
500 QQmlAttachedPropertiesFunc<QObject> attachedPropertiesFunction;
501 const QMetaObject *attachedPropertiesMetaObject;
502
503 int parserStatusCast;
504 int valueSourceCast;
505 int valueInterceptorCast;
506
507 QObject *(*extensionObjectCreate)(QObject *);
508 const QMetaObject *extensionMetaObject;
509
510 QQmlCustomParser *(*customParserFactory)();
511 QVector<int> *qmlTypeIds;
512 int finalizerCast;
513
514 bool forceAnonymous;
515 QMetaSequence listMetaSequence;
516 };
517
518 struct RegisterInterface {
519 int structVersion;
520
521 QMetaType typeId;
522 QMetaType listId;
523
524 const char *iid;
525
526 const char *uri;
527 QTypeRevision version;
528 };
529
530 struct RegisterAutoParent {
531 int structVersion;
532
533 AutoParentFunction function;
534 };
535
536 struct RegisterSingletonType {
537 int structVersion;
538
539 const char *uri;
540 QTypeRevision version;
541 const char *typeName;
542
543 std::function<QJSValue(QQmlEngine *, QJSEngine *)> scriptApi;
544 std::function<QObject*(QQmlEngine *, QJSEngine *)> qObjectApi;
545
546 const QMetaObject *instanceMetaObject;
547 QMetaType typeId;
548
549 QObject *(*extensionObjectCreate)(QObject *);
550 const QMetaObject *extensionMetaObject;
551
552 QTypeRevision revision;
553 };
554
555 struct RegisterSingletonTypeAndRevisions {
556 int structVersion;
557 const char *uri;
558 QTypeRevision version;
559
560 std::function<QObject*(QQmlEngine *, QJSEngine *)> qObjectApi;
561
562 const QMetaObject *instanceMetaObject;
563 const QMetaObject *classInfoMetaObject;
564
565 QMetaType typeId;
566
567 QObject *(*extensionObjectCreate)(QObject *);
568 const QMetaObject *extensionMetaObject;
569
570 QVector<int> *qmlTypeIds;
571 };
572
573 struct RegisterCompositeType {
574 int structVersion;
575 QUrl url;
576 const char *uri;
577 QTypeRevision version;
578 const char *typeName;
579 };
580
581 struct RegisterCompositeSingletonType {
582 int structVersion;
583 QUrl url;
584 const char *uri;
585 QTypeRevision version;
586 const char *typeName;
587 };
588
589 struct RegisterSequentialContainer {
590 int structVersion;
591 const char *uri;
592 QTypeRevision version;
593
594 // ### Qt7: Remove typeName. It's ignored because the only valid name is "list",
595 // and that's automatic.
596 const char *typeName;
597
598 QMetaType typeId;
599 QMetaSequence metaSequence;
600 QTypeRevision revision;
601 };
602
603 struct RegisterSequentialContainerAndRevisions {
604 int structVersion;
605 const char *uri;
606 QTypeRevision version;
607
608 const QMetaObject *classInfoMetaObject;
609 QMetaType typeId;
610 QMetaSequence metaSequence;
611
612 QVector<int> *qmlTypeIds;
613 };
614
615 struct Q_QML_EXPORT AOTCompiledContext {
616 enum: uint { InvalidStringId = (std::numeric_limits<uint>::max)() };
617
618 QQmlContextData *qmlContext;
619 QObject *qmlScopeObject;
620 QJSEngine *engine;
621 union {
622 QV4::ExecutableCompilationUnit *compilationUnit;
623 qintptr extraData;
624 };
625
626 QObject *thisObject() const;
627 QQmlEngine *qmlEngine() const;
628
629 QJSValue jsMetaType(int index) const;
630 void setInstructionPointer(int offset) const;
631 void setReturnValueUndefined() const;
632
633 // Run QQmlPropertyCapture::captureProperty() without retrieving the value.
634 bool captureLookup(uint index, QObject *object) const;
635 bool captureQmlContextPropertyLookup(uint index) const;
636 void captureTranslation() const;
637 QString translationContext() const;
638 QMetaType lookupResultMetaType(uint index) const;
639 void storeNameSloppy(uint nameIndex, void *value, QMetaType type) const;
640 QJSValue javaScriptGlobalProperty(uint nameIndex) const;
641
642 const QLoggingCategory *resolveLoggingCategory(QObject *wrapper, bool *ok) const;
643
644 void writeToConsole(
645 QtMsgType type, const QString &message,
646 const QLoggingCategory *loggingCategory) const;
647
648 QVariant constructValueType(
649 QMetaType resultMetaType, const QMetaObject *resultMetaObject,
650 int ctorIndex, void *ctorArg) const;
651
652 // All of these lookup functions should be used as follows:
653 //
654 // while (!fooBarLookup(...)) {
655 // setInstructionPointer(...);
656 // initFooBarLookup(...);
657 // if (engine->hasException()) {
658 // ...
659 // break;
660 // }
661 // }
662 //
663 // The bool-returning *Lookup functions exclusively run the happy path and return false if
664 // that fails in any way. The failure may either be in the lookup structs not being
665 // initialized or an exception being thrown.
666 // The init*Lookup functions initialize the lookup structs and amend any exceptions
667 // previously thrown with line numbers. They might also throw their own exceptions. If an
668 // exception is present after the initialization there is no way to carry out the lookup and
669 // the exception should be propagated. If not, the original lookup can be tried again.
670
671 bool callQmlContextPropertyLookup(
672 uint index, void **args, const QMetaType *types, int argc) const;
673 void initCallQmlContextPropertyLookup(uint index) const;
674
675 bool loadContextIdLookup(uint index, void *target) const;
676 void initLoadContextIdLookup(uint index) const;
677
678 bool callObjectPropertyLookup(uint index, QObject *object,
679 void **args, const QMetaType *types, int argc) const;
680 void initCallObjectPropertyLookup(uint index) const;
681
682 bool callGlobalLookup(uint index, void **args, const QMetaType *types, int argc) const;
683 void initCallGlobalLookup(uint index) const;
684
685 bool loadGlobalLookup(uint index, void *target, QMetaType type) const;
686 void initLoadGlobalLookup(uint index) const;
687
688 bool loadScopeObjectPropertyLookup(uint index, void *target) const;
689 void initLoadScopeObjectPropertyLookup(uint index, QMetaType type) const;
690
691 bool loadSingletonLookup(uint index, void *target) const;
692 void initLoadSingletonLookup(uint index, uint importNamespace) const;
693
694 bool loadAttachedLookup(uint index, QObject *object, void *target) const;
695 void initLoadAttachedLookup(uint index, uint importNamespace, QObject *object) const;
696
697 bool loadTypeLookup(uint index, void *target) const;
698 void initLoadTypeLookup(uint index, uint importNamespace) const;
699
700 bool getObjectLookup(uint index, QObject *object, void *target) const;
701 void initGetObjectLookup(uint index, QObject *object, QMetaType type) const;
702
703 bool getValueLookup(uint index, void *value, void *target) const;
704 void initGetValueLookup(uint index, const QMetaObject *metaObject, QMetaType type) const;
705
706 bool getEnumLookup(uint index, void *target) const;
707 void initGetEnumLookup(uint index, const QMetaObject *metaObject,
708 const char *enumerator, const char *enumValue) const;
709
710 bool setObjectLookup(uint index, QObject *object, void *value) const;
711 void initSetObjectLookup(uint index, QObject *object, QMetaType type) const;
712
713 bool setValueLookup(uint index, void *target, void *value) const;
714 void initSetValueLookup(uint index, const QMetaObject *metaObject, QMetaType type) const;
715 };
716
717 struct AOTCompiledFunction {
718 qintptr extraData;
719 QMetaType returnType;
720 QList<QMetaType> argumentTypes;
721 void (*functionPtr)(const AOTCompiledContext *context, void *resultPtr, void **arguments);
722 };
723
724#if QT_DEPRECATED_SINCE(6, 6)
725 QT_DEPRECATED_VERSION_X(6, 6, "Use AOTCompiledFunction instead")
726 typedef AOTCompiledFunction TypedFunction;
727#endif
728
729 struct CachedQmlUnit {
730 const QV4::CompiledData::Unit *qmlData;
731 const AOTCompiledFunction *aotCompiledFunctions;
732 void *unused2;
733 };
734
735 typedef const CachedQmlUnit *(*QmlUnitCacheLookupFunction)(const QUrl &url);
736 struct RegisterQmlUnitCacheHook {
737 int structVersion;
738 QmlUnitCacheLookupFunction lookupCachedQmlUnit;
739 };
740
741 enum RegistrationType {
742 TypeRegistration = 0,
743 InterfaceRegistration = 1,
744 AutoParentRegistration = 2,
745 SingletonRegistration = 3,
746 CompositeRegistration = 4,
747 CompositeSingletonRegistration = 5,
748 QmlUnitCacheHookRegistration = 6,
749 TypeAndRevisionsRegistration = 7,
750 SingletonAndRevisionsRegistration = 8,
751 SequentialContainerRegistration = 9,
752 SequentialContainerAndRevisionsRegistration = 10,
753 };
754
755 int Q_QML_EXPORT qmlregister(RegistrationType, void *);
756 void Q_QML_EXPORT qmlunregister(RegistrationType, quintptr);
757
758#if QT_DEPRECATED_SINCE(6, 3)
759 struct Q_QML_EXPORT SingletonFunctor
760 {
761 QT_DEPRECATED QObject *operator()(QQmlEngine *, QJSEngine *);
762 QPointer<QObject> m_object;
763 bool alreadyCalled = false;
764 };
765#endif
766
767 struct Q_QML_EXPORT SingletonInstanceFunctor
768 {
769 QObject *operator()(QQmlEngine *, QJSEngine *);
770
771 QPointer<QObject> m_object;
772
773 // Not a QPointer, so that you cannot assign it to a different
774 // engine when the first one is deleted.
775 // That would mess up the QML contexts.
776 QQmlEngine *m_engine = nullptr;
777 };
778
779 static int indexOfOwnClassInfo(const QMetaObject *metaObject, const char *key, int startOffset = -1)
780 {
781 if (!metaObject || !key)
782 return -1;
783
784 const int offset = metaObject->classInfoOffset();
785 const int start = (startOffset == -1)
786 ? (metaObject->classInfoCount() + offset - 1)
787 : startOffset;
788 for (int i = start; i >= offset; --i)
789 if (qstrcmp(str1: key, str2: metaObject->classInfo(index: i).name()) == 0) {
790 return i;
791 }
792 return -1;
793 }
794
795 inline const char *classInfo(const QMetaObject *metaObject, const char *key)
796 {
797 return metaObject->classInfo(index: indexOfOwnClassInfo(metaObject, key)).value();
798 }
799
800 inline QTypeRevision revisionClassInfo(const QMetaObject *metaObject, const char *key,
801 QTypeRevision defaultValue = QTypeRevision())
802 {
803 const int index = indexOfOwnClassInfo(metaObject, key);
804 return (index == -1) ? defaultValue
805 : QTypeRevision::fromEncodedVersion(
806 value: QLatin1StringView(metaObject->classInfo(index).value()).toInt());
807 }
808
809 Q_QML_EXPORT QList<QTypeRevision> revisionClassInfos(const QMetaObject *metaObject, const char *key);
810
811 inline bool boolClassInfo(const QMetaObject *metaObject, const char *key,
812 bool defaultValue = false)
813 {
814 const int index = indexOfOwnClassInfo(metaObject, key);
815 if (index == -1)
816 return defaultValue;
817 return qstrcmp(str1: metaObject->classInfo(index).value(), str2: "true") == 0;
818 }
819
820 inline const char *classElementName(const QMetaObject *metaObject)
821 {
822 const char *elementName = classInfo(metaObject, key: "QML.Element");
823 if (qstrcmp(str1: elementName, str2: "auto") == 0) {
824 const char *strippedClassName = metaObject->className();
825 for (const char *c = strippedClassName; *c != '\0'; c++) {
826 if (*c == ':')
827 strippedClassName = c + 1;
828 }
829
830 return strippedClassName;
831 }
832 if (qstrcmp(str1: elementName, str2: "anonymous") == 0)
833 return nullptr;
834
835 if (!elementName) {
836 qWarning().nospace() << "Missing QML.Element class info \"" << elementName << "\""
837 << " for " << metaObject->className();
838 }
839
840 return elementName;
841 }
842
843 template<class T, class = std::void_t<>>
844 struct QmlExtended
845 {
846 using Type = void;
847 };
848
849 template<class T>
850 struct QmlExtended<T, std::void_t<typename T::QmlExtendedType>>
851 {
852 using Type = typename std::conditional<
853 QmlTypeHasMarker<T, decltype(&T::qt_qmlMarker_extended)>::value,
854 typename T::QmlExtendedType, void>::type;
855 };
856
857 template<class T, class = std::void_t<>>
858 struct QmlExtendedNamespace
859 {
860 static constexpr const QMetaObject *metaObject() { return nullptr; }
861 };
862
863 template<class T>
864 struct QmlExtendedNamespace<T, std::void_t<decltype(T::qmlExtendedNamespace())>>
865 {
866 static constexpr const QMetaObject *metaObject()
867 {
868 if constexpr (QmlTypeHasMarker<T, decltype(&T::qt_qmlMarker_extendedNamespace)>::value)
869 return T::qmlExtendedNamespace();
870 else
871 return nullptr;
872 }
873 };
874
875 template<class T, class = std::void_t<>>
876 struct QmlResolved
877 {
878 using Type = T;
879 };
880
881 template<class T>
882 struct QmlResolved<T, std::void_t<typename T::QmlForeignType>>
883 {
884 using Type = typename std::conditional<
885 QmlTypeHasMarker<T, decltype(&T::qt_qmlMarker_foreign)>::value,
886 typename T::QmlForeignType, T>::type;
887 };
888
889 template<class T, class = std::void_t<>>
890 struct QmlUncreatable
891 {
892 static constexpr bool Value = false;
893 };
894
895 template<class T>
896 struct QmlUncreatable<T, std::void_t<typename T::QmlIsUncreatable>>
897 {
898 static constexpr bool Value =
899 QmlTypeHasMarker<T, decltype(&T::qt_qmlMarker_uncreatable)>::value
900 && bool(T::QmlIsUncreatable::yes);
901 };
902
903 template<class T, class = std::void_t<>>
904 struct QmlAnonymous
905 {
906 static constexpr bool Value = false;
907 };
908
909 template<class T>
910 struct QmlAnonymous<T, std::void_t<typename T::QmlIsAnonymous>>
911 {
912 static constexpr bool Value =
913 QmlTypeHasMarker<T, decltype(&T::qt_qmlMarker_anonymous)>::value
914 && bool(T::QmlIsAnonymous::yes);
915 };
916
917
918 template<class T, class = std::void_t<>>
919 struct QmlSingleton
920 {
921 static constexpr bool Value = false;
922 };
923
924 template<class T>
925 struct QmlSingleton<T, std::void_t<typename T::QmlIsSingleton>>
926 {
927 static constexpr bool Value =
928 QmlTypeHasMarker<T, decltype(&T::qt_qmlMarker_singleton)>::value
929 && bool(T::QmlIsSingleton::yes);
930 };
931
932 template<class T, class = std::void_t<>>
933 struct QmlSequence
934 {
935 static constexpr bool Value = false;
936 };
937
938 template<class T>
939 struct QmlSequence<T, std::void_t<typename T::QmlIsSequence>>
940 {
941 Q_STATIC_ASSERT((std::is_same_v<typename T::QmlSequenceValueType,
942 typename QmlResolved<T>::Type::value_type>));
943 static constexpr bool Value = bool(T::QmlIsSequence::yes);
944 };
945
946 template<class T, class = std::void_t<>>
947 struct QmlInterface
948 {
949 static constexpr bool Value = false;
950 };
951
952 template<class T>
953 struct QmlInterface<T, std::void_t<typename T::QmlIsInterface>>
954 {
955 static constexpr bool Value = bool(T::QmlIsInterface::yes);
956 };
957
958 template<class T, typename = std::void_t<>>
959 struct StaticMetaObject
960 {
961 static const QMetaObject *staticMetaObject() { return nullptr; }
962 };
963
964 template<class T>
965 struct StaticMetaObject<T, std::void_t<decltype(T::staticMetaObject)>>
966 {
967 static const QMetaObject *staticMetaObject() { return &T::staticMetaObject; }
968 };
969
970 template<class T>
971 struct QmlMetaType
972 {
973 static constexpr bool hasAcceptableCtors()
974 {
975 if constexpr (!std::is_default_constructible_v<T>)
976 return false;
977 else if constexpr (std::is_base_of_v<QObject, T>)
978 return true;
979 else
980 return std::is_copy_constructible_v<T>;
981 }
982
983 static QMetaType self()
984 {
985 if constexpr (std::is_base_of_v<QObject, T>)
986 return QMetaType::fromType<T*>();
987 else
988 return QMetaType::fromType<T>();
989 }
990
991 static QMetaType list()
992 {
993 if constexpr (std::is_base_of_v<QObject, T>)
994 return QMetaType::fromType<QQmlListProperty<T>>();
995 else
996 return QMetaType::fromType<QList<T>>();
997 }
998
999 static QMetaSequence sequence()
1000 {
1001 if constexpr (std::is_base_of_v<QObject, T>)
1002 return QMetaSequence();
1003 else
1004 return QMetaSequence::fromContainer<QList<T>>();
1005 }
1006 };
1007
1008 template<typename T, typename E, typename WrapperT = T>
1009 void qmlRegisterSingletonAndRevisions(const char *uri, int versionMajor,
1010 const QMetaObject *classInfoMetaObject,
1011 QVector<int> *qmlTypeIds, const QMetaObject *extension)
1012 {
1013 static_assert(std::is_base_of_v<QObject, T>);
1014 RegisterSingletonTypeAndRevisions api = {
1015 0,
1016
1017 uri,
1018 QTypeRevision::fromMajorVersion(majorVersion: versionMajor),
1019
1020 Constructors<T, WrapperT>::createSingletonInstance,
1021
1022 StaticMetaObject<T>::staticMetaObject(),
1023 classInfoMetaObject,
1024
1025 QmlMetaType<T>::self(),
1026
1027 ExtendedType<E>::createParent,
1028 extension ? extension : ExtendedType<E>::staticMetaObject(),
1029
1030 qmlTypeIds
1031 };
1032
1033 qmlregister(SingletonAndRevisionsRegistration, &api);
1034 }
1035
1036 template<typename T, typename E>
1037 void qmlRegisterTypeAndRevisions(const char *uri, int versionMajor,
1038 const QMetaObject *classInfoMetaObject,
1039 QVector<int> *qmlTypeIds, const QMetaObject *extension,
1040 bool forceAnonymous = false)
1041 {
1042 RegisterTypeAndRevisions type = {
1043 3,
1044 QmlMetaType<T>::self(),
1045 QmlMetaType<T>::list(),
1046 int(sizeof(T)),
1047 Constructors<T>::createInto,
1048 nullptr,
1049 ValueType<T, E>::create,
1050
1051 uri,
1052 QTypeRevision::fromMajorVersion(majorVersion: versionMajor),
1053
1054 StaticMetaObject<T>::staticMetaObject(),
1055 classInfoMetaObject,
1056
1057 attachedPropertiesFunc<T>(),
1058 attachedPropertiesMetaObject<T>(),
1059
1060 StaticCastSelector<T, QQmlParserStatus>::cast(),
1061 StaticCastSelector<T, QQmlPropertyValueSource>::cast(),
1062 StaticCastSelector<T, QQmlPropertyValueInterceptor>::cast(),
1063
1064 ExtendedType<E>::createParent,
1065 extension ? extension : ExtendedType<E>::staticMetaObject(),
1066
1067 &qmlCreateCustomParser<T>,
1068 qmlTypeIds,
1069 StaticCastSelector<T, QQmlFinalizerHook>::cast(),
1070
1071 forceAnonymous,
1072 QmlMetaType<T>::sequence(),
1073 };
1074
1075 // Initialize the extension so that we can find it by name or ID.
1076 qMetaTypeId<E>();
1077
1078 qmlregister(TypeAndRevisionsRegistration, &type);
1079 }
1080
1081 template<typename T>
1082 void qmlRegisterSequenceAndRevisions(const char *uri, int versionMajor,
1083 const QMetaObject *classInfoMetaObject,
1084 QVector<int> *qmlTypeIds)
1085 {
1086 RegisterSequentialContainerAndRevisions type = {
1087 0,
1088 uri,
1089 QTypeRevision::fromMajorVersion(majorVersion: versionMajor),
1090 classInfoMetaObject,
1091 QMetaType::fromType<T>(),
1092 QMetaSequence::fromContainer<T>(),
1093 qmlTypeIds
1094 };
1095
1096 qmlregister(SequentialContainerAndRevisionsRegistration, &type);
1097 }
1098
1099 template<>
1100 void Q_QML_EXPORT qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>(
1101 const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject,
1102 QVector<int> *qmlTypeIds, const QMetaObject *, bool);
1103
1104 constexpr QtPrivate::QMetaTypeInterface metaTypeForNamespace(
1105 const QtPrivate::QMetaTypeInterface::MetaObjectFn &metaObjectFunction, const char *name)
1106 {
1107 return {
1108 /*.revision=*/ .revision: 0,
1109 /*.alignment=*/ .alignment: 0,
1110 /*.size=*/ .size: 0,
1111 /*.flags=*/ .flags: 0,
1112 /*.typeId=*/ .typeId: {},
1113 /*.metaObject=*/ .metaObjectFn: metaObjectFunction,
1114 /*.name=*/ .name: name,
1115 /*.defaultCtr=*/ .defaultCtr: nullptr,
1116 /*.copyCtr=*/ .copyCtr: nullptr,
1117 /*.moveCtr=*/ .moveCtr: nullptr,
1118 /*.dtor=*/ .dtor: nullptr,
1119 /*.equals*/ .equals: nullptr,
1120 /*.lessThan*/ .lessThan: nullptr,
1121 /*.debugStream=*/ .debugStream: nullptr,
1122 /*.dataStreamOut=*/ .dataStreamOut: nullptr,
1123 /*.dataStreamIn=*/ .dataStreamIn: nullptr,
1124 /*.legacyRegisterOp=*/ .legacyRegisterOp: nullptr
1125 };
1126 }
1127
1128 Q_QML_EXPORT QObject *qmlExtendedObject(QObject *, int);
1129
1130 enum QmlRegistrationWarning {
1131 UnconstructibleType,
1132 UnconstructibleSingleton,
1133 NonQObjectWithAtached,
1134 };
1135
1136 Q_QML_EXPORT void qmlRegistrationWarning(QmlRegistrationWarning warning, QMetaType type);
1137
1138} // namespace QQmlPrivate
1139
1140QT_END_NAMESPACE
1141
1142#endif // QQMLPRIVATE_H
1143

source code of qtdeclarative/src/qml/qml/qqmlprivate.h