aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqml.cpp20
-rw-r--r--src/qml/qml/qqml.h9
-rw-r--r--src/qml/qml/qqmlengine.cpp13
-rw-r--r--src/qml/qml/qqmlerror.cpp5
-rw-r--r--src/qml/qml/qqmlimport.cpp17
-rw-r--r--src/qml/qml/qqmlmetatype.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype_p.h4
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp6
-rw-r--r--src/qml/qml/qqmlprivate.h7
-rw-r--r--src/qml/qml/qqmlproperty.cpp12
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp12
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)