diff --git a/x11-toolkits/qt6-declarative/Makefile b/x11-toolkits/qt6-declarative/Makefile index 7c94487156b3..b5dfeabf5e6a 100644 --- a/x11-toolkits/qt6-declarative/Makefile +++ b/x11-toolkits/qt6-declarative/Makefile @@ -1,38 +1,38 @@ PORTNAME= declarative DISTVERSION= ${QT6_VERSION} -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES= x11-toolkits PKGNAMEPREFIX= qt6- MAINTAINER= kde@FreeBSD.org COMMENT= Qt declarative framework for dynamic user interfaces BUILD_DEPENDS= ${LOCALBASE}/include/vulkan/vulkan.h:graphics/vulkan-headers LIB_DEPENDS= libxkbcommon.so:x11/libxkbcommon USES= cmake compiler:c++17-lang gl pkgconfig python \ qt-dist:6 USE_GL= opengl USE_LDCONFIG= ${PREFIX}/${QT_LIBDIR_REL} USE_QT= base svg \ languageserver:build shadertools:build CMAKE_ON= CMAKE_DISABLE_FIND_PACKAGE_LTTngUST .include .if ${ARCH} == aarch64 || ${ARCH} == amd64 || ${ARCH:Marmv?} || ${ARCH} == i386 PLIST_SUB+= QML_JIT="" .else PLIST_SUB+= QML_JIT="@comment " .endif post-install: # Install symlinks for user-facing tools while read line; do \ source="$$(${ECHO_CMD} $${line} | ${AWK} '{print $$1}')"; \ target="${STAGEDIR}${PREFIX}/$$(${ECHO_CMD} $${line} | ${AWK} '{print $$2}')"; \ ${RLN} $${source} $${target}; \ done <${BUILD_WRKSRC}/user_facing_tool_links.txt .include diff --git a/x11-toolkits/qt6-declarative/files/patch-QTBUG-142514 b/x11-toolkits/qt6-declarative/files/patch-QTBUG-142514 new file mode 100644 index 000000000000..996ca2882eea --- /dev/null +++ b/x11-toolkits/qt6-declarative/files/patch-QTBUG-142514 @@ -0,0 +1,122 @@ +From dc2358e98b8ddab532866a403ffc09d1162ad0f9 Mon Sep 17 00:00:00 2001 +From: Ulf Hermann +Date: Tue, 13 Jan 2026 11:53:27 +0100 +Subject: [PATCH] QtQml: Do not clear objects' propertyCaches on last GC run + +The property caches are not specific to the engine. The same object may +be exposed to other engines and still require its property cache. When +the clearing of the property caches on engine destruction was +introduced, the property caches were still engine-specific and we had no +choice but to clear them. Otherwise any further access would lead to a +dereference of a dangling pointer. + +Furthermore, when clearing the JS wrapper for a QObject, check if it's +actually the wrapper being deleted. We don't want to clear some other +engine's wrapper. + +Amends commit 749a7212e903d8e8c6f256edb1836b9449cc7fe1. +Amends commit c6b2dd879d02b21b18f80faab541f8f04286685a. + +Pick-to: 6.11 6.10 +Fixes: QTBUG-142514 +Change-Id: I40bb1aeca65225d56cb1d2ff498f5f1722216a70 +Reviewed-by: Fabian Kosmale +--- + +--- src/qml/jsruntime/qv4qobjectwrapper.cpp ++++ src/qml/jsruntime/qv4qobjectwrapper.cpp +@@ -1583,10 +1583,9 @@ + o->deleteLater(); + } else { + // If the object is C++-owned, we still have to release the weak reference we have +- // to it. +- ddata->jsWrapper.clear(); +- if (lastCall && ddata->propertyCache) +- ddata->propertyCache.reset(); ++ // to it. If the "main" wrapper is not ours, we should leave it alone, though. ++ if (ddata->jsWrapper.as() == this) ++ ddata->jsWrapper.clear(); + } + } + } +--- tests/auto/qml/qjsengine/tst_qjsengine.cpp ++++ tests/auto/qml/qjsengine/tst_qjsengine.cpp +@@ -1119,7 +1119,7 @@ + engine.newQObject(obj.data()); + QVERIFY(QQmlData::get(obj.data())->propertyCache); + } +- QVERIFY(!QQmlData::get(obj.data())->propertyCache); ++ QVERIFY(QQmlData::get(obj.data())->propertyCache); + } + + void tst_QJSEngine::newQMetaObject() { +--- tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt ++++ tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +@@ -326,6 +326,7 @@ + stringLength.qml + stringToByteArray.qml + structuredValueType.qml ++ multiEnginePropertyCache.qml + takenumber.qml + testlogger.js + text.qml +--- /dev/null ++++ tests/auto/qml/qmlcppcodegen/data/multiEnginePropertyCache.qml +@@ -0,0 +1,20 @@ ++pragma Strict ++import QtQml ++ ++QtObject { ++ id: root ++ ++ property int foo: 0 ++ onFooChanged: root.close1() ++ ++ property int bar: 0 ++ onBarChanged: close2() ++ ++ function close1() { ++ console.log("close1") ++ } ++ ++ function close2() { ++ console.log("close2") ++ } ++} +--- tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp ++++ tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +@@ -280,6 +280,7 @@ + void stringLength(); + void stringToByteArray(); + void structuredValueType(); ++ void multiEnginePropertyCache(); + void takeNumbers(); + void takeNumbers_data(); + void testIsnan(); +@@ -5795,6 +5796,26 @@ + QCOMPARE(o->property("w2").value(), w2); + } + ++void tst_QmlCppCodegen::multiEnginePropertyCache() ++{ ++ QQmlEngine engine; ++ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/multiEnginePropertyCache.qml"_s)); ++ QVERIFY2(c.isReady(), qPrintable(c.errorString())); ++ std::unique_ptr o(c.create()); ++ QVERIFY(o); ++ ++ { ++ QJSEngine other; ++ other.newQObject(o.get()); ++ } ++ ++ QTest::ignoreMessage(QtDebugMsg, "close1"); ++ o->setProperty("foo", 1); ++ ++ QTest::ignoreMessage(QtDebugMsg, "close2"); ++ o->setProperty("bar", 2); ++} ++ + void tst_QmlCppCodegen::takeNumbers() + { + QFETCH(QByteArray, method);