diff options
Diffstat (limited to 'src/qml/qml')
24 files changed, 187 insertions, 1151 deletions
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index 6d69294c17..ca13ce9211 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -18,7 +18,6 @@ SOURCES += \ $$PWD/qqmlparserstatus.cpp \ $$PWD/qqmltypeloader.cpp \ $$PWD/qqmlinfo.cpp \ - $$PWD/qqmlerror.cpp \ $$PWD/qqmlvaluetype.cpp \ $$PWD/qqmlcleanup.cpp \ $$PWD/qqmlpropertycache.cpp \ @@ -44,7 +43,6 @@ SOURCES += \ $$PWD/qqmltypewrapper.cpp \ $$PWD/qqmlfileselector.cpp \ $$PWD/qqmlobjectcreator.cpp \ - $$PWD/qqmldirparser.cpp \ $$PWD/qqmldelayedcallqueue.cpp \ $$PWD/qqmlloggingcategory.cpp @@ -81,7 +79,6 @@ HEADERS += \ $$PWD/qqmllist.h \ $$PWD/qqmllist_p.h \ $$PWD/qqmldata_p.h \ - $$PWD/qqmlerror.h \ $$PWD/qqmlvaluetype_p.h \ $$PWD/qqmlcleanup_p.h \ $$PWD/qqmlpropertycache_p.h \ @@ -112,7 +109,6 @@ HEADERS += \ $$PWD/qqmlfileselector_p.h \ $$PWD/qqmlfileselector.h \ $$PWD/qqmlobjectcreator_p.h \ - $$PWD/qqmldirparser_p.h \ $$PWD/qqmldelayedcallqueue_p.h \ $$PWD/qqmlloggingcategory_p.h diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h index 05a9f70247..bf9330856d 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); diff --git a/src/qml/qml/qqmlabstracturlinterceptor.h b/src/qml/qml/qqmlabstracturlinterceptor.h index 665b37fb3a..af231f51b2 100644 --- a/src/qml/qml/qqmlabstracturlinterceptor.h +++ b/src/qml/qml/qqmlabstracturlinterceptor.h @@ -55,8 +55,8 @@ public: UrlString = 0x1000 }; - QQmlAbstractUrlInterceptor() {} - virtual ~QQmlAbstractUrlInterceptor() {} + QQmlAbstractUrlInterceptor() = default; + virtual ~QQmlAbstractUrlInterceptor() = default; virtual QUrl intercept(const QUrl &path, DataType type) = 0; }; diff --git a/src/qml/qml/qqmlapplicationengine_p.h b/src/qml/qml/qqmlapplicationengine_p.h index 4795170bed..6cf6828832 100644 --- a/src/qml/qml/qqmlapplicationengine_p.h +++ b/src/qml/qml/qqmlapplicationengine_p.h @@ -74,7 +74,6 @@ public: void loadTranslations(const QUrl &rootFile); void finishLoad(QQmlComponent *component); QList<QObject *> objects; - QObject *appObj; #if QT_CONFIG(translation) QList<QTranslator *> translators; diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 7f0442d034..b164517011 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -314,7 +314,7 @@ protected: break; default: if (const QV4::QQmlValueTypeWrapper *vtw = result.as<const QV4::QQmlValueTypeWrapper>()) { - if (vtw->d()->valueType->typeId == pd->propType()) { + if (vtw->d()->valueType->metaType.id() == pd->propType()) { return vtw->write(m_target.data(), pd->coreIndex()); } } diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp deleted file mode 100644 index d87bf433b8..0000000000 --- a/src/qml/qml/qqmldirparser.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "qqmldirparser_p.h" -#include "qqmlerror.h" - -#include <QtCore/QtDebug> - -QT_BEGIN_NAMESPACE - -static int parseInt(const QStringRef &str, bool *ok) -{ - int pos = 0; - int number = 0; - while (pos < str.length() && str.at(pos).isDigit()) { - if (pos != 0) - number *= 10; - number += str.at(pos).unicode() - '0'; - ++pos; - } - if (pos != str.length()) - *ok = false; - else - *ok = true; - return number; -} - -static bool parseVersion(const QString &str, int *major, int *minor) -{ - const int dotIndex = str.indexOf(QLatin1Char('.')); - if (dotIndex != -1 && str.indexOf(QLatin1Char('.'), dotIndex + 1) == -1) { - bool ok = false; - *major = parseInt(QStringRef(&str, 0, dotIndex), &ok); - if (ok) - *minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok); - return ok; - } - return false; -} - -QQmlDirParser::QQmlDirParser() : _designerSupported(false) -{ -} - -QQmlDirParser::~QQmlDirParser() -{ -} - -inline static void scanSpace(const QChar *&ch) { - while (ch->isSpace() && !ch->isNull() && *ch != QLatin1Char('\n')) - ++ch; -} - -inline static void scanToEnd(const QChar *&ch) { - while (*ch != QLatin1Char('\n') && !ch->isNull()) - ++ch; -} - -inline static void scanWord(const QChar *&ch) { - while (!ch->isSpace() && !ch->isNull()) - ++ch; -} - -/*! -\a url is used for generating errors. -*/ -bool QQmlDirParser::parse(const QString &source) -{ - _errors.clear(); - _plugins.clear(); - _components.clear(); - _scripts.clear(); - _designerSupported = false; - _className.clear(); - - quint16 lineNumber = 0; - bool firstLine = true; - - const QChar *ch = source.constData(); - while (!ch->isNull()) { - ++lineNumber; - - bool invalidLine = false; - const QChar *lineStart = ch; - - scanSpace(ch); - if (*ch == QLatin1Char('\n')) { - ++ch; - continue; - } - if (ch->isNull()) - break; - - QString sections[4]; - int sectionCount = 0; - - do { - if (*ch == QLatin1Char('#')) { - scanToEnd(ch); - break; - } - const QChar *start = ch; - scanWord(ch); - if (sectionCount < 4) { - sections[sectionCount++] = source.mid(start-source.constData(), ch-start); - } else { - reportError(lineNumber, start-lineStart, QLatin1String("unexpected token")); - scanToEnd(ch); - invalidLine = true; - break; - } - scanSpace(ch); - } while (*ch != QLatin1Char('\n') && !ch->isNull()); - - if (!ch->isNull()) - ++ch; - - if (invalidLine) { - reportError(lineNumber, 0, - QStringLiteral("invalid qmldir directive contains too many tokens")); - continue; - } else if (sectionCount == 0) { - continue; // no sections, no party. - - } else if (sections[0] == QLatin1String("module")) { - if (sectionCount != 2) { - reportError(lineNumber, 0, - QStringLiteral("module identifier directive requires one argument, but %1 were provided").arg(sectionCount - 1)); - continue; - } - if (!_typeNamespace.isEmpty()) { - reportError(lineNumber, 0, - QStringLiteral("only one module identifier directive may be defined in a qmldir file")); - continue; - } - if (!firstLine) { - reportError(lineNumber, 0, - QStringLiteral("module identifier directive must be the first directive in a qmldir file")); - continue; - } - - _typeNamespace = sections[1]; - - } else if (sections[0] == QLatin1String("plugin")) { - if (sectionCount < 2 || sectionCount > 3) { - reportError(lineNumber, 0, - QStringLiteral("plugin directive requires one or two arguments, but %1 were provided").arg(sectionCount - 1)); - - continue; - } - - const Plugin entry(sections[1], sections[2]); - - _plugins.append(entry); - - } else if (sections[0] == QLatin1String("classname")) { - if (sectionCount < 2) { - reportError(lineNumber, 0, - QStringLiteral("classname directive requires an argument, but %1 were provided").arg(sectionCount - 1)); - - continue; - } - - _className = sections[1]; - - } else if (sections[0] == QLatin1String("internal")) { - if (sectionCount != 3) { - reportError(lineNumber, 0, - QStringLiteral("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1)); - continue; - } - Component entry(sections[1], sections[2], -1, -1); - entry.internal = true; - _components.insertMulti(entry.typeName, entry); - } else if (sections[0] == QLatin1String("singleton")) { - if (sectionCount < 3 || sectionCount > 4) { - reportError(lineNumber, 0, - QStringLiteral("singleton types require 2 or 3 arguments, but %1 were provided").arg(sectionCount - 1)); - continue; - } else if (sectionCount == 3) { - // handle qmldir directory listing case where singleton is defined in the following pattern: - // singleton TestSingletonType TestSingletonType.qml - Component entry(sections[1], sections[2], -1, -1); - entry.singleton = true; - _components.insertMulti(entry.typeName, entry); - } else { - // handle qmldir module listing case where singleton is defined in the following pattern: - // singleton TestSingletonType 2.0 TestSingletonType20.qml - int major, minor; - if (parseVersion(sections[2], &major, &minor)) { - const QString &fileName = sections[3]; - Component entry(sections[1], fileName, major, minor); - entry.singleton = true; - _components.insertMulti(entry.typeName, entry); - } else { - reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2])); - } - } - } else if (sections[0] == QLatin1String("typeinfo")) { - if (sectionCount != 2) { - reportError(lineNumber, 0, - QStringLiteral("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1)); - continue; - } -#ifdef QT_CREATOR - TypeInfo typeInfo(sections[1]); - _typeInfos.append(typeInfo); -#endif - - } else if (sections[0] == QLatin1String("designersupported")) { - if (sectionCount != 1) - reportError(lineNumber, 0, QStringLiteral("designersupported does not expect any argument")); - else - _designerSupported = true; - } else if (sections[0] == QLatin1String("depends")) { - if (sectionCount != 3) { - reportError(lineNumber, 0, - QStringLiteral("depends requires 2 arguments, but %1 were provided").arg(sectionCount - 1)); - continue; - } - - int major, minor; - if (parseVersion(sections[2], &major, &minor)) { - Component entry(sections[1], QString(), major, minor); - entry.internal = true; - _dependencies.insert(entry.typeName, entry); - } else { - reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2])); - } - } else if (sectionCount == 2) { - // No version specified (should only be used for relative qmldir files) - const Component entry(sections[0], sections[1], -1, -1); - _components.insertMulti(entry.typeName, entry); - } else if (sectionCount == 3) { - int major, minor; - if (parseVersion(sections[1], &major, &minor)) { - const QString &fileName = sections[2]; - - if (fileName.endsWith(QLatin1String(".js")) || fileName.endsWith(QLatin1String(".mjs"))) { - // A 'js' extension indicates a namespaced script import - const Script entry(sections[0], fileName, major, minor); - _scripts.append(entry); - } else { - const Component entry(sections[0], fileName, major, minor); - _components.insertMulti(entry.typeName, entry); - } - } else { - reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[1])); - } - } else { - reportError(lineNumber, 0, - QStringLiteral("a component declaration requires two or three arguments, but %1 were provided").arg(sectionCount)); - } - - firstLine = false; - } - - return hasError(); -} - -void QQmlDirParser::reportError(quint16 line, quint16 column, const QString &description) -{ - QQmlJS::DiagnosticMessage error; - error.loc.startLine = line; - error.loc.startColumn = column; - error.message = description; - _errors.append(error); -} - -bool QQmlDirParser::hasError() const -{ - if (! _errors.isEmpty()) - return true; - - return false; -} - -void QQmlDirParser::setError(const QQmlError &e) -{ - _errors.clear(); - reportError(e.line(), e.column(), e.description()); -} - -QList<QQmlError> QQmlDirParser::errors(const QString &uri) const -{ - QUrl url(uri); - QList<QQmlError> errors; - const int numErrors = _errors.size(); - errors.reserve(numErrors); - for (int i = 0; i < numErrors; ++i) { - const QQmlJS::DiagnosticMessage &msg = _errors.at(i); - QQmlError e; - QString description = msg.message; - description.replace(QLatin1String("$$URI$$"), uri); - e.setDescription(description); - e.setUrl(url); - e.setLine(msg.loc.startLine); - e.setColumn(msg.loc.startColumn); - errors << e; - } - return errors; -} - -QString QQmlDirParser::typeNamespace() const -{ - return _typeNamespace; -} - -void QQmlDirParser::setTypeNamespace(const QString &s) -{ - _typeNamespace = s; -} - -QList<QQmlDirParser::Plugin> QQmlDirParser::plugins() const -{ - return _plugins; -} - -QHash<QString, QQmlDirParser::Component> QQmlDirParser::components() const -{ - return _components; -} - -QHash<QString, QQmlDirParser::Component> QQmlDirParser::dependencies() const -{ - return _dependencies; -} - -QList<QQmlDirParser::Script> QQmlDirParser::scripts() const -{ - return _scripts; -} - -#ifdef QT_CREATOR -QList<QQmlDirParser::TypeInfo> QQmlDirParser::typeInfos() const -{ - return _typeInfos; -} -#endif - -bool QQmlDirParser::designerSupported() const -{ - return _designerSupported; -} - -QString QQmlDirParser::className() const -{ - return _className; -} - -QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component) -{ - const QString output = QStringLiteral("{%1 %2.%3}"). - arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion); - return debug << qPrintable(output); -} - -QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script) -{ - const QString output = QStringLiteral("{%1 %2.%3}"). - arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion); - return debug << qPrintable(output); -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/qqmldirparser_p.h b/src/qml/qml/qqmldirparser_p.h deleted file mode 100644 index d7e29813d1..0000000000 --- a/src/qml/qml/qqmldirparser_p.h +++ /dev/null @@ -1,167 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 QQMLDIRPARSER_P_H -#define QQMLDIRPARSER_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 <QtCore/QUrl> -#include <QtCore/QHash> -#include <QtCore/QDebug> -#include <private/qqmljsengine_p.h> -#include <private/qv4global_p.h> - -QT_BEGIN_NAMESPACE - -class QQmlError; -class QQmlEngine; -class Q_QML_PRIVATE_EXPORT QQmlDirParser -{ -public: - QQmlDirParser(); - ~QQmlDirParser(); - - bool parse(const QString &source); - - bool hasError() const; - void setError(const QQmlError &); - QList<QQmlError> errors(const QString &uri) const; - - QString typeNamespace() const; - void setTypeNamespace(const QString &s); - - struct Plugin - { - Plugin() {} - - Plugin(const QString &name, const QString &path) - : name(name), path(path) {} - - QString name; - QString path; - }; - - struct Component - { - Component() {} - - Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion) - : typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion), - internal(false), singleton(false) {} - - QString typeName; - QString fileName; - int majorVersion = 0; - int minorVersion = 0; - bool internal = false; - bool singleton = false; - }; - - struct Script - { - Script() {} - - Script(const QString &nameSpace, const QString &fileName, int majorVersion, int minorVersion) - : nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion) {} - - QString nameSpace; - QString fileName; - int majorVersion = 0; - int minorVersion = 0; - }; - - QHash<QString,Component> components() const; - QHash<QString,Component> dependencies() const; - QList<Script> scripts() const; - QList<Plugin> plugins() const; - bool designerSupported() const; - -#ifdef QT_CREATOR - struct TypeInfo - { - TypeInfo() {} - TypeInfo(const QString &fileName) - : fileName(fileName) {} - - QString fileName; - }; - - QList<TypeInfo> typeInfos() const; -#endif - - QString className() const; - -private: - bool maybeAddComponent(const QString &typeName, const QString &fileName, const QString &version, QHash<QString,Component> &hash, int lineNumber = -1, bool multi = true); - void reportError(quint16 line, quint16 column, const QString &message); - -private: - QList<QQmlJS::DiagnosticMessage> _errors; - QString _typeNamespace; - QHash<QString,Component> _components; // multi hash - QHash<QString,Component> _dependencies; - QList<Script> _scripts; - QList<Plugin> _plugins; - bool _designerSupported; -#ifdef QT_CREATOR - QList<TypeInfo> _typeInfos; -#endif - QString _className; -}; - -typedef QHash<QString,QQmlDirParser::Component> QQmlDirComponents; -typedef QList<QQmlDirParser::Script> QQmlDirScripts; -typedef QList<QQmlDirParser::Plugin> QQmlDirPlugins; - -QDebug &operator<< (QDebug &, const QQmlDirParser::Component &); -QDebug &operator<< (QDebug &, const QQmlDirParser::Script &); - -QT_END_NAMESPACE - -#endif // QQMLDIRPARSER_P_H diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 5841a480fc..0a26ed89cc 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -661,6 +661,10 @@ The following functions are also on the Qt object. /*! \qmlmethod object Qt::include(string url, jsobject callback) +\deprecated + +This method should not be used. Use ECMAScript modules instead and the native +JavaScript \c import and \c export statements instead. Includes another JavaScript file. This method can only be used from within JavaScript files, and not regular QML files. diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 8a9581fb35..d05c945ae4 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -64,7 +64,6 @@ #include "qqmlproperty_p.h" #include "qqmlpropertycache_p.h" #include "qqmlmetatype_p.h" -#include "qqmldirparser_p.h" #include <private/qintrusivelist_p.h> #include <private/qrecyclepool_p.h> #include <private/qfieldlist_p.h> @@ -80,6 +79,7 @@ #include <private/qv8engine_p.h> #include <private/qjsengine_p.h> +#include <private/qqmldirparser_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlerror.cpp b/src/qml/qml/qqmlerror.cpp deleted file mode 100644 index 61e9a3f37e..0000000000 --- a/src/qml/qml/qqmlerror.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "qqmlerror.h" -#include "qqmlglobal_p.h" - -#include <QtCore/qdebug.h> -#include <QtCore/qfile.h> -#include <QtCore/qstringlist.h> -#include <QtCore/qvector.h> -#include <QtCore/qpointer.h> - -#include <private/qv4errorobject_p.h> - -QT_BEGIN_NAMESPACE - -/*! - \class QQmlError - \since 5.0 - \inmodule QtQml - \brief The QQmlError class encapsulates a QML error. - - QQmlError includes a textual description of the error, as well - as location information (the file, line, and column). The toString() - method creates a single-line, human-readable string containing all of - this information, for example: - \code - file:///home/user/test.qml:7:8: Invalid property assignment: double expected - \endcode - - You can use qDebug(), qInfo(), or qWarning() to output errors to the console. - This method will attempt to open the file indicated by the error - and include additional contextual information. - \code - file:///home/user/test.qml:7:8: Invalid property assignment: double expected - y: "hello" - ^ - \endcode - - \sa QQuickView::errors(), QQmlComponent::errors() -*/ -class QQmlErrorPrivate -{ -public: - QQmlErrorPrivate(); - - QUrl url; - QString description; - quint16 line; - quint16 column; - QtMsgType messageType; - QPointer<QObject> object; -}; - -QQmlErrorPrivate::QQmlErrorPrivate() -: line(0), column(0), messageType(QtMsgType::QtWarningMsg), object() -{ -} - -/*! - Creates an empty error object. -*/ -QQmlError::QQmlError() -: d(nullptr) -{ -} - -/*! - Creates a copy of \a other. -*/ -QQmlError::QQmlError(const QQmlError &other) -: d(nullptr) -{ - *this = other; -} - -/*! - Assigns \a other to this error object. -*/ -QQmlError &QQmlError::operator=(const QQmlError &other) -{ - if (!other.d) { - delete d; - d = nullptr; - } else { - if (!d) - d = new QQmlErrorPrivate; - d->url = other.d->url; - d->description = other.d->description; - d->line = other.d->line; - d->column = other.d->column; - d->object = other.d->object; - d->messageType = other.d->messageType; - } - return *this; -} - -/*! - \internal -*/ -QQmlError::~QQmlError() -{ - delete d; d = nullptr; -} - -/*! - Returns true if this error is valid, otherwise false. -*/ -bool QQmlError::isValid() const -{ - return d != nullptr; -} - -/*! - Returns the url for the file that caused this error. -*/ -QUrl QQmlError::url() const -{ - if (d) - return d->url; - return QUrl(); -} - -/*! - Sets the \a url for the file that caused this error. -*/ -void QQmlError::setUrl(const QUrl &url) -{ - if (!d) - d = new QQmlErrorPrivate; - d->url = url; -} - -/*! - Returns the error description. -*/ -QString QQmlError::description() const -{ - if (d) - return d->description; - return QString(); -} - -/*! - Sets the error \a description. -*/ -void QQmlError::setDescription(const QString &description) -{ - if (!d) - d = new QQmlErrorPrivate; - d->description = description; -} - -/*! - Returns the error line number. -*/ -int QQmlError::line() const -{ - if (d) - return qmlSourceCoordinate(d->line); - return -1; -} - -/*! - Sets the error \a line number. -*/ -void QQmlError::setLine(int line) -{ - if (!d) - d = new QQmlErrorPrivate; - d->line = qmlSourceCoordinate(line); -} - -/*! - Returns the error column number. -*/ -int QQmlError::column() const -{ - if (d) - return qmlSourceCoordinate(d->column); - return -1; -} - -/*! - Sets the error \a column number. -*/ -void QQmlError::setColumn(int column) -{ - if (!d) - d = new QQmlErrorPrivate; - d->column = qmlSourceCoordinate(column); -} - -/*! - Returns the nearest object where this error occurred. - Exceptions in bound property expressions set this to the object - to which the property belongs. It will be 0 for all - other exceptions. - */ -QObject *QQmlError::object() const -{ - if (d) - return d->object; - return nullptr; -} - -/*! - Sets the nearest \a object where this error occurred. - */ -void QQmlError::setObject(QObject *object) -{ - if (!d) - d = new QQmlErrorPrivate; - d->object = object; -} - -/*! - \since 5.9 - - Returns the message type. - */ -QtMsgType QQmlError::messageType() const -{ - if (d) - return d->messageType; - return QtMsgType::QtWarningMsg; -} - -/*! - \since 5.9 - - Sets the \a messageType for this message. The message type determines which - QDebug handlers are responsible for receiving the message. - */ -void QQmlError::setMessageType(QtMsgType messageType) -{ - if (!d) - d = new QQmlErrorPrivate; - d->messageType = messageType; -} - -/*! - Returns the error as a human readable string. -*/ -QString QQmlError::toString() const -{ - QString rv; - - QUrl u(url()); - int l(line()); - - if (u.isEmpty() || (u.isLocalFile() && u.path().isEmpty())) - rv += QLatin1String("<Unknown File>"); - else - rv += u.toString(); - - if (l != -1) { - rv += QLatin1Char(':') + QString::number(l); - - int c(column()); - if (c != -1) - rv += QLatin1Char(':') + QString::number(c); - } - - rv += QLatin1String(": ") + description(); - - return rv; -} - -/*! - \relates QQmlError - \fn QDebug operator<<(QDebug debug, const QQmlError &error) - - Outputs a human readable version of \a error to \a debug. -*/ - -QDebug operator<<(QDebug debug, const QQmlError &error) -{ - debug << qPrintable(error.toString()); - - QUrl url = error.url(); - - if (error.line() > 0 && url.scheme() == QLatin1String("file")) { - QString file = url.toLocalFile(); - QFile f(file); - if (f.open(QIODevice::ReadOnly)) { - QByteArray data = f.readAll(); - QTextStream stream(data, QIODevice::ReadOnly); -#if QT_CONFIG(textcodec) - stream.setCodec("UTF-8"); -#endif - const QString code = stream.readAll(); - const auto lines = code.splitRef(QLatin1Char('\n')); - - if (lines.count() >= error.line()) { - const QStringRef &line = lines.at(error.line() - 1); - debug << "\n " << line.toLocal8Bit().constData(); - - if(error.column() > 0) { - int column = qMax(0, error.column() - 1); - column = qMin(column, line.length()); - - QByteArray ind; - ind.reserve(column); - for (int i = 0; i < column; ++i) { - const QChar ch = line.at(i); - if (ch.isSpace()) - ind.append(ch.unicode()); - else - ind.append(' '); - } - ind.append('^'); - debug << "\n " << ind.constData(); - } - } - } - } - return debug; -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlerror.h b/src/qml/qml/qqmlerror.h deleted file mode 100644 index ef529e3828..0000000000 --- a/src/qml/qml/qqmlerror.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 QQMLERROR_H -#define QQMLERROR_H - -#include <QtQml/qtqmlglobal.h> - -#include <QtCore/qurl.h> -#include <QtCore/qstring.h> - -QT_BEGIN_NAMESPACE - -// ### Qt 6: should this be called QQmlMessage, since it can have a message type? -class QDebug; -class QQmlErrorPrivate; -class Q_QML_EXPORT QQmlError -{ -public: - QQmlError(); - QQmlError(const QQmlError &); - QQmlError &operator=(const QQmlError &); - ~QQmlError(); - - bool isValid() const; - - QUrl url() const; - void setUrl(const QUrl &); - QString description() const; - void setDescription(const QString &); - int line() const; - void setLine(int); - int column() const; - void setColumn(int); - QObject *object() const; - void setObject(QObject *); - QtMsgType messageType() const; - void setMessageType(QtMsgType messageType); - - QString toString() const; -private: - QQmlErrorPrivate *d; -}; - -QDebug Q_QML_EXPORT operator<<(QDebug debug, const QQmlError &error); - -Q_DECLARE_TYPEINFO(QQmlError, Q_MOVABLE_TYPE); - -QT_END_NAMESPACE - -#endif // QQMLERROR_H diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index 0c1ffbf3a0..ac2629979f 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -46,6 +46,7 @@ #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/qqmlextensioninterface.h b/src/qml/qml/qqmlextensioninterface.h index c2d20ef0a3..d2eb79c5c9 100644 --- a/src/qml/qml/qqmlextensioninterface.h +++ b/src/qml/qml/qqmlextensioninterface.h @@ -51,14 +51,14 @@ class QQmlEngine; class Q_QML_EXPORT QQmlTypesExtensionInterface { public: - virtual ~QQmlTypesExtensionInterface() {} + virtual ~QQmlTypesExtensionInterface() = default; virtual void registerTypes(const char *uri) = 0; }; class Q_QML_EXPORT QQmlExtensionInterface : public QQmlTypesExtensionInterface { public: - ~QQmlExtensionInterface() override {} + ~QQmlExtensionInterface() override = default; virtual void initializeEngine(QQmlEngine *engine, const char *uri) = 0; }; diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp index 99031e1e74..465a342129 100644 --- a/src/qml/qml/qqmlfile.cpp +++ b/src/qml/qml/qqmlfile.cpp @@ -64,6 +64,7 @@ static char file_string[] = "file"; #if defined(Q_OS_ANDROID) static char assets_string[] = "assets"; +static char content_string[] = "content"; #endif class QQmlFilePrivate; @@ -452,6 +453,8 @@ bool QQmlFile::isSynchronous(const QUrl &url) #if defined(Q_OS_ANDROID) } else if (scheme.length() == 6 && 0 == scheme.compare(QLatin1String(assets_string), Qt::CaseInsensitive)) { return true; + } else if (scheme.length() == 7 && 0 == scheme.compare(QLatin1String(content_string), Qt::CaseInsensitive)) { + return true; #endif } else { @@ -492,7 +495,10 @@ bool QQmlFile::isSynchronous(const QString &url) return url.length() >= 8 /* assets:/ */ && url.startsWith(QLatin1String(assets_string), Qt::CaseInsensitive) && url[6] == QLatin1Char(':') && url[7] == QLatin1Char('/'); - + } else if (f == QLatin1Char('c') || f == QLatin1Char('C')) { + return url.length() >= 9 /* content:/ */ && + url.startsWith(QLatin1String(content_string), Qt::CaseInsensitive) && + url[7] == QLatin1Char(':') && url[8] == QLatin1Char('/'); } #endif @@ -556,7 +562,10 @@ bool QQmlFile::isLocalFile(const QString &url) return url.length() >= 8 /* assets:/ */ && url.startsWith(QLatin1String(assets_string), Qt::CaseInsensitive) && url[6] == QLatin1Char(':') && url[7] == QLatin1Char('/'); - + } else if (f == QLatin1Char('c') || f == QLatin1Char('C')) { + return url.length() >= 9 /* content:/ */ && + url.startsWith(QLatin1String(content_string), Qt::CaseInsensitive) && + url[7] == QLatin1Char(':') && url[8] == QLatin1Char('/'); } #endif @@ -580,6 +589,8 @@ QString QQmlFile::urlToLocalFileOrQrc(const QUrl& url) if (url.authority().isEmpty()) return url.toString(); return QString(); + } else if (url.scheme().compare(QLatin1String("content"), Qt::CaseInsensitive) == 0) { + return url.toString(); } #endif @@ -618,6 +629,8 @@ QString QQmlFile::urlToLocalFileOrQrc(const QString& url) #if defined(Q_OS_ANDROID) else if (url.startsWith(QLatin1String("assets:"), Qt::CaseInsensitive)) { return url; + } else if (url.startsWith(QLatin1String("content:"), Qt::CaseInsensitive)) { + return url; } #endif diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h index 302fdd56c4..818537560c 100644 --- a/src/qml/qml/qqmlglobal_p.h +++ b/src/qml/qml/qqmlglobal_p.h @@ -174,16 +174,6 @@ T qmlobject_cast(QObject *object) return 0; } -inline quint16 qmlSourceCoordinate(int n) -{ - return (n > 0 && n <= static_cast<int>(USHRT_MAX)) ? static_cast<quint16>(n) : 0; -} - -inline int qmlSourceCoordinate(quint16 n) -{ - return (n == 0) ? -1 : static_cast<int>(n); -} - #define IS_SIGNAL_CONNECTED(Sender, SenderType, Name, Arguments) \ do { \ QObject *sender = (Sender); \ diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index f801e9aeba..a8ec5d18f8 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -1102,13 +1102,6 @@ QString QQmlType::noCreationReason() const return d->extraData.cd->noCreationReason; } -int QQmlType::createSize() const -{ - if (!d || d->regType != CppType) - return 0; - return d->extraData.cd->allocationSize; -} - bool QQmlType::isCreatable() const { return d && d->regType == CppType && d->extraData.cd->newFunc; @@ -2172,11 +2165,14 @@ int QQmlMetaType::attachedPropertiesFuncId(QQmlEnginePrivate *engine, const QMet QMutexLocker lock(metaTypeDataLock()); QQmlMetaTypeData *data = metaTypeData(); - QQmlType type(data->metaObjectToType.value(mo)); - if (type.attachedPropertiesFunction(engine)) - return type.attachedPropertiesId(engine); - else - return -1; + for (auto it = data->metaObjectToType.constFind(mo), end = data->metaObjectToType.constEnd(); + it != end && it.key() == mo; ++it) { + const QQmlType type(it.value()); + if (type.attachedPropertiesFunction(engine)) + return type.attachedPropertiesId(engine); + } + + return -1; } QQmlAttachedPropertiesFunc QQmlMetaType::attachedPropertiesFuncById(QQmlEnginePrivate *engine, int id) diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 8256212207..3ad2de7bb3 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -196,8 +196,6 @@ public: typedef void (*CreateFunc)(void *); CreateFunc createFunction() const; - int createSize() const; - QQmlCustomParser *customParser() const; bool isCreatable() const; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 5af658194f..c36b3ed386 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -379,6 +379,28 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const } } + auto assertOrNull = [&](bool ok) + { + Q_ASSERT(ok || binding->type == QV4::CompiledData::Binding::Type_Null); + Q_UNUSED(ok); + }; + + auto assertType = [&](QV4::CompiledData::Binding::ValueType type) + { + Q_ASSERT(binding->type == type || binding->type == QV4::CompiledData::Binding::Type_Null); + Q_UNUSED(type); + }; + + if (property->isQObject()) { + if (binding->type == QV4::CompiledData::Binding::Type_Null) { + QObject *value = nullptr; + const bool ok = property->writeProperty(_qobject, &value, propertyWriteFlags); + Q_ASSERT(ok); + Q_UNUSED(ok); + return; + } + } + switch (propertyType) { case QMetaType::QVariant: { if (binding->type == QV4::CompiledData::Binding::Type_Number) { @@ -406,6 +428,13 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const QVariant value(binding->valueAsBoolean()); property->writeProperty(_qobject, &value, propertyWriteFlags); } + } else if (binding->type == QV4::CompiledData::Binding::Type_Null) { + if (property->isVarProperty()) { + _vmeMetaObject->setVMEProperty(property->coreIndex(), QV4::Value::nullValue()); + } else { + QVariant nullValue = QVariant::fromValue(nullptr); + property->writeProperty(_qobject, &nullValue, propertyWriteFlags); + } } else { QString stringValue = binding->valueAsString(compilationUnit.data()); if (property->isVarProperty()) { @@ -419,25 +448,25 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const } break; case QVariant::String: { - Q_ASSERT(binding->evaluatesToString()); + assertOrNull(binding->evaluatesToString()); QString value = binding->valueAsString(compilationUnit.data()); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::StringList: { - Q_ASSERT(binding->evaluatesToString()); + assertOrNull(binding->evaluatesToString()); QStringList value(binding->valueAsString(compilationUnit.data())); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::ByteArray: { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String); + assertType(QV4::CompiledData::Binding::Type_String); QByteArray value(binding->valueAsString(compilationUnit.data()).toUtf8()); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Url: { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String); + assertType(QV4::CompiledData::Binding::Type_String); QString string = binding->valueAsString(compilationUnit.data()); // Encoded dir-separators defeat QUrl processing - decode them first string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive); @@ -449,7 +478,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const } break; case QVariant::UInt: { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number); + assertType(QV4::CompiledData::Binding::Type_Number); double d = binding->valueAsNumber(compilationUnit->constants); uint value = uint(d); property->writeProperty(_qobject, &value, propertyWriteFlags); @@ -457,7 +486,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const } break; case QVariant::Int: { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number); + assertType(QV4::CompiledData::Binding::Type_Number); double d = binding->valueAsNumber(compilationUnit->constants); int value = int(d); property->writeProperty(_qobject, &value, propertyWriteFlags); @@ -465,13 +494,13 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const } break; case QMetaType::Float: { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number); + assertType(QV4::CompiledData::Binding::Type_Number); float value = float(binding->valueAsNumber(compilationUnit->constants)); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Double: { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number); + assertType(QV4::CompiledData::Binding::Type_Number); double value = binding->valueAsNumber(compilationUnit->constants); property->writeProperty(_qobject, &value, propertyWriteFlags); } @@ -479,7 +508,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const case QVariant::Color: { bool ok = false; uint colorValue = QQmlStringConverters::rgbaFromString(binding->valueAsString(compilationUnit.data()), &ok); - Q_ASSERT(ok); + assertOrNull(ok); struct { void *data[4]; } buffer; if (QQml_valueTypeProvider()->storeValueType(property->propType(), &colorValue, &buffer, sizeof(buffer))) { property->writeProperty(_qobject, &buffer, propertyWriteFlags); @@ -490,14 +519,14 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const case QVariant::Date: { bool ok = false; QDate value = QQmlStringConverters::dateFromString(binding->valueAsString(compilationUnit.data()), &ok); - Q_ASSERT(ok); + assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Time: { bool ok = false; QTime value = QQmlStringConverters::timeFromString(binding->valueAsString(compilationUnit.data()), &ok); - Q_ASSERT(ok); + assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; @@ -510,7 +539,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const const int msecsSinceStartOfDay = value.time().msecsSinceStartOfDay(); value = QDateTime(QDate::fromJulianDay(date), QTime::fromMSecsSinceStartOfDay(msecsSinceStartOfDay)); } - Q_ASSERT(ok); + assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; @@ -518,47 +547,47 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const case QVariant::Point: { bool ok = false; QPoint value = QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok).toPoint(); - Q_ASSERT(ok); + assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::PointF: { bool ok = false; QPointF value = QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok); - Q_ASSERT(ok); + assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Size: { bool ok = false; QSize value = QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok).toSize(); - Q_ASSERT(ok); + assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::SizeF: { bool ok = false; QSizeF value = QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok); - Q_ASSERT(ok); + assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Rect: { bool ok = false; QRect value = QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok).toRect(); - Q_ASSERT(ok); + assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::RectF: { bool ok = false; QRectF value = QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok); - Q_ASSERT(ok); + assertOrNull(ok); property->writeProperty(_qobject, &value, propertyWriteFlags); } break; case QVariant::Bool: { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean); + assertType(QV4::CompiledData::Binding::Type_Boolean); bool value = binding->valueAsBoolean(); property->writeProperty(_qobject, &value, propertyWriteFlags); } @@ -569,7 +598,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const float yp; } vec; bool ok = QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec)); - Q_ASSERT(ok); + assertOrNull(ok); Q_UNUSED(ok); property->writeProperty(_qobject, &vec, propertyWriteFlags); } @@ -581,7 +610,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const float zy; } vec; bool ok = QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec)); - Q_ASSERT(ok); + assertOrNull(ok); Q_UNUSED(ok); property->writeProperty(_qobject, &vec, propertyWriteFlags); } @@ -594,7 +623,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const float wp; } vec; bool ok = QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec)); - Q_ASSERT(ok); + assertOrNull(ok); Q_UNUSED(ok); property->writeProperty(_qobject, &vec, propertyWriteFlags); } @@ -607,37 +636,37 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const float zp; } vec; bool ok = QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec)); - Q_ASSERT(ok); + assertOrNull(ok); Q_UNUSED(ok); property->writeProperty(_qobject, &vec, propertyWriteFlags); } break; case QVariant::RegExp: - Q_ASSERT(!"not possible"); + assertOrNull(!"not possible"); break; default: { // generate single literal value assignment to a list property if required if (property->propType() == qMetaTypeId<QList<qreal> >()) { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number); + assertType(QV4::CompiledData::Binding::Type_Number); QList<qreal> value; value.append(binding->valueAsNumber(compilationUnit->constants)); property->writeProperty(_qobject, &value, propertyWriteFlags); break; } else if (property->propType() == qMetaTypeId<QList<int> >()) { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Number); + assertType(QV4::CompiledData::Binding::Type_Number); double n = binding->valueAsNumber(compilationUnit->constants); QList<int> value; value.append(int(n)); property->writeProperty(_qobject, &value, propertyWriteFlags); break; } else if (property->propType() == qMetaTypeId<QList<bool> >()) { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Boolean); + assertType(QV4::CompiledData::Binding::Type_Boolean); QList<bool> value; value.append(binding->valueAsBoolean()); property->writeProperty(_qobject, &value, propertyWriteFlags); break; } else if (property->propType() == qMetaTypeId<QList<QUrl> >()) { - Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_String); + assertType(QV4::CompiledData::Binding::Type_String); QString urlString = binding->valueAsString(compilationUnit.data()); QUrl u = urlString.isEmpty() ? QUrl() : compilationUnit->finalUrl().resolved(QUrl(urlString)); @@ -646,7 +675,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const property->writeProperty(_qobject, &value, propertyWriteFlags); break; } else if (property->propType() == qMetaTypeId<QList<QString> >()) { - Q_ASSERT(binding->evaluatesToString()); + assertOrNull(binding->evaluatesToString()); QList<QString> value; value.append(binding->valueAsString(compilationUnit.data())); property->writeProperty(_qobject, &value, propertyWriteFlags); @@ -661,6 +690,8 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const value = QJSValue(int(n)); } else value = QJSValue(n); + } else if (binding->type == QV4::CompiledData::Binding::Type_Null) { + value = QJSValue::NullValue; } else { value = QJSValue(binding->valueAsString(compilationUnit.data())); } diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 20d5c76029..73bfd7bbaa 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -898,6 +898,17 @@ struct StaticQtMetaObject : public QObject { return &staticQtMetaObject; } }; +static bool isNamedEnumeratorInScope(const QMetaObject *resolvedMetaObject, const QByteArray &scope, + const QByteArray &name) +{ + for (int i = resolvedMetaObject->enumeratorCount() - 1; i >= 0; --i) { + QMetaEnum m = resolvedMetaObject->enumerator(i); + if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) + return true; + } + return false; +} + static bool isNamedEnumerator(const QMetaObject *metaObj, const QByteArray &scopedName) { QByteArray scope; @@ -909,52 +920,21 @@ static bool isNamedEnumerator(const QMetaObject *metaObj, const QByteArray &scop } else { name = scopedName; } - const QMetaObject *meta; - if (scope == "Qt") - meta = StaticQtMetaObject::get(); - else - meta = metaObj; - for (int i = meta->enumeratorCount() - 1; i >= 0; --i) { - QMetaEnum m = meta->enumerator(i); - if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope))) - return true; - } - return false; -} - -static bool passTypeAsInt(int type) -{ - // We should not encounter the unknown type here. - // In order to check that we need extra information. - Q_ASSERT(type != QMetaType::UnknownType); - const QMetaType::TypeFlags flags = QMetaType::typeFlags(type); + if (scope == "Qt") + return isNamedEnumeratorInScope(StaticQtMetaObject::get(), scope, name); - // Cast enumerations to int. - if (flags & QMetaType::IsEnumeration) + if (isNamedEnumeratorInScope(metaObj, scope, name)) return true; - // Qt builtins can be handled as they are. - if (type < int(QMetaType::User)) - return false; - - // Pointers to QObjects and QGadgets, and QGadgets themselves can be handled as they are. - if (flags & (QMetaType::PointerToQObject | QMetaType::PointerToGadget | QMetaType::IsGadget)) - return false; - - // If it wasn't declared as metatype, better don't touch it. - if (!(flags & QMetaType::WasDeclaredAsMetaType)) - return false; - - // If it needs construction or destruction (that is, it is a structured type), - // pass as original type. - if (flags & (QMetaType::NeedsConstruction | QMetaType::NeedsDestruction)) - return false; + if (metaObj->d.relatedMetaObjects && !scope.isEmpty()) { + for (auto related = metaObj->d.relatedMetaObjects; *related; ++related) { + if (isNamedEnumeratorInScope(*related, scope, name)) + return true; + } + } - // A single value that's not a pointer to a QObject or QGadget, not a builtin type, was declared - // as meta type, but we don't know it as an enumeration (although it probably is one). - // Pass as int if it fits into an int. - return QMetaType::sizeOf(type) <= int(sizeof(int)); + return false; } QQmlPropertyCacheMethodArguments *QQmlPropertyCache::createArgumentsObject(int argc, const QList<QByteArray> &names) @@ -1658,14 +1638,18 @@ int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *u propTypeName = m.typeName(); } - if (type == QMetaType::UnknownType) { + if (QMetaType::sizeOf(type) <= int(sizeof(int))) { + if (QMetaType::typeFlags(type) & QMetaType::IsEnumeration) + return QMetaType::Int; + if (isNamedEnumerator(metaObject(), propTypeName)) - type = QVariant::Int; - else if (unknownTypeError) - *unknownTypeError = propTypeName; - } else if (passTypeAsInt(type)) { - type = QVariant::Int; - } + return QMetaType::Int; + + if (type == QMetaType::UnknownType) { + if (unknownTypeError) + *unknownTypeError = propTypeName; + } + } // else we know that it's a known type, as sizeOf(UnknownType) == 0 return type; } @@ -1704,18 +1688,23 @@ int *QQmlMetaObject::methodParameterTypes(int index, ArgTypeStorage *argStorage, for (int ii = 0; ii < argc; ++ii) { int type = m.parameterType(ii); - if (type == QMetaType::UnknownType) { + + if (QMetaType::sizeOf(type) > int(sizeof(int))) { + // Cannot be passed as int + // We know that it's a known type, as sizeOf(UnknownType) == 0 + } else if (QMetaType::typeFlags(type) & QMetaType::IsEnumeration) { + type = QMetaType::Int; + } else { if (argTypeNames.isEmpty()) argTypeNames = m.parameterTypes(); if (isNamedEnumerator(metaObject, argTypeNames.at(ii))) { - type = QVariant::Int; - } else { + type = QMetaType::Int; + } else if (type == QMetaType::UnknownType){ if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); return nullptr; } - } else if (passTypeAsInt(type)) { - type = QVariant::Int; + } args->arguments[ii + 1] = type; } @@ -1741,18 +1730,21 @@ int *QQmlMetaObject::methodParameterTypes(const QMetaMethod &m, ArgTypeStorage * for (int ii = 0; ii < argc; ++ii) { int type = m.parameterType(ii); - if (type == QMetaType::UnknownType) { + if (QMetaType::sizeOf(type) > int(sizeof(int))) { + // Cannot be passed as int + // We know that it's a known type, as sizeOf(UnknownType) == 0 + } else if (QMetaType::typeFlags(type) & QMetaType::IsEnumeration) { + type = QMetaType::Int; + } else { if (argTypeNames.isEmpty()) argTypeNames = m.parameterTypes(); if (isNamedEnumerator(_m.asT2(), argTypeNames.at(ii))) { - type = QVariant::Int; - } else { + type = QMetaType::Int; + } else if (type == QMetaType::UnknownType) { if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); return nullptr; } - } else if (passTypeAsInt(type)) { - type = QVariant::Int; } argStorage->operator[](ii + 1) = type; } diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index df6a8f1500..457558fb56 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1821,6 +1821,11 @@ QString QQmlTypeLoader::absoluteFilePath(const QString &path) // assets resource url QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(path)); return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString(); + } else if (path.count() > 8 && path.at(7) == QLatin1Char(':') && path.at(8) == QLatin1Char('/') && + path.startsWith(QLatin1String("content"), Qt::CaseInsensitive)) { + // content url + QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(path)); + return fileInfo.isFile() ? fileInfo.absoluteFilePath() : QString(); } #endif @@ -1878,6 +1883,11 @@ bool QQmlTypeLoader::fileExists(const QString &path, const QString &file) // assets resource url QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(path + file)); return fileInfo.isFile(); + } else if (path.count() > 8 && path.at(7) == QLatin1Char(':') && path.at(8) == QLatin1Char('/') && + path.startsWith(QLatin1String("content"), Qt::CaseInsensitive)) { + // content url + QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(path + file)); + return fileInfo.isFile(); } #endif @@ -1891,8 +1901,6 @@ bool QQmlTypeLoader::fileExists(const QString &path, const QString &file) if (!fileSet) return false; - QString absoluteFilePath; - bool *value = fileSet->object(file); if (value) { return *value; @@ -1915,7 +1923,7 @@ bool QQmlTypeLoader::directoryExists(const QString &path) bool isResource = path.at(0) == QLatin1Char(':'); #if defined(Q_OS_ANDROID) - isResource = isResource || path.startsWith(QLatin1String("assets:/")); + isResource = isResource || path.startsWith(QLatin1String("assets:/")) || path.startsWith(QLatin1String("content:/")); #endif if (isResource) { diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index cb6a467c6c..6fd0f0d37c 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -198,7 +198,6 @@ void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject) : gadgetPtr(QMetaType::create(typeId)) - , typeId(typeId) , metaType(typeId) { QObjectPrivate *op = QObjectPrivate::get(this); @@ -237,12 +236,12 @@ void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyData::WriteFlags fl QVariant QQmlValueType::value() { Q_ASSERT(gadgetPtr); - return QVariant(typeId, gadgetPtr); + return QVariant(metaType.id(), gadgetPtr); } void QQmlValueType::setValue(const QVariant &value) { - Q_ASSERT(typeId == value.userType()); + Q_ASSERT(metaType.id() == value.userType()); metaType.destruct(gadgetPtr); metaType.construct(gadgetPtr, value.constData()); } diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h index 4ea71e8955..89f1b71d61 100644 --- a/src/qml/qml/qqmlvaluetype_p.h +++ b/src/qml/qml/qqmlvaluetype_p.h @@ -84,7 +84,6 @@ private: void *gadgetPtr; public: - int typeId; QMetaType metaType; }; diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index b22d1530e2..7df5757b95 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -107,7 +107,7 @@ void Heap::QQmlValueTypeWrapper::destroy() void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const { - Q_ASSERT(valueType->typeId == value.userType()); + Q_ASSERT(valueType->metaType.id() == value.userType()); if (gadgetPtr) valueType->metaType.destruct(gadgetPtr); if (!gadgetPtr) @@ -118,7 +118,7 @@ void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const QVariant Heap::QQmlValueTypeWrapper::toVariant() const { Q_ASSERT(gadgetPtr); - return QVariant(valueType->typeId, gadgetPtr); + return QVariant(valueType->metaType.id(), gadgetPtr); } @@ -223,7 +223,7 @@ bool QQmlValueTypeWrapper::toGadget(void *data) const if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>()) if (!ref->readReferenceValue()) return false; - const int typeId = d()->valueType->typeId; + const int typeId = d()->valueType->metaType.id(); QMetaType::destruct(typeId, data); QMetaType::construct(typeId, data, d()->gadgetPtr); return true; @@ -307,7 +307,7 @@ bool QQmlValueTypeWrapper::isEqual(const QVariant& value) const int QQmlValueTypeWrapper::typeId() const { - return d()->valueType->typeId; + return d()->valueType->metaType.id(); } bool QQmlValueTypeWrapper::write(QObject *target, int propertyIndex) const @@ -354,10 +354,10 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(const FunctionObject *b, con // Prepare a buffer to pass to QMetaType::convert() QString convertResult; convertResult.~QString(); - if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->typeId, &convertResult, QMetaType::QString)) { + if (QMetaType::convert(w->d()->gadgetPtr, w->d()->valueType->metaType.id(), &convertResult, QMetaType::QString)) { result = convertResult; } else { - result += QString::fromUtf8(QMetaType::typeName(w->d()->valueType->typeId)) + result += QString::fromUtf8(QMetaType::typeName(w->d()->valueType->metaType.id())) + QLatin1Char('('); const QMetaObject *mo = w->d()->propertyCache()->metaObject(); const int propCount = mo->propertyCount(); diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index f713efb289..64dc581a56 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -1527,6 +1527,27 @@ static QString jsStack(QV4::ExecutionEngine *engine) { return stack; } +static QString serializeArray(Object *array, ExecutionEngine *v4) { + Scope scope(v4); + ScopedValue val(scope); + QString result; + + result += QLatin1Char('['); + const uint length = array->getLength(); + for (uint i = 0; i < length; ++i) { + if (i != 0) + result += QLatin1Char(','); + val = array->get(i); + if (val->isManaged() && val->managed()->isArrayLike()) + result += serializeArray(val->objectValue(), v4); + else + result += val->toQStringNoThrow(); + } + result += QLatin1Char(']'); + + return result; +}; + static ReturnedValue writeToConsole(const FunctionObject *b, const Value *, const Value *argv, int argc, ConsoleLogTypes logType, bool printStack = false) { @@ -1554,7 +1575,7 @@ static ReturnedValue writeToConsole(const FunctionObject *b, const Value *, cons result.append(QLatin1Char(' ')); if (argv[i].isManaged() && argv[i].managed()->isArrayLike()) - result += QLatin1Char('[') + argv[i].toQStringNoThrow() + QLatin1Char(']'); + result.append(serializeArray(argv[i].objectValue(), v4)); else result.append(argv[i].toQStringNoThrow()); } |