diff options
Diffstat (limited to 'src/qml/qml')
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; |