aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4qobjectwrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4qobjectwrapper.cpp')
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index a17de5d94d..61678acdad 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -814,6 +814,74 @@ void QObjectWrapper::virtualAdvanceIterator(Managed *m, ObjectIterator *it, Valu
QV4::Object::virtualAdvanceIterator(m, it, name, index, p, attributes);
}
+struct QObjectWrapperOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
+{
+ int propertyIndex = 0;
+ ~QObjectWrapperOwnPropertyKeyIterator() override = default;
+ PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
+
+};
+
+PropertyKey QObjectWrapperOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
+{
+ // Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
+ static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
+ static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
+ static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
+
+ const QObjectWrapper *that = static_cast<const QObjectWrapper*>(o);
+
+ QObject *thatObject = that->d()->object();
+ if (thatObject && !QQmlData::wasDeleted(thatObject)) {
+ const QMetaObject *mo = thatObject->metaObject();
+ // These indices don't apply to gadgets, so don't block them.
+ const bool preventDestruction = mo->superClass() || mo == &QObject::staticMetaObject;
+ const int propertyCount = mo->propertyCount();
+ if (propertyIndex < propertyCount) {
+ ExecutionEngine *thatEngine = that->engine();
+ Scope scope(thatEngine);
+ const QMetaProperty property = mo->property(propertyIndex);
+ ScopedString propName(scope, thatEngine->newString(QString::fromUtf8(property.name())));
+ ++propertyIndex;
+ if (attrs)
+ *attrs= QV4::Attr_Data;
+ if (pd) {
+ QQmlPropertyData local;
+ local.load(property);
+ pd->value = that->getProperty(thatEngine, thatObject, &local);
+ }
+ return propName->toPropertyKey();
+ }
+ const int methodCount = mo->methodCount();
+ while (propertyIndex < propertyCount + methodCount) {
+ Q_ASSERT(propertyIndex >= propertyCount);
+ int index = propertyIndex - propertyCount;
+ const QMetaMethod method = mo->method(index);
+ ++propertyIndex;
+ if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)))
+ continue;
+ ExecutionEngine *thatEngine = that->engine();
+ Scope scope(thatEngine);
+ ScopedString methodName(scope, thatEngine->newString(QString::fromUtf8(method.name())));
+ if (attrs)
+ *attrs = QV4::Attr_Data;
+ if (pd) {
+ QQmlPropertyData local;
+ local.load(method);
+ pd->value = that->getProperty(thatEngine, thatObject, &local);
+ }
+ return methodName->toPropertyKey();
+ }
+ }
+
+ return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
+}
+
+OwnPropertyKeyIterator *QObjectWrapper::virtualOwnPropertyKeys(const Object *)
+{
+ return new QObjectWrapperOwnPropertyKeyIterator;
+}
+
namespace QV4 {
struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase