diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2022-09-30 15:32:14 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-10-14 22:05:42 +0200 |
commit | 1aa0b1c3989eebcbdca6655648e397937c11fc24 (patch) | |
tree | 4a93ccc4480ccf7013e02a160456cdaee498ac60 /src/qml/jsruntime | |
parent | 700dfe7cb6705a79fa7ad3a6499787bcac9d5b31 (diff) |
QML: Track statement locations in sequence and value types
With this in place we can enforce that reference objects we add in the
future can only be written back in the same statement as they were
created.
Task-number: QTBUG-99766
Change-Id: I1c74bd239caa1bb5febd1a3705d8ee29a8fc4249
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4referenceobject_p.h | 30 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 11 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject_p.h | 4 |
3 files changed, 39 insertions, 6 deletions
diff --git a/src/qml/jsruntime/qv4referenceobject_p.h b/src/qml/jsruntime/qv4referenceobject_p.h index 3dfea409db..61b8f02206 100644 --- a/src/qml/jsruntime/qv4referenceobject_p.h +++ b/src/qml/jsruntime/qv4referenceobject_p.h @@ -32,6 +32,7 @@ DECLARE_HEAP_OBJECT(ReferenceObject, Object) { NoFlag = 0, CanWriteBack = 1 << 0, IsVariant = 1 << 1, + EnforcesLocation = 1 << 2, }; Q_DECLARE_FLAGS(Flags, Flag); @@ -59,6 +60,33 @@ DECLARE_HEAP_OBJECT(ReferenceObject, Object) { void setIsVariant(bool isVariant) { setFlag(IsVariant, isVariant); } bool isVariant() const { return hasFlag(IsVariant); } + + void setEnforcesLocation(bool enforces) { setFlag(EnforcesLocation, enforces); } + bool enforcesLocation() const { return hasFlag(EnforcesLocation); } + + void setLocation(const Function *function, quint16 statement) + { + m_function = function; + m_statementIndex = statement; + } + + const Function *function() const { return m_function; } + quint16 statementIndex() const { return m_statementIndex; } + + bool isAttachedToProperty() const + { + if (enforcesLocation()) { + if (CppStackFrame *frame = internalClass->engine->currentStackFrame) { + if (frame->v4Function != function() || frame->statementNumber() != statementIndex()) + return false; + } else { + return false; + } + } + + return true; + } + bool isReference() const { return m_property >= 0; } private: @@ -74,7 +102,9 @@ private: } QV4QPointer<QObject> m_object; + const Function *m_function; int m_property; + quint16 m_statementIndex; quint8 m_flags; }; diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 2558e376b5..6aadf68c05 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -162,6 +162,8 @@ void Heap::Sequence::init( QV4::Scope scope(internalClass->engine); QV4::Scoped<QV4::Sequence> o(scope, this); o->setArrayType(Heap::ArrayData::Custom); + if (CppStackFrame *frame = scope.engine->currentStackFrame) + setLocation(frame->v4Function, frame->statementNumber()); o->loadReference(); } @@ -422,18 +424,19 @@ bool Sequence::sort(const FunctionObject *f, const Value *, const Value *argv, i void *Sequence::getRawContainerPtr() const { return d()->storagePointer(); } -void Sequence::loadReference() const +bool Sequence::loadReference() const { Q_ASSERT(d()->object()); Q_ASSERT(d()->isReference()); - QV4::ReferenceObject::readReference(d()); + // If locations are enforced we only read once + return d()->enforcesLocation() || QV4::ReferenceObject::readReference(d()); } -void Sequence::storeReference() +bool Sequence::storeReference() { Q_ASSERT(d()->object()); Q_ASSERT(d()->isReference()); - QV4::ReferenceObject::writeBack(d()); + return d()->isAttachedToProperty() && QV4::ReferenceObject::writeBack(d()); } ReturnedValue Sequence::virtualGet(const Managed *that, PropertyKey id, const Value *receiver, bool *hasProperty) diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h index 6d0a85ded6..f6055e38e3 100644 --- a/src/qml/jsruntime/qv4sequenceobject_p.h +++ b/src/qml/jsruntime/qv4sequenceobject_p.h @@ -100,8 +100,8 @@ public: bool containerIsEqualTo(Managed *other); bool sort(const FunctionObject *f, const Value *, const Value *argv, int argc); void *getRawContainerPtr() const; - void loadReference() const; - void storeReference(); + bool loadReference() const; + bool storeReference(); }; } |