diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-04-23 09:33:25 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-04-23 09:34:29 +0200 |
commit | 580fa7dc88aae23053e44ffa335a15f6af112a20 (patch) | |
tree | 5bc915d7c2e252739122d9441bd0d7fa7175d0c2 /src/qml/qml | |
parent | 6767114285db9d0e16dc278d08f231e8561546b4 (diff) | |
parent | c00283bb3bb966bf60c307ec8283bd98c12318bf (diff) |
Merge remote-tracking branch 'origin/dev' into wip/scenegraphng
Change-Id: Ifec879473540b609403ac951967f6d9ecb0bb6f0
Diffstat (limited to 'src/qml/qml')
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 |