aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2019-04-23 09:33:25 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2019-04-23 09:34:29 +0200
commit580fa7dc88aae23053e44ffa335a15f6af112a20 (patch)
tree5bc915d7c2e252739122d9441bd0d7fa7175d0c2 /src/qml/qml
parent6767114285db9d0e16dc278d08f231e8561546b4 (diff)
parentc00283bb3bb966bf60c307ec8283bd98c12318bf (diff)
Merge remote-tracking branch 'origin/dev' into wip/scenegraphng
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qml.pri1
-rw-r--r--src/qml/qml/qqml.h5
-rw-r--r--src/qml/qml/qqmlbinding.cpp32
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp2
-rw-r--r--src/qml/qml/qqmldelayedcallqueue.cpp1
-rw-r--r--src/qml/qml/qqmlengine.cpp104
-rw-r--r--src/qml/qml/qqmlengine_p.h7
-rw-r--r--src/qml/qml/qqmlexpression.cpp1
-rw-r--r--src/qml/qml/qqmlglobal.cpp69
-rw-r--r--src/qml/qml/qqmlglobal_p.h4
-rw-r--r--src/qml/qml/qqmlimport.cpp13
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp82
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h21
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp1
-rw-r--r--src/qml/qml/qqmlmetatype.cpp3
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp31
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h6
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp1
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp99
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h24
-rw-r--r--src/qml/qml/qqmlpropertydata_p.h293
-rw-r--r--src/qml/qml/qqmlpropertyrawdata_p.h341
-rw-r--r--src/qml/qml/qqmltype.cpp43
-rw-r--r--src/qml/qml/qqmltype_p.h1
-rw-r--r--src/qml/qml/qqmltype_p_p.h14
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp62
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h3
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp29
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp153
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h3
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp2
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h1
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp6
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp4
-rw-r--r--src/qml/qml/v8/qv8engine_p.h15
36 files changed, 676 insertions, 803 deletions
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 0895e5ae68..9f79bfacdf 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -102,7 +102,6 @@ HEADERS += \
$$PWD/qqmlpropertycachevector_p.h \
$$PWD/qqmlpropertydata_p.h \
$$PWD/qqmlpropertyindex_p.h \
- $$PWD/qqmlpropertyrawdata_p.h \
$$PWD/qqmlmetaobject_p.h \
$$PWD/qqmlnotifier_p.h \
$$PWD/qqmlobjectorgadget_p.h \
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 05a9f70247..3000f56601 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -584,7 +584,6 @@ namespace QtQml {
const QMetaObject *, bool create);
#ifndef Q_QDOC
}
-#endif
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wheader-hygiene")
@@ -594,6 +593,8 @@ using namespace QtQml;
QT_WARNING_POP
+#endif // Q_QDOC
+
//The C++ version of protected namespaces in qmldir
Q_QML_EXPORT bool qmlProtectModule(const char* uri, int majVersion);
Q_QML_EXPORT void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor);
@@ -605,8 +606,6 @@ QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true)
return qmlAttachedPropertiesObject(&idx, obj, &T::staticMetaObject, create);
}
-Q_QML_EXPORT void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor);
-
inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName,
QJSValue (*callback)(QQmlEngine *, QJSEngine *))
{
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index a949df4968..b164517011 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -260,8 +260,6 @@ protected:
} else {
clearError();
}
-
- cancelPermanentGuards();
}
ep->dereferenceScarceResources();
@@ -643,24 +641,22 @@ QVector<QQmlProperty> QQmlBinding::dependencies() const
if (!m_target.data())
return dependencies;
- for (const auto &guardList : { permanentGuards, activeGuards }) {
- for (QQmlJavaScriptExpressionGuard *guard = guardList.first(); guard; guard = guardList.next(guard)) {
- if (guard->signalIndex() == -1) // guard's sender is a QQmlNotifier, not a QObject*.
- continue;
+ for (QQmlJavaScriptExpressionGuard *guard = activeGuards.first(); guard; guard = activeGuards.next(guard)) {
+ if (guard->signalIndex() == -1) // guard's sender is a QQmlNotifier, not a QObject*.
+ continue;
- QObject *senderObject = guard->senderAsObject();
- if (!senderObject)
- continue;
+ QObject *senderObject = guard->senderAsObject();
+ if (!senderObject)
+ continue;
- const QMetaObject *senderMeta = senderObject->metaObject();
- if (!senderMeta)
- continue;
+ const QMetaObject *senderMeta = senderObject->metaObject();
+ if (!senderMeta)
+ continue;
- for (int i = 0; i < senderMeta->propertyCount(); i++) {
- QMetaProperty property = senderMeta->property(i);
- if (property.notifySignalIndex() == QMetaObjectPrivate::signal(senderMeta, guard->signalIndex()).methodIndex()) {
- dependencies.push_back(QQmlProperty(senderObject, QString::fromUtf8(senderObject->metaObject()->property(i).name())));
- }
+ for (int i = 0; i < senderMeta->propertyCount(); i++) {
+ QMetaProperty property = senderMeta->property(i);
+ if (property.notifySignalIndex() == QMetaObjectPrivate::signal(senderMeta, guard->signalIndex()).methodIndex()) {
+ dependencies.push_back(QQmlProperty(senderObject, QString::fromUtf8(senderObject->metaObject()->property(i).name())));
}
}
}
@@ -670,7 +666,7 @@ QVector<QQmlProperty> QQmlBinding::dependencies() const
bool QQmlBinding::hasDependencies() const
{
- return !permanentGuards.isEmpty() || !activeGuards.isEmpty() || translationsCaptured();
+ return !activeGuards.isEmpty() || translationsCaptured();
}
class QObjectPointerBinding: public QQmlNonbindingBinding
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index cf6f831818..dc973630a7 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -209,8 +209,6 @@ void QQmlBoundSignalExpression::evaluate(void **a)
} else if (type == QMetaType::Int) {
//### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
jsCall->args[ii] = QV4::Value::fromInt32(*reinterpret_cast<const int*>(a[ii + 1]));
- } else if (type == qMetaTypeId<QQmlV4Handle>()) {
- jsCall->args[ii] = *reinterpret_cast<QQmlV4Handle *>(a[ii + 1]);
} else if (ep->isQObject(type)) {
if (!*reinterpret_cast<void* const *>(a[ii + 1]))
jsCall->args[ii] = QV4::Value::nullValue();
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 57ea685a5d..64d2a064df 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -51,8 +51,6 @@
#include "qqmlincubator_p.h"
#include <private/qqmljavascriptexpression_p.h>
-#include <private/qv8engine_p.h>
-
#include <private/qv4functionobject_p.h>
#include <private/qv4script_p.h>
#include <private/qv4scopedvalue_p.h>
diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp
index 61cb0a9065..857b5be8b8 100644
--- a/src/qml/qml/qqmldelayedcallqueue.cpp
+++ b/src/qml/qml/qqmldelayedcallqueue.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qqmldelayedcallqueue_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <private/qv4value_p.h>
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 0a26ed89cc..f070f16afd 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -86,19 +86,10 @@
#if QT_CONFIG(qml_animation)
#include <private/qqmltimer_p.h>
#endif
-#if QT_CONFIG(qml_list_model)
-#include <private/qqmllistmodel_p.h>
-#endif
#include <private/qqmlplatform_p.h>
-#include <private/qquickpackage_p.h>
-#if QT_CONFIG(qml_delegate_model)
-#include <private/qqmldelegatemodel_p.h>
-#endif
-#include <private/qqmlobjectmodel_p.h>
#if QT_CONFIG(qml_worker_script)
#include <private/qquickworkerscript_p.h>
#endif
-#include <private/qqmlinstantiator_p.h>
#include <private/qqmlloggingcategory_p.h>
#ifdef Q_OS_WIN // for %APPDATA%
@@ -116,13 +107,6 @@ Q_DECLARE_METATYPE(QQmlProperty)
QT_BEGIN_NAMESPACE
-void qmlRegisterBaseTypes(const char *uri, int versionMajor, int versionMinor)
-{
- QQmlEnginePrivate::registerBaseTypes(uri, versionMajor, versionMinor);
- QQmlEnginePrivate::registerQtQuick2Types(uri, versionMajor, versionMinor);
- QQmlValueTypeFactory::registerValueTypes(uri, versionMajor, versionMinor);
-}
-
// Declared in qqml.h
int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
const char *uri, int versionMajor,
@@ -215,63 +199,54 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
bool QQmlEnginePrivate::qml_debugging_enabled = false;
bool QQmlEnginePrivate::s_designerMode = false;
-// these types are part of the QML language
-void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int versionMinor)
+void QQmlEnginePrivate::defineModule()
{
- qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component");
- qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject");
- qmlRegisterType<QQmlBind>(uri, versionMajor, versionMinor,"Binding");
- qmlRegisterType<QQmlBind,8>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "Binding"); //Only available in >=2.8
- qmlRegisterCustomType<QQmlConnections>(uri, versionMajor, 0, "Connections", new QQmlConnectionsParser);
- if (!strcmp(uri, "QtQuick"))
- qmlRegisterCustomType<QQmlConnections,1>(uri, versionMajor, 7, "Connections", new QQmlConnectionsParser); //Only available in QtQuick >=2.7
- else
- qmlRegisterCustomType<QQmlConnections,1>(uri, versionMajor, 3, "Connections", new QQmlConnectionsParser); //Only available in QtQml >=2.3
+ const char uri[] = "QtQml";
+
+ qmlRegisterType<QQmlComponent>(uri, 2, 0, "Component");
+ qmlRegisterType<QObject>(uri, 2, 0, "QtObject");
+ qmlRegisterType<QQmlBind>(uri, 2, 0, "Binding");
+ qmlRegisterType<QQmlBind, 8>(uri, 2, 8, "Binding"); // Only available in >= 2.8
+ qmlRegisterCustomType<QQmlConnections>(uri, 2, 0, "Connections", new QQmlConnectionsParser);
+ qmlRegisterCustomType<QQmlConnections, 1>(uri, 2, 3, "Connections", new QQmlConnectionsParser); // Only available in QtQml >= 2.3
#if QT_CONFIG(qml_animation)
- qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
+ qmlRegisterType<QQmlTimer>(uri, 2, 0, "Timer");
#endif
- qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1
- qmlRegisterType<QQmlInstanceModel>();
-
- qmlRegisterType<QQmlLoggingCategory>(uri, versionMajor, 8, "LoggingCategory"); //Only available in >=2.8
- qmlRegisterType<QQmlLoggingCategory,1>(uri, versionMajor, 12, "LoggingCategory"); //Only available in >=2.12
-}
+ qmlRegisterType<QQmlLoggingCategory>(uri, 2, 8, "LoggingCategory"); // Only available in >= 2.8
+ qmlRegisterType<QQmlLoggingCategory, 1>(uri, 2, 12, "LoggingCategory"); // Only available in >= 2.12
-// These QtQuick types' implementation resides in the QtQml module
-void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
-{
-#if QT_CONFIG(qml_list_model)
- qmlRegisterType<QQmlListElement>(uri, versionMajor, versionMinor, "ListElement"); // Now in QtQml.Models, here for compatibility
- qmlRegisterCustomType<QQmlListModel>(uri, versionMajor, versionMinor, "ListModel", new QQmlListModelParser); // Now in QtQml.Models, here for compatibility
-#endif
-#if QT_CONFIG(qml_worker_script)
- qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
-#endif
- qmlRegisterType<QQuickPackage>(uri, versionMajor, versionMinor, "Package");
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-#if QT_CONFIG(qml_delegate_model)
- qmlRegisterType<QQmlDelegateModel>(uri, versionMajor, versionMinor, "VisualDataModel");
- qmlRegisterType<QQmlDelegateModelGroup>(uri, versionMajor, versionMinor, "VisualDataGroup");
+#if QT_CONFIG(qml_locale)
+ qmlRegisterUncreatableType<QQmlLocale>(uri, 2, 2, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
#endif
- qmlRegisterType<QQmlObjectModel>(uri, versionMajor, versionMinor, "VisualItemModel");
-#endif // < Qt 6
}
-void QQmlEnginePrivate::defineQtQuick2Module()
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+void QQmlEnginePrivate::registerQuickTypes()
{
- // register the base types into the QtQuick namespace
- registerBaseTypes("QtQuick",2,0);
+ // Don't add anything here. These are only for backwards compatibility.
+
+ const char uri[] = "QtQuick";
- // register the QtQuick2 types which are implemented in the QtQml module.
- registerQtQuick2Types("QtQuick",2,0);
+ qmlRegisterType<QQmlComponent>(uri, 2, 0, "Component");
+ qmlRegisterType<QObject>(uri, 2, 0, "QtObject");
+ qmlRegisterType<QQmlBind>(uri, 2, 0, "Binding");
+ qmlRegisterType<QQmlBind, 8>(uri, 2, 8, "Binding");
+ qmlRegisterCustomType<QQmlConnections>(uri, 2, 0, "Connections", new QQmlConnectionsParser);
+ qmlRegisterCustomType<QQmlConnections, 1>(uri, 2, 7, "Connections", new QQmlConnectionsParser);
+#if QT_CONFIG(qml_animation)
+ qmlRegisterType<QQmlTimer>(uri, 2, 0,"Timer");
+#endif
+ qmlRegisterType<QQmlLoggingCategory>(uri, 2, 8, "LoggingCategory");
+ qmlRegisterType<QQmlLoggingCategory, 1>(uri, 2, 12, "LoggingCategory");
+#if QT_CONFIG(qml_worker_script)
+ qmlRegisterType<QQuickWorkerScript>(uri, 2, 0, "WorkerScript");
+#endif
#if QT_CONFIG(qml_locale)
- qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
+ qmlRegisterUncreatableType<QQmlLocale>(uri, 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
#endif
-
- // Auto-increment the import to stay in sync with ALL future QtQuick minor versions from 5.11 onward
- qmlRegisterModule("QtQuick", 2, QT_VERSION_MINOR);
}
+#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bool QQmlEnginePrivate::designerMode()
{
@@ -976,14 +951,6 @@ void QQmlEnginePrivate::init()
if (baseModulesUninitialized) {
qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
- registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
-#if QT_CONFIG(qml_locale)
- qmlRegisterUncreatableType<QQmlLocale>("QtQml", 2, 2, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
-#endif
-
- // Auto-increment the import to stay in sync with ALL future QtQml minor versions from 5.11 onward
- qmlRegisterModule("QtQml", 2, QT_VERSION_MINOR);
-
QQmlData::init();
baseModulesUninitialized = false;
}
@@ -994,7 +961,6 @@ void QQmlEnginePrivate::init()
qRegisterMetaType<QQmlComponent::Status>();
qRegisterMetaType<QList<QObject*> >();
qRegisterMetaType<QList<int> >();
- qRegisterMetaType<QQmlV4Handle>();
qRegisterMetaType<QQmlBinding*>();
v8engine()->setEngine(q);
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 20d451d607..dab4e54cd6 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -249,9 +249,10 @@ public:
static QList<QQmlError> qmlErrorFromDiagnostics(const QString &fileName, const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages);
- static void registerBaseTypes(const char *uri, int versionMajor, int versionMinor);
- static void registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor);
- static void defineQtQuick2Module();
+ static void defineModule();
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ static void registerQuickTypes();
+#endif
static bool designerMode();
static void activateDesignerMode();
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index ac2629979f..6a11583f18 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -45,7 +45,6 @@
#include "qqmlcontext_p.h"
#include "qqmlscriptstring_p.h"
#include "qqmlbinding_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmlsourcecoordinate_p.h>
#include <QtCore/qdebug.h>
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index 1d60c518c4..acebb6bac3 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -149,7 +149,8 @@ QVariant QQmlValueTypeProvider::createVariantFromString(int type, const QString
return QVariant();
}
-QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, QQmlV4Handle obj, QV4::ExecutionEngine *e, bool *ok)
+QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, const QV4::Value &obj,
+ QV4::ExecutionEngine *e, bool *ok)
{
QVariant v;
@@ -225,63 +226,53 @@ bool QQmlValueTypeProvider::createFromString(int, const QString &, void *, size_
bool QQmlValueTypeProvider::createStringFrom(int, const void *, QString *) { return false; }
bool QQmlValueTypeProvider::variantFromString(const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromString(int, const QString &, QVariant *) { return false; }
-bool QQmlValueTypeProvider::variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *) { return false; }
+bool QQmlValueTypeProvider::variantFromJsObject(int, const QV4::Value &, QV4::ExecutionEngine *, QVariant *) { return false; }
bool QQmlValueTypeProvider::equal(int, const void *, const QVariant&) { return false; }
bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return false; }
bool QQmlValueTypeProvider::read(const QVariant&, void *, int) { return false; }
bool QQmlValueTypeProvider::write(int, const void *, QVariant&) { return false; }
-Q_GLOBAL_STATIC(QQmlValueTypeProvider, nullValueTypeProvider)
-static QQmlValueTypeProvider *valueTypeProvider = nullptr;
+struct ValueTypeProviderList {
+ QQmlValueTypeProvider nullProvider;
+ QQmlValueTypeProvider *head = &nullProvider;
+};
-static QQmlValueTypeProvider **getValueTypeProvider(void)
-{
- if (valueTypeProvider == nullptr) {
- valueTypeProvider = nullValueTypeProvider;
- }
-
- return &valueTypeProvider;
-}
+Q_GLOBAL_STATIC(ValueTypeProviderList, valueTypeProviders)
Q_QML_PRIVATE_EXPORT void QQml_addValueTypeProvider(QQmlValueTypeProvider *newProvider)
{
- static QQmlValueTypeProvider **providerPtr = getValueTypeProvider();
- newProvider->next = *providerPtr;
- *providerPtr = newProvider;
+ if (ValueTypeProviderList *providers = valueTypeProviders()) {
+ newProvider->next = providers->head;
+ providers->head = newProvider;
+ }
}
Q_QML_PRIVATE_EXPORT void QQml_removeValueTypeProvider(QQmlValueTypeProvider *oldProvider)
{
- if (oldProvider == nullValueTypeProvider) {
- // don't remove the null provider
- // we get here when the QtQml library is being unloaded
- return;
- }
-
- // the only entry with next = 0 is the null provider
- Q_ASSERT(oldProvider->next);
+ if (ValueTypeProviderList *providers = valueTypeProviders()) {
+ QQmlValueTypeProvider *prev = providers->head;
+ if (prev == oldProvider) {
+ providers->head = oldProvider->next;
+ return;
+ }
- QQmlValueTypeProvider *prev = valueTypeProvider;
- if (prev == oldProvider) {
- valueTypeProvider = oldProvider->next;
- return;
- }
+ // singly-linked list removal
+ for (; prev; prev = prev->next) {
+ if (prev->next != oldProvider)
+ continue; // this is not the provider you're looking for
+ prev->next = oldProvider->next;
+ return;
+ }
- // singly-linked list removal
- for ( ; prev; prev = prev->next) {
- if (prev->next != oldProvider)
- continue; // this is not the provider you're looking for
- prev->next = oldProvider->next;
- return;
+ qWarning("QQml_removeValueTypeProvider: was asked to remove provider %p but it was not found", oldProvider);
}
-
- qWarning("QQml_removeValueTypeProvider: was asked to remove provider %p but it was not found", oldProvider);
}
-Q_AUTOTEST_EXPORT QQmlValueTypeProvider *QQml_valueTypeProvider(void)
+Q_AUTOTEST_EXPORT QQmlValueTypeProvider *QQml_valueTypeProvider()
{
- static QQmlValueTypeProvider **providerPtr = getValueTypeProvider();
- return *providerPtr;
+ if (ValueTypeProviderList *providers = valueTypeProviders())
+ return providers->head;
+ return nullptr;
}
QQmlColorProvider::~QQmlColorProvider() {}
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index e2d53ab555..53caffe040 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -233,7 +233,7 @@ public:
QVariant createVariantFromString(const QString &);
QVariant createVariantFromString(int, const QString &, bool *);
- QVariant createVariantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, bool*);
+ QVariant createVariantFromJsObject(int, const QV4::Value &, QV4::ExecutionEngine *, bool *);
bool equalValueType(int, const void *, const QVariant&);
bool storeValueType(int, const void *, void *, size_t);
@@ -250,7 +250,7 @@ private:
virtual bool variantFromString(const QString &, QVariant *);
virtual bool variantFromString(int, const QString &, QVariant *);
- virtual bool variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *);
+ virtual bool variantFromJsObject(int, const QV4::Value &, QV4::ExecutionEngine *, QVariant *);
virtual bool equal(int, const void *, const QVariant&);
virtual bool store(int, const void *, void *, size_t);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 90c2c1fb96..9d5801bbc6 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -141,6 +141,13 @@ struct RegisteredPlugin {
struct StringRegisteredPluginMap : public QMap<QString, RegisteredPlugin> {
QMutex mutex;
+
+ ~StringRegisteredPluginMap()
+ {
+ QMutexLocker lock(&mutex);
+ for (const RegisteredPlugin &plugin : qAsConst(*this))
+ delete plugin.loader;
+ }
};
Q_GLOBAL_STATIC(StringRegisteredPluginMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri and the PluginLoaders
@@ -789,7 +796,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
*typeRecursionDetected = true;
} else {
QQmlType returnType = QQmlMetaType::typeForUrl(
- qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, nullptr);
+ qmlUrl, type, registrationType == QQmlType::CompositeSingletonType, errors);
if (type_return)
*type_return = returnType;
return returnType.isValid();
@@ -1256,7 +1263,7 @@ bool QQmlImportsPrivate::locateQmldir(const QString &uri, int vmaj, int vmin, QQ
QString url;
const QStringRef absolutePath = absoluteFilePath.leftRef(absoluteFilePath.lastIndexOf(Slash) + 1);
if (absolutePath.at(0) == Colon)
- url = QLatin1String("qrc://") + absolutePath.mid(1);
+ url = QLatin1String("qrc") + absolutePath;
else
url = QUrl::fromLocalFile(absolutePath.toString()).toString();
@@ -1471,7 +1478,7 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
QString localFileOrQrc = QQmlFile::urlToLocalFileOrQrc(qmldirUrl);
Q_ASSERT(!localFileOrQrc.isEmpty());
- QString dir = QQmlFile::urlToLocalFileOrQrc(resolveLocalUrl(base, importUri));
+ const QString dir = localFileOrQrc.left(localFileOrQrc.lastIndexOf(Slash) + 1);
if (!typeLoader->directoryExists(dir)) {
if (!isImplicitImport) {
QQmlError error;
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 380163202a..9a3a5218e0 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -109,7 +109,6 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
}
clearActiveGuards();
- clearPermanentGuards();
clearError();
if (m_scopeObject.isT2()) // notify DeleteWatcher of our deletion.
m_scopeObject.asT2()->_s = nullptr;
@@ -118,12 +117,8 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v)
{
activeGuards.setFlagValue(v);
- permanentGuards.setFlagValue(v);
- if (!v) {
+ if (!v)
clearActiveGuards();
- clearPermanentGuards();
- m_permanentDependenciesRegistered = false;
- }
}
void QQmlJavaScriptExpression::resetNotifyOnValueChanged()
@@ -216,10 +211,6 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
QV4::ReturnedValue res = v4Function->call(&callData->thisObject, callData->args, callData->argc(), static_cast<QV4::ExecutionContext *>(m_qmlScope.valueRef()));
QV4::Scope scope(v4);
QV4::ScopedValue result(scope, res);
- if (v4Function->hasQmlDependencies) {
- QV4::Heap::QmlContext *qc = m_qmlScope.as<QV4::QmlContext>()->d();
- QQmlPropertyCapture::registerQmlDependencies(qc, v4, v4Function->compiledFunction);
- }
if (scope.hasException()) {
if (watcher.wasDeleted())
@@ -254,7 +245,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
return result->asReturnedValue();
}
-void QQmlPropertyCapture::captureProperty(QQmlNotifier *n, Duration duration)
+void QQmlPropertyCapture::captureProperty(QQmlNotifier *n)
{
if (watcher->wasDeleted())
return;
@@ -274,17 +265,14 @@ void QQmlPropertyCapture::captureProperty(QQmlNotifier *n, Duration duration)
g->connect(n);
}
- if (duration == Permanently)
- expression->permanentGuards.prepend(g);
- else
- expression->activeGuards.prepend(g);
+ expression->activeGuards.prepend(g);
}
/*! \internal
\a n is in the signal index range (see QObjectPrivate::signalIndex()).
*/
-void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, Duration duration, bool doNotify)
+void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, bool doNotify)
{
if (watcher->wasDeleted())
return;
@@ -323,61 +311,8 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, Duration dur
g->connect(o, n, engine, doNotify);
}
- if (duration == Permanently)
- expression->permanentGuards.prepend(g);
- else
- expression->activeGuards.prepend(g);
- }
-}
-
-void QQmlPropertyCapture::registerQmlDependencies(QV4::Heap::QmlContext *context, const QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction)
-{
- // Let the caller check and avoid the function call :)
- Q_ASSERT(compiledFunction->hasQmlDependencies());
-
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->qmlEngine());
- if (!ep)
- return;
- QQmlPropertyCapture *capture = ep->propertyCapture;
- if (!capture || capture->watcher->wasDeleted())
- return;
-
- if (capture->expression->m_permanentDependenciesRegistered)
- return;
-
- capture->expression->m_permanentDependenciesRegistered = true;
-
- QV4::Heap::QQmlContextWrapper *wrapper = context->qml();
- QQmlContextData *qmlContext = wrapper->context->contextData();
-
- const quint32_le *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
- const int idObjectDependencyCount = compiledFunction->nDependingIdObjects;
- for (int i = 0; i < idObjectDependencyCount; ++i, ++idObjectDependency) {
- Q_ASSERT(int(*idObjectDependency) < qmlContext->idValueCount);
- capture->captureProperty(&qmlContext->idValues[*idObjectDependency].bindings,
- QQmlPropertyCapture::Permanently);
- }
-
- Q_ASSERT(qmlContext->contextObject);
- const quint32_le *contextPropertyDependency = compiledFunction->qmlContextPropertiesDependencyTable();
- const int contextPropertyDependencyCount = compiledFunction->nDependingContextProperties;
- for (int i = 0; i < contextPropertyDependencyCount; ++i) {
- const int propertyIndex = *contextPropertyDependency++;
- const int notifyIndex = *contextPropertyDependency++;
- capture->captureProperty(qmlContext->contextObject, propertyIndex, notifyIndex,
- QQmlPropertyCapture::Permanently);
- }
-
- QObject *scopeObject = wrapper->scopeObject;
- const quint32_le *scopePropertyDependency = compiledFunction->qmlScopePropertiesDependencyTable();
- const int scopePropertyDependencyCount = compiledFunction->nDependingScopeProperties;
- for (int i = 0; i < scopePropertyDependencyCount; ++i) {
- const int propertyIndex = *scopePropertyDependency++;
- const int notifyIndex = *scopePropertyDependency++;
- capture->captureProperty(scopeObject, propertyIndex, notifyIndex,
- QQmlPropertyCapture::Permanently);
+ expression->activeGuards.prepend(g);
}
-
}
QQmlError QQmlJavaScriptExpression::error(QQmlEngine *engine) const
@@ -471,13 +406,6 @@ void QQmlJavaScriptExpression::clearActiveGuards()
g->Delete();
}
-void QQmlJavaScriptExpression::clearPermanentGuards()
-{
- m_permanentDependenciesRegistered = false;
- while (QQmlJavaScriptExpressionGuard *g = permanentGuards.takeFirst())
- g->Delete();
-}
-
void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *e, void **)
{
QQmlJavaScriptExpression *expression =
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index de3fba0774..453c8ab8a8 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -144,7 +144,6 @@ public:
QQmlError error(QQmlEngine *) const;
void clearError();
void clearActiveGuards();
- void clearPermanentGuards();
QQmlDelayedError *delayedError();
static QV4::ReturnedValue evalFunction(QQmlContextData *ctxt, QObject *scope,
@@ -153,14 +152,6 @@ public:
protected:
void createQmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line);
- void cancelPermanentGuards() const
- {
- if (m_permanentDependenciesRegistered) {
- for (QQmlJavaScriptExpressionGuard *it = permanentGuards.first(); it; it = permanentGuards.next(it))
- it->cancelNotify();
- }
- }
-
void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f);
void setCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit);
@@ -169,7 +160,6 @@ protected:
// activeGuards:flag2 - useSharedContext
QBiPointer<QObject, DeleteWatcher> m_scopeObject;
QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> activeGuards;
- QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> permanentGuards;
void setTranslationsCaptured(bool captured) { m_error.setFlagValue(captured); }
bool translationsCaptured() const { return m_error.flag(); }
@@ -186,7 +176,6 @@ private:
QQmlContextData *m_context;
QQmlJavaScriptExpression **m_prevExpression;
QQmlJavaScriptExpression *m_nextExpression;
- bool m_permanentDependenciesRegistered = false;
QV4::PersistentValue m_qmlScope;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compilationUnit;
@@ -204,14 +193,8 @@ public:
Q_ASSERT(errorString == nullptr);
}
- enum Duration {
- OnlyOnce,
- Permanently
- };
-
- static void registerQmlDependencies(QV4::Heap::QmlContext *context, const QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
- void captureProperty(QQmlNotifier *, Duration duration = OnlyOnce);
- void captureProperty(QObject *, int, int, Duration duration = OnlyOnce, bool doNotify = true);
+ void captureProperty(QQmlNotifier *);
+ void captureProperty(QObject *, int, int, bool doNotify = true);
void captureTranslation() { translationCaptured = true; }
QQmlEngine *engine;
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 2f769c1aef..5349572921 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qqmllistwrapper_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmllist_p.h>
#include <private/qv4objectproto_p.h>
#include <qv4objectiterator_p.h>
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 0da96f61e4..32f281b4f2 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -278,6 +278,7 @@ void QQmlMetaType::clearTypeRegistrations()
data->idToType.clear();
data->nameToType.clear();
data->urlToType.clear();
+ data->typePropertyCaches.clear();
data->urlToNonFileImportType.clear();
data->metaObjectToType.clear();
data->uriToModule.clear();
@@ -1206,6 +1207,7 @@ void QQmlMetaType::unregisterType(int typeIndex)
removeQQmlTypePrivate(data->metaObjectToType, d);
for (auto & module : data->uriToModule)
module->remove(d);
+ data->clearPropertyCachesForMinorVersion(typeIndex);
data->types[typeIndex] = QQmlType();
}
}
@@ -1232,6 +1234,7 @@ void QQmlMetaType::freeUnusedTypesAndCaches()
for (auto &module : data->uriToModule)
module->remove(d);
+ data->clearPropertyCachesForMinorVersion(d->index);
*it = QQmlType();
} else {
++it;
diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp
index 13c46e4911..5dc0083f54 100644
--- a/src/qml/qml/qqmlmetatypedata.cpp
+++ b/src/qml/qml/qqmlmetatypedata.cpp
@@ -77,6 +77,27 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
priv->release();
}
+QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForMinorVersion(int index, int minorVersion) const
+{
+ return (index < typePropertyCaches.length())
+ ? typePropertyCaches.at(index).value(minorVersion).data()
+ : nullptr;
+}
+
+void QQmlMetaTypeData::setPropertyCacheForMinorVersion(int index, int minorVersion,
+ QQmlPropertyCache *cache)
+{
+ if (index >= typePropertyCaches.length())
+ typePropertyCaches.resize(index + 1);
+ typePropertyCaches[index][minorVersion] = cache;
+}
+
+void QQmlMetaTypeData::clearPropertyCachesForMinorVersion(int index)
+{
+ if (index < typePropertyCaches.length())
+ typePropertyCaches[index].clear();
+}
+
QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, int minorVersion)
{
if (QQmlPropertyCache *rv = propertyCaches.value(metaObject))
@@ -97,7 +118,7 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
{
Q_ASSERT(type.isValid());
- if (QQmlPropertyCache *pc = type.key()->propertyCacheForMinorVersion(minorVersion))
+ if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), minorVersion))
return pc;
QVector<QQmlType> types;
@@ -118,8 +139,8 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
metaObject = metaObject->superClass();
}
- if (QQmlPropertyCache *pc = type.key()->propertyCacheForMinorVersion(maxMinorVersion)) {
- const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(minorVersion, pc);
+ if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), maxMinorVersion)) {
+ setPropertyCacheForMinorVersion(type.index(), minorVersion, pc);
return pc;
}
@@ -190,13 +211,13 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
}
#endif
- const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(minorVersion, raw);
+ setPropertyCacheForMinorVersion(type.index(), minorVersion, raw);
if (hasCopied)
raw->release();
if (minorVersion != maxMinorVersion)
- const_cast<QQmlTypePrivate*>(type.key())->setPropertyCacheForMinorVersion(maxMinorVersion, raw);
+ setPropertyCacheForMinorVersion(type.index(), maxMinorVersion, raw);
return raw;
}
diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h
index 2c5a32be1b..c45bc16280 100644
--- a/src/qml/qml/qqmlmetatypedata_p.h
+++ b/src/qml/qml/qqmlmetatypedata_p.h
@@ -83,6 +83,7 @@ struct QQmlMetaTypeData
MetaObjects metaObjectToType;
typedef QHash<int, QQmlMetaType::StringConverter> StringConverters;
StringConverters stringConverters;
+ QVector<QHash<int, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches;
struct VersionedUri {
VersionedUri()
@@ -112,6 +113,11 @@ struct QQmlMetaTypeData
QHash<int, int> qmlLists;
QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches;
+
+ QQmlPropertyCache *propertyCacheForMinorVersion(int index, int minorVersion) const;
+ void setPropertyCacheForMinorVersion(int index, int minorVersion, QQmlPropertyCache *cache);
+ void clearPropertyCachesForMinorVersion(int index);
+
QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion);
QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion);
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index fc798a2c23..fe0946c6de 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -41,7 +41,6 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qqmldata_p.h>
#include <private/qmetaobjectbuilder_p.h>
-#include <private/qv8engine_p.h>
#include <qqmlengine.h>
#include <qdebug.h>
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 46457a8d76..a6546ae330 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -42,7 +42,6 @@
#include <private/qqmlengine_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlvmemetaobject_p.h>
-#include <private/qv8engine_p.h>
#include <private/qmetaobject_p.h>
#include <private/qmetaobjectbuilder_p.h>
@@ -99,8 +98,6 @@ static void flagsForPropertyType(int propType, QQmlPropertyData::Flags &flags)
flags.type = QQmlPropertyData::Flags::QmlBindingType;
} else if (propType == qMetaTypeId<QJSValue>()) {
flags.type = QQmlPropertyData::Flags::QJSValueType;
- } else if (propType == qMetaTypeId<QQmlV4Handle>()) {
- flags.type = QQmlPropertyData::Flags::V4HandleType;
} else {
QQmlMetaType::TypeCategory cat = QQmlMetaType::typeCategory(propType);
@@ -127,24 +124,27 @@ QQmlPropertyData::flagsForProperty(const QMetaProperty &p)
return flags;
}
-void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
+static void populate(QQmlPropertyData *data, const QMetaProperty &p)
{
- setCoreIndex(p.propertyIndex());
- setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
Q_ASSERT(p.revision() <= Q_INT16_MAX);
- setRevision(p.revision());
-
- setFlags(fastFlagsForProperty(p));
+ data->setCoreIndex(p.propertyIndex());
+ data->setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
+ data->setFlags(fastFlagsForProperty(p));
+ data->setRevision(p.revision());
+}
+void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
+{
+ populate(this, p);
int type = static_cast<int>(p.type());
if (type == QMetaType::QObjectStar) {
setPropType(type);
- _flags.type = Flags::QObjectDerivedType;
+ m_flags.type = Flags::QObjectDerivedType;
} else if (type == QMetaType::QVariant) {
setPropType(type);
- _flags.type = Flags::QVariantType;
+ m_flags.type = Flags::QVariantType;
} else if (type == QVariant::UserType || type == -1) {
- _flags.notFullyResolved = true;
+ m_flags.notFullyResolved = true;
} else {
setPropType(type);
}
@@ -152,13 +152,9 @@ void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
void QQmlPropertyData::load(const QMetaProperty &p)
{
+ populate(this, p);
setPropType(p.userType());
- setCoreIndex(p.propertyIndex());
- setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
- setFlags(fastFlagsForProperty(p));
- flagsForPropertyType(propType(), _flags);
- Q_ASSERT(p.revision() <= Q_INT16_MAX);
- setRevision(p.revision());
+ flagsForPropertyType(propType(), m_flags);
}
void QQmlPropertyData::load(const QMetaMethod &m)
@@ -168,23 +164,23 @@ void QQmlPropertyData::load(const QMetaMethod &m)
setPropType(m.returnType());
- _flags.type = Flags::FunctionType;
- if (m.methodType() == QMetaMethod::Signal)
- _flags.isSignal = true;
- else if (m.methodType() == QMetaMethod::Constructor) {
- _flags.isConstructor = true;
+ m_flags.type = Flags::FunctionType;
+ if (m.methodType() == QMetaMethod::Signal) {
+ m_flags.isSignal = true;
+ } else if (m.methodType() == QMetaMethod::Constructor) {
+ m_flags.isConstructor = true;
setPropType(QMetaType::QObjectStar);
}
- if (m.parameterCount()) {
- _flags.hasArguments = true;
- if ((m.parameterCount() == 1) && (m.parameterTypes().constFirst() == "QQmlV4Function*")) {
- _flags.isV4Function = true;
- }
+ const int paramCount = m.parameterCount();
+ if (paramCount) {
+ m_flags.hasArguments = true;
+ if ((paramCount == 1) && (m.parameterTypes().constFirst() == "QQmlV4Function*"))
+ m_flags.isV4Function = true;
}
if (m.attributes() & QMetaMethod::Cloned)
- _flags.isCloned = true;
+ m_flags.isCloned = true;
Q_ASSERT(m.revision() <= Q_INT16_MAX);
setRevision(m.revision());
@@ -192,37 +188,14 @@ void QQmlPropertyData::load(const QMetaMethod &m)
void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
{
- setCoreIndex(m.methodIndex());
- setPropType(QMetaType::Void);
- setArguments(nullptr);
- _flags.type = Flags::FunctionType;
- if (m.methodType() == QMetaMethod::Signal)
- _flags.isSignal = true;
- else if (m.methodType() == QMetaMethod::Constructor) {
- _flags.isConstructor = true;
- setPropType(QMetaType::QObjectStar);
- }
+ load(m);
const char *returnType = m.typeName();
if (!returnType)
returnType = "\0";
if ((*returnType != 'v') || (qstrcmp(returnType+1, "oid") != 0)) {
- _flags.notFullyResolved = true;
- }
-
- const int paramCount = m.parameterCount();
- if (paramCount) {
- _flags.hasArguments = true;
- if ((paramCount == 1) && (m.parameterTypes().constFirst() == "QQmlV4Function*")) {
- _flags.isV4Function = true;
- }
+ m_flags.notFullyResolved = true;
}
-
- if (m.attributes() & QMetaMethod::Cloned)
- _flags.isCloned = true;
-
- Q_ASSERT(m.revision() <= Q_INT16_MAX);
- setRevision(m.revision());
}
/*!
@@ -347,7 +320,7 @@ void QQmlPropertyCache::appendSignal(const QString &name, QQmlPropertyData::Flag
data.setArguments(nullptr);
QQmlPropertyData handler = data;
- handler._flags.isSignalHandler = true;
+ handler.m_flags.isSignalHandler = true;
if (types) {
int argumentCount = *types;
@@ -545,7 +518,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
data->setFlags(methodFlags);
data->lazyLoad(m);
- data->_flags.isDirect = !dynamicMetaObject;
+ data->m_flags.isDirect = !dynamicMetaObject;
Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
data->setMetaObjectOffset(allowedRevisionCache.count() - 1);
@@ -553,7 +526,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
if (data->isSignal()) {
sigdata = &signalHandlerIndexCache[signalHandlerIndex - signalHandlerIndexCacheStart];
*sigdata = *data;
- sigdata->_flags.isSignalHandler = true;
+ sigdata->m_flags.isSignalHandler = true;
}
QQmlPropertyData *old = nullptr;
@@ -595,7 +568,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
if (old) {
// We only overload methods in the same class, exactly like C++
if (old->isFunction() && old->coreIndex() >= methodOffset)
- data->_flags.isOverload = true;
+ data->m_flags.isOverload = true;
data->markAsOverrideOf(old);
}
@@ -626,7 +599,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
data->lazyLoad(p);
data->setTypeMinorVersion(typeMinorVersion);
- data->_flags.isDirect = !dynamicMetaObject;
+ data->m_flags.isDirect = !dynamicMetaObject;
Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
data->setMetaObjectOffset(allowedRevisionCache.count() - 1);
@@ -652,7 +625,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
}
if (isGadget) // always dispatch over a 'normal' meta-call so the QQmlValueType can intercept
- data->_flags.isDirect = false;
+ data->m_flags.isDirect = false;
else
data->trySetStaticMetaCallFunction(metaObject->d.static_metacall, ii - propOffset);
if (old)
@@ -663,7 +636,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
{
Q_ASSERT(data->notFullyResolved());
- data->_flags.notFullyResolved = false;
+ data->m_flags.notFullyResolved = false;
const QMetaObject *mo = firstCppMetaObject();
if (data->isFunction()) {
@@ -698,7 +671,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->setPropType(registerResult == -1 ? QMetaType::UnknownType : registerResult);
}
}
- flagsForPropertyType(data->propType(), data->_flags);
+ flagsForPropertyType(data->propType(), data->m_flags);
}
}
@@ -875,7 +848,7 @@ void QQmlPropertyData::markAsOverrideOf(QQmlPropertyData *predecessor)
setOverrideIndexIsProperty(!predecessor->isFunction());
setOverrideIndex(predecessor->coreIndex());
- predecessor->_flags.isOverridden = true;
+ predecessor->m_flags.isOverridden = true;
}
QQmlPropertyCacheMethodArguments *QQmlPropertyCache::createArgumentsObject(int argc, const QList<QByteArray> &names)
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 4f47e5d351..72692ee522 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -89,19 +89,19 @@ public:
QQmlPropertyCache *copy();
QQmlPropertyCache *copyAndAppend(const QMetaObject *,
- QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
+ QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCache *copyAndAppend(const QMetaObject *, int typeMinorVersion,
- QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
+ QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCache *copyAndReserve(int propertyCount,
int methodCount, int signalCount, int enumCount);
- void appendProperty(const QString &, QQmlPropertyRawData::Flags flags, int coreIndex,
+ void appendProperty(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
int propType, int revision, int notifyIndex);
- void appendSignal(const QString &, QQmlPropertyRawData::Flags, int coreIndex,
+ void appendSignal(const QString &, QQmlPropertyData::Flags, int coreIndex,
const int *types = nullptr, const QList<QByteArray> &names = QList<QByteArray>());
void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
const QList<QByteArray> &names = QList<QByteArray>());
@@ -187,9 +187,9 @@ private:
inline QQmlPropertyCache *copy(int reserve);
void append(const QMetaObject *, int typeMinorVersion,
- QQmlPropertyRawData::Flags propertyFlags = QQmlPropertyRawData::Flags(),
- QQmlPropertyRawData::Flags methodFlags = QQmlPropertyData::Flags(),
- QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
+ QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
+ QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCacheMethodArguments *createArgumentsObject(int count, const QList<QByteArray> &names);
@@ -243,8 +243,6 @@ private:
QByteArray _checksum;
};
-typedef QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCachePtr;
-
inline QQmlPropertyData *QQmlPropertyCache::ensureResolved(QQmlPropertyData *p) const
{
if (p && Q_UNLIKELY(p->notFullyResolved()))
diff --git a/src/qml/qml/qqmlpropertydata_p.h b/src/qml/qml/qqmlpropertydata_p.h
index a292bcc769..dec696226e 100644
--- a/src/qml/qml/qqmlpropertydata_p.h
+++ b/src/qml/qml/qqmlpropertydata_p.h
@@ -51,11 +51,12 @@
// We mean it.
//
-#include <private/qqmlpropertyrawdata_p.h>
+#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
-class QQmlPropertyData : public QQmlPropertyRawData
+class QQmlPropertyCacheMethodArguments;
+class QQmlPropertyData
{
public:
enum WriteFlag {
@@ -65,10 +66,193 @@ public:
};
Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
- inline QQmlPropertyData();
- inline QQmlPropertyData(const QQmlPropertyRawData &);
+ typedef QObjectPrivate::StaticMetaCallFunction StaticMetaCallFunction;
- inline bool operator==(const QQmlPropertyRawData &);
+ struct Flags {
+ enum Types {
+ OtherType = 0,
+ FunctionType = 1, // Is an invokable
+ QObjectDerivedType = 2, // Property type is a QObject* derived type
+ EnumType = 3, // Property type is an enum
+ QListType = 4, // Property type is a QML list
+ QmlBindingType = 5, // Property type is a QQmlBinding*
+ QJSValueType = 6, // Property type is a QScriptValue
+ // Gap, used to be V4HandleType
+ VarPropertyType = 8, // Property type is a "var" property of VMEMO
+ QVariantType = 9 // Property is a QVariant
+ };
+
+ // The _otherBits (which "pad" the Flags struct to align it nicely) are used
+ // to store the relative property index. It will only get used when said index fits. See
+ // trySetStaticMetaCallFunction for details.
+ // (Note: this padding is done here, because certain compilers have surprising behavior
+ // when an enum is declared in-between two bit fields.)
+ enum { BitsLeftInFlags = 10 };
+ unsigned otherBits : BitsLeftInFlags; // align to 32 bits
+
+ // Can apply to all properties, except IsFunction
+ unsigned isConstant : 1; // Has CONST flag
+ unsigned isWritable : 1; // Has WRITE function
+ unsigned isResettable : 1; // Has RESET function
+ unsigned isAlias : 1; // Is a QML alias to another property
+ unsigned isFinal : 1; // Has FINAL flag
+ unsigned isOverridden : 1; // Is overridden by a extension property
+ unsigned isDirect : 1; // Exists on a C++ QMetaObject
+
+ unsigned type : 4; // stores an entry of Types
+
+ // Apply only to IsFunctions
+ unsigned isVMEFunction : 1; // Function was added by QML
+ unsigned hasArguments : 1; // Function takes arguments
+ unsigned isSignal : 1; // Function is a signal
+ unsigned isVMESignal : 1; // Signal was added by QML
+ unsigned isV4Function : 1; // Function takes QQmlV4Function* args
+ unsigned isSignalHandler : 1; // Function is a signal handler
+ unsigned isOverload : 1; // Function is an overload of another function
+ unsigned isCloned : 1; // The function was marked as cloned
+ unsigned isConstructor : 1; // The function was marked is a constructor
+
+ // Internal QQmlPropertyCache flags
+ unsigned notFullyResolved : 1; // True if the type data is to be lazily resolved
+ unsigned overrideIndexIsProperty: 1;
+
+ inline Flags();
+ inline bool operator==(const Flags &other) const;
+ inline void copyPropertyTypeFlags(Flags from);
+ };
+
+ inline bool operator==(const QQmlPropertyData &) const;
+
+ Flags flags() const { return m_flags; }
+ void setFlags(Flags f)
+ {
+ unsigned otherBits = m_flags.otherBits;
+ m_flags = f;
+ m_flags.otherBits = otherBits;
+ }
+
+ bool isValid() const { return coreIndex() != -1; }
+
+ bool isConstant() const { return m_flags.isConstant; }
+ bool isWritable() const { return m_flags.isWritable; }
+ void setWritable(bool onoff) { m_flags.isWritable = onoff; }
+ bool isResettable() const { return m_flags.isResettable; }
+ bool isAlias() const { return m_flags.isAlias; }
+ bool isFinal() const { return m_flags.isFinal; }
+ bool isOverridden() const { return m_flags.isOverridden; }
+ bool isDirect() const { return m_flags.isDirect; }
+ bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; }
+ bool isFunction() const { return m_flags.type == Flags::FunctionType; }
+ bool isQObject() const { return m_flags.type == Flags::QObjectDerivedType; }
+ bool isEnum() const { return m_flags.type == Flags::EnumType; }
+ bool isQList() const { return m_flags.type == Flags::QListType; }
+ bool isQmlBinding() const { return m_flags.type == Flags::QmlBindingType; }
+ bool isQJSValue() const { return m_flags.type == Flags::QJSValueType; }
+ bool isVarProperty() const { return m_flags.type == Flags::VarPropertyType; }
+ bool isQVariant() const { return m_flags.type == Flags::QVariantType; }
+ bool isVMEFunction() const { return m_flags.isVMEFunction; }
+ bool hasArguments() const { return m_flags.hasArguments; }
+ bool isSignal() const { return m_flags.isSignal; }
+ bool isVMESignal() const { return m_flags.isVMESignal; }
+ bool isV4Function() const { return m_flags.isV4Function; }
+ bool isSignalHandler() const { return m_flags.isSignalHandler; }
+ bool isOverload() const { return m_flags.isOverload; }
+ void setOverload(bool onoff) { m_flags.isOverload = onoff; }
+ bool isCloned() const { return m_flags.isCloned; }
+ bool isConstructor() const { return m_flags.isConstructor; }
+
+ bool hasOverride() const { return overrideIndex() >= 0; }
+ bool hasRevision() const { return revision() != 0; }
+
+ bool isFullyResolved() const { return !m_flags.notFullyResolved; }
+
+ int propType() const { Q_ASSERT(isFullyResolved()); return m_propType; }
+ void setPropType(int pt)
+ {
+ Q_ASSERT(pt >= 0);
+ Q_ASSERT(pt <= std::numeric_limits<qint16>::max());
+ m_propType = quint16(pt);
+ }
+
+ int notifyIndex() const { return m_notifyIndex; }
+ void setNotifyIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ m_notifyIndex = qint16(idx);
+ }
+
+ bool overrideIndexIsProperty() const { return m_flags.overrideIndexIsProperty; }
+ void setOverrideIndexIsProperty(bool onoff) { m_flags.overrideIndexIsProperty = onoff; }
+
+ int overrideIndex() const { return m_overrideIndex; }
+ void setOverrideIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ m_overrideIndex = qint16(idx);
+ }
+
+ int coreIndex() const { return m_coreIndex; }
+ void setCoreIndex(int idx)
+ {
+ Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
+ m_coreIndex = qint16(idx);
+ }
+
+ quint8 revision() const { return m_revision; }
+ void setRevision(quint8 rev)
+ {
+ Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
+ m_revision = quint8(rev);
+ }
+
+ /* If a property is a C++ type, then we store the minor
+ * version of this type.
+ * This is required to resolve property or signal revisions
+ * if this property is used as a grouped property.
+ *
+ * Test.qml
+ * property TextEdit someTextEdit: TextEdit {}
+ *
+ * Test {
+ * someTextEdit.preeditText: "test" //revision 7
+ * someTextEdit.onEditingFinished: console.log("test") //revision 6
+ * }
+ *
+ * To determine if these properties with revisions are available we need
+ * the minor version of TextEdit as imported in Test.qml.
+ *
+ */
+
+ quint8 typeMinorVersion() const { return m_typeMinorVersion; }
+ void setTypeMinorVersion(quint8 rev)
+ {
+ Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
+ m_typeMinorVersion = quint8(rev);
+ }
+
+ QQmlPropertyCacheMethodArguments *arguments() const { return m_arguments; }
+ void setArguments(QQmlPropertyCacheMethodArguments *args) { m_arguments = args; }
+
+ int metaObjectOffset() const { return m_metaObjectOffset; }
+ void setMetaObjectOffset(int off)
+ {
+ Q_ASSERT(off >= std::numeric_limits<qint16>::min());
+ Q_ASSERT(off <= std::numeric_limits<qint16>::max());
+ m_metaObjectOffset = qint16(off);
+ }
+
+ StaticMetaCallFunction staticMetaCallFunction() const { return m_staticMetaCallFunction; }
+ void trySetStaticMetaCallFunction(StaticMetaCallFunction f, unsigned relativePropertyIndex)
+ {
+ if (relativePropertyIndex < (1 << Flags::BitsLeftInFlags) - 1) {
+ m_flags.otherBits = relativePropertyIndex;
+ m_staticMetaCallFunction = f;
+ }
+ }
+ quint16 relativePropertyIndex() const { Q_ASSERT(hasStaticMetaCallFunction()); return m_flags.otherBits; }
static Flags flagsForProperty(const QMetaProperty &);
void load(const QMetaProperty &);
@@ -128,27 +312,32 @@ private:
friend class QQmlPropertyCache;
void lazyLoad(const QMetaProperty &);
void lazyLoad(const QMetaMethod &);
- bool notFullyResolved() const { return _flags.notFullyResolved; }
-};
+ bool notFullyResolved() const { return m_flags.notFullyResolved; }
-QQmlPropertyData::QQmlPropertyData()
-{
- setCoreIndex(-1);
- setPropType(0);
- setNotifyIndex(-1);
- setOverrideIndex(-1);
- setRevision(0);
- setMetaObjectOffset(-1);
- setArguments(nullptr);
- trySetStaticMetaCallFunction(nullptr, 0);
-}
+ Flags m_flags;
+ qint16 m_coreIndex = -1;
+ quint16 m_propType = 0;
-QQmlPropertyData::QQmlPropertyData(const QQmlPropertyRawData &d)
-{
- *(static_cast<QQmlPropertyRawData *>(this)) = d;
-}
+ // The notify index is in the range returned by QObjectPrivate::signalIndex().
+ // This is different from QMetaMethod::methodIndex().
+ qint16 m_notifyIndex = -1;
+ qint16 m_overrideIndex = -1;
-bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
+ quint8 m_revision = 0;
+ quint8 m_typeMinorVersion = 0;
+ qint16 m_metaObjectOffset = -1;
+
+ QQmlPropertyCacheMethodArguments *m_arguments = nullptr;
+ StaticMetaCallFunction m_staticMetaCallFunction = nullptr;
+};
+
+#if QT_POINTER_SIZE == 4
+ Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 24);
+#else // QT_POINTER_SIZE == 8
+ Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 32);
+#endif
+
+bool QQmlPropertyData::operator==(const QQmlPropertyData &other) const
{
return flags() == other.flags() &&
propType() == other.propType() &&
@@ -157,6 +346,64 @@ bool QQmlPropertyData::operator==(const QQmlPropertyRawData &other)
revision() == other.revision();
}
+QQmlPropertyData::Flags::Flags()
+ : otherBits(0)
+ , isConstant(false)
+ , isWritable(false)
+ , isResettable(false)
+ , isAlias(false)
+ , isFinal(false)
+ , isOverridden(false)
+ , isDirect(false)
+ , type(OtherType)
+ , isVMEFunction(false)
+ , hasArguments(false)
+ , isSignal(false)
+ , isVMESignal(false)
+ , isV4Function(false)
+ , isSignalHandler(false)
+ , isOverload(false)
+ , isCloned(false)
+ , isConstructor(false)
+ , notFullyResolved(false)
+ , overrideIndexIsProperty(false)
+{}
+
+bool QQmlPropertyData::Flags::operator==(const QQmlPropertyData::Flags &other) const
+{
+ return isConstant == other.isConstant &&
+ isWritable == other.isWritable &&
+ isResettable == other.isResettable &&
+ isAlias == other.isAlias &&
+ isFinal == other.isFinal &&
+ isOverridden == other.isOverridden &&
+ type == other.type &&
+ isVMEFunction == other.isVMEFunction &&
+ hasArguments == other.hasArguments &&
+ isSignal == other.isSignal &&
+ isVMESignal == other.isVMESignal &&
+ isV4Function == other.isV4Function &&
+ isSignalHandler == other.isSignalHandler &&
+ isOverload == other.isOverload &&
+ isCloned == other.isCloned &&
+ isConstructor == other.isConstructor &&
+ notFullyResolved == other.notFullyResolved &&
+ overrideIndexIsProperty == other.overrideIndexIsProperty;
+}
+
+void QQmlPropertyData::Flags::copyPropertyTypeFlags(QQmlPropertyData::Flags from)
+{
+ switch (from.type) {
+ case QObjectDerivedType:
+ case EnumType:
+ case QListType:
+ case QmlBindingType:
+ case QJSValueType:
+ case QVariantType:
+ type = from.type;
+ }
+}
+
Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyData::WriteFlags)
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertyrawdata_p.h b/src/qml/qml/qqmlpropertyrawdata_p.h
deleted file mode 100644
index 833c0f6ad0..0000000000
--- a/src/qml/qml/qqmlpropertyrawdata_p.h
+++ /dev/null
@@ -1,341 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLPROPERTYRAWDATA_P_H
-#define QQMLPROPERTYRAWDATA_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <private/qobject_p.h>
-
-QT_BEGIN_NAMESPACE
-
-// We have this somewhat awful split between RawData and Data so that RawData can be
-// used in unions. In normal code, you should always use Data which initializes RawData
-// to an invalid state on construction.
-// ### We should be able to remove this split nowadays
-class QQmlPropertyCacheMethodArguments;
-class QQmlPropertyRawData
-{
-public:
- typedef QObjectPrivate::StaticMetaCallFunction StaticMetaCallFunction;
-
- struct Flags {
- enum Types {
- OtherType = 0,
- FunctionType = 1, // Is an invokable
- QObjectDerivedType = 2, // Property type is a QObject* derived type
- EnumType = 3, // Property type is an enum
- QListType = 4, // Property type is a QML list
- QmlBindingType = 5, // Property type is a QQmlBinding*
- QJSValueType = 6, // Property type is a QScriptValue
- V4HandleType = 7, // Property type is a QQmlV4Handle
- VarPropertyType = 8, // Property type is a "var" property of VMEMO
- QVariantType = 9 // Property is a QVariant
- };
-
- // The _otherBits (which "pad" the Flags struct to align it nicely) are used
- // to store the relative property index. It will only get used when said index fits. See
- // trySetStaticMetaCallFunction for details.
- // (Note: this padding is done here, because certain compilers have surprising behavior
- // when an enum is declared in-between two bit fields.)
- enum { BitsLeftInFlags = 10 };
- unsigned _otherBits : BitsLeftInFlags; // align to 32 bits
-
- // Can apply to all properties, except IsFunction
- unsigned isConstant : 1; // Has CONST flag
- unsigned isWritable : 1; // Has WRITE function
- unsigned isResettable : 1; // Has RESET function
- unsigned isAlias : 1; // Is a QML alias to another property
- unsigned isFinal : 1; // Has FINAL flag
- unsigned isOverridden : 1; // Is overridden by a extension property
- unsigned isDirect : 1; // Exists on a C++ QMetaObject
-
- unsigned type : 4; // stores an entry of Types
-
- // Apply only to IsFunctions
- unsigned isVMEFunction : 1; // Function was added by QML
- unsigned hasArguments : 1; // Function takes arguments
- unsigned isSignal : 1; // Function is a signal
- unsigned isVMESignal : 1; // Signal was added by QML
- unsigned isV4Function : 1; // Function takes QQmlV4Function* args
- unsigned isSignalHandler : 1; // Function is a signal handler
- unsigned isOverload : 1; // Function is an overload of another function
- unsigned isCloned : 1; // The function was marked as cloned
- unsigned isConstructor : 1; // The function was marked is a constructor
-
- // Internal QQmlPropertyCache flags
- unsigned notFullyResolved : 1; // True if the type data is to be lazily resolved
- unsigned overrideIndexIsProperty: 1;
-
- inline Flags();
- inline bool operator==(const Flags &other) const;
- inline void copyPropertyTypeFlags(Flags from);
- };
-
- Flags flags() const { return _flags; }
- void setFlags(Flags f)
- {
- unsigned otherBits = _flags._otherBits;
- _flags = f;
- _flags._otherBits = otherBits;
- }
-
- bool isValid() const { return coreIndex() != -1; }
-
- bool isConstant() const { return _flags.isConstant; }
- bool isWritable() const { return _flags.isWritable; }
- void setWritable(bool onoff) { _flags.isWritable = onoff; }
- bool isResettable() const { return _flags.isResettable; }
- bool isAlias() const { return _flags.isAlias; }
- bool isFinal() const { return _flags.isFinal; }
- bool isOverridden() const { return _flags.isOverridden; }
- bool isDirect() const { return _flags.isDirect; }
- bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; }
- bool isFunction() const { return _flags.type == Flags::FunctionType; }
- bool isQObject() const { return _flags.type == Flags::QObjectDerivedType; }
- bool isEnum() const { return _flags.type == Flags::EnumType; }
- bool isQList() const { return _flags.type == Flags::QListType; }
- bool isQmlBinding() const { return _flags.type == Flags::QmlBindingType; }
- bool isQJSValue() const { return _flags.type == Flags::QJSValueType; }
- bool isV4Handle() const { return _flags.type == Flags::V4HandleType; }
- bool isVarProperty() const { return _flags.type == Flags::VarPropertyType; }
- bool isQVariant() const { return _flags.type == Flags::QVariantType; }
- bool isVMEFunction() const { return _flags.isVMEFunction; }
- bool hasArguments() const { return _flags.hasArguments; }
- bool isSignal() const { return _flags.isSignal; }
- bool isVMESignal() const { return _flags.isVMESignal; }
- bool isV4Function() const { return _flags.isV4Function; }
- bool isSignalHandler() const { return _flags.isSignalHandler; }
- bool isOverload() const { return _flags.isOverload; }
- void setOverload(bool onoff) { _flags.isOverload = onoff; }
- bool isCloned() const { return _flags.isCloned; }
- bool isConstructor() const { return _flags.isConstructor; }
-
- bool hasOverride() const { return overrideIndex() >= 0; }
- bool hasRevision() const { return revision() != 0; }
-
- bool isFullyResolved() const { return !_flags.notFullyResolved; }
-
- int propType() const { Q_ASSERT(isFullyResolved()); return _propType; }
- void setPropType(int pt)
- {
- Q_ASSERT(pt >= 0);
- Q_ASSERT(pt <= std::numeric_limits<qint16>::max());
- _propType = quint16(pt);
- }
-
- int notifyIndex() const { return _notifyIndex; }
- void setNotifyIndex(int idx)
- {
- Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
- Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
- _notifyIndex = qint16(idx);
- }
-
- bool overrideIndexIsProperty() const { return _flags.overrideIndexIsProperty; }
- void setOverrideIndexIsProperty(bool onoff) { _flags.overrideIndexIsProperty = onoff; }
-
- int overrideIndex() const { return _overrideIndex; }
- void setOverrideIndex(int idx)
- {
- Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
- Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
- _overrideIndex = qint16(idx);
- }
-
- int coreIndex() const { return _coreIndex; }
- void setCoreIndex(int idx)
- {
- Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
- Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
- _coreIndex = qint16(idx);
- }
-
- quint8 revision() const { return _revision; }
- void setRevision(quint8 rev)
- {
- Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
- _revision = quint8(rev);
- }
-
- /* If a property is a C++ type, then we store the minor
- * version of this type.
- * This is required to resolve property or signal revisions
- * if this property is used as a grouped property.
- *
- * Test.qml
- * property TextEdit someTextEdit: TextEdit {}
- *
- * Test {
- * someTextEdit.preeditText: "test" //revision 7
- * someTextEdit.onEditingFinished: console.log("test") //revision 6
- * }
- *
- * To determine if these properties with revisions are available we need
- * the minor version of TextEdit as imported in Test.qml.
- *
- */
-
- quint8 typeMinorVersion() const { return _typeMinorVersion; }
- void setTypeMinorVersion(quint8 rev)
- {
- Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
- _typeMinorVersion = quint8(rev);
- }
-
- QQmlPropertyCacheMethodArguments *arguments() const { return _arguments; }
- void setArguments(QQmlPropertyCacheMethodArguments *args) { _arguments = args; }
-
- int metaObjectOffset() const { return _metaObjectOffset; }
- void setMetaObjectOffset(int off)
- {
- Q_ASSERT(off >= std::numeric_limits<qint16>::min());
- Q_ASSERT(off <= std::numeric_limits<qint16>::max());
- _metaObjectOffset = qint16(off);
- }
-
- StaticMetaCallFunction staticMetaCallFunction() const { return _staticMetaCallFunction; }
- void trySetStaticMetaCallFunction(StaticMetaCallFunction f, unsigned relativePropertyIndex)
- {
- if (relativePropertyIndex < (1 << Flags::BitsLeftInFlags) - 1) {
- _flags._otherBits = relativePropertyIndex;
- _staticMetaCallFunction = f;
- }
- }
- quint16 relativePropertyIndex() const { Q_ASSERT(hasStaticMetaCallFunction()); return _flags._otherBits; }
-
-private:
- Flags _flags;
- qint16 _coreIndex = 0;
- quint16 _propType = 0;
-
- // The notify index is in the range returned by QObjectPrivate::signalIndex().
- // This is different from QMetaMethod::methodIndex().
- qint16 _notifyIndex = 0;
- qint16 _overrideIndex = 0;
-
- quint8 _revision = 0;
- quint8 _typeMinorVersion = 0;
- qint16 _metaObjectOffset = 0;
-
- QQmlPropertyCacheMethodArguments *_arguments = nullptr;
- StaticMetaCallFunction _staticMetaCallFunction = nullptr;
-
- friend class QQmlPropertyData;
- friend class QQmlPropertyCache;
-};
-
-#if QT_POINTER_SIZE == 4
- Q_STATIC_ASSERT(sizeof(QQmlPropertyRawData) == 24);
-#else // QT_POINTER_SIZE == 8
- Q_STATIC_ASSERT(sizeof(QQmlPropertyRawData) == 32);
-#endif
-
-QQmlPropertyRawData::Flags::Flags()
- : _otherBits(0)
- , isConstant(false)
- , isWritable(false)
- , isResettable(false)
- , isAlias(false)
- , isFinal(false)
- , isOverridden(false)
- , isDirect(false)
- , type(OtherType)
- , isVMEFunction(false)
- , hasArguments(false)
- , isSignal(false)
- , isVMESignal(false)
- , isV4Function(false)
- , isSignalHandler(false)
- , isOverload(false)
- , isCloned(false)
- , isConstructor(false)
- , notFullyResolved(false)
- , overrideIndexIsProperty(false)
-{}
-
-bool QQmlPropertyRawData::Flags::operator==(const QQmlPropertyRawData::Flags &other) const
-{
- return isConstant == other.isConstant &&
- isWritable == other.isWritable &&
- isResettable == other.isResettable &&
- isAlias == other.isAlias &&
- isFinal == other.isFinal &&
- isOverridden == other.isOverridden &&
- type == other.type &&
- isVMEFunction == other.isVMEFunction &&
- hasArguments == other.hasArguments &&
- isSignal == other.isSignal &&
- isVMESignal == other.isVMESignal &&
- isV4Function == other.isV4Function &&
- isSignalHandler == other.isSignalHandler &&
- isOverload == other.isOverload &&
- isCloned == other.isCloned &&
- isConstructor == other.isConstructor &&
- notFullyResolved == other.notFullyResolved &&
- overrideIndexIsProperty == other.overrideIndexIsProperty;
-}
-
-void QQmlPropertyRawData::Flags::copyPropertyTypeFlags(QQmlPropertyRawData::Flags from)
-{
- switch (from.type) {
- case QObjectDerivedType:
- case EnumType:
- case QListType:
- case QmlBindingType:
- case QJSValueType:
- case V4HandleType:
- case QVariantType:
- type = from.type;
- }
-}
-
-QT_END_NAMESPACE
-
-#endif // QQMLPROPERTYRAWDATA_P_H
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
index efe190cbcf..88eedec061 100644
--- a/src/qml/qml/qqmltype.cpp
+++ b/src/qml/qml/qqmltype.cpp
@@ -118,7 +118,8 @@ QJSValue QQmlType::SingletonInstanceInfo::scriptApi(QQmlEngine *e) const
QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
: regType(type), iid(nullptr), typeId(0), listId(0), revision(0),
containsRevisionedAttributes(false), baseMetaObject(nullptr),
- index(-1), isSetup(false), isEnumSetup(false), haveSuperType(false)
+ index(-1), isSetup(false), isEnumFromCacheSetup(false), isEnumFromBaseSetup(false),
+ haveSuperType(false)
{
switch (type) {
case QQmlType::CppType:
@@ -176,8 +177,8 @@ QQmlTypePrivate::~QQmlTypePrivate()
}
QQmlType::QQmlType() = default;
-QQmlType::QQmlType(const QQmlType &other) = default;
-QQmlType::QQmlType(QQmlType &&other) = default;
+QQmlType::QQmlType(const QQmlType &) = default;
+QQmlType::QQmlType(QQmlType &&) = default;
QQmlType &QQmlType::operator =(const QQmlType &other) = default;
QQmlType &QQmlType::operator =(QQmlType &&other) = default;
QQmlType::QQmlType(const QQmlTypePrivate *priv) : d(priv) {}
@@ -347,19 +348,24 @@ void QQmlTypePrivate::init() const
void QQmlTypePrivate::initEnums(const QQmlPropertyCache *cache) const
{
- if (isEnumSetup) return;
+ if ((isEnumFromBaseSetup || !baseMetaObject)
+ && (isEnumFromCacheSetup || !cache)) {
+ return;
+ }
init();
QMutexLocker lock(QQmlMetaType::typeRegistrationLock());
- if (isEnumSetup) return;
- if (cache)
+ if (!isEnumFromCacheSetup && cache) {
insertEnumsFromPropertyCache(cache);
- if (baseMetaObject) // could be singleton type without metaobject
- insertEnums(baseMetaObject);
+ isEnumFromCacheSetup = true;
+ }
- isEnumSetup = true;
+ if (!isEnumFromBaseSetup && baseMetaObject) { // could be singleton type without metaobject
+ insertEnums(baseMetaObject);
+ isEnumFromBaseSetup = true;
+ }
}
void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
@@ -503,25 +509,6 @@ void QQmlTypePrivate::setName(const QString &uri, const QString &element)
name = uri.isEmpty() ? element : (uri + QLatin1Char('/') + element);
}
-QQmlPropertyCache *QQmlTypePrivate::propertyCacheForMinorVersion(int minorVersion) const
-{
- for (int i = 0; i < propertyCaches.count(); ++i)
- if (propertyCaches.at(i).minorVersion == minorVersion)
- return propertyCaches.at(i).cache.data();
- return nullptr;
-}
-
-void QQmlTypePrivate::setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache)
-{
- for (int i = 0; i < propertyCaches.count(); ++i) {
- if (propertyCaches.at(i).minorVersion == minorVersion) {
- propertyCaches[i].cache = cache;
- return;
- }
- }
- propertyCaches.append(PropertyCacheByMinorVersion(cache, minorVersion));
-}
-
QByteArray QQmlType::typeName() const
{
if (d) {
diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h
index 1d1345a0cb..0e59b1be06 100644
--- a/src/qml/qml/qqmltype_p.h
+++ b/src/qml/qml/qqmltype_p.h
@@ -89,7 +89,6 @@ public:
}
bool isValid() const { return !d.isNull(); }
- const QQmlTypePrivate *key() const { return d.data(); }
QByteArray typeName() const;
QString qmlTypeName() const;
diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h
index 380139f385..b317aff740 100644
--- a/src/qml/qml/qqmltype_p_p.h
+++ b/src/qml/qml/qqmltype_p_p.h
@@ -120,24 +120,14 @@ public:
int index;
mutable volatile bool isSetup:1;
- mutable volatile bool isEnumSetup:1;
+ mutable volatile bool isEnumFromCacheSetup:1;
+ mutable volatile bool isEnumFromBaseSetup:1;
mutable bool haveSuperType:1;
mutable QList<QQmlProxyMetaObject::ProxyData> metaObjects;
mutable QStringHash<int> enums;
mutable QStringHash<int> scopedEnumIndex; // maps from enum name to index in scopedEnums
mutable QList<QStringHash<int>*> scopedEnums;
- struct PropertyCacheByMinorVersion
- {
- PropertyCacheByMinorVersion() : cache(nullptr), minorVersion(-1) {}
- explicit PropertyCacheByMinorVersion(QQmlPropertyCache *pc, int ver) : cache(pc), minorVersion(ver) {}
- QQmlPropertyCachePtr cache;
- int minorVersion;
- };
- QVector<PropertyCacheByMinorVersion> propertyCaches;
- QQmlPropertyCache *propertyCacheForMinorVersion(int minorVersion) const;
- void setPropertyCacheForMinorVersion(int minorVersion, QQmlPropertyCache *cache);
-
void setName(const QString &uri, const QString &element);
private:
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index 3ec828ea2d..86513b5ff8 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "qqmltypewrapper_p.h"
-#include <private/qv8engine_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlcontext_p.h>
@@ -48,6 +47,8 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <private/qv4identifiertable_p.h>
+#include <private/qv4lookup_p.h>
QT_BEGIN_NAMESPACE
@@ -170,6 +171,7 @@ static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *n
ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
+ // Keep this code in sync with ::virtualResolveLookupGetter
Q_ASSERT(m->as<QQmlTypeWrapper>());
if (!id.isString())
@@ -426,6 +428,64 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const
return QV4::Encode(QQmlMetaObject::canConvert(theirType, myQmlType));
}
+ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup)
+{
+ // Keep this code in sync with ::virtualGet
+ PropertyKey id = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->runtimeStrings[lookup->nameIndex]);
+ if (!id.isString())
+ return Object::virtualResolveLookupGetter(object, engine, lookup);
+ Scope scope(engine);
+
+ const QQmlTypeWrapper *This = static_cast<const QQmlTypeWrapper *>(object);
+ ScopedString name(scope, id.asStringOrSymbol());
+ QQmlContextData *qmlContext = engine->callingQmlContext();
+
+ Scoped<QQmlTypeWrapper> w(scope, static_cast<const QQmlTypeWrapper *>(This));
+ QQmlType type = w->d()->type();
+
+ if (type.isValid()) {
+
+ if (type.isSingleton()) {
+ QQmlEngine *e = engine->qmlEngine();
+ QQmlType::SingletonInstanceInfo *siinfo = type.singletonInstanceInfo();
+ siinfo->init(e);
+
+ QObject *qobjectSingleton = siinfo->qobjectApi(e);
+ if (qobjectSingleton) {
+
+ const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums;
+ if (!includeEnums || !name->startsWithUpper()) {
+ QQmlData *ddata = QQmlData::get(qobjectSingleton, false);
+ if (ddata && ddata->propertyCache) {
+ ScopedValue val(scope, Value::fromReturnedValue(QV4::QObjectWrapper::wrap(engine, qobjectSingleton)));
+ QQmlPropertyData *property = ddata->propertyCache->property(name.getPointer(), qobjectSingleton, qmlContext);
+ if (property) {
+ lookup->qobjectLookup.ic = This->internalClass();
+ lookup->qobjectLookup.staticQObject = static_cast<Heap::QObjectWrapper *>(val->heapObject());
+ lookup->qobjectLookup.propertyCache = ddata->propertyCache;
+ lookup->qobjectLookup.propertyCache->addref();
+ lookup->qobjectLookup.propertyData = property;
+ lookup->getter = QV4::QObjectWrapper::lookupGetter;
+ return lookup->getter(lookup, engine, *This);
+ }
+ // Fall through to base implementation
+ }
+ // Fall through to base implementation
+ }
+ // Fall through to base implementation
+ }
+ // Fall through to base implementation
+ }
+ // Fall through to base implementation
+ }
+ return QV4::Object::virtualResolveLookupGetter(object, engine, lookup);
+}
+
+bool QQmlTypeWrapper::virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, Lookup *lookup, const Value &value)
+{
+ return Object::virtualResolveLookupSetter(object, engine, lookup, value);
+}
+
void Heap::QQmlScopedEnumWrapper::destroy()
{
QQmlType::derefHandle(typePrivate);
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index bc615e0f6c..c797a4ac10 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -111,6 +111,9 @@ struct Q_QML_EXPORT QQmlTypeWrapper : Object
static ReturnedValue create(ExecutionEngine *, QObject *, const QQmlRefPointer<QQmlTypeNameCache> &, const QQmlImportRef *,
Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums);
+ static ReturnedValue virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup);
+ static bool virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, Lookup *lookup, const Value &value);
+
protected:
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index 21505754bb..f08005fd20 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -80,19 +80,26 @@ QQmlValueTypeFactoryImpl::~QQmlValueTypeFactoryImpl()
bool QQmlValueTypeFactoryImpl::isValueType(int idx)
{
- if (idx >= (int)QVariant::UserType) {
- return (valueType(idx) != nullptr);
- } else if (idx >= 0
- && idx != QVariant::StringList
- && idx != QMetaType::QObjectStar
- && idx != QMetaType::VoidStar
- && idx != QMetaType::Nullptr
- && idx != QMetaType::QVariant
- && idx != QMetaType::QLocale) {
+ if (idx >= QMetaType::User)
+ return valueType(idx) != nullptr;
+
+ if (idx < 0)
+ return false;
+
+ // Qt internal types
+ switch (idx) {
+ case QMetaType::QStringList:
+ case QMetaType::QObjectStar:
+ case QMetaType::VoidStar:
+ case QMetaType::Nullptr:
+ case QMetaType::QVariant:
+ case QMetaType::QLocale:
+ case QMetaType::QImage: // scarce type, keep as QVariant
+ case QMetaType::QPixmap: // scarce type, keep as QVariant
+ return false;
+ default:
return true;
}
-
- return false;
}
const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t)
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 9ce1c82f09..cf6553d129 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -38,7 +38,7 @@
****************************************************************************/
#include "qqmlvaluetypewrapper_p.h"
-#include <private/qv8engine_p.h>
+
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlbinding_p.h>
#include <private/qqmlglobal_p.h>
@@ -51,6 +51,8 @@
#include <private/qv4stackframe_p.h>
#include <private/qv4objectiterator_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <private/qv4identifiertable_p.h>
+#include <private/qv4lookup_p.h>
#include <QtCore/qloggingcategory.h>
QT_BEGIN_NAMESPACE
@@ -372,6 +374,117 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(const FunctionObject *b, con
return Encode(b->engine()->newString(result));
}
+Q_ALWAYS_INLINE static ReturnedValue getGadgetProperty(ExecutionEngine *engine,
+ Heap::QQmlValueTypeWrapper *valueTypeWrapper,
+ QQmlPropertyData *property)
+{
+ if (property->isFunction()) {
+ // calling a Q_INVOKABLE function of a value type
+ return QV4::QObjectMethod::create(engine->rootContext(), valueTypeWrapper, property->coreIndex());
+ }
+
+#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \
+ if (property->propType() == metatype) { \
+ cpptype v; \
+ void *args[] = { &v, nullptr }; \
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(valueTypeWrapper->gadgetPtr), \
+ QMetaObject::ReadProperty, index, args); \
+ return QV4::Encode(constructor(v)); \
+ }
+
+ const QMetaObject *metaObject = valueTypeWrapper->propertyCache()->metaObject();
+
+ int index = property->coreIndex();
+ QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index);
+
+ // These four types are the most common used by the value type wrappers
+ VALUE_TYPE_LOAD(QMetaType::QReal, qreal, qreal);
+ VALUE_TYPE_LOAD(QMetaType::Int || property->isEnum(), int, int);
+ VALUE_TYPE_LOAD(QMetaType::Int, int, int);
+ VALUE_TYPE_LOAD(QMetaType::QString, QString, engine->newString);
+ VALUE_TYPE_LOAD(QMetaType::Bool, bool, bool);
+
+ QVariant v;
+ void *args[] = { nullptr, nullptr };
+ if (property->propType() == QMetaType::QVariant) {
+ args[0] = &v;
+ } else {
+ v = QVariant(property->propType(), static_cast<void *>(nullptr));
+ args[0] = v.data();
+ }
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(valueTypeWrapper->gadgetPtr), QMetaObject::ReadProperty,
+ index, args);
+ return engine->fromVariant(v);
+#undef VALUE_TYPE_LOAD
+}
+
+ReturnedValue QQmlValueTypeWrapper::virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine,
+ Lookup *lookup)
+{
+ PropertyKey id = engine->identifierTable->asPropertyKey(engine->currentStackFrame->v4Function->compilationUnit->
+ runtimeStrings[lookup->nameIndex]);
+ if (!id.isString())
+ return Object::virtualResolveLookupGetter(object, engine, lookup);
+
+ const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(object);
+ QV4::ExecutionEngine *v4 = r->engine();
+ Scope scope(v4);
+ ScopedString name(scope, id.asStringOrSymbol());
+
+ // Note: readReferenceValue() can change the reference->type.
+ if (const QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
+ if (!reference->readReferenceValue())
+ return Value::undefinedValue().asReturnedValue();
+ }
+
+ QQmlPropertyData *result = r->d()->propertyCache()->property(name.getPointer(), nullptr, nullptr);
+ if (!result)
+ return QV4::Object::virtualResolveLookupGetter(object, engine, lookup);
+
+ lookup->qgadgetLookup.ic = r->internalClass();
+ lookup->qgadgetLookup.propertyCache = r->d()->propertyCache();
+ lookup->qgadgetLookup.propertyCache->addref();
+ lookup->qgadgetLookup.propertyData = result;
+ lookup->getter = QQmlValueTypeWrapper::lookupGetter;
+ return lookup->getter(lookup, engine, *object);
+}
+
+ReturnedValue QQmlValueTypeWrapper::lookupGetter(Lookup *lookup, ExecutionEngine *engine, const Value &object)
+{
+ const auto revertLookup = [lookup, engine, &object]() {
+ lookup->qgadgetLookup.propertyCache->release();
+ lookup->qgadgetLookup.propertyCache = nullptr;
+ lookup->getter = Lookup::getterGeneric;
+ return Lookup::getterGeneric(lookup, engine, object);
+ };
+
+ // we can safely cast to a QV4::Object here. If object is something else,
+ // the internal class won't match
+ Heap::Object *o = static_cast<Heap::Object *>(object.heapObject());
+ if (!o || o->internalClass != lookup->qgadgetLookup.ic)
+ return revertLookup();
+
+ Heap::QQmlValueTypeWrapper *valueTypeWrapper =
+ const_cast<Heap::QQmlValueTypeWrapper*>(static_cast<const Heap::QQmlValueTypeWrapper *>(o));
+ if (valueTypeWrapper->propertyCache() != lookup->qgadgetLookup.propertyCache)
+ return revertLookup();
+
+ if (lookup->qgadgetLookup.ic->vtable == QQmlValueTypeReference::staticVTable()) {
+ Scope scope(engine);
+ Scoped<QQmlValueTypeReference> referenceWrapper(scope, valueTypeWrapper);
+ referenceWrapper->readReferenceValue();
+ }
+
+ QQmlPropertyData *property = lookup->qgadgetLookup.propertyData;
+ return getGadgetProperty(engine, valueTypeWrapper, property);
+}
+
+bool QQmlValueTypeWrapper::virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, Lookup *lookup,
+ const Value &value)
+{
+ return Object::virtualResolveLookupSetter(object, engine, lookup, value);
+}
+
ReturnedValue QQmlValueTypeWrapper::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlValueTypeWrapper>());
@@ -397,43 +510,7 @@ ReturnedValue QQmlValueTypeWrapper::virtualGet(const Managed *m, PropertyKey id,
if (hasProperty)
*hasProperty = true;
- if (result->isFunction())
- // calling a Q_INVOKABLE function of a value type
- return QV4::QObjectMethod::create(v4->rootContext(), r, result->coreIndex());
-
-#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \
- if (result->propType() == metatype) { \
- cpptype v; \
- void *args[] = { &v, 0 }; \
- metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args); \
- return QV4::Encode(constructor(v)); \
- }
-
- const QMetaObject *metaObject = r->d()->propertyCache()->metaObject();
-
- int index = result->coreIndex();
- QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index);
-
- void *gadget = r->d()->gadgetPtr;
-
- // These four types are the most common used by the value type wrappers
- VALUE_TYPE_LOAD(QMetaType::QReal, qreal, qreal);
- VALUE_TYPE_LOAD(QMetaType::Int || result->isEnum(), int, int);
- VALUE_TYPE_LOAD(QMetaType::Int, int, int);
- VALUE_TYPE_LOAD(QMetaType::QString, QString, v4->newString);
- VALUE_TYPE_LOAD(QMetaType::Bool, bool, bool);
-
- QVariant v;
- void *args[] = { nullptr, nullptr };
- if (result->propType() == QMetaType::QVariant) {
- args[0] = &v;
- } else {
- v = QVariant(result->propType(), static_cast<void *>(nullptr));
- args[0] = v.data();
- }
- metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args);
- return v4->fromVariant(v);
-#undef VALUE_TYPE_ACCESSOR
+ return getGadgetProperty(v4, r->d(), result);
}
bool QQmlValueTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index 8db9474132..baac129afa 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -112,6 +112,9 @@ public:
static PropertyAttributes virtualGetOwnProperty(const Managed *m, PropertyKey id, Property *p);
static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m, Value *target);
static ReturnedValue method_toString(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup);
+ static bool virtualResolveLookupSetter(Object *object, ExecutionEngine *engine, Lookup *lookup, const Value &value);
+ static ReturnedValue lookupGetter(Lookup *lookup, ExecutionEngine *engine, const Value &object);
static void initProto(ExecutionEngine *v4);
};
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index 6bc469c836..5d13415513 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -594,7 +594,7 @@ QList<QObject *> *QQmlVMEMetaObject::readPropertyAsList(int id) const
QV4::Scope scope(engine);
QV4::Scoped<QV4::VariantObject> v(scope, *(md->data() + id));
if (!v || (int)v->d()->data().userType() != qMetaTypeId<QList<QObject *> >()) {
- QVariant variant(qVariantFromValue(QList<QObject*>()));
+ QVariant variant(QVariant::fromValue(QList<QObject*>()));
v = engine->newVariantObject(variant);
md->set(engine, id, v);
}
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index 87dc9fb0b2..2371d70f10 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -66,7 +66,6 @@
#include "qqmlguard_p.h"
#include "qqmlcontext_p.h"
-#include <private/qv8engine_p.h>
#include <private/qflagpointer_p.h>
#include <private/qv4object_p.h>
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 9f629f974d..c6b7f2ab3f 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -39,8 +39,6 @@
#include "qqmlxmlhttprequest_p.h"
-#include <private/qv8engine_p.h>
-
#include "qqmlengine.h"
#include "qqmlengine_p.h"
#include <private/qqmlrefcount_p.h>
@@ -70,8 +68,6 @@
using namespace QV4;
-#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network)
-
#define V4THROW_REFERENCE(string) \
do { \
ScopedObject error(scope, scope.engine->newReferenceErrorObject(QStringLiteral(string))); \
@@ -2067,6 +2063,4 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
QT_END_NAMESPACE
-#endif // xmlstreamreader && qml_network
-
#include <qqmlxmlhttprequest.moc>
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 64dc581a56..3bc588b50e 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -436,7 +436,7 @@ ReturnedValue QtObject::method_font(const FunctionObject *b, const Value *, cons
QV4::ExecutionEngine *v4 = scope.engine;
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(argv[0]), v4, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, argv[0], v4, &ok);
if (!ok)
THROW_GENERIC_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified");
return scope.engine->fromVariant(v);
@@ -540,7 +540,7 @@ ReturnedValue QtObject::method_matrix4x4(const FunctionObject *b, const Value *,
if (argc == 1 && argv[0].isObject()) {
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(argv[0]), scope.engine, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, argv[0], scope.engine, &ok);
if (!ok)
THROW_GENERIC_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array");
return scope.engine->fromVariant(v);
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 23559618ef..f9b69cfacc 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -132,19 +132,6 @@ private:
QV4::ExecutionEngine *e;
};
-class Q_QML_PRIVATE_EXPORT QQmlV4Handle
-{
-public:
- QQmlV4Handle() : d(QV4::Encode::undefined()) {}
- explicit QQmlV4Handle(const QV4::Value &v) : d(v.asReturnedValue()) {}
- explicit QQmlV4Handle(QV4::ReturnedValue v) : d(v) {}
-
- operator QV4::ReturnedValue() const { return d; }
-
-private:
- quint64 d;
-};
-
class QObject;
class QQmlEngine;
class QNetworkAccessManager;
@@ -238,6 +225,4 @@ inline QV8Engine::Deletable *QV8Engine::extensionData(int index) const
QT_END_NAMESPACE
-Q_DECLARE_METATYPE(QQmlV4Handle)
-
#endif // QQMLV8ENGINE_P_H