aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/ftw/qflagpointer_p.h8
-rw-r--r--src/qml/qml/ftw/qqmlrefcount_p.h20
-rw-r--r--src/qml/qml/qml.pri21
-rw-r--r--src/qml/qml/qqml.h2
-rw-r--r--src/qml/qml/qqmlbinding.cpp11
-rw-r--r--src/qml/qml/qqmlbinding_p.h3
-rw-r--r--src/qml/qml/qqmlcomponent.cpp28
-rw-r--r--src/qml/qml/qqmlcomponent_p.h7
-rw-r--r--src/qml/qml/qqmldata_p.h2
-rw-r--r--src/qml/qml/qqmldirparser.cpp9
-rw-r--r--src/qml/qml/qqmldirparser_p.h3
-rw-r--r--src/qml/qml/qqmlengine.cpp90
-rw-r--r--src/qml/qml/qqmlengine.h16
-rw-r--r--src/qml/qml/qqmlguard_p.h28
-rw-r--r--src/qml/qml/qqmlimport.cpp20
-rw-r--r--src/qml/qml/qqmlimport_p.h3
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp10
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h17
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp13
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h4
-rw-r--r--src/qml/qml/qqmllocale.cpp4
-rw-r--r--src/qml/qml/qqmllocale_p.h2
-rw-r--r--src/qml/qml/qqmlmetatype.cpp59
-rw-r--r--src/qml/qml/qqmlmetatype_p.h7
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp35
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h4
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp122
-rw-r--r--src/qml/qml/qqmlopenmetaobject_p.h5
-rw-r--r--src/qml/qml/qqmlproperty.cpp2
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h6
-rw-r--r--src/qml/qml/qqmltypeloader.cpp128
-rw-r--r--src/qml/qml/qqmltypeloader_p.h41
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp51
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h10
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp25
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h6
-rw-r--r--src/qml/qml/qqmlvme_p.h4
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp6
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h6
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp29
-rw-r--r--src/qml/qml/qqmlxmlhttprequest_p.h4
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp28
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h4
-rw-r--r--src/qml/qml/v8/qv8engine.cpp33
-rw-r--r--src/qml/qml/v8/qv8engine_p.h9
46 files changed, 616 insertions, 331 deletions
diff --git a/src/qml/qml/ftw/qflagpointer_p.h b/src/qml/qml/ftw/qflagpointer_p.h
index 91ce74bec9..71b41cd30b 100644
--- a/src/qml/qml/ftw/qflagpointer_p.h
+++ b/src/qml/qml/ftw/qflagpointer_p.h
@@ -82,6 +82,8 @@ public:
inline T *data() const;
+ inline explicit operator bool() const;
+
private:
quintptr ptr_value = 0;
@@ -230,6 +232,12 @@ T *QFlagPointer<T>::data() const
return (T *)(ptr_value & ~FlagsMask);
}
+template<typename T>
+QFlagPointer<T>::operator bool() const
+{
+ return data() != nullptr;
+}
+
template<typename T, typename T2>
QBiPointer<T, T2>::QBiPointer()
{
diff --git a/src/qml/qml/ftw/qqmlrefcount_p.h b/src/qml/qml/ftw/qqmlrefcount_p.h
index 3cfb345b30..d32a08e0f5 100644
--- a/src/qml/qml/ftw/qqmlrefcount_p.h
+++ b/src/qml/qml/ftw/qqmlrefcount_p.h
@@ -85,19 +85,23 @@ public:
inline QQmlRefPointer();
inline QQmlRefPointer(T *, Mode m = AddRef);
inline QQmlRefPointer(const QQmlRefPointer<T> &);
+ inline QQmlRefPointer(QQmlRefPointer<T> &&);
inline ~QQmlRefPointer();
inline QQmlRefPointer<T> &operator=(const QQmlRefPointer<T> &o);
+ inline QQmlRefPointer<T> &operator=(QQmlRefPointer<T> &&o);
inline bool isNull() const { return !o; }
inline T* operator->() const { return o; }
inline T& operator*() const { return *o; }
- inline operator T*() const { return o; }
+ explicit inline operator bool() const { return o != nullptr; }
inline T* data() const { return o; }
inline QQmlRefPointer<T> &adopt(T *);
+ inline T* take() { T *res = o; o = nullptr; return res; }
+
private:
T *o;
};
@@ -156,6 +160,12 @@ QQmlRefPointer<T>::QQmlRefPointer(const QQmlRefPointer<T> &other)
if (o) o->addref();
}
+template <class T>
+QQmlRefPointer<T>::QQmlRefPointer(QQmlRefPointer<T> &&other)
+ : o(other.take())
+{
+}
+
template<class T>
QQmlRefPointer<T>::~QQmlRefPointer()
{
@@ -171,6 +181,14 @@ QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(const QQmlRefPointer<T> &other)
return *this;
}
+template <class T>
+QQmlRefPointer<T> &QQmlRefPointer<T>::operator=(QQmlRefPointer<T> &&other)
+{
+ QQmlRefPointer<T> m(std::move(other));
+ qSwap(o, m.o);
+ return *this;
+}
+
/*!
Takes ownership of \a other. take() does *not* add a reference, as it assumes ownership
of the callers reference of other.
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 412dc6cba2..6d69294c17 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -20,7 +20,6 @@ SOURCES += \
$$PWD/qqmlinfo.cpp \
$$PWD/qqmlerror.cpp \
$$PWD/qqmlvaluetype.cpp \
- $$PWD/qqmlxmlhttprequest.cpp \
$$PWD/qqmlcleanup.cpp \
$$PWD/qqmlpropertycache.cpp \
$$PWD/qqmlnotifier.cpp \
@@ -31,7 +30,6 @@ SOURCES += \
$$PWD/qqmlextensionplugin.cpp \
$$PWD/qqmlimport.cpp \
$$PWD/qqmllist.cpp \
- $$PWD/qqmllocale.cpp \
$$PWD/qqmljavascriptexpression.cpp \
$$PWD/qqmlabstractbinding.cpp \
$$PWD/qqmlvaluetypeproxybinding.cpp \
@@ -85,7 +83,6 @@ HEADERS += \
$$PWD/qqmldata_p.h \
$$PWD/qqmlerror.h \
$$PWD/qqmlvaluetype_p.h \
- $$PWD/qqmlxmlhttprequest_p.h \
$$PWD/qqmlcleanup_p.h \
$$PWD/qqmlpropertycache_p.h \
$$PWD/qqmlpropertyindex_p.h \
@@ -99,7 +96,6 @@ HEADERS += \
$$PWD/qqmlimport_p.h \
$$PWD/qqmlextensionplugin.h \
$$PWD/qqmlscriptstring_p.h \
- $$PWD/qqmllocale_p.h \
$$PWD/qqmlcomponentattached_p.h \
$$PWD/qqmljavascriptexpression_p.h \
$$PWD/qqmlabstractbinding_p.h \
@@ -120,5 +116,22 @@ HEADERS += \
$$PWD/qqmldelayedcallqueue_p.h \
$$PWD/qqmlloggingcategory_p.h
+qtConfig(qml-xml-http-request) {
+ HEADERS += \
+ $$PWD/qqmlxmlhttprequest_p.h
+
+ SOURCES += \
+ $$PWD/qqmlxmlhttprequest.cpp
+
+}
+
+qtConfig(qml-locale) {
+ HEADERS += \
+ $$PWD/qqmllocale_p.h
+
+ SOURCES += \
+ $$PWD/qqmllocale.cpp
+}
+
include(ftw/ftw.pri)
include(v8/v8.pri)
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 213f23cd98..2a8e236905 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -645,6 +645,8 @@ inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, i
return QQmlPrivate::qmlregister(QQmlPrivate::CompositeRegistration, &type);
}
+int Q_QML_EXPORT qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
+
QT_END_NAMESPACE
QML_DECLARE_TYPE(QObject)
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 30a18440a8..a4b3f1f4e4 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -337,7 +337,7 @@ protected:
class QQmlTranslationBinding : public GenericBinding<QMetaType::QString> {
public:
- QQmlTranslationBinding(QV4::CompiledData::CompilationUnit *compilationUnit, const QV4::CompiledData::Binding *binding)
+ QQmlTranslationBinding(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
{
setCompilationUnit(compilationUnit);
m_binding = binding;
@@ -374,11 +374,13 @@ public:
}
}
+ bool hasDependencies() const override final { return true; }
+
private:
const QV4::CompiledData::Binding *m_binding;
};
-QQmlBinding *QQmlBinding::createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
+QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
{
QQmlTranslationBinding *b = new QQmlTranslationBinding(unit, binding);
@@ -663,6 +665,11 @@ QVector<QQmlProperty> QQmlBinding::dependencies() const
return dependencies;
}
+bool QQmlBinding::hasDependencies() const
+{
+ return !permanentGuards.isEmpty() || !activeGuards.isEmpty() || translationsCaptured();
+}
+
class QObjectPointerBinding: public QQmlNonbindingBinding
{
QQmlMetaObject targetMetaObject;
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index a1295bd0ac..f192de4342 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -79,7 +79,7 @@ public:
const QString &url = QString(), quint16 lineNumber = 0);
static QQmlBinding *create(const QQmlPropertyData *property, QV4::Function *function,
QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope);
- static QQmlBinding *createTranslationBinding(QV4::CompiledData::CompilationUnit *unit, const QV4::CompiledData::Binding *binding,
+ static QQmlBinding *createTranslationBinding(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, const QV4::CompiledData::Binding *binding,
QObject *obj, QQmlContextData *ctxt);
~QQmlBinding() override;
@@ -118,6 +118,7 @@ public:
* Call this method from the UI thread.
*/
QVector<QQmlProperty> dependencies() const;
+ virtual bool hasDependencies() const;
protected:
virtual void doUpdate(const DeleteWatcher &watcher,
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 8885e69161..96f6c6aed6 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -334,7 +334,7 @@ void QQmlComponentPrivate::typeDataProgress(QQmlTypeData *, qreal p)
emit q->progressChanged(p);
}
-void QQmlComponentPrivate::fromTypeData(QQmlTypeData *data)
+void QQmlComponentPrivate::fromTypeData(const QQmlRefPointer<QQmlTypeData> &data)
{
url = data->finalUrl();
compilationUnit = data->compilationUnit();
@@ -343,15 +343,12 @@ void QQmlComponentPrivate::fromTypeData(QQmlTypeData *data)
Q_ASSERT(data->isError());
state.errors = data->errors();
}
-
- data->release();
}
void QQmlComponentPrivate::clear()
{
if (typeData) {
typeData->unregisterCallback(this);
- typeData->release();
typeData = nullptr;
}
@@ -387,7 +384,7 @@ QQmlComponent::~QQmlComponent()
if (d->typeData) {
d->typeData->unregisterCallback(d);
- d->typeData->release();
+ d->typeData = nullptr;
}
}
@@ -580,7 +577,7 @@ void QQmlComponent::setData(const QByteArray &data, const QUrl &url)
d->url = url;
- QQmlTypeData *typeData = QQmlEnginePrivate::get(d->engine)->typeLoader.getType(data, url);
+ QQmlRefPointer<QQmlTypeData> typeData = QQmlEnginePrivate::get(d->engine)->typeLoader.getType(data, url);
if (typeData->isCompleteOrError()) {
d->fromTypeData(typeData);
@@ -667,7 +664,7 @@ void QQmlComponentPrivate::loadUrl(const QUrl &newUrl, QQmlComponent::Compilatio
? QQmlTypeLoader::Asynchronous
: QQmlTypeLoader::PreferSynchronous;
- QQmlTypeData *data = QQmlEnginePrivate::get(engine)->typeLoader.getType(url, loaderMode);
+ QQmlRefPointer<QQmlTypeData> data = QQmlEnginePrivate::get(engine)->typeLoader.getType(url, loaderMode);
if (data->isCompleteOrError()) {
fromTypeData(data);
@@ -848,13 +845,10 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
// Do not create infinite recursion in object creation
static const int maxCreationDepth = 10;
- if (++creationDepth.localData() >= maxCreationDepth) {
+ if (creationDepth.localData() >= maxCreationDepth) {
qWarning("QQmlComponent: Component creation is recursing - aborting");
- --creationDepth.localData();
return nullptr;
}
- Q_ASSERT(creationDepth.localData() >= 1);
- depthIncreased = true;
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
@@ -878,10 +872,6 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
ddata->indestructible = true;
ddata->explicitIndestructibleSet = true;
ddata->rootObjectInCreation = false;
- } else {
- Q_ASSERT(creationDepth.localData() >= 1);
- --creationDepth.localData();
- depthIncreased = false;
}
return rv;
@@ -955,14 +945,10 @@ void QQmlComponent::completeCreate()
void QQmlComponentPrivate::completeCreate()
{
if (state.completePending) {
+ ++creationDepth.localData();
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
complete(ep, &state);
- }
-
- if (depthIncreased) {
- Q_ASSERT(creationDepth.localData() >= 1);
--creationDepth.localData();
- depthIncreased = false;
}
}
@@ -1421,7 +1407,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
QQmlComponentExtension *e = componentExtension(args->v4engine());
- QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocObject<QV4::QmlIncubatorObject>(mode));
+ QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->allocate<QV4::QmlIncubatorObject>(mode));
QV4::ScopedObject p(scope, e->incubationProto.value());
r->setPrototype(p);
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index 2a8d36f317..9b2db4bccf 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -79,7 +79,7 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public
public:
QQmlComponentPrivate()
- : typeData(nullptr), progress(0.), start(-1), engine(nullptr), creationContext(nullptr), depthIncreased(false) {}
+ : progress(0.), start(-1), engine(nullptr), creationContext(nullptr) {}
void loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous);
@@ -95,11 +95,11 @@ public:
QQmlContextData *context,
QQmlContextData *forContext);
- QQmlTypeData *typeData;
+ QQmlRefPointer<QQmlTypeData> typeData;
void typeDataReady(QQmlTypeData *) override;
void typeDataProgress(QQmlTypeData *, qreal) override;
- void fromTypeData(QQmlTypeData *data);
+ void fromTypeData(const QQmlRefPointer<QQmlTypeData> &data);
QUrl url;
qreal progress;
@@ -136,7 +136,6 @@ public:
QQmlEngine *engine;
QQmlGuardedContextData creationContext;
- bool depthIncreased;
void clear();
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 59fefde893..2468de6857 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -232,7 +232,7 @@ public:
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
QVector<DeferredData *> deferredData;
- void deferData(int objectIndex, QV4::CompiledData::CompilationUnit *, QQmlContextData *);
+ void deferData(int objectIndex, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &, QQmlContextData *);
void releaseDeferredData();
QV4::WeakValue jsWrapper;
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index 4cca8a4d58..8c89cf0e61 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -107,6 +107,7 @@ bool QQmlDirParser::parse(const QString &source)
_components.clear();
_scripts.clear();
_designerSupported = false;
+ _className.clear();
quint16 lineNumber = 0;
bool firstLine = true;
@@ -196,7 +197,8 @@ bool QQmlDirParser::parse(const QString &source)
continue;
}
- // Ignore these. qmlimportscanner uses them.
+ _className = sections[1];
+
} else if (sections[0] == QLatin1String("internal")) {
if (sectionCount != 3) {
reportError(lineNumber, 0,
@@ -377,6 +379,11 @@ bool QQmlDirParser::designerSupported() const
return _designerSupported;
}
+QString QQmlDirParser::className() const
+{
+ return _className;
+}
+
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
{
const QString output = QStringLiteral("{%1 %2.%3}").
diff --git a/src/qml/qml/qqmldirparser_p.h b/src/qml/qml/qqmldirparser_p.h
index 820c40238d..d7e29813d1 100644
--- a/src/qml/qml/qqmldirparser_p.h
+++ b/src/qml/qml/qqmldirparser_p.h
@@ -135,6 +135,8 @@ public:
QList<TypeInfo> typeInfos() const;
#endif
+ QString className() const;
+
private:
bool maybeAddComponent(const QString &typeName, const QString &fileName, const QString &version, QHash<QString,Component> &hash, int lineNumber = -1, bool multi = true);
void reportError(quint16 line, quint16 column, const QString &message);
@@ -150,6 +152,7 @@ private:
#ifdef QT_CREATOR
QList<TypeInfo> _typeInfos;
#endif
+ QString _className;
};
typedef QHash<QString,QQmlDirParser::Component> QQmlDirComponents;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index c6b39581a7..759d86c789 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -48,7 +48,6 @@
#include "qqmlcomponent.h"
#include "qqmlvme_p.h"
#include "qqmlstringconverters_p.h"
-#include "qqmlxmlhttprequest_p.h"
#include "qqmlscriptstring.h"
#include "qqmlglobal_p.h"
#include "qqmlcomponent_p.h"
@@ -79,13 +78,17 @@
#include <private/qobject_p.h>
#include <private/qmetaobject_p.h>
+#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
+#endif
#include <private/qqmlbind_p.h>
#include <private/qqmlconnections_p.h>
-#if QT_CONFIG(animation)
+#if QT_CONFIG(qml_animation)
#include <private/qqmltimer_p.h>
#endif
+#if QT_CONFIG(qml_list_model)
#include <private/qqmllistmodel_p.h>
+#endif
#include <private/qqmlplatform_p.h>
#include <private/qquickpackage_p.h>
#if QT_CONFIG(qml_delegate_model)
@@ -219,7 +222,7 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int
qmlRegisterType<QQmlBind,8>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "Binding"); //Only available in >=2.8
qmlRegisterType<QQmlConnections,1>(uri, versionMajor, (versionMinor < 3 ? 3 : versionMinor), "Connections"); //Only available in >=2.3
qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections");
-#if QT_CONFIG(animation)
+#if QT_CONFIG(qml_animation)
qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer");
#endif
qmlRegisterType<QQmlInstantiator>(uri, versionMajor, (versionMinor < 1 ? 1 : versionMinor), "Instantiator"); //Only available in >=2.1
@@ -232,8 +235,10 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int
// These QtQuick types' implementation resides in the QtQml module
void QQmlEnginePrivate::registerQtQuick2Types(const char *uri, int versionMajor, int versionMinor)
{
+#if QT_CONFIG(qml_list_model)
qmlRegisterType<QQmlListElement>(uri, versionMajor, versionMinor, "ListElement"); // Now in QtQml.Models, here for compatibility
qmlRegisterCustomType<QQmlListModel>(uri, versionMajor, versionMinor, "ListModel", new QQmlListModelParser); // Now in QtQml.Models, here for compatibility
+#endif
qmlRegisterType<QQuickWorkerScript>(uri, versionMajor, versionMinor, "WorkerScript");
qmlRegisterType<QQuickPackage>(uri, versionMajor, versionMinor, "Package");
#if QT_CONFIG(qml_delegate_model)
@@ -250,7 +255,9 @@ void QQmlEnginePrivate::defineQtQuick2Module()
// register the QtQuick2 types which are implemented in the QtQml module.
registerQtQuick2Types("QtQuick",2,0);
+#if QT_CONFIG(qml_locale)
qmlRegisterUncreatableType<QQmlLocale>("QtQuick", 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
+#endif
// Auto-increment the import to stay in sync with ALL future QtQuick minor versions from 5.11 onward
qmlRegisterModule("QtQuick", 2, QT_VERSION_MINOR);
@@ -951,7 +958,9 @@ void QQmlEnginePrivate::init()
if (baseModulesUninitialized) {
qmlRegisterType<QQmlComponent>("QML", 1, 0, "Component"); // required for the Compiler.
registerBaseTypes("QtQml", 2, 0); // import which provides language building blocks.
+#if QT_CONFIG(qml_locale)
qmlRegisterUncreatableType<QQmlLocale>("QtQml", 2, 2, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
+#endif
// Auto-increment the import to stay in sync with ALL future QtQml minor versions from 5.11 onward
qmlRegisterModule("QtQml", 2, QT_VERSION_MINOR);
@@ -1365,6 +1374,71 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
}
/*!
+ \fn template<typename T> T QQmlEngine::singletonInstance(int qmlTypeId)
+
+ Returns the instance of a singleton type that was registered under \a qmlTypeId.
+
+ The template argument \e T may be either QJSValue or a pointer to a QObject-derived
+ type and depends on how the singleton was registered. If no instance of \e T has been
+ created yet, it is created now. If \a qmlTypeId does not represent a valid singleton
+ type, either a default constructed QJSValue or a \c nullptr is returned.
+
+ QObject* example:
+ \code
+ class MySingleton : public QObject {
+ Q_OBJECT
+ static int typeId;
+ // ...
+ };
+
+ // Register with QObject* callback
+ MySingleton::typeId = qmlRegisterSingletonType<MySingleton>(...);
+
+ // Retrieve as QObject*
+ QQmlEngine engine;
+ MySingleton* instance = engine.singletonInstance<MySingleton*>(MySingleton::typeId);
+ \endcode
+
+ QJSValue example:
+ \code
+ // Register with QJSValue callback
+ int typeId = qmlRegisterSingletonType(...);
+
+ // Retrieve as QJSValue
+ QQmlEngine engine;
+ QJSValue instance = engine.singletonInstance<QJSValue>(typeId);
+ \endcode
+
+ It is recommended to store the QML type id during registration, e.g. as a static member
+ in the singleton class. Otherwise, a costly lookup via qmlTypeId() has to be performed
+ at run-time.
+
+ \sa qmlRegisterSingletonType(), qmlTypeId()
+ \since 5.12
+*/
+template<>
+QJSValue QQmlEngine::singletonInstance<QJSValue>(int qmlTypeId)
+{
+ QQmlType type = QQmlMetaType::qmlType(qmlTypeId, QQmlMetaType::TypeIdCategory::QmlType);
+
+ if (!type.isValid() || !type.isSingleton())
+ return QJSValue();
+
+ QQmlType::SingletonInstanceInfo* info = type.singletonInstanceInfo();
+ info->init(this);
+
+ if (QObject* o = info->qobjectApi(this))
+ return this->newQObject(o);
+ else {
+ QJSValue value = info->scriptApi(this);
+ if (!value.isUndefined())
+ return value;
+ }
+
+ return QJSValue();
+}
+
+/*!
Refreshes all binding expressions that use strings marked for translation.
Call this function after you have installed a new translator with
@@ -1699,7 +1773,7 @@ void QQmlData::NotifyList::layout()
todo = nullptr;
}
-void QQmlData::deferData(int objectIndex, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlContextData *context)
+void QQmlData::deferData(int objectIndex, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlContextData *context)
{
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
deferData->deferredIdx = objectIndex;
@@ -2266,7 +2340,7 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
Locker locker(this);
auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return QQmlMetaObject((*iter)->rootPropertyCache());
+ return QQmlMetaObject((*iter)->rootPropertyCache().data());
} else {
QQmlType type = QQmlMetaType::qmlType(t);
return QQmlMetaObject(type.baseMetaObject());
@@ -2278,7 +2352,7 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
Locker locker(this);
auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return QQmlMetaObject((*iter)->rootPropertyCache());
+ return QQmlMetaObject((*iter)->rootPropertyCache().data());
} else {
QQmlType type = QQmlMetaType::qmlType(t);
return QQmlMetaObject(type.metaObject());
@@ -2290,7 +2364,7 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
Locker locker(this);
auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return (*iter)->rootPropertyCache();
+ return (*iter)->rootPropertyCache().data();
} else {
QQmlType type = QQmlMetaType::qmlType(t);
locker.unlock();
@@ -2303,7 +2377,7 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, int minorVe
Locker locker(this);
auto iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return (*iter)->rootPropertyCache();
+ return (*iter)->rootPropertyCache().data();
} else {
QQmlType type = QQmlMetaType::qmlType(t);
locker.unlock();
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 73ad2754c8..871e6bd9b4 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -143,6 +143,9 @@ public:
bool outputWarningsToStandardError() const;
void setOutputWarningsToStandardError(bool);
+ template<typename T>
+ T singletonInstance(int qmlTypeId);
+
public Q_SLOTS:
void retranslate();
@@ -167,6 +170,19 @@ private:
Q_DECLARE_PRIVATE(QQmlEngine)
};
+template<>
+Q_QML_EXPORT QJSValue QQmlEngine::singletonInstance<QJSValue>(int qmlTypeId);
+
+template<typename T>
+T QQmlEngine::singletonInstance(int qmlTypeId) {
+ QJSValue instance = singletonInstance<QJSValue>(qmlTypeId);
+ if (!instance.isQObject())
+ return nullptr;
+
+ QObject *object = instance.toQObject();
+ return qobject_cast<T>(object);
+}
+
QT_END_NAMESPACE
#endif // QQMLENGINE_H
diff --git a/src/qml/qml/qqmlguard_p.h b/src/qml/qml/qqmlguard_p.h
index 808bf4c709..3ac63926a0 100644
--- a/src/qml/qml/qqmlguard_p.h
+++ b/src/qml/qml/qqmlguard_p.h
@@ -106,6 +106,34 @@ protected:
virtual void objectDestroyed(T *) {}
};
+template <typename T>
+class QQmlStrongJSQObjectReference : public QQmlGuard<T>
+{
+public:
+ void setObject(T *o, QObject *parent) {
+ T *old = this->object();
+ if (o == old)
+ return;
+
+ if (m_jsOwnership && old && old->parent() == parent)
+ QQml_setParent_noEvent(old, nullptr);
+
+ this->QQmlGuard<T>::operator=(o);
+
+ if (o && !o->parent() && !QQmlData::keepAliveDuringGarbageCollection(o)) {
+ m_jsOwnership = true;
+ QQml_setParent_noEvent(o, parent);
+ } else {
+ m_jsOwnership = false;
+ }
+ }
+
+private:
+ using QQmlGuard<T>::setObject;
+ using QQmlGuard<T>::operator=;
+ bool m_jsOwnership = false;
+};
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QQmlGuard<QObject>)
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 005db4248e..962c92fdb0 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -735,7 +735,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
int *vmajor, int *vminor, QQmlType *type_return, QString *base,
bool *typeRecursionDetected,
QQmlType::RegistrationType registrationType,
- QQmlImport::RecursionRestriction recursionRestriction) const
+ QQmlImport::RecursionRestriction recursionRestriction,
+ QList<QQmlError> *errors) const
{
if (majversion >= 0 && minversion >= 0) {
QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion);
@@ -818,8 +819,19 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
};
for (uint i = 0; i < sizeof(urlsToTry) / sizeof(urlsToTry[0]); ++i) {
const QString url = urlsToTry[i];
- exists = !typeLoader->absoluteFilePath(QQmlFile::urlToLocalFileOrQrc(url)).isEmpty();
+ const QString localPath = QQmlFile::urlToLocalFileOrQrc(url);
+ exists = !typeLoader->absoluteFilePath(localPath).isEmpty();
if (exists) {
+ // don't let function.qml confuse the use of "new Function(...)" for example.
+ if (!QQml_isFileCaseCorrect(localPath)) {
+ exists = false;
+ if (errors) {
+ QQmlError caseError;
+ caseError.setDescription(QLatin1String("File name case mismatch"));
+ errors->append(caseError);
+ }
+ break;
+ }
qmlUrl = url;
break;
}
@@ -906,7 +918,7 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS
for (int i=0; i<imports.count(); ++i) {
const QQmlImportInstance *import = imports.at(i);
if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, base,
- &typeRecursionDetected, registrationType, recursionRestriction)) {
+ &typeRecursionDetected, registrationType, recursionRestriction, errors)) {
if (qmlCheckTypes()) {
// check for type clashes
for (int j = i+1; j<imports.count(); ++j) {
@@ -2048,7 +2060,7 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
if (QQmlExtensionPlugin *plugin = qobject_cast<QQmlExtensionPlugin *>(instance)) {
// basepath should point to the directory of the module, not the plugin file itself:
- QQmlExtensionPluginPrivate::get(plugin)->baseUrl = QUrl::fromLocalFile(basePath);
+ QQmlExtensionPluginPrivate::get(plugin)->baseUrl = QQmlImports::urlFromLocalFileOrQrcOrUrl(basePath);
}
iface->registerTypes(moduleId);
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 2437979ef8..283bd40660 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -94,7 +94,8 @@ struct QQmlImportInstance
int *vmajor, int *vminor, QQmlType* type_return,
QString *base = nullptr, bool *typeRecursionDetected = nullptr,
QQmlType::RegistrationType = QQmlType::AnyRegistrationType,
- QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion,
+ QList<QQmlError> *errors = nullptr) const;
};
class QQmlImportNamespace
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 93ec9421ed..9f2a96d5d9 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -93,8 +93,7 @@ void QQmlDelayedError::catchJavaScriptException(QV4::ExecutionEngine *engine)
QQmlJavaScriptExpression::QQmlJavaScriptExpression()
- : m_error(nullptr),
- m_context(nullptr),
+ : m_context(nullptr),
m_prevExpression(nullptr),
m_nextExpression(nullptr),
m_v4Function(nullptr)
@@ -247,6 +246,9 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
while (QQmlJavaScriptExpressionGuard *g = capture.guards.takeFirst())
g->Delete();
+ if (!watcher.wasDeleted())
+ setTranslationsCaptured(capture.translationCaptured);
+
ep->propertyCapture = lastPropertyCapture;
return result->asReturnedValue();
@@ -392,7 +394,7 @@ QQmlDelayedError *QQmlJavaScriptExpression::delayedError()
{
if (!m_error)
m_error = new QQmlDelayedError;
- return m_error;
+ return m_error.data();
}
QV4::ReturnedValue
@@ -458,7 +460,7 @@ void QQmlJavaScriptExpression::setupFunction(QV4::ExecutionContext *qmlContext,
setCompilationUnit(m_v4Function->compilationUnit);
}
-void QQmlJavaScriptExpression::setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit)
+void QQmlJavaScriptExpression::setCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
{
m_compilationUnit = compilationUnit;
}
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 01af3b89ca..de3fba0774 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -162,7 +162,7 @@ protected:
}
void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f);
- void setCompilationUnit(QV4::CompiledData::CompilationUnit *compilationUnit);
+ void setCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit);
// We store some flag bits in the following flag pointers.
// activeGuards:flag1 - notifyOnValueChanged
@@ -171,13 +171,17 @@ protected:
QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> activeGuards;
QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> permanentGuards;
+ void setTranslationsCaptured(bool captured) { m_error.setFlagValue(captured); }
+ bool translationsCaptured() const { return m_error.flag(); }
+
private:
friend class QQmlContextData;
friend class QQmlPropertyCapture;
friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
friend class QQmlTranslationBinding;
- QQmlDelayedError *m_error;
+ // m_error:flag1 translationsCapturedDuringEvaluation
+ QFlagPointer<QQmlDelayedError> m_error;
QQmlContextData *m_context;
QQmlJavaScriptExpression **m_prevExpression;
@@ -208,12 +212,14 @@ public:
static void registerQmlDependencies(QV4::Heap::QmlContext *context, const QV4::ExecutionEngine *engine, const QV4::CompiledData::Function *compiledFunction);
void captureProperty(QQmlNotifier *, Duration duration = OnlyOnce);
void captureProperty(QObject *, int, int, Duration duration = OnlyOnce, bool doNotify = true);
+ void captureTranslation() { translationCaptured = true; }
QQmlEngine *engine;
QQmlJavaScriptExpression *expression;
QQmlJavaScriptExpression::DeleteWatcher *watcher;
QFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> guards;
QStringList *errorString;
+ bool translationCaptured = false;
};
QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
@@ -260,18 +266,17 @@ void QQmlJavaScriptExpression::setScopeObject(QObject *v)
bool QQmlJavaScriptExpression::hasError() const
{
- return m_error && m_error->isValid();
+ return !m_error.isNull() && m_error->isValid();
}
bool QQmlJavaScriptExpression::hasDelayedError() const
{
- return m_error;
+ return !m_error.isNull();
}
inline void QQmlJavaScriptExpression::clearError()
{
- if (m_error)
- delete m_error;
+ delete m_error.data();
m_error = nullptr;
}
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 3fbe3df2ab..5e30f09eec 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -74,7 +74,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, i
Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>());
r->d()->object = object;
r->d()->propertyType = propType;
void *args[] = { &r->d()->property(), nullptr };
@@ -86,7 +86,7 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProp
{
Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocObject<QmlListWrapper>());
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>());
r->d()->object = prop.object;
r->d()->property() = prop;
r->d()->propertyType = propType;
@@ -102,9 +102,14 @@ QVariant QmlListWrapper::toVariant() const
}
-ReturnedValue QmlListWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QmlListWrapper::get(const Managed *m, StringOrSymbol *n, bool *hasProperty)
{
Q_ASSERT(m->as<QmlListWrapper>());
+
+ if (n->isSymbol())
+ return Object::get(m, n, hasProperty);
+ String *name = static_cast<String *>(n);
+
const QmlListWrapper *w = static_cast<const QmlListWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
@@ -140,7 +145,7 @@ ReturnedValue QmlListWrapper::getIndexed(const Managed *m, uint index, bool *has
return Primitive::undefinedValue().asReturnedValue();
}
-bool QmlListWrapper::put(Managed *m, String *name, const Value &value)
+bool QmlListWrapper::put(Managed *m, StringOrSymbol *name, const Value &value)
{
// doesn't do anything. Should we throw?
Q_UNUSED(m);
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index e02831c8d1..4b53d91933 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -93,9 +93,9 @@ struct Q_QML_EXPORT QmlListWrapper : Object
QVariant toVariant() const;
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
- static bool put(Managed *m, String *name, const Value &value);
+ static bool put(Managed *m, StringOrSymbol *name, const Value &value);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
};
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index b4f7092a22..c5a85dd4d3 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -350,7 +350,7 @@ ReturnedValue QQmlDateExtension::method_timeZoneUpdated(const QV4::FunctionObjec
if (argc != 0)
THROW_ERROR("Locale: Date.timeZoneUpdated(): Invalid arguments");
- QV4::DatePrototype::timezoneUpdated();
+ QV4::DatePrototype::timezoneUpdated(scope.engine);
RETURN_UNDEFINED();
}
@@ -825,7 +825,7 @@ QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
{
QV4::Scope scope(v4);
QV4LocaleDataDeletable *d = localeV4Data(scope.engine);
- QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocObject<QQmlLocaleData>());
+ QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocate<QQmlLocaleData>());
*wrapper->d()->locale = locale;
QV4::ScopedObject p(scope, d->prototype.value());
wrapper->setPrototype(p);
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index 8341b1f555..859c36e11b 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -58,6 +58,8 @@
#include <private/qqmlglobal_p.h>
#include <private/qv4object_p.h>
+QT_REQUIRE_CONFIG(qml_locale);
+
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index d842a7795f..dd027818cd 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -264,7 +264,14 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
{
if (scriptCallback && scriptApi(e).isUndefined()) {
- setScriptApi(e, scriptCallback(e, e));
+ QJSValue value = scriptCallback(e, e);
+ if (value.isQObject()) {
+ QObject *o = value.toQObject();
+ // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
+ // should behave identically to QML singleton types.
+ e->setContextForObject(o, new QQmlContext(e->rootContext(), e));
+ }
+ setScriptApi(e, value);
} else if (qobjectCallback && !qobjectApi(e)) {
QObject *o = qobjectCallback(e, e);
setQObjectApi(e, o);
@@ -273,6 +280,9 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e)
}
// if this object can use a property cache, create it now
QQmlData::ensurePropertyCache(e, o);
+ // even though the object is defined in C++, qmlContext(obj) and qmlEngine(obj)
+ // should behave identically to QML singleton types.
+ e->setContextForObject(o, new QQmlContext(e->rootContext(), e));
} else if (!url.isEmpty() && !qobjectApi(e)) {
QQmlComponent component(e, url, QQmlComponent::PreferSynchronous);
QObject *o = component.beginCreate(e->rootContext());
@@ -576,7 +586,7 @@ QQmlType QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
Q_ASSERT(isComposite());
if (!engine || !d)
return QQmlType();
- QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt);
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
if (td.isNull() || !td->isComplete())
return QQmlType();
QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
@@ -590,11 +600,11 @@ QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) c
Q_ASSERT(isComposite());
if (!engine)
return nullptr;
- QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt);
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()));
if (td.isNull() || !td->isComplete())
return nullptr;
QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
- return compilationUnit->rootPropertyCache();
+ return compilationUnit->rootPropertyCache().data();
}
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
@@ -841,7 +851,7 @@ QQmlPropertyCache *QQmlTypePrivate::propertyCacheForMinorVersion(int minorVersio
{
for (int i = 0; i < propertyCaches.count(); ++i)
if (propertyCaches.at(i).minorVersion == minorVersion)
- return propertyCaches.at(i).cache;
+ return propertyCaches.at(i).cache.data();
return nullptr;
}
@@ -1853,6 +1863,23 @@ void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)
p->maxMinorVersion = qMax(p->maxMinorVersion, versionMinor);
}
+//From qqml.h
+int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
+{
+ QMutexLocker lock(metaTypeDataLock());
+ QQmlMetaTypeData *data = metaTypeData();
+
+ QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data);
+ if (!module)
+ return -1;
+
+ QQmlType type = module->type(QHashedStringRef(qmlName), versionMinor);
+ if (!type.isValid())
+ return -1;
+
+ return type.index();
+}
+
bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri, int majorVersion)
{
const QQmlMetaTypeData *data = metaTypeData();
@@ -2232,19 +2259,25 @@ QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStrin
}
/*!
- Returns the type (if any) that corresponds to the QVariant::Type \a userType.
- Returns null if no type is registered.
+ Returns the type (if any) that corresponds to \a typeId. Depending on \a category, the
+ \a typeId is interpreted either as QVariant::Type or as QML type id returned by one of the
+ qml type registration functions. Returns null if no type is registered.
*/
-QQmlType QQmlMetaType::qmlType(int userType)
+QQmlType QQmlMetaType::qmlType(int typeId, TypeIdCategory category)
{
QMutexLocker lock(metaTypeDataLock());
QQmlMetaTypeData *data = metaTypeData();
- QQmlTypePrivate *type = data->idToType.value(userType);
- if (type && type->typeId == userType)
- return QQmlType(type);
- else
- return QQmlType();
+ if (category == TypeIdCategory::MetaType) {
+ QQmlTypePrivate *type = data->idToType.value(typeId);
+ if (type && type->typeId == typeId)
+ return QQmlType(type);
+ } else if (category == TypeIdCategory::QmlType) {
+ QQmlType type = data->types.value(typeId);
+ if (type.isValid())
+ return type;
+ }
+ return QQmlType();
}
/*!
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 51bf485a3e..6df439cd7a 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -91,11 +91,16 @@ public:
static QList<QQmlType> qmlSingletonTypes();
static QList<QQmlType> qmlAllTypes();
+ enum class TypeIdCategory {
+ MetaType,
+ QmlType
+ };
+
static QQmlType qmlType(const QString &qualifiedName, int, int);
static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int);
static QQmlType qmlType(const QMetaObject *);
static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor);
- static QQmlType qmlType(int);
+ static QQmlType qmlType(int typeId, TypeIdCategory category = TypeIdCategory::MetaType);
static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false);
static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject);
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 5aaf79c9e5..f6f18ab35f 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -71,7 +71,7 @@ struct ActiveOCRestorer
};
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlContextData *creationContext,
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlContextData *creationContext,
QQmlIncubatorPrivate *incubator)
: phase(Startup)
, compilationUnit(compilationUnit)
@@ -99,7 +99,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::Compil
}
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
+QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
: phase(Startup)
, compilationUnit(compilationUnit)
, resolvedTypes(compilationUnit->resolvedTypes)
@@ -193,7 +193,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
context->importedScripts.set(v4, scripts);
QV4::ScopedValue v(scope);
for (int i = 0; i < compilationUnit->dependentScripts.count(); ++i) {
- QQmlScriptData *s = compilationUnit->dependentScripts.at(i);
+ QQmlRefPointer<QQmlScriptData> s = compilationUnit->dependentScripts.at(i);
scripts->putIndexed(i, (v = s->scriptValueForContext(context)));
}
} else if (sharedState->creationContext) {
@@ -252,7 +252,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance, QQmlData::
Q_ASSERT(!sharedState->allJavaScriptObjects);
sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount);
- QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
+ QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
qSwap(_qmlContext, qmlContext);
@@ -312,7 +312,7 @@ bool QQmlObjectCreator::populateDeferredBinding(const QQmlProperty &qmlProperty,
if (!sharedState->allJavaScriptObjects)
sharedState->allJavaScriptObjects = valueScope.alloc(compilationUnit->totalObjectCount);
- QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
+ QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
qSwap(_qmlContext, qmlContext);
@@ -1144,9 +1144,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
isComponent = true;
- QQmlComponent *component = new QQmlComponent(engine, compilationUnit, index, parent);
+ QQmlComponent *component = new QQmlComponent(engine, compilationUnit.data(), index, parent);
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compilationUnit, obj, QStringLiteral("<component>"), context->url()));
+ compilationUnit.data(), obj, QStringLiteral("<component>"), context->url()));
QQmlComponentPrivate::get(component)->creationContext = context;
instance = component;
ddata = QQmlData::get(instance, /*create*/true);
@@ -1157,7 +1157,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QQmlType type = typeRef->type;
if (type.isValid()) {
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compilationUnit, obj, type.qmlTypeName(), context->url()));
+ compilationUnit.data(), obj, type.qmlTypeName(), context->url()));
void *ddataMemory = nullptr;
type.create(&instance, &ddataMemory, sizeof(QQmlData));
@@ -1190,8 +1190,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
} else {
Q_ASSERT(typeRef->compilationUnit);
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
- compilationUnit, obj, typeRef->compilationUnit->fileName(),
- context->url()));
+ compilationUnit.data(), obj, typeRef->compilationUnit->fileName(),
+ context->url()));
if (typeRef->compilationUnit->data->isSingleton())
{
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
@@ -1254,7 +1254,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
customParser->engine = QQmlEnginePrivate::get(engine);
- customParser->imports = compilationUnit->typeNameCache;
+ customParser->imports = compilationUnit->typeNameCache.data();
QList<const QV4::CompiledData::Binding *> bindings;
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
@@ -1264,7 +1264,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
bindings << binding;
}
}
- customParser->applyBindings(instance, compilationUnit, bindings);
+ customParser->applyBindings(instance, compilationUnit.data(), bindings);
customParser->engine = nullptr;
customParser->imports = (QQmlTypeNameCache*)nullptr;
@@ -1280,7 +1280,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (installPropertyCache) {
if (ddata->propertyCache)
ddata->propertyCache->release();;
- ddata->propertyCache = cache;
+ ddata->propertyCache = cache.data();
ddata->propertyCache->addref();
}
@@ -1292,7 +1292,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
++sharedState->allJavaScriptObjects;
QV4::Scope valueScope(v4);
- QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
+ QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc());
qSwap(_qmlContext, qmlContext);
@@ -1344,6 +1344,11 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
data->clearPendingBindingBit(b->targetPropertyIndex().coreIndex());
b->setEnabled(true, QQmlPropertyData::BypassInterceptor |
QQmlPropertyData::DontRemoveBinding);
+ if (!b->isValueTypeProxy()) {
+ QQmlBinding *binding = static_cast<QQmlBinding*>(b.data());
+ if (!binding->hasError() && !binding->hasDependencies())
+ b->removeFromObject();
+ }
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
return nullptr;
@@ -1436,7 +1441,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
vmeMetaObject = new QQmlVMEMetaObject(v4, _qobject, cache, compilationUnit, _compiledObjectIndex);
if (_ddata->propertyCache)
_ddata->propertyCache->release();
- _ddata->propertyCache = cache;
+ _ddata->propertyCache = cache.data();
_ddata->propertyCache->addref();
scopeObjectProtector = _ddata->jsWrapper.value();
} else {
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 67a5bdd827..435b213341 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -85,7 +85,7 @@ class Q_QML_PRIVATE_EXPORT QQmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
public:
- QQmlObjectCreator(QQmlContextData *parentContext, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr);
+ QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr);
~QQmlObjectCreator();
QObject *create(int subComponentIndex = -1, QObject *parent = nullptr, QQmlInstantiationInterrupt *interrupt = nullptr);
@@ -104,7 +104,7 @@ public:
QFiniteStack<QPointer<QObject> > &allCreatedObjects() const { return sharedState->allCreatedObjects; }
private:
- QQmlObjectCreator(QQmlContextData *contextData, QV4::CompiledData::CompilationUnit *compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
+ QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
void init(QQmlContextData *parentContext);
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index 1b44bbdda3..fc798a2c23 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -181,46 +181,75 @@ void QQmlOpenMetaObjectTypePrivate::init(const QMetaObject *metaObj)
class QQmlOpenMetaObjectPrivate
{
public:
- QQmlOpenMetaObjectPrivate(QQmlOpenMetaObject *_q)
- : q(_q), parent(nullptr), type(nullptr), cacheProperties(false) {}
+ QQmlOpenMetaObjectPrivate(QQmlOpenMetaObject *_q, bool _autoCreate, QObject *obj)
+ : q(_q), object(obj), autoCreate(_autoCreate) {}
+
+ struct Property {
+ private:
+ QVariant m_value;
+ QPointer<QObject> qobjectTracker;
+ public:
+ bool valueSet = false;
+
+ QVariant value() const {
+ if (QMetaType::typeFlags(m_value.userType()) & QMetaType::PointerToQObject
+ && qobjectTracker.isNull())
+ return QVariant::fromValue<QObject*>(nullptr);
+ return m_value;
+ }
+ QVariant &valueRef() { return m_value; }
+ void setValue(const QVariant &v) {
+ m_value = v;
+ valueSet = true;
+ if (QMetaType::typeFlags(v.userType()) & QMetaType::PointerToQObject)
+ qobjectTracker = m_value.value<QObject*>();
+ }
+ };
- inline QPair<QVariant, bool> &getDataRef(int idx) {
- while (data.count() <= idx)
- data << QPair<QVariant, bool>(QVariant(), false);
- return data[idx];
+ inline void setPropertyValue(int idx, const QVariant &value) {
+ if (data.count() <= idx)
+ data.resize(idx + 1);
+ data[idx].setValue(value);
}
- inline QVariant &getData(int idx) {
- QPair<QVariant, bool> &prop = getDataRef(idx);
- if (!prop.second) {
- prop.first = q->initialValue(idx);
- prop.second = true;
- }
- return prop.first;
+ inline Property &propertyRef(int idx) {
+ if (data.count() <= idx)
+ data.resize(idx + 1);
+ Property &prop = data[idx];
+ if (!prop.valueSet)
+ prop.setValue(q->initialValue(idx));
+ return prop;
+ }
+
+ inline QVariant propertyValue(int idx) {
+ auto &prop = propertyRef(idx);
+ return prop.value();
+ }
+
+ inline QVariant &propertyValueRef(int idx) {
+ auto &prop = propertyRef(idx);
+ return prop.valueRef();
}
- inline bool hasData(int idx) const {
+ inline bool hasProperty(int idx) const {
if (idx >= data.count())
return false;
- return data[idx].second;
+ return data[idx].valueSet;
}
- bool autoCreate;
QQmlOpenMetaObject *q;
- QAbstractDynamicMetaObject *parent;
- QList<QPair<QVariant, bool> > data;
+ QAbstractDynamicMetaObject *parent = nullptr;
+ QVector<Property> data;
QObject *object;
- QQmlOpenMetaObjectType *type;
- bool cacheProperties;
+ QQmlRefPointer<QQmlOpenMetaObjectType> type;
+ bool autoCreate;
+ bool cacheProperties = false;
};
QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base, bool automatic)
-: d(new QQmlOpenMetaObjectPrivate(this))
+: d(new QQmlOpenMetaObjectPrivate(this, automatic, obj))
{
- d->autoCreate = automatic;
- d->object = obj;
-
- d->type = new QQmlOpenMetaObjectType(base ? base : obj->metaObject(), nullptr);
+ d->type.adopt(new QQmlOpenMetaObjectType(base ? base : obj->metaObject(), nullptr));
d->type->d->referers.insert(this);
QObjectPrivate *op = QObjectPrivate::get(obj);
@@ -230,13 +259,9 @@ QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, const QMetaObject *base, bo
}
QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj, QQmlOpenMetaObjectType *type, bool automatic)
-: d(new QQmlOpenMetaObjectPrivate(this))
+: d(new QQmlOpenMetaObjectPrivate(this, automatic, obj))
{
- d->autoCreate = automatic;
- d->object = obj;
-
d->type = type;
- d->type->addref();
d->type->d->referers.insert(this);
QObjectPrivate *op = QObjectPrivate::get(obj);
@@ -250,13 +275,12 @@ QQmlOpenMetaObject::~QQmlOpenMetaObject()
if (d->parent)
delete d->parent;
d->type->d->referers.remove(this);
- d->type->release();
delete d;
}
QQmlOpenMetaObjectType *QQmlOpenMetaObject::type() const
{
- return d->type;
+ return d->type.data();
}
void QQmlOpenMetaObject::emitPropertyNotification(const QByteArray &propertyName)
@@ -276,13 +300,11 @@ int QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void *
int propId = id - d->type->d->propertyOffset;
if (c == QMetaObject::ReadProperty) {
propertyRead(propId);
- *reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
+ *reinterpret_cast<QVariant *>(a[0]) = d->propertyValue(propId);
} else if (c == QMetaObject::WriteProperty) {
- if (propId >= d->data.count() || d->data.at(propId).first != *reinterpret_cast<QVariant *>(a[0])) {
+ if (propId >= d->data.count() || d->data.at(propId).value() != *reinterpret_cast<QVariant *>(a[0])) {
propertyWrite(propId);
- QPair<QVariant, bool> &prop = d->getDataRef(propId);
- prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
- prop.second = true;
+ d->setPropertyValue(propId, propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0])));
propertyWritten(propId);
activate(o, d->type->d->signalOffset + propId, nullptr);
}
@@ -303,14 +325,12 @@ QAbstractDynamicMetaObject *QQmlOpenMetaObject::parent() const
QVariant QQmlOpenMetaObject::value(int id) const
{
- return d->getData(id);
+ return d->propertyValue(id);
}
void QQmlOpenMetaObject::setValue(int id, const QVariant &value)
{
- QPair<QVariant, bool> &prop = d->getDataRef(id);
- prop.first = propertyWriteValue(id, value);
- prop.second = true;
+ d->setPropertyValue(id, propertyWriteValue(id, value));
activate(d->object, id + d->type->d->signalOffset, nullptr);
}
@@ -320,23 +340,18 @@ QVariant QQmlOpenMetaObject::value(const QByteArray &name) const
if (iter == d->type->d->names.cend())
return QVariant();
- return d->getData(*iter);
+ return d->propertyValue(*iter);
}
-QVariant &QQmlOpenMetaObject::operator[](const QByteArray &name)
+QVariant &QQmlOpenMetaObject::valueRef(const QByteArray &name)
{
QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
Q_ASSERT(iter != d->type->d->names.cend());
- return d->getData(*iter);
-}
-
-QVariant &QQmlOpenMetaObject::operator[](int id)
-{
- return d->getData(id);
+ return d->propertyValueRef(*iter);
}
-bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
+bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val, bool force)
{
QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.constFind(name);
@@ -348,11 +363,10 @@ bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
}
if (id >= 0) {
- QVariant &dataVal = d->getData(id);
- if (dataVal == val)
+ if (!force && d->propertyValue(id) == val)
return false;
- dataVal = val;
+ d->setPropertyValue(id, val);
activate(d->object, id + d->type->d->signalOffset, nullptr);
return true;
}
@@ -363,7 +377,7 @@ bool QQmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
// returns true if this value has been initialized by a call to either value() or setValue()
bool QQmlOpenMetaObject::hasValue(int id) const
{
- return d->hasData(id);
+ return d->hasProperty(id);
}
void QQmlOpenMetaObject::setCached(bool c)
diff --git a/src/qml/qml/qqmlopenmetaobject_p.h b/src/qml/qml/qqmlopenmetaobject_p.h
index 4905190b75..168a2a6f7f 100644
--- a/src/qml/qml/qqmlopenmetaobject_p.h
+++ b/src/qml/qml/qqmlopenmetaobject_p.h
@@ -100,11 +100,10 @@ public:
~QQmlOpenMetaObject() override;
QVariant value(const QByteArray &) const;
- bool setValue(const QByteArray &, const QVariant &);
+ bool setValue(const QByteArray &, const QVariant &, bool force = false);
QVariant value(int) const;
void setValue(int, const QVariant &);
- QVariant &operator[](const QByteArray &);
- QVariant &operator[](int);
+ QVariant &valueRef(const QByteArray &);
bool hasValue(int) const;
int count() const;
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index c4487f91a3..bc0124eeab 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -255,7 +255,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
{
if (!obj) return;
- QQmlTypeNameCache *typeNameCache = context?context->imports:nullptr;
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context?context->imports:nullptr;
QObject *currentObject = obj;
QVector<QStringRef> path;
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index b78a2ddd20..0785910cec 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -979,13 +979,13 @@ public:
void append(QQmlPropertyCache *cache) { cache->addref(); data.append(cache); }
QQmlPropertyCache *at(int index) const { return data.at(index).data(); }
- void set(int index, QQmlPropertyCache *replacement) {
+ void set(int index, const QQmlRefPointer<QQmlPropertyCache> &replacement) {
if (QQmlPropertyCache *oldCache = data.at(index).data()) {
- if (replacement == oldCache)
+ if (replacement.data() == oldCache)
return;
oldCache->release();
}
- data[index] = replacement;
+ data[index] = replacement.data();
replacement->addref();
}
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index c656fac4ff..e886198e80 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -504,11 +504,12 @@ void QQmlDataBlob::addDependency(QQmlDataBlob *blob)
if (!blob ||
blob->status() == Error || blob->status() == Complete ||
- status() == Error || status() == Complete || m_isDone ||
- m_waitingFor.contains(blob))
+ status() == Error || status() == Complete || m_isDone)
return;
- blob->addref();
+ for (auto existingDep: qAsConst(m_waitingFor))
+ if (existingDep.data() == blob)
+ return;
m_data.setStatus(WaitingForDependencies);
@@ -691,13 +692,11 @@ void QQmlDataBlob::tryDone()
void QQmlDataBlob::cancelAllWaitingFor()
{
while (m_waitingFor.count()) {
- QQmlDataBlob *blob = m_waitingFor.takeLast();
+ QQmlRefPointer<QQmlDataBlob> blob = m_waitingFor.takeLast();
Q_ASSERT(blob->m_waitingOnMe.contains(this));
blob->m_waitingOnMe.removeOne(this);
-
- blob->release();
}
}
@@ -706,7 +705,8 @@ void QQmlDataBlob::notifyAllWaitingOnMe()
while (m_waitingOnMe.count()) {
QQmlDataBlob *blob = m_waitingOnMe.takeLast();
- Q_ASSERT(blob->m_waitingFor.contains(this));
+ 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);
}
@@ -714,13 +714,19 @@ void QQmlDataBlob::notifyAllWaitingOnMe()
void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
{
- Q_ASSERT(m_waitingFor.contains(blob));
Q_ASSERT(blob->status() == Error || blob->status() == Complete);
QQmlCompilingProfiler prof(typeLoader()->profiler(), blob);
m_inCallback = true;
- m_waitingFor.removeOne(blob);
+ 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);
@@ -728,8 +734,6 @@ void QQmlDataBlob::notifyComplete(QQmlDataBlob *blob)
dependencyComplete(blob);
}
- blob->release();
-
if (!isError() && m_waitingFor.isEmpty())
allDependenciesDone();
@@ -1327,20 +1331,17 @@ QQmlTypeLoader::Blob::Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoa
QQmlTypeLoader::Blob::~Blob()
{
- for (int ii = 0; ii < m_qmldirs.count(); ++ii)
- m_qmldirs.at(ii)->release();
}
bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QV4::CompiledData::Import *import, int priority, QList<QQmlError> *errors)
{
- QQmlQmldirData *data = typeLoader()->getQmldir(url);
+ QQmlRefPointer<QQmlQmldirData> data = typeLoader()->getQmldir(url);
data->setImport(this, import);
data->setPriority(this, priority);
if (data->status() == Error) {
// This qmldir must not exist - which is not an error
- data->release();
return true;
} else if (data->status() == Complete) {
// This data is already available
@@ -1348,11 +1349,11 @@ bool QQmlTypeLoader::Blob::fetchQmldir(const QUrl &url, const QV4::CompiledData:
}
// Wait for this data to become available
- addDependency(data);
+ addDependency(data.data());
return true;
}
-bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors)
+bool QQmlTypeLoader::Blob::updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors)
{
QString qmldirIdentifier = data->urlString();
QString qmldirUrl = qmldirIdentifier.left(qmldirIdentifier.lastIndexOf(QLatin1Char('/')) + 1);
@@ -1378,8 +1379,8 @@ bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::Compile
const auto qmldirScripts = qmldir.scripts();
for (const QQmlDirParser::Script &script : qmldirScripts) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
- QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
- addDependency(blob);
+ QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl);
+ addDependency(blob.data());
scriptImported(blob, import->location, script.nameSpace, importQualifier);
}
@@ -1398,8 +1399,8 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
const QString &importQualifier = stringAt(import->qualifierIndex);
if (import->type == QV4::CompiledData::Import::ImportScript) {
QUrl scriptUrl = finalUrl().resolved(QUrl(importUri));
- QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
- addDependency(blob);
+ QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl);
+ addDependency(blob.data());
scriptImported(blob, import->location, importQualifier, QString());
} else if (import->type == QV4::CompiledData::Import::ImportLibrary) {
@@ -1426,8 +1427,8 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
const auto qmldirScripts = qmldir.scripts();
for (const QQmlDirParser::Script &script : qmldirScripts) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
- QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
- addDependency(blob);
+ QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(scriptUrl);
+ addDependency(blob.data());
scriptImported(blob, import->location, script.nameSpace, importQualifier);
}
@@ -1499,14 +1500,6 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
return true;
}
-void QQmlTypeLoader::Blob::dependencyError(QQmlDataBlob *blob)
-{
- if (blob->type() == QQmlDataBlob::QmldirFile) {
- QQmlQmldirData *data = static_cast<QQmlQmldirData *>(blob);
- data->release();
- }
-}
-
void QQmlTypeLoader::Blob::dependencyComplete(QQmlDataBlob *blob)
{
if (blob->type() == QQmlDataBlob::QmldirFile) {
@@ -1532,7 +1525,7 @@ bool QQmlTypeLoader::Blob::isDebugging() const
return typeLoader()->engine()->handle()->debugger() != nullptr;
}
-bool QQmlTypeLoader::Blob::qmldirDataAvailable(QQmlQmldirData *data, QList<QQmlError> *errors)
+bool QQmlTypeLoader::Blob::qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &data, QList<QQmlError> *errors)
{
bool resolve = true;
@@ -1552,7 +1545,6 @@ bool QQmlTypeLoader::Blob::qmldirDataAvailable(QQmlQmldirData *data, QList<QQmlE
if (resolve) {
// This is the (current) best resolution for this import
if (!updateQmldir(data, import, errors)) {
- data->release();
return false;
}
@@ -1562,7 +1554,6 @@ bool QQmlTypeLoader::Blob::qmldirDataAvailable(QQmlQmldirData *data, QList<QQmlE
}
}
- data->release();
return true;
}
@@ -1664,7 +1655,7 @@ QUrl QQmlTypeLoader::normalize(const QUrl &unNormalizedUrl)
/*!
Returns a QQmlTypeData for the specified \a url. The QQmlTypeData may be cached.
*/
-QQmlTypeData *QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode)
+QQmlRefPointer<QQmlTypeData> QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode)
{
Q_ASSERT(!unNormalizedUrl.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() ||
@@ -1707,8 +1698,6 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode)
}
}
- typeData->addref();
-
return typeData;
}
@@ -1716,20 +1705,20 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &unNormalizedUrl, Mode mode)
Returns a QQmlTypeData for the given \a data with the provided base \a url. The
QQmlTypeData will not be cached.
*/
-QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url, Mode mode)
+QQmlRefPointer<QQmlTypeData> QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url, Mode mode)
{
LockHolder<QQmlTypeLoader> holder(this);
QQmlTypeData *typeData = new QQmlTypeData(url, this);
QQmlTypeLoader::loadWithStaticData(typeData, data, mode);
- return typeData;
+ return QQmlRefPointer<QQmlTypeData>(typeData, QQmlRefPointer<QQmlTypeData>::Adopt);
}
/*!
Return a QQmlScriptBlob for \a url. The QQmlScriptData may be cached.
*/
-QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &unNormalizedUrl)
+QQmlRefPointer<QQmlScriptBlob> QQmlTypeLoader::getScript(const QUrl &unNormalizedUrl)
{
Q_ASSERT(!unNormalizedUrl.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(unNormalizedUrl).isEmpty() ||
@@ -1754,15 +1743,13 @@ QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &unNormalizedUrl)
}
}
- scriptBlob->addref();
-
return scriptBlob;
}
/*!
Returns a QQmlQmldirData for \a url. The QQmlQmldirData may be cached.
*/
-QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url)
+QQmlRefPointer<QQmlQmldirData> QQmlTypeLoader::getQmldir(const QUrl &url)
{
Q_ASSERT(!url.isRelative() &&
(QQmlFile::urlToLocalFileOrQrc(url).isEmpty() ||
@@ -1778,8 +1765,6 @@ QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url)
QQmlTypeLoader::load(qmldirData);
}
- qmldirData->addref();
-
return qmldirData;
}
@@ -2073,17 +2058,9 @@ QQmlTypeData::QQmlTypeData(const QUrl &url, QQmlTypeLoader *manager)
QQmlTypeData::~QQmlTypeData()
{
- for (int ii = 0; ii < m_scripts.count(); ++ii)
- m_scripts.at(ii).script->release();
- for (int ii = 0; ii < m_compositeSingletons.count(); ++ii) {
- if (QQmlTypeData *tdata = m_compositeSingletons.at(ii).typeData)
- tdata->release();
- }
- for (auto it = m_resolvedTypes.constBegin(), end = m_resolvedTypes.constEnd();
- it != end; ++it) {
- if (QQmlTypeData *tdata = it->typeData)
- tdata->release();
- }
+ m_scripts.clear();
+ m_compositeSingletons.clear();
+ m_resolvedTypes.clear();
}
const QList<QQmlTypeData::ScriptReference> &QQmlTypeData::resolvedScripts() const
@@ -2201,7 +2178,7 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeName
{
QQmlPropertyCacheCreator<QV4::CompiledData::CompilationUnit> propertyCacheCreator(&m_compiledData->propertyCaches,
&pendingGroupPropertyBindings,
- engine, m_compiledData, &m_importCache);
+ engine, m_compiledData.data(), &m_importCache);
QQmlCompileError error = propertyCacheCreator.buildMetaObjects();
if (error.isSet()) {
setError(error);
@@ -2209,7 +2186,7 @@ void QQmlTypeData::createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeName
}
}
- QQmlPropertyCacheAliasCreator<QV4::CompiledData::CompilationUnit> aliasCreator(&m_compiledData->propertyCaches, m_compiledData);
+ QQmlPropertyCacheAliasCreator<QV4::CompiledData::CompilationUnit> aliasCreator(&m_compiledData->propertyCaches, m_compiledData.data());
aliasCreator.appendAliasPropertiesToMetaObjects();
pendingGroupPropertyBindings.resolveMissingPropertyCaches(engine, &m_compiledData->propertyCaches);
@@ -2393,8 +2370,7 @@ void QQmlTypeData::done()
}
m_compiledData->typeNameCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
- QQmlScriptData *scriptData = script.script->scriptData();
- scriptData->addref();
+ QQmlRefPointer<QQmlScriptData> scriptData = script.script->scriptData();
m_compiledData->dependentScripts << scriptData;
}
}
@@ -2637,8 +2613,8 @@ void QQmlTypeData::resolveTypes()
// Add any imported scripts to our resolved set
const auto resolvedScripts = m_importCache.resolvedScripts();
for (const QQmlImports::ScriptReference &script : resolvedScripts) {
- QQmlScriptBlob *blob = typeLoader()->getScript(script.location);
- addDependency(blob);
+ QQmlRefPointer<QQmlScriptBlob> blob = typeLoader()->getScript(script.location);
+ addDependency(blob.data());
ScriptReference ref;
//ref.location = ...
@@ -2681,7 +2657,7 @@ void QQmlTypeData::resolveTypes()
// TODO: give an error message? If so, we should record and show the path of the cycle.
continue;
}
- addDependency(ref.typeData);
+ addDependency(ref.typeData.data());
ref.prefix = csRef.prefix;
m_compositeSingletons << ref;
@@ -2711,7 +2687,7 @@ void QQmlTypeData::resolveTypes()
if (ref.type.isComposite()) {
ref.typeData = typeLoader()->getType(ref.type.sourceUrl());
- addDependency(ref.typeData);
+ addDependency(ref.typeData.data());
}
ref.majorVersion = majorVersion;
ref.minorVersion = minorVersion;
@@ -2743,7 +2719,7 @@ QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
for (const QQmlTypeData::TypeReference &singleton: m_compositeSingletons)
(*typeNameCache)->add(singleton.type.qmlTypeName(), singleton.type.sourceUrl(), singleton.prefix);
- m_importCache.populateCache(*typeNameCache);
+ m_importCache.populateCache(typeNameCache->data());
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
@@ -2833,7 +2809,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &
return true;
}
-void QQmlTypeData::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &/*nameSpace*/)
+void QQmlTypeData::scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &/*nameSpace*/)
{
ScriptReference ref;
ref.script = blob;
@@ -2959,8 +2935,6 @@ void QQmlScriptData::clear()
typeNameCache = nullptr;
}
- for (int ii = 0; ii < scripts.count(); ++ii)
- scripts.at(ii)->release();
scripts.clear();
// An addref() was made when the QQmlCleanup was added to the engine.
@@ -2968,19 +2942,15 @@ void QQmlScriptData::clear()
}
QQmlScriptBlob::QQmlScriptBlob(const QUrl &url, QQmlTypeLoader *loader)
-: QQmlTypeLoader::Blob(url, JavaScriptFile, loader), m_scriptData(nullptr)
+: QQmlTypeLoader::Blob(url, JavaScriptFile, loader)
{
}
QQmlScriptBlob::~QQmlScriptBlob()
{
- if (m_scriptData) {
- m_scriptData->release();
- m_scriptData = nullptr;
- }
}
-QQmlScriptData *QQmlScriptBlob::scriptData() const
+QQmlRefPointer<QQmlScriptData> QQmlScriptBlob::scriptData() const
{
return m_scriptData;
}
@@ -3017,11 +2987,12 @@ void QQmlScriptBlob::dataReceived(const SourceCodeData &data)
}
QmlIR::ScriptDirectivesCollector collector(&irUnit);
+ irUnit.jsParserEngine.setDirectives(&collector);
QList<QQmlError> errors;
QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(
- &irUnit.jsModule, &irUnit.jsGenerator, urlString(), finalUrlString(),
- source, &errors, &collector);
+ &irUnit.jsModule, &irUnit.jsParserEngine, &irUnit.jsGenerator, urlString(), finalUrlString(),
+ source, &errors);
// No need to addref on unit, it's initial refcount is 1
source.clear();
if (!errors.isEmpty()) {
@@ -3095,6 +3066,7 @@ void QQmlScriptBlob::done()
}
m_scriptData->typeNameCache->add(script.qualifier, scriptIndex, script.nameSpace);
}
+ m_scripts.clear();
m_importCache.populateCache(m_scriptData->typeNameCache);
}
@@ -3104,7 +3076,7 @@ QString QQmlScriptBlob::stringAt(int index) const
return m_scriptData->m_precompiledScript->data->stringAt(index);
}
-void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace)
+void QQmlScriptBlob::scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace)
{
ScriptReference ref;
ref.script = blob;
@@ -3118,7 +3090,7 @@ void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledDat
void QQmlScriptBlob::initializeFromCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit)
{
Q_ASSERT(!m_scriptData);
- m_scriptData = new QQmlScriptData();
+ m_scriptData.adopt(new QQmlScriptData());
m_scriptData->url = finalUrl();
m_scriptData->urlString = finalUrlString();
m_scriptData->m_precompiledScript = unit;
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index e75719866d..98ac4b1bc1 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -217,7 +217,7 @@ private:
QList<QQmlDataBlob *> m_waitingOnMe;
// List of QQmlDataBlob's that I am waiting for to complete.
- QList<QQmlDataBlob *> m_waitingFor;
+ QVector<QQmlRefPointer<QQmlDataBlob>> m_waitingFor;
int m_redirectCount:30;
bool m_inCallback:1;
@@ -279,14 +279,13 @@ public:
bool addImport(const QV4::CompiledData::Import *import, QList<QQmlError> *errors);
bool fetchQmldir(const QUrl &url, const QV4::CompiledData::Import *import, int priority, QList<QQmlError> *errors);
- bool updateQmldir(QQmlQmldirData *data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors);
+ bool updateQmldir(const QQmlRefPointer<QQmlQmldirData> &data, const QV4::CompiledData::Import *import, QList<QQmlError> *errors);
private:
- virtual bool qmldirDataAvailable(QQmlQmldirData *, QList<QQmlError> *);
+ virtual bool qmldirDataAvailable(const QQmlRefPointer<QQmlQmldirData> &, QList<QQmlError> *);
- virtual void scriptImported(QQmlScriptBlob *, const QV4::CompiledData::Location &, const QString &, const QString &) {}
+ virtual void scriptImported(const QQmlRefPointer<QQmlScriptBlob> &, const QV4::CompiledData::Location &, const QString &, const QString &) {}
- void dependencyError(QQmlDataBlob *) override;
void dependencyComplete(QQmlDataBlob *) override;
protected:
@@ -296,7 +295,7 @@ public:
QQmlImports m_importCache;
QHash<const QV4::CompiledData::Import*, int> m_unresolvedImports;
- QList<QQmlQmldirData *> m_qmldirs;
+ QVector<QQmlRefPointer<QQmlQmldirData>> m_qmldirs;
QQmlMetaType::CachedUnitLookupError m_cachedUnitStatus = QQmlMetaType::CachedUnitLookupError::NoError;
};
@@ -307,11 +306,11 @@ public:
static QUrl normalize(const QUrl &unNormalizedUrl);
- QQmlTypeData *getType(const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
- QQmlTypeData *getType(const QByteArray &, const QUrl &url, Mode mode = PreferSynchronous);
+ QQmlRefPointer<QQmlTypeData> getType(const QUrl &unNormalizedUrl, Mode mode = PreferSynchronous);
+ QQmlRefPointer<QQmlTypeData> getType(const QByteArray &, const QUrl &url, Mode mode = PreferSynchronous);
- QQmlScriptBlob *getScript(const QUrl &unNormalizedUrl);
- QQmlQmldirData *getQmldir(const QUrl &);
+ QQmlRefPointer<QQmlScriptBlob> getScript(const QUrl &unNormalizedUrl);
+ QQmlRefPointer<QQmlQmldirData> getQmldir(const QUrl &);
QString absoluteFilePath(const QString &path);
bool directoryExists(const QString &path);
@@ -424,13 +423,13 @@ class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob
public:
struct TypeReference
{
- TypeReference() : majorVersion(0), minorVersion(0), typeData(nullptr), needsCreation(true) {}
+ TypeReference() : majorVersion(0), minorVersion(0), needsCreation(true) {}
QV4::CompiledData::Location location;
QQmlType type;
int majorVersion;
int minorVersion;
- QQmlTypeData *typeData;
+ QQmlRefPointer<QQmlTypeData> typeData;
QString prefix; // used by CompositeSingleton types
QString qualifiedName() const;
bool needsCreation;
@@ -438,11 +437,9 @@ public:
struct ScriptReference
{
- ScriptReference() : script(nullptr) {}
-
QV4::CompiledData::Location location;
QString qualifier;
- QQmlScriptBlob *script;
+ QQmlRefPointer<QQmlScriptBlob> script;
};
private:
@@ -495,7 +492,7 @@ private:
bool reportErrors = true,
QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType);
- void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
+ void scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
SourceCodeData m_backupSourceCode; // used when cache verification fails.
@@ -541,7 +538,7 @@ public:
QUrl url;
QString urlString;
QQmlTypeNameCache *typeNameCache;
- QList<QQmlScriptBlob *> scripts;
+ QVector<QQmlRefPointer<QQmlScriptBlob>> scripts;
QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
@@ -571,15 +568,13 @@ public:
struct ScriptReference
{
- ScriptReference() : script(nullptr) {}
-
QV4::CompiledData::Location location;
QString qualifier;
QString nameSpace;
- QQmlScriptBlob *script;
+ QQmlRefPointer<QQmlScriptBlob> script;
};
- QQmlScriptData *scriptData() const;
+ QQmlRefPointer<QQmlScriptData> scriptData() const;
protected:
void dataReceived(const SourceCodeData &) override;
@@ -589,11 +584,11 @@ protected:
QString stringAt(int index) const override;
private:
- void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
+ void scriptImported(const QQmlRefPointer<QQmlScriptBlob> &blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) override;
void initializeFromCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit);
QList<ScriptReference> m_scripts;
- QQmlScriptData *m_scriptData;
+ QQmlRefPointer<QQmlScriptData> m_scriptData;
};
class Q_AUTOTEST_EXPORT QQmlQmldirData : public QQmlTypeLoader::Blob
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index ce35e966aa..7270cffb00 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -95,12 +95,17 @@ QObject* QQmlTypeWrapper::singletonObject() const
QVariant QQmlTypeWrapper::toVariant() const
{
- QObject *qobjectSingleton = singletonObject();
- if (qobjectSingleton)
+ // Only Singleton type wrappers can be converted to a variant.
+ if (!isSingleton())
+ return QVariant();
+
+ QQmlEngine *e = engine()->qmlEngine();
+ QQmlType::SingletonInstanceInfo *siinfo = d()->type().singletonInstanceInfo();
+ siinfo->init(e);
+ if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
return QVariant::fromValue<QObject*>(qobjectSingleton);
- // only QObject Singleton Type can be converted to a variant.
- return QVariant();
+ return QVariant::fromValue<QJSValue>(siinfo->scriptApi(e));
}
@@ -111,7 +116,7 @@ ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o,
Q_ASSERT(t.isValid());
Scope scope(engine);
- Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>());
+ Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocate<QQmlTypeWrapper>());
w->d()->mode = mode; w->d()->object = o;
w->d()->typePrivate = t.priv();
QQmlType::refHandle(w->d()->typePrivate);
@@ -120,15 +125,15 @@ ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o,
// Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a
// namespace.
-ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const QQmlImportRef *importNamespace,
+ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, const QQmlRefPointer<QQmlTypeNameCache> &t, const QQmlImportRef *importNamespace,
Heap::QQmlTypeWrapper::TypeNameMode mode)
{
Q_ASSERT(t);
Q_ASSERT(importNamespace);
Scope scope(engine);
- Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>());
- w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace;
+ Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocate<QQmlTypeWrapper>());
+ w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t.data(); w->d()->importNamespace = importNamespace;
t->addref();
return w.asReturnedValue();
}
@@ -162,10 +167,14 @@ static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *n
return v4->throwTypeError(message);
}
-ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlTypeWrapper::get(const Managed *m, StringOrSymbol *n, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlTypeWrapper>());
+ if (n->isSymbol())
+ return Object::get(m, n, hasProperty);
+ String *name = static_cast<String *>(n);
+
QV4::ExecutionEngine *v4 = static_cast<const QQmlTypeWrapper *>(m)->engine();
QV4::Scope scope(v4);
@@ -232,7 +241,7 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp
value = type.scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok);
if (ok) {
- Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocObject<QQmlScopedEnumWrapper>());
+ Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocate<QQmlScopedEnumWrapper>());
enumWrapper->d()->typePrivate = type.priv();
QQmlType::refHandle(enumWrapper->d()->typePrivate);
enumWrapper->d()->scopeEnumIndex = value;
@@ -295,8 +304,12 @@ ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProp
}
-bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value)
+bool QQmlTypeWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
{
+ if (n->isSymbol())
+ return Object::put(m, n, value);
+ String *name = static_cast<String *>(n);
+
Q_ASSERT(m->as<QQmlTypeWrapper>());
QQmlTypeWrapper *w = static_cast<QQmlTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = w->engine();
@@ -337,11 +350,14 @@ bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value)
return false;
}
-PropertyAttributes QQmlTypeWrapper::query(const Managed *m, String *name)
+PropertyAttributes QQmlTypeWrapper::query(const Managed *m, StringOrSymbol *name)
{
+ if (name->isSymbol())
+ return Object::query(m, name);
+ String *n = static_cast<String *>(name);
// ### Implement more efficiently.
bool hasProperty = false;
- static_cast<Object *>(const_cast<Managed*>(m))->get(name, &hasProperty);
+ static_cast<Object *>(const_cast<Managed*>(m))->get(n, &hasProperty);
return hasProperty ? Attr_Data : Attr_Invalid;
}
@@ -385,10 +401,9 @@ ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value
if (!theirDData->compilationUnit)
return Encode(false);
- QQmlTypeData *td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl());
+ QQmlRefPointer<QQmlTypeData> td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl());
CompiledData::CompilationUnit *cu = td->compilationUnit();
myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId);
- td->release();
} else {
myQmlType = qenginepriv->metaObjectForType(myTypeId);
}
@@ -410,9 +425,13 @@ QQmlType Heap::QQmlScopedEnumWrapper::type() const
return QQmlType(typePrivate);
}
-ReturnedValue QQmlScopedEnumWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlScopedEnumWrapper::get(const Managed *m, StringOrSymbol *n, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlScopedEnumWrapper>());
+ if (n->isSymbol())
+ return Object::get(m, n, hasProperty);
+ String *name = static_cast<String *>(n);
+
const QQmlScopedEnumWrapper *resource = static_cast<const QQmlScopedEnumWrapper *>(m);
QV4::ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 25ff7ba7c8..30bbc8d179 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -108,13 +108,13 @@ struct Q_QML_EXPORT QQmlTypeWrapper : Object
static ReturnedValue create(ExecutionEngine *, QObject *, const QQmlType &,
Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums);
- static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const QQmlImportRef *,
+ static ReturnedValue create(ExecutionEngine *, QObject *, const QQmlRefPointer<QQmlTypeNameCache> &, const QQmlImportRef *,
Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums);
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static bool put(Managed *m, String *name, const Value &value);
- static PropertyAttributes query(const Managed *, String *name);
+ static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
+ static bool put(Managed *m, StringOrSymbol *name, const Value &value);
+ static PropertyAttributes query(const Managed *, StringOrSymbol *name);
static bool isEqualTo(Managed *that, Managed *o);
static ReturnedValue instanceOf(const Object *typeObject, const Value &var);
};
@@ -124,7 +124,7 @@ struct Q_QML_EXPORT QQmlScopedEnumWrapper : Object
V4_OBJECT2(QQmlScopedEnumWrapper, Object)
V4_NEEDS_DESTROY
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
};
}
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding_p.h b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
index ba0d305bd9..35b54c339b 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding_p.h
+++ b/src/qml/qml/qqmlvaluetypeproxybinding_p.h
@@ -55,7 +55,7 @@
QT_BEGIN_NAMESPACE
-class QQmlValueTypeProxyBinding : public QQmlAbstractBinding
+class Q_AUTOTEST_EXPORT QQmlValueTypeProxyBinding : public QQmlAbstractBinding
{
public:
QQmlValueTypeProxyBinding(QObject *o, QQmlPropertyIndex coreIndex);
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 6196a09d94..7e0cf64bed 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -186,7 +186,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *obj
Scope scope(engine);
initProto(engine);
- Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocObject<QQmlValueTypeReference>());
+ Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->allocate<QQmlValueTypeReference>());
r->d()->object = object;
r->d()->property = property;
r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject));
@@ -200,7 +200,7 @@ ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVaria
Scope scope(engine);
initProto(engine);
- Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocObject<QQmlValueTypeWrapper>());
+ Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->allocate<QQmlValueTypeWrapper>());
r->d()->setPropertyCache(QJSEnginePrivate::get(engine)->cache(metaObject));
r->d()->valueType = QQmlValueTypeFactory::valueType(typeId);
r->d()->gadgetPtr = nullptr;
@@ -241,12 +241,16 @@ bool QQmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
return false;
}
-PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, String *name)
+PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, StringOrSymbol *name)
{
+ if (name->isSymbol())
+ return Object::query(m, name);
+
+ String *n = static_cast<String *>(name);
Q_ASSERT(m->as<const QQmlValueTypeWrapper>());
const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
- QQmlPropertyData *result = r->d()->propertyCache()->property(name, nullptr, nullptr);
+ QQmlPropertyData *result = r->d()->propertyCache()->property(n, nullptr, nullptr);
return result ? Attr_Data : Attr_Invalid;
}
@@ -355,9 +359,14 @@ ReturnedValue QQmlValueTypeWrapper::method_toString(const FunctionObject *b, con
return Encode(b->engine()->newString(result));
}
-ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, StringOrSymbol *n, bool *hasProperty)
{
Q_ASSERT(m->as<QQmlValueTypeWrapper>());
+
+ if (n->isSymbol())
+ return Object::get(m, n, hasProperty);
+ String *name = static_cast<String *>(n);
+
const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = r->engine();
@@ -413,8 +422,12 @@ ReturnedValue QQmlValueTypeWrapper::get(const Managed *m, String *name, bool *ha
#undef VALUE_TYPE_ACCESSOR
}
-bool QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value)
+bool QQmlValueTypeWrapper::put(Managed *m, StringOrSymbol *n, const Value &value)
{
+ if (n->isSymbol())
+ return Object::put(m, n, value);
+ String *name = static_cast<String *>(n);
+
Q_ASSERT(m->as<QQmlValueTypeWrapper>());
ExecutionEngine *v4 = static_cast<QQmlValueTypeWrapper *>(m)->engine();
Scope scope(v4);
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index f99d207d68..5a684bfb4d 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -106,10 +106,10 @@ public:
int typeId() const;
bool write(QObject *target, int propertyIndex) const;
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
- static bool put(Managed *m, String *name, const Value &value);
+ static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
+ static bool put(Managed *m, StringOrSymbol *name, const Value &value);
static bool isEqualTo(Managed *m, Managed *other);
- static PropertyAttributes query(const Managed *, String *name);
+ static PropertyAttributes query(const Managed *, StringOrSymbol *name);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_toString(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index 9a94ac6258..13c5524d96 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -124,6 +124,10 @@ private:
// Used to check that a QQmlVME that is interrupted mid-execution
// is still valid. Checks all the objects and contexts have not been
// deleted.
+//
+// VME stands for Virtual Machine Execution. QML files used to
+// be compiled to a byte code data structure that a virtual machine executed
+// (for constructing the tree of QObjects and setting properties).
class QQmlVMEGuard
{
public:
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index c1d3980b58..6bc0f0aa1e 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -106,7 +106,7 @@ void QQmlVMEVariantQObjectPtr::objectDestroyed(QObject *)
QV4::Scope scope(v4);
QV4::Scoped<QV4::MemberData> sp(scope, m_target->propertyAndMethodStorage.value());
if (sp) {
- QV4::MemberData::Index index{ sp->d(), sp->d()->values.values + m_index };
+ QV4::PropertyIndex index{ sp->d(), sp->d()->values.values + m_index };
index.set(v4, QV4::Primitive::nullValue());
}
}
@@ -176,7 +176,7 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
}
-QQmlInterceptorMetaObject::QQmlInterceptorMetaObject(QObject *obj, QQmlPropertyCache *cache)
+QQmlInterceptorMetaObject::QQmlInterceptorMetaObject(QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache)
: object(obj),
cache(cache),
interceptors(nullptr),
@@ -316,7 +316,7 @@ QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObje
QQmlVMEMetaObject::QQmlVMEMetaObject(QV4::ExecutionEngine *engine,
QObject *obj,
- QQmlPropertyCache *cache, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId)
+ const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &qmlCompilationUnit, int qmlObjectId)
: QQmlInterceptorMetaObject(obj, cache),
engine(engine),
ctxt(QQmlData::get(obj, true)->outerContext),
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index 0c82686d47..dbcc9d2884 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -94,7 +94,7 @@ public:
class Q_QML_PRIVATE_EXPORT QQmlInterceptorMetaObject : public QAbstractDynamicMetaObject
{
public:
- QQmlInterceptorMetaObject(QObject *obj, QQmlPropertyCache *cache);
+ QQmlInterceptorMetaObject(QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache);
~QQmlInterceptorMetaObject() override;
void registerInterceptor(QQmlPropertyIndex index, QQmlPropertyValueInterceptor *interceptor);
@@ -104,7 +104,7 @@ public:
QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o) override;
// Used by auto-tests for inspection
- QQmlPropertyCache *propertyCache() const { return cache; }
+ QQmlPropertyCache *propertyCache() const { return cache.data(); }
bool intercepts(QQmlPropertyIndex propertyIndex) const
{
@@ -146,7 +146,7 @@ class QQmlVMEMetaObjectEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
{
public:
- QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, QQmlPropertyCache *cache, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId);
+ QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &qmlCompilationUnit, int qmlObjectId);
~QQmlVMEMetaObject() override;
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 567d83f3ee..41531c1df3 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -228,7 +228,7 @@ public:
static ReturnedValue create(ExecutionEngine *, NodeImpl *, const QList<NodeImpl *> &);
// JS API
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
};
@@ -250,7 +250,7 @@ public:
V4_NEEDS_DESTROY
// JS API
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static ReturnedValue getIndexed(const Managed *m, uint index, bool *hasProperty);
// C++ API
@@ -595,7 +595,7 @@ ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
Scope scope(v4);
QQmlXMLHttpRequestData *d = xhrdata(v4);
if (d->nodePrototype.isUndefined()) {
- ScopedObject p(scope, v4->memoryManager->allocObject<NodePrototype>());
+ ScopedObject p(scope, v4->memoryManager->allocate<NodePrototype>());
d->nodePrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
@@ -606,7 +606,7 @@ ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data)
{
Scope scope(v4);
- Scoped<Node> instance(scope, v4->memoryManager->allocObject<Node>(data));
+ Scoped<Node> instance(scope, v4->memoryManager->allocate<Node>(data));
ScopedObject p(scope);
switch (data->type) {
@@ -876,7 +876,7 @@ ReturnedValue Document::load(ExecutionEngine *v4, const QByteArray &data)
return Encode::null();
}
- ScopedObject instance(scope, v4->memoryManager->allocObject<Node>(document));
+ ScopedObject instance(scope, v4->memoryManager->allocate<Node>(document));
document->release(); // the GC should own the NodeImpl via Node now
ScopedObject p(scope);
instance->setPrototype((p = Document::prototype(v4)));
@@ -904,9 +904,14 @@ ReturnedValue NamedNodeMap::getIndexed(const Managed *m, uint index, bool *hasPr
return Encode::undefined();
}
-ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue NamedNodeMap::get(const Managed *m, StringOrSymbol *n, bool *hasProperty)
{
Q_ASSERT(m->as<NamedNodeMap>());
+
+ if (n->isSymbol())
+ return Object::get(m, n, hasProperty);
+ String *name = static_cast<String *>(n);
+
const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
QV4::ExecutionEngine *v4 = r->engine();
@@ -930,7 +935,7 @@ ReturnedValue NamedNodeMap::get(const Managed *m, String *name, bool *hasPropert
ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QList<NodeImpl *> &list)
{
- return (v4->memoryManager->allocObject<NamedNodeMap>(data, list))->asReturnedValue();
+ return (v4->memoryManager->allocate<NamedNodeMap>(data, list))->asReturnedValue();
}
ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProperty)
@@ -949,7 +954,7 @@ ReturnedValue NodeList::getIndexed(const Managed *m, uint index, bool *hasProper
return Encode::undefined();
}
-ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue NodeList::get(const Managed *m, StringOrSymbol *name, bool *hasProperty)
{
Q_ASSERT(m->as<NodeList>());
const NodeList *r = static_cast<const NodeList *>(m);
@@ -957,14 +962,14 @@ ReturnedValue NodeList::get(const Managed *m, String *name, bool *hasProperty)
name->makeIdentifier();
- if (name->equals(v4->id_length()))
+ if (name->identifier() == v4->id_length()->identifier())
return Primitive::fromInt32(r->d()->d->children.count()).asReturnedValue();
return Object::get(m, name, hasProperty);
}
ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data)
{
- return (v4->memoryManager->allocObject<NodeList>(data))->asReturnedValue();
+ return (v4->memoryManager->allocate<NodeList>(data))->asReturnedValue();
}
ReturnedValue Document::method_documentElement(const FunctionObject *b, const Value *thisObject, const Value *, int)
@@ -1643,7 +1648,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f);
QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->v8Engine->networkAccessManager(), scope.engine);
- Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocObject<QQmlXMLHttpRequestWrapper>(r));
+ Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototype(proto);
return w.asReturnedValue();
@@ -2049,7 +2054,7 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
{
Scope scope(v4);
- Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocObject<QQmlXMLHttpRequestCtor>(v4));
+ Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocate<QQmlXMLHttpRequestCtor>(v4));
ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
v4->globalObject->defineReadonlyProperty(s, ctor);
diff --git a/src/qml/qml/qqmlxmlhttprequest_p.h b/src/qml/qml/qqmlxmlhttprequest_p.h
index f2836d8301..7515ef8dcc 100644
--- a/src/qml/qml/qqmlxmlhttprequest_p.h
+++ b/src/qml/qml/qqmlxmlhttprequest_p.h
@@ -55,7 +55,7 @@
#include <QtCore/qglobal.h>
#include <private/qqmlglobal_p.h>
-#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network)
+QT_REQUIRE_CONFIG(qml_xml_http_request);
QT_BEGIN_NAMESPACE
@@ -64,7 +64,5 @@ void qt_rem_qmlxmlhttprequest(QV4::ExecutionEngine *engine, void *);
QT_END_NAMESPACE
-#endif // xmlstreamreader && qml_network
-
#endif // QQMLXMLHTTPREQUEST_P_H
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index f04bee7f19..e4fe84bf25 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -44,7 +44,9 @@
#include <private/qqmlcomponent_p.h>
#include <private/qqmlloggingcategory_p.h>
#include <private/qqmlstringconverters_p.h>
+#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
+#endif
#include <private/qv8engine_p.h>
#include <private/qqmldelayedcallqueue_p.h>
#include <QFileInfo>
@@ -138,7 +140,9 @@ void Heap::QtObject::init(QQmlEngine *qmlEngine)
o->defineDefaultProperty(QStringLiteral("btoa"), QV4::QtObject::method_btoa);
o->defineDefaultProperty(QStringLiteral("atob"), QV4::QtObject::method_atob);
o->defineDefaultProperty(QStringLiteral("resolvedUrl"), QV4::QtObject::method_resolvedUrl);
+#if QT_CONFIG(qml_locale)
o->defineDefaultProperty(QStringLiteral("locale"), QV4::QtObject::method_locale);
+#endif
o->defineDefaultProperty(QStringLiteral("binding"), QV4::QtObject::method_binding);
if (qmlEngine) {
@@ -193,7 +197,7 @@ ReturnedValue QtObject::findAndAdd(const QString *name, bool &foundProperty) con
return Encode::undefined();
}
-ReturnedValue QtObject::get(const Managed *m, String *name, bool *hasProperty)
+ReturnedValue QtObject::get(const Managed *m, StringOrSymbol *name, bool *hasProperty)
{
bool hasProp = false;
if (hasProperty == nullptr) {
@@ -1152,7 +1156,7 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
if (!parentArg)
THROW_GENERIC_ERROR("Qt.createQmlObject(): Missing parent object");
- QQmlTypeData *typeData = QQmlEnginePrivate::get(engine)->typeLoader.getType(
+ QQmlRefPointer<QQmlTypeData> typeData = QQmlEnginePrivate::get(engine)->typeLoader.getType(
qml.toUtf8(), url, QQmlTypeLoader::Synchronous);
Q_ASSERT(typeData->isCompleteOrError());
QQmlComponent component(engine);
@@ -1309,6 +1313,7 @@ ReturnedValue QtObject::method_createComponent(const FunctionObject *b, const Va
return QV4::QObjectWrapper::wrap(scope.engine, c);
}
+#if QT_CONFIG(qml_locale)
/*!
\qmlmethod Qt::locale(name)
@@ -1343,6 +1348,7 @@ ReturnedValue QtObject::method_locale(const FunctionObject *b, const Value *, co
return QQmlLocale::locale(scope.engine, code);
}
+#endif
void Heap::QQmlBindingFunction::init(const QV4::FunctionObject *bindingFunction)
{
@@ -1416,7 +1422,7 @@ ReturnedValue QtObject::method_binding(const FunctionObject *b, const Value *, c
if (!f)
THROW_TYPE_ERROR_WITH_MESSAGE("binding(): argument (binding expression) must be a function");
- return Encode(scope.engine->memoryManager->allocObject<QQmlBindingFunction>(f));
+ return Encode(scope.engine->memoryManager->allocate<QQmlBindingFunction>(f));
}
@@ -1551,7 +1557,7 @@ static ReturnedValue writeToConsole(const FunctionObject *b, const Value *, cons
if (i != start)
result.append(QLatin1Char(' '));
- if (argv[i].as<ArrayObject>())
+ if (argv[i].isManaged() && argv[i].managed()->isArrayLike())
result += QLatin1Char('[') + argv[i].toQStringNoThrow() + QLatin1Char(']');
else
result.append(argv[i].toQStringNoThrow());
@@ -1795,7 +1801,7 @@ void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions ext
globalObject->defineDefaultProperty(QStringLiteral("print"), QV4::ConsoleObject::method_log);
- QV4::ScopedObject console(scope, globalObject->engine()->memoryManager->allocObject<QV4::ConsoleObject>());
+ QV4::ScopedObject console(scope, globalObject->engine()->memoryManager->allocate<QV4::ConsoleObject>());
globalObject->defineDefaultProperty(QStringLiteral("console"), console);
}
@@ -1850,6 +1856,10 @@ ReturnedValue GlobalExtensions::method_qsTranslate(const FunctionObject *b, cons
if (argc > i)
n = argv[i].toInt32();
+ if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr))
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureTranslation();
+
QString result = QCoreApplication::translate(context.toUtf8().constData(),
text.toUtf8().constData(),
comment.toUtf8().constData(),
@@ -1953,6 +1963,10 @@ ReturnedValue GlobalExtensions::method_qsTr(const FunctionObject *b, const Value
if (argc > 2)
n = argv[2].toInt32();
+ if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr))
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureTranslation();
+
QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(),
comment.toUtf8().constData(), n);
@@ -2033,6 +2047,10 @@ ReturnedValue GlobalExtensions::method_qsTrId(const FunctionObject *b, const Val
if (argc > 1)
n = argv[1].toInt32();
+ if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr))
+ if (ep->propertyCapture)
+ ep->propertyCapture->captureTranslation();
+
return Encode(scope.engine->newString(qtTrId(argv[0].toQStringNoThrow().toUtf8().constData(), n)));
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index ee3b5f7d6e..60a2a6b87d 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -93,7 +93,7 @@ struct QtObject : Object
{
V4_OBJECT2(QtObject, Object)
- static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static ReturnedValue get(const Managed *m, StringOrSymbol *name, bool *hasProperty);
static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
static ReturnedValue method_isQtObject(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
@@ -126,7 +126,9 @@ struct QtObject : Object
static ReturnedValue method_resolvedUrl(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_createQmlObject(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_createComponent(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+#if QT_CONFIG(qml_locale)
static ReturnedValue method_locale(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+#endif
static ReturnedValue method_binding(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_get_platform(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 038a75d50a..b5e25fb6d4 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -39,14 +39,21 @@
#include "qv8engine_p.h"
+#if QT_CONFIG(qml_sequence_object)
#include "qv4sequenceobject_p.h"
+#endif
+
#include "private/qjsengine_p.h"
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmllist_p.h>
#include <private/qqmlengine_p.h>
+#if QT_CONFIG(qml_xml_http_request)
#include <private/qqmlxmlhttprequest_p.h>
+#endif
+#if QT_CONFIG(qml_locale)
#include <private/qqmllocale_p.h>
+#endif
#include <private/qqmlglobal_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <private/qqmlplatform_p.h>
@@ -78,6 +85,7 @@
#include <private/qv4script_p.h>
#include <private/qv4include_p.h>
#include <private/qv4jsonobject_p.h>
+#include <private/qv4identifiertable_p.h>
Q_DECLARE_METATYPE(QList<int>)
@@ -123,11 +131,12 @@ static void restoreJSValue(QDataStream &stream, void *data)
}
}
-QV8Engine::QV8Engine(QJSEngine *qq, QV4::ExecutionEngine *v4)
- : q(qq)
- , m_engine(nullptr)
+QV8Engine::QV8Engine(QV4::ExecutionEngine *v4)
+ : m_engine(nullptr)
, m_v4Engine(v4)
+#if QT_CONFIG(qml_xml_http_request)
, m_xmlHttpRequestData(nullptr)
+#endif
{
#ifdef Q_PROCESSOR_X86_32
if (!qCpuHasFeature(SSE2)) {
@@ -157,7 +166,7 @@ QV8Engine::~QV8Engine()
qDeleteAll(m_extensionData);
m_extensionData.clear();
-#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network)
+#if QT_CONFIG(qml_xml_http_request)
qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData);
m_xmlHttpRequestData = nullptr;
#endif
@@ -180,14 +189,16 @@ void QV8Engine::initializeGlobal()
QV4::Scope scope(m_v4Engine);
QV4::GlobalExtensions::init(m_v4Engine->globalObject, QJSEngine::AllExtensions);
- QV4::ScopedObject qt(scope, m_v4Engine->memoryManager->allocObject<QV4::QtObject>(m_engine));
+ QV4::ScopedObject qt(scope, m_v4Engine->memoryManager->allocate<QV4::QtObject>(m_engine));
m_v4Engine->globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
+#if QT_CONFIG(qml_locale)
QQmlLocale::registerStringLocaleCompare(m_v4Engine);
QQmlDateExtension::registerExtension(m_v4Engine);
QQmlNumberExtension::registerExtension(m_v4Engine);
+#endif
-#if QT_CONFIG(xmlstreamreader) && QT_CONFIG(qml_network)
+#if QT_CONFIG(qml_xml_http_request)
qt_add_domexceptions(m_v4Engine);
m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine);
#endif
@@ -196,8 +207,10 @@ void QV8Engine::initializeGlobal()
{
for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) {
- if (m_v4Engine->globalObject->internalClass()->nameMap.at(i))
- m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->string);
+ if (m_v4Engine->globalObject->internalClass()->nameMap.at(i).isValid()) {
+ QV4::Identifier id = m_v4Engine->globalObject->internalClass()->nameMap.at(i);
+ m_illegalNames.insert(id.toQString());
+ }
}
}
}
@@ -221,14 +234,14 @@ static void freeze_recursive(QV4::ExecutionEngine *v4, QV4::Object *object)
if (!instanceOfObject)
return;
- QV4::InternalClass *frozen = object->internalClass()->propertiesFrozen();
+ QV4::Heap::InternalClass *frozen = object->internalClass()->propertiesFrozen();
if (object->internalClass() == frozen)
return;
object->setInternalClass(frozen);
QV4::ScopedObject o(scope);
for (uint i = 0; i < frozen->size; ++i) {
- if (!frozen->nameMap.at(i))
+ if (!frozen->nameMap.at(i).isValid())
continue;
o = *object->propertyData(i);
if (o)
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index b6a378667e..d90f1827fe 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -154,10 +154,9 @@ class Q_QML_PRIVATE_EXPORT QV8Engine
friend class QJSEngine;
public:
// static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
- static QV4::ExecutionEngine *getV4(QJSEngine *q) { return q->handle(); }
static QV4::ExecutionEngine *getV4(QV8Engine *d) { return d->m_v4Engine; }
- QV8Engine(QJSEngine* qq, QV4::ExecutionEngine *v4);
+ QV8Engine(QV4::ExecutionEngine *v4);
virtual ~QV8Engine();
// This enum should be in sync with QQmlEngine::ObjectOwnership
@@ -170,10 +169,11 @@ public:
void initQmlGlobalObject();
void setEngine(QQmlEngine *engine);
QQmlEngine *engine() { return m_engine; }
- QJSEngine *publicEngine() { return q; }
QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; }
+#if QT_CONFIG(qml_xml_http_request)
void *xmlHttpRequestData() const { return m_xmlHttpRequestData; }
+#endif
void freezeObject(const QV4::Value &value);
@@ -202,13 +202,14 @@ public:
int consoleCountHelper(const QString &file, quint16 line, quint16 column);
protected:
- QJSEngine* q;
QQmlEngine *m_engine;
QQmlDelayedCallQueue m_delayedCallQueue;
QV4::ExecutionEngine *m_v4Engine;
+#if QT_CONFIG(qml_xml_http_request)
void *m_xmlHttpRequestData;
+#endif
QVector<Deletable *> m_extensionData;