diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2025-08-27 14:51:16 +0200 |
|---|---|---|
| committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2025-09-02 12:02:15 +0000 |
| commit | 22ebf6c98205294f3fd8c0911ec13f955c222007 (patch) | |
| tree | 62aea7189ce5e6f9a22b0a63f8f10c50b32257fe | |
| parent | 96ac0f92a7f6dc82ad7d725373b89d73d1a4d475 (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.cpp | 28 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4sequenceobject_p.h | 1 |
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(); |
