Merge remote-tracking branch 'origin/dev' into wip/qt6

Change-Id: I4476733af61fcf3a2af1d121a4585c3fae1c240e
This commit is contained in:
Simon Hausmann 2019-07-12 20:36:14 +02:00
commit 880a143eb5
208 changed files with 9220 additions and 3568 deletions

View File

@ -58,7 +58,7 @@ Item {
property alias cellColor: rectangle.color
//![4]
//![5]
signal clicked(color cellColor)
signal clicked(cellColor: color)
//![5]
width: 40; height: 25

View File

@ -5,9 +5,9 @@ SUBDIRS += \
builtins \
qtqml \
models \
labsmodels \
folderlistmodel
labsmodels
qtConfig(qml-itemmodel): SUBDIRS += folderlistmodel
qtConfig(qml-worker-script): SUBDIRS += workerscript
qtHaveModule(sql): SUBDIRS += localstorage
qtConfig(settings): SUBDIRS += settings

View File

@ -37,6 +37,7 @@
**
****************************************************************************/
#include <private/qv4scopedvalue_p.h>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
#include <QtQml/qjsvalue.h>

View File

@ -61,6 +61,7 @@
#include <QtQml/qqml.h>
#include <private/qv4util_p.h>
#include <private/qv4global_p.h>
#include <private/qv4staticvalue_p.h>
#include "qtquickparticlesglobal_p.h"
QT_BEGIN_NAMESPACE

View File

@ -40,6 +40,8 @@
#include "qqmlpreviewfileloader.h"
#include "qqmlpreviewservice.h"
#include <QtQml/qqmlfile.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qstandardpaths.h>

View File

@ -93,7 +93,9 @@ QQmlPreviewHandler::QQmlPreviewHandler(QObject *parent) : QObject(parent)
QQmlPreviewHandler::~QQmlPreviewHandler()
{
#if QT_CONFIG(translation)
removeTranslators();
#endif
clear();
}
@ -223,6 +225,7 @@ void QQmlPreviewHandler::doZoom()
m_lastPosition.initLastSavedWindowPosition(m_currentWindow);
}
#if QT_CONFIG(translation)
void QQmlPreviewHandler::removeTranslators()
{
if (!m_qtTranslator.isNull()) {
@ -255,6 +258,7 @@ void QQmlPreviewHandler::language(const QUrl &context, const QLocale &locale)
for (QQmlEngine *engine : qAsConst(m_engines))
engine->retranslate();
}
#endif
void QQmlPreviewHandler::clear()
{

View File

@ -81,7 +81,9 @@ public:
void loadUrl(const QUrl &url);
void rerun();
void zoom(qreal newFactor);
#if QT_CONFIG(translation)
void language(const QUrl &context, const QLocale &locale);
#endif
void clear();
@ -115,7 +117,9 @@ private:
void frameSwapped();
void fpsTimerHit();
#if QT_CONFIG(translation)
void removeTranslators();
#endif
QScopedPointer<QQuickItem> m_dummyItem;
QList<QQmlEngine *> m_engines;
@ -145,8 +149,10 @@ private:
FrameTime m_rendering;
FrameTime m_synchronizing;
#if QT_CONFIG(translation)
QScopedPointer<QTranslator> m_qtTranslator;
QScopedPointer<QTranslator> m_qmlTranslator;
#endif
};
QT_END_NAMESPACE

View File

@ -64,7 +64,9 @@ QQmlPreviewServiceImpl::QQmlPreviewServiceImpl(QObject *parent) :
connect(this, &QQmlPreviewServiceImpl::load, &m_handler, &QQmlPreviewHandler::loadUrl);
connect(this, &QQmlPreviewServiceImpl::rerun, &m_handler, &QQmlPreviewHandler::rerun);
connect(this, &QQmlPreviewServiceImpl::zoom, &m_handler, &QQmlPreviewHandler::zoom);
#if QT_CONFIG(translation)
connect(this, &QQmlPreviewServiceImpl::language, &m_handler, &QQmlPreviewHandler::language);
#endif
connect(&m_handler, &QQmlPreviewHandler::error, this, &QQmlPreviewServiceImpl::forwardError,
Qt::DirectConnection);
connect(&m_handler, &QQmlPreviewHandler::fps, this, &QQmlPreviewServiceImpl::forwardFps,
@ -135,6 +137,7 @@ void QQmlPreviewServiceImpl::messageReceived(const QByteArray &data)
emit zoom(static_cast<qreal>(factor));
break;
}
#if QT_CONFIG(translation)
case Language: {
QUrl context;
QString locale;
@ -143,6 +146,7 @@ void QQmlPreviewServiceImpl::messageReceived(const QByteArray &data)
locale.isEmpty() ? QLocale() : QLocale(locale));
break;
}
#endif
default:
forwardError(QString::fromLatin1("Invalid command: %1").arg(command));
break;

View File

@ -99,7 +99,9 @@ signals:
void rerun();
void clearCache();
void zoom(qreal factor);
#if QT_CONFIG(translation)
void language(const QUrl &context, const QLocale &locale);
#endif
private:
QScopedPointer<QQmlPreviewFileEngineHandler> m_fileEngine;

View File

@ -1,3 +1,35 @@
!build_pass {
# Create a header containing a hash that describes this library. For a
# released version of Qt, we'll use the .tag file that is updated by git
# archive with the commit hash. For unreleased versions, we'll ask git
# describe. Note that it won't update unless qmake is run again, even if
# the commit change also changed something in this library.
tagFile = $$PWD/../../.tag
tag =
exists($$tagFile) {
tag = $$cat($$tagFile, singleline)
QMAKE_INTERNAL_INCLUDED_FILES += $$tagFile
}
!equals(tag, "$${LITERAL_DOLLAR}Format:%H$${LITERAL_DOLLAR}") {
QML_COMPILE_HASH = $$tag
} else:exists($$PWD/../../.git) {
commit = $$system(git rev-parse HEAD)
QML_COMPILE_HASH = $$commit
}
compile_hash_contents = \
"// Generated file, DO NOT EDIT" \
"$${LITERAL_HASH}define QML_COMPILE_HASH \"$$QML_COMPILE_HASH\"" \
"$${LITERAL_HASH}define QML_COMPILE_HASH_LENGTH $$str_size($$QML_COMPILE_HASH)"
write_file("$$OUT_PWD/qml_compile_hash_p.h", compile_hash_contents)|error()
}
HEADERS += \
$$PWD/qqmlapiversion_p.h \
$$PWD/qqmljsdiagnosticmessage_p.h
$$PWD/qqmljsdiagnosticmessage_p.h \
$$PWD/qqmljsfixedpoolarray_p.h \
$$PWD/qqmljsmemorypool_p.h \
$$PWD/qv4alloca_p.h \
$$PWD/qv4calldata_p.h \
$$PWD/qv4compileddata_p.h \
$$PWD/qv4staticvalue_p.h \
$$PWD/qv4stringtoarrayindex_p.h

View File

@ -0,0 +1,140 @@
/****************************************************************************
**
** 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 QQMLJSFIXEDPOOLARRAY_P_H
#define QQMLJSFIXEDPOOLARRAY_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/qglobal.h>
#include <private/qqmljsmemorypool_p.h>
QT_BEGIN_NAMESPACE
namespace QQmlJS {
template <typename T>
class FixedPoolArray
{
T *data;
int count = 0;
public:
FixedPoolArray()
: data(nullptr)
{}
FixedPoolArray(MemoryPool *pool, int size)
{ allocate(pool, size); }
void allocate(MemoryPool *pool, int size)
{
count = size;
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
}
void allocate(MemoryPool *pool, const QVector<T> &vector)
{
count = vector.count();
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
if (QTypeInfo<T>::isComplex) {
for (int i = 0; i < count; ++i)
new (data + i) T(vector.at(i));
} else {
memcpy(data, static_cast<const void*>(vector.constData()), count * sizeof(T));
}
}
template <typename Container>
void allocate(MemoryPool *pool, const Container &container)
{
count = container.count();
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
typename Container::ConstIterator it = container.constBegin();
for (int i = 0; i < count; ++i)
new (data + i) T(*it++);
}
int size() const
{ return count; }
const T &at(int index) const {
Q_ASSERT(index >= 0 && index < count);
return data[index];
}
T &at(int index) {
Q_ASSERT(index >= 0 && index < count);
return data[index];
}
T &operator[](int index) {
return at(index);
}
int indexOf(const T &value) const {
for (int i = 0; i < count; ++i)
if (data[i] == value)
return i;
return -1;
}
const T *begin() const { return data; }
const T *end() const { return data + count; }
T *begin() { return data; }
T *end() { return data + count; }
};
} // namespace QQmlJS
QT_END_NAMESPACE
#endif // QQMLJSFIXEDPOOLARRAY_P_H

View File

@ -51,8 +51,6 @@
// We mean it.
//
#include "qqmljsglobal_p.h"
#include <QtCore/qglobal.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qdebug.h>
@ -65,7 +63,7 @@ namespace QQmlJS {
class Managed;
class QML_PARSER_EXPORT MemoryPool : public QSharedData
class MemoryPool : public QSharedData
{
MemoryPool(const MemoryPool &other);
void operator =(const MemoryPool &other);
@ -162,7 +160,7 @@ private:
};
};
class QML_PARSER_EXPORT Managed
class Managed
{
Q_DISABLE_COPY(Managed)
public:
@ -174,81 +172,6 @@ public:
void operator delete(void *, MemoryPool *) {}
};
template <typename T>
class FixedPoolArray
{
T *data;
int count = 0;
public:
FixedPoolArray()
: data(nullptr)
{}
FixedPoolArray(MemoryPool *pool, int size)
{ allocate(pool, size); }
void allocate(MemoryPool *pool, int size)
{
count = size;
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
}
void allocate(MemoryPool *pool, const QVector<T> &vector)
{
count = vector.count();
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
if (QTypeInfo<T>::isComplex) {
for (int i = 0; i < count; ++i)
new (data + i) T(vector.at(i));
} else {
memcpy(data, static_cast<const void*>(vector.constData()), count * sizeof(T));
}
}
template <typename Container>
void allocate(MemoryPool *pool, const Container &container)
{
count = container.count();
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
typename Container::ConstIterator it = container.constBegin();
for (int i = 0; i < count; ++i)
new (data + i) T(*it++);
}
int size() const
{ return count; }
const T &at(int index) const {
Q_ASSERT(index >= 0 && index < count);
return data[index];
}
T &at(int index) {
Q_ASSERT(index >= 0 && index < count);
return data[index];
}
T &operator[](int index) {
return at(index);
}
int indexOf(const T &value) const {
for (int i = 0; i < count; ++i)
if (data[i] == value)
return i;
return -1;
}
const T *begin() const { return data; }
const T *end() const { return data + count; }
T *begin() { return data; }
T *end() { return data + count; }
};
} // namespace QQmlJS
QT_END_NAMESPACE

View File

@ -50,6 +50,8 @@
// We mean it.
//
#include <functional>
#include <QtCore/qstring.h>
#include <QtCore/qscopeguard.h>
#include <QtCore/qvector.h>
@ -62,6 +64,7 @@
#include <private/qendian_p.h>
#include <private/qv4staticvalue_p.h>
#include <functional>
QT_BEGIN_NAMESPACE
@ -72,12 +75,10 @@ QT_BEGIN_NAMESPACE
// Also change the comment behind the number to describe the latest change. This has the added
// benefit that if another patch changes the version too, it will result in a merge conflict, and
// not get removed silently.
#define QV4_DATA_STRUCTURE_VERSION 0x23 // Remove trace slots
#define QV4_DATA_STRUCTURE_VERSION 0x24 // Collect function parameter types
class QIODevice;
class QQmlPropertyData;
class QQmlTypeNameCache;
class QQmlScriptData;
class QQmlType;
class QQmlEngine;
@ -255,6 +256,29 @@ struct Block
};
static_assert(sizeof(Block) == 12, "Block structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
enum class BuiltinType : unsigned int {
Var = 0, Variant, Int, Bool, Real, String, Url, Color,
Font, Time, Date, DateTime, Rect, Point, Size,
Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion, InvalidBuiltin
};
struct ParameterType
{
union {
quint32 _dummy;
quint32_le_bitfield<0, 1> indexIsBuiltinType;
quint32_le_bitfield<1, 31> typeNameIndexOrBuiltinType;
};
};
static_assert(sizeof(ParameterType) == 4, "ParameterType structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Parameter
{
quint32_le nameIndex;
ParameterType type;
};
static_assert(sizeof(Parameter) == 8, "Parameter structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
// for unaligned access. The ordering of the fields is also from largest to smallest.
struct Function
@ -273,6 +297,7 @@ struct Function
quint16_le length;
quint16_le nFormals;
quint32_le formalsOffset; // Can't turn this into a calculated offset because of the mutation in CompilationUnit::createUnitData.
ParameterType returnType;
quint32_le localsOffset;
quint16_le nLocals;
quint16_le nLineNumbers;
@ -294,13 +319,13 @@ struct Function
// quint32 formalsIndex[nFormals]
// quint32 localsIndex[nLocals]
const quint32_le *formalsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + formalsOffset); }
const Parameter *formalsTable() const { return reinterpret_cast<const Parameter *>(reinterpret_cast<const char *>(this) + formalsOffset); }
const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
const CodeOffsetToLine *lineNumberTable() const { return reinterpret_cast<const CodeOffsetToLine *>(reinterpret_cast<const char *>(this) + lineNumberOffset()); }
// --- QQmlPropertyCacheCreator interface
const quint32_le *formalsBegin() const { return formalsTable(); }
const quint32_le *formalsEnd() const { return formalsTable() + nFormals; }
const Parameter *formalsBegin() const { return formalsTable(); }
const Parameter *formalsEnd() const { return formalsTable() + nFormals; }
// ---
const quint32_le *labelInfoTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + labelInfosOffset()); }
@ -308,7 +333,7 @@ struct Function
const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; }
static int calculateSize(int nFormals, int nLocals, int nLines, int nInnerfunctions, int labelInfoSize, int codeSize) {
int trailingData = (nFormals + nLocals + nInnerfunctions + labelInfoSize)*sizeof (quint32)
int trailingData = nFormals * sizeof(Parameter) + (nLocals + nInnerfunctions + labelInfoSize)*sizeof (quint32)
+ nLines*sizeof(CodeOffsetToLine);
size_t size = align(align(sizeof(Function)) + size_t(trailingData)) + align(codeSize);
Q_ASSERT(size < INT_MAX);
@ -319,7 +344,7 @@ struct Function
return (a + 7) & ~size_t(7);
}
};
static_assert(sizeof(Function) == 52, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
static_assert(sizeof(Function) == 56, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Method {
enum Type {
@ -602,23 +627,6 @@ struct Enum
};
static_assert(sizeof(Enum) == 12, "Enum structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
enum class BuiltinType : unsigned int {
Var = 0, Variant, Int, Bool, Real, String, Url, Color,
Font, Time, Date, DateTime, Rect, Point, Size,
Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion, InvalidBuiltin
};
struct Parameter
{
quint32_le nameIndex;
union {
quint32 _dummy;
quint32_le_bitfield<0, 1> indexIsBuiltinType;
quint32_le_bitfield<1, 31> typeNameIndexOrBuiltinType;
};
};
static_assert(sizeof(Parameter) == 8, "Parameter structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct Signal
{
quint32_le nameIndex;
@ -1087,9 +1095,6 @@ struct TypeReferenceMap : QHash<int, TypeReference>
using DependentTypesHasher = std::function<QByteArray()>;
// index is per-object binding index
typedef QVector<QQmlPropertyData*> BindingPropertyData;
// This is how this hooks into the existing structures:
struct CompilationUnitBase
@ -1119,10 +1124,10 @@ struct CompilationUnitBase
}
// pointers either to data->constants() or little-endian memory copy.
QV4::Heap::String **runtimeStrings = nullptr; // Array
Heap::String **runtimeStrings = nullptr; // Array
const StaticValue* constants = nullptr;
QV4::StaticValue *runtimeRegularExpressions = nullptr;
QV4::Heap::InternalClass **runtimeClasses = nullptr;
Heap::InternalClass **runtimeClasses = nullptr;
const StaticValue** imports = nullptr;
};

View File

@ -50,14 +50,24 @@
// We mean it.
//
#include <QtQml/private/qtqmlglobal_p.h>
#include <QtQml/private/qv4global_p.h>
#include <QtCore/private/qnumeric_p.h>
#ifdef QT_NO_DEBUG
#define QV4_NEARLY_ALWAYS_INLINE Q_ALWAYS_INLINE
#else
#define QV4_NEARLY_ALWAYS_INLINE inline
#endif
QT_BEGIN_NAMESPACE
namespace QV4 {
// ReturnedValue is used to return values from runtime methods
// the type has to be a primitive type (no struct or union), so that the compiler
// will return it in a register on all platforms.
// It will be returned in rax on x64, [eax,edx] on x86 and [r0,r1] on arm
typedef quint64 ReturnedValue;
struct Double {
quint64 d;
@ -105,7 +115,7 @@ struct Double {
}
};
struct Q_QML_PRIVATE_EXPORT StaticValue
struct StaticValue
{
StaticValue() = default;
constexpr StaticValue(quint64 val) : _val(val) {}
@ -180,9 +190,9 @@ struct Q_QML_PRIVATE_EXPORT StaticValue
quint64 _val;
QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR quint64 &rawValueRef() { return _val; }
QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR quint64 rawValue() const { return _val; }
QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setRawValue(quint64 raw) { _val = raw; }
QV4_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR quint64 &rawValueRef() { return _val; }
QV4_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR quint64 rawValue() const { return _val; }
QV4_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setRawValue(quint64 raw) { _val = raw; }
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
static inline int valueOffset() { return 0; }
@ -192,22 +202,22 @@ struct Q_QML_PRIVATE_EXPORT StaticValue
static inline int tagOffset() { return 0; }
#endif
static inline constexpr quint64 tagValue(quint32 tag, quint32 value) { return quint64(tag) << 32 | value; }
QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
QML_NEARLY_ALWAYS_INLINE constexpr quint32 value() const { return _val & quint64(~quint32(0)); }
QML_NEARLY_ALWAYS_INLINE constexpr quint32 tag() const { return _val >> 32; }
QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setTag(quint32 tag) { setTagValue(tag, value()); }
QV4_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; }
QV4_NEARLY_ALWAYS_INLINE constexpr quint32 value() const { return _val & quint64(~quint32(0)); }
QV4_NEARLY_ALWAYS_INLINE constexpr quint32 tag() const { return _val >> 32; }
QV4_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setTag(quint32 tag) { setTagValue(tag, value()); }
QML_NEARLY_ALWAYS_INLINE constexpr int int_32() const
QV4_NEARLY_ALWAYS_INLINE constexpr int int_32() const
{
return int(value());
}
QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setInt_32(int i)
QV4_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setInt_32(int i)
{
setTagValue(quint32(ValueTypeInternal::Integer), quint32(i));
}
QML_NEARLY_ALWAYS_INLINE uint uint_32() const { return value(); }
QV4_NEARLY_ALWAYS_INLINE uint uint_32() const { return value(); }
QML_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setEmpty()
QV4_NEARLY_ALWAYS_INLINE Q_DECL_RELAXED_CONSTEXPR void setEmpty()
{
setTagValue(quint32(ValueTypeInternal::Empty), 0);
}
@ -353,7 +363,7 @@ struct Q_QML_PRIVATE_EXPORT StaticValue
#endif
}
QML_NEARLY_ALWAYS_INLINE double doubleValue() const {
QV4_NEARLY_ALWAYS_INLINE double doubleValue() const {
Q_ASSERT(isDouble());
double d;
StaticValue v = *this;
@ -362,7 +372,7 @@ struct Q_QML_PRIVATE_EXPORT StaticValue
return d;
}
QML_NEARLY_ALWAYS_INLINE void setDouble(double d) {
QV4_NEARLY_ALWAYS_INLINE void setDouble(double d) {
if (qt_is_nan(d))
d = qt_qnan();
memcpy(&_val, &d, 8);
@ -383,7 +393,7 @@ struct Q_QML_PRIVATE_EXPORT StaticValue
return false;
}
QML_NEARLY_ALWAYS_INLINE static bool isInt32(double d) {
QV4_NEARLY_ALWAYS_INLINE static bool isInt32(double d) {
int i = int(d);
return (i == d && !(d == 0 && std::signbit(d)));
}

View File

@ -2,21 +2,17 @@ INCLUDEPATH += $$PWD
INCLUDEPATH += $$OUT_PWD
HEADERS += \
$$PWD/qv4alloca_p.h \
$$PWD/qv4bytecodegenerator_p.h \
$$PWD/qv4compileddata_p.h \
$$PWD/qv4compiler_p.h \
$$PWD/qv4compilercontext_p.h \
$$PWD/qv4compilercontrolflow_p.h \
$$PWD/qv4compilerglobal_p.h \
$$PWD/qv4compilerscanfunctions_p.h \
$$PWD/qv4codegen_p.h \
$$PWD/qqmlirbuilder_p.h \
$$PWD/qv4instr_moth_p.h \
$$PWD/qv4bytecodehandler_p.h \
$$PWD/qv4calldata_p.h \
$$PWD/qv4util_p.h \
$$PWD/qv4staticvalue_p.h \
$$PWD/qv4stringtoarrayindex_p.h
$$PWD/qv4util_p.h
SOURCES += \
$$PWD/qv4bytecodegenerator.cpp \

View File

@ -56,6 +56,7 @@ QT_USE_NAMESPACE
static const quint32 emptyStringIndex = 0;
using namespace QmlIR;
using namespace QQmlJS;
#define COMPILE_EXCEPTION(location, desc) \
{ \
@ -63,6 +64,84 @@ using namespace QmlIR;
return false; \
}
bool Parameter::init(QV4::Compiler::JSUnitGenerator *stringGenerator, const QString &parameterName,
const QString &typeName)
{
return init(this, stringGenerator, stringGenerator->registerString(parameterName), stringGenerator->registerString(typeName));
}
bool Parameter::init(QV4::CompiledData::Parameter *param, const QV4::Compiler::JSUnitGenerator *stringGenerator,
int parameterNameIndex, int typeNameIndex)
{
param->nameIndex = parameterNameIndex;
return initType(&param->type, stringGenerator, typeNameIndex);
}
bool Parameter::initType(QV4::CompiledData::ParameterType *paramType, const QV4::Compiler::JSUnitGenerator *stringGenerator, int typeNameIndex)
{
paramType->indexIsBuiltinType = false;
paramType->typeNameIndexOrBuiltinType = 0;
const QString typeName = stringGenerator->stringForIndex(typeNameIndex);
auto builtinType = stringToBuiltinType(typeName);
if (builtinType == QV4::CompiledData::BuiltinType::InvalidBuiltin) {
if (typeName.isEmpty() || !typeName.at(0).isUpper())
return false;
paramType->indexIsBuiltinType = false;
paramType->typeNameIndexOrBuiltinType = typeNameIndex;
Q_ASSERT(quint32(typeNameIndex) < (1u << 31));
} else {
paramType->indexIsBuiltinType = true;
paramType->typeNameIndexOrBuiltinType = static_cast<quint32>(builtinType);
Q_ASSERT(quint32(builtinType) < (1u << 31));
}
return true;
}
QV4::CompiledData::BuiltinType Parameter::stringToBuiltinType(const QString &typeName)
{
static const struct TypeNameToType {
const char *name;
size_t nameLength;
QV4::CompiledData::BuiltinType type;
} propTypeNameToTypes[] = {
{ "int", strlen("int"), QV4::CompiledData::BuiltinType::Int },
{ "bool", strlen("bool"), QV4::CompiledData::BuiltinType::Bool },
{ "double", strlen("double"), QV4::CompiledData::BuiltinType::Real },
{ "real", strlen("real"), QV4::CompiledData::BuiltinType::Real },
{ "string", strlen("string"), QV4::CompiledData::BuiltinType::String },
{ "url", strlen("url"), QV4::CompiledData::BuiltinType::Url },
{ "color", strlen("color"), QV4::CompiledData::BuiltinType::Color },
// Internally QTime, QDate and QDateTime are all supported.
// To be more consistent with JavaScript we expose only
// QDateTime as it matches closely with the Date JS type.
// We also call it "date" to match.
// { "time", strlen("time"), Property::Time },
// { "date", strlen("date"), Property::Date },
{ "date", strlen("date"), QV4::CompiledData::BuiltinType::DateTime },
{ "rect", strlen("rect"), QV4::CompiledData::BuiltinType::Rect },
{ "point", strlen("point"), QV4::CompiledData::BuiltinType::Point },
{ "size", strlen("size"), QV4::CompiledData::BuiltinType::Size },
{ "font", strlen("font"), QV4::CompiledData::BuiltinType::Font },
{ "vector2d", strlen("vector2d"), QV4::CompiledData::BuiltinType::Vector2D },
{ "vector3d", strlen("vector3d"), QV4::CompiledData::BuiltinType::Vector3D },
{ "vector4d", strlen("vector4d"), QV4::CompiledData::BuiltinType::Vector4D },
{ "quaternion", strlen("quaternion"), QV4::CompiledData::BuiltinType::Quaternion },
{ "matrix4x4", strlen("matrix4x4"), QV4::CompiledData::BuiltinType::Matrix4x4 },
{ "variant", strlen("variant"), QV4::CompiledData::BuiltinType::Variant },
{ "var", strlen("var"), QV4::CompiledData::BuiltinType::Var }
};
static const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
sizeof(propTypeNameToTypes[0]);
for (int typeIndex = 0; typeIndex < propTypeNameToTypesCount; ++typeIndex) {
const TypeNameToType *t = propTypeNameToTypes + typeIndex;
if (typeName == QLatin1String(t->name, static_cast<int>(t->nameLength))) {
return t->type;
}
}
return QV4::CompiledData::BuiltinType::InvalidBuiltin;
}
void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &loc)
{
inheritedTypeNameIndex = typeNameIndex;
@ -247,64 +326,11 @@ QStringList Signal::parameterStringList(const QV4::Compiler::StringTableGenerato
{
QStringList result;
result.reserve(parameters->count);
for (SignalParameter *param = parameters->first; param; param = param->next)
for (Parameter *param = parameters->first; param; param = param->next)
result << stringPool->stringForIndex(param->nameIndex);
return result;
}
static void replaceWithSpace(QString &str, int idx, int n)
{
QChar *data = str.data() + idx;
const QChar space(QLatin1Char(' '));
for (int ii = 0; ii < n; ++ii)
*data++ = space;
}
void Document::removeScriptPragmas(QString &script)
{
const QLatin1String pragma("pragma");
const QLatin1String library("library");
QQmlJS::Lexer l(nullptr);
l.setCode(script, 0);
int token = l.lex();
while (true) {
if (token != QQmlJSGrammar::T_DOT)
return;
int startOffset = l.tokenOffset();
int startLine = l.tokenStartLine();
token = l.lex();
if (token != QQmlJSGrammar::T_PRAGMA ||
l.tokenStartLine() != startLine ||
script.midRef(l.tokenOffset(), l.tokenLength()) != pragma)
return;
token = l.lex();
if (token != QQmlJSGrammar::T_IDENTIFIER ||
l.tokenStartLine() != startLine)
return;
const QStringRef pragmaValue = script.midRef(l.tokenOffset(), l.tokenLength());
int endOffset = l.tokenLength() + l.tokenOffset();
token = l.lex();
if (l.tokenStartLine() == startLine)
return;
if (pragmaValue == library) {
replaceWithSpace(script, startOffset, endOffset - startOffset);
} else {
return;
}
}
}
Document::Document(bool debugMode)
: jsModule(debugMode)
, program(nullptr)
@ -764,40 +790,6 @@ bool IRBuilder::visit(QQmlJS::AST::UiEnumDeclaration *node)
bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
{
static const struct TypeNameToType {
const char *name;
size_t nameLength;
QV4::CompiledData::BuiltinType type;
} propTypeNameToTypes[] = {
{ "int", strlen("int"), QV4::CompiledData::BuiltinType::Int },
{ "bool", strlen("bool"), QV4::CompiledData::BuiltinType::Bool },
{ "double", strlen("double"), QV4::CompiledData::BuiltinType::Real },
{ "real", strlen("real"), QV4::CompiledData::BuiltinType::Real },
{ "string", strlen("string"), QV4::CompiledData::BuiltinType::String },
{ "url", strlen("url"), QV4::CompiledData::BuiltinType::Url },
{ "color", strlen("color"), QV4::CompiledData::BuiltinType::Color },
// Internally QTime, QDate and QDateTime are all supported.
// To be more consistent with JavaScript we expose only
// QDateTime as it matches closely with the Date JS type.
// We also call it "date" to match.
// { "time", strlen("time"), Property::Time },
// { "date", strlen("date"), Property::Date },
{ "date", strlen("date"), QV4::CompiledData::BuiltinType::DateTime },
{ "rect", strlen("rect"), QV4::CompiledData::BuiltinType::Rect },
{ "point", strlen("point"), QV4::CompiledData::BuiltinType::Point },
{ "size", strlen("size"), QV4::CompiledData::BuiltinType::Size },
{ "font", strlen("font"), QV4::CompiledData::BuiltinType::Font },
{ "vector2d", strlen("vector2d"), QV4::CompiledData::BuiltinType::Vector2D },
{ "vector3d", strlen("vector3d"), QV4::CompiledData::BuiltinType::Vector3D },
{ "vector4d", strlen("vector4d"), QV4::CompiledData::BuiltinType::Vector4D },
{ "quaternion", strlen("quaternion"), QV4::CompiledData::BuiltinType::Quaternion },
{ "matrix4x4", strlen("matrix4x4"), QV4::CompiledData::BuiltinType::Matrix4x4 },
{ "variant", strlen("variant"), QV4::CompiledData::BuiltinType::Variant },
{ "var", strlen("var"), QV4::CompiledData::BuiltinType::Var }
};
static const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
sizeof(propTypeNameToTypes[0]);
if (node->type == QQmlJS::AST::UiPublicMember::Signal) {
Signal *signal = New<Signal>();
QString signalName = node->name.toString();
@ -807,7 +799,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
signal->location.line = loc.startLine;
signal->location.column = loc.startColumn;
signal->parameters = New<PoolList<SignalParameter> >();
signal->parameters = New<PoolList<Parameter> >();
QQmlJS::AST::UiParameterList *p = node->parameters;
while (p) {
@ -818,38 +810,13 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
return false;
}
const TypeNameToType *type = nullptr;
for (int typeIndex = 0; typeIndex < propTypeNameToTypesCount; ++typeIndex) {
const TypeNameToType *t = propTypeNameToTypes + typeIndex;
if (memberType == QLatin1String(t->name, static_cast<int>(t->nameLength))) {
type = t;
break;
}
Parameter *param = New<Parameter>();
if (!param->init(jsGenerator, p->name.toString(), memberType)) {
QString errStr = QCoreApplication::translate("QQmlParser","Invalid signal parameter type: ");
errStr.append(memberType);
recordError(node->typeToken, errStr);
return false;
}
SignalParameter *param = New<SignalParameter>();
if (!type) {
if (memberType.at(0).isUpper()) {
// Must be a QML object type.
// Lazily determine type during compilation.
param->indexIsBuiltinType = false;
param->typeNameIndexOrBuiltinType = registerString(memberType);
Q_ASSERT(quint32(jsGenerator->getStringId(memberType)) < (1u << 31));
} else {
QString errStr = QCoreApplication::translate("QQmlParser","Invalid signal parameter type: ");
errStr.append(memberType);
recordError(node->typeToken, errStr);
return false;
}
} else {
// the parameter is a known basic type
param->indexIsBuiltinType = true;
param->typeNameIndexOrBuiltinType = static_cast<quint32>(type->type);
Q_ASSERT(quint32(type->type) < (1u << 31));
}
param->nameIndex = registerString(p->name.toString());
signal->parameters->append(param);
p = p->next;
}
@ -875,15 +842,10 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node)
Property *property = New<Property>();
property->isReadOnly = node->isReadonlyMember;
bool typeFound = false;
for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) {
const TypeNameToType *t = propTypeNameToTypes + ii;
if (memberType == QLatin1String(t->name, static_cast<int>(t->nameLength))) {
property->setBuiltinType(t->type);
typeFound = true;
}
}
QV4::CompiledData::BuiltinType builtinPropertyType = Parameter::stringToBuiltinType(memberType);
bool typeFound = builtinPropertyType != QV4::CompiledData::BuiltinType::InvalidBuiltin;
if (typeFound)
property->setBuiltinType(builtinPropertyType);
if (!typeFound && memberType.at(0).isUpper()) {
const QStringRef &typeModifier = node->typeModifier;
@ -960,13 +922,16 @@ bool IRBuilder::visit(QQmlJS::AST::UiSourceElement *node)
f->index = index;
f->nameIndex = registerString(funDecl->name.toString());
const QStringList formals = funDecl->formals ? funDecl->formals->formals() : QStringList();
QString returnTypeName = funDecl->typeAnnotation ? funDecl->typeAnnotation->type->toString() : QString();
Parameter::initType(&f->returnType, jsGenerator, registerString(returnTypeName));
const QQmlJS::AST::BoundNames formals = funDecl->formals ? funDecl->formals->formals() : QQmlJS::AST::BoundNames();
int formalsCount = formals.size();
f->formals.allocate(pool, formalsCount);
int i = 0;
for (const QString &arg : formals) {
f->formals[i] = registerString(arg);
for (const auto &arg : formals) {
f->formals[i].init(jsGenerator, arg.id, arg.typeName());
++i;
}
@ -1696,7 +1661,7 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
signalToWrite->nParameters = s->parameters->count;
QV4::CompiledData::Parameter *parameterToWrite = reinterpret_cast<QV4::CompiledData::Parameter*>(signalPtr + sizeof(*signalToWrite));
for (SignalParameter *param = s->parameters->first; param; param = param->next, ++parameterToWrite)
for (Parameter *param = s->parameters->first; param; param = param->next, ++parameterToWrite)
*parameterToWrite = *param;
int size = QV4::CompiledData::Signal::calculateSize(s->parameters->count);
@ -1782,19 +1747,11 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, Binding
return bindingPtr;
}
JSCodeGen::JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator *jsUnitGenerator,
QV4::Compiler::Module *jsModule, QQmlJS::Engine *jsEngine,
QQmlJS::AST::UiProgram *qmlRoot,
const QV4::Compiler::StringTableGenerator *stringPool, const QSet<QString> &globalNames)
: QV4::Compiler::Codegen(jsUnitGenerator, /*strict mode*/false)
, sourceCode(sourceCode)
, jsEngine(jsEngine)
, qmlRoot(qmlRoot)
, stringPool(stringPool)
JSCodeGen::JSCodeGen(Document *document, const QSet<QString> &globalNames)
: QV4::Compiler::Codegen(&document->jsGenerator, /*strict mode*/false), document(document)
{
m_globalNames = globalNames;
_module = jsModule;
_module = &document->jsModule;
_fileNameIsUrl = true;
}
@ -1802,17 +1759,17 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
{
auto qmlName = [&](const CompiledFunctionOrExpression &c) {
if (c.nameIndex != 0)
return stringPool->stringForIndex(c.nameIndex);
return document->stringAt(c.nameIndex);
else
return QStringLiteral("%qml-expression-entry");
};
QVector<int> runtimeFunctionIndices(functions.size());
QV4::Compiler::ScanFunctions scan(this, sourceCode, QV4::Compiler::ContextType::Global);
QV4::Compiler::ScanFunctions scan(this, document->code, QV4::Compiler::ContextType::Global);
scan.enterGlobalEnvironment(QV4::Compiler::ContextType::Binding);
for (const CompiledFunctionOrExpression &f : functions) {
Q_ASSERT(f.node != qmlRoot);
Q_ASSERT(f.parentNode && f.parentNode != qmlRoot);
Q_ASSERT(f.node != document->program);
Q_ASSERT(f.parentNode && f.parentNode != document->program);
QQmlJS::AST::FunctionDeclaration *function = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(f.node);
if (function) {
@ -1835,7 +1792,7 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
for (int i = 0; i < functions.count(); ++i) {
const CompiledFunctionOrExpression &qmlFunction = functions.at(i);
QQmlJS::AST::Node *node = qmlFunction.node;
Q_ASSERT(node != qmlRoot);
Q_ASSERT(node != document->program);
QQmlJS::AST::FunctionDeclaration *function = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(node);
@ -1850,7 +1807,7 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
body = function->body;
} else {
// Synthesize source elements.
QQmlJS::MemoryPool *pool = jsEngine->pool();
QQmlJS::MemoryPool *pool = document->jsParserEngine.pool();
QQmlJS::AST::Statement *stmt = node->statementCast();
if (!stmt) {
@ -1870,3 +1827,58 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
return runtimeFunctionIndices;
}
bool JSCodeGen::generateCodeForComponents(const QVector<quint32> &componentRoots)
{
for (int i = 0; i < componentRoots.count(); ++i) {
if (!compileComponent(componentRoots.at(i)))
return false;
}
return compileComponent(/*root object*/0);
}
bool JSCodeGen::compileComponent(int contextObject)
{
const QmlIR::Object *obj = document->objects.at(contextObject);
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
Q_ASSERT(obj->bindingCount() == 1);
const QV4::CompiledData::Binding *componentBinding = obj->firstBinding();
Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
contextObject = componentBinding->value.objectIndex;
}
return compileJavaScriptCodeInObjectsRecursively(contextObject, contextObject);
}
bool JSCodeGen::compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex)
{
QmlIR::Object *object = document->objects.at(objectIndex);
if (object->flags & QV4::CompiledData::Object::IsComponent)
return true;
if (object->functionsAndExpressions->count > 0) {
QList<QmlIR::CompiledFunctionOrExpression> functionsToCompile;
for (QmlIR::CompiledFunctionOrExpression *foe = object->functionsAndExpressions->first; foe; foe = foe->next)
functionsToCompile << *foe;
const QVector<int> runtimeFunctionIndices = generateJSCodeForFunctionsAndBindings(functionsToCompile);
if (hasError())
return false;
object->runtimeFunctionIndices.allocate(document->jsParserEngine.pool(),
runtimeFunctionIndices);
}
for (const QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) {
if (binding->type < QV4::CompiledData::Binding::Type_Object)
continue;
int target = binding->value.objectIndex;
int scope = binding->type == QV4::CompiledData::Binding::Type_Object ? target : scopeObjectIndex;
if (!compileJavaScriptCodeInObjectsRecursively(binding->value.objectIndex, scope))
return false;
}
return true;
}

View File

@ -55,6 +55,7 @@
#include <private/qv4compiler_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qqmljsmemorypool_p.h>
#include <private/qqmljsfixedpoolarray_p.h>
#include <private/qv4codegen_p.h>
#include <private/qv4compiler_p.h>
#include <QTextStream>
@ -215,22 +216,30 @@ struct Enum
};
struct SignalParameter : public QV4::CompiledData::Parameter
struct Parameter : public QV4::CompiledData::Parameter
{
SignalParameter *next;
Parameter *next;
bool init(QV4::Compiler::JSUnitGenerator *stringGenerator, const QString &parameterName, const QString &typeName);
static bool init(QV4::CompiledData::Parameter *param, const QV4::Compiler::JSUnitGenerator *stringGenerator,
int parameterNameIndex, int typeNameIndex);
static bool initType(QV4::CompiledData::ParameterType *paramType,
const QV4::Compiler::JSUnitGenerator *stringGenerator, int typeNameIndex);
static QV4::CompiledData::BuiltinType stringToBuiltinType(const QString &typeName);
};
struct Signal
{
int nameIndex;
QV4::CompiledData::Location location;
PoolList<SignalParameter> *parameters;
PoolList<Parameter> *parameters;
QStringList parameterStringList(const QV4::Compiler::StringTableGenerator *stringPool) const;
int parameterCount() const { return parameters->count; }
PoolList<SignalParameter>::Iterator parametersBegin() const { return parameters->begin(); }
PoolList<SignalParameter>::Iterator parametersEnd() const { return parameters->end(); }
PoolList<Parameter>::Iterator parametersBegin() const { return parameters->begin(); }
PoolList<Parameter>::Iterator parametersEnd() const { return parameters->end(); }
Signal *next;
};
@ -260,17 +269,18 @@ struct Function
QV4::CompiledData::Location location;
int nameIndex;
quint32 index; // index in parsedQML::functions
FixedPoolArray<int> formals;
QQmlJS::FixedPoolArray<Parameter> formals;
QV4::CompiledData::ParameterType returnType;
// --- QQmlPropertyCacheCreator interface
const int *formalsBegin() const { return formals.begin(); }
const int *formalsEnd() const { return formals.end(); }
const Parameter *formalsBegin() const { return formals.begin(); }
const Parameter *formalsEnd() const { return formals.end(); }
// ---
Function *next;
};
struct Q_QML_PRIVATE_EXPORT CompiledFunctionOrExpression
struct Q_QMLCOMPILER_PRIVATE_EXPORT CompiledFunctionOrExpression
{
CompiledFunctionOrExpression()
{}
@ -281,7 +291,7 @@ struct Q_QML_PRIVATE_EXPORT CompiledFunctionOrExpression
CompiledFunctionOrExpression *next = nullptr;
};
struct Q_QML_PRIVATE_EXPORT Object
struct Q_QMLCOMPILER_PRIVATE_EXPORT Object
{
Q_DECLARE_TR_FUNCTIONS(Object)
public:
@ -340,9 +350,9 @@ public:
QString bindingAsString(Document *doc, int scriptIndex) const;
PoolList<CompiledFunctionOrExpression> *functionsAndExpressions;
FixedPoolArray<int> runtimeFunctionIndices;
QQmlJS::FixedPoolArray<int> runtimeFunctionIndices;
FixedPoolArray<quint32> namedObjectsInComponent;
QQmlJS::FixedPoolArray<quint32> namedObjectsInComponent;
int namedObjectsInComponentCount() const { return namedObjectsInComponent.size(); }
const quint32 *namedObjectsInComponentTable() const { return namedObjectsInComponent.begin(); }
@ -357,7 +367,7 @@ private:
PoolList<Function> *functions;
};
struct Q_QML_PRIVATE_EXPORT Pragma
struct Q_QMLCOMPILER_PRIVATE_EXPORT Pragma
{
enum PragmaType {
PragmaSingleton = 0x1
@ -367,7 +377,7 @@ struct Q_QML_PRIVATE_EXPORT Pragma
QV4::CompiledData::Location location;
};
struct Q_QML_PRIVATE_EXPORT Document
struct Q_QMLCOMPILER_PRIVATE_EXPORT Document
{
Document(bool debugMode);
QString code;
@ -383,11 +393,9 @@ struct Q_QML_PRIVATE_EXPORT Document
int registerString(const QString &str) { return jsGenerator.registerString(str); }
QString stringAt(int index) const { return jsGenerator.stringForIndex(index); }
static void removeScriptPragmas(QString &script);
};
class Q_QML_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives
class Q_QMLCOMPILER_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives
{
QmlIR::Document *document;
QQmlJS::Engine *engine;
@ -401,7 +409,7 @@ public:
void importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column) override;
};
struct Q_QML_PRIVATE_EXPORT IRBuilder : public QQmlJS::AST::Visitor
struct Q_QMLCOMPILER_PRIVATE_EXPORT IRBuilder : public QQmlJS::AST::Visitor
{
Q_DECLARE_TR_FUNCTIONS(QQmlCodeGenerator)
public:
@ -432,7 +440,7 @@ public:
void throwRecursionDepthError() override
{
recordError(AST::SourceLocation(),
recordError(QQmlJS::AST::SourceLocation(),
QStringLiteral("Maximum statement or expression depth exceeded"));
}
@ -451,13 +459,19 @@ public:
QStringRef textRefAt(const QQmlJS::AST::SourceLocation &first,
const QQmlJS::AST::SourceLocation &last) const;
void setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement, AST::Node *parentNode);
void setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST::Statement *statement,
QQmlJS::AST::Node *parentNode);
void tryGeneratingTranslationBinding(const QStringRef &base, QQmlJS::AST::ArgumentList *args, QV4::CompiledData::Binding *binding);
void appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value, AST::Node *parentNode);
void appendBinding(QQmlJS::AST::UiQualifiedId *name, QQmlJS::AST::Statement *value,
QQmlJS::AST::Node *parentNode);
void appendBinding(QQmlJS::AST::UiQualifiedId *name, int objectIndex, bool isOnAssignment = false);
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, QQmlJS::AST::Statement *value, AST::Node *parentNode);
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation, const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex, int objectIndex, bool isListItem = false, bool isOnAssignment = false);
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation,
const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex,
QQmlJS::AST::Statement *value, QQmlJS::AST::Node *parentNode);
void appendBinding(const QQmlJS::AST::SourceLocation &qualifiedNameLocation,
const QQmlJS::AST::SourceLocation &nameLocation, quint32 propertyNameIndex,
int objectIndex, bool isListItem = false, bool isOnAssignment = false);
bool appendAlias(QQmlJS::AST::UiPublicMember *node);
@ -499,7 +513,7 @@ public:
QV4::Compiler::JSUnitGenerator *jsGenerator;
};
struct Q_QML_PRIVATE_EXPORT QmlUnitGenerator
struct Q_QMLCOMPILER_PRIVATE_EXPORT QmlUnitGenerator
{
void generate(Document &output, const QV4::CompiledData::DependentTypesHasher &dependencyHasher = QV4::CompiledData::DependentTypesHasher());
@ -508,34 +522,23 @@ private:
char *writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const;
};
struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen
struct Q_QMLCOMPILER_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen
{
JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator *jsUnitGenerator, QV4::Compiler::Module *jsModule,
QQmlJS::Engine *jsEngine, QQmlJS::AST::UiProgram *qmlRoot,
const QV4::Compiler::StringTableGenerator *stringPool, const QSet<QString> &globalNames);
JSCodeGen(Document *document, const QSet<QString> &globalNames);
// Returns mapping from input functions to index in IR::Module::functions / compiledData->runtimeFunctions
QVector<int> generateJSCodeForFunctionsAndBindings(const QList<CompiledFunctionOrExpression> &functions);
bool generateCodeForComponents(const QVector<quint32> &componentRoots);
bool compileComponent(int contextObject);
bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex);
private:
QString sourceCode;
QQmlJS::Engine *jsEngine; // needed for memory pool
QQmlJS::AST::UiProgram *qmlRoot;
const QV4::Compiler::StringTableGenerator *stringPool;
Document *document;
};
} // namespace QmlIR
inline QQmlJS::DiagnosticMessage qQmlCompileError(const QV4::CompiledData::Location &location,
const QString &description)
{
QQmlJS::DiagnosticMessage error;
error.line = location.line;
error.column = location.column;
error.message = description;
return error;
}
QT_END_NAMESPACE
#endif // QQMLIRBUILDER_P_H

View File

@ -206,7 +206,6 @@ int BytecodeGenerator::addInstructionHelper(Instr::Type type, const Instr &i, in
lastInstrType = int(type);
lastInstr = i;
#if QT_CONFIG(qml_debug)
if (debugMode && type != Instr::Type::Debug) {
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // broken gcc warns about Instruction::Debug()
@ -219,9 +218,6 @@ QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // broken gcc warns about Instru
}
QT_WARNING_POP
}
#else
Q_UNUSED(debugMode);
#endif
const int pos = instructions.size();

View File

@ -62,6 +62,11 @@ class SourceLocation;
}
namespace QV4 {
namespace Compiler {
struct Context;
}
namespace Moth {
class BytecodeGenerator {

View File

@ -48,7 +48,6 @@
#include <private/qqmljsast_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qv4stringtoarrayindex_p.h>
#include <private/qv4staticvalue_p.h>
#include <private/qv4compilercontext_p.h>
#include <private/qv4compilercontrolflow_p.h>
@ -69,6 +68,7 @@ static const bool disable_lookups = false;
QT_USE_NAMESPACE
using namespace QV4;
using namespace QV4::Compiler;
using namespace QQmlJS;
using namespace QQmlJS::AST;
static inline void setJumpOutLocation(QV4::Moth::BytecodeGenerator *bytecodeGenerator,
@ -610,6 +610,8 @@ void Codegen::initializeAndDestructureBindingElement(AST::PatternElement *e, con
if (hasError())
return;
accept(e->typeAnnotation);
if (e->initializer) {
if (!baseRef.isValid()) {
// assignment
@ -885,6 +887,12 @@ bool Codegen::visit(ExportDeclaration *ast)
return false;
}
bool Codegen::visit(TypeAnnotation *ast)
{
throwSyntaxError(ast->firstSourceLocation(), QLatin1String("Type annotations are not supported (yet)."));
return false;
}
bool Codegen::visit(StatementList *)
{
Q_UNREACHABLE();

View File

@ -50,7 +50,6 @@
// We mean it.
//
#include "private/qv4global_p.h"
#include <private/qqmljsastvisitor_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qqmljsast_p.h>
@ -63,8 +62,6 @@
QT_BEGIN_NAMESPACE
using namespace QQmlJS;
namespace QV4 {
namespace Moth {
@ -81,7 +78,7 @@ struct ControlFlow;
struct ControlFlowCatch;
struct ControlFlowFinally;
class Q_QML_PRIVATE_EXPORT Codegen: protected QQmlJS::AST::Visitor
class Q_QMLCOMPILER_PRIVATE_EXPORT Codegen: protected QQmlJS::AST::Visitor
{
protected:
using BytecodeGenerator = QV4::Moth::BytecodeGenerator;
@ -93,14 +90,14 @@ public:
void generateFromProgram(const QString &fileName,
const QString &finalUrl,
const QString &sourceCode,
AST::Program *ast,
QQmlJS::AST::Program *ast,
Module *module,
ContextType contextType = ContextType::Global);
void generateFromModule(const QString &fileName,
const QString &finalUrl,
const QString &sourceCode,
AST::ESModule *ast,
QQmlJS::AST::ESModule *ast,
Module *module);
public:
@ -487,10 +484,10 @@ protected:
}
};
void enterContext(AST::Node *node);
void enterContext(QQmlJS::AST::Node *node);
int leaveContext();
public:
Context *enterBlock(AST::Node *node);
Context *enterBlock(QQmlJS::AST::Node *node);
int leaveBlock() { return leaveContext(); }
protected:
void leaveLoop();
@ -521,18 +518,18 @@ public:
int registerQmlContextPropertyGetterLookup(int nameIndex) { return jsUnitGenerator->registerQmlContextPropertyGetterLookup(nameIndex); }
// Returns index in _module->functions
virtual int defineFunction(const QString &name, AST::Node *ast,
AST::FormalParameterList *formals,
AST::StatementList *body);
virtual int defineFunction(const QString &name, QQmlJS::AST::Node *ast,
QQmlJS::AST::FormalParameterList *formals,
QQmlJS::AST::StatementList *body);
protected:
void statement(AST::Statement *ast);
void statement(AST::ExpressionNode *ast);
void condition(AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue,
void statement(QQmlJS::AST::Statement *ast);
void statement(QQmlJS::AST::ExpressionNode *ast);
void condition(QQmlJS::AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue,
const BytecodeGenerator::Label *iffalse,
bool trueBlockFollowsCondition);
inline Reference expression(AST::ExpressionNode *ast, const QString &name = QString())
inline Reference expression(QQmlJS::AST::ExpressionNode *ast, const QString &name = QString())
{
if (!ast || hasError())
return Reference();
@ -542,131 +539,134 @@ protected:
return popResult();
}
inline void accept(AST::Node *node)
inline void accept(QQmlJS::AST::Node *node)
{
if (!hasError() && node)
node->accept(this);
}
void program(AST::Program *ast);
void statementList(AST::StatementList *ast);
void variableDeclaration(AST::PatternElement *ast);
void variableDeclarationList(AST::VariableDeclarationList *ast);
void program(QQmlJS::AST::Program *ast);
void statementList(QQmlJS::AST::StatementList *ast);
void variableDeclaration(QQmlJS::AST::PatternElement *ast);
void variableDeclarationList(QQmlJS::AST::VariableDeclarationList *ast);
Reference targetForPatternElement(AST::PatternElement *p);
void initializeAndDestructureBindingElement(AST::PatternElement *e, const Reference &baseRef = Reference(), bool isDefinition = false);
void destructurePropertyList(const Reference &object, AST::PatternPropertyList *bindingList, bool isDefinition = false);
void destructureElementList(const Reference &array, AST::PatternElementList *bindingList, bool isDefinition = false);
void destructurePattern(AST::Pattern *p, const Reference &rhs);
Reference targetForPatternElement(QQmlJS::AST::PatternElement *p);
void initializeAndDestructureBindingElement(QQmlJS::AST::PatternElement *e, const Reference &baseRef = Reference(), bool isDefinition = false);
void destructurePropertyList(const Reference &object, QQmlJS::AST::PatternPropertyList *bindingList, bool isDefinition = false);
void destructureElementList(const Reference &array, QQmlJS::AST::PatternElementList *bindingList, bool isDefinition = false);
void destructurePattern(QQmlJS::AST::Pattern *p, const Reference &rhs);
Reference referenceForPropertyName(const Codegen::Reference &object, AST::PropertyName *name);
Reference referenceForPropertyName(const Codegen::Reference &object, QQmlJS::AST::PropertyName *name);
void emitReturn(const Reference &expr);
// nodes
bool visit(AST::ArgumentList *ast) override;
bool visit(AST::CaseBlock *ast) override;
bool visit(AST::CaseClause *ast) override;
bool visit(AST::CaseClauses *ast) override;
bool visit(AST::Catch *ast) override;
bool visit(AST::DefaultClause *ast) override;
bool visit(AST::Elision *ast) override;
bool visit(AST::Finally *ast) override;
bool visit(AST::FormalParameterList *ast) override;
bool visit(AST::Program *ast) override;
bool visit(AST::StatementList *ast) override;
bool visit(AST::UiArrayMemberList *ast) override;
bool visit(AST::UiImport *ast) override;
bool visit(AST::UiHeaderItemList *ast) override;
bool visit(AST::UiPragma *ast) override;
bool visit(AST::UiObjectInitializer *ast) override;
bool visit(AST::UiObjectMemberList *ast) override;
bool visit(AST::UiParameterList *ast) override;
bool visit(AST::UiProgram *ast) override;
bool visit(AST::UiQualifiedId *ast) override;
bool visit(AST::VariableDeclarationList *ast) override;
bool visit(QQmlJS::AST::ArgumentList *ast) override;
bool visit(QQmlJS::AST::CaseBlock *ast) override;
bool visit(QQmlJS::AST::CaseClause *ast) override;
bool visit(QQmlJS::AST::CaseClauses *ast) override;
bool visit(QQmlJS::AST::Catch *ast) override;
bool visit(QQmlJS::AST::DefaultClause *ast) override;
bool visit(QQmlJS::AST::Elision *ast) override;
bool visit(QQmlJS::AST::Finally *ast) override;
bool visit(QQmlJS::AST::FormalParameterList *ast) override;
bool visit(QQmlJS::AST::Program *ast) override;
bool visit(QQmlJS::AST::StatementList *ast) override;
bool visit(QQmlJS::AST::UiArrayMemberList *ast) override;
bool visit(QQmlJS::AST::UiImport *ast) override;
bool visit(QQmlJS::AST::UiHeaderItemList *ast) override;
bool visit(QQmlJS::AST::UiPragma *ast) override;
bool visit(QQmlJS::AST::UiObjectInitializer *ast) override;
bool visit(QQmlJS::AST::UiObjectMemberList *ast) override;
bool visit(QQmlJS::AST::UiParameterList *ast) override;
bool visit(QQmlJS::AST::UiProgram *ast) override;
bool visit(QQmlJS::AST::UiQualifiedId *ast) override;
bool visit(QQmlJS::AST::VariableDeclarationList *ast) override;
bool visit(AST::PatternElement *ast) override;
bool visit(AST::PatternElementList *ast) override;
bool visit(AST::PatternProperty *ast) override;
bool visit(AST::PatternPropertyList *ast) override;
bool visit(QQmlJS::AST::PatternElement *ast) override;
bool visit(QQmlJS::AST::PatternElementList *ast) override;
bool visit(QQmlJS::AST::PatternProperty *ast) override;
bool visit(QQmlJS::AST::PatternPropertyList *ast) override;
bool visit(AST::ExportDeclaration *ast) override;
bool visit(QQmlJS::AST::ExportDeclaration *ast) override;
bool visit(QQmlJS::AST::TypeAnnotation *ast) override;
// expressions
bool visit(AST::Expression *ast) override;
bool visit(AST::ArrayPattern *ast) override;
bool visit(AST::ArrayMemberExpression *ast) override;
bool visit(AST::BinaryExpression *ast) override;
bool visit(AST::CallExpression *ast) override;
bool visit(AST::ConditionalExpression *ast) override;
bool visit(AST::DeleteExpression *ast) override;
bool visit(AST::FalseLiteral *ast) override;
bool visit(AST::SuperLiteral *ast) override;
bool visit(AST::FieldMemberExpression *ast) override;
bool visit(AST::TaggedTemplate *ast) override;
bool visit(AST::FunctionExpression *ast) override;
bool visit(AST::IdentifierExpression *ast) override;
bool visit(AST::NestedExpression *ast) override;
bool visit(AST::NewExpression *ast) override;
bool visit(AST::NewMemberExpression *ast) override;
bool visit(AST::NotExpression *ast) override;
bool visit(AST::NullExpression *ast) override;
bool visit(AST::NumericLiteral *ast) override;
bool visit(AST::ObjectPattern *ast) override;
bool visit(AST::PostDecrementExpression *ast) override;
bool visit(AST::PostIncrementExpression *ast) override;
bool visit(AST::PreDecrementExpression *ast) override;
bool visit(AST::PreIncrementExpression *ast) override;
bool visit(AST::RegExpLiteral *ast) override;
bool visit(AST::StringLiteral *ast) override;
bool visit(AST::TemplateLiteral *ast) override;
bool visit(AST::ThisExpression *ast) override;
bool visit(AST::TildeExpression *ast) override;
bool visit(AST::TrueLiteral *ast) override;
bool visit(AST::TypeOfExpression *ast) override;
bool visit(AST::UnaryMinusExpression *ast) override;
bool visit(AST::UnaryPlusExpression *ast) override;
bool visit(AST::VoidExpression *ast) override;
bool visit(AST::FunctionDeclaration *ast) override;
bool visit(AST::YieldExpression *ast) override;
bool visit(AST::ClassExpression *ast) override;
bool visit(AST::ClassDeclaration *ast) override;
bool visit(QQmlJS::AST::Expression *ast) override;
bool visit(QQmlJS::AST::ArrayPattern *ast) override;
bool visit(QQmlJS::AST::ArrayMemberExpression *ast) override;
bool visit(QQmlJS::AST::BinaryExpression *ast) override;
bool visit(QQmlJS::AST::CallExpression *ast) override;
bool visit(QQmlJS::AST::ConditionalExpression *ast) override;
bool visit(QQmlJS::AST::DeleteExpression *ast) override;
bool visit(QQmlJS::AST::FalseLiteral *ast) override;
bool visit(QQmlJS::AST::SuperLiteral *ast) override;
bool visit(QQmlJS::AST::FieldMemberExpression *ast) override;
bool visit(QQmlJS::AST::TaggedTemplate *ast) override;
bool visit(QQmlJS::AST::FunctionExpression *ast) override;
bool visit(QQmlJS::AST::IdentifierExpression *ast) override;
bool visit(QQmlJS::AST::NestedExpression *ast) override;
bool visit(QQmlJS::AST::NewExpression *ast) override;
bool visit(QQmlJS::AST::NewMemberExpression *ast) override;
bool visit(QQmlJS::AST::NotExpression *ast) override;
bool visit(QQmlJS::AST::NullExpression *ast) override;
bool visit(QQmlJS::AST::NumericLiteral *ast) override;
bool visit(QQmlJS::AST::ObjectPattern *ast) override;
bool visit(QQmlJS::AST::PostDecrementExpression *ast) override;
bool visit(QQmlJS::AST::PostIncrementExpression *ast) override;
bool visit(QQmlJS::AST::PreDecrementExpression *ast) override;
bool visit(QQmlJS::AST::PreIncrementExpression *ast) override;
bool visit(QQmlJS::AST::RegExpLiteral *ast) override;
bool visit(QQmlJS::AST::StringLiteral *ast) override;
bool visit(QQmlJS::AST::TemplateLiteral *ast) override;
bool visit(QQmlJS::AST::ThisExpression *ast) override;
bool visit(QQmlJS::AST::TildeExpression *ast) override;
bool visit(QQmlJS::AST::TrueLiteral *ast) override;
bool visit(QQmlJS::AST::TypeOfExpression *ast) override;
bool visit(QQmlJS::AST::UnaryMinusExpression *ast) override;
bool visit(QQmlJS::AST::UnaryPlusExpression *ast) override;
bool visit(QQmlJS::AST::VoidExpression *ast) override;
bool visit(QQmlJS::AST::FunctionDeclaration *ast) override;
bool visit(QQmlJS::AST::YieldExpression *ast) override;
bool visit(QQmlJS::AST::ClassExpression *ast) override;
bool visit(QQmlJS::AST::ClassDeclaration *ast) override;
// statements
bool visit(AST::Block *ast) override;
bool visit(AST::BreakStatement *ast) override;
bool visit(AST::ContinueStatement *ast) override;
bool visit(AST::DebuggerStatement *ast) override;
bool visit(AST::DoWhileStatement *ast) override;
bool visit(AST::EmptyStatement *ast) override;
bool visit(AST::ExpressionStatement *ast) override;
bool visit(AST::ForEachStatement *ast) override;
bool visit(AST::ForStatement *ast) override;
bool visit(AST::IfStatement *ast) override;
bool visit(AST::LabelledStatement *ast) override;
bool visit(AST::ReturnStatement *ast) override;
bool visit(AST::SwitchStatement *ast) override;
bool visit(AST::ThrowStatement *ast) override;
bool visit(AST::TryStatement *ast) override;
bool visit(AST::VariableStatement *ast) override;
bool visit(AST::WhileStatement *ast) override;
bool visit(AST::WithStatement *ast) override;
bool visit(QQmlJS::AST::Block *ast) override;
bool visit(QQmlJS::AST::BreakStatement *ast) override;
bool visit(QQmlJS::AST::ContinueStatement *ast) override;
bool visit(QQmlJS::AST::DebuggerStatement *ast) override;
bool visit(QQmlJS::AST::DoWhileStatement *ast) override;
bool visit(QQmlJS::AST::EmptyStatement *ast) override;
bool visit(QQmlJS::AST::ExpressionStatement *ast) override;
bool visit(QQmlJS::AST::ForEachStatement *ast) override;
bool visit(QQmlJS::AST::ForStatement *ast) override;
bool visit(QQmlJS::AST::IfStatement *ast) override;
bool visit(QQmlJS::AST::LabelledStatement *ast) override;
bool visit(QQmlJS::AST::ReturnStatement *ast) override;
bool visit(QQmlJS::AST::SwitchStatement *ast) override;
bool visit(QQmlJS::AST::ThrowStatement *ast) override;
bool visit(QQmlJS::AST::TryStatement *ast) override;
bool visit(QQmlJS::AST::VariableStatement *ast) override;
bool visit(QQmlJS::AST::WhileStatement *ast) override;
bool visit(QQmlJS::AST::WithStatement *ast) override;
// ui object members
bool visit(AST::UiArrayBinding *ast) override;
bool visit(AST::UiObjectBinding *ast) override;
bool visit(AST::UiObjectDefinition *ast) override;
bool visit(AST::UiPublicMember *ast) override;
bool visit(AST::UiScriptBinding *ast) override;
bool visit(AST::UiSourceElement *ast) override;
bool visit(QQmlJS::AST::UiArrayBinding *ast) override;
bool visit(QQmlJS::AST::UiObjectBinding *ast) override;
bool visit(QQmlJS::AST::UiObjectDefinition *ast) override;
bool visit(QQmlJS::AST::UiPublicMember *ast) override;
bool visit(QQmlJS::AST::UiScriptBinding *ast) override;
bool visit(QQmlJS::AST::UiSourceElement *ast) override;
bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r, const AST::SourceLocation &loc);
virtual void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail);
virtual void throwReferenceError(const AST::SourceLocation &loc, const QString &detail);
bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r,
const QQmlJS::AST::SourceLocation &loc);
virtual void throwSyntaxError(const QQmlJS::AST::SourceLocation &loc, const QString &detail);
virtual void throwReferenceError(const QQmlJS::AST::SourceLocation &loc, const QString &detail);
void throwRecursionDepthError() override
{
throwSyntaxError(AST::SourceLocation(),
throwSyntaxError(QQmlJS::AST::SourceLocation(),
QStringLiteral("Maximum statement or expression depth exceeded"));
}
@ -679,31 +679,33 @@ public:
ErrorType errorType() const { return _errorType; }
bool hasError() const { return _errorType != NoError; }
DiagnosticMessage error() const;
QQmlJS::DiagnosticMessage error() const;
QUrl url() const;
Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right);
Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right);
struct Arguments { int argc; int argv; bool hasSpread; };
Arguments pushArgs(AST::ArgumentList *args);
Arguments pushArgs(QQmlJS::AST::ArgumentList *args);
void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject);
Arguments pushTemplateArgs(AST::TemplateLiteral *args);
bool handleTaggedTemplate(Reference base, AST::TaggedTemplate *ast);
void createTemplateObject(AST::TemplateLiteral *t);
Arguments pushTemplateArgs(QQmlJS::AST::TemplateLiteral *args);
bool handleTaggedTemplate(Reference base, QQmlJS::AST::TaggedTemplate *ast);
void createTemplateObject(QQmlJS::AST::TemplateLiteral *t);
void setUseFastLookups(bool b) { useFastLookups = b; }
void handleTryCatch(AST::TryStatement *ast);
void handleTryFinally(AST::TryStatement *ast);
void handleTryCatch(QQmlJS::AST::TryStatement *ast);
void handleTryFinally(QQmlJS::AST::TryStatement *ast);
Reference referenceForName(const QString &name, bool lhs, const QQmlJS::AST::SourceLocation &accessLocation = QQmlJS::AST::SourceLocation());
Reference referenceForName(
const QString &name, bool lhs,
const QQmlJS::AST::SourceLocation &accessLocation = QQmlJS::AST::SourceLocation());
QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData = true);
static QV4::CompiledData::CompilationUnit compileModule(
bool debugMode, const QString &url, const QString &sourceCode,
const QDateTime &sourceTimeStamp, QList<DiagnosticMessage> *diagnostics);
const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics);
Context *currentContext() const { return _context; }
BytecodeGenerator *generator() const { return bytecodeGenerator; }
@ -762,7 +764,7 @@ protected:
int _returnAddress;
Context *_context;
Context *_functionContext = nullptr;
AST::LabelledStatement *_labelledStatement;
QQmlJS::AST::LabelledStatement *_labelledStatement;
QV4::Compiler::JSUnitGenerator *jsUnitGenerator;
BytecodeGenerator *bytecodeGenerator = nullptr;
Moth::BytecodeGenerator::Label *_returnLabel = nullptr;
@ -806,9 +808,10 @@ protected:
};
private:
VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast);
void handleConstruct(const Reference &base, AST::ArgumentList *args);
void throwError(ErrorType errorType, const AST::SourceLocation &loc, const QString &detail);
VolatileMemoryLocations scanVolatileMemoryLocations(QQmlJS::AST::Node *ast);
void handleConstruct(const Reference &base, QQmlJS::AST::ArgumentList *args);
void throwError(ErrorType errorType, const QQmlJS::AST::SourceLocation &loc,
const QString &detail);
};
}

View File

@ -38,13 +38,14 @@
****************************************************************************/
#include <qv4compiler_p.h>
#include <qv4compileddata_p.h>
#include <qv4codegen_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qv4staticvalue_p.h>
#include <private/qv4alloca_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsast_p.h>
#include <private/qml_compile_hash_p.h>
#include <private/qqmlirbuilder_p.h>
#include <QCryptographicHash>
// Efficient implementation that takes advantage of powers of two.
@ -268,8 +269,11 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
registerString(module->finalUrl);
for (Context *f : qAsConst(module->functions)) {
registerString(f->name);
for (int i = 0; i < f->arguments.size(); ++i)
registerString(f->arguments.at(i));
registerString(f->returnType);
for (int i = 0; i < f->arguments.size(); ++i) {
registerString(f->arguments.at(i).id);
registerString(f->arguments.at(i).typeName());
}
for (int i = 0; i < f->locals.size(); ++i)
registerString(f->locals.at(i));
}
@ -436,7 +440,9 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
function->length = irFunction->formals ? irFunction->formals->length() : 0;
function->nFormals = irFunction->arguments.size();
function->formalsOffset = currentOffset;
currentOffset += function->nFormals * sizeof(quint32);
currentOffset += function->nFormals * sizeof(CompiledData::Parameter);
QmlIR::Parameter::initType(&function->returnType, this, getStringId(irFunction->returnType));
function->sizeOfLocalTemporalDeadZone = irFunction->sizeOfLocalTemporalDeadZone;
function->sizeOfRegisterTemporalDeadZone = irFunction->sizeOfRegisterTemporalDeadZone;
@ -465,9 +471,11 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
function->codeSize = irFunction->code.size();
// write formals
quint32_le *formals = (quint32_le *)(f + function->formalsOffset);
for (int i = 0; i < irFunction->arguments.size(); ++i)
formals[i] = getStringId(irFunction->arguments.at(i));
CompiledData::Parameter *formals = (CompiledData::Parameter *)(f + function->formalsOffset);
for (int i = 0; i < irFunction->arguments.size(); ++i) {
QmlIR::Parameter::init(&formals[i], this, getStringId(irFunction->arguments.at(i).id),
getStringId(irFunction->arguments.at(i).typeName()));
}
// write locals
quint32_le *locals = (quint32_le *)(f + function->localsOffset);

View File

@ -53,9 +53,10 @@
#include <QtCore/qstring.h>
#include <QtCore/qhash.h>
#include <QtCore/qstringlist.h>
#include <private/qv4global_p.h>
#include <private/qv4compilerglobal_p.h>
#include <private/qqmljsastfwd_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qv4staticvalue_p.h>
QT_BEGIN_NAMESPACE
@ -72,10 +73,12 @@ struct JSClassMember;
namespace Compiler {
struct Context;
struct Module;
struct Class;
struct TemplateObject;
struct Q_QML_PRIVATE_EXPORT StringTableGenerator {
struct Q_QMLCOMPILER_PRIVATE_EXPORT StringTableGenerator {
StringTableGenerator();
int registerString(const QString &str);
@ -102,7 +105,7 @@ private:
bool frozen = false;
};
struct Q_QML_PRIVATE_EXPORT JSUnitGenerator {
struct Q_QMLCOMPILER_PRIVATE_EXPORT JSUnitGenerator {
static void generateUnitChecksum(CompiledData::Unit *unit);
struct MemberInfo {

View File

@ -50,7 +50,6 @@
// We mean it.
//
#include "private/qv4global_p.h"
#include <private/qqmljsast_p.h>
#include <private/qv4compileddata_p.h>
#include <QtCore/QStringList>
@ -62,8 +61,13 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
namespace Moth {
class BytecodeGenerator;
}
namespace Compiler {
class Codegen;
struct ControlFlow;
enum class ContextType {
@ -189,7 +193,8 @@ struct Context {
MemberMap members;
QSet<QString> usedVariables;
QQmlJS::AST::FormalParameterList *formals = nullptr;
QStringList arguments;
QQmlJS::AST::BoundNames arguments;
QString returnType;
QStringList locals;
QStringList moduleRequests;
QVector<ImportEntry> importEntries;
@ -288,7 +293,7 @@ struct Context {
{
// search backwards to handle duplicate argument names correctly
for (int i = arguments.size() - 1; i >= 0; --i) {
if (arguments.at(i) == name)
if (arguments.at(i).id == name)
return i;
}
return -1;

View File

@ -50,7 +50,6 @@
// We mean it.
//
#include <private/qv4global_p.h>
#include <private/qv4codegen_p.h>
#include <private/qqmljsast_p.h>
#include <private/qv4bytecodegenerator_p.h>
@ -279,7 +278,7 @@ struct ControlFlowWith : public ControlFlowUnwind
struct ControlFlowBlock : public ControlFlowUnwind
{
ControlFlowBlock(Codegen *cg, AST::Node *ast)
ControlFlowBlock(Codegen *cg, QQmlJS::AST::Node *ast)
: ControlFlowUnwind(cg, Block)
{
block = cg->enterBlock(ast);
@ -314,11 +313,11 @@ struct ControlFlowBlock : public ControlFlowUnwind
struct ControlFlowCatch : public ControlFlowUnwind
{
AST::Catch *catchExpression;
QQmlJS::AST::Catch *catchExpression;
bool insideCatch = false;
BytecodeGenerator::ExceptionHandler exceptionLabel;
ControlFlowCatch(Codegen *cg, AST::Catch *catchExpression)
ControlFlowCatch(Codegen *cg, QQmlJS::AST::Catch *catchExpression)
: ControlFlowUnwind(cg, Catch), catchExpression(catchExpression),
exceptionLabel(generator()->newExceptionHandler())
{
@ -372,10 +371,10 @@ struct ControlFlowCatch : public ControlFlowUnwind
struct ControlFlowFinally : public ControlFlowUnwind
{
AST::Finally *finally;
QQmlJS::AST::Finally *finally;
bool insideFinally = false;
ControlFlowFinally(Codegen *cg, AST::Finally *finally)
ControlFlowFinally(Codegen *cg, QQmlJS::AST::Finally *finally)
: ControlFlowUnwind(cg, Finally), finally(finally)
{
Q_ASSERT(finally != nullptr);

View File

@ -0,0 +1,74 @@
/****************************************************************************
**
** 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 QV4COMPILERGLOBAL_H
#define QV4COMPILERGLOBAL_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/qglobal.h>
#include <QString>
#include <private/qtqmlcompilerglobal_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
enum class ObjectLiteralArgument {
Value,
Method,
Getter,
Setter
};
} // namespace QV4
QT_END_NAMESPACE
#endif // QV4COMPILERGLOBAL_H

View File

@ -52,6 +52,7 @@
QT_USE_NAMESPACE
using namespace QV4;
using namespace QV4::Compiler;
using namespace QQmlJS;
using namespace QQmlJS::AST;
static CompiledData::Location location(const QQmlJS::AST::SourceLocation &astLocation)
@ -202,16 +203,16 @@ bool ScanFunctions::visit(ExportDeclaration *declaration)
_context->exportEntries << entry;
}
} else if (auto *vstmt = AST::cast<AST::VariableStatement*>(declaration->variableStatementOrDeclaration)) {
QStringList boundNames;
BoundNames boundNames;
for (VariableDeclarationList *it = vstmt->declarations; it; it = it->next) {
if (!it->declaration)
continue;
it->declaration->boundNames(&boundNames);
}
for (const QString &name: boundNames) {
for (const auto &name: boundNames) {
Compiler::ExportEntry entry;
entry.localName = name;
entry.exportName = name;
entry.localName = name.id;
entry.exportName = name.id;
entry.location = location(vstmt->firstSourceLocation());
_context->exportEntries << entry;
}
@ -326,26 +327,26 @@ bool ScanFunctions::visit(PatternElement *ast)
if (!ast->isVariableDeclaration())
return true;
QStringList names;
BoundNames names;
ast->boundNames(&names);
QQmlJS::AST::SourceLocation lastInitializerLocation = ast->lastSourceLocation();
if (_context->lastBlockInitializerLocation.isValid())
lastInitializerLocation = _context->lastBlockInitializerLocation;
for (const QString &name : qAsConst(names)) {
if (_context->isStrict && (name == QLatin1String("eval") || name == QLatin1String("arguments")))
for (const auto &name : qAsConst(names)) {
if (_context->isStrict && (name.id == QLatin1String("eval") || name.id == QLatin1String("arguments")))
_cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Variable name may not be eval or arguments in strict mode"));
checkName(QStringRef(&name), ast->identifierToken);
if (name == QLatin1String("arguments"))
checkName(QStringRef(&name.id), ast->identifierToken);
if (name.id == QLatin1String("arguments"))
_context->usesArgumentsObject = Context::ArgumentsObjectNotUsed;
if (ast->scope == VariableScope::Const && !ast->initializer && !ast->isForDeclaration && !ast->destructuringPattern()) {
_cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Missing initializer in const declaration"));
return false;
}
if (!_context->addLocalVar(name, ast->initializer ? Context::VariableDefinition : Context::VariableDeclaration, ast->scope,
if (!_context->addLocalVar(name.id, ast->initializer ? Context::VariableDefinition : Context::VariableDeclaration, ast->scope,
/*function*/nullptr, lastInitializerLocation)) {
_cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Identifier %1 has already been declared").arg(name));
_cg->throwSyntaxError(ast->identifierToken, QStringLiteral("Identifier %1 has already been declared").arg(name.id));
return false;
}
}
@ -679,6 +680,9 @@ bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete
_context->isArrowFunction = true;
else if (expr->isGenerator)
_context->isGenerator = true;
if (expr->typeAnnotation)
_context->returnType = expr->typeAnnotation->type->toString();
}
@ -691,11 +695,11 @@ bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete
bool isSimpleParameterList = formals && formals->isSimpleParameterList();
_context->arguments = formals ? formals->formals() : QStringList();
_context->arguments = formals ? formals->formals() : BoundNames();
const QStringList boundNames = formals ? formals->boundNames() : QStringList();
const BoundNames boundNames = formals ? formals->boundNames() : BoundNames();
for (int i = 0; i < boundNames.size(); ++i) {
const QString &arg = boundNames.at(i);
const QString &arg = boundNames.at(i).id;
if (_context->isStrict || !isSimpleParameterList) {
bool duplicate = (boundNames.indexOf(arg, i + 1) != -1);
if (duplicate) {
@ -712,6 +716,7 @@ bool ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParamete
if (!_context->arguments.contains(arg))
_context->addLocalVar(arg, Context::VariableDefinition, VariableScope::Var);
}
return true;
}

View File

@ -50,7 +50,7 @@
// We mean it.
//
#include "private/qv4global_p.h"
#include <private/qtqmlcompilerglobal_p.h>
#include <private/qqmljsastvisitor_p.h>
#include <private/qqmljsast_p.h>
#include <private/qqmljsengine_p.h>
@ -62,8 +62,6 @@
QT_BEGIN_NAMESPACE
using namespace QQmlJS;
namespace QV4 {
namespace Moth {
@ -83,84 +81,87 @@ class ScanFunctions: protected QQmlJS::AST::Visitor
typedef QScopedValueRollback<bool> TemporaryBoolAssignment;
public:
ScanFunctions(Codegen *cg, const QString &sourceCode, ContextType defaultProgramType);
void operator()(AST::Node *node);
void operator()(QQmlJS::AST::Node *node);
void enterGlobalEnvironment(ContextType compilationMode);
void enterEnvironment(AST::Node *node, ContextType compilationMode, const QString &name);
void enterEnvironment(QQmlJS::AST::Node *node, ContextType compilationMode,
const QString &name);
void leaveEnvironment();
void enterQmlFunction(AST::FunctionDeclaration *ast)
void enterQmlFunction(QQmlJS::AST::FunctionDeclaration *ast)
{ enterFunction(ast, false); }
protected:
using Visitor::visit;
using Visitor::endVisit;
void checkDirectivePrologue(AST::StatementList *ast);
void checkDirectivePrologue(QQmlJS::AST::StatementList *ast);
void checkName(const QStringRef &name, const AST::SourceLocation &loc);
void checkName(const QStringRef &name, const QQmlJS::AST::SourceLocation &loc);
bool visit(AST::Program *ast) override;
void endVisit(AST::Program *) override;
bool visit(QQmlJS::AST::Program *ast) override;
void endVisit(QQmlJS::AST::Program *) override;
bool visit(AST::ESModule *ast) override;
void endVisit(AST::ESModule *) override;
bool visit(QQmlJS::AST::ESModule *ast) override;
void endVisit(QQmlJS::AST::ESModule *) override;
bool visit(AST::ExportDeclaration *declaration) override;
bool visit(AST::ImportDeclaration *declaration) override;
bool visit(QQmlJS::AST::ExportDeclaration *declaration) override;
bool visit(QQmlJS::AST::ImportDeclaration *declaration) override;
bool visit(AST::CallExpression *ast) override;
bool visit(AST::PatternElement *ast) override;
bool visit(AST::IdentifierExpression *ast) override;
bool visit(AST::ExpressionStatement *ast) override;
bool visit(AST::FunctionExpression *ast) override;
bool visit(AST::TemplateLiteral *ast) override;
bool visit(AST::SuperLiteral *) override;
bool visit(AST::FieldMemberExpression *) override;
bool visit(AST::ArrayPattern *) override;
bool visit(QQmlJS::AST::CallExpression *ast) override;
bool visit(QQmlJS::AST::PatternElement *ast) override;
bool visit(QQmlJS::AST::IdentifierExpression *ast) override;
bool visit(QQmlJS::AST::ExpressionStatement *ast) override;
bool visit(QQmlJS::AST::FunctionExpression *ast) override;
bool visit(QQmlJS::AST::TemplateLiteral *ast) override;
bool visit(QQmlJS::AST::SuperLiteral *) override;
bool visit(QQmlJS::AST::FieldMemberExpression *) override;
bool visit(QQmlJS::AST::ArrayPattern *) override;
bool enterFunction(AST::FunctionExpression *ast, bool enterName);
bool enterFunction(QQmlJS::AST::FunctionExpression *ast, bool enterName);
void endVisit(AST::FunctionExpression *) override;
void endVisit(QQmlJS::AST::FunctionExpression *) override;
bool visit(AST::ObjectPattern *ast) override;
bool visit(QQmlJS::AST::ObjectPattern *ast) override;
bool visit(AST::PatternProperty *ast) override;
void endVisit(AST::PatternProperty *) override;
bool visit(QQmlJS::AST::PatternProperty *ast) override;
void endVisit(QQmlJS::AST::PatternProperty *) override;
bool visit(AST::FunctionDeclaration *ast) override;
void endVisit(AST::FunctionDeclaration *) override;
bool visit(QQmlJS::AST::FunctionDeclaration *ast) override;
void endVisit(QQmlJS::AST::FunctionDeclaration *) override;
bool visit(AST::ClassExpression *ast) override;
void endVisit(AST::ClassExpression *) override;
bool visit(QQmlJS::AST::ClassExpression *ast) override;
void endVisit(QQmlJS::AST::ClassExpression *) override;
bool visit(AST::ClassDeclaration *ast) override;
void endVisit(AST::ClassDeclaration *) override;
bool visit(QQmlJS::AST::ClassDeclaration *ast) override;
void endVisit(QQmlJS::AST::ClassDeclaration *) override;
bool visit(AST::DoWhileStatement *ast) override;
bool visit(AST::ForStatement *ast) override;
void endVisit(AST::ForStatement *) override;
bool visit(AST::ForEachStatement *ast) override;
void endVisit(AST::ForEachStatement *) override;
bool visit(QQmlJS::AST::DoWhileStatement *ast) override;
bool visit(QQmlJS::AST::ForStatement *ast) override;
void endVisit(QQmlJS::AST::ForStatement *) override;
bool visit(QQmlJS::AST::ForEachStatement *ast) override;
void endVisit(QQmlJS::AST::ForEachStatement *) override;
bool visit(AST::ThisExpression *ast) override;
bool visit(QQmlJS::AST::ThisExpression *ast) override;
bool visit(AST::Block *ast) override;
void endVisit(AST::Block *ast) override;
bool visit(QQmlJS::AST::Block *ast) override;
void endVisit(QQmlJS::AST::Block *ast) override;
bool visit(AST::CaseBlock *ast) override;
void endVisit(AST::CaseBlock *ast) override;
bool visit(QQmlJS::AST::CaseBlock *ast) override;
void endVisit(QQmlJS::AST::CaseBlock *ast) override;
bool visit(AST::Catch *ast) override;
void endVisit(AST::Catch *ast) override;
bool visit(QQmlJS::AST::Catch *ast) override;
void endVisit(QQmlJS::AST::Catch *ast) override;
bool visit(AST::WithStatement *ast) override;
void endVisit(AST::WithStatement *ast) override;
bool visit(QQmlJS::AST::WithStatement *ast) override;
void endVisit(QQmlJS::AST::WithStatement *ast) override;
void throwRecursionDepthError() override;
protected:
bool enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::StatementList *body, bool enterName);
bool enterFunction(QQmlJS::AST::Node *ast, const QString &name,
QQmlJS::AST::FormalParameterList *formals,
QQmlJS::AST::StatementList *body, bool enterName);
void calcEscapingVariables();
// fields:
@ -173,7 +174,7 @@ protected:
ContextType defaultProgramType;
private:
static constexpr AST::Node *astNodeForGlobalEnvironment = nullptr;
static constexpr QQmlJS::AST::Node *astNodeForGlobalEnvironment = nullptr;
};
}

View File

@ -50,7 +50,7 @@
//
// We mean it.
//
#include <private/qv4global_p.h>
#include <private/qv4staticvalue_p.h>
#include <private/qv4compileddata_p.h> // for CompiledData::CodeOffsetToLine used by the dumper
#include <qendian.h>

View File

@ -178,6 +178,13 @@
"section": "QML",
"condition": "features.thread",
"output": [ "privateFeature" ]
},
"qml-itemmodel": {
"label": "QML Item Model",
"purpose": "Provides the item model for item views in QML",
"section": "QML",
"condition": "features.itemmodel",
"output": [ "privateFeature" ]
}
},

View File

@ -1,4 +1,5 @@
include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
include($QT_INSTALL_DOCS/config/exampleurl-qtdeclarative.qdocconf)
project = QtQml
description = Qt QML Reference Documentation

View File

@ -59,8 +59,8 @@ Rectangle {
//! [signal declaration]
signal trigger
signal send (string notice)
signal perform (string task, variant object)
signal send(notice: string)
signal perform(task: string, object: variant)
//! [signal declaration]
//! [signal handler declaration]
@ -88,7 +88,7 @@ Rectangle {
Rectangle {
id: messenger
signal send( string person, string notice)
signal send(person: string, notice: string)
onSend: {
console.log("For " + person + ", the notice is: " + notice)
@ -102,7 +102,7 @@ Rectangle {
Rectangle {
id: relay
signal send( string person, string notice)
signal send(person: string, notice: string)
onSend: console.log("Send signal to: " + person + ", " + notice)
Component.onCompleted: {

View File

@ -52,7 +52,7 @@
import QtQuick 2.0
Item {
function myQmlFunction(msg) {
function myQmlFunction(msg: string) : string {
console.log("Got message:", msg)
return "some return value"
}

View File

@ -60,13 +60,13 @@ QQmlEngine engine;
QQmlComponent component(&engine, "MyItem.qml");
QObject *object = component.create();
QVariant returnedValue;
QVariant msg = "Hello from C++";
QString returnedValue;
QString msg = "Hello from C++";
QMetaObject::invokeMethod(object, "myQmlFunction",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, msg));
Q_RETURN_ARG(QString, returnedValue),
Q_ARG(QString, msg));
qDebug() << "QML function returned:" << returnedValue.toString();
qDebug() << "QML function returned:" << returnedValue;
delete object;
//![0]
}

View File

@ -55,7 +55,7 @@ Item {
id: item
width: 100; height: 100
signal qmlSignal(string msg)
signal qmlSignal(msg: string)
MouseArea {
anchors.fill: parent

View File

@ -70,7 +70,7 @@ Rectangle {
}
}
// define the signal the SignalTransition is connected with
signal mysignal(string mystr)
signal mysignal(mystr: string)
// on clicking the button emit the signal with a single string argument
onClicked: button.mysignal("test")
}

View File

@ -166,9 +166,12 @@ updated, and any \c onButtonTextChanged handlers would not be called.
\section2 Invoking QML Methods
All QML methods are exposed to the meta-object system and can be called from C++
using QMetaObject::invokeMethod(). Method parameters and return values passed
from QML are always translated into QVariant values in C++.
All QML methods are exposed to the meta-object system and can be called from
C++ using QMetaObject::invokeMethod(). You can specify types for the parameters
and the return value after the colon character, as shown in the code snippet
below. This can be useful, for example, when you want to connect a signal in
C++ with a certain signature to a QML-defined method. If you omit the types,
the C++ signature will use QVariant.
Here is a C++ application that calls a QML method using
QMetaObject::invokeMethod():
@ -182,9 +185,12 @@ QMetaObject::invokeMethod():
\li \snippet qml/qtbinding/functions-qml/main.cpp 0
\endtable
Notice the Q_RETURN_ARG() and Q_ARG() arguments for QMetaObject::invokeMethod()
must be specified as QVariant types, as this is the generic data type used for
QML method parameters and return values.
Notice the parameter and return type specified after the colon. You can use \l
{QML Basic Types}{basic types} and \l {QML Object Types}{object types} as type
names.
If the type is omitted in QML, then you must specify QVariant as type with
Q_RETURN_ARG() and Q_ARG() when calling QMetaObject::invokeMethod.
\section2 Connecting to QML Signals
@ -210,9 +216,8 @@ QObject::connect(), so that the \c cppSlot() method is called whenever the
\snippet qml/qtbinding/signals-qml/main.cpp 0
\endtable
When a QML object type is used as a signal parameter, the parameter should
use \l var as the type, and the value should be received in C++ using the
QVariant type:
A QML object type in a signal parameter is translated to a pointer to the class
in C++:
\table
\row
@ -226,7 +231,7 @@ QVariant type:
id: item
width: 100; height: 100
signal qmlSignal(var anObject)
signal qmlSignal(anObject: Item)
MouseArea {
anchors.fill: parent
@ -241,18 +246,16 @@ QVariant type:
{
Q_OBJECT
public slots:
void cppSlot(const QVariant &v) {
qDebug() << "Called the C++ slot with value:" << v;
void cppSlot(QQuickItem *item) {
qDebug() << "Called the C++ slot with item:" << item;
QQuickItem *item =
qobject_cast<QQuickItem*>(v.value<QObject*>());
qDebug() << "Item dimensions:" << item->width()
<< item->height();
}
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGuiApplication app(argc, argv);
QQuickView view(QUrl::fromLocalFile("MyItem.qml"));
QObject *item = view.rootObject();

View File

@ -38,13 +38,14 @@
****************************************************************************/
#include <qv4argumentsobject_p.h>
#include <qv4arrayobject_p.h>
#include <qv4alloca_p.h>
#include <qv4scopedvalue_p.h>
#include <qv4string_p.h>
#include <qv4function_p.h>
#include <qv4jscall_p.h>
#include <qv4symbol_p.h>
#include <private/qv4alloca_p.h>
using namespace QV4;
DEFINE_OBJECT_VTABLE(ArgumentsObject);

View File

@ -39,7 +39,7 @@
#include "qv4compilationunitmapper_p.h"
#include "qv4compileddata_p.h"
#include <private/qv4compileddata_p.h>
#include <QFileInfo>
#include <QDateTime>
#include <QCoreApplication>

View File

@ -52,8 +52,6 @@
#include <time.h>
#include <private/qqmljsengine_p.h>
#include <wtf/MathExtras.h>
#if defined(Q_OS_LINUX) && QT_CONFIG(timezone)

View File

@ -52,6 +52,7 @@
//
#include "qv4global_p.h"
#include <private/qv4staticvalue_p.h>
#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE

View File

@ -39,8 +39,6 @@
#include <qv4engine_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compilercontext_p.h>
#include <private/qv4codegen_p.h>
#include <private/qqmljsdiagnosticmessage_p.h>

View File

@ -57,7 +57,6 @@
#include <private/qintrusivelist_p.h>
#include "qv4enginebase_p.h"
#include <private/qqmlrefcount_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qqmldelayedcallqueue_p.h>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmutex.h>

View File

@ -47,7 +47,7 @@
#include "qv4string_p.h"
#include <private/qv4mm_p.h>
#include <qv4codegen_p.h>
#include <private/qv4codegen_p.h>
#ifndef Q_OS_WIN
# include <time.h>

View File

@ -44,11 +44,11 @@
#include <private/qv4lookup_p.h>
#include <private/qv4qmlcontext_p.h>
#include <private/qv4identifiertable_p.h>
#include <private/qv4instr_moth_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qqmlengine_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
#include <private/qqmlscriptdata_p.h>
#include <private/qv4module_p.h>
#include <private/qv4compilationunitmapper_p.h>
#include <private/qml_compile_hash_p.h>
@ -784,7 +784,7 @@ QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Bind
case Binding::Type_Boolean:
return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
case Binding::Type_Number:
return QString::number(bindingValueAsNumber(binding));
return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
case Binding::Type_Invalid:
return QString();
#if !QT_CONFIG(translation)

View File

@ -61,9 +61,13 @@
QT_BEGIN_NAMESPACE
class QQmlScriptData;
class QQmlEnginePrivate;
namespace QV4 {
// index is per-object binding index
typedef QVector<QQmlPropertyData*> BindingPropertyData;
class CompilationUnitMapper;
struct ResolvedTypeReference;
// map from name index
@ -131,7 +135,7 @@ public:
// index is object index. This allows fast access to the
// property data when initializing bindings, avoiding expensive
// lookups by string (property name).
QVector<CompiledData::BindingPropertyData> bindingPropertyDataPerObject;
QVector<BindingPropertyData> bindingPropertyDataPerObject;
// mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects
// this is initialized on-demand by QQmlContextData

View File

@ -100,9 +100,9 @@ Function::Function(ExecutionEngine *engine, ExecutableCompilationUnit *unit,
for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[localsIndices[i]]), Attr_NotConfigurable);
const quint32_le *formalsIndices = compiledFunction->formalsTable();
const CompiledData::Parameter *formalsIndices = compiledFunction->formalsTable();
for (quint32 i = 0; i < compiledFunction->nFormals; ++i)
ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[formalsIndices[i]]), Attr_NotConfigurable);
ic = ic->addMember(engine->identifierTable->asPropertyKey(compilationUnit->runtimeStrings[formalsIndices[i].nameIndex]), Attr_NotConfigurable);
internalClass = ic->d();
nFormals = compiledFunction->nFormals;

View File

@ -53,6 +53,7 @@
#include "qv4global_p.h"
#include <private/qv4executablecompilationunit_p.h>
#include <private/qv4context_p.h>
#include <private/qv4string_p.h>
namespace JSC {
class MacroAssemblerCodeRef;
@ -93,7 +94,7 @@ public:
return static_cast<QV4::ExecutableCompilationUnit *>(compilationUnit);
}
QV4::Heap::String *runtimeString(uint i)
QV4::Heap::String *runtimeString(uint i) const
{
return compilationUnit->runtimeStrings[i];
}
@ -120,7 +121,7 @@ public:
void updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> &parameters);
inline Heap::String *name() const {
return compilationUnit->runtimeStrings[compiledFunction->nameIndex];
return runtimeString(compiledFunction->nameIndex);
}
static QString prettyName(const Function *function, const void *address);

View File

@ -59,10 +59,10 @@
#include "private/qqmlbuiltinfunctions_p.h"
#include <private/qv4jscall_p.h>
#include <private/qv4vme_moth_p.h>
#include <private/qv4alloca_p.h>
#include <QtCore/QDebug>
#include <algorithm>
#include "qv4alloca_p.h"
#include "qv4profiling_p.h"
using namespace QV4;

View File

@ -52,6 +52,7 @@
//
#include <QtCore/qglobal.h>
#include <private/qv4compilerglobal_p.h>
#include <QString>
#ifdef QT_NO_DEBUG
@ -207,11 +208,6 @@ struct SetMapObject;
struct PromiseObject;
struct PromiseCapability;
// ReturnedValue is used to return values from runtime methods
// the type has to be a primitive type (no struct or union), so that the compiler
// will return it in a register on all platforms.
// It will be returned in rax on x64, [eax,edx] on x86 and [r0,r1] on arm
typedef quint64 ReturnedValue;
struct CallData;
struct Scope;
struct ScopedValue;
@ -341,13 +337,6 @@ struct Q_QML_EXPORT StackFrame {
};
typedef QVector<StackFrame> StackTrace;
enum class ObjectLiteralArgument {
Value,
Method,
Getter,
Setter
};
namespace JIT {
enum class CallResultDestination {

View File

@ -49,18 +49,14 @@
#include "qv4string_p.h"
#include "qv4jscall_p.h"
#include <private/qqmljsengine_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
#include <qv4codegen_p.h>
#include <private/qv4codegen_p.h>
#include <private/qv4alloca_p.h>
#include "private/qlocale_tools_p.h"
#include "private/qtools_p.h"
#include <QtCore/QDebug>
#include <QtCore/QString>
#include <iostream>
#include "qv4alloca_p.h"
#include <wtf/MathExtras.h>

View File

@ -167,7 +167,6 @@ void QV4Include::finished()
QByteArray data = m_reply->readAll();
QString code = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(code);
QV4::Scoped<QV4::QmlContext> qml(scope, m_qmlContext.value());
QV4::Script script(v4, qml, /*parse as QML binding*/false, code, m_url.toString());

View File

@ -52,7 +52,7 @@
#include <qglobal.h>
#include <QtQml/private/qv4staticvalue_p.h>
#include <private/qv4staticvalue_p.h>
#include <QtCore/qnumeric.h>
#include <QtCore/private/qnumeric_p.h>
#include <cmath>

View File

@ -57,6 +57,7 @@
#include <private/qv4variantobject_p.h>
#include <private/qv4identifiertable_p.h>
#include <private/qv4lookup_p.h>
#include <private/qv4qmlcontext_p.h>
#if QT_CONFIG(qml_sequence_object)
#include <private/qv4sequenceobject_p.h>
@ -80,7 +81,9 @@
#include <QtCore/qtimer.h>
#include <QtCore/qatomic.h>
#include <QtCore/qmetaobject.h>
#if QT_CONFIG(qml_itemmodel)
#include <QtCore/qabstractitemmodel.h>
#endif
#include <QtCore/qloggingcategory.h>
#include <vector>
@ -1233,7 +1236,9 @@ private:
std::vector<bool> *stdVectorBoolPtr;
std::vector<QString> *stdVectorQStringPtr;
std::vector<QUrl> *stdVectorQUrlPtr;
#if QT_CONFIG(qml_itemmodel)
std::vector<QModelIndex> *stdVectorQModelIndexPtr;
#endif
char allocData[MaxSizeOf7<QVariant,
QString,
@ -1693,8 +1698,10 @@ void *CallArgument::dataPtr()
return stdVectorQStringPtr;
else if (type == qMetaTypeId<std::vector<QUrl>>())
return stdVectorQUrlPtr;
#if QT_CONFIG(qml_itemmodel)
else if (type == qMetaTypeId<std::vector<QModelIndex>>())
return stdVectorQModelIndexPtr;
#endif
else if (type != 0)
return (void *)&allocData;
return nullptr;
@ -1845,7 +1852,10 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
|| callType == qMetaTypeId<std::vector<bool>>()
|| callType == qMetaTypeId<std::vector<QString>>()
|| callType == qMetaTypeId<std::vector<QUrl>>()
|| callType == qMetaTypeId<std::vector<QModelIndex>>()) {
#if QT_CONFIG(qml_itemmodel)
|| callType == qMetaTypeId<std::vector<QModelIndex>>()
#endif
) {
queryEngine = true;
const QV4::Object* object = value.as<QV4::Object>();
if (callType == qMetaTypeId<std::vector<int>>()) {
@ -1863,9 +1873,11 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
} else if (callType == qMetaTypeId<std::vector<QUrl>>()) {
stdVectorQUrlPtr = nullptr;
fromContainerValue<std::vector<QUrl>>(object, callType, &CallArgument::stdVectorQUrlPtr, queryEngine);
#if QT_CONFIG(qml_itemmodel)
} else if (callType == qMetaTypeId<std::vector<QModelIndex>>()) {
stdVectorQModelIndexPtr = nullptr;
fromContainerValue<std::vector<QModelIndex>>(object, callType, &CallArgument::stdVectorQModelIndexPtr, queryEngine);
#endif
}
#endif
} else if (QMetaType::typeFlags(callType)

View File

@ -56,7 +56,7 @@
#include <cassert>
#include <typeinfo>
#include <iostream>
#include "qv4alloca_p.h"
#include <private/qv4alloca_p.h>
QT_BEGIN_NAMESPACE

View File

@ -59,6 +59,7 @@
#include <private/qqmltypewrapper_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <private/qqmljsast_p.h>
#include "qv4qobjectwrapper_p.h"
#include "qv4symbol_p.h"
#include "qv4generatorobject_p.h"

View File

@ -51,6 +51,7 @@
//
#include <private/qv4global_p.h>
#include <private/qv4staticvalue_p.h>
QT_BEGIN_NAMESPACE

View File

@ -39,9 +39,10 @@
#include "qv4engine_p.h"
#include "qv4runtimecodegen_p.h"
#include "qv4compilerscanfunctions_p.h"
#include <private/qv4compilerscanfunctions_p.h>
using namespace QV4;
using namespace QQmlJS;
void RuntimeCodegen::generateFromFunctionExpression(const QString &fileName,
const QString &sourceCode,

View File

@ -66,11 +66,11 @@ public:
void generateFromFunctionExpression(const QString &fileName,
const QString &sourceCode,
AST::FunctionExpression *ast,
QQmlJS::AST::FunctionExpression *ast,
Compiler::Module *module);
void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail) override;
void throwReferenceError(const AST::SourceLocation &loc, const QString &detail) override;
void throwSyntaxError(const QQmlJS::AST::SourceLocation &loc, const QString &detail) override;
void throwReferenceError(const QQmlJS::AST::SourceLocation &loc, const QString &detail) override;
private:
ExecutionEngine *engine;

View File

@ -60,6 +60,7 @@
#include <QScopedValueRollback>
using namespace QV4;
using namespace QQmlJS;
Script::Script(ExecutionEngine *v4, QmlContext *qml, const QQmlRefPointer<ExecutableCompilationUnit> &compilationUnit)
: line(1), column(0), context(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
@ -245,7 +246,6 @@ Script *Script::createFromFileOrCache(ExecutionEngine *engine, QmlContext *qmlCo
QByteArray data = f.readAll();
QString sourceCode = QString::fromUtf8(data);
QmlIR::Document::removeScriptPragmas(sourceCode);
auto result = new QV4::Script(engine, qmlContext, /*parseAsBinding*/false, sourceCode, originalUrl.toString());
result->contextType = QV4::Compiler::ContextType::ScriptImportedByQML;

View File

@ -49,8 +49,10 @@
#include "qv4runtime_p.h"
#include "qv4objectiterator_p.h"
#include <private/qqmlvaluetypewrapper_p.h>
#if QT_CONFIG(qml_itemmodel)
#include <private/qqmlmodelindexvaluetype_p.h>
#include <QtCore/qabstractitemmodel.h>
#endif
#include <algorithm>
@ -75,6 +77,16 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
}
// F(elementType, elementTypeName, sequenceType, defaultValue)
#if QT_CONFIG(qml_itemmodel)
#define FOREACH_QML_SEQUENCE_TYPE_FOR_ITEMMODEL(F) \
F(QModelIndex, QModelIndex, QModelIndexList, QModelIndex()) \
F(QModelIndex, QModelIndexVector, QVector<QModelIndex>, QModelIndex()) \
F(QModelIndex, QModelIndexStdVector, std::vector<QModelIndex>, QModelIndex()) \
F(QItemSelectionRange, QItemSelectionRange, QItemSelection, QItemSelectionRange())
#else
#define FOREACH_QML_SEQUENCE_TYPE_FOR_ITEMMODEL(F)
#endif
#define FOREACH_QML_SEQUENCE_TYPE(F) \
F(int, IntVector, QVector<int>, 0) \
F(qreal, RealVector, QVector<qreal>, 0.0) \
@ -92,10 +104,7 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
F(QUrl, Url, QList<QUrl>, QUrl()) \
F(QUrl, UrlVector, QVector<QUrl>, QUrl()) \
F(QUrl, UrlStdVector, std::vector<QUrl>, QUrl()) \
F(QModelIndex, QModelIndex, QModelIndexList, QModelIndex()) \
F(QModelIndex, QModelIndexVector, QVector<QModelIndex>, QModelIndex()) \
F(QModelIndex, QModelIndexStdVector, std::vector<QModelIndex>, QModelIndex()) \
F(QItemSelectionRange, QItemSelectionRange, QItemSelection, QItemSelectionRange())
FOREACH_QML_SEQUENCE_TYPE_FOR_ITEMMODEL(F)
static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, const QString &element)
{
@ -112,6 +121,7 @@ static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, co
return engine->newString(element.toString())->asReturnedValue();
}
#if QT_CONFIG(qml_itemmodel)
static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, const QModelIndex &element)
{
const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(QMetaType::QModelIndex);
@ -124,6 +134,7 @@ static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *engine, co
const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(metaTypeId);
return QV4::QQmlValueTypeWrapper::create(engine, QVariant::fromValue(element), vtmo, metaTypeId);
}
#endif
static QV4::ReturnedValue convertElementToValue(QV4::ExecutionEngine *, qreal element)
{
@ -150,6 +161,7 @@ static QString convertElementToString(const QUrl &element)
return element.toString();
}
#if QT_CONFIG(qml_itemmodel)
static QString convertElementToString(const QModelIndex &element)
{
return reinterpret_cast<const QQmlModelIndexValueType *>(&element)->toString();
@ -159,6 +171,7 @@ static QString convertElementToString(const QItemSelectionRange &element)
{
return reinterpret_cast<const QQmlItemSelectionRangeValueType *>(&element)->toString();
}
#endif
static QString convertElementToString(qreal element)
{
@ -192,6 +205,7 @@ template <> QUrl convertValueToElement(const Value &value)
return QUrl(value.toQString());
}
#if QT_CONFIG(qml_itemmodel)
template <> QModelIndex convertValueToElement(const Value &value)
{
const QQmlValueTypeWrapper *v = value.as<QQmlValueTypeWrapper>();
@ -207,6 +221,7 @@ template <> QItemSelectionRange convertValueToElement(const Value &value)
return v->toVariant().value<QItemSelectionRange>();
return QItemSelectionRange();
}
#endif
template <> qreal convertValueToElement(const Value &value)
{
@ -667,6 +682,7 @@ typedef QQmlSequence<QVector<QUrl> > QQmlUrlVectorList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlVectorList);
typedef QQmlSequence<std::vector<QUrl> > QQmlUrlStdVectorList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlStdVectorList);
#if QT_CONFIG(qml_itemmodel)
typedef QQmlSequence<QModelIndexList> QQmlQModelIndexList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexList);
typedef QQmlSequence<QVector<QModelIndex> > QQmlQModelIndexVectorList;
@ -675,6 +691,7 @@ typedef QQmlSequence<std::vector<QModelIndex> > QQmlQModelIndexStdVectorList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexStdVectorList);
typedef QQmlSequence<QItemSelection> QQmlQItemSelectionRangeList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQItemSelectionRangeList);
#endif
typedef QQmlSequence<QList<bool> > QQmlBoolList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlBoolList);
typedef QQmlSequence<QList<qreal> > QQmlRealList;

View File

@ -45,7 +45,7 @@
#include <private/qv4mm_p.h>
#include "qv4scopedvalue_p.h"
#include "qv4symbol_p.h"
#include "qv4alloca_p.h"
#include <private/qv4alloca_p.h>
#include "qv4jscall_p.h"
#include "qv4stringiterator_p.h"
#include <QtCore/QDateTime>

View File

@ -38,11 +38,11 @@
****************************************************************************/
#include "qv4vme_moth_p.h"
#include "qv4instr_moth_p.h"
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
#include <private/qv4instr_moth_p.h>
#include <private/qv4value_p.h>
#include <private/qv4debugging_p.h>
#include <private/qv4function_p.h>
@ -56,11 +56,10 @@
#include <private/qv4profiling_p.h>
#include <private/qv4jscall_p.h>
#include <private/qv4generatorobject_p.h>
#include <private/qv4alloca_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <iostream>
#include "qv4alloca_p.h"
#if QT_CONFIG(qml_jit)
#include <private/qv4baselinejit_p.h>
#endif

View File

@ -52,6 +52,7 @@
//
#include <private/qv4global_p.h>
#include <private/qv4staticvalue_p.h>
QT_BEGIN_NAMESPACE

View File

@ -46,6 +46,7 @@
#include <QtCore/qalgorithms.h>
#include <QtCore/private/qnumeric_p.h>
#include <QtCore/qloggingcategory.h>
#include <private/qv4alloca_p.h>
#include <qqmlengine.h>
#include "PageReservation.h"
#include "PageAllocation.h"
@ -59,7 +60,6 @@
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include "qv4alloca_p.h"
#include "qv4profiling_p.h"
#include "qv4mapobject_p.h"
#include "qv4setobject_p.h"

View File

@ -4,11 +4,9 @@ HEADERS += \
$$PWD/qqmljsastvisitor_p.h \
$$PWD/qqmljsengine_p.h \
$$PWD/qqmljslexer_p.h \
$$PWD/qqmljsmemorypool_p.h \
$$PWD/qqmljsglobal_p.h \
$$PWD/qqmljskeywords_p.h \
$$PWD/qqmljsengine_p.h \
$$PWD/qqmljsglobal_p.h \
$$PWD/qqmljssourcelocation_p.h
SOURCES += \

View File

@ -299,6 +299,9 @@ public:
AST::ExportsList *ExportsList;
AST::ExportClause *ExportClause;
AST::ExportDeclaration *ExportDeclaration;
AST::TypeAnnotation *TypeAnnotation;
AST::TypeArgumentList *TypeArgumentList;
AST::Type *Type;
AST::UiProgram *UiProgram;
AST::UiHeaderItemList *UiHeaderItemList;
@ -424,6 +427,8 @@ protected:
diagnostic_messages.append(compileError(location, message));
}
bool ensureNoFunctionTypeAnnotations(AST::TypeAnnotation *returnTypeAnnotation, AST::FormalParameterList *formals);
protected:
Engine *driver;
MemoryPool *pool;
@ -594,6 +599,21 @@ int Parser::lookaheadToken(Lexer *lexer)
return yytoken;
}
bool Parser::ensureNoFunctionTypeAnnotations(AST::TypeAnnotation *returnValueAnnotation, AST::FormalParameterList *formals)
{
for (auto formal = formals; formal; formal = formal->next) {
if (formal->element && formal->element->typeAnnotation) {
syntaxError(formal->element->typeAnnotation->firstSourceLocation(), "Type annotations are not permitted in function parameters in JavaScript functions");
return false;
}
}
if (returnValueAnnotation) {
syntaxError(returnValueAnnotation->firstSourceLocation(), "Type annotations are not permitted for the return value of JavaScript functions");
return false;
}
return true;
}
//#define PARSER_DEBUG
bool Parser::parse(int startToken)
@ -1086,6 +1106,17 @@ UiParameterListOpt: UiParameterList;
} break;
./
UiParameterList: QmlIdentifier T_COLON UiPropertyType;
/.
case $rule_number: {
AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(3).UiQualifiedId->finish(), stringRef(1));
node->identifierToken = loc(1);
node->colonToken = loc(2);
node->propertyTypeToken = loc(3);
sym(1).Node = node;
} break;
./
UiParameterList: UiPropertyType QmlIdentifier;
/.
case $rule_number: {
@ -1096,6 +1127,18 @@ UiParameterList: UiPropertyType QmlIdentifier;
} break;
./
UiParameterList: UiParameterList T_COMMA QmlIdentifier T_COLON UiPropertyType;
/.
case $rule_number: {
AST::UiParameterList *node = new (pool) AST::UiParameterList(sym(1).UiParameterList, sym(5).UiQualifiedId->finish(), stringRef(3));
node->propertyTypeToken = loc(5);
node->commaToken = loc(2);
node->identifierToken = loc(3);
node->colonToken = loc(4);
sym(1).Node = node;
} break;
./
UiParameterList: UiParameterList T_COMMA UiPropertyType QmlIdentifier;
/.
case $rule_number: {
@ -1355,7 +1398,7 @@ UiObjectMember: T_READONLY T_PROPERTY UiPropertyType QmlIdentifier T_COLON Expre
} break;
./
UiObjectMember: FunctionDeclaration;
UiObjectMember: FunctionDeclarationWithTypes;
/.
case $rule_number: {
sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
@ -1470,6 +1513,63 @@ JsIdentifier: T_AS;
IdentifierReference: JsIdentifier;
BindingIdentifier: IdentifierReference;
--------------------------------------------------------------------------------------------------------
-- Types
--------------------------------------------------------------------------------------------------------
TypeArguments: Type;
/.
case $rule_number: {
sym(1).TypeArgumentList = new (pool) AST::TypeArgumentList(sym(1).Type);
} break;
./
TypeArguments: TypeArguments T_COMMA Type;
/.
case $rule_number: {
sym(1).TypeArgumentList = new (pool) AST::TypeArgumentList(sym(1).TypeArgumentList, sym(3).Type);
} break;
./
Type: UiQualifiedId T_LT TypeArguments T_GT;
/.
case $rule_number: {
sym(1).Type = new (pool) AST::Type(sym(1).UiQualifiedId, sym(3).TypeArgumentList->finish());
} break;
./
Type: T_RESERVED_WORD;
/.
case $rule_number: {
AST::UiQualifiedId *id = new (pool) AST::UiQualifiedId(stringRef(1));
id->identifierToken = loc(1);
sym(1).Type = new (pool) AST::Type(id->finish());
} break;
./
Type: UiQualifiedId;
/.
case $rule_number: {
sym(1).Type = new (pool) AST::Type(sym(1).UiQualifiedId);
} break;
./
TypeAnnotation: T_COLON Type;
/.
case $rule_number: {
sym(1).TypeAnnotation = new (pool) AST::TypeAnnotation(sym(2).Type);
sym(1).TypeAnnotation->colonToken = loc(1);
} break;
./
TypeAnnotationOpt: TypeAnnotation;
TypeAnnotationOpt: ;
/.
case $rule_number: {
sym(1).TypeAnnotation = nullptr;
} break;
./
--------------------------------------------------------------------------------------------------------
-- Expressions
--------------------------------------------------------------------------------------------------------
@ -2851,7 +2951,14 @@ VarDeclaration: Var VariableDeclarationList;
VarDeclaration_In: Var VariableDeclarationList_In;
/.
case $rule_number: {
AST::VariableStatement *node = new (pool) AST::VariableStatement(sym(2).VariableDeclarationList->finish(sym(1).scope));
AST::VariableDeclarationList *declarations = sym(2).VariableDeclarationList->finish(sym(1).scope);
for (auto it = declarations; it; it = it->next) {
if (it->declaration && it->declaration->typeAnnotation) {
syntaxError(it->declaration->typeAnnotation->firstSourceLocation(), "Type annotations are not permitted in variable declarations");
return false;
}
}
AST::VariableStatement *node = new (pool) AST::VariableStatement(declarations);
node->declarationKindToken = loc(1);
sym(1).Node = node;
} break;
@ -2888,22 +2995,22 @@ VariableDeclarationList_In: VariableDeclarationList_In T_COMMA VariableDeclarati
} break;
./
LexicalBinding: BindingIdentifier InitializerOpt;
LexicalBinding: BindingIdentifier TypeAnnotationOpt InitializerOpt;
/. case $rule_number: Q_FALLTHROUGH(); ./
LexicalBinding_In: BindingIdentifier InitializerOpt_In;
LexicalBinding_In: BindingIdentifier TypeAnnotationOpt InitializerOpt_In;
/. case $rule_number: Q_FALLTHROUGH(); ./
VariableDeclaration: BindingIdentifier InitializerOpt;
VariableDeclaration: BindingIdentifier TypeAnnotationOpt InitializerOpt;
/. case $rule_number: Q_FALLTHROUGH(); ./
VariableDeclaration_In: BindingIdentifier InitializerOpt_In;
VariableDeclaration_In: BindingIdentifier TypeAnnotationOpt InitializerOpt_In;
/.
case $rule_number: {
auto *node = new (pool) AST::PatternElement(stringRef(1), sym(2).Expression);
auto *node = new (pool) AST::PatternElement(stringRef(1), sym(2).TypeAnnotation, sym(3).Expression);
node->identifierToken = loc(1);
sym(1).Node = node;
// if initializer is an anonymous function expression, we need to assign identifierref as it's name
if (auto *f = asAnonymousFunctionDefinition(sym(2).Expression))
if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression))
f->name = stringRef(1);
if (auto *c = asAnonymousClassDefinition(sym(2).Expression))
if (auto *c = asAnonymousClassDefinition(sym(3).Expression))
c->name = stringRef(1);
} break;
./
@ -3053,15 +3160,15 @@ BindingProperty: PropertyName T_COLON BindingPattern InitializerOpt_In;
} break;
./
BindingElement: BindingIdentifier InitializerOpt_In;
BindingElement: BindingIdentifier TypeAnnotationOpt InitializerOpt_In;
/.
case $rule_number: {
AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(1), sym(2).Expression);
AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(1), sym(2).TypeAnnotation, sym(3).Expression);
node->identifierToken = loc(1);
// if initializer is an anonymous function expression, we need to assign identifierref as it's name
if (auto *f = asAnonymousFunctionDefinition(sym(2).Expression))
if (auto *f = asAnonymousFunctionDefinition(sym(3).Expression))
f->name = stringRef(1);
if (auto *c = asAnonymousClassDefinition(sym(2).Expression))
if (auto *c = asAnonymousClassDefinition(sym(3).Expression))
c->name = stringRef(1);
sym(1).Node = node;
} break;
@ -3078,7 +3185,7 @@ BindingElement: BindingPattern InitializerOpt_In;
BindingRestElement: T_ELLIPSIS BindingIdentifier;
/.
case $rule_number: {
AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(2), nullptr, AST::PatternElement::RestElement);
AST::PatternElement *node = new (pool) AST::PatternElement(stringRef(2), /*type annotation*/nullptr, nullptr, AST::PatternElement::RestElement);
node->identifierToken = loc(2);
sym(1).Node = node;
} break;
@ -3268,12 +3375,16 @@ IterationStatement: T_FOR T_LPAREN ForDeclaration InOrOf Expression_In T_RPAREN
} break;
./
ForDeclaration: LetOrConst BindingIdentifier;
ForDeclaration: LetOrConst BindingIdentifier TypeAnnotationOpt;
/. case $rule_number: Q_FALLTHROUGH(); ./
ForDeclaration: Var BindingIdentifier;
ForDeclaration: Var BindingIdentifier TypeAnnotationOpt;
/.
case $rule_number: {
auto *node = new (pool) AST::PatternElement(stringRef(2), nullptr);
if (auto typeAnnotation = sym(3).TypeAnnotation) {
syntaxError(typeAnnotation->firstSourceLocation(), "Type annotations are not permitted in variable declarations");
return false;
}
auto *node = new (pool) AST::PatternElement(stringRef(2), sym(3).TypeAnnotation, nullptr);
node->identifierToken = loc(2);
node->scope = sym(1).scope;
node->isForDeclaration = true;
@ -3560,59 +3671,85 @@ DebuggerStatement: T_DEBUGGER T_SEMICOLON;
-- otherwise conflict.
Function: T_FUNCTION %prec REDUCE_HERE;
FunctionDeclaration: Function BindingIdentifier T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
FunctionDeclaration: Function BindingIdentifier T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
if (!ensureNoFunctionTypeAnnotations(sym(6).TypeAnnotation, sym(4).FormalParameterList))
return false;
AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList,
/*type annotation*/nullptr);
node->functionToken = loc(1);
node->identifierToken = loc(2);
node->lparenToken = loc(3);
node->rparenToken = loc(5);
node->lbraceToken = loc(7);
node->rbraceToken = loc(9);
sym(1).Node = node;
} break;
./
FunctionDeclarationWithTypes: Function BindingIdentifier T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList,
sym(6).TypeAnnotation);
node->functionToken = loc(1);
node->identifierToken = loc(2);
node->lparenToken = loc(3);
node->rparenToken = loc(5);
node->lbraceToken = loc(7);
node->rbraceToken = loc(9);
sym(1).Node = node;
} break;
./
FunctionDeclaration_Default: FunctionDeclaration;
FunctionDeclaration_Default: Function T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
if (!ensureNoFunctionTypeAnnotations(sym(5).TypeAnnotation, sym(3).FormalParameterList))
return false;
AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(QStringRef(), sym(3).FormalParameterList, sym(7).StatementList,
/*type annotation*/nullptr);
node->functionToken = loc(1);
node->lparenToken = loc(2);
node->rparenToken = loc(4);
node->lbraceToken = loc(6);
node->rbraceToken = loc(8);
sym(1).Node = node;
} break;
./
FunctionDeclaration_Default: FunctionDeclaration;
FunctionDeclaration_Default: Function T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
FunctionExpression: T_FUNCTION BindingIdentifier T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
AST::FunctionDeclaration *node = new (pool) AST::FunctionDeclaration(QStringRef(), sym(3).FormalParameterList, sym(6).StatementList);
node->functionToken = loc(1);
node->lparenToken = loc(2);
node->rparenToken = loc(4);
node->lbraceToken = loc(5);
node->rbraceToken = loc(7);
sym(1).Node = node;
} break;
./
FunctionExpression: T_FUNCTION BindingIdentifier T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
if (!ensureNoFunctionTypeAnnotations(sym(6).TypeAnnotation, sym(4).FormalParameterList))
return false;
AST::FunctionExpression *node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList,
/*type annotation*/nullptr);
node->functionToken = loc(1);
if (! stringRef(2).isNull())
node->identifierToken = loc(2);
node->lparenToken = loc(3);
node->rparenToken = loc(5);
node->lbraceToken = loc(6);
node->rbraceToken = loc(8);
node->lbraceToken = loc(7);
node->rbraceToken = loc(9);
sym(1).Node = node;
} break;
./
FunctionExpression: T_FUNCTION T_LPAREN FormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
FunctionExpression: T_FUNCTION T_LPAREN FormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(6).StatementList);
if (!ensureNoFunctionTypeAnnotations(sym(5).TypeAnnotation, sym(3).FormalParameterList))
return false;
AST::FunctionExpression *node = new (pool) AST::FunctionExpression(QStringRef(), sym(3).FormalParameterList, sym(7).StatementList,
/*type annotation*/nullptr);
node->functionToken = loc(1);
node->lparenToken = loc(2);
node->rparenToken = loc(4);
node->lbraceToken = loc(5);
node->rbraceToken = loc(7);
node->lbraceToken = loc(6);
node->rbraceToken = loc(8);
sym(1).Node = node;
} break;
./
@ -3722,7 +3859,7 @@ ArrowFunction_In: ArrowParameters T_ARROW ConciseBodyLookahead T_FORCE_BLOCK Fun
ArrowParameters: BindingIdentifier;
/.
case $rule_number: {
AST::PatternElement *e = new (pool) AST::PatternElement(stringRef(1), nullptr, AST::PatternElement::Binding);
AST::PatternElement *e = new (pool) AST::PatternElement(stringRef(1), /*type annotation*/nullptr, nullptr, AST::PatternElement::Binding);
e->identifierToken = loc(1);
sym(1).FormalParameterList = (new (pool) AST::FormalParameterList(nullptr, e))->finish(pool);
} break;
@ -3756,30 +3893,34 @@ ConciseBodyLookahead: ;
} break;
./
MethodDefinition: PropertyName T_LPAREN StrictFormalParameters T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
MethodDefinition: PropertyName T_LPAREN StrictFormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(1), sym(3).FormalParameterList, sym(6).StatementList);
if (!ensureNoFunctionTypeAnnotations(sym(5).TypeAnnotation, sym(3).FormalParameterList))
return false;
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(1), sym(3).FormalParameterList, sym(7).StatementList);
f->functionToken = sym(1).PropertyName->firstSourceLocation();
f->lparenToken = loc(2);
f->rparenToken = loc(4);
f->lbraceToken = loc(5);
f->rbraceToken = loc(7);
f->lbraceToken = loc(6);
f->rbraceToken = loc(8);
AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, f, AST::PatternProperty::Method);
node->colonToken = loc(2);
sym(1).Node = node;
} break;
./
MethodDefinition: T_STAR PropertyName GeneratorLParen StrictFormalParameters T_RPAREN FunctionLBrace GeneratorBody GeneratorRBrace;
MethodDefinition: T_STAR PropertyName GeneratorLParen StrictFormalParameters T_RPAREN TypeAnnotationOpt FunctionLBrace GeneratorBody GeneratorRBrace;
/.
case $rule_number: {
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
if (!ensureNoFunctionTypeAnnotations(sym(6).TypeAnnotation, sym(4).FormalParameterList))
return false;
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList);
f->functionToken = sym(2).PropertyName->firstSourceLocation();
f->lparenToken = loc(3);
f->rparenToken = loc(5);
f->lbraceToken = loc(6);
f->rbraceToken = loc(8);
f->lbraceToken = loc(7);
f->rbraceToken = loc(9);
f->isGenerator = true;
AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Method);
node->colonToken = loc(2);
@ -3788,30 +3929,34 @@ MethodDefinition: T_STAR PropertyName GeneratorLParen StrictFormalParameters T_R
./
MethodDefinition: T_GET PropertyName T_LPAREN T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
MethodDefinition: T_GET PropertyName T_LPAREN T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), nullptr, sym(6).StatementList);
if (!ensureNoFunctionTypeAnnotations(sym(5).TypeAnnotation, /*formals*/nullptr))
return false;
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), nullptr, sym(7).StatementList);
f->functionToken = sym(2).PropertyName->firstSourceLocation();
f->lparenToken = loc(3);
f->rparenToken = loc(4);
f->lbraceToken = loc(5);
f->rbraceToken = loc(7);
f->lbraceToken = loc(6);
f->rbraceToken = loc(8);
AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Getter);
node->colonToken = loc(2);
sym(1).Node = node;
} break;
./
MethodDefinition: T_SET PropertyName T_LPAREN PropertySetParameterList T_RPAREN FunctionLBrace FunctionBody FunctionRBrace;
MethodDefinition: T_SET PropertyName T_LPAREN PropertySetParameterList T_RPAREN TypeAnnotationOpt FunctionLBrace FunctionBody FunctionRBrace;
/.
case $rule_number: {
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).StatementList);
if (!ensureNoFunctionTypeAnnotations(sym(6).TypeAnnotation, sym(4).FormalParameterList))
return false;
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(8).StatementList);
f->functionToken = sym(2).PropertyName->firstSourceLocation();
f->lparenToken = loc(3);
f->rparenToken = loc(5);
f->lbraceToken = loc(6);
f->rbraceToken = loc(8);
f->lbraceToken = loc(7);
f->rbraceToken = loc(9);
AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Setter);
node->colonToken = loc(2);
sym(1).Node = node;

View File

@ -131,7 +131,7 @@ FormalParameterList *ExpressionNode::reparseAsFormalParameterList(MemoryPool *po
}
AST::PatternElement *binding = nullptr;
if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(expr)) {
binding = new (pool) AST::PatternElement(idExpr->name, rhs);
binding = new (pool) AST::PatternElement(idExpr->name, /*type annotation*/nullptr, rhs);
binding->identifierToken = idExpr->identifierToken;
} else if (AST::Pattern *p = expr->patternCast()) {
SourceLocation loc;
@ -961,6 +961,7 @@ void FunctionDeclaration::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(formals, visitor);
accept(typeAnnotation, visitor);
accept(body, visitor);
}
@ -971,6 +972,7 @@ void FunctionExpression::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(formals, visitor);
accept(typeAnnotation, visitor);
accept(body, visitor);
}
@ -982,9 +984,9 @@ FunctionExpression *FunctionExpression::asFunctionDefinition()
return this;
}
QStringList FormalParameterList::formals() const
BoundNames FormalParameterList::formals() const
{
QStringList formals;
BoundNames formals;
int i = 0;
for (const FormalParameterList *it = this; it; it = it->next) {
if (it->element) {
@ -992,18 +994,18 @@ QStringList FormalParameterList::formals() const
int duplicateIndex = formals.indexOf(name);
if (duplicateIndex >= 0) {
// change the name of the earlier argument to enforce the lookup semantics from the spec
formals[duplicateIndex] += QLatin1String("#") + QString::number(i);
formals[duplicateIndex].id += QLatin1String("#") + QString::number(i);
}
formals += name;
formals += {name, it->element->typeAnnotation};
}
++i;
}
return formals;
}
QStringList FormalParameterList::boundNames() const
BoundNames FormalParameterList::boundNames() const
{
QStringList names;
BoundNames names;
for (const FormalParameterList *it = this; it; it = it->next) {
if (it->element)
it->element->boundNames(&names);
@ -1271,6 +1273,35 @@ void UiQualifiedId::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void Type::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(typeId, visitor);
accept(typeArguments, visitor);
}
visitor->endVisit(this);
}
void TypeArgumentList::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
for (TypeArgumentList *it = this; it; it = it->next)
accept(it->typeId, visitor);
}
visitor->endVisit(this);
}
void TypeAnnotation::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(type, visitor);
}
visitor->endVisit(this);
}
void UiImport::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
@ -1339,13 +1370,14 @@ void PatternElement::accept0(Visitor *visitor)
{
if (visitor->visit(this)) {
accept(bindingTarget, visitor);
accept(typeAnnotation, visitor);
accept(initializer, visitor);
}
visitor->endVisit(this);
}
void PatternElement::boundNames(QStringList *names)
void PatternElement::boundNames(BoundNames *names)
{
if (bindingTarget) {
if (PatternElementList *e = elementList())
@ -1353,7 +1385,7 @@ void PatternElement::boundNames(QStringList *names)
else if (PatternPropertyList *p = propertyList())
p->boundNames(names);
} else {
names->append(bindingIdentifier.toString());
names->append({bindingIdentifier.toString(), typeAnnotation});
}
}
@ -1369,7 +1401,7 @@ void PatternElementList::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void PatternElementList::boundNames(QStringList *names)
void PatternElementList::boundNames(BoundNames *names)
{
for (PatternElementList *it = this; it; it = it->next) {
if (it->element)
@ -1382,13 +1414,14 @@ void PatternProperty::accept0(Visitor *visitor)
if (visitor->visit(this)) {
accept(name, visitor);
accept(bindingTarget, visitor);
accept(typeAnnotation, visitor);
accept(initializer, visitor);
}
visitor->endVisit(this);
}
void PatternProperty::boundNames(QStringList *names)
void PatternProperty::boundNames(BoundNames *names)
{
PatternElement::boundNames(names);
}
@ -1404,7 +1437,7 @@ void PatternPropertyList::accept0(Visitor *visitor)
visitor->endVisit(this);
}
void PatternPropertyList::boundNames(QStringList *names)
void PatternPropertyList::boundNames(BoundNames *names)
{
for (PatternPropertyList *it = this; it; it = it->next)
it->property->boundNames(names);
@ -1478,6 +1511,31 @@ void UiVersionSpecifier::accept0(Visitor *visitor)
}
visitor->endVisit(this);
}
QString Type::toString() const
{
QString result;
toString(&result);
return result;
}
void Type::toString(QString *out) const
{
for (QQmlJS::AST::UiQualifiedId *it = typeId; it; it = it->next) {
out->append(it->name);
if (it->next)
out->append(QLatin1Char('.'));
}
if (typeArguments) {
out->append(QLatin1Char('<'));
if (auto subType = static_cast<TypeArgumentList*>(typeArguments)->typeId)
subType->toString(out);
out->append(QLatin1Char('>'));
};
}
} } // namespace QQmlJS::AST
QT_END_NAMESPACE

View File

@ -53,7 +53,8 @@
#include "qqmljsastvisitor_p.h"
#include "qqmljsglobal_p.h"
#include "qqmljsmemorypool_p.h"
#include <private/qqmljsmemorypool_p.h>
#include <QtCore/qstring.h>
@ -233,6 +234,9 @@ public:
Kind_PatternElementList,
Kind_PatternProperty,
Kind_PatternPropertyList,
Kind_Type,
Kind_TypeArgumentList,
Kind_TypeAnnotation,
Kind_UiArrayBinding,
Kind_UiImport,
@ -303,6 +307,131 @@ public:
int kind = Kind_Undefined;
};
class QML_PARSER_EXPORT UiQualifiedId: public Node
{
public:
QQMLJS_DECLARE_AST_NODE(UiQualifiedId)
UiQualifiedId(const QStringRef &name)
: next(this), name(name)
{ kind = K; }
UiQualifiedId(UiQualifiedId *previous, const QStringRef &name)
: name(name)
{
kind = K;
next = previous->next;
previous->next = this;
}
UiQualifiedId *finish()
{
UiQualifiedId *head = next;
next = nullptr;
return head;
}
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return identifierToken; }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : identifierToken; }
// attributes
UiQualifiedId *next;
QStringRef name;
SourceLocation identifierToken;
};
class QML_PARSER_EXPORT Type: public Node
{
public:
QQMLJS_DECLARE_AST_NODE(Type)
Type(UiQualifiedId *typeId, Node *typeArguments = nullptr)
: typeId(typeId)
, typeArguments(typeArguments)
{ kind = K; }
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return typeId->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return typeArguments ? typeArguments->lastSourceLocation() : typeId->lastSourceLocation(); }
QString toString() const;
void toString(QString *out) const;
// attributes
UiQualifiedId *typeId;
Node *typeArguments; // TypeArgumentList
};
class QML_PARSER_EXPORT TypeArgumentList: public Node
{
public:
QQMLJS_DECLARE_AST_NODE(TypeArgumentList)
TypeArgumentList(Type *typeId)
: typeId(typeId)
, next(nullptr)
{ kind = K; }
TypeArgumentList(TypeArgumentList *previous, Type *typeId)
: typeId(typeId)
{
kind = K;
next = previous->next;
previous->next = this;
}
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return typeId->firstSourceLocation(); }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : typeId->lastSourceLocation(); }
inline TypeArgumentList *finish()
{
TypeArgumentList *front = next;
next = nullptr;
return front;
}
// attributes
Type *typeId;
TypeArgumentList *next;
};
class QML_PARSER_EXPORT TypeAnnotation: public Node
{
public:
QQMLJS_DECLARE_AST_NODE(TypeAnnotation)
TypeAnnotation(Type *type)
: type(type)
{ kind = K; }
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return colonToken; }
SourceLocation lastSourceLocation() const override
{ return type->lastSourceLocation(); }
// attributes
Type *type;
SourceLocation colonToken;
};
class QML_PARSER_EXPORT ExpressionNode: public Node
{
public:
@ -704,6 +833,34 @@ public:
SourceLocation propertyNameToken;
};
struct QML_PARSER_EXPORT BoundName
{
QString id;
TypeAnnotation *typeAnnotation = nullptr;
BoundName(const QString &id, TypeAnnotation *typeAnnotation)
: id(id), typeAnnotation(typeAnnotation)
{}
BoundName() = default;
QString typeName() const { return typeAnnotation ? typeAnnotation->type->toString() : QString(); }
};
struct BoundNames : public QVector<BoundName>
{
int indexOf(const QString &name, int from = 0) const
{
auto found = std::find_if(constBegin() + from, constEnd(),
[name](const BoundName &it) { return it.id == name; });
if (found == constEnd())
return -1;
return found - constBegin();
}
bool contains(const QString &name) const
{
return indexOf(name) != -1;
}
};
class QML_PARSER_EXPORT PatternElement : public Node
{
public:
@ -728,8 +885,9 @@ public:
: initializer(i), type(t)
{ kind = K; }
PatternElement(const QStringRef &n, ExpressionNode *i = nullptr, Type t = Binding)
PatternElement(const QStringRef &n, TypeAnnotation *typeAnnotation = nullptr, ExpressionNode *i = nullptr, Type t = Binding)
: bindingIdentifier(n), initializer(i), type(t)
, typeAnnotation(typeAnnotation)
{
Q_ASSERT(t >= RestElement);
kind = K;
@ -749,7 +907,7 @@ public:
{ return identifierToken.isValid() ? identifierToken : (bindingTarget ? bindingTarget->firstSourceLocation() : initializer->firstSourceLocation()); }
SourceLocation lastSourceLocation() const override
{ return initializer ? initializer->lastSourceLocation() : (bindingTarget ? bindingTarget->lastSourceLocation() : identifierToken); }
{ return initializer ? initializer->lastSourceLocation() : (bindingTarget ? bindingTarget->lastSourceLocation() : (typeAnnotation ? typeAnnotation->lastSourceLocation() : identifierToken)); }
ExpressionNode *destructuringTarget() const { return bindingTarget; }
Pattern *destructuringPattern() const { return bindingTarget ? bindingTarget->patternCast() : nullptr; }
@ -759,7 +917,7 @@ public:
bool isVariableDeclaration() const { return scope != VariableScope::NoScope; }
bool isLexicallyScoped() const { return scope == VariableScope::Let || scope == VariableScope::Const; }
virtual void boundNames(QStringList *names);
virtual void boundNames(BoundNames *names);
// attributes
SourceLocation identifierToken;
@ -767,6 +925,7 @@ public:
ExpressionNode *bindingTarget = nullptr;
ExpressionNode *initializer = nullptr;
Type type = Literal;
TypeAnnotation *typeAnnotation = nullptr;
// when used in a VariableDeclarationList
VariableScope scope = VariableScope::NoScope;
bool isForDeclaration = false;
@ -796,7 +955,7 @@ public:
void accept0(Visitor *visitor) override;
void boundNames(QStringList *names);
void boundNames(BoundNames *names);
SourceLocation firstSourceLocation() const override
{ return elision ? elision->firstSourceLocation() : element->firstSourceLocation(); }
@ -819,7 +978,7 @@ public:
{ kind = K; }
PatternProperty(PropertyName *name, const QStringRef &n, ExpressionNode *i = nullptr)
: PatternElement(n, i), name(name)
: PatternElement(n, /*type annotation*/nullptr, i), name(name)
{ kind = K; }
PatternProperty(PropertyName *name, Pattern *pattern, ExpressionNode *i = nullptr)
@ -836,7 +995,7 @@ public:
return loc.isValid() ? loc : name->lastSourceLocation();
}
void boundNames(QStringList *names) override;
void boundNames(BoundNames *names) override;
bool convertLiteralToAssignmentPattern(MemoryPool *pool, SourceLocation *errorLocation, QString *errorMessage) override;
// attributes
@ -864,7 +1023,7 @@ public:
void accept0(Visitor *visitor) override;
void boundNames(QStringList *names);
void boundNames(BoundNames *names);
inline PatternPropertyList *finish ()
{
@ -2154,8 +2313,9 @@ class QML_PARSER_EXPORT FunctionExpression: public ExpressionNode
public:
QQMLJS_DECLARE_AST_NODE(FunctionExpression)
FunctionExpression(const QStringRef &n, FormalParameterList *f, StatementList *b):
name (n), formals (f), body (b)
FunctionExpression(const QStringRef &n, FormalParameterList *f, StatementList *b, TypeAnnotation *typeAnnotation = nullptr):
name (n), formals (f), body (b),
typeAnnotation(typeAnnotation)
{ kind = K; }
void accept0(Visitor *visitor) override;
@ -2174,6 +2334,7 @@ public:
bool isGenerator = false;
FormalParameterList *formals;
StatementList *body;
TypeAnnotation *typeAnnotation;
SourceLocation functionToken;
SourceLocation identifierToken;
SourceLocation lparenToken;
@ -2187,8 +2348,8 @@ class QML_PARSER_EXPORT FunctionDeclaration: public FunctionExpression
public:
QQMLJS_DECLARE_AST_NODE(FunctionDeclaration)
FunctionDeclaration(const QStringRef &n, FormalParameterList *f, StatementList *b):
FunctionExpression(n, f, b)
FunctionDeclaration(const QStringRef &n, FormalParameterList *f, StatementList *b, TypeAnnotation *typeAnnotation = nullptr):
FunctionExpression(n, f, b, typeAnnotation)
{ kind = K; }
void accept0(Visitor *visitor) override;
@ -2258,9 +2419,9 @@ public:
return false;
}
QStringList formals() const;
BoundNames formals() const;
QStringList boundNames() const;
BoundNames boundNames() const;
void accept0(Visitor *visitor) override;
@ -2809,44 +2970,6 @@ public:
SourceLocation semicolonToken;
};
class QML_PARSER_EXPORT UiQualifiedId: public Node
{
public:
QQMLJS_DECLARE_AST_NODE(UiQualifiedId)
UiQualifiedId(const QStringRef &name)
: next(this), name(name)
{ kind = K; }
UiQualifiedId(UiQualifiedId *previous, const QStringRef &name)
: name(name)
{
kind = K;
next = previous->next;
previous->next = this;
}
UiQualifiedId *finish()
{
UiQualifiedId *head = next;
next = nullptr;
return head;
}
void accept0(Visitor *visitor) override;
SourceLocation firstSourceLocation() const override
{ return identifierToken; }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : identifierToken; }
// attributes
UiQualifiedId *next;
QStringRef name;
SourceLocation identifierToken;
};
class QML_PARSER_EXPORT UiImport: public Node
{
public:
@ -3114,10 +3237,10 @@ public:
void accept0(Visitor *) override;
SourceLocation firstSourceLocation() const override
{ return propertyTypeToken; }
{ return colonToken.isValid() ? identifierToken : propertyTypeToken; }
SourceLocation lastSourceLocation() const override
{ return next ? next->lastSourceLocation() : identifierToken; }
{ return next ? next->lastSourceLocation() : (colonToken.isValid() ? propertyTypeToken : identifierToken); }
inline UiParameterList *finish ()
{
@ -3133,6 +3256,7 @@ public:
SourceLocation commaToken;
SourceLocation propertyTypeToken;
SourceLocation identifierToken;
SourceLocation colonToken;
};
class QML_PARSER_EXPORT UiPublicMember: public UiObjectMember

View File

@ -158,6 +158,9 @@ class NestedExpression;
class ClassExpression;
class ClassDeclaration;
class ClassElementList;
class TypeArgumentList;
class Type;
class TypeAnnotation;
// ui elements
class UiProgram;

View File

@ -403,6 +403,15 @@ public:
virtual bool visit(DebuggerStatement *) { return true; }
virtual void endVisit(DebuggerStatement *) {}
virtual bool visit(Type *) { return true; }
virtual void endVisit(Type *) {}
virtual bool visit(TypeArgumentList *) { return true; }
virtual void endVisit(TypeArgumentList *) {}
virtual bool visit(TypeAnnotation *) { return true; }
virtual void endVisit(TypeAnnotation *) {}
virtual void throwRecursionDepthError() = 0;
quint16 recursionDepth() const { return m_recursionDepth; }

View File

@ -52,9 +52,10 @@
//
#include "qqmljsglobal_p.h"
#include "qqmljsmemorypool_p.h"
#include "qqmljssourcelocation_p.h"
#include <private/qqmljsmemorypool_p.h>
#include <QtCore/qstring.h>
#include <QtCore/qset.h>

View File

@ -39,10 +39,10 @@
#include "qqmljslexer_p.h"
#include "qqmljsengine_p.h"
#include "qqmljsmemorypool_p.h"
#include "qqmljskeywords_p.h"
#include <private/qqmljsdiagnosticmessage_p.h>
#include <private/qqmljsmemorypool_p.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qvarlengtharray.h>

View File

@ -19,31 +19,6 @@ gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks
DEFINES += QT_NO_FOREACH
!build_pass {
# Create a header containing a hash that describes this library. For a
# released version of Qt, we'll use the .tag file that is updated by git
# archive with the commit hash. For unreleased versions, we'll ask git
# describe. Note that it won't update unless qmake is run again, even if
# the commit change also changed something in this library.
tagFile = $$PWD/../../.tag
tag =
exists($$tagFile) {
tag = $$cat($$tagFile, singleline)
QMAKE_INTERNAL_INCLUDED_FILES += $$tagFile
}
!equals(tag, "$${LITERAL_DOLLAR}Format:%H$${LITERAL_DOLLAR}") {
QML_COMPILE_HASH = $$tag
} else:exists($$PWD/../../.git) {
commit = $$system(git rev-parse HEAD)
QML_COMPILE_HASH = $$commit
}
compile_hash_contents = \
"// Generated file, DO NOT EDIT" \
"$${LITERAL_HASH}define QML_COMPILE_HASH \"$$QML_COMPILE_HASH\"" \
"$${LITERAL_HASH}define QML_COMPILE_HASH_LENGTH $$str_size($$QML_COMPILE_HASH)"
write_file("$$OUT_PWD/qml_compile_hash_p.h", compile_hash_contents)|error()
}
exists("qqml_enable_gcov") {
QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors
LIBS_PRIVATE += -lgcov
@ -64,7 +39,9 @@ greaterThan(QT_CLANG_MAJOR_VERSION, 3)|greaterThan(QT_CLANG_MINOR_VERSION, 3)| \
WERROR += -Wno-error=unused-const-variable
HEADERS += qtqmlglobal.h \
qtqmlglobal_p.h
qtqmlglobal_p.h \
qtqmlcompilerglobal.h \
qtqmlcompilerglobal_p.h
#modules
include(common/common.pri)

View File

@ -1,7 +1,14 @@
SOURCES += \
$$PWD/qqml.cpp \
$$PWD/qqmldatablob.cpp \
$$PWD/qqmldirdata.cpp \
$$PWD/qqmlerror.cpp \
$$PWD/qqmlopenmetaobject.cpp \
$$PWD/qqmlscriptblob.cpp \
$$PWD/qqmlscriptdata.cpp \
$$PWD/qqmltypedata.cpp \
$$PWD/qqmltypeloaderqmldircontent.cpp \
$$PWD/qqmltypeloaderthread.cpp \
$$PWD/qqmlvmemetaobject.cpp \
$$PWD/qqmlengine.cpp \
$$PWD/qqmlexpression.cpp \
@ -61,10 +68,18 @@ SOURCES += \
$$PWD/qqmlpropertyvalidator.cpp
HEADERS += \
$$PWD/qqmldatablob_p.h \
$$PWD/qqmldirdata_p.h \
$$PWD/qqmlglobal_p.h \
$$PWD/qqmlopenmetaobject_p.h \
$$PWD/qqmlscriptblob_p.h \
$$PWD/qqmlscriptdata_p.h \
$$PWD/qqmltypedata_p.h \
$$PWD/qqmltypeloaderqmldircontent_p.h \
$$PWD/qqmltypeloaderthread_p.h \
$$PWD/qqmlvmemetaobject_p.h \
$$PWD/qqml.h \
$$PWD/qqmlerror.h \
$$PWD/qqmlproperty.h \
$$PWD/qqmlcomponent.h \
$$PWD/qqmlcomponent_p.h \
@ -163,5 +178,13 @@ qtConfig(qml-locale) {
$$PWD/qqmllocale.cpp
}
qtConfig(qml-network) {
HEADERS += \
$$PWD/qqmltypeloadernetworkreplyproxy_p.h
SOURCES += \
$$PWD/qqmltypeloadernetworkreplyproxy.cpp
}
include(ftw/ftw.pri)
include(v8/v8.pri)

View File

@ -37,6 +37,7 @@
**
****************************************************************************/
#include <QtQml/qqmlfile.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QTranslator>
#include <QQmlComponent>

View File

@ -49,6 +49,7 @@
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlvaluetypewrapper_p.h>
#include <private/qv4qmlcontext_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <private/qv4variantobject_p.h>
#include <private/qv4jscall_p.h>

View File

@ -63,6 +63,7 @@
#include <private/qqmlabstractbinding_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <private/qv4functionobject_p.h>
QT_BEGIN_NAMESPACE

View File

@ -56,6 +56,7 @@
#include <private/qv4value_p.h>
#include <private/qv4jscall_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <private/qv4qmlcontext_p.h>
#include <QtCore/qdebug.h>

View File

@ -569,6 +569,12 @@ void QQmlComponent::setData(const QByteArray &data, const QUrl &url)
{
Q_D(QQmlComponent);
if (!d->engine) {
// ###Qt6: In Qt 6, it should be impossible for users to create a QQmlComponent without an engine, and we can remove this check
qWarning("QQmlComponent: Must provide an engine before calling setData");
return;
}
d->clear();
d->url = url;
@ -774,6 +780,12 @@ QObject *QQmlComponent::create(QQmlContext *context)
{
Q_D(QQmlComponent);
if (!d->engine) {
// ###Qt6: In Qt 6, it should be impossible for users to create a QQmlComponent without an engine, and we can remove this check
qWarning("QQmlComponent: Must provide an engine before calling create");
return nullptr;
}
if (!context)
context = d->engine->rootContext();

View File

@ -60,6 +60,7 @@
#include "qqmlerror.h"
#include "qqml.h"
#include <private/qqmlobjectcreator_p.h>
#include <private/qqmltypedata_p.h>
#include <QtCore/QString>
#include <QtCore/QStringList>

View File

@ -39,7 +39,7 @@
#include "qqmlcustomparser_p.h"
#include <private/qqmltypecompiler_p.h>
#include <private/qv4compileddata_p.h>
#include <QtCore/qdebug.h>

View File

@ -53,7 +53,7 @@
#include "qqmlerror.h"
#include "qqmlbinding_p.h"
#include <private/qqmltypecompiler_p.h>
#include <private/qv4compileddata_p.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qxmlstream.h>

View File

@ -0,0 +1,639 @@
/****************************************************************************
**
** 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$
**
****************************************************************************/
#include <private/qqmldatablob_p.h>
#include <private/qqmlglobal_p.h>
#include <private/qqmlprofiler_p.h>
#include <private/qqmltypeloader_p.h>
#include <private/qqmltypeloaderthread_p.h>
#include <QtQml/qqmlengine.h>
#ifdef DATABLOB_DEBUG
#define ASSERT_CALLBACK() do { if (!m_typeLoader || !m_typeLoader->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while (false)
#else
#define ASSERT_CALLBACK()
#endif
DEFINE_BOOL_CONFIG_OPTION(dumpErrors, QML_DUMP_ERRORS);
QT_BEGIN_NAMESPACE
/*!
\class QQmlDataBlob
\brief The QQmlDataBlob encapsulates a data request that can be issued to a QQmlTypeLoader.
\internal
QQmlDataBlob's are loaded by a QQmlTypeLoader. The user creates the QQmlDataBlob
and then calls QQmlTypeLoader::load() or QQmlTypeLoader::loadWithStaticData() to load it.
The QQmlTypeLoader invokes callbacks on the QQmlDataBlob as data becomes available.
*/
/*!
\enum QQmlDataBlob::Status
This enum describes the status of the data blob.
\list
\li Null The blob has not yet been loaded by a QQmlTypeLoader
\li Loading The blob is loading network data. The QQmlDataBlob::setData() callback has not yet been
invoked or has not yet returned.
\li WaitingForDependencies The blob is waiting for dependencies to be done before continuing.
This status only occurs after the QQmlDataBlob::setData() callback has been made, and when the
blob has outstanding dependencies.
\li Complete The blob's data has been loaded and all dependencies are done.
\li Error An error has been set on this blob.
\endlist
*/
/*!
\enum QQmlDataBlob::Type
This enum describes the type of the data blob.
\list
\li QmlFile This is a QQmlTypeData
\li JavaScriptFile This is a QQmlScriptData
\li QmldirFile This is a QQmlQmldirData
\endlist
*/
/*!
Create a new QQmlDataBlob for \a url and of the provided \a type.
*/
QQmlDataBlob::QQmlDataBlob(const QUrl &url, Type type, QQmlTypeLoader *manager)
: m_typeLoader(manager), m_type(type), m_url(url), m_finalUrl(url), m_redirectCount(0),
m_inCallback(false), m_isDone(false)
{
//Set here because we need to get the engine from the manager
if (m_typeLoader->engine() && m_typeLoader->engine()->urlInterceptor())
m_url = m_typeLoader->engine()->urlInterceptor()->intercept(m_url,
(QQmlAbstractUrlInterceptor::DataType)m_type);
}
/*! \internal */
QQmlDataBlob::~QQmlDataBlob()
{
Q_ASSERT(m_waitingOnMe.isEmpty());
cancelAllWaitingFor();
}
/*!
Must be called before loading can occur.
*/
void QQmlDataBlob::startLoading()
{
Q_ASSERT(status() == QQmlDataBlob::Null);
m_data.setStatus(QQmlDataBlob::Loading);
}
/*!
Returns the type provided to the constructor.
*/
QQmlDataBlob::Type QQmlDataBlob::type() const
{
return m_type;
}
/*!
Returns the blob's status.
*/
QQmlDataBlob::Status QQmlDataBlob::status() const
{
return m_data.status();
}
/*!
Returns true if the status is Null.
*/
bool QQmlDataBlob::isNull() const
{
return status() == Null;
}
/*!
Returns true if the status is Loading.
*/
bool QQmlDataBlob::isLoading() const
{
return status() == Loading;
}
/*!
Returns true if the status is WaitingForDependencies.
*/
bool QQmlDataBlob::isWaiting() const
{
return status() == WaitingForDependencies ||
status() == ResolvingDependencies;
}
/*!
Returns true if the status is Complete.
*/
bool QQmlDataBlob::isComplete() const
{
return status() == Complete;
}
/*!
Returns true if the status is Error.
*/
bool QQmlDataBlob::isError() const
{
return status() == Error;
}
/*!
Returns true if the status is Complete or Error.
*/
bool QQmlDataBlob::isCompleteOrError() const
{
Status s = status();
return s == Error || s == Complete;
}
/*!
Returns the data download progress from 0 to 1.
*/
qreal QQmlDataBlob::progress() const
{
quint8 p = m_data.progress();
if (p == 0xFF) return 1.;
else return qreal(p) / qreal(0xFF);
}
/*!
Returns the physical url of the data. Initially this is the same as
finalUrl(), but if a URL interceptor is set, it will work on this URL
and leave finalUrl() alone.
\sa finalUrl()
*/
QUrl QQmlDataBlob::url() const
{
return m_url;
}
QString QQmlDataBlob::urlString() const
{
if (m_urlString.isEmpty())
m_urlString = m_url.toString();
return m_urlString;
}
/*!
Returns the logical URL to be used for resolving further URLs referred to in
the code.
This is the blob url passed to the constructor. If a URL interceptor rewrites
the URL, this one stays the same. If a network redirect happens while fetching
the data, this url is updated to reflect the new location. Therefore, if both
an interception and a redirection happen, the final url will indirectly
incorporate the result of the interception, potentially breaking further
lookups.
\sa url()
*/
QUrl QQmlDataBlob::finalUrl() const
{
return m_finalUrl;
}
/*!
Returns the finalUrl() as a string.
*/
QString QQmlDataBlob::finalUrlString() const
{
if (m_finalUrlString.isEmpty())
m_finalUrlString = m_finalUrl.toString();
return m_finalUrlString;
}
/*!
Return the errors on this blob.
May only be called from the load thread, or after the blob isCompleteOrError().
*/
QList<QQmlError> QQmlDataBlob::errors() const
{
Q_ASSERT(isCompleteOrError() || (m_typeLoader && m_typeLoader->m_thread->isThisThread()));
return m_errors;
}
/*!
Mark this blob as having \a errors.
All outstanding dependencies will be cancelled. Requests to add new dependencies
will be ignored. Entry into the Error state is irreversable.
The setError() method may only be called from within a QQmlDataBlob callback.
*/
void QQmlDataBlob::setError(const QQmlError &errors)
{
ASSERT_CALLBACK();
QList<QQmlError> l;
l << errors;
setError(l);
}
/*!
\overload
*/
void QQmlDataBlob::setError(const QList<QQmlError> &errors)
{
ASSERT_CALLBACK();
Q_ASSERT(status() != Error);
Q_ASSERT(m_errors.isEmpty());
m_errors = errors; // Must be set before the m_data fence
m_data.setStatus(Error);
if (dumpErrors()) {
qWarning().nospace() << "Errors for " << urlString();
for (int ii = 0; ii < errors.count(); ++ii)
qWarning().nospace() << " " << qPrintable(errors.at(ii).toString());
}
cancelAllWaitingFor();
if (!m_inCallback)
tryDone();
}
void QQmlDataBlob::setError(const QQmlJS::DiagnosticMessage &error)
{
QQmlError e;
e.setColumn(error.column);
e.setLine(error.line);
e.setDescription(error.message);
e.setUrl(url());
setError(e);
}
void QQmlDataBlob::setError(const QVector<QQmlJS::DiagnosticMessage> &errors)
{
QList<QQmlError> finalErrors;
finalErrors.reserve(errors.count());
for (const auto &error : errors) {
QQmlError e;
e.setColumn(error.column);
e.setLine(error.line);
e.setDescription(error.message);
e.setUrl(url());
finalErrors << e;
}
setError(finalErrors);
}
void QQmlDataBlob::setError(const QString &description)
{
QQmlError e;
e.setDescription(description);
e.setUrl(url());
setError(e);
}
/*!
Wait for \a blob to become complete or to error. If \a blob is already
complete or in error, or this blob is already complete, this has no effect.
The setError() method may only be called from within a QQmlDataBlob callback.
*/
void QQmlDataBlob::addDependency(QQmlDataBlob *blob)
{
ASSERT_CALLBACK();
Q_ASSERT(status() != Null);
if (!blob ||
blob->status() == Error || blob->status() == Complete ||
status() == Error || status() == Complete || m_isDone)
return;
for (auto existingDep: qAsConst(m_waitingFor))
if (existingDep.data() == blob)
return;
m_data.setStatus(WaitingForDependencies);
m_waitingFor.append(blob);
blob->m_waitingOnMe.append(this);
}
/*!
\fn void QQmlDataBlob::dataReceived(const Data &data)
Invoked when data for the blob is received. Implementors should use this callback
to determine a blob's dependencies. Within this callback you may call setError()
or addDependency().
*/
/*!
Invoked once data has either been received or a network error occurred, and all
dependencies are complete.
You can set an error in this method, but you cannot add new dependencies. Implementors
should use this callback to finalize processing of data.
The default implementation does nothing.
XXX Rename processData() or some such to avoid confusion between done() (processing thread)
and completed() (main thread)
*/
void QQmlDataBlob::done()
{
}
#if QT_CONFIG(qml_network)
/*!
Invoked if there is a network error while fetching this blob.
The default implementation sets an appropriate QQmlError.
*/
void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError)
{
Q_UNUSED(networkError);
QQmlError error;
error.setUrl(m_url);
const char *errorString = nullptr;
switch (networkError) {
default:
errorString = "Network error";
break;
case QNetworkReply::ConnectionRefusedError:
errorString = "Connection refused";
break;
case QNetworkReply::RemoteHostClosedError:
errorString = "Remote host closed the connection";
break;
case QNetworkReply::HostNotFoundError:
errorString = "Host not found";
break;
case QNetworkReply::TimeoutError:
errorString = "Timeout";
break;
case QNetworkReply::ProxyConnectionRefusedError:
case QNetworkReply::ProxyConnectionClosedError:
case QNetworkReply::ProxyNotFoundError:
case QNetworkReply::ProxyTimeoutError:
case QNetworkReply::ProxyAuthenticationRequiredError:
case QNetworkReply::UnknownProxyError:
errorString = "Proxy error";
break;
case QNetworkReply::ContentAccessDenied:
errorString = "Access denied";
break;
case QNetworkReply::ContentNotFoundError:
errorString = "File not found";
break;
case QNetworkReply::AuthenticationRequiredError:
errorString = "Authentication required";
break;
};
error.setDescription(QLatin1String(errorString));
setError(error);
}
#endif // qml_network
/*!
Called if \a blob, which was previously waited for, has an error.
The default implementation does nothing.
*/
void QQmlDataBlob::dependencyError(QQmlDataBlob *blob)
{
Q_UNUSED(blob);
}
/*!
Called if \a blob, which was previously waited for, has completed.
The default implementation does nothing.
*/
void QQmlDataBlob::dependencyComplete(QQmlDataBlob *blob)
{
Q_UNUSED(blob);
}
/*!
Called when all blobs waited for have completed. This occurs regardless of
whether they are in error, or complete state.
The default implementation does nothing.
*/
void QQmlDataBlob::allDependenciesDone()
{
m_data.setStatus(QQmlDataBlob::ResolvingDependencies);
}
/*!
Called when the download progress of this blob changes. \a progress goes
from 0 to 1.
This callback is only invoked if an asynchronous load for this blob is
made. An asynchronous load is one in which the Asynchronous mode is
specified explicitly, or one that is implicitly delayed due to a network
operation.
The default implementation does nothing.
*/
void QQmlDataBlob::downloadProgressChanged(qreal progress)
{
Q_UNUSED(progress);
}
/*!
Invoked on the main thread sometime after done() was called on the load thread.
You cannot modify the blobs state at all in this callback and cannot depend on the
order or timeliness of these callbacks. Implementors should use this callback to notify
dependencies on the main thread that the blob is done and not a lot else.
This callback is only invoked if an asynchronous load for this blob is
made. An asynchronous load is one in which the Asynchronous mode is
specified explicitly, or one that is implicitly delayed due to a network
operation.
The default implementation does nothing.
*/
void QQmlDataBlob::completed()
{
}
void QQmlDataBlob::tryDone()
{
if (status() != Loading && m_waitingFor.isEmpty() && !m_isDone) {
m_isDone = true;
addref();
#ifdef DATABLOB_DEBUG
qWarning("QQmlDataBlob::done() %s", qPrintable(urlString()));
#endif
done();
if (status() != Error)
m_data.setStatus(Complete);
notifyAllWaitingOnMe();
// Locking is not required here, as anyone expecting callbacks must
// already be protected against the blob being completed (as set above);
#ifdef DATABLOB_DEBUG
qWarning("QQmlDataBlob: Dispatching completed");
#endif
m_typeLoader->m_thread->callCompleted(this);
release();
}
}
void QQmlDataBlob::cancelAllWaitingFor()
{
while (m_waitingFor.count()) {
QQmlRefPointer<QQmlDataBlob> blob = m_waitingFor.takeLast();
Q_ASSERT(blob->m_waitingOnMe.contains(this));
blob->m_waitingOnMe.removeOne(this);
}
}
void QQmlDataBlob::notifyAllWaitingOnMe()
{
while (m_waitingOnMe.count()) {
QQmlDataBlob *blob = m_waitingOnMe.takeLast();
Q_ASSERT(std::any_of(blob->m_waitingFor.constBegin(), blob->m_waitingFor.constEnd(),
[this](const QQmlRefPointer<QQmlDataBlob> &waiting) { return waiting.data() == this; }));
blob->notifyComplete(this);
}
}
void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
{
Q_ASSERT(blob->status() == Error || blob->status() == Complete);
QQmlCompilingProfiler prof(typeLoader()->profiler(), blob);
m_inCallback = true;
QQmlRefPointer<QQmlDataBlob> blobRef;
for (int i = 0; i < m_waitingFor.count(); ++i) {
if (m_waitingFor.at(i).data() == blob) {
blobRef = m_waitingFor.takeAt(i);
break;
}
}
Q_ASSERT(blobRef);
if (blob->status() == Error) {
dependencyError(blob);
} else if (blob->status() == Complete) {
dependencyComplete(blob);
}
if (!isError() && m_waitingFor.isEmpty())
allDependenciesDone();
m_inCallback = false;
tryDone();
}
QString QQmlDataBlob::SourceCodeData::readAll(QString *error) const
{
error->clear();
if (hasInlineSourceCode)
return inlineSourceCode;
QFile f(fileInfo.absoluteFilePath());
if (!f.open(QIODevice::ReadOnly)) {
*error = f.errorString();
return QString();
}
const qint64 fileSize = fileInfo.size();
if (uchar *mappedData = f.map(0, fileSize)) {
QString source = QString::fromUtf8(reinterpret_cast<const char *>(mappedData), fileSize);
f.unmap(mappedData);
return source;
}
QByteArray data(fileSize, Qt::Uninitialized);
if (f.read(data.data(), data.length()) != data.length()) {
*error = f.errorString();
return QString();
}
return QString::fromUtf8(data);
}
QDateTime QQmlDataBlob::SourceCodeData::sourceTimeStamp() const
{
if (hasInlineSourceCode)
return QDateTime();
return fileInfo.lastModified();
}
bool QQmlDataBlob::SourceCodeData::exists() const
{
if (hasInlineSourceCode)
return true;
return fileInfo.exists();
}
bool QQmlDataBlob::SourceCodeData::isEmpty() const
{
if (hasInlineSourceCode)
return inlineSourceCode.isEmpty();
return fileInfo.size() == 0;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,257 @@
/****************************************************************************
**
** 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 QQMLDATABLOB_P_H
#define QQMLDATABLOB_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/qqmlrefcount_p.h>
#include <private/qqmljsdiagnosticmessage_p.h>
#include <private/qv4compileddata_p.h>
#if QT_CONFIG(qml_network)
#include <QtNetwork/qnetworkreply.h>
#endif
#include <QtQml/qqmlerror.h>
#include <QtQml/qqmlabstracturlinterceptor.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qurl.h>
QT_BEGIN_NAMESPACE
class QQmlTypeLoader;
class Q_QML_PRIVATE_EXPORT QQmlDataBlob : public QQmlRefCount
{
public:
enum Status {
Null, // Prior to QQmlTypeLoader::load()
Loading, // Prior to data being received and dataReceived() being called
WaitingForDependencies, // While there are outstanding addDependency()s
ResolvingDependencies, // While resolving outstanding dependencies, to detect cycles
Complete, // Finished
Error // Error
};
enum Type { //Matched in QQmlAbstractUrlInterceptor
QmlFile = QQmlAbstractUrlInterceptor::QmlFile,
JavaScriptFile = QQmlAbstractUrlInterceptor::JavaScriptFile,
QmldirFile = QQmlAbstractUrlInterceptor::QmldirFile
};
QQmlDataBlob(const QUrl &, Type, QQmlTypeLoader* manager);
~QQmlDataBlob() override;
void startLoading();
QQmlTypeLoader *typeLoader() const { return m_typeLoader; }
Type type() const;
Status status() const;
bool isNull() const;
bool isLoading() const;
bool isWaiting() const;
bool isComplete() const;
bool isError() const;
bool isCompleteOrError() const;
qreal progress() const;
QUrl url() const;
QString urlString() const;
QUrl finalUrl() const;
QString finalUrlString() const;
QList<QQmlError> errors() const;
class SourceCodeData {
public:
QString readAll(QString *error) const;
QDateTime sourceTimeStamp() const;
bool exists() const;
bool isEmpty() const;
private:
friend class QQmlDataBlob;
friend class QQmlTypeLoader;
QString inlineSourceCode;
QFileInfo fileInfo;
bool hasInlineSourceCode = false;
};
protected:
// Can be called from within callbacks
void setError(const QQmlError &);
void setError(const QList<QQmlError> &errors);
void setError(const QQmlJS::DiagnosticMessage &error);
void setError(const QVector<QQmlJS::DiagnosticMessage> &errors);
void setError(const QString &description);
void addDependency(QQmlDataBlob *);
// Callbacks made in load thread
virtual void dataReceived(const SourceCodeData &) = 0;
virtual void initializeFromCachedUnit(const QV4::CompiledData::Unit*) = 0;
virtual void done();
#if QT_CONFIG(qml_network)
virtual void networkError(QNetworkReply::NetworkError);
#endif
virtual void dependencyError(QQmlDataBlob *);
virtual void dependencyComplete(QQmlDataBlob *);
virtual void allDependenciesDone();
// Callbacks made in main thread
virtual void downloadProgressChanged(qreal);
virtual void completed();
protected:
// Manager that is currently fetching data for me
QQmlTypeLoader *m_typeLoader;
private:
friend class QQmlTypeLoader;
friend class QQmlTypeLoaderThread;
void tryDone();
void cancelAllWaitingFor();
void notifyAllWaitingOnMe();
void notifyComplete(QQmlDataBlob *);
struct ThreadData {
private:
enum {
StatusMask = 0x0000FFFF,
StatusShift = 0,
ProgressMask = 0x00FF0000,
ProgressShift = 16,
AsyncMask = 0x80000000,
NoMask = 0
};
public:
inline ThreadData()
: _p(0)
{
}
inline QQmlDataBlob::Status status() const
{
return QQmlDataBlob::Status((_p.loadRelaxed() & StatusMask) >> StatusShift);
}
inline void setStatus(QQmlDataBlob::Status status)
{
while (true) {
int d = _p.loadRelaxed();
int nd = (d & ~StatusMask) | ((status << StatusShift) & StatusMask);
if (d == nd || _p.testAndSetOrdered(d, nd)) return;
}
}
inline bool isAsync() const
{
return _p.loadRelaxed() & AsyncMask;
}
inline void setIsAsync(bool v)
{
while (true) {
int d = _p.loadRelaxed();
int nd = (d & ~AsyncMask) | (v ? AsyncMask : NoMask);
if (d == nd || _p.testAndSetOrdered(d, nd)) return;
}
}
inline quint8 progress() const
{
return quint8((_p.loadRelaxed() & ProgressMask) >> ProgressShift);
}
inline void setProgress(quint8 v)
{
while (true) {
int d = _p.loadRelaxed();
int nd = (d & ~ProgressMask) | ((v << ProgressShift) & ProgressMask);
if (d == nd || _p.testAndSetOrdered(d, nd)) return;
}
}
private:
QAtomicInt _p;
};
ThreadData m_data;
// m_errors should *always* be written before the status is set to Error.
// We use the status change as a memory fence around m_errors so that locking
// isn't required. Once the status is set to Error (or Complete), m_errors
// cannot be changed.
QList<QQmlError> m_errors;
Type m_type;
QUrl m_url;
QUrl m_finalUrl;
mutable QString m_urlString;
mutable QString m_finalUrlString;
// List of QQmlDataBlob's that are waiting for me to complete.
QList<QQmlDataBlob *> m_waitingOnMe;
// List of QQmlDataBlob's that I am waiting for to complete.
QVector<QQmlRefPointer<QQmlDataBlob>> m_waitingFor;
int m_redirectCount:30;
bool m_inCallback:1;
bool m_isDone:1;
};
QT_END_NAMESPACE
#endif // QQMLDATABLOB_P_H

View File

@ -43,6 +43,7 @@
#include <private/qv4value_p.h>
#include <private/qv4jscall_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <private/qv4qmlcontext_p.h>
#include <QQmlError>

View File

@ -0,0 +1,96 @@
/****************************************************************************
**
** 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$
**
****************************************************************************/
#include <private/qqmldirdata_p.h>
QT_BEGIN_NAMESPACE
QQmlQmldirData::QQmlQmldirData(const QUrl &url, QQmlTypeLoader *loader)
: QQmlTypeLoader::Blob(url, QmldirFile, loader)
{
}
const QString &QQmlQmldirData::content() const
{
return m_content;
}
const QV4::CompiledData::Import *QQmlQmldirData::import(QQmlTypeLoader::Blob *blob) const
{
QHash<QQmlTypeLoader::Blob *, const QV4::CompiledData::Import *>::const_iterator it =
m_imports.find(blob);
if (it == m_imports.end())
return nullptr;
return *it;
}
void QQmlQmldirData::setImport(QQmlTypeLoader::Blob *blob, const QV4::CompiledData::Import *import)
{
m_imports[blob] = import;
}
int QQmlQmldirData::priority(QQmlTypeLoader::Blob *blob) const
{
QHash<QQmlTypeLoader::Blob *, int>::const_iterator it = m_priorities.find(blob);
if (it == m_priorities.end())
return 0;
return *it;
}
void QQmlQmldirData::setPriority(QQmlTypeLoader::Blob *blob, int priority)
{
m_priorities[blob] = priority;
}
void QQmlQmldirData::dataReceived(const SourceCodeData &data)
{
QString error;
m_content = data.readAll(&error);
if (!error.isEmpty()) {
setError(error);
return;
}
}
void QQmlQmldirData::initializeFromCachedUnit(const QV4::CompiledData::Unit *)
{
Q_UNIMPLEMENTED();
}
QT_END_NAMESPACE

View File

@ -0,0 +1,86 @@
/****************************************************************************
**
** 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 QQMLDIRDATA_P_H
#define QQMLDIRDATA_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/qqmltypeloader_p.h>
QT_BEGIN_NAMESPACE
class Q_AUTOTEST_EXPORT QQmlQmldirData : public QQmlTypeLoader::Blob
{
private:
friend class QQmlTypeLoader;
QQmlQmldirData(const QUrl &, QQmlTypeLoader *);
public:
const QString &content() const;
const QV4::CompiledData::Import *import(QQmlTypeLoader::Blob *) const;
void setImport(QQmlTypeLoader::Blob *, const QV4::CompiledData::Import *);
int priority(QQmlTypeLoader::Blob *) const;
void setPriority(QQmlTypeLoader::Blob *, int);
protected:
void dataReceived(const SourceCodeData &) override;
void initializeFromCachedUnit(const QV4::CompiledData::Unit *) override;
private:
QString m_content;
QHash<QQmlTypeLoader::Blob *, const QV4::CompiledData::Import *> m_imports;
QHash<QQmlTypeLoader::Blob *, int> m_priorities;
};
QT_END_NAMESPACE
#endif // QQMLDIRDATA_P_H

View File

@ -51,14 +51,15 @@
#include "qqmlscriptstring.h"
#include "qqmlglobal_p.h"
#include "qqmlcomponent_p.h"
#include "qqmldirparser_p.h"
#include "qqmlextensioninterface.h"
#include "qqmllist_p.h"
#include "qqmltypenamecache_p.h"
#include "qqmlnotifier_p.h"
#include "qqmlincubator.h"
#include "qqmlabstracturlinterceptor.h"
#include <private/qqmldirparser_p.h>
#include <private/qqmlboundsignal_p.h>
#include <private/qqmljsdiagnosticmessage_p.h>
#include <QtCore/qstandardpaths.h>
#include <QtCore/qsettings.h>
#include <QtCore/qmetaobject.h>
@ -1790,7 +1791,7 @@ void QQmlData::deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCo
deferData->context = context;
const QV4::CompiledData::Object *compiledObject = compilationUnit->objectAt(objectIndex);
const QV4::CompiledData::BindingPropertyData &propertyData = compilationUnit->bindingPropertyDataPerObject.at(objectIndex);
const QV4::BindingPropertyData &propertyData = compilationUnit->bindingPropertyDataPerObject.at(objectIndex);
const QV4::CompiledData::Binding *binding = compiledObject->bindingTable();
for (quint32 i = 0; i < compiledObject->nBindings; ++i, ++binding) {
@ -2115,10 +2116,11 @@ void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError
dumpwarning(error);
}
QList<QQmlError> QQmlEnginePrivate::qmlErrorFromDiagnostics(const QString &fileName, const QList<DiagnosticMessage> &diagnosticMessages)
QList<QQmlError> QQmlEnginePrivate::qmlErrorFromDiagnostics(
const QString &fileName, const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages)
{
QList<QQmlError> errors;
for (const DiagnosticMessage &m : diagnosticMessages) {
for (const QQmlJS::DiagnosticMessage &m : diagnosticMessages) {
if (m.isWarning()) {
qWarning("%s:%d : %s", qPrintable(fileName), m.line, qPrintable(m.message));
continue;
@ -2325,6 +2327,17 @@ QString QQmlEngine::offlineStorageDatabaseFilePath(const QString &databaseName)
return d->offlineStorageDatabaseDirectory() + QLatin1String(md5.result().toHex());
}
// #### Qt 6: Remove this function, it exists only for binary compatibility.
/*!
* \internal
*/
bool QQmlEngine::addNamedBundle(const QString &name, const QString &fileName)
{
Q_UNUSED(name)
Q_UNUSED(fileName)
return false;
}
QString QQmlEnginePrivate::offlineStorageDatabaseDirectory() const
{
Q_Q(const QQmlEngine);

View File

@ -66,6 +66,7 @@
#include <private/qintrusivelist_p.h>
#include <private/qrecyclepool_p.h>
#include <private/qfieldlist_p.h>
#include <private/qv4engine_p.h>
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>

View File

@ -46,6 +46,7 @@
#include "qqmlscriptstring_p.h"
#include "qqmlbinding_p.h"
#include <private/qqmlsourcecoordinate_p.h>
#include <private/qv4qmlcontext_p.h>
#include <QtCore/qdebug.h>

View File

@ -55,6 +55,7 @@
#include <private/qqmlengine_p.h>
#include <private/qfieldlist_p.h>
#include <private/qqmltypemodule_p.h>
#include <private/qqmltypeloaderqmldircontent_p.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonarray.h>

View File

@ -40,6 +40,7 @@
#ifndef QQMLINFO_H
#define QQMLINFO_H
#include <QtQml/qtqmlglobal.h>
#include <QtCore/qdebug.h>
#include <QtCore/qurl.h>
#include <QtQml/qqmlerror.h>

View File

@ -136,10 +136,10 @@ QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *seriali
QmlIR::Signal *s = pool->New<QmlIR::Signal>();
s->nameIndex = serializedSignal->nameIndex;
s->location = serializedSignal->location;
s->parameters = pool->New<QmlIR::PoolList<QmlIR::SignalParameter> >();
s->parameters = pool->New<QmlIR::PoolList<QmlIR::Parameter> >();
for (uint i = 0; i < serializedSignal->nParameters; ++i) {
QmlIR::SignalParameter *p = pool->New<QmlIR::SignalParameter>();
QmlIR::Parameter *p = pool->New<QmlIR::Parameter>();
*static_cast<QV4::CompiledData::Parameter*>(p) = *serializedSignal->parameterAt(i);
s->parameters->append(p);
}
@ -188,11 +188,12 @@ QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *seriali
f->index = functionIndices.count() - 1;
f->location = compiledFunction->location;
f->nameIndex = compiledFunction->nameIndex;
f->returnType = compiledFunction->returnType;
f->formals.allocate(pool, int(compiledFunction->nFormals));
const quint32_le *formalNameIdx = compiledFunction->formalsTable();
const QV4::CompiledData::Parameter *formalNameIdx = compiledFunction->formalsTable();
for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
f->formals[i] = *formalNameIdx;
*static_cast<QV4::CompiledData::Parameter*>(&f->formals[i]) = *formalNameIdx;
object->functions->append(f);
}

View File

@ -44,6 +44,7 @@
#include <private/qqmltype_p_p.h>
#include <private/qqmltypeloader_p.h>
#include <private/qqmlextensionplugin_p.h>
#include <private/qv4executablecompilationunit_p.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qmutex.h>

View File

@ -55,6 +55,7 @@
#include <private/qqmlvaluetypeproxybinding_p.h>
#include <private/qqmldebugconnector_p.h>
#include <private/qqmldebugserviceinterfaces_p.h>
#include <private/qqmlscriptdata_p.h>
#include <private/qjsvalue_p.h>
#include <qtqml_tracepoints_p.h>
@ -735,7 +736,7 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
QQmlListProperty<void> savedList;
qSwap(_currentList, savedList);
const QV4::CompiledData::BindingPropertyData &propertyData = compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex);
const QV4::BindingPropertyData &propertyData = compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex);
if (_compiledObject->idNameIndex) {
const QQmlPropertyData *idProperty = propertyData.last();
@ -1445,8 +1446,12 @@ void QQmlObjectCreator::clear()
return;
Q_ASSERT(phase != Startup);
while (!sharedState->allCreatedObjects.isEmpty())
delete sharedState->allCreatedObjects.pop();
while (!sharedState->allCreatedObjects.isEmpty()) {
auto object = sharedState->allCreatedObjects.pop();
if (engine->objectOwnership(object) != QQmlEngine::CppOwnership) {
delete object;
}
}
while (sharedState->componentAttached) {
QQmlComponentAttached *a = sharedState->componentAttached;

View File

@ -53,17 +53,16 @@
#include <private/qqmlimport_p.h>
#include <private/qqmltypenamecache_p.h>
#include <private/qv4compileddata_p.h>
#include <private/qqmltypecompiler_p.h>
#include <private/qfinitestack_p.h>
#include <private/qrecursionwatcher_p.h>
#include <private/qqmlprofiler_p.h>
#include <private/qv4qmlcontext_p.h>
#include <qpointer.h>
QT_BEGIN_NAMESPACE
class QQmlAbstractBinding;
struct QQmlTypeCompiler;
class QQmlInstantiationInterrupt;
class QQmlIncubatorPrivate;

Some files were not shown because too many files have changed in this diff Show More