1116301
From 5a7aa7881fa2c7abffb3d34a6b642fe4efcadbf4 Mon Sep 17 00:00:00 2001
1116301
From: Fabian Kosmale <fabian.kosmale@qt.io>
1116301
Date: Thu, 17 Dec 2020 11:22:34 +0100
1116301
Subject: [PATCH 21/28] QML: Fix proxy iteration
1116301
1116301
If the target of a proxy was extensible, we did not set the
1116301
iteratorTarget to its correct value, and thus the ForInIteratorObject
1116301
would not be usable.
1116301
1116301
Fixes: QTBUG-86323
1116301
Change-Id: Id1924ac4087bab38c006b8eba92b619b79d36b7a
1116301
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
1116301
(cherry picked from commit dd740d6b3469448dc1fd31c1742781e923e9f274)
1116301
---
1116301
 src/qml/jsruntime/qv4proxy.cpp                |  8 +++--
1116301
 .../qqmlecmascript/data/proxyIteration.qml    | 29 +++++++++++++++++++
1116301
 .../qml/qqmlecmascript/tst_qqmlecmascript.cpp | 10 +++++++
1116301
 3 files changed, 45 insertions(+), 2 deletions(-)
1116301
 create mode 100644 tests/auto/qml/qqmlecmascript/data/proxyIteration.qml
1116301
1116301
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
1116301
index 1505eae426..8bfc9fc3ba 100644
1116301
--- a/src/qml/jsruntime/qv4proxy.cpp
1116301
+++ b/src/qml/jsruntime/qv4proxy.cpp
1116301
@@ -624,8 +624,10 @@ OwnPropertyKeyIterator *ProxyObject::virtualOwnPropertyKeys(const Object *m, Val
1116301
         else
1116301
             targetNonConfigurableKeys->push_back(keyAsValue);
1116301
     }
1116301
-    if (target->isExtensible() && targetNonConfigurableKeys->getLength() == 0)
1116301
+    if (target->isExtensible() && targetNonConfigurableKeys->getLength() == 0) {
1116301
+        *iteratorTarget = *m;
1116301
         return new ProxyObjectOwnPropertyKeyIterator(trapKeys);
1116301
+    }
1116301
 
1116301
     ScopedArrayObject uncheckedResultKeys(scope, scope.engine->newArrayObject());
1116301
     uncheckedResultKeys->copyArrayData(trapKeys);
1116301
@@ -639,8 +641,10 @@ OwnPropertyKeyIterator *ProxyObject::virtualOwnPropertyKeys(const Object *m, Val
1116301
         }
1116301
     }
1116301
 
1116301
-    if (target->isExtensible())
1116301
+    if (target->isExtensible()) {
1116301
+        *iteratorTarget = *m;
1116301
         return new ProxyObjectOwnPropertyKeyIterator(trapKeys);
1116301
+    }
1116301
 
1116301
     len = targetConfigurableKeys->getLength();
1116301
     for (uint i = 0; i < len; ++i) {
1116301
diff --git a/tests/auto/qml/qqmlecmascript/data/proxyIteration.qml b/tests/auto/qml/qqmlecmascript/data/proxyIteration.qml
1116301
new file mode 100644
1116301
index 0000000000..affba7d9f1
1116301
--- /dev/null
1116301
+++ b/tests/auto/qml/qqmlecmascript/data/proxyIteration.qml
1116301
@@ -0,0 +1,29 @@
1116301
+import QtQml 2
1116301
+
1116301
+QtObject {
1116301
+  id: root
1116301
+  property int sum
1116301
+  Component.onCompleted: {
1116301
+    const target = { prop1: 1, prop2: 2, prop3: 3 };
1116301
+    const handler = {
1116301
+      get: function(target, key) {
1116301
+        return target[key]+1;
1116301
+      },
1116301
+      ownKeys: function() {
1116301
+        return ["prop1", "prop3"];
1116301
+      },
1116301
+      getOwnPropertyDescriptor: function(target, key) {
1116301
+        return {
1116301
+          value: this.get(target, key),
1116301
+          enumerable: true,
1116301
+          configurable: true
1116301
+        };
1116301
+      }
1116301
+    };
1116301
+    const proxy = new Proxy(target, handler);
1116301
+    for (var prop in proxy) {
1116301
+      root.sum += proxy[prop] // prop2 gets skipped, the values of 1 and 3 get incremented
1116301
+    }
1116301
+    // so root.sum should be 6 now
1116301
+  }
1116301
+}
1116301
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
1116301
index 3a9d1bfb4c..9198d3bebf 100644
1116301
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
1116301
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
1116301
@@ -382,6 +382,7 @@ private slots:
1116301
     void semicolonAfterProperty();
1116301
     void hugeStack();
1116301
     void variantConversionMethod();
1116301
+    void proxyIteration();
1116301
     void proxyHandlerTraps();
1116301
     void gcCrashRegressionTest();
1116301
 
1116301
@@ -9306,6 +9307,15 @@ void tst_qqmlecmascript::variantConversionMethod()
1116301
     QCOMPARE(obj.funcCalled, QLatin1String("QModelIndex"));
1116301
 }
1116301
 
1116301
+void tst_qqmlecmascript::proxyIteration()
1116301
+{
1116301
+    QQmlEngine engine;
1116301
+    QQmlComponent component(&engine, testFileUrl("proxyIteration.qml"));
1116301
+    QScopedPointer<QObject> root(component.create());
1116301
+    QVERIFY2(root != nullptr, qPrintable(component.errorString()));
1116301
+    QCOMPARE(root->property("sum").toInt(), 6);
1116301
+}
1116301
+
1116301
 void tst_qqmlecmascript::proxyHandlerTraps()
1116301
 {
1116301
     const QString expression = QStringLiteral(R"SNIPPET(
1116301
-- 
1116301
2.31.1
1116301