aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2025-08-27 14:51:16 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2025-09-02 12:02:15 +0000
commit22ebf6c98205294f3fd8c0911ec13f955c222007 (patch)
tree62aea7189ce5e6f9a22b0a63f8f10c50b32257fe
parent96ac0f92a7f6dc82ad7d725373b89d73d1a4d475 (diff)
QtQml: Extract method to create the inline storage for Sequence
We will get a different kind of storage in addition. The unification of the different init() methods uncovers a bug: The storage can indeed be nullptr when querying the size later. If you construct a detached sequence from a null container, there is no reason to create the internal storage. The size is evidently 0 in that case. Fix sizeInline() to tell us as much. Pick-to: 6.8 Task-number: QTBUG-129972 Task-number: QTBUG-139025 Change-Id: I33347805fc79f81c69c3191a76ff9167186b43f0 Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io> (cherry picked from commit 706e479e3b7a71f070ef6c05f00143e1842f2ec8) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 06d100df8dfbadbbe6877d7c010e28c2ab50ccf4)
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp28
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h1
2 files changed, 20 insertions, 9 deletions
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index ae0ab27371..d9744dac14 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -80,8 +80,13 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
static qsizetype sizeInline(const Heap::Sequence *p)
{
- Q_ASSERT(p->storagePointer()); // Must readReference() before
- return p->metaSequence().size(p->storagePointer());
+ if (const void *container = p->storagePointer())
+ return p->metaSequence().size(container);
+
+ // It can be stored inline, and the container can still be nullptr.
+ // This happens if we construct it from a nullptr in the first place and never update it.
+ // It means it's empty.
+ return 0;
}
struct SequenceOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
@@ -121,16 +126,13 @@ void Heap::Sequence::initTypes(QMetaType listType, QMetaSequence metaSequence)
Q_ASSERT(m_listType);
m_metaSequence = metaSequence.iface();
Q_ASSERT(m_metaSequence);
- QV4::Scope scope(internalClass->engine);
- QV4::Scoped<QV4::Sequence> o(scope, this);
- o->setArrayType(Heap::ArrayData::Custom);
}
void Heap::Sequence::init(QMetaType listType, QMetaSequence metaSequence, const void *container)
{
ReferenceObject::init(nullptr, -1, NoFlag);
initTypes(listType, metaSequence);
- m_container = listType.create(container);
+ createInlineStorage(container);
}
void Heap::Sequence::init(
@@ -142,12 +144,20 @@ void Heap::Sequence::init(
if (CppStackFrame *frame = internalClass->engine->currentStackFrame)
setLocation(frame->v4Function, frame->statementNumber());
- if (container)
- m_container = listType.create(container);
- else if (flags & EnforcesLocation)
+ createInlineStorage(container);
+ if (!container && (flags & EnforcesLocation))
QV4::ReferenceObject::readReference(this);
}
+void Heap::Sequence::createInlineStorage(const void *container)
+{
+ QV4::Scope scope(internalClass->engine);
+ QV4::Scoped<QV4::Sequence> o(scope, this);
+ o->setArrayType(Heap::ArrayData::Custom);
+ if (container)
+ m_container = listType().create(container);
+}
+
Heap::Sequence *Heap::Sequence::detached() const
{
return internalClass->engine->memoryManager->allocate<QV4::Sequence>(
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index fb9e9ff5ea..a3d920c144 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -96,6 +96,7 @@ private:
friend struct QV4::SequenceOwnPropertyKeyIterator;
void initTypes(QMetaType listType, QMetaSequence metaSequence);
+ void createInlineStorage(const void *container);
bool loadReference();
bool storeReference();