aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorTarja Sundqvist <tarja.sundqvist@qt.io>2025-12-15 16:14:22 +0200
committerTarja Sundqvist <tarja.sundqvist@qt.io>2025-12-15 16:14:22 +0200
commitb58ec3b086518da5aa573f99426235854c23e35f (patch)
tree861a9935d8f1cdba2fdca546836a351736dbddbf /src/qml
parent4826f86e274f1b29bd769e6790824f9e62a40f62 (diff)
parent22032227d16c39211e2ebceef97d21f4d89c7c87 (diff)
Merge tag 'v6.5.8-lts-lgpl' into 6.56.5
Qt 6.5.8-lts-lgpl release
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/doc/snippets/qml/qsTrId.1.qml17
-rw-r--r--src/qml/doc/src/cmake/qt_add_qml_module.qdoc4
-rw-r--r--src/qml/jsruntime/qv4engine.cpp11
-rw-r--r--src/qml/jsruntime/qv4engine_p.h2
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp2
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp10
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp2
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp3
-rw-r--r--src/qml/qml/qqml.cpp8
-rw-r--r--src/qml/qml/qqml.h5
-rw-r--r--src/qml/qml/qqmlbuiltinfunctions.cpp7
-rw-r--r--src/qml/qml/qqmlcomponent.cpp48
-rw-r--r--src/qml/qml/qqmlcomponent_p.h43
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp2
-rw-r--r--src/qml/qml/qqmlimport_p.h20
-rw-r--r--src/qml/qml/qqmllocale.cpp1
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp13
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h30
-rw-r--r--src/qml/qml/qqmlproperty.cpp12
-rw-r--r--src/qml/qml/qqmltypeloader.cpp7
-rw-r--r--src/qml/qml/qqmltypeloader_p.h1
-rw-r--r--src/qml/qml/qqmltypeloaderthread.cpp11
-rw-r--r--src/qml/qml/qqmltypeloaderthread_p.h2
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp10
24 files changed, 204 insertions, 67 deletions
diff --git a/src/qml/doc/snippets/qml/qsTrId.1.qml b/src/qml/doc/snippets/qml/qsTrId.1.qml
index 4989adad25..6776620c77 100644
--- a/src/qml/doc/snippets/qml/qsTrId.1.qml
+++ b/src/qml/doc/snippets/qml/qsTrId.1.qml
@@ -3,9 +3,18 @@
import QtQuick
+Item {
//![0]
-Text {
- //% "hello"
- text: qsTrId("hello_id")
-}
+ Text {
+ //% "hello"
+ text: qsTrId("hello_id")
+ }
//![0]
+
+//![1]
+ Text {
+ /*% "hello" */
+ text: qsTrId("hello_id")
+ }
+//![1]
+}
diff --git a/src/qml/doc/src/cmake/qt_add_qml_module.qdoc b/src/qml/doc/src/cmake/qt_add_qml_module.qdoc
index 79c3cd8082..353505c78f 100644
--- a/src/qml/doc/src/cmake/qt_add_qml_module.qdoc
+++ b/src/qml/doc/src/cmake/qt_add_qml_module.qdoc
@@ -520,8 +520,8 @@ class MyItem: public QQuickItem { ... };
\endcode
then one has to make sure that the module containing \c QQuickItem, called
-\c Quick, is declared as a dependency via the \c DEPENDENCIES option. Not doing
-so might result in errors during type compilation with
+\c QtQuick, is declared as a dependency via the \c DEPENDENCIES option. Not
+doing so might result in errors during type compilation with
\l{QML type compiler}{qmltc} or during binding and function compilation to C++
with \l{qmlcachegen-auto}{qmlcachegen}.
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 99fad7e3c3..a807cc42df 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -105,7 +105,8 @@ using namespace QV4;
// odd while the statics are being initialized, and stays even afterwards.
// Any further engines created while the statics are being initialized busy-wait until engineSerial
// is even.
-static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
+Q_CONSTINIT static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
+Q_CONSTINIT static QBasicAtomicInt hasPreview = Q_BASIC_ATOMIC_INITIALIZER(0);
int ExecutionEngine::s_maxCallDepth = -1;
int ExecutionEngine::s_jitCallCountThreshold = 3;
int ExecutionEngine::s_maxJSStackSize = 4 * 1024 * 1024;
@@ -889,6 +890,12 @@ void ExecutionEngine::setProfiler(Profiling::Profiler *profiler)
Q_ASSERT(!m_profiler);
m_profiler.reset(profiler);
}
+
+void ExecutionEngine::setPreviewing(bool enabled)
+{
+ hasPreview.storeRelease(enabled);
+}
+
#endif // QT_CONFIG(qml_debug)
void ExecutionEngine::initRootContext()
@@ -2212,7 +2219,7 @@ QV4::Value *ExecutionEngine::registerNativeModule(const QUrl &url, const QV4::Va
bool ExecutionEngine::diskCacheEnabled() const
{
- return (!disableDiskCache() && !debugger()) || forceDiskCache();
+ return (!disableDiskCache() && !debugger() && !hasPreview.loadAcquire()) || forceDiskCache();
}
void ExecutionEngine::callInContext(QV4::Function *function, QObject *self,
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 75c8efd67e..99b9e526f6 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -514,12 +514,14 @@ public:
void setDebugger(Debugging::Debugger *) {}
void setProfiler(Profiling::Profiler *) {}
+ static void setPreviewing(bool) {}
#else
QV4::Debugging::Debugger *debugger() const { return m_debugger.data(); }
QV4::Profiling::Profiler *profiler() const { return m_profiler.data(); }
void setDebugger(Debugging::Debugger *debugger);
void setProfiler(Profiling::Profiler *profiler);
+ static void setPreviewing(bool enabled);
#endif // QT_CONFIG(qml_debug)
ExecutionContext *currentContext() const { return currentStackFrame->context(); }
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index 90eb326d65..eac2aca059 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -94,6 +94,8 @@ void Heap::ForInIteratorObject::markObjects(Heap::Base *that, MarkStack *markSta
o->object->mark(markStack);
if (o->current)
o->current->mark(markStack);
+ if (o->target)
+ o->target->mark(markStack);
o->workArea[0].mark(markStack);
o->workArea[1].mark(markStack);
Object::markObjects(that, markStack);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 50389e06ec..ecd947ccc3 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -1021,6 +1021,16 @@ ReturnedValue QObjectWrapper::virtualResolveLookupGetter(const Object *object, E
ReturnedValue QObjectWrapper::lookupAttached(
Lookup *l, ExecutionEngine *engine, const Value &object)
{
+ if (&QObjectWrapper::lookupAttached == &Lookup::getterGeneric) {
+ // Certain compilers, e.g. MSVC, will "helpfully" deduplicate methods that are completely
+ // equal. As a result, the pointers are the same, which wreaks havoc on the logic that
+ // decides how to retrieve the property.
+ qFatal("Your C++ compiler is broken.");
+ }
+
+ // This getter marks the presence of a lookup for an attached object.
+ // It falls back to the generic lookup when run through the interpreter, but AOT-compiled
+ // code can get clever with it.
return Lookup::getterGeneric(l, engine, object);
}
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 98bb6347d3..2613cff99a 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -777,7 +777,7 @@ ReturnedValue StringPrototype::method_replace(const FunctionObject *b, const Val
nMatchOffsets += re->captureCount() * 2;
if (!regExp->global())
break;
- offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
+ offset = qMax(offset, matchOffsets[oldSize + 1]) + 1;
}
if (regExp->global()) {
regExp->setLastIndex(0);
diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp
index d91dfb95db..7ffdffad7b 100644
--- a/src/qml/qml/ftw/qqmlthread.cpp
+++ b/src/qml/qml/ftw/qqmlthread.cpp
@@ -195,6 +195,9 @@ void QQmlThread::shutdown()
d->m_shutdown = true;
+ if (d->mainSync)
+ d->wakeOne();
+
if (QCoreApplication::closingDown())
d->quit();
else
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index 94a91629f3..44e8955b7a 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -1602,7 +1602,13 @@ static void initTypeWrapperLookup(
QV4::Scoped<QV4::QQmlTypeWrapper> wrapper(
scope, QV4::QQmlTypeWrapper::create(
scope.engine, nullptr, context->qmlContext->imports(), importRef));
- wrapper = l->qmlContextPropertyGetter(l, context->engine->handle(), wrapper);
+
+ // This is not a contextGetter since we actually load from the namespace.
+ wrapper = l->getter(l, context->engine->handle(), wrapper);
+
+ // In theory, the getter may have populated the lookup's property cache.
+ l->releasePropertyCache();
+
l->qmlContextPropertyGetter = qmlContextPropertyGetter;
if (qmlContextPropertyGetter == QV4::QQmlContextWrapper::lookupSingleton)
l->qmlContextSingletonLookup.singletonObject = wrapper->heapObject();
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 0650cee167..73e8a09601 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -630,6 +630,11 @@ QObject *qmlAttachedPropertiesObject(const QObject *obj, bool create = true)
// super types should be registered as CppType (or not at all). We only need the object and its
// QML engine to resolve composite types. Therefore, the function is actually a static property
// of the C++ type system and we can cache it here for improved performance on further lookups.
+ if (const auto func = QQmlPrivate::attachedPropertiesFunc<T>())
+ return qmlAttachedPropertiesObject(const_cast<QObject *>(obj), func, create);
+
+ // Usually the above func should not be nullptr. However, to be safe, keep this fallback
+ // via the metaobject.
static const auto func = qmlAttachedPropertiesFunction(nullptr, &T::staticMetaObject);
return qmlAttachedPropertiesObject(const_cast<QObject *>(obj), func, create);
}
diff --git a/src/qml/qml/qqmlbuiltinfunctions.cpp b/src/qml/qml/qqmlbuiltinfunctions.cpp
index fdc28d727d..0251a72049 100644
--- a/src/qml/qml/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/qqmlbuiltinfunctions.cpp
@@ -2307,12 +2307,13 @@ ReturnedValue GlobalExtensions::method_qsTrNoOp(const FunctionObject *, const Va
\tt{//% <string>}
+ \snippet qml/qsTrId.1.qml 0
+
or
- \tt{\\begincomment% <string> \\endcomment}
+ \tt{\begincomment% <string> \endcomment}
- Example:
- \snippet qml/qsTrId.1.qml 0
+ \snippet qml/qsTrId.1.qml 1
Creating binary translation (QM) files suitable for use with this function requires passing
the \c -idbased option to the \c lrelease tool.
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 5a6fd4c8d3..7b2107b858 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -455,6 +455,10 @@ QQmlComponent::~QQmlComponent()
if (d->typeData) {
d->typeData->unregisterCallback(d);
+ if (d->engine) {
+ QQmlEnginePrivate::get(d->engine)->typeLoader.drop(
+ QQmlDataBlob::Ptr(d->typeData.data()));
+ }
d->typeData.reset();
}
}
@@ -1013,6 +1017,14 @@ QObject *QQmlComponent::beginCreate(QQmlContext *context)
return d->beginCreate(QQmlContextData::get(context));
}
+static QQmlParserStatus *parserStatusCast(const QQmlType &type, QObject *rv)
+{
+ const int parserStatusCast = type.parserStatusCast();
+ return parserStatusCast == -1
+ ? nullptr
+ : reinterpret_cast<QQmlParserStatus *>(reinterpret_cast<char *>(rv) + parserStatusCast);
+}
+
QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> context)
{
Q_Q(QQmlComponent);
@@ -1074,7 +1086,7 @@ QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> conte
if (!loadedType.isValid()) {
enginePriv->referenceScarceResources();
- state.initCreator(std::move(context), compilationUnit, creationContext);
+ state.initCreator(context, compilationUnit, creationContext);
rv = state.creator()->create(start, nullptr, nullptr, isInlineComponent ? QQmlObjectCreator::InlineComponent : QQmlObjectCreator::NormalObject);
if (!rv)
state.appendCreatorErrors();
@@ -1083,26 +1095,21 @@ QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> conte
// TODO: extract into function
rv = loadedType.createWithQQmlData();
QQmlPropertyCache::ConstPtr propertyCache = QQmlData::ensurePropertyCache(rv);
- QQmlParserStatus *parserStatus = nullptr;
- const int parserStatusCast = loadedType.parserStatusCast();
- if (parserStatusCast != -1) {
- parserStatus = reinterpret_cast<QQmlParserStatus*>(reinterpret_cast<char *>(rv) + parserStatusCast);
+ if (QQmlParserStatus *parserStatus = parserStatusCast(loadedType, rv)) {
parserStatus->classBegin();
+ state.ensureRequiredPropertyStorage(rv);
+ } else if (loadedType.finalizerCast() != -1) {
+ state.ensureRequiredPropertyStorage(rv);
}
+
for (int i = 0, propertyCount = propertyCache->propertyCount(); i < propertyCount; ++i) {
if (const QQmlPropertyData *propertyData = propertyCache->property(i); propertyData->isRequired()) {
- state.ensureRequiredPropertyStorage();
+ state.ensureRequiredPropertyStorage(rv);
RequiredPropertyInfo info;
info.propertyName = propertyData->name(rv);
state.addPendingRequiredProperty(rv, propertyData, info);
}
}
- if (parserStatus)
- parserStatus->componentComplete();
- if (const int finalizerCast = loadedType.finalizerCast(); finalizerCast != -1) {
- auto* hook = reinterpret_cast<QQmlFinalizerHook *>(reinterpret_cast<char *>(rv) + finalizerCast);
- hook->componentFinalized();
- }
}
if (rv) {
@@ -1113,6 +1120,12 @@ QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> conte
ddata->indestructible = true;
ddata->explicitIndestructibleSet = true;
ddata->rootObjectInCreation = false;
+
+ // Assign parent context to the object if we haven't created one.
+ if (!ddata->outerContext)
+ ddata->outerContext = context.data();
+ if (!ddata->context)
+ ddata->context = context.data();
}
return rv;
@@ -1249,7 +1262,18 @@ void QQmlComponentPrivate::completeCreate()
state.errors.push_back(QQmlComponentPrivate::AnnotatedQmlError { error, true });
}
}
+
if (loadedType.isValid()) {
+ QObject *rv = state.target();
+ if (QQmlParserStatus *parserStatus = parserStatusCast(loadedType, rv))
+ parserStatus->componentComplete();
+
+ if (const int finalizerCast = loadedType.finalizerCast(); finalizerCast != -1) {
+ auto *hook = reinterpret_cast<QQmlFinalizerHook *>(
+ reinterpret_cast<char *>(rv) + finalizerCast);
+ hook->componentFinalized();
+ }
+
/*
We can directly set completePending to false, as finalize is only concerned
with setting up pending bindings, but that cannot happen here, as we're
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index df6ccc58ca..35e4a3b219 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -111,7 +111,7 @@ public:
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QQmlComponentPrivate::ConstructionState);
- inline void ensureRequiredPropertyStorage();
+ inline void ensureRequiredPropertyStorage(QObject *target);
inline RequiredProperties *requiredProperties();
inline void addPendingRequiredProperty(
const QObject *object, const QQmlPropertyData *propData,
@@ -126,16 +126,31 @@ public:
inline const QQmlObjectCreator *creator() const;
inline void clear();
inline bool hasCreator() const;
- inline QQmlObjectCreator *initCreator(QQmlRefPointer<QQmlContextData> parentContext,
- const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
- const QQmlRefPointer<QQmlContextData> &creationContext);
+ inline QQmlObjectCreator *initCreator(
+ const QQmlRefPointer<QQmlContextData> &parentContext,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QQmlRefPointer<QQmlContextData> &creationContext);
QList<AnnotatedQmlError> errors;
inline bool isCompletePending() const;
inline void setCompletePending(bool isPending);
- private:
- QBiPointer<QQmlObjectCreator, RequiredProperties> m_creatorOrRequiredProperties;
+ QObject *target() const
+ {
+ if (m_creatorOrRequiredProperties.isNull())
+ return nullptr;
+
+ if (m_creatorOrRequiredProperties.isT1()) {
+ const auto &objects = m_creatorOrRequiredProperties.asT1()->allCreatedObjects();
+ return objects.isEmpty() ? nullptr : objects.at(0);
+ }
+
+ Q_ASSERT(m_creatorOrRequiredProperties.isT2());
+ return m_creatorOrRequiredProperties.asT2()->target;
+ }
+
+ private:
+ QBiPointer<QQmlObjectCreator, RequiredPropertiesAndTarget> m_creatorOrRequiredProperties;
};
ConstructionState state;
@@ -267,15 +282,17 @@ inline void QQmlComponentPrivate::ConstructionState::clear()
}
}
-inline QQmlObjectCreator *QQmlComponentPrivate::ConstructionState::initCreator(QQmlRefPointer<QQmlContextData> parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QQmlRefPointer<QQmlContextData> &creationContext)
+inline QQmlObjectCreator *QQmlComponentPrivate::ConstructionState::initCreator(
+ const QQmlRefPointer<QQmlContextData> &parentContext,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QQmlRefPointer<QQmlContextData> &creationContext)
{
if (m_creatorOrRequiredProperties.isT1())
delete m_creatorOrRequiredProperties.asT1();
else
delete m_creatorOrRequiredProperties.asT2();
m_creatorOrRequiredProperties = new QQmlObjectCreator(
- std::move(parentContext), compilationUnit,
- creationContext);
+ parentContext, compilationUnit, creationContext);
return m_creatorOrRequiredProperties.asT1();
}
@@ -293,13 +310,15 @@ inline void QQmlComponentPrivate::ConstructionState::setCompletePending(bool isP
\internal
This is meant to be used in the context of QQmlComponent::loadFromModule,
when dealing with a C++ type. In that case, we do not have a creator,
- and need a separate storage for required properties.
+ and need a separate storage for required properties and the target object.
*/
-inline void QQmlComponentPrivate::ConstructionState::ensureRequiredPropertyStorage()
+inline void QQmlComponentPrivate::ConstructionState::ensureRequiredPropertyStorage(QObject *target)
{
Q_ASSERT(m_creatorOrRequiredProperties.isT2() || m_creatorOrRequiredProperties.isNull());
if (m_creatorOrRequiredProperties.isNull())
- m_creatorOrRequiredProperties = new RequiredProperties;
+ m_creatorOrRequiredProperties = new RequiredPropertiesAndTarget(target);
+ else
+ m_creatorOrRequiredProperties.asT2()->target = target;
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index d3f43cb8c4..d68e778ce2 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -132,7 +132,7 @@ int QQmlCustomParser::evaluateEnum(const QString &script, bool *ok) const
// Allow recursion so that we can find enums from the same document.
const QQmlTypeNameCache::Result result
= imports.asT2()->query<QQmlImport::AllowRecursion>(scope);
- if (result.isValid()) {
+ if (result.type.isValid()) {
type = result.type;
} else if (result.importNamespace) {
dot = nextDot(dot);
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index ae1bd87035..fe8ae5295c 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -297,6 +297,18 @@ public:
void addPluginPath(const QString& path);
+ static void sanitizeUNCPath(QString *path)
+ {
+ // This handles the UNC path case as when the path is retrieved from the QUrl it
+ // will convert the host name from upper case to lower case. So the absoluteFilePath
+ // is changed at this point to make sure it will match later on in that case.
+ if (path->startsWith(QStringLiteral("//"))) {
+ // toLocalFile() since that faithfully restores all the things you can do to a
+ // path but not a URL, in particular weird characters like '%'.
+ *path = QUrl::fromLocalFile(*path).toLocalFile();
+ }
+ }
+
template<typename Callback>
LocalQmldirResult locateLocalQmldir(
const QString &uri, QTypeRevision version, LocalQmldirSearchLocation location,
@@ -397,13 +409,7 @@ QQmlImportDatabase::LocalQmldirResult QQmlImportDatabase::locateLocalQmldir(
url = QStringLiteral("qrc") + absolutePath;
} else {
url = QUrl::fromLocalFile(absolutePath).toString();
- // This handles the UNC path case as when the path is retrieved from the QUrl it
- // will convert the host name from upper case to lower case. So the absoluteFilePath
- // is changed at this point to make sure it will match later on in that case.
- if (qmldirAbsoluteFilePath.startsWith(QStringLiteral("//"))) {
- qmldirAbsoluteFilePath = QUrl::fromLocalFile(qmldirAbsoluteFilePath)
- .toString(QUrl::RemoveScheme);
- }
+ sanitizeUNCPath(&qmldirAbsoluteFilePath);
}
QmldirCache *cache = new QmldirCache;
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index d0025324f4..64e105c74c 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -8,7 +8,6 @@
#include <QtCore/qtimezone.h>
#include <private/qlocale_p.h>
-#include <private/qlocale_data_p.h>
#include <private/qv4dateobject_p.h>
#include <private/qv4numberobject_p.h>
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 80db703e73..119053828f 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -52,7 +52,7 @@ Q_TRACE_POINT(qtqml, QQmlObjectCreator_createInstance_entry, const QV4::Compiled
Q_TRACE_POINT(qtqml, QQmlObjectCreator_createInstance_exit, const QString &typeName)
QQmlObjectCreator::QQmlObjectCreator(
- QQmlRefPointer<QQmlContextData> parentContext,
+ const QQmlRefPointer<QQmlContextData> &parentContext,
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
const QQmlRefPointer<QQmlContextData> &creationContext,
QQmlIncubatorPrivate *incubator)
@@ -64,7 +64,7 @@ QQmlObjectCreator::QQmlObjectCreator(
, isContextObject(true)
, incubator(incubator)
{
- init(std::move(parentContext));
+ init(parentContext);
sharedState->componentAttached = nullptr;
sharedState->allCreatedBindings.allocate(compilationUnit->totalBindingsCount());
@@ -83,7 +83,8 @@ QQmlObjectCreator::QQmlObjectCreator(
}
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlRefPointer<QQmlContextData> parentContext,
+QQmlObjectCreator::QQmlObjectCreator(
+ const QQmlRefPointer<QQmlContextData> &parentContext,
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
QQmlObjectCreatorSharedState *inheritedSharedState, bool isContextObject)
: phase(Startup)
@@ -94,12 +95,12 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlRefPointer<QQmlContextData> parentConte
, isContextObject(isContextObject)
, incubator(nullptr)
{
- init(std::move(parentContext));
+ init(parentContext);
}
-void QQmlObjectCreator::init(QQmlRefPointer<QQmlContextData> providedParentContext)
+void QQmlObjectCreator::init(const QQmlRefPointer<QQmlContextData> &providedParentContext)
{
- parentContext = std::move(providedParentContext);
+ parentContext = providedParentContext;
engine = parentContext->engine();
v4 = engine->handle();
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 36249b45bc..07d8da213d 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -78,6 +78,17 @@ private:
class RequiredProperties : public QHash<RequiredPropertyKey, RequiredPropertyInfo> {};
+class RequiredPropertiesAndTarget : public RequiredProperties
+{
+public:
+ RequiredPropertiesAndTarget(QObject *target) : target(target) {}
+ RequiredPropertiesAndTarget(const RequiredPropertiesAndTarget &) = default;
+ RequiredPropertiesAndTarget(RequiredPropertiesAndTarget &&) = default;
+ RequiredPropertiesAndTarget &operator=(const RequiredPropertiesAndTarget &) = default;
+ RequiredPropertiesAndTarget &operator=(RequiredPropertiesAndTarget &&) = default;
+ QObject *target = nullptr;
+};
+
struct DeferredQPropertyBinding {
QObject *target = nullptr;
int properyIndex = -1;
@@ -105,10 +116,11 @@ class Q_QML_PRIVATE_EXPORT QQmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
public:
- QQmlObjectCreator(QQmlRefPointer<QQmlContextData> parentContext,
- const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
- const QQmlRefPointer<QQmlContextData> &creationContext,
- QQmlIncubatorPrivate *incubator = nullptr);
+ QQmlObjectCreator(
+ const QQmlRefPointer<QQmlContextData> &parentContext,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QQmlRefPointer<QQmlContextData> &creationContext,
+ QQmlIncubatorPrivate *incubator = nullptr);
~QQmlObjectCreator();
enum CreationFlags { NormalObject = 1, InlineComponent = 2 };
@@ -159,12 +171,12 @@ public:
}
private:
- QQmlObjectCreator(QQmlRefPointer<QQmlContextData> contextData,
- const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
- QQmlObjectCreatorSharedState *inheritedSharedState,
- bool isContextObject);
+ QQmlObjectCreator(
+ const QQmlRefPointer<QQmlContextData> &contextData,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ QQmlObjectCreatorSharedState *inheritedSharedState, bool isContextObject);
- void init(QQmlRefPointer<QQmlContextData> parentContext);
+ void init(const QQmlRefPointer<QQmlContextData> &parentContext);
QObject *createInstance(int index, QObject *parent = nullptr, bool isContextObject = false);
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 1430c20099..e8d5b0c8cb 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -872,18 +872,18 @@ static void removeOldBinding(QObject *object, QQmlPropertyIndex index, QQmlPrope
oldBinding = oldBinding->nextBinding();
}
- if (valueTypeIndex != -1
- && oldBinding
- && oldBinding->kind() == QQmlAbstractBinding::ValueTypeProxy) {
- oldBinding = static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
- }
-
if (!oldBinding) {
// Clear the binding bit so that the binding doesn't appear later for any reason
data->clearBindingBit(coreIndex);
return;
}
+ if (valueTypeIndex != -1 && oldBinding->kind() == QQmlAbstractBinding::ValueTypeProxy) {
+ oldBinding = static_cast<QQmlValueTypeProxyBinding *>(oldBinding.data())->binding(index);
+ if (!oldBinding)
+ return;
+ }
+
if (!(flags & QQmlPropertyPrivate::DontEnable))
oldBinding->setEnabled(false, {});
oldBinding->removeFromObject();
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 5c9916193d..72ad77b41c 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -213,6 +213,13 @@ void QQmlTypeLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::C
doLoad(CachedLoader(unit), blob, mode);
}
+void QQmlTypeLoader::drop(const QQmlDataBlob::Ptr &blob)
+{
+ // We must not destroy a QQmlDataBlob from the main thread
+ // since it will shuffle its dependencies around.
+ m_thread->drop(blob);
+}
+
void QQmlTypeLoader::loadWithStaticDataThread(const QQmlDataBlob::Ptr &blob, const QByteArray &data)
{
ASSERT_LOADTHREAD();
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 1e1a03c607..854778125a 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -151,6 +151,7 @@ public:
void load(QQmlDataBlob *, Mode = PreferSynchronous);
void loadWithStaticData(QQmlDataBlob *, const QByteArray &, Mode = PreferSynchronous);
void loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode = PreferSynchronous);
+ void drop(const QQmlDataBlob::Ptr &blob);
QQmlEngine *engine() const;
void initializeEngine(QQmlEngineExtensionInterface *, const char *);
diff --git a/src/qml/qml/qqmltypeloaderthread.cpp b/src/qml/qml/qqmltypeloaderthread.cpp
index 3d35962c08..66e1300684 100644
--- a/src/qml/qml/qqmltypeloaderthread.cpp
+++ b/src/qml/qml/qqmltypeloaderthread.cpp
@@ -102,6 +102,11 @@ void QQmlTypeLoaderThread::initializeEngine(QQmlEngineExtensionInterface *iface,
callMethodInMain(&This::initializeEngineExtensionMain, iface, uri);
}
+void QQmlTypeLoaderThread::drop(const QQmlDataBlob::Ptr &b)
+{
+ postMethodToThread(&This::dropThread, b);
+}
+
void QQmlTypeLoaderThread::loadThread(const QQmlDataBlob::Ptr &b)
{
m_loader->loadThread(b);
@@ -148,4 +153,10 @@ void QQmlTypeLoaderThread::initializeEngineExtensionMain(QQmlEngineExtensionInte
iface->initializeEngine(m_loader->engine(), uri);
}
+void QQmlTypeLoaderThread::dropThread(const QQmlDataBlob::Ptr &b)
+{
+ // Simply drop the reference to b
+ Q_UNUSED(b);
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypeloaderthread_p.h b/src/qml/qml/qqmltypeloaderthread_p.h
index 4f65fc0cbd..e9d2f2da36 100644
--- a/src/qml/qml/qqmltypeloaderthread_p.h
+++ b/src/qml/qml/qqmltypeloaderthread_p.h
@@ -56,6 +56,7 @@ public:
void callDownloadProgressChanged(const QQmlDataBlob::Ptr &b, qreal p);
void initializeEngine(QQmlExtensionInterface *, const char *);
void initializeEngine(QQmlEngineExtensionInterface *, const char *);
+ void drop(const QQmlDataBlob::Ptr &b);
private:
void loadThread(const QQmlDataBlob::Ptr &b);
@@ -65,6 +66,7 @@ private:
void callDownloadProgressChangedMain(const QQmlDataBlob::Ptr &b, qreal p);
void initializeExtensionMain(QQmlExtensionInterface *iface, const char *uri);
void initializeEngineExtensionMain(QQmlEngineExtensionInterface *iface, const char *uri);
+ void dropThread(const QQmlDataBlob::Ptr &b);
QQmlTypeLoader *m_loader;
#if QT_CONFIG(qml_network)
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 07ba1bf9ff..6bd26f65dd 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -706,6 +706,16 @@ ReturnedValue QQmlValueTypeWrapper::lookupGetter(Lookup *lookup, ExecutionEngine
bool QQmlValueTypeWrapper::lookupSetter(
Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
{
+ if (&QQmlValueTypeWrapper::lookupSetter == &QV4::Lookup::setterFallback) {
+ // Certain compilers, e.g. MSVC, will "helpfully" deduplicate methods that are completely
+ // equal. As a result, the pointers are the same, which wreaks havoc on the logic that
+ // decides how to retrieve the property.
+ qFatal("Your C++ compiler is broken.");
+ }
+
+ // This setter marks the presence of a value type setter lookup.
+ // It falls back to the fallback lookup when run through the interpreter, but AOT-compiled
+ // code can get clever with it.
return QV4::Lookup::setterFallback(l, engine, object, value);
}