aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-09-30 15:32:14 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-10-14 22:05:42 +0200
commit1aa0b1c3989eebcbdca6655648e397937c11fc24 (patch)
tree4a93ccc4480ccf7013e02a160456cdaee498ac60 /src/qml/jsruntime
parent700dfe7cb6705a79fa7ad3a6499787bcac9d5b31 (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.h30
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp11
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h4
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();
};
}