diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index 26b5348f21..7186adb88c 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -610,6 +610,12 @@ void QQmlJSImportVisitor::processDefaultProperties() const QQmlJSMetaProperty defaultProp = parentScope->property(defaultPropertyName); auto propType = defaultProp.type(); const auto handleUnresolvedDefaultProperty = [&](const QQmlJSScope::ConstPtr &) { + + // Since we don't know the property type, we need to assume it's QQmlComponent and that + // IDs from the inner scopes are inaccessible. + for (const QQmlJSScope::Ptr &scope : std::as_const(*it)) + scope->setIsWrappedInImplicitComponent(true); + // Property type is not fully resolved we cannot tell any more than this m_logger->log(QStringLiteral("Property \"%1\" has incomplete type \"%2\". You may be " "missing an import.") @@ -735,9 +741,20 @@ void QQmlJSImportVisitor::processPropertyBindingObjects() for (const PendingPropertyObjectBinding &objectBinding : std::as_const(m_pendingPropertyObjectBindings)) { const QString propertyName = objectBinding.name; - QQmlJSScope::ConstPtr childScope = objectBinding.childScope; + QQmlJSScope::Ptr childScope = objectBinding.childScope; - if (!isTypeResolved(objectBinding.scope)) // guarantees property lookup + const auto handleUnresolvedType = [&](const QQmlJSScope::ConstPtr &type) { + // Since we don't know the property type we need to assume that it's QQmlComponent and + // that IDs from the child scope are inaccessible outside of it. + childScope->setIsWrappedInImplicitComponent(true); + + m_logger->log(QStringLiteral("Type %1 is used but it is not resolved") + .arg(getScopeName(type, type->scopeType())), + qmlUnresolvedType, type->sourceLocation()); + }; + + // guarantees property lookup + if (!isTypeResolved(objectBinding.scope, handleUnresolvedType)) continue; QQmlJSMetaProperty property = objectBinding.scope->property(propertyName); @@ -748,6 +765,11 @@ void QQmlJSImportVisitor::processPropertyBindingObjects() continue; } const auto handleUnresolvedProperty = [&](const QQmlJSScope::ConstPtr &) { + + // Since we don't know the property type we need to assume that it's QQmlComponent and + // that IDs from the child scope are inaccessible outside of it. + childScope->setIsWrappedInImplicitComponent(true); + // Property type is not fully resolved we cannot tell any more than this m_logger->log(QStringLiteral("Property \"%1\" has incomplete type \"%2\". You may be " "missing an import.") @@ -774,7 +796,7 @@ void QQmlJSImportVisitor::processPropertyBindingObjects() continue; } - objectBinding.childScope->setIsWrappedInImplicitComponent( + childScope->setIsWrappedInImplicitComponent( causesImplicitComponentWrapping(property, childScope)); // unique because it's per-scope and per-property diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index cae3628628..2b88519f4e 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -167,6 +167,7 @@ set(qml_files indirectlyShadowable.qml infinities.qml infinitiesToInt.qml + insertContextOnInvalidType.qml intEnumCompare.qml intOverflow.qml intToEnum.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/insertContextOnInvalidType.qml b/tests/auto/qml/qmlcppcodegen/data/insertContextOnInvalidType.qml new file mode 100644 index 0000000000..38186e22cf --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/insertContextOnInvalidType.qml @@ -0,0 +1,7 @@ +import QtQml +import Handlerei + +HandleHandler { + property var handleDelegateOutter: handleDelegate + handle: QtObject { id: handleDelegate } +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index c1ab9476a9..eab0a70abd 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -130,6 +130,7 @@ private slots: void infinities(); void infinitiesToInt(); void innerObjectNonShadowable(); + void insertContextOnInvalidType(); void intEnumCompare(); void intOverflow(); void intToEnum(); @@ -2475,6 +2476,36 @@ void tst_QmlCppCodegen::innerObjectNonShadowable() QCOMPARE(rootObject->objectName(), u"foo"_s); } +class HandleHandler : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQmlComponent *handle MEMBER m_handle) + +private: + QQmlComponent *m_handle = nullptr; +}; + +void tst_QmlCppCodegen::insertContextOnInvalidType() +{ + qmlRegisterType("Handlerei", 1, 0, "HandleHandler"); + + QQmlEngine engine; + QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/insertContextOnInvalidType.qml"_s)); + + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + + QTest::ignoreMessage( + QtWarningMsg, + "qrc:/qt/qml/TestTypes/insertContextOnInvalidType.qml:5: " + "ReferenceError: handleDelegate is not defined"); + QScopedPointer rootObject(component.create()); + QVERIFY(rootObject); + + const char *outter = "handleDelegateOutter"; + QVERIFY(rootObject->metaObject()->indexOfProperty(outter) != -1); + QVERIFY(!rootObject->property(outter).isValid()); +} + void tst_QmlCppCodegen::intEnumCompare() { QQmlEngine engine;