diff options
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqml.cpp | 20 | ||||
-rw-r--r-- | src/qml/qml/qqml.h | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 13 | ||||
-rw-r--r-- | src/qml/qml/qqmlerror.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlimport.cpp | 17 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 4 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlprivate.h | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlproperty.cpp | 12 | ||||
-rw-r--r-- | src/qml/qml/qqmlxmlhttprequest.cpp | 12 |
11 files changed, 90 insertions, 19 deletions
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp index 613816e3f7..8a50b51b5d 100644 --- a/src/qml/qml/qqml.cpp +++ b/src/qml/qml/qqml.cpp @@ -76,6 +76,26 @@ int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *q return QQmlMetaType::typeId(uri, versionMajor, versionMinor, qmlName); } +// From qqmlprivate.h +QObject *QQmlPrivate::RegisterSingletonFunctor::operator()(QQmlEngine *qeng, QJSEngine *) +{ + if (qeng->thread() != m_object->thread()) { + QQmlError error; + error.setDescription(QLatin1String("Registered object must live in the same thread as the engine it was registered with")); + QQmlEnginePrivate::get(qeng)->warning(qeng, error); + return nullptr; + } + if (alreadyCalled) { + QQmlError error; + error.setDescription(QLatin1String("Singleton registered by registerSingletonInstance must only be accessed from one engine")); + QQmlEnginePrivate::get(qeng)->warning(qeng, error); + return nullptr; + } + alreadyCalled = true; + qeng->setObjectOwnership(m_object, QQmlEngine::CppOwnership); + return m_object; +}; + /* This method is "over generalized" to allow us to (potentially) register more types of things in the future without adding exported symbols. diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index 4f3bfb76b0..bfd1c88b28 100644 --- a/src/qml/qml/qqml.h +++ b/src/qml/qml/qqml.h @@ -667,6 +667,15 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api); } +template<typename T> +inline auto qmlRegisterSingletonInstance(const char *uri, int versionMajor, int versionMinor, + const char *typeName, T *cppObject) -> typename std::enable_if<std::is_base_of<QObject, T>::value, int>::type +{ + QQmlPrivate::RegisterSingletonFunctor registrationFunctor; + registrationFunctor.m_object = cppObject; + return qmlRegisterSingletonType<T>(uri, versionMajor, versionMinor, typeName, registrationFunctor); +} + inline int qmlRegisterSingletonType(const QUrl &url, const char *uri, int versionMajor, int versionMinor, const char *qmlName) { if (url.isRelative()) { diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 7ba5fc08a5..0580efe0d2 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -2454,17 +2454,20 @@ QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type) } else if (siinfo->qobjectCallback) { QObject *o = siinfo->qobjectCallback(q, q); if (!o) { - qFatal("qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.", - qPrintable(QString::fromUtf8(type.typeName()))); + QQmlError error; + error.setMessageType(QtMsgType::QtCriticalMsg); + error.setDescription(QString::asprintf("qmlRegisterSingletonType(): \"%s\" is not available because the callback function returns a null pointer.", + qPrintable(QString::fromUtf8(type.typeName())))); + warning(error); + } else { + // if this object can use a property cache, create it now + QQmlData::ensurePropertyCache(q, o); } - // if this object can use a property cache, create it now - QQmlData::ensurePropertyCache(q, o); // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj) // should behave identically to QML singleton types. q->setContextForObject(o, new QQmlContext(q->rootContext(), q)); value = q->newQObject(o); singletonInstances.insert(type, value); - } else if (!siinfo->url.isEmpty()) { QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous); QObject *o = component.beginCreate(q->rootContext()); diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp index 739d5ce4cd..0b94ed3b49 100644 --- a/src/qml/qml/qqmlerror.cpp +++ b/src/qml/qml/qqmlerror.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qqmlerror.h" +#include "qqmlfile.h" #include "qqmlsourcecoordinate_p.h" #include <private/qqmljsdiagnosticmessage_p.h> @@ -307,8 +308,8 @@ QDebug operator<<(QDebug debug, const QQmlError &error) QUrl url = error.url(); - if (error.line() > 0 && url.scheme() == QLatin1String("file")) { - QString file = url.toLocalFile(); + if (error.line() > 0 && (url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("qrc"))) { + QString file = QQmlFile::urlToLocalFileOrQrc(url); QFile f(file); if (f.open(QIODevice::ReadOnly)) { QByteArray data = f.readAll(); diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index f4cdb45aff..7c9c0da01a 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -395,9 +395,18 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports:: const QQmlDirComponents &components = import->qmlDirComponents; + const int importMajorVersion = import->majversion; + const int importMinorVersion = import->minversion; + auto shouldSkipSingleton = [importMajorVersion, importMinorVersion](int singletonMajorVersion, int singletonMinorVersion) -> bool { + return importMajorVersion != -1 && + (singletonMajorVersion > importMajorVersion || (singletonMajorVersion == importMajorVersion && singletonMinorVersion > importMinorVersion)); + }; + ConstIterator cend = components.constEnd(); for (ConstIterator cit = components.constBegin(); cit != cend; ++cit) { if (cit->singleton && excludeBaseUrl(import->url, cit->fileName, baseUrl.toString())) { + if (shouldSkipSingleton(cit->majorVersion, cit->minorVersion)) + continue; QQmlImports::CompositeSingletonReference ref; ref.typeName = cit->typeName; ref.prefix = set.prefix; @@ -408,7 +417,9 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports:: } if (QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion)) { - module->walkCompositeSingletons([&resultList, &set](const QQmlType &singleton) { + module->walkCompositeSingletons([&resultList, &set, &shouldSkipSingleton](const QQmlType &singleton) { + if (shouldSkipSingleton(singleton.majorVersion(), singleton.minorVersion())) + return; QQmlImports::CompositeSingletonReference ref; ref.typeName = singleton.elementName(); ref.prefix = set.prefix; @@ -1947,7 +1958,9 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths) if (qmlImportTrace()) qDebug().nospace() << "QQmlImportDatabase::setImportPathList: " << paths; - fileImportPath = paths; + fileImportPath.clear(); + for (auto it = paths.crbegin(); it != paths.crend(); ++it) + addImportPath(*it); // Our existing cached paths may have been invalidated clearDirCache(); diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index f21427ff69..2c641d3845 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -60,7 +60,7 @@ struct LockedData : private QQmlMetaTypeData }; Q_GLOBAL_STATIC(LockedData, metaTypeData) -Q_GLOBAL_STATIC_WITH_ARGS(QMutex, metaTypeDataLock, (QMutex::Recursive)) +Q_GLOBAL_STATIC(QRecursiveMutex, metaTypeDataLock) class QQmlMetaTypeDataPtr { @@ -804,7 +804,7 @@ QQmlType QQmlMetaType::typeForUrl(const QString &urlString, return QQmlType(); } -QMutex *QQmlMetaType::typeRegistrationLock() +QRecursiveMutex *QQmlMetaType::typeRegistrationLock() { return metaTypeDataLock(); } diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index c2535a7fd5..6c2b0bb2a6 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE class QQmlTypeModule; -class QMutex; +class QRecursiveMutex; class QQmlError; namespace QV4 { class ExecutableCompilationUnit; } @@ -160,7 +160,7 @@ public: static void prependCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler); static void removeCachedUnitLookupFunction(QQmlPrivate::QmlUnitCacheLookupFunction handler); - static QMutex *typeRegistrationLock(); + static QRecursiveMutex *typeRegistrationLock(); static QString prettyTypeName(const QObject *object); diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index d5681b3449..f89608cd5d 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -57,6 +57,7 @@ #include <private/qqmldebugserviceinterfaces_p.h> #include <private/qqmlscriptdata_p.h> #include <private/qjsvalue_p.h> +#include <private/qv4generatorobject_p.h> #include <qtqml_tracepoints_p.h> @@ -1135,7 +1136,10 @@ void QQmlObjectCreator::setupFunctions() if (!property->isVMEFunction()) continue; - function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction); + if (runtimeFunction->isGenerator()) + function = QV4::GeneratorFunction::create(qmlContext, runtimeFunction); + else + function = QV4::FunctionObject::createScriptFunction(qmlContext, runtimeFunction); _vmeMetaObject->setVmeMethod(property->coreIndex(), function); } } diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h index eff78195d9..e6dd5e0b16 100644 --- a/src/qml/qml/qqmlprivate.h +++ b/src/qml/qml/qqmlprivate.h @@ -322,6 +322,13 @@ namespace QQmlPrivate int Q_QML_EXPORT qmlregister(RegistrationType, void *); void Q_QML_EXPORT qmlunregister(RegistrationType, quintptr); + struct Q_QML_EXPORT RegisterSingletonFunctor + { + QObject *operator()(QQmlEngine *, QJSEngine *); + + QObject *m_object; + bool alreadyCalled = false; + }; } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp index c8166695ba..5f57e0eca1 100644 --- a/src/qml/qml/qqmlproperty.cpp +++ b/src/qml/qml/qqmlproperty.cpp @@ -1216,10 +1216,18 @@ bool QQmlPropertyPrivate::write(QObject *object, if (propertyType == variantType && !isUrl && propertyType != qMetaTypeId<QList<QUrl>>() && !property.isQList()) { return property.writeProperty(object, const_cast<void *>(value.constData()), flags); } else if (property.isQObject()) { - QQmlMetaObject valMo = rawMetaObjectForType(enginePriv, variantType); + QVariant val = value; + int varType = variantType; + if (variantType == QMetaType::Nullptr) { + // This reflects the fact that you can assign a nullptr to a QObject pointer + // Without the change to QObjectStar, rawMetaObjectForType would not give us a QQmlMetaObject + varType = QMetaType::QObjectStar; + val = QVariant(QMetaType::QObjectStar, nullptr); + } + QQmlMetaObject valMo = rawMetaObjectForType(enginePriv, varType); if (valMo.isNull()) return false; - QObject *o = *static_cast<QObject *const *>(value.constData()); + QObject *o = *static_cast<QObject *const *>(val.constData()); QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyType); if (o) diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index b435f8ef66..4db0562c0e 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1570,7 +1570,8 @@ void QQmlXMLHttpRequest::dispatchCallbackNow(Object *thisObj, bool done, bool er if (scope.engine->hasException) { QQmlError error = scope.engine->catchExceptionAsQmlError(); - QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error); + QQmlEnginePrivate *qmlEnginePrivate = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr; + QQmlEnginePrivate::warning(qmlEnginePrivate, error); } }; @@ -1761,8 +1762,13 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(const FunctionObject *b, const // Argument 1 - URL QUrl url = QUrl(argv[1].toQStringNoThrow()); - if (url.isRelative()) - url = scope.engine->callingQmlContext()->resolvedUrl(url); + if (url.isRelative()) { + QQmlContextData *qmlContextData = scope.engine->callingQmlContext(); + if (qmlContextData) + url = qmlContextData->resolvedUrl(url); + else + url = scope.engine->resolvedUrl(url.url()); + } bool async = true; // Argument 2 - async (optional) |