Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlpropertycache_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
5#ifndef QQMLPROPERTYCACHE_P_H
6#define QQMLPROPERTYCACHE_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qlinkedstringhash_p.h>
20#include <private/qqmlenumdata_p.h>
21#include <private/qqmlenumvalue_p.h>
22#include <private/qqmlpropertydata_p.h>
23#include <private/qqmlrefcount_p.h>
24#include <private/qexpected_p.h>
25
26#include <QtCore/qvarlengtharray.h>
27#include <QtCore/qvector.h>
28#include <QtCore/qversionnumber.h>
29#include <QtCore/qxpfunctional.h>
30#include <QtCore/qloggingcategory.h>
31
32#include <limits>
33
34class tst_qqmlpropertycache;
35
36QT_BEGIN_NAMESPACE
37
38class QCryptographicHash;
39class QJSEngine;
40class QMetaObjectBuilder;
41class QQmlContextData;
42class QQmlPropertyCache;
44class QQmlVMEMetaObject;
45
47{
48public:
50
56
58 {
59 const auto dd = d.loadAcquire();
60 if (dd & Shared)
61 reinterpret_cast<SharedHolder *>(dd ^ Shared)->release();
62 }
63
64private:
65 friend class QQmlPropertyCache;
67 : d(other.d.loadRelaxed())
68 {
69 // other has to survive until this ctor is done. So d cannot disappear before.
70 const auto od = other.d.loadRelaxed();
71 if (od & Shared)
72 reinterpret_cast<SharedHolder *>(od ^ Shared)->addref();
73 }
74
75 QQmlMetaObjectPointer(QQmlMetaObjectPointer &&other) = delete;
76 QQmlMetaObjectPointer &operator=(QQmlMetaObjectPointer &&other) = delete;
77 QQmlMetaObjectPointer &operator=(const QQmlMetaObjectPointer &other) = delete;
78
79public:
80 void setSharedOnce(QMetaObject *shared) const
81 {
82 SharedHolder *holder = new SharedHolder(shared);
83 if (!d.testAndSetRelease(0, quintptr(holder) | Shared))
84 holder->release();
85 }
86
87 const QMetaObject *metaObject() const
88 {
89 const auto dd = d.loadAcquire();
90 if (dd & Shared)
91 return reinterpret_cast<SharedHolder *>(dd ^ Shared)->metaObject;
92 return reinterpret_cast<const QMetaObject *>(dd);
93 }
94
95 bool isShared() const
96 {
97 // This works because static metaobjects need to be set in the ctor and once a shared
98 // metaobject has been set, it cannot be removed anymore.
99 const auto dd = d.loadRelaxed();
100 return !dd || (dd & Shared);
101 }
102
103 bool isNull() const
104 {
105 return d.loadRelaxed() == 0;
106 }
107
108private:
109 enum Tag {
110 Static = 0,
111 Shared = 1
112 };
113
114 struct SharedHolder final : public QQmlRefCounted<SharedHolder>
115 {
116 Q_DISABLE_COPY_MOVE(SharedHolder)
117 SharedHolder(QMetaObject *shared) : metaObject(shared) {}
118 ~SharedHolder() { free(metaObject); }
119 QMetaObject *metaObject;
120 };
121
122 mutable QBasicAtomicInteger<quintptr> d = 0;
123};
124
125// TODO should be moved somewhere else?
126namespace OverrideSemantics {
127enum class Status : uint8_t {
128 Valid = 0,
129 NoOverride, // Derived { (virtual|final) property var a;} Base {}
130
131 MissingBase, // Derived { override property var a;} Base {}
132 OverridingFinal, // Derived { * property var a;} Base {final property var a;}
133 OverridingNonVirtual, // Derived { (virtual|final) property var a;} Base {property var a;}
134 OverridingNonVirtualError, // Derived { override property var a;} Base {property var a;}
135 MissingOverrideOrFinalSpecifier, // Derived { (virtual) property var a;} Base { virtual property var a;}
136
137 InvokabilityMismatch, // property overrides method(function, slot, invokable) or vice-versa
138
140};
141
142inline bool isValidOverride(Status res)
143{
144 return res == Status::NoOverride
145 || res == Status::Valid
146 // MissingOverrideOrFinalSpecifier, OverridingNonVirtual and InvokabilityMismatch
147 // are currently considered valid to preserve backwards compatibility.
148 // It will become invalid in Qt7
151}
152
153enum class CheckMode : uint8_t {
154 Minimal = 0, // pre virtual and override keywords
156};
157
158[[nodiscard]] Q_AUTOTEST_EXPORT Status handleOverride(QQmlPropertyData &overridingProperty,
161
164
165} // namespace OverrideSemantics
166
167Q_DECLARE_LOGGING_CATEGORY(qqmlPropertyCacheAppend)
168
169/*
170 * QQmlPropertyCache has the following structure:
171 *
172 * It maintains a non-owning map (StringCache) that associates each property name
173 * with a pointer to a QQmlPropertyData object. Each pointer refers to an element
174 * stored in one of the owning containers — for example, PropertyIndexCache or
175 * MethodsIndexCache.
176 *
177 * As a result, if an owning container such as PropertyIndexCache is resized,
178 * the entries in StringCache become invalid.
179 *
180 * To protect users of this class from such undefined behavior, most modifying
181 * methods are kept private. A few trusted classes, such as QQmlPropertyCacheCreator,
182 * are declared as friends. As the name suggests, QQmlPropertyCacheCreator is responsible
183 * for constructing and populating a QQmlPropertyCache instance in one controlled place,
184 * ensuring that all indices and data remain coherent.
185 *
186 * Because the internal logic of this class is non-trivial, the unit test
187 * (tst_qqmlpropertycache) is also declared as a friend to support proper testing
188 * and maintainability.
189 */
190class Q_QML_EXPORT QQmlPropertyCache final : public QQmlRefCounted<QQmlPropertyCache>
191{
192public:
193 using Ptr = QQmlRefPointer<QQmlPropertyCache>;
194
195 struct ConstPtr : public QQmlRefPointer<const QQmlPropertyCache>
196 {
197 using QQmlRefPointer<const QQmlPropertyCache>::QQmlRefPointer;
198
199 ConstPtr(const Ptr &ptr) : ConstPtr(ptr.data(), AddRef) {}
200 ConstPtr(Ptr &&ptr) : ConstPtr(ptr.take(), Adopt) {}
201 ConstPtr &operator=(const Ptr &ptr) { return operator=(ConstPtr(ptr)); }
202 ConstPtr &operator=(Ptr &&ptr) { return operator=(ConstPtr(std::move(ptr))); }
203 };
204
205 static Ptr createStandalone(
206 const QMetaObject *, QTypeRevision metaObjectRevision = QTypeRevision::zero());
207
208 QQmlPropertyCache(
209 OverrideSemantics::HandlerRef handleOverride = OverrideSemantics::handleOverride)
210 : _handleOverride(handleOverride) { };
211 ~QQmlPropertyCache();
212
213 void update(const QMetaObject *);
214 void invalidate(const QMetaObject *);
215
216 QQmlPropertyCache::Ptr copy() const;
217
218 QQmlPropertyCache::Ptr copyAndAppend(
219 const QMetaObject *, QTypeRevision typeVersion,
220 QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
221 QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
222 QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags()) const;
223
224 QQmlPropertyCache::Ptr copyAndReserve(
225 int propertyCount, int methodCount, int signalCount, int enumCount) const;
226
227 const QMetaObject *metaObject() const;
228 const QMetaObject *createMetaObject() const;
229 const QMetaObject *firstCppMetaObject() const;
230
231 template<typename K>
232 const QQmlPropertyData *property(const K &key, QObject *object,
233 const QQmlRefPointer<QQmlContextData> &context) const
234 {
235 return findProperty(stringCache.find(key), object, context);
236 }
237
238 const QQmlPropertyData *property(int) const;
239 const QQmlPropertyData *maybeUnresolvedProperty(int) const;
240 const QQmlPropertyData *method(int) const;
241 const QQmlPropertyData *signal(int index) const;
242 QQmlEnumData *qmlEnum(int) const;
243 int methodIndexToSignalIndex(int) const;
244
245 QString defaultPropertyName() const;
246 const QQmlPropertyData *defaultProperty() const;
247
248 // Return a reference here so that we don't have to addref/release all the time
249 inline const QQmlPropertyCache::ConstPtr &parent() const;
250
251 // is used by the Qml Designer
252 void setParent(QQmlPropertyCache::ConstPtr newParent);
253
254 inline const QQmlPropertyData *overrideData(const QQmlPropertyData *) const;
255 inline bool isAllowedInRevision(const QQmlPropertyData *) const;
256
257 static const QQmlPropertyData *property(
258 QObject *, QStringView, const QQmlRefPointer<QQmlContextData> &,
259 QQmlPropertyData *);
260 static const QQmlPropertyData *property(QObject *, const QLatin1String &, const QQmlRefPointer<QQmlContextData> &,
261 QQmlPropertyData *);
262 static const QQmlPropertyData *property(QObject *, const QV4::String *, const QQmlRefPointer<QQmlContextData> &,
263 QQmlPropertyData *);
264
265 //see QMetaObjectPrivate::originalClone
266 int originalClone(int index) const;
267 static int originalClone(const QObject *, int index);
268
269 QList<QByteArray> signalParameterNames(int index) const;
270 static QString signalParameterStringForJS(
271 const QList<QByteArray> &parameterNameList, QString *errorString = nullptr);
272
273 const char *className() const;
274
275 inline int propertyCount() const;
276 inline int ownPropertyCount() const { return int(propertyIndexCache.count()); }
277 inline int propertyOffset() const;
278 inline int methodCount() const;
279 inline int ownMethodCount() const { return int(methodIndexCache.count()); }
280 inline int methodOffset() const;
281 inline int signalCount() const;
282 inline int ownSignalCount() const { return int(signalHandlerIndexCache.count()); }
283 inline int signalOffset() const;
284 inline int ownEnumCount() const;
285
286 void toMetaObjectBuilder(QMetaObjectBuilder &) const;
287
288 inline bool callJSFactoryMethod(QObject *object, void **args) const;
289
290 static bool determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount, int *stringCount);
291 static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
292
293 QByteArray checksum(QHash<quintptr, QByteArray> *checksums, bool *ok) const;
294
295 QTypeRevision allowedRevision(int index) const { return allowedRevisionCache[index]; }
296 void setAllowedRevision(int index, QTypeRevision allowed) { allowedRevisionCache[index] = allowed; }
297
298private:
299 friend class QQmlEnginePrivate;
300 friend class QQmlCompiler;
301 template <typename T> friend class QQmlPropertyCacheCreator;
302 template <typename T> friend class QQmlPropertyCacheAliasCreator;
303 template <typename T> friend class QQmlComponentAndAliasResolver;
304 friend class QQmlMetaObject;
305 friend class ::tst_qqmlpropertycache;
306
307 QQmlPropertyCache(
308 const QQmlMetaObjectPointer &metaObject,
309 OverrideSemantics::HandlerRef handleOverride = OverrideSemantics::handleOverride)
310 : _handleOverride(handleOverride), _metaObject(metaObject)
311 {
312 }
313
314 inline QQmlPropertyCache::Ptr copy(const QQmlMetaObjectPointer &mo, int reserve) const;
315
316 void append(const QMetaObject *, QTypeRevision typeVersion,
317 QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
318 QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
319 QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
320
321 // TODO incorporate warning from maybeLog
322 using Error = OverrideSemantics::Status;
323 using AppendResult = q23::expected<void, Error>;
324
325 // TODO QTBUG-141728
326 // Always adds a property to the propertyIndex even if override semantics are invalid, not
327 // accessible by name though
328 AppendResult appendPropertyAttr(const QString &name, QQmlPropertyData &&data);
329 AppendResult appendAlias(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
330 QMetaType propType, QTypeRevision version, int notifyIndex,
331 int encodedTargetIndex, int targetObjectId);
332 AppendResult appendComponentWrapper(int coreIndex, int wrappedObjectIndex);
333 void appendSignal(const QString &, QQmlPropertyData::Flags, int coreIndex,
334 const QMetaType *types = nullptr,
335 const QList<QByteArray> &names = QList<QByteArray>());
336 void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
337 QMetaType returnType, const QList<QByteArray> &names,
338 const QList<QMetaType> &parameterTypes);
339 void appendEnum(const QString &, const QList<QQmlEnumValue> &);
340
341 QQmlPropertyCacheMethodArguments *createArgumentsObject(int count,
342 const QList<QByteArray> &names);
343
344 typedef QList<QQmlPropertyData> IndexCache;
345 typedef QLinkedStringMultiHash<std::pair<int, QQmlPropertyData *> > StringCache;
346 typedef QList<QTypeRevision> AllowedRevisionCache;
347
348 const QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *,
349 const QQmlRefPointer<QQmlContextData> &) const;
350 const QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *,
351 const QQmlRefPointer<QQmlContextData> &) const;
352
353 template<typename K>
354 QQmlPropertyData *findNamedProperty(const K &key) const
355 {
356 StringCache::mapped_type *it = stringCache.value(key);
357 return it ? it->second : 0;
358 }
359
360 template<typename K>
361 void setNamedProperty(const K &key, int index, QQmlPropertyData *data)
362 {
363 stringCache.insert(key, std::make_pair(index, data));
364 }
365
366 // Conditionally logs diagnostics for override semantics.
367 //
368 // Important: "Valid" override semantics do not imply "no warning".
369 // Some override situations are allowed by the language rules but are still
370 // diagnosed to help users avoid surprising or unintended behavior.
371 //
372 // Does not construct diagnostic messages when no logging is required
373 // to compute qPrintable(name) and className() only when needed.
374 template <typename String>
375 void maybeLog(OverrideSemantics::Status status, const String &name) const
376 {
377 switch (status) {
378 case OverrideSemantics::Status::OverridingFinal: {
379 qCWarning(qqmlPropertyCacheAppend).noquote()
380 << QStringLiteral("Final member %1 is overridden in class %2. The "
381 "override won't be used.")
382 .arg(qPrintable(name), className());
383 return;
384 }
385 case OverrideSemantics::Status::MissingBase: {
386 qCWarning(qqmlPropertyCacheAppend).noquote()
387 << QStringLiteral("Member %1 of the object %2 does not override anything."
388 " Consider removing \"override\". ")
389 .arg(qPrintable(name), className());
390 return;
391 }
392 case OverrideSemantics::Status::OverridingNonVirtual: {
393 // TODO: Make this a warning as soon as we can
394 qCDebug(qqmlPropertyCacheAppend).noquote()
395 << QStringLiteral("Member %1 of the object %2 overrides a non-virtual member. "
396 "Consider renaming it or mark it virtual in the base object")
397 .arg(qPrintable(name), className());
398 return;
399 }
400 case OverrideSemantics::Status::OverridingNonVirtualError: {
401 qCWarning(qqmlPropertyCacheAppend).noquote()
402 << QStringLiteral("Member %1 of the object %2 overrides a non-virtual member. "
403 "Consider renaming it or mark it virtual in the base object")
404 .arg(qPrintable(name), className());
405 return;
406 }
407 case OverrideSemantics::Status::MissingOverrideOrFinalSpecifier: {
408 qCWarning(qqmlPropertyCacheAppend).noquote()
409 << QStringLiteral(
410 "Member %1 of the object %2 overrides a member of the base object. "
411 "Consider renaming it or adding final or override specifier")
412 .arg(qPrintable(name), className());
413 return;
414 }
415 // TODO QTBUG-98320, when override is cleaned up for methods, we need a warning for InvokabilityMismatch
416 default:
417 return;
418 }
419 }
420
421private:
422 OverrideSemantics::HandlerRef _handleOverride;
423
424 int propertyIndexCacheStart = 0; // placed here to avoid gap between QQmlRefCount and _parent
425 QQmlPropertyCache::ConstPtr _parent;
426
427 IndexCache propertyIndexCache;
428 IndexCache methodIndexCache;
429 IndexCache signalHandlerIndexCache;
430 StringCache stringCache;
431 AllowedRevisionCache allowedRevisionCache;
432 QList<QQmlEnumData> enumCache;
433
434 QQmlMetaObjectPointer _metaObject;
435 QByteArray _dynamicClassName;
436 QByteArray _dynamicStringData;
437 QByteArray _listPropertyAssignBehavior;
438 QString _defaultPropertyName;
439 QQmlPropertyCacheMethodArguments *argumentsCache = nullptr;
440 int methodIndexCacheStart = 0;
441 int signalHandlerIndexCacheStart = 0;
442 int _jsFactoryMethodIndex = -1;
443};
444
445// Returns this property cache's metaObject. May be null if it hasn't been created yet.
446inline const QMetaObject *QQmlPropertyCache::metaObject() const
447{
448 return _metaObject.metaObject();
449}
450
451// Returns the first C++ type's QMetaObject - that is, the first QMetaObject not created by
452// QML
453inline const QMetaObject *QQmlPropertyCache::firstCppMetaObject() const
454{
455 const QQmlPropertyCache *p = this;
456 while (p->_metaObject.isShared())
457 p = p->parent().data();
458 return p->_metaObject.metaObject();
459}
460
461inline const QQmlPropertyData *QQmlPropertyCache::property(int index) const
462{
463 if (index < 0 || index >= propertyCount())
464 return nullptr;
465
466 if (index < propertyIndexCacheStart)
467 return _parent->property(index);
468
469 return &propertyIndexCache.at(index - propertyIndexCacheStart);
470}
471
472inline const QQmlPropertyData *QQmlPropertyCache::method(int index) const
473{
474 if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.size()))
475 return nullptr;
476
477 if (index < methodIndexCacheStart)
478 return _parent->method(index);
479
480 return const_cast<const QQmlPropertyData *>(&methodIndexCache.at(index - methodIndexCacheStart));
481}
482
483/*! \internal
484 \a index MUST be in the signal index range (see QObjectPrivate::signalIndex()).
485 This is different from QMetaMethod::methodIndex().
486*/
487inline const QQmlPropertyData *QQmlPropertyCache::signal(int index) const
488{
489 if (index < 0 || index >= (signalHandlerIndexCacheStart + signalHandlerIndexCache.size()))
490 return nullptr;
491
492 if (index < signalHandlerIndexCacheStart)
493 return _parent->signal(index);
494
495 const QQmlPropertyData *rv = const_cast<const QQmlPropertyData *>(&methodIndexCache.at(index - signalHandlerIndexCacheStart));
496 Q_ASSERT(rv->isSignal() || rv->coreIndex() == -1);
497 return rv;
498}
499
500inline QQmlEnumData *QQmlPropertyCache::qmlEnum(int index) const
501{
502 if (index < 0 || index >= enumCache.size())
503 return nullptr;
504
505 return const_cast<QQmlEnumData *>(&enumCache.at(index));
506}
507
508inline int QQmlPropertyCache::methodIndexToSignalIndex(int index) const
509{
510 if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.size()))
511 return index;
512
513 if (index < methodIndexCacheStart)
514 return _parent->methodIndexToSignalIndex(index);
515
516 return index - methodIndexCacheStart + signalHandlerIndexCacheStart;
517}
518
519// Returns the name of the default property for this cache
520inline QString QQmlPropertyCache::defaultPropertyName() const
521{
522 return _defaultPropertyName;
523}
524
525inline const QQmlPropertyCache::ConstPtr &QQmlPropertyCache::parent() const
526{
527 return _parent;
528}
529
530const QQmlPropertyData *
531QQmlPropertyCache::overrideData(const QQmlPropertyData *data) const
532{
533 if (!data->hasOverride())
534 return nullptr;
535
536 if (data->overrideIndexIsProperty())
537 return property(data->overrideIndex());
538 else
539 return method(data->overrideIndex());
540}
541
542bool QQmlPropertyCache::isAllowedInRevision(const QQmlPropertyData *data) const
543{
544 // Aliases can't be revisioned.
545 if (data->isAlias())
546 return true;
547
548 const QTypeRevision requested = data->revision();
549 const int offset = data->metaObjectOffset();
550 if (offset == -1 && requested == QTypeRevision::zero())
551 return true;
552
553 Q_ASSERT(offset >= 0);
554 Q_ASSERT(offset < allowedRevisionCache.size());
555 const QTypeRevision allowed = allowedRevisionCache[offset];
556
557 if (requested.hasMajorVersion()) {
558 if (requested.majorVersion() > allowed.majorVersion())
559 return false;
560 if (requested.majorVersion() < allowed.majorVersion())
561 return true;
562 }
563
564 return !requested.hasMinorVersion() || requested.minorVersion() <= allowed.minorVersion();
565}
566
567int QQmlPropertyCache::propertyCount() const
568{
569 return propertyIndexCacheStart + int(propertyIndexCache.size());
570}
571
572int QQmlPropertyCache::propertyOffset() const
573{
574 return propertyIndexCacheStart;
575}
576
577int QQmlPropertyCache::methodCount() const
578{
579 return methodIndexCacheStart + int(methodIndexCache.size());
580}
581
582int QQmlPropertyCache::methodOffset() const
583{
584 return methodIndexCacheStart;
585}
586
587int QQmlPropertyCache::signalCount() const
588{
589 return signalHandlerIndexCacheStart + int(signalHandlerIndexCache.size());
590}
591
592int QQmlPropertyCache::signalOffset() const
593{
594 return signalHandlerIndexCacheStart;
595}
596
597int QQmlPropertyCache::ownEnumCount() const
598{
599 return int(enumCache.size());
600}
601
602bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const
603{
604 if (_jsFactoryMethodIndex != -1) {
605 if (const QMetaObject *mo = _metaObject.metaObject()) {
606 mo->d.static_metacall(object, QMetaObject::InvokeMetaMethod,
607 _jsFactoryMethodIndex, args);
608 return true;
609 }
610 return false;
611 }
612 if (_parent)
613 return _parent->callJSFactoryMethod(object, args);
614 return false;
615}
616
617QT_END_NAMESPACE
618
619#endif // QQMLPROPERTYCACHE_P_H
friend class QJSEngine
const QMetaObject * metaObject() const
void setSharedOnce(QMetaObject *shared) const
static Status checkMinimal(const QQmlPropertyData *const existingProperty)
static Status check(const QQmlPropertyData &overridingProperty, const QQmlPropertyData *const existingProperty, CheckMode mode)
static bool hasInvalidModifierCombintation(const QQmlPropertyData &overridingProperty)
static Status checkFull(const QQmlPropertyData &overridingProperty, const QQmlPropertyData *const existingProperty)
Status handleOverride(QQmlPropertyData &overridingProperty, QQmlPropertyData *existingProperty, CheckMode mode)
bool isValidOverride(Status res)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
const QQmlPropertyData * qQmlPropertyCacheProperty(QObject *obj, T name, const QQmlRefPointer< QQmlContextData > &context, QQmlPropertyData *local)
static const QByteArray stringData(const QMetaObject *mo, int index)
static QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const T &propertyName)
#define Q_INT16_MAX
static const char * qQmlPropertyCacheToString(QLatin1String string)
static QByteArray qQmlPropertyCacheToString(const QV4::String *string)
static std::pair< bool, int > deriveEncodingAndLength(const char *str)
static QHashedString signalNameToHandlerName(const QHashedString &methodName)
static int metaObjectSignalCount(const QMetaObject *metaObject)