aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qml')
-rw-r--r--tests/auto/qml/CMakeLists.txt21
-rw-r--r--tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp5
-rw-r--r--tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp5
-rw-r--r--tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp44
-rw-r--r--tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp2
-rw-r--r--tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt6
-rw-r--r--tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp10
-rw-r--r--tests/auto/qml/bindingdependencyapi/CMakeLists.txt6
-rw-r--r--tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp34
-rw-r--r--tests/auto/qml/common/CMakeLists.txt11
-rw-r--r--tests/auto/qml/common/tst_qml_common.cpp168
-rw-r--r--tests/auto/qml/common/tst_qml_common.h35
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp2
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp36
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp13
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp16
-rw-r--r--tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/condition.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/exception.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/quit.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/test.js2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/data/timer.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp74
-rw-r--r--tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp56
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml2
-rw-r--r--tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp26
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml4
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp59
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/broken.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/window.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/window1.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/window2.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/data/zoom.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp4
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt6
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml2
-rw-r--r--tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp14
-rw-r--r--tests/auto/qml/debugger/qv4debugger/CMakeLists.txt9
-rw-r--r--tests/auto/qml/debugger/qv4debugger/commontypes.h4
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml4
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/module1.js5
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/module2.mjs7
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/module3.mjs0
-rw-r--r--tests/auto/qml/debugger/qv4debugger/data/module4.mjs0
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp81
-rw-r--r--tests/auto/qml/debugger/shared/debugutil.cpp2
-rw-r--r--tests/auto/qml/debugger/shared/debugutil_p.h2
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugprocess.cpp4
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugprocess_p.h2
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp2
-rw-r--r--tests/auto/qml/debugger/shared/qqmldebugtestservice.h2
-rw-r--r--tests/auto/qml/ecmascripttests/CMakeLists.txt13
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations10
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/CMakeLists.txt28
-rw-r--r--tests/auto/qml/ecmascripttests/qjstest/main.cpp90
-rwxr-xr-xtests/auto/qml/ecmascripttests/test262.py611
-rw-r--r--tests/auto/qml/ecmascripttests/test262runner.cpp (renamed from tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp)529
-rw-r--r--tests/auto/qml/ecmascripttests/test262runner.h (renamed from tests/auto/qml/ecmascripttests/qjstest/test262runner.h)54
-rw-r--r--tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp94
-rw-r--r--tests/auto/qml/linebylinelex/BLACKLIST5
-rw-r--r--tests/auto/qml/linebylinelex/CMakeLists.txt28
-rw-r--r--tests/auto/qml/linebylinelex/tst_linebylinelex.cpp17
-rw-r--r--tests/auto/qml/parserstress/CMakeLists.txt6
-rw-r--r--tests/auto/qml/parserstress/tst_parserstress.cpp6
-rw-r--r--tests/auto/qml/qjsengine/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp464
-rw-r--r--tests/auto/qml/qjsmanagedvalue/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp23
-rw-r--r--tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h2
-rw-r--r--tests/auto/qml/qjsonbinding/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp11
-rw-r--r--tests/auto/qml/qjsprimitivevalue/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp34
-rw-r--r--tests/auto/qml/qjsvalue/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.cpp42
-rw-r--r--tests/auto/qml/qjsvalue/tst_qjsvalue.h9
-rw-r--r--tests/auto/qml/qjsvalueiterator/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp6
-rw-r--r--tests/auto/qml/qml/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qml/data/resizeItem.qml28
-rw-r--r--tests/auto/qml/qml/data/sizedItem.qml19
-rw-r--r--tests/auto/qml/qml/data/unsizedItem.qml18
-rw-r--r--tests/auto/qml/qml/tst_qml.cpp127
-rw-r--r--tests/auto/qml/qmlbasicapp/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp2
-rw-r--r--tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h2
-rw-r--r--tests/auto/qml/qmlbasicapp/main.qml2
-rw-r--r--tests/auto/qml/qmlbasicapp/manual_imports.cpp2
-rw-r--r--tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp2
-rw-r--r--tests/auto/qml/qmlcachegen/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml11
-rw-r--r--tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml7
-rw-r--r--tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc5
-rw-r--r--tests/auto/qml/qmlcachegen/data/aotstats/qmldir3
-rw-r--r--tests/auto/qml/qmlcachegen/data/truncateTest.qml764
-rw-r--r--tests/auto/qml/qmlcachegen/scriptstringprops.h2
-rw-r--r--tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp159
-rw-r--r--tests/auto/qml/qmlcppcodegen/CMakeLists.txt18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Action.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/B.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/BaseConstraint.qml9
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt279
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/CppMethodListReturnType.qml12
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Dummy2.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/EditConstraint.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupOnQJSValueNonStrict.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupShadowed.qml19
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/NotificationItem.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/NotificationsUtils.js3
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Panel.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Planner.qml50
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Satisfaction.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml12
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/Variable.qml22
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ambiguous.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ambiguousAs.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/arrayCtor.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/asCast.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump.qml33
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump_infinite.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/basicDTZ.qml40
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp19
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/birthdayparty.h8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/boolCoercions.qml45
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/boolPointerMerge.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/childobject.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/compareOriginals.qml39
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/comparisonTypes.qml54
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/consoleTrace.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/conversionInDeadCode.qml32
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/conversions2.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/convertPrimitiveToVar.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.h34
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/convertToOriginalReadAcumulatorForUnaryOperators.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dateConstruction.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dateConversions.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dialogButtonBox.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dummyobjekt.h29
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h41
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enforceSignature.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumConversion.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumFromBadSingleton.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumMarkedAsFlag.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumProblems.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumProperty.h71
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/enumproblems.h68
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/equalityQUrl.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/equalityTestsWithNullOrUndefined.qml14
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/exceptionFromInner.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/extra/extra.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/extra2/extra.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/failures.qml60
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/fallbackresettable.qml23
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/fileDialog.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/flagEnum.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h38
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.h42
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.qml34
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/idAccess.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/ignoredFunctionReturn.qml14
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml39
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/intToEnum.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/interactive.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/internalConversion.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/invisible.h36
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/iteration.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/jsArrayMethods.qml28
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsUntyped.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParams.qml26
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParamsUntyped.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/listConversion.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/listOfInvisible.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/listToString.qml25
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/listprovider.h24
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/math.qml1
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/mathMinMax.qml59
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/mathStaticProperties.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/mergedObjectRead.qml14
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/mergedObjectWrite.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/methodOnListLookup.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/methods.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/multiforeign.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/multipleCtors.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/nullAccessInsideSignalHandler.qml33
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/nullComparison.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/nullishCoalescing.qml37
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml42
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/objectLookupOnListElement.qml34
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/objectWithStringListMethod.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h53
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/optionalComparison.qml77
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/person.cpp20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/person.h44
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/qtbug113150.qml13
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/readEnumFromInstance.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/readonlyListProperty.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml19
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/resettable.h39
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/resettable.qml23
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/returnAfterReject.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml19
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h56
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.qml20
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/setLookupConversion.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/setLookupOriginalScope.qml17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml31
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/shadowedMethod.qml35
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/shadowedPrimitiveCmpEqNull.qml16
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/signalsWithLists.qml18
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/state.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/structuredValueType.qml8
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/theme.cpp2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/theme.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/thisObject.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/timelinetheme.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/topLevelComponent.qml14
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/trigraphs.qml5
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/tst_qmlcppcodegen_verify.cpp47
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/undefinedToDouble.qml6
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/urlString.qml7
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/valueTypeCast.qml43
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml34
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantMap.qml27
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h17
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml11
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantReturn.qml15
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/variantreturn.h63
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/voidConversion.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/weathermoduleurl.h61
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/withlength.h28
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h2
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h31
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml10
-rw-r--r--tests/auto/qml/qmlcppcodegen/data/writeback.qml43
-rw-r--r--tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp5745
-rw-r--r--tests/auto/qml/qmldiskcache/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp404
-rw-r--r--tests/auto/qml/qmlformat/CMakeLists.txt9
-rw-r--r--tests/auto/qml/qmlformat/data/Annotations.formatted.qml17
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/Example1.formatted2.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/FrontInline.formatted.qml3
-rw-r--r--tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml4
-rw-r--r--tests/auto/qml/qmlformat/data/arrayEndComma.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml15
-rw-r--r--tests/auto/qml/qmlformat/data/class.formatted.js5
-rw-r--r--tests/auto/qml/qmlformat/data/class.js1
-rw-r--r--tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml11
-rw-r--r--tests/auto/qml/qmlformat/data/commentInEnum.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml4
-rw-r--r--tests/auto/qml/qmlformat/data/commentInQmlObject.qml5
-rw-r--r--tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml24
-rw-r--r--tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml9
-rw-r--r--tests/auto/qml/qmlformat/data/directives.formatted.js8
-rw-r--r--tests/auto/qml/qmlformat/data/directives.js9
-rw-r--r--tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js6
-rw-r--r--tests/auto/qml/qmlformat/data/directivesWithComments.js8
-rw-r--r--tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/dontRemoveComments.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml2
-rw-r--r--tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml13
-rw-r--r--tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml11
-rw-r--r--tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/enumWithValues.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/escapeChars.formatted.qml16
-rw-r--r--tests/auto/qml/qmlformat/data/escapeChars.qml16
-rw-r--r--tests/auto/qml/qmlformat/data/esm.formatted.mjs44
-rw-r--r--tests/auto/qml/qmlformat/data/esm.mjs33
-rw-r--r--tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/filesOption/valid1.qml9
-rw-r--r--tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml10
-rw-r--r--tests/auto/qml/qmlformat/data/filesOption/valid2.qml9
-rw-r--r--tests/auto/qml/qmlformat/data/forOf.formatted.qml1
-rw-r--r--tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml3
-rw-r--r--tests/auto/qml/qmlformat/data/importStatements.formatted.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/importStatements.qml12
-rw-r--r--tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml6
-rw-r--r--tests/auto/qml/qmlformat/data/javascriptBlock.qml5
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js6
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js1
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js7
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaWithIfElse.js1
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js9
-rw-r--r--tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js1
-rw-r--r--tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js4
-rw-r--r--tests/auto/qml/qmlformat/data/messyIfStatement.js2
-rw-r--r--tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs20
-rw-r--r--tests/auto/qml/qmlformat/data/mini_esm.mjs3
-rw-r--r--tests/auto/qml/qmlformat/data/multilineComment.formatted.qml6
-rw-r--r--tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml2
-rw-r--r--tests/auto/qml/qmlformat/data/nestedIf.formatted.qml1
-rw-r--r--tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml137
-rw-r--r--tests/auto/qml/qmlformat/data/objectDestructuring.qml77
-rw-r--r--tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml3
-rw-r--r--tests/auto/qml/qmlformat/data/objectsSpacing.qml4
-rw-r--r--tests/auto/qml/qmlformat/data/pragma.formatted.js4
-rw-r--r--tests/auto/qml/qmlformat/data/pragma.formatted.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/pragma.js1
-rw-r--r--tests/auto/qml/qmlformat/data/pragma.qml8
-rw-r--r--tests/auto/qml/qmlformat/data/propertyNames.formatted.qml6
-rw-r--r--tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml2
-rw-r--r--tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js1
-rw-r--r--tests/auto/qml/qmlformat/data/simpleJSStatement.js1
-rw-r--r--tests/auto/qml/qmlformat/data/simpleLoop.formatted.js4
-rw-r--r--tests/auto/qml/qmlformat/data/simpleLoop.js1
-rw-r--r--tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js4
-rw-r--r--tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js1
-rw-r--r--tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml9
-rw-r--r--tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js11
-rw-r--r--tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js9
-rw-r--r--tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js9
-rw-r--r--tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js1
-rw-r--r--tests/auto/qml/qmlformat/data/twoFunctions.formatted.js12
-rw-r--r--tests/auto/qml/qmlformat/data/twoFunctions.js3
-rw-r--r--tests/auto/qml/qmlformat/tst_qmlformat.cpp311
-rw-r--r--tests/auto/qml/qmlimportscanner/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json30
-rw-r--r--tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Drawer.qml.json30
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Imports.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json46
-rw-r--r--tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Simple.qml.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Singleton.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Things.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json36
-rw-r--r--tests/auto/qml/qmlimportscanner/data/localImport.qml.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json34
-rw-r--r--tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json30
-rw-r--r--tests/auto/qml/qmlimportscanner/data/rootPath.json40
-rw-r--r--tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp4
-rw-r--r--tests/auto/qml/qmllint/CMakeLists.txt12
-rw-r--r--tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml5
-rw-r--r--tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir2
-rw-r--r--tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml14
-rw-r--r--tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes31
-rw-r--r--tests/auto/qml/qmllint/data/LocaleTest/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc10
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir1
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir1
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qmldir5
-rw-r--r--tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes112
-rw-r--r--tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml12
-rw-r--r--tests/auto/qml/qmllint/data/MyStyle/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/NeedImportPath.qml5
-rw-r--r--tests/auto/qml/qmllint/data/Qtbug111015/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes20
-rw-r--r--tests/auto/qml/qmllint/data/SharedFunctions.js5
-rw-r--r--tests/auto/qml/qmllint/data/StringToDateTime/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes14
-rw-r--r--tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes20
-rw-r--r--tests/auto/qml/qmllint/data/Things/plugins.qmltypes20
-rw-r--r--tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml12
-rw-r--r--tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml12
-rw-r--r--tests/auto/qml/qmllint/data/addressableValue.qml8
-rw-r--r--tests/auto/qml/qmllint/data/attachedImportUse.qml7
-rw-r--r--tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml8
-rw-r--r--tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes513
-rw-r--r--tests/auto/qml/qmllint/data/coercetovoid.qml8
-rw-r--r--tests/auto/qml/qmllint/data/customParser.qml4
-rw-r--r--tests/auto/qml/qmllint/data/dontCheckJSTypes.qml11
-rw-r--r--tests/auto/qml/qmllint/data/findMemberPrint.qml13
-rw-r--r--tests/auto/qml/qmllint/data/generalizedGroupHint.qml23
-rw-r--r--tests/auto/qml/qmllint/data/groupedAttachedLayout.qml20
-rw-r--r--tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml11
-rw-r--r--tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/importNonexistentFile.qml3
-rw-r--r--tests/auto/qml/qmllint/data/importNullDevice.qml3
-rw-r--r--tests/auto/qml/qmllint/data/initReadonly.qml1
-rw-r--r--tests/auto/qml/qmllint/data/inlineComponent.qml1
-rw-r--r--tests/auto/qml/qmllint/data/invalidIdLookup.qml10
-rw-r--r--tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml8
-rw-r--r--tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml8
-rw-r--r--tests/auto/qml/qmllint/data/locale.qml6
-rw-r--r--tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml9
-rw-r--r--tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml9
-rw-r--r--tests/auto/qml/qmllint/data/multifix.fixed.qml14
-rw-r--r--tests/auto/qml/qmllint/data/multifix.qml13
-rw-r--r--tests/auto/qml/qmllint/data/notQmlRootMethods.qml8
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml1
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml8
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml19
-rw-r--r--tests/auto/qml/qmllint/data/qEventPoint.qml9
-rw-r--r--tests/auto/qml/qmllint/data/qmlRootMethods.qml12
-rw-r--r--tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml2
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml9
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml5
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml6
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml7
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml5
-rw-r--r--tests/auto/qml/qmllint/data/scriptInTemplate.qml6
-rw-r--r--tests/auto/qml/qmllint/data/scripts/Foo.js6
-rw-r--r--tests/auto/qml/qmllint/data/scripts/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/scripts/scripts.qmltypes22
-rw-r--r--tests/auto/qml/qmllint/data/scriptstring.qml73
-rw-r--r--tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini2
-rw-r--r--tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml7
-rw-r--r--tests/auto/qml/qmllint/data/something.qml2
-rw-r--r--tests/auto/qml/qmllint/data/storeNameMethod.qml12
-rw-r--r--tests/auto/qml/qmllint/data/stringToDateTime.qml7
-rw-r--r--tests/auto/qml/qmllint/data/untitled/components/Foo.qml5
-rw-r--r--tests/auto/qml/qmllint/data/untitled/main.qml9
-rw-r--r--tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/useConstInvokable.qml5
-rw-r--r--tests/auto/qml/qmllint/data/validLiterals.qml6
-rw-r--r--tests/auto/qml/qmllint/data/valueTypesFromString.qml7
-rw-r--r--tests/auto/qml/qmllint/data/variantMapLookup.qml13
-rw-r--r--tests/auto/qml/qmllint/data/writeListProperty.qml7
-rw-r--r--tests/auto/qml/qmllint/lintplugin.cpp48
-rw-r--r--tests/auto/qml/qmllint/lintplugin.h4
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp531
-rw-r--r--tests/auto/qml/qmlplugindump/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp6
-rw-r--r--tests/auto/qml/qmlsplitlib/CMakeLists.txt24
-rw-r--r--tests/auto/qml/qmlsplitlib/lib.h2
-rw-r--r--tests/auto/qml/qmlsplitlib/lib2.cpp5
-rw-r--r--tests/auto/qml/qmlsplitlib/lib2.h30
-rw-r--r--tests/auto/qml/qmlsplitlib/main.qml2
-rw-r--r--tests/auto/qml/qmlsplitlib/main2.qml8
-rw-r--r--tests/auto/qml/qmlsplitlib/manual_imports.cpp2
-rw-r--r--tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp15
-rw-r--r--tests/auto/qml/qmltc/BLACKLIST5
-rw-r--r--tests/auto/qml/qmltc/CMakeLists.txt15
-rw-r--r--tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt28
-rw-r--r--tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml5
-rw-r--r--tests/auto/qml/qmltc/QmltcExportedTests/CMakeLists.txt31
-rw-r--r--tests/auto/qml/qmltc/QmltcExportedTests/HelloExportedWorld.qml5
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt21
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/Connections.qml12
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/QmlTableModel.qml62
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/aliases.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/custominitialization.h64
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithrequiredproperties.h75
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/myCheckBox.qml5
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/mySignals.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/properties.qml14
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/qtbug120700_main.qml25
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/qtbug123476.qml9
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/requiredProperties.qml61
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/signalConnections.qml46
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/singletons.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/stringToUrl.qml12
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/subfolder/code.js2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/translations.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/translationsById.qml2
-rw-r--r--tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml2
-rw-r--r--tests/auto/qml/qmltc/nameconflict.cpp2
-rw-r--r--tests/auto/qml/qmltc/nameconflict.h2
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.cpp198
-rw-r--r--tests/auto/qml/qmltc/tst_qmltc.h14
-rw-r--r--tests/auto/qml/qmltc_manual/CMakeLists.txt9
-rw-r--r--tests/auto/qml/qmltc_manual/testclasses.h2
-rw-r--r--tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp2
-rw-r--r--tests/auto/qml/qmltc_qprocess/CMakeLists.txt17
-rw-r--r--tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h2
-rw-r--r--tests/auto/qml/qmltc_qprocess/cpptypes/typewithrequiredproperty.h27
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/QmlBaseFromAnotherModule.qml13
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredProperty.qml18
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredPropertyFromOutside.qml18
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/constructFromString.qml7
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/innerLevelRequiredProperty.qml10
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml2
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/invalidTypeAnnotation.qml20
-rw-r--r--tests/auto/qml/qmltc_qprocess/data/unboundRequiredPropertyInInlineComponent.qml10
-rw-r--r--tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp128
-rw-r--r--tests/auto/qml/qmltyperegistrar/CMakeLists.txt28
-rw-r--r--tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt4
-rw-r--r--tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h51
-rw-r--r--tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h2
-rw-r--r--tests/auto/qml/qmltyperegistrar/duplicatedExports.h2
-rw-r--r--tests/auto/qml/qmltyperegistrar/enum.cpp5
-rw-r--r--tests/auto/qml/qmltyperegistrar/enum.h40
-rw-r--r--tests/auto/qml/qmltyperegistrar/foo.cpp2
-rw-r--r--tests/auto/qml/qmltyperegistrar/foo.h2
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp2
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/foreign.h2
-rw-r--r--tests/auto/qml/qmltyperegistrar/foreign/private/foreign_p.h (renamed from tests/auto/qml/qmltyperegistrar/foreign/foreign_p.h)3
-rw-r--r--tests/auto/qml/qmltyperegistrar/hppheader.hpp2
-rw-r--r--tests/auto/qml/qmltyperegistrar/missingTypes.json167
-rw-r--r--tests/auto/qml/qmltyperegistrar/noextheader2
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp651
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h388
-rw-r--r--tests/auto/qml/qqmlanybinding/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp4
-rw-r--r--tests/auto/qml/qqmlanybinding/withbindable.h2
-rw-r--r--tests/auto/qml/qqmlapplicationengine/CMakeLists.txt13
-rw-r--r--tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp2
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/CMakeLists.txt30
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/Main.qml5
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.qmbin0 -> 92 bytes
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.ts12
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/main.cpp26
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/CMakeLists.txt30
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/Main.qml13
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.qmbin0 -> 91 bytes
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.ts12
-rw-r--r--tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/main.cpp23
-rw-r--r--tests/auto/qml/qqmlapplicationengine/testapp/main.cpp2
-rw-r--r--tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp59
-rw-r--r--tests/auto/qml/qqmlbinding/CMakeLists.txt42
-rw-r--r--tests/auto/qml/qqmlbinding/WithBindableProperties.h2
-rw-r--r--tests/auto/qml/qqmlbinding/data/bindingOverwriting2.qml21
-rw-r--r--tests/auto/qml/qqmlbinding/data/propertiesAttachedToBindingItself.qml18
-rw-r--r--tests/auto/qml/qqmlbinding/data/restoreBinding2.qml2
-rw-r--r--tests/auto/qml/qqmlbinding/data/restoreBinding3.qml2
-rw-r--r--tests/auto/qml/qqmlbinding/data/restoreBinding4.qml2
-rw-r--r--tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml13
-rw-r--r--tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml23
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp85
-rw-r--r--tests/auto/qml/qqmlchangeset/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp39
-rw-r--r--tests/auto/qml/qqmlcomponent/CMakeLists.txt11
-rw-r--r--tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml28
-rw-r--r--tests/auto/qml/qqmlcomponent/data/createObject.qml3
-rw-r--r--tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml14
-rw-r--r--tests/auto/qml/qqmlcomponent/data/createQmlObject.qml21
-rw-r--r--tests/auto/qml/qqmlcomponent/data/dynamic.qml6
-rw-r--r--tests/auto/qml/qqmlcomponent/data/removeBinding.qml32
-rw-r--r--tests/auto/qml/qqmlcomponent/lifecyclewatcher.h24
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp186
-rw-r--r--tests/auto/qml/qqmlconnections/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml15
-rw-r--r--tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp83
-rw-r--r--tests/auto/qml/qqmlconsole/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlconsole/data/assert.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/categorized_logging.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/exception.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/logging.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/profiling.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/data/tracing.qml2
-rw-r--r--tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp35
-rw-r--r--tests/auto/qml/qqmlcontext/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlcontext/data/A.qml6
-rw-r--r--tests/auto/qml/qqmlcontext/data/B.qml6
-rw-r--r--tests/auto/qml/qqmlcontext/data/C.qml6
-rw-r--r--tests/auto/qml/qqmlcontext/data/destroyContextObject.qml5
-rw-r--r--tests/auto/qml/qqmlcontext/data/gcDeletesContextObject.qml5
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp229
-rw-r--r--tests/auto/qml/qqmlcpputils/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp21
-rw-r--r--tests/auto/qml/qqmldelegatemodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml2
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml138
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml50
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/integerModel.qml2
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/listModel.qml2
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/modifyObjectUnderConstruction.qml18
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/overriddenModelData.qml55
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/persistedItemsCache.qml62
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/requiredModelData.qml50
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/resetModelData.qml16
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/typedModelData.qml64
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/universalModelData.qml72
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/viewUpdatedOnDelegateChoiceAffectingRoleChange.qml93
-rw-r--r--tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp411
-rw-r--r--tests/auto/qml/qqmldirparser/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmldirparser/data/versioned-internal/qmldir3
-rw-r--r--tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp24
-rw-r--r--tests/auto/qml/qqmlecmascript/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qqmlecmascript/data/AssignListPropertyByIndexOnGadget.qml20
-rw-r--r--tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml1
-rw-r--r--tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml1
-rw-r--r--tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.3.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.4.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml13
-rw-r--r--tests/auto/qml/qqmlecmascript/data/date.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml30
-rw-r--r--tests/auto/qml/qqmlecmascript/data/getThis.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/lookupsDoNotBypassProxy.qml29
-rw-r--r--tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml1
-rw-r--r--tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml1
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs3.qml12
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qpropertyResetCorrectlyLinked.qml8
-rw-r--r--tests/auto/qml/qqmlecmascript/data/resetGadget.qml9
-rw-r--r--tests/auto/qml/qqmlecmascript/data/restoreObserverAfterReset.qml20
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml21
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml30
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml36
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml21
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml19
-rw-r--r--tests/auto/qml/qqmlecmascript/data/singletonTest.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/data/singletonTest2.qml2
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.cpp59
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h217
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp409
-rw-r--r--tests/auto/qml/qqmlengine/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml19
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml5
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml11
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml11
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml5
-rw-r--r--tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir3
-rw-r--r--tests/auto/qml/qqmlengine/data/markCurrentFunctionAsTranslationBinding.qml7
-rw-r--r--tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs2
-rw-r--r--tests/auto/qml/qqmlengine/data/nativeModuleImport.qml2
-rw-r--r--tests/auto/qml/qqmlengine/data/variantListQJsonConversion.qml18
-rw-r--r--tests/auto/qml/qqmlengine/declarativelyregistered.cpp2
-rw-r--r--tests/auto/qml/qqmlengine/declarativelyregistered.h2
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp146
-rw-r--r--tests/auto/qml/qqmlengine/variantlistQJsonConversion.h53
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/TestType.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/testFile1.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/testFile2.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/testFile3.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/data/types.qml2
-rw-r--r--tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp29
-rw-r--r--tests/auto/qml/qqmlerror/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlerror/tst_qqmlerror.cpp2
-rw-r--r--tests/auto/qml/qqmlexpression/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp38
-rw-r--r--tests/auto/qml/qqmlextensionplugin/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlextensionplugin/data/dummy.qml2
-rw-r--r--tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp4
-rw-r--r--tests/auto/qml/qqmlfile/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlfile/tst_qqmlfile.cpp2
-rw-r--r--tests/auto/qml/qqmlfileselector/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml6
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir3
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/MyButton.qml7
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/MyButton.qml7
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/MyButton.qml7
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/Name.js1
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/main.qml9
-rw-r--r--tests/auto/qml/qqmlfileselector/data/qmldirtest2/qmldir5
-rw-r--r--tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp45
-rw-r--r--tests/auto/qml/qqmlglobal/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp2
-rw-r--r--tests/auto/qml/qqmlimport/CMakeLists.txt22
-rw-r--r--tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml2
-rw-r--r--tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml2
-rw-r--r--tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/Preferred.qml5
-rw-r--r--tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/qmldir3
-rw-r--r--tests/auto/qml/qqmlimport/data/MyModuleName/Font.js4
-rw-r--r--tests/auto/qml/qqmlimport/data/MyModuleName/qmldir2
-rw-r--r--tests/auto/qml/qqmlimport/data/fileDotSlashImport.qml6
-rw-r--r--tests/auto/qml/qqmlimport/data/noimport/Main.qml5
-rw-r--r--tests/auto/qml/qqmlimport/data/noimport/qmldir3
-rw-r--r--tests/auto/qml/qqmlimport/data/prefer2.qml3
-rw-r--r--tests/auto/qml/qqmlimport/data/qualifiedScriptImport.qml8
-rw-r--r--tests/auto/qml/qqmlimport/data/testfile_supported.qml2
-rw-r--r--tests/auto/qml/qqmlimport/data/testfile_unsupported.qml2
-rw-r--r--tests/auto/qml/qqmlimport/qmldir2
-rw-r--r--tests/auto/qml/qqmlimport/qmlimports.qt.conf3
-rw-r--r--tests/auto/qml/qqmlimport/tst_qqmlimport.cpp156
-rw-r--r--tests/auto/qml/qqmlincubator/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlincubator/data/garbageCollection2.qml12
-rw-r--r--tests/auto/qml/qqmlincubator/testtypes.cpp2
-rw-r--r--tests/auto/qml/qqmlincubator/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp12
-rw-r--r--tests/auto/qml/qqmlinfo/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlinfo/attached.cpp2
-rw-r--r--tests/auto/qml/qqmlinfo/attached.h2
-rw-r--r--tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp4
-rw-r--r--tests/auto/qml/qqmlinstantiator/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml20
-rw-r--r--tests/auto/qml/qqmlinstantiator/data/removeDuringModelChange.qml10
-rw-r--r--tests/auto/qml/qqmlinstantiator/stringmodel.h2
-rw-r--r--tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp103
-rw-r--r--tests/auto/qml/qqmlitemmodels/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlitemmodels/data/modelindex.qml2
-rw-r--r--tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml2
-rw-r--r--tests/auto/qml/qqmlitemmodels/qtestmodel.h7
-rw-r--r--tests/auto/qml/qqmlitemmodels/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp4
-rw-r--r--tests/auto/qml/qqmljsscope/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt3
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h23
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp2
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h2
-rw-r--r--tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h2
-rw-r--r--tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h2
-rw-r--r--tests/auto/qml/qqmljsscope/data/attachedTypeResolution.qml6
-rw-r--r--tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml16
-rw-r--r--tests/auto/qml/qqmljsscope/data/ownModuleName.qml10
-rw-r--r--tests/auto/qml/qqmljsscope/data/requiredAlias.qml20
-rw-r--r--tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp329
-rw-r--r--tests/auto/qml/qqmllanguage/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qqmllanguage/data/AliasHolder.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnumSelfReference.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/Comps/IconPropertiesGroup.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/Comps/OverlayDrawer.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/Comps/qmldir4
-rw-r--r--tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml27
-rw-r--r--tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml8
-rw-r--r--tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir4
-rw-r--r--tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml15
-rw-r--r--tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/UIToolBar.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/alias.16.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/aliasWriter.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/ambiguousComponents.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/asCastToInlineComponent.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/asValueType.qml20
-rw-r--r--tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml35
-rw-r--r--tests/auto/qml/qqmllanguage/data/badICAnnotation.qml25
-rw-r--r--tests/auto/qml/qqmllanguage/data/badSingleton/SingletonTest.qml (renamed from tests/auto/qml/qqmllanguage/data/SingletonTest.qml)0
-rw-r--r--tests/auto/qml/qqmllanguage/data/badSingleton/qmldir (renamed from tests/auto/qml/qqmllanguage/data/qmldir)0
-rw-r--r--tests/auto/qml/qqmllanguage/data/badSingleton/qtbug_85932.qml (renamed from tests/auto/qml/qqmllanguage/data/qtbug_85932.qml)0
-rw-r--r--tests/auto/qml/qqmllanguage/data/corpseInQmlList.qml13
-rw-r--r--tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/derivedFromUnexposedBase.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/dynamicGroupPropertyRejected.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/enumPropsManyUnderlyingTypes.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/enumScopes.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentWithImplicitComponent.qml27
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt2
-rw-r--r--tests/auto/qml/qqmllanguage/data/invokableCtors.qml12
-rw-r--r--tests/auto/qml/qqmllanguage/data/isNullOrUndefined_interpreter.qml22
-rw-r--r--tests/auto/qml/qqmllanguage/data/isNullOrUndefined_jit.qml22
-rw-r--r--tests/auto/qml/qqmllanguage/data/jitExceptions.qml16
-rw-r--r--tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml191
-rw-r--r--tests/auto/qml/qqmllanguage/data/longConversion.qml28
-rw-r--r--tests/auto/qml/qqmllanguage/data/manuallyCallSignalHandler.qml11
-rw-r--r--tests/auto/qml/qqmllanguage/data/nestedVectors.qml27
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectInList.qml17
-rw-r--r--tests/auto/qml/qqmllanguage/data/objectMethodClone.qml23
-rw-r--r--tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml14
-rw-r--r--tests/auto/qml/qqmllanguage/data/optionalChainCallOnNullProperty.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/overrideDefaultProperty.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/retainThis.qml49
-rw-r--r--tests/auto/qml/qqmllanguage/data/signatureEnforced.qml5
-rw-r--r--tests/auto/qml/qqmllanguage/data/signatureIgnored.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js2
-rw-r--r--tests/auto/qml/qqmllanguage/data/singletonTest17.qml2
-rw-r--r--tests/auto/qml/qqmllanguage/data/typedObjectList.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/unregisteredValueTypeConversion.qml10
-rw-r--r--tests/auto/qml/qqmllanguage/data/variantObjectList.qml17
-rw-r--r--tests/auto/qml/qqmllanguage/testhelper/CMakeLists.txt13
-rw-r--r--tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.cpp7
-rw-r--r--tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.h20
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp54
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h640
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp1216
-rw-r--r--tests/auto/qml/qqmllistcompositor/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp21
-rw-r--r--tests/auto/qml/qqmllistmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllistmodel/data/nestedLists.qml37
-rw-r--r--tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp255
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp160
-rw-r--r--tests/auto/qml/qqmllistreference/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllistreference/data/consoleLogSyntheticList.qml8
-rw-r--r--tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml21
-rw-r--r--tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp62
-rw-r--r--tests/auto/qml/qqmllocale/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmllocale/tst_qqmllocale.cpp31
-rw-r--r--tests/auto/qml/qqmlmetaobject/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp2
-rw-r--r--tests/auto/qml/qqmlmetatype/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlmetatype/data/Components/App.qml2
-rw-r--r--tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp114
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp95
-rw-r--r--tests/auto/qml/qqmlnotifier/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp2
-rw-r--r--tests/auto/qml/qqmlobjectmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp2
-rw-r--r--tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp2
-rw-r--r--tests/auto/qml/qqmlparser/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlparser/tst_qqmlparser.cpp88
-rw-r--r--tests/auto/qml/qqmlpromise/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-get-length.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml2
-rw-r--r--tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp2
-rw-r--r--tests/auto/qml/qqmlproperty/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlproperty/data/invalidateQPropertyChangeTriggers.qml50
-rw-r--r--tests/auto/qml/qqmlproperty/data/listAssignmentSignals.qml13
-rw-r--r--tests/auto/qml/qqmlproperty/data/propertyStartsWithOn.qml9
-rw-r--r--tests/auto/qml/qqmlproperty/interfaces.h2
-rw-r--r--tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp91
-rw-r--r--tests/auto/qml/qqmlpropertycache/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/duplicateIdsAndGeneralizedGroupProperties.qml64
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/overriddenSignal.qml36
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal.qml8
-rw-r--r--tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal2.qml6
-rw-r--r--tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp84
-rw-r--r--tests/auto/qml/qqmlpropertymap/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp29
-rw-r--r--tests/auto/qml/qqmlqt/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlqt/data/qtbug_125495.qml5
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp34
-rw-r--r--tests/auto/qml/qqmlsettings/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlsettings/data/aliases.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/basic.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/categories.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/cpp-aliases.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/siblings.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/data/types.qml2
-rw-r--r--tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp2
-rw-r--r--tests/auto/qml/qqmlsqldatabase/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml2
-rw-r--r--tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp7
-rw-r--r--tests/auto/qml/qqmltablemodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmltablemodel/data/TestModel.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/TestUtils.js2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/common.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/complex.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/empty.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/intAndDouble.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml2
-rw-r--r--tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp2
-rw-r--r--tests/auto/qml/qqmltimer/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qqmltimer/tst_qqmltimer.cpp97
-rw-r--r--tests/auto/qml/qqmltranslation/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmltranslation/data/jstranslation.qml1
-rw-r--r--tests/auto/qml/qqmltranslation/data/pragmacontext.qml8
-rw-r--r--tests/auto/qml/qqmltranslation/data/pragmacontextstringliteral.qml8
-rw-r--r--tests/auto/qml/qqmltranslation/data/translation.js6
-rw-r--r--tests/auto/qml/qqmltranslation/data/translation.qml4
-rw-r--r--tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp65
-rw-r--r--tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp30
-rw-r--r--tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h3
-rw-r--r--tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp2
-rw-r--r--tests/auto/qml/qqmltypeloader/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/plugin.h2
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp2
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/slow.h2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/GenericView.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/Intercept.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/NiceView.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/doesExist.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/a.qml3
-rw-r--r--tests/auto/qml/qqmltypeloader/data/load_synchronous.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/test_intercept.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/data/test_load_complete.qml2
-rw-r--r--tests/auto/qml/qqmltypeloader/declarativetesttype.h2
-rw-r--r--tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp68
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml2
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml5
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml17
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp7
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/testtypes.h216
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp191
-rw-r--r--tests/auto/qml/qqmlvaluetypes/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/constructors.qml14
-rw-r--r--tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml4
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.cpp2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.h2
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp543
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect18
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort.qml15
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml8
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml9
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml19
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open.qml9
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml1
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml9
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml2
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.qml20
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.reply3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect14
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect14
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/responseURL.qml21
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expectbin258 -> 263 bytes
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect14
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect14
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml11
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect19
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect16
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml5
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml8
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml10
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml3
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/status.expect12
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/status.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml4
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/data/text.expect6
-rw-r--r--tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp107
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp18
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp2
-rw-r--r--tests/auto/qml/qquickworkerscript/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp103
-rw-r--r--tests/auto/qml/qrcqml/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qrcqml/tst_qrcqml.cpp12
-rw-r--r--tests/auto/qml/qtqmlmodules/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp20
-rw-r--r--tests/auto/qml/qv4assembler/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qv4assembler/data/crash.qml2
-rw-r--r--tests/auto/qml/qv4assembler/tst_qv4assembler.cpp2
-rw-r--r--tests/auto/qml/qv4estable/CMakeLists.txt24
-rw-r--r--tests/auto/qml/qv4estable/tst_qv4estable.cpp40
-rw-r--r--tests/auto/qml/qv4identifiertable/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp2
-rw-r--r--tests/auto/qml/qv4mm/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qv4mm/data/createdestroy.qml2
-rw-r--r--tests/auto/qml/qv4mm/data/createobjects.qml2
-rw-r--r--tests/auto/qml/qv4mm/data/simpleObject.qml3
-rw-r--r--tests/auto/qml/qv4mm/data/storeLocal.qml34
-rw-r--r--tests/auto/qml/qv4mm/tst_qv4mm.cpp544
-rw-r--r--tests/auto/qml/qv4regexp/CMakeLists.txt6
-rw-r--r--tests/auto/qml/qv4regexp/tst_qv4regexp.cpp2
-rw-r--r--tests/auto/qml/qv4urlobject/CMakeLists.txt26
-rw-r--r--tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp153
-rw-r--r--tests/auto/qml/qwidgetsinqml/CMakeLists.txt8
-rw-r--r--tests/auto/qml/qwidgetsinqml/dummy_imports.qml7
-rw-r--r--tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp19
-rw-r--r--tests/auto/qml/registrationmacros/CMakeLists.txt6
-rw-r--r--tests/auto/qml/registrationmacros/tst_registrationmacros.cpp2
-rw-r--r--tests/auto/qml/registrationmacros/types.cpp2
-rw-r--r--tests/auto/qml/registrationmacros/types.h2
-rw-r--r--tests/auto/qml/v4misc/CMakeLists.txt6
-rw-r--r--tests/auto/qml/v4misc/tst_v4misc.cpp2
1127 files changed, 26200 insertions, 5879 deletions
diff --git a/tests/auto/qml/CMakeLists.txt b/tests/auto/qml/CMakeLists.txt
index 77663f350d..6b81f4c616 100644
--- a/tests/auto/qml/CMakeLists.txt
+++ b/tests/auto/qml/CMakeLists.txt
@@ -17,8 +17,9 @@ add_subdirectory(qjsonbinding)
add_subdirectory(qqmlfile)
if(NOT INTEGRITY)
- # The INTEGRITY linker tends to crash on tst_qqmlfileselector
+ # The INTEGRITY linker tends to crash on tst_qqmlfileselector and tst_qml_common
add_subdirectory(qqmlfileselector)
+ add_subdirectory(common)
endif()
# Limit set of tests to run for static Qt builds.
@@ -33,7 +34,9 @@ add_subdirectory(qqmlerror)
add_subdirectory(qqmlincubator)
add_subdirectory(qqmlinfo)
add_subdirectory(qqmllistreference)
-add_subdirectory(qqmllocale)
+if(QT_FEATURE_qml_locale)
+ add_subdirectory(qqmllocale)
+endif()
add_subdirectory(qqmlmetaobject)
if(NOT ANDROID) # QTBUG-100003
add_subdirectory(qqmlmoduleplugin)
@@ -45,7 +48,9 @@ add_subdirectory(qqmlpromise)
add_subdirectory(qtqmlmodules)
add_subdirectory(qquickfolderlistmodel)
add_subdirectory(qqmlapplicationengine)
-add_subdirectory(qqmlsettings)
+if(QT_FEATURE_settings)
+ add_subdirectory(qqmlsettings)
+endif()
if(NOT INTEGRITY)
# There's no mounted filesystem on INTEGRITY therefore skipping qmldiskcache
@@ -55,7 +60,7 @@ endif()
add_subdirectory(qqmlmetatype)
if(TARGET Qt::Quick)
add_subdirectory(qmltc_manual)
- # QML Type Compiler tests cannot be run on webOS due to missing support for multiple
+ # QML type compiler tests cannot be run on webOS due to missing support for multiple
# consecutive window creation from a single QtWayland client
if(NOT WEBOS)
add_subdirectory(qmltc)
@@ -76,6 +81,7 @@ if(TARGET Qt::Widgets)
add_subdirectory(qjsengine)
add_subdirectory(qjsvalue)
add_subdirectory(qjsmanagedvalue)
+ add_subdirectory(qwidgetsinqml)
endif()
if(QT_FEATURE_process AND QT_FEATURE_qml_debug)
add_subdirectory(debugger)
@@ -140,9 +146,14 @@ if(QT_FEATURE_private_tests)
add_subdirectory(qqmltreemodeltotablemodel)
add_subdirectory(qv4assembler)
add_subdirectory(qv4mm)
+ add_subdirectory(qv4estable)
add_subdirectory(qv4identifiertable)
add_subdirectory(qv4regexp)
- if(QT_FEATURE_process AND NOT QNX)
+ add_subdirectory(qv4urlobject)
+ if(QT_FEATURE_process AND NOT QNX AND NOT
+ (ANDROID AND CLANG AND
+ CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "14.0.0" AND
+ CMAKE_CXX_COMPILER_VERSION VERSION_LESS "15.0.0"))
add_subdirectory(ecmascripttests)
endif()
add_subdirectory(bindingdependencyapi)
diff --git a/tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt b/tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt
index 03099ef616..9e6ba7fcb6 100644
--- a/tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qabstractanimationjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qabstractanimationjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qabstractanimationjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qabstractanimationjob
SOURCES
tst_qabstractanimationjob.cpp
diff --git a/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp b/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp
index e2e5e59e95..40eb8a6910 100644
--- a/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp
+++ b/tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/private/qabstractanimationjob_p.h>
@@ -53,8 +53,7 @@ void tst_QAbstractAnimationJob::construction()
void tst_QAbstractAnimationJob::destruction()
{
- TestableQAbstractAnimation *anim = new TestableQAbstractAnimation;
- delete anim;
+ std::unique_ptr<TestableQAbstractAnimation> anim = std::make_unique<TestableQAbstractAnimation>();
}
void tst_QAbstractAnimationJob::currentLoop()
diff --git a/tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt b/tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt
index 286bdeed4a..db46ef71dc 100644
--- a/tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qanimationgroupjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qanimationgroupjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qanimationgroupjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qanimationgroupjob
SOURCES
tst_qanimationgroupjob.cpp
diff --git a/tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp b/tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp
index cac9581803..a3fe188b65 100644
--- a/tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -236,7 +236,7 @@ void tst_QAnimationGroupJob::addChildTwice()
{
QAbstractAnimationJob *subGroup;
QAbstractAnimationJob *subGroup2;
- auto *parent = new QSequentialAnimationGroupJob();
+ auto parent = std::make_unique<QSequentialAnimationGroupJob>();
subGroup = new QAbstractAnimationJob;
parent->appendAnimation(subGroup);
@@ -266,7 +266,6 @@ void tst_QAnimationGroupJob::addChildTwice()
QCOMPARE(parent->children()->first(), subGroup2);
QCOMPARE(parent->children()->last(), subGroup);
- delete parent;
}
QTEST_MAIN(tst_QAnimationGroupJob)
diff --git a/tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt b/tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt
index 74e3b3fed4..0a275aaaa1 100644
--- a/tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qparallelanimationgroupjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qparallelanimationgroupjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qparallelanimationgroupjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qparallelanimationgroupjob
SOURCES
tst_qparallelanimationgroupjob.cpp
diff --git a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
index a11ae75033..91c47586c1 100644
--- a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -395,8 +395,8 @@ void tst_QParallelAnimationGroupJob::deleteChildrenWithRunningGroup()
// test if children can be activated when their group is stopped
QParallelAnimationGroupJob group;
- TestAnimation *anim1 = new TestAnimation(200);
- group.appendAnimation(anim1);
+ std::unique_ptr<TestAnimation> anim1 = std::make_unique<TestAnimation>(200);
+ group.appendAnimation(anim1.get());
QCOMPARE(group.duration(), anim1->duration());
@@ -406,7 +406,7 @@ void tst_QParallelAnimationGroupJob::deleteChildrenWithRunningGroup()
QTRY_VERIFY(group.currentLoopTime() > 0);
- delete anim1;
+ anim1.reset();
QVERIFY(group.children()->isEmpty());
QCOMPARE(group.duration(), 0);
QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
@@ -793,34 +793,34 @@ void tst_QParallelAnimationGroupJob::addAndRemoveDuration()
{
QParallelAnimationGroupJob group;
QCOMPARE(group.duration(), 0);
- TestAnimation *test = new TestAnimation(250); // 0, duration = 250;
- group.appendAnimation(test);
+ std::unique_ptr<TestAnimation> test = std::make_unique<TestAnimation>(250); // 0, duration = 250;
+ group.appendAnimation(test.get());
QCOMPARE(test->group(), static_cast<QAnimationGroupJob*>(&group));
QCOMPARE(test->duration(), 250);
QCOMPARE(group.duration(), 250);
- TestAnimation *test2 = new TestAnimation(750); // 1
- group.appendAnimation(test2);
+ std::unique_ptr<TestAnimation> test2 = std::make_unique<TestAnimation>(750); // 1
+ group.appendAnimation(test2.get());
QCOMPARE(test2->group(), static_cast<QAnimationGroupJob*>(&group));
QCOMPARE(group.duration(), 750);
- TestAnimation *test3 = new TestAnimation(500); // 2
- group.appendAnimation(test3);
+ std::unique_ptr<TestAnimation> test3 = std::make_unique<TestAnimation>(500); // 2
+ group.appendAnimation(test3.get());
QCOMPARE(test3->group(), static_cast<QAnimationGroupJob*>(&group));
QCOMPARE(group.duration(), 750);
- group.removeAnimation(test2); // remove the one with duration = 750
- delete test2;
+ group.removeAnimation(test2.get()); // remove the one with duration = 750
+ test2.reset();
QCOMPARE(group.duration(), 500);
- group.removeAnimation(test3); // remove the one with duration = 500
- delete test3;
+ group.removeAnimation(test3.get()); // remove the one with duration = 500
+ test3.reset();
QCOMPARE(group.duration(), 250);
- group.removeAnimation(test); // remove the last one (with duration = 250)
+ group.removeAnimation(test.get()); // remove the last one (with duration = 250)
QCOMPARE(test->group(), static_cast<QAnimationGroupJob*>(nullptr));
QCOMPARE(group.duration(), 0);
- delete test;
+ test.reset();
}
void tst_QParallelAnimationGroupJob::pauseResume()
@@ -878,16 +878,16 @@ void tst_QParallelAnimationGroupJob::pauseResume()
void tst_QParallelAnimationGroupJob::crashWhenRemovingUncontrolledAnimation()
{
QParallelAnimationGroupJob group;
- TestAnimation *anim = new TestAnimation;
+ std::unique_ptr<TestAnimation> anim = std::make_unique<TestAnimation>();
anim->setLoopCount(-1);
- TestAnimation *anim2 = new TestAnimation;
+ std::unique_ptr<TestAnimation> anim2 = std::make_unique<TestAnimation>();
anim2->setLoopCount(-1);
- group.appendAnimation(anim);
- group.appendAnimation(anim2);
+ group.appendAnimation(anim.get());
+ group.appendAnimation(anim2.get());
group.start();
- delete anim;
+ anim.reset();
// it would crash here because the internals of the group would still have a reference to anim
- delete anim2;
+ anim2.reset();
}
void tst_QParallelAnimationGroupJob::uncontrolledWithLoops()
diff --git a/tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt b/tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt
index 5f67083ea4..2dc9e42f90 100644
--- a/tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qpauseanimationjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qpauseanimationjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qpauseanimationjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qpauseanimationjob
SOURCES
tst_qpauseanimationjob.cpp
diff --git a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp
index db433af8c6..c658f590c9 100644
--- a/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp
+++ b/tests/auto/qml/animation/qpauseanimationjob/tst_qpauseanimationjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
diff --git a/tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt b/tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt
index e9a680ace5..fa7ad06a03 100644
--- a/tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt
+++ b/tests/auto/qml/animation/qsequentialanimationgroupjob/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qsequentialanimationgroupjob Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsequentialanimationgroupjob LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qsequentialanimationgroupjob
SOURCES
tst_qsequentialanimationgroupjob.cpp
diff --git a/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
index cc67df420c..71aa2240ff 100644
--- a/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQml/private/qsequentialanimationgroupjob_p.h>
@@ -110,7 +110,7 @@ public:
{
states << newState;
if (beEvil) {
- delete job->group();
+ delete job->group(); //manual delete intentional
groupDeleted = true;
}
}
@@ -1090,8 +1090,8 @@ void tst_QSequentialAnimationGroupJob::deleteChildrenWithRunningGroup()
// test if children can be activated when their group is stopped
QSequentialAnimationGroupJob group;
- TestAnimation *anim1 = new TestAnimation(200);
- group.appendAnimation(anim1);
+ std::unique_ptr<TestAnimation> anim1 = std::make_unique<TestAnimation>(200);
+ group.appendAnimation(anim1.get());
QCOMPARE(group.duration(), anim1->duration());
@@ -1102,7 +1102,7 @@ void tst_QSequentialAnimationGroupJob::deleteChildrenWithRunningGroup()
QTest::qWait(100);
QTRY_VERIFY(group.currentLoopTime() > 0);
- delete anim1;
+ anim1.reset();
QVERIFY(group.children()->isEmpty());
QCOMPARE(group.duration(), 0);
QCOMPARE(group.state(), QAnimationGroupJob::Stopped);
diff --git a/tests/auto/qml/bindingdependencyapi/CMakeLists.txt b/tests/auto/qml/bindingdependencyapi/CMakeLists.txt
index e8ab157548..febc0bcfdd 100644
--- a/tests/auto/qml/bindingdependencyapi/CMakeLists.txt
+++ b/tests/auto/qml/bindingdependencyapi/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_bindingdependencyapi Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_bindingdependencyapi LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp b/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp
index 5fbf28b15b..6b1f4e1622 100644
--- a/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp
+++ b/tests/auto/qml/bindingdependencyapi/tst_bindingdependencyapi.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -104,12 +104,12 @@ void tst_bindingdependencyapi::testSingleDep()
QQmlEngine engine;
QQmlComponent c(&engine);
c.setData(code, QUrl());
- QObject *rect = c.create();
+ std::unique_ptr<QObject> rect { c.create() };
QTest::qWait(10);
- QVERIFY(rect != nullptr);
+ QVERIFY(rect.get() != nullptr);
QObject *text = rect->findChildren<QQuickText *>().front();
- QObject *referencedObject = rect->objectName() == referencedObjectName ? rect : rect->findChild<QObject *>(referencedObjectName);
+ QObject *referencedObject = rect->objectName() == referencedObjectName ? rect.get() : rect->findChild<QObject *>(referencedObjectName);
auto data = QQmlData::get(text);
QVERIFY(data);
@@ -125,8 +125,6 @@ void tst_bindingdependencyapi::testSingleDep()
QCOMPARE(dependency.property().name(), "labelText");
QCOMPARE(dependency.read().toString(), QStringLiteral("Hello world!"));
QCOMPARE(dependency, QQmlProperty(referencedObject, "labelText"));
-
- delete rect;
}
bool tst_bindingdependencyapi::findProperties(const QVector<QQmlProperty> &properties, QObject *obj, const QString &propertyName, const QVariant &value)
@@ -183,12 +181,12 @@ void tst_bindingdependencyapi::testManyDeps()
QQmlEngine engine;
QQmlComponent c(&engine);
c.setData(code, QUrl());
- QObject *rect = c.create();
+ std::unique_ptr<QObject> rect { c.create() };
if (c.isError()) {
qWarning() << c.errorString();
}
QTest::qWait(100);
- QVERIFY(rect != nullptr);
+ QVERIFY(rect.get() != nullptr);
QObject *text = rect->findChildren<QQuickText *>().front();
QObject *configObj = rect->findChild<QObject *>("config");
@@ -201,11 +199,9 @@ void tst_bindingdependencyapi::testManyDeps()
auto dependencies = binding->dependencies();
QCOMPARE(dependencies.size(), 3);
- QVERIFY(findProperties(dependencies, rect, "name", "world"));
+ QVERIFY(findProperties(dependencies, rect.get(), "name", "world"));
QVERIFY(findProperties(dependencies, text, "greeting", "Hello"));
QVERIFY(findProperties(dependencies, configObj, "helloWorldTemplate", "%1 %2!"));
-
- delete rect;
}
void tst_bindingdependencyapi::testConditionalDependencies_data()
@@ -263,12 +259,12 @@ void tst_bindingdependencyapi::testConditionalDependencies()
QQmlEngine engine;
QQmlComponent c(&engine);
c.setData(code, QUrl());
- QObject *rect = c.create();
+ std::unique_ptr<QObject> rect { c.create() };
QTest::qWait(10);
- QVERIFY(rect != nullptr);
+ QVERIFY(rect.get() != nullptr);
QObject *text = rect->findChildren<QQuickText *>().front();
- QObject *referencedObject = rect->objectName() == referencedObjectName ? rect : rect->findChild<QObject *>(referencedObjectName);
+ QObject *referencedObject = rect->objectName() == referencedObjectName ? rect.get() : rect->findChild<QObject *>(referencedObjectName);
auto data = QQmlData::get(text);
QVERIFY(data);
@@ -290,8 +286,6 @@ void tst_bindingdependencyapi::testConditionalDependencies()
dependencies = binding->dependencies();
QCOMPARE(dependencies.size(), 1);
QVERIFY(findProperties(dependencies, referencedObject, "haveDep", false));
-
- delete rect;
}
void tst_bindingdependencyapi::testBindingLoop()
@@ -306,12 +300,12 @@ void tst_bindingdependencyapi::testBindingLoop()
"text: labelText\n"
"}\n"
"}"), QUrl());
- QObject *rect = c.create();
+ std::unique_ptr<QObject> rect { c.create() };
if (c.isError()) {
qWarning() << c.errorString();
}
QTest::qWait(100);
- QVERIFY(rect != nullptr);
+ QVERIFY(rect.get() != nullptr);
QObject *text = rect->findChildren<QQuickText *>().front();
auto data = QQmlData::get(text);
@@ -324,10 +318,8 @@ void tst_bindingdependencyapi::testBindingLoop()
QCOMPARE(dependencies.size(), 1);
auto dependency = dependencies.front();
QVERIFY(dependency.isValid());
- QCOMPARE(quintptr(dependency.object()), quintptr(rect));
+ QCOMPARE(quintptr(dependency.object()), quintptr(rect.get()));
QCOMPARE(dependency.property().name(), "labelText");
-
- delete rect;
}
void tst_bindingdependencyapi::testQproperty()
diff --git a/tests/auto/qml/common/CMakeLists.txt b/tests/auto/qml/common/CMakeLists.txt
new file mode 100644
index 0000000000..4b7714a11d
--- /dev/null
+++ b/tests/auto/qml/common/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_policy(SET QTP0001 NEW)
+
+qt_internal_add_test(tst_qml_common
+ SOURCES
+ tst_qml_common.cpp tst_qml_common.h
+ LIBRARIES
+ Qt::QmlPrivate
+)
diff --git a/tests/auto/qml/common/tst_qml_common.cpp b/tests/auto/qml/common/tst_qml_common.cpp
new file mode 100644
index 0000000000..e9baae5d53
--- /dev/null
+++ b/tests/auto/qml/common/tst_qml_common.cpp
@@ -0,0 +1,168 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "tst_qml_common.h"
+
+using namespace Qt::StringLiterals;
+
+void tst_qml_common::tst_propertyNameToChangedSignalName_data()
+{
+ QTest::addColumn<QString>("property");
+ QTest::addColumn<QString>("expected");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s << u"helloWorldChanged"_s;
+ QTest::addRow("changedProperty") << u"changed"_s << u"changedChanged"_s;
+ QTest::addRow("chängedProperty") << u"chänged"_s << u"chängedChanged"_s;
+}
+void tst_qml_common::tst_propertyNameToChangedSignalName()
+{
+ QFETCH(QString, property);
+ QFETCH(QString, expected);
+
+ QVERIFY(QQmlSignalNames::isChangedSignalName(expected));
+ QCOMPARE(QQmlSignalNames::propertyNameToChangedSignalName(property), expected);
+ QCOMPARE(QQmlSignalNames::changedSignalNameToPropertyName(expected).value(), property);
+}
+
+void tst_qml_common::tst_propertyNameToChangedHandlerName_data()
+{
+ QTest::addColumn<QString>("property");
+ QTest::addColumn<QString>("expected");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s << u"onHelloWorldChanged"_s;
+ QTest::addRow("changedProperty") << u"changed"_s << u"onChangedChanged"_s;
+ QTest::addRow("chängedProperty") << u"chänged"_s << u"onChängedChanged"_s;
+ QTest::addRow("äProperty") << u"ä"_s << u"onÄChanged"_s;
+ QTest::addRow("_Property") << u"_"_s << u"on_Changed"_s;
+ QTest::addRow("___123aProperty") << u"___123a"_s << u"on___123AChanged"_s;
+ QTest::addRow("___123Property") << u"___123"_s << u"on___123Changed"_s;
+ QTest::addRow("AProperty") << u"A"_s << u"onAChanged"_s;
+ QTest::addRow("_Property") << u"_"_s << u"on_Changed"_s;
+ QTest::addRow("$Property") << u"$"_s << u"on$Changed"_s;
+}
+void tst_qml_common::tst_propertyNameToChangedHandlerName()
+{
+ QFETCH(QString, property);
+ QFETCH(QString, expected);
+
+ QVERIFY(QQmlSignalNames::isChangedHandlerName(expected));
+ QCOMPARE(QQmlSignalNames::propertyNameToChangedHandlerName(property), expected);
+ auto reverse = QQmlSignalNames::changedHandlerNameToPropertyName(expected);
+ QVERIFY(reverse);
+ QEXPECT_FAIL("AProperty",
+ "Cannot distinguish between property names starting with upper case"
+ " from properties starting with a lower case letter.",
+ Continue);
+ QCOMPARE(reverse.value(), property);
+}
+
+void tst_qml_common::tst_signalNameToHandlerName_data()
+{
+ QTest::addColumn<QString>("signalName");
+ QTest::addColumn<QString>("expected");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s << u"onHelloWorld"_s;
+ QTest::addRow("changedProperty") << u"changed"_s << u"onChanged"_s;
+ QTest::addRow("chängedProperty") << u"chänged"_s << u"onChänged"_s;
+ QTest::addRow("äProperty") << u"ä"_s << u"onÄ"_s;
+ QTest::addRow("_Property") << u"_"_s << u"on_"_s;
+ QTest::addRow("___123aProperty") << u"___123a"_s << u"on___123A"_s;
+ QTest::addRow("___123Property") << u"___123"_s << u"on___123"_s;
+ QTest::addRow("AProperty") << u"A"_s << u"onA"_s;
+ QTest::addRow("_Property") << u"_"_s << u"on_"_s;
+ QTest::addRow("$Property") << u"$"_s << u"on$"_s;
+}
+
+void tst_qml_common::tst_signalNameToHandlerName()
+{
+ QFETCH(QString, signalName);
+ QFETCH(QString, expected);
+
+ QVERIFY(QQmlSignalNames::isHandlerName(expected));
+ QCOMPARE(QQmlSignalNames::signalNameToHandlerName(signalName), expected);
+
+ auto result = QQmlSignalNames::handlerNameToSignalName(expected);
+ QVERIFY(result.has_value());
+
+ QEXPECT_FAIL("AProperty",
+ "Cannot distinguish between signal names starting with upper case"
+ " from signal names starting with a lower case letter.",
+ Continue);
+
+ QCOMPARE(result.value(), signalName);
+}
+
+void tst_qml_common::tst_changedSignalNameToPropertyName_data()
+{
+ // only test when it should return nothing, see also tst_propertyNameToChangedSignalName.
+ QTest::addColumn<QString>("changedSignalName");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s;
+ QTest::addRow("Changed") << u"Changed"_s;
+ QTest::addRow("empty") << u""_s;
+}
+
+void tst_qml_common::tst_changedSignalNameToPropertyName()
+{
+ QFETCH(QString, changedSignalName);
+
+ QVERIFY(!QQmlSignalNames::changedSignalNameToPropertyName(changedSignalName).has_value());
+}
+
+void tst_qml_common::tst_changedHandlerNameToPropertyName_data()
+{
+ // only test when it should return nothing, see also tst_propertyNameToChangedHandler.
+ QTest::addColumn<QString>("changedHandler");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s;
+ QTest::addRow("Changed") << u"Changed"_s;
+ QTest::addRow("empty") << u""_s;
+ QTest::addRow("empty2") << u"onChanged"_s;
+ QTest::addRow("on") << u"on"_s;
+}
+void tst_qml_common::tst_changedHandlerNameToPropertyName()
+{
+ QFETCH(QString, changedHandler);
+
+ QVERIFY(!QQmlSignalNames::changedHandlerNameToPropertyName(changedHandler).has_value());
+}
+
+void tst_qml_common::tst_handlerNameToSignalName_data()
+{
+ // only test when it should return nothing, see also tst_signalNameToHandlerName.
+ QTest::addColumn<QString>("handler");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s;
+ QTest::addRow("Changed") << u"Changed"_s;
+ QTest::addRow("empty") << u""_s;
+ QTest::addRow("on") << u"on"_s;
+}
+void tst_qml_common::tst_handlerNameToSignalName()
+{
+ QFETCH(QString, handler);
+
+ QVERIFY(!QQmlSignalNames::handlerNameToSignalName(handler).has_value());
+}
+
+void tst_qml_common::tst_isChangedHandlerName_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<bool>("expected");
+
+ QTest::addRow("normalProperty") << u"helloWorld"_s << false;
+ QTest::addRow("Changed") << u"Changed"_s << false;
+ QTest::addRow("empty") << u""_s << false;
+ QTest::addRow("empty2") << u"onChanged"_s << false;
+ QTest::addRow("on") << u"on"_s << false;
+ QTest::addRow("on_Changed") << u"on_Changed"_s << true;
+ QTest::addRow("on$Changed") << u"on$Changed"_s << true;
+}
+void tst_qml_common::tst_isChangedHandlerName()
+{
+ QFETCH(QString, name);
+ QFETCH(bool, expected);
+
+ QCOMPARE(QQmlSignalNames::isChangedHandlerName(name), expected);
+}
+
+QTEST_MAIN(tst_qml_common)
diff --git a/tests/auto/qml/common/tst_qml_common.h b/tests/auto/qml/common/tst_qml_common.h
new file mode 100644
index 0000000000..98e462ded6
--- /dev/null
+++ b/tests/auto/qml/common/tst_qml_common.h
@@ -0,0 +1,35 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TST_QML_COMMON_H
+#define TST_QML_COMMON_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtTest/qtest.h>
+#include <QtQml/private/qqmlsignalnames_p.h>
+
+class tst_qml_common : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void tst_propertyNameToChangedSignalName_data();
+ void tst_propertyNameToChangedSignalName();
+ void tst_propertyNameToChangedHandlerName();
+ void tst_propertyNameToChangedHandlerName_data();
+ void tst_signalNameToHandlerName();
+ void tst_signalNameToHandlerName_data();
+
+ void tst_changedSignalNameToPropertyName();
+ void tst_changedSignalNameToPropertyName_data();
+ void tst_changedHandlerNameToPropertyName();
+ void tst_changedHandlerNameToPropertyName_data();
+ void tst_handlerNameToSignalName();
+ void tst_handlerNameToSignalName_data();
+
+ void tst_isChangedHandlerName();
+ void tst_isChangedHandlerName_data();
+};
+
+#endif // TST_QML_COMMON_H
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt b/tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt
index d3df19bc40..07b6e26544 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qdebugmessageservice/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qdebugmessageservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qdebugmessageservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/data/test.qml b/tests/auto/qml/debugger/qdebugmessageservice/data/test.qml
index b8134b37e6..bdb91d08e5 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/data/test.qml
+++ b/tests/auto/qml/debugger/qdebugmessageservice/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
index 11c4203429..cd39b51b25 100644
--- a/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
+++ b/tests/auto/qml/debugger/qdebugmessageservice/tst_qdebugmessageservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//QQmlDebugTest
#include "../shared/debugutil_p.h"
diff --git a/tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt b/tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt
index 146999b9bd..91941de381 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qpacketprotocol/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qpacketprotocol Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qpacketprotocol LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qpacketprotocol
SOURCES
../shared/debugutil.cpp ../shared/debugutil_p.h
diff --git a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
index 81d8694406..2ce062b0cc 100644
--- a/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
+++ b/tests/auto/qml/debugger/qpacketprotocol/tst_qpacketprotocol.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QSignalSpy>
#include <QTimer>
@@ -18,9 +18,9 @@ class tst_QPacketProtocol : public QObject
Q_OBJECT
private:
- QTcpServer *m_server;
- QTcpSocket *m_client;
- QTcpSocket *m_serverConn;
+ std::unique_ptr<QTcpServer> m_server;
+ std::unique_ptr<QTcpSocket> m_client;
+ std::unique_ptr<QTcpSocket> m_serverConn;
private slots:
void init();
@@ -34,34 +34,34 @@ private slots:
void tst_QPacketProtocol::init()
{
- m_server = new QTcpServer(this);
+ m_server = std::make_unique<QTcpServer>(this);
m_serverConn = nullptr;
QVERIFY(m_server->listen(QHostAddress("127.0.0.1")));
- m_client = new QTcpSocket(this);
+ m_client = std::make_unique<QTcpSocket>(this);
- QSignalSpy serverSpy(m_server, SIGNAL(newConnection()));
- QSignalSpy clientSpy(m_client, SIGNAL(connected()));
+ QSignalSpy serverSpy(m_server.get(), SIGNAL(newConnection()));
+ QSignalSpy clientSpy(m_client.get(), SIGNAL(connected()));
m_client->connectToHost(m_server->serverAddress(), m_server->serverPort());
QVERIFY(clientSpy.size() > 0 || clientSpy.wait());
QVERIFY(serverSpy.size() > 0 || serverSpy.wait());
- m_serverConn = m_server->nextPendingConnection();
+ m_serverConn.reset(m_server->nextPendingConnection());
}
void tst_QPacketProtocol::cleanup()
{
- delete m_client;
- delete m_serverConn;
- delete m_server;
+ m_client.reset();
+ m_serverConn.reset();
+ m_server.reset();
}
void tst_QPacketProtocol::send()
{
- QPacketProtocol in(m_client);
- QPacketProtocol out(m_serverConn);
+ QPacketProtocol in(m_client.get());
+ QPacketProtocol out(m_serverConn.get());
QByteArray ba;
int num;
@@ -82,8 +82,8 @@ void tst_QPacketProtocol::packetsAvailable()
{
QFETCH(int, packetCount);
- QPacketProtocol out(m_client);
- QPacketProtocol in(m_serverConn);
+ QPacketProtocol out(m_client.get());
+ QPacketProtocol in(m_serverConn.get());
QCOMPARE(out.packetsAvailable(), qint64(0));
QCOMPARE(in.packetsAvailable(), qint64(0));
@@ -109,8 +109,8 @@ void tst_QPacketProtocol::packetsAvailable_data()
void tst_QPacketProtocol::read()
{
- QPacketProtocol in(m_client);
- QPacketProtocol out(m_serverConn);
+ QPacketProtocol in(m_client.get());
+ QPacketProtocol out(m_serverConn.get());
QVERIFY(in.read().isEmpty());
diff --git a/tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt
index 6b33ee0024..d0a63440da 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugclient/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebugclient Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugclient LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmldebugclient
SOURCES
../shared/debugutil.cpp ../shared/debugutil_p.h
diff --git a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
index 509791b96d..d0e9c22f2c 100644
--- a/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugclient/tst_qqmldebugclient.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugtestservice.h"
@@ -44,11 +44,16 @@ void tst_QQmlDebugClient::initTestCase()
m_service = new QQmlDebugTestService("tst_QQmlDebugClient::handshake()");
- foreach (const QString &service, QQmlDebuggingEnabler::debuggerServices())
+ const QStringList debuggerServices = QQmlDebuggingEnabler::debuggerServices();
+ for (const QString &service : debuggerServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
- foreach (const QString &service, QQmlDebuggingEnabler::inspectorServices())
+
+ const QStringList inspectorServices = QQmlDebuggingEnabler::inspectorServices();
+ for (const QString &service : inspectorServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
- foreach (const QString &service, QQmlDebuggingEnabler::profilerServices())
+
+ const QStringList profilerServices = QQmlDebuggingEnabler::profilerServices();
+ for (const QString &service : profilerServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
const QString waitingMsg = QString("QML Debugger: Waiting for connection on port %1...").arg(PORT);
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt
index b73c2aa218..53b1e9c683 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebuggingenabler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebuggingenabler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmldebuggingenabler
SOURCES
../../shared/debugutil.cpp ../../shared/debugutil_p.h
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml
index 9bd5130e71..2474016705 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp
index ab599e9a23..03a65f56ca 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenabler/tst_qqmldebuggingenabler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugprocess_p.h"
@@ -41,14 +41,14 @@ void tst_QQmlDebuggingEnabler::data()
QTest::addColumn<bool>("blockMode");
QTest::addColumn<QStringList>("services");
- QStringList connectors({
+ const QStringList connectors({
QLatin1String("QQmlDebugServer"),
QLatin1String("QQmlNativeDebugConnector")
});
- QList<bool> blockModes({ true, false });
+ const QList<bool> blockModes({ true, false });
- QList<QStringList> serviceLists({
+ const QList<QStringList> serviceLists({
QStringList(),
QQmlDebuggingEnabler::nativeDebuggerServices(),
QQmlDebuggingEnabler::debuggerServices(),
@@ -57,9 +57,9 @@ void tst_QQmlDebuggingEnabler::data()
QQmlDebuggingEnabler::debuggerServices() + QQmlDebuggingEnabler::inspectorServices()
});
- foreach (const QString &connector, connectors) {
- foreach (bool blockMode, blockModes) {
- foreach (const QStringList &serviceList, serviceLists) {
+ for (const QString &connector : connectors) {
+ for (bool blockMode : blockModes) {
+ for (const QStringList &serviceList : serviceLists) {
QString name = connector + QLatin1Char(',')
+ QLatin1String(blockMode ? "block" : "noblock") + QLatin1Char(',')
+ serviceList.join(QLatin1Char('-'));
@@ -103,7 +103,7 @@ void tst_QQmlDebuggingEnabler::qmlscene()
m_clients = QQmlDebugTest::createOtherClients(m_connection);
m_connection->connectToHost("127.0.0.1", m_process->debugPort());
QVERIFY(m_connection->waitForConnected());
- foreach (QQmlDebugClient *client, m_clients)
+ for (QQmlDebugClient *client : std::as_const(m_clients))
QCOMPARE(client->state(), (services.isEmpty() || services.contains(client->name())) ?
QQmlDebugClient::Enabled : QQmlDebugClient::Unavailable);
}
diff --git a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp
index 33bb0d6d37..6baaf8f430 100644
--- a/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp
+++ b/tests/auto/qml/debugger/qqmldebuggingenabler/qqmldebuggingenablerserver/qqmldebuggingenablerserver.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qcoreapplication.h>
#include <QtCore/qlibraryinfo.h>
diff --git a/tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt
index e48f8e965d..3d65442ebf 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugjs/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebugjs Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugjs LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml b/tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml
index 03bc85f5a4..6650096b55 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/breakOnAnchor.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.11
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
index 3a846c0eeb..254924743e 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/breakpointRelocation.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml b/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml
index 2d747c28a5..3ebe44ea76 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/changeBreakpoint.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml b/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml
index a4952f79cc..0f02f62750 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/condition.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml b/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml
index e67713ba67..f58b474876 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/createComponent.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml b/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml
index dc3be646ce..807735573e 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/exception.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml b/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml
index 0af1188015..bcd8f4e9d5 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/loadjsfile.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import "test.js" as Script
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
index 6cf2d7c030..4cc13a7952 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/oncompleted.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml b/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml
index 026911d1cc..788cd86cce 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/quit.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml b/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml
index 4f21b53ff4..ab8566b77c 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/quitInJS.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import "quit.js" as Quit;
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml b/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml
index f442a9c491..1de3078f19 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/stepAction.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/test.js b/tests/auto/qml/debugger/qqmldebugjs/data/test.js
index 7a28dafdd2..f631b1657b 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/test.js
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/test.js
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
function printMessage(msg)
{
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/test.qml b/tests/auto/qml/debugger/qqmldebugjs/data/test.qml
index 687955dffc..bc84f7b3af 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml b/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml
index 923acb72ad..a823a9a407 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml
+++ b/tests/auto/qml/debugger/qqmldebugjs/data/timer.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
index ac607df0a0..35a94aae78 100644
--- a/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjs/tst_qqmldebugjs.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugprocess_p.h"
@@ -140,8 +140,8 @@ private slots:
void letConstLocals();
private:
- ConnectResult init(bool qmlscene, const QString &qmlFile = QString(TEST_QMLFILE),
- bool blockMode = true, bool restrictServices = false);
+ ConnectResult runAndConnect(bool qmlscene, const QString &qmlFile = QString(TEST_QMLFILE),
+ bool blockMode = true, bool restrictServices = false);
QList<QQmlDebugClient *> createClients() override;
QPointer<QV4DebugClient> m_client;
@@ -163,7 +163,7 @@ void tst_QQmlDebugJS::initTestCase()
QQmlDebugTest::initTestCase();
}
#include <iostream>
-QQmlDebugTest::ConnectResult tst_QQmlDebugJS::init(bool qmlscene, const QString &qmlFile,
+QQmlDebugTest::ConnectResult tst_QQmlDebugJS::runAndConnect(bool qmlscene, const QString &qmlFile,
bool blockMode, bool restrictServices)
{
const QString executable = qmlscene
@@ -195,7 +195,7 @@ void tst_QQmlDebugJS::connect()
QFETCH(bool, restrictMode);
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene, QString(TEST_QMLFILE), blockMode, restrictMode), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, QString(TEST_QMLFILE), blockMode, restrictMode), ConnectSuccess);
m_client->connect();
QVERIFY(waitForClientSignal(SIGNAL(connected())));
}
@@ -205,7 +205,7 @@ void tst_QQmlDebugJS::interrupt()
//void connect()
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene), ConnectSuccess);
m_client->connect();
m_client->interrupt();
@@ -217,7 +217,7 @@ void tst_QQmlDebugJS::getVersion()
//void version()
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene), ConnectSuccess);
m_client->connect();
QVERIFY(waitForClientSignal(SIGNAL(connected())));
@@ -231,7 +231,7 @@ void tst_QQmlDebugJS::getVersionWhenAttaching()
//void version()
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene, QLatin1String(TIMER_QMLFILE), false), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, QLatin1String(TIMER_QMLFILE), false), ConnectSuccess);
m_client->connect();
m_client->version();
@@ -244,7 +244,7 @@ void tst_QQmlDebugJS::disconnect()
//void disconnect()
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene), ConnectSuccess);
m_client->connect();
m_client->disconnect();
@@ -257,7 +257,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnCompleted()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -276,7 +276,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComponentCreated()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, CREATECOMPONENT_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, CREATECOMPONENT_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -294,7 +294,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnTimerCallback()
QFETCH(bool, qmlscene);
int sourceLine = 10;
- QCOMPARE(init(qmlscene, TIMER_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, TIMER_QMLFILE), ConnectSuccess);
m_client->connect();
//We can set the breakpoint after connect() here because the timer is repeating and if we miss
@@ -315,7 +315,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptInDifferentFile()
QFETCH(bool, qmlscene);
int sourceLine = 6;
- QCOMPARE(init(qmlscene, LOADJSFILE_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, LOADJSFILE_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(TEST_JSFILE), sourceLine, -1, true);
m_client->connect();
@@ -335,7 +335,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnComment()
int sourceLine = 9;
int actualLine = 11;
- QCOMPARE(init(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -356,7 +356,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnEmptyLine()
int sourceLine = 10;
int actualLine = 11;
- QCOMPARE(init(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -376,7 +376,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptOnOptimizedBinding()
QFETCH(bool, qmlscene);
int sourceLine = 14;
- QCOMPARE(init(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, BREAKPOINTRELOCATION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(BREAKPOINTRELOCATION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -395,7 +395,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptWithCondition()
int out = 10;
int sourceLine = 12;
- QCOMPARE(init(qmlscene, CONDITION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, CONDITION_QMLFILE), ConnectSuccess);
m_client->connect();
//The breakpoint is in a timer loop so we can set it after connect().
@@ -425,7 +425,7 @@ void tst_QQmlDebugJS::setBreakpointInScriptThatQuits()
{
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene, QUIT_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, QUIT_QMLFILE), ConnectSuccess);
int sourceLine = 11;
@@ -465,7 +465,7 @@ void tst_QQmlDebugJS::setBreakpointInJavaScript()
QTRY_COMPARE(process.state(), QProcess::NotRunning);
}
- QCOMPARE(init(qmlscene, QUITINJS_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, QUITINJS_QMLFILE), ConnectSuccess);
const int sourceLine = 2;
@@ -488,7 +488,7 @@ void tst_QQmlDebugJS::setBreakpointInJavaScript()
void tst_QQmlDebugJS::setBreakpointWhenAttaching()
{
int sourceLine = 10;
- QCOMPARE(init(true, QLatin1String(TIMER_QMLFILE), false), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, QLatin1String(TIMER_QMLFILE), false), ConnectSuccess);
m_client->connect();
@@ -509,7 +509,7 @@ void tst_QQmlDebugJS::clearBreakpoint()
int sourceLine1 = 12;
int sourceLine2 = 13;
- QCOMPARE(init(qmlscene, CHANGEBREAKPOINT_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, CHANGEBREAKPOINT_QMLFILE), ConnectSuccess);
m_client->connect();
//The breakpoints are in a timer loop so we can set them after connect().
@@ -556,7 +556,7 @@ void tst_QQmlDebugJS::changeBreakpoint()
int sourceLine2 = 12;
int sourceLine1 = 13;
const QString file = QLatin1String(CHANGEBREAKPOINT_QMLFILE);
- QCOMPARE(init(qmlscene, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, file), ConnectSuccess);
bool isStopped = false;
QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() { isStopped = true; });
@@ -629,7 +629,7 @@ void tst_QQmlDebugJS::setExceptionBreak()
//void setExceptionBreak(QString type, bool enabled = false);
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene, EXCEPTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, EXCEPTION_QMLFILE), ConnectSuccess);
m_client->setExceptionBreak(QV4DebugClient::All,true);
m_client->connect();
QVERIFY(waitForClientSignal(SIGNAL(stopped())));
@@ -641,7 +641,7 @@ void tst_QQmlDebugJS::stepNext()
QFETCH(bool, qmlscene);
int sourceLine = 12;
- QCOMPARE(init(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -669,7 +669,7 @@ void tst_QQmlDebugJS::stepIn()
int sourceLine = 16;
int actualLine = 11;
- QCOMPARE(init(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine, 1, true);
m_client->connect();
@@ -691,7 +691,7 @@ void tst_QQmlDebugJS::stepOut()
int sourceLine = 12;
int actualLine = 16;
- QCOMPARE(init(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -713,7 +713,7 @@ void tst_QQmlDebugJS::continueDebugging()
int sourceLine1 = 16;
int sourceLine2 = 13;
- QCOMPARE(init(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, STEPACTION_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine1, -1, true);
m_client->setBreakpoint(QLatin1String(STEPACTION_QMLFILE), sourceLine2, -1, true);
@@ -736,7 +736,7 @@ void tst_QQmlDebugJS::backtrace()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -752,7 +752,7 @@ void tst_QQmlDebugJS::getFrameDetails()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -768,7 +768,7 @@ void tst_QQmlDebugJS::getScopeDetails()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -781,7 +781,7 @@ void tst_QQmlDebugJS::getScopeDetails()
void tst_QQmlDebugJS::evaluateInGlobalScope()
{
//void evaluate(QString expr, int frame = -1);
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
m_client->connect();
@@ -802,7 +802,7 @@ void tst_QQmlDebugJS::evaluateInLocalScope()
QFETCH(bool, qmlscene);
int sourceLine = 9;
- QCOMPARE(init(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene, ONCOMPLETED_QMLFILE), ConnectSuccess);
m_client->setBreakpoint(QLatin1String(ONCOMPLETED_QMLFILE), sourceLine, -1, true);
m_client->connect();
@@ -889,7 +889,7 @@ void tst_QQmlDebugJS::getScripts()
//void scripts(int types = -1, QList<int> ids = QList<int>(), bool includeSource = false, QVariant filter = QVariant());
QFETCH(bool, qmlscene);
- QCOMPARE(init(qmlscene), ConnectSuccess);
+ QCOMPARE(runAndConnect(qmlscene), ConnectSuccess);
m_client->setBreakpoint(QString(TEST_QMLFILE), 10, -1, true);
m_client->connect();
@@ -908,7 +908,7 @@ void tst_QQmlDebugJS::getScripts()
void tst_QQmlDebugJS::encodeQmlScope()
{
QString file(ENCODEQMLSCOPE_QMLFILE);
- QCOMPARE(init(true, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, file), ConnectSuccess);
int numFrames = 0;
int numExpectedScopes = 0;
@@ -968,7 +968,7 @@ void tst_QQmlDebugJS::encodeQmlScope()
void tst_QQmlDebugJS::breakOnAnchor()
{
QString file(BREAKONANCHOR_QMLFILE);
- QCOMPARE(init(true, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, file), ConnectSuccess);
int breaks = 0;
bool stopped = false;
@@ -1005,7 +1005,7 @@ void tst_QQmlDebugJS::breakOnAnchor()
void tst_QQmlDebugJS::breakPointIds()
{
QString file(BREAKPOINTIDS_QMLFILE);
- QCOMPARE(init(true, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, file), ConnectSuccess);
int breaks = 0;
int breakPointIds[] = { -1, -1, -1, -1, -1, -1};
@@ -1038,7 +1038,7 @@ void tst_QQmlDebugJS::breakPointIds()
void tst_QQmlDebugJS::letConstLocals()
{
QString file(LETCONSTLOCALS_QMLFILE);
- QCOMPARE(init(true, file), ConnectSuccess);
+ QCOMPARE(runAndConnect(true, file), ConnectSuccess);
QObject::connect(m_client.data(), &QV4DebugClient::stopped, this, [&]() {
m_client->frame();
diff --git a/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp b/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp
index b24e4c4445..4b3d7dc6fa 100644
--- a/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp
+++ b/tests/auto/qml/debugger/qqmldebugjsserver/qqmldebugjsserver.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtGui/qguiapplication.h>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt
index 471336139d..03dcb24b3f 100644
--- a/tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebuglocal/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebuglocal Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebuglocal LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmldebuglocal
SOURCES
../shared/debugutil.cpp ../shared/debugutil_p.h
diff --git a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
index 7449062332..bca70b7273 100644
--- a/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
+++ b/tests/auto/qml/debugger/qqmldebuglocal/tst_qqmldebuglocal.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qqmldebugtestservice.h"
#include "debugutil_p.h"
diff --git a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt
index ea07333ec7..54fe36b7d5 100644
--- a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebugprocess Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugprocess LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmldebugprocess
SOURCES
../../shared/qqmldebugprocess.cpp ../../shared/qqmldebugprocess_p.h
diff --git a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp
index 7b1faa1131..2a403fa361 100644
--- a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp
+++ b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocess/tst_qqmldebugprocess.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qqmldebugprocess_p.h>
#include <QtTest>
diff --git a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp
index 595fe70e58..f275c2e836 100644
--- a/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp
+++ b/tests/auto/qml/debugger/qqmldebugprocess/qqmldebugprocessprocess/qqmldebugprocessprocess.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qdebug.h>
#include <QtCore/qcoreapplication.h>
diff --git a/tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt
index 33b7ba1c2f..2169cb8e0e 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugservice/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldebugservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmldebugservice/data/test.qml b/tests/auto/qml/debugger/qqmldebugservice/data/test.qml
index 687955dffc..bc84f7b3af 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebugservice/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
index 7dbff4279e..462caf930f 100644
--- a/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugservice/tst_qqmldebugservice.cpp
@@ -1,6 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qqmldebugtestservice.h"
#include "debugutil_p.h"
@@ -30,7 +29,7 @@ public:
tst_QQmlDebugService();
private:
- QQmlDebugConnection *m_conn;
+ std::unique_ptr<QQmlDebugConnection> m_conn;
QQmlDebugTestService *m_service;
private slots:
@@ -60,20 +59,23 @@ void tst_QQmlDebugService::initTestCase()
<< QStringLiteral("tst_QQmlDebugService"));
m_service = new QQmlDebugTestService("tst_QQmlDebugService", 2);
- foreach (const QString &service, QQmlDebuggingEnabler::debuggerServices())
+ const QStringList debuggerServices = QQmlDebuggingEnabler::debuggerServices();
+ for (const QString &service : debuggerServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
- foreach (const QString &service, QQmlDebuggingEnabler::inspectorServices())
+
+ const QStringList inspectorServices = QQmlDebuggingEnabler::inspectorServices();
+ for (const QString &service : inspectorServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
- foreach (const QString &service, QQmlDebuggingEnabler::profilerServices())
+
+ const QStringList profilerServices = QQmlDebuggingEnabler::profilerServices();
+ for (const QString &service : profilerServices)
QCOMPARE(QQmlDebugConnector::instance()->service(service), (QQmlDebugService *)nullptr);
const QString waitingMsg = QString("QML Debugger: Waiting for connection on port %1...").arg(PORT);
QTest::ignoreMessage(QtDebugMsg, waitingMsg.toLatin1().constData());
QQmlDebuggingEnabler::startTcpDebugServer(PORT);
- new QQmlEngine(this);
-
- m_conn = new QQmlDebugConnection(this);
+ m_conn = std::make_unique<QQmlDebugConnection>(this);
for (int i = 0; i < 50; ++i) {
// try for 5 seconds ...
@@ -136,7 +138,7 @@ void tst_QQmlDebugService::state()
QCOMPARE(m_service->state(), QQmlDebugService::Unavailable);
{
- QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn.get());
QTRY_COMPARE(client.state(), QQmlDebugClient::Enabled);
QTRY_COMPARE(m_service->state(), QQmlDebugService::Enabled);
}
@@ -154,7 +156,7 @@ void tst_QQmlDebugService::state()
void tst_QQmlDebugService::sendMessage()
{
- QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn.get());
QByteArray msg = "hello!";
@@ -175,7 +177,7 @@ void tst_QQmlDebugService::sendMessage()
void tst_QQmlDebugService::checkSupportForDataStreamVersion()
{
- QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn.get());
QByteArray msg = "hello!";
@@ -192,22 +194,19 @@ void tst_QQmlDebugService::idForObject()
{
QCOMPARE(QQmlDebugService::idForObject(nullptr), -1);
- QObject *objA = new QObject;
+ std::unique_ptr<QObject> objA = std::make_unique<QObject>();
- int idA = QQmlDebugService::idForObject(objA);
+ int idA = QQmlDebugService::idForObject(objA.get());
QVERIFY(idA >= 0);
- QCOMPARE(QQmlDebugService::objectForId(idA), objA);
+ QCOMPARE(QQmlDebugService::objectForId(idA), objA.get());
- int idAA = QQmlDebugService::idForObject(objA);
+ int idAA = QQmlDebugService::idForObject(objA.get());
QCOMPARE(idAA, idA);
- QObject *objB = new QObject;
- int idB = QQmlDebugService::idForObject(objB);
+ std::unique_ptr<QObject> objB = std::make_unique<QObject>();
+ int idB = QQmlDebugService::idForObject(objB.get());
QVERIFY(idB != idA);
- QCOMPARE(QQmlDebugService::objectForId(idB), objB);
-
- delete objA;
- delete objB;
+ QCOMPARE(QQmlDebugService::objectForId(idB), objB.get());
}
void tst_QQmlDebugService::objectForId()
@@ -215,19 +214,18 @@ void tst_QQmlDebugService::objectForId()
QCOMPARE(QQmlDebugService::objectForId(-1), static_cast<QObject*>(nullptr));
QCOMPARE(QQmlDebugService::objectForId(1), static_cast<QObject*>(nullptr));
- QObject *obj = new QObject;
- int id = QQmlDebugService::idForObject(obj);
- QCOMPARE(QQmlDebugService::objectForId(id), obj);
+ std::unique_ptr<QObject> obj = std::make_unique<QObject>();
+ int id = QQmlDebugService::idForObject(obj.get());
+ QCOMPARE(QQmlDebugService::objectForId(id), obj.get());
- delete obj;
+ obj.reset();
QCOMPARE(QQmlDebugService::objectForId(id), static_cast<QObject*>(nullptr));
}
void tst_QQmlDebugService::checkSupportForOldDataStreamVersion()
{
//create a new connection;
- delete m_conn;
- m_conn = new QQmlDebugConnection(this);
+ m_conn = std::make_unique<QQmlDebugConnection>(this);
m_conn->setMaximumDataStreamVersion(QDataStream::Qt_5_0);
for (int i = 0; i < 50; ++i) {
// try for 5 seconds ...
@@ -238,7 +236,7 @@ void tst_QQmlDebugService::checkSupportForOldDataStreamVersion()
}
QVERIFY(m_conn->isConnected());
- QQmlDebugTestClient client("tst_QQmlDebugService", m_conn);
+ QQmlDebugTestClient client("tst_QQmlDebugService", m_conn.get());
QByteArray msg = "hello!";
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt
index fd44b5d32f..56c2e8d88a 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugtranslationclient/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qqmldebugtranslationclient Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugtranslationclient LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml b/tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml
index 5b4784bbff..e90f9a5a80 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebugtranslationclient/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp b/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp
index 4ad9699cb9..068ab69d4c 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp
+++ b/tests/auto/qml/debugger/qqmldebugtranslationclient/tst_qqmldebugtranslationclient.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//QQmlDebugTest
#include <debugutil_p.h>
@@ -105,9 +105,7 @@ private:
if (newCurrentOutputLine > m_currentOutputLine) {
// lets wait a little bit more to not cut anything
int triggeredCount = 0;
- int debugCounter = 0;
do {
- debugCounter++;
triggeredCount = m_process->output().size();
QTest::qWait(updateTimeOut);
newCurrentOutputLine = m_process->output().size();
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt b/tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt
index 7f971df399..5081f51557 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qqmldebugtranslationservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldebugtranslationservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml
index 1212fa100a..5d3957bffa 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml
+++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/data/test.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp
index 0e0340b672..88d7bd39fd 100644
--- a/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp
+++ b/tests/auto/qml/debugger/qqmldebugtranslationservice/tst_qqmldebugtranslationservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
//QQmlDebugTest
#include <debugutil_p.h>
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt b/tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt
index 39435fe894..12c5b4ad1f 100644
--- a/tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlenginecontrol Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlenginecontrol LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
index 638389eb3c..bd01c69163 100644
--- a/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
+++ b/tests/auto/qml/debugger/qqmlenginecontrol/tst_qqmlenginecontrol.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include <QtQuickTestUtils/private/qmlutils_p.h>
diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt
index 8b4fc93594..bb36f678c3 100644
--- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlenginedebuginspectorintegration Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlenginedebuginspectorintegration LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
index 890f4eeef6..7bbc8830b1 100644
--- a/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebuginspectorintegrationtest/tst_qqmlenginedebuginspectorintegration.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "../shared/debugutil_p.h"
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -24,7 +24,7 @@ public:
tst_QQmlEngineDebugInspectorIntegration();
private:
- ConnectResult init(bool restrictServices);
+ ConnectResult runAndConnect(bool restrictServices);
QList<QQmlDebugClient *> createClients() override;
QQmlEngineDebugObjectReference findRootObject();
@@ -68,7 +68,7 @@ tst_QQmlEngineDebugInspectorIntegration::tst_QQmlEngineDebugInspectorIntegration
{
}
-QQmlDebugTest::ConnectResult tst_QQmlEngineDebugInspectorIntegration::init(bool restrictServices)
+QQmlDebugTest::ConnectResult tst_QQmlEngineDebugInspectorIntegration::runAndConnect(bool restrictServices)
{
return QQmlDebugTest::connectTo(
QLibraryInfo::path(QLibraryInfo::BinariesPath) + "/qml",
@@ -96,15 +96,15 @@ void tst_QQmlEngineDebugInspectorIntegration::connect_data()
void tst_QQmlEngineDebugInspectorIntegration::connect()
{
QFETCH(bool, restrictMode);
- QCOMPARE(init(restrictMode), ConnectSuccess);
+ QCOMPARE(runAndConnect(restrictMode), ConnectSuccess);
}
void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
bool success = false;
- QQmlEngineDebugObjectReference rootObject = findRootObject();
+ const QQmlEngineDebugObjectReference rootObject = findRootObject();
QVERIFY(rootObject.debugId != -1);
const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
int lineNumber = rootObject.source.lineNumber;
@@ -114,7 +114,7 @@ void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
QVERIFY(success);
QVERIFY(QQmlDebugTest::waitForSignal(m_engineDebugClient, SIGNAL(result())));
- foreach (QQmlEngineDebugObjectReference child, rootObject.children) {
+ for (const QQmlEngineDebugObjectReference &child : rootObject.children) {
success = false;
lineNumber = child.source.lineNumber;
columnNumber = child.source.columnNumber;
@@ -127,12 +127,12 @@ void tst_QQmlEngineDebugInspectorIntegration::objectLocationLookup()
void tst_QQmlEngineDebugInspectorIntegration::select()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
- QQmlEngineDebugObjectReference rootObject = findRootObject();
+ const QQmlEngineDebugObjectReference rootObject = findRootObject();
QList<int> childIds;
int requestId = 0;
- foreach (const QQmlEngineDebugObjectReference &child, rootObject.children) {
+ for (const QQmlEngineDebugObjectReference &child : rootObject.children) {
requestId = m_inspectorClient->select(QList<int>() << child.debugId);
QTRY_COMPARE(m_recipient->lastResponseId, requestId);
QVERIFY(m_recipient->lastResult);
@@ -145,7 +145,7 @@ void tst_QQmlEngineDebugInspectorIntegration::select()
void tst_QQmlEngineDebugInspectorIntegration::createObject()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
QString qml = QLatin1String("Rectangle {\n"
" id: xxxyxxx\n"
@@ -172,7 +172,7 @@ void tst_QQmlEngineDebugInspectorIntegration::createObject()
void tst_QQmlEngineDebugInspectorIntegration::moveObject()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
QQmlEngineDebugObjectReference rootObject = findRootObject();
@@ -197,7 +197,7 @@ void tst_QQmlEngineDebugInspectorIntegration::moveObject()
void tst_QQmlEngineDebugInspectorIntegration::destroyObject()
{
- QCOMPARE(init(true), ConnectSuccess);
+ QCOMPARE(runAndConnect(true), ConnectSuccess);
QCOMPARE(m_inspectorClient->state(), QQmlDebugClient::Enabled);
QQmlEngineDebugObjectReference rootObject = findRootObject();
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt b/tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt
index 4d4a939da5..d412368767 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlenginedebugservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlenginedebugservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml
index 9e4546bdac..bda1673b18 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/complexItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Test 1.0
@@ -7,7 +7,7 @@ Item {
id: root
width: 10; height: 20; scale: blueRect.scale;
Rectangle { id: blueRect; width: 500; height: 600; color: "blue"; }
- Text { font.bold: true; color: blueRect.color; }
+ Text { id: blueText; font.bold: true; color: blueRect.color; }
MouseArea {
onEntered: { console.log('hello') }
}
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml
index a472988772..3203cc5bfc 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/customTypes.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Backend 1.0
CustomTypes {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml
index 0532b44726..994b2f82f1 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/debuggerCrashOnAttach.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Controls 2.5
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml
index ebbf3f85e3..ded2b620ce 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/emptyItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
Item {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml
index ea0c3ff8c0..0a2e68f786 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/fetchValueType.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml
index 118b13f2d7..e107ed5259 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/itemWithFunctions.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
Item {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml
index eb0c65b42f..27f6ffcc92 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/jsonTest.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import JsonTest 1.0
JsonTest {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml b/tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml
index fee3f969b8..d8fe7f98c3 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/data/rectangleWithTransitions.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
Rectangle {
diff --git a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
index e6e21cbb9e..a63c690cf0 100644
--- a/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
+++ b/tests/auto/qml/debugger/qqmlenginedebugservice/tst_qqmlenginedebugservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -22,6 +22,7 @@
#include <QtQml/qqmlproperty.h>
#include <QtQml/qqmlincubator.h>
#include <QtQml/qqmlapplicationengine.h>
+#include <QtQml/private/qqmlsignalnames_p.h>
#include <QtQuick/qquickitem.h>
#include <QtNetwork/qhostaddress.h>
@@ -244,7 +245,7 @@ void tst_QQmlEngineDebugService::recursiveObjectTest(
QCOMPARE(p.objectDebugId, QQmlDebugService::idForObject(o));
// signal properties are fake - they are generated from QQmlAbstractBoundSignal children
- if (p.name.startsWith("on") && p.name.size() > 2 && p.name[2].isUpper()) {
+ if (QQmlSignalNames::isHandlerName(p.name)) {
QString signal = p.value.toString();
QQmlBoundSignalExpression *expr = QQmlPropertyPrivate::signalExpression(QQmlProperty(o, p.name));
QVERIFY(expr && expr->expression() == signal);
@@ -414,10 +415,10 @@ void tst_QQmlEngineDebugService::watch_property()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->addWatch(prop, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->addWatch(QQmlEngineDebugPropertyReference(), &success);
QVERIFY(success);
@@ -458,10 +459,10 @@ void tst_QQmlEngineDebugService::watch_object()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->addWatch(obj, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->addWatch(QQmlEngineDebugObjectReference(), &success);
QVERIFY(success);
@@ -525,10 +526,10 @@ void tst_QQmlEngineDebugService::watch_expression()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->addWatch(obj, expr, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->addWatch(QQmlEngineDebugObjectReference(), expr, &success);
QVERIFY(success);
@@ -600,10 +601,10 @@ void tst_QQmlEngineDebugService::queryAvailableEngines()
{
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryAvailableEngines(&success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryAvailableEngines(&success);
QVERIFY(success);
@@ -628,10 +629,10 @@ void tst_QQmlEngineDebugService::queryRootContexts()
QVERIFY(m_dbg->engines().size());
const QQmlEngineDebugEngineReference engine = m_dbg->engines()[0];
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryRootContexts(engine, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryRootContexts(engine, &success);
QVERIFY(success);
@@ -659,10 +660,10 @@ void tst_QQmlEngineDebugService::queryObject()
QQmlEngineDebugObjectReference rootObject = findRootObject();
QVERIFY(!rootObject.className.isEmpty());
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
recursive ? unconnected->queryObjectRecursive(rootObject, &success) : unconnected->queryObject(rootObject, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
recursive ? m_dbg->queryObjectRecursive(rootObject, &success) : m_dbg->queryObject(rootObject, &success);
QVERIFY(success);
@@ -690,9 +691,9 @@ void tst_QQmlEngineDebugService::queryObject()
QQmlEngineDebugObjectReference text;
for (const QQmlEngineDebugObjectReference &child : obj.children) {
QVERIFY(!child.className.isEmpty());
- if (child.className == "Rectangle")
+ if (child.idString == "blueRect")
rect = child;
- else if (child.className == "Text")
+ else if (child.idString == "blueText")
text = child;
}
@@ -731,13 +732,13 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation()
int lineNumber = rootObject.source.lineNumber;
int columnNumber = rootObject.source.columnNumber;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
recursive ? unconnected->queryObjectsForLocationRecursive(fileName, lineNumber,
columnNumber, &success)
: unconnected->queryObjectsForLocation(fileName, lineNumber,
columnNumber, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
recursive ? m_dbg->queryObjectsForLocationRecursive(fileName, lineNumber,
columnNumber, &success)
@@ -769,9 +770,9 @@ void tst_QQmlEngineDebugService::queryObjectsForLocation()
QQmlEngineDebugObjectReference text;
for (const QQmlEngineDebugObjectReference &child : obj.children) {
QVERIFY(!child.className.isEmpty());
- if (child.className == "Rectangle")
+ if (child.idString == "blueRect")
rect = child;
- else if (child.className == "Text")
+ else if (child.idString == "blueText")
text = child;
}
@@ -813,9 +814,9 @@ void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451()
"text: \"test\"\n"
"}");
component.setData(content, rootObject.source.url);
- QObject *object = component.create(context);
+ std::unique_ptr<QObject> object { component.create(context) };
QVERIFY(object);
- int idNew = QQmlDebugService::idForObject(object);
+ int idNew = QQmlDebugService::idForObject(object.get());
QVERIFY(idNew >= 0);
const QString fileName = QFileInfo(rootObject.source.url.toString()).fileName();
@@ -839,7 +840,7 @@ void tst_QQmlEngineDebugService::regression_QTCREATORBUG_7451()
QVERIFY(QQmlDebugTest::waitForSignal(m_dbg, SIGNAL(result())));
}
- delete object;
+ object.reset();
QObject *deleted = QQmlDebugService::objectForId(idNew);
QVERIFY(!deleted);
@@ -870,10 +871,10 @@ void tst_QQmlEngineDebugService::queryObjectWithNonStreamableTypes()
QQmlEngineDebugObjectReference rootObject = findRootObject(4, true);
QVERIFY(!rootObject.className.isEmpty());
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryObject(rootObject, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryObject(rootObject, &success);
QVERIFY(success);
@@ -914,10 +915,10 @@ void tst_QQmlEngineDebugService::queryExpressionResult()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryExpressionResult(objectId, expr, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryExpressionResult(objectId, expr, &success);
QVERIFY(success);
@@ -967,10 +968,10 @@ void tst_QQmlEngineDebugService::queryExpressionResultBC()
bool success;
- QQmlEngineDebugClient *unconnected = new QQmlEngineDebugClient(nullptr);
+ std::unique_ptr<QQmlEngineDebugClient> unconnected = std::make_unique<QQmlEngineDebugClient>(nullptr);
unconnected->queryExpressionResultBC(objectId, expr, &success);
QVERIFY(!success);
- delete unconnected;
+ unconnected.reset();
m_dbg->queryExpressionResultBC(objectId, expr, &success);
QVERIFY(success);
diff --git a/tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt b/tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt
index 7e6fb3559d..34a9b7a393 100644
--- a/tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlinspector/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlinspector Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlinspector LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
index 897d8c8688..7f4e5eb73f 100644
--- a/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
+++ b/tests/auto/qml/debugger/qqmlinspector/tst_qqmlinspector.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "../shared/debugutil_p.h"
#include "../shared/qqmldebugprocess_p.h"
diff --git a/tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt b/tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt
index 705361c3be..f6d8988ec2 100644
--- a/tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlnativeconnector/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlnativeconnector Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlnativeconnector LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlnativeconnector
SOURCES
tst_qqmlnativeconnector.cpp
diff --git a/tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp b/tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp
index 55a9aeb3f5..dd9789cdc5 100644
--- a/tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp
+++ b/tests/auto/qml/debugger/qqmlnativeconnector/tst_qqmlnativeconnector.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qjsondocument.h>
#include <QtCore/qjsonobject.h>
diff --git a/tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt b/tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt
index 3eaf14b35d..83d33a617f 100644
--- a/tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlpreview/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlpreview Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlpreview LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
list(APPEND test_data "data/window.qml")
list(APPEND test_data "data/qtquick2.qml")
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/broken.qml b/tests/auto/qml/debugger/qqmlpreview/data/broken.qml
index 75387c42aa..e8f82461a0 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/broken.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/broken.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml b/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml
index 4013dfc9ff..d49b94fc7e 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/qtquick2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/window.qml b/tests/auto/qml/debugger/qqmlpreview/data/window.qml
index 951b9a7f10..1141292a2c 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/window.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/window.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.0
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/window1.qml b/tests/auto/qml/debugger/qqmlpreview/data/window1.qml
index 4a24041dea..20c7ab04ea 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/window1.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/window1.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.3
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/window2.qml b/tests/auto/qml/debugger/qqmlpreview/data/window2.qml
index 0de5dc36c8..d144cfb033 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/window2.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/window2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQuick.Window 2.3
diff --git a/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml b/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml
index 86445a2fdc..18712a7e2d 100644
--- a/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml
+++ b/tests/auto/qml/debugger/qqmlpreview/data/zoom.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
index 0c4fd568a9..5874100ebd 100644
--- a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
+++ b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qqmldebugprocess_p.h>
#include <debugutil_p.h>
@@ -303,7 +303,7 @@ void tst_QQmlPreview::zoom()
for (auto testZoomFactor : {2.0f, 1.5f, 0.5f}) {
m_client->triggerZoom(testZoomFactor);
- verifyZoomFactor(m_process, testZoomFactor);
+ verifyZoomFactor(m_process, testZoomFactor * baseZoomFactor);
}
m_client->triggerZoom(-1.0f);
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt b/tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt
index 1e6c4c1753..d770f1fb27 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlprofilerservice Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlprofilerservice LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
index 3a7c093fa5..6e16eaa7b1 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/controlFromJS.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.0
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml b/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml
index 026911d1cc..788cd86cce 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/data/quit.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
index 53971d3e8b..2088f958ae 100644
--- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
+++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugprocess_p.h"
@@ -80,7 +80,7 @@ void QQmlProfilerTestClient::addEvent(const QQmlProfilerEvent &event)
const QQmlProfilerEventType &type = types[typeIndex];
- QVERIFY(event.timestamp() >= lastTimestamp);
+ const qint64 oldTimestamp = lastTimestamp;
lastTimestamp = event.timestamp();
switch (type.message()) {
@@ -149,6 +149,8 @@ void QQmlProfilerTestClient::addEvent(const QQmlProfilerEvent &event)
}
break;
}
+
+ QCOMPARE_GE(lastTimestamp, oldTimestamp);
}
class tst_QQmlProfilerService : public QQmlDebugTest
@@ -287,7 +289,7 @@ void tst_QQmlProfilerService::checkJsHeap()
qint64 allocated = 0;
qint64 used = 0;
qint64 lastTimestamp = -1;
- foreach (const QQmlProfilerEvent &message, m_client->jsHeapMessages) {
+ for (const QQmlProfilerEvent &message : std::as_const(m_client->jsHeapMessages)) {
const auto amount = message.number<qint64>(0);
const QQmlProfilerEventType &type = m_client->types.at(message.typeIndex());
switch (type.detailType()) {
@@ -440,7 +442,7 @@ bool tst_QQmlProfilerService::verify(tst_QQmlProfilerService::MessageListType ty
return true;
} while (++position < target->size() && target->at(position).timestamp() == timestamp);
- foreach (const QString &message, warnings)
+ for (const QString &message : std::as_const(warnings))
qWarning() << message.toLocal8Bit().constData();
return false;
@@ -580,7 +582,7 @@ void tst_QQmlProfilerService::scenegraphData()
QCOMPARE(connectTo(true, "scenegraphTest.qml"), ConnectSuccess);
while (!m_process->output().contains(QLatin1String("tick")))
- QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput())));
+ QVERIFY(QQmlDebugTest::waitForSignal(m_process, SIGNAL(readyReadStandardOutput()), 30000));
m_client->client->setRecording(false);
checkTraceReceived();
@@ -594,7 +596,7 @@ void tst_QQmlProfilerService::scenegraphData()
// interleaved. Also, events could carry the same time stamps and be sorted in an unexpected way
// if the clocks are acting up.
qint64 renderFrameTime = -1;
- foreach (const QQmlProfilerEvent &msg, m_client->asynchronousMessages) {
+ for (const QQmlProfilerEvent &msg : std::as_const(m_client->asynchronousMessages)) {
const QQmlProfilerEventType &type = m_client->types.at(msg.typeIndex());
if (type.detailType() == SceneGraphRendererFrame) {
renderFrameTime = msg.timestamp();
diff --git a/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt b/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt
index 0b60a0092b..42f6cf931a 100644
--- a/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt
+++ b/tests/auto/qml/debugger/qv4debugger/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4debugger Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4debugger LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -17,11 +23,12 @@ qt_add_library(testCppTypes STATIC)
qt_autogen_tools_initial_setup(testCppTypes)
target_link_libraries(testCppTypes PRIVATE Qt::Qml Qt::QmlPrivate Qt::Quick)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(testCppTypes
URI TestTypes
SOURCES
commontypes.h
- AUTO_RESOURCE_PREFIX
OUTPUT_DIRECTORY TestTypes
)
qt_autogen_tools_initial_setup(testCppTypesplugin)
diff --git a/tests/auto/qml/debugger/qv4debugger/commontypes.h b/tests/auto/qml/debugger/qv4debugger/commontypes.h
index 01b2125ae3..b63059b0e6 100644
--- a/tests/auto/qml/debugger/qv4debugger/commontypes.h
+++ b/tests/auto/qml/debugger/qv4debugger/commontypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef COMMONTYPES_H
#define COMMONTYPES_H
@@ -14,7 +14,7 @@ class MyType : public QQuickItem
QML_ELEMENT
public:
MyType(QQuickItem *parent = nullptr) : QQuickItem(parent) {}
- Q_INVOKABLE void name(QQmlV4Function*) const {}
+ Q_INVOKABLE void name(QQmlV4FunctionPtr) const {}
};
#endif // COMMONTYPES_H
diff --git a/tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml b/tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml
new file mode 100644
index 0000000000..2582a23ec5
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/breakPointInJSModule.qml
@@ -0,0 +1,4 @@
+import QtQml 2.15
+import "module1.js" as Module1
+
+QtObject {}
diff --git a/tests/auto/qml/debugger/qv4debugger/data/module1.js b/tests/auto/qml/debugger/qv4debugger/data/module1.js
new file mode 100644
index 0000000000..9ce1f1e6b1
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/module1.js
@@ -0,0 +1,5 @@
+.pragma library
+
+.import "module2.mjs" as Module2
+
+Module2.crashMe();
diff --git a/tests/auto/qml/debugger/qv4debugger/data/module2.mjs b/tests/auto/qml/debugger/qv4debugger/data/module2.mjs
new file mode 100644
index 0000000000..80f82af953
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/module2.mjs
@@ -0,0 +1,7 @@
+import * as Module3 from "module3.mjs"
+import * as Module4 from "module4.mjs"
+
+export function crashMe()
+{
+ console.log("Hello world!");
+}
diff --git a/tests/auto/qml/debugger/qv4debugger/data/module3.mjs b/tests/auto/qml/debugger/qv4debugger/data/module3.mjs
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/module3.mjs
diff --git a/tests/auto/qml/debugger/qv4debugger/data/module4.mjs b/tests/auto/qml/debugger/qv4debugger/data/module4.mjs
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/auto/qml/debugger/qv4debugger/data/module4.mjs
diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
index 6f147446f0..3da401b5bb 100644
--- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtTest/QtTest>
@@ -167,7 +168,7 @@ public slots:
m_thrownValue = job.exceptionValue();
}
- foreach (const TestBreakPoint &bp, m_breakPointsToAddWhenPaused)
+ for (const TestBreakPoint &bp : std::as_const(m_breakPointsToAddWhenPaused))
debugger->addBreakPoint(bp.fileName, bp.lineNumber);
m_breakPointsToAddWhenPaused.clear();
@@ -216,10 +217,14 @@ public:
QJsonArray scopes = frameObj.value(QLatin1String("scopes")).toArray();
int nscopes = scopes.size();
int s = 0;
- for (s = 0; s < nscopes; ++s) {
- QJsonObject o = scopes.at(s).toObject();
- if (o.value(QLatin1String("type")).toInt(-2) == 1) // CallContext
- break;
+ if (m_targetScope != -1) {
+ s = m_targetScope;
+ } else {
+ for (s = 0; s < nscopes; ++s) {
+ QJsonObject o = scopes.at(s).toObject();
+ if (o.value(QLatin1String("type")).toInt(-2) == 1) // CallContext
+ break;
+ }
}
if (s == nscopes)
return;
@@ -249,6 +254,7 @@ public:
bool m_wasPaused;
QV4Debugger::PauseReason m_pauseReason;
bool m_captureContextInfo;
+ int m_targetScope = -1;
QList<QV4Debugger::ExecutionState> m_statesWhenPaused;
QList<TestBreakPoint> m_breakPointsToAddWhenPaused;
QVector<QV4::StackFrame> m_stackTrace;
@@ -274,9 +280,10 @@ public:
void dumpStackTrace() const
{
qDebug() << "Stack depth:" << m_stackTrace.size();
- foreach (const QV4::StackFrame &frame, m_stackTrace)
+ for (const QV4::StackFrame &frame : m_stackTrace) {
qDebug("\t%s (%s:%d:%d)", qPrintable(frame.function), qPrintable(frame.source),
- frame.line, frame.column);
+ qAbs(frame.line), frame.column);
+ }
}
};
@@ -322,6 +329,9 @@ private slots:
void readThis();
void signalParameters();
void debuggerNoCrash();
+
+ void breakPointInJSModule();
+
private:
QV4Debugger *debugger() const
{
@@ -329,27 +339,27 @@ private:
}
void evaluateJavaScript(const QString &script, const QString &fileName, int lineNumber = 1)
{
- QMetaObject::invokeMethod(m_engine, "evaluate", Qt::QueuedConnection,
+ QMetaObject::invokeMethod(m_engine.get(), "evaluate", Qt::QueuedConnection,
Q_ARG(QString, script), Q_ARG(QString, fileName),
Q_ARG(int, lineNumber));
- waitForSignal(m_engine, SIGNAL(evaluateFinished()), /*timeout*/0);
+ waitForSignal(m_engine.get(), SIGNAL(evaluateFinished()), /*timeout*/0);
}
- TestEngine *m_engine;
+ std::unique_ptr<TestEngine> m_engine;
QV4::ExecutionEngine *m_v4;
- TestAgent *m_debuggerAgent;
- QThread *m_javaScriptThread;
+ std::unique_ptr<TestAgent> m_debuggerAgent;
+ std::unique_ptr<QThread> m_javaScriptThread;
};
void tst_qv4debugger::init()
{
- m_javaScriptThread = new QThread;
- m_engine = new TestEngine;
+ m_javaScriptThread = std::make_unique<QThread>();
+ m_engine = std::make_unique<TestEngine>();
m_v4 = m_engine->v4Engine();
m_v4->setDebugger(new QV4Debugger(m_v4));
- m_engine->moveToThread(m_javaScriptThread);
+ m_engine->moveToThread(m_javaScriptThread.get());
m_javaScriptThread->start();
- m_debuggerAgent = new TestAgent(m_v4);
+ m_debuggerAgent = std::make_unique<TestAgent>(m_v4);
m_debuggerAgent->addDebugger(debugger());
}
@@ -357,11 +367,11 @@ void tst_qv4debugger::cleanup()
{
m_javaScriptThread->exit();
m_javaScriptThread->wait();
- delete m_engine;
- delete m_javaScriptThread;
+ m_engine.reset();
+ m_javaScriptThread.reset();
m_engine = nullptr;
m_v4 = nullptr;
- delete m_debuggerAgent;
+ m_debuggerAgent.reset();
m_debuggerAgent = nullptr;
}
@@ -453,7 +463,7 @@ void tst_qv4debugger::removeBreakPointForNextInstruction()
"someCall();\n"
"var i = 42;";
- QMetaObject::invokeMethod(m_engine, "injectFunction", Qt::BlockingQueuedConnection,
+ QMetaObject::invokeMethod(m_engine.get(), "injectFunction", Qt::BlockingQueuedConnection,
Q_ARG(QString, "someCall"), Q_ARG(InjectedFunction, someCall));
debugger()->addBreakPoint("removeBreakPointForNextInstruction", 2);
@@ -967,6 +977,35 @@ void tst_qv4debugger::debuggerNoCrash()
debugThread->wait();
}
+void tst_qv4debugger::breakPointInJSModule()
+{
+ QQmlEngine engine;
+ QV4::ExecutionEngine *v4 = engine.handle();
+ QPointer<QV4Debugger> v4Debugger = new QV4Debugger(v4);
+ v4->setDebugger(v4Debugger.data());
+
+ QScopedPointer<QThread> debugThread(new QThread);
+ debugThread->start();
+ QScopedPointer<TestAgent> debuggerAgent(new TestAgent(v4));
+ debuggerAgent->addDebugger(v4Debugger);
+ debuggerAgent->moveToThread(debugThread.data());
+
+ QQmlComponent component(&engine, testFileUrl("breakPointInJSModule.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ debuggerAgent->m_captureContextInfo = true;
+ debuggerAgent->m_targetScope = 1;
+ v4Debugger->addBreakPoint("module2.mjs", 6);
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+
+ QVERIFY(!debuggerAgent->m_capturedScope.isEmpty());
+
+ debugThread->quit();
+ debugThread->wait();
+}
+
tst_qv4debugger::tst_qv4debugger() : QQmlDataTest(QT_QMLTEST_DATADIR) { }
QTEST_MAIN(tst_qv4debugger)
diff --git a/tests/auto/qml/debugger/shared/debugutil.cpp b/tests/auto/qml/debugger/shared/debugutil.cpp
index bce2c28378..28d40d768d 100644
--- a/tests/auto/qml/debugger/shared/debugutil.cpp
+++ b/tests/auto/qml/debugger/shared/debugutil.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "debugutil_p.h"
#include "qqmldebugprocess_p.h"
diff --git a/tests/auto/qml/debugger/shared/debugutil_p.h b/tests/auto/qml/debugger/shared/debugutil_p.h
index 0303aa2da9..188cc14c32 100644
--- a/tests/auto/qml/debugger/shared/debugutil_p.h
+++ b/tests/auto/qml/debugger/shared/debugutil_p.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DEBUGUTIL_P_H
#define DEBUGUTIL_P_H
diff --git a/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp b/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp
index 4944ba2e15..97477370c8 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugprocess.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qqmldebugprocess_p.h"
@@ -56,7 +56,7 @@ QString QQmlDebugProcess::stateString() const
void QQmlDebugProcess::start(const QStringList &arguments)
{
-#ifdef Q_OS_MAC
+#ifdef Q_OS_MACOS
// make sure m_executable points to the actual binary even if it's inside an app bundle
QFileInfo binFile(m_executable);
if (!binFile.isExecutable()) {
diff --git a/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h b/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h
index 56ed9b9830..94554928a5 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h
+++ b/tests/auto/qml/debugger/shared/qqmldebugprocess_p.h
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QQMLDEBUGPROCESS_P_H
#define QQMLDEBUGPROCESS_P_H
diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
index daafa8c26e..4884c9d400 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qqmldebugtestservice.h"
#include <QThread>
diff --git a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
index 150ded9b1b..a2a3ce6161 100644
--- a/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
+++ b/tests/auto/qml/debugger/shared/qqmldebugtestservice.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef QQMLDEBUGTESTSERVICE_H
#define QQMLDEBUGTESTSERVICE_H
diff --git a/tests/auto/qml/ecmascripttests/CMakeLists.txt b/tests/auto/qml/ecmascripttests/CMakeLists.txt
index d3da3adb53..1ee70cb101 100644
--- a/tests/auto/qml/ecmascripttests/CMakeLists.txt
+++ b/tests/auto/qml/ecmascripttests/CMakeLists.txt
@@ -5,15 +5,22 @@
## tst_ecmascripttests Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_ecmascripttests LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
test262/*)
list(APPEND test_data ${test_data_glob})
+list(FILTER test_data EXCLUDE REGEX ".git")
qt_internal_add_test(tst_ecmascripttests
SOURCES
- qjstest/test262runner.cpp qjstest/test262runner.h
+ test262runner.cpp test262runner.h
tst_ecmascripttests.cpp
LIBRARIES
Qt::QmlPrivate
@@ -40,7 +47,3 @@ else()
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/test262"
)
endif()
-
-if(NOT CMAKE_CROSSCOMPILING)
- add_subdirectory(qjstest)
-endif()
diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations
index 75fdd1cb0c..cc5eae456d 100644
--- a/tests/auto/qml/ecmascripttests/TestExpectations
+++ b/tests/auto/qml/ecmascripttests/TestExpectations
@@ -18,6 +18,12 @@ language/statements/labeled/let-identifier-with-newline.js sloppyFails
language/statements/while/let-identifier-with-newline.js sloppyFails
language/statements/with/let-identifier-with-newline.js sloppyFails
+# These failures are a defect in the Yarr regexp engine we are using.
+# They all amount to some variation of: /\udf06/u.exec('\ud834\udf06')
+built-ins/RegExp/prototype/Symbol.match/builtin-infer-unicode.js
+built-ins/RegExp/prototype/Symbol.search/u-lastindex-advance.js
+built-ins/RegExp/prototype/exec/u-lastindex-adv.js
+
# The ES6/7 spec says that [[DefineOwnProperty]] on the module namespace exotic object
# always returns false. This was changed in https://github.com/tc39/ecma262/pull/858
# but it's not in the published spec yet.
@@ -92,7 +98,6 @@ built-ins/Array/prototype/slice/length-exceeding-integer-limit-proxied-array.js
built-ins/Array/prototype/slice/length-exceeding-integer-limit.js fails
built-ins/Array/prototype/some/15.4.4.17-3-28.js fails
built-ins/Array/prototype/some/15.4.4.17-3-29.js fails
-built-ins/Array/prototype/sort/comparefn-nonfunction-call-throws.js fails
built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js fails
built-ins/Array/prototype/splice/clamps-length-to-integer-limit.js fails
built-ins/Array/prototype/splice/create-ctor-non-object.js fails
@@ -211,7 +216,6 @@ built-ins/Promise/prototype/then/ctor-throws.js fails
built-ins/Promise/race/ctx-ctor.js fails
built-ins/Proxy/ownKeys/return-duplicate-entries-throws.js fails
built-ins/Proxy/ownKeys/return-duplicate-symbol-entries-throws.js fails
-built-ins/RegExp/prototype/Symbol.match/builtin-success-u-return-val-groups.js fails
built-ins/RegExp/prototype/Symbol.split/species-ctor.js fails
built-ins/RegExp/prototype/exec/S15.10.6.2_A5_T3.js fails
built-ins/RegExp/prototype/exec/failure-lastindex-access.js fails
@@ -249,8 +253,6 @@ built-ins/String/prototype/toLocaleLowerCase/special_casing_conditional.js fails
built-ins/String/prototype/toLowerCase/Final_Sigma_U180E.js fails
built-ins/String/prototype/toLowerCase/special_casing_conditional.js fails
built-ins/TypedArray/prototype/constructor.js fails
-built-ins/TypedArray/prototype/fill/fill-values-conversion-operations-consistent-nan.js fails
-built-ins/TypedArray/prototype/slice/bit-precision.js fails
built-ins/TypedArray/prototype/sort/arraylength-internal.js fails
built-ins/TypedArray/prototype/sort/comparefn-call-throws.js fails
built-ins/TypedArray/prototype/sort/comparefn-calls.js fails
diff --git a/tests/auto/qml/ecmascripttests/qjstest/CMakeLists.txt b/tests/auto/qml/ecmascripttests/qjstest/CMakeLists.txt
deleted file mode 100644
index 86ca5f97a3..0000000000
--- a/tests/auto/qml/ecmascripttests/qjstest/CMakeLists.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-# Generated from qjstest.pro.
-
-#####################################################################
-## qjstest Tool:
-#####################################################################
-
-qt_get_tool_target_name(target_name qjstest)
-qt_internal_add_tool(${target_name}
- TARGET_DESCRIPTION "Javascript test runner"
- SOURCES
- main.cpp
- test262runner.cpp test262runner.h
- DEFINES
- QT_DEPRECATED_WARNINGS
- INCLUDE_DIRECTORIES
- .
- LIBRARIES
- Qt::Gui
- Qt::QmlPrivate
-)
-qt_internal_return_unless_building_tools()
-
-#### Keys ignored in scope 1:.:.:qjstest.pro:<TRUE>:
-# QMAKE_TARGET_DESCRIPTION = "Javascript" "test" "runner"
-# TEMPLATE = "app"
diff --git a/tests/auto/qml/ecmascripttests/qjstest/main.cpp b/tests/auto/qml/ecmascripttests/qjstest/main.cpp
deleted file mode 100644
index 7bffedae81..0000000000
--- a/tests/auto/qml/ecmascripttests/qjstest/main.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <QJSEngine>
-#include <QCoreApplication>
-#include <QCommandLineParser>
-#include <qdebug.h>
-#include <stdlib.h>
-
-#include "test262runner.h"
-
-int main(int argc, char **argv)
-{
- QCoreApplication app(argc, argv);
-
-
- QCommandLineParser parser;
- parser.addHelpOption();
- parser.addVersionOption();
- QCommandLineOption verbose("verbose", "Verbose output");
- parser.addOption(verbose);
- QCommandLineOption commandOption("command", "Javascript command line interpreter", "command");
- parser.addOption(commandOption);
- QCommandLineOption testDir("tests", "path to the tests", "tests", "test262");
- parser.addOption(testDir);
- QCommandLineOption cat("cat", "Print packaged test code that would be run");
- parser.addOption(cat);
- QCommandLineOption parallel("parallel", "Run tests in parallel");
- parser.addOption(parallel);
- QCommandLineOption jit("jit", "JIT all code");
- parser.addOption(jit);
- QCommandLineOption bytecode("interpret", "Run using the bytecode interpreter");
- parser.addOption(bytecode);
- QCommandLineOption withExpectations("with-test-expectations", "Parse TestExpectations to deal with known failures");
- parser.addOption(withExpectations);
- QCommandLineOption updateExpectations("update-expectations", "Update TestExpectations to remove unexepected passes");
- parser.addOption(updateExpectations);
- QCommandLineOption writeExpectations("write-expectations", "Generate a new TestExpectations file based on the results of the run");
- parser.addOption(writeExpectations);
- parser.addPositionalArgument("[filter]", "Only run tests that contain filter in their name");
-
- parser.process(app);
-
- Test262Runner testRunner(parser.value(commandOption), parser.value(testDir), QStringLiteral("TestExpectations"));
-
- QStringList otherArgs = parser.positionalArguments();
- if (otherArgs.size() > 1) {
- qWarning() << "too many arguments";
- return 1;
- } else if (otherArgs.size()) {
- testRunner.setFilter(otherArgs.at(0));
- }
-
- if (parser.isSet(cat)) {
- testRunner.cat();
- return 0;
- }
-
- if (parser.isSet(updateExpectations) && parser.isSet(writeExpectations)) {
- qWarning() << "Can only specify one of --update-expectations and --write-expectations.";
- exit(1);
- }
-
- if (parser.isSet(jit) && parser.isSet(bytecode)) {
- qWarning() << "Can only specify one of --jit and --interpret.";
- exit(1);
- }
-
- int flags = 0;
- if (parser.isSet(verbose))
-
- flags |= Test262Runner::Verbose;
- if (parser.isSet(parallel))
- flags |= Test262Runner::Parallel;
- if (parser.isSet(jit))
- flags |= Test262Runner::ForceJIT;
- if (parser.isSet(bytecode))
- flags |= Test262Runner::ForceBytecode;
- if (parser.isSet(withExpectations))
- flags |= Test262Runner::WithTestExpectations;
- if (parser.isSet(updateExpectations))
- flags |= Test262Runner::UpdateTestExpectations;
- if (parser.isSet(writeExpectations))
- flags |= Test262Runner::WriteTestExpectations;
- testRunner.setFlags(flags);
-
- if (testRunner.run())
- return EXIT_SUCCESS;
- else
- return EXIT_FAILURE;
-}
diff --git a/tests/auto/qml/ecmascripttests/test262.py b/tests/auto/qml/ecmascripttests/test262.py
deleted file mode 100755
index 01c990950c..0000000000
--- a/tests/auto/qml/ecmascripttests/test262.py
+++ /dev/null
@@ -1,611 +0,0 @@
-#!/usr/bin/env python
-# Copyright (C) 2017 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-# Copyright 2009 the Sputnik authors. All rights reserved.
-# This code is governed by the BSD license found in the LICENSE file.
-
-# This is derived from sputnik.py, the Sputnik console test runner,
-# with elements from packager.py, which is separately
-# copyrighted. TODO: Refactor so there is less duplication between
-# test262.py and packager.py.
-
-import sys
-from os import path
-rootDir = path.dirname(path.realpath(__file__))
-sys.path.insert(0, path.abspath(rootDir + "/test262/tools/packaging"))
-
-import logging
-import optparse
-import os
-import platform
-import re
-import subprocess
-import tempfile
-import time
-import xml.dom.minidom
-import datetime
-import shutil
-import json
-import stat
-import multiprocessing
-import signal
-
-
-from parseTestRecord import parseTestRecord, stripHeader
-
-from packagerConfig import *
-
-# excluded features that are still experimental and not part of any official standard
-# see also the features.txt file in test262/
-excludedFeatures = [
- "BigInt",
- "class-fields-public",
- "class-fields-private",
- "Promise.prototype.finally",
- "async-iteration",
- "Symbol.asyncIterator",
- "object-rest",
- "object-spread",
- "optional-catch-binding",
- "regexp-dotall",
- "regexp-lookbehind",
- "regexp-named-groups",
- "regexp-unicode-property-escapes",
- "Atomics",
- "SharedArrayBuffer",
- "Array.prototype.flatten",
- "Array.prototype.flatMap",
- "string-trimming",
- "String.prototype.trimEnd",
- "String.prototype.trimStart",
- "numeric-separator-literal",
-
- # optional features, not supported by us
- "caller"
-]
-
-# ############# Helpers needed for parallel multi-process test execution ############
-
-def runTest(case, args):
- return case.Run(args)
-
-def runTestVarArgs(args):
- return runTest(*args)
-
-def initWorkerProcess():
- signal.signal(signal.SIGINT, signal.SIG_IGN)
-
-# #############
-
-class Test262Error(Exception):
- def __init__(self, message):
- self.message = message
-
-def ReportError(s):
- raise Test262Error(s)
-
-
-class TestExpectations:
- def __init__(self, enabled):
- self.testsToSkip = []
- self.failingTests = []
- f = open(rootDir + "/TestExpectations")
- if not enabled:
- return
- for line in f.read().splitlines():
- line = line.strip()
- if len(line) == 0 or line[0] == "#":
- continue
- record = line.split()
- if len(record) == 1:
- self.failingTests.append(record[0])
- else:
- test = record[0]
- expectation = record[1]
- if expectation == "skip":
- self.testsToSkip.append(test)
- f.close()
-
- def update(self, progress):
- unexpectedPasses = [c.case.name for c in progress.failed_tests if c.case.IsNegative()]
-
- # If a test fails that we expected to fail, then it actually passed unexpectedly.
- failures = [c.case.name for c in progress.failed_tests if not c.case.IsNegative()]
- for failure in failures:
- if failure in self.failingTests:
- unexpectedPasses.append(failure)
-
- f = open(rootDir + "/TestExpectations")
- lines = f.read().splitlines()
- oldLen = len(lines)
- for result in unexpectedPasses:
- expectationLine = result
- try:
- lines.remove(expectationLine)
- except ValueError:
- pass
-
- f.close()
- if len(lines) != oldLen:
- f = open(rootDir + "/TestExpectations", "w")
- f.write("\n".join(lines))
- f.close()
- print "Changes to TestExpectations written!"
-
-
-if not os.path.exists(EXCLUDED_FILENAME):
- print "Cannot generate (JSON) test262 tests without a file," + \
- " %s, showing which tests have been disabled!" % EXCLUDED_FILENAME
- sys.exit(1)
-EXCLUDE_LIST = xml.dom.minidom.parse(EXCLUDED_FILENAME)
-EXCLUDE_LIST = EXCLUDE_LIST.getElementsByTagName("test")
-EXCLUDE_LIST = [x.getAttribute("id") for x in EXCLUDE_LIST]
-
-
-def BuildOptions():
- result = optparse.OptionParser()
- result.add_option("--command", default="qmljs", help="The command-line to run")
- result.add_option("--tests", default=path.abspath(rootDir + '/test262'),
- help="Path to the tests")
- result.add_option("--cat", default=False, action="store_true",
- help="Print packaged test code that would be run")
- result.add_option("--summary", default=True, action="store_true",
- help="Print summary after running tests")
- result.add_option("--full-summary", default=False, action="store_true",
- help="Print summary and test output after running tests")
- result.add_option("--strict_only", default=False, action="store_true",
- help="Test only strict mode")
- result.add_option("--non_strict_only", default=False, action="store_true",
- help="Test only non-strict mode")
- result.add_option("--parallel", default=False, action="store_true",
- help="Run tests in parallel")
- result.add_option("--with-test-expectations", default=False, action="store_true",
- help="Parse TestExpectations to deal with tests known to fail")
- result.add_option("--update-expectations", default=False, action="store_true",
- help="Update test expectations fail when a test passes that was expected to fail")
- # TODO: Once enough tests are made strict compat, change the default
- # to "both"
- result.add_option("--unmarked_default", default="non_strict",
- help="default mode for tests of unspecified strictness")
- return result
-
-
-def ValidateOptions(options):
- if not options.command:
- ReportError("A --command must be specified.")
- if not path.exists(options.tests):
- ReportError("Couldn't find test path '%s'" % options.tests)
-
-
-placeHolderPattern = re.compile(r"\{\{(\w+)\}\}")
-
-
-def IsWindows():
- p = platform.system()
- return (p == 'Windows') or (p == 'Microsoft')
-
-
-class TempFile(object):
-
- def __init__(self, suffix="", prefix="tmp", text=False):
- self.suffix = suffix
- self.prefix = prefix
- self.text = text
- self.fd = None
- self.name = None
- self.is_closed = False
- self.Open()
-
- def Open(self):
- (self.fd, self.name) = tempfile.mkstemp(
- suffix = self.suffix,
- prefix = self.prefix,
- text = self.text)
-
- def Write(self, str):
- os.write(self.fd, str)
-
- def Read(self):
- f = file(self.name)
- result = f.read()
- f.close()
- return result
-
- def Close(self):
- if not self.is_closed:
- self.is_closed = True
- os.close(self.fd)
-
- def Dispose(self):
- try:
- self.Close()
- os.unlink(self.name)
- except OSError, e:
- logging.error("Error disposing temp file: %s", str(e))
-
-
-class TestResult(object):
-
- def __init__(self, exit_code, stdout, stderr, case):
- self.exit_code = exit_code
- self.stdout = stdout
- self.stderr = stderr
- self.case = case
-
- def ReportOutcome(self, long_format):
- name = self.case.GetName()
- mode = self.case.GetMode()
- if self.HasUnexpectedOutcome():
- if self.case.IsNegative():
- print "=== %s was expected to fail in %s, but didn't ===" % (name, mode)
- else:
- if long_format:
- print "=== %s failed in %s ===" % (name, mode)
- else:
- print "%s in %s: " % (name, mode)
- out = self.stdout.strip()
- if len(out) > 0:
- print "--- output ---"
- print out
- err = self.stderr.strip()
- if len(err) > 0:
- print "--- errors ---"
- print err
- if long_format:
- print "==="
- elif self.case.IsNegative():
- print "%s failed in %s as expected" % (name, mode)
- else:
- print "%s passed in %s" % (name, mode)
-
- def HasFailed(self):
- return self.exit_code != 0
-
- def HasUnexpectedOutcome(self):
- if self.case.IsNegative():
- return not self.HasFailed()
- else:
- return self.HasFailed()
-
-
-class TestCase(object):
-
- def __init__(self, suite, name, full_path, strict_mode):
- self.suite = suite
- self.name = name
- self.full_path = full_path
- self.strict_mode = strict_mode
- f = open(self.full_path)
- self.contents = f.read()
- f.close()
- testRecord = parseTestRecord(self.contents, name)
- self.test = testRecord["test"]
- if 'features' in testRecord:
- self.features = testRecord["features"];
- else:
- self.features = []
- del testRecord["test"]
- del testRecord["header"]
- self.testRecord = testRecord;
-
-
- def GetName(self):
- return self.name
-
- def GetMode(self):
- if self.strict_mode:
- return "strict mode"
- else:
- return "non-strict mode"
-
- def GetPath(self):
- return self.name
-
- def NegateResult(self):
- if self.IsNegative():
- del self.testRecord['negative']
- else:
- self.testRecord['negative'] = "Some failure";
-
- def IsNegative(self):
- return 'negative' in self.testRecord
-
- def IsOnlyStrict(self):
- return 'onlyStrict' in self.testRecord
-
- def IsNoStrict(self):
- return 'noStrict' in self.testRecord
-
- def IsExperimental(self):
- for f in self.features:
- if excludedFeatures.count(f) >= 1:
- return True;
- return False
-
- def GetSource(self):
- # "var testDescrip = " + str(self.testRecord) + ';\n\n' + \
- source = self.suite.GetInclude("assert.js") + \
- self.suite.GetInclude("sta.js") + \
- self.test + '\n'
- if 'includes' in self.testRecord:
- for inc in self.testRecord['includes']:
- source += self.suite.GetInclude(inc);
-
- if self.strict_mode:
- source = '"use strict";\nvar strict_mode = true;\n' + source
- else:
- source = "var strict_mode = false; \n" + source
- return source
-
- def InstantiateTemplate(self, template, params):
- def GetParameter(match):
- key = match.group(1)
- return params.get(key, match.group(0))
- return placeHolderPattern.sub(GetParameter, template)
-
- def Execute(self, command):
- if IsWindows():
- args = '%s' % command
- else:
- args = command.split(" ")
- stdout = TempFile(prefix="test262-out-")
- stderr = TempFile(prefix="test262-err-")
- try:
- logging.info("exec: %s", str(args))
- process = subprocess.Popen(
- args,
- shell = IsWindows(),
- stdout = stdout.fd,
- stderr = stderr.fd
- )
- code = process.wait()
- out = stdout.Read()
- err = stderr.Read()
- finally:
- stdout.Dispose()
- stderr.Dispose()
- return (code, out, err)
-
- def RunTestIn(self, command_template, tmp):
- tmp.Write(self.GetSource())
- tmp.Close()
- command = self.InstantiateTemplate(command_template, {
- 'path': tmp.name
- })
- (code, out, err) = self.Execute(command)
- return TestResult(code, out, err, self)
-
- def Run(self, command_template):
- tmp = TempFile(suffix=".js", prefix="test262-", text=True)
- try:
- result = self.RunTestIn(command_template, tmp)
- finally:
- tmp.Dispose()
- return result
-
- def Print(self):
- print self.GetSource()
-
-
-class ProgressIndicator(object):
-
- def __init__(self, count):
- self.count = count
- self.succeeded = 0
- self.failed = 0
- self.failed_tests = []
-
- def HasRun(self, result):
- result.ReportOutcome(True)
- if result.HasUnexpectedOutcome():
- self.failed += 1
- self.failed_tests.append(result)
- else:
- self.succeeded += 1
-
-
-def MakePlural(n):
- if (n == 1):
- return (n, "")
- else:
- return (n, "s")
-
-
-class TestSuite(object):
-
- def __init__(self, root, strict_only, non_strict_only, unmarked_default, load_expectations):
- # TODO: derive from packagerConfig.py
- self.test_root = path.join(root, 'test')
- self.lib_root = path.join(root, 'harness')
- self.strict_only = strict_only
- self.non_strict_only = non_strict_only
- self.unmarked_default = unmarked_default
- self.include_cache = { }
- self.expectations = TestExpectations(load_expectations)
-
- def IsExcludedTest(self, path):
- if path.startswith('annexB'):
- return True;
- if path.startswith('harness'):
- return True;
- if path.startswith('intl402'):
- return True;
- return False;
-
- def Validate(self):
- if not path.exists(self.test_root):
- ReportError("No test repository found")
- if not path.exists(self.lib_root):
- ReportError("No test library found")
-
- def IsHidden(self, path):
- return path.startswith('.') or path == 'CVS'
-
- def IsTestCase(self, path):
- return path.endswith('.js')
-
- def ShouldRun(self, rel_path, tests):
- if len(tests) == 0:
- return True
- for test in tests:
- if test in rel_path:
- return True
- return False
-
- def GetInclude(self, name):
- if not name in self.include_cache:
- static = path.join(self.lib_root, name)
- if path.exists(static):
- f = open(static)
- contents = stripHeader(f.read())
- contents = re.sub(r'\r\n', '\n', contents)
- self.include_cache[name] = contents + "\n"
- f.close()
- else:
- ReportError("Can't find: " + static)
- return self.include_cache[name]
-
- def EnumerateTests(self, tests):
- logging.info("Listing tests in %s", self.test_root)
- cases = []
- for root, dirs, files in os.walk(self.test_root):
- for f in [x for x in dirs if self.IsHidden(x)]:
- dirs.remove(f)
- dirs.sort()
- for f in sorted(files):
- if self.IsTestCase(f):
- full_path = path.join(root, f)
- if full_path.startswith(self.test_root):
- rel_path = full_path[len(self.test_root)+1:]
- else:
- logging.warning("Unexpected path %s", full_path)
- rel_path = full_path
- if self.ShouldRun(rel_path, tests) and not self.IsExcludedTest(rel_path):
- basename = path.basename(full_path)[:-3]
- name = rel_path.replace('.js', '')
- if EXCLUDE_LIST.count(basename) >= 1 or self.expectations.testsToSkip.count(name) >= 1:
- print 'Excluded: ' + rel_path
- else:
- if not self.non_strict_only:
- strict_case = TestCase(self, name, full_path, True)
- if self.expectations.failingTests.count(name) >= 1:
- strict_case.NegateResult()
- if not strict_case.IsNoStrict() and not strict_case.IsExperimental():
- if strict_case.IsOnlyStrict() or \
- self.unmarked_default in ['both', 'strict']:
- cases.append(strict_case)
- if not self.strict_only:
- non_strict_case = TestCase(self, name, full_path, False)
- if self.expectations.failingTests.count(name) >= 1:
- non_strict_case.NegateResult()
- if not non_strict_case.IsOnlyStrict() and not non_strict_case.IsExperimental():
- if non_strict_case.IsNoStrict() or \
- self.unmarked_default in ['both', 'non_strict']:
- cases.append(non_strict_case)
- logging.info("Done listing tests")
- return cases
-
- def PrintSummary(self, progress):
- print
- print "=== Summary ==="
- count = progress.count
- succeeded = progress.succeeded
- failed = progress.failed
- print " - Ran %i test%s" % MakePlural(count)
- if progress.failed == 0:
- print " - All tests succeeded"
- else:
- percent = ((100.0 * succeeded) / count,)
- print " - Passed %i test%s (%.1f%%)" % (MakePlural(succeeded) + percent)
- percent = ((100.0 * failed) / count,)
- print " - Failed %i test%s (%.1f%%)" % (MakePlural(failed) + percent)
- positive = [c for c in progress.failed_tests if not c.case.IsNegative()]
- negative = [c for c in progress.failed_tests if c.case.IsNegative()]
- if len(positive) > 0:
- print
- print "Failed tests"
- for result in positive:
- print " %s in %s" % (result.case.GetName(), result.case.GetMode())
- if len(negative) > 0:
- print
- print "Expected to fail but passed ---"
- for result in negative:
- print " %s in %s" % (result.case.GetName(), result.case.GetMode())
-
- def PrintFailureOutput(self, progress):
- for result in progress.failed_tests:
- print
- result.ReportOutcome(False)
-
- def Run(self, command_template, tests, print_summary, full_summary, parallel, update_expectations):
- if not "{{path}}" in command_template:
- command_template += " {{path}}"
- cases = self.EnumerateTests(tests)
- if len(cases) == 0:
- ReportError("No tests to run")
- progress = ProgressIndicator(len(cases))
-
- if parallel:
- pool = multiprocessing.Pool(processes=multiprocessing.cpu_count(), initializer=initWorkerProcess)
- results = pool.imap_unordered(func=runTestVarArgs, iterable=[(case, command_template) for case in cases], chunksize=multiprocessing.cpu_count() * 8)
- for result in results:
- progress.HasRun(result)
- else:
- for case in cases:
- result = case.Run(command_template)
- progress.HasRun(result)
- if print_summary:
- self.PrintSummary(progress)
- if full_summary:
- self.PrintFailureOutput(progress)
- else:
- print
- print "Use --full-summary to see output from failed tests"
- print
- if update_expectations:
- self.expectations.update(progress)
- return progress.failed == 0
-
- def Print(self, tests):
- cases = self.EnumerateTests(tests)
- if len(cases) > 0:
- cases[0].Print()
-
-
-def Main():
- # Uncomment the next line for more logging info.
- #logging.basicConfig(level=logging.DEBUG)
- # Some date tests rely on being run in pacific time and the USA's locale:
- os.environ["TZ"] = "America/Los_Angeles" # it *matters* that this is (7m8s) *East* of PST's nominal meridian !
- os.environ["LANG"] = "en_US.UTF-8"
- os.environ["LC_TIME"] = "en_US.UTF-8"
- parser = BuildOptions()
- (options, args) = parser.parse_args()
- ValidateOptions(options)
- test_suite = TestSuite(options.tests,
- options.strict_only,
- options.non_strict_only,
- options.unmarked_default,
- options.with_test_expectations)
- test_suite.Validate()
- if options.cat:
- test_suite.Print(args)
- return 0
- else:
- if test_suite.Run(options.command, args,
- options.summary or options.full_summary,
- options.full_summary,
- options.parallel,
- options.update_expectations):
- return 0
- else:
- return 1
-
-
-if __name__ == '__main__':
- try:
- sys.exit(Main())
- except Test262Error, e:
- print "Error: %s" % e.message
- sys.exit(1)
diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp b/tests/auto/qml/ecmascripttests/test262runner.cpp
index fc09182f19..ff45b1b657 100644
--- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.cpp
+++ b/tests/auto/qml/ecmascripttests/test262runner.cpp
@@ -1,22 +1,26 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "test262runner.h"
-#include <qfile.h>
+#include <qdebug.h>
#include <qdir.h>
#include <qdiriterator.h>
-#include <qdebug.h>
+#include <qfile.h>
+#include <qjsondocument.h>
+#include <qjsonobject.h>
+#include <qlibraryinfo.h>
#include <qprocess.h>
#include <qtemporaryfile.h>
+#include <qthread.h>
-#include <private/qv4script_p.h>
-#include "private/qv4globalobject_p.h"
#include "private/qqmlbuiltinfunctions_p.h"
#include "private/qv4arraybuffer_p.h"
+#include "private/qv4globalobject_p.h"
#include <QtCore/QLoggingCategory>
+#include <private/qv4script_p.h>
-#include "qrunnable.h"
+using namespace Qt::StringLiterals;
static const char *excludedFeatures[] = {
"BigInt",
@@ -72,7 +76,7 @@ static ReturnedValue method_detachArrayBuffer(const FunctionObject *f, const Val
return Encode::null();
}
-static void initD262(ExecutionEngine *e)
+void initD262(ExecutionEngine *e)
{
Scope scope(e);
ScopedObject d262(scope, e->newObject());
@@ -85,10 +89,7 @@ static void initD262(ExecutionEngine *e)
}
-QT_END_NAMESPACE
-
-Q_DECLARE_LOGGING_CATEGORY(lcJsTest);
-Q_LOGGING_CATEGORY(lcJsTest, "qt.v4.ecma262.tests", QtWarningMsg);
+Q_STATIC_LOGGING_CATEGORY(lcJsTest, "qt.v4.ecma262.tests", QtWarningMsg);
Test262Runner::Test262Runner(const QString &command, const QString &dir, const QString &expectationsFile)
: command(command), testDir(dir), expectationsFile(expectationsFile)
@@ -99,7 +100,8 @@ Test262Runner::Test262Runner(const QString &command, const QString &dir, const Q
Test262Runner::~Test262Runner()
{
- delete threadPool;
+ if (threadPool)
+ delete threadPool;
}
void Test262Runner::cat()
@@ -113,18 +115,282 @@ void Test262Runner::cat()
printf("%s", data.content.constData());
}
+void Test262Runner::assignTaskOrTerminate(int processIndex)
+{
+ if (tasks.isEmpty()) {
+ sendDone(processIndex);
+ return;
+ }
+
+ currentTasks[processIndex] = tasks.dequeue();
+ TestData &task = currentTasks[processIndex];
+
+ // Sloppy run + maybe strict run later
+ if (task.runInSloppyMode) {
+ if (task.runInStrictMode)
+ task.stillNeedStrictRun = true;
+ assignSloppy(processIndex);
+ return;
+ }
+
+ // Only strict run
+ if (task.runInStrictMode) {
+ assignStrict(processIndex);
+ return;
+ }
+
+ // TODO: Start a timer for timeouts?
+}
+
+void Test262Runner::assignSloppy(int processIndex)
+{
+ QProcess &p = *processes[processIndex];
+ TestData &task = currentTasks[processIndex];
+
+ QJsonObject json;
+ json.insert("mode", "sloppy");
+ json.insert("testData", QString::fromUtf8(task.content));
+ json.insert("runAsModule", false);
+ json.insert("testCasePath", "");
+ json.insert("harnessForModules", "");
+ p.write(QJsonDocument(json).toJson(QJsonDocument::Compact));
+ p.write("\r\n");
+}
+
+void Test262Runner::assignStrict(int processIndex)
+{
+ QProcess &p = *processes[processIndex];
+ TestData &task = currentTasks[processIndex];
+
+ QJsonObject json;
+ json.insert("mode", "strict");
+ QString strictContent = "'use strict';\n" + QString::fromUtf8(task.content);
+ json.insert("testData", strictContent);
+ json.insert("runAsModule", task.runAsModuleCode);
+ json.insert("testCasePath", QFileInfo(testDir + "/test/" + task.test).absoluteFilePath());
+ json.insert("harnessForModules", QString::fromUtf8(task.harness));
+ p.write(QJsonDocument(json).toJson(QJsonDocument::Compact));
+ p.write("\r\n");
+}
+
+void Test262Runner::sendDone(int processIndex)
+{
+ QProcess &p = *processes[processIndex];
+
+ QJsonObject json;
+ json.insert("done", true);
+ p.write(QJsonDocument(json).toJson(QJsonDocument::Compact));
+ p.write("\r\n");
+}
+
+void Test262Runner::createProcesses()
+{
+ const int processCount = QThread::idealThreadCount();
+ qDebug() << "Running in parallel with" << processCount << "processes";
+ for (int i = 0; i < processCount; ++i) {
+ processes.emplace_back(std::make_unique<QProcess>());
+ QProcess &p = *processes[i];
+ QProcess::connect(&p, &QProcess::started, this, [&, i]() {
+ assignTaskOrTerminate(i);
+ });
+
+ QProcess::connect(&p, &QIODevice::readyRead, this, [&, i]() {
+ QProcess &p = *processes[i];
+ QString output;
+ while (output.isEmpty())
+ output = p.readLine();
+ QJsonDocument response = QJsonDocument::fromJson(output.toUtf8());
+
+ TestData &testData(currentTasks[i]);
+ auto mode = response["mode"].toString();
+ auto state = TestCase::State(response["resultState"].toInt(int(TestCase::State::Fails)));
+ auto errorMessage = response["resultErrorMessage"].toString();
+
+ auto &result = mode == "strict" ? testData.strictResult : testData.sloppyResult;
+ result = TestCase::Result(state, errorMessage);
+ if (testData.negative)
+ result.negateResult();
+
+ if (testData.stillNeedStrictRun) {
+ testData.stillNeedStrictRun = false;
+ assignStrict(i);
+ } else {
+ addResult(testData);
+ assignTaskOrTerminate(i);
+ }
+ });
+
+ QObject::connect(&p, &QProcess::finished, this,
+ [this, processCount, i](int exitCode, QProcess::ExitStatus status) {
+ if (status != QProcess::NormalExit || exitCode != 0) {
+ TestData &testData(currentTasks[i]);
+
+ auto &result = testData.stillNeedStrictRun
+ ? testData.sloppyResult
+ : testData.strictResult;
+ result = TestCase::Result(
+ TestCase::Crashes,
+ QStringLiteral("Process %1 of %2 exited with a non-normal status")
+ .arg(i).arg(processCount - 1));
+
+ addResult(testData);
+ }
+
+ --runningCount;
+ if (runningCount == 0)
+ loop.exit();
+ });
+
+ p.setProgram(QCoreApplication::applicationFilePath());
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ env.insert(u"runnerProcess"_s, u"1"_s);
+ p.setProcessEnvironment(env);
+ ++runningCount;
+ p.start();
+ }
+}
+
+class SingleTest : public QRunnable
+{
+public:
+ SingleTest(Test262Runner *runner, const TestData &data)
+ : runner(runner), data(data)
+ {}
+ void run() override;
+
+ Test262Runner *runner;
+ TestData data;
+};
+
+TestCase::Result getTestExecutionResult(QV4::ExecutionEngine &vm)
+{
+ TestCase::State state;
+ QString errorMessage;
+ if (vm.hasException) {
+ state = TestCase::State::Fails;
+ QV4::Scope scope(&vm);
+ QV4::ScopedValue val(scope, vm.catchException());
+ errorMessage = val->toQString();
+ } else {
+ state = TestCase::State::Passes;
+ }
+ return TestCase::Result(state, errorMessage);
+}
+
+void SingleTest::run()
+{
+ if (data.runInSloppyMode) {
+ QV4::ExecutionEngine vm;
+ Test262Runner::executeTest(vm, data.content);
+ TestCase::Result ok = getTestExecutionResult(vm);
+
+ if (data.negative)
+ ok.negateResult();
+
+ data.sloppyResult = ok;
+ } else {
+ data.sloppyResult = TestCase::Result(TestCase::Skipped);
+ }
+ if (data.runInStrictMode) {
+ QString testCasePath = QFileInfo(runner->testDirectory() + "/test/" + data.test).absoluteFilePath();
+ QByteArray c = "'use strict';\n" + data.content;
+
+ QV4::ExecutionEngine vm;
+ Test262Runner::executeTest(vm, c, testCasePath, data.harness, data.runAsModuleCode);
+ TestCase::Result ok = getTestExecutionResult(vm);
+
+ if (data.negative)
+ ok.negateResult();
+
+ data.strictResult = ok;
+ } else {
+ data.strictResult = TestCase::Result(TestCase::Skipped);
+ }
+ runner->addResult(data);
+}
+
+void Test262Runner::executeTest(QV4::ExecutionEngine &vm, const QString &testData,
+ const QString &testCasePath, const QString &harnessForModules,
+ bool runAsModule)
+{
+ QV4::Scope scope(&vm);
+ QV4::GlobalExtensions::init(vm.globalObject,
+ QJSEngine::ConsoleExtension | QJSEngine::GarbageCollectionExtension);
+ QV4::initD262(&vm);
+
+ if (runAsModule) {
+ const QUrl rootModuleUrl = QUrl::fromLocalFile(testCasePath);
+ // inject all modules with the harness
+ QVector<QUrl> modulesToLoad = { rootModuleUrl };
+ while (!modulesToLoad.isEmpty()) {
+ QUrl url = modulesToLoad.takeFirst();
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> module;
+
+ QFile f(url.toLocalFile());
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray content = harnessForModules.toLocal8Bit() + f.readAll();
+ module = vm.compileModule(url.toString(),
+ QString::fromUtf8(content.constData(),content.size()),
+ QFileInfo(f).lastModified());
+ if (vm.hasException)
+ break;
+ } else {
+ vm.throwError(QStringLiteral("Could not load module"));
+ break;
+ }
+
+ const QStringList moduleRequests = module->baseCompilationUnit()->moduleRequests();
+ for (const QString &request: moduleRequests) {
+ const QUrl absoluteRequest = module->finalUrl().resolved(QUrl(request));
+ const auto module = vm.moduleForUrl(absoluteRequest);
+ if (module.native == nullptr && module.compiled == nullptr)
+ modulesToLoad << absoluteRequest;
+ }
+ }
+
+ if (!vm.hasException) {
+ const auto rootModule = vm.loadModule(rootModuleUrl);
+ if (rootModule.compiled && rootModule.compiled->instantiate())
+ rootModule.compiled->evaluate();
+ }
+ } else {
+ QV4::ScopedContext ctx(scope, vm.rootContext());
+
+ QV4::Script script(ctx, QV4::Compiler::ContextType::Global, testData);
+ script.parse();
+
+ if (!vm.hasException)
+ script.run();
+ }
+}
+
+void Test262Runner::runWithThreadPool()
+{
+ threadPool = new QThreadPool();
+ threadPool->setStackSize(16*1024*1024);
+ qDebug() << "Running in parallel with" << QThread::idealThreadCount() << "threads";
+
+ for (const TestCase &testCase : std::as_const(testCases)) {
+ TestData testData = getTestData(testCase);
+ if (testData.isExcluded || testData.async)
+ continue;
+ SingleTest *test = new SingleTest(this, testData);
+ threadPool->start(test);
+ }
+
+ while (!threadPool->waitForDone(10'000)) {
+ if (lcJsTest().isEnabled(QtDebugMsg)) {
+ // heartbeat, only needed when there is no other debug output
+ qDebug("test262: in progress...");
+ }
+ }
+}
+
bool Test262Runner::run()
{
if (!loadTests())
return false;
- if (flags & Parallel) {
- threadPool = new QThreadPool;
- threadPool->setStackSize(16*1024*1024);
- if (flags & Verbose)
- qDebug() << "Running in parallel with" << QThread::idealThreadCount() << "threads.";
- }
-
if (flags & ForceJIT)
qputenv("QV4_JIT_CALL_THRESHOLD", QByteArray("0"));
else if (flags & ForceBytecode)
@@ -136,14 +402,24 @@ bool Test262Runner::run()
for (auto it = testCases.constBegin(); it != testCases.constEnd(); ++it) {
auto c = it.value();
if (!c.skipTestCase) {
- int result = runSingleTest(c);
- if (result == -2)
- return false;
+ TestData data = getTestData(c);
+ if (data.isExcluded || data.async)
+ continue;
+
+ tasks.append(data);
}
}
- if (threadPool)
- threadPool->waitForDone();
+ if (command.isEmpty()) {
+#if QT_CONFIG(process)
+ createProcesses();
+ loop.exec();
+#else
+ runWithThreadPool();
+#endif
+ } else {
+ runAsExternalTests();
+ }
const bool testsOk = report();
@@ -167,7 +443,7 @@ bool Test262Runner::report()
if (c.strictResult.state == c.strictExpectation.state
&& c.sloppyResult.state == c.sloppyExpectation.state)
continue;
- auto report = [&](TestCase::Result expected, TestCase::Result result, const char *s) {
+ auto report = [&](const TestCase::Result &expected, const TestCase::Result &result, const char *s) {
if (result.state == TestCase::Crashes)
crashes << (it.key() + " crashed in " + s + " mode");
if (result.state == TestCase::Fails && expected.state == TestCase::Passes)
@@ -420,7 +696,10 @@ void Test262Runner::updateTestExpectations()
}
QTemporaryFile updatedExpectations;
- updatedExpectations.open();
+ if (!updatedExpectations.open()) {
+ qFatal("Could not open temporary TestExpectations file: %s",
+ qPrintable(updatedExpectations.errorString()));
+ }
while (!file.atEnd()) {
QByteArray originalLine = file.readLine();
@@ -458,9 +737,12 @@ void Test262Runner::writeTestExpectations()
QFile file(expectationsFile);
QTemporaryFile expectations;
- expectations.open();
+ if (!expectations.open()) {
+ qFatal("Could not open temporary TestExpectations file: %s",
+ qPrintable(expectations.errorString()));
+ }
- for (auto c : std::as_const(testCases)) {
+ for (const auto &c : std::as_const(testCases)) {
TestExpectationLine line = TestExpectationLine::fromTestCase(c);
expectations.write(line.toLine());
}
@@ -474,175 +756,50 @@ void Test262Runner::writeTestExpectations()
qWarning() << "Could not write new TestExpectations file at" << expectationsFile;
}
-static TestCase::Result executeTest(const QByteArray &data, bool runAsModule = false,
- const QString &testCasePath = QString(),
- const QByteArray &harnessForModules = QByteArray())
+void Test262Runner::runAsExternalTests()
{
- QString testData = QString::fromUtf8(data.constData(), data.size());
-
- QV4::ExecutionEngine vm;
-
- QV4::Scope scope(&vm);
-
- QV4::GlobalExtensions::init(vm.globalObject, QJSEngine::ConsoleExtension | QJSEngine::GarbageCollectionExtension);
- QV4::initD262(&vm);
-
- if (runAsModule) {
- const QUrl rootModuleUrl = QUrl::fromLocalFile(testCasePath);
- // inject all modules with the harness
- QVector<QUrl> modulesToLoad = { rootModuleUrl };
- while (!modulesToLoad.isEmpty()) {
- QUrl url = modulesToLoad.takeFirst();
- QQmlRefPointer<QV4::ExecutableCompilationUnit> module;
-
- QFile f(url.toLocalFile());
- if (f.open(QIODevice::ReadOnly)) {
- QByteArray content = harnessForModules + f.readAll();
- module = vm.compileModule(url.toString(), QString::fromUtf8(content.constData(), content.size()), QFileInfo(f).lastModified());
- if (vm.hasException)
- break;
- vm.injectCompiledModule(module);
- } else {
- vm.throwError(QStringLiteral("Could not load module"));
- break;
+ for (TestData &testData : tasks) {
+ auto runTest = [&] (const char *header, TestCase::Result *result) {
+ QTemporaryFile tempFile;
+ if (!tempFile.open()) {
+ qFatal("Could not open temporary test data file: %s",
+ qPrintable(tempFile.errorString()));
}
-
- for (const QString &request: module->moduleRequests()) {
- const QUrl absoluteRequest = module->finalUrl().resolved(QUrl(request));
- const auto module = vm.moduleForUrl(absoluteRequest);
- if (module.native == nullptr && module.compiled == nullptr)
- modulesToLoad << absoluteRequest;
+ tempFile.write(header);
+ tempFile.write(testData.content);
+ tempFile.close();
+
+ QProcess process;
+ process.start(command, QStringList(tempFile.fileName()));
+ if (!process.waitForFinished(-1) || process.error() == QProcess::FailedToStart) {
+ qWarning() << "Could not execute" << command;
+ *result = TestCase::Result(TestCase::Crashes);
}
- }
-
- if (!vm.hasException) {
- const auto rootModule = vm.loadModule(rootModuleUrl);
- if (rootModule.compiled && rootModule.compiled->instantiate(&vm))
- rootModule.compiled->evaluate();
- }
- } else {
- QV4::ScopedContext ctx(scope, vm.rootContext());
-
- QV4::Script script(ctx, QV4::Compiler::ContextType::Global, testData);
- script.parse();
-
- if (!vm.hasException)
- script.run();
- }
-
- if (vm.hasException) {
- QV4::Scope scope(&vm);
- QV4::ScopedValue val(scope, vm.catchException());
- return TestCase::Result(TestCase::Fails, val->toQString());
- }
- return TestCase::Result(TestCase::Passes);
-}
-
-class SingleTest : public QRunnable
-{
-public:
- SingleTest(Test262Runner *runner, const TestData &data)
- : runner(runner), data(data)
- {
- command = runner->command;
- }
- void run() override;
-
- void runExternalTest();
-
- QString command;
- Test262Runner *runner;
- TestData data;
-};
-
-void SingleTest::run()
-{
- if (!command.isEmpty()) {
- runExternalTest();
- return;
- }
-
- if (data.runInSloppyMode) {
- TestCase::Result ok = ::executeTest(data.content);
- if (data.negative)
- ok.negateResult();
-
- data.sloppyResult = ok;
- } else {
- data.sloppyResult = TestCase::Result(TestCase::Skipped);
- }
- if (data.runInStrictMode) {
- const QString testCasePath = QFileInfo(runner->testDir + "/test/" + data.test).absoluteFilePath();
- QByteArray c = "'use strict';\n" + data.content;
- TestCase::Result ok = ::executeTest(c, data.runAsModuleCode, testCasePath, data.harness);
- if (data.negative)
- ok.negateResult();
-
- data.strictResult = ok;
- } else {
- data.strictResult = TestCase::Result(TestCase::Skipped);
- }
- runner->addResult(data);
-}
-
-void SingleTest::runExternalTest()
-{
- auto runTest = [this] (const char *header, TestCase::Result *result) {
- QTemporaryFile tempFile;
- tempFile.open();
- tempFile.write(header);
- tempFile.write(data.content);
- tempFile.close();
-
- QProcess process;
-// if (flags & Verbose)
-// process.setReadChannelMode(QProcess::ForwardedChannels);
-
- process.start(command, QStringList(tempFile.fileName()));
- if (!process.waitForFinished(-1) || process.error() == QProcess::FailedToStart) {
- qWarning() << "Could not execute" << command;
- *result = TestCase::Result(TestCase::Crashes);
- }
- if (process.exitStatus() != QProcess::NormalExit) {
- *result = TestCase::Result(TestCase::Crashes);
- }
- bool ok = (process.exitCode() == EXIT_SUCCESS);
- if (data.negative)
- ok = !ok;
- *result = ok ? TestCase::Result(TestCase::Passes)
- : TestCase::Result(TestCase::Fails, process.readAllStandardError());
- };
-
- if (data.runInSloppyMode)
- runTest("", &data.sloppyResult);
- if (data.runInStrictMode)
- runTest("'use strict';\n", &data.strictResult);
-
- runner->addResult(data);
-}
-
-int Test262Runner::runSingleTest(TestCase testCase)
-{
- TestData data = getTestData(testCase);
-// qDebug() << "starting test" << data.test;
+ if (process.exitStatus() != QProcess::NormalExit) {
+ *result = TestCase::Result(TestCase::Crashes);
+ }
+ bool ok = (process.exitCode() == EXIT_SUCCESS);
+ if (testData.negative)
+ ok = !ok;
+ *result = ok ? TestCase::Result(TestCase::Passes)
+ : TestCase::Result(TestCase::Fails, process.readAllStandardError());
+ };
- if (data.isExcluded || data.async)
- return 0;
+ if (testData.runInSloppyMode)
+ runTest("", &testData.sloppyResult);
+ if (testData.runInStrictMode)
+ runTest("'use strict';\n", &testData.strictResult);
- if (threadPool) {
- SingleTest *test = new SingleTest(this, data);
- threadPool->start(test);
- return 0;
+ addResult(testData);
}
- SingleTest test(this, data);
- test.run();
- return 0;
}
void Test262Runner::addResult(TestCase result)
{
{
+#if !QT_CONFIG(process)
QMutexLocker locker(&mutex);
+#endif
Q_ASSERT(result.strictExpectation.state == testCases[result.test].strictExpectation.state);
Q_ASSERT(result.sloppyExpectation.state == testCases[result.test].sloppyExpectation.state);
testCases[result.test] = result;
@@ -847,3 +1004,5 @@ QByteArray Test262Runner::harness(const QByteArray &name)
harnessFiles.insert(name, content);
return content;
}
+
+QT_END_NAMESPACE
diff --git a/tests/auto/qml/ecmascripttests/qjstest/test262runner.h b/tests/auto/qml/ecmascripttests/test262runner.h
index e2bf26296f..a989ac5188 100644
--- a/tests/auto/qml/ecmascripttests/qjstest/test262runner.h
+++ b/tests/auto/qml/ecmascripttests/test262runner.h
@@ -1,14 +1,24 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#ifndef TEST262RUNNER_H
#define TEST262RUNNER_H
-#include <qstring.h>
-#include <qstringlist.h>
-#include <qset.h>
+
+#include <qeventloop.h>
#include <qmap.h>
#include <qmutex.h>
+#include <qprocess.h>
+#include <qqueue.h>
+#include <qset.h>
#include <qthreadpool.h>
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+struct ExecutionEngine;
+void initD262(ExecutionEngine *e);
+}
+
struct TestCase {
TestCase() = default;
TestCase(const QString &test)
@@ -40,16 +50,18 @@ struct TestCase {
}
};
- bool skipTestCase = false;
Result strictExpectation = Result(Passes);
Result sloppyExpectation = Result(Passes);
Result strictResult = Result(Skipped);
Result sloppyResult = Result(Skipped);
+ bool skipTestCase = false;
+ bool stillNeedStrictRun = false;
QString test;
};
struct TestData : TestCase {
+ TestData() = default;
TestData(const TestCase &testCase)
: TestCase(testCase) {}
// flags
@@ -67,8 +79,12 @@ struct TestData : TestCase {
QByteArray content;
};
-class Test262Runner
+class SingleTest;
+
+class Test262Runner : public QObject
{
+ Q_OBJECT
+
public:
Test262Runner(const QString &command, const QString &testDir, const QString &expectationsFile);
~Test262Runner();
@@ -95,6 +111,12 @@ public:
bool run();
bool report();
+ QString testDirectory() const { return testDir; }
+
+ static void executeTest(QV4::ExecutionEngine &vm, const QString &testData,
+ const QString &testCasePath = QString(),
+ const QString &harnessForModules = QString(),
+ bool runAsModule = false);
private:
friend class SingleTest;
@@ -102,7 +124,16 @@ private:
void loadTestExpectations();
void updateTestExpectations();
void writeTestExpectations();
- int runSingleTest(TestCase testCase);
+
+ void runWithThreadPool();
+
+ void runAsExternalTests();
+ void createProcesses();
+ void assignTaskOrTerminate(int processIndex);
+ void assignSloppy(int processIndex);
+ void assignStrict(int processIndex);
+ void sendDone(int processIndex);
+ QString readUntilNull(QProcess &p);
TestData getTestData(const TestCase &testCase);
void parseYaml(const QByteArray &content, TestData *data);
@@ -116,14 +147,21 @@ private:
QString expectationsFile;
int flags = 0;
- QMutex mutex;
QString filter;
QMap<QString, TestCase> testCases;
QHash<QByteArray, QByteArray> harnessFiles;
QThreadPool *threadPool = nullptr;
+ QMutex mutex;
+
+ QEventLoop loop;
+ std::vector<std::unique_ptr<QProcess>> processes;
+ int runningCount = 0;
+ QQueue<TestData> tasks;
+ QHash<int, TestData> currentTasks;
};
+QT_END_NAMESPACE
#endif
diff --git a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
index 03c5b18474..11d724f795 100644
--- a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
+++ b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
@@ -1,11 +1,22 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-#include <QtTest/QtTest>
-#include <QProcess>
+#include <QFileInfo>
+#include <QJSEngine>
+#include <QJsonDocument>
+#include <QJsonObject>
#include <QLibraryInfo>
-#include <qjstest/test262runner.h>
+#include <QProcess>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtTest/QtTest>
+
+#include "test262runner.h"
+#include "private/qqmlbuiltinfunctions_p.h"
+#include "private/qv4arraybuffer_p.h"
+#include "private/qv4globalobject_p.h"
+#include "private/qv4script_p.h"
+
+#include <stdio.h>
class tst_EcmaScriptTests : public QQmlDataTest
{
@@ -40,7 +51,7 @@ static inline bool isNoise(QByteArrayView name)
#ifdef QT_V4_WANT_ES262_WARNINGS
return false;
#else
- const QByteArrayView noisy("qt.qml.compiler");
+ const QByteArrayView noisy("qt.qml.usedbeforedeclared");
return name.startsWith(noisy) && (name.size() <= noisy.size() || name[noisy.size()] == '.');
#endif
}
@@ -59,7 +70,7 @@ void tst_EcmaScriptTests::filterCategories(QLoggingCategory *category)
void tst_EcmaScriptTests::initTestCase()
{
QQmlDataTest::initTestCase();
- /* Suppress lcQmlCompiler's "qt.qml.compiler" warnings; we aren't in a
+ /* Suppress lcQmlCompiler's "qt.qml.usedbeforedeclared" warnings; we aren't in a
position to fix test262's many warnings and they flood messages so we
didn't get to see actual failures unless we passed -maxwarnings with a
huge value on the command-line (resulting in huge log output).
@@ -94,7 +105,74 @@ void tst_EcmaScriptTests::runJitted()
QVERIFY(result);
}
-QTEST_GUILESS_MAIN(tst_EcmaScriptTests)
+//// v RUNNER PROCESS MODE v ////
-#include "tst_ecmascripttests.moc"
+void readInput(bool &done, QString &mode, QString &testData, QString &testCasePath,
+ QString &harnessForModules, bool &runAsModule)
+{
+ QTextStream in(stdin);
+ QString input;
+ while (input.isEmpty())
+ input = in.readLine();
+
+ QJsonDocument json = QJsonDocument::fromJson(input.toUtf8());
+ done = json["done"].toBool(false);
+ mode = json["mode"].toString();
+ testData = json["testData"].toString();
+ testCasePath = json["testCasePath"].toString();
+ harnessForModules = json["harnessForModules"].toString();
+ runAsModule = json["runAsModule"].toBool(false);
+}
+
+void printResult(QV4::ExecutionEngine &vm, const QString &mode)
+{
+ QJsonObject result;
+ result.insert("mode", mode);
+ if (vm.hasException) {
+ QV4::Scope scope(&vm);
+ QV4::ScopedValue val(scope, vm.catchException());
+
+ result.insert("resultState", int(TestCase::State::Fails));
+ result.insert("resultErrorMessage", val->toQString());
+ } else {
+ result.insert("resultState", int(TestCase::State::Passes));
+ }
+ QTextStream(stdout) << QJsonDocument(result).toJson(QJsonDocument::Compact) << "\r\n";
+}
+
+void doRunnerProcess()
+{
+ bool done = false;
+ QString mode;
+ QString testData;
+ QString testCasePath;
+ QString harnessForModules;
+ bool runAsModule = false;
+
+ while (!done) {
+ QV4::ExecutionEngine vm;
+ readInput(done, mode, testData, testCasePath, harnessForModules, runAsModule);
+ if (done)
+ break;
+ Test262Runner::executeTest(vm, testData, testCasePath, harnessForModules, runAsModule);
+ printResult(vm, mode);
+ }
+}
+
+//// ^ RUNNER PROCESS MODE ^ ////
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ if (qEnvironmentVariableIntValue("runnerProcess") == 1) {
+ doRunnerProcess();
+ } else {
+ tst_EcmaScriptTests tc;
+ QTEST_SET_MAIN_SOURCE_PATH
+ return QTest::qExec(&tc, argc, argv);
+ }
+}
+
+#include "tst_ecmascripttests.moc"
diff --git a/tests/auto/qml/linebylinelex/BLACKLIST b/tests/auto/qml/linebylinelex/BLACKLIST
deleted file mode 100644
index 0fd7f604e3..0000000000
--- a/tests/auto/qml/linebylinelex/BLACKLIST
+++ /dev/null
@@ -1,5 +0,0 @@
-# QTBUG-105697
-[testFormatter]
-android
-[testLineByLineLex]
-android
diff --git a/tests/auto/qml/linebylinelex/CMakeLists.txt b/tests/auto/qml/linebylinelex/CMakeLists.txt
index 868d13d7a7..92d956a972 100644
--- a/tests/auto/qml/linebylinelex/CMakeLists.txt
+++ b/tests/auto/qml/linebylinelex/CMakeLists.txt
@@ -2,14 +2,20 @@
## tst_linebylinelex Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_linebylinelex LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect linebyline test data
file(GLOB_RECURSE test_data_glob
- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
- linebylinelex/data/*)
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ data/*)
# Collect qmlformat test data
file(GLOB_RECURSE test_data_glob2
- RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/..
- qmlformat/data/*)
+ RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+ ../qmlformat/data/*)
list(APPEND test_data ${test_data_glob} ${test_data_glob2})
qt_internal_add_test(tst_linebylinelex
@@ -19,17 +25,5 @@ qt_internal_add_test(tst_linebylinelex
Qt::Qml
Qt::QuickTestUtilsPrivate
TESTDATA ${test_data}
-)
-
-## Scopes:
-#####################################################################
-
-qt_internal_extend_target(tst_linebylinelex CONDITION ANDROID OR IOS
- DEFINES
- QT_QMLTEST_DATADIR=":/"
-)
-
-qt_internal_extend_target(tst_linebylinelex CONDITION NOT ANDROID AND NOT IOS
- DEFINES
- QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/.."
+ BUILTIN_TESTDATA
)
diff --git a/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp b/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp
index 02ce1f33f3..040ccfa9a6 100644
--- a/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp
+++ b/tests/auto/qml/linebylinelex/tst_linebylinelex.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -13,7 +13,7 @@ QT_USE_NAMESPACE
using namespace Qt::StringLiterals;
using namespace QQmlJS;
-class TestLineByLineLex : public QQmlDataTest
+class TestLineByLineLex : public QObject
{
Q_OBJECT
@@ -21,7 +21,7 @@ public:
TestLineByLineLex();
private Q_SLOTS:
- void initTestCase() override;
+ void initTestCase();
void testLineByLineLex_data();
void testLineByLineLex();
@@ -34,17 +34,14 @@ private:
QString m_qmljsrootgenPath;
QString m_qmltyperegistrarPath;
- QString m_baseDir;
};
TestLineByLineLex::TestLineByLineLex()
- : QQmlDataTest(QT_QMLTEST_DATADIR), m_baseDir(QString::fromLocal8Bit(QT_QMLTEST_DATADIR))
{
}
void TestLineByLineLex::initTestCase()
{
- QQmlDataTest::initTestCase();
}
void TestLineByLineLex::testLineByLineLex_data()
@@ -59,22 +56,18 @@ void TestLineByLineLex::testLineByLineLex()
{
QFETCH(QString, filename);
- QString filePath = m_baseDir + u"/linebylinelex/data/"_s + filename;
+ QString filePath = QFINDTESTDATA("data/" + filename);
runLex(filePath);
}
void TestLineByLineLex::testFormatter_data()
{
QTest::addColumn<QString>("filename");
- QDir formatData(m_baseDir + u"/qmlformat/data"_s);
- bool hasTestData = false; // ### TODO: fix test to always have data
+ QDir formatData(QFINDTESTDATA("qmlformat/data"));
for (const QFileInfo &fInfo :
formatData.entryInfoList(QStringList({ u"*.qml"_s, u"*.js"_s }), QDir::Files)) {
QTest::newRow(qPrintable(fInfo.fileName())) << fInfo.absoluteFilePath();
- hasTestData = true;
}
- if (!hasTestData)
- QSKIP("No test data found!");
}
void TestLineByLineLex::testFormatter()
diff --git a/tests/auto/qml/parserstress/CMakeLists.txt b/tests/auto/qml/parserstress/CMakeLists.txt
index 876e8e30ee..5a2751504b 100644
--- a/tests/auto/qml/parserstress/CMakeLists.txt
+++ b/tests/auto/qml/parserstress/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_parserstress Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_parserstress LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/parserstress/tst_parserstress.cpp b/tests/auto/qml/parserstress/tst_parserstress.cpp
index 99af0247a8..a881d12294 100644
--- a/tests/auto/qml/parserstress/tst_parserstress.cpp
+++ b/tests/auto/qml/parserstress/tst_parserstress.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -41,9 +41,9 @@ QFileInfoList tst_parserstress::findJSFiles(const QDir &d)
rv << fileInfo;
}
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ const QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
+ for (const QString &dir : dirs) {
QDir sub = d;
sub.cd(dir);
rv << findJSFiles(sub);
diff --git a/tests/auto/qml/qjsengine/CMakeLists.txt b/tests/auto/qml/qjsengine/CMakeLists.txt
index 84c738c34f..452eafa3ad 100644
--- a/tests/auto/qml/qjsengine/CMakeLists.txt
+++ b/tests/auto/qml/qjsengine/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsengine Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsengine LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -28,6 +34,7 @@ qt_internal_add_test(tst_qjsengine
Qt::GuiPrivate
Qt::Qml
Qt::QmlPrivate
+ Qt::QuickTestUtilsPrivate
LIBRARIES # special case
Threads::Threads # special case
TESTDATA ${test_data} "dummy_imports.qml"
diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
index 21f4ff033b..7bf3b34f86 100644
--- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp
+++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -17,6 +17,9 @@
#include <QScopeGuard>
#include <QUrl>
#include <QModelIndex>
+#include <QtQml/qqmllist.h>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <private/qv4functionobject_p.h>
#ifdef Q_CC_MSVC
#define NO_INLINE __declspec(noinline)
@@ -107,6 +110,8 @@ private slots:
void collectGarbageNestedWrappersTwoEngines();
void gcWithNestedDataStructure();
void stacktrace();
+ void unshiftAndSort();
+ void unshiftAndPushAndSort();
void numberParsing_data();
void numberParsing();
void automaticSemicolonInsertion();
@@ -136,7 +141,10 @@ private slots:
void reentrancy_Array();
void reentrancy_objectCreation();
void jsIncDecNonObjectProperty();
- void JSONparse();
+ void JSON_Parse();
+ void JSON_Stringify_data();
+ void JSON_Stringify();
+ void JSON_Stringify_WithReplacer_QTBUG_95324();
void arraySort();
void lookupOnDisappearingProperty();
void arrayConcat();
@@ -290,6 +298,8 @@ private slots:
void staticInNestedClasses();
void callElement();
+ void functionCtorGeneratedCUIsNotCollectedByGc();
+
void tdzViolations_data();
void tdzViolations();
@@ -301,6 +311,15 @@ private slots:
void callWithSpreadOnElement();
void spreadNoOverflow();
+ void symbolToVariant();
+
+ void garbageCollectedObjectMethodBase();
+
+ void optionalChainWithElementLookup();
+
+ void deleteDefineCycle();
+ void deleteFromSparseArray();
+
public:
Q_INVOKABLE QJSValue throwingCppMethod1();
Q_INVOKABLE void throwingCppMethod2();
@@ -377,7 +396,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithArgumentsCalled(QString, QString, QString)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithArgumentsCalled(QString,QString,QString)));
eng.evaluate("dummy.slotToCall('arg', 'arg2');");
QCOMPARE(spy.size(), 1);
@@ -388,7 +407,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithArgumentsCalled(QString, QString, QString)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithArgumentsCalled(QString,QString,QString)));
eng.evaluate("dummy.slotToCall('arg', 'arg2', 'arg3');");
QCOMPARE(spy.size(), 1);
@@ -399,7 +418,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithOverloadedArgumentsCalled(QString, Qt::KeyboardModifier, Qt::KeyboardModifiers)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithOverloadedArgumentsCalled(QString,Qt::KeyboardModifier,Qt::KeyboardModifiers)));
eng.evaluate(QStringLiteral("dummy.slotToCall('arg', %1);").arg(QString::number(Qt::ControlModifier)));
QCOMPARE(spy.size(), 1);
@@ -411,7 +430,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithTwoOverloadedArgumentsCalled(QString, Qt::KeyboardModifiers, Qt::KeyboardModifier)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithTwoOverloadedArgumentsCalled(QString,Qt::KeyboardModifiers,Qt::KeyboardModifier)));
QJSValue v = eng.evaluate(QStringLiteral("dummy.slotToCallTwoDefault('arg', %1);").arg(QString::number(Qt::MetaModifier | Qt::KeypadModifier)));
QCOMPARE(spy.size(), 1);
@@ -432,7 +451,7 @@ void tst_QJSEngine::callQObjectSlot()
eng.globalObject().setProperty(QStringLiteral("Qt"), value);
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithOverloadedArgumentsCalled(QString, Qt::KeyboardModifier, Qt::KeyboardModifiers)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithOverloadedArgumentsCalled(QString,Qt::KeyboardModifier,Qt::KeyboardModifiers)));
QJSValue v = eng.evaluate(QStringLiteral("dummy.slotToCall('arg', Qt.ControlModifier);"));
QCOMPARE(spy.size(), 1);
@@ -443,7 +462,7 @@ void tst_QJSEngine::callQObjectSlot()
}
{
- QSignalSpy spy(&dummy, SIGNAL(slotWithTwoOverloadedArgumentsCalled(QString, Qt::KeyboardModifiers, Qt::KeyboardModifier)));
+ QSignalSpy spy(&dummy, SIGNAL(slotWithTwoOverloadedArgumentsCalled(QString,Qt::KeyboardModifiers,Qt::KeyboardModifier)));
QJSValue v = eng.evaluate(QStringLiteral("dummy.slotToCallTwoDefault('arg', Qt.MetaModifier | Qt.KeypadModifier);"));
QCOMPARE(spy.size(), 1);
@@ -905,7 +924,7 @@ void tst_QJSEngine::newQObjectRace()
{
int newObjectCount = 1000;
#if defined(Q_OS_QNX)
- newObjectCount = 256;
+ newObjectCount = 128;
#endif
for (int i=0;i<newObjectCount;++i)
{
@@ -932,7 +951,7 @@ void tst_QJSEngine::newQObject_ownership()
{
QJSValue v = eng.newQObject(ptr);
}
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
QVERIFY(ptr.isNull());
@@ -944,16 +963,16 @@ void tst_QJSEngine::newQObject_ownership()
QJSValue v = eng.newQObject(ptr);
}
QObject *before = ptr;
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
QCOMPARE(ptr.data(), before);
delete ptr;
}
{
- QObject *parent = new QObject();
- QObject *child = new QObject(parent);
+ std::unique_ptr<QObject> parent = std::make_unique<QObject>();
+ QObject *child = new QObject(parent.get());
QJSValue v = eng.newQObject(child);
QCOMPARE(v.toQObject(), child);
- delete parent;
+ parent.reset();
QCOMPARE(v.toQObject(), (QObject *)nullptr);
}
{
@@ -962,23 +981,22 @@ void tst_QJSEngine::newQObject_ownership()
{
QJSValue v = eng.newQObject(ptr);
}
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
// no parent, so it should be like ScriptOwnership
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
QVERIFY(ptr.isNull());
}
{
- QObject *parent = new QObject();
- QPointer<QObject> child = new QObject(parent);
+ std::unique_ptr<QObject> parent = std::make_unique<QObject>();
+ QPointer<QObject> child = new QObject(parent.get());
QVERIFY(child != nullptr);
{
QJSValue v = eng.newQObject(child);
}
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
// has parent, so it should be like QtOwnership
QVERIFY(child != nullptr);
- delete parent;
}
{
QPointer<QObject> ptr = new QObject();
@@ -987,7 +1005,7 @@ void tst_QJSEngine::newQObject_ownership()
QQmlEngine::setObjectOwnership(ptr.data(), QQmlEngine::CppOwnership);
QJSValue v = eng.newQObject(ptr);
}
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
QVERIFY(!ptr.isNull());
@@ -1038,6 +1056,17 @@ private:
int m_called = 1;
};
+class TestQMetaObject2 : public QObject
+{
+ Q_OBJECT
+public:
+ Q_INVOKABLE TestQMetaObject2(int a) : m_called(a) {}
+ int called() const { return m_called; }
+
+private:
+ int m_called = 1;
+};
+
void tst_QJSEngine::newQObjectPropertyCache()
{
QScopedPointer<QObject> obj(new QObject);
@@ -1113,6 +1142,18 @@ void tst_QJSEngine::newQMetaObject() {
QCOMPARE(metaObject.property("C").toInt(), 2);
}
+ {
+ QJSEngine engine;
+ const QJSValue metaObject = engine.newQMetaObject(&TestQMetaObject2::staticMetaObject);
+ engine.globalObject().setProperty("Example"_L1, metaObject);
+
+ const QJSValue invalid = engine.evaluate("new Example()"_L1);
+ QVERIFY(invalid.isError());
+ QCOMPARE(invalid.toString(), "Error: Insufficient arguments"_L1);
+
+ const QJSValue valid = engine.evaluate("new Example(123)"_L1);
+ QCOMPARE(qjsvalue_cast<TestQMetaObject2 *>(valid)->called(), 123);
+ }
}
void tst_QJSEngine::exceptionInSlot()
@@ -1642,6 +1683,8 @@ void tst_QJSEngine::valueConversion_basic()
QCOMPARE(eng.fromScriptValue<unsigned short>(num), (unsigned short)(123));
QCOMPARE(eng.fromScriptValue<float>(num), float(123));
QCOMPARE(eng.fromScriptValue<double>(num), double(123));
+ QCOMPARE(eng.fromScriptValue<long>(num), long(123));
+ QCOMPARE(eng.fromScriptValue<ulong>(num), ulong(123));
QCOMPARE(eng.fromScriptValue<qlonglong>(num), qlonglong(123));
QCOMPARE(eng.fromScriptValue<qulonglong>(num), qulonglong(123));
}
@@ -1653,6 +1696,8 @@ void tst_QJSEngine::valueConversion_basic()
QCOMPARE(eng.fromScriptValue<unsigned short>(num), (unsigned short)(123));
QCOMPARE(eng.fromScriptValue<float>(num), float(123));
QCOMPARE(eng.fromScriptValue<double>(num), double(123));
+ QCOMPARE(eng.fromScriptValue<long>(num), long(123));
+ QCOMPARE(eng.fromScriptValue<ulong>(num), ulong(123));
QCOMPARE(eng.fromScriptValue<qlonglong>(num), qlonglong(123));
QCOMPARE(eng.fromScriptValue<qulonglong>(num), qulonglong(123));
}
@@ -1672,11 +1717,20 @@ void tst_QJSEngine::valueConversion_basic()
QCOMPARE(eng.fromScriptValue<QChar>(eng.toScriptValue(c)), c);
}
+ {
+ QList<QObject *> list = {this};
+ QQmlListProperty<QObject> prop(this, &list);
+ QJSValue jsVal = eng.toScriptValue(prop);
+ QCOMPARE(eng.fromScriptValue<QQmlListProperty<QObject>>(jsVal), prop);
+ }
+
QVERIFY(eng.toScriptValue(static_cast<void *>(nullptr)).isNull());
}
void tst_QJSEngine::valueConversion_QVariant()
{
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
QJSEngine eng;
// qScriptValueFromValue() should be "smart" when the argument is a QVariant
{
@@ -1686,6 +1740,8 @@ void tst_QJSEngine::valueConversion_QVariant()
}
// Checking nested QVariants
{
+ // ### Qt 7: QVariant nesting is evil; we should check if we can get rid of it
+ // main use case for it was QSignalSpy
QVariant tmp1;
QVariant tmp2(QMetaType::fromType<QVariant>(), &tmp1);
QCOMPARE(QMetaType::Type(tmp2.userType()), QMetaType::QVariant);
@@ -1764,6 +1820,7 @@ void tst_QJSEngine::valueConversion_QVariant()
QVERIFY(val.isObject());
QCOMPARE(val.property(42).toString(), map.value(QStringLiteral("42")).toString());
}
+ QT_WARNING_POP
}
void tst_QJSEngine::valueConversion_basic2()
@@ -1884,7 +1941,7 @@ void tst_QJSEngine::collectGarbage()
QPointer<QObject> ptr = new QObject();
QVERIFY(ptr != nullptr);
(void)eng.newQObject(ptr);
- eng.collectGarbage();
+ gc(*eng.handle(), GCFlags::DontSendPostedEvents);
if (ptr)
QGuiApplication::sendPostedEvents(ptr, QEvent::DeferredDelete);
QVERIFY(ptr.isNull());
@@ -1919,8 +1976,8 @@ void tst_QJSEngine::collectGarbageNestedWrappersTwoEngines()
QCOMPARE(engine1.evaluate("foobar.dummy.baz").toInt(), 42);
QCOMPARE(engine2.evaluate("foobar.dummy.baz").toInt(), 43);
- engine1.collectGarbage();
- engine2.collectGarbage();
+ gc(*engine1.handle());
+ gc(*engine2.handle());
// The GC should not collect dummy object wrappers neither in engine1 nor engine2, we
// verify that by checking whether the baz property still has its previous value.
@@ -2058,6 +2115,81 @@ void tst_QJSEngine::stacktrace()
}
}
+void tst_QJSEngine::unshiftAndSort()
+{
+ QJSEngine engine;
+ QJSValue func = engine.evaluate(R"""(
+ (function (objectArr, currIdx) {
+ objectArr.unshift({"sortIndex": currIdx});
+ objectArr.sort(function(a, b) {
+ if (a.sortIndex > b.sortIndex)
+ return 1;
+ if (a.sortIndex < b.sortIndex)
+ return -1;
+ return 0;
+ });
+ return objectArr;
+ })
+ )""");
+ QVERIFY(func.isCallable());
+ QJSValue objectArr = engine.newArray();
+
+ for (int i = 0; i < 5; ++i) {
+ objectArr = func.call({objectArr, i});
+ QVERIFY2(!objectArr.isError(), qPrintable(objectArr.toString()));
+ const int length = objectArr.property("length").toInt();
+
+ // It did add one element
+ QCOMPARE(length, i + 1);
+
+ for (int x = 0; x < length; ++x) {
+ // We didn't sort cruft into the array.
+ QVERIFY(!objectArr.property(x).isUndefined());
+
+ // The array is actually sorted.
+ QCOMPARE(objectArr.property(x).property("sortIndex").toInt(), x);
+ }
+ }
+}
+
+void tst_QJSEngine::unshiftAndPushAndSort()
+{
+ QJSEngine engine;
+ QJSValue func = engine.evaluate(R"""(
+ (function (objectArr, currIdx) {
+ objectArr.unshift({"sortIndex": currIdx});
+ objectArr.push({"sortIndex": currIdx + 1});
+ objectArr.sort(function(a, b) {
+ if (a.sortIndex > b.sortIndex)
+ return 1;
+ if (a.sortIndex < b.sortIndex)
+ return -1;
+ return 0;
+ });
+ return objectArr;
+ })
+ )""");
+ QVERIFY(func.isCallable());
+ QJSValue objectArr = engine.newArray();
+
+ for (int i = 0; i < 20; i += 2) {
+ objectArr = func.call({objectArr, i});
+ QVERIFY2(!objectArr.isError(), qPrintable(objectArr.toString()));
+ const int length = objectArr.property("length").toInt();
+
+ // It did add 2 elements
+ QCOMPARE(length, i + 2);
+
+ for (int x = 0; x < length; ++x) {
+ // We didn't sort cruft into the array.
+ QVERIFY(!objectArr.property(x).isUndefined());
+
+ // The array is actually sorted.
+ QCOMPARE(objectArr.property(x).property("sortIndex").toInt(), x);
+ }
+ }
+}
+
void tst_QJSEngine::numberParsing_data()
{
QTest::addColumn<QString>("string");
@@ -3305,13 +3437,65 @@ void tst_QJSEngine::jsIncDecNonObjectProperty()
}
}
-void tst_QJSEngine::JSONparse()
+void tst_QJSEngine::JSON_Parse()
{
QJSEngine eng;
QJSValue ret = eng.evaluate("var json=\"{\\\"1\\\": null}\"; JSON.parse(json);");
QVERIFY(ret.isObject());
}
+void tst_QJSEngine::JSON_Stringify_data()
+{
+ QTest::addColumn<QString>("object");
+ QTest::addColumn<QString>("json");
+
+ // Basic "smoke" test. More tests are provided by test262 suite.
+ // Don't test with multiple key-value pairs on the same level,
+ // because serialization order might not be deterministic.
+ // Note: parenthesis are required, otherwise objects will be interpretted as code blocks.
+ QTest::newRow("empty") << "({})" << "{}";
+ QTest::newRow("string") << "({a: 'b'})" << "{\"a\":\"b\"}";
+ QTest::newRow("number") << "({c: 42})" << "{\"c\":42}";
+ QTest::newRow("boolean") << "({d: true})" << "{\"d\":true}";
+ QTest::newRow("key is array") << "({[[12, 34]]: 56})" << "{\"12,34\":56}";
+ QTest::newRow("value is date") << "({d: new Date('2000-01-20T12:00:00.000Z')})" << "{\"d\":\"2000-01-20T12:00:00.000Z\"}";
+}
+
+void tst_QJSEngine::JSON_Stringify()
+{
+ QFETCH(QString, object);
+ QFETCH(QString, json);
+
+ QJSEngine eng;
+
+ QJSValue obj = eng.evaluate(object);
+ QVERIFY(obj.isObject());
+
+ QJSValue func = eng.evaluate("(function(obj) { return JSON.stringify(obj); })");
+ QVERIFY(func.isCallable());
+
+ QJSValue ret = func.call(QJSValueList{obj});
+ QVERIFY(ret.isString());
+ QCOMPARE(ret.toString(), json);
+}
+
+void tst_QJSEngine::JSON_Stringify_WithReplacer_QTBUG_95324()
+{
+ QJSEngine eng;
+ QJSValue json = eng.evaluate(R"(
+ function replacer(k, v) {
+ if (this[k] instanceof Date) {
+ return Math.floor(this[k].getTime() / 1000.0);
+ }
+ return v;
+ }
+ const obj = {d: new Date('2000-01-20T12:00:00.000Z')};
+ JSON.stringify(obj, replacer);
+ )");
+ QVERIFY(json.isString());
+ QCOMPARE(json.toString(), QString::fromLatin1("{\"d\":948369600}"));
+}
+
void tst_QJSEngine::arraySort()
{
// tests that calling Array.sort with a bad sort function doesn't cause issues
@@ -3480,9 +3664,6 @@ void tst_QJSEngine::qRegularExpressionExport()
// effect at a given date (QTBUG-9770).
void tst_QJSEngine::dateRoundtripJSQtJS()
{
-#ifdef Q_OS_WIN
- QSKIP("This test fails on Windows due to a bug in QDateTime.");
-#endif
qint64 secs = QDate(2009, 1, 1).startOfDay(QTimeZone::UTC).toSecsSinceEpoch();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
@@ -3497,9 +3678,6 @@ void tst_QJSEngine::dateRoundtripJSQtJS()
void tst_QJSEngine::dateRoundtripQtJSQt()
{
-#ifdef Q_OS_WIN
- QSKIP("This test fails on Windows due to a bug in QDateTime.");
-#endif
QDateTime qtDate = QDate(2009, 1, 1).startOfDay();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
@@ -3513,9 +3691,6 @@ void tst_QJSEngine::dateRoundtripQtJSQt()
void tst_QJSEngine::dateConversionJSQt()
{
-#ifdef Q_OS_WIN
- QSKIP("This test fails on Windows due to a bug in QDateTime.");
-#endif
qint64 secs = QDate(2009, 1, 1).startOfDay(QTimeZone::UTC).toSecsSinceEpoch();
QJSEngine eng;
for (int i = 0; i < 8000; ++i) {
@@ -3740,7 +3915,7 @@ void tst_QJSEngine::prototypeChainGc()
QJSValue factory = engine.evaluate("(function() { return Object.create(Object.create({})); })");
QVERIFY(factory.isCallable());
QJSValue obj = factory.call();
- engine.collectGarbage();
+ gc(*engine.handle());
QJSValue proto = getProto.call(QJSValueList() << obj);
proto = getProto.call(QJSValueList() << proto);
@@ -3759,7 +3934,7 @@ void tst_QJSEngine::prototypeChainGc_QTBUG38299()
"delete mapping.prop1\n"
"\n");
// Don't hang!
- engine.collectGarbage();
+ gc(*engine.handle());
}
void tst_QJSEngine::dynamicProperties()
@@ -4403,6 +4578,12 @@ void tst_QJSEngine::tracing()
QTest::ignoreMessage(QtDebugMsg, "a (:1)\nb (:1)\nc (:1)\n%entry (:1)");
engine.evaluate("function a() { console.trace(); } function b() { a(); } function c() { b(); }");
engine.evaluate("c()");
+
+ QQmlTestMessageHandler messageHandler;
+ messageHandler.setIncludeCategoriesEnabled(true);
+ engine.evaluate("c()");
+ QCOMPARE(messageHandler.messageString(),
+ QLatin1String("js: a (:1)\nb (:1)\nc (:1)\n%entry (:1)"));
}
void tst_QJSEngine::asserts()
@@ -4497,7 +4678,6 @@ void tst_QJSEngine::privateMethods()
}
QVERIFY(privateMethods.contains("myPrivateMethod"));
- QVERIFY(privateMethods.contains("_q_reregisterTimers"));
privateMethods << QStringLiteral("deleteLater") << QStringLiteral("destroyed");
QJSValueIterator it(jsWrapper);
@@ -4571,7 +4751,7 @@ public:
bool called = false;
- Q_INVOKABLE void callMe(QQmlV4Function *) {
+ Q_INVOKABLE void callMe(QQmlV4FunctionPtr) {
called = true;
}
};
@@ -5749,6 +5929,38 @@ void tst_QJSEngine::callElement()
QCOMPARE(engine.evaluate(program).toString(), u"a"_s);
}
+void tst_QJSEngine::functionCtorGeneratedCUIsNotCollectedByGc()
+{
+ QJSEngine engine;
+ auto v4 = engine.handle();
+ QVERIFY(!v4->isGCOngoing);
+
+ // run gc until roots are collected
+ // we run the gc steps manually, so use "Forever" as the dealine to avoid interference
+ v4->memoryManager->gcStateMachine->deadline = QDeadlineTimer(QDeadlineTimer::Forever);
+ auto sm = v4->memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::InitMarkPersistentValues) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ const QString program = "new Function('a', 'b', 'let x = \"Hello\"; return a + b');";
+ auto sumFunc = engine.evaluate(program);
+ QVERIFY(sumFunc.isCallable());
+ auto *function = QJSValuePrivate::asManagedType<QV4::JavaScriptFunctionObject>(&sumFunc);
+ auto *cu = function->d()->function->executableCompilationUnit();
+ QVERIFY(cu->runtimeStrings); // should exist for "Hello"
+ QVERIFY(cu->runtimeStrings[0]->isMarked());
+ while (sm->state != QV4::GCState::Invalid) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ auto sum = sumFunc.call({QJSValue(12), QJSValue(13)});
+ QCOMPARE(sum.toInt(), 25);
+}
+
void tst_QJSEngine::tdzViolations_data()
{
QTest::addColumn<QString>("type");
@@ -6028,6 +6240,184 @@ void tst_QJSEngine::spreadNoOverflow()
QCOMPARE(result.errorType(), QJSValue::RangeError);
}
+void tst_QJSEngine::symbolToVariant()
+{
+ QJSEngine engine;
+ const QJSValue val = engine.newSymbol("asymbol");
+ QCOMPARE(val.toVariant(), QStringLiteral("Symbol(asymbol)"));
+
+ const QVariant retained = val.toVariant(QJSValue::RetainJSObjects);
+ QCOMPARE(retained.metaType(), QMetaType::fromType<QJSValue>());
+ QVERIFY(retained.value<QJSValue>().strictlyEquals(val));
+
+ QCOMPARE(val.toVariant(QJSValue::ConvertJSObjects), QStringLiteral("Symbol(asymbol)"));
+}
+
+class PACHelper : public QObject {
+ Q_OBJECT
+public:
+ Q_INVOKABLE bool shExpMatch(const QString &, const QString &) { return false; }
+ Q_INVOKABLE QString dnsResolve(const QString &) { return QString{}; }
+};
+
+class ProxyAutoConf {
+public:
+ void exposeQObjectMethodsAsGlobal(QJSEngine *engine, QObject *object)
+ {
+ QJSValue helper = engine->newQObject(object);
+ QJSValue g = engine->globalObject();
+ QJSValueIterator it(helper);
+ while (it.hasNext()) {
+ it.next();
+ if (!it.value().isCallable())
+ continue;
+ g.setProperty(it.name(), it.value());
+ }
+ }
+
+ bool parse(const QString & pacBytes)
+ {
+ jsFindProxyForURL = QJSValue();
+ engine = std::make_unique<QJSEngine>();
+ exposeQObjectMethodsAsGlobal(engine.get(), new PACHelper);
+ engine->evaluate(pacBytes);
+ jsFindProxyForURL = engine->globalObject().property(QStringLiteral("FindProxyForURL"));
+ return true;
+ }
+
+ QString findProxyForUrl(const QString &url, const QString &host)
+ {
+ QJSValueList args;
+ args << url << host;
+ gc(*engine->handle(), GCFlags::DontSendPostedEvents);
+ QJSValue callResult = jsFindProxyForURL.call(args);
+ return callResult.toString().trimmed();
+ }
+
+private:
+ std::unique_ptr<QJSEngine> engine;
+ QJSValue jsFindProxyForURL;
+};
+
+QString const pacstring = R"js(
+function FindProxyForURL(host) {
+ list_split_all = Array(
+ "oneoneoneoneo.oneo.oneo.oneoneo.one",
+ "twotwotwotwotw.otwo.twot.wotwotw.otw",
+ "threethreethr.eeth.reet.hreethr.eet",
+ "fourfourfourfo.urfo.urfo.urfourf.our",
+ "fivefivefivef.ivef.ivef.ivefive.fiv",
+ "sixsixsixsixsi.xsix.sixs.ixsixsi.xsi",
+ "sevensevenseve.nsev.ense.venseve.nse",
+ "eight.eighteigh.tei",
+ "*.nin.eninen.ine"
+ )
+ list_myip_direct =
+ "10.254.0.0/255.255.0.0"
+ for (i = 0; i < list_split_all.length; ++i)
+ for (j = 0; j < list_myip_direct.length; ++j)
+ shExpMatch(host, list_split_all)
+ shExpMatch()
+ dnsResolve()}
+)js";
+
+void tst_QJSEngine::garbageCollectedObjectMethodBase()
+{
+ ProxyAutoConf proxyConf;
+ bool pac_read = false;
+
+ const auto processUrl = [&](QString const &url, QString const &host)
+ {
+ if (!pac_read) {
+ proxyConf.parse(pacstring);
+ pac_read = true;
+ }
+ return proxyConf.findProxyForUrl(url, host);
+ };
+
+ const QString url = QStringLiteral("https://servername.domain.test");
+ const QString host = QStringLiteral("servername.domain.test");
+
+ for (size_t i = 0; i < 5; ++i) {
+ auto future = std::async(processUrl, url, host);
+ QCOMPARE(future.get(), QLatin1String("Error: Insufficient arguments"));
+ }
+}
+
+void tst_QJSEngine::optionalChainWithElementLookup()
+{
+ QJSEngine engine;
+
+ const QString program = R"js(
+ (function(xxx) { return xxx?.title["en"] ?? "A" })
+ )js";
+
+ QJSManagedValue func = QJSManagedValue(engine.evaluate(program), &engine);
+ QVERIFY(func.isFunction());
+
+ QCOMPARE(func.call({QJSValue::NullValue}).toString(), "A");
+ QCOMPARE(func.call({QJSValue::UndefinedValue}).toString(), "A");
+
+ const QJSValue nice
+ = engine.toScriptValue(QVariantMap { {"title", QVariantMap { {"en", "B"} } } });
+ QCOMPARE(func.call({nice}).toString(), "B");
+
+ const QJSValue naughty1
+ = engine.toScriptValue(QVariantMap { {"title", QVariantMap { {"fr", "B"} } } });
+ QCOMPARE(func.call({naughty1}).toString(), "A");
+
+ const QJSValue naughty2
+ = engine.toScriptValue(QVariantMap { {"foos", QVariantMap { {"en", "B"} } } });
+ QVERIFY(func.call({naughty2}).isUndefined());
+ QVERIFY(engine.hasError());
+ QCOMPARE(engine.catchError().toString(), "TypeError: Cannot read property 'en' of undefined");
+ QVERIFY(!engine.hasError());
+
+ QVERIFY(func.call({ QJSValue(4) }).isUndefined());
+ QVERIFY(engine.hasError());
+ QCOMPARE(engine.catchError().toString(), "TypeError: Cannot read property 'en' of undefined");
+ QVERIFY(!engine.hasError());
+}
+
+void tst_QJSEngine::deleteDefineCycle()
+{
+ QJSEngine engine;
+ QStringList stackTrace;
+
+ QJSValue result = engine.evaluate(QString::fromLatin1(R"(
+ let global = ({})
+
+ for (let j = 0; j < 1000; j++) {
+ for (let i = 0; i < 2; i++) {
+ const name = "test" + i
+ delete global[name]
+ Object.defineProperty(global, name, { get() { return 0 }, configurable: true })
+ }
+ }
+ )"), {}, 1, &stackTrace);
+ QVERIFY(stackTrace.isEmpty());
+}
+
+void tst_QJSEngine::deleteFromSparseArray()
+{
+ QJSEngine engine;
+
+ // Should not crash
+ const QJSValue result = engine.evaluate(QLatin1String(R"((function() {
+ let o = [];
+ o[10000] = 10;
+ o[20000] = 20;
+ for (let k in o)
+ delete o[k];
+ return o;
+ })())"));
+
+ QVERIFY(result.isArray());
+ QCOMPARE(result.property("length").toNumber(), 20001);
+ QVERIFY(result.property(10000).isUndefined());
+ QVERIFY(result.property(20000).isUndefined());
+}
+
QTEST_MAIN(tst_QJSEngine)
#include "tst_qjsengine.moc"
diff --git a/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt b/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt
index 7400bc5f1f..3bc5c39bf9 100644
--- a/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt
+++ b/tests/auto/qml/qjsmanagedvalue/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsmanagedvalue Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsmanagedvalue LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qjsmanagedvalue
SOURCES
tst_qjsmanagedvalue.cpp tst_qjsmanagedvalue.h
diff --git a/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp b/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp
index f11ae73a59..35f5bbadc4 100644
--- a/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp
+++ b/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qjsmanagedvalue.h"
@@ -542,7 +542,7 @@ void tst_QJSManagedValue::toVariant()
}
- // array
+ // variant list
{
auto handler = qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &, const QString &) {
if (type == QtMsgType::QtWarningMsg)
@@ -553,12 +553,10 @@ void tst_QJSManagedValue::toVariant()
QVariantList listIn;
listIn << 123 << QStringLiteral("hello");
QJSManagedValue array(eng.toManagedValue(listIn));
- QVERIFY(array.isArray());
QCOMPARE(array.property(QStringLiteral("length")).toInt(), 2);
QVariant retained = array.toVariant();
- QCOMPARE(retained.metaType(), QMetaType::fromType<QJSValue>());
- QVERIFY(QJSManagedValue(retained.value<QJSValue>(), &eng).strictlyEquals(array));
+ QCOMPARE(retained.metaType(), QMetaType::fromType<QVariantList>());
QVariantList listOut = retained.toList();
QCOMPARE(listOut.size(), listIn.size());
@@ -566,7 +564,6 @@ void tst_QJSManagedValue::toVariant()
QCOMPARE(listOut.at(i), listIn.at(i));
// round-trip conversion
QJSManagedValue array2(eng.toManagedValue(retained));
- QVERIFY(array2.isArray());
QCOMPARE(array2.property(QStringLiteral("length")).toInt(), array.property(QStringLiteral("length")).toInt());
for (int i = 0; i < array.property(QStringLiteral("length")).toInt(); ++i)
QVERIFY(array2.property(i).strictlyEquals(array.property(i)));
@@ -1525,8 +1522,6 @@ void tst_QJSManagedValue::strictlyEquals()
{
QJSManagedValue var1(eng.toManagedValue(QVariant(QStringList() << QStringLiteral("a"))));
QJSManagedValue var2(eng.toManagedValue(QVariant(QStringList() << QStringLiteral("a"))));
- QVERIFY(var1.isArray());
- QVERIFY(var2.isArray());
QVERIFY(!var1.strictlyEquals(var2));
}
{
@@ -1582,22 +1577,22 @@ void tst_QJSManagedValue::castToPointer()
void tst_QJSManagedValue::engineDeleted()
{
- QJSEngine *eng = new QJSEngine;
+ std::unique_ptr<QJSEngine> eng = std::make_unique<QJSEngine>();
QObject *temp = new QObject(); // Owned by JS engine, as newQObject() sets JS ownership explicitly
QJSManagedValue v1(eng->toManagedValue(123));
QCOMPARE(v1.type(), QJSManagedValue::Number);
QJSManagedValue v2(eng->toManagedValue(QStringLiteral("ciao")));
QCOMPARE(v2.type(), QJSManagedValue::String);
- QJSManagedValue v3(eng->newObject(), eng);
+ QJSManagedValue v3(eng->newObject(), eng.get());
QCOMPARE(v3.type(), QJSManagedValue::Object);
QVERIFY(!v3.isNull());
- QJSManagedValue v4(eng->newQObject(temp), eng);
+ QJSManagedValue v4(eng->newQObject(temp), eng.get());
QCOMPARE(v4.type(), QJSManagedValue::Object);
QVERIFY(!v4.isNull());
- QJSManagedValue v5(QStringLiteral("Hello"), eng);
+ QJSManagedValue v5(QStringLiteral("Hello"), eng.get());
QCOMPARE(v2.type(), QJSManagedValue::String);
- delete eng;
+ eng.reset();
// You can still check the type, but anything involving the engine is obviously prohibited.
QCOMPARE(v1.type(), QJSManagedValue::Undefined);
@@ -1742,7 +1737,7 @@ void tst_QJSManagedValue::stringByIndex()
const QString testString = QStringLiteral("foobar");
QJSManagedValue str(testString, &engine);
- for (uint i = 0; i < testString.size(); ++i) {
+ for (qsizetype i = 0; i < testString.size(); ++i) {
QVERIFY(str.hasOwnProperty(i));
QVERIFY(str.hasProperty(i));
diff --git a/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h b/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h
index 6f6add433e..bb5a6be3ca 100644
--- a/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h
+++ b/tests/auto/qml/qjsmanagedvalue/tst_qjsmanagedvalue.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QJSMANAGEDVALUE_H
#define TST_QJSMANAGEDVALUE_H
diff --git a/tests/auto/qml/qjsonbinding/CMakeLists.txt b/tests/auto/qml/qjsonbinding/CMakeLists.txt
index 66f3e94e4c..fa80e764ef 100644
--- a/tests/auto/qml/qjsonbinding/CMakeLists.txt
+++ b/tests/auto/qml/qjsonbinding/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsonbinding Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsonbinding LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp b/tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp
index 6235ff376d..450560833f 100644
--- a/tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp
+++ b/tests/auto/qml/qjsonbinding/tst_qjsonbinding.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQml/QtQml>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -67,7 +67,8 @@ private:
QByteArray tst_qjsonbinding::readAsUtf8(const QString &fileName)
{
QFile file(testFile(fileName));
- file.open(QIODevice::ReadOnly);
+ if (!file.open(QIODevice::ReadOnly))
+ qFatal("Cannot open file %s", qPrintable(fileName));
QTextStream stream(&file);
return stream.readAll().trimmed().toUtf8();
}
@@ -144,7 +145,11 @@ void tst_qjsonbinding::cppJsConversion()
{
QJSValue jsValue = eng.toScriptValue(jsonValue);
+#if QT_DEPRECATED_SINCE(6, 9)
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QVERIFY(!jsValue.isVariant());
+ QT_WARNING_POP
+#endif
switch (jsonValue.type()) {
case QJsonValue::Null:
QVERIFY(jsValue.isNull());
@@ -193,7 +198,6 @@ void tst_qjsonbinding::cppJsConversion()
if (jsonValue.isObject()) {
QJsonObject jsonObject = jsonValue.toObject();
QJSValue jsObject = eng.toScriptValue(jsonObject);
- QVERIFY(!jsObject.isVariant());
QVERIFY(jsObject.isObject());
QJSValue stringified = stringify.call(QJSValueList() << jsObject);
@@ -205,7 +209,6 @@ void tst_qjsonbinding::cppJsConversion()
} else if (jsonValue.isArray()) {
QJsonArray jsonArray = jsonValue.toArray();
QJSValue jsArray = eng.toScriptValue(jsonArray);
- QVERIFY(!jsArray.isVariant());
QVERIFY(jsArray.isArray());
QJSValue stringified = stringify.call(QJSValueList() << jsArray);
diff --git a/tests/auto/qml/qjsprimitivevalue/CMakeLists.txt b/tests/auto/qml/qjsprimitivevalue/CMakeLists.txt
index 18b3ee938c..c709a5aa56 100644
--- a/tests/auto/qml/qjsprimitivevalue/CMakeLists.txt
+++ b/tests/auto/qml/qjsprimitivevalue/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsprimitivevalue Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsprimitivevalue LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qjsprimitivevalue
SOURCES
tst_qjsprimitivevalue.cpp
diff --git a/tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp b/tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp
index 7609842f17..232200e633 100644
--- a/tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp
+++ b/tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/qobject.h>
#include <QtQml/qjsengine.h>
@@ -19,6 +19,7 @@ private slots:
void unaryOperators();
void toFromVariant();
+ void coercion();
void ctor_invalid();
void ctor_undefinedWithEngine();
@@ -313,25 +314,37 @@ void tst_QJSPrimitiveValue::toFromVariant()
switch (operand.type()) {
case QJSPrimitiveValue::Undefined:
QVERIFY(!var.isValid());
+ QCOMPARE(operand.metaType(), QMetaType());
+ QCOMPARE(operand.data(), nullptr);
break;
case QJSPrimitiveValue::Null:
QCOMPARE(var.typeId(), QMetaType::Nullptr);
+ QCOMPARE(operand.metaType(), QMetaType::fromType<std::nullptr_t>());
+ QCOMPARE(operand.data(), nullptr);
break;
case QJSPrimitiveValue::Boolean:
QCOMPARE(var.typeId(), QMetaType::Bool);
QCOMPARE(var.toBool(), operand.toBoolean());
+ QCOMPARE(operand.metaType(), QMetaType::fromType<bool>());
+ QCOMPARE(*static_cast<const bool *>(operand.data()), operand.toBoolean());
break;
case QJSPrimitiveValue::Integer:
QCOMPARE(var.typeId(), QMetaType::Int);
QCOMPARE(var.toInt(), operand.toInteger());
+ QCOMPARE(operand.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(*static_cast<const int *>(operand.data()), operand.toInteger());
break;
case QJSPrimitiveValue::Double:
QCOMPARE(var.typeId(), QMetaType::Double);
QCOMPARE(var.toDouble(), operand.toDouble());
+ QCOMPARE(operand.metaType(), QMetaType::fromType<double>());
+ QCOMPARE(*static_cast<const double *>(operand.data()), operand.toDouble());
break;
case QJSPrimitiveValue::String:
QCOMPARE(var.typeId(), QMetaType::QString);
QCOMPARE(var.toString(), operand.toString());
+ QCOMPARE(operand.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(*static_cast<const QString *>(operand.data()), operand.toString());
break;
}
@@ -344,6 +357,25 @@ void tst_QJSPrimitiveValue::toFromVariant()
}
}
+void tst_QJSPrimitiveValue::coercion()
+{
+ for (const QJSPrimitiveValue &operand : operands) {
+ QCOMPARE(operand.to<QJSPrimitiveValue::Undefined>(), QJSPrimitiveUndefined());
+ QCOMPARE(operand.to<QJSPrimitiveValue::Null>(), QJSPrimitiveNull());
+ QCOMPARE(operand.to<QJSPrimitiveValue::Boolean>(), operand.toBoolean());
+ QCOMPARE(operand.to<QJSPrimitiveValue::Integer>(), operand.toInteger());
+ QCOMPARE(operand.to<QJSPrimitiveValue::String>(), operand.toString());
+
+ const QJSPrimitiveValue lhs = operand.to<QJSPrimitiveValue::Double>();
+ QCOMPARE(lhs.type(), QJSPrimitiveValue::Double);
+ const double rhs = operand.toDouble();
+ if (std::isnan(rhs))
+ QVERIFY(std::isnan(lhs.toDouble()));
+ else
+ QCOMPARE(lhs.toDouble(), rhs);
+ }
+}
+
void tst_QJSPrimitiveValue::ctor_invalid()
{
QJSPrimitiveValue v;
diff --git a/tests/auto/qml/qjsvalue/CMakeLists.txt b/tests/auto/qml/qjsvalue/CMakeLists.txt
index fcd51fff44..212109c878 100644
--- a/tests/auto/qml/qjsvalue/CMakeLists.txt
+++ b/tests/auto/qml/qjsvalue/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsvalue Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsvalue LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# special case begin
# TODO: Prepare for removal, once Platform brings in Threads.
if(NOT TARGET Threads::Threads)
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
index 516abed9e8..6a10b5910d 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qjsvalue.h"
@@ -19,11 +19,6 @@ tst_QJSValue::tst_QJSValue()
{
}
-tst_QJSValue::~tst_QJSValue()
-{
- delete engine;
-}
-
void tst_QJSValue::ctor_invalid()
{
QJSEngine eng;
@@ -369,10 +364,11 @@ void tst_QJSValue::toString()
// variant should use internal valueOf(), then fall back to QVariant::toString(),
// then fall back to "QVariant(typename)"
QJSValue variant = eng.toScriptValue(QPoint(10, 20));
+ QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
QVERIFY(!variant.isVariant());
+ QT_WARNING_POP
QCOMPARE(variant.toString(), QString::fromLatin1("QPoint(10, 20)"));
variant = eng.toScriptValue(QUrl());
- QVERIFY(!variant.isVariant());
QVERIFY(variant.isUrl());
QVERIFY(variant.toString().isEmpty());
@@ -1085,13 +1081,8 @@ void tst_QJSValue::toVariant()
QVariantList listIn;
listIn << 123 << "hello";
QJSValue array = eng.toScriptValue(listIn);
- QVERIFY(array.isArray());
QCOMPARE(array.property("length").toInt(), 2);
- QVariant retained = array.toVariant(QJSValue::RetainJSObjects);
- QCOMPARE(retained.metaType(), QMetaType::fromType<QJSValue>());
- QVERIFY(retained.value<QJSValue>().strictlyEquals(array));
-
QVariant ret = array.toVariant();
QCOMPARE(ret.typeId(), QMetaType::QVariantList);
QVariantList listOut = ret.toList();
@@ -1100,7 +1091,6 @@ void tst_QJSValue::toVariant()
QCOMPARE(listOut.at(i), listIn.at(i));
// round-trip conversion
QJSValue array2 = eng.toScriptValue(ret);
- QVERIFY(array2.isArray());
QCOMPARE(array2.property("length").toInt(), array.property("length").toInt());
for (int i = 0; i < array.property("length").toInt(); ++i)
QVERIFY(array2.property(i).strictlyEquals(array.property(i)));
@@ -1124,6 +1114,25 @@ void tst_QJSValue::toVariant()
QCOMPARE(func.toVariant().metaType(), QMetaType::fromType<QJSValue>());
}
+
+ // object with custom prototype
+ {
+ QJSValue object = eng.evaluate(R"js(
+ (function(){
+ function Person(firstName, lastName) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+ return new Person("John", "Doe");
+ })();
+ )js");
+ QVERIFY(object.isObject());
+ auto asVariant = object.toVariant();
+ QCOMPARE(asVariant.metaType(), QMetaType::fromType<QVariantMap>());
+ auto variantMap = asVariant.value<QVariantMap>();
+ QVERIFY(variantMap.contains("firstName"));
+ QCOMPARE(variantMap["firstName"].toString(), "John");
+ }
}
void tst_QJSValue::toPrimitive_data()
@@ -2345,8 +2354,6 @@ void tst_QJSValue::strictlyEquals()
{
QJSValue var1 = eng.toScriptValue(QVariant(QStringList() << "a"));
QJSValue var2 = eng.toScriptValue(QVariant(QStringList() << "a"));
- QVERIFY(var1.isArray());
- QVERIFY(var2.isArray());
QVERIFY(!var1.strictlyEquals(var2));
}
{
@@ -2586,7 +2593,7 @@ void tst_QJSValue::prettyPrinter()
void tst_QJSValue::engineDeleted()
{
- QJSEngine *eng = new QJSEngine;
+ std::unique_ptr<QJSEngine> eng = std::make_unique<QJSEngine>();
QObject *temp = new QObject(); // Owned by JS engine, as newQObject() sets JS ownership explicitly
QJSValue v1 = eng->toScriptValue(123);
QVERIFY(v1.isNumber());
@@ -2599,7 +2606,7 @@ void tst_QJSValue::engineDeleted()
QJSValue v5 = "Hello";
QVERIFY(v2.isString());
- delete eng;
+ eng.reset();
QVERIFY(!v1.isUndefined()); // Primitive value is stored inline
QVERIFY(v2.isUndefined());
@@ -2810,6 +2817,7 @@ void tst_QJSValue::deleteFromDifferentThread()
thread->start();
condition.wait(&mutex);
QTRY_VERIFY(thread->isFinished());
+ storage.clearFreePageHint();
QTRY_COMPARE(storage.firstPage, nullptr);
#endif
}
diff --git a/tests/auto/qml/qjsvalue/tst_qjsvalue.h b/tests/auto/qml/qjsvalue/tst_qjsvalue.h
index 5b77bc2e15..459c0535c0 100644
--- a/tests/auto/qml/qjsvalue/tst_qjsvalue.h
+++ b/tests/auto/qml/qjsvalue/tst_qjsvalue.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QJSVALUE_H
#define TST_QJSVALUE_H
@@ -16,7 +16,6 @@ class tst_QJSValue : public QObject
public:
tst_QJSValue();
- virtual ~tst_QJSValue();
private slots:
void ctor_invalid();
@@ -129,11 +128,9 @@ private slots:
private:
void newEngine()
{
- if (engine)
- delete engine;
- engine = new QJSEngine();
+ engine = std::make_unique<QJSEngine>();
}
- QJSEngine *engine;
+ std::unique_ptr<QJSEngine> engine;
};
#endif
diff --git a/tests/auto/qml/qjsvalueiterator/CMakeLists.txt b/tests/auto/qml/qjsvalueiterator/CMakeLists.txt
index 85ac6c7a58..961674e50d 100644
--- a/tests/auto/qml/qjsvalueiterator/CMakeLists.txt
+++ b/tests/auto/qml/qjsvalueiterator/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qjsvalueiterator Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qjsvalueiterator LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qjsvalueiterator
SOURCES
tst_qjsvalueiterator.cpp
diff --git a/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp b/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp
index e329cf948f..a671bf42e2 100644
--- a/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp
+++ b/tests/auto/qml/qjsvalueiterator/tst_qjsvalueiterator.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
@@ -447,7 +447,7 @@ void tst_QJSValueIterator::iterateNonObject()
void tst_QJSValueIterator::iterateOverObjectFromDeletedEngine()
{
- QJSEngine *engine = new QJSEngine;
+ std::unique_ptr<QJSEngine> engine = std::make_unique<QJSEngine>();
QJSValue objet = engine->newObject();
// populate object with properties
@@ -465,7 +465,7 @@ void tst_QJSValueIterator::iterateOverObjectFromDeletedEngine()
it.next();
QVERIFY(properties.contains(it.name()));
- delete engine;
+ engine.reset();
QVERIFY(objet.isUndefined());
QVERIFY(it.name().isEmpty());
diff --git a/tests/auto/qml/qml/CMakeLists.txt b/tests/auto/qml/qml/CMakeLists.txt
index a696d80c4d..39056384de 100644
--- a/tests/auto/qml/qml/CMakeLists.txt
+++ b/tests/auto/qml/qml/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -15,4 +21,6 @@ qt_internal_add_test(tst_qml
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
LIBRARIES
Qt::QuickTestUtilsPrivate
+ Qt::Gui
+ Qt::GuiPrivate
)
diff --git a/tests/auto/qml/qml/data/resizeItem.qml b/tests/auto/qml/qml/data/resizeItem.qml
new file mode 100644
index 0000000000..c416451ccc
--- /dev/null
+++ b/tests/auto/qml/qml/data/resizeItem.qml
@@ -0,0 +1,28 @@
+import QtQuick
+
+Rectangle {
+ id: rect
+ color: "green"
+
+ Timer {
+ id: exitTimer
+ running: false
+ onTriggered: Qt.quit()
+ }
+
+ Timer {
+ id: resizeTimer
+ running: false
+ onTriggered: {
+ rect.width = 100
+ rect.height = 50
+ exitTimer.start()
+ }
+ }
+
+ Window.onHeightChanged: {
+ if (rect.Window.width > 0)
+ console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
+ resizeTimer.start()
+ }
+}
diff --git a/tests/auto/qml/qml/data/sizedItem.qml b/tests/auto/qml/qml/data/sizedItem.qml
new file mode 100644
index 0000000000..edcb0e8629
--- /dev/null
+++ b/tests/auto/qml/qml/data/sizedItem.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Rectangle {
+ id: rect
+ color: "blue"
+ width: 200; height: 150
+
+ Timer {
+ id: exitTimer
+ running: false
+ onTriggered: Qt.quit()
+ }
+
+ Window.onHeightChanged: {
+ if (rect.Window.width > 0)
+ console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
+ exitTimer.restart()
+ }
+}
diff --git a/tests/auto/qml/qml/data/unsizedItem.qml b/tests/auto/qml/qml/data/unsizedItem.qml
new file mode 100644
index 0000000000..e32784762f
--- /dev/null
+++ b/tests/auto/qml/qml/data/unsizedItem.qml
@@ -0,0 +1,18 @@
+import QtQuick
+
+Rectangle {
+ id: rect
+ color: "green"
+
+ Timer {
+ id: exitTimer
+ running: false
+ onTriggered: Qt.quit()
+ }
+
+ Window.onHeightChanged: {
+ if (rect.Window.width > 0)
+ console.info("window", rect.Window.width, rect.Window.height, "content", rect.width, rect.height)
+ exitTimer.restart()
+ }
+}
diff --git a/tests/auto/qml/qml/tst_qml.cpp b/tests/auto/qml/qml/tst_qml.cpp
index de884d8257..befc68d443 100644
--- a/tests/auto/qml/qml/tst_qml.cpp
+++ b/tests/auto/qml/qml/tst_qml.cpp
@@ -1,11 +1,16 @@
// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtCore/qlibraryinfo.h>
#include <QtCore/qprocess.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpa/qplatformintegration.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
+Q_LOGGING_CATEGORY(lcQml, "qt.qml.tests");
+
class tst_qml : public QQmlDataTest
{
Q_OBJECT
@@ -15,6 +20,8 @@ public:
private slots:
void initTestCase() override;
void nonWindow();
+ void itemAndWindowGeometry_data();
+ void itemAndWindowGeometry();
private:
QString qmlPath;
@@ -42,6 +49,124 @@ void tst_qml::nonWindow()
QCOMPARE(qml.exitCode(), 0); // Should not exit with code 2
}
+void tst_qml::itemAndWindowGeometry_data()
+{
+ QTest::addColumn<QString>("config");
+ QTest::addColumn<QString>("geometry");
+ QTest::addColumn<QString>("qmlfile");
+ QTest::addColumn<QSize>("expectedWindowSize");
+ QTest::addColumn<QSize>("expectedContentSize");
+
+ const QString none; // empty string
+
+ auto sizeOrInvalid = [](int w, int h) {
+ static const bool wm = QGuiApplicationPrivate::platformIntegration()->
+ hasCapability(QPlatformIntegration::WindowManagement);
+ return wm ? QSize(w, h) : QSize();
+ };
+
+ QTest::newRow("default: unsized")
+ << none << none << "unsizedItem.qml"
+ << QSize() << QSize(); // default size depends on window system
+ QTest::newRow("default: unsized with geometry")
+ << none << "100x100+50+50" << "unsizedItem.qml"
+ << sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
+ QTest::newRow("resizeToItem: unsized")
+ << "resizeToItem" << none << "unsizedItem.qml"
+ << QSize() << QSize(0, 0);
+ QTest::newRow("resizeToItem: unsized with geometry")
+ << "resizeToItem" << "100x100+50+50" << "unsizedItem.qml"
+ << sizeOrInvalid(100, 100) << QSize(0, 0);
+
+ QTest::newRow("default: sized")
+ << none << none << "sizedItem.qml"
+ << QSize() << QSize();
+ QTest::newRow("default: sized with geometry")
+ << none << "100x100+50+50" << "sizedItem.qml"
+ << sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
+ QTest::newRow("resizeToItem: sized")
+ << "resizeToItem" << none << "sizedItem.qml"
+ << sizeOrInvalid(200, 150) << sizeOrInvalid(200, 150);
+ QTest::newRow("resizeToItem: sized with geometry")
+ << "resizeToItem" << "320x240+50+50" << "sizedItem.qml"
+ << sizeOrInvalid(320, 240) << QSize(200, 150);
+
+ QTest::newRow("default: resizing")
+ << none << none << "resizeItem.qml"
+ << QSize() << QSize();
+ QTest::newRow("default: resizing with geometry")
+ << none << "100x100+50+50" << "resizeItem.qml"
+ << sizeOrInvalid(100, 100) << sizeOrInvalid(100, 100);
+ QTest::newRow("resizeToItem: resizing")
+ << "resizeToItem" << none << "resizeItem.qml"
+ << sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
+ QTest::newRow("resizeToItem: resizing with geometry")
+ << "resizeToItem" << "320x240+50+50" << "resizeItem.qml"
+ << sizeOrInvalid(100, 50) << sizeOrInvalid(100, 50);
+}
+
+/*
+ - A root Item will get put into a Window depending on config (implementations in
+ tools/qml/ResizeItemToWindow.qml and ResizeWindowToItem.qml).
+ - The window system will enforce a minimum size.
+ - In the default configuration, the root Item should then get resized to fit
+ (QTBUG-114068 / QTBUG-116753).
+ - In resizeToItem configuration, if the item width/height are not set, the window would
+ try to be 0x0, but the window system won't allow it.
+ - This also tests the `--qwindowgeometry` argument: with the default config, the
+ item should be resized to fit, but not with `-c resizeToItem`.
+*/
+void tst_qml::itemAndWindowGeometry()
+{
+#ifdef Q_OS_WIN
+ QSKIP("console.info does not go to stderr on Windows.");
+#endif
+
+ QFETCH(QString, config);
+ QFETCH(QString, geometry);
+ QFETCH(QString, qmlfile);
+ QFETCH(QSize, expectedWindowSize);
+ QFETCH(QSize, expectedContentSize);
+
+ QStringList args;
+ if (!config.isEmpty())
+ args << "-c" << config;
+ if (!geometry.isEmpty())
+ args << "--qwindowgeometry" << geometry;
+ args << testFile(qmlfile);
+ QProcess qml;
+ qml.start(qmlPath, args);
+ QVERIFY(qml.waitForFinished());
+ QCOMPARE(qml.exitStatus(), QProcess::NormalExit);
+ const QByteArray output = qml.readAllStandardError();
+ const auto sizeLineIndex = output.lastIndexOf("window");
+ QCOMPARE_GE(sizeLineIndex, 0);
+ const auto newlineIndex = output.indexOf('\n', sizeLineIndex);
+ QCOMPARE_GT(newlineIndex, sizeLineIndex);
+ // expect a line like "window 120 120 content 120 120"
+ const auto sizes = output.sliced(sizeLineIndex, newlineIndex - sizeLineIndex).split(' ');
+ QCOMPARE_GE(sizes.size(), 6);
+ QCOMPARE(sizes[0], "window");
+ QCOMPARE(sizes[3], "content");
+ const QSize windowSize(sizes[1].toInt(), sizes[2].toInt());
+ const QSize contentSize(sizes[4].toInt(), sizes[5].toInt());
+ qCDebug(lcQml) << sizes
+ << "window" << windowSize << "expect" << expectedWindowSize
+ << "content" << contentSize << "expect" << expectedContentSize;
+ QVERIFY(!windowSize.isEmpty());
+ if (config != "resizeToItem") {
+ // default config:
+ // ResizeItemToWindow.qml should have resized the item to its window
+ QCOMPARE(contentSize, windowSize);
+ }
+ // windowSize can be off-by-one on hidpi (e.g. QT_SCALE_FACTOR=2 on xcb);
+ // perhaps that's a bug somewhere, but so far we aren't testing hidpi on CI
+ if (expectedWindowSize.isValid())
+ QCOMPARE(windowSize, expectedWindowSize);
+ if (expectedContentSize.isValid())
+ QCOMPARE(contentSize, expectedContentSize);
+}
+
QTEST_MAIN(tst_qml)
#include <tst_qml.moc>
diff --git a/tests/auto/qml/qmlbasicapp/CMakeLists.txt b/tests/auto/qml/qmlbasicapp/CMakeLists.txt
index 8328a6b3f4..add4c560a8 100644
--- a/tests/auto/qml/qmlbasicapp/CMakeLists.txt
+++ b/tests/auto/qml/qmlbasicapp/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlbasicapp LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmlbasicapp
SOURCES
tst_qmlbasicapp.cpp
diff --git a/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp b/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp
index 7f2736a76b..f3846569cb 100644
--- a/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp
+++ b/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "timemodel.h"
diff --git a/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h b/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h
index b42542be31..2cc8f2e756 100644
--- a/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h
+++ b/tests/auto/qml/qmlbasicapp/TimeExample2/timemodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TIMEMODEL_H
#define TIMEMODEL_H
diff --git a/tests/auto/qml/qmlbasicapp/main.qml b/tests/auto/qml/qmlbasicapp/main.qml
index 37598a5235..8c10b0881f 100644
--- a/tests/auto/qml/qmlbasicapp/main.qml
+++ b/tests/auto/qml/qmlbasicapp/main.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import TimeExample2 // import types from the plugin
import BasicExtension
diff --git a/tests/auto/qml/qmlbasicapp/manual_imports.cpp b/tests/auto/qml/qmlbasicapp/manual_imports.cpp
index 61df826af4..57adb572dd 100644
--- a/tests/auto/qml/qmlbasicapp/manual_imports.cpp
+++ b/tests/auto/qml/qmlbasicapp/manual_imports.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
diff --git a/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp b/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp
index fd72a0910f..3b9028154c 100644
--- a/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp
+++ b/tests/auto/qml/qmlbasicapp/tst_qmlbasicapp.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlEngine>
#include <QQmlComponent>
diff --git a/tests/auto/qml/qmlcachegen/CMakeLists.txt b/tests/auto/qml/qmlcachegen/CMakeLists.txt
index d92d5e6166..d88de460e9 100644
--- a/tests/auto/qml/qmlcachegen/CMakeLists.txt
+++ b/tests/auto/qml/qmlcachegen/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmlcachegen Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlcachegen LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -22,6 +28,7 @@ qt_internal_add_test(tst_qmlcachegen
Qt::Gui
Qt::QmlPrivate
Qt::QuickTestUtilsPrivate
+ Qt::QmlCompilerPrivate
TESTDATA ${test_data}
)
diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml
new file mode 100644
index 0000000000..b48004dc87
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsClean.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+ property int i: 100
+ property int j: i * 2
+
+ function s() : string {
+ let s = "abc"
+ return s + "def "
+ }
+}
diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml
new file mode 100644
index 0000000000..3d96760e96
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/aotstats/AotstatsMixed.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ property int i: Math.max(1, 2) // OK
+ function f() { return 1 } // Error: No specified return type
+ property string s: g() // Error: g?
+}
diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc b/tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc
new file mode 100644
index 0000000000..4f156ad2ef
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/aotstats/cachegentest.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/cachegentest">
+ <file alias="qmldir">qmldir</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmlcachegen/data/aotstats/qmldir b/tests/auto/qml/qmlcachegen/data/aotstats/qmldir
new file mode 100644
index 0000000000..72047cc99d
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/aotstats/qmldir
@@ -0,0 +1,3 @@
+module cachegentest
+AotstatsClean 254.0 AotstatsClean.qml
+AotstatsMixed 254.0 AotstatsMixed.qml
diff --git a/tests/auto/qml/qmlcachegen/data/truncateTest.qml b/tests/auto/qml/qmlcachegen/data/truncateTest.qml
new file mode 100644
index 0000000000..fee768cf77
--- /dev/null
+++ b/tests/auto/qml/qmlcachegen/data/truncateTest.qml
@@ -0,0 +1,764 @@
+import QtQuick 2.15
+import QtQuick.Layouts 2.15
+
+Item {
+ width: 400
+ height: 400
+
+ component Button : Item {
+ property string text
+ property Item background
+ }
+
+ ColumnLayout {
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+ Button {
+ text: "A Special Button"
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 40
+ color: "red"
+ border.color: "#26282a"
+ border.width: 1
+ radius: 4
+ }
+ }
+
+ }
+}
diff --git a/tests/auto/qml/qmlcachegen/scriptstringprops.h b/tests/auto/qml/qmlcachegen/scriptstringprops.h
index 521455c098..96c86f1c59 100644
--- a/tests/auto/qml/qmlcachegen/scriptstringprops.h
+++ b/tests/auto/qml/qmlcachegen/scriptstringprops.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SCRIPT_STRING_PROPS_H
#define SCRIPT_STRING_PROPS_H
diff --git a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
index 60d4a5df32..34ad3bbc98 100644
--- a/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
+++ b/tests/auto/qml/qmlcachegen/tst_qmlcachegen.cpp
@@ -1,8 +1,9 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
+#include <QJsonDocument>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QProcess>
@@ -11,6 +12,7 @@
#include <QSysInfo>
#include <QLoggingCategory>
#include <private/qqmlcomponent_p.h>
+#include <private/qqmljscompilerstats_p.h>
#include <private/qqmlscriptdata_p.h>
#include <private/qv4compileddata_p.h>
#include <qtranslator.h>
@@ -63,8 +65,14 @@ private slots:
void inlineComponent();
void posthocRequired();
+ void gracefullyHandleTruncatedCacheFile();
+
void scriptStringCachegenInteraction();
void saveableUnitPointer();
+
+ void aotstatsSerialization();
+ void aotstatsGeneration_data();
+ void aotstatsGeneration();
};
// A wrapper around QQmlComponent to ensure the temporary reference counts
@@ -349,7 +357,7 @@ void tst_qmlcachegen::signalHandlerParameters()
};
QVERIFY(isStringIndexInStringTable(compilationUnit->objectAt(0)->signalAt(0)->parameterAt(0)->nameIndex));
- QVERIFY(!compilationUnit->dynamicStrings.isEmpty());
+ QVERIFY(!compilationUnit->baseCompilationUnit()->dynamicStrings.isEmpty());
}
}
@@ -714,7 +722,8 @@ void tst_qmlcachegen::moduleScriptImport()
{
auto componentPrivate = QQmlComponentPrivate::get(&component);
QVERIFY(componentPrivate);
- auto compilationUnit = componentPrivate->compilationUnit->dependentScripts.first()->compilationUnit();
+ auto compilationUnit = componentPrivate->compilationUnit->dependentScriptsPtr()
+ ->first()->compilationUnit();
QVERIFY(compilationUnit);
auto unitData = compilationUnit->unitData();
QVERIFY(unitData);
@@ -839,6 +848,23 @@ void tst_qmlcachegen::posthocRequired()
qPrintable(component.errorString()));
}
+void tst_qmlcachegen::gracefullyHandleTruncatedCacheFile()
+{
+#if defined(QTEST_CROSS_COMPILED)
+ QSKIP("Cannot call qmlcachegen on cross-compiled target.");
+#endif
+
+ bool ok = generateCache(testFile("truncateTest.qml"));
+ QVERIFY(ok);
+ const QString qmlcFile = testFile("truncateTest.qmlc");
+ QVERIFY(QFile::exists(qmlcFile));
+ QFile::resize(qmlcFile, QFileInfo(qmlcFile).size() / 2);
+ QQmlEngine engine;
+ CleanlyLoadingComponent component(&engine, testFileUrl("truncateTest.qml"));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+}
+
void tst_qmlcachegen::scriptStringCachegenInteraction()
{
#if defined(QTEST_CROSS_COMPILED)
@@ -875,6 +901,133 @@ void tst_qmlcachegen::saveableUnitPointer()
QCOMPARE(unit.flags, flags);
}
+void tst_qmlcachegen::aotstatsSerialization()
+{
+ const auto createEntry = [](const auto &d, const auto &n, const auto &e, const auto &l,
+ const auto &c, const auto &s) -> QQmlJS::AotStatsEntry {
+ QQmlJS::AotStatsEntry entry;
+ entry.codegenDuration = d;
+ entry.functionName = n;
+ entry.errorMessage = e;
+ entry.line = l;
+ entry.column = c;
+ entry.codegenSuccessful = s;
+ return entry;
+ };
+
+ const auto equal = [](const auto &e1, const auto &e2) -> bool {
+ return e1.codegenDuration == e2.codegenDuration && e1.functionName == e2.functionName
+ && e1.errorMessage == e2.errorMessage && e1.line == e2.line
+ && e1.column == e2.column && e1.codegenSuccessful == e2.codegenSuccessful;
+ };
+
+ // AotStats
+ // +-ModuleA
+ // | +-File1
+ // | | +-e1
+ // | | +-e2
+ // | +-File2
+ // | | +-e3
+ // +-ModuleB
+ // | +-File3
+ // | | +-e4
+
+ QQmlJS::AotStats original;
+ QQmlJS::AotStatsEntry e1 = createEntry(std::chrono::microseconds(500), "f1", "", 1, 1, true);
+ QQmlJS::AotStatsEntry e2 = createEntry(std::chrono::microseconds(200), "f2", "err1", 5, 4, false);
+ QQmlJS::AotStatsEntry e3 = createEntry(std::chrono::microseconds(750), "f3", "", 20, 4, true);
+ QQmlJS::AotStatsEntry e4 = createEntry(std::chrono::microseconds(300), "f4", "err2", 5, 8, false);
+ original.addEntry("ModuleA", "File1", e1);
+ original.addEntry("ModuleA", "File1", e2);
+ original.addEntry("ModuleA", "File2", e3);
+ original.addEntry("ModuleB", "File3", e4);
+
+ const auto parsed = QQmlJS::AotStats::fromJsonDocument(original.toJsonDocument());
+ QCOMPARE(parsed.entries().size(), original.entries().size());
+
+ const auto &parsedA = parsed.entries()["ModuleA"];
+ const auto &originalA = original.entries()["ModuleA"];
+ QCOMPARE(parsedA.size(), originalA.size());
+ QCOMPARE(parsedA["File1"].size(), originalA["File1"].size());
+ QVERIFY(equal(parsedA["File1"][0], originalA["File1"][0]));
+ QVERIFY(equal(parsedA["File1"][1], originalA["File1"][1]));
+ QCOMPARE(parsedA["File2"].size(), originalA["File2"].size());
+ QVERIFY(equal(parsedA["File2"][0], originalA["File2"][0]));
+
+ const auto &parsedB = parsed.entries()["ModuleB"];
+ const auto &originalB = original.entries()["ModuleB"];
+ QCOMPARE(parsedB.size(), originalB.size());
+ QCOMPARE(parsedB["File3"].size(), originalB["File3"].size());
+ QVERIFY(equal(parsedB["File3"][0], originalB["File3"][0]));
+}
+
+struct FunctionEntry
+{
+ QString name;
+ QString errorMessage;
+ bool codegenSuccessful;
+};
+
+void tst_qmlcachegen::aotstatsGeneration_data()
+{
+ QTest::addColumn<QString>("qmlFile");
+ QTest::addColumn<QList<FunctionEntry>>("entries");
+
+ QTest::addRow("clean") << "AotstatsClean.qml"
+ << QList<FunctionEntry>{ { "j", "", true }, { "s", "", true } };
+
+ const QString fError = "function without return type annotation returns int. This may prevent "
+ "proper compilation to Cpp.";
+ const QString sError = "method g cannot be resolved.";
+ QTest::addRow("mixed") << "AotstatsMixed.qml"
+ << QList<FunctionEntry>{ { "i", "", true },
+ { "f", fError, false },
+ { "s", sError, false } };
+}
+
+void tst_qmlcachegen::aotstatsGeneration()
+{
+#if defined(QTEST_CROSS_COMPILED)
+ QSKIP("Cannot call qmlcachegen on cross-compiled target.");
+#endif
+ QFETCH(QString, qmlFile);
+ QFETCH(QList<FunctionEntry>, entries);
+
+ QTemporaryDir dir;
+ QProcess proc;
+ proc.setProgram(QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath) + "/qmlcachegen"_L1);
+ const QString cppOutput = dir.filePath(qmlFile + ".cpp");
+ const QString aotstatsOutput = cppOutput + ".aotstats";
+ proc.setArguments({ "--bare",
+ "--resource-path", "/cachegentest/data/aotstats/" + qmlFile,
+ "-i", testFile("aotstats/qmldir"),
+ "--resource", testFile("aotstats/cachegentest.qrc"),
+ "--dump-aot-stats",
+ "--module-id=Aotstats",
+ "-o", cppOutput,
+ testFile("aotstats/" + qmlFile) });
+ proc.start();
+ QVERIFY(proc.waitForFinished() && proc.exitStatus() == QProcess::NormalExit);
+
+ QVERIFY(QFileInfo::exists(aotstatsOutput));
+ QFile aotstatsFile(aotstatsOutput);
+ QVERIFY(aotstatsFile.open(QIODevice::Text | QIODevice::ReadOnly));
+ const auto document = QJsonDocument::fromJson(aotstatsFile.readAll());
+ const auto aotstats = QQmlJS::AotStats::fromJsonDocument(document);
+ QVERIFY(aotstats.entries().size() == 1); // One module
+ const auto &moduleEntries = aotstats.entries()["Aotstats"];
+ QVERIFY(moduleEntries.size() == 1); // Only one qml file was compiled
+ const auto &fileEntries = moduleEntries[moduleEntries.keys().first()];
+
+ for (const auto &entry : entries) {
+ const auto it = std::find_if(fileEntries.cbegin(), fileEntries.cend(),
+ [&](const auto &e) { return e.functionName == entry.name; });
+ QVERIFY(it != fileEntries.cend());
+ QVERIFY(it->codegenSuccessful == entry.codegenSuccessful);
+ QVERIFY(it->errorMessage == entry.errorMessage);
+ }
+}
+
const QQmlScriptString &ScriptStringProps::undef() const
{
return m_undef;
diff --git a/tests/auto/qml/qmlcppcodegen/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/CMakeLists.txt
index 8644e00cde..715ad6162a 100644
--- a/tests/auto/qml/qmlcppcodegen/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlcppcodegen LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
add_subdirectory(data)
qt_internal_add_test(tst_qmlcppcodegen
@@ -8,9 +14,13 @@ qt_internal_add_test(tst_qmlcppcodegen
tst_qmlcppcodegen.cpp
LIBRARIES
Qt::QmlPrivate
- Qt::Gui
+ Qt::GuiPrivate
codegen_test_module
codegen_test_moduleplugin
+ codegen_test_hidden
+ codegen_test_hiddenplugin
+ codegen_test_stringbuilder
+ codegen_test_stringbuilderplugin
)
qt_internal_add_test(tst_qmlcppcodegen_interpreted
@@ -18,9 +28,13 @@ qt_internal_add_test(tst_qmlcppcodegen_interpreted
tst_qmlcppcodegen.cpp
LIBRARIES
Qt::QmlPrivate
- Qt::Gui
+ Qt::GuiPrivate
codegen_test_module
codegen_test_moduleplugin
+ codegen_test_hidden
+ codegen_test_hiddenplugin
+ codegen_test_stringbuilder
+ codegen_test_stringbuilderplugin
DEFINES
QT_TEST_FORCE_INTERPRETER
)
diff --git a/tests/auto/qml/qmlcppcodegen/data/Action.qml b/tests/auto/qml/qmlcppcodegen/data/Action.qml
new file mode 100644
index 0000000000..99b86fb31c
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Action.qml
@@ -0,0 +1,7 @@
+import QtQuick
+import QtQuick.Controls as QQC2
+import QtQuick.Templates as T
+
+QQC2.Action {
+ property bool visible: true
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/B.qml b/tests/auto/qml/qmlcppcodegen/data/B.qml
new file mode 100644
index 0000000000..97e895ecad
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/B.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property rect r
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/BaseConstraint.qml b/tests/auto/qml/qmlcppcodegen/data/BaseConstraint.qml
new file mode 100644
index 0000000000..2615778f6a
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/BaseConstraint.qml
@@ -0,0 +1,9 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property int satisfaction: Satisfaction.NONE
+ property QtObject output
+
+ function inputsKnown(mark: int) : bool { return true }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
index 0737d77005..7f2e6ad967 100644
--- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
+++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt
@@ -4,41 +4,61 @@
set(cpp_sources
ambiguous.h
birthdayparty.cpp birthdayparty.h
+ convertQJSPrimitiveValueToIntegral.h
cppbaseclass.h
druggeljug.h
+ dummyobjekt.h
dynamicmeta.h
enumproblems.h
enumProperty.h
+ getOptionalLookup.h
gadgetwithenum.h
invisible.h
+ listprovider.h
multiforeign.h
objectwithmethod.h
person.cpp person.h
+ resettable.h
+ sequenceToIterable.h
sequencetypeexample.cpp sequencetypeexample.h
state.h
theme.cpp theme.h
timelinetheme.cpp timelinetheme.h
+ variantMapLookup.h
+ variantreturn.h
+ weathermoduleurl.h
wrapwithvariant.h
withlength.h
)
set(qml_files
AccessModelMethodsFromOutside.qml
+ Action.qml
ArraySequenceLengthInterop.qml
+ B.qml
BadType.qml
+ BaseConstraint.qml
BaseMember.qml
BindingExpression.qml
+ CxxTypeFromDir.qml
+ CxxTypeFromImplicit.qml
Cycle1.qml
Cycle2.qml
Cycle3.qml
- CxxTypeFromDir.qml
- CxxTypeFromImplicit.qml
+ CppMethodListReturnType.qml
Dummy.qml
+ Dummy2.qml
+ EditConstraint.qml
Enums.qml
Foozle.qml
+ GetOptionalLookupOnQJSValueNonStrict.qml
+ GetOptionalLookupShadowed.qml
Loopy.qml
+ NotificationItem.qml
+ NotificationsUtils.js
OkType.qml
Panel.qml
+ Planner.qml
ProgressBar/Keyframe.qml
ProgressBar/KeyframeGroup.qml
ProgressBar/ProgressBar.ui.qml
@@ -46,98 +66,145 @@ set(qml_files
ProgressBar/Timeline.qml
ProgressBar/TimelineAnimation.qml
RootWithoutId.qml
+ Satisfaction.qml
SelectionRectangle.qml
+ ShadowedObjectName.qml
+ ShadowedObjectNameDerived.qml
+ StoreMetaEnum.qml
Test.qml
TestCase.qml
+ Variable.qml
WindowDerived.qml
aliasLookup.qml
ambiguous1/Ambiguous.qml
ambiguous2/Ambiguous.qml
+ ambiguousAs.qml
ambiguousSignals.qml
anchorsFill.qml
argumentConversion.qml
array.qml
+ arrayCtor.qml
asCast.qml
attachedBaseEnum.qml
badSequence.qml
+ basicBlocksWithBackJump.qml
+ basicBlocksWithBackJump_infinite.qml
+ basicDTZ.qml
bindToValueType.qml
blockComments.qml
+ boolCoercions.qml
+ boolPointerMerge.qml
boundComponents.qml
callContextPropertyLookupResult.qml
callWithSpread.qml
childobject.qml
colorAsVariant.qml
colorString.qml
- consoleObject.qml
+ compareOriginals.qml
+ comparisonTypes.qml
componentReturnType.qml
compositeTypeMethod.qml
compositesingleton.qml
+ consoleObject.qml
+ consoleTrace.qml
construct.qml
contextParam.qml
conversionDecrement.qml
+ conversionInDeadCode.qml
conversions.qml
conversions2.qml
+ convertPrimitiveToVar.qml
+ convertQJSPrimitiveValueToIntegral.qml
+ convertToOriginalReadAcumulatorForUnaryOperators.qml
curlygrouped.qml
cycleHead.qml
+ dateConstruction.qml
dateConversions.qml
deadShoeSize.qml
deadStoreLoop.qml
dialog.qml
+ dialogButtonBox.qml
dynamicscene.qml
+ enforceSignature.qml
enumConversion.qml
+ enumFromBadSingleton.qml
enumInvalid.qml
enumLookup.qml
+ enumMarkedAsFlag.qml
enumProblems.qml
enumScope.qml
enumsInOtherObject.qml
enumsUser.qml
equalityQObjects.qml
+ equalityQUrl.qml
+ equalityTestsWithNullOrUndefined.qml
equalityVarAndNonStorable.qml
equalsUndefined.qml
+ exceptionFromInner.qml
excessiveParameters.qml
extendedTypes.qml
+ extra/extra.qml
failures.qml
fallbacklookups.qml
+ fallbackresettable.qml
fileDialog.qml
+ flagEnum.qml
fromBoolValue.qml
- functionLookup.qml
funcWithParams.qml
+ functionLookup.qml
functionReturningVoid.qml
functionTakingVar.qml
+ getOptionalLookup.qml
globals.qml
- hidden/Main.qml
- hidden/Style.qml
idAccess.qml
+ ignoredFunctionReturn.qml
immediateQuit.qml
imports/QmlBench/Globals.qml
importsFromImportPath.qml
+ indirectlyShadowable.qml
infinities.qml
infinitiesToInt.qml
- invisibleBase.qml
- invisibleTypes.qml
- invisibleListElementType.qml
intEnumCompare.qml
intOverflow.qml
+ intToEnum.qml
interactive.qml
interceptor.qml
+ internalConversion.qml
+ invisibleBase.qml
+ invisibleListElementType.qml
+ invisibleTypes.qml
isnan.qml
+ iteration.qml
javaScriptArgument.qml
+ jsArrayMethods.qml
+ jsArrayMethodsUntyped.qml
+ jsArrayMethodsWithParams.qml
+ jsArrayMethodsWithParamsUntyped.qml
jsMathObject.qml
jsimport.qml
jsmoduleimport.qml
layouts.qml
- library.js
letAndConst.qml
+ library.js
listAsArgument.qml
+ listConversion.qml
listIndices.qml
+ listOfInvisible.qml
listPropertyAsModel.qml
+ listToString.qml
listlength.qml
math.qml
+ mathMinMax.qml
mathOperations.qml
+ mathStaticProperties.qml
+ mergedObjectRead.qml
+ mergedObjectWrite.qml
+ methodOnListLookup.qml
methods.qml
modulePrefix.qml
moveRegVoid.qml
multiforeign.qml
+ multipleCtors.qml
namespaceWithEnum.qml
noBindingLoop.qml
noQQmlData.qml
@@ -146,9 +213,14 @@ set(qml_files
notEqualsInt.qml
notNotString.qml
nullAccess.qml
+ nullAccessInsideSignalHandler.qml
nullComparison.qml
+ nullishCoalescing.qml
numbersInJsPrimitive.qml
objectInVar.qml
+ objectLookupOnListElement.qml
+ objectWithStringListMethod.qml
+ optionalComparison.qml
outOfBounds.qml
overriddenMember.qml
ownProperty.qml
@@ -157,48 +229,76 @@ set(qml_files
popContextAfterRet.qml
prefixedMetaType.qml
pressAndHoldButton.qml
- registerelimination.qml
+ qtbug113150.qml
+ reduceWithNullThis.qml
+ readEnumFromInstance.qml
+ readonlyListProperty.qml
registerPropagation.qml
+ registerelimination.qml
+ renameAdjust.qml
+ resettable.qml
+ returnAfterReject.qml
revisions.qml
+ scopeIdLookup.qml
scopeVsObject.qml
+ scopedEnum.qml
script.js
script.mjs
+ sequenceToIterable.qml
+ setLookupConversion.qml
+ setLookupOriginalScope.qml
+ shadowedAsCasts.qml
+ shadowedMethod.qml
+ shadowedPrimitiveCmpEqNull.qml
shared/Slider.qml
shifts.qml
signal.qml
signalHandler.qml
signalIndexMismatch.qml
+ signalsWithLists.qml
signatureIgnored.qml
specificParent.qml
storeElementSideEffects.qml
stringArg.qml
stringLength.qml
stringToByteArray.qml
+ structuredValueType.qml
testlogger.js
text.qml
themerbad.qml
themergood.qml
+ thisObject.qml
throwObjectName.qml
toString.qml
+ topLevelComponent.qml
translation.qml
+ trigraphs.qml
trivialSignalHandler.qml
typePropagationLoop.qml
typePropertyClash.qml
typedArray.qml
undefinedResets.qml
+ undefinedToDouble.qml
unknownAttached.qml
unknownParameter.qml
unstoredUndefined.qml
unusedAttached.qml
urlString.qml
usingCxxTypesFromFileImports.qml
+ valueTypeCast.qml
valueTypeCopy.qml
+ valueTypeDefault.qml
valueTypeLists.qml
valueTypeProperty.qml
valueTypeReference.qml
+ variantMap.qml
+ variantMapLookup.qml
+ variantReturn.qml
variantlist.qml
versionmismatch.qml
+ voidConversion.qml
voidfunction.qml
+ writeback.qml
dummy_imports.qml
)
@@ -214,21 +314,88 @@ set_source_files_properties("shared/Slider.qml"
set_source_files_properties("hidden/Style.qml"
PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
+qt_policy(SET QTP0001 NEW)
+
+# Add the module for the hidden files before setting QTP0004, so that we don't add a qmldir in
+# "hidden". That would defeat the purpose.
+
+qt_add_library(codegen_test_hidden STATIC)
+qt_autogen_tools_initial_setup(codegen_test_hidden)
+
+set_target_properties(codegen_test_hidden PROPERTIES
+ # We really want qmlcachegen here, even if qmlsc is available
+ QT_QMLCACHEGEN_EXECUTABLE qmlcachegen
+ QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks
+)
+
+target_compile_definitions(codegen_test_hidden PUBLIC
+ -DGENERATED_CPP_FOLDER="${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache"
+)
+
+qt_policy(SET QTP0004 OLD)
+qt6_add_qml_module(codegen_test_hidden
+ URI HiddenTestTypes
+ QML_FILES
+ hidden/Main.qml
+ hidden/Style.qml
+ OUTPUT_DIRECTORY HiddenTestTypes
+ __QT_INTERNAL_DISAMBIGUATE_QMLDIR_RESOURCE
+)
+
+add_dependencies(codegen_test_hidden Qt::Quick)
+
+qt_autogen_tools_initial_setup(codegen_test_hiddenplugin)
+
+qt_policy(SET QTP0004 NEW)
+
+qt_add_library(codegen_test_stringbuilder STATIC)
+qt_autogen_tools_initial_setup(codegen_test_stringbuilder)
+
+set_target_properties(codegen_test_stringbuilder PROPERTIES
+ # We really want qmlcachegen here, even if qmlsc is available
+ QT_QMLCACHEGEN_EXECUTABLE qmlcachegen
+ QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks
+)
+
+target_compile_definitions(codegen_test_stringbuilder PRIVATE
+ -DGENERATED_CPP_FOLDER="${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache"
+ QT_USE_QSTRINGBUILDER
+)
+
+qt6_add_qml_module(codegen_test_stringbuilder
+ URI StringBuilderTestTypes
+ SOURCES
+ writableVariantMap.h
+ QML_FILES
+ writeVariantMap.qml
+ OUTPUT_DIRECTORY stringbuilderTestTypes
+ __QT_INTERNAL_DISAMBIGUATE_QMLDIR_RESOURCE
+)
+
+qt_autogen_tools_initial_setup(codegen_test_stringbuilderplugin)
+
qt_add_library(codegen_test_module STATIC)
qt_autogen_tools_initial_setup(codegen_test_module)
set_target_properties(codegen_test_module PROPERTIES
# We really want qmlcachegen here, even if qmlsc is available
QT_QMLCACHEGEN_EXECUTABLE qmlcachegen
+ QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks
+)
+
+
+
+target_compile_definitions(codegen_test_module PUBLIC
+ -DGENERATED_CPP_FOLDER="${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache"
)
qt6_add_qml_module(codegen_test_module
VERSION 1.5
URI TestTypes
IMPORT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/imports/"
- AUTO_RESOURCE_PREFIX
DEPENDENCIES
QtQuick
+ QtQuick.Controls
QtQuick.Templates
QtQuick.Shapes
SOURCES
@@ -238,8 +405,96 @@ qt6_add_qml_module(codegen_test_module
RESOURCES
${resource_files}
OUTPUT_DIRECTORY TestTypes # Make sure tst_qmlcachegen doesn't see our output
+ __QT_INTERNAL_DISAMBIGUATE_QMLDIR_RESOURCE
)
+if(${CMAKE_VERSION} GREATER_EQUAL "3.19.0")
+ qt_target_qml_sources(codegen_test_module
+ QML_FILES extra2/extra.qml
+ )
+else()
+ target_compile_definitions(codegen_test_module PUBLIC
+ -DVERY_OLD_CMAKE=1
+ )
+endif()
+
add_dependencies(codegen_test_module Qt::Quick Qt::QuickTemplates2 Qt::QuickShapesPrivate)
qt_autogen_tools_initial_setup(codegen_test_moduleplugin)
+
+
+qt_add_library(codegen_test_module_verify STATIC)
+qt_autogen_tools_initial_setup(codegen_test_module_verify)
+
+set_target_properties(codegen_test_module_verify PROPERTIES
+ # We really want qmlcachegen here, even if qmlsc is available
+ QT_QMLCACHEGEN_EXECUTABLE qmlcachegen
+ QT_QMLCACHEGEN_ARGUMENTS --validate-basic-blocks
+)
+
+
+qt6_add_qml_module(codegen_test_module_verify
+ VERSION 1.5
+ URI TestTypes
+ IMPORT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/imports/"
+ DEPENDENCIES
+ QtQuick
+ QtQuick.Controls
+ QtQuick.Templates
+ QtQuick.Shapes
+ SOURCES
+ ${cpp_sources}
+ QML_FILES
+ ${qml_files}
+ RESOURCES
+ ${resource_files}
+ OUTPUT_DIRECTORY verify/TestTypes # Make sure tst_qmlcachegen doesn't see our output
+ TARGET_PATH verify/TestTypes # Different target path to avoid resource file name clashes
+ __QT_INTERNAL_DISAMBIGUATE_QMLDIR_RESOURCE
+)
+
+add_dependencies(codegen_test_module_verify Qt::Quick Qt::QuickTemplates2 Qt::QuickShapesPrivate)
+
+qt_autogen_tools_initial_setup(codegen_test_module_verifyplugin)
+
+
+qt_internal_add_test(tst_qmlcppcodegen_verify
+ SOURCES
+ tst_qmlcppcodegen_verify.cpp
+)
+
+add_dependencies(tst_qmlcppcodegen_verify codegen_test_module codegen_test_module_verify)
+
+set(a_files "")
+set(b_files "")
+
+foreach(qml_file IN LISTS qml_files)
+ string(REGEX REPLACE "\\.(js|mjs|qml)$" "_\\1" compiled_file ${qml_file})
+ string(REGEX REPLACE "[$#?]+" "_" compiled_file ${compiled_file})
+
+ list(APPEND
+ a_files
+ "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/codegen_test_module_${compiled_file}.cpp")
+
+ list(APPEND
+ b_files
+ "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/codegen_test_module_verify_${compiled_file}.cpp")
+endforeach()
+
+qt_add_resources(tst_qmlcppcodegen_verify "a"
+ PREFIX
+ "/a"
+ FILES
+ ${a_files}
+ BASE
+ "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/"
+)
+
+qt_add_resources(tst_qmlcppcodegen_verify "b"
+ PREFIX
+ "/b"
+ FILES
+ ${b_files}
+ BASE
+ "${CMAKE_CURRENT_BINARY_DIR}/.rcc/qmlcache/"
+)
diff --git a/tests/auto/qml/qmlcppcodegen/data/CppMethodListReturnType.qml b/tests/auto/qml/qmlcppcodegen/data/CppMethodListReturnType.qml
new file mode 100644
index 0000000000..9c3ce4e877
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/CppMethodListReturnType.qml
@@ -0,0 +1,12 @@
+pragma Strict
+
+import QtQuick
+import TestTypes
+
+Item {
+ ListProvider {
+ id: listProvider
+ }
+
+ property var list: listProvider.intList()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/Dummy2.qml b/tests/auto/qml/qmlcppcodegen/data/Dummy2.qml
new file mode 100644
index 0000000000..a3bbef1888
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Dummy2.qml
@@ -0,0 +1,18 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+
+import QtQml
+
+QtObject {
+ property int value
+ property Dummy2 child
+ property int dummyEnum
+
+ signal triggered()
+ signal signalWithArg(int one, bool two)
+ property real onValue
+ property real offValue
+
+ function someFunction(a: int, b: bool, c: Dummy2, d: real, e: int) : int { return 42 }
+ property string strProp
+ function concat(a: string, b: string) : string { return a + b }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/EditConstraint.qml b/tests/auto/qml/qmlcppcodegen/data/EditConstraint.qml
new file mode 100644
index 0000000000..ce278fbdf9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/EditConstraint.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property Variable myOutput
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupOnQJSValueNonStrict.qml b/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupOnQJSValueNonStrict.qml
new file mode 100644
index 0000000000..5a89e996b4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupOnQJSValueNonStrict.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ property Action action: Action { }
+ property bool b: action?.visible
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupShadowed.qml b/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupShadowed.qml
new file mode 100644
index 0000000000..eacefc3017
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/GetOptionalLookupShadowed.qml
@@ -0,0 +1,19 @@
+pragma Strict
+
+import QtQml
+import QtQuick
+
+QtObject {
+ id: root
+
+ component Base : QtObject {
+ property int i: 1
+ }
+
+ component Derived : Base {
+ property string i: "a"
+ }
+
+ property Base base: Derived { }
+ property var res: root.base?.i
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/NotificationItem.qml b/tests/auto/qml/qmlcppcodegen/data/NotificationItem.qml
new file mode 100644
index 0000000000..fba4df6453
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/NotificationItem.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes as MobileShell
+
+QtObject {
+ id: notificationItem
+ objectName: MobileShell.NotificationsUtils.determineNotificationHeadingText(notificationItem)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/NotificationsUtils.js b/tests/auto/qml/qmlcppcodegen/data/NotificationsUtils.js
new file mode 100644
index 0000000000..079270e1b9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/NotificationsUtils.js
@@ -0,0 +1,3 @@
+function determineNotificationHeadingText(notificationItem) {
+ return "heading";
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/Panel.qml b/tests/auto/qml/qmlcppcodegen/data/Panel.qml
index 84e926b8d2..7f589d23e8 100644
--- a/tests/auto/qml/qmlcppcodegen/data/Panel.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/Panel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qmlcppcodegen/data/Planner.qml b/tests/auto/qml/qmlcppcodegen/data/Planner.qml
new file mode 100644
index 0000000000..ddb2fff053
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Planner.qml
@@ -0,0 +1,50 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: planner
+ property Variable last: Variable { value: 10 }
+
+ function newMark() : int {
+ return 5;
+ }
+
+ function addPropagate(i: int) : bool {
+ return false;
+ }
+
+ function typeErasedRemoveOne(v: QtObject) { removeOne(v as Variable) }
+
+ // Work with various shadowable members and return values.
+ function removeOne(v: Variable) {
+ let vDeterminedBy = v.determinedBy;
+ for (let i = 0, length = v.length(); i < length; ++i) {
+ let next = v.constraint(i) as BaseConstraint;
+ if (next.satisfaction === Satisfaction.NONE)
+ objectName += "n"
+ else if (next !== vDeterminedBy)
+ objectName += "d"
+ else
+ objectName += "x"
+ }
+ }
+
+ function typeErasedRun(c: QtObject) { run(c as BaseConstraint) }
+
+ function run(initial: BaseConstraint) {
+ let mark = planner.newMark();
+ let c = initial;
+
+ let output = c.output as Variable;
+ if (output.mark !== mark && c.inputsKnown(mark)) {
+ output.mark = mark;
+ }
+ }
+
+ function verify(i: int) {
+ if (last.value !== i)
+ console.error("failed", last.value, i);
+ else
+ console.log("success")
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml
index 21a3832366..a44af04a50 100644
--- a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/ProgressBar.ui.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
import QtQuick.Window 2.3
diff --git a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml
index 707f0d9be9..43ff1b62b1 100644
--- a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/Root.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.9
diff --git a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml
index b97e8956bf..75ad2245f2 100644
--- a/tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/ProgressBar/TimelineAnimation.qml
@@ -2,5 +2,5 @@ import QtQuick
NumberAnimation {
property bool pingPong
- signal finished()
+ signal finishedEvil()
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/Satisfaction.qml b/tests/auto/qml/qmlcppcodegen/data/Satisfaction.qml
new file mode 100644
index 0000000000..74968c65ea
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Satisfaction.qml
@@ -0,0 +1,10 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ enum Value {
+ NONE = 0,
+ FORWARD = 1,
+ BACKWARD = 2
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml
new file mode 100644
index 0000000000..f079f4a94e
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectName.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property int objectName: 12
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml
new file mode 100644
index 0000000000..f988cd6bc9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/ShadowedObjectNameDerived.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+ShadowedObjectName {
+ property double objectName: 17.4
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml b/tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml
new file mode 100644
index 0000000000..eb3da15a3a
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/StoreMetaEnum.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ enum Foo {
+ Bar,
+ Baz
+ }
+
+ property var eF: StoreMetaEnum.Foo
+ property int bar: eF.Bar
+ property int baz: eF.Baz
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/Variable.qml b/tests/auto/qml/qmlcppcodegen/data/Variable.qml
new file mode 100644
index 0000000000..f5af97757f
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/Variable.qml
@@ -0,0 +1,22 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: variable
+ property int value: 0
+ property int mark: 0
+ property BaseConstraint determinedBy: null
+ property list<BaseConstraint> constraints: [
+ BaseConstraint {
+ satisfaction: variable.value == 0 ? Satisfaction.NONE : Satisfaction.FORWARD
+ }
+ ]
+
+ function length(): int {
+ return constraints.length
+ }
+
+ function constraint(i: int) : BaseConstraint {
+ return constraints[i];
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ambiguous.h b/tests/auto/qml/qmlcppcodegen/data/ambiguous.h
index 5ea20dbcd1..8f964d593c 100644
--- a/tests/auto/qml/qmlcppcodegen/data/ambiguous.h
+++ b/tests/auto/qml/qmlcppcodegen/data/ambiguous.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef AMBIGUOUS_H
#define AMBIGUOUS_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/ambiguousAs.qml b/tests/auto/qml/qmlcppcodegen/data/ambiguousAs.qml
new file mode 100644
index 0000000000..2b7cbd593d
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/ambiguousAs.qml
@@ -0,0 +1,15 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: self
+ property bool useSelf: true
+ property QtObject other: {
+ var a;
+ if (useSelf)
+ a = self
+ else
+ a = 15
+ return a as QtObject
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/arrayCtor.qml b/tests/auto/qml/qmlcppcodegen/data/arrayCtor.qml
new file mode 100644
index 0000000000..9886a14cb1
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/arrayCtor.qml
@@ -0,0 +1,11 @@
+pragma Strict
+import QML
+
+QtObject {
+ property list<int> defaultCtor: new Array()
+ property list<int> oneArgCtor: new Array(5)
+ property list<int> multiArgCtor: new Array(2, 3, 3, 4)
+ property list<bool> arrayTrue: new Array(true)
+ property list<bool> arrayFalse: new Array(false)
+ property list<real> arrayNegative: new Array(-14)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/asCast.qml b/tests/auto/qml/qmlcppcodegen/data/asCast.qml
index 1befc08d0a..cb8155ca6c 100644
--- a/tests/auto/qml/qmlcppcodegen/data/asCast.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/asCast.qml
@@ -28,4 +28,14 @@ Item {
property QtObject dummyAsItem: dummy as Item
property QtObject dummyAsRectangle: dummy as Rectangle
property QtObject dummyAsDummy: dummy as Dummy
+
+ property QtObject nullAsObject: null as QtObject
+ property QtObject nullAsItem: null as Item
+ property QtObject nullAsRectangle: null as Rectangle
+ property QtObject nullAsDummy: null as Dummy
+
+ property QtObject undefinedAsObject: undefined as QtObject
+ property QtObject undefinedAsItem: undefined as Item
+ property QtObject undefinedAsRectangle: undefined as Rectangle
+ property QtObject undefinedAsDummy: undefined as Dummy
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump.qml b/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump.qml
new file mode 100644
index 0000000000..5b254fe494
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump.qml
@@ -0,0 +1,33 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ function t1() {
+ let i = 0
+ let foo = false
+ if (true) {
+ for (i = 0; i < 42 ; ++i) {}
+ } else {
+ console.log(foo)
+ }
+ }
+
+ function t2() {
+ let foo = false
+ if (false) {
+ while(Math.random() < 0.5) {}
+ } else {
+ console.log(foo)
+ }
+ }
+
+ function t3() {
+ let foo = false
+ if (Math.random() < 0.5) {
+ console.log(foo)
+ } else {
+ while(Math.random() < 0.5) {}
+ console.log(foo)
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump_infinite.qml b/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump_infinite.qml
new file mode 100644
index 0000000000..997ff68736
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/basicBlocksWithBackJump_infinite.qml
@@ -0,0 +1,13 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ function infinite() {
+ let foo = false
+ if (true) {
+ while (true) {}
+ } else {
+ console.log(foo)
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/basicDTZ.qml b/tests/auto/qml/qmlcppcodegen/data/basicDTZ.qml
new file mode 100644
index 0000000000..bc9506a533
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/basicDTZ.qml
@@ -0,0 +1,40 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: win
+ property real width: 640
+ property real height: 480
+ property string title: "none"
+
+ function t1(): void {
+ const w = win.width
+ const h = win.height
+
+ if (w > 0 && h > 0) {
+ const wByH = h / 3.0 * 4.0
+ }
+ }
+
+ function t2(): void {
+ let i = 42
+ win.title = "Foo " + i
+
+ for (let j = 0; j < 10; j++) {
+ win.title = "Bar " + j
+ }
+
+ for (let k = 0; k < i; k++) {
+ win.title = "Baz " + k
+ }
+ }
+
+ function t3(): void {
+ let v1 = 1
+ let v2 = 2
+
+ if (true) {
+ v1 = v2
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp b/tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp
index 048459f03a..10a2c90b38 100644
--- a/tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp
+++ b/tests/auto/qml/qmlcppcodegen/data/birthdayparty.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "birthdayparty.h"
@@ -36,6 +36,23 @@ Person *BirthdayParty::guest(int index) const
return m_guests.at(index);
}
+QStringList BirthdayParty::guestNames() const
+{
+ QStringList names;
+ for (Person *guest: m_guests)
+ names.append(guest->name());
+ return names;
+}
+
+QVariantList BirthdayParty::stuffs() const
+{
+ return QVariantList({
+ QVariant::fromValue(objectName()),
+ QVariant::fromValue(m_guests.size()),
+ QVariant::fromValue(m_host)
+ });
+}
+
void BirthdayParty::invite(const QString &name)
{
auto *person = new Person(this);
diff --git a/tests/auto/qml/qmlcppcodegen/data/birthdayparty.h b/tests/auto/qml/qmlcppcodegen/data/birthdayparty.h
index a6871c39b1..8dd640c67f 100644
--- a/tests/auto/qml/qmlcppcodegen/data/birthdayparty.h
+++ b/tests/auto/qml/qmlcppcodegen/data/birthdayparty.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef BIRTHDAYPARTY_H
#define BIRTHDAYPARTY_H
@@ -52,7 +52,6 @@ private:
};
struct Foozle {
- Q_GADGET
int foo = 1;
};
@@ -61,6 +60,8 @@ class BirthdayParty : public QObject
Q_OBJECT
Q_PROPERTY(Person *host READ host WRITE setHost NOTIFY hostChanged FINAL)
Q_PROPERTY(QQmlListProperty<Person> guests READ guests)
+ Q_PROPERTY(QStringList guestNames READ guestNames FINAL)
+ Q_PROPERTY(QVariantList stuffs READ stuffs FINAL)
QML_ELEMENT
QML_ATTACHED(BirthdayPartyAttached)
QML_EXTENDED(BirthDayPartyExtended)
@@ -74,6 +75,9 @@ public:
int guestCount() const;
Person *guest(int) const;
+ QStringList guestNames() const;
+ QVariantList stuffs() const;
+
Q_INVOKABLE void invite(const QString &name);
static BirthdayPartyAttached *qmlAttachedProperties(QObject *object);
diff --git a/tests/auto/qml/qmlcppcodegen/data/boolCoercions.qml b/tests/auto/qml/qmlcppcodegen/data/boolCoercions.qml
new file mode 100644
index 0000000000..6b8ebb3f38
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/boolCoercions.qml
@@ -0,0 +1,45 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property rect a
+ property bool t1: a
+
+ property int c: 1
+ property bool t2: c
+
+ property url e: "qrc:/ab/c.txt"
+ property bool t3: e
+
+ property string f: "a"
+ property bool t4: f
+
+ property var j: 1
+ property bool t5: j
+
+ id: k
+ property bool t6: k
+
+ property date l
+ property bool t7: l
+
+ property url m
+ property bool t8: m
+
+
+
+ property int b: 0
+ property bool f1: b
+
+ property QtObject d: null
+ property bool f2: d
+
+ property string g
+ property bool f3: g
+
+ property var h: undefined
+ property bool f4: h
+
+ property var i: null
+ property bool f5: i
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/boolPointerMerge.qml b/tests/auto/qml/qmlcppcodegen/data/boolPointerMerge.qml
new file mode 100644
index 0000000000..b2d4d7c5d0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/boolPointerMerge.qml
@@ -0,0 +1,15 @@
+pragma Strict
+import TestTypes
+import QtQuick
+
+Loader {
+ id: self
+ source: "BaseMember.qml"
+ property int ppp: -99
+
+ onItemChanged: {
+ var base = item as BaseMember;
+ if (base)
+ base.ppp = ppp
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/childobject.qml b/tests/auto/qml/qmlcppcodegen/data/childobject.qml
index 3775ee16bc..76ad8fbbb2 100644
--- a/tests/auto/qml/qmlcppcodegen/data/childobject.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/childobject.qml
@@ -4,6 +4,19 @@ import TestTypes
QtObject {
property ObjectWithMethod child: ObjectWithMethod {
objectName: "kraut"
+
+ function doString() { overloaded("string"); }
+ function doNumber() { overloaded(5.2); }
+ function doArray() { overloaded({a: 2, b: 3, c: 3}); }
+
+ function doString2() { overloaded2("string"); }
+ function doNumber2() { overloaded2(5.2); }
+
+ // Artificially pass an extra argument to avoid choosing the "string" overload.
+ // Unfortunately this is still order-dependent on the metaobject level.
+ function doArray2() { overloaded2({a: 2, b: 3, c: 3}, 1); }
+
+ function doFoo() { foo(this); }
}
objectName: child.objectName
property int doneThing: child.doThing()
diff --git a/tests/auto/qml/qmlcppcodegen/data/compareOriginals.qml b/tests/auto/qml/qmlcppcodegen/data/compareOriginals.qml
new file mode 100644
index 0000000000..3d40ffee62
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/compareOriginals.qml
@@ -0,0 +1,39 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ component Variable: QtObject {
+ property int value: 4
+ }
+
+ property Variable first: Variable {}
+ property Variable last: Variable {
+ id: last
+ }
+
+ property int compareOriginals: {
+ var matches = 0;
+ for (var i = 0; i < 6; i++) {
+ first.value = i; // do a shadowed assignment
+ if (last.value != i)
+ ++matches
+ }
+ return matches;
+ }
+
+ property bool optionalThis: {
+ var a
+ if (2 == 2)
+ a = this
+ else
+ a = undefined
+
+ var b
+ if (2 == 2)
+ b = this
+ else
+ b = undefined
+
+ return a === b
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/comparisonTypes.qml b/tests/auto/qml/qmlcppcodegen/data/comparisonTypes.qml
new file mode 100644
index 0000000000..423cd55ed4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/comparisonTypes.qml
@@ -0,0 +1,54 @@
+import QtQml
+
+QtObject {
+ component Variable: QtObject {
+ property int value: 4
+ }
+
+ component VariableShadow: Variable {
+ property string value: "1"
+ }
+
+ property Variable last: VariableShadow {}
+
+ function find(n: int) : int {
+ var found = 0
+ for (var i = 0; i < n; i++) {
+ if (last.value == i)
+ ++found
+ }
+ return found;
+ }
+
+ function findStrict(n: int) : int {
+ var found = 0
+ for (var i = 0; i < n; i++) {
+ if (last.value === i)
+ ++found
+ }
+ return found;
+ }
+
+ function findNot(n: int) : int {
+ var found = 0
+ for (var i = 0; i < n; i++) {
+ if (last.value != i)
+ ++found
+ }
+ return found;
+ }
+
+ function findNotStrict(n: int) : int {
+ var found = 0
+ for (var i = 0; i < n; i++) {
+ if (last.value !== i)
+ ++found
+ }
+ return found;
+ }
+
+ property int found: find(3)
+ property int foundStrict: findStrict(10)
+ property int foundNot: findNot(3)
+ property int foundNotStrict: findNotStrict(10)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/consoleTrace.qml b/tests/auto/qml/qmlcppcodegen/data/consoleTrace.qml
new file mode 100644
index 0000000000..a80af89ddd
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/consoleTrace.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ function a() { b() }
+ function b() { c() }
+ function c() { console.trace() }
+ Component.onCompleted: a()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/conversionInDeadCode.qml b/tests/auto/qml/qmlcppcodegen/data/conversionInDeadCode.qml
new file mode 100644
index 0000000000..b2e7b40c00
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/conversionInDeadCode.qml
@@ -0,0 +1,32 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ // This does not look like dead code, but each access to 'result' generates a
+ // DeadTemoralZoneCheck instruction that we ignore when compiling to C++
+ // after checking statically that 'result' is alive throughout the function.
+ // Therefore, this function is a torture test for the dead code elimination.
+ function calc(a: int, b: int) : int {
+ let result = a;
+ if (b < 0) {
+ if (b < -1)
+ result -= b;
+ if (b < -2)
+ result /= b;
+ } else {
+ if (b > 1)
+ result *= b;
+ if (b > 2)
+ result += b;
+ }
+ return result;
+ }
+
+ property int a: calc(10, -3);
+ property int b: calc(10, -2);
+ property int c: calc(10, -1);
+ property int d: calc(10, 0);
+ property int e: calc(10, 1);
+ property int f: calc(10, 2);
+ property int g: calc(10, 3);
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/conversions2.qml b/tests/auto/qml/qmlcppcodegen/data/conversions2.qml
index c3a9414ae2..d0d1fc9b8f 100644
--- a/tests/auto/qml/qmlcppcodegen/data/conversions2.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/conversions2.qml
@@ -94,6 +94,8 @@ Item {
}
function qtest_signalHandlerName(sn) {
+ // Warning: to not test for signal handlers like this in actual code.
+ // Use the helper methods in QQmlSignalNames instead.
if (sn.substr(0, 2) === "on" && sn[2] === sn[2].toUpperCase())
return sn
return "on" + sn.substr(0, 1).toUpperCase() + sn.substr(1)
diff --git a/tests/auto/qml/qmlcppcodegen/data/convertPrimitiveToVar.qml b/tests/auto/qml/qmlcppcodegen/data/convertPrimitiveToVar.qml
new file mode 100644
index 0000000000..f7c2cc4058
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/convertPrimitiveToVar.qml
@@ -0,0 +1,18 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: foo
+
+ property int offsetValue
+
+ function send(data : variant) {
+ }
+
+ Component.onCompleted: () => {
+ let deltaOffset = 42
+ deltaOffset -= 1
+ foo.offsetValue = deltaOffset
+ foo.send({offset: deltaOffset})
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.h b/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.h
new file mode 100644
index 0000000000..459dd62374
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef CONVERTQJSPRIMITIVEVALUETOINTEGRAL_H
+#define CONVERTQJSPRIMITIVEVALUETOINTEGRAL_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class Moo485 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(int uid READ uid CONSTANT FINAL)
+
+public:
+ explicit Moo485(QObject *parent = nullptr) : QObject(parent) { }
+ int uid() const { return 4711; }
+};
+
+class Foo485 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(quint16 uid MEMBER m_uid FINAL)
+
+public:
+ explicit Foo485(QObject *parent = nullptr) : QObject(parent) { }
+ quint16 m_uid = 0;
+};
+
+#endif // CONVERTQJSPRIMITIVEVALUETOINTEGRAL_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.qml b/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.qml
new file mode 100644
index 0000000000..6a15d6f775
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/convertQJSPrimitiveValueToIntegral.qml
@@ -0,0 +1,13 @@
+import QtQuick
+import TestTypes
+
+
+Item {
+ id: root
+
+ property Moo485 moo
+
+ readonly property Foo485 foo: Foo485 {
+ uid: root.moo.uid ?? 0xFFFF
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/convertToOriginalReadAcumulatorForUnaryOperators.qml b/tests/auto/qml/qmlcppcodegen/data/convertToOriginalReadAcumulatorForUnaryOperators.qml
new file mode 100644
index 0000000000..6eb14bba57
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/convertToOriginalReadAcumulatorForUnaryOperators.qml
@@ -0,0 +1,13 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: self
+ property int i: 0
+ property Planner planner: null
+
+ function satisfy(mark: int) {
+ planner.addPropagate(mark);
+ i = +mark;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h b/tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h
index eecc3d968e..812415ae24 100644
--- a/tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h
+++ b/tests/auto/qml/qmlcppcodegen/data/cppbaseclass.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef CPPBASECLASS_H
#define CPPBASECLASS_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/dateConstruction.qml b/tests/auto/qml/qmlcppcodegen/data/dateConstruction.qml
new file mode 100644
index 0000000000..fc8a34da71
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/dateConstruction.qml
@@ -0,0 +1,20 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property date now: new Date()
+ property date now2: new Date(now)
+ property date fromString: new Date("1995-12-17T03:24:00")
+ property date fromNumber: new Date(777)
+ property date fromPrimitive: new Date(objectName.length === 0 ? 57 : "1997-02-13T13:04:12")
+ property date from2: new Date(1996, 1)
+ property date from3: new Date(1996, 2, 3)
+ property date from4: new Date(1996, 3, 4, 5)
+ property date from5: new Date(1996, 4, 5, 6, 7)
+ property date from6: new Date(1996, 5, 6, 7, 8, 9)
+ property date from7: new Date(1996, 6, 7, 8, 9, 10, 11)
+ property date from8: new Date(1996, 7, 8, 9, 10, 11, 12, 13)
+
+ property date withUnderflow: new Date(-4, -5, -6, -7, -8, -9, -10)
+ property date invalid: new Date("foo", "bar")
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml b/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml
index 38a34f7487..5c0a426466 100644
--- a/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/dateConversions.qml
@@ -9,12 +9,17 @@ QtObject {
property string dateString: date
property string timeString: time
+ property real dateNumber: date
+ property real timeNumber: time
+
function shuffle() {
Druggeljug.myDate = date;
Druggeljug.myTime = time;
dateString = Druggeljug.myDate;
timeString = Druggeljug.myTime;
+ dateNumber = Druggeljug.myDate;
+ timeNumber = Druggeljug.myTime;
}
function fool() {
@@ -22,4 +27,9 @@ QtObject {
Druggeljug.myTime = Druggeljug.myDate;
Druggeljug.myDate = tmp;
}
+
+ function invalidate() {
+ date = new Date("foo", "bar");
+ time = new Date("bar", "foo");
+ }
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/dialogButtonBox.qml b/tests/auto/qml/qmlcppcodegen/data/dialogButtonBox.qml
new file mode 100644
index 0000000000..b30e0124c8
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/dialogButtonBox.qml
@@ -0,0 +1,8 @@
+pragma Strict
+import QtQuick.Controls.Basic
+
+ApplicationWindow {
+ footer: DialogButtonBox {
+ standardButtons: DialogButtonBox.Ok | DialogButtonBox.Cancel
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/dummyobjekt.h b/tests/auto/qml/qmlcppcodegen/data/dummyobjekt.h
new file mode 100644
index 0000000000..ace319f91f
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/dummyobjekt.h
@@ -0,0 +1,29 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef DUMMYOBJEKT_H
+#define DUMMYOBJEKT_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+#if QT_DEPRECATED_SINCE(6, 4)
+class DummyObjekt : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ enum Test {
+ TestA = 1,
+ TestB
+ };
+ Q_ENUM(Test)
+
+ // Deliberately not default constructible
+ explicit DummyObjekt(QObject *parent) : QObject(parent) {}
+};
+#endif
+
+#endif // DUMMYOBJEKT_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h b/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
index 64c2850bda..d8358b6a9c 100644
--- a/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
+++ b/tests/auto/qml/qmlcppcodegen/data/dynamicmeta.h
@@ -1,38 +1,48 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DYNAMICMETA_H
#define DYNAMICMETA_H
#include <private/qobject_p.h>
+#include <private/qmetaobjectbuilder_p.h>
#include <QtQmlIntegration/qqmlintegration.h>
-struct FreeDeleter {
- void operator()(QMetaObject *meta) { free(meta); }
-};
-
template<typename T>
class MetaObjectData : public QDynamicMetaObjectData
{
Q_DISABLE_COPY_MOVE(MetaObjectData)
public:
- MetaObjectData() = default;
- ~MetaObjectData() = default;
+ MetaObjectData()
+ {
+ QMetaObjectBuilder builder;
+ builder.setSuperClass(&T::staticMetaObject);
+ builder.setFlags(builder.flags() | DynamicMetaObject);
+ metaObject = builder.toMetaObject();
+ };
+
+ ~MetaObjectData() {
+ free(metaObject);
+ };
QMetaObject *toDynamicMetaObject(QObject *) override
{
- return const_cast<QMetaObject *>(&T::staticMetaObject);
+ return metaObject;
}
int metaCall(QObject *o, QMetaObject::Call call, int idx, void **argv) override
{
return o->qt_metacall(call, idx, argv);
}
+
+ QMetaObject *metaObject = nullptr;
};
class DynamicMeta : public QObject
{
Q_OBJECT
Q_PROPERTY(int foo READ foo WRITE setFoo NOTIFY fooChanged FINAL)
+ Q_PROPERTY(qreal value READ value WRITE setValue RESET resetValue NOTIFY valueChanged FINAL)
+ Q_PROPERTY(qreal shadowable READ shadowable CONSTANT)
QML_ELEMENT
public:
@@ -54,11 +64,26 @@ public:
Q_INVOKABLE int bar(int baz) { return baz + 12; }
+ qreal value() const { return m_value; }
+ qreal shadowable() const { return 25; }
+
+public slots:
+ void resetValue() { setValue(0); }
+ void setValue(qreal value)
+ {
+ if (m_value == value)
+ return;
+ m_value = value;
+ emit valueChanged();
+ }
+
Q_SIGNALS:
void fooChanged();
+ void valueChanged();
private:
int m_foo = 0;
+ qreal m_value = 0;
};
class DynamicMetaSingleton : public DynamicMeta
diff --git a/tests/auto/qml/qmlcppcodegen/data/enforceSignature.qml b/tests/auto/qml/qmlcppcodegen/data/enforceSignature.qml
new file mode 100644
index 0000000000..571a000199
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/enforceSignature.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+ id: mainItem
+
+ function arg(item: Binding) : QtObject { return item }
+ function ret(item: QtObject) : Binding { return item }
+
+ property QtObject a: arg(mainItem);
+ property QtObject b: ret(mainItem);
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml b/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml
index fee2c50e15..61ddd2162d 100644
--- a/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/enumConversion.qml
@@ -1,7 +1,12 @@
+pragma Strict
import TestTypes
MyType {
id: root
+
+ property alias status: root.a
+
property int test: myEnumType.type
property bool test_1: myEnumType.type
+ objectName: root.status + "m"
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumFromBadSingleton.qml b/tests/auto/qml/qmlcppcodegen/data/enumFromBadSingleton.qml
new file mode 100644
index 0000000000..3176fde315
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/enumFromBadSingleton.qml
@@ -0,0 +1,6 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ objectName: "Dummy: " + DummyObjekt.TestA
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumMarkedAsFlag.qml b/tests/auto/qml/qmlcppcodegen/data/enumMarkedAsFlag.qml
new file mode 100644
index 0000000000..2ef37cbdf0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/enumMarkedAsFlag.qml
@@ -0,0 +1,6 @@
+import QML
+import TestTypes
+
+QtObject {
+ property int flagValue: ControlFlags.Both
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumProblems.qml b/tests/auto/qml/qmlcppcodegen/data/enumProblems.qml
index f9a4eb144b..6a57b0e64a 100644
--- a/tests/auto/qml/qmlcppcodegen/data/enumProblems.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/enumProblems.qml
@@ -11,4 +11,9 @@ QtObject {
readonly property FooThing fighter: root.f.get(Foo.Fighter)
readonly property FooThing bar: root.f.get(Foo.Component)
}
+
+ property int a: FooFactory.B
+ property int b: f.t8
+ property int c: FooFactory.D
+ property int d: f.t16
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumProperty.h b/tests/auto/qml/qmlcppcodegen/data/enumProperty.h
index 8c13e860a3..8d6405a059 100644
--- a/tests/auto/qml/qmlcppcodegen/data/enumProperty.h
+++ b/tests/auto/qml/qmlcppcodegen/data/enumProperty.h
@@ -15,20 +15,87 @@ public:
Tri = 0x04,
};
Q_ENUM(MyEnum)
- Q_PROPERTY(MyEnum type READ type)
+ Q_PROPERTY(MyEnum type READ type CONSTANT)
MyEnum type() const { return MyEnum::Tri; }
};
class MyType : public QObject
{
Q_OBJECT
- Q_PROPERTY(MyEnumType myEnumType READ myEnumType)
+ Q_PROPERTY(MyEnumType myEnumType READ myEnumType CONSTANT)
+ Q_PROPERTY(A a READ a WRITE setA NOTIFY aChanged FINAL)
QML_ELEMENT
public:
+ enum A { B, C, D };
+ Q_ENUM(A)
+
MyEnumType myEnumType() const { return m_type; }
+ A a() const { return m_a; }
+ void setA(A newA)
+ {
+ if (m_a == newA)
+ return;
+ m_a = newA;
+ emit aChanged();
+ }
+
+ Q_INVOKABLE int method(quint16, const QString &) { return 24; }
+ Q_INVOKABLE int method(quint16, MyType::A a) { return int(a); }
+
+Q_SIGNALS:
+ void aChanged();
+
private:
MyEnumType m_type;
+ A m_a = B;
+};
+
+class CommunicationPermission
+{
+ Q_GADGET
+public:
+ enum CommunicationMode : quint8 {
+ Access = 0x01,
+ Advertise = 0x02,
+ Default = Access | Advertise,
+ };
+ Q_DECLARE_FLAGS(CommunicationModes, CommunicationMode)
+ Q_FLAG(CommunicationModes)
+
+ void setCommunicationModes(CommunicationModes modes) { m_modes = modes; }
+ CommunicationModes communicationModes() const { return m_modes; }
+
+private:
+ CommunicationModes m_modes;
+};
+
+struct QQmlCommunicationPermission : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(CommunicationPermission)
+ QML_EXTENDED_NAMESPACE(CommunicationPermission)
+ Q_PROPERTY(CommunicationPermission::CommunicationModes communicationModes READ communicationModes WRITE setCommunicationmodes NOTIFY communicationModesChanged)
+
+public:
+ CommunicationPermission::CommunicationModes communicationModes() const
+ {
+ return m_permission.communicationModes();
+ }
+
+ void setCommunicationmodes(const CommunicationPermission::CommunicationModes &newCommunicationModes)
+ {
+ if (communicationModes() == newCommunicationModes)
+ return;
+ m_permission.setCommunicationModes(newCommunicationModes);
+ emit communicationModesChanged();
+ }
+
+signals:
+ void communicationModesChanged();
+
+private:
+ CommunicationPermission m_permission;
};
#endif // ENUMPROPERTY_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/enumproblems.h b/tests/auto/qml/qmlcppcodegen/data/enumproblems.h
index 08a00acf7e..36f97bec5a 100644
--- a/tests/auto/qml/qmlcppcodegen/data/enumproblems.h
+++ b/tests/auto/qml/qmlcppcodegen/data/enumproblems.h
@@ -1,10 +1,11 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef ENUMPROBLEMS_H
#define ENUMPROBLEMS_H
#include <QObject>
+#include <QtCore/qflags.h>
#include <QtQml/qqml.h>
#include <QtQml/qqmlregistration.h>
@@ -45,9 +46,74 @@ class FooThingWrapper {
class FooFactory : public QObject {
Q_OBJECT
QML_ELEMENT
+ Q_PROPERTY(T8 t8 READ t8 CONSTANT FINAL)
+ Q_PROPERTY(T16 t16 READ t16 CONSTANT FINAL)
public:
+ enum T8: qint8 {
+ A, B, C
+ };
+ Q_ENUM(T8)
+
+ enum T16: qint16 {
+ D = 500, E, F
+ };
+ Q_ENUM(T16)
+
+ T8 t8() const { return C; }
+ T16 t16() const { return E; }
+
Q_INVOKABLE Foo* get(Foo::Type type) const { return new Foo(type); }
};
+class ControlFlags : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_UNCREATABLE("Flag Container Class")
+public:
+
+ enum Option {
+ ControlA = 0x1,
+ ControlB = 0x2,
+ Both = ControlA | ControlB
+ };
+
+ Q_DECLARE_FLAGS(Options, Option)
+ Q_FLAG(Option)
+};
+
+class ScopedEnum : public QObject {
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Data)
+ Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
+
+public:
+ enum class DType {
+ A = 27, B
+ };
+ Q_ENUM(DType)
+
+ enum EType {
+ C = 7, D
+ };
+ Q_ENUM(EType)
+};
+
+class UnscopedEnum : public QObject {
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Data2)
+ Q_CLASSINFO("RegisterEnumClassesUnscoped", "true")
+
+public:
+ enum class DType {
+ A = 26, B
+ };
+ Q_ENUM(DType)
+
+ enum EType {
+ C = 6, D
+ };
+ Q_ENUM(EType)
+};
+
#endif // ENUMPROBLEMS_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/equalityQUrl.qml b/tests/auto/qml/qmlcppcodegen/data/equalityQUrl.qml
new file mode 100644
index 0000000000..55ac68592c
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/equalityQUrl.qml
@@ -0,0 +1,16 @@
+pragma Strict
+import QtQuick
+
+Item {
+ property url emptyUrl: ""
+ property url sourceUrl: "some/path/file.png"
+
+ property bool emptyUrlStrict: emptyUrl === Qt.resolvedUrl("")
+ property bool emptyUrlWeak: emptyUrl == Qt.resolvedUrl("")
+
+ property bool sourceUrlStrict: sourceUrl === Qt.url("some/path/file.png");
+ property bool sourceUrlWeak: sourceUrl == Qt.url("some/path/file.png");
+
+ property bool sourceIsNotEmptyStrict: sourceUrl !== emptyUrl
+ property bool sourceIsNotEmptyWeak: sourceUrl != emptyUrl
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/equalityTestsWithNullOrUndefined.qml b/tests/auto/qml/qmlcppcodegen/data/equalityTestsWithNullOrUndefined.qml
new file mode 100644
index 0000000000..cd0c433ea9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/equalityTestsWithNullOrUndefined.qml
@@ -0,0 +1,14 @@
+pragma Strict
+
+import QtQml
+import QtQuick
+
+Window {
+ property var foo
+ Component.onCompleted: {
+ console.log(foo !== null)
+ console.log(foo === null)
+ console.log(foo !== undefined)
+ console.log(foo === undefined)
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/exceptionFromInner.qml b/tests/auto/qml/qmlcppcodegen/data/exceptionFromInner.qml
new file mode 100644
index 0000000000..13855356f2
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/exceptionFromInner.qml
@@ -0,0 +1,10 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property QtObject theNull: null
+
+ function doFail() : string { return theNull.objectName }
+ function delegateFail() : string { doFail() }
+ function disbelieveFail() : string { delegateFail() }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/extra/extra.qml b/tests/auto/qml/qmlcppcodegen/data/extra/extra.qml
new file mode 100644
index 0000000000..e8f51984b8
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/extra/extra.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+B {
+ r: ({x: 4, y: 6, width: 8, height: 10})
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/extra2/extra.qml b/tests/auto/qml/qmlcppcodegen/data/extra2/extra.qml
new file mode 100644
index 0000000000..e8f51984b8
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/extra2/extra.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+B {
+ r: ({x: 4, y: 6, width: 8, height: 10})
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/failures.qml b/tests/auto/qml/qmlcppcodegen/data/failures.qml
index f90fb44fe1..3b0e4908ab 100644
--- a/tests/auto/qml/qmlcppcodegen/data/failures.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/failures.qml
@@ -9,6 +9,7 @@ QtObject {
property string attachedForNasty: Nasty.objectName
property Nasty nasty: Nasty {
+ id: theNasty
objectName: Component.objectName
}
@@ -30,18 +31,10 @@ QtObject {
Component.onCompleted: doesNotExist()
- property string aString: self + "a"
-
property BirthdayParty party: BirthdayParty {
onPartyStarted: (foozle) => { objectName = foozle }
}
- signal foo()
- signal bar()
-
- // Cannot assign potential undefined
- onFoo: objectName = self.bar()
-
property int enumFromGadget1: GadgetWithEnum.CONNECTED + 1
property int enumFromGadget2: TT2.GadgetWithEnum.CONNECTED + 1
@@ -62,4 +55,55 @@ QtObject {
let a;
return a;
}
+
+ function getText(myArr: list<string>): string {
+ myArr.shiftss()
+ }
+
+ function readTracks(metadataList : list<badType>): int {
+ return metadataList.length
+ }
+
+ function dtzFail() : int {
+ for (var a = 10; a < 20; ++a) {
+ switch (a) {
+ case 11:
+ let b = 5;
+ break;
+ case 10:
+ console.log(b);
+ break;
+ }
+ }
+ return a;
+ }
+
+ // TODO: Drop these once we can manipulate QVariant-wrapped lists.
+ property list<withLength> withLengths
+ property int l: withLengths.length
+ property withLength w: withLengths[10]
+
+ property unconstructibleWithLength uwl: 12 + 1
+
+ // Cannot generate code for getters
+ property rect r3: ({ get x() { return 42; }, y: 4 })
+
+ property int nonIterable: {
+ var result = 1;
+ for (var a in Component)
+ ++result;
+ return result;
+ }
+
+ property alias selfself: self
+ property alias nastyBad: theNasty.bad
+ function writeToUnknown() : int {
+ self.selfself.nastyBad = undefined;
+ return 5;
+ }
+
+ readonly property int someNumber: 10
+ function writeToReadonly() { someNumber = 20 }
+
+ property var silly: [,0]
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/fallbackresettable.qml b/tests/auto/qml/qmlcppcodegen/data/fallbackresettable.qml
new file mode 100644
index 0000000000..44b55e245a
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/fallbackresettable.qml
@@ -0,0 +1,23 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+DynamicMeta {
+ id: self
+ value: 999
+
+ property double notResettable: 10
+ property double notResettable2: { return undefined }
+
+ property DynamicMeta shadowing: DynamicMeta {
+ property var shadowable: undefined
+ }
+
+ function doReset() { self.value = undefined }
+ function doReset2() { self.value = shadowing.shadowable }
+ function doNotReset() { self.notResettable = undefined }
+
+ signal aaa()
+ signal bbb()
+ onAaa: objectName = self.bbb()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/fileDialog.qml b/tests/auto/qml/qmlcppcodegen/data/fileDialog.qml
index b8bd466717..6634982de2 100644
--- a/tests/auto/qml/qmlcppcodegen/data/fileDialog.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/fileDialog.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
diff --git a/tests/auto/qml/qmlcppcodegen/data/flagEnum.qml b/tests/auto/qml/qmlcppcodegen/data/flagEnum.qml
new file mode 100644
index 0000000000..3ea5cf98db
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/flagEnum.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import TestTypes
+
+CommunicationPermission {
+ communicationModes: CommunicationPermission.Access
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h b/tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h
index 839e026b77..3c81cd2e7f 100644
--- a/tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h
+++ b/tests/auto/qml/qmlcppcodegen/data/gadgetwithenum.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef GADGETWITHENUM_H
#define GADGETWITHENUM_H
@@ -26,4 +26,40 @@ namespace GadgetWithEnumWrapper {
QML_NAMED_ELEMENT(NamespaceWithEnum)
};
+struct Gadget
+{
+ Q_GADGET
+ QML_VALUE_TYPE(gadget)
+
+public:
+ enum class Prop1 { High, low, VeryHigh, VeryLow };
+ Q_ENUM(Prop1)
+
+ enum class Prop2 { VeryHigh, High, low, VeryLow };
+ Q_ENUM(Prop2)
+};
+
+class Backend : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ Q_PROPERTY(prop priority READ priority FINAL CONSTANT)
+ Q_PROPERTY(Gadget gadget READ gadget FINAL CONSTANT)
+ Q_CLASSINFO("RegisterEnumsFromRelatedTypes", "false")
+
+public:
+ enum prop { High, low, VeryHigh, VeryLow };
+ Q_ENUM(prop)
+
+ explicit Backend(QObject *parent = nullptr) : QObject(parent) {}
+
+ prop priority() const { return m_priority; }
+ Gadget gadget() const { return m_gadget; }
+
+private:
+ prop m_priority = low;
+ Gadget m_gadget;
+};
+
#endif // GADGETWITHENUM_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.h b/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.h
new file mode 100644
index 0000000000..e8a24cd707
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.h
@@ -0,0 +1,42 @@
+#ifndef GETOPTIONALLOOKUP_H
+#define GETOPTIONALLOOKUP_H
+
+#include <QObject>
+#include <QQmlEngine>
+
+class GOL_Object : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(int i READ i CONSTANT FINAL)
+ Q_PROPERTY(QString s READ s CONSTANT FINAL)
+ Q_PROPERTY(GOL_Object *childA READ childA WRITE setChildA NOTIFY childAChanged FINAL)
+ Q_PROPERTY(Enum e READ e CONSTANT FINAL)
+
+public:
+ GOL_Object(QObject *parent = nullptr) : QObject(parent) { }
+
+ int i() const { return m_i; }
+ void setI(int i) { m_i = i; }
+
+ QString s() const { return m_s; }
+ void setS(QString s) { m_s = s; }
+
+ GOL_Object *childA() const { return m_childA; }
+ void setChildA(GOL_Object *a) { m_childA = a; }
+
+ enum Enum { V1, V2 };
+ Q_ENUM(Enum)
+ Enum e() const { return Enum::V2; }
+
+signals:
+ void childAChanged();
+
+private:
+ int m_i = 5;
+ QString m_s = "6";
+ GOL_Object *m_childA = nullptr;
+};
+
+#endif // GETOPTIONALLOOKUP_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.qml b/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.qml
new file mode 100644
index 0000000000..ee360d7142
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/getOptionalLookup.qml
@@ -0,0 +1,34 @@
+pragma Strict
+pragma ValueTypeBehavior: Addressable
+
+import QtQuick
+
+GOL_Object {
+ id: root
+
+ property rect r: Qt.rect(0, 0, 20, 50)
+ property point p: Qt.point(0, -10)
+ property var v: Qt.point(5, 5)
+ property var u: undefined
+
+ property int to1: root?.i
+ property string to2: root?.s
+ property GOL_Object to3: root?.childA
+ property var to4: root.childA?.i
+ property var to5: (undefined as GOL_Object)?.childA
+ property int to6: (root as GOL_Object)?.s.length
+
+ property int tv1: root.r?.bottom
+ property int tv2: root.p?.y
+
+ property int te1: root?.e
+ property int te2: GOL_Object?.V2
+ property bool te3: root?.e === GOL_Object?.V1
+ property bool te4: root?.e === GOL_Object?.V2
+
+ property int tc1: root?.p.y
+ property int tc2: root.r?.x
+
+ property var tc4: root?.childA?.s
+ property var tc5: root.childA?.s
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/idAccess.qml b/tests/auto/qml/qmlcppcodegen/data/idAccess.qml
index 2090926872..6ca1f7f66b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/idAccess.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/idAccess.qml
@@ -1,3 +1,4 @@
+pragma Strict
import QtQuick
Item {
@@ -11,5 +12,9 @@ Item {
Text {
id: ttt
+ onTextChanged: {
+ root.objectName = "dead"
+ ttt.objectName = "context"
+ }
}
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/ignoredFunctionReturn.qml b/tests/auto/qml/qmlcppcodegen/data/ignoredFunctionReturn.qml
new file mode 100644
index 0000000000..640e2bc22a
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/ignoredFunctionReturn.qml
@@ -0,0 +1,14 @@
+import QtQuick
+
+Item {
+ id: root
+
+ Component {
+ id: comp
+ Rectangle {
+ color: "blue"
+ }
+ }
+
+ Component.onCompleted: comp.createObject(root, {"width": 200, "height": 200})
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml b/tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml
new file mode 100644
index 0000000000..de31527e5b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/indirectlyShadowable.qml
@@ -0,0 +1,39 @@
+import QtQml
+
+QtObject {
+ id: self
+ objectName: "self"
+
+ component Inner : QtObject {
+ property QtObject shadowable: QtObject {
+ objectName: "shadowable"
+ }
+ }
+
+ component Outer : QtObject {
+ property Inner inner: Inner {}
+ }
+
+ component Evil : Outer {
+ property string inner: "evil"
+ }
+
+ property Outer outer: Outer {}
+ property Outer evil: Evil {}
+
+ property QtObject notShadowable: QtObject {
+ objectName: "notShadowable"
+ }
+
+ function getInnerShadowable() {
+ notShadowable = outer.inner.shadowable;
+ }
+
+ function setInnerShadowable() {
+ outer.inner.shadowable = self;
+ }
+
+ function turnEvil() {
+ outer = evil;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/intToEnum.qml b/tests/auto/qml/qmlcppcodegen/data/intToEnum.qml
new file mode 100644
index 0000000000..e255f4e8f4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/intToEnum.qml
@@ -0,0 +1,7 @@
+pragma Strict
+import TestTypes
+
+MyType {
+ a: myEnumType.type === 4 ? 2 : 1
+ property int b: method("12", "hh")
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/interactive.qml b/tests/auto/qml/qmlcppcodegen/data/interactive.qml
index e857df96e7..be5e5f0d40 100644
--- a/tests/auto/qml/qmlcppcodegen/data/interactive.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/interactive.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
pragma Strict
import QtQuick 2.9
diff --git a/tests/auto/qml/qmlcppcodegen/data/internalConversion.qml b/tests/auto/qml/qmlcppcodegen/data/internalConversion.qml
new file mode 100644
index 0000000000..7304b7a6b9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/internalConversion.qml
@@ -0,0 +1,16 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property QtObject offset: QtObject {
+ id: a
+ property string mark
+ }
+
+ function markInputs(mark: string) {
+ offset.objectName = mark;
+ a.mark = mark;
+ }
+
+ Component.onCompleted: markInputs("hello")
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/invisible.h b/tests/auto/qml/qmlcppcodegen/data/invisible.h
index a385ee975f..4f4ebb87ad 100644
--- a/tests/auto/qml/qmlcppcodegen/data/invisible.h
+++ b/tests/auto/qml/qmlcppcodegen/data/invisible.h
@@ -1,11 +1,12 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef INVISIBLE_H
#define INVISIBLE_H
#include <QtCore/qobject.h>
#include <QtQmlIntegration/qqmlintegration.h>
+#include <QtQml/qqmllist.h>
class Invisible : public QObject
{
@@ -45,6 +46,39 @@ class DerivedFromInvisible : public Invisible
{
Q_OBJECT
QML_ELEMENT
+ Q_PROPERTY(double implicitWidth MEMBER m_implicitWidth NOTIFY implicitWidthChanged FINAL)
+public:
+ DerivedFromInvisible(QObject *parent = nullptr) : Invisible(parent) {}
+
+signals:
+ void implicitWidthChanged();
+
+private:
+ double m_implicitWidth = 27;
+};
+
+class WithListPropertyOfDerivedFromInvisible : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QQmlListProperty<DerivedFromInvisible> children READ children NOTIFY childrenChanged FINAL)
+
+public:
+ WithListPropertyOfDerivedFromInvisible(QObject *parent = nullptr) : QObject(parent)
+ {
+ m_children.append(new DerivedFromInvisible(this));
+ }
+
+ QQmlListProperty<DerivedFromInvisible> children()
+ {
+ return QQmlListProperty<DerivedFromInvisible>(this, &m_children);
+ }
+
+signals:
+ void childrenChanged();
+
+private:
+ QList<DerivedFromInvisible *> m_children;
};
#endif // INVISIBLE_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/iteration.qml b/tests/auto/qml/qmlcppcodegen/data/iteration.qml
new file mode 100644
index 0000000000..8632eefa1b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/iteration.qml
@@ -0,0 +1,20 @@
+pragma Strict
+
+import QtQml
+
+QtObject {
+ property list<int> ints: [3, 4, 5]
+ property list<QtObject> objects: [
+ QtObject { objectName: "a" },
+ QtObject { objectName: "b" },
+ QtObject { objectName: "c" }
+ ]
+
+ Component.onCompleted: {
+ for (var a in objects) {
+ objectName += objects[a].objectName;
+ for (var b in ints)
+ objectName += ints[b];
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/jsArrayMethods.qml b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethods.qml
new file mode 100644
index 0000000000..ff372bca45
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethods.qml
@@ -0,0 +1,28 @@
+pragma Strict
+import QML
+
+QtObject {
+ id: self
+
+ property QtObject l1: QtObject { objectName: "klaus" }
+ property QtObject l2: QtObject { function toString(): string { return "teil" } }
+ property QtObject l3: QtObject { }
+
+ function jsArray() : list<var> { return [l1, l2, l3, l1, l2, l3] }
+ property list<QtObject> listProperty: [l1, l2, l3, l1, l2, l3]
+
+ property string jsArrayToString: jsArray().toString()
+ property string listPropertyToString: listProperty.toString()
+
+ property bool listPropertyIncludes: listProperty.includes(l3)
+ property bool jsArrayIncludes: jsArray().includes(l3)
+
+ property string listPropertyJoin: listProperty.join()
+ property string jsArrayJoin: jsArray().join()
+
+ property int listPropertyIndexOf: listProperty.indexOf(l2)
+ property int jsArrayIndexOf: jsArray().indexOf(l2)
+
+ property int listPropertyLastIndexOf: listProperty.lastIndexOf(l3)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(l3)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsUntyped.qml b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsUntyped.qml
new file mode 100644
index 0000000000..7426c692fe
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsUntyped.qml
@@ -0,0 +1,17 @@
+import QML
+
+QtObject {
+ id: self
+
+ property QtObject l1
+ property QtObject l2
+ property QtObject l3
+
+ function jsArray() { return [l1, l2, l3, l1, l2, l3] }
+
+ property string jsArrayToString: jsArray().toString()
+ property bool jsArrayIncludes: jsArray().includes(l3)
+ property string jsArrayJoin: jsArray().join()
+ property int jsArrayIndexOf: jsArray().indexOf(l2)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(l3)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParams.qml b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParams.qml
new file mode 100644
index 0000000000..293e7cbda5
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParams.qml
@@ -0,0 +1,26 @@
+pragma Strict
+import QML
+
+QtObject {
+ id: self
+
+ required property int i
+ required property int j
+ required property int k
+
+ property QtObject l1: QtObject { objectName: "klaus" }
+ property QtObject l2: QtObject { function toString(): string { return "teil" } }
+ property QtObject l3: QtObject { }
+
+ function jsArray() : list<var> { return [l1, l2, l3, l1, l2, l3] }
+ property list<QtObject> listProperty: [l1, l2, l3, l1, l2, l3]
+
+ property list<QtObject> listPropertySlice: listProperty.slice(i, j)
+ property list<var> jsArraySlice: jsArray().slice(i, j)
+
+ property int listPropertyIndexOf: listProperty.indexOf(l2, i)
+ property int jsArrayIndexOf: jsArray().indexOf(l2, i)
+
+ property int listPropertyLastIndexOf: listProperty.lastIndexOf(l3, i)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(l3, i)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParamsUntyped.qml b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParamsUntyped.qml
new file mode 100644
index 0000000000..9e928bd6f6
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/jsArrayMethodsWithParamsUntyped.qml
@@ -0,0 +1,18 @@
+import QML
+
+QtObject {
+ id: self
+
+ required property int i
+ required property int j
+ required property int k
+
+ property QtObject l1
+ property QtObject l2
+ property QtObject l3
+
+ function jsArray() { return [l1, l2, l3, l1, l2, l3] }
+ property var jsArraySlice: jsArray().slice(i, j)
+ property int jsArrayIndexOf: jsArray().indexOf(l2, i)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(l3, i)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/listConversion.qml b/tests/auto/qml/qmlcppcodegen/data/listConversion.qml
new file mode 100644
index 0000000000..ca86d9a1d6
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/listConversion.qml
@@ -0,0 +1,17 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+BirthdayParty {
+ id: self
+
+ guests: [
+ Person { name: "Horst 1" },
+ Person { name: "Horst 2" },
+ Person { name: "Horst 3" }
+ ]
+
+ property list<QtObject> o: self.guests
+ property list<string> s: self.guestNames
+ property list<var> v: self.stuffs
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/listOfInvisible.qml b/tests/auto/qml/qmlcppcodegen/data/listOfInvisible.qml
new file mode 100644
index 0000000000..f3698d78ab
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/listOfInvisible.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import TestTypes
+
+WithListPropertyOfDerivedFromInvisible {
+ property real width: children[0].implicitWidth
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/listToString.qml b/tests/auto/qml/qmlcppcodegen/data/listToString.qml
new file mode 100644
index 0000000000..e9e4b85956
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/listToString.qml
@@ -0,0 +1,25 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property list<string> stringList: ["one", "two"]
+ property list<int> intList: [1, 2]
+ property list<QtObject> objectList: [this, this]
+
+ Component.onCompleted: {
+ console.log(stringList)
+ console.log(stringList + "")
+
+ console.log(intList)
+ console.log(intList + "")
+
+ console.log(objectList)
+ console.log(objectList + "")
+
+ console.log(["a", "b"]);
+
+ // TODO: Cannot do this, yet, because we cannot coerce a list to string on the fly.
+ // We need to store it as list first.
+ // console.log(["a", "b"] + "");
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/listprovider.h b/tests/auto/qml/qmlcppcodegen/data/listprovider.h
new file mode 100644
index 0000000000..076944b586
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/listprovider.h
@@ -0,0 +1,24 @@
+#ifndef QLISTPROVIDER_H
+#define QLISTPROVIDER_H
+
+#include <QObject>
+#include <QQmlEngine>
+
+class QListProvider : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(ListProvider)
+
+public:
+ explicit QListProvider(QObject *parent = nullptr) : QObject(parent) { }
+
+ Q_INVOKABLE QList<int> intList() const
+ {
+ QList<int> list;
+ for (int i = 0; i < 3; ++i)
+ list.append(i);
+ return list;
+ }
+};
+
+#endif // QLISTPROVIDER_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/math.qml b/tests/auto/qml/qmlcppcodegen/data/math.qml
index cc6cd3741a..ad6303e682 100644
--- a/tests/auto/qml/qmlcppcodegen/data/math.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/math.qml
@@ -3,4 +3,5 @@ import QML
QtObject {
property int a: Math.max(5, 7, 9, -111)
property var b: 50 / 22
+ property real c: Math.PI * 2
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/mathMinMax.qml b/tests/auto/qml/qmlcppcodegen/data/mathMinMax.qml
new file mode 100644
index 0000000000..654b699918
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/mathMinMax.qml
@@ -0,0 +1,59 @@
+pragma Strict
+import QtQml
+import QtQuick
+
+Rectangle {
+ Component.onCompleted: {
+ // Math.max()
+ console.log(Math.max(1, 1));
+ console.log(Math.max(1, 2));
+ console.log(Math.max(2, 1));
+ console.log(Math.max(0, 0));
+ console.log(Math.max(-1, 0));
+ console.log(Math.max(0, -1));
+ console.log(Math.max(-1, -1));
+
+ console.log(Math.max(0, 0, 0));
+ console.log(Math.max(0, 0, 1, 0, 0, 0));
+ console.log(Math.max(-2, -1, 0, 1, 2));
+ console.log(Math.max(2, 1, 0, -1, -2));
+ console.log(Math.max(9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ console.log(Math.max(0.0, 0.0, 0.0))
+ console.log(Math.max(-0.001, 0.001, 0.002))
+ console.log(Math.max(5.4, 1, 0.002))
+ console.log(Math.max(null, 0, -1, 8E-2, NaN, undefined, true, false, Infinity))
+ console.log(Math.max(0, -1, 8E-2, true, false, Infinity))
+ console.log(Math.max(0, -1, 8E-2, true, false))
+ console.log(Math.max(0, -1, 8E-2, false))
+ console.log(Math.max(0, -1, 8E-2, true, false, Infinity))
+ console.log(Math.max(-1, -8, null))
+ console.log(Math.max(undefined, 20, 70))
+
+ // Math.min()
+ console.log(Math.min(1, 1));
+ console.log(Math.min(1, +2));
+ console.log(Math.min(2, 1));
+ console.log(Math.min(0, 0));
+ console.log(Math.min(-1, 0));
+ console.log(Math.min(0, -1));
+ console.log(Math.min(-1, -1));
+
+ console.log(Math.min(0, 0, 0));
+ console.log(Math.min(0, 0, 1, 0, 0, 0));
+ console.log(Math.min(-2, -1, 0, 1, 2));
+ console.log(Math.min(2, 1, 0, -1, -2));
+ console.log(Math.min(9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ console.log(Math.min(0.0, 0.0, 0.0))
+ console.log(Math.min(-0.001, 0.001, 0.002))
+ console.log(Math.min(5.4, 1, 0.002))
+ console.log(Math.min(null, 0, -1, 8E-2, NaN, undefined, true, false, Infinity))
+ console.log(Math.min(0, -1, 8E-2, true, false, Infinity))
+ console.log(Math.min(0, -1, 8E-2, true, false))
+ console.log(Math.min(0, -1, 8E-2, false))
+ console.log(Math.min(0, -1, 8E-2, true, false, Infinity))
+ console.log(Math.min(-1, -8, null))
+ console.log(Math.min(undefined, 20, 70))
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/mathStaticProperties.qml b/tests/auto/qml/qmlcppcodegen/data/mathStaticProperties.qml
new file mode 100644
index 0000000000..fad74a28bd
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/mathStaticProperties.qml
@@ -0,0 +1,17 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+pragma Strict
+
+import QML
+
+QtObject {
+ property double e: Math.E
+ property double ln10: Math.LN10
+ property double ln2: Math.LN2
+ property double log10e: Math.LOG10E
+ property double log2e: Math.LOG2E
+ property double pi: Math.PI
+ property double sqrt1_2: Math.SQRT1_2
+ property double sqrt2: Math.SQRT2
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/mergedObjectRead.qml b/tests/auto/qml/qmlcppcodegen/data/mergedObjectRead.qml
new file mode 100644
index 0000000000..161e21e643
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/mergedObjectRead.qml
@@ -0,0 +1,14 @@
+pragma Strict
+import QtQuick
+
+Item {
+ objectName: "a"
+
+ function f(arg: Item) : string {
+ // Read arg as QtObject and Item, merged into QtObject.
+ console.log(arg)
+ return arg.x
+ }
+
+ Component.onCompleted: objectName = f(null)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/mergedObjectWrite.qml b/tests/auto/qml/qmlcppcodegen/data/mergedObjectWrite.qml
new file mode 100644
index 0000000000..5f4bb4ff87
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/mergedObjectWrite.qml
@@ -0,0 +1,15 @@
+pragma Strict
+import QtQuick
+
+Item {
+ objectName: "a"
+
+ function f(arg: Item) : string {
+ // Write arg as Item, read it as QtObject.
+ arg.x = 5
+ console.log(arg)
+ return arg.objectName
+ }
+
+ Component.onCompleted: objectName = f(null)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/methodOnListLookup.qml b/tests/auto/qml/qmlcppcodegen/data/methodOnListLookup.qml
new file mode 100644
index 0000000000..b6b7179438
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/methodOnListLookup.qml
@@ -0,0 +1,16 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+QtObject {
+ objectName: people[0].getName()
+ property list<Person> people: [
+ Person {
+ name: "no one"
+ }
+ ]
+
+ function boom() : string {
+ return people[1].getName()
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/methods.qml b/tests/auto/qml/qmlcppcodegen/data/methods.qml
index 3abd14c9c1..c045c2249b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/methods.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/methods.qml
@@ -35,6 +35,8 @@ BirthdayParty {
}
function stuff(sn) {
+ // Warning: to not test for signal handlers like this in actual code.
+ // Use the helper methods in QQmlSignalNames instead.
if (sn.substr(0, 2) === "on" && sn[2] === sn[2].toUpperCase())
return sn
return "on" + sn.substr(0, 1).toUpperCase() + sn.substr(1)
diff --git a/tests/auto/qml/qmlcppcodegen/data/multiforeign.h b/tests/auto/qml/qmlcppcodegen/data/multiforeign.h
index 290b6370f5..6c46d5ad86 100644
--- a/tests/auto/qml/qmlcppcodegen/data/multiforeign.h
+++ b/tests/auto/qml/qmlcppcodegen/data/multiforeign.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef MULTIFOREIGN_H
#define MULTIFOREIGN_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/multipleCtors.qml b/tests/auto/qml/qmlcppcodegen/data/multipleCtors.qml
new file mode 100644
index 0000000000..61dfdb7ca5
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/multipleCtors.qml
@@ -0,0 +1,13 @@
+pragma Strict
+
+import TestTypes
+import QtQml
+
+QtObject {
+ property rect r: Qt.rect(1, 2, 3, 4)
+ property point p: Qt.point(5, 6);
+
+ property withLength wr: r
+ property withLength wp: p
+ property withLength wi: 17
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/nullAccessInsideSignalHandler.qml b/tests/auto/qml/qmlcppcodegen/data/nullAccessInsideSignalHandler.qml
new file mode 100644
index 0000000000..8fe47b7296
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/nullAccessInsideSignalHandler.qml
@@ -0,0 +1,33 @@
+import QtQuick
+
+Item {
+ id: root
+ visible: true
+
+ property var speaker
+ signal say_hello()
+
+ Component{
+ id: speakerComp
+ Text {
+ text: "HELLO"
+ function say_hello() {
+ console.log(text)
+ }
+ }
+ }
+
+ Timer {
+ interval: 1; running: true; repeat: false
+ onTriggered: root.say_hello();
+ }
+
+ Component.onCompleted:
+ {
+ root.speaker = speakerComp.createObject(root);
+
+ root.say_hello.connect(root.speaker.say_hello);
+
+ root.speaker.destroy();
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/nullComparison.qml b/tests/auto/qml/qmlcppcodegen/data/nullComparison.qml
index 1f9af7169b..53b3697c9b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/nullComparison.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/nullComparison.qml
@@ -6,6 +6,7 @@ QtObject {
property int w: 1
property int x: 1
property int y: 1
+ property int z: 1
Component.onCompleted: {
var g = null;
if (g !== null) {
@@ -22,5 +23,15 @@ QtObject {
if (h === undefined) {
y = 5;
}
+
+ var o = this;
+ if (o != null)
+ z += 7;
+ if (o == null)
+ z += 6;
+ if (g == null)
+ z += 10;
+ if (g != null)
+ z += 20;
}
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/nullishCoalescing.qml b/tests/auto/qml/qmlcppcodegen/data/nullishCoalescing.qml
new file mode 100644
index 0000000000..f84f93c5d2
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/nullishCoalescing.qml
@@ -0,0 +1,37 @@
+pragma Strict
+pragma ValueTypeBehavior: Addressable
+
+import QtQuick
+
+GOL_Object {
+ id: root
+
+ property int p1: 5 ?? -1
+ property string p2: "6" ?? "-1"
+
+ property var p3: undefined ?? undefined
+ property var p4: undefined ?? null
+ property var p5: undefined ?? -1
+ property var p6: undefined ?? "-1"
+
+ property var p7: null ?? undefined
+ property var p8: null ?? null
+ property var p9: null ?? -1
+ property var p10: null ?? "-1"
+
+ property int p11: GOL_Object.V2 ?? "-1"
+
+ property int p12: 1 ?? 2 ?? 3
+ property int p13: "1" ?? "2" ?? "3"
+ property var p14: undefined ?? "2" ?? undefined
+ property var p15: undefined ?? undefined ?? 1
+
+ property var p16
+ property var p17
+
+ Component.onCompleted: {
+ p16 = (root.childA as GOL_Object)?.i ?? -1
+ root.childA = root
+ p17 = (root.childA as GOL_Object)?.i ?? -1
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml b/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml
index f12d3f5ea2..ec848429e8 100644
--- a/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/numbersInJsPrimitive.qml
@@ -4,23 +4,57 @@ import TestTypes
QtObject {
function writeValues() {
+ Druggeljug.myInt8 = 35
+ Druggeljug.myUint8 = 36
+ Druggeljug.myInt16 = 37
+ Druggeljug.myUint16 = 38
Druggeljug.myInt = 39
Druggeljug.myUint = 40
Druggeljug.myInt32 = 41
Druggeljug.myUint32 = 42
}
+ function negateValues() {
+ Druggeljug.myInt8 = -Druggeljug.myInt8;
+ Druggeljug.myUint8 = -Druggeljug.myUint8;
+ Druggeljug.myInt16 = -Druggeljug.myInt16;
+ Druggeljug.myUint16 = -Druggeljug.myUint16;
+ Druggeljug.myInt = -Druggeljug.myInt;
+ Druggeljug.myUint = -Druggeljug.myUint;
+ Druggeljug.myInt32 = -Druggeljug.myInt32;
+ Druggeljug.myUint32 = -Druggeljug.myUint32;
+ }
+
+ function shuffleValues() {
+ Druggeljug.myInt8 = Druggeljug.myUint8;
+ Druggeljug.myUint8 = Druggeljug.myInt16;
+ Druggeljug.myInt16 = Druggeljug.myUint16;
+ Druggeljug.myUint16 = Druggeljug.myInt;
+ Druggeljug.myInt = Druggeljug.myUint;
+ Druggeljug.myUint = Druggeljug.myInt32;
+ Druggeljug.myInt32 = Druggeljug.myUint32;
+ Druggeljug.myUint32 = Druggeljug.myInt8;
+ }
+
function readValueAsString(i: int) : string {
switch (i) {
- case 0: return Druggeljug.myInt;
- case 1: return Druggeljug.myUint;
- case 2: return Druggeljug.myInt32;
- case 3: return Druggeljug.myUint32;
+ case 0: return Druggeljug.myInt8;
+ case 1: return Druggeljug.myUint8;
+ case 2: return Druggeljug.myInt16;
+ case 3: return Druggeljug.myUint16;
+ case 4: return Druggeljug.myInt;
+ case 5: return Druggeljug.myUint;
+ case 6: return Druggeljug.myInt32;
+ case 7: return Druggeljug.myUint32;
default: return "";
}
}
function storeValues() {
+ Druggeljug.storeMyInt8(1330)
+ Druggeljug.storeMyUint8(1331)
+ Druggeljug.storeMyInt16(1332)
+ Druggeljug.storeMyUint16(1333)
Druggeljug.storeMyInt(1334)
Druggeljug.storeMyUint(1335)
Druggeljug.storeMyInt32(1336)
diff --git a/tests/auto/qml/qmlcppcodegen/data/objectLookupOnListElement.qml b/tests/auto/qml/qmlcppcodegen/data/objectLookupOnListElement.qml
new file mode 100644
index 0000000000..4804921b02
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/objectLookupOnListElement.qml
@@ -0,0 +1,34 @@
+pragma Strict
+import QtQuick
+
+Item {
+ id: stack
+
+ property int current: 0
+
+ onCurrentChanged: setZOrders()
+ Component.onCompleted: setZOrders()
+
+ function setZOrders() {
+ for (var i = 0; i < Math.max(stack.children.length, 3); ++i) {
+ stack.children[i].z = (i == current ? 1 : 0)
+ stack.children[i].enabled = (i == current)
+ }
+ }
+
+ function zOrders() : list<int> {
+ return [
+ stack.children[0].z,
+ stack.children[1].z,
+ stack.children[2].z
+ ]
+ }
+
+ function clearChildren() {
+ children.length = 0;
+ }
+
+ Item {}
+ Item {}
+ Item {}
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/objectWithStringListMethod.qml b/tests/auto/qml/qmlcppcodegen/data/objectWithStringListMethod.qml
new file mode 100644
index 0000000000..14f84c57d0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/objectWithStringListMethod.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ readonly property ObjectWithStringListMethod foo: ObjectFactory.getFoo()
+ Component.onCompleted: console.log(foo ? foo.names().length : "-")
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h b/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h
index 348862985f..f43a0d5531 100644
--- a/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h
+++ b/tests/auto/qml/qmlcppcodegen/data/objectwithmethod.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef OBJECTWITHMETOD_H
#define OBJECTWITHMETOD_H
@@ -7,6 +7,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qproperty.h>
#include <QtQml/qqml.h>
+#include <QtQml/private/qv4engine_p.h>
// Make objectName available. It doesn't exist on the builtin QtObject type
struct QObjectForeignForObjectName {
@@ -27,6 +28,20 @@ public:
Q_INVOKABLE int doThing() const { return theThing; }
QProperty<int> theThing;
QBindable<int> theThingBindable() { return QBindable<int>(&theThing); }
+
+ // The meta methods are populated back to front.
+ // The V4Function flag should not bleed into the others in either case.
+
+ Q_INVOKABLE void overloaded(QQmlV4FunctionPtr) { setObjectName(QStringLiteral("javaScript")); }
+ Q_INVOKABLE void overloaded(double) { setObjectName(QStringLiteral("double")); }
+ Q_INVOKABLE void overloaded(const QString &) { setObjectName(QStringLiteral("string")); }
+
+ Q_INVOKABLE void foo(const QString &bla) { setObjectName(bla); }
+ Q_INVOKABLE void foo(ObjectWithMethod *) { setObjectName(QStringLiteral("ObjectWithMethod")); }
+
+ Q_INVOKABLE void overloaded2(double) { setObjectName(QStringLiteral("double")); }
+ Q_INVOKABLE void overloaded2(const QString &) { setObjectName(QStringLiteral("string")); }
+ Q_INVOKABLE void overloaded2(QQmlV4FunctionPtr) { setObjectName(QStringLiteral("javaScript")); }
};
class OverriddenObjectName : public ObjectWithMethod
@@ -56,4 +71,40 @@ private:
QProperty<QString> m_objectName;
};
+class ObjectWithStringListMethod : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ explicit ObjectWithStringListMethod(QObject *parent = nullptr) : QObject(parent)
+ {
+ m_names.append("One");
+ m_names.append("Two");
+ }
+
+ Q_INVOKABLE QStringList names() const { return m_names; }
+
+private:
+ QStringList m_names;
+};
+
+class ObjectFactory : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ explicit ObjectFactory(QObject *parent = nullptr) : QObject(parent) {}
+ Q_INVOKABLE ObjectWithStringListMethod *getFoo()
+ {
+ if (!m_foo)
+ m_foo = new ObjectWithStringListMethod(this);
+ return m_foo;
+ }
+
+private:
+ ObjectWithStringListMethod *m_foo = nullptr;
+};
+
#endif // OBJECTWITHMETHOD_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/optionalComparison.qml b/tests/auto/qml/qmlcppcodegen/data/optionalComparison.qml
new file mode 100644
index 0000000000..4dbc541721
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/optionalComparison.qml
@@ -0,0 +1,77 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property list<QtObject> elms: [this, null, null]
+
+ property int found: find(this)
+ property int foundNot: findNot(this)
+ property int foundStrict: findStrict(this)
+ property int foundStrictNot: findStrictNot(this)
+
+ function find(elm : QtObject) : int {
+ let found = 0;
+ for (var i = 0; i < elms.length; i++) {
+ var value = elms[i];
+ if (value == elm)
+ ++found;
+ }
+ return found;
+ }
+
+ function findNot(elm : QtObject) : int {
+ let found = 0;
+ for (var i = 0; i < elms.length; i++) {
+ var value = elms[i];
+ if (value != elm)
+ ++found;
+ }
+ return found;
+ }
+
+ function findStrict(elm : QtObject) : int {
+ let found = 0;
+ for (var i = 0; i < elms.length; i++) {
+ var value = elms[i];
+ if (value === elm)
+ ++found;
+ }
+ return found;
+ }
+
+ function findStrictNot(elm : QtObject) : int {
+ let found = 0;
+ for (var i = 0; i < elms.length; i++) {
+ var value = elms[i];
+ if (value !== elm)
+ ++found;
+ }
+ return found;
+ }
+
+ property bool optionalNull: {
+ let a // Produces a QJsPrimitiveValue we can compare to null below
+ if (objectName.length === 0)
+ a = null
+ else
+ a = undefined
+
+ return a === null
+ }
+
+ property int undefinedEqualsUndefined: {
+ var matches = 0;
+
+ // Overrun the array so that we get some undefined !== undefined.
+ for (var i = 0; i < 4; i++) {
+ var val1 = elms[i]
+ for (var j = 0; j < 4; j++) {
+ var val2 = elms[j]
+ if (!(val1 !== val2))
+ ++matches
+ }
+ }
+
+ return matches;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/person.cpp b/tests/auto/qml/qmlcppcodegen/data/person.cpp
index 4dcd6fd56f..946dfbcdaa 100644
--- a/tests/auto/qml/qmlcppcodegen/data/person.cpp
+++ b/tests/auto/qml/qmlcppcodegen/data/person.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "person.h"
@@ -98,3 +98,21 @@ void Person::setCousins(const QList<Person *> &newCousins)
m_cousins = newCousins;
emit cousinsChanged();
}
+
+QRectF Person::area() const
+{
+ return m_area;
+}
+
+void Person::setArea(const QRectF &newArea)
+{
+ if (m_area.valueBypassingBindings() == newArea)
+ return;
+ m_area = newArea;
+ emit areaChanged();
+}
+
+QBindable<QRectF> Person::areaBindable()
+{
+ return QBindable<QRectF>(&m_area);
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/person.h b/tests/auto/qml/qmlcppcodegen/data/person.h
index fba4a9e9a5..c46aa757a7 100644
--- a/tests/auto/qml/qmlcppcodegen/data/person.h
+++ b/tests/auto/qml/qmlcppcodegen/data/person.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef PERSON_H
#define PERSON_H
@@ -8,6 +8,35 @@
#include <QtQml/qqml.h>
#include <QtQml/qqmlengine.h>
#include <QtCore/qproperty.h>
+#include <QtCore/qrect.h>
+
+struct Inner
+{
+ Q_GADGET
+ QML_VALUE_TYPE(inner)
+ QML_STRUCTURED_VALUE
+ Q_PROPERTY(int i MEMBER i)
+
+private:
+ friend bool operator==(const Inner &lhs, const Inner &rhs) { return lhs.i == rhs.i; }
+ friend bool operator!=(const Inner &lhs, const Inner &rhs) { return !(lhs == rhs); }
+
+ int i = 11;
+};
+
+struct Outer
+{
+ Q_GADGET
+ QML_VALUE_TYPE(outer)
+ QML_STRUCTURED_VALUE
+ Q_PROPERTY(Inner inner MEMBER inner)
+
+private:
+ friend bool operator==(const Outer &lhs, const Outer &rhs) { return lhs.inner == rhs.inner; }
+ friend bool operator!=(const Outer &lhs, const Outer &rhs) { return !(lhs == rhs); }
+
+ Inner inner;
+};
// Intentionally opaque type
class Barzle : public QObject {};
@@ -22,6 +51,8 @@ class Person : public QObject
Q_PROPERTY(QList<Barzle *> barzles READ barzles WRITE setBarzles NOTIFY barzlesChanged FINAL)
Q_PROPERTY(QList<Person *> cousins READ cousins WRITE setCousins NOTIFY cousinsChanged FINAL)
Q_PROPERTY(QByteArray data READ data WRITE setData NOTIFY dataChanged FINAL)
+ Q_PROPERTY(QRectF area READ area WRITE setArea NOTIFY areaChanged) // not FINAL
+ Q_PROPERTY(QRectF area2 READ area WRITE setArea NOTIFY areaChanged BINDABLE areaBindable FINAL)
QML_ELEMENT
public:
Person(QObject *parent = nullptr);
@@ -52,6 +83,12 @@ public:
QList<Person *> cousins() const;
void setCousins(const QList<Person *> &newCousins);
+ QRectF area() const;
+ void setArea(const QRectF &newArea);
+ QBindable<QRectF> areaBindable();
+
+ Q_INVOKABLE QString getName() const { return m_name; }
+
signals:
void nameChanged();
void shoeSizeChanged();
@@ -62,6 +99,10 @@ signals:
void ambiguous(int a = 9);
void cousinsChanged();
+ void objectListHappened(const QList<QObject *> &);
+ void variantListHappened(const QList<QVariant> &);
+
+ void areaChanged();
private:
QString m_name;
@@ -70,6 +111,7 @@ private:
QList<Barzle *> m_barzles;
QList<Person *> m_cousins;
QProperty<QByteArray> m_data;
+ QProperty<QRectF> m_area;
};
class BarzleListRegistration
diff --git a/tests/auto/qml/qmlcppcodegen/data/qtbug113150.qml b/tests/auto/qml/qmlcppcodegen/data/qtbug113150.qml
new file mode 100644
index 0000000000..c7103eaf05
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/qtbug113150.qml
@@ -0,0 +1,13 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+pragma Strict
+
+import QtQuick
+
+Window {
+ // If static properties of the Math global object are not directly
+ // supported, a warning should be issued in turn failing the build
+ // due to `pragma Strict`.
+ width: 200 * Math.PI
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/readEnumFromInstance.qml b/tests/auto/qml/qmlcppcodegen/data/readEnumFromInstance.qml
new file mode 100644
index 0000000000..d0176e6b15
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/readEnumFromInstance.qml
@@ -0,0 +1,16 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ id: root
+
+ property int priority: Backend.gadget.VeryHigh
+ property int prop2: Backend.priority
+
+ property bool priorityIsVeryHigh: root.priority == Backend.VeryHigh
+
+ function cyclePriority() : int {
+ root.priority = Backend.gadget.High;
+ return root.priority;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/readonlyListProperty.qml b/tests/auto/qml/qmlcppcodegen/data/readonlyListProperty.qml
new file mode 100644
index 0000000000..149638283b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/readonlyListProperty.qml
@@ -0,0 +1,17 @@
+import QtQml
+
+QtObject {
+ id: testObj
+
+ // "readonly" means the identity of the list cannot be changed.
+ // Its contents can be changed.
+ readonly default property list<QtObject> theList
+
+ Component.onCompleted: {
+ for (var i = 0; i < 4; i++)
+ testObj.theList.push(testObj)
+ }
+
+ property int l: theList.length
+}
+
diff --git a/tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml b/tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml
new file mode 100644
index 0000000000..c6fda8c739
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/reduceWithNullThis.qml
@@ -0,0 +1,18 @@
+import QtQml
+
+QtObject {
+ id: mainItem
+ property int topPadding: 12
+ property int bottomPadding: 12
+
+ property int preferredHeight: mainItem.children.reduce(maximumImplicitHeightReducer, 0) + topPadding + bottomPadding
+ function maximumImplicitHeightReducer(accumulator: real, item: Binding): real {
+ return Math.max(accumulator, (item.objectName + "b").length);
+ }
+
+ property int preferredHeight2: mainItem.children.reduce((accumulator, item) => {
+ return Math.max(accumulator, (item.objectName + "b").length);
+ }, 0) + topPadding + bottomPadding
+
+ property list<Binding> children: [ Binding { objectName: "aaa" } ]
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml b/tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml
new file mode 100644
index 0000000000..9352163ba7
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/renameAdjust.qml
@@ -0,0 +1,19 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: last
+ property int value: 10
+
+ function verify(i: int) {
+ if (last.value !== i)
+ console.error("failed", last.value, i);
+ else
+ console.log("success")
+ }
+
+ Component.onCompleted: {
+ verify(10)
+ verify(11)
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/resettable.h b/tests/auto/qml/qmlcppcodegen/data/resettable.h
new file mode 100644
index 0000000000..755c8de237
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/resettable.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef RESETTABLE_H
+#define RESETTABLE_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class ResettableProperty : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Resettable)
+ Q_PROPERTY(qreal value READ value WRITE setValue RESET resetValue NOTIFY valueChanged FINAL)
+ Q_PROPERTY(qreal shadowable READ shadowable CONSTANT)
+
+public:
+ explicit ResettableProperty(QObject *parent = nullptr) : QObject(parent) {}
+ qreal value() const { return m_value; }
+ qreal shadowable() const { return 25; }
+
+public slots:
+ void resetValue() { setValue(0); }
+ void setValue(qreal value)
+ {
+ if (m_value == value)
+ return;
+ m_value = value;
+ emit valueChanged();
+ }
+
+signals:
+ void valueChanged();
+
+private:
+ qreal m_value = 0;
+};
+
+#endif // RESETTABLE_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/resettable.qml b/tests/auto/qml/qmlcppcodegen/data/resettable.qml
new file mode 100644
index 0000000000..561655032d
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/resettable.qml
@@ -0,0 +1,23 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+Resettable {
+ id: self
+ value: 999
+
+ property double notResettable: 10
+ property double notResettable2: { return undefined }
+
+ property Resettable shadowing: Resettable {
+ property var shadowable: undefined
+ }
+
+ function doReset() { self.value = undefined }
+ function doReset2() { self.value = shadowing.shadowable }
+ function doNotReset() { self.notResettable = undefined }
+
+ signal aaa()
+ signal bbb()
+ onAaa: objectName = self.bbb()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/returnAfterReject.qml b/tests/auto/qml/qmlcppcodegen/data/returnAfterReject.qml
new file mode 100644
index 0000000000..e0b85eb270
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/returnAfterReject.qml
@@ -0,0 +1,15 @@
+import QtQml
+
+QtObject {
+ id: remaining
+
+ property int bar: 0
+
+ Component.onCompleted: {
+ let remainingTime = 123
+ if (remainingTime < 0) {
+ remainingTime += 24 * 60 * 60
+ }
+ remaining.bar = isNaN(remainingTime) ? 0 : remainingTime
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml b/tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml
new file mode 100644
index 0000000000..e23f180598
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/scopeIdLookup.qml
@@ -0,0 +1,20 @@
+pragma ComponentBehavior: Bound
+
+import QtQml
+
+QtObject {
+ id: root
+
+ property QtObject b: QtObject {
+ id: bar
+ objectName: "outer"
+ }
+
+ property Instantiator i: Instantiator {
+ model: 1
+ delegate: QtObject {
+ property QtObject bar: QtObject { objectName: "inner" }
+ Component.onCompleted: root.objectName = bar.objectName
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml b/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml
new file mode 100644
index 0000000000..8b9f161b06
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml
@@ -0,0 +1,19 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ property int good: Data.DType.A
+ property int bad: Data.A
+
+ property int wrong: Data.EType.C
+ property int right: Data.C
+
+ property int notgood: Data2.DType.A
+ property int notbad: Data2.A
+
+ property int notwrong: Data2.EType.C
+ property int notright: Data2.C
+
+ property int passable: Enums.AppState.Blue
+ property int wild: Enums.Green
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h
new file mode 100644
index 0000000000..76c72fff36
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.h
@@ -0,0 +1,56 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef SEQUENCETOITERABLE_H
+#define SEQUENCETOITERABLE_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class Entry : public QObject {
+ Q_OBJECT
+
+public:
+ explicit Entry(const QString &name, QObject *parent = nullptr)
+ : QObject(parent), m_name(name)
+ {
+ setObjectName(name);
+ }
+
+private:
+ QString m_name;
+};
+
+class EntryWrapper {
+ Q_GADGET
+ QML_FOREIGN(Entry)
+ QML_NAMED_ELEMENT(Entry)
+ QML_UNCREATABLE("These are my Entry objects")
+};
+
+class EntryListRegistration
+{
+ Q_GADGET
+ QML_FOREIGN(QList<Entry*>)
+ QML_ANONYMOUS
+ QML_SEQUENTIAL_CONTAINER(Entry*)
+};
+
+class EntrySource : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ explicit EntrySource(QObject* parent = nullptr) : QObject(parent) {
+ for (int i = 0; i < 10; i++) {
+ m_entries.push_back(new Entry(QString("Item %1").arg(i), this));
+ }
+ }
+ Q_INVOKABLE QList<Entry*> getEntries() const { return m_entries; }
+
+private:
+ QList<Entry*> m_entries;
+};
+
+#endif // SEQUENCETOITERABLE_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.qml b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.qml
new file mode 100644
index 0000000000..23e2645128
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/sequenceToIterable.qml
@@ -0,0 +1,20 @@
+pragma Strict
+import QtQuick
+import TestTypes
+
+Item {
+ Component.onCompleted: () => {
+ repeater.model = EntrySource.getEntries()
+ }
+
+ Repeater {
+ id: repeater
+ Item {
+ required property int index
+ required property QtObject modelData
+ objectName: modelData + ": " + index
+ }
+ }
+
+ property int c: children.length
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/setLookupConversion.qml b/tests/auto/qml/qmlcppcodegen/data/setLookupConversion.qml
new file mode 100644
index 0000000000..404ee8653b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/setLookupConversion.qml
@@ -0,0 +1,17 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: first
+ property int value
+
+ objectName: a.objectName
+ property QtObject a: QtObject {}
+ function t() { a.objectName = "a" }
+
+ Component.onCompleted: {
+ for (let i = 0; i < 10; ++i) {
+ first.value = i;
+ }
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/setLookupOriginalScope.qml b/tests/auto/qml/qmlcppcodegen/data/setLookupOriginalScope.qml
new file mode 100644
index 0000000000..9975bfdfa4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/setLookupOriginalScope.qml
@@ -0,0 +1,17 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property Component newEditConstraint: EditConstraint {}
+ property Variable variable: Variable {}
+ property EditConstraint edit
+
+ function trigger() {
+ change(variable, 55);
+ }
+
+ function change(v: Variable, newValue: int) {
+ edit = newEditConstraint.createObject(null, {myOutput: v}) as EditConstraint;
+ v.value = newValue;
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml b/tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml
new file mode 100644
index 0000000000..ccb50f4934
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/shadowedAsCasts.qml
@@ -0,0 +1,31 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property ShadowedObjectName shadowed1: ShadowedObjectName {}
+ property ShadowedObjectName shadowed2: ShadowedObjectName {}
+ property QtObject shadowed3: ShadowedObjectNameDerived {}
+
+ function returnShadowed2() : QtObject { return shadowed2 }
+
+ function a(mark: int) {
+ // as-cast can be optimized out if we're clever.
+ (shadowed1 as QtObject).objectName = mark;
+ }
+
+ function b(mark: int) {
+ // method return values can contain shadowed properties!
+ returnShadowed2().objectName = mark;
+ }
+
+ function c(mark: int) {
+ // Has to do an actual as-cast, but results in ShadowedObjectNameDerived!
+ (shadowed3 as ShadowedObjectName).objectName = mark;
+ }
+
+ Component.onCompleted: {
+ a(43);
+ b(42);
+ c(41);
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/shadowedMethod.qml b/tests/auto/qml/qmlcppcodegen/data/shadowedMethod.qml
new file mode 100644
index 0000000000..590fb40b17
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/shadowedMethod.qml
@@ -0,0 +1,35 @@
+pragma Strict
+import QtQuick
+
+Item {
+ component B: Item {
+ function contains(point: point) : string {
+ return "b"
+ }
+ }
+
+
+ component C: Item {
+ function contains(point: point) : string {
+ return "c"
+ }
+ }
+
+ property Item a: Item {}
+ property B b: B {}
+ property C c: C {}
+
+ function doThing() : var { return a.contains(Qt.point(0, 0)) }
+
+ property var athing;
+ property var bthing;
+ property var cthing;
+
+ Component.onCompleted: {
+ athing = doThing();
+ a = b;
+ bthing = doThing();
+ a = c;
+ cthing = doThing();
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/shadowedPrimitiveCmpEqNull.qml b/tests/auto/qml/qmlcppcodegen/data/shadowedPrimitiveCmpEqNull.qml
new file mode 100644
index 0000000000..0e130b9afc
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/shadowedPrimitiveCmpEqNull.qml
@@ -0,0 +1,16 @@
+import QtQuick
+
+QtObject {
+ id: win
+
+ component Foo: QtObject {
+ property int progress: 0
+ }
+
+ property int progress: 0
+ readonly property Foo configuring: Foo {}
+
+ Component.onCompleted: {
+ win.configuring.progress = win?.progress ?? 0
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml b/tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml
index 58a567f4db..3a0349966d 100644
--- a/tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/shared/Slider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/qml/qmlcppcodegen/data/signalsWithLists.qml b/tests/auto/qml/qmlcppcodegen/data/signalsWithLists.qml
new file mode 100644
index 0000000000..9a07b206d4
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/signalsWithLists.qml
@@ -0,0 +1,18 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+Person {
+ property list<var> varlist: [1, "foo", this, undefined, true]
+ property list<QtObject> objlist: [this, null, this]
+
+ function sendSignals() {
+ variantListHappened(varlist);
+ objectListHappened(objlist);
+ }
+
+ property int happening: 0
+
+ onObjectListHappened: (objects) => { happening += objects.length }
+ onVariantListHappened: (variants) => { happening += variants.length }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/state.h b/tests/auto/qml/qmlcppcodegen/data/state.h
index 1afcebc4ea..708e681781 100644
--- a/tests/auto/qml/qmlcppcodegen/data/state.h
+++ b/tests/auto/qml/qmlcppcodegen/data/state.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef STATE_H
#define STATE_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/structuredValueType.qml b/tests/auto/qml/qmlcppcodegen/data/structuredValueType.qml
new file mode 100644
index 0000000000..158dff2d0b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/structuredValueType.qml
@@ -0,0 +1,8 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property rect r: ({x: 1, y: 2, width: 3, height: 4})
+ property rect r2: { var x = 42; return {x}; }
+ property weatherModelUrl w: ({ strings: ["one", "two", "three"] })
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/theme.cpp b/tests/auto/qml/qmlcppcodegen/data/theme.cpp
index c8a2612753..10302645c0 100644
--- a/tests/auto/qml/qmlcppcodegen/data/theme.cpp
+++ b/tests/auto/qml/qmlcppcodegen/data/theme.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "theme.h"
diff --git a/tests/auto/qml/qmlcppcodegen/data/theme.h b/tests/auto/qml/qmlcppcodegen/data/theme.h
index f70a3b440e..3e56ec1f9f 100644
--- a/tests/auto/qml/qmlcppcodegen/data/theme.h
+++ b/tests/auto/qml/qmlcppcodegen/data/theme.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef THEME_H
#define THEME_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/thisObject.qml b/tests/auto/qml/qmlcppcodegen/data/thisObject.qml
new file mode 100644
index 0000000000..50664eced2
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/thisObject.qml
@@ -0,0 +1,11 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property QtObject warned
+
+ function f(arg: QtObject) { warned = arg }
+ function warn() { f(this) }
+
+ Component.onCompleted: warn()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp b/tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp
index 1853d2dc12..04e1797c7c 100644
--- a/tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp
+++ b/tests/auto/qml/qmlcppcodegen/data/timelinetheme.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "timelinetheme.h"
diff --git a/tests/auto/qml/qmlcppcodegen/data/timelinetheme.h b/tests/auto/qml/qmlcppcodegen/data/timelinetheme.h
index 335e43b570..3e7da77cc9 100644
--- a/tests/auto/qml/qmlcppcodegen/data/timelinetheme.h
+++ b/tests/auto/qml/qmlcppcodegen/data/timelinetheme.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TIMELINETHEME_H
#define TIMELINETHEME_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/topLevelComponent.qml b/tests/auto/qml/qmlcppcodegen/data/topLevelComponent.qml
new file mode 100644
index 0000000000..a73e28f642
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/topLevelComponent.qml
@@ -0,0 +1,14 @@
+pragma Strict
+import QtQml
+
+Component {
+ QtObject {
+ id: root
+
+ function myOpen() {
+ root.objectName = "foo"
+ }
+
+ Component.onCompleted: myOpen()
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/trigraphs.qml b/tests/auto/qml/qmlcppcodegen/data/trigraphs.qml
new file mode 100644
index 0000000000..e7bf5ccec9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/trigraphs.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ objectName: "??= ??/ ??' ??( ??) ??! ??< ??> ??-"
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/tst_qmlcppcodegen_verify.cpp b/tests/auto/qml/qmlcppcodegen/data/tst_qmlcppcodegen_verify.cpp
new file mode 100644
index 0000000000..02629ad7f6
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/tst_qmlcppcodegen_verify.cpp
@@ -0,0 +1,47 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+
+#include <QtTest>
+#include <QtCore/qobject.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qbytearray.h>
+
+class tst_QmlCppCodegenVerify : public QObject
+{
+ Q_OBJECT
+private slots:
+ void verifyGeneratedSources_data();
+ void verifyGeneratedSources();
+};
+
+void tst_QmlCppCodegenVerify::verifyGeneratedSources_data()
+{
+ QTest::addColumn<QString>("file");
+
+ QDir a(":/a");
+ const QStringList entries = a.entryList(QDir::Files);
+ for (const QString &entry : entries)
+ QTest::addRow("%s", entry.toUtf8().constData()) << entry;
+}
+
+void tst_QmlCppCodegenVerify::verifyGeneratedSources()
+{
+ QFETCH(QString, file);
+ QFile a(":/a/" + file);
+ QFile b(":/b/" + file.replace("codegen_test_module", "codegen_test_module_verify"));
+
+ QVERIFY(a.open(QIODevice::ReadOnly));
+ QVERIFY(b.open(QIODevice::ReadOnly));
+
+ const QByteArray aData = a.readAll();
+ const QByteArray bData = b.readAll()
+ .replace("verify/TestTypes", "TestTypes")
+ .replace("verify_TestTypes", "TestTypes");
+
+ QCOMPARE(aData, bData);
+}
+
+QTEST_MAIN(tst_QmlCppCodegenVerify)
+
+#include "tst_qmlcppcodegen_verify.moc"
diff --git a/tests/auto/qml/qmlcppcodegen/data/undefinedToDouble.qml b/tests/auto/qml/qmlcppcodegen/data/undefinedToDouble.qml
new file mode 100644
index 0000000000..e76443a2e0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/undefinedToDouble.qml
@@ -0,0 +1,6 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property double d: Math.max(undefined, 40)
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/urlString.qml b/tests/auto/qml/qmlcppcodegen/data/urlString.qml
index 511c54532c..a83855ebdb 100644
--- a/tests/auto/qml/qmlcppcodegen/data/urlString.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/urlString.qml
@@ -9,5 +9,12 @@ QtObject {
Component.onCompleted: {
c = "http://dddddd.com";
self.d = "http://aaaaaa.com";
+ myUrlChanged(c)
+ }
+
+ signal myUrlChanged(urlParam: url)
+
+ onMyUrlChanged: (urlParam) => {
+ objectName = urlParam;
}
}
diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeCast.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeCast.qml
new file mode 100644
index 0000000000..a775773dda
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeCast.qml
@@ -0,0 +1,43 @@
+pragma ValueTypeBehavior: Addressable
+import QtQml
+
+QtObject {
+ id: root
+ property rect r: Qt.rect(10, 20, 3, 4)
+ property var v: r
+ property real x: (v as rect).x
+
+ function f(input: bool) : var {
+ if (input)
+ return 0
+ return Qt.point(2, 2)
+ }
+
+ property var vv: Qt.point(5, 5)
+ property var uu: undefined
+
+ property int tv3: (root.vv as point)?.x
+ property var tv4: (root.uu as rect)?.x
+ property int tc3: (root?.vv as point)?.y
+ property var tc6: (root?.uu as rect)?.height
+ property var tc7: (f(true) as point)?.x
+ property var tc8: (f(false) as point)?.x
+
+ property string greeting1
+ property string greeting2
+
+ readonly property string defaultGreeting: "Default Greeting"
+ property QtObject o: QtObject {
+ id: o
+ property var customGreeting
+ function greet() : string {
+ return (o.customGreeting as string) ?? root.defaultGreeting
+ }
+ }
+
+ Component.onCompleted: {
+ root.greeting1 = o.greet()
+ o.customGreeting = "Custom Greeting"
+ root.greeting2 = o.greet()
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml
index cca634753d..d33133bb6b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeCopy.qml
@@ -1,4 +1,4 @@
-pragma ValueTypeBehavior: Copy
+pragma ValueTypeBehavior: Copy, Addressable
import QtQml
QtObject {
diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml
new file mode 100644
index 0000000000..42a55e832d
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeDefault.qml
@@ -0,0 +1,34 @@
+import QtQml
+
+
+QtObject {
+ id: root
+
+ property list<double> numbers: {
+ var result = [];
+ for (var i = 0; i < 10; ++i)
+ result[i] = i;
+ return result;
+ }
+
+ property rect r: ({x: 1, y: 2, width: 3, height: 4})
+
+ function evil() : double {
+ var numbers = root.numbers;
+ root.numbers = [];
+ var a = 0;
+ for (var j = 0; j < 10; ++j) {
+ a += numbers[j];
+ }
+ return a;
+ }
+
+ function fvil() : double {
+ var r = root.r;
+ root.r = {x: 5, y: 6, width: 7, height: 8};
+ return r.x;
+ }
+
+ property double e: evil()
+ property double f: fvil()
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml b/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml
index 568f39820c..a87f88ecf9 100644
--- a/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml
+++ b/tests/auto/qml/qmlcppcodegen/data/valueTypeReference.qml
@@ -1,4 +1,4 @@
-pragma ValueTypeBehavior: Reference
+pragma ValueTypeBehavior: Reference, Inaddressable
import QtQml
QtObject {
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantMap.qml b/tests/auto/qml/qmlcppcodegen/data/variantMap.qml
new file mode 100644
index 0000000000..d7147ec5fc
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantMap.qml
@@ -0,0 +1,27 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ property Component shadowable: QtObject {}
+ property B b: B { id: theB }
+ property rect r: theB.r
+ property var v: { "1": null, "25": undefined, "19": "19" }
+
+ property Component c: Component {
+ id: unshadowable
+ QtObject {}
+ }
+
+ // We need this extra function in order to coerce the result of the shadowable
+ // method call back to QtObject
+ function createShadowable() : QtObject {
+ return shadowable.createObject(this, {objectName: "a"})
+ }
+
+ objectName: {
+ return createShadowable().objectName
+ + " " + unshadowable.createObject(this, {objectName: "b"}).objectName
+ }
+
+ Component.onCompleted: b.r = { x: 12, y: 13, width: 14, height: 15 }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h
new file mode 100644
index 0000000000..61d38228b0
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.h
@@ -0,0 +1,17 @@
+#pragma once
+#include <QObject>
+#include <QVariantMap>
+#include <QtQml/qqmlregistration.h>
+
+class VariantMapLookupFoo : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QVariantMap data READ data CONSTANT)
+
+public:
+ VariantMapLookupFoo(QObject *parent = nullptr) : QObject(parent) { }
+
+private:
+ QVariantMap data() const { return { { "value", 42 } }; }
+};
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml
new file mode 100644
index 0000000000..4e56cb9448
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantMapLookup.qml
@@ -0,0 +1,11 @@
+pragma Strict
+import TestTypes
+import QtQuick
+
+Item {
+ property int i: moo.data.value
+
+ VariantMapLookupFoo {
+ id: moo
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantReturn.qml b/tests/auto/qml/qmlcppcodegen/data/variantReturn.qml
new file mode 100644
index 0000000000..cca26265c9
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantReturn.qml
@@ -0,0 +1,15 @@
+pragma Strict
+import QtQml
+import TestTypes
+
+QtObject {
+ property DirectBindable a: DirectBindable {
+ id: aId
+ x: WeatherModelUrlUtils.url(1)
+ }
+
+ property IndirectBindable b: IndirectBindable {
+ id: bId
+ y: aId.x
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/variantreturn.h b/tests/auto/qml/qmlcppcodegen/data/variantreturn.h
new file mode 100644
index 0000000000..87718aaef3
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/variantreturn.h
@@ -0,0 +1,63 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef VARIANTERETURN_H
+#define VARIANTERETURN_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+#include <QtQml/qqmlregistration.h>
+
+#include "weathermoduleurl.h"
+
+class DirectBindable : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(WeatherModelUrl x READ x WRITE setX NOTIFY xChanged BINDABLE bindableX)
+
+public:
+ explicit DirectBindable(QObject *parent = nullptr) : QObject(parent) {}
+
+ WeatherModelUrl x() const { return m_x.value(); }
+ void setX(const WeatherModelUrl& newX) { m_x.setValue(newX);}
+ QBindable<WeatherModelUrl> bindableX() { return QBindable<WeatherModelUrl>(&m_x); }
+
+Q_SIGNALS:
+ void xChanged();
+
+private:
+ Q_OBJECT_BINDABLE_PROPERTY(DirectBindable, WeatherModelUrl, m_x, &DirectBindable::xChanged)
+};
+
+class IndirectBindable : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(WeatherModelUrl y READ y WRITE setY NOTIFY yChanged BINDABLE bindableY)
+ Q_PROPERTY(int z READ z NOTIFY zChanged)
+
+public:
+ explicit IndirectBindable(QObject *parent = nullptr) : QObject(parent) {
+ m_z.setBinding([this]()->int {
+ return m_y.value().timeIndex() * 2;
+ });
+ }
+
+ WeatherModelUrl y() const { return m_y.value(); }
+ void setY(const WeatherModelUrl& newY) { m_y.setValue(newY); }
+ QBindable<WeatherModelUrl> bindableY() { return QBindable<WeatherModelUrl>(&m_y); }
+
+ int z() const { return m_z.value(); }
+ QBindable<int> bindableZ() const { return QBindable<int>(&m_z); }
+
+Q_SIGNALS:
+ void yChanged();
+ void zChanged();
+
+private:
+ Q_OBJECT_BINDABLE_PROPERTY(IndirectBindable, WeatherModelUrl, m_y, &IndirectBindable::yChanged)
+ Q_OBJECT_BINDABLE_PROPERTY(IndirectBindable, int, m_z, &IndirectBindable::zChanged)
+};
+
+#endif // VARIANTRETURN_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/voidConversion.qml b/tests/auto/qml/qmlcppcodegen/data/voidConversion.qml
new file mode 100644
index 0000000000..f5826d9e48
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/voidConversion.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ id: item
+ property point p: Qt.point(20, 10)
+
+ Component.onCompleted: {
+ item.p = undefined
+ }
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/weathermoduleurl.h b/tests/auto/qml/qmlcppcodegen/data/weathermoduleurl.h
new file mode 100644
index 0000000000..998118dc5b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/weathermoduleurl.h
@@ -0,0 +1,61 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef WEATHERMODELURL_H
+#define WEATHERMODELURL_H
+
+#include <QtQml/qqmlregistration.h>
+#include <QtCore/qobject.h>
+
+class WeatherModelUrl
+{
+ Q_GADGET
+ QML_STRUCTURED_VALUE
+ QML_VALUE_TYPE(weatherModelUrl)
+ Q_PROPERTY(qsizetype timeIndex READ timeIndex CONSTANT)
+ Q_PROPERTY(QStringList strings READ strings WRITE setStrings)
+
+public:
+ WeatherModelUrl() : m_timeIndex(-1) {}
+ WeatherModelUrl(qsizetype timeIdx) : m_timeIndex(timeIdx) {}
+
+ qsizetype timeIndex() const { return m_timeIndex; }
+
+ QStringList strings() const { return m_strings; }
+ void setStrings(const QStringList &newStrings)
+ {
+ if (m_strings != newStrings)
+ m_strings = newStrings;
+ }
+
+private:
+ friend bool operator==(const WeatherModelUrl &a, const WeatherModelUrl &b)
+ {
+ return a.m_timeIndex == b.m_timeIndex;
+ }
+
+ friend bool operator!=(const WeatherModelUrl &a, const WeatherModelUrl &b)
+ {
+ return !(a == b);
+ }
+
+ qsizetype m_timeIndex;
+ QStringList m_strings;
+};
+
+class WeatherModelUrlUtils : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+
+public:
+ WeatherModelUrlUtils(QObject *parent = nullptr) : QObject(parent) {}
+
+ Q_INVOKABLE static WeatherModelUrl url(int timeIdx)
+ {
+ return WeatherModelUrl(timeIdx);
+ }
+};
+
+#endif // WEATHERMODELURL_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/withlength.h b/tests/auto/qml/qmlcppcodegen/data/withlength.h
index ba95522c53..26c6307f2b 100644
--- a/tests/auto/qml/qmlcppcodegen/data/withlength.h
+++ b/tests/auto/qml/qmlcppcodegen/data/withlength.h
@@ -1,11 +1,13 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef WITHLENGTH_H
#define WITHLENGTH_H
#include <QtCore/qobject.h>
-#include <QtQmlIntegration/qqmlintegration.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qrect.h>
+#include <QtQml/qqml.h>
struct ValueTypeWithLength
{
@@ -18,6 +20,8 @@ struct ValueTypeWithLength
public:
ValueTypeWithLength() = default;
Q_INVOKABLE ValueTypeWithLength(int length) : m_length(length) {}
+ Q_INVOKABLE ValueTypeWithLength(QPointF point) : m_length(point.manhattanLength()) {}
+ Q_INVOKABLE ValueTypeWithLength(QRectF rect) : m_length(rect.width()) {}
Q_INVOKABLE QString toString() const { return QStringLiteral("no"); }
int length() const { return m_length; }
@@ -26,4 +30,24 @@ private:
int m_length = 19;
};
+struct InnerWithLength {
+ int m_length;
+};
+
+struct UnconstructibleWithLength
+{
+ Q_GADGET
+ QML_VALUE_TYPE(unconstructibleWithLength)
+
+ QML_FOREIGN(InnerWithLength)
+ QML_EXTENDED(UnconstructibleWithLength)
+
+public:
+ UnconstructibleWithLength() = default;
+ Q_INVOKABLE UnconstructibleWithLength(int length) : v{length} {}
+
+private:
+ InnerWithLength v;
+};
+
#endif // WITHLENGTH_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h b/tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h
index dce78fa9c9..7de49f095a 100644
--- a/tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h
+++ b/tests/auto/qml/qmlcppcodegen/data/wrapwithvariant.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef WRAPWITHVARIANT_H
#define WRAPWITHVARIANT_H
diff --git a/tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h b/tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h
new file mode 100644
index 0000000000..3c0fedd28b
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/writableVariantMap.h
@@ -0,0 +1,31 @@
+#pragma once
+#include <QObject>
+#include <QVariantMap>
+#include <QtQml/qqmlregistration.h>
+
+class WritableVariantMap : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QVariantMap data READ data WRITE setData NOTIFY dataChanged)
+
+public:
+ WritableVariantMap(QObject *parent = nullptr) : QObject(parent) { }
+
+ QVariantMap data() const { return m_data; }
+ void setData(const QVariantMap &data)
+ {
+ if (m_data != data) {
+ m_data = data;
+ emit dataChanged();
+ }
+ }
+
+signals:
+ void dataChanged();
+
+private:
+ QVariantMap m_data;
+};
+
+
diff --git a/tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml b/tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml
new file mode 100644
index 0000000000..536e53b408
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/writeVariantMap.qml
@@ -0,0 +1,10 @@
+pragma Strict
+import StringBuilderTestTypes
+
+WritableVariantMap {
+ id: dragSource
+ property string modelData: "Drag Me"
+ data: ({
+ "text/plain": "%" + dragSource.modelData + "%"
+ })
+}
diff --git a/tests/auto/qml/qmlcppcodegen/data/writeback.qml b/tests/auto/qml/qmlcppcodegen/data/writeback.qml
new file mode 100644
index 0000000000..359f00efb7
--- /dev/null
+++ b/tests/auto/qml/qmlcppcodegen/data/writeback.qml
@@ -0,0 +1,43 @@
+pragma Strict
+
+import TestTypes
+import QtQml
+
+Person {
+ id: self
+
+ area {
+ width: 19
+ height: 199
+ }
+
+ property list<int> ints: [4, 3, 2, 1]
+
+ property outer recursive
+ property Person shadowable: Person {
+ id: notShadowable
+ area.width: self.area.width
+ area2.height: self.area2.height
+ }
+
+ Component.onCompleted: {
+ area.width = 16
+ area2.height = 17
+
+ self.area.x = 4
+ self.area2.y = 5
+
+ // You cannot do this on the shadowable Person because
+ // shadowable.area may not actually be a QRectF anymore.
+ notShadowable.area.x = 40
+ notShadowable.area2.y = 50
+
+ self.recursive.inner.i = 99;
+
+ self.ints[0] = 12;
+ ints[1] = 22;
+ ints[6] = 33;
+ }
+
+ property int inner: recursive.inner.i
+}
diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
index 400075c08d..53cc068e8c 100644
--- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
+++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp
@@ -1,10 +1,16 @@
-// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-#include "data/druggeljug.h"
#include <data/birthdayparty.h>
#include <data/cppbaseclass.h>
+#include <data/druggeljug.h>
+#include <data/enumProperty.h>
#include <data/enumproblems.h>
+#include <data/getOptionalLookup.h>
#include <data/objectwithmethod.h>
+#include <data/resettable.h>
+#include <data/weathermoduleurl.h>
+#include <data/withlength.h>
#include <QtQml/private/qqmlengine_p.h>
#include <QtQml/private/qqmlpropertycachecreator_p.h>
@@ -12,6 +18,7 @@
#include <QtTest>
#include <QtQml>
#include <QtGui/qcolor.h>
+#include <QtGui/qpa/qplatformdialoghelper.h>
#if QT_CONFIG(process)
#include <QtCore/qprocess.h>
@@ -26,146 +33,460 @@ class tst_QmlCppCodegen : public QObject
Q_OBJECT
private slots:
void initTestCase();
+ void cleanupTestCase();
- void simpleBinding();
- void cppValueTypeList();
+ void accessModelMethodFromOutSide();
+ void aliasLookup();
+ void ambiguousAs();
+ void ambiguousSignals();
void anchorsFill();
- void signalHandler();
- void idAccess();
- void globals();
- void multiLookup();
- void enums();
- void funcWithParams();
- void intOverflow();
- void stringLength();
- void scopeVsObject();
- void compositeTypeMethod();
- void excessiveParameters();
- void jsImport();
- void jsmoduleImport();
- void methods();
- void math();
- void unknownParameter();
+ void argumentConversion();
void array();
- void equalsUndefined();
- void conversions();
- void interestingFiles_data();
- void interestingFiles();
- void extendedTypes();
- void construct();
- void contextParam();
- void attachedType();
- void componentReturnType();
- void onAssignment();
- void failures();
- void enumScope();
- void unusedAttached();
+ void arrayCtor();
+ void asCast();
void attachedBaseEnum();
- void nullAccess();
- void interceptor();
- void nonNotifyable();
- void importsFromImportPath();
- void aliasLookup();
- void outOfBoundsArray();
- void compositeSingleton();
- void lotsOfRegisters();
- void inPlaceDecrement();
- void shifts();
- void valueTypeProperty();
- void propertyOfParent();
- void accessModelMethodFromOutSide();
- void functionArguments();
+ void attachedSelf();
+ void attachedType();
+ void badSequence();
+ void basicBlocksWithBackJump();
+ void basicBlocksWithBackJump_infinite();
+ void basicDTZ();
+ void bindToValueType();
void bindingExpression();
- void voidFunction();
- void overriddenProperty();
- void listLength();
- void parentProperty();
- void registerElimination();
- void asCast();
- void noQQmlData();
- void scopeObjectDestruction();
+ void blockComments();
+ void boolCoercions();
+ void boolPointerMerge();
+ void boundComponents();
+ void callContextPropertyLookupResult();
+ void callWithSpread();
void colorAsVariant();
- void bindToValueType();
- void undefinedResets();
- void innerObjectNonShadowable();
- void ownPropertiesNonShadowable();
- void modulePrefix();
void colorString();
- void urlString();
- void callContextPropertyLookupResult();
+ void compareOriginals();
+ void comparisonTypes();
+ void componentReturnType();
+ void compositeSingleton();
+ void compositeTypeMethod();
+ void consoleObject();
+ void consoleTrace();
+ void construct();
+ void contextParam();
+ void conversionDecrement();
+ void conversionInDeadCode();
+ void conversions();
+ void convertPrimitiveToVar();
+ void convertQJSPrimitiveValueToIntegral();
+ void convertToOriginalReadAcumulatorForUnaryOperators();
+ void cppMethodListReturnType();
+ void cppValueTypeList();
+ void dateConstruction();
+ void dateConversions();
void deadShoeSize();
- void listIndices();
- void jsMathObject();
- void intEnumCompare();
- void attachedSelf();
- void functionReturningVoid();
- void functionCallOnNamespaced();
+ void dialogButtonBox();
+ void enumConversion();
+ void enumFromBadSingleton();
+ void enumLookup();
+ void enumMarkedAsFlag();
+ void enumProblems();
+ void enumScope();
+ void enums();
+ void enforceSignature();
+ void enumsInOtherObject();
+ void equalityQObjects();
+ void equalityQUrl();
+ void equalityTestsWithNullOrUndefined();
+ void equalityVarAndNonStorable();
+ void equalityVarAndStorable();
+ void equalsUndefined();
+ void evadingAmbiguity();
+ void exceptionFromInner();
+ void excessiveParameters();
+ void extendedTypes();
+ void failures();
+ void fallbackLookups();
+ void fileImportsContainCxxTypes();
+ void flagEnum();
void flushBeforeCapture();
- void unknownAttached();
- void variantlist();
- void popContextAfterRet();
- void revisions();
- void invisibleBase();
- void notEqualsInt();
- void infinities();
- void blockComments();
+ void fromBoolValue();
+ void funcWithParams();
+ void functionArguments();
+ void functionCallOnNamespaced();
void functionLookup();
- void objectInVar();
+ void functionReturningVoid();
void functionTakingVar();
- void testIsnan();
- void fallbackLookups();
- void typedArray();
- void prefixedType();
- void evadingAmbiguity();
- void fromBoolValue();
- void invisibleTypes();
+ void getLookupOfScript();
+ void getOptionalLookup();
+ void getOptionalLookup_data();
+ void getOptionalLookupOnQJSValueNonStrict();
+ void getOptionalLookupShadowed();
+ void globals();
+ void idAccess();
+ void ignoredFunctionReturn();
+ void importsFromImportPath();
+ void inPlaceDecrement();
+ void inaccessibleProperty();
+ void indirectlyShadowable();
+ void infinities();
+ void infinitiesToInt();
+ void innerObjectNonShadowable();
+ void intEnumCompare();
+ void intOverflow();
+ void intToEnum();
+ void interceptor();
+ void interestingFiles();
+ void interestingFiles_data();
+ void internalConversion();
void invalidPropertyType();
- void valueTypeLists();
- void boundComponents();
+ void invisibleBase();
void invisibleListElementType();
- void typePropertyClash();
- void objectToString();
- void throwObjectName();
+ void invisibleSingleton();
+ void invisibleTypes();
+ void iteration();
void javaScriptArgument();
- void translation();
- void stringArg();
- void conversionDecrement();
- void unstoredUndefined();
- void registerPropagation();
- void argumentConversion();
- void badSequence();
- void enumLookup();
- void trivialSignalHandler();
- void stringToByteArray();
+ void jsArrayMethods();
+ void jsArrayMethodsWithParams();
+ void jsArrayMethodsWithParams_data();
+ void jsImport();
+ void jsMathObject();
+ void jsmoduleImport();
+ void lengthAccessArraySequenceCompat();
+ void letAndConst();
+ void listAsArgument();
+ void listConversion();
+ void listIndices();
+ void listLength();
+ void listOfInvisible();
void listPropertyAsModel();
- void notNotString();
+ void listToString();
+ void lotsOfRegisters();
+ void math();
+ void mathMinMax();
void mathOperations();
- void inaccessibleProperty();
- void typePropagationLoop();
- void signatureIgnored();
- void listAsArgument();
- void letAndConst();
- void signalIndexMismatch();
- void callWithSpread();
- void nullComparison();
- void consoleObject();
+ void mathStaticProperties();
+ void mergedObjectReadWrite();
+ void methodOnListLookup();
+ void methods();
+ void modulePrefix();
+ void multiDirectory_data();
+ void multiDirectory();
void multiForeign();
+ void multiLookup();
+ void multipleCtors();
void namespaceWithEnum();
- void enumProblems();
- void enumConversion();
- void ambiguousSignals();
- void fileImportsContainCxxTypes();
- void lengthAccessArraySequenceCompat();
- void storeElementSideEffects();
+ void noQQmlData();
+ void nonNotifyable();
+ void notEqualsInt();
+ void notNotString();
+ void nullAccess();
+ void nullAccessInsideSignalHandler();
+ void nullComparison();
+ void nullishCoalescing();
+ void nullishCoalescing_data();
void numbersInJsPrimitive();
- void infinitiesToInt();
- void equalityVarAndNonStorable();
- void equalityQObjects();
- void dateConversions();
+ void objectInVar();
+ void objectLookupOnListElement();
+ void objectToString();
+ void objectWithStringListMethod();
+ void onAssignment();
+ void optionalComparison();
+ void outOfBoundsArray();
+ void overriddenProperty();
+ void ownPropertiesNonShadowable();
+ void parentProperty();
+ void popContextAfterRet();
+ void prefixedType();
+ void propertyOfParent();
+ void reduceWithNullThis();
+ void readEnumFromInstance();
+ void readonlyListProperty();
+ void registerElimination();
+ void registerPropagation();
+ void renameAdjust();
+
+ void resettableProperty();
+ void resettableProperty_data();
+
+ void returnAfterReject();
+ void revisions();
+ void scopeIdLookup();
+ void scopeObjectDestruction();
+ void scopeVsObject();
+ void scopedEnum();
+ void sequenceToIterable();
+ void setLookupConversion();
+ void setLookupOriginalScope();
+ void shadowedAsCasts();
+ void shadowedMethod();
+ void shadowedPrimitiveCmpEqNull();
+ void shifts();
+ void signalHandler();
+ void signalIndexMismatch();
+ void signalsWithLists();
+ void signatureIgnored();
+ void simpleBinding();
+ void storeElementSideEffects();
+ void storeMetaEnum();
+ void stringArg();
+ void stringLength();
+ void stringToByteArray();
+ void structuredValueType();
+ void testIsnan();
+ void thisObject();
+ void throwObjectName();
+ void topLevelComponent();
+ void translation();
+ void trigraphs();
+ void trivialSignalHandler();
+ void typePropagationLoop();
+ void typePropertyClash();
+ void typedArray();
+ void undefinedResets();
+ void undefinedToDouble();
+ void unknownAttached();
+ void unknownParameter();
+ void unstoredUndefined();
+ void unusedAttached();
+ void urlString();
void valueTypeBehavior();
- void invisibleSingleton();
+ void valueTypeLists();
+ void valueTypeProperty();
+ void variantMapLookup();
+ void variantReturn();
+ void variantlist();
+ void variantMap();
+ void voidConversion();
+ void voidFunction();
+ void writeBack();
+ void writeVariantMap();
};
+static QByteArray arg1()
+{
+ const QStringList args = QCoreApplication::instance()->arguments();
+ return args.size() > 1 ? args[1].toUtf8() : QByteArray("undefined");
+}
+
+namespace QmlCacheGeneratedCode {
+namespace _qt_qml_TestTypes_failures_qml {
+extern const QQmlPrivate::AOTCompiledFunction aotBuiltFunctions[];
+}
+}
+
+static void checkColorProperties(QQmlComponent *component)
+{
+ QVERIFY2(component->isReady(), qPrintable(component->errorString()));
+ QScopedPointer<QObject> rootObject(component->create());
+ QVERIFY(rootObject);
+
+ const QMetaObject *mo = QMetaType::fromName("QQuickIcon").metaObject();
+ QVERIFY(mo != nullptr);
+
+ const QMetaProperty prop = mo->property(mo->indexOfProperty("color"));
+ QVERIFY(prop.isValid());
+
+ const QVariant a = rootObject->property("a");
+ QVERIFY(a.isValid());
+
+ const QVariant iconColor = prop.readOnGadget(rootObject->property("icon").data());
+ QVERIFY(iconColor.isValid());
+
+ const QMetaType colorType = QMetaType::fromName("QColor");
+ QVERIFY(colorType.isValid());
+
+ QCOMPARE(a.metaType(), colorType);
+ QCOMPARE(iconColor.metaType(), colorType);
+
+ QCOMPARE(iconColor, a);
+}
+
+static const double numbers[] = {
+ qQNaN(), -qInf(),
+ std::numeric_limits<double>::min(),
+ std::numeric_limits<float>::min(),
+ std::numeric_limits<qint32>::min(),
+ -1000.2, -100, -2, -1.333, -1, -0.84, -0.5,
+
+ // -0 and 0 are not different on the QML side. Therefore, don't keep them adjacent.
+ // Otherwise the bindings won't get re-evaluated.
+ std::copysign(0.0, -1), 1, 0.0,
+
+ 0.5, 0.77, 1.4545, 2, 199, 2002.13,
+ std::numeric_limits<qint32>::max(),
+ std::numeric_limits<quint32>::max(),
+ std::numeric_limits<float>::max(),
+ std::numeric_limits<double>::max(),
+ qInf()
+};
+
+class MyCppType : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool useListDelegate
+ READ useListDelegate
+ WRITE setUseListDelegate
+ NOTIFY useListDelegateChanged)
+public:
+ explicit MyCppType(QObject * parent = nullptr) : QObject(parent) {}
+
+ bool useListDelegate() const { return m_useListDelegate; }
+ void setUseListDelegate(bool useListDelegate)
+ {
+ if (useListDelegate != m_useListDelegate) {
+ m_useListDelegate = useListDelegate;
+ emit useListDelegateChanged();
+ }
+ }
+
+signals:
+ void useListDelegateChanged();
+
+private:
+ bool m_useListDelegate = false;
+};
+
+class InvisibleListElementType : public QObject
+{
+ Q_OBJECT
+public:
+ InvisibleListElementType(QObject *parent = nullptr) : QObject(parent) {}
+};
+
+template<typename T>
+QString toOperand(double arg);
+
+template<>
+QString toOperand<double>(double arg)
+{
+ if (qIsNull(arg))
+ return std::signbit(arg) ? QStringLiteral("(-0)") : QStringLiteral("(0)");
+
+ return u'(' + QJSPrimitiveValue(arg).toString() + u')';
+}
+
+template<>
+QString toOperand<int>(double arg)
+{
+ const int iArg = QJSPrimitiveValue(arg).toInteger();
+ return u'(' + QJSPrimitiveValue(iArg).toString() + u')';
+}
+
+template<>
+QString toOperand<bool>(double arg)
+{
+ const bool bArg = QJSPrimitiveValue(arg).toBoolean();
+ return u'(' + QJSPrimitiveValue(bArg).toString() + u')';
+}
+
+template<typename T1, typename T2>
+double jsEval(double arg1, double arg2, const QString &op, QJSEngine *engine)
+{
+ auto evalBinary = [&](const QString &jsOp) {
+ return engine->evaluate(toOperand<T1>(arg1) + jsOp + toOperand<T2>(arg2)).toNumber();
+ };
+
+ auto evalBinaryConst = [&](const QString &jsOp) {
+ return engine->evaluate(toOperand<T1>(arg1) + jsOp + u'9').toNumber();
+ };
+
+ auto evalUnary = [&](const QString &jsOp) {
+ return engine->evaluate(jsOp + toOperand<T1>(arg1)).toNumber();
+ };
+
+ auto evalInPlace = [&](const QString &jsOp) {
+ return engine->evaluate(
+ u"(function() {var a = "_s + toOperand<T1>(arg1)+ u"; return "_s
+ + jsOp + u"a;})()"_s).toNumber();
+ };
+
+ if (op == u"unot")
+ return evalUnary(u"!"_s);
+ if (op == u"uplus")
+ return evalUnary(u"+"_s);
+ if (op == u"uminus")
+ return evalUnary(u"-"_s);
+ if (op == u"ucompl")
+ return evalUnary(u"~"_s);
+
+ if (op == u"increment")
+ return evalInPlace(u"++"_s);
+ if (op == u"decrement")
+ return evalInPlace(u"--"_s);
+
+ if (op == u"add")
+ return evalBinary(u"+"_s);
+ if (op == u"sub")
+ return evalBinary(u"-"_s);
+ if (op == u"mul")
+ return evalBinary(u"*"_s);
+ if (op == u"div")
+ return evalBinary(u"/"_s);
+ if (op == u"exp")
+ return evalBinary(u"**"_s);
+ if (op == u"mod")
+ return evalBinary(u"%"_s);
+
+ if (op == u"bitAnd")
+ return evalBinary(u"&"_s);
+ if (op == u"bitOr")
+ return evalBinary(u"|"_s);
+ if (op == u"bitXor")
+ return evalBinary(u"^"_s);
+
+ if (op == u"bitAndConst")
+ return evalBinaryConst(u"&"_s);
+ if (op == u"bitOrConst")
+ return evalBinaryConst(u"|"_s);
+ if (op == u"bitXorConst")
+ return evalBinaryConst(u"^"_s);
+
+ if (op == u"ushr")
+ return evalBinary(u">>>"_s);
+ if (op == u"shr")
+ return evalBinary(u">>"_s);
+ if (op == u"shl")
+ return evalBinary(u"<<"_s);
+
+ if (op == u"ushrConst")
+ return evalBinaryConst(u">>>"_s);
+ if (op == u"shrConst")
+ return evalBinaryConst(u">>"_s);
+ if (op == u"shlConst")
+ return evalBinaryConst(u"<<"_s);
+
+ qDebug() << op;
+ Q_UNREACHABLE_RETURN(0);
+}
+
+static QList<QString> convertToStrings(const QList<qint64> &ints)
+{
+ QList<QString> strings;
+ for (qint64 i : ints)
+ strings.append(QString::number(i));
+ return strings;
+}
+
+static QRegularExpression bindingLoopMessage(const QUrl &url, char var)
+{
+ // The actual string depends on how many times QObject* was registered with what parameters.
+ return QRegularExpression(
+ "%1:4:1: QML [^:]+: Binding loop detected for property \"%2\""_L1
+ .arg(url.toString()).arg(QLatin1Char(var)));
+}
+
+static void listsEqual(QObject *listProp, QObject *array, const char *method)
+{
+ const QByteArray listPropertyPropertyName = QByteArray("listProperty") + method;
+ const QByteArray jsArrayPropertyName = QByteArray("jsArray") + method;
+
+ const QQmlListReference listPropertyProperty(listProp, listPropertyPropertyName.constData());
+ const QVariantList jsArrayProperty = array->property(jsArrayPropertyName.constData()).toList();
+
+ const qsizetype listPropertyCount = listPropertyProperty.count();
+ QCOMPARE(listPropertyCount, jsArrayProperty.count());
+
+ for (qsizetype i = 0; i < listPropertyCount; ++i)
+ QCOMPARE(listPropertyProperty.at(i), jsArrayProperty.at(i).value<QObject *>());
+}
+
void tst_QmlCppCodegen::initTestCase()
{
#ifdef QT_TEST_FORCE_INTERPRETER
@@ -173,40 +494,91 @@ void tst_QmlCppCodegen::initTestCase()
#endif
}
-void tst_QmlCppCodegen::simpleBinding()
+void tst_QmlCppCodegen::cleanupTestCase()
+{
+ // This code checks for basic blocks validation failures in the tests
+ QStringList expectedFailures = {
+ "codegen_test_module_basicBlocksWithBackJump_infinite_qml.cpp",
+ "codegen_test_module_verify_basicBlocksWithBackJump_infinite_qml.cpp",
+ };
+
+ QString generatedCppFolder = GENERATED_CPP_FOLDER;
+ QDirIterator dirIterator(generatedCppFolder, { "*.cpp" }, QDir::Files);
+ while (dirIterator.hasNext()) {
+ QFile file(dirIterator.next());
+ if (!file.open(QIODeviceBase::ReadOnly | QIODeviceBase::Text)) {
+ qDebug() << "Couldn't open generated file";
+ continue;
+ }
+
+ const auto content = file.readAll();
+ if (bool validationFailed = content.contains("// QV4_BASIC_BLOCK_VALIDATION_FAILED:"_L1)) {
+ if (expectedFailures.contains(dirIterator.fileInfo().fileName())) {
+ QEXPECT_FAIL("", "Expected failure", Continue);
+ }
+ const auto message = file.fileName() + ": Basic blocks validation failed.";
+ QVERIFY2(!validationFailed, message.toStdString().c_str());
+ }
+ }
+}
+
+void tst_QmlCppCodegen::accessModelMethodFromOutSide()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Test.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/AccessModelMethodsFromOutside.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+
+ QTest::ignoreMessage(QtDebugMsg, "3");
+ QTest::ignoreMessage(QtDebugMsg, "Apple");
QScopedPointer<QObject> object(component.create());
- QVERIFY2(!object.isNull(), component.errorString().toUtf8().constData());
- QCOMPARE(object->property("foo").toInt(), int(3));
- {
- CppBaseClass *base = qobject_cast<CppBaseClass *>(object.data());
- Q_ASSERT(base);
- QVERIFY(!base->cppProp.hasBinding());
- QCOMPARE(base->cppProp.value(), 7);
- QVERIFY(base->cppProp2.hasBinding());
- QCOMPARE(base->cppProp2.value(), 14);
- base->cppProp.setValue(9);
- QCOMPARE(base->cppProp.value(), 9);
- QCOMPARE(base->cppProp2.value(), 18);
- }
+ QCOMPARE(object->property("cost1").toDouble(), 3);
+ QCOMPARE(object->property("name1").toString(), u"Orange"_s);
+ QCOMPARE(object->property("cost2").toDouble(), 1.95);
+ QCOMPARE(object->property("name2").toString(), u"Banana"_s);
}
-void tst_QmlCppCodegen::cppValueTypeList()
+void tst_QmlCppCodegen::aliasLookup()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Test.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/aliasLookup.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
- QVERIFY2(!object.isNull(), component.errorString().toUtf8().constData());
- QCOMPARE(object->property("a").toInt(), 16);
- QMetaObject::invokeMethod(object.data(), "incA");
- QCOMPARE(object->property("a").toInt(), 17);
+ QVERIFY(!object.isNull());
- QCOMPARE(object->property("b").toDouble(), 0.25);
- QMetaObject::invokeMethod(object.data(), "incB");
- QCOMPARE(object->property("b").toDouble(), 13.5);
+ const QVariant t = object->property("t");
+ QCOMPARE(t.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(t.toString(), u"12"_s);
+}
+
+void tst_QmlCppCodegen::ambiguousAs()
+{
+ QQmlEngine e;
+ const QUrl url(u"qrc:/qt/qml/TestTypes/ambiguousAs.qml"_s);
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("other").value<QObject *>(), o.data());
+ o->setProperty("useSelf", QVariant::fromValue(false));
+ QCOMPARE(o->property("other").value<QObject *>(), nullptr);
+}
+
+void tst_QmlCppCodegen::ambiguousSignals()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguousSignals.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"tomorrow"_s);
+ Person *p = qobject_cast<Person *>(o.data());
+ QVERIFY(p);
+ emit p->ambiguous(12);
+ QCOMPARE(o->objectName(), u"12foo"_s);
+ emit p->ambiguous();
+ QCOMPARE(o->objectName(), u"9foo"_s);
}
void tst_QmlCppCodegen::anchorsFill()
@@ -231,342 +603,629 @@ void tst_QmlCppCodegen::anchorsFill()
QCOMPARE(child->property("width").toInt(), 47);
}
-void tst_QmlCppCodegen::signalHandler()
+void tst_QmlCppCodegen::argumentConversion()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signal.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/argumentConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ auto checkNaN = [&](const char *propName) {
+ const QVariant prop = o->property(propName);
+ QCOMPARE(prop.metaType(), QMetaType::fromType<double>());
+ QVERIFY(qIsNaN(prop.toDouble()));
+ };
+
+ checkNaN("a");
+ checkNaN("b");
+ checkNaN("e");
+
+ QCOMPARE(o->property("c").toDouble(), 3.0);
+ QCOMPARE(o->property("d").toDouble(), -1.0);
+ QCOMPARE(o->property("f").toDouble(), 10.0);
+}
+
+void tst_QmlCppCodegen::array()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/array.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->objectName(), QString());
- QCOMPARE(object->property("ff").toInt(), 4);
+ const QJSValue value1 = object->property("values1").value<QJSValue>();
+ QVERIFY(value1.isArray());
+ QCOMPARE(value1.property(u"length"_s).toInt(), 3);
+ QCOMPARE(value1.property(0).toInt(), 1);
+ QCOMPARE(value1.property(1).toInt(), 2);
+ QCOMPARE(value1.property(2).toInt(), 3);
- object->setObjectName(u"foo"_s);
- QCOMPARE(object->property("ff").toInt(), 12);
+ const QJSValue value2 = object->property("values2").value<QJSValue>();
+ QVERIFY(value2.isArray());
+ QCOMPARE(value2.property(u"length"_s).toInt(), 0);
}
-void tst_QmlCppCodegen::idAccess()
+void tst_QmlCppCodegen::arrayCtor()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/idAccess.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/arrayCtor.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QVERIFY(object->property("y").toInt() != 48);
- QCOMPARE(object->property("y").toInt(), 12);
- object->setProperty("z", 13);
- QCOMPARE(object->property("y").toInt(), 13);
- object->setProperty("x", QVariant::fromValue(333));
- QCOMPARE(object->property("y").toInt(), 48);
+ QCOMPARE(object->property("defaultCtor"), QVariant::fromValue(QList<int>()));
+ QCOMPARE(object->property("oneArgCtor"), QVariant::fromValue(QList<int>(5)));
+ QCOMPARE(object->property("multiArgCtor"), QVariant::fromValue(QList<int>({2, 3, 3, 4})));
+ QCOMPARE(object->property("arrayTrue"), QVariant::fromValue(QList<bool>({true})));
+ QCOMPARE(object->property("arrayFalse"), QVariant::fromValue(QList<bool>({false})));
+ QCOMPARE(object->property("arrayNegative"), QVariant::fromValue(QList<double>()));
+}
- // The binding was broken by setting the property
- object->setProperty("z", 14);
- QCOMPARE(object->property("y").toInt(), 48);
+void tst_QmlCppCodegen::asCast()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/asCast.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
- QObject *ttt = qmlContext(object.data())->objectForName(u"ttt"_s);
- QFont f = qvariant_cast<QFont>(ttt->property("font"));
- QCOMPARE(f.pointSize(), 22);
+ QQmlContext *context = qmlContext(root.data());
+ const QObject *object = context->objectForName(u"object"_s);
+ const QObject *item = context->objectForName(u"item"_s);
+ const QObject *rectangle = context->objectForName(u"rectangle"_s);
+ const QObject *dummy = context->objectForName(u"dummy"_s);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsObject")), object);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsItem")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsDummy")), nullptr);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsObject")), item);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsItem")), item);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsDummy")), nullptr);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsObject")), rectangle);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsItem")), rectangle);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsRectangle")), rectangle);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsDummy")), nullptr);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsObject")), dummy);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsItem")), dummy);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsDummy")), dummy);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("nullAsObject")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("nullAsItem")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("nullAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("nullAsDummy")), nullptr);
+
+ QCOMPARE(qvariant_cast<QObject *>(root->property("undefinedAsObject")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("undefinedAsItem")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("undefinedAsRectangle")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(root->property("undefinedAsDummy")), nullptr);
}
-static QByteArray arg1()
+void tst_QmlCppCodegen::attachedBaseEnum()
{
- const QStringList args = QCoreApplication::instance()->arguments();
- return args.size() > 1 ? args[1].toUtf8() : QByteArray("undefined");
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/attachedBaseEnum.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+
+ QObject *drag = qvariant_cast<QObject *>(object->property("drag"));
+ QVERIFY(drag);
+
+ // Drag.YAxis is 2, but we cannot #include it here.
+ bool ok = false;
+ QCOMPARE(drag->property("axis").toInt(&ok), 2);
+ QVERIFY(ok);
}
-void tst_QmlCppCodegen::globals()
+void tst_QmlCppCodegen::attachedSelf()
{
QQmlEngine engine;
- int exitCode = -1;
- QObject::connect(&engine, &QQmlEngine::exit, [&](int code) { exitCode = code; });
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/globals.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/SelectionRectangle.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- const QByteArray message = QByteArray("Start 2 ") + arg1();
- QTest::ignoreMessage(QtDebugMsg, message.constData());
+ QObject *handle = qvariant_cast<QObject *>(o->property("aa"));
+ QVERIFY(handle);
+ QVERIFY(qvariant_cast<QObject *>(handle->property("rect")) != nullptr);
+}
+void tst_QmlCppCodegen::attachedType()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/text.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QTRY_COMPARE(exitCode, 0);
+ QCOMPARE(object->property("dayz").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
+ QCOMPARE(object->property("oParty").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
- QObject *application = qvariant_cast<QObject *>(object->property("application"));
- QVERIFY(application);
- QCOMPARE(QString::fromUtf8(application->metaObject()->className()),
- u"QQuickApplication"_s);
+ QObject *party = qvariant_cast<QObject *>(object->property("party"));
+ QVERIFY(party);
+ QCOMPARE(party->property("eee").toInt(), 21);
+ QCOMPARE(party->property("fff").toInt(), 33);
+ QCOMPARE(object->property("ggg").toInt(), 37);
+}
- QTest::ignoreMessage(QtDebugMsg, "End");
- QMetaObject::invokeMethod(application, "aboutToQuit");
+void tst_QmlCppCodegen::badSequence()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/badSequence.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- const QVariant somewhere = object->property("somewhere");
- QCOMPARE(somewhere.userType(), QMetaType::QUrl);
- QCOMPARE(qvariant_cast<QUrl>(somewhere).toString(), u"qrc:/somewhere/else.qml"_s);
+ Person *self = qobject_cast<Person *>(o.data());
+ QVERIFY(self);
+ QVERIFY(self->barzles().isEmpty());
+ QVERIFY(self->cousins().isEmpty());
- const QVariant somewhereString = object->property("somewhereString");
- QCOMPARE(somewhereString.userType(), QMetaType::QString);
- QCOMPARE(somewhereString.toString(), u"qrc:/somewhere/else.qml"_s);
+ Person *other = o->property("other").value<Person *>();
+ QVERIFY(other);
- const QVariant plain = object->property("plain");
- QCOMPARE(plain.userType(), QMetaType::QUrl);
- QCOMPARE(qvariant_cast<QUrl>(plain).toString(), u"/not/here.qml"_s);
+ QVERIFY(other->barzles().isEmpty());
+ QVERIFY(other->cousins().isEmpty());
+
+ Barzle f1;
+ Barzle f2;
+ const QList<Barzle *> barzles { &f1, &f2 };
+ const QList<Person *> cousins { self, other };
+
+ other->setBarzles(barzles);
+ QCOMPARE(self->barzles(), barzles);
+ QCOMPARE(self->property("l").toInt(), 2);
+
+ other->setCousins(cousins);
+ QCOMPARE(self->cousins(), cousins);
+ QCOMPARE(self->property("m").toInt(), 2);
+
+ QQmlListProperty<Person> others
+ = self->property("others").value<QQmlListProperty<Person>>();
+ QCOMPARE(others.count(&others), 2);
+ QCOMPARE(others.at(&others, 0), cousins[0]);
+ QCOMPARE(others.at(&others, 1), cousins[1]);
+
+ QQmlListProperty<Person> momsCousins
+ = self->property("momsCousins").value<QQmlListProperty<Person>>();
+ QCOMPARE(momsCousins.count(&momsCousins), 2);
+ QCOMPARE(momsCousins.at(&momsCousins, 0), cousins[0]);
+ QCOMPARE(momsCousins.at(&momsCousins, 1), cousins[1]);
+
+ QQmlListProperty<Person> dadsCousins
+ = self->property("dadsCousins").value<QQmlListProperty<Person>>();
+ QCOMPARE(dadsCousins.count(&dadsCousins), 1);
+ QCOMPARE(dadsCousins.at(&dadsCousins, 0), other);
}
-void tst_QmlCppCodegen::multiLookup()
+static bool expectingMessage = false;
+static void handler(QtMsgType type, const QMessageLogContext &, const QString &message)
+{
+ QVERIFY(expectingMessage);
+ QCOMPARE(type, QtDebugMsg);
+ QCOMPARE(message, u"false");
+ expectingMessage = false;
+}
+
+void tst_QmlCppCodegen::basicBlocksWithBackJump()
{
- // Multiple lookups of singletons (Qt in this case) don't clash with one another.
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/immediateQuit.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/basicBlocksWithBackJump.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
- const QByteArray message = QByteArray("End: ") + arg1();
- QTest::ignoreMessage(QtDebugMsg, message.constData());
+ const auto oldHandler = qInstallMessageHandler(&handler);
+ const auto guard = qScopeGuard([oldHandler]() { qInstallMessageHandler(oldHandler); });
- QSignalSpy quitSpy(&engine, &QQmlEngine::quit);
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(quitSpy.size(), 1);
+ // t1 does not log anything
+ QMetaObject::invokeMethod(o.data(), "t1");
+
+ // t2 logs "false" exactly once
+ expectingMessage = true;
+ QMetaObject::invokeMethod(o.data(), "t2");
+ QVERIFY(!expectingMessage);
+
+ // t3 logs "false" exactly once
+ expectingMessage = true;
+ QMetaObject::invokeMethod(o.data(), "t3");
+ QVERIFY(!expectingMessage);
}
-void tst_QmlCppCodegen::enums()
+void tst_QmlCppCodegen::basicBlocksWithBackJump_infinite()
{
QQmlEngine engine;
- {
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Enums.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/basicBlocksWithBackJump_infinite.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+}
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/Enums.qml:4:1: "
- "QML Enums: Layout must be attached to Item elements");
- QScopedPointer<QObject> object(component.create());
+void tst_QmlCppCodegen::basicDTZ()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/basicDTZ.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
- QVERIFY(!object.isNull());
- bool ok = false;
- QCOMPARE(object->property("appState").toInt(&ok), 2);
- QVERIFY(ok);
- QCOMPARE(object->property("color").toString(), u"blue"_s);
+ QCOMPARE(o->property("title").toString(), u"none");
- QTRY_COMPARE(object->property("appState").toInt(&ok), 1);
- QVERIFY(ok);
- QCOMPARE(object->property("color").toString(), u"green"_s);
+ QMetaObject::invokeMethod(o.data(), "t1");
+ QMetaObject::invokeMethod(o.data(), "t2");
+ QMetaObject::invokeMethod(o.data(), "t3");
+
+ QCOMPARE(o->property("title").toString(), u"Baz 41");
+}
+
+void tst_QmlCppCodegen::bindToValueType()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/bindToValueType.qml"_s));
+ checkColorProperties(&component);
+}
+
+void tst_QmlCppCodegen::bindingExpression()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BindingExpression.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+
+ QObject *child = qmlContext(object.data())->objectForName(u"child"_s);
+
+ double width = 200;
+ double y = 10;
+ for (int i = 0; i < 10; ++i) {
+ QCOMPARE(object->property("width").toDouble(), width);
+ QCOMPARE(object->property("height").toDouble(), width);
+ QCOMPARE(object->property("y").toDouble(), y);
- const auto func = qmlAttachedPropertiesFunction(
- object.data(), QMetaType::fromName("QQuickLayout*").metaObject());
+ const double childY = y + (width - 100) / 2;
+ QCOMPARE(child->property("y").toDouble(), childY);
+ QCOMPARE(object->property("mass"), childY > 100 ? u"heavy"_s : u"light"_s);
+ QCOMPARE(object->property("test_division").toDouble(), width / 1000 + 50);
+ QCOMPARE(object->property("test_ternary").toDouble(), 2.2);
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/enumsInOtherObject.qml:4:25: "
- "QML Enums: Layout must be attached to Item elements");
- QObject *attached = qmlAttachedPropertiesObject(object.data(), func);
+ const int test_switch = object->property("test_switch").toInt();
+ switch (int(width) % 3) {
+ case 0:
+ QCOMPARE(test_switch, 130);
+ break;
+ case 1:
+ QCOMPARE(test_switch, 380);
+ break;
+ case 2:
+ QCOMPARE(test_switch, 630);
+ break;
+ }
- const QVariant prop = attached->property("alignment");
- QVERIFY(prop.isValid());
- QCOMPARE(qvariant_cast<Qt::Alignment>(prop), Qt::AlignCenter);
+ width = 200 * i;
+ y = 10 + i;
+ object->setProperty("width", width);
+ object->setProperty("y", y);
}
- {
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumsInOtherObject.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("color").toString(), u"blue"_s);
- QTRY_COMPARE(object->property("color").toString(), u"green"_s);
+}
+
+void tst_QmlCppCodegen::blockComments()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/blockComments.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("implicitHeight").toDouble(), 8.0);
+}
+
+void tst_QmlCppCodegen::boolCoercions()
+{
+ QQmlEngine e;
+ const QUrl url(u"qrc:/qt/qml/TestTypes/boolCoercions.qml"_s);
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":41:5: Unable to assign [undefined] to bool"_L1));
+ QScopedPointer<QObject> o(c.create());
+
+ for (char p = '1'; p <= '8'; ++p) {
+ const QVariant t = o->property(qPrintable(QLatin1String("t%1").arg(p)));
+ QCOMPARE(t.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(t.toBool());
+ }
+
+ for (char p = '1'; p <= '5'; ++p) {
+ const QVariant f = o->property(qPrintable(QLatin1String("f%1").arg(p)));
+ QCOMPARE(f.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(!f.toBool());
}
}
-void tst_QmlCppCodegen::funcWithParams()
+void tst_QmlCppCodegen::boolPointerMerge()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/boolPointerMerge.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QObject *item = o->property("item").value<QObject *>();
+ QVERIFY(item);
+ QCOMPARE(item->property("ppp").toInt(), -99);
+}
+
+void tst_QmlCppCodegen::boundComponents()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/funcWithParams.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("bar").toInt(), 30);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/boundComponents.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QObject *c1o = o->property("o").value<QObject *>();
+ QVERIFY(c1o != nullptr);
+ QCOMPARE(c1o->objectName(), u"bar"_s);
+
+ QObject *c2o = c1o->property("o").value<QObject *>();
+ QVERIFY(c2o != nullptr);
+ QCOMPARE(c2o->objectName(), u"bar12"_s);
}
-void tst_QmlCppCodegen::intOverflow()
+void tst_QmlCppCodegen::callContextPropertyLookupResult()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intOverflow.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("a").toDouble(), 1.09951162778e+12);
- QCOMPARE(object->property("b").toInt(), 5);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/callContextPropertyLookupResult.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QVERIFY(qvariant_cast<QQmlComponent *>(o->property("c")) != nullptr);
}
-void tst_QmlCppCodegen::stringLength()
+void tst_QmlCppCodegen::callWithSpread()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringLength.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("stringLength").toInt(), 8);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/callWithSpread.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtCriticalMsg, "That is great!");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
}
-void tst_QmlCppCodegen::scopeVsObject()
+void tst_QmlCppCodegen::colorAsVariant()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/scopeVsObject.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/colorAsVariant.qml"_s));
+ checkColorProperties(&component);
+}
+
+void tst_QmlCppCodegen::colorString()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/colorString.qml"_s));
+
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
+
+ QCOMPARE(qvariant_cast<QColor>(rootObject->property("c")), QColor::fromRgb(0xdd, 0xdd, 0xdd));
+ QCOMPARE(qvariant_cast<QColor>(rootObject->property("d")), QColor::fromRgb(0xaa, 0xaa, 0xaa));
+ QCOMPARE(qvariant_cast<QColor>(rootObject->property("e")), QColor::fromRgb(0x11, 0x22, 0x33));
+}
+
+void tst_QmlCppCodegen::compareOriginals()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compareOriginals.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->property("objectName").toString(), u"foobar"_s);
+
+ QCOMPARE(object->property("compareOriginals").toInt(), 5);
+ QVERIFY(object->property("optionalThis").toBool());
}
-void tst_QmlCppCodegen::compositeTypeMethod()
+void tst_QmlCppCodegen::comparisonTypes()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compositeTypeMethod.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/comparisonTypes.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QSignalSpy spy(object.data(), SIGNAL(foo()));
- QTRY_VERIFY(spy.size() > 0);
+
+ QCOMPARE(object->property("found").toInt(), 1);
+ QCOMPARE(object->property("foundStrict").toInt(), 0);
+
+ QCOMPARE(object->property("foundNot").toInt(), 2);
+ QCOMPARE(object->property("foundNotStrict").toInt(), 10);
}
-void tst_QmlCppCodegen::excessiveParameters()
+void tst_QmlCppCodegen::componentReturnType()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/excessiveParameters.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/componentReturnType.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QSignalSpy spy(object.data(), SIGNAL(foo()));
- QTRY_VERIFY(spy.size() > 0);
+
+ QCOMPARE(object->property("count").toInt(), 10);
+ QCOMPARE(QQmlListReference(object.data(), "children").count(), 11);
}
-void tst_QmlCppCodegen::jsImport()
+void tst_QmlCppCodegen::compositeSingleton()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsimport.qml"_s));
+ engine.addImportPath(u":/qt/qml/TestTypes/imports/"_s);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compositesingleton.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("value").toInt(), 42);
+ QScopedPointer<QObject> o(component.create());
+ QCOMPARE(o->property("x").toDouble(), 4.5);
+ QCOMPARE(o->property("y").toDouble(), 10.0);
+ QCOMPARE(o->property("smooth").toBool(), true);
}
-void tst_QmlCppCodegen::jsmoduleImport()
+void tst_QmlCppCodegen::compositeTypeMethod()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsmoduleimport.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compositeTypeMethod.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->property("ok").toBool(), true);
- QVariant okFunc = object->property("okFunc");
- QCOMPARE(okFunc.metaType(), QMetaType::fromType<QJSValue>());
- QJSValue val = engine.toScriptValue(okFunc);
- QJSValue result = val.call();
- QVERIFY(result.isBool());
- QVERIFY(result.toBool());
+ QSignalSpy spy(object.data(), SIGNAL(foo()));
+ QTRY_VERIFY(spy.size() > 0);
}
-void tst_QmlCppCodegen::methods()
+void tst_QmlCppCodegen::consoleObject()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/methods.qml"_s));
- QVERIFY(component.isReady());
-
- QTest::ignoreMessage(QtDebugMsg, "The Bar");
- QTest::ignoreMessage(QtWarningMsg, QRegularExpression(u"TypeError: .* is not a function"_s));
- QScopedPointer<QObject> obj(component.create());
- QVERIFY(obj);
- BirthdayParty *party(qobject_cast<BirthdayParty *>(obj.data()));
-
- QVERIFY(party && party->host());
- QCOMPARE(party->guestCount(), 5);
+ static const QString urlString = u"qrc:/qt/qml/TestTypes/consoleObject.qml"_s;
+ QQmlComponent c(&engine, QUrl(urlString));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- bool foundGreen = false;
- bool foundFoo = false;
- for (int ii = 0; ii < party->guestCount(); ++ii) {
- if (party->guest(ii)->name() == u"William Green"_s)
- foundGreen = true;
- if (party->guest(ii)->name() == u"The Foo"_s)
- foundFoo = true;
- }
+ QTest::ignoreMessage(QtDebugMsg, "b 4.55");
+ QTest::ignoreMessage(QtDebugMsg, "b 4.55");
+ QTest::ignoreMessage(QtInfoMsg, "b 4.55");
+ QTest::ignoreMessage(QtWarningMsg, "b 4.55");
+ QTest::ignoreMessage(QtCriticalMsg, "b 4.55");
- QVERIFY(foundGreen);
- QVERIFY(foundFoo);
+ // Unfortunately we cannot check the logging category with QTest::ignoreMessage
+ QTest::ignoreMessage(QtDebugMsg, "b 4.55");
+ QTest::ignoreMessage(QtDebugMsg, "b 4.55");
+ QTest::ignoreMessage(QtInfoMsg, "b 4.55");
+ QTest::ignoreMessage(QtWarningMsg, "b 4.55");
+ QTest::ignoreMessage(QtCriticalMsg, "b 4.55");
- QCOMPARE(obj->property("n1").toString(), u"onGurk"_s);
- QCOMPARE(obj->property("n2").toString(), u"onSemmeln"_s);
- QCOMPARE(obj->property("n3"), QVariant());
+ const QRegularExpression re(u"QQmlComponentAttached\\(0x[0-9a-f]+\\) b 4\\.55"_s);
+ QTest::ignoreMessage(QtDebugMsg, re);
+ QTest::ignoreMessage(QtDebugMsg, re);
+ QTest::ignoreMessage(QtInfoMsg, re);
+ QTest::ignoreMessage(QtWarningMsg, re);
+ QTest::ignoreMessage(QtCriticalMsg, re);
- {
- QVariant ret;
- obj->metaObject()->invokeMethod(obj.data(), "retrieveVar", Q_RETURN_ARG(QVariant, ret));
- QCOMPARE(ret.typeId(), QMetaType::QString);
- QCOMPARE(ret.toString(), u"Jack Smith"_s);
- }
+ QTest::ignoreMessage(QtDebugMsg, "a undefined b false null 7");
+ QTest::ignoreMessage(QtDebugMsg, "");
+ QTest::ignoreMessage(QtDebugMsg, "4");
+ QTest::ignoreMessage(QtDebugMsg, "");
- {
- QString ret;
- obj->metaObject()->invokeMethod(obj.data(), "retrieveString", Q_RETURN_ARG(QString, ret));
- QCOMPARE(ret, u"Jack Smith"_s);
- }
+ const QRegularExpression re2(u"QQmlComponentAttached\\(0x[0-9a-f]+\\)"_s);
+ QTest::ignoreMessage(QtDebugMsg, re2);
- QCOMPARE(party->host()->shoeSize(), 12);
- obj->metaObject()->invokeMethod(obj.data(), "storeElement");
- QCOMPARE(party->host()->shoeSize(), 13);
- QJSManagedValue v = engine.toManagedValue(obj->property("dresses"));
- QVERIFY(v.isArray());
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QJSManagedValue inner(v.property(2), &engine);
- QVERIFY(inner.isArray());
- QCOMPARE(inner.property(0).toInt(), 1);
- QCOMPARE(inner.property(1).toInt(), 2);
- QCOMPARE(inner.property(2).toInt(), 3);
+ auto oldHandler = qInstallMessageHandler(
+ [](QtMsgType, const QMessageLogContext &ctxt, const QString &) {
+ QCOMPARE(ctxt.file, urlString.toUtf8());
+ QCOMPARE(ctxt.function, QByteArray("expression for onCompleted"));
+ QVERIFY(ctxt.line > 0);
+ });
+ const auto guard = qScopeGuard([oldHandler]() { qInstallMessageHandler(oldHandler); });
- QCOMPARE(obj->property("enumValue").toInt(), 2);
+ QScopedPointer<QObject> p(c.create());
+ QVERIFY(!p.isNull());
}
-void tst_QmlCppCodegen::math()
+void tst_QmlCppCodegen::consoleTrace()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/math.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/consoleTrace.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
+
+#if !defined(QT_NO_DEBUG) || defined(QT_TEST_FORCE_INTERPRETER)
+ // All line numbers in debug mode or when interpreting
+
+ QTest::ignoreMessage(QtDebugMsg, R"(c (qrc:/qt/qml/TestTypes/consoleTrace.qml:6)
+b (qrc:/qt/qml/TestTypes/consoleTrace.qml:5)
+a (qrc:/qt/qml/TestTypes/consoleTrace.qml:4)
+expression for onCompleted (qrc:/qt/qml/TestTypes/consoleTrace.qml:7))");
+#else
+ // Only top-most line number otherwise
+
+ QTest::ignoreMessage(QtDebugMsg, R"(c (qrc:/qt/qml/TestTypes/consoleTrace.qml:6)
+b (qrc:/qt/qml/TestTypes/consoleTrace.qml)
+a (qrc:/qt/qml/TestTypes/consoleTrace.qml)
+expression for onCompleted (qrc:/qt/qml/TestTypes/consoleTrace.qml))");
+#endif
+
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->property("a").toInt(), 9);
- QCOMPARE(object->property("b").toDouble(), 50.0 / 22.0);
}
-void tst_QmlCppCodegen::unknownParameter()
+void tst_QmlCppCodegen::construct()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unknownParameter.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/construct.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- QCOMPARE(object->property("cppProp").toInt(), 18);
+
+ const QJSManagedValue v = engine.toManagedValue(object->property("foo"));
+ QVERIFY(v.isError());
+ QCOMPARE(v.toString(), u"Error: bar"_s);
+
+ QCOMPARE(object->property("aaa").toInt(), 12);
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/construct.qml:9: Error: ouch");
+ object->metaObject()->invokeMethod(object.data(), "ouch");
+ QCOMPARE(object->property("aaa").toInt(), 13);
}
-void tst_QmlCppCodegen::array()
+void tst_QmlCppCodegen::contextParam()
{
+ // The compiler cannot resolve context parameters.
+ // Make sure the binding is interpreted.
+
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/array.qml"_s));
+
+ QVariantMap m;
+ m.insert(u"foo"_s, 10);
+ engine.rootContext()->setContextProperty(u"contextParam"_s, m);
+
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/contextParam.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- const QJSValue value1 = object->property("values1").value<QJSValue>();
- QVERIFY(value1.isArray());
- QCOMPARE(value1.property(u"length"_s).toInt(), 3);
- QCOMPARE(value1.property(0).toInt(), 1);
- QCOMPARE(value1.property(1).toInt(), 2);
- QCOMPARE(value1.property(2).toInt(), 3);
- const QJSValue value2 = object->property("values2").value<QJSValue>();
- QVERIFY(value2.isArray());
- QCOMPARE(value2.property(u"length"_s).toInt(), 0);
+ QCOMPARE(object->property("foo").toInt(), 10);
}
-void tst_QmlCppCodegen::equalsUndefined()
+void tst_QmlCppCodegen::conversionDecrement()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalsUndefined.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/conversionDecrement.qml"_s));
- QCOMPARE(object->property("a").toInt(), 50);
- QCOMPARE(object->property("b").toInt(), 5000);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("currentPageIndex").toInt(), 0);
+ o->setProperty("pages", 5);
+ QCOMPARE(o->property("currentPageIndex").toInt(), 3);
+ o->setProperty("pages", 4);
+ QCOMPARE(o->property("currentPageIndex").toInt(), 0);
+ o->setProperty("pages", 6);
+ QCOMPARE(o->property("currentPageIndex").toInt(), 4);
+ o->setProperty("pages", 60);
+ QCOMPARE(o->property("currentPageIndex").toInt(), 3);
+}
+
+void tst_QmlCppCodegen::conversionInDeadCode()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/conversionInDeadCode.qml"_s));
+
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("a").toInt(), -4);
+ QCOMPARE(o->property("b").toInt(), 12);
+ QCOMPARE(o->property("c").toInt(), 10);
+ QCOMPARE(o->property("d").toInt(), 10);
+ QCOMPARE(o->property("e").toInt(), 10);
+ QCOMPARE(o->property("f").toInt(), 20);
+ QCOMPARE(o->property("g").toInt(), 33);
}
void tst_QmlCppCodegen::conversions()
@@ -699,157 +1358,260 @@ void tst_QmlCppCodegen::conversions()
QVERIFY(!undef.isValid());
}
-void tst_QmlCppCodegen::interestingFiles_data()
+void tst_QmlCppCodegen::convertPrimitiveToVar()
{
- QTest::addColumn<QString>("file");
- QTest::addColumn<bool>("isValid");
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/convertPrimitiveToVar.qml"_s));
- QTest::addRow("conversions2") << u"conversions2.qml"_s << true;
- QTest::addRow("TestCase") << u"TestCase.qml"_s << true;
- QTest::addRow("layouts") << u"layouts.qml"_s << true;
- QTest::addRow("interactive") << u"interactive.qml"_s << true;
- QTest::addRow("Panel") << u"Panel.qml"_s << true;
- QTest::addRow("ProgressBar") << u"ProgressBar/ProgressBar.ui.qml"_s << true;
- QTest::addRow("Root") << u"ProgressBar/Root.qml"_s << true;
- QTest::addRow("noscope") << u"noscope.qml"_s << true;
- QTest::addRow("dynamicscene") << u"dynamicscene.qml"_s << true;
- QTest::addRow("curlygrouped") << u"curlygrouped.qml"_s << true;
- QTest::addRow("cycleHead") << u"cycleHead.qml"_s << false;
- QTest::addRow("deadStoreLoop") << u"deadStoreLoop.qml"_s << true;
- QTest::addRow("moveRegVoid") << u"moveRegVoid.qml"_s << true;
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("offsetValue").toInt(), 41);
}
-void tst_QmlCppCodegen::interestingFiles()
+void tst_QmlCppCodegen::convertQJSPrimitiveValueToIntegral()
{
- QFETCH(QString, file);
- QFETCH(bool, isValid);
-
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/%1"_s.arg(file)));
- if (isValid) {
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- } else {
- QVERIFY(component.isError());
- }
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/convertQJSPrimitiveValueToIntegral.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
}
-void tst_QmlCppCodegen::extendedTypes()
+void tst_QmlCppCodegen::convertToOriginalReadAcumulatorForUnaryOperators()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/extendedTypes.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
-
- QTest::ignoreMessage(QtDebugMsg, "6 QSizeF(10, 20) 30");
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/convertToOriginalReadAcumulatorForUnaryOperators.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
- QCOMPARE(object->property("a").toInt(), 6);
- QCOMPARE(qvariant_cast<QSizeF>(object->property("b")), QSizeF(10, 20));
- QCOMPARE(object->property("c").toInt(), 30);
- QCOMPARE(object->property("d").toString(), u"QSizeF(10, 20)"_s);
+void tst_QmlCppCodegen::cppMethodListReturnType()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/CppMethodListReturnType.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QCOMPARE(object->property("e").toInt(), 2);
+ QCOMPARE(o->property("list").toList()[2].toInt(), 2);
}
-void tst_QmlCppCodegen::construct()
+void tst_QmlCppCodegen::cppValueTypeList()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/construct.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Test.qml"_s));
QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
-
- const QJSManagedValue v = engine.toManagedValue(object->property("foo"));
- QVERIFY(v.isError());
- QCOMPARE(v.toString(), u"Error: bar"_s);
+ QVERIFY2(!object.isNull(), component.errorString().toUtf8().constData());
+ QCOMPARE(object->property("a").toInt(), 16);
+ QMetaObject::invokeMethod(object.data(), "incA");
+ QCOMPARE(object->property("a").toInt(), 17);
- QCOMPARE(object->property("aaa").toInt(), 12);
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/construct.qml:9: Error: ouch");
- object->metaObject()->invokeMethod(object.data(), "ouch");
- QCOMPARE(object->property("aaa").toInt(), 13);
+ QCOMPARE(object->property("b").toDouble(), 0.25);
+ QMetaObject::invokeMethod(object.data(), "incB");
+ QCOMPARE(object->property("b").toDouble(), 13.5);
}
-void tst_QmlCppCodegen::contextParam()
+void tst_QmlCppCodegen::dateConstruction()
{
- // The compiler cannot resolve context parameters.
- // Make sure the binding is interpreted.
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dateConstruction.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QDateTime now = QDateTime::currentDateTime();
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(o->property("now").value<QDateTime>().toMSecsSinceEpoch() >= now.toMSecsSinceEpoch());
+ QCOMPARE(o->property("now2"), o->property("now"));
+ QCOMPARE(o->property("fromString").value<QDateTime>(),
+ QDateTime(QDate(1995, 12, 17), QTime(3, 24), QTimeZone::LocalTime));
+ QCOMPARE(o->property("fromNumber").value<QDateTime>().toMSecsSinceEpoch(), 777);
+ QCOMPARE(o->property("fromPrimitive").value<QDateTime>().toMSecsSinceEpoch(), 57);
+ o->setObjectName("foo"_L1);
+ QCOMPARE(o->property("fromPrimitive").value<QDateTime>(),
+ QDateTime(QDate(1997, 2, 13), QTime(13, 4, 12), QTimeZone::LocalTime));
+
+ QCOMPARE(o->property("from2").value<QDateTime>(),
+ QDateTime(QDate(1996, 2, 1), QTime(), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from3").value<QDateTime>(),
+ QDateTime(QDate(1996, 3, 3), QTime(), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from4").value<QDateTime>(),
+ QDateTime(QDate(1996, 4, 4), QTime(5, 0), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from5").value<QDateTime>(),
+ QDateTime(QDate(1996, 5, 5), QTime(6, 7), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from6").value<QDateTime>(),
+ QDateTime(QDate(1996, 6, 6), QTime(7, 8, 9), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from7").value<QDateTime>(),
+ QDateTime(QDate(1996, 7, 7), QTime(8, 9, 10, 11), QTimeZone::LocalTime));
+ QCOMPARE(o->property("from8").value<QDateTime>(),
+ QDateTime(QDate(1996, 8, 8), QTime(9, 10, 11, 12), QTimeZone::LocalTime));
+
+ QCOMPARE(o->property("withUnderflow").value<QDateTime>(),
+ QDateTime(QDate(-6, 7, 24), QTime(16, 51, 50, 990), QTimeZone::LocalTime));
+ QCOMPARE(o->property("invalid").value<QDateTime>(), QDateTime());
+}
+void tst_QmlCppCodegen::dateConversions()
+{
QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dateConversions.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- QVariantMap m;
- m.insert(u"foo"_s, 10);
- engine.rootContext()->setContextProperty(u"contextParam"_s, m);
+ Druggeljug *ref = engine.singletonInstance<Druggeljug *>("TestTypes", "Druggeljug");
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/contextParam.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
+ const QDateTime refDate = engine.coerceValue<QDate, QDateTime>(ref->myDate());
+ const QDateTime refTime = engine.coerceValue<QTime, QDateTime>(ref->myTime());
+
+ QCOMPARE(o->property("date").value<QDateTime>(), refDate);
+ QCOMPARE(o->property("time").value<QDateTime>(), refTime);
+
+ QCOMPARE(o->property("dateString").toString(),
+ (engine.coerceValue<QDateTime, QString>(refDate)));
+ QCOMPARE(o->property("dateNumber").toDouble(),
+ (engine.coerceValue<QDateTime, double>(refDate)));
+ QCOMPARE(o->property("timeString").toString(),
+ (engine.coerceValue<QDateTime, QString>(refTime)));
+ QCOMPARE(o->property("timeNumber").toDouble(),
+ (engine.coerceValue<QDateTime, double>(refTime)));
+
+ QMetaObject::invokeMethod(o.data(), "shuffle");
+
+ QCOMPARE(ref->myDate(), (engine.coerceValue<QDateTime, QDate>(refDate)));
+ QCOMPARE(ref->myTime(), (engine.coerceValue<QDateTime, QTime>(refTime)));
+
+ const QDate date = ref->myDate();
+ const QTime time = ref->myTime();
+
+ QCOMPARE(o->property("dateString").toString(), (engine.coerceValue<QDate, QString>(date)));
+ QCOMPARE(o->property("dateNumber").toDouble(), (engine.coerceValue<QDate, double>(date)));
+ QCOMPARE(o->property("timeString").toString(), (engine.coerceValue<QTime, QString>(time)));
+ QCOMPARE(o->property("timeNumber").toDouble(), (engine.coerceValue<QTime, double>(time)));
+
+ QMetaObject::invokeMethod(o.data(), "fool");
+
+ QCOMPARE(ref->myDate(), (engine.coerceValue<QTime, QDate>(time)));
+ QCOMPARE(ref->myTime(), (engine.coerceValue<QDate, QTime>(date)));
+
+ QMetaObject::invokeMethod(o.data(), "invalidate");
+ QMetaObject::invokeMethod(o.data(), "shuffle");
+
+ QCOMPARE(o->property("dateString").toString(), "Invalid Date"_L1);
+ QVERIFY(qIsNaN(o->property("dateNumber").toDouble()));
+ QCOMPARE(o->property("timeString").toString(), "Invalid Date"_L1);
+ QVERIFY(qIsNaN(o->property("timeNumber").toDouble()));
- QCOMPARE(object->property("foo").toInt(), 10);
}
-void tst_QmlCppCodegen::attachedType()
+void tst_QmlCppCodegen::deadShoeSize()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/text.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("dayz").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
- QCOMPARE(object->property("oParty").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
-
- QObject *party = qvariant_cast<QObject *>(object->property("party"));
- QVERIFY(party);
- QCOMPARE(party->property("eee").toInt(), 21);
- QCOMPARE(party->property("fff").toInt(), 33);
- QCOMPARE(object->property("ggg").toInt(), 37);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/deadShoeSize.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/deadShoeSize.qml:5: Error: ouch");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("shoeSize").toInt(), 0);
}
-void tst_QmlCppCodegen::componentReturnType()
+void tst_QmlCppCodegen::dialogButtonBox()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/componentReturnType.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
+ const QUrl copy(u"qrc:/qt/qml/TestTypes/dialogButtonBox.qml"_s);
+ QQmlComponent c(&engine, copy);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QObject *footer = o->property("footer").value<QObject *>();
+ QVERIFY(footer);
- QCOMPARE(object->property("count").toInt(), 10);
- QCOMPARE(QQmlListReference(object.data(), "children").count(), 11);
+ QCOMPARE(footer->property("standardButtons").value<QPlatformDialogHelper::StandardButton>(),
+ QPlatformDialogHelper::Ok | QPlatformDialogHelper::Cancel);
}
-void tst_QmlCppCodegen::onAssignment()
+void tst_QmlCppCodegen::enumConversion()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/pressAndHoldButton.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QCOMPARE(object->property("pressed").toBool(), false);
- QCOMPARE(object->property("scale").toDouble(), 1.0);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- object->metaObject()->invokeMethod(object.data(), "press");
- QTRY_COMPARE(object->property("pressed").toBool(), true);
- QCOMPARE(object->property("scale").toDouble(), 0.9);
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("test").toInt(), 0x04);
+ QCOMPARE(o->property("test_1").toBool(), true);
+ QCOMPARE(o->objectName(), u"0m"_s);
+}
- object->metaObject()->invokeMethod(object.data(), "release");
- QCOMPARE(object->property("pressed").toBool(), false);
- QCOMPARE(object->property("scale").toDouble(), 1.0);
+void tst_QmlCppCodegen::enumFromBadSingleton()
+{
+ QQmlEngine e;
+ const QUrl url(u"qrc:/qt/qml/TestTypes/enumFromBadSingleton.qml"_s);
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+#if QT_DEPRECATED_SINCE(6,4)
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(
+ url.toString()
+ + u":5:5: TypeError: Cannot read property 'TestA' of undefined"_s));
+#else
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(
+ url.toString()
+ + u":5:5: ReferenceError: DummyObjekt is not defined"_s));
+#endif
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QVERIFY(o->objectName().isEmpty());
}
-namespace QmlCacheGeneratedCode {
-namespace _qt_qml_TestTypes_failures_qml {
-extern const QQmlPrivate::TypedFunction aotBuiltFunctions[];
+void tst_QmlCppCodegen::enumLookup()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumLookup.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QCOMPARE(o->property("ready").toBool(), true);
}
+
+void tst_QmlCppCodegen::enumMarkedAsFlag()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumMarkedAsFlag.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QCOMPARE(o->property("flagValue").toInt(), 3);
}
-void tst_QmlCppCodegen::failures()
+void tst_QmlCppCodegen::enumProblems()
{
- const auto &aotFailure
- = QmlCacheGeneratedCode::_qt_qml_TestTypes_failures_qml::aotBuiltFunctions[0];
- QVERIFY(aotFailure.argumentTypes.isEmpty());
- QVERIFY(!aotFailure.functionPtr);
- QCOMPARE(aotFailure.extraData, 0);
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumProblems.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> outer(c.create());
+ QVERIFY(!outer.isNull());
+ QObject *inner = outer->property("o").value<QObject *>();
+ QVERIFY(inner);
+
+ Foo *bar = inner->property("bar").value<Foo *>();
+ QVERIFY(bar);
+ QCOMPARE(bar->type(), Foo::Component);
+
+ Foo *fighter = inner->property("fighter").value<Foo *>();
+ QVERIFY(fighter);
+ QCOMPARE(fighter->type(), Foo::Fighter);
+
+ QCOMPARE(outer->property("a").toInt(), FooFactory::B);
+ QCOMPARE(outer->property("b").toInt(), FooFactory::C);
+ QCOMPARE(outer->property("c").toInt(), FooFactory::D);
+ QCOMPARE(outer->property("d").toInt(), FooFactory::E);
}
void tst_QmlCppCodegen::enumScope()
@@ -861,283 +1623,370 @@ void tst_QmlCppCodegen::enumScope()
QCOMPARE(object->property("flow").toInt(), 1);
}
-void tst_QmlCppCodegen::unusedAttached()
+void tst_QmlCppCodegen::enums()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unusedAttached.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Enums.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
+
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/Enums.qml:4:1: "
+ "QML Enums: Layout must be attached to Item elements");
QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ bool ok = false;
+ QCOMPARE(object->property("appState").toInt(&ok), 2);
+ QVERIFY(ok);
+ QCOMPARE(object->property("color").toString(), u"blue"_s);
+
+ QTRY_COMPARE(object->property("appState").toInt(&ok), 1);
+ QVERIFY(ok);
+ QCOMPARE(object->property("color").toString(), u"green"_s);
+
const auto func = qmlAttachedPropertiesFunction(
- object.data(), QMetaType::fromName("QQuickKeyNavigationAttached*").metaObject());
+ object.data(), QMetaType::fromName("QQuickLayout*").metaObject());
+
QObject *attached = qmlAttachedPropertiesObject(object.data(), func);
- const QVariant prop = attached->property("priority");
+
+ const QVariant prop = attached->property("alignment");
QVERIFY(prop.isValid());
- QCOMPARE(QByteArray(prop.metaType().name()), "QQuickKeyNavigationAttached::Priority");
- bool ok = false;
- QCOMPARE(prop.toInt(&ok), 0);
- QVERIFY(ok);
+ QCOMPARE(qvariant_cast<Qt::Alignment>(prop), Qt::AlignCenter);
+
}
-void tst_QmlCppCodegen::attachedBaseEnum()
+void tst_QmlCppCodegen::enforceSignature()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/attachedBaseEnum.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enforceSignature.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QObject *drag = qvariant_cast<QObject *>(object->property("drag"));
- QVERIFY(drag);
+ const QVariant a = object->property("a");
+ QCOMPARE(a.metaType(), QMetaType::fromType<QObject *>());
+ QCOMPARE(a.value<QObject *>(), nullptr);
- // Drag.YAxis is 2, but we cannot #include it here.
- bool ok = false;
- QCOMPARE(drag->property("axis").toInt(&ok), 2);
- QVERIFY(ok);
+ const QVariant b = object->property("b");
+ QCOMPARE(b.metaType(), QMetaType::fromType<QObject *>());
+ QCOMPARE(b.value<QObject *>(), nullptr);
}
-void tst_QmlCppCodegen::nullAccess()
+void tst_QmlCppCodegen::enumsInOtherObject()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullAccess.qml"_s));
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/enumsInOtherObject.qml:4:25: "
+ "QML Enums: Layout must be attached to Item elements");
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumsInOtherObject.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
-
- QTest::ignoreMessage(QtWarningMsg,
- "qrc:/qt/qml/TestTypes/nullAccess.qml:4:5: TypeError: "
- "Cannot read property 'width' of null");
- QTest::ignoreMessage(QtWarningMsg,
- "qrc:/qt/qml/TestTypes/nullAccess.qml:5:5: TypeError: "
- "Cannot read property 'height' of null");
- QTest::ignoreMessage(QtWarningMsg,
- "qrc:/qt/qml/TestTypes/nullAccess.qml:6: TypeError: Value is null and "
- "could not be converted to an object");
QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("color").toString(), u"blue"_s);
+ QTRY_COMPARE(object->property("color").toString(), u"green"_s);
+}
- QCOMPARE(object->property("width").toDouble(), 0.0);
- QCOMPARE(object->property("height").toDouble(), 0.0);
+void tst_QmlCppCodegen::equalityQObjects()
+{
+ QQmlEngine engine;
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityQObjects.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+ QScopedPointer<QObject> object(c1.create());
+ QVERIFY(!object.isNull() && !c1.isError());
+
+ QVERIFY(object->property("derivedIsNotNull").toBool());
+ QVERIFY(object->property("nullObjectIsNull").toBool());
+ QVERIFY(object->property("nonNullObjectIsNotNull").toBool());
+ QVERIFY(object->property("compareSameObjects").toBool());
+ QVERIFY(object->property("compareDifferentObjects").toBool());
+ QVERIFY(object->property("compareObjectWithNullObject").toBool());
+
+ QVERIFY(object->property("nonStrict_derivedIsNotNull").toBool());
+ QVERIFY(object->property("nonStrict_nullObjectIsNull").toBool());
+ QVERIFY(object->property("nonStrict_nonNullObjectIsNotNull").toBool());
+ QVERIFY(object->property("nonStrict_compareSameObjects").toBool());
+ QVERIFY(object->property("nonStrict_compareDifferentObjects").toBool());
+ QVERIFY(object->property("nonStrict_compareObjectWithNullObject").toBool());
}
-void tst_QmlCppCodegen::interceptor()
+void tst_QmlCppCodegen::equalityQUrl()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/interceptor.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("x").toInt(), 100);
- QCOMPARE(object->property("y").toInt(), 100);
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityQUrl.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- QVERIFY(object->property("width").toInt() != 200);
- QVERIFY(object->property("height").toInt() != 200);
- QVERIFY(object->property("qProperty1").toInt() != 300);
- QVERIFY(object->property("qProperty2").toInt() != 300);
- QTRY_COMPARE(object->property("width").toInt(), 200);
- QTRY_COMPARE(object->property("height").toInt(), 200);
- QTRY_COMPARE(object->property("qProperty1").toInt(), 300);
- QTRY_COMPARE(object->property("qProperty2").toInt(), 300);
+ QScopedPointer<QObject> object(c1.create());
+ QVERIFY(!object.isNull() && !c1.isError());
+ QVERIFY(object->property("emptyUrlStrict").toBool());
+ QVERIFY(object->property("emptyUrlWeak").toBool());
+ QVERIFY(object->property("sourceUrlStrict").toBool());
+ QVERIFY(object->property("sourceUrlWeak").toBool());
+ QVERIFY(object->property("sourceIsNotEmptyStrict").toBool());
+ QVERIFY(object->property("sourceIsNotEmptyWeak").toBool());
}
-void tst_QmlCppCodegen::nonNotifyable()
+void tst_QmlCppCodegen::equalityTestsWithNullOrUndefined()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nonNotifyable.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityTestsWithNullOrUndefined.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o);
+}
- QCOMPARE(qvariant_cast<QDateTime>(object->property("dayz")),
- QDateTime(QDate(2121, 1, 12), QTime()));
- QCOMPARE(qvariant_cast<QDateTime>(object->property("oParty")),
- QDateTime(QDate(2111, 12, 11), QTime()));
+void tst_QmlCppCodegen::equalityVarAndNonStorable()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityVarAndNonStorable.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+
+ QScopedPointer<QObject> object(c1.create());
+ QVERIFY(!object.isNull() && !c1.isError());
+ QVERIFY(!object->property("aIsNull").toBool());
+ QVERIFY(object->property("aIsNotNull").toBool());
+ QVERIFY(object->property("aIsNotUndefined").toBool());
+ QVERIFY(object->property("objectIsNotNull").toBool());
+ QVERIFY(!object->property("typedArrayIsNull").toBool());
+ QVERIFY(object->property("isUndefined").toBool());
+ QVERIFY(!object->property("derivedIsNull").toBool());
+
+ QVERIFY(object->property("primitiveIsNull").toBool());
+ QVERIFY(object->property("primitiveIsDefined").toBool());
+ QVERIFY(object->property("primitiveIsUndefined").toBool());
+
+ QVERIFY(object->property("jsValueIsNull").toBool());
+ QVERIFY(object->property("jsValueIsDefined").toBool());
+ QVERIFY(object->property("jsValueIsUndefined").toBool());
+
+ QVERIFY(object->property("nullVarIsUndefined").toBool());
+ QVERIFY(object->property("nullIsUndefined").toBool());
+ QVERIFY(object->property("nullVarIsNull").toBool());
+ QVERIFY(object->property("nullIsNotUndefined").toBool());
}
-void tst_QmlCppCodegen::importsFromImportPath()
+void tst_QmlCppCodegen::equalityVarAndStorable()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/importsFromImportPath.qml"_s));
+ QQmlComponent planner(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Planner.qml"_s));
+ QVERIFY2(!planner.isError(), qPrintable(planner.errorString()));
+ QScopedPointer<QObject> p(planner.create());
+ QVERIFY(!p.isNull());
- // We might propagate the import path, eventually, but for now instantiating is not important.
- // If the compiler accepts the file, it's probably fine.
- QVERIFY(component.isError());
- QCOMPARE(component.errorString(),
- u"qrc:/qt/qml/TestTypes/importsFromImportPath.qml:1 module \"Module\" is not installed\n"_s);
+ QQmlComponent variable(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Variable.qml"_s));
+ QVERIFY2(!variable.isError(), qPrintable(variable.errorString()));
+ QScopedPointer<QObject> v(variable.create());
+ QVERIFY(!v.isNull());
+
+ QVERIFY(p->objectName().isEmpty());
+ QMetaObject::invokeMethod(p.data(), "typeErasedRemoveOne", v.data());
+ QCOMPARE(p->objectName(), u"n");
+
+ v->setProperty("value", 1);
+ QMetaObject::invokeMethod(p.data(), "typeErasedRemoveOne", v.data());
+ QCOMPARE(p->objectName(), u"nd");
+
+ QQmlComponent constraint(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BaseConstraint.qml"_s));
+ QVERIFY2(!constraint.isError(), qPrintable(constraint.errorString()));
+ QScopedPointer<QObject> c(constraint.create());
+ QVERIFY(!c.isNull());
+
+ c->setProperty("output", QVariant::fromValue(v.data()));
+ QCOMPARE(v->property("mark").toInt(), 0);
+ QMetaObject::invokeMethod(p.data(), "typeErasedRun", c.data());
+ QCOMPARE(v->property("mark").toInt(), 5);
+
+ QTest::ignoreMessage(QtDebugMsg, "success");
+ QMetaObject::invokeMethod(p.data(), "verify", 10);
+
+ QTest::ignoreMessage(QtCriticalMsg, "failed 10 11");
+ QMetaObject::invokeMethod(p.data(), "verify", 11);
}
-void tst_QmlCppCodegen::aliasLookup()
+void tst_QmlCppCodegen::equalsUndefined()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/aliasLookup.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalsUndefined.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
- const QVariant t = object->property("t");
- QCOMPARE(t.metaType(), QMetaType::fromType<QString>());
- QCOMPARE(t.toString(), u"12"_s);
+ QCOMPARE(object->property("a").toInt(), 50);
+ QCOMPARE(object->property("b").toInt(), 5000);
}
-void tst_QmlCppCodegen::outOfBoundsArray()
+void tst_QmlCppCodegen::evadingAmbiguity()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/outOfBounds.qml"_s));
- QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QTest::ignoreMessage(QtDebugMsg, "oob undefined");
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QVERIFY(object->metaObject()->indexOfProperty("oob") > 0);
- QVERIFY(!object->property("oob").isValid());
- const QVariant oob2 = object->property("oob2");
- QCOMPARE(oob2.metaType(), QMetaType::fromType<QObject *>());
- QCOMPARE(oob2.value<QObject *>(), nullptr);
+ // We need to add an import path here because we cannot namespace the implicit import.
+ // The implicit import is what we use for all the other tests, even if we explicitly
+ // import TestTypes. That is because the TestTypes module is in a subdirectory "data".
+ engine.addImportPath(u":/"_s);
+
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguous1/Ambiguous.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+ QScopedPointer<QObject> o1(c1.create());
+ QCOMPARE(o1->objectName(), QStringLiteral("Ambiguous"));
+ QCOMPARE(o1->property("i").toString(), QStringLiteral("Ambiguous1"));
+
+ QQmlComponent c2(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguous2/Ambiguous.qml"_s));
+ QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
+ QScopedPointer<QObject> o2(c2.create());
+ QCOMPARE(o2->objectName(), QStringLiteral("Ambiguous"));
+ QCOMPARE(o2->property("i").toString(), QStringLiteral("Ambiguous2"));
}
-void tst_QmlCppCodegen::compositeSingleton()
+void tst_QmlCppCodegen::exceptionFromInner()
{
QQmlEngine engine;
- engine.addImportPath(u":/qt/qml/TestTypes/imports/"_s);
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/compositesingleton.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/exceptionFromInner.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QScopedPointer<QObject> o(component.create());
- QCOMPARE(o->property("x").toDouble(), 4.5);
- QCOMPARE(o->property("y").toDouble(), 10.0);
- QCOMPARE(o->property("smooth").toBool(), true);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/exceptionFromInner.qml:7: TypeError: "
+ "Cannot read property 'objectName' of null");
+ QMetaObject::invokeMethod(object.data(), "disbelieveFail");
}
-void tst_QmlCppCodegen::lotsOfRegisters()
+void tst_QmlCppCodegen::excessiveParameters()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/page.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/excessiveParameters.qml"_s));
QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
+ QSignalSpy spy(object.data(), SIGNAL(foo()));
+ QTRY_VERIFY(spy.size() > 0);
+}
- const auto compare = [&]() {
- const qreal implicitBackgroundWidth = object->property("implicitBackgroundWidth").toDouble();
- const qreal leftInset = object->property("leftInset").toDouble();
- const qreal rightInset = object->property("rightInset").toDouble();
- const qreal contentWidth = object->property("contentWidth").toDouble();
- const qreal leftPadding = object->property("leftPadding").toDouble();
- const qreal rightPadding = object->property("rightPadding").toDouble();
- const qreal implicitFooterWidth = object->property("implicitFooterWidth").toDouble();
- const qreal implicitHeaderWidth = object->property("implicitHeaderWidth").toDouble();
+void tst_QmlCppCodegen::extendedTypes()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/extendedTypes.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
- const qreal implicitWidth = object->property("implicitWidth").toDouble();
- QCOMPARE(implicitWidth, qMax(qMax(implicitBackgroundWidth + leftInset + rightInset,
- contentWidth + leftPadding + rightPadding),
- qMax(implicitHeaderWidth, implicitFooterWidth)));
- };
+ QTest::ignoreMessage(QtDebugMsg, "6 QSizeF(10, 20) 30");
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- compare();
+ QCOMPARE(object->property("a").toInt(), 6);
+ QCOMPARE(qvariant_cast<QSizeF>(object->property("b")), QSizeF(10, 20));
+ QCOMPARE(object->property("c").toInt(), 30);
+ QCOMPARE(object->property("d").toString(), u"QSizeF(10, 20)"_s);
- const QList<const char *> props = {
- "leftInset", "rightInset", "contentWidth", "leftPadding", "rightPadding"
- };
+ QCOMPARE(object->property("e").toInt(), 2);
+}
- for (int i = 0; i < 100; ++i) {
- QVERIFY(object->setProperty(props[i % props.size()], (i * 17) % 512));
- compare();
- }
+void tst_QmlCppCodegen::failures()
+{
+ const auto &aotFailure
+ = QmlCacheGeneratedCode::_qt_qml_TestTypes_failures_qml::aotBuiltFunctions[0];
+ QVERIFY(!aotFailure.functionPtr);
+ QCOMPARE(aotFailure.functionIndex, 0);
}
-void tst_QmlCppCodegen::inPlaceDecrement()
+void tst_QmlCppCodegen::fallbackLookups()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dialog.qml"_s));
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QObject *header = qvariant_cast<QObject *>(object->property("header"));
- QVERIFY(header);
- QObject *background = qvariant_cast<QObject *>(header->property("background"));
- QObject *parent = qvariant_cast<QObject *>(background->property("parent"));
+ const QUrl document(u"qrc:/qt/qml/TestTypes/fallbacklookups.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(background->property("width").toInt(), parent->property("width").toInt() + 1);
- QCOMPARE(background->property("height").toInt(), parent->property("height").toInt() - 1);
+ QCOMPARE(o->objectName(), QString());
+ int result = 0;
- QVERIFY(object->setProperty("width", QVariant::fromValue(17)));
- QVERIFY(parent->property("width").toInt() > 0);
- QVERIFY(object->setProperty("height", QVariant::fromValue(53)));
- QVERIFY(parent->property("height").toInt() > 0);
+ QMetaObject::invokeMethod(o.data(), "withContext", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 16);
+ QCOMPARE(o->objectName(), QStringLiteral("aa93"));
- QCOMPARE(background->property("width").toInt(), parent->property("width").toInt() + 1);
- QCOMPARE(background->property("height").toInt(), parent->property("height").toInt() - 1);
+ QMetaObject::invokeMethod(o.data(), "withId", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 17);
+ QCOMPARE(o->objectName(), QStringLiteral("bb94"));
- QCOMPARE(object->property("a").toInt(), 1024);
+ QObject *singleton = nullptr;
+ QMetaObject::invokeMethod(o.data(), "getSingleton", Q_RETURN_ARG(QObject*, singleton));
+ QVERIFY(singleton);
+
+ QMetaObject::invokeMethod(o.data(), "withSingleton", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 18);
+ QCOMPARE(singleton->objectName(), QStringLiteral("cc95"));
+
+ QMetaObject::invokeMethod(o.data(), "withProperty", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 19);
+ QCOMPARE(singleton->objectName(), QStringLiteral("dd96"));
}
-void tst_QmlCppCodegen::shifts()
+void tst_QmlCppCodegen::fileImportsContainCxxTypes()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/shifts.qml"_s));
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
-
- QCOMPARE(object->property("a").toInt(), 9728);
- QCOMPARE(object->property("b").toInt(), 4864);
- QCOMPARE(object->property("c").toInt(), 19448);
- QCOMPARE(object->property("d").toInt(), 9731);
- QCOMPARE(object->property("e").toInt(), 0);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/usingCxxTypesFromFileImports.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"horst guenther"_s);
}
-void tst_QmlCppCodegen::valueTypeProperty()
+void tst_QmlCppCodegen::flagEnum()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/valueTypeProperty.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/flagEnum.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QFont font = qvariant_cast<QFont>(object->property("font"));
- QCOMPARE(object->property("foo").toString(), font.family());
- font.setFamily(u"Bar"_s);
- object->setProperty("font", QVariant::fromValue(font));
- QCOMPARE(object->property("foo").toString(), u"Bar"_s);
+ QQmlCommunicationPermission *p = qobject_cast<QQmlCommunicationPermission *>(o.data());
+ QCOMPARE(p->communicationModes(), CommunicationPermission::Access);
}
-void tst_QmlCppCodegen::propertyOfParent()
+void tst_QmlCppCodegen::flushBeforeCapture()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/RootWithoutId.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
-
- QObject *child = qmlContext(object.data())->objectForName(u"item"_s);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/noBindingLoop.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- bool expected = false;
+ QCOMPARE(o->property("deviation").toDouble(), 9.0 / 3.3333);
+ QCOMPARE(o->property("samples").toInt(), 16);
+ QCOMPARE(o->property("radius").toDouble(), 8.0);
+}
- for (int i = 0; i < 3; ++i) {
- const QVariant foo = object->property("foo");
- QCOMPARE(foo.metaType(), QMetaType::fromType<bool>());
- QCOMPARE(foo.toBool(), expected);
+void tst_QmlCppCodegen::fromBoolValue()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/fromBoolValue.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QCOMPARE(o->property("a").toBool(), true);
+ o->setProperty("x", 100);
+ QCOMPARE(o->property("a").toBool(), false);
- const QVariant bar = object->property("bar");
- QCOMPARE(bar.metaType(), QMetaType::fromType<bool>());
- QCOMPARE(bar.toBool(), expected);
+ QCOMPARE(o->property("width").toInt(), 100);
+ QCOMPARE(o->property("b").toBool(), false);
- const QVariant visible = child->property("visible");
- QCOMPARE(visible.metaType(), QMetaType::fromType<bool>());
- QCOMPARE(visible.toBool(), expected);
+ QScopedPointer<QObject> parent(c.create());
+ o->setProperty("parent", QVariant::fromValue(parent.data()));
+ QCOMPARE(o->property("width").toInt(), 100);
+ QCOMPARE(o->property("b").toBool(), false);
- expected = !expected;
- object->setProperty("foo", expected);
- }
+ o->setProperty("state", QVariant::fromValue(u"foo"_s));
+ QCOMPARE(o->property("width").toInt(), 0);
+ QCOMPARE(o->property("b").toBool(), false);
}
-void tst_QmlCppCodegen::accessModelMethodFromOutSide()
+void tst_QmlCppCodegen::funcWithParams()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/AccessModelMethodsFromOutside.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
-
- QTest::ignoreMessage(QtDebugMsg, "3");
- QTest::ignoreMessage(QtDebugMsg, "Apple");
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/funcWithParams.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
-
- QCOMPARE(object->property("cost1").toDouble(), 3);
- QCOMPARE(object->property("name1").toString(), u"Orange"_s);
- QCOMPARE(object->property("cost2").toDouble(), 1.95);
- QCOMPARE(object->property("name2").toString(), u"Banana"_s);
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("bar").toInt(), 30);
}
// QML-generated types have no C++ names, but we want to call a method that
@@ -1150,42 +1999,55 @@ void tst_QmlCppCodegen::accessModelMethodFromOutSide()
// the metatype of the argument we pass does not match the metatype of the
// argument the method expects. In order to work around it, we specialize
// qMetaTypeInterfaceForType() and produce a "correct" metatype this way.
-class Dummy_QMLTYPE_0;
+class Dummy2_QMLTYPE_0;
// We set this to the actual value retrieved from an actual instance of the QML
// type before retrieving the metatype interface for the first time.
static const QtPrivate::QMetaTypeInterface *dummyMetaTypeInterface = nullptr;
template<>
-const QtPrivate::QMetaTypeInterface *QtPrivate::qMetaTypeInterfaceForType<Dummy_QMLTYPE_0 *>() {
+const QtPrivate::QMetaTypeInterface *QtPrivate::qMetaTypeInterfaceForType<Dummy2_QMLTYPE_0 *>() {
return dummyMetaTypeInterface;
}
void tst_QmlCppCodegen::functionArguments()
{
+ qmlClearTypeRegistrations();
+
QQmlEngine engine;
+ QQmlComponent preheat(&engine);
+ preheat.setData(R"(
+ import QtQml
+ import TestTypes
+ QtObject {
+ objectName: Style.objectName
+ }
+ )", QUrl(u"qrc:/qt/qml/TestTypes/preheat.qml"_s));
+ QVERIFY2(preheat.isReady(), qPrintable(preheat.errorString()));
+ QScopedPointer<QObject> hot(preheat.create());
+ QVERIFY(!hot.isNull());
- // Ensure that Dummy gets counter value 0. Don't do that at home
+ // Ensure that Dummy gets counter value 1. Don't do that at home
QScopedValueRollback<QAtomicInt> rb(QQmlPropertyCacheCreatorBase::classIndexCounter, 0);
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Dummy.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Dummy2.qml"_s));
QVERIFY2(component.isReady(), component.errorString().toUtf8());
QScopedPointer<QObject> object(component.create());
const QMetaObject *metaObject = object->metaObject();
dummyMetaTypeInterface = metaObject->metaType().iface();
const QByteArray className = QByteArray(metaObject->className());
- QCOMPARE(className, "Dummy_QMLTYPE_0");
+ QCOMPARE(className, "Dummy2_QMLTYPE_0");
int result;
int a = 1;
bool b = false;
- Dummy_QMLTYPE_0 *c = nullptr;
+ Dummy2_QMLTYPE_0 *c = nullptr;
double d = -1.2;
int e = 3;
metaObject->invokeMethod(
object.data(), "someFunction", Q_RETURN_ARG(int, result),
- Q_ARG(int, a), Q_ARG(bool, b), Q_ARG(Dummy_QMLTYPE_0 *, c),
+ Q_ARG(int, a), Q_ARG(bool, b), Q_ARG(Dummy2_QMLTYPE_0 *, c),
Q_ARG(double, d), Q_ARG(int, e));
QCOMPARE(result, 42);
@@ -1198,473 +2060,780 @@ void tst_QmlCppCodegen::functionArguments()
QCOMPARE(concatenated, u"foobar"_s);
}
-void tst_QmlCppCodegen::bindingExpression()
+void tst_QmlCppCodegen::functionCallOnNamespaced()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BindingExpression.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
-
- QObject *child = qmlContext(object.data())->objectForName(u"child"_s);
-
- double width = 200;
- double y = 10;
- for (int i = 0; i < 10; ++i) {
- QCOMPARE(object->property("width").toDouble(), width);
- QCOMPARE(object->property("height").toDouble(), width);
- QCOMPARE(object->property("y").toDouble(), y);
-
- const double childY = y + (width - 100) / 2;
- QCOMPARE(child->property("y").toDouble(), childY);
- QCOMPARE(object->property("mass"), childY > 100 ? u"heavy"_s : u"light"_s);
- QCOMPARE(object->property("test_division").toDouble(), width / 1000 + 50);
- QCOMPARE(object->property("test_ternary").toDouble(), 2.2);
-
- const int test_switch = object->property("test_switch").toInt();
- switch (int(width) % 3) {
- case 0:
- QCOMPARE(test_switch, 130);
- break;
- case 1:
- QCOMPARE(test_switch, 380);
- break;
- case 2:
- QCOMPARE(test_switch, 630);
- break;
- }
+ {
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/themergood.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("i").toInt(), 12);
+ }
- width = 200 * i;
- y = 10 + i;
- object->setProperty("width", width);
- object->setProperty("y", y);
+ {
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/themerbad.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("r"), QVariant::fromValue(QRectF(5.0, 10.0, 1.0, 1.0)));
}
}
-void tst_QmlCppCodegen::voidFunction()
+void tst_QmlCppCodegen::functionLookup()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/voidfunction.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QVERIFY(object->objectName().isEmpty());
- object->metaObject()->invokeMethod(object.data(), "doesNotReturnValue");
- QCOMPARE(object->objectName(), u"barbar"_s);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/functionLookup.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ const QVariant foo = o->property("bar");
+ QCOMPARE(foo.metaType(), QMetaType::fromType<QJSValue>());
+ const QJSManagedValue method(engine.toScriptValue(foo), &engine);
+ QVERIFY(method.isFunction());
+ const QJSValue result = method.call();
+ QVERIFY(result.isString());
+ QCOMPARE(result.toString(), QStringLiteral("a99"));
}
-void tst_QmlCppCodegen::overriddenProperty()
+void tst_QmlCppCodegen::functionReturningVoid()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/childobject.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->objectName(), u"kraut"_s);
- QCOMPARE(object->property("doneThing").toInt(), 5);
- QCOMPARE(object->property("usingFinal").toInt(), 5);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/functionReturningVoid.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- auto checkAssignment = [&]() {
- const QString newName = u"worscht"_s;
- QMetaObject::invokeMethod(object.data(), "setChildObjectName", Q_ARG(QString, newName));
- QCOMPARE(object->objectName(), newName);
- };
- checkAssignment();
+ // It should be able to call the methods and wrap the void values into invalid QVariants,
+ // without crashing.
+ QVERIFY(o->metaObject()->indexOfProperty("aa") >= 0);
+ QVERIFY(o->metaObject()->indexOfProperty("bb") >= 0);
+ QVERIFY(!o->property("aa").isValid());
+ QVERIFY(!o->property("bb").isValid());
+}
- ObjectWithMethod *benign = new ObjectWithMethod(object.data());
- benign->theThing = 10;
- benign->setObjectName(u"cabbage"_s);
- object->setProperty("child", QVariant::fromValue(benign));
- QCOMPARE(object->objectName(), u"cabbage"_s);
- checkAssignment();
- QCOMPARE(object->property("doneThing").toInt(), 10);
- QCOMPARE(object->property("usingFinal").toInt(), 10);
+void tst_QmlCppCodegen::functionTakingVar()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/functionTakingVar.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- OverriddenObjectName *evil = new OverriddenObjectName(object.data());
- QTest::ignoreMessage(QtWarningMsg,
- "Final member fff is overridden in class OverriddenObjectName. "
- "The override won't be used.");
- object->setProperty("child", QVariant::fromValue(evil));
+ QVERIFY(!o->property("c").isValid());
- QCOMPARE(object->objectName(), u"borschtsch"_s);
+ int value = 11;
+ QQmlEnginePrivate *e = QQmlEnginePrivate::get(&engine);
+ void *args[] = { nullptr, reinterpret_cast<void *>(std::addressof(value)) };
+ QMetaType types[] = { QMetaType::fromType<void>(), QMetaType::fromType<std::decay_t<int>>() };
+ e->executeRuntimeFunction(document, 0, o.data(), 1, args, types);
- checkAssignment();
- QCOMPARE(object->property("doneThing").toInt(), 7);
- QCOMPARE(object->property("usingFinal").toInt(), 5);
+ QCOMPARE(o->property("c"), QVariant::fromValue<int>(11));
}
-void tst_QmlCppCodegen::listLength()
+void tst_QmlCppCodegen::getLookupOfScript()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listlength.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("l").toInt(), 2);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/NotificationItem.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"heading"_s);
}
-void tst_QmlCppCodegen::parentProperty()
+void tst_QmlCppCodegen::getOptionalLookup_data()
{
- QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/parentProp.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> object(component.create());
- QVERIFY(!object.isNull());
- QCOMPARE(object->property("c").toInt(), 11);
- QCOMPARE(object->property("i").toInt(), 22);
- object->setProperty("a", QVariant::fromValue(22));
- QCOMPARE(object->property("c").toInt(), 28);
- object->setProperty("implicitWidth", QVariant::fromValue(14));
- QCOMPARE(object->property("i").toInt(), 26);
+ QTest::addColumn<QString>("propertyName");
+ QTest::addColumn<QVariant>("expected");
- QObject *child = qmlContext(object.data())->objectForName(u"child"_s);
- QObject *sibling = qmlContext(object.data())->objectForName(u"sibling"_s);
- QObject *evil = qmlContext(object.data())->objectForName(u"evil"_s);
+ // Objects
+ QTest::addRow("int on object") << u"to1"_s << QVariant(5);
+ QTest::addRow("string on object") << u"to2"_s << QVariant("6");
+ QTest::addRow("object on object") << u"to3"_s << QVariant::fromValue<QObject *>(nullptr);
+ QTest::addRow("int on null") << u"to4"_s << QVariant(); // undefined
+ QTest::addRow("any on undefined as object") << u"to5"_s << QVariant(); // undefined
+ QTest::addRow("int on string on object") << u"to6"_s << QVariant(1);
- child->setProperty("parent", QVariant::fromValue(sibling));
+ // Value Types
+ QTest::addRow("int on rect") << u"tv1"_s << QVariant(50);
+ QTest::addRow("int on point") << u"tv2"_s << QVariant(-10);
+ QTest::addRow("int on undefined as point") << u"tv4"_s << QVariant(); // undefined
- QCOMPARE(child->property("b").toInt(), 0);
- QCOMPARE(child->property("i").toInt(), 28);
- QCOMPARE(object->property("i").toInt(), 56);
+ // Enums
+ QTest::addRow("enum on object") << u"te1"_s << QVariant(1);
+ QTest::addRow("enum on type") << u"te2"_s << QVariant(1);
+ QTest::addRow("enums comparison 1") << u"te3"_s << QVariant(false);
+ QTest::addRow("enums comparison 2") << u"te4"_s << QVariant(true);
- child->setProperty("parent", QVariant::fromValue(evil));
+ // Complex chains
+ QTest::addRow("mixed 1") << u"tc1"_s << QVariant(-10);
+ QTest::addRow("mixed 2") << u"tc2"_s << QVariant(0);
+ QTest::addRow("early out 1") << u"tc4"_s << QVariant(); // undefined
+ QTest::addRow("early out 2") << u"tc5"_s << QVariant(); // undefined
+}
- QCOMPARE(child->property("b").toInt(), 5994);
- QCOMPARE(object->property("c").toInt(), 5996);
+void tst_QmlCppCodegen::getOptionalLookup()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/getOptionalLookup.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(child->property("i").toInt(), 443);
- QCOMPARE(object->property("i").toInt(), 886);
+ QFETCH(QString, propertyName);
+ QFETCH(QVariant, expected);
- {
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/specificParent.qml"_s));
+ QVariant actual = o->property(propertyName.toLocal8Bit());
+ QCOMPARE(actual, expected);
+}
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+void tst_QmlCppCodegen::getOptionalLookupOnQJSValueNonStrict()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/GetOptionalLookupOnQJSValueNonStrict.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(rootObject->property("a").toReal(), 77.0);
- }
+ QVERIFY(o->property("b").toBool());
}
-void tst_QmlCppCodegen::registerElimination()
+void tst_QmlCppCodegen::getOptionalLookupShadowed()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/registerelimination.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ const QUrl document(u"qrc:/qt/qml/TestTypes/GetOptionalLookupShadowed.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QCOMPARE(o->property("res").toString(), "a");
+}
+
+void tst_QmlCppCodegen::globals()
+{
+ QQmlEngine engine;
+ int exitCode = -1;
+ QObject::connect(&engine, &QQmlEngine::exit, [&](int code) { exitCode = code; });
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/globals.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+
+ const QByteArray message = QByteArray("Start 2 ") + arg1();
+ QTest::ignoreMessage(QtDebugMsg, message.constData());
+
QScopedPointer<QObject> object(component.create());
QVERIFY(!object.isNull());
+ QTRY_COMPARE(exitCode, 0);
- // Increment of 23 hits both 0 and 460
- for (int input = -23; input < 700; input += 23) {
- object->setProperty("input", input);
- if (input <= 0 || input >= 460)
- QCOMPARE(object->property("output").toInt(), 459);
- else
- QCOMPARE(object->property("output").toInt(), input);
- }
+ QObject *application = qvariant_cast<QObject *>(object->property("application"));
+ QVERIFY(application);
+ QCOMPARE(QString::fromUtf8(application->metaObject()->className()),
+ u"QQuickApplication"_s);
+
+ QTest::ignoreMessage(QtDebugMsg, "End");
+ QMetaObject::invokeMethod(application, "aboutToQuit");
+
+ const QVariant somewhere = object->property("somewhere");
+ QCOMPARE(somewhere.userType(), QMetaType::QUrl);
+ QCOMPARE(qvariant_cast<QUrl>(somewhere).toString(), u"qrc:/somewhere/else.qml"_s);
+
+ const QVariant somewhereString = object->property("somewhereString");
+ QCOMPARE(somewhereString.userType(), QMetaType::QString);
+ QCOMPARE(somewhereString.toString(), u"qrc:/somewhere/else.qml"_s);
+
+ const QVariant plain = object->property("plain");
+ QCOMPARE(plain.userType(), QMetaType::QUrl);
+ QCOMPARE(qvariant_cast<QUrl>(plain).toString(), u"/not/here.qml"_s);
}
-void tst_QmlCppCodegen::asCast()
+void tst_QmlCppCodegen::idAccess()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/asCast.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QScopedPointer<QObject> root(component.create());
- QVERIFY(!root.isNull());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/idAccess.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QQmlContext *context = qmlContext(root.data());
- const QObject *object = context->objectForName(u"object"_s);
- const QObject *item = context->objectForName(u"item"_s);
- const QObject *rectangle = context->objectForName(u"rectangle"_s);
- const QObject *dummy = context->objectForName(u"dummy"_s);
+ QVERIFY(object->property("y").toInt() != 48);
+ QCOMPARE(object->property("y").toInt(), 12);
+ object->setProperty("z", 13);
+ QCOMPARE(object->property("y").toInt(), 13);
+ object->setProperty("x", QVariant::fromValue(333));
+ QCOMPARE(object->property("y").toInt(), 48);
- QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsObject")), object);
- QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsItem")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsRectangle")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(root->property("objectAsDummy")), nullptr);
+ // The binding was broken by setting the property
+ object->setProperty("z", 14);
+ QCOMPARE(object->property("y").toInt(), 48);
- QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsObject")), item);
- QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsItem")), item);
- QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsRectangle")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(root->property("itemAsDummy")), nullptr);
+ QObject *ttt = qmlContext(object.data())->objectForName(u"ttt"_s);
+ QFont f = qvariant_cast<QFont>(ttt->property("font"));
+ QCOMPARE(f.pointSize(), 22);
- QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsObject")), rectangle);
- QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsItem")), rectangle);
- QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsRectangle")), rectangle);
- QCOMPARE(qvariant_cast<QObject *>(root->property("rectangleAsDummy")), nullptr);
+ QObject::connect(object.data(), &QObject::objectNameChanged, ttt, [&](){
+ ttt->setParent(nullptr);
+ QJSEngine::setObjectOwnership(ttt, QJSEngine::CppOwnership);
+ object.reset(ttt);
+ });
- QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsObject")), dummy);
- QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsItem")), dummy);
- QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsRectangle")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(root->property("dummyAsDummy")), dummy);
+ QVERIFY(object->objectName().isEmpty());
+ QVERIFY(ttt->objectName().isEmpty());
+ ttt->setProperty("text", u"kill"_s);
+ QCOMPARE(object.data(), ttt);
+ QCOMPARE(ttt->objectName(), u"context"_s);
}
-void tst_QmlCppCodegen::noQQmlData()
+void tst_QmlCppCodegen::ignoredFunctionReturn()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/noQQmlData.qml"_s));
- QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ignoredFunctionReturn.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+}
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/noQQmlData.qml:7: TypeError: "
- "Cannot read property 'name' of null");
- QScopedPointer<QObject> root(component.create());
- QVERIFY(!root.isNull());
+void tst_QmlCppCodegen::importsFromImportPath()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/importsFromImportPath.qml"_s));
- BirthdayParty *party = qobject_cast<BirthdayParty *>(root.data());
- QVERIFY(party != nullptr);
+ // We might propagate the import path, eventually, but for now instantiating is not important.
+ // If the compiler accepts the file, it's probably fine.
+ QVERIFY(component.isError());
+ QCOMPARE(component.errorString(),
+ u"qrc:/qt/qml/TestTypes/importsFromImportPath.qml:1 module \"Module\" is not installed\n"_s);
+}
- QCOMPARE(party->host(), nullptr);
- QCOMPARE(party->property("n").toString(), QString());
+void tst_QmlCppCodegen::inPlaceDecrement()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dialog.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QObject *header = qvariant_cast<QObject *>(object->property("header"));
+ QVERIFY(header);
+ QObject *background = qvariant_cast<QObject *>(header->property("background"));
+ QObject *parent = qvariant_cast<QObject *>(background->property("parent"));
- Person *host1 = new Person(party);
- party->setHost(host1);
- QCOMPARE(party->property("n").toString(), u"Bart in da house!"_s);
- host1->setName(u"Marge"_s);
- QCOMPARE(party->property("n").toString(), u"Marge in da house!"_s);
+ QCOMPARE(background->property("width").toInt(), parent->property("width").toInt() + 1);
+ QCOMPARE(background->property("height").toInt(), parent->property("height").toInt() - 1);
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/noQQmlData.qml:7: TypeError: "
- "Cannot read property 'name' of null");
+ QVERIFY(object->setProperty("width", QVariant::fromValue(17)));
+ QVERIFY(parent->property("width").toInt() > 0);
+ QVERIFY(object->setProperty("height", QVariant::fromValue(53)));
+ QVERIFY(parent->property("height").toInt() > 0);
- // Doesn't crash
- party->setHost(nullptr);
+ QCOMPARE(background->property("width").toInt(), parent->property("width").toInt() + 1);
+ QCOMPARE(background->property("height").toInt(), parent->property("height").toInt() - 1);
- // Lookups are initialized now, and we introduce an object without QQmlData
- Person *host2 = new Person(party);
- party->setHost(host2);
- QCOMPARE(party->property("n").toString(), u"Bart in da house!"_s);
- host2->setName(u"Homer"_s);
- QCOMPARE(party->property("n").toString(), u"Homer in da house!"_s);
+ QCOMPARE(object->property("a").toInt(), 1024);
+}
- QMetaObject::invokeMethod(party, "burn");
- engine.collectGarbage();
+void tst_QmlCppCodegen::inaccessibleProperty()
+{
+ QQmlEngine engine;
- // Does not crash
- party->setProperty("inDaHouse", u" burns!"_s);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/versionmismatch.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- // Mr Burns may or may not burn, depending on whether we use lookups.
- // If using lookups, the binding is aborted when we find the isQueuedForDeletion flag.
- // If reading the property directly, we don't have to care about it.
- QVERIFY(party->property("n").toString().startsWith(u"Mr Burns"_s));
+ QCOMPARE(o->property("c").toInt(), 5);
}
-void tst_QmlCppCodegen::scopeObjectDestruction()
+void tst_QmlCppCodegen::indirectlyShadowable()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/fileDialog.qml"_s));
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+ const QString url = u"qrc:/qt/qml/TestTypes/indirectlyShadowable.qml"_s;
+ QQmlComponent c(&engine, QUrl(url));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QObject *dialog = rootObject->property("dialog").value<QObject *>();
- QVERIFY(dialog);
+ const auto verifyShadowable = [&](const QString &objectName) {
+ QObject *outer = o->property("outer").value<QObject *>();
+ QVERIFY(outer);
+ QObject *inner = outer->property("inner").value<QObject *>();
+ QVERIFY(inner);
+ QObject *shadowable = inner->property("shadowable").value<QObject *>();
+ QVERIFY(shadowable);
+ QCOMPARE(shadowable->objectName(), objectName);
+ };
- // We cannot check the warning messages. The AOT compiled code complains about reading the
- // "parent" property of an object scheduled for deletion. The runtime silently returns undefined
- // at that point and then complains about not being able to read a property on undefined.
+ const auto verifyNotShadowable = [&](const QString &objectName) {
+ QObject *notShadowable = o->property("notShadowable").value<QObject *>();
+ QCOMPARE(notShadowable->objectName(), objectName);
+ };
- // Doesn't crash, even though it triggers bindings on scope objects scheduled for deletion.
- QMetaObject::invokeMethod(dialog, "open");
-}
+ const auto verifyEvil = [&]() {
+ QObject *outer = o->property("outer").value<QObject *>();
+ QVERIFY(outer);
+ QCOMPARE(outer->property("inner").toString(), u"evil"_s);
+ };
-static void checkColorProperties(QQmlComponent *component)
-{
- QVERIFY2(component->isReady(), qPrintable(component->errorString()));
- QScopedPointer<QObject> rootObject(component->create());
- QVERIFY(rootObject);
+ verifyShadowable(u"shadowable"_s);
+ verifyNotShadowable(u"notShadowable"_s);
- const QMetaObject *mo = QMetaType::fromName("QQuickIcon").metaObject();
- QVERIFY(mo != nullptr);
+ QMetaObject::invokeMethod(o.data(), "setInnerShadowable");
- const QMetaProperty prop = mo->property(mo->indexOfProperty("color"));
- QVERIFY(prop.isValid());
+ verifyShadowable(u"self"_s);
+ verifyNotShadowable(u"notShadowable"_s);
- const QVariant a = rootObject->property("a");
- QVERIFY(a.isValid());
+ QMetaObject::invokeMethod(o.data(), "getInnerShadowable");
- const QVariant iconColor = prop.readOnGadget(rootObject->property("icon").data());
- QVERIFY(iconColor.isValid());
+ verifyShadowable(u"self"_s);
+ verifyNotShadowable(u"self"_s);
- const QMetaType colorType = QMetaType::fromName("QColor");
- QVERIFY(colorType.isValid());
+ QMetaObject::invokeMethod(o.data(), "turnEvil");
- QCOMPARE(a.metaType(), colorType);
- QCOMPARE(iconColor.metaType(), colorType);
+ verifyEvil();
+ verifyNotShadowable(u"self"_s);
- QCOMPARE(iconColor, a);
+ // Does not produce an error message because JavaScript.
+ QMetaObject::invokeMethod(o.data(), "setInnerShadowable");
+
+ verifyEvil();
+ verifyNotShadowable(u"self"_s);
+
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + u":29: Error: Cannot assign [undefined] to QObject*"_s));
+ QMetaObject::invokeMethod(o.data(), "getInnerShadowable");
+
+ verifyEvil();
+ verifyNotShadowable(u"self"_s);
}
-void tst_QmlCppCodegen::colorAsVariant()
+void tst_QmlCppCodegen::infinities()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/colorAsVariant.qml"_s));
- checkColorProperties(&component);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/infinities.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ QCOMPARE(o->property("positiveInfinity").toDouble(), std::numeric_limits<double>::infinity());
+ QCOMPARE(o->property("negativeInfinity").toDouble(), -std::numeric_limits<double>::infinity());
+
+ const double positiveZero = o->property("positiveZero").toDouble();
+ QCOMPARE(positiveZero, 0.0);
+ QVERIFY(!std::signbit(positiveZero));
+
+ const double negativeZero = o->property("negativeZero").toDouble();
+ QCOMPARE(negativeZero, -0.0);
+ QVERIFY(std::signbit(negativeZero));
+
+ QVERIFY(qIsNaN(o->property("naN").toDouble()));
}
-void tst_QmlCppCodegen::bindToValueType()
+void tst_QmlCppCodegen::infinitiesToInt()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/bindToValueType.qml"_s));
- checkColorProperties(&component);
+
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/infinitiesToInt.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ const char *props[] = {"a", "b", "c"};
+ for (const char *prop : props) {
+ const QVariant i = o->property(prop);
+ QCOMPARE(i.metaType(), QMetaType::fromType<int>());
+ bool ok = false;
+ QCOMPARE(i.toInt(&ok), 0);
+ QVERIFY(ok);
+ }
}
-void tst_QmlCppCodegen::undefinedResets()
+void tst_QmlCppCodegen::innerObjectNonShadowable()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/undefinedResets.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ownProperty.qml"_s));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
QScopedPointer<QObject> rootObject(component.create());
QVERIFY(rootObject);
- Person *person = qobject_cast<Person *>(rootObject.data());
- QVERIFY(person);
- QCOMPARE(person->shoeSize(), 0);
- QCOMPARE(person->name(), u"Marge"_s);
-
- person->setShoeSize(11);
+ QCOMPARE(rootObject->objectName(), u"foo"_s);
+}
- QCOMPARE(person->shoeSize(), 11);
- QCOMPARE(person->name(), u"Bart"_s);
+void tst_QmlCppCodegen::intEnumCompare()
+{
+ QQmlEngine engine;
+ {
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intEnumCompare.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("a").toBool(), true);
+ QCOMPARE(o->property("b").toBool(), false);
+ QCOMPARE(o->property("c").toBool(), true);
+ QCOMPARE(o->property("d").toBool(), false);
+ }
- person->setShoeSize(10);
- QCOMPARE(person->shoeSize(), 10);
- QCOMPARE(person->name(), u"Marge"_s);
+ {
+ // We cannot use Qt.red in QML because it's lower case.
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumInvalid.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("c").toBool(), true);
+ QCOMPARE(o->property("d").toBool(), false);
+ }
+}
- person->setName(u"no one"_s);
- QCOMPARE(person->name(), u"no one"_s);
+void tst_QmlCppCodegen::intOverflow()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intOverflow.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("a").toDouble(), 1.09951162778e+12);
+ QCOMPARE(object->property("b").toInt(), 5);
+}
- person->setObjectName(u"the one"_s);
- QCOMPARE(person->name(), u"Bart"_s);
+void tst_QmlCppCodegen::intToEnum()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intToEnum.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ MyType *m = qobject_cast<MyType *>(o.data());
+ QCOMPARE(m->a(), MyType::D);
+ QCOMPARE(m->property("b").toInt(), 24);
}
-void tst_QmlCppCodegen::innerObjectNonShadowable()
+void tst_QmlCppCodegen::interceptor()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ownProperty.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/interceptor.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+ QCOMPARE(object->property("x").toInt(), 100);
+ QCOMPARE(object->property("y").toInt(), 100);
- QCOMPARE(rootObject->objectName(), u"foo"_s);
+ QVERIFY(object->property("width").toInt() != 200);
+ QVERIFY(object->property("height").toInt() != 200);
+ QVERIFY(object->property("qProperty1").toInt() != 300);
+ QVERIFY(object->property("qProperty2").toInt() != 300);
+ QTRY_COMPARE(object->property("width").toInt(), 200);
+ QTRY_COMPARE(object->property("height").toInt(), 200);
+ QTRY_COMPARE(object->property("qProperty1").toInt(), 300);
+ QTRY_COMPARE(object->property("qProperty2").toInt(), 300);
}
-void tst_QmlCppCodegen::ownPropertiesNonShadowable()
+void tst_QmlCppCodegen::interestingFiles()
{
+ QFETCH(QString, file);
+ QFETCH(bool, isValid);
+
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/overriddenMember.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/%1"_s.arg(file)));
+ if (isValid) {
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ } else {
+ QVERIFY(component.isError());
+ }
+}
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+void tst_QmlCppCodegen::interestingFiles_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<bool>("isValid");
- QCOMPARE(rootObject->property("ppp").toInt(), 16);
- QCOMPARE(rootObject->property("ppp2").toInt(), 9);
- QCOMPARE(rootObject->property("ppp3").toInt(), 12);
+ QTest::addRow("conversions2") << u"conversions2.qml"_s << true;
+ QTest::addRow("TestCase") << u"TestCase.qml"_s << true;
+ QTest::addRow("layouts") << u"layouts.qml"_s << true;
+ QTest::addRow("interactive") << u"interactive.qml"_s << true;
+ QTest::addRow("Panel") << u"Panel.qml"_s << true;
+ QTest::addRow("ProgressBar") << u"ProgressBar/ProgressBar.ui.qml"_s << true;
+ QTest::addRow("Root") << u"ProgressBar/Root.qml"_s << true;
+ QTest::addRow("noscope") << u"noscope.qml"_s << true;
+ QTest::addRow("dynamicscene") << u"dynamicscene.qml"_s << true;
+ QTest::addRow("curlygrouped") << u"curlygrouped.qml"_s << true;
+ QTest::addRow("cycleHead") << u"cycleHead.qml"_s << false;
+ QTest::addRow("deadStoreLoop") << u"deadStoreLoop.qml"_s << true;
+ QTest::addRow("moveRegVoid") << u"moveRegVoid.qml"_s << true;
}
-void tst_QmlCppCodegen::modulePrefix()
+void tst_QmlCppCodegen::internalConversion()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/modulePrefix.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/internalConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(!obj.isNull());
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+ QObject *offset = obj->property("offset").value<QObject *>();
+ QVERIFY(offset);
- QCOMPARE(rootObject->property("foo").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
- QCOMPARE(rootObject->property("bar").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
- QCOMPARE(rootObject->property("baz").toString(), QStringLiteral("ItIsTheSingleton"));
+ QCOMPARE(offset->objectName(), "hello"_L1);
+ QCOMPARE(offset->property("mark").toString(), "hello"_L1);
}
-void tst_QmlCppCodegen::colorString()
+void tst_QmlCppCodegen::invalidPropertyType()
{
+ // Invisible on purpose
+ qmlRegisterType<MyCppType>("App", 1, 0, "MyCppType");
+
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/colorString.qml"_s));
+ QQmlComponent okComponent(&engine, QUrl(u"qrc:/qt/qml/TestTypes/OkType.qml"_s));
+ QVERIFY2(okComponent.isReady(), qPrintable(okComponent.errorString()));
+ QScopedPointer<QObject> picker(okComponent.create());
+ QVERIFY2(!picker.isNull(), qPrintable(okComponent.errorString()));
+ QObject *inner = qmlContext(picker.data())->objectForName(u"inner"_s);
+ QVERIFY(inner);
+ MyCppType *myCppType = qobject_cast<MyCppType *>(inner);
+ QVERIFY(myCppType);
+ QVERIFY(!myCppType->useListDelegate());
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BadType.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.createWithInitialProperties(
+ QVariantMap {{u"picker"_s, QVariant::fromValue(picker.data())}}));
+ QVERIFY2(!o.isNull(), qPrintable(c.errorString()));
+ QVERIFY(!myCppType->useListDelegate());
- QCOMPARE(qvariant_cast<QColor>(rootObject->property("c")), QColor::fromRgb(0xdd, 0xdd, 0xdd));
- QCOMPARE(qvariant_cast<QColor>(rootObject->property("d")), QColor::fromRgb(0xaa, 0xaa, 0xaa));
- QCOMPARE(qvariant_cast<QColor>(rootObject->property("e")), QColor::fromRgb(0x11, 0x22, 0x33));
+ o->setProperty("useListDelegate", QVariant::fromValue<bool>(true));
+ QVERIFY(myCppType->useListDelegate());
}
-void tst_QmlCppCodegen::urlString()
+void tst_QmlCppCodegen::invisibleBase()
{
QQmlEngine engine;
- QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/urlString.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleBase.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("n")), o.data());
+}
- QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QScopedPointer<QObject> rootObject(component.create());
- QVERIFY(rootObject);
+void tst_QmlCppCodegen::invisibleListElementType()
+{
+ qmlRegisterType<InvisibleListElementType>("Invisible", 1, 0, "InvisibleListElement");
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleListElementType.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QCOMPARE(qvariant_cast<QUrl>(rootObject->property("c")), QUrl(u"http://dddddd.com"_s));
- QCOMPARE(qvariant_cast<QUrl>(rootObject->property("d")), QUrl(u"http://aaaaaa.com"_s));
- QCOMPARE(qvariant_cast<QUrl>(rootObject->property("e")), QUrl(u"http://a112233.de"_s));
+ QObject *a = o->property("a").value<QObject *>();
+ QVERIFY(a);
+
+ const QVariant x = a->property("x");
+ QCOMPARE(x.metaType(), QMetaType::fromType<QQmlListReference>());
+ const QQmlListReference ref = x.value<QQmlListReference>();
+ QVERIFY(ref.isValid());
+ QCOMPARE(ref.size(), 0);
}
+void tst_QmlCppCodegen::invisibleSingleton()
+{
+ // We may have seen Style.qml as singleton before, which would make the assignment pass.
+ // So let's flush the type registry.
+ qmlClearTypeRegistrations();
-void tst_QmlCppCodegen::callContextPropertyLookupResult()
+ QQmlEngine engine;
+ const QUrl copy(u"qrc:/qt/qml/HiddenTestTypes/hidden/Main.qml"_s);
+ QQmlComponent c(&engine, copy);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "qrc:/qt/qml/HiddenTestTypes/hidden/Main.qml:4:5: "
+ "Unable to assign [undefined] to QColor");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("c"), QVariant(QMetaType::fromName("QColor")));
+}
+
+void tst_QmlCppCodegen::invisibleTypes()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/callContextPropertyLookupResult.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleTypes.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QVERIFY(qvariant_cast<QQmlComponent *>(o->property("c")) != nullptr);
+ QObject *singleton = qvariant_cast<QObject *>(o->property("singleton"));
+ QVERIFY(singleton != nullptr);
+ QCOMPARE(singleton->metaObject()->className(), "SingletonModel");
+
+ QObject *attached = qvariant_cast<QObject *>(o->property("attached"));
+ QVERIFY(attached != nullptr);
+ QCOMPARE(attached->metaObject()->className(), "AttachedAttached");
+
+// TODO: This doesn't work in interpreted mode:
+// const QMetaObject *meta = qvariant_cast<const QMetaObject *>(o->property("metaobject"));
+// QVERIFY(meta != nullptr);
+// QCOMPARE(meta->className(), "DerivedFromInvisible");
}
-void tst_QmlCppCodegen::deadShoeSize()
+void tst_QmlCppCodegen::iteration()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/deadShoeSize.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/iteration.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/deadShoeSize.qml:5: Error: ouch");
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("shoeSize").toInt(), 0);
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->objectName(), "a345b345c345"_L1);
}
-void tst_QmlCppCodegen::listIndices()
+void tst_QmlCppCodegen::javaScriptArgument()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listIndices.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/javaScriptArgument.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
- QQmlListReference list(o.data(), "items");
- QCOMPARE(list.count(), 3);
- for (int i = 0; i < 3; ++i)
- QCOMPARE(list.at(i), o.data());
- QCOMPARE(o->property("numItems").toInt(), 3);
- QCOMPARE(qvariant_cast<QObject *>(o->property("fractional")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(o->property("negativeZero")), o.data());
- QCOMPARE(qvariant_cast<QObject *>(o->property("infinity")), nullptr);
- QCOMPARE(qvariant_cast<QObject *>(o->property("nan")), nullptr);
+ QCOMPARE(o->property("a").toDouble(), 4.0);
+ QCOMPARE(o->property("b").toDouble(), 9.0);
+ QCOMPARE(o->property("c").toString(), u"5t-1"_s);
+ QCOMPARE(o->property("d").toString(), u"9"_s);
+ QCOMPARE(o->property("e").toString(), u"10"_s);
+ QCOMPARE(o->property("f").toString(), u"-10"_s);
+
+ const QStringList scales {
+ "0 ", "1 ", "10 ", "100 ", "1000 ", "9.77k", "97.7k", "977k", "9.54M", "95.4M", "954M",
+ "9.31G", "93.1G", "931G", "9.09T", "-1 ", "-10 ", "-100 ", "-1000 ", "-9.77k", "-97.7k",
+ "-977k", "-9.54M", "-95.4M", "-954M", "-9.31G", "-93.1G", "-931G", "-9.09T"
+ };
+
+ QCOMPARE(o->property("scales").value<QStringList>(), scales);
+
+ double thing = 12.0;
+ QString result;
+ QMetaObject::invokeMethod(
+ o.data(), "forwardArg", Q_RETURN_ARG(QString, result), Q_ARG(double, thing));
+ QCOMPARE(result, u"12 ");
}
-static const double numbers[] = {
- qQNaN(), -qInf(),
- std::numeric_limits<double>::min(),
- std::numeric_limits<float>::min(),
- std::numeric_limits<qint32>::min(),
- -1000.2, -100, -2, -1.333, -1, -0.84, -0.5,
+void tst_QmlCppCodegen::jsArrayMethods()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsArrayMethods.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- // -0 and 0 are not different on the QML side. Therefore, don't keep them adjacent.
- // Otherwise the bindings won't get re-evaluated.
- std::copysign(0.0, -1), 1, 0.0,
+ QQmlComponent untyped(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsArrayMethodsUntyped.qml"_s));
+ QVERIFY2(untyped.isReady(), qPrintable(untyped.errorString()));
+ QScopedPointer<QObject> check(untyped.create());
+ QVERIFY(!check.isNull());
- 0.5, 0.77, 1.4545, 2, 199, 2002.13,
- std::numeric_limits<qint32>::max(),
- std::numeric_limits<quint32>::max(),
- std::numeric_limits<float>::max(),
- std::numeric_limits<double>::max(),
- qInf()
-};
+ check->setProperty("l1", object->property("l1"));
+ check->setProperty("l2", object->property("l2"));
+ check->setProperty("l3", object->property("l3"));
+
+ QCOMPARE(object->property("listPropertyToString"), object->property("jsArrayToString"));
+ QCOMPARE(object->property("listPropertyToString"), check->property("jsArrayToString"));
+
+ QCOMPARE(object->property("listPropertyIncludes"), object->property("jsArrayIncludes"));
+ QVERIFY(object->property("listPropertyIncludes").toBool());
+
+ QCOMPARE(object->property("listPropertyJoin"), object->property("jsArrayJoin"));
+ QCOMPARE(object->property("listPropertyJoin"), check->property("jsArrayJoin"));
+ QVERIFY(object->property("listPropertyJoin").toString().contains(QStringLiteral("klaus")));
+
+ QCOMPARE(object->property("listPropertyIndexOf"), object->property("jsArrayIndexOf"));
+ QCOMPARE(object->property("listPropertyIndexOf").toInt(), 1);
+
+ QCOMPARE(object->property("listPropertyLastIndexOf"), object->property("jsArrayLastIndexOf"));
+ QCOMPARE(object->property("listPropertyLastIndexOf").toInt(), 5);
+}
+
+void tst_QmlCppCodegen::jsArrayMethodsWithParams()
+{
+ QFETCH(int, i);
+ QFETCH(int, j);
+ QFETCH(int, k);
+ QQmlEngine engine;
+ QQmlComponent component
+ (&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsArrayMethodsWithParams.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QQmlComponent untyped(
+ &engine, QUrl(u"qrc:/qt/qml/TestTypes/jsArrayMethodsWithParamsUntyped.qml"_s));
+ QVERIFY2(untyped.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.createWithInitialProperties({
+ {QStringLiteral("i"), i},
+ {QStringLiteral("j"), j},
+ {QStringLiteral("k"), k}
+ }));
+ QVERIFY(!object.isNull());
+ QScopedPointer<QObject> check(untyped.createWithInitialProperties({
+ {QStringLiteral("i"), i},
+ {QStringLiteral("j"), j},
+ {QStringLiteral("k"), k}
+ }));
+ QVERIFY(!check.isNull());
+ check->setProperty("l1", object->property("l1"));
+ check->setProperty("l2", object->property("l2"));
+ check->setProperty("l3", object->property("l3"));
+
+ listsEqual(object.data(), object.data(), "Slice");
+ listsEqual(object.data(), check.data(), "Slice");
+ QCOMPARE(object->property("listPropertyIndexOf"), object->property("jsArrayIndexOf"));
+ QCOMPARE(object->property("listPropertyIndexOf"), check->property("jsArrayIndexOf"));
+ QCOMPARE(object->property("listPropertyLastIndexOf"), object->property("jsArrayLastIndexOf"));
+ QCOMPARE(object->property("listPropertyLastIndexOf"), check->property("jsArrayLastIndexOf"));
+}
+
+void tst_QmlCppCodegen::jsArrayMethodsWithParams_data()
+{
+ QTest::addColumn<int>("i");
+ QTest::addColumn<int>("j");
+ QTest::addColumn<int>("k");
+
+ const int indices[] = {
+ std::numeric_limits<int>::min(),
+ -10, -3, -2, -1, 0, 1, 2, 3, 10,
+ std::numeric_limits<int>::max(),
+ };
+
+ // We cannot test the full cross product. So, take a random sample instead.
+ const qsizetype numIndices = sizeof(indices) / sizeof(int);
+ qsizetype seed = QRandomGenerator::global()->generate();
+ const int numSamples = 4;
+ for (int i = 0; i < numSamples; ++i) {
+ seed = qHash(i, seed);
+ const int vi = indices[qAbs(seed) % numIndices];
+ for (int j = 0; j < numSamples; ++j) {
+ seed = qHash(j, seed);
+ const int vj = indices[qAbs(seed) % numIndices];
+ for (int k = 0; k < numSamples; ++k) {
+ seed = qHash(k, seed);
+ const int vk = indices[qAbs(seed) % numIndices];
+ const QString tag = QLatin1String("%1/%2/%3").arg(
+ QString::number(vi), QString::number(vj), QString::number(vk));
+ QTest::newRow(qPrintable(tag)) << vi << vj << vk;
+
+ // output all the tags so that we can find out
+ // what combination caused a test to hang.
+ qDebug().noquote() << "scheduling" << tag;
+ }
+ }
+ }
+}
+
+void tst_QmlCppCodegen::jsImport()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsimport.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("value").toInt(), 42);
+}
void tst_QmlCppCodegen::jsMathObject()
{
@@ -1707,708 +2876,1247 @@ void tst_QmlCppCodegen::jsMathObject()
qDebug() << name << "failed.";
}
-void tst_QmlCppCodegen::intEnumCompare()
+void tst_QmlCppCodegen::jsmoduleImport()
{
QQmlEngine engine;
- {
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/intEnumCompare.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("a").toBool(), true);
- QCOMPARE(o->property("b").toBool(), false);
- QCOMPARE(o->property("c").toBool(), true);
- QCOMPARE(o->property("d").toBool(), false);
- }
-
- {
- // We cannot use Qt.red in QML because it's lower case.
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumInvalid.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("c").toBool(), true);
- QCOMPARE(o->property("d").toBool(), false);
- }
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/jsmoduleimport.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("ok").toBool(), true);
+ QVariant okFunc = object->property("okFunc");
+ QCOMPARE(okFunc.metaType(), QMetaType::fromType<QJSValue>());
+ QJSValue val = engine.toScriptValue(okFunc);
+ QJSValue result = val.call();
+ QVERIFY(result.isBool());
+ QVERIFY(result.toBool());
}
-void tst_QmlCppCodegen::attachedSelf()
+void tst_QmlCppCodegen::lengthAccessArraySequenceCompat()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/SelectionRectangle.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ArraySequenceLengthInterop.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("length").toInt(), 100);
+}
- QObject *handle = qvariant_cast<QObject *>(o->property("aa"));
- QVERIFY(handle);
- QVERIFY(qvariant_cast<QObject *>(handle->property("rect")) != nullptr);
+void tst_QmlCppCodegen::letAndConst()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/letAndConst.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"ab"_s);
}
-void tst_QmlCppCodegen::functionReturningVoid()
+void tst_QmlCppCodegen::listAsArgument()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/functionReturningVoid.qml"_s));
+
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listAsArgument.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QCOMPARE(o->property("i").toInt(), 4);
+ QCOMPARE(o->property("j").toInt(), 2);
+ QCOMPARE(o->property("i1").toInt(), 2);
+ QCOMPARE(o->property("i2").toInt(), 4);
+ QCOMPARE(o->property("d").value<QObject *>()->objectName(), u"this one"_s);
- // It should be able to call the methods and wrap the void values into invalid QVariants,
- // without crashing.
- QVERIFY(o->metaObject()->indexOfProperty("aa") >= 0);
- QVERIFY(o->metaObject()->indexOfProperty("bb") >= 0);
- QVERIFY(!o->property("aa").isValid());
- QVERIFY(!o->property("bb").isValid());
+ int singleInt = 0;
+ QList<int> moreInts;
+ QMetaObject::invokeMethod(o.data(), "returnInts1", Q_RETURN_ARG(QList<int>, moreInts));
+ QCOMPARE(moreInts, QList<int>({5, 4, 3, 2, 1}));
+ QMetaObject::invokeMethod(o.data(), "selectSecondInt", Q_RETURN_ARG(int, singleInt), Q_ARG(QList<int>, moreInts));
+ QCOMPARE(singleInt, 4);
}
-void tst_QmlCppCodegen::functionCallOnNamespaced()
+void tst_QmlCppCodegen::listConversion()
{
- QQmlEngine engine;
- {
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/themergood.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("i").toInt(), 12);
- }
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/listConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- {
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/themerbad.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("r"), QVariant::fromValue(QRectF(5.0, 10.0, 1.0, 1.0)));
+ QQmlListProperty<QObject> list = o->property("o").value<QQmlListProperty<QObject>>();
+ QCOMPARE(list.count(&list), 3);
+ for (int i = 0; i < 3; ++i) {
+ QObject *entry = list.at(&list, i);
+ Person *person = qobject_cast<Person *>(entry);
+ QVERIFY(person);
+ QCOMPARE(person->name(), u"Horst %1"_s.arg(i + 1));
}
+
+ QStringList strings = o->property("s").value<QStringList>();
+ QCOMPARE(strings, QStringList({u"Horst 1"_s, u"Horst 2"_s, u"Horst 3"_s}));
+
+ QVariantList vars = o->property("v").toList();
+ QCOMPARE(vars, QVariantList({
+ QString(),
+ QVariant::fromValue<qsizetype>(3),
+ QVariant::fromValue<Person *>(nullptr)
+ }));
}
-void tst_QmlCppCodegen::flushBeforeCapture()
+void tst_QmlCppCodegen::listIndices()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/noBindingLoop.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listIndices.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(o);
- QCOMPARE(o->property("deviation").toDouble(), 9.0 / 3.3333);
- QCOMPARE(o->property("samples").toInt(), 16);
- QCOMPARE(o->property("radius").toDouble(), 8.0);
+ QQmlListReference list(o.data(), "items");
+ QCOMPARE(list.count(), 3);
+ for (int i = 0; i < 3; ++i)
+ QCOMPARE(list.at(i), o.data());
+ QCOMPARE(o->property("numItems").toInt(), 3);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("fractional")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("negativeZero")), o.data());
+ QCOMPARE(qvariant_cast<QObject *>(o->property("infinity")), nullptr);
+ QCOMPARE(qvariant_cast<QObject *>(o->property("nan")), nullptr);
}
-void tst_QmlCppCodegen::unknownAttached()
+void tst_QmlCppCodegen::listLength()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unknownAttached.qml"_s));
- QVERIFY(c.isError());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listlength.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("l").toInt(), 2);
}
-void tst_QmlCppCodegen::variantlist()
+void tst_QmlCppCodegen::listOfInvisible()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/variantlist.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
-
- const QVariantList things = qvariant_cast<QVariantList>(o->property("things"));
- QCOMPARE(things.size(), 2);
- QCOMPARE(things[0].toString(), u"thing"_s);
- QCOMPARE(things[1].toInt(), 30);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listOfInvisible.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("width").toDouble(), 27.0);
}
-void tst_QmlCppCodegen::popContextAfterRet()
+void tst_QmlCppCodegen::listPropertyAsModel()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/popContextAfterRet.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listPropertyAsModel.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->objectName(), QString());
- o->setProperty("stackViewDepth", 1);
- QCOMPARE(o->objectName(), u"backgroundImage"_s);
- o->setProperty("stackViewDepth", 2);
- QCOMPARE(o->objectName(), u"backgroundBlur"_s);
- o->setProperty("stackViewDepth", 1);
- QCOMPARE(o->objectName(), u"backgroundImage"_s);
+ QQmlListReference children(o.data(), "children");
+ QCOMPARE(children.count(), 5);
}
-void tst_QmlCppCodegen::revisions()
+void tst_QmlCppCodegen::listToString()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/revisions.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listToString.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(QtDebugMsg, "[one,two]");
+ QTest::ignoreMessage(QtDebugMsg, "one,two");
+ QTest::ignoreMessage(QtDebugMsg, "[1,2]");
+ QTest::ignoreMessage(QtDebugMsg, "1,2");
+ QTest::ignoreMessage(
+ QtDebugMsg,
+ QRegularExpression("\\[QObject_QML_[0-9]+\\(0x[0-9a-f]+\\),"
+ "QObject_QML_[0-9]+\\(0x[0-9a-f]+\\)\\]"));
+ QTest::ignoreMessage(
+ QtDebugMsg,
+ QRegularExpression("QObject_QML_[0-9]+\\(0x[0-9a-f]+\\),"
+ "QObject_QML_[0-9]+\\(0x[0-9a-f]+\\)"));
+
+ QTest::ignoreMessage(QtDebugMsg, "[a,b]");
+
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+}
- QCOMPARE(o->property("delayed").toBool(), true);
- QCOMPARE(o->property("gotten").toInt(), 5);
+void tst_QmlCppCodegen::lotsOfRegisters()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/page.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ const auto compare = [&]() {
+ const qreal implicitBackgroundWidth = object->property("implicitBackgroundWidth").toDouble();
+ const qreal leftInset = object->property("leftInset").toDouble();
+ const qreal rightInset = object->property("rightInset").toDouble();
+ const qreal contentWidth = object->property("contentWidth").toDouble();
+ const qreal leftPadding = object->property("leftPadding").toDouble();
+ const qreal rightPadding = object->property("rightPadding").toDouble();
+ const qreal implicitFooterWidth = object->property("implicitFooterWidth").toDouble();
+ const qreal implicitHeaderWidth = object->property("implicitHeaderWidth").toDouble();
+
+ const qreal implicitWidth = object->property("implicitWidth").toDouble();
+ QCOMPARE(implicitWidth, qMax(qMax(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding),
+ qMax(implicitHeaderWidth, implicitFooterWidth)));
+ };
+
+ compare();
+
+ const QList<const char *> props = {
+ "leftInset", "rightInset", "contentWidth", "leftPadding", "rightPadding"
+ };
+
+ for (int i = 0; i < 100; ++i) {
+ QVERIFY(object->setProperty(props[i % props.size()], (i * 17) % 512));
+ compare();
+ }
}
-void tst_QmlCppCodegen::invisibleBase()
+void tst_QmlCppCodegen::math()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleBase.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(qvariant_cast<QObject *>(o->property("n")), o.data());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/math.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("a").toInt(), 9);
+ QCOMPARE(object->property("b").toDouble(), 50.0 / 22.0);
+ QCOMPARE(object->property("c").toDouble(), std::atan(1.0) * 8.0);
}
-void tst_QmlCppCodegen::notEqualsInt()
+void tst_QmlCppCodegen::mathMinMax()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/notEqualsInt.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/mathMinMax.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ // Math.max()
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "2");
+ QTest::ignoreMessage(QtDebugMsg, "2");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "2");
+ QTest::ignoreMessage(QtDebugMsg, "2");
+ QTest::ignoreMessage(QtDebugMsg, "9");
+
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "0.002");
+ QTest::ignoreMessage(QtDebugMsg, "5.4");
+ QTest::ignoreMessage(QtDebugMsg, "NaN");
+ QTest::ignoreMessage(QtDebugMsg, "Infinity");
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "0.08");
+ QTest::ignoreMessage(QtDebugMsg, "Infinity");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "NaN");
+
+ // Math.min()
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "1");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "-2");
+ QTest::ignoreMessage(QtDebugMsg, "-2");
+ QTest::ignoreMessage(QtDebugMsg, "0");
+
+ QTest::ignoreMessage(QtDebugMsg, "0");
+ QTest::ignoreMessage(QtDebugMsg, "-0.001");
+ QTest::ignoreMessage(QtDebugMsg, "0.002");
+ QTest::ignoreMessage(QtDebugMsg, "NaN");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-1");
+ QTest::ignoreMessage(QtDebugMsg, "-8");
+ QTest::ignoreMessage(QtDebugMsg, "NaN");
+
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QObject *t = qmlContext(o.data())->objectForName(u"t"_s);
- QVERIFY(t);
- QCOMPARE(t->property("text").toString(), u"Foo"_s);
- QMetaObject::invokeMethod(o.data(), "foo");
- QCOMPARE(t->property("text").toString(), u"Bar"_s);
+ QVERIFY(!o.isNull());
}
-void tst_QmlCppCodegen::infinities()
+void tst_QmlCppCodegen::mathOperations()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/infinities.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/mathOperations.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("positiveInfinity").toDouble(), std::numeric_limits<double>::infinity());
- QCOMPARE(o->property("negativeInfinity").toDouble(), -std::numeric_limits<double>::infinity());
+ const QMetaObject *metaObject = o->metaObject();
- const double positiveZero = o->property("positiveZero").toDouble();
- QCOMPARE(positiveZero, 0.0);
- QVERIFY(!std::signbit(positiveZero));
+ char t1;
+ char t2;
+ QString name;
+ const auto guard = qScopeGuard([&]() {
+ if (QTest::currentTestFailed()) {
+ qDebug() << t1 << t2 << name << "failed on:";
+ qDebug() << "doubles" << o->property("a").toDouble() << o->property("b").toDouble();
+ qDebug() << "integers" << o->property("ia").toInt() << o->property("ib").toInt();
+ qDebug() << "booleans" << o->property("ba").toBool() << o->property("bb").toBool();
+ }
+ });
- const double negativeZero = o->property("negativeZero").toDouble();
- QCOMPARE(negativeZero, -0.0);
- QVERIFY(std::signbit(negativeZero));
+ for (double a : numbers) {
+ for (double b : numbers) {
+ o->setProperty("a", a);
+ o->setProperty("b", b);
+ for (int i = 0, end = metaObject->propertyCount(); i != end; ++i) {
+ const QMetaProperty prop = metaObject->property(i);
+ const QByteArray propName = prop.name();
- QVERIFY(qIsNaN(o->property("naN").toDouble()));
+ if (propName.size() < 3 || propName == "objectName")
+ continue;
+
+ t1 = propName[0];
+ t2 = propName[1];
+ name = QString::fromUtf8(propName.mid(2));
+
+ double expected;
+
+ switch (t2) {
+ case 'd':
+ case '_':
+ switch (t1) {
+ case 'd':
+ expected = jsEval<double, double>(a, b, name, &engine);
+ break;
+ case 'i':
+ expected = jsEval<int, double>(a, b, name, &engine);
+ break;
+ case 'b':
+ expected = jsEval<bool, double>(a, b, name, &engine);
+ break;
+ }
+ break;
+ case 'i':
+ switch (t1) {
+ case 'd':
+ expected = jsEval<double, int>(a, b, name, &engine);
+ break;
+ case 'i':
+ expected = jsEval<int, int>(a, b, name, &engine);
+ break;
+ case 'b':
+ expected = jsEval<bool, int>(a, b, name, &engine);
+ break;
+ }
+ break;
+ case 'b':
+ switch (t1) {
+ case 'd':
+ expected = jsEval<double, bool>(a, b, name, &engine);
+ break;
+ case 'i':
+ expected = jsEval<int, bool>(a, b, name, &engine);
+ break;
+ case 'b':
+ expected = jsEval<bool, bool>(a, b, name, &engine);
+ break;
+ }
+ break;
+ }
+
+ const double result = prop.read(o.data()).toDouble();
+ QCOMPARE(result, expected);
+ }
+ }
+ }
}
-void tst_QmlCppCodegen::blockComments()
+void tst_QmlCppCodegen::mathStaticProperties()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/blockComments.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(o->property("implicitHeight").toDouble(), 8.0);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/mathStaticProperties.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ // Approximate values based on
+ // https://262.ecma-international.org/14.0/#sec-value-properties-of-the-math-object
+ QCOMPARE(object->property("e").toDouble(), 2.7182818284590452354);
+ QCOMPARE(object->property("ln10").toDouble(), 2.302585092994046);
+ QCOMPARE(object->property("ln2").toDouble(), 0.6931471805599453);
+ QCOMPARE(object->property("log10e").toDouble(), 0.4342944819032518);
+ QCOMPARE(object->property("log2e").toDouble(), 1.4426950408889634);
+ QCOMPARE(object->property("pi").toDouble(), 3.1415926535897932);
+ QCOMPARE(object->property("sqrt1_2").toDouble(), 0.7071067811865476);
+ QCOMPARE(object->property("sqrt2").toDouble(), 1.4142135623730951);
}
-void tst_QmlCppCodegen::functionLookup()
+void tst_QmlCppCodegen::mergedObjectReadWrite()
+{
+ QQmlEngine e;
+ {
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/mergedObjectRead.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtDebugMsg, "null");
+ QTest::ignoreMessage(
+ QtWarningMsg, QRegularExpression("TypeError: Cannot read property 'x' of null"));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ }
+
+ {
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/mergedObjectWrite.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ QRegularExpression(
+ "TypeError: Value is null and could not be converted to an object"));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ }
+}
+
+void tst_QmlCppCodegen::methodOnListLookup()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/functionLookup.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- const QVariant foo = o->property("bar");
- QCOMPARE(foo.metaType(), QMetaType::fromType<QJSValue>());
- const QJSManagedValue method(engine.toScriptValue(foo), &engine);
- QVERIFY(method.isFunction());
- const QJSValue result = method.call();
- QVERIFY(result.isString());
- QCOMPARE(result.toString(), QStringLiteral("a99"));
+ const QUrl url(u"qrc:/qt/qml/TestTypes/methodOnListLookup.qml"_s);
+ QQmlComponent component(&engine, url);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->objectName(), u"no one");
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString()
+ + ":14: TypeError: Cannot call method 'getName' of undefined"_L1));
+ QMetaObject::invokeMethod(o.data(), "boom");
}
-void tst_QmlCppCodegen::objectInVar()
+void tst_QmlCppCodegen::methods()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/objectInVar.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
- QCOMPARE(qvariant_cast<QObject*>(o->property("thing")), o.data());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/methods.qml"_s));
+ QVERIFY(component.isReady());
- bool result = false;
- QVERIFY(QMetaObject::invokeMethod(o.data(), "doThing", Q_RETURN_ARG(bool, result)));
- QVERIFY(result);
+ QTest::ignoreMessage(QtDebugMsg, "The Bar");
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(u"TypeError: .* is not a function"_s));
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(obj);
+ BirthdayParty *party(qobject_cast<BirthdayParty *>(obj.data()));
- o->setProperty("thing", QVariant::fromValue<std::nullptr_t>(nullptr));
- QVERIFY(QMetaObject::invokeMethod(o.data(), "doThing", Q_RETURN_ARG(bool, result)));
- QVERIFY(!result);
+ QVERIFY(party && party->host());
+ QCOMPARE(party->guestCount(), 5);
+
+ bool foundGreen = false;
+ bool foundFoo = false;
+ for (int ii = 0; ii < party->guestCount(); ++ii) {
+ if (party->guest(ii)->name() == u"William Green"_s)
+ foundGreen = true;
+ if (party->guest(ii)->name() == u"The Foo"_s)
+ foundFoo = true;
+ }
+
+ QVERIFY(foundGreen);
+ QVERIFY(foundFoo);
+
+ QCOMPARE(obj->property("n1").toString(), u"onGurk"_s);
+ QCOMPARE(obj->property("n2").toString(), u"onSemmeln"_s);
+ QCOMPARE(obj->property("n3"), QVariant());
+
+ {
+ QVariant ret;
+ obj->metaObject()->invokeMethod(obj.data(), "retrieveVar", Q_RETURN_ARG(QVariant, ret));
+ QCOMPARE(ret.typeId(), QMetaType::QString);
+ QCOMPARE(ret.toString(), u"Jack Smith"_s);
+ }
+
+ {
+ QString ret;
+ obj->metaObject()->invokeMethod(obj.data(), "retrieveString", Q_RETURN_ARG(QString, ret));
+ QCOMPARE(ret, u"Jack Smith"_s);
+ }
+
+ QCOMPARE(party->host()->shoeSize(), 12);
+ obj->metaObject()->invokeMethod(obj.data(), "storeElement");
+ QCOMPARE(party->host()->shoeSize(), 13);
+ QJSManagedValue v = engine.toManagedValue(obj->property("dresses"));
+ QVERIFY(v.isArray());
+
+ QJSManagedValue inner(v.property(2), &engine);
+ QVERIFY(inner.isArray());
+ QCOMPARE(inner.property(0).toInt(), 1);
+ QCOMPARE(inner.property(1).toInt(), 2);
+ QCOMPARE(inner.property(2).toInt(), 3);
+
+ QCOMPARE(obj->property("enumValue").toInt(), 2);
}
-void tst_QmlCppCodegen::functionTakingVar()
+void tst_QmlCppCodegen::modulePrefix()
{
QQmlEngine engine;
- const QUrl document(u"qrc:/qt/qml/TestTypes/functionTakingVar.qml"_s);
- QQmlComponent c(&engine, document);
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/modulePrefix.qml"_s));
- QVERIFY(!o->property("c").isValid());
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
- int value = 11;
- QQmlEnginePrivate *e = QQmlEnginePrivate::get(&engine);
- void *args[] = { nullptr, reinterpret_cast<void *>(std::addressof(value)) };
- QMetaType types[] = { QMetaType::fromType<void>(), QMetaType::fromType<std::decay_t<int>>() };
- e->executeRuntimeFunction(document, 0, o.data(), 1, args, types);
+ QCOMPARE(rootObject->property("foo").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
+ QCOMPARE(rootObject->property("bar").toDateTime(), QDateTime(QDate(1911, 3, 4), QTime()));
+ QCOMPARE(rootObject->property("baz").toString(), QStringLiteral("ItIsTheSingleton"));
+}
- QCOMPARE(o->property("c"), QVariant::fromValue<int>(11));
+void tst_QmlCppCodegen::multiDirectory_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addRow("from qt_add_qml_module")
+ << QUrl(u"qrc:/qt/qml/TestTypes/extra/extra.qml"_s);
+#ifndef VERY_OLD_CMAKE
+ QTest::addRow("from qt_target_qml_sources")
+ << QUrl(u"qrc:/qt/qml/TestTypes/extra2/extra.qml"_s);
+#endif
}
-void tst_QmlCppCodegen::testIsnan()
+void tst_QmlCppCodegen::multiDirectory()
{
+ QFETCH(QUrl, url);
QQmlEngine engine;
- const QUrl document(u"qrc:/qt/qml/TestTypes/isnan.qml"_s);
- QQmlComponent c(&engine, document);
+ QQmlComponent component(&engine, url);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
+
+ QCOMPARE(rootObject->property("r").value<QRectF>(), QRectF(4, 6, 8, 10));
+}
+
+void tst_QmlCppCodegen::multiForeign()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/multiforeign.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"not here and not there"_s);
+}
- QCOMPARE(o->property("good").toDouble(), 10.1);
- QVERIFY(qIsNaN(o->property("bad").toDouble()));
+void tst_QmlCppCodegen::multiLookup()
+{
+ // Multiple lookups of singletons (Qt in this case) don't clash with one another.
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/immediateQuit.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
- const QVariant a = o->property("a");
- QCOMPARE(a.metaType(), QMetaType::fromType<bool>());
- QVERIFY(!a.toBool());
+ const QByteArray message = QByteArray("End: ") + arg1();
+ QTest::ignoreMessage(QtDebugMsg, message.constData());
- const QVariant b = o->property("b");
- QCOMPARE(b.metaType(), QMetaType::fromType<bool>());
- QVERIFY(b.toBool());
+ QSignalSpy quitSpy(&engine, &QQmlEngine::quit);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(quitSpy.size(), 1);
}
-void tst_QmlCppCodegen::fallbackLookups()
+void tst_QmlCppCodegen::multipleCtors()
{
QQmlEngine engine;
- const QUrl document(u"qrc:/qt/qml/TestTypes/fallbacklookups.qml"_s);
- QQmlComponent c(&engine, document);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/multipleCtors.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("wr").value<ValueTypeWithLength>().length(), 3);
+ QCOMPARE(o->property("wp").value<ValueTypeWithLength>().length(), 11);
+ QCOMPARE(o->property("wi").value<ValueTypeWithLength>().length(), 17);
+}
- QCOMPARE(o->objectName(), QString());
- int result = 0;
+void tst_QmlCppCodegen::namespaceWithEnum()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/namespaceWithEnum.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("i").toInt(), 2);
+}
- QMetaObject::invokeMethod(o.data(), "withContext", Q_RETURN_ARG(int, result));
- QCOMPARE(result, 16);
- QCOMPARE(o->objectName(), QStringLiteral("aa93"));
+void tst_QmlCppCodegen::noQQmlData()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/noQQmlData.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QMetaObject::invokeMethod(o.data(), "withId", Q_RETURN_ARG(int, result));
- QCOMPARE(result, 17);
- QCOMPARE(o->objectName(), QStringLiteral("bb94"));
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/noQQmlData.qml:7: TypeError: "
+ "Cannot read property 'name' of null");
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
- QObject *singleton = nullptr;
- QMetaObject::invokeMethod(o.data(), "getSingleton", Q_RETURN_ARG(QObject*, singleton));
- QVERIFY(singleton);
+ BirthdayParty *party = qobject_cast<BirthdayParty *>(root.data());
+ QVERIFY(party != nullptr);
- QMetaObject::invokeMethod(o.data(), "withSingleton", Q_RETURN_ARG(int, result));
- QCOMPARE(result, 18);
- QCOMPARE(singleton->objectName(), QStringLiteral("cc95"));
+ QCOMPARE(party->host(), nullptr);
+ QCOMPARE(party->property("n").toString(), QString());
- QMetaObject::invokeMethod(o.data(), "withProperty", Q_RETURN_ARG(int, result));
- QCOMPARE(result, 19);
- QCOMPARE(singleton->objectName(), QStringLiteral("dd96"));
+ Person *host1 = new Person(party);
+ party->setHost(host1);
+ QCOMPARE(party->property("n").toString(), u"Bart in da house!"_s);
+ host1->setName(u"Marge"_s);
+ QCOMPARE(party->property("n").toString(), u"Marge in da house!"_s);
+
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/noQQmlData.qml:7: TypeError: "
+ "Cannot read property 'name' of null");
+
+ // Doesn't crash
+ party->setHost(nullptr);
+
+ // Lookups are initialized now, and we introduce an object without QQmlData
+ Person *host2 = new Person(party);
+ party->setHost(host2);
+ QCOMPARE(party->property("n").toString(), u"Bart in da house!"_s);
+ host2->setName(u"Homer"_s);
+ QCOMPARE(party->property("n").toString(), u"Homer in da house!"_s);
+
+ QMetaObject::invokeMethod(party, "burn");
+ engine.collectGarbage();
+
+ // Does not crash
+ party->setProperty("inDaHouse", u" burns!"_s);
+
+ // Mr Burns may or may not burn, depending on whether we use lookups.
+ // If using lookups, the binding is aborted when we find the isQueuedForDeletion flag.
+ // If reading the property directly, we don't have to care about it.
+ QVERIFY(party->property("n").toString().startsWith(u"Mr Burns"_s));
}
-void tst_QmlCppCodegen::typedArray()
+void tst_QmlCppCodegen::nonNotifyable()
{
QQmlEngine engine;
- const QUrl document(u"qrc:/qt/qml/TestTypes/typedArray.qml"_s);
- QQmlComponent c(&engine, document);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nonNotifyable.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(qvariant_cast<QDateTime>(object->property("dayz")),
+ QDateTime(QDate(2121, 1, 12), QTime()));
+ QCOMPARE(qvariant_cast<QDateTime>(object->property("oParty")),
+ QDateTime(QDate(2111, 12, 11), QTime()));
+}
+
+void tst_QmlCppCodegen::notEqualsInt()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/notEqualsInt.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(o);
- QDateTime date;
- QVERIFY(qvariant_cast<QList<int>>(o->property("values2")).isEmpty());
- QCOMPARE(qvariant_cast<QList<int>>(o->property("values3")),
- QList<int>({1, 2, 3, 4}));
- QCOMPARE(qvariant_cast<QList<QDateTime>>(o->property("values4")),
- QList<QDateTime>({date, date, date}));
- QCOMPARE(qvariant_cast<QList<double>>(o->property("values5")),
- QList<double>({1, 2, 3.4, 30, 0, 0}));
- date = QDateTime::currentDateTime();
- o->setProperty("aDate", date);
- QCOMPARE(qvariant_cast<QList<QDateTime>>(o->property("values4")),
- QList<QDateTime>({date, date, date}));
+ QObject *t = qmlContext(o.data())->objectForName(u"t"_s);
+ QVERIFY(t);
+ QCOMPARE(t->property("text").toString(), u"Foo"_s);
+ QMetaObject::invokeMethod(o.data(), "foo");
+ QCOMPARE(t->property("text").toString(), u"Bar"_s);
+}
- QQmlListProperty<QObject> values6
- = qvariant_cast<QQmlListProperty<QObject>>(o->property("values6"));
- QCOMPARE(values6.count(&values6), 3);
- for (int i = 0; i < 3; ++i)
- QCOMPARE(values6.at(&values6, i), o.data());
+void tst_QmlCppCodegen::notNotString()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/notNotString.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- QCOMPARE(o->property("inIntList").toInt(), 2);
- QCOMPARE(qvariant_cast<QDateTime>(o->property("inDateList")), date);
- QCOMPARE(o->property("inRealList").toDouble(), 30.0);
- QCOMPARE(o->property("inCharList").toString(), QStringLiteral("f"));
+ QCOMPARE(o->property("notNotString").value<bool>(), false);
+ o->setObjectName(u"a"_s);
+ QCOMPARE(o->property("notNotString").value<bool>(), true);
+}
- const QMetaObject *metaObject = o->metaObject();
- QMetaMethod method = metaObject->method(metaObject->indexOfMethod("stringAt10(QString)"));
- QVERIFY(method.isValid());
+void tst_QmlCppCodegen::nullAccess()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullAccess.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
- // If LoadElement threw an exception the function would certainly return neither 10 nor 20.
- int result = 0;
- method.invoke(
- o.data(), Q_RETURN_ARG(int, result), Q_ARG(QString, QStringLiteral("a")));
- QCOMPARE(result, 10);
- method.invoke(
- o.data(), Q_RETURN_ARG(int, result), Q_ARG(QString, QStringLiteral("aaaaaaaaaaa")));
- QCOMPARE(result, 20);
+ QTest::ignoreMessage(QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/nullAccess.qml:4:5: TypeError: "
+ "Cannot read property 'width' of null");
+ QTest::ignoreMessage(QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/nullAccess.qml:5:5: TypeError: "
+ "Cannot read property 'height' of null");
+ QTest::ignoreMessage(QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/nullAccess.qml:6: TypeError: Value is null and "
+ "could not be converted to an object");
+ QScopedPointer<QObject> object(component.create());
+
+ QCOMPARE(object->property("width").toDouble(), 0.0);
+ QCOMPARE(object->property("height").toDouble(), 0.0);
}
-void tst_QmlCppCodegen::prefixedType()
+void tst_QmlCppCodegen::nullAccessInsideSignalHandler()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullAccessInsideSignalHandler.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QTest::ignoreMessage(QtWarningMsg,
+ "qrc:/qt/qml/TestTypes/nullAccessInsideSignalHandler.qml:15: ReferenceError: "
+ "text is not defined");
+ QScopedPointer<QObject> object(component.create());
+ QSignalSpy spy(object.data(), SIGNAL(say_hello()));
+ QTRY_VERIFY(spy.size() > 0);
+}
- // We need to add an import path here because we cannot namespace the implicit import.
- // The implicit import is what we use for all the other tests, even if we explicitly
- // import TestTypes. That is because the TestTypes module is in a subdirectory "data".
- engine.addImportPath(u":/"_s);
- const QUrl document(u"qrc:/qt/qml/TestTypes/prefixedMetaType.qml"_s);
- QQmlComponent c(&engine, document);
+void tst_QmlCppCodegen::nullComparison()
+{
+ QQmlEngine engine;
+
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullComparison.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ QVERIFY(!o.isNull());
- QCOMPARE(o->property("state").toInt(), 2);
- QVERIFY(qvariant_cast<QObject *>(o->property("a")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("b")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("c")) == nullptr);
+ QCOMPARE(o->property("v").toInt(), 1);
+ QCOMPARE(o->property("w").toInt(), 3);
+ QCOMPARE(o->property("x").toInt(), 1);
+ QCOMPARE(o->property("y").toInt(), 5);
+ QCOMPARE(o->property("z").toInt(), 18);
+}
- QVERIFY(qvariant_cast<QObject *>(o->property("d")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("e")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("f")) == nullptr);
+void tst_QmlCppCodegen::nullishCoalescing_data()
+{
+ QTest::addColumn<QString>("propertyName");
+ QTest::addColumn<QVariant>("expected");
- QVERIFY(qvariant_cast<QObject *>(o->property("g")) != nullptr);
- QVERIFY(qvariant_cast<QObject *>(o->property("h")) != nullptr);
+ const auto undefinedValue = QVariant();
+ const auto nullValue = QVariant::fromMetaType(QMetaType::fromType<std::nullptr_t>(), nullptr);
- QCOMPARE(o->property("countG").toInt(), 11);
- QCOMPARE(o->property("countH").toInt(), 11);
-}
+ QTest::addRow("trivial-good-int") << "p1" << QVariant(5);
+ QTest::addRow("trivial-good-string") << "p2" << QVariant("6");
-void tst_QmlCppCodegen::evadingAmbiguity()
-{
- QQmlEngine engine;
+ QTest::addRow("trivial-bad-undefined-undefined") << "p3" << undefinedValue;
+ QTest::addRow("trivial-bad-undefined-null") << "p4" << nullValue;
+ QTest::addRow("trivial-bad-undefined-int") << "p5" << QVariant(-1);
+ QTest::addRow("trivial-bad-undefined-string") << "p6" << QVariant("-1");
- // We need to add an import path here because we cannot namespace the implicit import.
- // The implicit import is what we use for all the other tests, even if we explicitly
- // import TestTypes. That is because the TestTypes module is in a subdirectory "data".
- engine.addImportPath(u":/"_s);
+ QTest::addRow("trivial-bad-null-undefined") << "p7" << undefinedValue;
+ QTest::addRow("trivial-bad-null-null") << "p8" << nullValue;
+ QTest::addRow("trivial-bad-null-int") << "p9" << QVariant(-1);
+ QTest::addRow("trivial-bad-null-string") << "p10" << QVariant("-1");
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguous1/Ambiguous.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- QScopedPointer<QObject> o1(c1.create());
- QCOMPARE(o1->objectName(), QStringLiteral("Ambiguous"));
- QCOMPARE(o1->property("i").toString(), QStringLiteral("Ambiguous1"));
+ QTest::addRow("enum1") << "p11" << QVariant(1);
- QQmlComponent c2(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguous2/Ambiguous.qml"_s));
- QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
- QScopedPointer<QObject> o2(c2.create());
- QCOMPARE(o2->objectName(), QStringLiteral("Ambiguous"));
- QCOMPARE(o2->property("i").toString(), QStringLiteral("Ambiguous2"));
+ QTest::addRow("multiple ?? int") << "p12" << QVariant(1);
+ QTest::addRow("multiple ?? string") << "p13" << QVariant("1");
+ QTest::addRow("multiple ?? mixed2") << "p14" << QVariant("2");
+ QTest::addRow("multiple ?? mixed3") << "p15" << QVariant(1);
+
+ QTest::addRow("optional + nullish bad") << "p16" << QVariant(-1);
+ QTest::addRow("optional + nullish good") << "p17" << QVariant(5);
}
-void tst_QmlCppCodegen::fromBoolValue()
+void tst_QmlCppCodegen::nullishCoalescing()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/fromBoolValue.qml"_s));
+ const QUrl document(u"qrc:/qt/qml/TestTypes/nullishCoalescing.qml"_s);
+ QQmlComponent c(&engine, document);
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QCOMPARE(o->property("a").toBool(), true);
- o->setProperty("x", 100);
- QCOMPARE(o->property("a").toBool(), false);
-
- QCOMPARE(o->property("width").toInt(), 100);
- QCOMPARE(o->property("b").toBool(), false);
+ QVERIFY(o);
- QScopedPointer<QObject> parent(c.create());
- o->setProperty("parent", QVariant::fromValue(parent.data()));
- QCOMPARE(o->property("width").toInt(), 100);
- QCOMPARE(o->property("b").toBool(), false);
+ QFETCH(QString, propertyName);
+ QFETCH(QVariant, expected);
- o->setProperty("state", QVariant::fromValue(u"foo"_s));
- QCOMPARE(o->property("width").toInt(), 0);
- QCOMPARE(o->property("b").toBool(), false);
+ QVariant actual = o->property(propertyName.toLocal8Bit());
+ QCOMPARE(actual, expected);
}
-void tst_QmlCppCodegen::invisibleTypes()
+void tst_QmlCppCodegen::numbersInJsPrimitive()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleTypes.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/numbersInJsPrimitive.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QObject *singleton = qvariant_cast<QObject *>(o->property("singleton"));
- QVERIFY(singleton != nullptr);
- QCOMPARE(singleton->metaObject()->className(), "SingletonModel");
+ const QList<qint64> zeroes
+ = {0, 0, 0, 0, 0, 0, 0, 0};
+ const QList<qint64> written
+ = {35, 36, 37, 38, 39, 40, 41, 42};
+ const QList<qint64> writtenNegative
+ = {-35, 220, -37, 65498, -39, 4294967256, -41, 4294967254};
+ const QList<QList<qint64>> writtenShuffled = {
+ { -36, 219, -38, 65497, -40, 4294967255, -42, 4294967260 },
+ { -37, 218, -39, 65496, -41, 4294967254, -36, 4294967259 },
+ { -38, 217, -40, 65495, -42, 4294967260, -37, 4294967258 },
+ { -39, 216, -41, 65494, -36, 4294967259, -38, 4294967257 },
+ { -40, 215, -42, 65500, -37, 4294967258, -39, 4294967256 },
+ { -41, 214, -36, 65499, -38, 4294967257, -40, 4294967255 },
+ { -42, 220, -37, 65498, -39, 4294967256, -41, 4294967254 },
+ { -36, 219, -38, 65497, -40, 4294967255, -42, 4294967260 },
+ };
- QObject *attached = qvariant_cast<QObject *>(o->property("attached"));
- QVERIFY(attached != nullptr);
- QCOMPARE(attached->metaObject()->className(), "AttachedAttached");
+ const QList<qint64> stored
+ = {50, 51, 1332, 1333, 1334, 1335, 1336, 1337};
+ const QList<qint64> storedNegative
+ = {-50, 205, -1332, 64203, -1334, 4294965961, -1336, 4294965959};
+ const QList<QList<qint64>> storedShuffled = {
+ { -51, 204, -1333, 64202, -1335, 4294965960, -1337, 4294967245 },
+ { -52, 203, -1334, 64201, -1336, 4294965959, -51, 4294967244 },
+ { -53, 202, -1335, 64200, -1337, 4294967245, -52, 4294967243 },
+ { -54, 201, -1336, 64199, -51, 4294967244, -53, 4294967242 },
+ { -55, 200, -1337, 65485, -52, 4294967243, -54, 4294967241 },
+ { -56, 199, -51, 65484, -53, 4294967242, -55, 4294967240 },
+ { -57, 205, -52, 65483, -54, 4294967241, -56, 4294967239 },
+ { -51, 204, -53, 65482, -55, 4294967240, -57, 4294967245 },
+ };
-// TODO: This doesn't work in interpreted mode:
-// const QMetaObject *meta = qvariant_cast<const QMetaObject *>(o->property("metaobject"));
-// QVERIFY(meta != nullptr);
-// QCOMPARE(meta->className(), "DerivedFromInvisible");
-}
+ QStringList asStrings(8);
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(zeroes));
-class MyCppType : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(bool useListDelegate
- READ useListDelegate
- WRITE setUseListDelegate
- NOTIFY useListDelegateChanged)
-public:
- explicit MyCppType(QObject * parent = nullptr) : QObject(parent) {}
+ QMetaObject::invokeMethod(o.data(), "writeValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(written));
- bool useListDelegate() const { return m_useListDelegate; }
- void setUseListDelegate(bool useListDelegate)
- {
- if (useListDelegate != m_useListDelegate) {
- m_useListDelegate = useListDelegate;
- emit useListDelegateChanged();
+ QMetaObject::invokeMethod(o.data(), "negateValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(writtenNegative));
+
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(o.data(), "shuffleValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
}
+ QCOMPARE(asStrings, convertToStrings(writtenShuffled[i]));
}
-signals:
- void useListDelegateChanged();
+ QMetaObject::invokeMethod(o.data(), "storeValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(stored));
-private:
- bool m_useListDelegate = false;
-};
+ QMetaObject::invokeMethod(o.data(), "negateValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(storedNegative));
+
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(o.data(), "shuffleValues");
+ for (int i = 0; i < 8; ++i) {
+ QMetaObject::invokeMethod(
+ o.data(), "readValueAsString",
+ Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ }
+ QCOMPARE(asStrings, convertToStrings(storedShuffled[i]));
+ }
+}
-void tst_QmlCppCodegen::invalidPropertyType()
+void tst_QmlCppCodegen::objectInVar()
{
- // Invisible on purpose
- qmlRegisterType<MyCppType>("App", 1, 0, "MyCppType");
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/objectInVar.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(qvariant_cast<QObject*>(o->property("thing")), o.data());
+
+ bool result = false;
+ QVERIFY(QMetaObject::invokeMethod(o.data(), "doThing", Q_RETURN_ARG(bool, result)));
+ QVERIFY(result);
+ o->setProperty("thing", QVariant::fromValue<std::nullptr_t>(nullptr));
+ QVERIFY(QMetaObject::invokeMethod(o.data(), "doThing", Q_RETURN_ARG(bool, result)));
+ QVERIFY(!result);
+}
+
+void tst_QmlCppCodegen::objectLookupOnListElement()
+{
QQmlEngine engine;
- QQmlComponent okComponent(&engine, QUrl(u"qrc:/qt/qml/TestTypes/OkType.qml"_s));
- QVERIFY2(okComponent.isReady(), qPrintable(okComponent.errorString()));
- QScopedPointer<QObject> picker(okComponent.create());
- QVERIFY2(!picker.isNull(), qPrintable(okComponent.errorString()));
- QObject *inner = qmlContext(picker.data())->objectForName(u"inner"_s);
- QVERIFY(inner);
- MyCppType *myCppType = qobject_cast<MyCppType *>(inner);
- QVERIFY(myCppType);
- QVERIFY(!myCppType->useListDelegate());
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/BadType.qml"_s));
+ const QUrl url(u"qrc:/qt/qml/TestTypes/objectLookupOnListElement.qml"_s);
+ QQmlComponent c1(&engine, url);
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+
+ QScopedPointer<QObject> object(c1.create());
+ QVERIFY(!object.isNull());
+
+ QList<int> zOrders;
+ QMetaObject::invokeMethod(object.data(), "zOrders", Q_RETURN_ARG(QList<int>, zOrders));
+ QCOMPARE(zOrders, (QList<int>{1, 0, 0}));
+ object->setProperty("current", 1);
+ QMetaObject::invokeMethod(object.data(), "zOrders", Q_RETURN_ARG(QList<int>, zOrders));
+ QCOMPARE(zOrders, (QList<int>{0, 1, 0}));
+
+ QMetaObject::invokeMethod(object.data(), "clearChildren");
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString()
+ + u":21: TypeError: Cannot read property 'z' of undefined"_s));
+ QMetaObject::invokeMethod(object.data(), "zOrders", Q_RETURN_ARG(QList<int>, zOrders));
+ QCOMPARE(zOrders, (QList<int>()));
+}
+
+void tst_QmlCppCodegen::objectToString()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/toString.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.createWithInitialProperties(
- QVariantMap {{u"picker"_s, QVariant::fromValue(picker.data())}}));
- QVERIFY2(!o.isNull(), qPrintable(c.errorString()));
- QVERIFY(!myCppType->useListDelegate());
- o->setProperty("useListDelegate", QVariant::fromValue<bool>(true));
- QVERIFY(myCppType->useListDelegate());
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/toString.qml:6: no");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("yes").toString(), u"yes yes"_s);
+ QCOMPARE(o->property("no").toString(), u" no"_s); // throws, but that is ignored
}
-void tst_QmlCppCodegen::valueTypeLists()
+void tst_QmlCppCodegen::objectWithStringListMethod()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/valueTypeLists.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/objectWithStringListMethod.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtDebugMsg, "2");
QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
- QCOMPARE(qvariant_cast<QRectF>(o->property("rectInBounds")), QRectF(1, 2, 3, 4));
- QVERIFY(o->metaObject()->indexOfProperty("rectOutOfBounds") > 0);
- QVERIFY(!o->property("rectOutOfBounds").isValid());
+void tst_QmlCppCodegen::onAssignment()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/pressAndHoldButton.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
- QCOMPARE(qvariant_cast<QString>(o->property("stringInBounds")), QStringLiteral("bbb"));
- QVERIFY(o->metaObject()->indexOfProperty("stringOutOfBounds") > 0);
- QVERIFY(!o->property("stringOutOfBounds").isValid());
+ QCOMPARE(object->property("pressed").toBool(), false);
+ QCOMPARE(object->property("scale").toDouble(), 1.0);
- QCOMPARE(qvariant_cast<int>(o->property("intInBounds")), 7);
- QVERIFY(o->metaObject()->indexOfProperty("intOutOfBounds") > 0);
- QVERIFY(!o->property("intOutOfBounds").isValid());
+ object->metaObject()->invokeMethod(object.data(), "press");
+ QTRY_COMPARE(object->property("pressed").toBool(), true);
+ QCOMPARE(object->property("scale").toDouble(), 0.9);
- QCOMPARE(qvariant_cast<QString>(o->property("charInBounds")), QStringLiteral("d"));
- QVERIFY(o->metaObject()->indexOfProperty("charOutOfBounds") > 0);
- QVERIFY(!o->property("charOutOfBounds").isValid());
+ object->metaObject()->invokeMethod(object.data(), "release");
+ QCOMPARE(object->property("pressed").toBool(), false);
+ QCOMPARE(object->property("scale").toDouble(), 1.0);
}
-void tst_QmlCppCodegen::boundComponents()
+void tst_QmlCppCodegen::optionalComparison()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/boundComponents.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/optionalComparison.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QObject *c1o = o->property("o").value<QObject *>();
- QVERIFY(c1o != nullptr);
- QCOMPARE(c1o->objectName(), u"bar"_s);
+ QCOMPARE(object->property("found").toInt(), 1);
+ QCOMPARE(object->property("foundStrict").toInt(), 1);
+ QCOMPARE(object->property("foundNot").toInt(), 2);
+ QCOMPARE(object->property("foundStrictNot").toInt(), 2);
- QObject *c2o = c1o->property("o").value<QObject *>();
- QVERIFY(c2o != nullptr);
- QCOMPARE(c2o->objectName(), u"bar12"_s);
+ // this === this, null === null (x4), undefined === undefined
+ QCOMPARE(object->property("undefinedEqualsUndefined").toInt(), 6);
+
+ QCOMPARE(object->property("optionalNull").toBool(), true);
+ object->setObjectName("foo"_L1);
+ QCOMPARE(object->property("optionalNull").toBool(), false);
}
-class InvisibleListElementType : public QObject
+void tst_QmlCppCodegen::outOfBoundsArray()
{
- Q_OBJECT
-public:
- InvisibleListElementType(QObject *parent = nullptr) : QObject(parent) {}
-};
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/outOfBounds.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
-void tst_QmlCppCodegen::invisibleListElementType()
+ QTest::ignoreMessage(QtDebugMsg, "oob undefined");
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QVERIFY(object->metaObject()->indexOfProperty("oob") > 0);
+ QVERIFY(!object->property("oob").isValid());
+ const QVariant oob2 = object->property("oob2");
+ QCOMPARE(oob2.metaType(), QMetaType::fromType<QObject *>());
+ QCOMPARE(oob2.value<QObject *>(), nullptr);
+}
+
+void tst_QmlCppCodegen::overriddenProperty()
{
- qmlRegisterType<InvisibleListElementType>("Invisible", 1, 0, "InvisibleListElement");
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/invisibleListElementType.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/childobject.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QObject *a = o->property("a").value<QObject *>();
- QVERIFY(a);
+ QObject *child = object->property("child").value<QObject *>();
+ QVERIFY(child);
- const QVariant x = a->property("x");
- QCOMPARE(x.metaType(), QMetaType::fromType<QQmlListReference>());
- const QQmlListReference ref = x.value<QQmlListReference>();
- QVERIFY(ref.isValid());
- QCOMPARE(ref.size(), 0);
+ QCOMPARE(object->objectName(), u"kraut"_s);
+ QCOMPARE(object->property("doneThing").toInt(), 5);
+ QCOMPARE(object->property("usingFinal").toInt(), 5);
+
+ auto checkAssignment = [&]() {
+ const QString newName = u"worscht"_s;
+ QMetaObject::invokeMethod(object.data(), "setChildObjectName", Q_ARG(QString, newName));
+ QCOMPARE(object->objectName(), newName);
+ };
+ checkAssignment();
+
+ QMetaObject::invokeMethod(child, "doString");
+ QCOMPARE(child->objectName(), u"string"_s);
+ QMetaObject::invokeMethod(child, "doNumber");
+ QCOMPARE(child->objectName(), u"double"_s);
+ QMetaObject::invokeMethod(child, "doArray");
+ QCOMPARE(child->objectName(), u"javaScript"_s);
+
+ QMetaObject::invokeMethod(child, "doString2");
+ QCOMPARE(child->objectName(), u"string"_s);
+ QMetaObject::invokeMethod(child, "doNumber2");
+ QCOMPARE(child->objectName(), u"double"_s);
+ QMetaObject::invokeMethod(child, "doArray2");
+ QCOMPARE(child->objectName(), u"javaScript"_s);
+
+ QMetaObject::invokeMethod(child, "doFoo");
+ QCOMPARE(child->objectName(), u"ObjectWithMethod"_s);
+
+ ObjectWithMethod *benign = new ObjectWithMethod(object.data());
+ benign->theThing = 10;
+ benign->setObjectName(u"cabbage"_s);
+ object->setProperty("child", QVariant::fromValue(benign));
+ QCOMPARE(object->objectName(), u"cabbage"_s);
+ checkAssignment();
+ QCOMPARE(object->property("doneThing").toInt(), 10);
+ QCOMPARE(object->property("usingFinal").toInt(), 10);
+
+ OverriddenObjectName *evil = new OverriddenObjectName(object.data());
+ QTest::ignoreMessage(QtWarningMsg,
+ "Final member fff is overridden in class OverriddenObjectName. "
+ "The override won't be used.");
+ object->setProperty("child", QVariant::fromValue(evil));
+
+ QCOMPARE(object->objectName(), u"borschtsch"_s);
+
+ checkAssignment();
+ QCOMPARE(object->property("doneThing").toInt(), 7);
+ QCOMPARE(object->property("usingFinal").toInt(), 5);
}
-void tst_QmlCppCodegen::typePropertyClash()
+void tst_QmlCppCodegen::ownPropertiesNonShadowable()
{
QQmlEngine engine;
- engine.rootContext()->setContextProperty(u"size"_s, 5);
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/typePropertyClash.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"Size: 5"_s);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/overriddenMember.qml"_s));
+
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
+
+ QCOMPARE(rootObject->property("ppp").toInt(), 16);
+ QCOMPARE(rootObject->property("ppp2").toInt(), 9);
+ QCOMPARE(rootObject->property("ppp3").toInt(), 12);
}
-void tst_QmlCppCodegen::objectToString()
+void tst_QmlCppCodegen::parentProperty()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/toString.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/parentProp.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("c").toInt(), 11);
+ QCOMPARE(object->property("i").toInt(), 22);
+ object->setProperty("a", QVariant::fromValue(22));
+ QCOMPARE(object->property("c").toInt(), 28);
+ object->setProperty("implicitWidth", QVariant::fromValue(14));
+ QCOMPARE(object->property("i").toInt(), 26);
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/toString.qml:6: no");
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QObject *child = qmlContext(object.data())->objectForName(u"child"_s);
+ QObject *sibling = qmlContext(object.data())->objectForName(u"sibling"_s);
+ QObject *evil = qmlContext(object.data())->objectForName(u"evil"_s);
- QCOMPARE(o->property("yes").toString(), u"yes yes"_s);
- QCOMPARE(o->property("no").toString(), u" no"_s); // throws, but that is ignored
+ child->setProperty("parent", QVariant::fromValue(sibling));
+
+ QCOMPARE(child->property("b").toInt(), 0);
+ QCOMPARE(child->property("i").toInt(), 28);
+ QCOMPARE(object->property("i").toInt(), 56);
+
+ child->setProperty("parent", QVariant::fromValue(evil));
+
+ QCOMPARE(child->property("b").toInt(), 5994);
+ QCOMPARE(object->property("c").toInt(), 5996);
+
+ QCOMPARE(child->property("i").toInt(), 443);
+ QCOMPARE(object->property("i").toInt(), 886);
+
+ {
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/specificParent.qml"_s));
+
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
+
+ QCOMPARE(rootObject->property("a").toReal(), 77.0);
+ }
}
-void tst_QmlCppCodegen::throwObjectName()
+void tst_QmlCppCodegen::popContextAfterRet()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/throwObjectName.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/popContextAfterRet.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
-
- QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/throwObjectName.qml:5:5: ouch");
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QVERIFY(o->objectName().isEmpty());
+ QVERIFY(o);
+
+ QCOMPARE(o->objectName(), QString());
+ o->setProperty("stackViewDepth", 1);
+ QCOMPARE(o->objectName(), u"backgroundImage"_s);
+ o->setProperty("stackViewDepth", 2);
+ QCOMPARE(o->objectName(), u"backgroundBlur"_s);
+ o->setProperty("stackViewDepth", 1);
+ QCOMPARE(o->objectName(), u"backgroundImage"_s);
}
-void tst_QmlCppCodegen::javaScriptArgument()
+void tst_QmlCppCodegen::prefixedType()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/javaScriptArgument.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ // We need to add an import path here because we cannot namespace the implicit import.
+ // The implicit import is what we use for all the other tests, even if we explicitly
+ // import TestTypes. That is because the TestTypes module is in a subdirectory "data".
+ engine.addImportPath(u":/"_s);
+
+ const QUrl document(u"qrc:/qt/qml/TestTypes/prefixedMetaType.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QVERIFY(o);
- QCOMPARE(o->property("a").toDouble(), 4.0);
- QCOMPARE(o->property("b").toDouble(), 9.0);
- QCOMPARE(o->property("c").toString(), u"5t-1"_s);
- QCOMPARE(o->property("d").toString(), u"9"_s);
- QCOMPARE(o->property("e").toString(), u"10"_s);
- QCOMPARE(o->property("f").toString(), u"-10"_s);
+ QCOMPARE(o->property("state").toInt(), 2);
+ QVERIFY(qvariant_cast<QObject *>(o->property("a")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("b")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("c")) == nullptr);
- const QStringList scales {
- "0 ", "1 ", "10 ", "100 ", "1000 ", "9.77k", "97.7k", "977k", "9.54M", "95.4M", "954M",
- "9.31G", "93.1G", "931G", "9.09T", "-1 ", "-10 ", "-100 ", "-1000 ", "-9.77k", "-97.7k",
- "-977k", "-9.54M", "-95.4M", "-954M", "-9.31G", "-93.1G", "-931G", "-9.09T"
- };
+ QVERIFY(qvariant_cast<QObject *>(o->property("d")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("e")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("f")) == nullptr);
- QCOMPARE(o->property("scales").value<QStringList>(), scales);
+ QVERIFY(qvariant_cast<QObject *>(o->property("g")) != nullptr);
+ QVERIFY(qvariant_cast<QObject *>(o->property("h")) != nullptr);
- double thing = 12.0;
- QString result;
- QMetaObject::invokeMethod(
- o.data(), "forwardArg", Q_RETURN_ARG(QString, result), Q_ARG(double, thing));
- QCOMPARE(result, u"12 ");
+ QCOMPARE(o->property("countG").toInt(), 11);
+ QCOMPARE(o->property("countH").toInt(), 11);
}
-void tst_QmlCppCodegen::translation()
+void tst_QmlCppCodegen::propertyOfParent()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/translation.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/RootWithoutId.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
- QCOMPARE(o->property("translate2"), u"s"_s);
- QCOMPARE(o->property("translate3"), u"s"_s);
- QCOMPARE(o->property("translate4"), u"s"_s);
+ QObject *child = qmlContext(object.data())->objectForName(u"item"_s);
- QCOMPARE(o->property("translateNoop2"), u"s"_s);
- QCOMPARE(o->property("translateNoop3"), u"s"_s);
+ bool expected = false;
- QCOMPARE(o->property("tr1"), u"s"_s);
- QCOMPARE(o->property("tr2"), u"s"_s);
- QCOMPARE(o->property("tr3"), u"s"_s);
+ for (int i = 0; i < 3; ++i) {
+ const QVariant foo = object->property("foo");
+ QCOMPARE(foo.metaType(), QMetaType::fromType<bool>());
+ QCOMPARE(foo.toBool(), expected);
- QCOMPARE(o->property("trNoop1"), u"s"_s);
- QCOMPARE(o->property("trNoop2"), u"s"_s);
+ const QVariant bar = object->property("bar");
+ QCOMPARE(bar.metaType(), QMetaType::fromType<bool>());
+ QCOMPARE(bar.toBool(), expected);
- QCOMPARE(o->property("trId1"), u"s"_s);
- QCOMPARE(o->property("trId2"), u"s"_s);
+ const QVariant visible = child->property("visible");
+ QCOMPARE(visible.metaType(), QMetaType::fromType<bool>());
+ QCOMPARE(visible.toBool(), expected);
- QCOMPARE(o->property("trIdNoop1"), u"s"_s);
+ expected = !expected;
+ object->setProperty("foo", expected);
+ }
}
-void tst_QmlCppCodegen::stringArg()
+void tst_QmlCppCodegen::reduceWithNullThis()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringArg.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/reduceWithNullThis.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- QCOMPARE(o->property("stringArg"), u"a foozly thing"_s);
- QCOMPARE(o->property("falseArg"), u"a 0 thing"_s);
- QCOMPARE(o->property("trueArg"), u"a 1 thing"_s);
- QCOMPARE(o->property("zeroArg"), u"a 0 thing"_s);
- QCOMPARE(o->property("intArg"), u"a 11 thing"_s);
- QCOMPARE(o->property("realArg"), u"a 12.25 thing"_s);
+ QCOMPARE(object->property("preferredHeight").toDouble(), 28.0);
+ QCOMPARE(object->property("preferredHeight2").toDouble(), 28.0);
}
-void tst_QmlCppCodegen::conversionDecrement()
+void tst_QmlCppCodegen::readEnumFromInstance()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/conversionDecrement.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ const QString url = u"qrc:/qt/qml/TestTypes/readEnumFromInstance.qml"_s;
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QQmlComponent component(&engine, QUrl(url));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
- QCOMPARE(o->property("currentPageIndex").toInt(), 0);
- o->setProperty("pages", 5);
- QCOMPARE(o->property("currentPageIndex").toInt(), 3);
- o->setProperty("pages", 4);
- QCOMPARE(o->property("currentPageIndex").toInt(), 0);
- o->setProperty("pages", 6);
- QCOMPARE(o->property("currentPageIndex").toInt(), 4);
- o->setProperty("pages", 60);
- QCOMPARE(o->property("currentPageIndex").toInt(), 3);
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + ":7:5: Unable to assign [undefined] to int"_L1));
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("priority"), QVariant::fromValue<int>(0));
+ QCOMPARE(object->property("prop2"), QVariant::fromValue<int>(1));
+ QCOMPARE(object->property("priorityIsVeryHigh"), QVariant::fromValue<bool>(false));
+
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + ":13: Error: Cannot assign [undefined] to int"_L1));
+
+ int result = 0;
+ QMetaObject::invokeMethod(object.data(), "cyclePriority", Q_RETURN_ARG(int, result));
+ QCOMPARE(result, 0);
}
-void tst_QmlCppCodegen::unstoredUndefined()
+void tst_QmlCppCodegen::readonlyListProperty()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unstoredUndefined.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QCOMPARE(o->objectName(), u"NaN"_s);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/readonlyListProperty.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("l").toInt(), 4);
+}
+
+void tst_QmlCppCodegen::registerElimination()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/registerelimination.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ // Increment of 23 hits both 0 and 460
+ for (int input = -23; input < 700; input += 23) {
+ object->setProperty("input", input);
+ if (input <= 0 || input >= 460)
+ QCOMPARE(object->property("output").toInt(), 459);
+ else
+ QCOMPARE(object->property("output").toInt(), input);
+ }
}
void tst_QmlCppCodegen::registerPropagation()
@@ -2431,784 +4139,989 @@ void tst_QmlCppCodegen::registerPropagation()
QCOMPARE(undefined, u"undefined"_s);
}
-void tst_QmlCppCodegen::argumentConversion()
+void tst_QmlCppCodegen::renameAdjust()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/argumentConversion.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/renameAdjust.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- auto checkNaN = [&](const char *propName) {
- const QVariant prop = o->property(propName);
- QCOMPARE(prop.metaType(), QMetaType::fromType<double>());
- QVERIFY(qIsNaN(prop.toDouble()));
- };
+ QTest::ignoreMessage(QtDebugMsg, "success");
+ QTest::ignoreMessage(QtCriticalMsg, "failed 10 11");
- checkNaN("a");
- checkNaN("b");
- checkNaN("e");
-
- QCOMPARE(o->property("c").toDouble(), 3.0);
- QCOMPARE(o->property("d").toDouble(), -1.0);
- QCOMPARE(o->property("f").toDouble(), 10.0);
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
}
-void tst_QmlCppCodegen::badSequence()
+void tst_QmlCppCodegen::resettableProperty()
{
+ QFETCH(QString, url);
+
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/badSequence.qml"_s));
+ QQmlComponent c(&engine, QUrl(url));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
-
- Person *self = qobject_cast<Person *>(o.data());
- QVERIFY(self);
- QVERIFY(self->barzles().isEmpty());
- QVERIFY(self->cousins().isEmpty());
-
- Person *other = o->property("other").value<Person *>();
- QVERIFY(other);
- QVERIFY(other->barzles().isEmpty());
- QVERIFY(other->cousins().isEmpty());
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + u":10:5: Unable to assign [undefined] to double"_s));
- Barzle f1;
- Barzle f2;
- const QList<Barzle *> barzles { &f1, &f2 };
- const QList<Person *> cousins { self, other };
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- other->setBarzles(barzles);
- QCOMPARE(self->barzles(), barzles);
- QCOMPARE(self->property("l").toInt(), 2);
+ QCOMPARE(o->property("value").toDouble(), 999);
+ QMetaObject::invokeMethod(o.data(), "doReset");
+ QCOMPARE(o->property("value").toDouble(), 0);
- other->setCousins(cousins);
- QCOMPARE(self->cousins(), cousins);
- QCOMPARE(self->property("m").toInt(), 2);
+ o->setProperty("value", double(82));
+ QCOMPARE(o->property("value").toDouble(), 82);
+ QMetaObject::invokeMethod(o.data(), "doReset2");
+ QCOMPARE(o->property("value").toDouble(), 0);
- QQmlListProperty<Person> others
- = self->property("others").value<QQmlListProperty<Person>>();
- QCOMPARE(others.count(&others), 2);
- QCOMPARE(others.at(&others, 0), cousins[0]);
- QCOMPARE(others.at(&others, 1), cousins[1]);
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + u":18: Error: Cannot assign [undefined] to double"_s));
+ QCOMPARE(o->property("notResettable").toDouble(), 10);
+ QMetaObject::invokeMethod(o.data(), "doNotReset");
+ QCOMPARE(o->property("notResettable").toDouble(), 10);
+ QCOMPARE(o->property("notResettable2").toDouble(), 0); // not NaN
- QQmlListProperty<Person> momsCousins
- = self->property("momsCousins").value<QQmlListProperty<Person>>();
- QCOMPARE(momsCousins.count(&momsCousins), 2);
- QCOMPARE(momsCousins.at(&momsCousins, 0), cousins[0]);
- QCOMPARE(momsCousins.at(&momsCousins, 1), cousins[1]);
+ o->setObjectName(u"namename"_s);
+ QTest::ignoreMessage(
+ QtWarningMsg, qPrintable(url + u":22: Error: Cannot assign [undefined] to QString"_s));
+ QMetaObject::invokeMethod(o.data(), "aaa");
+ QCOMPARE(o->objectName(), u"namename"_s);
+}
- QQmlListProperty<Person> dadsCousins
- = self->property("dadsCousins").value<QQmlListProperty<Person>>();
- QCOMPARE(dadsCousins.count(&dadsCousins), 1);
- QCOMPARE(dadsCousins.at(&dadsCousins, 0), other);
+void tst_QmlCppCodegen::resettableProperty_data()
+{
+ QTest::addColumn<QString>("url");
+ QTest::addRow("object lookups") << u"qrc:/qt/qml/TestTypes/resettable.qml"_s;
+ QTest::addRow("fallback lookups") << u"qrc:/qt/qml/TestTypes/fallbackresettable.qml"_s;
}
-void tst_QmlCppCodegen::enumLookup()
+void tst_QmlCppCodegen::returnAfterReject()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumLookup.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/returnAfterReject.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
-
- QCOMPARE(o->property("ready").toBool(), true);
+ QVERIFY(o);
+ QCOMPARE(o->property("bar").toInt(), 123);
}
-void tst_QmlCppCodegen::trivialSignalHandler()
+void tst_QmlCppCodegen::revisions()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/trivialSignalHandler.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/revisions.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(o->property("a").toString(), u"no"_s);
- QCOMPARE(o->property("b").toInt(), -1);
- QCOMPARE(o->property("b").toDouble(), -1.0);
+ QCOMPARE(o->property("delayed").toBool(), true);
+ QCOMPARE(o->property("gotten").toInt(), 5);
+}
- o->setObjectName(u"yes"_s);
- QCOMPARE(o->property("a").toString(), u"yes"_s);
- QCOMPARE(o->property("b").toInt(), 5);
- QCOMPARE(o->property("c").toDouble(), 2.5);
+void tst_QmlCppCodegen::scopeIdLookup()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/scopeIdLookup.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("objectName").toString(), u"outer"_s);
}
-void tst_QmlCppCodegen::stringToByteArray()
+void tst_QmlCppCodegen::scopeObjectDestruction()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringToByteArray.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/fileDialog.qml"_s));
- Person *person = qobject_cast<Person *>(o.data());
- QVERIFY(person);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
- QCOMPARE(person->dataBindable().value(), QByteArray("some data"));
- QCOMPARE(person->name(), u"some data"_s);
+ QObject *dialog = rootObject->property("dialog").value<QObject *>();
+ QVERIFY(dialog);
+
+ // We cannot check the warning messages. The AOT compiled code complains about reading the
+ // "parent" property of an object scheduled for deletion. The runtime silently returns undefined
+ // at that point and then complains about not being able to read a property on undefined.
+
+ // Doesn't crash, even though it triggers bindings on scope objects scheduled for deletion.
+ QMetaObject::invokeMethod(dialog, "open");
}
-void tst_QmlCppCodegen::listPropertyAsModel()
+void tst_QmlCppCodegen::scopeVsObject()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listPropertyAsModel.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
-
- QQmlListReference children(o.data(), "children");
- QCOMPARE(children.count(), 5);
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/scopeVsObject.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("objectName").toString(), u"foobar"_s);
}
-void tst_QmlCppCodegen::notNotString()
+void tst_QmlCppCodegen::scopedEnum()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/notNotString.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
+ const QString url = u"qrc:/qt/qml/TestTypes/scopedEnum.qml"_s;
+ QQmlComponent component(&engine, QUrl(url));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
- QCOMPARE(o->property("notNotString").value<bool>(), false);
- o->setObjectName(u"a"_s);
- QCOMPARE(o->property("notNotString").value<bool>(), true);
-}
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url + u":6:5: Unable to assign [undefined] to int"_s));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url + u":8: TypeError: Cannot read property 'C' of undefined"_s));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url + u":14: TypeError: Cannot read property 'C' of undefined"_s));
-template<typename T>
-QString toOperand(double arg);
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("good").toInt(), 27);
+ QCOMPARE(object->property("bad").toInt(), 0);
+ QCOMPARE(object->property("wrong").toInt(), 0);
+ QCOMPARE(object->property("right").toInt(), 7);
-template<>
-QString toOperand<double>(double arg)
-{
- if (qIsNull(arg))
- return std::signbit(arg) ? QStringLiteral("(-0)") : QStringLiteral("(0)");
+ QCOMPARE(object->property("notgood").toInt(), 26);
+ QCOMPARE(object->property("notbad").toInt(), 26);
+ QCOMPARE(object->property("notwrong").toInt(), 0);
+ QCOMPARE(object->property("notright").toInt(), 6);
- return u'(' + QJSPrimitiveValue(arg).toString() + u')';
+ QCOMPARE(object->property("passable").toInt(), 2);
+ QCOMPARE(object->property("wild").toInt(), 1);
}
-template<>
-QString toOperand<int>(double arg)
+void tst_QmlCppCodegen::sequenceToIterable()
{
- const int iArg = QJSPrimitiveValue(arg).toInteger();
- return u'(' + QJSPrimitiveValue(iArg).toString() + u')';
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/sequenceToIterable.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("c").toInt(), 11);
+
+ QQmlListReference children(object.data(), "children");
+ QCOMPARE(children.count(), 11);
+ static const QRegularExpression name("Entry\\(0x[0-9a-f]+, \"Item ([0-9])\"\\): ([0-9])");
+ for (int i = 0; i < 10; ++i) {
+ const auto match = name.match(children.at(i)->objectName());
+ QVERIFY(match.hasMatch());
+ QCOMPARE(match.captured(1), QString::number(i));
+ }
}
-template<>
-QString toOperand<bool>(double arg)
+void tst_QmlCppCodegen::setLookupConversion()
{
- const bool bArg = QJSPrimitiveValue(arg).toBoolean();
- return u'(' + QJSPrimitiveValue(bArg).toString() + u')';
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/setLookupConversion.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(o->objectName().isEmpty());
+ QMetaObject::invokeMethod(o.data(), "t");
+ QCOMPARE(o->objectName(), u"a"_s);
+ QCOMPARE(o->property("value").toInt(), 9);
}
-template<typename T1, typename T2>
-double jsEval(double arg1, double arg2, const QString &op, QJSEngine *engine)
+void tst_QmlCppCodegen::setLookupOriginalScope()
{
- auto evalBinary = [&](const QString &jsOp) {
- return engine->evaluate(toOperand<T1>(arg1) + jsOp + toOperand<T2>(arg2)).toNumber();
- };
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/setLookupOriginalScope.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- auto evalBinaryConst = [&](const QString &jsOp) {
- return engine->evaluate(toOperand<T1>(arg1) + jsOp + u'9').toNumber();
- };
+ QObject *v = o->property("variable").value<QObject *>();
+ QCOMPARE(v->property("value").toInt(), 0);
- auto evalUnary = [&](const QString &jsOp) {
- return engine->evaluate(jsOp + toOperand<T1>(arg1)).toNumber();
- };
+ QMetaObject::invokeMethod(o.data(), "trigger");
+ QObject *edit = o->property("edit").value<QObject *>();
+ QVERIFY(edit);
+ QCOMPARE(edit->property("myOutput").value<QObject *>(), v);
+ QCOMPARE(v->property("value").toInt(), 55);
+}
- auto evalInPlace = [&](const QString &jsOp) {
- return engine->evaluate(
- u"(function() {var a = "_s + toOperand<T1>(arg1)+ u"; return "_s
- + jsOp + u"a;})()"_s).toNumber();
- };
+void tst_QmlCppCodegen::shadowedAsCasts()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/shadowedAsCasts.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY(!obj.isNull());
+
+ QObject *shadowed1 = obj->property("shadowed1").value<QObject *>();
+ QVERIFY(shadowed1);
+ QVERIFY(shadowed1->objectName().isEmpty());
+ const QVariant name1 = shadowed1->property("objectName");
+ QCOMPARE(name1.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(name1.toInt(), 43);
+
+ QObject *shadowed2 = obj->property("shadowed2").value<QObject *>();
+ QVERIFY(shadowed2);
+ QVERIFY(shadowed2->objectName().isEmpty());
+ const QVariant name2 = shadowed2->property("objectName");
+ QCOMPARE(name2.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(name2.toInt(), 42);
+
+ QObject *shadowed3 = obj->property("shadowed3").value<QObject *>();
+ QVERIFY(shadowed3);
+ QVERIFY(shadowed3->objectName().isEmpty());
+ const QVariant name3 = shadowed3->property("objectName");
+ QCOMPARE(name3.metaType(), QMetaType::fromType<double>());
+ QCOMPARE(name3.toDouble(), 41.0);
+}
+
+void tst_QmlCppCodegen::shadowedMethod()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/shadowedMethod.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("athing"), QVariant::fromValue<bool>(false));
+ QCOMPARE(o->property("bthing"), QVariant::fromValue(u"b"_s));
+ QCOMPARE(o->property("cthing"), QVariant::fromValue(u"c"_s));
+}
- if (op == u"unot")
- return evalUnary(u"!"_s);
- if (op == u"uplus")
- return evalUnary(u"+"_s);
- if (op == u"uminus")
- return evalUnary(u"-"_s);
- if (op == u"ucompl")
- return evalUnary(u"~"_s);
+void tst_QmlCppCodegen::shadowedPrimitiveCmpEqNull()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/shadowedPrimitiveCmpEqNull.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
- if (op == u"increment")
- return evalInPlace(u"++"_s);
- if (op == u"decrement")
- return evalInPlace(u"--"_s);
+void tst_QmlCppCodegen::shifts()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/shifts.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- if (op == u"add")
- return evalBinary(u"+"_s);
- if (op == u"sub")
- return evalBinary(u"-"_s);
- if (op == u"mul")
- return evalBinary(u"*"_s);
- if (op == u"div")
- return evalBinary(u"/"_s);
- if (op == u"exp")
- return evalBinary(u"**"_s);
- if (op == u"mod")
- return evalBinary(u"%"_s);
+ QCOMPARE(object->property("a").toInt(), 9728);
+ QCOMPARE(object->property("b").toInt(), 4864);
+ QCOMPARE(object->property("c").toInt(), 19448);
+ QCOMPARE(object->property("d").toInt(), 9731);
+ QCOMPARE(object->property("e").toInt(), 0);
+}
- if (op == u"bitAnd")
- return evalBinary(u"&"_s);
- if (op == u"bitOr")
- return evalBinary(u"|"_s);
- if (op == u"bitXor")
- return evalBinary(u"^"_s);
+void tst_QmlCppCodegen::signalHandler()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signal.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->objectName(), QString());
+ QCOMPARE(object->property("ff").toInt(), 4);
- if (op == u"bitAndConst")
- return evalBinaryConst(u"&"_s);
- if (op == u"bitOrConst")
- return evalBinaryConst(u"|"_s);
- if (op == u"bitXorConst")
- return evalBinaryConst(u"^"_s);
+ object->setObjectName(u"foo"_s);
+ QCOMPARE(object->property("ff").toInt(), 12);
+}
- if (op == u"ushr")
- return evalBinary(u">>>"_s);
- if (op == u"shr")
- return evalBinary(u">>"_s);
- if (op == u"shl")
- return evalBinary(u"<<"_s);
+void tst_QmlCppCodegen::signalIndexMismatch()
+{
+ QQmlEngine engine;
- if (op == u"ushrConst")
- return evalBinaryConst(u">>>"_s);
- if (op == u"shrConst")
- return evalBinaryConst(u">>"_s);
- if (op == u"shlConst")
- return evalBinaryConst(u"<<"_s);
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signalIndexMismatch.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- qDebug() << op;
- Q_UNREACHABLE_RETURN(0);
+ QScopedPointer<QObject> item(c1.create());
+ const auto visualIndexBeforeMoveList = item->property("visualIndexBeforeMove").toList();
+ const auto visualIndexAfterMoveList = item->property("visualIndexAfterMove").toList();
+
+ QCOMPARE(visualIndexBeforeMoveList, QList<QVariant>({ 0, 1, 2 }));
+ QCOMPARE(visualIndexAfterMoveList, QList<QVariant>({ 0, 1, 2 }));
}
-void tst_QmlCppCodegen::mathOperations()
+void tst_QmlCppCodegen::signalsWithLists()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/mathOperations.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signalsWithLists.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- const QMetaObject *metaObject = o->metaObject();
+ QVariantList varlist = o->property("varlist").toList();
+ QCOMPARE(varlist.size(), 5);
+ QCOMPARE(varlist[0], QVariant::fromValue(1));
+ QCOMPARE(varlist[1], QVariant::fromValue(u"foo"_s));
+ QCOMPARE(varlist[2], QVariant::fromValue(o.data()));
+ QCOMPARE(varlist[3], QVariant());
+ QCOMPARE(varlist[4], QVariant::fromValue(true));
- char t1;
- char t2;
- QString name;
- const auto guard = qScopeGuard([&]() {
- if (QTest::currentTestFailed()) {
- qDebug() << t1 << t2 << name << "failed on:";
- qDebug() << "doubles" << o->property("a").toDouble() << o->property("b").toDouble();
- qDebug() << "integers" << o->property("ia").toInt() << o->property("ib").toInt();
- qDebug() << "booleans" << o->property("ba").toBool() << o->property("bb").toBool();
- }
- });
+ QQmlListProperty<QObject> objlist = o->property("objlist").value<QQmlListProperty<QObject>>();
+ QCOMPARE(objlist.count(&objlist), 3);
+ QCOMPARE(objlist.at(&objlist, 0), o.data());
+ QCOMPARE(objlist.at(&objlist, 1), nullptr);
+ QCOMPARE(objlist.at(&objlist, 2), o.data());
- for (double a : numbers) {
- for (double b : numbers) {
- o->setProperty("a", a);
- o->setProperty("b", b);
- for (int i = 0, end = metaObject->propertyCount(); i != end; ++i) {
- const QMetaProperty prop = metaObject->property(i);
- const QByteArray propName = prop.name();
+ QCOMPARE(o->property("happening").toInt(), 0);
+ o->metaObject()->invokeMethod(o.data(), "sendSignals");
+ QCOMPARE(o->property("happening").toInt(), 8);
+}
- if (propName.size() < 3 || propName == "objectName")
- continue;
+void tst_QmlCppCodegen::signatureIgnored()
+{
+ QQmlEngine engine;
- t1 = propName[0];
- t2 = propName[1];
- name = QString::fromUtf8(propName.mid(2));
+ QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signatureIgnored.qml"_s));
+ QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- double expected;
+ QScopedPointer<QObject> ignored(c1.create());
+ QCOMPARE(ignored->property("l").toInt(), 5);
+ QCOMPARE(ignored->property("m").toInt(), 77);
+ QCOMPARE(ignored->property("n").toInt(), 67);
+}
- switch (t2) {
- case 'd':
- case '_':
- switch (t1) {
- case 'd':
- expected = jsEval<double, double>(a, b, name, &engine);
- break;
- case 'i':
- expected = jsEval<int, double>(a, b, name, &engine);
- break;
- case 'b':
- expected = jsEval<bool, double>(a, b, name, &engine);
- break;
- }
- break;
- case 'i':
- switch (t1) {
- case 'd':
- expected = jsEval<double, int>(a, b, name, &engine);
- break;
- case 'i':
- expected = jsEval<int, int>(a, b, name, &engine);
- break;
- case 'b':
- expected = jsEval<bool, int>(a, b, name, &engine);
- break;
- }
- break;
- case 'b':
- switch (t1) {
- case 'd':
- expected = jsEval<double, bool>(a, b, name, &engine);
- break;
- case 'i':
- expected = jsEval<int, bool>(a, b, name, &engine);
- break;
- case 'b':
- expected = jsEval<bool, bool>(a, b, name, &engine);
- break;
- }
- break;
- }
+void tst_QmlCppCodegen::simpleBinding()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/Test.qml"_s));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY2(!object.isNull(), component.errorString().toUtf8().constData());
+ QCOMPARE(object->property("foo").toInt(), int(3));
- const double result = prop.read(o.data()).toDouble();
- QCOMPARE(result, expected);
- }
- }
+ {
+ CppBaseClass *base = qobject_cast<CppBaseClass *>(object.data());
+ Q_ASSERT(base);
+ QVERIFY(!base->cppProp.hasBinding());
+ QCOMPARE(base->cppProp.value(), 7);
+ QVERIFY(base->cppProp2.hasBinding());
+ QCOMPARE(base->cppProp2.value(), 14);
+ base->cppProp.setValue(9);
+ QCOMPARE(base->cppProp.value(), 9);
+ QCOMPARE(base->cppProp2.value(), 18);
}
}
-void tst_QmlCppCodegen::inaccessibleProperty()
+void tst_QmlCppCodegen::storeElementSideEffects()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/versionmismatch.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/storeElementSideEffects.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(o->property("c").toInt(), 5);
+ const QJSValue prop = o->property("myItem").value<QJSValue>();
+ QVERIFY(prop.isArray());
+ QCOMPARE(prop.property(0).toInt(), 10);
}
-void tst_QmlCppCodegen::typePropagationLoop()
+void tst_QmlCppCodegen::storeMetaEnum()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/typePropagationLoop.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/StoreMetaEnum.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(o->property("j").toInt(), 3);
+ QCOMPARE(o->property("bar").toInt(), 0);
+ QCOMPARE(o->property("baz").toInt(), 1);
}
-void tst_QmlCppCodegen::signatureIgnored()
+void tst_QmlCppCodegen::stringArg()
{
QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringArg.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signatureIgnored.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
-
- QScopedPointer<QObject> ignored(c1.create());
- QCOMPARE(ignored->property("l").toInt(), 5);
- QCOMPARE(ignored->property("m").toInt(), 77);
- QCOMPARE(ignored->property("n").toInt(), 67);
+ QCOMPARE(o->property("stringArg"), u"a foozly thing"_s);
+ QCOMPARE(o->property("falseArg"), u"a 0 thing"_s);
+ QCOMPARE(o->property("trueArg"), u"a 1 thing"_s);
+ QCOMPARE(o->property("zeroArg"), u"a 0 thing"_s);
+ QCOMPARE(o->property("intArg"), u"a 11 thing"_s);
+ QCOMPARE(o->property("realArg"), u"a 12.25 thing"_s);
}
-void tst_QmlCppCodegen::listAsArgument()
+void tst_QmlCppCodegen::stringLength()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringLength.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("stringLength").toInt(), 8);
+}
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/listAsArgument.qml"_s));
+void tst_QmlCppCodegen::stringToByteArray()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/stringToByteArray.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
-
QScopedPointer<QObject> o(c.create());
- QCOMPARE(o->property("i").toInt(), 4);
- QCOMPARE(o->property("j").toInt(), 2);
- QCOMPARE(o->property("i1").toInt(), 2);
- QCOMPARE(o->property("i2").toInt(), 4);
- QCOMPARE(o->property("d").value<QObject *>()->objectName(), u"this one"_s);
- int singleInt = 0;
- QList<int> moreInts;
- QMetaObject::invokeMethod(o.data(), "returnInts1", Q_RETURN_ARG(QList<int>, moreInts));
- QCOMPARE(moreInts, QList<int>({5, 4, 3, 2, 1}));
- QMetaObject::invokeMethod(o.data(), "selectSecondInt", Q_RETURN_ARG(int, singleInt), Q_ARG(QList<int>, moreInts));
- QCOMPARE(singleInt, 4);
+ Person *person = qobject_cast<Person *>(o.data());
+ QVERIFY(person);
+
+ QCOMPARE(person->dataBindable().value(), QByteArray("some data"));
+ QCOMPARE(person->name(), u"some data"_s);
}
-void tst_QmlCppCodegen::letAndConst()
+void tst_QmlCppCodegen::structuredValueType()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/letAndConst.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/structuredValueType.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"ab"_s);
+
+ QCOMPARE(o->property("r").value<QRectF>(), QRectF(1, 2, 3, 4));
+ QCOMPARE(o->property("r2").value<QRectF>(), QRectF(42, 0, 0, 0));
+
+ WeatherModelUrl w;
+ w.setStrings(QStringList({"one", "two", "three"}));
+
+ QCOMPARE(o->property("w").value<WeatherModelUrl>(), w);
}
-void tst_QmlCppCodegen::signalIndexMismatch()
+void tst_QmlCppCodegen::testIsnan()
{
QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/isnan.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/signalIndexMismatch.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+ QCOMPARE(o->property("good").toDouble(), 10.1);
+ QVERIFY(qIsNaN(o->property("bad").toDouble()));
- QScopedPointer<QObject> item(c1.create());
- const auto visualIndexBeforeMoveList = item->property("visualIndexBeforeMove").toList();
- const auto visualIndexAfterMoveList = item->property("visualIndexAfterMove").toList();
+ const QVariant a = o->property("a");
+ QCOMPARE(a.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(!a.toBool());
- QCOMPARE(visualIndexBeforeMoveList, QList<QVariant>({ 0, 1, 2 }));
- QCOMPARE(visualIndexAfterMoveList, QList<QVariant>({ 0, 1, 2 }));
+ const QVariant b = o->property("b");
+ QCOMPARE(b.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(b.toBool());
}
-void tst_QmlCppCodegen::callWithSpread()
+void tst_QmlCppCodegen::thisObject()
{
- QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/callWithSpread.qml"_s));
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/thisObject.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QTest::ignoreMessage(QtCriticalMsg, "That is great!");
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
+ QCOMPARE(o->property("warned").value<QObject *>(), o.data());
}
-void tst_QmlCppCodegen::nullComparison()
+void tst_QmlCppCodegen::throwObjectName()
{
QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/throwObjectName.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/nullComparison.qml"_s));
+ QTest::ignoreMessage(QtWarningMsg, "qrc:/qt/qml/TestTypes/throwObjectName.qml:5:5: ouch");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(o->objectName().isEmpty());
+}
+
+void tst_QmlCppCodegen::topLevelComponent()
+{
+ // TODO: Once we stop accepting top level Component elements, this test can be removed.
+
+ QQmlEngine e;
+
+ const QUrl url(u"qrc:/qt/qml/TestTypes/topLevelComponent.qml"_s);
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + u":4:1: Using a Component as the root of a QML document "
+ "is deprecated: types defined in qml documents are "
+ "automatically wrapped into Components when needed."_s));
+
+ QQmlComponent c(&e, url);
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
- QCOMPARE(o->property("v").toInt(), 1);
- QCOMPARE(o->property("w").toInt(), 3);
- QCOMPARE(o->property("x").toInt(), 1);
- QCOMPARE(o->property("y").toInt(), 5);
+ QQmlComponent *inner = qobject_cast<QQmlComponent *>(o.data());
+ QVERIFY(inner);
+
+ QScopedPointer<QObject> o2(inner->create());
+ QCOMPARE(o2->objectName(), u"foo"_s);
}
-void tst_QmlCppCodegen::consoleObject()
+void tst_QmlCppCodegen::translation()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/consoleObject.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/translation.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- QTest::ignoreMessage(QtDebugMsg, "b 4.55");
- QTest::ignoreMessage(QtDebugMsg, "b 4.55");
- QTest::ignoreMessage(QtInfoMsg, "b 4.55");
- QTest::ignoreMessage(QtWarningMsg, "b 4.55");
- QTest::ignoreMessage(QtCriticalMsg, "b 4.55");
+ QCOMPARE(o->property("translate2"), u"s"_s);
+ QCOMPARE(o->property("translate3"), u"s"_s);
+ QCOMPARE(o->property("translate4"), u"s"_s);
- // Unfortunately we cannot check the logging category with QTest::ignoreMessage
- QTest::ignoreMessage(QtDebugMsg, "b 4.55");
- QTest::ignoreMessage(QtDebugMsg, "b 4.55");
- QTest::ignoreMessage(QtInfoMsg, "b 4.55");
- QTest::ignoreMessage(QtWarningMsg, "b 4.55");
- QTest::ignoreMessage(QtCriticalMsg, "b 4.55");
+ QCOMPARE(o->property("translateNoop2"), u"s"_s);
+ QCOMPARE(o->property("translateNoop3"), u"s"_s);
- const QRegularExpression re(u"QQmlComponentAttached\\(0x[0-9a-f]+\\) b 4\\.55"_s);
- QTest::ignoreMessage(QtDebugMsg, re);
- QTest::ignoreMessage(QtDebugMsg, re);
- QTest::ignoreMessage(QtInfoMsg, re);
- QTest::ignoreMessage(QtWarningMsg, re);
- QTest::ignoreMessage(QtCriticalMsg, re);
+ QCOMPARE(o->property("tr1"), u"s"_s);
+ QCOMPARE(o->property("tr2"), u"s"_s);
+ QCOMPARE(o->property("tr3"), u"s"_s);
- QTest::ignoreMessage(QtDebugMsg, "a undefined b false null 7");
- QTest::ignoreMessage(QtDebugMsg, "");
- QTest::ignoreMessage(QtDebugMsg, "4");
- QTest::ignoreMessage(QtDebugMsg, "");
+ QCOMPARE(o->property("trNoop1"), u"s"_s);
+ QCOMPARE(o->property("trNoop2"), u"s"_s);
- const QRegularExpression re2(u"QQmlComponentAttached\\(0x[0-9a-f]+\\)"_s);
- QTest::ignoreMessage(QtDebugMsg, re2);
+ QCOMPARE(o->property("trId1"), u"s"_s);
+ QCOMPARE(o->property("trId2"), u"s"_s);
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QCOMPARE(o->property("trIdNoop1"), u"s"_s);
}
-void tst_QmlCppCodegen::multiForeign()
+void tst_QmlCppCodegen::trigraphs()
{
- QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/multiforeign.qml"_s));
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/trigraphs.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"not here and not there"_s);
+ QCOMPARE(o->objectName(), u"?""?= ?""?/ ?""?' ?""?( ?""?) ?""?! ?""?< ?""?> ?""?-"_s);
}
-void tst_QmlCppCodegen::namespaceWithEnum()
+void tst_QmlCppCodegen::trivialSignalHandler()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/namespaceWithEnum.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/trivialSignalHandler.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->property("i").toInt(), 2);
+
+ QCOMPARE(o->property("a").toString(), u"no"_s);
+ QCOMPARE(o->property("b").toInt(), -1);
+ QCOMPARE(o->property("b").toDouble(), -1.0);
+
+ o->setObjectName(u"yes"_s);
+ QCOMPARE(o->property("a").toString(), u"yes"_s);
+ QCOMPARE(o->property("b").toInt(), 5);
+ QCOMPARE(o->property("c").toDouble(), 2.5);
}
-void tst_QmlCppCodegen::enumProblems()
+void tst_QmlCppCodegen::typePropagationLoop()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumProblems.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> outer(c.create());
- QVERIFY(!outer.isNull());
- QObject *inner = outer->property("o").value<QObject *>();
- QVERIFY(inner);
- Foo *bar = inner->property("bar").value<Foo *>();
- QVERIFY(bar);
- QCOMPARE(bar->type(), Foo::Component);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/typePropagationLoop.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
- Foo *fighter = inner->property("fighter").value<Foo *>();
- QVERIFY(fighter);
- QCOMPARE(fighter->type(), Foo::Fighter);
+ QCOMPARE(o->property("j").toInt(), 3);
}
-void tst_QmlCppCodegen::enumConversion()
+void tst_QmlCppCodegen::typePropertyClash()
{
QQmlEngine engine;
-
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/enumConversion.qml"_s));
+ engine.rootContext()->setContextProperty(u"size"_s, 5);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/typePropertyClash.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), u"Size: 5"_s);
+}
+void tst_QmlCppCodegen::typedArray()
+{
+ QQmlEngine engine;
+ const QUrl document(u"qrc:/qt/qml/TestTypes/typedArray.qml"_s);
+ QQmlComponent c(&engine, document);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(o);
- QCOMPARE(o->property("test").toInt(), 0x04);
- QCOMPARE(o->property("test_1").toBool(), true);
+ QDateTime date;
+ QVERIFY(qvariant_cast<QList<int>>(o->property("values2")).isEmpty());
+ QCOMPARE(qvariant_cast<QList<int>>(o->property("values3")),
+ QList<int>({1, 2, 3, 4}));
+ QCOMPARE(qvariant_cast<QList<QDateTime>>(o->property("values4")),
+ QList<QDateTime>({date, date, date}));
+ {
+ const QList<double> actual
+ = qvariant_cast<QList<double>>(o->property("values5"));
+ const QList<double> expected
+ = QList<double>({1, 2, 3.4, 30, std::numeric_limits<double>::quiet_NaN(), 0});
+ QCOMPARE(actual.size(), expected.size());
+ for (qsizetype i = 0, end = actual.size(); i != end; ++i) {
+ if (std::isnan(expected[i]))
+ QVERIFY(std::isnan(actual[i]));
+ else
+ QCOMPARE(actual[i], expected[i]);
+ }
+ }
+ date = QDateTime::currentDateTime();
+ o->setProperty("aDate", date);
+ QCOMPARE(qvariant_cast<QList<QDateTime>>(o->property("values4")),
+ QList<QDateTime>({date, date, date}));
+
+ QQmlListProperty<QObject> values6
+ = qvariant_cast<QQmlListProperty<QObject>>(o->property("values6"));
+ QCOMPARE(values6.count(&values6), 3);
+ for (int i = 0; i < 3; ++i)
+ QCOMPARE(values6.at(&values6, i), o.data());
+
+ QCOMPARE(o->property("inIntList").toInt(), 2);
+ QCOMPARE(qvariant_cast<QDateTime>(o->property("inDateList")), date);
+ QCOMPARE(o->property("inRealList").toDouble(), 30.0);
+ QCOMPARE(o->property("inCharList").toString(), QStringLiteral("f"));
+
+ const QMetaObject *metaObject = o->metaObject();
+ QMetaMethod method = metaObject->method(metaObject->indexOfMethod("stringAt10(QString)"));
+ QVERIFY(method.isValid());
+
+ // If LoadElement threw an exception the function would certainly return neither 10 nor 20.
+ int result = 0;
+ method.invoke(
+ o.data(), Q_RETURN_ARG(int, result), Q_ARG(QString, QStringLiteral("a")));
+ QCOMPARE(result, 10);
+ method.invoke(
+ o.data(), Q_RETURN_ARG(int, result), Q_ARG(QString, QStringLiteral("aaaaaaaaaaa")));
+ QCOMPARE(result, 20);
}
-void tst_QmlCppCodegen::storeElementSideEffects()
+void tst_QmlCppCodegen::undefinedResets()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/undefinedResets.qml"_s));
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/storeElementSideEffects.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
- QScopedPointer<QObject> o(c.create());
- QVERIFY(o);
+ Person *person = qobject_cast<Person *>(rootObject.data());
+ QVERIFY(person);
+ QCOMPARE(person->shoeSize(), 0);
+ QCOMPARE(person->name(), u"Marge"_s);
- const QJSValue prop = o->property("myItem").value<QJSValue>();
- QVERIFY(prop.isArray());
- QCOMPARE(prop.property(0).toInt(), 10);
-};
+ person->setShoeSize(11);
-void tst_QmlCppCodegen::ambiguousSignals()
+ QCOMPARE(person->shoeSize(), 11);
+ QCOMPARE(person->name(), u"Bart"_s);
+
+ person->setShoeSize(10);
+ QCOMPARE(person->shoeSize(), 10);
+ QCOMPARE(person->name(), u"Marge"_s);
+
+ person->setName(u"no one"_s);
+ QCOMPARE(person->name(), u"no one"_s);
+
+ person->setObjectName(u"the one"_s);
+ QCOMPARE(person->name(), u"Bart"_s);
+}
+
+void tst_QmlCppCodegen::undefinedToDouble()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ambiguousSignals.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/undefinedToDouble.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"tomorrow"_s);
- Person *p = qobject_cast<Person *>(o.data());
- QVERIFY(p);
- emit p->ambiguous(12);
- QCOMPARE(o->objectName(), u"12foo"_s);
- emit p->ambiguous();
- QCOMPARE(o->objectName(), u"9foo"_s);
+ const QVariant d = o->property("d");
+ QCOMPARE(d.metaType(), QMetaType::fromType<double>());
+ QVERIFY(std::isnan(d.toDouble()));
}
-void tst_QmlCppCodegen::fileImportsContainCxxTypes()
+void tst_QmlCppCodegen::unknownAttached()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/usingCxxTypesFromFileImports.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->objectName(), u"horst guenther"_s);
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unknownAttached.qml"_s));
+ QVERIFY(c.isError());
}
-void tst_QmlCppCodegen::lengthAccessArraySequenceCompat()
+void tst_QmlCppCodegen::unknownParameter()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/ArraySequenceLengthInterop.qml"_s));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unknownParameter.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QCOMPARE(object->property("cppProp").toInt(), 18);
+}
+
+void tst_QmlCppCodegen::unstoredUndefined()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unstoredUndefined.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->property("length").toInt(), 100);
+ QCOMPARE(o->objectName(), u"NaN"_s);
}
-static QList<QString> convertToStrings(const QList<int> &ints)
+void tst_QmlCppCodegen::unusedAttached()
{
- QList<QString> strings;
- for (int i : ints)
- strings.append(QString::number(i));
- return strings;
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/unusedAttached.qml"_s));
+ QVERIFY2(!component.isError(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+
+ const auto func = qmlAttachedPropertiesFunction(
+ object.data(), QMetaType::fromName("QQuickKeyNavigationAttached*").metaObject());
+ QObject *attached = qmlAttachedPropertiesObject(object.data(), func);
+ const QVariant prop = attached->property("priority");
+ QVERIFY(prop.isValid());
+ QCOMPARE(QByteArray(prop.metaType().name()), "QQuickKeyNavigationAttached::Priority");
+ bool ok = false;
+ QCOMPARE(prop.toInt(&ok), 0);
+ QVERIFY(ok);
}
-void tst_QmlCppCodegen::numbersInJsPrimitive()
+void tst_QmlCppCodegen::urlString()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/numbersInJsPrimitive.qml"_s));
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/urlString.qml"_s));
- const QList<int> zeroes = {0, 0, 0, 0};
- const QList<int> written = {39, 40, 41, 42};
- const QList<int> stored = {1334, 1335, 1336, 1337};
- QStringList asStrings(4);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> rootObject(component.create());
+ QVERIFY(rootObject);
- for (int i = 0; i < 4; ++i) {
- QMetaObject::invokeMethod(
- o.data(), "readValueAsString",
- Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ QCOMPARE(qvariant_cast<QUrl>(rootObject->property("c")), QUrl(u"http://dddddd.com"_s));
+ QCOMPARE(qvariant_cast<QUrl>(rootObject->property("d")), QUrl(u"http://aaaaaa.com"_s));
+ QCOMPARE(qvariant_cast<QUrl>(rootObject->property("e")), QUrl(u"http://a112233.de"_s));
+ QCOMPARE(rootObject->objectName(), QLatin1String("http://dddddd.com"));
+}
+
+void tst_QmlCppCodegen::valueTypeBehavior()
+{
+ QQmlEngine engine;
+
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeCopy.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'e'));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'f'));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("e").toDouble(), 45.0);
+ QCOMPARE(o->property("f").toDouble(), 1.0);
}
- QCOMPARE(asStrings, convertToStrings(zeroes));
- QMetaObject::invokeMethod(o.data(), "writeValues");
- for (int i = 0; i < 4; ++i) {
- QMetaObject::invokeMethod(
- o.data(), "readValueAsString",
- Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeReference.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'e'));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'f'));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(qIsNaN(o->property("e").toDouble()));
+ QCOMPARE(o->property("f").toDouble(), 5.0);
}
- QCOMPARE(asStrings, convertToStrings(written));
- QMetaObject::invokeMethod(o.data(), "storeValues");
- for (int i = 0; i < 4; ++i) {
- QMetaObject::invokeMethod(
- o.data(), "readValueAsString",
- Q_RETURN_ARG(QString, asStrings[i]), Q_ARG(int, i));
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeDefault.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'e'));
+ QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(url, 'f'));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QVERIFY(qIsNaN(o->property("e").toDouble()));
+ QCOMPARE(o->property("f").toDouble(), 5.0);
+ }
+
+ {
+ const QUrl url(u"qrc:/qt/qml/TestTypes/valueTypeCast.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("x"), 10);
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString()
+ + u":8: TypeError: Cannot read property 'x' of undefined"_s));
+ o->setProperty("v", QLatin1String("not a rect"));
+
+ // If the binding throws an exception, the value doesn't change.
+ QCOMPARE(o->property("x"), 10);
+
+ QCOMPARE(o->property("tv3"), 5);
+ QCOMPARE(o->property("tc3"), 5);
+ QCOMPARE(o->property("tc6"), QVariant());
+ QCOMPARE(o->property("tc7"), QVariant());
+ QCOMPARE(o->property("tc8"), 2);
+
+ // The default greeting is never applied because undefined can be coerced to string
+ QCOMPARE(o->property("greeting1"), QLatin1String("undefined"));
+ QCOMPARE(o->property("greeting2"), QLatin1String("Custom Greeting"));
}
- QCOMPARE(asStrings, convertToStrings(stored));
}
-void tst_QmlCppCodegen::infinitiesToInt()
+void tst_QmlCppCodegen::valueTypeLists()
{
QQmlEngine engine;
-
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/infinitiesToInt.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/valueTypeLists.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- const char *props[] = {"a", "b", "c"};
- for (const char *prop : props) {
- const QVariant i = o->property(prop);
- QCOMPARE(i.metaType(), QMetaType::fromType<int>());
- bool ok = false;
- QCOMPARE(i.toInt(&ok), 0);
- QVERIFY(ok);
- }
+ QCOMPARE(qvariant_cast<QRectF>(o->property("rectInBounds")), QRectF(1, 2, 3, 4));
+ QVERIFY(o->metaObject()->indexOfProperty("rectOutOfBounds") > 0);
+ QVERIFY(!o->property("rectOutOfBounds").isValid());
+
+ QCOMPARE(qvariant_cast<QString>(o->property("stringInBounds")), QStringLiteral("bbb"));
+ QVERIFY(o->metaObject()->indexOfProperty("stringOutOfBounds") > 0);
+ QVERIFY(!o->property("stringOutOfBounds").isValid());
+
+ QCOMPARE(qvariant_cast<int>(o->property("intInBounds")), 7);
+ QVERIFY(o->metaObject()->indexOfProperty("intOutOfBounds") > 0);
+ QVERIFY(!o->property("intOutOfBounds").isValid());
+
+ QCOMPARE(qvariant_cast<QString>(o->property("charInBounds")), QStringLiteral("d"));
+ QVERIFY(o->metaObject()->indexOfProperty("charOutOfBounds") > 0);
+ QVERIFY(!o->property("charOutOfBounds").isValid());
}
-void tst_QmlCppCodegen::equalityVarAndNonStorable()
+void tst_QmlCppCodegen::valueTypeProperty()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/valueTypeProperty.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityVarAndNonStorable.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
+ QFont font = qvariant_cast<QFont>(object->property("font"));
+ QCOMPARE(object->property("foo").toString(), font.family());
+ font.setFamily(u"Bar"_s);
+ object->setProperty("font", QVariant::fromValue(font));
+ QCOMPARE(object->property("foo").toString(), u"Bar"_s);
+}
- QScopedPointer<QObject> object(c1.create());
- QVERIFY(!object.isNull() && !c1.isError());
- QVERIFY(!object->property("aIsNull").toBool());
- QVERIFY(object->property("aIsNotNull").toBool());
- QVERIFY(object->property("aIsNotUndefined").toBool());
- QVERIFY(object->property("objectIsNotNull").toBool());
- QVERIFY(!object->property("typedArrayIsNull").toBool());
- QVERIFY(object->property("isUndefined").toBool());
- QVERIFY(!object->property("derivedIsNull").toBool());
+void tst_QmlCppCodegen::variantMapLookup()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/variantMapLookup.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("i"), 42);
+}
- QVERIFY(object->property("primitiveIsNull").toBool());
- QVERIFY(object->property("primitiveIsDefined").toBool());
- QVERIFY(object->property("primitiveIsUndefined").toBool());
+void tst_QmlCppCodegen::variantReturn()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, QUrl(u"qrc:/qt/qml/TestTypes/variantReturn.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QVERIFY(object->property("jsValueIsNull").toBool());
- QVERIFY(object->property("jsValueIsDefined").toBool());
- QVERIFY(object->property("jsValueIsUndefined").toBool());
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
- QVERIFY(object->property("nullVarIsUndefined").toBool());
- QVERIFY(object->property("nullIsUndefined").toBool());
- QVERIFY(object->property("nullVarIsNull").toBool());
- QVERIFY(object->property("nullIsNotUndefined").toBool());
-};
+ QObject *a = o->property("a").value<QObject *>();
+ QVERIFY(a);
+ const QVariant x = a->property("x");
+ const QMetaObject *meta = x.metaType().metaObject();
+ QVERIFY(meta);
+ const QMetaProperty property = meta->property(meta->indexOfProperty("timeIndex"));
+ QVERIFY(property.isValid());
+ const QVariant timeIndex = property.readOnGadget(x.data());
+ QCOMPARE(timeIndex.metaType(), QMetaType::fromType<qsizetype>());
+ QCOMPARE(timeIndex.value<qsizetype>(), qsizetype(1));
-void tst_QmlCppCodegen::equalityQObjects()
+ QObject *b = o->property("b").value<QObject *>();
+ QVERIFY(b);
+ QCOMPARE(b->property("z").toInt(), 2);
+}
+
+void tst_QmlCppCodegen::variantlist()
{
QQmlEngine engine;
- QQmlComponent c1(&engine, QUrl(u"qrc:/qt/qml/TestTypes/equalityQObjects.qml"_s));
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- QScopedPointer<QObject> object(c1.create());
- QVERIFY(!object.isNull() && !c1.isError());
-
- QVERIFY(object->property("derivedIsNotNull").toBool());
- QVERIFY(object->property("nullObjectIsNull").toBool());
- QVERIFY(object->property("nonNullObjectIsNotNull").toBool());
- QVERIFY(object->property("compareSameObjects").toBool());
- QVERIFY(object->property("compareDifferentObjects").toBool());
- QVERIFY(object->property("compareObjectWithNullObject").toBool());
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/variantlist.qml"_s));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QVERIFY(object->property("nonStrict_derivedIsNotNull").toBool());
- QVERIFY(object->property("nonStrict_nullObjectIsNull").toBool());
- QVERIFY(object->property("nonStrict_nonNullObjectIsNotNull").toBool());
- QVERIFY(object->property("nonStrict_compareSameObjects").toBool());
- QVERIFY(object->property("nonStrict_compareDifferentObjects").toBool());
- QVERIFY(object->property("nonStrict_compareObjectWithNullObject").toBool());
+ const QVariantList things = qvariant_cast<QVariantList>(o->property("things"));
+ QCOMPARE(things.size(), 2);
+ QCOMPARE(things[0].toString(), u"thing"_s);
+ QCOMPARE(things[1].toInt(), 30);
}
-void tst_QmlCppCodegen::dateConversions()
+void tst_QmlCppCodegen::variantMap()
{
QQmlEngine engine;
- QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/dateConversions.qml"_s));
+ QQmlComponent c(&engine, QUrl(u"qrc:/qt/qml/TestTypes/variantMap.qml"_s));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- Druggeljug *ref = engine.singletonInstance<Druggeljug *>("TestTypes", "Druggeljug");
-
- const QDateTime refDate = engine.coerceValue<QDate, QDateTime>(ref->myDate());
- const QDateTime refTime = engine.coerceValue<QTime, QDateTime>(ref->myTime());
-
- QCOMPARE(o->property("date").value<QDateTime>(), refDate);
- QCOMPARE(o->property("time").value<QDateTime>(), refTime);
-
- QCOMPARE(o->property("dateString").toString(), (engine.coerceValue<QDateTime, QString>(refDate)));
- QCOMPARE(o->property("timeString").toString(), (engine.coerceValue<QDateTime, QString>(refTime)));
+ QCOMPARE(o->objectName(), "a b"_L1);
+ QCOMPARE(o->property("r"), QVariant::fromValue(QRectF(12, 13, 14, 15)));
- QMetaObject::invokeMethod(o.data(), "shuffle");
+ const QVariantMap expected = QVariantMap {
+ { u"1"_s, QVariant::fromValue<std::nullptr_t>(nullptr) },
+ { u"19"_s, QVariant::fromValue(u"19"_s) },
+ { u"25"_s, QVariant() }
+ };
- QCOMPARE(ref->myDate(), (engine.coerceValue<QDateTime, QDate>(refDate)));
- QCOMPARE(ref->myTime(), (engine.coerceValue<QDateTime, QTime>(refTime)));
+ QCOMPARE(o->property("v").toMap(), expected);
+}
- const QDate date = ref->myDate();
- const QTime time = ref->myTime();
+void tst_QmlCppCodegen::voidConversion()
+{
+ QQmlEngine engine;
+ const QUrl url(u"qrc:/qt/qml/TestTypes/voidConversion.qml"_s);
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
- QCOMPARE(o->property("dateString").toString(), (engine.coerceValue<QDate, QString>(date)));
- QCOMPARE(o->property("timeString").toString(), (engine.coerceValue<QTime, QString>(time)));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + u":8: Error: Cannot assign [undefined] to QPointF"_s));
- QMetaObject::invokeMethod(o.data(), "fool");
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
- QCOMPARE(ref->myDate(), (engine.coerceValue<QTime, QDate>(time)));
- QCOMPARE(ref->myTime(), (engine.coerceValue<QDate, QTime>(date)));
+ QCOMPARE(o->property("p"), QPointF(20, 10));
}
-static QRegularExpression bindingLoopMessage(const QUrl &url, char var)
+void tst_QmlCppCodegen::voidFunction()
{
- // The actual string depends on how many times QObject* was registered with what parameters.
- return QRegularExpression(
- "%1:4:1: QML [^:]+: Binding loop detected for property \"%2\""_L1
- .arg(url.toString()).arg(QLatin1Char(var)));
+ QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/voidfunction.qml"_s));
+ QVERIFY2(component.isReady(), component.errorString().toUtf8());
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+ QVERIFY(object->objectName().isEmpty());
+ object->metaObject()->invokeMethod(object.data(), "doesNotReturnValue");
+ QCOMPARE(object->objectName(), u"barbar"_s);
}
-void tst_QmlCppCodegen::valueTypeBehavior()
+void tst_QmlCppCodegen::writeBack()
{
QQmlEngine engine;
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/TestTypes/writeback.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
- const QUrl copy(u"qrc:/qt/qml/TestTypes/valueTypeCopy.qml"_s);
+ Person *person = qobject_cast<Person *>(object.data());
+ QVERIFY(person);
+ QCOMPARE(person->area(), QRectF(4, 5, 16, 17));
+ QCOMPARE(person->property("inner").toInt(), 99);
- QQmlComponent c1(&engine, copy);
- QVERIFY2(c1.isReady(), qPrintable(c1.errorString()));
- QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(copy, 'e'));
- QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(copy, 'f'));
- QScopedPointer<QObject> o1(c1.create());
- QVERIFY(!o1.isNull());
- QCOMPARE(o1->property("e").toDouble(), 45.0);
- QCOMPARE(o1->property("f").toDouble(), 1.0);
+ Person *shadowable = person->property("shadowable").value<Person *>();
+ QVERIFY(shadowable);
+ QCOMPARE(shadowable->area(), QRectF(40, 50, 16, 17));
- const QUrl reference(u"qrc:/qt/qml/TestTypes/valueTypeReference.qml"_s);
- QQmlComponent c2(&engine, reference);
- QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
- QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(reference, 'e'));
- QTest::ignoreMessage(QtWarningMsg, bindingLoopMessage(reference, 'f'));
- QScopedPointer<QObject> o2(c2.create());
- QVERIFY(!o2.isNull());
- QVERIFY(qIsNaN(o2->property("e").toDouble()));
- QCOMPARE(o2->property("f").toDouble(), 5.0);
+ QCOMPARE(person->property("ints"), QVariant::fromValue(QList<int>({12, 22, 2, 1, 0, 0, 33})));
}
-void tst_QmlCppCodegen::invisibleSingleton()
+void tst_QmlCppCodegen::writeVariantMap()
{
QQmlEngine engine;
- const QUrl copy(u"qrc:/qt/qml/TestTypes/hidden/Main.qml"_s);
- QQmlComponent c(&engine, copy);
- QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QQmlComponent component(&engine, QUrl(u"qrc:/qt/qml/StringBuilderTestTypes/writeVariantMap.qml"_s));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ const QVariantMap v = object->property("data").toMap();
+ QCOMPARE(v.size(), 1);
+ const QVariant textPlain = v[u"text/plain"_s];
+ QCOMPARE(textPlain.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(textPlain.toString(), u"%Drag Me%"_s);
- QTest::ignoreMessage(
- QtWarningMsg,
- "qrc:/qt/qml/TestTypes/hidden/Main.qml:4:5: "
- "Unable to assign [undefined] to QColor");
- QScopedPointer<QObject> o(c.create());
- QVERIFY(!o.isNull());
- QCOMPARE(o->property("c"), QVariant(QMetaType::fromName("QColor")));
}
QTEST_MAIN(tst_QmlCppCodegen)
diff --git a/tests/auto/qml/qmldiskcache/CMakeLists.txt b/tests/auto/qml/qmldiskcache/CMakeLists.txt
index b6fd92d653..e47d2a7f75 100644
--- a/tests/auto/qml/qmldiskcache/CMakeLists.txt
+++ b/tests/auto/qml/qmldiskcache/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmldiskcache Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmldiskcache LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmldiskcache
SOURCES
tst_qmldiskcache.cpp
diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
index 19a6731ff7..810fdecafd 100644
--- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
+++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
@@ -34,12 +34,18 @@ private slots:
void recompileAfterDirectoryChange();
void fileSelectors();
void localAliases();
+ void aliasToAlias();
void cacheResources();
void stableOrderOfDependentCompositeTypes();
void singletonDependency();
void cppRegisteredSingletonDependency();
void cacheModuleScripts();
void reuseStaticMappings();
+ void invalidateSaveLoadCache();
+ void duplicateIdsInInlineComponents();
+
+ void inlineComponentDoesNotCauseConstantInvalidation_data();
+ void inlineComponentDoesNotCauseConstantInvalidation();
private:
QDir m_qmlCacheDirectory;
@@ -98,7 +104,7 @@ struct TestCompiler
{
closeMapping();
testFilePath = baseDirectory + QStringLiteral("/test.qml");
- cacheFilePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ cacheFilePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath));
mappedFile.setFileName(cacheFilePath);
}
@@ -170,7 +176,7 @@ struct TestCompiler
return false;
}
- const QString targetCacheFilePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ const QString targetCacheFilePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(targetTestFilePath));
QFile source(cacheFilePath);
@@ -197,16 +203,14 @@ struct TestCompiler
{
const QString path = fileName.isEmpty() ? testFilePath : tempDir.path() + "/" + fileName;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> unit
- = QV4::ExecutableCompilationUnit::create();
+ auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
return unit->loadFromDisk(QUrl::fromLocalFile(path),
QFileInfo(path).lastModified(), &lastErrorString);
}
quintptr unitData()
{
- QQmlRefPointer<QV4::ExecutableCompilationUnit> unit
- = QV4::ExecutableCompilationUnit::create();
+ auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
return unit->loadFromDisk(QUrl::fromLocalFile(testFilePath),
QFileInfo(testFilePath).lastModified(), &lastErrorString)
? quintptr(unit->unitData())
@@ -289,12 +293,12 @@ void tst_qmldiskcache::loadLocalAsFallback()
f.write(reinterpret_cast<const char *>(&unit), sizeof(unit));
}
- QQmlRefPointer<QV4::ExecutableCompilationUnit> unit = QV4::ExecutableCompilationUnit::create();
+ auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
bool loaded = unit->loadFromDisk(QUrl::fromLocalFile(testCompiler.testFilePath),
QFileInfo(testCompiler.testFilePath).lastModified(),
&testCompiler.lastErrorString);
QVERIFY2(loaded, qPrintable(testCompiler.lastErrorString));
- QCOMPARE(unit->objectCount(), 1);
+ QCOMPARE(unit->qmlData->nObjects, 1u);
}
void tst_qmldiskcache::regenerateAfterChange()
@@ -606,7 +610,7 @@ void tst_qmldiskcache::fileSelectors()
QVERIFY(!obj.isNull());
QCOMPARE(obj->property("value").toInt(), 42);
- QFile cacheFile(QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath)));
QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName()));
}
@@ -622,7 +626,7 @@ void tst_qmldiskcache::fileSelectors()
QVERIFY(!obj.isNull());
QCOMPARE(obj->property("value").toInt(), 100);
- QFile cacheFile(QV4::ExecutableCompilationUnit::localCacheFilePath(
+ QFile cacheFile(QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(selectedTestFilePath)));
QVERIFY2(cacheFile.exists(), qPrintable(cacheFile.fileName()));
}
@@ -671,6 +675,55 @@ void tst_qmldiskcache::localAliases()
}
}
+void tst_qmldiskcache::aliasToAlias()
+{
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ const QByteArray contents = QByteArrayLiteral(R"(
+ import QML
+ QtObject {
+ id: foo
+ readonly property alias myAlias: bar.prop
+
+ property QtObject o: QtObject {
+ id: bar
+
+ property QtObject o: QtObject {
+ id: baz
+ readonly property int value: 100
+ }
+
+ readonly property alias prop: baz.value
+ }
+ }
+ )");
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+ QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString));
+ }
+
+ {
+ CleanlyLoadingComponent component(&engine, testCompiler.testFilePath);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->property("myAlias").toInt(), 100);
+ }
+
+ engine.clearComponentCache();
+
+ {
+ CleanlyLoadingComponent component(&engine, testCompiler.testFilePath);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->property("myAlias").toInt(), 100);
+ }
+}
+
static QSet<QString> entrySet(const QDir &dir)
{
const auto &list = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
@@ -782,7 +835,7 @@ void tst_qmldiskcache::stableOrderOfDependentCompositeTypes()
QVERIFY2(firstDependentTypeClassName.contains("QMLTYPE"), firstDependentTypeClassName.constData());
QVERIFY2(secondDependentTypeClassName.contains("QMLTYPE"), secondDependentTypeClassName.constData());
- const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -861,7 +914,7 @@ void tst_qmldiskcache::singletonDependency()
QCOMPARE(obj->property("value").toInt(), 42);
}
- const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -919,7 +972,7 @@ void tst_qmldiskcache::cppRegisteredSingletonDependency()
QCOMPARE(value.toInt(), 42);
}
- const QString testFileCachePath = QV4::ExecutableCompilationUnit::localCacheFilePath(
+ const QString testFileCachePath = QV4::CompiledData::CompilationUnit::localCacheFilePath(
QUrl::fromLocalFile(testFilePath));
QVERIFY(QFile::exists(testFileCachePath));
QDateTime initialCacheTimeStamp = QFileInfo(testFileCachePath).lastModified();
@@ -961,7 +1014,8 @@ void tst_qmldiskcache::cacheModuleScripts()
auto componentPrivate = QQmlComponentPrivate::get(&component);
QVERIFY(componentPrivate);
- auto compilationUnit = componentPrivate->compilationUnit->dependentScripts.first()->compilationUnit();
+ auto compilationUnit = componentPrivate->compilationUnit->dependentScriptsPtr()
+ ->first()->compilationUnit();
QVERIFY(compilationUnit);
auto unitData = compilationUnit->unitData();
QVERIFY(unitData);
@@ -1007,6 +1061,326 @@ void tst_qmldiskcache::reuseStaticMappings()
QCOMPARE(testCompiler.unitData(), data1);
}
+class AParent : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int x MEMBER x)
+public:
+ AParent(QObject *parent = nullptr) : QObject(parent) {}
+ int x = 25;
+};
+
+class BParent : public QObject
+{
+ Q_OBJECT
+
+ // Insert y before x, to change the property index of x
+ Q_PROPERTY(int y MEMBER y)
+
+ Q_PROPERTY(int x MEMBER x)
+public:
+ BParent(QObject *parent = nullptr) : QObject(parent) {}
+ int y = 13;
+ int x = 25;
+};
+
+static QString writeTempFile(
+ const QTemporaryDir &tempDir, const QString &fileName, const char *contents) {
+ QFile f(tempDir.path() + '/' + fileName);
+ const bool ok = f.open(QIODevice::WriteOnly | QIODevice::Truncate);
+ Q_ASSERT(ok);
+ f.write(contents);
+ return f.fileName();
+};
+
+void tst_qmldiskcache::invalidateSaveLoadCache()
+{
+ qmlRegisterType<AParent>("Base", 1, 0, "Parent");
+ std::unique_ptr<QQmlEngine> e = std::make_unique<QQmlEngine>();
+
+ // If you store a CU to a .qmlc file at run time, the .qmlc file will contain
+ // alias entries with the encodedMetaPropertyIndex pre-resolved. That's in
+ // contrast to .qmlc files generated ahead of time. Exploit that to cause
+ // a need to recompile the file.
+
+ QTemporaryDir tempDir;
+ writeTempFile(
+ tempDir, QLatin1String("B.qml"),
+ R"(
+ import QML
+ QtObject {
+ component C: QtObject {}
+ }
+ )");
+
+ const QString fileName = writeTempFile(
+ tempDir, QLatin1String("a.qml"),
+ R"(
+ import Base
+ Parent {
+ id: self
+ property alias z: self.x
+ component C: Parent {}
+ property C c: C {}
+ property B.C d: B.C {}
+ }
+ )");
+ const QUrl url = QUrl::fromLocalFile(fileName);
+ waitForFileSystem();
+
+ {
+ QQmlComponent a(e.get(), url);
+ QVERIFY2(a.isReady(), qPrintable(a.errorString()));
+ QScopedPointer<QObject> ao(a.create());
+ QVERIFY(!ao.isNull());
+ AParent *ap = qobject_cast<AParent *>(ao.data());
+ QCOMPARE(ap->property("z").toInt(), ap->x);
+ }
+
+ QString errorString;
+ auto oldUnit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
+ QVERIFY2(oldUnit->loadFromDisk(url, QFileInfo(fileName).lastModified(), &errorString), qPrintable(errorString));
+
+ // Produce a checksum mismatch.
+ e->clearComponentCache();
+ qmlClearTypeRegistrations();
+ qmlRegisterType<BParent>("Base", 1, 0, "Parent");
+ e = std::make_unique<QQmlEngine>();
+
+ {
+ QQmlComponent b(e.get(), url);
+ QVERIFY2(b.isReady(), qPrintable(b.errorString()));
+ QScopedPointer<QObject> bo(b.create());
+ QVERIFY(!bo.isNull());
+ BParent *bp = qobject_cast<BParent *>(bo.data());
+ QCOMPARE(bp->property("z").toInt(), bp->x);
+ }
+
+ // Make it recompile again. If we ever get rid of the metaobject indices in compilation units,
+ // the above test will not test the save/load cache anymore. Therefore, in order to make really
+ // sure that we get a new CU that invalidates the save/load cache, modify the file in place.
+
+ e->clearComponentCache();
+ {
+ QFile file(fileName);
+ QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Append));
+ file.write(" ");
+ }
+ waitForFileSystem();
+
+ {
+ QQmlComponent b(e.get(), url);
+ QVERIFY2(b.isReady(), qPrintable(b.errorString()));
+ QScopedPointer<QObject> bo(b.create());
+ QVERIFY(!bo.isNull());
+ BParent *bp = qobject_cast<BParent *>(bo.data());
+ QCOMPARE(bp->property("z").toInt(), bp->x);
+ }
+
+ // Verify that the mapped unit data is actually different now.
+ // The cache should have been invalidated after all.
+ // So, now we should be able to load a freshly written CU.
+
+ auto unit = QQml::makeRefPointer<QV4::CompiledData::CompilationUnit>();
+ QVERIFY2(unit->loadFromDisk(url, QFileInfo(fileName).lastModified(), &errorString), qPrintable(errorString));
+
+ QVERIFY(unit->unitData() != oldUnit->unitData());
+}
+
+void tst_qmldiskcache::duplicateIdsInInlineComponents()
+{
+ // Exercise the case of loading strange generalized group properties from .qmlc.
+
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ const QByteArray contents = QByteArrayLiteral(R"(
+ import QtQml
+ QtObject {
+ component First : QtObject {
+ property QtObject aa: QtObject {
+ id: a
+ }
+ property Binding bb: Binding {
+ a.objectName: "test1"
+ }
+ }
+
+ component Second : QtObject {
+ property QtObject aa: QtObject {
+ id: a
+ }
+ property Binding bb: Binding {
+ a.objectName: "test2"
+ }
+
+ property Component cc: QtObject {
+ property QtObject aa: QtObject {
+ id: a
+ }
+ property Binding bb: Binding {
+ a.objectName: "test3"
+ }
+ }
+ }
+
+ property First first: First {}
+ property Second second: Second {}
+ property QtObject third: second.cc.createObject();
+
+ objectName: first.aa.objectName + second.aa.objectName + third.aa.objectName;
+ }
+ )");
+
+ {
+ testCompiler.clearCache();
+ QVERIFY2(testCompiler.compile(contents), qPrintable(testCompiler.lastErrorString));
+ QVERIFY2(testCompiler.verify(), qPrintable(testCompiler.lastErrorString));
+ }
+
+ {
+ CleanlyLoadingComponent component(&engine, testCompiler.testFilePath);
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->objectName(), "test1test2test3");
+ }
+
+ engine.clearComponentCache();
+
+ {
+ CleanlyLoadingComponent component(&engine, testCompiler.testFilePath);
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY(!obj.isNull());
+ QCOMPARE(obj->objectName(), "test1test2test3");
+ }
+}
+
+void tst_qmldiskcache::inlineComponentDoesNotCauseConstantInvalidation_data()
+{
+ QTest::addColumn<QByteArray>("code");
+
+ QTest::addRow("simple") << QByteArray(R"(
+ import QtQml
+ QtObject {
+ component Test: QtObject {
+ property int i: 28
+ }
+ property Test test: Test {
+ objectName: "foobar"
+ }
+ property int k: test.i
+ }
+ )");
+
+ QTest::addRow("with function") << QByteArray(R"(
+ import QtQml
+ QtObject {
+ component Test : QtObject {
+ id: self
+ property int i: 2
+ property alias j: self.i
+ }
+ property Test test: Test {
+ function updateValue() {}
+ objectName: 'foobar'
+ j: 28
+ }
+ property int k: test.j
+ }
+ )");
+
+ QTest::addRow("in nested") << QByteArray(R"(
+ import QtQuick
+ Item {
+ Item {
+ component Line: Item {
+ property alias endY: pathLine.y
+ Item {
+ Item {
+ id: pathLine
+ }
+ }
+ }
+ }
+ Line {
+ id: primaryLine
+ endY: 28
+ }
+ property int k: primaryLine.endY
+ }
+ )");
+
+ QTest::addRow("with revision") << QByteArray(R"(
+ import QtQuick
+ ListView {
+ Item {
+ id: scrollBar
+ }
+ delegate: Image {
+ mipmap: true
+ }
+ Item {
+ id: refreshNodesIndicator
+ }
+ property int k: delegate.createObject().mipmap ? 28 : 4
+ }
+ )");
+}
+
+void tst_qmldiskcache::inlineComponentDoesNotCauseConstantInvalidation()
+{
+ QFETCH(QByteArray, code);
+
+ QQmlEngine engine;
+
+ TestCompiler testCompiler(&engine);
+ QVERIFY(testCompiler.tempDir.isValid());
+
+ auto check = [&](){
+ QQmlComponent c(&engine, QUrl::fromLocalFile(testCompiler.testFilePath));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("k"), QVariant::fromValue<int>(28));
+ };
+
+ testCompiler.reset();
+ QVERIFY(testCompiler.writeTestFile(code));
+
+ QVERIFY(testCompiler.loadTestFile());
+
+ const quintptr data1 = testCompiler.unitData();
+ QVERIFY(data1 != 0);
+ QCOMPARE(testCompiler.unitData(), data1);
+ check();
+
+ engine.clearComponentCache();
+
+ // inline component does not invalidate cache
+ QVERIFY(testCompiler.loadTestFile());
+ QCOMPARE(testCompiler.unitData(), data1);
+ check();
+
+ testCompiler.reset();
+ QVERIFY(testCompiler.writeTestFile(R"(
+ import QtQml
+ QtObject {
+ component Test : QtObject {
+ property double d: 2
+ }
+ property Test test: Test {
+ objectName: 'foobar'
+ }
+ })"));
+ QVERIFY(testCompiler.loadTestFile());
+ const quintptr data2 = testCompiler.unitData();
+ QVERIFY(data2);
+ QVERIFY(data1 != data2);
+}
+
QTEST_MAIN(tst_qmldiskcache)
#include "tst_qmldiskcache.moc"
diff --git a/tests/auto/qml/qmlformat/CMakeLists.txt b/tests/auto/qml/qmlformat/CMakeLists.txt
index 2c908a9190..76923d66de 100644
--- a/tests/auto/qml/qmlformat/CMakeLists.txt
+++ b/tests/auto/qml/qmlformat/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmlformat Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlformat LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -24,8 +30,11 @@ qt_internal_add_test(tst_qmlformat
Qt::TestPrivate
Qt::QuickTestUtilsPrivate
TESTDATA ${test_data}
+ TIMEOUT 3000
)
+add_dependencies(tst_qmlformat Qt::qmlformat)
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
index 92cbeb55f7..019b7f0141 100644
--- a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
@@ -10,17 +10,14 @@ import QtCharts 2.0
@Pippo {
atg1: 3
}
-@Annotation2 {
-}
+@Annotation2 {}
Item {
- @Annotate {
- }
+ @Annotate {}
anchors.fill: parent
@AnnotateMore {
property int x: 5
}
- @AnnotateALot {
- }
+ @AnnotateALot {}
property variant othersSlice: 0
//![1]
@@ -79,19 +76,17 @@ Item {
@BindingAnn {
bType: 2
}
- val2: Item {
- }
+ val2: Item {}
@BindingAnn {
bType: 3
}
val3: [
- Item {
- }
+ Item {}
]
@BindingAnn {
bType: 4
}
- Animation on val {
+ Animation on val {
duration: 34
}
}
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml
index 8b181f607e..b1662e8898 100644
--- a/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.2spaces.qml
@@ -43,7 +43,7 @@ Item {
property bool some_bool: false
// This comment is related to the property animation
- PropertyAnimation on x {
+ PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
@@ -54,6 +54,7 @@ Item {
// Another orphan
// More orphans
+
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool something_computed: function (x) {
const PI = 3, DAYS_PER_YEAR = 365.25;
@@ -124,6 +125,7 @@ Item {
}
// Another orphan inside something_computed
+
return "foobar";
}()
@@ -133,11 +135,9 @@ Item {
// This is an orphan
// This is a cool text
- Text {
- },
+ Text {},
// This is a cool rectangle
- Rectangle {
- }
+ Rectangle {}
]
// some_read_only_bool
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.qml
index cb8865d94e..c4aef78924 100644
--- a/tests/auto/qml/qmlformat/data/Example1.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.qml
@@ -43,7 +43,7 @@ Item {
property bool some_bool: false
// This comment is related to the property animation
- PropertyAnimation on x {
+ PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
@@ -54,6 +54,7 @@ Item {
// Another orphan
// More orphans
+
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool something_computed: function (x) {
const PI = 3, DAYS_PER_YEAR = 365.25;
@@ -124,6 +125,7 @@ Item {
}
// Another orphan inside something_computed
+
return "foobar";
}()
@@ -133,11 +135,9 @@ Item {
// This is an orphan
// This is a cool text
- Text {
- },
+ Text {},
// This is a cool rectangle
- Rectangle {
- }
+ Rectangle {}
]
// some_read_only_bool
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml b/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml
index ef964f6f60..7cea50213a 100644
--- a/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted.tabs.qml
@@ -43,7 +43,7 @@ Item {
property bool some_bool: false
// This comment is related to the property animation
- PropertyAnimation on x {
+ PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
@@ -54,6 +54,7 @@ Item {
// Another orphan
// More orphans
+
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool something_computed: function (x) {
const PI = 3, DAYS_PER_YEAR = 365.25;
@@ -124,6 +125,7 @@ Item {
}
// Another orphan inside something_computed
+
return "foobar";
}()
@@ -133,11 +135,9 @@ Item {
// This is an orphan
// This is a cool text
- Text {
- },
+ Text {},
// This is a cool rectangle
- Rectangle {
- }
+ Rectangle {}
]
// some_read_only_bool
diff --git a/tests/auto/qml/qmlformat/data/Example1.formatted2.qml b/tests/auto/qml/qmlformat/data/Example1.formatted2.qml
index aa662a3d5f..7049686900 100644
--- a/tests/auto/qml/qmlformat/data/Example1.formatted2.qml
+++ b/tests/auto/qml/qmlformat/data/Example1.formatted2.qml
@@ -39,6 +39,7 @@ Item {
// Another orphan
// More orphans
+
property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3]
property bool some_bool: false
default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool
@@ -114,6 +115,7 @@ Item {
}
// Another orphan inside something_computed
+
return "foobar";
}()
@@ -140,14 +142,12 @@ Item {
// This is an orphan
// This is a cool text
- Text {
- },
+ Text {},
// This is a cool rectangle
- Rectangle {
- }
+ Rectangle {}
]
// This comment is related to the property animation
- PropertyAnimation on x {
+ PropertyAnimation on x {
id: foo2
x: 3
y: x + 3
diff --git a/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
index 7dfe435ac0..95b4fcf4a3 100644
--- a/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/FrontInline.formatted.qml
@@ -1,4 +1,3 @@
// This comment should be directly above Item after formatting
-Item {
-}
+Item {}
diff --git a/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml b/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml
new file mode 100644
index 0000000000..8ae4dd7c88
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/arrayEndComma.formatted.qml
@@ -0,0 +1,4 @@
+Item {
+ // should keep its comma
+ property var some_array_literal: [30, 20, 0.3,]
+}
diff --git a/tests/auto/qml/qmlformat/data/arrayEndComma.qml b/tests/auto/qml/qmlformat/data/arrayEndComma.qml
new file mode 100644
index 0000000000..1aec09515c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/arrayEndComma.qml
@@ -0,0 +1,8 @@
+Item {
+ // should keep its comma
+ property var some_array_literal: [
+ 30,
+ 20,
+ 0.3,
+ ]
+}
diff --git a/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml
new file mode 100644
index 0000000000..ac4cf97881
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.formatted.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Item {
+ Component.onCompleted: {
+ let f = ([]) => {};
+ let g = ([a]) => {};
+ let h = ([a, b]) => {};
+ let i = ([a, ...b]) => {};
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml
new file mode 100644
index 0000000000..2a47b2f152
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/arrowFunctionWithBinding.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item { Component.onCompleted: { let f = ([]) => {};
+ let g = ([a]) => {};
+ let h = ([a, b]) => {};
+ let i = ([a, ...b]) => {};
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml
new file mode 100644
index 0000000000..071e3bc69f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.formatted.qml
@@ -0,0 +1,12 @@
+/* comment with spaces */
+
+/*
+ another comment
+ */
+//
+
+// another comment /*test */
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml
new file mode 100644
index 0000000000..c99415aeed
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/blanklinesAfterComment.qml
@@ -0,0 +1,15 @@
+/* comment with spaces */
+
+/*
+ another comment
+ */
+//
+
+
+// another comment /*test */
+
+
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/class.formatted.js b/tests/auto/qml/qmlformat/data/class.formatted.js
new file mode 100644
index 0000000000..eeb1faf64e
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/class.formatted.js
@@ -0,0 +1,5 @@
+class Person {
+ constructor(name) {
+ this._name = name;
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/class.js b/tests/auto/qml/qmlformat/data/class.js
new file mode 100644
index 0000000000..116061d515
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/class.js
@@ -0,0 +1 @@
+class Person{constructor(name){this._name = name;}}
diff --git a/tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml b/tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml
new file mode 100644
index 0000000000..583c315c4b
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/commentInEnum.formatted.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+ // This to enum
+ enum Foo {
+ A = 3, // This is A
+ B, // This is B
+ C = 4, // This is C
+ D // This is D
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/commentInEnum.qml b/tests/auto/qml/qmlformat/data/commentInEnum.qml
new file mode 100644
index 0000000000..3a1b15d278
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/commentInEnum.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ // This to enum
+ enum Foo {
+ A = 3, // This is A
+ B, // This is B
+ C = 4, // This is C
+ D // This is D
+ }
+
+}
diff --git a/tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml b/tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml
new file mode 100644
index 0000000000..749dc65b7c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/commentInQmlObject.formatted.qml
@@ -0,0 +1,4 @@
+import QtQml
+
+// hello world
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/commentInQmlObject.qml b/tests/auto/qml/qmlformat/data/commentInQmlObject.qml
new file mode 100644
index 0000000000..9aca637e4f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/commentInQmlObject.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ // hello world
+}
diff --git a/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml
new file mode 100644
index 0000000000..0bfcc58179
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.formatted.qml
@@ -0,0 +1,24 @@
+import QtQml
+
+QtObject {
+
+ function evil({
+ hello = "world",
+ x = 42
+ }, [n = 42, m = 43, o = 44], {
+ destructuring,
+ is = {
+ a,
+ lot,
+ of
+ },
+ fun = 42
+ } = {
+ destructuring: 123,
+ is: {
+ x: 123
+ },
+ fun: 456
+ }) {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml
new file mode 100644
index 0000000000..f41661ed67
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/destructuringFunctionParameter.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+QtObject {
+
+ function evil({ hello = "world", x = 42 },
+ [n = 42, m = 43, o = 44],
+ { destructuring, is = {a, lot, of}, fun = 42 } = {destructuring : 123, is : {x : 123}, fun : 456}) {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/directives.formatted.js b/tests/auto/qml/qmlformat/data/directives.formatted.js
new file mode 100644
index 0000000000..3d0a4db544
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/directives.formatted.js
@@ -0,0 +1,8 @@
+.pragma library
+.import "fun.js" as Fun
+.import Qt.test 1.0 as JsQtTest
+.import Qt.Quick as Test
+
+Fun.begin();
+Test.do_stuff();
+JsQtTest.do_stuff();
diff --git a/tests/auto/qml/qmlformat/data/directives.js b/tests/auto/qml/qmlformat/data/directives.js
new file mode 100644
index 0000000000..b8e1b785ac
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/directives.js
@@ -0,0 +1,9 @@
+
+.pragma library
+
+.import "fun.js" as Fun
+.import Qt.test 1.0 as JsQtTest
+
+
+.import Qt.Quick as Test
+Fun.begin();Test.do_stuff();JsQtTest.do_stuff();
diff --git a/tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js b/tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js
new file mode 100644
index 0000000000..c130f72453
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/directivesWithComments.formatted.js
@@ -0,0 +1,6 @@
+.pragma library // use as library
+/*
+ Fun is necessary
+ */
+.import "fun.js" as Fun
+.import Qt.test 1.0 as JsQtTest // yet another comment not to be lost
diff --git a/tests/auto/qml/qmlformat/data/directivesWithComments.js b/tests/auto/qml/qmlformat/data/directivesWithComments.js
new file mode 100644
index 0000000000..7206bb27ed
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/directivesWithComments.js
@@ -0,0 +1,8 @@
+
+.pragma library // use as library
+
+/*
+ Fun is necessary
+ */
+.import "fun.js" as Fun
+.import Qt.test 1.0 as JsQtTest // yet another comment not to be lost
diff --git a/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml b/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml
index 0c7a2829c9..8eaac71178 100644
--- a/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/dontRemoveComments.formatted.qml
@@ -1,13 +1,15 @@
Item {
- property var test: [{
+ property var test: [
+ {
// Testing
"foo": "bar"
- }]
+ }
+ ]
onTestChanged: {
fooBar(test, {
- // Testing
- "foo": "bar"
- });
+ // Testing
+ "foo": "bar"
+ });
}
}
diff --git a/tests/auto/qml/qmlformat/data/dontRemoveComments.qml b/tests/auto/qml/qmlformat/data/dontRemoveComments.qml
index 1797834879..2d2b4b6705 100644
--- a/tests/auto/qml/qmlformat/data/dontRemoveComments.qml
+++ b/tests/auto/qml/qmlformat/data/dontRemoveComments.qml
@@ -1,8 +1,10 @@
Item {
- property var test: [{
-// Testing
+ property var test: [
+ {
+ // Testing
"foo": "bar"
- }]
+ }
+ ]
onTestChanged: {
fooBar(test, {
diff --git a/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml
index edbb12c6e6..de6a23f9c7 100644
--- a/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/ecmaScriptClassInQml.formatted.qml
@@ -4,11 +4,13 @@ Item {
function f() {
var count = 0;
+
class Person {
constructor(name){
this._name = name;
}
}
+
class Employee extends Person {
constructor(name, age){
super(name);
diff --git a/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml
new file mode 100644
index 0000000000..f41942e054
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.formatted.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+
+ function patron(a, ...b) {
+ }
+
+ function patron1(a, ...[b, ...args]) {
+ }
+
+ function patron2(...{}) {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml
new file mode 100644
index 0000000000..28364f29c9
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/ellipsisFunctionArgument.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+
+ function patron(a, ...b) {
+ }
+
+ function patron1(a, ...[b, ...args]) {}
+
+ function patron2(...{}) {}
+} \ No newline at end of file
diff --git a/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml b/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml
new file mode 100644
index 0000000000..bbf978936f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/enumWithValues.formatted.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Rectangle {
+ enum AxisAlignment {
+ Bottom = 0,
+ Left = 1,
+ Right = 2
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/enumWithValues.qml b/tests/auto/qml/qmlformat/data/enumWithValues.qml
new file mode 100644
index 0000000000..2dbe7fbac5
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/enumWithValues.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Rectangle{
+enum AxisAlignment{
+Bottom = 0,
+Left = 1,
+Right = 2
+}
+}
diff --git a/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml b/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml
new file mode 100644
index 0000000000..3f6807834f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/escapeChars.formatted.qml
@@ -0,0 +1,16 @@
+import QtQuick
+
+Item {
+ x: {
+ const s = "\"";
+ let a = {
+ "\"": "\\"
+ };
+
+ let patron = {
+ "\\\"\n\n": "\?\?\\\"",
+ "": "",
+ "\'\"\n": 1
+ };
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/escapeChars.qml b/tests/auto/qml/qmlformat/data/escapeChars.qml
new file mode 100644
index 0000000000..c82ff3119e
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/escapeChars.qml
@@ -0,0 +1,16 @@
+import QtQuick
+
+Item {
+ x: {
+ const s = "\""
+ let a = {
+ "\"": "\\"
+ };
+
+ let patron = {
+ "\\\"\n\n" : "\?\?\\\"","": "", "\'\"\n":1
+ };
+
+
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/esm.formatted.mjs b/tests/auto/qml/qmlformat/data/esm.formatted.mjs
new file mode 100644
index 0000000000..f0b3fd7753
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/esm.formatted.mjs
@@ -0,0 +1,44 @@
+//Imports
+import defaultExport from "module-name";
+import * as name from "module-name";
+import { export1 } from "module-name";
+import { export1 as alias1 } from "module-name";
+import { default as alias } from "module-name";
+import { export1, export2 } from "module-name";
+import { export1, export2 as alias2 } from "module-name";
+import defaultExport, { export1, a } from "module-name";
+import defaultExport, * as name from "module-name";
+import "module-name";
+
+// Exporting declarations
+export let name1, name2; // also var
+export const name1 = 1, name2 = 2; // also var, let
+export function functionName() {}
+export class ClassName {
+ constructor(h){
+ this.h = h;
+ }
+}
+export function* generatorFunctionName() {}
+export const {
+ name1,
+ name2: bar
+} = o;
+export const [name1, name2] = array;
+
+// Export list
+export { name1, nameN };
+export { variable1 as name1, variable2 as name2, nameN };
+export { name1 as default };
+
+// Default exports
+export default function* generatorFunctionName() {
+ return 1;
+}
+
+// Aggregating modules
+export * from "module-name";
+export { name1, nameN } from "module-name";
+export { import1 as name1, import2 as name2, nameN } from "module-name";
+export { default } from "module-name";
+export { default as name1 } from "module-name";
diff --git a/tests/auto/qml/qmlformat/data/esm.mjs b/tests/auto/qml/qmlformat/data/esm.mjs
new file mode 100644
index 0000000000..83e22fdedd
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/esm.mjs
@@ -0,0 +1,33 @@
+//Imports
+import defaultExport from "module-name";
+import * as name from "module-name"
+import {export1} from "module-name";
+import { export1 as alias1 } from "module-name";
+import { default as alias } from "module-name"
+import { export1, export2 } from "module-name";
+import {export1,export2 as alias2} from "module-name";
+import defaultExport,{export1,a} from "module-name"
+import defaultExport, * as name from "module-name";
+import "module-name";
+
+
+// Exporting declarations
+export let name1,name2; // also var
+export const name1=1,name2=2 // also var, let
+export function functionName() {}
+export class ClassName{constructor(h){this.h=h;}}
+export function* generatorFunctionName() {}
+export const {name1, name2: bar}=o;export const [name1,name2]=array
+
+// Export list
+export {name1,nameN};export {variable1 as name1,variable2 as name2,nameN }
+export {name1 as default};
+
+// Default exports
+export default function* generatorFunctionName() {return 1;}
+
+// Aggregating modules
+export * from "module-name";
+export { name1,nameN} from "module-name"
+export { import1 as name1, import2 as name2,nameN } from "module-name";export { default, } from "module-name";
+export { default as name1 } from "module-name";
diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml b/tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml
new file mode 100644
index 0000000000..a995f0479f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/filesOption/valid1.formatted.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ property int a
+ function aa() {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid1.qml b/tests/auto/qml/qmlformat/data/filesOption/valid1.qml
new file mode 100644
index 0000000000..8aef366bd9
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/filesOption/valid1.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+property int a
+function aa(){}
+} \ No newline at end of file
diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml b/tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml
new file mode 100644
index 0000000000..a995f0479f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/filesOption/valid2.formatted.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ property int a
+ function aa() {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/filesOption/valid2.qml b/tests/auto/qml/qmlformat/data/filesOption/valid2.qml
new file mode 100644
index 0000000000..f2cb636c00
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/filesOption/valid2.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ property int a
+ function aa() {}
+}
diff --git a/tests/auto/qml/qmlformat/data/forOf.formatted.qml b/tests/auto/qml/qmlformat/data/forOf.formatted.qml
index fa9ff9c631..0cc4f9fecd 100644
--- a/tests/auto/qml/qmlformat/data/forOf.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/forOf.formatted.qml
@@ -3,6 +3,7 @@ import QtQml 2.0
QtObject {
Component.onCompleted: {
var list = [[1, 2], [3, 4], [5, 6]];
+
for (const [x, y] of list)
console.log("X: " + x + "; Y: " + y);
for (let [x, y] of list)
diff --git a/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml b/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml
index d452ba2b8c..91f520b5fc 100644
--- a/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/functionsSpacing.formatted.qml
@@ -6,8 +6,7 @@ Item {
}
function test2() {
}
- Button {
- }
+ Button {}
function test4() {
}
diff --git a/tests/auto/qml/qmlformat/data/importStatements.formatted.qml b/tests/auto/qml/qmlformat/data/importStatements.formatted.qml
new file mode 100644
index 0000000000..6613becaca
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/importStatements.formatted.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+import QtQuick
+import QtQuick.Controls
+
+import org.test.module
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/importStatements.qml b/tests/auto/qml/qmlformat/data/importStatements.qml
new file mode 100644
index 0000000000..efe1872e93
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/importStatements.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+
+import QtQuick
+import QtQuick.Controls
+
+import org.test.module
+
+
+
+QtObject {
+}
diff --git a/tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml b/tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml
new file mode 100644
index 0000000000..09ab9454e1
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/javascriptBlock.formatted.qml
@@ -0,0 +1,6 @@
+Item {
+ block1: {
+ console.log("Hello, world!");
+ }
+ emptyBlock: {}
+}
diff --git a/tests/auto/qml/qmlformat/data/javascriptBlock.qml b/tests/auto/qml/qmlformat/data/javascriptBlock.qml
new file mode 100644
index 0000000000..1665c81f42
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/javascriptBlock.qml
@@ -0,0 +1,5 @@
+Item {
+ block1: {console.log("Hello, world!");}
+ emptyBlock: {
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js
new file mode 100644
index 0000000000..62a5e36f5e
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.formatted.js
@@ -0,0 +1,6 @@
+var b = function () {
+ var a = 1;
+ for (var ii = 1; ii < 10; ++ii) {
+ a = a * ii;
+ }
+};
diff --git a/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js
new file mode 100644
index 0000000000..0155cff7f9
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaFunctionWithLoop.js
@@ -0,0 +1 @@
+var b=function(){var a=1;for(var ii=1;ii<10;++ii){a=a*ii;}}
diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js
new file mode 100644
index 0000000000..3bc7f683c4
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.formatted.js
@@ -0,0 +1,7 @@
+var f = function () {
+ if (true) {
+ console.log("true");
+ } else {
+ console.log("false");
+ }
+};
diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElse.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.js
new file mode 100644
index 0000000000..aaf731e5f0
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElse.js
@@ -0,0 +1 @@
+var f = function(){if(true){ console.log("true");} else {console.log("false");}}
diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js
new file mode 100644
index 0000000000..99db6fb372
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.formatted.js
@@ -0,0 +1,9 @@
+var l = function () {
+ var nl = function () {
+ if (true) {
+ console.log("true");
+ } else {
+ console.log("false");
+ }
+ };
+};
diff --git a/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js
new file mode 100644
index 0000000000..23ae087b04
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/lambdaWithIfElseInsideLambda.js
@@ -0,0 +1 @@
+var l = function(){var nl = function(){if(true){console.log("true");}else{console.log("false");}};};
diff --git a/tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js b/tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js
new file mode 100644
index 0000000000..cd7d75314c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/messyIfStatement.formatted.js
@@ -0,0 +1,4 @@
+if (((typeof ezJsu !== 'undefined') && ezJsu === true) || ((typeof _ez_sa !== 'undefined') && _ez_sa === true)) {
+ a.defaultStoreUrl = '//g.ezoic.net/ezoic/imp.gif';
+ a.defaultStoreA = '//g.ezoic.net/ezoic/i.gif';// Single Line Comments here
+}
diff --git a/tests/auto/qml/qmlformat/data/messyIfStatement.js b/tests/auto/qml/qmlformat/data/messyIfStatement.js
new file mode 100644
index 0000000000..cdd4c7bd9d
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/messyIfStatement.js
@@ -0,0 +1,2 @@
+if (((typeof ezJsu!=='undefined')&&ezJsu===true)||((typeof _ez_sa !=='undefined')&&_ez_sa === true)) {a.defaultStoreUrl='//g.ezoic.net/ezoic/imp.gif';a.defaultStoreA ='//g.ezoic.net/ezoic/i.gif';// Single Line Comments here
+}
diff --git a/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs b/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs
new file mode 100644
index 0000000000..37f8ccb698
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/mini_esm.formattedTabs.mjs
@@ -0,0 +1,20 @@
+//Imports
+import defaultExport from "module-name";
+import "module-name";
+export class ClassName {
+ constructor(h){
+ this.h = h;
+ }
+}
+export const {
+ n1,
+ n3,
+ n4,
+ name2: bar
+} = o;
+export const [name1, name2] = array;
+function stuff() {
+ var l = () => {
+ 1 + 1;
+ };
+}
diff --git a/tests/auto/qml/qmlformat/data/mini_esm.mjs b/tests/auto/qml/qmlformat/data/mini_esm.mjs
new file mode 100644
index 0000000000..9d6c2406dc
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/mini_esm.mjs
@@ -0,0 +1,3 @@
+//Imports
+import defaultExport from "module-name";import "module-name";export class ClassName{constructor(h){this.h=h;}}
+export const {n1,n3,n4,name2:bar}=o;export const [name1,name2]=array;function stuff(){var l=()=>{1+1};};
diff --git a/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml b/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml
index 45d04c5887..46e3e963ea 100644
--- a/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/multilineComment.formatted.qml
@@ -1,11 +1,9 @@
Item {
- Item {
- }
+ Item {}
/* This is a multiline comment.
it should stay attached to Commented instead of getting orphaned.
*/
// This should also stick to Commented
- Commented {
- }
+ Commented {}
}
diff --git a/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml b/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml
index 5536ecf513..fc1915f647 100644
--- a/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/nestedFunctions.formatted.qml
@@ -1,11 +1,13 @@
Item {
function a() {
function nested() {}
+
foo();
}
function b() {
function nested() {}
+
bar();
}
}
diff --git a/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml b/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml
index 4ff5a40a23..ebb125f36d 100644
--- a/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/nestedIf.formatted.qml
@@ -26,6 +26,7 @@ Item {
x();
}
}
+
if (x && y)
if (x < y)
return 0;
diff --git a/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml b/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml
new file mode 100644
index 0000000000..94e97076b1
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/objectDestructuring.formatted.qml
@@ -0,0 +1,137 @@
+import QtQml
+
+QtObject {
+
+ function set1() {
+ const array = [1, 2, 3, 4];
+ const [a, b] = [1, 2];
+ const [aa, , bb] = array;
+ const [aaa = 23, bbb] = array;
+ const [a1, b1, ...rest1] = array;
+ const [a2, , b2, ...rest2] = array;
+ const [a3, b3, ...{
+ pop,
+ push
+ }] = array;
+ const [a4, b4, ...[c, d]] = array;
+
+ const obj = {
+ _a: 1,
+ _b: 2
+ };
+ const {
+ a5,
+ b5
+ } = obj;
+ const {
+ a6: a_,
+ b6: b1_
+ } = obj;
+ const {
+ a7: a11 = 4,
+ b11 = 34,
+ c1: b111,
+ d1
+ } = obj;
+ let key = a;
+ const {
+ [key]: a___
+ } = obj;
+ }
+
+ function set2() {
+ // declare first
+ let a, b, a1, b1, c, d, rest, pop, push;
+ const array = [1, 2, 3, 4];
+ [a, b] = array;
+ [a, , b] = array;
+ [a = aDefault, b] = array;
+ [a, b, ...rest] = array;
+ [a, , b, ...rest] = array;
+ [a, b, ...{
+ pop,
+ push
+ }] = array;
+ [a, b, ...[c, d]] = array;
+
+ const obj = {
+ _a: 1,
+ _b: 2
+ };
+ ({
+ a,
+ b
+ } = obj); // brackets are required
+ ({
+ a: a1,
+ b: b1
+ } = obj);
+
+ const complicatedObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: {
+ e: 3,
+ f: [4, 5, 6]
+ }
+ },
+ g: [7, 8, 9]
+ };
+
+ const {
+ patron,
+ b: {
+ mafik,
+ d: {
+ e,
+ f: [, secondF, ...restF]
+ }
+ },
+ g: [firstG, ...restG]
+ } = complicatedObject;
+ }
+
+ Component.onCompleted: {
+ const myFunction = myLambda => {
+ const myObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: [3, 4, 5]
+ },
+ e: {
+ f: 6,
+ g: {
+ h: 7,
+ i: [8, 9, 10]
+ }
+ }
+ };
+
+ myLambda(myObject);
+ };
+
+ myFunction(({
+ a,
+ b: {
+ c,
+ d: [firstD]
+ },
+ e: {
+ f,
+ g: {
+ h,
+ i: [, secondI]
+ }
+ }
+ }) => {
+ console.log(a); // 1
+ console.log(c); // 2
+ console.log(firstD); // 3
+ console.log(f); // 6
+ console.log(h); // 7
+ console.log(secondI); // 9
+ });
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/objectDestructuring.qml b/tests/auto/qml/qmlformat/data/objectDestructuring.qml
new file mode 100644
index 0000000000..0487153125
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/objectDestructuring.qml
@@ -0,0 +1,77 @@
+import QtQml
+
+QtObject {
+
+ function set1() {
+ const array = [1,2,3,4];
+ const [a, b] = [1,2];
+ const [aa, , bb] = array;
+ const [aaa = 23, bbb] = array;
+ const [a1, b1, ...rest1] = array;
+ const [a2, , b2, ...rest2] = array;
+ const [a3, b3, ...{ pop, push }] = array;
+ const [a4, b4, ...[c, d]] = array;
+
+ const obj = {_a:1,_b:2};
+ const { a5, b5 } = obj;
+ const { a6: a_, b6: b1_ } = obj;
+ const { a7: a11 = 4, b11 = 34, c1: b111, d1 } = obj;
+ let key = a;
+ const { [key]: a___ } = obj;
+ }
+
+ function set2() {
+ // declare first
+ let a, b, a1, b1, c, d, rest, pop, push;
+ const array = [1,2,3,4];
+ [a, b] = array;
+ [a, , b] = array;
+ [a = aDefault, b] = array;
+ [a, b, ...rest] = array;
+ [a, , b, ...rest] = array;
+ [a, b, ...{ pop, push }] = array;
+ [a, b, ...[c, d]] = array;
+
+ const obj = {_a:1,_b:2};
+ ({ a, b } = obj); // brackets are required
+ ({ a: a1, b: b1 } = obj);
+
+ const complicatedObject = {
+ a: 1,
+ b: {
+ c: 2,
+ d: {
+ e: 3,
+ f: [4, 5, 6]
+ }
+ },
+ g: [7, 8, 9]
+ };
+
+ const { patron, b: { mafik, d: { e, f: [ , secondF, ...restF ] } }, g: [ firstG, ...restG ] } = complicatedObject;
+ }
+
+ Component.onCompleted: {
+ const myFunction = (myLambda) => {
+ const myObject = {
+ a: 1,
+ b: {c: 2, d: [3, 4, 5] }, e: {
+ f: 6,
+ g: { h: 7, i: [8, 9, 10]
+ }
+ }
+ };
+
+ myLambda(myObject);
+ };
+
+ myFunction(({ a, b: { c, d: [ firstD ] }, e: { f, g: { h, i: [ , secondI ] } } }) => {
+ console.log(a); // 1
+ console.log(c); // 2
+ console.log(firstD); // 3
+ console.log(f); // 6
+ console.log(h); // 7
+ console.log(secondI); // 9
+ });
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml b/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml
index bd0406e595..df26a9b599 100644
--- a/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/objectsSpacing.formatted.qml
@@ -1,6 +1,9 @@
Item {
+ Button {}
+
Button {
+ id: foo
}
height: 360
diff --git a/tests/auto/qml/qmlformat/data/objectsSpacing.qml b/tests/auto/qml/qmlformat/data/objectsSpacing.qml
index 6adc89778c..0239b05145 100644
--- a/tests/auto/qml/qmlformat/data/objectsSpacing.qml
+++ b/tests/auto/qml/qmlformat/data/objectsSpacing.qml
@@ -3,6 +3,10 @@ Item {
Button {
}
+ Button {
+ id: foo
+ }
+
height: 360
width: 360
diff --git a/tests/auto/qml/qmlformat/data/pragma.formatted.js b/tests/auto/qml/qmlformat/data/pragma.formatted.js
new file mode 100644
index 0000000000..3f57e537ac
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/pragma.formatted.js
@@ -0,0 +1,4 @@
+"use strict";
+{
+ function f() {}
+}
diff --git a/tests/auto/qml/qmlformat/data/pragma.formatted.qml b/tests/auto/qml/qmlformat/data/pragma.formatted.qml
new file mode 100644
index 0000000000..143db39888
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/pragma.formatted.qml
@@ -0,0 +1,8 @@
+pragma Singleton
+pragma ComponentBehavior: Bound
+pragma FunctionSignatureBehavior: Enforced
+pragma ValueTypeBehavior: Copy, Addressable
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/pragma.js b/tests/auto/qml/qmlformat/data/pragma.js
new file mode 100644
index 0000000000..b81d52d853
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/pragma.js
@@ -0,0 +1 @@
+"use strict";{function f(){}}
diff --git a/tests/auto/qml/qmlformat/data/pragma.qml b/tests/auto/qml/qmlformat/data/pragma.qml
new file mode 100644
index 0000000000..7469277395
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/pragma.qml
@@ -0,0 +1,8 @@
+pragma Singleton
+ pragma ComponentBehavior: Bound
+ pragma FunctionSignatureBehavior: Enforced
+pragma ValueTypeBehavior: Copy, Addressable
+
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml b/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml
index 94b5877957..9214014889 100644
--- a/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/propertyNames.formatted.qml
@@ -3,11 +3,11 @@ Item {
var copiedItem = "copied value";
var computedItem = "computedName";
var obj = {
- "identifierName": "identifier value",
+ identifierName: "identifier value",
"string name": "string value",
- "Infinity": "numeric value",
+ Infinity: "numeric value",
[computedItem]: "computed value",
- "copiedItem": copiedItem
+ copiedItem
};
}
}
diff --git a/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml b/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml
index b9bcc34e8c..767bfe7e61 100644
--- a/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml
+++ b/tests/auto/qml/qmlformat/data/settings/Example1.formatted_mac_cr.qml
@@ -1 +1 @@
-/* This file is licensed under the not a license license 1. You may not comply 2. Goodbye */ // Importing this is very important import QtQuick 5.15 // Muddling the waters! import QtQuick.Models 3.14 as muddle // Importing that is important too import Z import That import This // THIS IS VERY IMPORTANT! import Y import X.Z import X.Y import A.LLOHA import A.B.B.A // This comment is related to Item Item { // This to id // Also id. (line 2) // This is the third id // fourth id comment id: foo // This to enum enum Foo { A = 3, // This is A B, // This is B C = 4, // This is C D // This is D } // Orphan comment // Another orphan // More orphans property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3] property bool some_bool: false default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool // some_read_only_bool readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0 property bool something_computed: function (x) { const PI = 3, DAYS_PER_YEAR = 365.25; var x = 3 + 2; x["bla"] = 50; // This is an orphan inside something_computed // Are these getting duplicated? // This one to var few! var few = new WhatEver(); x += Math.sin(3); x--; --x; x++; ++x; for (var x = 0; x < 100; x++) { x++; console.log("Foo"); } for (var x in [3, 2, 1]) { y++; console.log("Bar"); } while (true) { console.log("Wee"); } with (foo) { bar; x += 5; } // This is related to with! x3: do { console.log("Hello"); } while (3 == 0) try { dangerous(); } catch (e) { console.log(e); } finally { console.log("What else?"); } switch (x) { case 0: x = 1; break; case 1: x = 5; break; case 4: x = 100; break; } if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); } else { console.log("false"); } if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); x--; } else { console.log("false"); } // Another orphan inside something_computed return "foobar"; }() signal say(string name, bool caps) // This one to aFunc() function aFunc() { var x = 3; return x; } x: 3 // Very cool myFavouriteThings: [ // This is an orphan // This is a cool text Text { }, // This is a cool rectangle Rectangle { } ] // This comment is related to the property animation PropertyAnimation on x { id: foo2 x: 3 y: x + 3 } Component.onCompleted: console.log("Foo!") Text { required property string batman signal boo(int count, int times, real duration) text: "Bla" } } \ No newline at end of file
+/* This file is licensed under the not a license license 1. You may not comply 2. Goodbye */ // Importing this is very important import QtQuick 5.15 // Muddling the waters! import QtQuick.Models 3.14 as muddle // Importing that is important too import Z import That import This // THIS IS VERY IMPORTANT! import Y import X.Z import X.Y import A.LLOHA import A.B.B.A // This comment is related to Item Item { // This to id // Also id. (line 2) // This is the third id // fourth id comment id: foo // This to enum enum Foo { A = 3, // This is A B, // This is B C = 4, // This is C D // This is D } // Orphan comment // Another orphan // More orphans property variant some_array_literal: [30, 20, Math["PI"], [4, 3, 2], "foo", 0.3] property bool some_bool: false default property bool some_default_bool: 500 % 5 !== 0 // some_default_bool // some_read_only_bool readonly property bool some_read_only_bool: Math.sin(3) && (aFunc()[30] + 5) | 2 != 0 property bool something_computed: function (x) { const PI = 3, DAYS_PER_YEAR = 365.25; var x = 3 + 2; x["bla"] = 50; // This is an orphan inside something_computed // Are these getting duplicated? // This one to var few! var few = new WhatEver(); x += Math.sin(3); x--; --x; x++; ++x; for (var x = 0; x < 100; x++) { x++; console.log("Foo"); } for (var x in [3, 2, 1]) { y++; console.log("Bar"); } while (true) { console.log("Wee"); } with (foo) { bar; x += 5; } // This is related to with! x3: do { console.log("Hello"); } while (3 == 0) try { dangerous(); } catch (e) { console.log(e); } finally { console.log("What else?"); } switch (x) { case 0: x = 1; break; case 1: x = 5; break; case 4: x = 100; break; } if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); } else { console.log("false"); } if (x == 50) { console.log("true"); } else if (x == 50) { console.log("other thing"); x--; } else { console.log("false"); } // Another orphan inside something_computed return "foobar"; }() signal say(string name, bool caps) // This one to aFunc() function aFunc() { var x = 3; return x; } x: 3 // Very cool myFavouriteThings: [ // This is an orphan // This is a cool text Text { }, // This is a cool rectangle Rectangle { } ] // This comment is related to the property animation PropertyAnimation on x { id: foo2 x: 3 y: x + 3 } Component.onCompleted: console.log("Foo!") Text { required property string batman signal boo(int count, int times, real duration) text: "Bla" } } \ No newline at end of file
diff --git a/tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js b/tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js
new file mode 100644
index 0000000000..fbdec1038c
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleJSStatement.formatted.js
@@ -0,0 +1 @@
+let v = 1;
diff --git a/tests/auto/qml/qmlformat/data/simpleJSStatement.js b/tests/auto/qml/qmlformat/data/simpleJSStatement.js
new file mode 100644
index 0000000000..d954a87fc0
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleJSStatement.js
@@ -0,0 +1 @@
+let v=1;
diff --git a/tests/auto/qml/qmlformat/data/simpleLoop.formatted.js b/tests/auto/qml/qmlformat/data/simpleLoop.formatted.js
new file mode 100644
index 0000000000..435fc145bf
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleLoop.formatted.js
@@ -0,0 +1,4 @@
+var a = 1;
+for (var ii = 1; ii < 10; ++ii) {
+ a = a * ii;
+}
diff --git a/tests/auto/qml/qmlformat/data/simpleLoop.js b/tests/auto/qml/qmlformat/data/simpleLoop.js
new file mode 100644
index 0000000000..08b172991f
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleLoop.js
@@ -0,0 +1 @@
+var a=1;for(var ii=1;ii<10;++ii){a=a*ii;}
diff --git a/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js
new file mode 100644
index 0000000000..d5b34291e6
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.formatted.js
@@ -0,0 +1,4 @@
+function f() {
+ let a = 0;
+ return a;
+}
diff --git a/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js
new file mode 100644
index 0000000000..c49be5e2bd
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/simpleOnelinerJSFunc.js
@@ -0,0 +1 @@
+function f(){let a=0;return a; }
diff --git a/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml b/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml
index 40cf5068da..923f0642d7 100644
--- a/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/statesAndTransitions.formatted.qml
@@ -2,15 +2,12 @@ QtObject {
id: foo
states: [
- State {
- }
+ State {}
]
transitions: [
- Transition {
- }
+ Transition {}
]
// This needs to be *before* states and transitions after formatting
- Item {
- }
+ Item {}
}
diff --git a/tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js b/tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js
new file mode 100644
index 0000000000..592db7a02b
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/threeFunctions.formattedFuncSpacing.js
@@ -0,0 +1,11 @@
+function one() {
+ var a=1;
+}
+
+function two(a, b) {
+ console.log(a,b);
+}
+
+function three(c) {
+ var a=c;
+}
diff --git a/tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js b/tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js
new file mode 100644
index 0000000000..6575a9fbd8
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/threeFunctions.formattedTabs.js
@@ -0,0 +1,9 @@
+function one() {
+ var a = 1;
+}
+function two(a, b) {
+ console.log(a, b);
+}
+function three(c) {
+ var a = c;
+}
diff --git a/tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js b/tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js
new file mode 100644
index 0000000000..afcf8acf02
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/threeFunctions.formattedW2.js
@@ -0,0 +1,9 @@
+function one() {
+ var a = 1;
+}
+function two(a, b) {
+ console.log(a, b);
+}
+function three(c) {
+ var a = c;
+}
diff --git a/tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js b/tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js
new file mode 100644
index 0000000000..648591f221
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/threeFunctionsOneLine.js
@@ -0,0 +1 @@
+function one() {var a=1;}function two(a, b) {console.log(a,b);}function three(c){var a=c;}
diff --git a/tests/auto/qml/qmlformat/data/twoFunctions.formatted.js b/tests/auto/qml/qmlformat/data/twoFunctions.formatted.js
new file mode 100644
index 0000000000..b7414de053
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/twoFunctions.formatted.js
@@ -0,0 +1,12 @@
+function one() {
+ var a = 1;
+ if (a === true) {
+ a = 5;
+ }
+}
+
+function two(a, b) {
+ for (; b < 5; ++b) {
+ a = a * b;
+ }
+}
diff --git a/tests/auto/qml/qmlformat/data/twoFunctions.js b/tests/auto/qml/qmlformat/data/twoFunctions.js
new file mode 100644
index 0000000000..b410ebd167
--- /dev/null
+++ b/tests/auto/qml/qmlformat/data/twoFunctions.js
@@ -0,0 +1,3 @@
+function one(){var a=1;if (a===true){a=5;}}
+
+function two(a,b){for(;b<5;++b){a=a*b;}}
diff --git a/tests/auto/qml/qmlformat/tst_qmlformat.cpp b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
index c14dd794fc..11d4c9d2c7 100644
--- a/tests/auto/qml/qmlformat/tst_qmlformat.cpp
+++ b/tests/auto/qml/qmlformat/tst_qmlformat.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QDir>
@@ -16,6 +16,25 @@
using namespace QQmlJS::Dom;
+// TODO refactor extension helpers
+const QString QML_EXT = ".qml";
+const QString JS_EXT = ".js";
+const QString MJS_EXT = ".mjs";
+
+static QStringView fileExt(QStringView filename)
+{
+ if (filename.endsWith(QML_EXT)) {
+ return QML_EXT;
+ }
+ if (filename.endsWith(JS_EXT)) {
+ return JS_EXT;
+ }
+ if (filename.endsWith(MJS_EXT)) {
+ return MJS_EXT;
+ }
+ Q_UNREACHABLE();
+};
+
class TestQmlformat: public QQmlDataTest
{
Q_OBJECT
@@ -27,6 +46,7 @@ public:
private Q_SLOTS:
void initTestCase() override;
+ //actually testFormat tests CLI of qmlformat
void testFormat();
void testFormat_data();
@@ -40,10 +60,19 @@ private Q_SLOTS:
void testBackupFileLimit();
+ void testFilesOption_data();
+ void testFilesOption();
+
+ void plainJS_data();
+ void plainJS();
+
+ void ecmascriptModule();
+
private:
QString readTestFile(const QString &path);
+ //TODO(QTBUG-117849) refactor this helper function
QString runQmlformat(const QString &fileToFormat, QStringList args, bool shouldSucceed = true,
- RunOption rOption = RunOption::OnCopy);
+ RunOption rOption = RunOption::OnCopy, QStringView ext = QML_EXT);
QString formatInMemory(const QString &fileToFormat, bool *didSucceed = nullptr,
LineWriterOptions options = LineWriterOptions(),
WriteOutChecks extraChecks = WriteOutCheck::ReparseCompare,
@@ -52,9 +81,11 @@ private:
QString m_qmlformatPath;
QStringList m_excludedDirs;
QStringList m_invalidFiles;
+ QStringList m_ignoreFiles;
QStringList findFiles(const QDir &);
bool isInvalidFile(const QFileInfo &fileName) const;
+ bool isIgnoredFile(const QFileInfo &fileName) const;
};
// Don't fail on warnings because we read a lot of QML files that might intentionally be malformed.
@@ -85,6 +116,7 @@ void TestQmlformat::initTestCase()
m_excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
m_excludedDirs << "doc/src/snippets/qtquick1/imports";
m_excludedDirs << "tests/manual/v4";
+ m_excludedDirs << "tests/manual/qmllsformatter";
m_excludedDirs << "tests/auto/qml/ecmascripttests";
m_excludedDirs << "tests/auto/qml/qmllint";
@@ -126,6 +158,15 @@ void TestQmlformat::initTestCase()
m_invalidFiles << "tests/auto/qml/qqmllanguage/data/nullishCoalescing_RHS_Or.qml";
m_invalidFiles << "tests/auto/qml/qqmllanguage/data/typeAnnotations.2.qml";
m_invalidFiles << "tests/auto/qml/qqmlparser/data/disallowedtypeannotations/qmlnestedfunction.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/emptyFile.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/missingRHS.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/missingRHS.parserfail.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/attachedPropertyMissingRHS.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/groupedPropertyMissingRHS.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/completions/afterDots.qml";
+ m_invalidFiles << "tests/auto/qmlls/modules/data/completions/bindingAfterDot.qml";
+ m_invalidFiles << "tests/auto/qmlls/modules/data/completions/defaultBindingAfterDot.qml";
+ m_invalidFiles << "tests/auto/qmlls/utils/data/qualifiedModule.qml";
// Files that get changed:
// rewrite of import "bla/bla/.." to import "bla"
@@ -145,6 +186,10 @@ void TestQmlformat::initTestCase()
m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon1.qml";
m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon_error1.qml";
m_invalidFiles << "tests/auto/qml/qqmlecmascript/data/incrDecrSemicolon2.qml";
+
+ // These files are too big
+ m_ignoreFiles << "tests/benchmarks/qml/qmldom/data/longQmlFile.qml";
+ m_ignoreFiles << "tests/benchmarks/qml/qmldom/data/deeplyNested.qml";
}
QStringList TestQmlformat::findFiles(const QDir &d)
@@ -157,15 +202,17 @@ QStringList TestQmlformat::findFiles(const QDir &d)
QStringList rv;
- QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
- QDir::Files);
- foreach (const QString &file, files) {
- rv << d.absoluteFilePath(file);
+ const QStringList files = d.entryList(QStringList() << QLatin1String("*.qml"),
+ QDir::Files);
+ for (const QString &file: files) {
+ QString absoluteFilePath = d.absoluteFilePath(file);
+ if (!isIgnoredFile(QFileInfo(absoluteFilePath)))
+ rv << absoluteFilePath;
}
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
- QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
+ const QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
+ QDir::NoSymLinks);
+ for (const QString &dir: dirs) {
QDir sub = d;
sub.cd(dir);
rv << findFiles(sub);
@@ -183,6 +230,15 @@ bool TestQmlformat::isInvalidFile(const QFileInfo &fileName) const
return false;
}
+bool TestQmlformat::isIgnoredFile(const QFileInfo &fileName) const
+{
+ for (const QString &file : m_ignoreFiles) {
+ if (fileName.absoluteFilePath().endsWith(file))
+ return true;
+ }
+ return false;
+}
+
QString TestQmlformat::readTestFile(const QString &path)
{
QFile file(testFile(path));
@@ -304,6 +360,60 @@ void TestQmlformat::testFormat_data()
QTest::newRow("ecmaScriptClassInQml")
<< "ecmaScriptClassInQml.qml"
<< "ecmaScriptClassInQml.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("arrowFunctionWithBinding")
+ << "arrowFunctionWithBinding.qml"
+ << "arrowFunctionWithBinding.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("blanklinesAfterComment")
+ << "blanklinesAfterComment.qml"
+ << "blanklinesAfterComment.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("pragmaValueList")
+ << "pragma.qml"
+ << "pragma.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("objectDestructuring")
+ << "objectDestructuring.qml"
+ << "objectDestructuring.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("destructuringFunctionParameter")
+ << "destructuringFunctionParameter.qml"
+ << "destructuringFunctionParameter.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("ellipsisFunctionArgument")
+ << "ellipsisFunctionArgument.qml"
+ << "ellipsisFunctionArgument.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("importStatements")
+ << "importStatements.qml"
+ << "importStatements.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("arrayEndComma")
+ << "arrayEndComma.qml"
+ << "arrayEndComma.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("escapeChars")
+ << "escapeChars.qml"
+ << "escapeChars.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("javascriptBlock")
+ << "javascriptBlock.qml"
+ << "javascriptBlock.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ QTest::newRow("enumWithValues")
+ << "enumWithValues.qml"
+ << "enumWithValues.formatted.qml" << QStringList{} << RunOption::OnCopy;
+ //plainJS
+ QTest::newRow("nestedLambdaWithIfElse")
+ << "lambdaWithIfElseInsideLambda.js"
+ << "lambdaWithIfElseInsideLambda.formatted.js" << QStringList{} << RunOption::OnCopy;
+
+ QTest::newRow("indentEquals2")
+ << "threeFunctionsOneLine.js"
+ << "threeFunctions.formattedW2.js" << QStringList{"-w=2"} << RunOption::OnCopy;
+
+ QTest::newRow("tabIndents")
+ << "threeFunctionsOneLine.js"
+ << "threeFunctions.formattedTabs.js" << QStringList{"-t"} << RunOption::OnCopy;
+
+ QTest::newRow("normalizedFunctionSpacing")
+ << "threeFunctionsOneLine.js"
+ << "threeFunctions.formattedFuncSpacing.js"
+ << QStringList{ "-n", "--functions-spacing" } << RunOption::OnCopy;
+
+ QTest::newRow("esm_tabIndents")
+ << "mini_esm.mjs"
+ << "mini_esm.formattedTabs.mjs" << QStringList{ "-t" } << RunOption::OnCopy;
}
void TestQmlformat::testFormat()
@@ -313,7 +423,82 @@ void TestQmlformat::testFormat()
QFETCH(QStringList, args);
QFETCH(RunOption, runOption);
- QCOMPARE(runQmlformat(testFile(file), args, true, runOption), readTestFile(fileFormatted));
+ auto formatted = runQmlformat(testFile(file), args, true, runOption, fileExt(file));
+ QEXPECT_FAIL("normalizedFunctionSpacing",
+ "Normalize && function spacing are not yet supported for JS", Abort);
+ auto exp = readTestFile(fileFormatted);
+ QCOMPARE(formatted, exp);
+}
+
+void TestQmlformat::plainJS_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<QString>("fileFormatted");
+
+ QTest::newRow("simpleStatement") << "simpleJSStatement.js"
+ << "simpleJSStatement.formatted.js";
+ QTest::newRow("simpleFunction") << "simpleOnelinerJSFunc.js"
+ << "simpleOnelinerJSFunc.formatted.js";
+ QTest::newRow("simpleLoop") << "simpleLoop.js"
+ << "simpleLoop.formatted.js";
+ QTest::newRow("messyIfStatement") << "messyIfStatement.js"
+ << "messyIfStatement.formatted.js";
+ QTest::newRow("lambdaFunctionWithLoop") << "lambdaFunctionWithLoop.js"
+ << "lambdaFunctionWithLoop.formatted.js";
+ QTest::newRow("lambdaWithIfElse") << "lambdaWithIfElse.js"
+ << "lambdaWithIfElse.formatted.js";
+ QTest::newRow("nestedLambdaWithIfElse") << "lambdaWithIfElseInsideLambda.js"
+ << "lambdaWithIfElseInsideLambda.formatted.js";
+ QTest::newRow("twoFunctions") << "twoFunctions.js"
+ << "twoFunctions.formatted.js";
+ QTest::newRow("pragma") << "pragma.js"
+ << "pragma.formatted.js";
+ QTest::newRow("classConstructor") << "class.js"
+ << "class.formatted.js";
+ QTest::newRow("legacyDirectives") << "directives.js"
+ << "directives.formatted.js";
+ QTest::newRow("legacyDirectivesWithComments") << "directivesWithComments.js"
+ << "directivesWithComments.formatted.js";
+}
+
+void TestQmlformat::plainJS()
+{
+ QFETCH(QString, file);
+ QFETCH(QString, fileFormatted);
+
+ bool wasSuccessful;
+ LineWriterOptions opts;
+#ifdef Q_OS_WIN
+ opts.lineEndings = QQmlJS::Dom::LineWriterOptions::LineEndings::Windows;
+#endif
+ QString output = formatInMemory(testFile(file), &wasSuccessful, opts, WriteOutCheck::None);
+
+ QVERIFY(wasSuccessful && !output.isEmpty());
+
+ // TODO(QTBUG-119404)
+ QEXPECT_FAIL("classConstructor", "see QTBUG-119404", Abort);
+ // TODO(QTBUG-119770)
+ QEXPECT_FAIL("legacyDirectivesWithComments", "see QTBUG-119770", Abort);
+ auto exp = readTestFile(fileFormatted);
+ QCOMPARE(output, exp);
+}
+
+void TestQmlformat::ecmascriptModule()
+{
+ QString file("esm.mjs");
+ QString formattedFile("esm.formatted.mjs");
+
+ bool wasSuccessful;
+ LineWriterOptions opts;
+#ifdef Q_OS_WIN
+ opts.lineEndings = QQmlJS::Dom::LineWriterOptions::LineEndings::Windows;
+#endif
+ QString output = formatInMemory(testFile(file), &wasSuccessful, opts, WriteOutCheck::None);
+
+ QVERIFY(wasSuccessful && !output.isEmpty());
+
+ auto exp = readTestFile(formattedFile);
+ QCOMPARE(output, readTestFile(formattedFile));
}
#if !defined(QTEST_CROSS_COMPILED) // sources not available when cross compiled
@@ -326,9 +511,23 @@ void TestQmlformat::testExample_data()
QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
QString tests = QLatin1String(SRCDIR) + "/../../../../tests/";
+ QStringList exampleFiles;
+ QStringList testFiles;
QStringList files;
- files << findFiles(QDir(examples));
- files << findFiles(QDir(tests));
+ exampleFiles << findFiles(QDir(examples));
+ testFiles << findFiles(QDir(tests));
+
+ // Actually this test is an e2e test and not the unit test.
+ // At the moment of writing, CI lacks providing instruments for the automated tests
+ // which might be time-consuming, as for example this one.
+ // Therefore as part of QTBUG-122990 this test was copied to the /manual/e2e/qml/qmlformat
+ // however very small fraction of the test data is still preserved here for the sake of
+ // testing automatically at least a small part of the examples
+ const int nBatch = 10;
+ files << exampleFiles.mid(0, nBatch) << exampleFiles.mid(exampleFiles.size() / 2, nBatch)
+ << exampleFiles.mid(exampleFiles.size() - nBatch, nBatch);
+ files << testFiles.mid(0, nBatch) << testFiles.mid(exampleFiles.size() / 2, nBatch)
+ << testFiles.mid(exampleFiles.size() - nBatch, nBatch);
for (const QString &file : files)
QTest::newRow(qPrintable(file)) << file;
@@ -417,12 +616,79 @@ void TestQmlformat::testBackupFileLimit()
};
}
+void TestQmlformat::testFilesOption_data()
+{
+ QTest::addColumn<QString>("containerFile");
+ QTest::addColumn<QStringList>("individualFiles");
+
+ QTest::newRow("initial") << "fileListToFormat"
+ << QStringList{"valid1.qml", "invalidEntry:cannot be parsed", "valid2.qml"};
+}
+
+void TestQmlformat::testFilesOption()
+{
+ QFETCH(QString, containerFile);
+ QFETCH(QStringList, individualFiles);
+
+ // Create a temporary directory
+ QTemporaryDir tempDir;
+ tempDir.setAutoRemove(false);
+ QStringList actualFormattedFilesPath;
+
+ // Iterate through files in the source directory and copy them to the temporary directory
+ const auto sourceDir = dataDirectory() + QDir::separator() + "filesOption";
+
+ // Create a file that contains the list of files to be formatted
+ const QString tempFilePath = tempDir.path() + QDir::separator() + containerFile;
+ QFile container(tempFilePath);
+ if (container.open(QIODevice::Text | QIODevice::WriteOnly)) {
+ QTextStream out(&container);
+
+ for (const auto &file : individualFiles) {
+ QString destinationFilePath = tempDir.path() + QDir::separator() + file;
+ if (QFile::copy(sourceDir + QDir::separator() + file, destinationFilePath))
+ actualFormattedFilesPath << destinationFilePath;
+ out << destinationFilePath << "\n";
+ }
+
+ container.close();
+ } else {
+ QFAIL("Cannot create temp test file\n");
+ return;
+ }
+
+ {
+ QProcess process;
+ process.start(m_qmlformatPath, QStringList{"-F", tempFilePath});
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ }
+
+ const auto readFile = [](const QString &filePath){
+ QFile file(filePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "Error on opening the file " << filePath;
+ return QByteArray{};
+ }
+
+ return file.readAll();
+ };
+
+ for (const auto &filePath : actualFormattedFilesPath) {
+ auto expectedFormattedFile = QFileInfo(filePath).fileName();
+ const auto expectedFormattedFilePath = sourceDir + QDir::separator() +
+ expectedFormattedFile.replace(".qml", ".formatted.qml");
+
+ QCOMPARE(readFile(filePath), readFile(expectedFormattedFilePath));
+ }
+}
+
QString TestQmlformat::runQmlformat(const QString &fileToFormat, QStringList args,
- bool shouldSucceed, RunOption rOptions)
+ bool shouldSucceed, RunOption rOptions, QStringView ext)
{
// Copy test file to temporary location
QTemporaryDir tempDir;
- const QString tempFile = tempDir.path() + QDir::separator() + "to_format.qml";
+ const QString tempFile = (tempDir.path() + QDir::separator() + "to_format") % ext;
if (rOptions == RunOption::OnCopy) {
QFile::copy(fileToFormat, tempFile);
@@ -446,7 +712,8 @@ QString TestQmlformat::runQmlformat(const QString &fileToFormat, QStringList arg
QFile temp(tempFile);
- temp.open(QIODevice::ReadOnly);
+ if (!temp.open(QIODevice::ReadOnly))
+ qFatal("Could not open %s", qPrintable(tempFile));
QString formatted = QString::fromUtf8(temp.readAll());
return formatted;
@@ -456,19 +723,17 @@ QString TestQmlformat::formatInMemory(const QString &fileToFormat, bool *didSucc
LineWriterOptions options, WriteOutChecks extraChecks,
WriteOutChecks largeChecks)
{
- DomItem env = DomEnvironment::create(
+ auto env = DomEnvironment::create(
QStringList(), // as we load no dependencies we do not need any paths
QQmlJS::Dom::DomEnvironment::Option::SingleThreaded
| QQmlJS::Dom::DomEnvironment::Option::NoDependencies);
DomItem tFile;
- env.loadFile(
- fileToFormat, QString(),
- [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; },
- LoadOption::DefaultLoad);
- env.loadPendingDependencies();
+ env->loadFile(FileToLoad::fromFileSystem(env, fileToFormat),
+ [&tFile](Path, const DomItem &, const DomItem &newIt) { tFile = newIt; });
+ env->loadPendingDependencies();
MutableDomItem myFile = tFile.field(Fields::currentItem);
- DomItem writtenOut;
+ bool writtenOut;
QString resultStr;
if (myFile.field(Fields::isValid).value().toBool()) {
WriteOutChecks checks = extraChecks;
@@ -486,7 +751,7 @@ QString TestQmlformat::formatInMemory(const QString &fileToFormat, bool *didSucc
res.flush();
}
if (didSucceed)
- *didSucceed = bool(writtenOut);
+ *didSucceed = writtenOut;
return resultStr;
}
diff --git a/tests/auto/qml/qmlimportscanner/CMakeLists.txt b/tests/auto/qml/qmlimportscanner/CMakeLists.txt
index 042e8fd3d5..a1a22d7309 100644
--- a/tests/auto/qml/qmlimportscanner/CMakeLists.txt
+++ b/tests/auto/qml/qmlimportscanner/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmlimportscanner Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlimportscanner LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json b/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json
index a688511ed0..8860b629d1 100644
--- a/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json
+++ b/tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json
@@ -10,29 +10,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -40,9 +36,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -50,8 +46,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json b/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json
index 084e4354b3..085d0bf6d4 100644
--- a/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json
+++ b/tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json
@@ -5,24 +5,20 @@
"type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -30,9 +26,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -40,8 +36,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json b/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json
index c50fe5ab51..c0cad1e3a1 100644
--- a/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json
+++ b/tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json
@@ -10,29 +10,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -40,9 +36,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -50,8 +46,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json b/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json
index 447c664785..3abcd58b1c 100644
--- a/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/Drawer.qml.json
@@ -1,23 +1,19 @@
[
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -25,9 +21,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -35,8 +31,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Imports.json b/tests/auto/qml/qmlimportscanner/data/Imports.json
index 5e23e7b1ad..ee6903b1da 100644
--- a/tests/auto/qml/qmlimportscanner/data/Imports.json
+++ b/tests/auto/qml/qmlimportscanner/data/Imports.json
@@ -10,29 +10,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -40,9 +36,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -50,8 +46,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json b/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json
index 06df9295fe..0e733b551f 100644
--- a/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json
@@ -1,39 +1,29 @@
[
{
"classname": "QtQuick2Plugin",
- "name": "QtQuick",
"linkTarget": "Qt6::qtquick2plugin",
+ "name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
- },
- {
- "name": "Things",
- "plugin": "doesNotExistPlugin",
- "relativePath": "Things",
"type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -41,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -51,8 +41,14 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
+ },
+ {
+ "name": "Things",
+ "plugin": "doesNotExistPlugin",
+ "relativePath": "Things",
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json b/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json
index 213798d04d..d0d427f595 100644
--- a/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json
+++ b/tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json
@@ -5,29 +5,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -35,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -45,8 +41,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Simple.qml.json b/tests/auto/qml/qmlimportscanner/data/Simple.qml.json
index 213798d04d..d0d427f595 100644
--- a/tests/auto/qml/qmlimportscanner/data/Simple.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/Simple.qml.json
@@ -5,29 +5,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -35,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -45,8 +41,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Singleton.json b/tests/auto/qml/qmlimportscanner/data/Singleton.json
index cb24e57f60..1813d01efe 100644
--- a/tests/auto/qml/qmlimportscanner/data/Singleton.json
+++ b/tests/auto/qml/qmlimportscanner/data/Singleton.json
@@ -10,29 +10,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -40,9 +36,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -50,8 +46,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/Things.json b/tests/auto/qml/qmlimportscanner/data/Things.json
index ee5caecfda..a6081c89d8 100644
--- a/tests/auto/qml/qmlimportscanner/data/Things.json
+++ b/tests/auto/qml/qmlimportscanner/data/Things.json
@@ -11,29 +11,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -41,9 +37,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -51,8 +47,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json b/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json
index 2d2b602fb1..7094d1c8e3 100644
--- a/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json
@@ -1,27 +1,19 @@
[
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
- "name": "QtQml",
- "plugin": "qmlmetaplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
- },
- {
"classname": "QtQmlPlugin",
"linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
+ "name": "QtQml",
"plugin": "qmlplugin",
"pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "prefer": ":/qt-project.org/imports/QtQml/",
+ "relativePath": "QtQml",
+ "type": "module"
},
{
- "name": "Methods.js",
- "type": "javascript"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -29,9 +21,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -39,8 +31,12 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
+ },
+ {
+ "name": "Methods.js",
+ "type": "javascript"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/localImport.qml.json b/tests/auto/qml/qmlimportscanner/data/localImport.qml.json
index ee5caecfda..a6081c89d8 100644
--- a/tests/auto/qml/qmlimportscanner/data/localImport.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/localImport.qml.json
@@ -11,29 +11,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -41,9 +37,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -51,8 +47,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json b/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json
index 213798d04d..d0d427f595 100644
--- a/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json
@@ -5,29 +5,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -35,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -45,8 +41,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json b/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json
index ee5caecfda..a6081c89d8 100644
--- a/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json
@@ -11,29 +11,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -41,9 +37,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -51,8 +47,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json b/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json
index 447c664785..3abcd58b1c 100644
--- a/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json
+++ b/tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json
@@ -1,23 +1,19 @@
[
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -25,9 +21,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -35,8 +31,8 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/data/rootPath.json b/tests/auto/qml/qmlimportscanner/data/rootPath.json
index 942c8d6000..41ce0f9a45 100644
--- a/tests/auto/qml/qmlimportscanner/data/rootPath.json
+++ b/tests/auto/qml/qmlimportscanner/data/rootPath.json
@@ -5,29 +5,25 @@
"name": "QtQuick",
"plugin": "qtquick2plugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQuick/",
"relativePath": "QtQuick",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQuick/"
+ "type": "module"
},
{
- "classname": "QtQmlMetaPlugin",
- "linkTarget": "Qt6::QmlMeta",
+ "classname": "QtQmlPlugin",
+ "linkTarget": "Qt6::qmlplugin",
"name": "QtQml",
- "plugin": "qmlmetaplugin",
+ "plugin": "qmlplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/",
"relativePath": "QtQml",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/"
+ "type": "module"
},
{
- "classname": "QtQmlPlugin",
- "linkTarget": "Qt6::qmlplugin",
- "name": "QtQml.Base",
- "plugin": "qmlplugin",
- "pluginIsOptional": true,
- "relativePath": "QtQml/Base",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Base/"
+ "name": "QML",
+ "prefer": ":/qt-project.org/imports/QML/",
+ "relativePath": "QML",
+ "type": "module"
},
{
"classname": "QtQmlModelsPlugin",
@@ -35,9 +31,9 @@
"name": "QtQml.Models",
"plugin": "modelsplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/Models/",
"relativePath": "QtQml/Models",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/Models/"
+ "type": "module"
},
{
"classname": "QtQmlWorkerScriptPlugin",
@@ -45,9 +41,9 @@
"name": "QtQml.WorkerScript",
"plugin": "workerscriptplugin",
"pluginIsOptional": true,
+ "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/",
"relativePath": "QtQml/WorkerScript",
- "type": "module",
- "prefer": ":/qt-project.org/imports/QtQml/WorkerScript/"
+ "type": "module"
},
{
"name": "QTBUG-45916.js",
@@ -68,12 +64,12 @@
"type": "module"
},
{
- "name": "Imports",
- "relativePath": "Imports",
+ "name": "Module",
"type": "module"
},
{
- "name": "Module",
+ "name": "Imports",
+ "relativePath": "Imports",
"type": "module"
}
]
diff --git a/tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp b/tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp
index 02cebc349c..49b3418401 100644
--- a/tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp
+++ b/tests/auto/qml/qmlimportscanner/tst_qmlimportscanner.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QProcess>
@@ -149,7 +149,7 @@ void TestQmlimportscanner::runQmlimportscanner(const QString &mode, const QStrin
QVERIFY(generated.isArray());
QFile imports(resultFile);
- imports.open(QIODevice::ReadOnly);
+ QVERIFY(imports.open(QIODevice::ReadOnly));
QJsonDocument expected = QJsonDocument::fromJson(imports.readAll(), &error);
QCOMPARE(error.error, QJsonParseError::NoError);
QVERIFY(expected.isArray());
diff --git a/tests/auto/qml/qmllint/CMakeLists.txt b/tests/auto/qml/qmllint/CMakeLists.txt
index 422e7a08b3..5a3e2d9c0d 100644
--- a/tests/auto/qml/qmllint/CMakeLists.txt
+++ b/tests/auto/qml/qmllint/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmllint Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmllint LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -42,9 +48,15 @@ qt_internal_extend_target(tst_qmllint CONDITION NOT ANDROID AND NOT IOS
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
+if (TARGET qmllint)
+ add_dependencies(tst_qmllint Qt::qmllint)
+endif()
+
if (TARGET qmljsrootgen)
qt_internal_extend_target(tst_qmllint
DEFINES
QT_QMLJSROOTGEN_PRESENT
)
+
+ add_dependencies(tst_qmllint Qt::qmljsrootgen)
endif()
diff --git a/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml
new file mode 100644
index 0000000000..4141884af9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string myProperty
+}
diff --git a/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir
new file mode 100644
index 0000000000..b6e958d657
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir
@@ -0,0 +1,2 @@
+module ModuleInImportPath
+A 1.0 A.qml
diff --git a/tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml b/tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml
new file mode 100644
index 0000000000..8b20fe9ae9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml
@@ -0,0 +1,14 @@
+import QtQuick
+
+Item {
+ id: item
+ visible: true
+
+ enum Mode {
+ Hours,
+ Minutes
+ }
+
+ property int mode: item.Mode.Hours
+ property string s: item.mode === IsNotAnEntryOfEnum.Mode.Hour ? "green" : "tomato"
+}
diff --git a/tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes b/tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes
new file mode 100644
index 0000000000..b5baa22357
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes
@@ -0,0 +1,31 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "AppManager.h"
+ name: "AppManager"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["LocaleTest/AppManager 1.0"]
+ isCreatable: false
+ isSingleton: true
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "primaryLocale"
+ type: "QLocale"
+ read: "getPrimaryLocale"
+ notify: "primaryLocaleChanged"
+ index: 0
+ isReadonly: true
+ }
+ Signal {
+ name: "primaryLocaleChanged"
+ Parameter { type: "QLocale" }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/LocaleTest/qmldir b/tests/auto/qml/qmllint/data/LocaleTest/qmldir
new file mode 100644
index 0000000000..2dc0799d5b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/LocaleTest/qmldir
@@ -0,0 +1,3 @@
+module LocaleTest
+typeinfo localeTest.qmltypes
+depends QtQml
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml b/tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml
new file mode 100644
index 0000000000..5dda9a4d12
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property int o: 12
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc b/tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc
new file mode 100644
index 0000000000..b6df21ec4c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/qt/qml/MultiDirectory">
+ <file>qmldir</file>
+ <file>Outer.qml</file>
+ <file>qml/qmldir</file>
+ <file>qml/Inner.qml</file>
+ <file>qml/pages/qmldir</file>
+ <file>qml/pages/Page.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml b/tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml
new file mode 100644
index 0000000000..01b7c331d9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+Outer {
+ o: 25
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml
new file mode 100644
index 0000000000..7efc889fb1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+Inner {
+ o: 32
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir
new file mode 100644
index 0000000000..56ef19d41b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir
@@ -0,0 +1 @@
+prefer :/qt/qml/MultiDirectory/
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir b/tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir
new file mode 100644
index 0000000000..56ef19d41b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir
@@ -0,0 +1 @@
+prefer :/qt/qml/MultiDirectory/
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qmldir b/tests/auto/qml/qmllint/data/MultiDirectory/qmldir
new file mode 100644
index 0000000000..699132dc4f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qmldir
@@ -0,0 +1,5 @@
+module MultiDirectory
+prefer :/qt/qml/MultiDirectory
+Outer 1.0 Outer.qml
+Inner 1.0 qml/Inner.qml
+Page 1.0 qml/pages/Page.qml
diff --git a/tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes b/tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes
new file mode 100644
index 0000000000..92c1b0953e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes
@@ -0,0 +1,112 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "mystyle.h"
+ name: "MyStyle"
+ accessSemantics: "reference"
+ prototype: "QQuickAttachedPropertyPropagator"
+ exports: ["MyStyle/MyStyle 1.0", "MyStyle/MyStyle 254.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [256, 65024]
+ attachedType: "MyStyle"
+ Enum {
+ name: "Theme"
+ values: ["Light", "Dark"]
+ }
+ Property {
+ name: "theme"
+ type: "Theme"
+ read: "theme"
+ write: "setTheme"
+ reset: "resetTheme"
+ notify: "themeChanged"
+ index: 0
+ isFinal: true
+ }
+ Property {
+ name: "windowColor"
+ type: "QColor"
+ read: "windowColor"
+ notify: "themeChanged"
+ index: 1
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "windowTextColor"
+ type: "QColor"
+ read: "windowTextColor"
+ notify: "themeChanged"
+ index: 2
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "buttonColor"
+ type: "QColor"
+ read: "buttonColor"
+ notify: "themeChanged"
+ index: 3
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "buttonTextColor"
+ type: "QColor"
+ read: "buttonTextColor"
+ notify: "themeChanged"
+ index: 4
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "toolBarColor"
+ type: "QColor"
+ read: "toolBarColor"
+ notify: "themeChanged"
+ index: 5
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "popupColor"
+ type: "QColor"
+ read: "popupColor"
+ notify: "themeChanged"
+ index: 6
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "popupBorderColor"
+ type: "QColor"
+ read: "popupBorderColor"
+ notify: "themeChanged"
+ index: 7
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "backgroundDimColor"
+ type: "QColor"
+ read: "backgroundDimColor"
+ notify: "themeChanged"
+ index: 8
+ isReadonly: true
+ isFinal: true
+ }
+ Signal { name: "themeChanged" }
+ }
+ Component {
+ file: "qquickattachedpropertypropagator.h"
+ name: "QQuickAttachedPropertyPropagator"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml b/tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml
new file mode 100644
index 0000000000..5920797d9b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml
@@ -0,0 +1,12 @@
+import QtQuick
+import QtQuick.Templates as T
+import MyStyle
+
+T.ToolBar {
+ id: control
+
+ property color c: MyStyle.toolBarColor
+ background: Rectangle {
+ color: MyStyle.toolBarColor
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/MyStyle/qmldir b/tests/auto/qml/qmllint/data/MyStyle/qmldir
new file mode 100644
index 0000000000..8cc4246f7c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MyStyle/qmldir
@@ -0,0 +1,4 @@
+module MyStyle
+typeinfo MyStyle.qmltypes
+ToolBar 254.0 ToolBar.qml
+import QtQuick.Controls.Material
diff --git a/tests/auto/qml/qmllint/data/NeedImportPath.qml b/tests/auto/qml/qmllint/data/NeedImportPath.qml
new file mode 100644
index 0000000000..0a63b58f7c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/NeedImportPath.qml
@@ -0,0 +1,5 @@
+import ModuleInImportPath
+
+A {
+ myProperty: "Hello World"
+}
diff --git a/tests/auto/qml/qmllint/data/Qtbug111015/qmldir b/tests/auto/qml/qmllint/data/Qtbug111015/qmldir
new file mode 100644
index 0000000000..3bf1d48e13
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Qtbug111015/qmldir
@@ -0,0 +1,3 @@
+module Qtbug111015
+typeinfo qtbug111015.qmltypes
+import QtQml
diff --git a/tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes b/tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes
new file mode 100644
index 0000000000..7de521a379
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Qtbug111015/qtbug111015.qmltypes
@@ -0,0 +1,20 @@
+import QtQuick.tooling 1.2
+
+Module {
+ Component {
+ file: "typewithjsonobjectlist.h"
+ name: "TypeWithJsonObjectList"
+ exports: ["QmlLintTestLib/TypeWithJsonObjectList 1.0"]
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property { name: "jsonObjectList"; type: "QJsonObject"; isList: true; read: "getJsonObjectList"; index: 0; isReadonly: true }
+ }
+ Component {
+ file: "typewithjsonarray.h"
+ name: "TypeWithJsonArray"
+ exports: ["QmlLintTestLib/TypeWithJsonArray 1.0"]
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property { name: "jsonArray"; type: "QJsonArray"; read: "getJsonArray"; index: 0; isReadonly: true }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/SharedFunctions.js b/tests/auto/qml/qmllint/data/SharedFunctions.js
new file mode 100644
index 0000000000..3398d2d6d7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/SharedFunctions.js
@@ -0,0 +1,5 @@
+.pragma library
+
+function setColorAlpha(color, alpha) {
+ return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha)
+}
diff --git a/tests/auto/qml/qmllint/data/StringToDateTime/qmldir b/tests/auto/qml/qmllint/data/StringToDateTime/qmldir
new file mode 100644
index 0000000000..761f613496
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/StringToDateTime/qmldir
@@ -0,0 +1,3 @@
+module StringToDateTime
+typeinfo stringToDateTime.qmltypes
+import QtQml
diff --git a/tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes b/tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes
new file mode 100644
index 0000000000..e0f13fa2ec
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes
@@ -0,0 +1,14 @@
+import QtQuick.tooling 1.2
+Module {
+ Component {
+ file: "stringToQDateTime.h"
+ name: "StringToDateTimeComponent"
+ exports: ["QmlLintTestLib/StringToDateTime 1.0"]
+ exportMetaObjectRevisions: [256]
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property { name: "aDate"; type: "QDate"; read: "getADate"; write: "setADate" }
+ Property { name: "aTime"; type: "QTime"; read: "getATime"; write: "setATime" }
+ Property { name: "aDateTime"; type: "QDateTime"; read: "getADateTime"; write: "setADateTime" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes b/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes
index 04ca30c184..77ad6a3cef 100644
--- a/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes
+++ b/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes
@@ -178,4 +178,24 @@ Module {
exportMetaObjectRevisions: [256]
Method { name: "createObject"; isJavaScriptFunction: true }
}
+ Component {
+ file: "variantMapLookup.h"
+ name: "VariantMapLookupFoo"
+ prototype: "QObject"
+ exports: ["TestTypes/VariantMapLookupFoo 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "data"
+ type: "QVariantMap"
+ read: "data"
+ index: 0
+ }
+ }
+ Component {
+ file: "foo.h"
+ name: "Foo"
+ prototype: "QObject"
+ exports: ["TestTypes/Foo 1.0"]
+ Method { name: "print" }
+ }
}
diff --git a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
index 9d36d91a90..3b0da602ac 100644
--- a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
+++ b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
@@ -12,6 +12,7 @@ Module {
exports: ["Things/SomethingEntirelyStrange 1.0"]
Enum {
name: "AnEnum"
+ isScoped: true
values: {
"AAA": 0,
"BBB": 1,
@@ -20,7 +21,7 @@ Module {
}
Enum {
name: "TheEnum"
- scoped: false
+ isScoped: false
values: {
"V1": 0,
"V2": 1
@@ -96,4 +97,21 @@ Module {
Property { name: "foo"; type: "string" }
hasCustomParser: true
}
+ Component {
+ file: "mediaplayer-qml.h"
+ name: "MediaPlayerStateMachine"
+ accessSemantics: "value"
+ exports: ["Mediaplayer/MediaPlayerStateMachine 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [256]
+ }
+ Component {
+ file: "constinvokable.h"
+ name: "ConstInvokable"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["Things/ConstInvokable 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method { name: "getObject"; type: "QObject"; isPointer: true; isTypeConstant: true }
+ }
}
diff --git a/tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml b/tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml
new file mode 100644
index 0000000000..197b74fa60
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ Rectangle {
+ property real divisor: 0
+
+ Timer {
+ onTriggered: divisor = 1
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml b/tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml
new file mode 100644
index 0000000000..198e2146f5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ Rectangle {
+ property real divisor: 0
+
+ Timer {
+ onTriggered: function() {"use strict"; divisor = 1 }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/addressableValue.qml b/tests/auto/qml/qmllint/data/addressableValue.qml
new file mode 100644
index 0000000000..9b93728ed8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/addressableValue.qml
@@ -0,0 +1,8 @@
+pragma ValueTypeBehavior: Addressable
+
+import QtQml
+import scripts
+
+QtObject {
+ property var v: "red" as vvv
+}
diff --git a/tests/auto/qml/qmllint/data/attachedImportUse.qml b/tests/auto/qml/qmllint/data/attachedImportUse.qml
new file mode 100644
index 0000000000..56b4e2bf7c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/attachedImportUse.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ id: control
+ objectName: control.BirthdayParty.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml b/tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml
new file mode 100644
index 0000000000..cdc2b28c07
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+Item {
+
+ property alias innerObj: {
+ id: inner
+ }
+
+}
diff --git a/tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes b/tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes
new file mode 100644
index 0000000000..96f98dd14e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes
@@ -0,0 +1,513 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -builtins'
+
+Module {
+ dependencies: []
+ Component {
+ name: "Qt"
+ Enum {
+ name: "GlobalColor"
+ values: {
+ "color0": 0,
+ "color1": 1,
+ "black": 2,
+ "white": 3,
+ "darkGray": 4,
+ "gray": 5,
+ "lightGray": 6,
+ "red": 7,
+ "green": 8,
+ "blue": 9,
+ "cyan": 10,
+ "magenta": 11,
+ "yellow": 12,
+ "darkRed": 13,
+ "darkGreen": 14,
+ "darkBlue": 15,
+ "darkCyan": 16,
+ "darkMagenta": 17,
+ "darkYellow": 18,
+ "transparent": 19
+ }
+ }
+ Enum {
+ name: "KeyboardModifiers"
+ values: {
+ "NoModifier": 0,
+ "ShiftModifier": 33554432,
+ "ControlModifier": 67108864,
+ "AltModifier": 134217728,
+ "MetaModifier": 268435456,
+ "KeypadModifier": 536870912,
+ "GroupSwitchModifier": 1073741824,
+ "KeyboardModifierMask": -33554432
+ }
+ }
+ Enum {
+ name: "MouseButtons"
+ values: {
+ "NoButton": 0,
+ "LeftButton": 1,
+ "RightButton": 2,
+ "MidButton": 4, // For backwards compatibility
+ "MiddleButton": 4,
+ "BackButton": 8,
+ "XButton1": 8,
+ "ExtraButton1": 8,
+ "ForwardButton": 16,
+ "XButton2": 16,
+ "ExtraButton2": 16,
+ "TaskButton": 32,
+ "ExtraButton3": 32,
+ "ExtraButton4": 64,
+ "ExtraButton5": 128,
+ "ExtraButton6": 256,
+ "ExtraButton7": 512,
+ "ExtraButton8": 1024,
+ "ExtraButton9": 2048,
+ "ExtraButton10": 4096,
+ "ExtraButton11": 8192,
+ "ExtraButton12": 16384,
+ "ExtraButton13": 32768,
+ "ExtraButton14": 65536,
+ "ExtraButton15": 131072,
+ "ExtraButton16": 262144,
+ "ExtraButton17": 524288,
+ "ExtraButton18": 1048576,
+ "ExtraButton19": 2097152,
+ "ExtraButton20": 4194304,
+ "ExtraButton21": 8388608,
+ "ExtraButton22": 16777216,
+ "ExtraButton23": 33554432,
+ "ExtraButton24": 67108864,
+ "AllButtons": 134217727,
+ "MaxMouseButton": 67108864,
+ "MouseButtonMask": -1
+ }
+ }
+ Enum {
+ name: "Orientation"
+ values: {
+ "Horizontal": 1,
+ "Vertical": 2
+ }
+ }
+ Enum {
+ name: "Orientations"
+ values: {
+ "Horizontal": 1,
+ "Vertical": 2
+ }
+ }
+ Enum {
+ name: "FocusPolicy"
+ values: {
+ "NoFocus": 0,
+ "TabFocus": 1,
+ "ClickFocus": 2,
+ "StrongFocus": 11,
+ "WheelFocus": 15
+ }
+ }
+ Enum {
+ name: "TabFocusBehavior"
+ values: {
+ "NoTabFocus": 0,
+ "TabFocusTextControls": 1,
+ "TabFocusListControls": 2,
+ "TabFocusAllControls": 255
+ }
+ }
+ Enum {
+ name: "SortOrder"
+ values: {
+ "AscendingOrder": 0,
+ "DescendingOrder": 1
+ }
+ }
+ Enum {
+ name: "SplitBehavior"
+ values: {
+ "KeepEmptyParts": 0,
+ "SkipEmptyParts": 1
+ }
+ }
+ Enum {
+ name: "Alignment"
+ values: {
+ "AlignLeft": 1,
+ "AlignLeading": 1,
+ "AlignRight": 2,
+ "AlignTrailing": 2,
+ "AlignHCenter": 4,
+ "AlignJustify": 8,
+ "AlignAbsolute": 16,
+ "AlignHorizontal_Mask": 31,
+ "AlignTop": 32,
+ "AlignBottom": 64,
+ "AlignVCenter": 128,
+ "AlignBaseline": 256,
+ "AlignVertical_Mask": 480,
+ "AlignCenter": 132
+ }
+ }
+ Enum {
+ name: "TextFlag"
+ values: {
+ "TextSingleLine": 256,
+ "TextDontClip": 512,
+ "TextExpandTabs": 1024,
+ "TextShowMnemonic": 2048,
+ "TextWordWrap": 4096,
+ "TextWrapAnywhere": 8192,
+ "TextDontPrint": 16384,
+ "TextIncludeTrailingSpaces": 134217728,
+ "TextHideMnemonic": 32768,
+ "TextJustificationForced": 65536,
+ "TextForceLeftToRight": 131072,
+ "TextForceRightToLeft": 262144,
+ "TextLongestVariant": 524288,
+ "TextBypassShaping": 1048576
+ }
+ }
+ Enum {
+ name: "TextElideMode"
+ values: {
+ "ElideLeft": 0,
+ "ElideRight": 1,
+ "ElideMiddle": 2,
+ "ElideNone": 3
+ }
+ }
+ Enum {
+ name: "WindowType"
+ values: {
+ "Widget": 0,
+ "Window": 1,
+ "Dialog": 3,
+ "Sheet": 5,
+ "Drawer": 7,
+ "Popup": 9,
+ "Tool": 11,
+ "ToolTip": 13,
+ "SplashScreen": 15,
+ "Desktop": 17,
+ "SubWindow": 18,
+ "ForeignWindow": 33,
+ "CoverWindow": 65,
+ "WindowType_Mask": 255,
+ "MSWindowsFixedSizeDialogHint": 256,
+ "MSWindowsOwnDC": 512,
+ "BypassWindowManagerHint": 1024,
+ "X11BypassWindowManagerHint": 1024,
+ "FramelessWindowHint": 2048,
+ "WindowTitleHint": 4096,
+ "WindowSystemMenuHint": 8192,
+ "WindowMinimizeButtonHint": 16384,
+ "WindowMaximizeButtonHint": 32768,
+ "WindowMinMaxButtonsHint": 49152,
+ "WindowContextHelpButtonHint": 65536,
+ "WindowShadeButtonHint": 131072,
+ "WindowStaysOnTopHint": 262144,
+ "WindowTransparentForInput": 524288,
+ "WindowOverridesSystemGestures": 1048576,
+ "WindowDoesNotAcceptFocus": 2097152,
+ "MaximizeUsingFullscreenGeometryHint": 4194304,
+ "CustomizeWindowHint": 33554432,
+ "WindowStaysOnBottomHint": 67108864,
+ "WindowCloseButtonHint": 134217728,
+ "MacWindowToolBarButtonHint": 268435456,
+ "BypassGraphicsProxyWidget": 536870912,
+ "NoDropShadowWindowHint": 1073741824,
+ "WindowFullscreenButtonHint": -2147483648
+ }
+ }
+ Enum {
+ name: "WindowFlags"
+ values: {
+ "Widget": 0,
+ "Window": 1,
+ "Dialog": 3,
+ "Sheet": 5,
+ "Drawer": 7,
+ "Popup": 9,
+ "Tool": 11,
+ "ToolTip": 13,
+ "SplashScreen": 15,
+ "Desktop": 17,
+ "SubWindow": 18,
+ "ForeignWindow": 33,
+ "CoverWindow": 65,
+ "WindowType_Mask": 255,
+ "MSWindowsFixedSizeDialogHint": 256,
+ "MSWindowsOwnDC": 512,
+ "BypassWindowManagerHint": 1024,
+ "X11BypassWindowManagerHint": 1024,
+ "FramelessWindowHint": 2048,
+ "WindowTitleHint": 4096,
+ "WindowSystemMenuHint": 8192,
+ "WindowMinimizeButtonHint": 16384,
+ "WindowMaximizeButtonHint": 32768,
+ "WindowMinMaxButtonsHint": 49152,
+ "WindowContextHelpButtonHint": 65536,
+ "WindowShadeButtonHint": 131072,
+ "WindowStaysOnTopHint": 262144,
+ "WindowTransparentForInput": 524288,
+ "WindowOverridesSystemGestures": 1048576,
+ "WindowDoesNotAcceptFocus": 2097152,
+ "MaximizeUsingFullscreenGeometryHint": 4194304,
+ "CustomizeWindowHint": 33554432,
+ "WindowStaysOnBottomHint": 67108864,
+ "WindowCloseButtonHint": 134217728,
+ "MacWindowToolBarButtonHint": 268435456,
+ "BypassGraphicsProxyWidget": 536870912,
+ "NoDropShadowWindowHint": 1073741824,
+ "WindowFullscreenButtonHint": -2147483648
+ }
+ }
+ Enum {
+ name: "WindowState"
+ values: {
+ "WindowNoState": 0,
+ "WindowMinimized": 1,
+ "WindowMaximized": 2,
+ "WindowFullScreen": 4,
+ "WindowActive": 8
+ }
+ }
+ Enum {
+ name: "WindowStates"
+ values: {
+ "WindowNoState": 0,
+ "WindowMinimized": 1,
+ "WindowMaximized": 2,
+ "WindowFullScreen": 4,
+ "WindowActive": 8
+ }
+ }
+ Enum {
+ name: "ApplicationState"
+ values: {
+ "ApplicationSuspended": 0,
+ "ApplicationHidden": 1,
+ "ApplicationInactive": 2,
+ "ApplicationActive": 4
+ }
+ }
+ Enum {
+ name: "ScreenOrientation"
+ values: {
+ "PrimaryOrientation": 0,
+ "PortraitOrientation": 1,
+ "LandscapeOrientation": 2,
+ "InvertedPortraitOrientation": 4,
+ "InvertedLandscapeOrientation": 8
+ }
+ }
+ Enum {
+ name: "ScreenOrientations"
+ values: {
+ "PrimaryOrientation": 0,
+ "PortraitOrientation": 1,
+ "LandscapeOrientation": 2,
+ "InvertedPortraitOrientation": 4,
+ "InvertedLandscapeOrientation": 8
+ }
+ }
+ Enum {
+ name: "WidgetAttribute"
+ values: {
+ "WA_Disabled": 0,
+ "WA_UnderMouse": 1,
+ "WA_MouseTracking": 2,
+ "WA_ContentsPropagated": 3,
+ "WA_OpaquePaintEvent": 4,
+ "WA_NoBackground": 4,
+ "WA_StaticContents": 5,
+ "WA_LaidOut": 7,
+ "WA_PaintOnScreen": 8,
+ "WA_NoSystemBackground": 9,
+ "WA_UpdatesDisabled": 10,
+ "WA_Mapped": 11,
+ "WA_MacNoClickThrough": 12,
+ "WA_InputMethodEnabled": 14,
+ "WA_WState_Visible": 15,
+ "WA_WState_Hidden": 16,
+ "WA_ForceDisabled": 32,
+ "WA_KeyCompression": 33,
+ "WA_PendingMoveEvent": 34,
+ "WA_PendingResizeEvent": 35,
+ "WA_SetPalette": 36,
+ "WA_SetFont": 37,
+ "WA_SetCursor": 38,
+ "WA_NoChildEventsFromChildren": 39,
+ "WA_WindowModified": 41,
+ "WA_Resized": 42,
+ "WA_Moved": 43,
+ "WA_PendingUpdate": 44,
+ "WA_InvalidSize": 45,
+ "WA_MacBrushedMetal": 46,
+ "WA_MacMetalStyle": 46,
+ "WA_CustomWhatsThis": 47,
+ "WA_LayoutOnEntireRect": 48,
+ "WA_OutsideWSRange": 49,
+ "WA_GrabbedShortcut": 50,
+ "WA_TransparentForMouseEvents": 51,
+ "WA_PaintUnclipped": 52,
+ "WA_SetWindowIcon": 53,
+ "WA_NoMouseReplay": 54,
+ "WA_DeleteOnClose": 55,
+ "WA_RightToLeft": 56,
+ "WA_SetLayoutDirection": 57,
+ "WA_NoChildEventsForParent": 58,
+ "WA_ForceUpdatesDisabled": 59,
+ "WA_WState_Created": 60,
+ "WA_WState_CompressKeys": 61,
+ "WA_WState_InPaintEvent": 62,
+ "WA_WState_Reparented": 63,
+ "WA_WState_ConfigPending": 64,
+ "WA_WState_Polished": 66,
+ "WA_WState_DND": 67,
+ "WA_WState_OwnSizePolicy": 68,
+ "WA_WState_ExplicitShowHide": 69,
+ "WA_ShowModal": 70,
+ "WA_MouseNoMask": 71,
+ "WA_GroupLeader": 72,
+ "WA_NoMousePropagation": 73,
+ "WA_Hover": 74,
+ "WA_InputMethodTransparent": 75,
+ "WA_QuitOnClose": 76,
+ "WA_KeyboardFocusChange": 77,
+ "WA_AcceptDrops": 78,
+ "WA_DropSiteRegistered": 79,
+ "WA_ForceAcceptDrops": 79,
+ "WA_WindowPropagation": 80,
+ "WA_NoX11EventCompression": 81,
+ "WA_TintedBackground": 82,
+ "WA_X11OpenGLOverlay": 83,
+ "WA_AlwaysShowToolTips": 84,
+ "WA_MacOpaqueSizeGrip": 85,
+ "WA_SetStyle": 86,
+ "WA_SetLocale": 87,
+ "WA_MacShowFocusRect": 88,
+ "WA_MacNormalSize": 89,
+ "WA_MacSmallSize": 90,
+ "WA_MacMiniSize": 91,
+ "WA_LayoutUsesWidgetRect": 92,
+ "WA_StyledBackground": 93,
+ "WA_MSWindowsUseDirect3D": 94,
+ "WA_CanHostQMdiSubWindowTitleBar": 95,
+ "WA_MacAlwaysShowToolWindow": 96,
+ "WA_StyleSheet": 97,
+ "WA_ShowWithoutActivating": 98,
+ "WA_X11BypassTransientForHint": 99,
+ "WA_NativeWindow": 100,
+ "WA_DontCreateNativeAncestors": 101,
+ "WA_MacVariableSize": 102,
+ "WA_DontShowOnScreen": 103,
+ "WA_X11NetWmWindowTypeDesktop": 104,
+ "WA_X11NetWmWindowTypeDock": 105,
+ "WA_X11NetWmWindowTypeToolBar": 106,
+ "WA_X11NetWmWindowTypeMenu": 107,
+ "WA_X11NetWmWindowTypeUtility": 108,
+ "WA_X11NetWmWindowTypeSplash": 109,
+ "WA_X11NetWmWindowTypeDialog": 110,
+ "WA_X11NetWmWindowTypeDropDownMenu": 111,
+ "WA_X11NetWmWindowTypePopupMenu": 112,
+ "WA_X11NetWmWindowTypeToolTip": 113,
+ "WA_X11NetWmWindowTypeNotification": 114,
+ "WA_X11NetWmWindowTypeCombo": 115,
+ "WA_X11NetWmWindowTypeDND": 116,
+ "WA_MacFrameworkScaled": 117,
+ "WA_SetWindowModality": 118,
+ "WA_WState_WindowOpacitySet": 119,
+ "WA_TranslucentBackground": 120,
+ "WA_AcceptTouchEvents": 121,
+ "WA_WState_AcceptedTouchBeginEvent": 122,
+ "WA_TouchPadAcceptSingleTouchEvents": 123,
+ "WA_X11DoNotAcceptFocus": 126,
+ "WA_MacNoShadow": 127,
+ "WA_AlwaysStackOnTop": 128,
+ "WA_TabletTracking": 129,
+ "WA_ContentsMarginsRespectsSafeArea": 130,
+ "WA_StyleSheetTarget": 131,
+ "WA_AttributeCount": 132
+ }
+ }
+ Enum {
+ name: "ApplicationAttribute"
+ values: {
+ "AA_ImmediateWidgetCreation": 0,
+ "AA_MSWindowsUseDirect3DByDefault": 1,
+ "AA_DontShowIconsInMenus": 2,
+ "AA_NativeWindows": 3,
+ "AA_DontCreateNativeWidgetSiblings": 4,
+ "AA_PluginApplication": 5,
+ "AA_MacPluginApplication": 5,
+ "AA_DontUseNativeMenuBar": 6,
+ "AA_MacDontSwapCtrlAndMeta": 7,
+ "AA_Use96Dpi": 8,
+ "AA_X11InitThreads": 10,
+ "AA_SynthesizeTouchForUnhandledMouseEvents": 11,
+ "AA_SynthesizeMouseForUnhandledTouchEvents": 12,
+ "AA_UseHighDpiPixmaps": 13,
+ "AA_ForceRasterWidgets": 14,
+ "AA_UseDesktopOpenGL": 15,
+ "AA_UseOpenGLES": 16,
+ "AA_UseSoftwareOpenGL": 17,
+ "AA_ShareOpenGLContexts": 18,
+ "AA_SetPalette": 19,
+ "AA_EnableHighDpiScaling": 20,
+ "AA_DisableHighDpiScaling": 21,
+ "AA_UseStyleSheetPropagationInWidgetStyles": 22,
+ "AA_DontUseNativeDialogs": 23,
+ "AA_SynthesizeMouseForUnhandledTabletEvents": 24,
+ "AA_CompressHighFrequencyEvents": 25,
+ "AA_DontCheckOpenGLContextThreadAffinity": 26,
+ "AA_DisableShaderDiskCache": 27,
+ "AA_DontShowShortcutsInContextMenus": 28,
+ "AA_CompressTabletEvents": 29,
+ "AA_DisableWindowContextHelpButton": 30,
+ "AA_DisableSessionManager": 31,
+ "AA_AttributeCount": 32
+ }
+ }
+ Enum {
+ name: "ImageConversionFlags"
+ values: {
+ "ColorMode_Mask": 3,
+ "AutoColor": 0,
+ "ColorOnly": 3,
+ "MonoOnly": 2,
+ "AlphaDither_Mask": 12,
+ "ThresholdAlphaDither": 0,
+ "OrderedAlphaDither": 4,
+ "DiffuseAlphaDither": 8,
+ "NoAlpha": 12,
+ "Dither_Mask": 48,
+ "DiffuseDither": 0,
+ "OrderedDither": 16,
+ "ThresholdDither": 32,
+ "DitherMode_Mask": 192,
+ "AutoDither": 0,
+ "PreferDither": 64,
+ "AvoidDither": 128,
+ "NoOpaqueDetection": 256,
+ "NoFormatConversion": 512
+ }
+ }
+ Enum {
+ name: "BGMode"
+ values: {
+ "TransparentMode": 0,
+ "OpaqueMode": 1
+ }
+ }
+ }
+ Component { name: "QEasingCurve"; prototype: "QQmlEasingValueType" }
+}
diff --git a/tests/auto/qml/qmllint/data/coercetovoid.qml b/tests/auto/qml/qmllint/data/coercetovoid.qml
new file mode 100644
index 0000000000..f1b593ea3a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/coercetovoid.qml
@@ -0,0 +1,8 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ function touchThisAndReturnSomething(x: int) {
+ return x + 1;
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/customParser.qml b/tests/auto/qml/qmllint/data/customParser.qml
index a83ae7e823..324ca20953 100644
--- a/tests/auto/qml/qmllint/data/customParser.qml
+++ b/tests/auto/qml/qmllint/data/customParser.qml
@@ -7,11 +7,11 @@ Rectangle {
states: [
State {
name: "red_color"
- PropertyChanges { target: root; color: "red" }
+ PropertyChanges { root.color: "red" }
},
State {
name: "blue_color"
- PropertyChanges { target: root; color: "blue" }
+ PropertyChanges { root.color: "blue" }
}
]
}
diff --git a/tests/auto/qml/qmllint/data/dontCheckJSTypes.qml b/tests/auto/qml/qmllint/data/dontCheckJSTypes.qml
new file mode 100644
index 0000000000..dc582936b9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/dontCheckJSTypes.qml
@@ -0,0 +1,11 @@
+import QtQuick
+
+import "SharedFunctions.js" as Functions
+
+Item {
+ Rectangle {
+ color: Functions.setColorAlpha(Qt.color("orange"), 0.15)
+ x: Functions.setColorAlpha.asdfg
+ y: Functions.asdfg
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/findMemberPrint.qml b/tests/auto/qml/qmllint/data/findMemberPrint.qml
new file mode 100644
index 0000000000..69146eb06b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/findMemberPrint.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+import TestTypes
+
+QtObject {
+ property var foooooooo: Foo {
+ id: foo
+ }
+
+ function f(): void {
+ foo.print()
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/generalizedGroupHint.qml b/tests/auto/qml/qmllint/data/generalizedGroupHint.qml
new file mode 100644
index 0000000000..5fec03f7f3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/generalizedGroupHint.qml
@@ -0,0 +1,23 @@
+import QtQuick
+
+Window {
+ width: 640
+ height: 480
+ visible: true
+ title: 'Resolve my color type'
+
+ Item {
+ id: foo
+
+ states: [
+ State {
+ PropertyChanges {
+ target: foo
+ myColor: Qt.rgba(0.5, 0.5, 0.5, 0.16)
+ }
+ }
+ ]
+
+ property color myColor: 'black'
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/groupedAttachedLayout.qml b/tests/auto/qml/qmllint/data/groupedAttachedLayout.qml
new file mode 100644
index 0000000000..7cfe98d4f8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/groupedAttachedLayout.qml
@@ -0,0 +1,20 @@
+import QtQuick
+import QtQuick.Layouts
+
+Window {
+ id: root
+
+ Rectangle {
+ id: redRect
+ }
+
+ Item {
+ states: [
+ State {
+ PropertyChanges {
+ redRect.Layout.fillWidth: true
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml
new file mode 100644
index 0000000000..d018110b86
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml
@@ -0,0 +1,11 @@
+import QtQuick
+import QtQuick.Controls
+
+Window {
+ width: 640; height: 480
+ visible: true
+
+ Button {
+ text: "a"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir
new file mode 100644
index 0000000000..acb456ffd9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir
@@ -0,0 +1,3 @@
+module moduleWithQrc
+prefer :/qt/qml/moduleWithQrc/
+
diff --git a/tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc
new file mode 100644
index 0000000000..43d3ec805c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/qt/qml/qmllint65/">
+ <file alias="main.qml">moduleWithQrc/main.qml</file>
+ </qresource>
+</RCC>
+
diff --git a/tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc b/tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc
new file mode 100644
index 0000000000..cb362e2d55
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/qt/qml/qmllint65">
+ <file alias="qmldir">moduleWithQrc/qmldir</file>
+ </qresource>
+</RCC>
+
diff --git a/tests/auto/qml/qmllint/data/importNonexistentFile.qml b/tests/auto/qml/qmllint/data/importNonexistentFile.qml
new file mode 100644
index 0000000000..847023936a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/importNonexistentFile.qml
@@ -0,0 +1,3 @@
+import "¯\(ツ)/¯:/invalid/url"
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/importNullDevice.qml b/tests/auto/qml/qmllint/data/importNullDevice.qml
new file mode 100644
index 0000000000..5ff3090d75
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/importNullDevice.qml
@@ -0,0 +1,3 @@
+import "/dev/null"
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/initReadonly.qml b/tests/auto/qml/qmllint/data/initReadonly.qml
index 5a3cafff23..a9a2a0016b 100644
--- a/tests/auto/qml/qmllint/data/initReadonly.qml
+++ b/tests/auto/qml/qmllint/data/initReadonly.qml
@@ -2,4 +2,5 @@ import QtQml
QtObject {
readonly property int i: 14
+ readonly property int j: i + 20
}
diff --git a/tests/auto/qml/qmllint/data/inlineComponent.qml b/tests/auto/qml/qmllint/data/inlineComponent.qml
index ce6998a980..364d5319de 100644
--- a/tests/auto/qml/qmllint/data/inlineComponent.qml
+++ b/tests/auto/qml/qmllint/data/inlineComponent.qml
@@ -1,6 +1,7 @@
import QtQuick 2.0
Item {
+ component MyIC: IC {}
component IC : QtObject {}
QtObject {
component IC2: QtObject {}
diff --git a/tests/auto/qml/qmllint/data/invalidIdLookup.qml b/tests/auto/qml/qmllint/data/invalidIdLookup.qml
new file mode 100644
index 0000000000..b351e5cfea
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/invalidIdLookup.qml
@@ -0,0 +1,10 @@
+import Things
+import QtQml
+
+QtObject {
+ property MediaPlayerStateMachine m: MediaPlayerStateMachine {
+ id: stateMachine
+ }
+
+ objectName: stateMachine.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml b/tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml
new file mode 100644
index 0000000000..89c52e0e52
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/jsonArrayIsRecognized.qml
@@ -0,0 +1,8 @@
+import QtQuick
+import Qtbug111015 1.0
+
+Item {
+ TypeWithJsonArray {
+ jsonArray: []
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml b/tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml
new file mode 100644
index 0000000000..0a96fa9f92
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/jsonObjectIsRecognized.qml
@@ -0,0 +1,8 @@
+import QtQuick
+import Qtbug111015 1.0
+
+Item {
+ TypeWithJsonObjectList {
+ jsonObjectList: []
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/locale.qml b/tests/auto/qml/qmllint/data/locale.qml
new file mode 100644
index 0000000000..4ff9e6392c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/locale.qml
@@ -0,0 +1,6 @@
+import QtQml
+import LocaleTest
+
+QtObject {
+ property int monday: AppManager.primaryLocale.firstDayOfWeek
+}
diff --git a/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml
new file mode 100644
index 0000000000..14c716c35d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml
@@ -0,0 +1,9 @@
+import QtQuick as test
+
+test.Rectangle { // crashed qqmljsimportvisitor
+ id: mainRect
+ width: 100
+ height: 100
+ visible: true
+ rotation: 11
+}
diff --git a/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml
new file mode 100644
index 0000000000..4e03d8091d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml
@@ -0,0 +1,9 @@
+import QtQuick as test
+
+test.Item {
+ property test.color c
+
+ property var p: test.Grid {}
+
+ component IC: test.Rectangle {}
+}
diff --git a/tests/auto/qml/qmllint/data/multifix.fixed.qml b/tests/auto/qml/qmllint/data/multifix.fixed.qml
new file mode 100644
index 0000000000..d2188f2318
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multifix.fixed.qml
@@ -0,0 +1,14 @@
+pragma ComponentBehavior: Bound
+import QtQml
+
+QtObject {
+ id: root
+
+ property Component cursorDelegate: QtObject {
+ objectName: root.objectName
+ }
+
+ property Component background: QtObject {
+ objectName: root.objectName
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/multifix.qml b/tests/auto/qml/qmllint/data/multifix.qml
new file mode 100644
index 0000000000..5f05ae7e62
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multifix.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ id: root
+
+ property Component cursorDelegate: QtObject {
+ objectName: root.objectName
+ }
+
+ property Component background: QtObject {
+ objectName: root.objectName
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/notQmlRootMethods.qml b/tests/auto/qml/qmllint/data/notQmlRootMethods.qml
new file mode 100644
index 0000000000..6d067d572d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/notQmlRootMethods.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ function a() { self.deleteLater(); }
+ function b() { self.destroyed(); }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml b/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml
index 2a51cceac3..b6c0f59c7f 100644
--- a/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml
+++ b/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml
@@ -5,5 +5,6 @@ Item {
anchors.horizontalCenter: undefined
anchors.verticalCenter: undefined
anchors.baseline: undefined
+ Component.onCompleted: anchors.bottom = undefined
}
}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml
new file mode 100644
index 0000000000..fa7d4ef1ac
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Rectangle {
+ State {
+ name: "test"
+ PropertyChanges { target: root; color: "blue" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml
new file mode 100644
index 0000000000..94873463f1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Window {
+ Item {
+ id: foo
+ property color myColor: 'black'
+
+ states: [
+ State {
+ PropertyChanges {
+ target: foo
+ myColor: Qt.rgba(0.5, 0.5, 0.5, 0.16)
+ notThere: "a"
+ }
+ }
+ ]
+
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/qEventPoint.qml b/tests/auto/qml/qmllint/data/qEventPoint.qml
new file mode 100644
index 0000000000..086e710b48
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qEventPoint.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+TapHandler {
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onSingleTapped: (eventPoint, button) => {
+ console.log("Single tap at", eventPoint, "with button", button)
+ }
+ onTapped: console.log("tapped")
+}
diff --git a/tests/auto/qml/qmllint/data/qmlRootMethods.qml b/tests/auto/qml/qmllint/data/qmlRootMethods.qml
new file mode 100644
index 0000000000..5541de3a32
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qmlRootMethods.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ objectName: self.toString()
+
+ Component.onCompleted: {
+ self.destroy();
+ self.destroy(25);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
index 4847fc9196..ad88f1c58c 100644
--- a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
+++ b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
@@ -2,5 +2,5 @@ import Things 1.0
Something {
property var a: SomethingEntirelyStrange {}
- property var b: SomethingEntirelyStrange.AAA
+ property var b: SomethingEntirelyStrange.AnEnum.AAA
}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml
new file mode 100644
index 0000000000..de142337b4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml
@@ -0,0 +1,9 @@
+import QtQml
+import QtQuick
+
+QtObject {
+ id: root
+ component Comp : Item { }
+ property Comp c: Comp{ }
+ function comp() { return root.c }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml
new file mode 100644
index 0000000000..0585ceceb2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+QtObject {
+ function enumeration() { return Text.AlignRight }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml
new file mode 100644
index 0000000000..dc03311e73
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ function f() { }
+ function method() { return f }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml
new file mode 100644
index 0000000000..bb79978d85
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ id: root
+ property int i: 1
+ function prop() { return root.i }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml
new file mode 100644
index 0000000000..78f02a8b67
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ function type() { return 1 + 1 }
+}
diff --git a/tests/auto/qml/qmllint/data/scriptInTemplate.qml b/tests/auto/qml/qmllint/data/scriptInTemplate.qml
new file mode 100644
index 0000000000..ba333dcd3e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scriptInTemplate.qml
@@ -0,0 +1,6 @@
+import QtQml
+import scripts
+
+QtObject {
+ objectName: `Result: ${Foo.getText()}`
+}
diff --git a/tests/auto/qml/qmllint/data/scripts/Foo.js b/tests/auto/qml/qmllint/data/scripts/Foo.js
new file mode 100644
index 0000000000..1d5106f733
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scripts/Foo.js
@@ -0,0 +1,6 @@
+.pragma library
+
+function getText() {
+ return "whohoooooo"
+}
+
diff --git a/tests/auto/qml/qmllint/data/scripts/qmldir b/tests/auto/qml/qmllint/data/scripts/qmldir
new file mode 100644
index 0000000000..b4bf844348
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scripts/qmldir
@@ -0,0 +1,4 @@
+module scripts
+typeinfo scripts.qmltypes
+Foo 1.0 Foo.js
+
diff --git a/tests/auto/qml/qmllint/data/scripts/scripts.qmltypes b/tests/auto/qml/qmllint/data/scripts/scripts.qmltypes
new file mode 100644
index 0000000000..ebbfc41eb2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scripts/scripts.qmltypes
@@ -0,0 +1,22 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "value.h"
+ name: "ValueType"
+ accessSemantics: "value"
+ exports: ["scripts/vvv 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method {
+ name: "ValueType"
+ isConstructor: true
+ Parameter { name: "v"; type: "QString" }
+ }
+ Method { name: "ValueType"; isCloned: true; isConstructor: true }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/scriptstring.qml b/tests/auto/qml/qmllint/data/scriptstring.qml
new file mode 100644
index 0000000000..733434e924
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scriptstring.qml
@@ -0,0 +1,73 @@
+import QtQuick
+
+Window {
+ id: root
+
+ Rectangle {
+ id: main
+
+ MouseArea {
+ id: mouse
+ property int clickCount: 0
+ onClicked: {
+ clickCount++
+
+ switch ( clickCount % 3 ) {
+ case 1 :
+ main.state = "middleState"
+ break
+ case 2 :
+ main.state = "rightState"
+ break
+ default :
+ main.state = "leftState"
+ }
+ }
+ }
+
+ Rectangle {
+ id: mover
+ anchors {
+ left: undefined
+ right: undefined
+ horizontalCenter: undefined
+ top: main.top
+ bottom: main.bottom
+ }
+ }
+
+ states: [
+ State {
+ name: "leftState"
+ AnchorChanges {
+ target: mover
+ anchors.left: main.left
+ anchors.right: undefined
+ anchors.horizontalCenter: undefined
+ }
+ },
+ State {
+ name: "middleState"
+ AnchorChanges {
+ target: mover
+ anchors {
+ left: undefined
+ right: undefined
+ horizontalCenter: main.horizontalCenter
+ }
+ }
+ },
+ State {
+ name: "rightState"
+ AnchorChanges {
+ target: mover
+ anchors {
+ left: undefined
+ right: main.right
+ horizontalCenter: undefined
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini b/tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini
new file mode 100644
index 0000000000..a72e0e29e2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini
@@ -0,0 +1,2 @@
+[Warnings]
+TestWarning=disable
diff --git a/tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml b/tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml
new file mode 100644
index 0000000000..b9250a2d11
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ Rectangle {
+ radius: 5
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/something.qml b/tests/auto/qml/qmllint/data/something.qml
new file mode 100644
index 0000000000..38998f606d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/something.qml
@@ -0,0 +1,2 @@
+import ModuleInImportPath
+A {}
diff --git a/tests/auto/qml/qmllint/data/storeNameMethod.qml b/tests/auto/qml/qmllint/data/storeNameMethod.qml
new file mode 100644
index 0000000000..fca02b288f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/storeNameMethod.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ Rectangle {
+
+ Timer {
+ function foo() {}
+ onTriggered: foo = 1
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/stringToDateTime.qml b/tests/auto/qml/qmllint/data/stringToDateTime.qml
new file mode 100644
index 0000000000..dc4bd6cda5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/stringToDateTime.qml
@@ -0,0 +1,7 @@
+import StringToDateTime
+
+StringToDateTime {
+ aDate: "2023-03-29"
+ aTime: "15:10:41"
+ aDateTime: "2023-03-29 15:10:41"
+}
diff --git a/tests/auto/qml/qmllint/data/untitled/components/Foo.qml b/tests/auto/qml/qmllint/data/untitled/components/Foo.qml
new file mode 100644
index 0000000000..10e5741900
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/untitled/components/Foo.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Text {
+ text: "Here I am!"
+}
diff --git a/tests/auto/qml/qmllint/data/untitled/main.qml b/tests/auto/qml/qmllint/data/untitled/main.qml
new file mode 100644
index 0000000000..cf8980ab55
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/untitled/main.qml
@@ -0,0 +1,9 @@
+pragma Strict
+
+import QtQuick
+import 'qrc:/untitled/components' as C
+
+Window {
+ id: root
+ C.Foo {}
+}
diff --git a/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc b/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc
new file mode 100644
index 0000000000..0ad0d57fbb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/untitled/">
+ <file alias="main.qml">main.qml</file>
+ <file alias="components/Foo.qml">components/Foo.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmllint/data/useConstInvokable.qml b/tests/auto/qml/qmllint/data/useConstInvokable.qml
new file mode 100644
index 0000000000..4f89e89918
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/useConstInvokable.qml
@@ -0,0 +1,5 @@
+import Things
+
+ConstInvokable {
+ objectName: getObject().objectName
+}
diff --git a/tests/auto/qml/qmllint/data/validLiterals.qml b/tests/auto/qml/qmllint/data/validLiterals.qml
index 4f8c575cd3..55792eaae2 100644
--- a/tests/auto/qml/qmllint/data/validLiterals.qml
+++ b/tests/auto/qml/qmllint/data/validLiterals.qml
@@ -29,9 +29,9 @@ QtObject {
property date date1: "2021-08-13T14:16:21.435Z"
- property point point1: "1,2"
+ property point point1: ({ x: 1, y: 2 })
- property size size1: "50x50"
+ property size size1: ({ width: 50, height: 50 })
- property rect rect1: "10,20,30x30"
+ property rect rect1: ({ x: 10, y: 20, width: 30, height: 30 })
}
diff --git a/tests/auto/qml/qmllint/data/valueTypesFromString.qml b/tests/auto/qml/qmllint/data/valueTypesFromString.qml
new file mode 100644
index 0000000000..fc013f858f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/valueTypesFromString.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ property point p: "30,50"
+ property rect p3: "10, 20, 30x50"
+ property size p4: "30x50"
+}
diff --git a/tests/auto/qml/qmllint/data/variantMapLookup.qml b/tests/auto/qml/qmllint/data/variantMapLookup.qml
new file mode 100644
index 0000000000..7f50879932
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/variantMapLookup.qml
@@ -0,0 +1,13 @@
+pragma Strict
+import TestTypes
+import QtQuick
+
+Item {
+ VariantMapLookupFoo {
+ id: moo
+ }
+ Component.onCompleted: {
+ moo.data.value = 5
+ moo.data["value"] = 6
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/writeListProperty.qml b/tests/auto/qml/qmllint/data/writeListProperty.qml
new file mode 100644
index 0000000000..8015fdf51b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/writeListProperty.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ id: self
+ property Item a: Item { id: a }
+ Component.onCompleted: self.data = [ a ]
+}
diff --git a/tests/auto/qml/qmllint/lintplugin.cpp b/tests/auto/qml/qmllint/lintplugin.cpp
index 47279adcaa..58b174cb6b 100644
--- a/tests/auto/qml/qmllint/lintplugin.cpp
+++ b/tests/auto/qml/qmllint/lintplugin.cpp
@@ -1,11 +1,11 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "lintplugin.h"
using namespace Qt::StringLiterals;
-static constexpr LoggerWarningId plugin { "testPlugin.test" };
+static constexpr QQmlSA::LoggerWarningId plugin{ "testPlugin.test" };
class ElementTest : public QQmlSA::ElementPass
{
@@ -17,25 +17,25 @@ public:
bool shouldRun(const QQmlSA::Element &element) override
{
- return element->baseType() == m_rectangle;
+ return element.baseType() == m_rectangle;
}
void run(const QQmlSA::Element &element) override
{
- auto property = element->property(u"radius"_s);
- if (!property.isValid() || element->property(u"radius"_s).typeName() != u"double") {
- emitWarning(u"Failed to verify radius property", plugin, element->sourceLocation());
+ auto property = element.property(u"radius"_s);
+ if (!property.isValid() || element.property(u"radius"_s).typeName() != u"double") {
+ emitWarning(u"Failed to verify radius property", plugin, element.sourceLocation());
return;
}
- auto bindings = element->propertyBindings(u"radius"_s);
+ auto bindings = element.propertyBindings(u"radius"_s);
if (bindings.isEmpty() || bindings.constFirst().numberValue() != 5) {
emitWarning(u"Failed to verify radius property binding", plugin,
- element->sourceLocation());
+ element.sourceLocation());
return;
}
- emitWarning(u"ElementTest OK", plugin, element->sourceLocation());
+ emitWarning(u"ElementTest OK", plugin, element.sourceLocation());
}
private:
@@ -48,37 +48,37 @@ public:
PropertyTest(QQmlSA::PassManager *manager) : QQmlSA::PropertyPass(manager) { }
void onBinding(const QQmlSA::Element &element, const QString &propertyName,
- const QQmlJSMetaPropertyBinding &binding, const QQmlSA::Element &bindingScope,
+ const QQmlSA::Binding &binding, const QQmlSA::Element &bindingScope,
const QQmlSA::Element &value) override
{
emitWarning(u"Saw binding on %1 property %2 with value %3 (and type %4) in scope %5"_s
- .arg(element->baseTypeName(), propertyName,
+ .arg(element.baseTypeName(), propertyName,
value.isNull()
? u"NULL"_s
- : (value->internalName().isNull() ? value->baseTypeName()
- : value->baseTypeName()))
- .arg(binding.bindingType())
- .arg(bindingScope->baseTypeName()),
- plugin, bindingScope->sourceLocation());
+ : (value.name().isNull() ? value.baseTypeName()
+ : value.name()))
+ .arg(qToUnderlying(binding.bindingType()))
+ .arg(bindingScope.baseTypeName()),
+ plugin, bindingScope.sourceLocation());
}
void onRead(const QQmlSA::Element &element, const QString &propertyName,
- const QQmlSA::Element &readScope, QQmlJS::SourceLocation location) override
+ const QQmlSA::Element &readScope, QQmlSA::SourceLocation location) override
{
emitWarning(u"Saw read on %1 property %2 in scope %3"_s.arg(
- element->baseTypeName(), propertyName, readScope->baseTypeName()),
+ element.baseTypeName(), propertyName, readScope.baseTypeName()),
plugin, location);
}
void onWrite(const QQmlSA::Element &element, const QString &propertyName,
const QQmlSA::Element &value, const QQmlSA::Element &writeScope,
- QQmlJS::SourceLocation location) override
+ QQmlSA::SourceLocation location) override
{
emitWarning(u"Saw write on %1 property %2 with value %3 in scope %4"_s.arg(
- element->baseTypeName(), propertyName,
- (value->internalName().isNull() ? value->baseTypeName()
- : value->internalName()),
- writeScope->baseTypeName()),
+ element.baseTypeName(), propertyName,
+ (value.name().isNull() ? value.baseTypeName()
+ : value.name()),
+ writeScope.baseTypeName()),
plugin, location);
}
};
@@ -109,7 +109,7 @@ private:
void LintPlugin::registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement)
{
- if (!rootElement->filePath().endsWith(u"_pluginTest.qml"))
+ if (!rootElement.filePath().endsWith(u"_pluginTest.qml"))
return;
manager->registerElementPass(std::make_unique<ElementTest>(manager));
diff --git a/tests/auto/qml/qmllint/lintplugin.h b/tests/auto/qml/qmllint/lintplugin.h
index 76733ca7a7..c121657456 100644
--- a/tests/auto/qml/qmllint/lintplugin.h
+++ b/tests/auto/qml/qmllint/lintplugin.h
@@ -1,12 +1,12 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef LINTPLUGIN_H
#define LINTPLUGIN_H
#include <QtPlugin>
#include <QtCore/qobject.h>
-#include <QtQmlCompiler/private/qqmlsa_p.h>
+#include <QtQmlCompiler/qqmlsa.h>
class LintPlugin : public QObject, public QQmlSA::LintPlugin
{
diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp
index a5e906ce9a..7f7b5317cc 100644
--- a/tests/auto/qml/qmllint/tst_qmllint.cpp
+++ b/tests/auto/qml/qmllint/tst_qmllint.cpp
@@ -1,6 +1,6 @@
// Copyright (C) 2016 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sergio Martins <sergio.martins@kdab.com>
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QProcess>
@@ -43,6 +43,11 @@ public:
Flags flags = {};
};
+ struct Environment : public QList<QPair<QString, QString>>
+ {
+ using QList<QPair<QString, QString>>::QList;
+ };
+
private Q_SLOTS:
void initTestCase() override;
@@ -73,12 +78,19 @@ private Q_SLOTS:
void autoqmltypes();
void resources();
+ void multiDirectory();
+
void requiredProperty();
void settingsFile();
void additionalImplicitImport();
+ void qrcUrlImport();
+
+ void incorrectImportFromHost_data();
+ void incorrectImportFromHost();
+
void attachedPropertyReuse();
void missingBuiltinsNoCrash();
@@ -90,11 +102,21 @@ private Q_SLOTS:
void lintModule();
void testLineEndings();
+ void valueTypesFromString();
+
+ void ignoreSettingsNotCommandLineOptions();
+ void backslashedQmldirPath();
+
+ void environment_data();
+ void environment();
+
+ void maxWarnings();
#if QT_CONFIG(library)
void testPlugin();
void quickPlugin();
#endif
+
private:
enum DefaultImportOption { NoDefaultImports, UseDefaultImports };
enum ContainOption { StringNotContained, StringContained };
@@ -105,17 +127,24 @@ private:
enum LintType { LintFile, LintModule };
+ static QStringList warningsShouldFailArgs() {
+ static QStringList args {"-W", "0"};
+ return args;
+ }
+
QString runQmllint(const QString &fileToLint, std::function<void(QProcess &)> handleResult,
const QStringList &extraArgs = QStringList(), bool ignoreSettings = true,
- bool addImportDirs = true, bool absolutePath = true);
+ bool addImportDirs = true, bool absolutePath = true,
+ const Environment &env = {});
QString runQmllint(const QString &fileToLint, bool shouldSucceed,
const QStringList &extraArgs = QStringList(), bool ignoreSettings = true,
- bool addImportDirs = true, bool absolutePath = true);
+ bool addImportDirs = true, bool absolutePath = true,
+ const Environment &env = {});
void callQmllint(const QString &fileToLint, bool shouldSucceed, QJsonArray *warnings = nullptr,
QStringList importDirs = {}, QStringList qmltypesFiles = {},
QStringList resources = {},
DefaultImportOption defaultImports = UseDefaultImports,
- QList<QQmlJSLogger::Category> *categories = nullptr, bool autoFixable = false,
+ QList<QQmlJS::LoggerCategory> *categories = nullptr, bool autoFixable = false,
LintType type = LintFile);
void searchWarnings(const QJsonArray &warnings, const QString &string,
@@ -137,7 +166,7 @@ private:
void runTest(const QString &testFile, const Result &result, QStringList importDirs = {},
QStringList qmltypesFiles = {}, QStringList resources = {},
DefaultImportOption defaultImports = UseDefaultImports,
- QList<QQmlJSLogger::Category> *categories = nullptr);
+ QList<QQmlJS::LoggerCategory> *categories = nullptr);
QString m_qmllintPath;
QString m_qmljsrootgenPath;
@@ -258,6 +287,12 @@ void TestQmllint::testUnqualified_data()
Message {
QStringLiteral("index is implicitly injected into this delegate. "
"Add a required property instead.") } } };
+ QTest::newRow("storeSloppy")
+ << QStringLiteral("UnqualifiedInStoreSloppy.qml")
+ << Result{ { Message{ QStringLiteral("Unqualified access"), 9, 26} } };
+ QTest::newRow("storeStrict")
+ << QStringLiteral("UnqualifiedInStoreStrict.qml")
+ << Result{ { Message{ QStringLiteral("Unqualified access"), 9, 52} } };
}
void TestQmllint::testUnknownCausesFail()
@@ -355,12 +390,12 @@ void TestQmllint::verifyJsRoot()
QString currentJsRootContent, generatedJsRootContent;
QFile currentJsRoot(currentJsRootPath);
- QVERIFY(currentJsRoot.open(QFile::ReadOnly));
+ QVERIFY(currentJsRoot.open(QFile::ReadOnly | QIODevice::Text));
currentJsRootContent = QString::fromUtf8(currentJsRoot.readAll());
currentJsRoot.close();
QFile generatedJsRoot(dir.path() + QDir::separator() + "jsroot.qmltypes");
- QVERIFY(generatedJsRoot.open(QFile::ReadOnly));
+ QVERIFY(generatedJsRoot.open(QFile::ReadOnly | QIODevice::Text));
generatedJsRootContent = QString::fromUtf8(generatedJsRoot.readAll());
generatedJsRoot.close();
@@ -383,7 +418,7 @@ void TestQmllint::autoqmltypes()
{
QProcess process;
process.setWorkingDirectory(testFile("autoqmltypes"));
- process.start(m_qmllintPath, { QStringLiteral("test.qml") });
+ process.start(m_qmllintPath, warningsShouldFailArgs() << QStringLiteral("test.qml") );
process.waitForFinished();
@@ -393,6 +428,21 @@ void TestQmllint::autoqmltypes()
QVERIFY(process.readAllStandardError()
.contains("is not a qmldir file. Assuming qmltypes"));
QVERIFY(process.readAllStandardOutput().isEmpty());
+
+ {
+ QProcess bare;
+ bare.setWorkingDirectory(testFile("autoqmltypes"));
+ bare.start(m_qmllintPath, warningsShouldFailArgs() << QStringLiteral("--bare") << QStringLiteral("test.qml") );
+ bare.waitForFinished();
+
+ const QByteArray errors = bare.readAllStandardError();
+ QVERIFY(!errors.contains("is not a qmldir file. Assuming qmltypes"));
+ QVERIFY(errors.contains("Failed to import TestTest."));
+ QVERIFY(bare.readAllStandardOutput().isEmpty());
+
+ QCOMPARE(bare.exitStatus(), QProcess::NormalExit);
+ QVERIFY(bare.exitCode() != 0);
+ }
}
void TestQmllint::resources()
@@ -422,6 +472,17 @@ void TestQmllint::resources()
}
}
+void TestQmllint::multiDirectory()
+{
+ callQmllint(
+ testFile("MultiDirectory/qml/Inner.qml"), true, nullptr,
+ {}, {}, { testFile("MultiDirectory/multi.qrc") });
+
+ callQmllint(
+ testFile("MultiDirectory/qml/pages/Page.qml"), true, nullptr,
+ {}, {}, { testFile("MultiDirectory/multi.qrc") });
+}
+
void TestQmllint::dirtyQmlCode_data()
{
QTest::addColumn<QString>("filename");
@@ -444,12 +505,12 @@ void TestQmllint::dirtyQmlCode_data()
QTest::newRow("MemberNotFound")
<< QStringLiteral("memberNotFound.qml")
<< Result { { Message {
- QStringLiteral("Property \"foo\" not found on type \"QtObject\""), 6,
+ QStringLiteral("Member \"foo\" not found on type \"QtObject\""), 6,
31 } } };
QTest::newRow("UnknownJavascriptMethd")
<< QStringLiteral("unknownJavascriptMethod.qml")
<< Result { { Message {
- QStringLiteral("Property \"foo2\" not found on type \"Methods\""), 5,
+ QStringLiteral("Member \"foo2\" not found on type \"Methods\""), 5,
25 } } };
QTest::newRow("badAlias")
<< QStringLiteral("badAlias.qml")
@@ -463,6 +524,12 @@ void TestQmllint::dirtyQmlCode_data()
QStringLiteral("Invalid alias expression. Only IDs and field member "
"expressions can be aliased"),
5, 26 } } };
+ QTest::newRow("badAliasNotAnExpression")
+ << QStringLiteral("badAliasNotAnExpression.qml")
+ << Result { { Message {
+ QStringLiteral("Invalid alias expression. Only IDs and field member "
+ "expressions can be aliased"),
+ 4, 30 } } };
QTest::newRow("aliasCycle1") << QStringLiteral("aliasCycle.qml")
<< Result { { Message {
QStringLiteral("Alias \"b\" is part of an alias cycle"),
@@ -485,17 +552,17 @@ void TestQmllint::dirtyQmlCode_data()
9, 34 } } };
QTest::newRow("badParent")
<< QStringLiteral("badParent.qml")
- << Result { { Message { QStringLiteral("Property \"rrr\" not found on type \"Item\""),
+ << Result { { Message { QStringLiteral("Member \"rrr\" not found on type \"Item\""),
5, 34 } } };
QTest::newRow("parentIsComponent")
<< QStringLiteral("parentIsComponent.qml")
<< Result { { Message {
- QStringLiteral("Property \"progress\" not found on type \"QQuickItem\""), 7,
+ QStringLiteral("Member \"progress\" not found on type \"QQuickItem\""), 7,
39 } } };
QTest::newRow("badTypeAssertion")
<< QStringLiteral("badTypeAssertion.qml")
<< Result { { Message {
- QStringLiteral("Property \"rrr\" not found on type \"QQuickItem\""), 5,
+ QStringLiteral("Member \"rrr\" not found on type \"QQuickItem\""), 5,
39 } } };
QTest::newRow("incompleteQmltypes")
<< QStringLiteral("incompleteQmltypes.qml")
@@ -504,7 +571,7 @@ void TestQmllint::dirtyQmlCode_data()
26 } } };
QTest::newRow("incompleteQmltypes2")
<< QStringLiteral("incompleteQmltypes2.qml")
- << Result { { Message { QStringLiteral("Property \"weDontKnowIt\" "
+ << Result { { Message { QStringLiteral("Member \"weDontKnowIt\" "
"not found on type \"CustomPalette\""),
5, 35 } } };
QTest::newRow("incompleteQmltypes3")
@@ -526,11 +593,11 @@ void TestQmllint::dirtyQmlCode_data()
QTest::newRow("javascriptMethodsInModule")
<< QStringLiteral("javascriptMethodsInModuleBad.qml")
<< Result { { Message {
- QStringLiteral("Property \"unknownFunc\" not found on type \"Foo\""), 5,
+ QStringLiteral("Member \"unknownFunc\" not found on type \"Foo\""), 5,
21 } } };
QTest::newRow("badEnumFromQtQml")
<< QStringLiteral("badEnumFromQtQml.qml")
- << Result { { Message { QStringLiteral("Property \"Linear123\" not "
+ << Result { { Message { QStringLiteral("Member \"Linear123\" not "
"found on type \"QQmlEasingEnums\""),
4, 30 } } };
QTest::newRow("anchors3")
@@ -548,13 +615,13 @@ void TestQmllint::dirtyQmlCode_data()
"unknown grouped property scope nanchors.") } } };
QTest::newRow("badAliasObject")
<< QStringLiteral("badAliasObject.qml")
- << Result { { Message { QStringLiteral("Property \"wrongwrongwrong\" not "
+ << Result { { Message { QStringLiteral("Member \"wrongwrongwrong\" not "
"found on type \"QtObject\""),
8, 40 } } };
QTest::newRow("badScript") << QStringLiteral("badScript.qml")
<< Result { { Message {
QStringLiteral(
- "Property \"stuff\" not found on type \"Empty\""),
+ "Member \"stuff\" not found on type \"Empty\""),
5, 21 } } };
QTest::newRow("badScriptOnAttachedProperty")
<< QStringLiteral("badScript.attached.qml")
@@ -565,7 +632,7 @@ void TestQmllint::dirtyQmlCode_data()
QTest::newRow("segFault (bad)")
<< QStringLiteral("SegFault.bad.qml")
<< Result { { Message { QStringLiteral(
- "Property \"foobar\" not found on type \"QQuickScreenAttached\"") } } };
+ "Member \"foobar\" not found on type \"QQuickScreenAttached\"") } } };
QTest::newRow("VariableUsedBeforeDeclaration")
<< QStringLiteral("useBeforeDeclaration.qml")
<< Result { { Message {
@@ -585,7 +652,7 @@ void TestQmllint::dirtyQmlCode_data()
"than the signal it handles.") } } };
QTest::newRow("OnAssignment") << QStringLiteral("onAssignment.qml")
<< Result { { Message { QStringLiteral(
- "Property \"loops\" not found on type \"bool\"") } } };
+ "Member \"loops\" not found on type \"bool\"") } } };
QTest::newRow("BadAttached") << QStringLiteral("badAttached.qml")
<< Result { { Message { QStringLiteral(
"unknown attached property scope WrongAttached.") } } };
@@ -702,13 +769,13 @@ void TestQmllint::dirtyQmlCode_data()
QTest::newRow("badAttachedProperty")
<< QStringLiteral("badAttachedProperty.qml")
<< Result { { Message {
- QStringLiteral("Property \"progress\" not found on type \"TestType\"") } } };
+ QStringLiteral("Member \"progress\" not found on type \"TestType\"") } } };
QTest::newRow("badAttachedPropertyNested")
<< QStringLiteral("badAttachedPropertyNested.qml")
<< Result { { Message { QStringLiteral(
- "Property \"progress\" not found on type \"QObject\""),
+ "Member \"progress\" not found on type \"QObject\""),
12, 41 } },
- { Message { QString("Property \"progress\" not found on type \"QObject\""),
+ { Message { QString("Member \"progress\" not found on type \"QObject\""),
6, 37 } } };
QTest::newRow("badAttachedPropertyTypeString")
<< QStringLiteral("badAttachedPropertyTypeString.qml")
@@ -780,6 +847,14 @@ singleTicks: ' \\' \\\\'
expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
16, 27 } },
{ Result::ExitsNormally, Result::AutoFixable } };
+ QTest::addRow("multifix")
+ << QStringLiteral("multifix.qml")
+ << Result { {
+ Message { QStringLiteral("Unqualified access"), 7, 19, QtWarningMsg},
+ Message { QStringLiteral("Unqualified access"), 11, 19, QtWarningMsg},
+ }, {}, {
+ Message { QStringLiteral("pragma ComponentBehavior: Bound\n"), 1, 1 }
+ }, { Result::AutoFixable }};
QTest::newRow("unresolvedType")
<< QStringLiteral("unresolvedType.qml")
<< Result { { Message { QStringLiteral(
@@ -812,7 +887,7 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("QtQuick.Window 2.0")
<< QStringLiteral("qtquickWindow20.qml")
<< Result { { Message { QStringLiteral(
- "Property \"window\" not found on type \"QQuickWindow\"") } } };
+ "Member \"window\" not found on type \"QQuickWindow\"") } } };
QTest::newRow("unresolvedAttachedType")
<< QStringLiteral("unresolvedAttachedType.qml")
<< Result { { Message { QStringLiteral(
@@ -879,22 +954,22 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("enumInvalid")
<< QStringLiteral("enumInvalid.qml")
<< Result { { Message {
- QStringLiteral("Property \"red\" not found on type \"QtObject\"") } } };
+ QStringLiteral("Member \"red\" not found on type \"QtObject\"") } } };
QTest::newRow("inaccessibleId")
<< QStringLiteral("inaccessibleId.qml")
<< Result { { Message {
- QStringLiteral("Property \"objectName\" not found on type \"int\"") } } };
+ QStringLiteral("Member \"objectName\" not found on type \"int\"") } } };
QTest::newRow("inaccessibleId2")
<< QStringLiteral("inaccessibleId2.qml")
<< Result { { Message {
- QStringLiteral("Property \"objectName\" not found on type \"int\"") } } };
+ QStringLiteral("Member \"objectName\" not found on type \"int\"") } } };
QTest::newRow("unknownTypeCustomParser")
<< QStringLiteral("unknownTypeCustomParser.qml")
<< Result { { Message { QStringLiteral("TypeDoesNotExist was not found.") } } };
QTest::newRow("nonNullStored")
<< QStringLiteral("nonNullStored.qml")
<< Result { { Message { QStringLiteral(
- "Property \"objectName\" not found on type \"Foozle\"") } },
+ "Member \"objectName\" not found on type \"Foozle\"") } },
{ Message { QStringLiteral("Unqualified access") } } };
QTest::newRow("cppPropertyChangeHandlers-wrong-parameters-size-bindable")
<< QStringLiteral("badCppPropertyChangeHandlers1.qml")
@@ -936,13 +1011,13 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("didYouMean(property)")
<< QStringLiteral("didYouMeanProperty.qml")
<< Result { { Message { QStringLiteral(
- "Property \"hoight\" not found on type \"Rectangle\"") },
+ "Member \"hoight\" not found on type \"Rectangle\"") },
{},
{ Message { QStringLiteral("height") } } } };
QTest::newRow("didYouMean(propertyCall)")
<< QStringLiteral("didYouMeanPropertyCall.qml")
<< Result {
- { Message { QStringLiteral("Property \"lgg\" not found on type \"Console\"") },
+ { Message { QStringLiteral("Member \"lgg\" not found on type \"Console\"") },
{},
{ Message { QStringLiteral("log") } } }
};
@@ -955,7 +1030,7 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("didYouMean(enum)")
<< QStringLiteral("didYouMeanEnum.qml")
<< Result { { Message { QStringLiteral(
- "Property \"Readx\" not found on type \"QQuickImage\"") },
+ "Member \"Readx\" not found on type \"QQuickImage\"") },
{},
{ Message { QStringLiteral("Ready") } } } };
QTest::newRow("nullBinding") << QStringLiteral("nullBinding.qml")
@@ -1020,9 +1095,8 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
QTest::newRow("NotScopedEnumCpp")
<< QStringLiteral("NotScopedEnumCpp.qml")
<< Result{ { Message{
- QStringLiteral(
- "Type is an unscoped enum. You cannot access \"V1\" from here."),
- 5, 57 } } };
+ QStringLiteral("You cannot access unscoped enum \"TheEnum\" from here."), 5,
+ 49 } } };
QTest::newRow("unresolvedArrayBinding")
<< QStringLiteral("unresolvedArrayBinding.qml")
@@ -1044,6 +1118,56 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
"in nested components."), 0, 0, QtInfoMsg } },
Result::AutoFixable
};
+ QTest::newRow("IsNotAnEntryOfEnum")
+ << QStringLiteral("IsNotAnEntryOfEnum.qml")
+ << Result{ {
+ Message {
+ QStringLiteral("Member \"Mode\" not found on type \"Item\""), 12,
+ 29, QtWarningMsg },
+ Message{
+ QStringLiteral("\"Hour\" is not an entry of enum \"Mode\"."), 13,
+ 62, QtInfoMsg }
+ },
+ {},
+ { Message{ QStringLiteral("Hours") } }
+ };
+
+ QTest::newRow("StoreNameMethod")
+ << QStringLiteral("storeNameMethod.qml")
+ << Result { { Message { QStringLiteral("Cannot assign to method foo") } } };
+
+ QTest::newRow("CoerceToVoid")
+ << QStringLiteral("coercetovoid.qml")
+ << Result { { Message {
+ QStringLiteral("Function without return type annotation returns double")
+ } } };
+
+ QTest::newRow("lowerCaseQualifiedImport")
+ << QStringLiteral("lowerCaseQualifiedImport.qml")
+ << Result{ {
+ Message{ u"Import qualifier 'test' must start with a capital letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Rectangle' must start with an upper case letter."_s },
+ } };
+ QTest::newRow("lowerCaseQualifiedImport2")
+ << QStringLiteral("lowerCaseQualifiedImport2.qml")
+ << Result{ {
+ Message{ u"Import qualifier 'test' must start with a capital letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Item' must start with an upper case letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Rectangle' must start with an upper case letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.color' must start with an upper case letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Grid' must start with an upper case letter."_s },
+ } };
+ QTest::newRow("notQmlRootMethods")
+ << QStringLiteral("notQmlRootMethods.qml")
+ << Result{ {
+ Message{ u"Member \"deleteLater\" not found on type \"QtObject\""_s },
+ Message{ u"Member \"destroyed\" not found on type \"QtObject\""_s },
+ } };
}
void TestQmllint::dirtyQmlCode()
@@ -1167,6 +1291,7 @@ void TestQmllint::cleanQmlCode_data()
QTest::newRow("QVariant") << QStringLiteral("qvariant.qml");
QTest::newRow("Accessible") << QStringLiteral("accessible.qml");
QTest::newRow("qjsroot") << QStringLiteral("qjsroot.qml");
+ QTest::newRow("qmlRootMethods") << QStringLiteral("qmlRootMethods.qml");
QTest::newRow("InlineComponent") << QStringLiteral("inlineComponent.qml");
QTest::newRow("InlineComponentWithComponents") << QStringLiteral("inlineComponentWithComponents.qml");
QTest::newRow("InlineComponentsChained") << QStringLiteral("inlineComponentsChained.qml");
@@ -1216,6 +1341,21 @@ void TestQmllint::cleanQmlCode_data()
QTest::newRow("propertyWithOn") << QStringLiteral("switcher.qml");
QTest::newRow("constructorProperty") << QStringLiteral("constructorProperty.qml");
QTest::newRow("onlyMajorVersion") << QStringLiteral("onlyMajorVersion.qml");
+ QTest::newRow("attachedImportUse") << QStringLiteral("attachedImportUse.qml");
+ QTest::newRow("VariantMapGetPropertyLookup") << QStringLiteral("variantMapLookup.qml");
+ QTest::newRow("StringToDateTime") << QStringLiteral("stringToDateTime.qml");
+ QTest::newRow("ScriptInTemplate") << QStringLiteral("scriptInTemplate.qml");
+ QTest::newRow("AddressableValue") << QStringLiteral("addressableValue.qml");
+ QTest::newRow("WriteListProperty") << QStringLiteral("writeListProperty.qml");
+ QTest::newRow("dontConfuseMemberPrintWithGlobalPrint") << QStringLiteral("findMemberPrint.qml");
+ QTest::newRow("groupedAttachedLayout") << QStringLiteral("groupedAttachedLayout.qml");
+ QTest::newRow("QQmlScriptString") << QStringLiteral("scriptstring.qml");
+ QTest::newRow("QEventPoint") << QStringLiteral("qEventPoint.qml");
+ QTest::newRow("locale") << QStringLiteral("locale.qml");
+ QTest::newRow("constInvokable") << QStringLiteral("useConstInvokable.qml");
+ QTest::newRow("dontCheckJSTypes") << QStringLiteral("dontCheckJSTypes.qml");
+ QTest::newRow("jsonObjectIsRecognized") << QStringLiteral("jsonObjectIsRecognized.qml");
+ QTest::newRow("jsonArrayIsRecognized") << QStringLiteral("jsonArrayIsRecognized.qml");
}
void TestQmllint::cleanQmlCode()
@@ -1239,10 +1379,10 @@ void TestQmllint::compilerWarnings_data()
QTest::newRow("qQmlV4Function") << QStringLiteral("varargs.qml") << Result::clean() << true;
QTest::newRow("multiGrouped") << QStringLiteral("multiGrouped.qml") << Result::clean() << true;
- QTest::newRow("shadowable") << QStringLiteral("shadowable.qml")
- << Result { { Message { QStringLiteral(
- "with type NotSoSimple can be shadowed") } } }
- << true;
+ QTest::newRow("shadowable")
+ << QStringLiteral("shadowable.qml")
+ << Result { { Message {QStringLiteral("with type NotSoSimple can be shadowed") } } }
+ << true;
QTest::newRow("tooFewParameters")
<< QStringLiteral("tooFewParams.qml")
<< Result { { Message { QStringLiteral("No matching override found") } } } << true;
@@ -1261,6 +1401,51 @@ void TestQmllint::compilerWarnings_data()
<< Result { { { QStringLiteral(
"Functions without type annotations won't be compiled") } } }
<< true;
+ QTest::newRow("generalizedGroupHint")
+ << QStringLiteral("generalizedGroupHint.qml")
+ << Result { { { QStringLiteral(
+ "Cannot resolve property type for binding on myColor. "
+ "You may want use ID-based grouped properties here.") } } }
+ << true;
+ QTest::newRow("invalidIdLookup")
+ << QStringLiteral("invalidIdLookup.qml")
+ << Result { { {
+ QStringLiteral("Cannot retrieve a non-object type by ID: stateMachine")
+ } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-component")
+ << QStringLiteral("returnTypeAnnotation_component.qml")
+ << Result{ { { "Could not compile function comp: function without return type "
+ "annotation returns (component in" },
+ { "returnTypeAnnotation_component.qml)::c with type Comp. "
+ "This may prevent proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-enum")
+ << QStringLiteral("returnTypeAnnotation_enum.qml")
+ << Result{ { { "Could not compile function enumeration: function without return type "
+ "annotation returns QQuickText::HAlignment::AlignRight. "
+ "This may prevent proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-method")
+ << QStringLiteral("returnTypeAnnotation_method.qml")
+ << Result{ { { "Could not compile function method: function without return type "
+ "annotation returns (component in " }, // Don't check the build folder path
+ { "returnTypeAnnotation_method.qml)::f(...). This may "
+ "prevent proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-property")
+ << QStringLiteral("returnTypeAnnotation_property.qml")
+ << Result{ { { "Could not compile function prop: function without return type "
+ "annotation returns (component in " }, // Don't check the build folder path
+ { "returnTypeAnnotation_property.qml)::i with type int. This may prevent "
+ "proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-type")
+ << QStringLiteral("returnTypeAnnotation_type.qml")
+ << Result{ { { "Could not compile function type: function without return type "
+ "annotation returns double. This may prevent proper compilation to "
+ "Cpp." } } }
+ << true;
}
void TestQmllint::compilerWarnings()
@@ -1273,11 +1458,15 @@ void TestQmllint::compilerWarnings()
auto categories = QQmlJSLogger::defaultCategories();
- auto category = std::find(categories.begin(), categories.end(), qmlCompiler);
+ auto category = std::find_if(categories.begin(), categories.end(), [](const QQmlJS::LoggerCategory& category) {
+ return category.id() == qmlCompiler;
+ });
Q_ASSERT(category != categories.end());
- if (enableCompilerWarnings)
- category->setLevel(u"warning"_s);
+ if (enableCompilerWarnings) {
+ category->setLevel(QtWarningMsg);
+ category->setIgnored(false);
+ }
runTest(filename, result, {}, {}, {}, UseDefaultImports, &categories);
}
@@ -1285,7 +1474,7 @@ void TestQmllint::compilerWarnings()
QString TestQmllint::runQmllint(const QString &fileToLint,
std::function<void(QProcess &)> handleResult,
const QStringList &extraArgs, bool ignoreSettings,
- bool addImportDirs, bool absolutePath)
+ bool addImportDirs, bool absolutePath, const Environment &env)
{
auto qmlImportDir = QLibraryInfo::path(QLibraryInfo::QmlImportsPath);
QStringList args;
@@ -1311,6 +1500,11 @@ QString TestQmllint::runQmllint(const QString &fileToLint,
QString errors;
auto verify = [&](bool isSilent) {
QProcess process;
+ QProcessEnvironment processEnv = QProcessEnvironment::systemEnvironment();
+ for (const auto &entry : env)
+ processEnv.insert(entry.first, entry.second);
+
+ process.setProcessEnvironment(processEnv);
process.setWorkingDirectory(QFileInfo(absoluteFilePath).absolutePath());
process.start(m_qmllintPath, args);
handleResult(process);
@@ -1353,7 +1547,7 @@ QString TestQmllint::runQmllint(const QString &fileToLint,
QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed,
const QStringList &extraArgs, bool ignoreSettings,
- bool addImportDirs, bool absolutePath)
+ bool addImportDirs, bool absolutePath, const Environment &env)
{
return runQmllint(
fileToLint,
@@ -1366,13 +1560,13 @@ QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed,
else
QVERIFY(process.exitCode() != 0);
},
- extraArgs, ignoreSettings, addImportDirs, absolutePath);
+ extraArgs, ignoreSettings, addImportDirs, absolutePath, env);
}
void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJsonArray *warnings,
QStringList importPaths, QStringList qmldirFiles,
QStringList resources, DefaultImportOption defaultImports,
- QList<QQmlJSLogger::Category> *categories, bool autoFixable,
+ QList<QQmlJS::LoggerCategory> *categories, bool autoFixable,
LintType type)
{
QJsonArray jsonOutput;
@@ -1382,18 +1576,22 @@ void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJs
QQmlJSLinter::LintResult lintResult;
+ const QStringList resolvedImportPaths = defaultImports == UseDefaultImports
+ ? m_defaultImportPaths + importPaths
+ : importPaths;
if (type == LintFile) {
+ const QList<QQmlJS::LoggerCategory> resolvedCategories =
+ categories != nullptr ? *categories : QQmlJSLogger::defaultCategories();
lintResult = m_linter.lintFile(
- lintedFile, nullptr, true, &jsonOutput,
- defaultImports == UseDefaultImports ? m_defaultImportPaths + importPaths
- : importPaths,
- qmldirFiles, resources,
- categories != nullptr ? *categories : QQmlJSLogger::defaultCategories());
+ lintedFile, nullptr, true, &jsonOutput, resolvedImportPaths, qmldirFiles,
+ resources, resolvedCategories);
} else {
- lintResult = m_linter.lintModule(fileToLint, true, &jsonOutput);
+ lintResult =
+ m_linter.lintModule(fileToLint, true, &jsonOutput, resolvedImportPaths, resources);
}
bool success = lintResult == QQmlJSLinter::LintSuccess;
+ QEXPECT_FAIL("qtquickdialog", "Will fail until QTBUG-104091 is implemented", Abort);
QVERIFY2(success == shouldSucceed, QJsonDocument(jsonOutput).toJson());
if (warnings) {
@@ -1425,7 +1623,7 @@ void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJs
if (QFileInfo(fixedPath).exists()) {
QFile fixedFile(fixedPath);
- fixedFile.open(QFile::ReadOnly);
+ QVERIFY(fixedFile.open(QFile::ReadOnly));
QString fixedFileContents = QString::fromUtf8(fixedFile.readAll());
#ifdef Q_OS_WIN
fixedCode = fixedCode.replace(u"\r\n"_s, u"\n"_s);
@@ -1447,7 +1645,7 @@ void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJs
void TestQmllint::runTest(const QString &testFile, const Result &result, QStringList importDirs,
QStringList qmltypesFiles, QStringList resources,
DefaultImportOption defaultImports,
- QList<QQmlJSLogger::Category> *categories)
+ QList<QQmlJS::LoggerCategory> *categories)
{
QJsonArray warnings;
callQmllint(testFile, result.flags.testFlag(Result::Flag::ExitsNormally), &warnings, importDirs,
@@ -1604,17 +1802,17 @@ void TestQmllint::requiredProperty()
void TestQmllint::settingsFile()
{
- QVERIFY(runQmllint("settings/unqualifiedSilent/unqualified.qml", true, QStringList(), false)
+ QVERIFY(runQmllint("settings/unqualifiedSilent/unqualified.qml", true, warningsShouldFailArgs(), false)
.isEmpty());
- QVERIFY(runQmllint("settings/unusedImportWarning/unused.qml", false, QStringList(), false)
+ QVERIFY(runQmllint("settings/unusedImportWarning/unused.qml", false, warningsShouldFailArgs(), false)
.contains(QStringLiteral("Warning: %1:2:1: Unused import")
.arg(testFile("settings/unusedImportWarning/unused.qml"))));
- QVERIFY(runQmllint("settings/bare/bare.qml", false, {}, false, false)
+ QVERIFY(runQmllint("settings/bare/bare.qml", false, warningsShouldFailArgs(), false, false)
.contains(QStringLiteral("Failed to find the following builtins: "
- "builtins.qmltypes, jsroot.qmltypes")));
- QVERIFY(runQmllint("settings/qmltypes/qmltypes.qml", false, QStringList(), false)
+ "jsroot.qmltypes, builtins.qmltypes")));
+ QVERIFY(runQmllint("settings/qmltypes/qmltypes.qml", false, warningsShouldFailArgs(), false)
.contains(QStringLiteral("not a qmldir file. Assuming qmltypes.")));
- QVERIFY(runQmllint("settings/qmlimports/qmlimports.qml", true, QStringList(), false).isEmpty());
+ QVERIFY(runQmllint("settings/qmlimports/qmlimports.qml", true, warningsShouldFailArgs(), false).isEmpty());
}
void TestQmllint::additionalImplicitImport()
@@ -1623,17 +1821,56 @@ void TestQmllint::additionalImplicitImport()
const auto guard = qScopeGuard([this]() {m_linter.clearCache(); });
runTest("additionalImplicitImport.qml", Result::clean(), {}, {},
{ testFile("implicitImportResource.qrc") });
+}
+
+void TestQmllint::qrcUrlImport()
+{
+ const auto guard = qScopeGuard([this]() { m_linter.clearCache(); });
+ QJsonArray warnings;
+ callQmllint(testFile("untitled/main.qml"), true, &warnings, {}, {},
+ { testFile("untitled/qrcUrlImport.qrc") });
+ checkResult(warnings, Result::clean());
}
-void TestQmllint::attachedPropertyReuse()
+void TestQmllint::incorrectImportFromHost_data()
{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<Result>("result");
+
+ QTest::newRow("NonexistentFile")
+ << QStringLiteral("importNonexistentFile.qml")
+ << Result{ { Message{
+ QStringLiteral("File or directory you are trying to import does not exist"),
+ 1, 1 } } };
+#ifndef Q_OS_WIN
+ // there is no /dev/null device on Win
+ QTest::newRow("NullDevice")
+ << QStringLiteral("importNullDevice.qml")
+ << Result{ { Message{ QStringLiteral("is neither a file nor a directory. Are sure the "
+ "import path is correct?"),
+ 1, 1 } } };
+#endif
+}
+
+void TestQmllint::incorrectImportFromHost()
+{
+ QFETCH(QString, filename);
+ QFETCH(Result, result);
+
+ runTest(filename, result);
+}
+void TestQmllint::attachedPropertyReuse()
+{
auto categories = QQmlJSLogger::defaultCategories();
- auto category = std::find(categories.begin(), categories.end(), qmlAttachedPropertyReuse);
+ auto category = std::find_if(categories.begin(), categories.end(), [](const QQmlJS::LoggerCategory& category) {
+ return category.id() == qmlAttachedPropertyReuse;
+ });
Q_ASSERT(category != categories.end());
- category->setLevel(u"warning"_s);
+ category->setLevel(QtWarningMsg);
+ category->setIgnored(false);
runTest("attachedPropNotReused.qml",
Result { { Message { QStringLiteral("Using attached type QQuickKeyNavigationAttached "
"already initialized in a parent "
@@ -1641,6 +1878,24 @@ void TestQmllint::attachedPropertyReuse()
{}, {}, {}, UseDefaultImports, &categories);
runTest("attachedPropEnum.qml", Result::clean(), {}, {}, {}, UseDefaultImports, &categories);
+ runTest("MyStyle/ToolBar.qml", Result {
+ {
+ Message {
+ "Using attached type MyStyle already initialized in a parent scope"_L1,
+ 10,
+ 16
+ }
+ },
+ {},
+ {
+ Message {
+ "Reference it by id instead"_L1,
+ 10,
+ 16
+ }
+ },
+ Result::AutoFixable
+ });
}
void TestQmllint::missingBuiltinsNoCrash()
@@ -1662,13 +1917,13 @@ void TestQmllint::missingBuiltinsNoCrash()
checkResult(warnings,
Result { { Message { QStringLiteral("Failed to find the following builtins: "
- "builtins.qmltypes, jsroot.qmltypes") } } });
+ "jsroot.qmltypes, builtins.qmltypes") } } });
}
void TestQmllint::absolutePath()
{
- QString absPathOutput = runQmllint("memberNotFound.qml", false, {}, true, true, true);
- QString relPathOutput = runQmllint("memberNotFound.qml", false, {}, true, true, false);
+ QString absPathOutput = runQmllint("memberNotFound.qml", false, warningsShouldFailArgs(), true, true, true);
+ QString relPathOutput = runQmllint("memberNotFound.qml", false, warningsShouldFailArgs(), true, true, false);
const QString absolutePath = QFileInfo(testFile("memberNotFound.qml")).absoluteFilePath();
QVERIFY(absPathOutput.contains(absolutePath));
@@ -1683,10 +1938,14 @@ void TestQmllint::importMultipartUri()
void TestQmllint::lintModule_data()
{
QTest::addColumn<QString>("module");
+ QTest::addColumn<QStringList>("importPaths");
+ QTest::addColumn<QStringList>("resources");
QTest::addColumn<Result>("result");
QTest::addRow("Things")
<< u"Things"_s
+ << QStringList()
+ << QStringList()
<< Result {
{ Message {
u"Type \"QPalette\" not found. Used in SomethingEntirelyStrange.palette"_s,
@@ -1696,16 +1955,30 @@ void TestQmllint::lintModule_data()
};
QTest::addRow("missingQmltypes")
<< u"Fake5Compat.GraphicalEffects.private"_s
+ << QStringList()
+ << QStringList()
<< Result { { Message { u"QML types file does not exist"_s } } };
+
+ QTest::addRow("moduleWithQrc")
+ << u"moduleWithQrc"_s
+ << QStringList({ testFile("hidden") })
+ << QStringList({
+ testFile("hidden/qmake_moduleWithQrc.qrc"),
+ testFile("hidden/moduleWithQrc_raw_qml_0.qrc")
+ })
+ << Result::clean();
}
void TestQmllint::lintModule()
{
QFETCH(QString, module);
+ QFETCH(QStringList, importPaths);
+ QFETCH(QStringList, resources);
QFETCH(Result, result);
QJsonArray warnings;
- callQmllint(module, false, &warnings, {}, {}, {}, {}, nullptr, false, LintModule);
+ callQmllint(module, result.flags & Result::ExitsNormally, &warnings, importPaths, {}, resources,
+ UseDefaultImports, nullptr, false, LintModule);
checkResult(warnings, result);
}
@@ -1739,6 +2012,25 @@ void TestQmllint::testLineEndings()
}
}
+void TestQmllint::valueTypesFromString()
+{
+ runTest("valueTypesFromString.qml",
+ Result{ {
+ Message{
+ u"Binding is not supported: Type QSizeF should be constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a string."_s },
+ Message{
+ u"Binding is not supported: Type QRectF should be constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a string."_s },
+ Message{
+ u"Binding is not supported: Type QPointF should be constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a string."_s },
+ },
+ { /*bad messages */ },
+ {
+ Message{ u"({ width: 30, height: 50 })"_s },
+ Message{ u"({ x: 10, y: 20, width: 30, height: 50 })"_s },
+ Message{ u"({ x: 30, y: 50 })"_s },
+ } });
+}
+
#if QT_CONFIG(library)
void TestQmllint::testPlugin()
{
@@ -1780,6 +2072,9 @@ void TestQmllint::testPlugin()
Result { { Message { u"QtQuick.Controls and NO QtQuick present"_s } } });
// Verify that none of the passes do anything when they're not supposed to
runTest("nothing_pluginTest.qml", Result::clean());
+
+ QVERIFY(runQmllint("settings/plugin/elemenpass_pluginSettingTest.qml", true, QStringList(), false)
+ .isEmpty());
}
// TODO: Eventually tests for (real) plugins need to be moved into a separate file
@@ -1835,7 +2130,7 @@ void TestQmllint::quickPlugin()
Message { u"SplitView attached property only works with Items"_s },
Message { u"ScrollIndicator must be attached to a Flickable"_s },
Message { u"ScrollBar must be attached to a Flickable or ScrollView"_s },
- Message { u"Accessible must be attached to an Item"_s },
+ Message { u"Accessible must be attached to an Item or an Action"_s },
Message { u"EnterKey attached property only works with Items"_s },
Message {
u"LayoutDirection attached property only works with Items and Windows"_s },
@@ -1885,8 +2180,108 @@ void TestQmllint::quickPlugin()
runTest("pluginQuick_attachedClean.qml", Result::clean());
runTest("pluginQuick_attachedIgnore.qml", Result::clean());
runTest("pluginQuick_noCrashOnUneresolved.qml", Result {}); // we don't care about the specific warnings
+
+ runTest("pluginQuick_propertyChangesParsed.qml",
+ Result { {
+ Message {
+ u"Property \"myColor\" is custom-parsed in PropertyChanges. "
+ "You should phrase this binding as \"foo.myColor: Qt.rgba(0.5, ...\""_s,
+ 12, 30
+ },
+ Message {
+ u"You should remove any bindings on the \"target\" property and avoid "
+ "custom-parsed bindings in PropertyChanges."_s,
+ 11, 29
+ },
+ Message {
+ u"Unknown property \"notThere\" in PropertyChanges."_s,
+ 13, 31
+ }
+ } });
+ runTest("pluginQuick_propertyChangesInvalidTarget.qml", Result {}); // we don't care about the specific warnings
+}
+
+void TestQmllint::environment_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<bool>("shouldSucceed");
+ QTest::addColumn<QStringList>("extraArgs");
+ QTest::addColumn<Environment>("env");
+ QTest::addColumn<QString>("expectedWarning");
+
+ const QString fileThatNeedsImportPath = testFile(u"NeedImportPath.qml"_s);
+ const QString importPath = testFile(u"ImportPath"_s);
+ const QString invalidImportPath = testFile(u"ImportPathThatDoesNotExist"_s);
+ const QString noWarningExpected;
+
+ QTest::addRow("missing-import-dir")
+ << fileThatNeedsImportPath << false << warningsShouldFailArgs()
+ << Environment{ { u"QML_IMPORT_PATH"_s, importPath } } << noWarningExpected;
+
+ QTest::addRow("import-dir-via-arg")
+ << fileThatNeedsImportPath << true << QStringList{ u"-I"_s, importPath }
+ << Environment{ { u"QML_IMPORT_PATH"_s, invalidImportPath } } << noWarningExpected;
+
+ QTest::addRow("import-dir-via-env")
+ << fileThatNeedsImportPath << true << QStringList{ u"-E"_s }
+ << Environment{ { u"QML_IMPORT_PATH"_s, importPath } }
+ << u"Using import directories passed from environment variable \"QML_IMPORT_PATH\": \"%1\"."_s
+ .arg(importPath);
+
+ QTest::addRow("import-dir-via-env2")
+ << fileThatNeedsImportPath << true << QStringList{ u"-E"_s }
+ << Environment{ { u"QML2_IMPORT_PATH"_s, importPath } }
+ << u"Using import directories passed from the deprecated environment variable \"QML2_IMPORT_PATH\": \"%1\"."_s
+ .arg(importPath);
}
+
+void TestQmllint::environment()
+{
+ QFETCH(QString, file);
+ QFETCH(bool, shouldSucceed);
+ QFETCH(QStringList, extraArgs);
+ QFETCH(Environment, env);
+ QFETCH(QString, expectedWarning);
+
+ const QString output = runQmllint(file, shouldSucceed, extraArgs, false, true, false, env);
+ if (!expectedWarning.isEmpty()) {
+ QVERIFY(output.contains(expectedWarning));
+ }
+}
+
+void TestQmllint::maxWarnings()
+{
+ // warnings are not fatal by default
+ runQmllint(testFile("badScript.qml"), true);
+ // or when max-warnings is set to -1
+ runQmllint(testFile("badScript.qml"), true, {"-W", "-1"});
+ // 1 warning => should fail
+ runQmllint(testFile("badScript.qml"), false, {"--max-warnings", "0"});
+ // only 1 warning => should exit normally
+ runQmllint(testFile("badScript.qml"), true, {"--max-warnings", "1"});
+}
+
#endif
-QTEST_MAIN(TestQmllint)
+void TestQmllint::ignoreSettingsNotCommandLineOptions()
+{
+ const QString importPath = testFile(u"ImportPath"_s);
+ // makes sure that ignore settings only ignores settings and not command line options like
+ // "-I".
+ const QString output = runQmllint(testFile(u"NeedImportPath.qml"_s), true,
+ QStringList{ u"-I"_s, importPath }, true);
+ // should not complain about not finding the module that is in importPath
+ QCOMPARE(output, QString());
+}
+
+void TestQmllint::backslashedQmldirPath()
+{
+ const QString qmldirPath
+ = testFile(u"ImportPath/ModuleInImportPath/qmldir"_s).replace('/', QDir::separator());
+ const QString output = runQmllint(
+ testFile(u"something.qml"_s), true, QStringList{ u"-i"_s, qmldirPath });
+ QVERIFY(output.isEmpty());
+}
+
+QTEST_GUILESS_MAIN(TestQmllint)
#include "tst_qmllint.moc"
diff --git a/tests/auto/qml/qmlplugindump/CMakeLists.txt b/tests/auto/qml/qmlplugindump/CMakeLists.txt
index 9153660ef0..053268bcfb 100644
--- a/tests/auto/qml/qmlplugindump/CMakeLists.txt
+++ b/tests/auto/qml/qmlplugindump/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qmlplugindump Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlplugindump LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmlplugindump
SOURCES
tst_qmlplugindump.cpp
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp
index 171a185ad7..793191695d 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "dummy.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h
index 0fb354d6c4..b72814df82 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DUMMY_H
#define DUMMY_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp
index eec547cd29..1409876ec6 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "dummy_plugin.h"
#include "dummy.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h
index 2c3f25ae61..45437e0500 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DUMMY_PLUGIN_H
#define DUMMY_PLUGIN_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp
index e84355eb11..4c8da8aeab 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "plugin.h"
#include "types.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h
index f16177351d..02c9d42022 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef PLUGIN_H
#define PLUGIN_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h
index 5fdc5fa1e4..7a1b73ac90 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/types.h
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPES_H
#define TYPES_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp
index 04fcfc5edd..9ba1365d40 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "imports.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h
index 386cce9f4d..e88deda2f9 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef IMPORTS_H
#define IMPORTS_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp
index b71719fb6f..c215917c7d 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "imports_plugin.h"
#include "imports.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h
index 17855d5a22..1353bbd24a 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef IMPORTS_PLUGIN_H
#define IMPORTS_PLUGIN_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp
index 117b6db82f..6295ec2201 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "versions.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h
index 991823aaf3..b5afc16c2a 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef VERSIONS_H
#define VERSIONS_H
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp
index 6a554c596d..9c1a2d4a4e 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "versions_plugin.h"
#include "versions.h"
diff --git a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h
index 9bc70ca473..aba5f1fac7 100644
--- a/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h
+++ b/tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef VERSIONS_PLUGIN_H
#define VERSIONS_PLUGIN_H
diff --git a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
index 50af75380d..2e7b704413 100644
--- a/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
+++ b/tests/auto/qml/qmlplugindump/tst_qmlplugindump.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QLibraryInfo>
@@ -152,10 +152,10 @@ void tst_qmlplugindump::plugin()
QVERIFY2(dumper.waitForStarted(), qPrintable(dumper.errorString()));
QVERIFY2(dumper.waitForFinished(), qPrintable(dumper.errorString()));
- const QString &result = dumper.readAllStandardOutput();
+ const QByteArray result = dumper.readAllStandardOutput();
QFile expectedFile(expectedPath);
QVERIFY2(expectedFile.open(QIODevice::ReadOnly), qPrintable(expectedFile.errorString()));
- const QString expected = expectedFile.readAll();
+ const QByteArray expected = expectedFile.readAll();
QCOMPARE(result, expected);
}
diff --git a/tests/auto/qml/qmlsplitlib/CMakeLists.txt b/tests/auto/qml/qmlsplitlib/CMakeLists.txt
index 523ab5cbfd..7c77d5fbae 100644
--- a/tests/auto/qml/qmlsplitlib/CMakeLists.txt
+++ b/tests/auto/qml/qmlsplitlib/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmlsplitlib LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
include(GenerateExportHeader)
qt_add_library(tst_qmlsplitlib_library
@@ -13,6 +19,17 @@ generate_export_header(tst_qmlsplitlib_library)
target_link_libraries(tst_qmlsplitlib_library Qt::Core Qt::QmlIntegration)
+qt_add_library(tst-qmlsplitlib-library-2
+ lib2.h
+ lib2.cpp
+)
+qt_autogen_tools_initial_setup(tst-qmlsplitlib-library-2)
+target_include_directories(tst-qmlsplitlib-library-2 PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # find autogenerated header
+generate_export_header(tst-qmlsplitlib-library-2)
+
+target_link_libraries(tst-qmlsplitlib-library-2 Qt::Core Qt::QmlIntegration)
+
+
qt_internal_add_test(tst_qmlsplitlib
SOURCES
tst_qmlsplitlib.cpp
@@ -23,12 +40,15 @@ qt_internal_add_test(tst_qmlsplitlib
qt_autogen_tools_initial_setup(tst_qmlsplitlib)
qt6_generate_foreign_qml_types(tst_qmlsplitlib_library tst_qmlsplitlib)
+qt6_generate_foreign_qml_types(tst-qmlsplitlib-library-2 tst_qmlsplitlib)
+
+qt_policy(SET QTP0001 NEW)
qt6_add_qml_module(tst_qmlsplitlib
URI "SplitLib"
- AUTO_RESOURCE_PREFIX
QML_FILES
main.qml
+ main2.qml
)
-target_link_libraries(tst_qmlsplitlib PRIVATE tst_qmlsplitlib_library)
+target_link_libraries(tst_qmlsplitlib PRIVATE tst_qmlsplitlib_library tst-qmlsplitlib-library-2)
diff --git a/tests/auto/qml/qmlsplitlib/lib.h b/tests/auto/qml/qmlsplitlib/lib.h
index 02fc88894d..b6c394a3b6 100644
--- a/tests/auto/qml/qmlsplitlib/lib.h
+++ b/tests/auto/qml/qmlsplitlib/lib.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SPLITLIB_LIB_H
#define SPLITLIB_LIB_H
diff --git a/tests/auto/qml/qmlsplitlib/lib2.cpp b/tests/auto/qml/qmlsplitlib/lib2.cpp
new file mode 100644
index 0000000000..d4489f5c77
--- /dev/null
+++ b/tests/auto/qml/qmlsplitlib/lib2.cpp
@@ -0,0 +1,5 @@
+#include "lib2.h"
+
+bool SplitLib2::transmogrify() { return true; }
+
+#include "moc_lib2.cpp"
diff --git a/tests/auto/qml/qmlsplitlib/lib2.h b/tests/auto/qml/qmlsplitlib/lib2.h
new file mode 100644
index 0000000000..6d6aaddda5
--- /dev/null
+++ b/tests/auto/qml/qmlsplitlib/lib2.h
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef SPLITLIB_LIB2_H
+#define SPLITLIB_LIB2_H
+#include "tst-qmlsplitlib-library-2_export.h"
+
+#include <QtQmlIntegration/qqmlintegration.h>
+#include <QtCore/qglobal.h>
+#include <QObject>
+
+class TST_QMLSPLITLIB_LIBRARY_2_EXPORT SplitLib2 : public QObject
+{
+public:
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_INVOKABLE bool transmogrify();
+};
+
+
+class TST_QMLSPLITLIB_LIBRARY_2_EXPORT Foo2 : public QObject
+{
+public:
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Bar2)
+ QML_SINGLETON
+};
+
+#endif
diff --git a/tests/auto/qml/qmlsplitlib/main.qml b/tests/auto/qml/qmlsplitlib/main.qml
index 2309a2e8c3..47be48acc4 100644
--- a/tests/auto/qml/qmlsplitlib/main.qml
+++ b/tests/auto/qml/qmlsplitlib/main.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import SplitLib
diff --git a/tests/auto/qml/qmlsplitlib/main2.qml b/tests/auto/qml/qmlsplitlib/main2.qml
new file mode 100644
index 0000000000..c5081c6627
--- /dev/null
+++ b/tests/auto/qml/qmlsplitlib/main2.qml
@@ -0,0 +1,8 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import SplitLib
+
+SplitLib2 {
+ property string s: Bar2.objectName
+}
diff --git a/tests/auto/qml/qmlsplitlib/manual_imports.cpp b/tests/auto/qml/qmlsplitlib/manual_imports.cpp
index f1b30f8352..dd1c8dbe89 100644
--- a/tests/auto/qml/qmlsplitlib/manual_imports.cpp
+++ b/tests/auto/qml/qmlsplitlib/manual_imports.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
diff --git a/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp b/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp
index 893ed77ff7..d04a1c6845 100644
--- a/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp
+++ b/tests/auto/qml/qmlsplitlib/tst_qmlsplitlib.cpp
@@ -1,17 +1,19 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlEngine>
#include <QQmlComponent>
#include <QObject>
#include <qtest.h>
#include "lib.h"
+#include "lib2.h"
class tst_splitlib : public QObject
{
Q_OBJECT
private slots:
void verifyComponent();
+ void verifyComponent2();
};
void tst_splitlib::verifyComponent()
@@ -25,5 +27,16 @@ void tst_splitlib::verifyComponent()
QVERIFY(lib);
}
+void tst_splitlib::verifyComponent2()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, QStringLiteral("qrc:/qt/qml/SplitLib/main2.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer o(c.create());
+ QVERIFY(!o.isNull());
+ auto lib = qobject_cast<SplitLib2 *>(o.get());
+ QVERIFY(lib);
+}
+
QTEST_MAIN(tst_splitlib)
#include "tst_qmlsplitlib.moc"
diff --git a/tests/auto/qml/qmltc/BLACKLIST b/tests/auto/qml/qmltc/BLACKLIST
deleted file mode 100644
index 004fbeb8d9..0000000000
--- a/tests/auto/qml/qmltc/BLACKLIST
+++ /dev/null
@@ -1,5 +0,0 @@
-[listView]
-qnx ci
-# QTBUG-101342
-[listView]
-android
diff --git a/tests/auto/qml/qmltc/CMakeLists.txt b/tests/auto/qml/qmltc/CMakeLists.txt
index 4b86a6c018..1e6c6b9e30 100644
--- a/tests/auto/qml/qmltc/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/CMakeLists.txt
@@ -1,8 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmltc LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
add_subdirectory(QmltcTests)
add_subdirectory(NamespaceTest/Subfolder)
+add_subdirectory(QmltcExportedTests)
+add_subdirectory(QmltcExportedNoFileNameTest)
set(test_sources
nameconflict.h nameconflict.cpp
@@ -18,6 +26,11 @@ set(qmltc_module_libs
# automatic type registration that comes from the plugin)
qmltc_test_moduleplugin
qmltc_namespace_test_module
+ qmltc_namespace_test_moduleplugin
+ qmltc_exported_tests_module
+ qmltc_exported_tests_moduleplugin
+ qmltc_exported_no_file_name_test_module
+ qmltc_exported_no_file_name_test_moduleplugin
)
qt_internal_add_test(tst_qmltc_diskcache
SOURCES ${test_sources}
@@ -25,6 +38,7 @@ qt_internal_add_test(tst_qmltc_diskcache
)
target_compile_definitions(tst_qmltc_diskcache PRIVATE
QMLTC_TESTS_DISABLE_CACHE=0
+ QT_NO_URL_CAST_FROM_STRING #QTBUG-113875
)
qt_internal_add_test(tst_qmltc_nodiskcache
@@ -33,6 +47,7 @@ qt_internal_add_test(tst_qmltc_nodiskcache
)
target_compile_definitions(tst_qmltc_nodiskcache PRIVATE
QMLTC_TESTS_DISABLE_CACHE=1
+ QT_NO_URL_CAST_FROM_STRING #QTBUG-113875
)
# Add qmltc documentation example to the tests. This is not beautiful but allows
diff --git a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt
index f661cdea1e..daf1139a8f 100644
--- a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/CMakeLists.txt
@@ -24,9 +24,10 @@ qt_autogen_tools_initial_setup(qmltc_namespace_test_module)
target_link_libraries(qmltc_namespace_test_module PUBLIC ${common_libraries})
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(qmltc_namespace_test_module
URI NamespaceTest.Subfolder
- AUTO_RESOURCE_PREFIX
SOURCES
${cpp_sources}
QML_FILES
diff --git a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml
index 101e9f69a1..3576353b02 100644
--- a/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml
+++ b/tests/auto/qml/qmltc/NamespaceTest/Subfolder/Type.qml
@@ -1,5 +1,5 @@
import QtQuick
Item {
- property string data
+ property string data: "Hello from namespace"
}
diff --git a/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt
new file mode 100644
index 0000000000..47f920129a
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/CMakeLists.txt
@@ -0,0 +1,28 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_add_library(qmltc_exported_no_file_name_test_module STATIC)
+qt_autogen_tools_initial_setup(qmltc_exported_no_file_name_test_module)
+
+set(common_libraries
+ Qt::QuickPrivate
+)
+
+target_link_libraries(qmltc_exported_no_file_name_test_module PUBLIC ${common_libraries})
+
+qt_policy(SET QTP0001 NEW)
+
+qt6_add_qml_module(qmltc_exported_no_file_name_test_module
+ URI QmltcExportedNoFileNameTest
+ QML_FILES
+ HelloExportedWorldNoFileName.qml
+ DEPENDENCIES
+ Qt::Quick
+ ENABLE_TYPE_COMPILER
+ QMLTC_EXPORT_DIRECTIVE "Q_DECL_EXPORT"
+ # explicitly omitting QMLTC_EXPORT_FILE_NAME
+)
+
+target_include_directories(qmltc_exported_no_file_name_test_module PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
+
+qt_autogen_tools_initial_setup(qmltc_exported_no_file_name_test_moduleplugin)
diff --git a/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml
new file mode 100644
index 0000000000..89986df5a6
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcExportedNoFileNameTest/HelloExportedWorldNoFileName.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property string myString: "Hello! I should be exported by qmltc"
+}
diff --git a/tests/auto/qml/qmltc/QmltcExportedTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcExportedTests/CMakeLists.txt
new file mode 100644
index 0000000000..709297bed4
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcExportedTests/CMakeLists.txt
@@ -0,0 +1,31 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_add_library(qmltc_exported_tests_module STATIC)
+qt_autogen_tools_initial_setup(qmltc_exported_tests_module)
+
+include(GenerateExportHeader)
+generate_export_header(qmltc_exported_tests_module)
+
+set(common_libraries
+ Qt::QuickPrivate
+)
+
+target_link_libraries(qmltc_exported_tests_module PUBLIC ${common_libraries})
+
+qt_policy(SET QTP0001 NEW)
+
+qt6_add_qml_module(qmltc_exported_tests_module
+ URI QmltcExportedTests
+ QML_FILES
+ HelloExportedWorld.qml
+ DEPENDENCIES
+ Qt::Quick
+ ENABLE_TYPE_COMPILER
+ QMLTC_EXPORT_DIRECTIVE "QMLTC_EXPORTED_TESTS_MODULE_EXPORT"
+ QMLTC_EXPORT_FILE_NAME "qmltc_exported_tests_module_export.h"
+)
+
+target_include_directories(qmltc_exported_tests_module PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
+
+qt_autogen_tools_initial_setup(qmltc_exported_tests_moduleplugin)
diff --git a/tests/auto/qml/qmltc/QmltcExportedTests/HelloExportedWorld.qml b/tests/auto/qml/qmltc/QmltcExportedTests/HelloExportedWorld.qml
new file mode 100644
index 0000000000..5e6886bced
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcExportedTests/HelloExportedWorld.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string myString: "Hello! I should be exported by qmltc"
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
index 870d21f61d..4c472ec4ab 100644
--- a/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
+++ b/tests/auto/qml/qmltc/QmltcTests/CMakeLists.txt
@@ -22,6 +22,8 @@ set(cpp_sources
cpptypes/singletontype.h cpptypes/singletontype.cpp
cpptypes/typewithnamespace.h cpptypes/typewithnamespace.cpp
cpptypes/typewithsignal.h
+ cpptypes/custominitialization.h
+ cpptypes/typewithrequiredproperties.h
)
set(qml_sources
@@ -44,11 +46,16 @@ set(qml_sources
regexpBindings.qml
AliasBase.qml
aliasAssignments.qml
+ Connections.qml
qtbug103956/SubComponent.qml
qtbug103956/MainComponent.qml
qtbug103956/qtbug103956_main.qml
+ qtbug120700_main.qml
+
+ qtbug123476.qml
+
signalHandlers.qml
javaScriptFunctions.qml
changingBindings.qml
@@ -108,6 +115,9 @@ set(qml_sources
inlineComponentsFromDifferentFiles.qml
singletons.qml
mySignals.qml
+ stringToUrl.qml
+ myCheckBox.qml
+ signalConnections.qml
# support types:
DefaultPropertySingleChild.qml
@@ -125,6 +135,8 @@ set(qml_sources
NamespacedTypes.qml
badFile.qml
+
+ requiredProperties.qml
)
set(js_sources
@@ -135,10 +147,16 @@ set(common_libraries
Qt::Core
Qt::QmlPrivate
Qt::QuickPrivate
+ Qt::QuickTemplates2Private
Qt::TestPrivate
Qt::Gui # QColor, QMatrix4x4, ...
)
+if (QT_FEATURE_qml_table_model)
+ list(APPEND qml_sources QmlTableModel.qml)
+ list(APPEND common_libraries Qt::LabsQmlModelsPrivate)
+endif()
+
set_source_files_properties(NameConflict.qml PROPERTIES
QT_QMLTC_FILE_BASENAME ResolvedNameConflict)
@@ -166,10 +184,11 @@ qt_internal_add_resource(qmltc_test_module "qmake_immediate"
${qmake_immediate_resource_files}
)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(qmltc_test_module
VERSION 1.0
URI QmltcTests
- AUTO_RESOURCE_PREFIX
SOURCES
${cpp_sources}
QML_FILES
diff --git a/tests/auto/qml/qmltc/QmltcTests/Connections.qml b/tests/auto/qml/qmltc/QmltcTests/Connections.qml
new file mode 100644
index 0000000000..d7fc0d87c6
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/Connections.qml
@@ -0,0 +1,12 @@
+import QtQuick
+
+Rectangle {
+ property string hello
+
+ id: root
+
+ Connections {
+ target: root
+ function onHelloChanged(argument) {}
+ }
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml b/tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml
index 9dbe9d6fbe..d3c1cfe293 100644
--- a/tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/InlineComponentProvider.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/QmlTableModel.qml b/tests/auto/qml/qmltc/QmltcTests/QmlTableModel.qml
new file mode 100644
index 0000000000..696c2b40bb
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/QmlTableModel.qml
@@ -0,0 +1,62 @@
+// Copyright (C) 2019 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 2.12
+import QtQuick.Window 2.12
+import Qt.labs.qmlmodels 1.0
+
+TableView {
+ anchors.fill: parent
+ columnSpacing: 1
+ rowSpacing: 1
+ boundsBehavior: Flickable.StopAtBounds
+
+ model: TableModel {
+ property string testName: "MyTableModel"
+ TableModelColumn { display: "checked" }
+ TableModelColumn { display: "amount" }
+ TableModelColumn { display: "fruitType" }
+ TableModelColumn { display: "fruitName" }
+ TableModelColumn { display: "fruitPrice" }
+
+ // Each row is one type of fruit that can be ordered
+ rows: [
+ {
+ // Each property is one cell/column.
+ checked: false,
+ amount: 1,
+ fruitType: "Apple",
+ fruitName: "Granny Smith",
+ fruitPrice: 1.50
+ },
+ {
+ checked: true,
+ amount: 4,
+ fruitType: "Orange",
+ fruitName: "Navel",
+ fruitPrice: 2.50
+ },
+ {
+ checked: false,
+ amount: 1,
+ fruitType: "Banana",
+ fruitName: "Cavendish",
+ fruitPrice: 3.50
+ }
+ ]
+ }
+ delegate: TextInput {
+ text: model.display
+ padding: 12
+ selectByMouse: true
+
+ onAccepted: model.display = text
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#efefef"
+ z : -1
+ }
+ }
+}
+
diff --git a/tests/auto/qml/qmltc/QmltcTests/aliases.qml b/tests/auto/qml/qmltc/QmltcTests/aliases.qml
index 9f13f7b17a..41c34b4187 100644
--- a/tests/auto/qml/qmltc/QmltcTests/aliases.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/aliases.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml b/tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml
index 680e297edb..70636c0a2e 100644
--- a/tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/appendToQQmlListProperty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QmltcTests
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/custominitialization.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/custominitialization.h
new file mode 100644
index 0000000000..7546f344d2
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/custominitialization.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef CUSTOMINITIALIAZATION_H_
+#define CUSTOMINITIALIAZATION_H_
+
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQml/qqmllist.h>
+#include <QtQml/qqmlregistration.h>
+
+class ExtensionType : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+ Q_PROPERTY(double propertyFromExtension READ getPropertyFromExtension WRITE
+ setPropertyFromExtension)
+ Q_PROPERTY(QQmlListProperty<QQuickItem> extensionObjectList READ getExtensionObjectList)
+
+ QProperty<double> m_propertyFromExtension{ 0 };
+ QList<QQuickItem *> m_extensionObjectList;
+
+public:
+ ExtensionType(QObject *parent = nullptr) : QObject(parent) { }
+
+ double getPropertyFromExtension() const { return m_propertyFromExtension; }
+ void setPropertyFromExtension(double v) { m_propertyFromExtension = v; }
+
+ QQmlListProperty<QQuickItem> getExtensionObjectList()
+ {
+ return QQmlListProperty<QQuickItem>(this, &m_extensionObjectList);
+ }
+};
+
+class TypeForCustomInitialization : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(QQmlListProperty<QQuickItem> cppObjectList READ getCppObjectList)
+ Q_PROPERTY(
+ double defaultedBindable BINDABLE bindableDefaultedBindable READ default WRITE default)
+
+ QML_EXTENDED(ExtensionType)
+
+ QList<QQuickItem *> m_cppObjectList;
+ QProperty<double> m_defaultedBindable;
+
+public:
+ TypeForCustomInitialization(QObject *parent = nullptr) : QObject(parent) { }
+
+ QQmlListProperty<QQuickItem> getCppObjectList()
+ {
+ return QQmlListProperty<QQuickItem>(this, &m_cppObjectList);
+ }
+
+ QBindable<double> bindableDefaultedBindable()
+ {
+ return QBindable<double>(&m_defaultedBindable);
+ }
+};
+
+#endif // CUSTOMINITIALIAZATION_H_
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp
index 422e0021f1..1487dbcf15 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "deferredpropertytypes.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h
index d9aa801c77..1701d6ee91 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/deferredpropertytypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DEFERREDPROPERTYTYPES_H
#define DEFERREDPROPERTYTYPES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp
index 16f555c0b7..b6ed76eed4 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "extensiontypes.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h
index 667e2952ce..080d3b4380 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/extensiontypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef EXTENSIONTYPES_H
#define EXTENSIONTYPES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h
index 31cb385cfd..3135f4e3d3 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/private/testprivateproperty_p.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// NB: fake private header for testing purposes
#ifndef TESTPRIVATEPROPERTY_P_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h
index 293aece065..a2e1518fc3 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/singletontype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SINGLETONTYPE_H
#define SINGLETONTYPE_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp
index fd70c0a3f4..b44945fba0 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testattachedtype.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h
index b7cc6348aa..2e3ef97009 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testattachedtype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTATTACHEDTYPE_H
#define TESTATTACHEDTYPE_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp
index 410aae1528..45d6c3e322 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testgroupedtype.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h
index f895f19531..cef875545c 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testgroupedtype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTGROUPEDTYPE_H
#define TESTGROUPEDTYPE_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp
index c1d101653c..f24728b597 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "private/testprivateproperty_p.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h
index 230c86affd..22863ba52a 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/testprivateproperty.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTPRIVATEPROPERTY_H
#define TESTPRIVATEPROPERTY_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h
index 873c38771e..b0f1a17adc 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithmanyproperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef PROPERTYALIASATTRIBUTES_H
#define PROPERTYALIASATTRIBUTES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp
index fbfaf447da..ae4aaa5092 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "typewithnamespace.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h
index 7b8bc7803a..173e8624ff 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithnamespace.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHNAMESPACE_H
#define TYPEWITHNAMESPACE_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp
index 80557209a5..eb0dae7465 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "typewithproperties.h"
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h
index e06f9079f9..d7a0d03405 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithproperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHPROPERTIES_H
#define TYPEWITHPROPERTIES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithrequiredproperties.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithrequiredproperties.h
new file mode 100644
index 0000000000..cc1ded9f74
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithrequiredproperties.h
@@ -0,0 +1,75 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+#include <QtQuick/qquickitem.h>
+#include <QtQml/qqmllist.h>
+#include <QtQml/qqmlregistration.h>
+
+#ifndef TYPEWITHREQUIREDPROPERTIES_H_
+# define TYPEWITHREQUIREDPROPERTIES_H_
+
+class ExtensionTypeWithRequiredProperties : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+
+ Q_PROPERTY(double requiredPropertyFromExtension READ getRequiredPropertyFromExtension WRITE
+ setRequiredPropertyFromExtension REQUIRED)
+
+ QProperty<double> m_requiredPropertyFromExtension{};
+
+public:
+ ExtensionTypeWithRequiredProperties(QObject *parent = nullptr) : QObject(parent) { }
+
+ double getRequiredPropertyFromExtension() const { return m_requiredPropertyFromExtension; }
+ void setRequiredPropertyFromExtension(double v) { m_requiredPropertyFromExtension = v; }
+};
+
+class TypeWithRequiredProperties : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(QQuickItem *inheritedRequiredProperty READ getInheritedRequiredProperty WRITE
+ setInheritedRequiredProperty REQUIRED)
+ Q_PROPERTY(int inheritedRequiredPropertyThatWillBeBound READ
+ getInheritedRequiredPropertyThatWillBeBound WRITE
+ setInheritedRequiredPropertyThatWillBeBound REQUIRED)
+ Q_PROPERTY(int nonRequiredInheritedPropertyThatWillBeMarkedRequired READ
+ getNonRequiredInheritedPropertyThatWillBeMarkedRequired WRITE
+ setNonRequiredInheritedPropertyThatWillBeMarkedRequired REQUIRED)
+
+ QML_EXTENDED(ExtensionTypeWithRequiredProperties)
+
+ QProperty<QQuickItem *> m_inheritedRequiredProperty{};
+ QProperty<int> m_inheritedRequiredPropertyThatWillBeBound{};
+ QProperty<int> m_nonRequiredInheritedPropertyThatWillBeMarkedRequired{};
+
+public:
+ TypeWithRequiredProperties(QObject *parent = nullptr) : QObject(parent) { }
+
+ QQuickItem *getInheritedRequiredProperty() const { return m_inheritedRequiredProperty; }
+ void setInheritedRequiredProperty(QQuickItem *v) { m_inheritedRequiredProperty = v; }
+
+ int getInheritedRequiredPropertyThatWillBeBound() const
+ {
+ return m_inheritedRequiredPropertyThatWillBeBound;
+ }
+ void setInheritedRequiredPropertyThatWillBeBound(int v)
+ {
+ m_inheritedRequiredPropertyThatWillBeBound = v;
+ }
+
+ int getNonRequiredInheritedPropertyThatWillBeMarkedRequired() const
+ {
+ return m_nonRequiredInheritedPropertyThatWillBeMarkedRequired;
+ }
+ void setNonRequiredInheritedPropertyThatWillBeMarkedRequired(int v)
+ {
+ m_nonRequiredInheritedPropertyThatWillBeMarkedRequired = v;
+ }
+};
+
+#endif // TYPEWITHREQUIREDPROPERTIES_H_
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h
index 139b431a40..6bb94ae051 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithsignal.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHSIGNAL_H
#define TYPEWITHSIGNAL_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h
index 9d68275b1e..8bf068ba35 100644
--- a/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h
+++ b/tests/auto/qml/qmltc/QmltcTests/cpptypes/typewithspecialproperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHSPECIALPROPERTIES_H
#define TYPEWITHSPECIALPROPERTIES_H
diff --git a/tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml b/tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml
index a037776a52..2c21298c35 100644
--- a/tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/generalizedGroupedProperty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml b/tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml
index f9146083f6..284a8f5034 100644
--- a/tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/inlineComponents.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick as MyQtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/myCheckBox.qml b/tests/auto/qml/qmltc/QmltcTests/myCheckBox.qml
new file mode 100644
index 0000000000..c5a2f5a7b8
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/myCheckBox.qml
@@ -0,0 +1,5 @@
+import QtQuick.Templates
+
+CheckBox {
+
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/mySignals.qml b/tests/auto/qml/qmltc/QmltcTests/mySignals.qml
index c79a0518c2..0348a0af54 100644
--- a/tests/auto/qml/qmltc/QmltcTests/mySignals.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/mySignals.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QmltcTests
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/properties.qml b/tests/auto/qml/qmltc/QmltcTests/properties.qml
index ca827519d5..f42b14a356 100644
--- a/tests/auto/qml/qmltc/QmltcTests/properties.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/properties.qml
@@ -26,13 +26,13 @@ QtObject {
property date dateP
property font fontP
property matrix4x4 matrix4x4P
- property point pointP
- property quaternion quatP
- property rect rectP
- property size sizeP
- property vector2d vec2dP
- property vector3d vec3dP
- property vector4d vec4dP
+ property point pointP: ({ x: 100, y: 200 })
+ property quaternion quatP: ({ x: 100, y: 200, z: 300, scalar: 400 })
+ property rect rectP: ({ x: 100, y: 200, width: 300, height: 400 })
+ property size sizeP: ({ width: 100, height: 200 })
+ property vector2d vec2dP : ({ x: 100, y: 200 })
+ property vector3d vec3dP: ({ x: 100, y: 200, z: 300 })
+ property vector4d vec4dP: ({ x: 100, y: 200, z: 300, w: 400 })
default property QtObject defaultObjP
readonly property string readonlyStringP: "foobar"
diff --git a/tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml b/tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml
index 66cd948ac4..fb57a2bbc8 100644
--- a/tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/propertyAliasAttributes.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QmltcTests
diff --git a/tests/auto/qml/qmltc/QmltcTests/qtbug120700_main.qml b/tests/auto/qml/qmltc/QmltcTests/qtbug120700_main.qml
new file mode 100644
index 0000000000..0796d00732
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/qtbug120700_main.qml
@@ -0,0 +1,25 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QmltcTests 1.0
+
+TypeForCustomInitialization {
+ id: myWindow
+ required property int someValue
+
+ property alias someValueAlias: myWindow.someValue
+ property int someValueBinding: someValue + 1
+
+ property bool wasSomeValueChanged: false
+
+ property int someComplexValueThatWillBeSet: { return 5 }
+ property int someComplexValueThatWillNotBeSet: { return 5 }
+
+ property list<int> valueTypeList : []
+ property list<Item> objectTypeList : []
+
+ //QTBUG-114403: onValueChanged should not trigger when setting
+ //the initial values.
+ onSomeValueChanged: { wasSomeValueChanged = true; }
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/qtbug123476.qml b/tests/auto/qml/qmltc/QmltcTests/qtbug123476.qml
new file mode 100644
index 0000000000..79aa178de4
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/qtbug123476.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ // qmltc should see that rectangle is used as the type argument
+ // for the list and produce an import for QQuickRectangle.
+ // Failure to do so will produce code that cannot compile and the
+ // test will fail at build time.
+ property list<Rectangle> listWithUniqueReferenceToType : []
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml b/tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml
index 7c4dad5a4e..d4eb72786b 100644
--- a/tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/repeaterCrash.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/requiredProperties.qml b/tests/auto/qml/qmltc/QmltcTests/requiredProperties.qml
new file mode 100644
index 0000000000..77e9c88b9b
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/requiredProperties.qml
@@ -0,0 +1,61 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QmltcTests 1.0
+
+TypeWithRequiredProperties {
+ id: self
+ required property int primitiveType
+ required property list<int> valueList
+ required property list<Item> objectList
+
+ property int propertyThatWillBeMarkedRequired
+
+ // This is already bound so it should not appear as part of the
+ // bundle.
+ inheritedRequiredPropertyThatWillBeBound : 10
+
+ // This should be ignored as it alias a required property we are
+ // already going to consider. It should thus not appear as part of
+ // the bundle.
+ property alias aliasToRequiredProperty : self.primitiveType
+
+ required propertyThatWillBeMarkedRequired
+ required nonRequiredInheritedPropertyThatWillBeMarkedRequired
+
+ property alias aliasToRequiredInner: inner.requiredInner
+
+ // This should be ignored as the underlying property is already bound.
+ property alias aliasToRequiredBoundedInner: inner.requiredBoundedInner
+
+ property alias aliasToInnerThatWillBeMarkedRequired: inner.nonRequiredInner
+ required aliasToInnerThatWillBeMarkedRequired
+
+ property int notRequired
+ property alias requiredAliasToUnrequiredProperty : self.notRequired
+ required requiredAliasToUnrequiredProperty
+
+ // When we have an alias to a required property in the same scope
+ // we exclude the alias in favor of setting the property directly.
+ // See for example aliasToRequiredProperty in this file.
+ //
+ // The following alias should instead be picked up, as it point to
+ // an inner scope.
+ // Nonetheless, an initial implementation had a bug that would
+ // discard the alias as long as a property with the same name as
+ // the target was present in the same scope.
+ //
+ // The following alias tests this initially failing case.
+ property alias aliasToPropertyThatShadows: inner.primitiveType
+
+ property Item children : Item {
+ id: inner
+ required property int requiredInner
+ property int nonRequiredInner
+ required property int requiredBoundedInner
+ requiredBoundedInner: 43
+
+ required property int primitiveType
+ }
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/signalConnections.qml b/tests/auto/qml/qmltc/QmltcTests/signalConnections.qml
new file mode 100644
index 0000000000..d88e3920c3
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/signalConnections.qml
@@ -0,0 +1,46 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ id: root
+
+ property bool cycleEnabled: false
+ property bool cycleFirst: false
+ property bool cycleSecond: false
+
+ property Timer enableTimer: Timer {
+ running: root.cycleEnabled
+ interval: 1
+ onTriggered: {
+ conn.enabled = !conn.enabled;
+ root.cycleEnabled = false;
+ }
+ }
+
+ property Timer firstTimer: Timer {
+ id: firstTimer
+ objectName: "first"
+ running: root.cycleFirst
+ interval: 1
+ onTriggered: root.cycleFirst = false
+ }
+
+ property Timer secondTimer: Timer {
+ objectName: "second"
+ running: root.cycleSecond
+ interval: 1
+ onTriggered: conn.target = this;
+ repeat: true
+ }
+
+ property Connections conn: Connections {
+ id: conn
+ target: firstTimer
+ function onTriggered(m) {
+ root.objectName = target.objectName
+ root.cycleSecond = false;
+ }
+ }
+}
diff --git a/tests/auto/qml/qmltc/QmltcTests/singletons.qml b/tests/auto/qml/qmltc/QmltcTests/singletons.qml
index a45e502bc0..d30a50dd6b 100644
--- a/tests/auto/qml/qmltc/QmltcTests/singletons.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/singletons.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QmltcTests
diff --git a/tests/auto/qml/qmltc/QmltcTests/stringToUrl.qml b/tests/auto/qml/qmltc/QmltcTests/stringToUrl.qml
new file mode 100644
index 0000000000..1172c42032
--- /dev/null
+++ b/tests/auto/qml/qmltc/QmltcTests/stringToUrl.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.12
+
+QtObject {
+ readonly property FontLoader iconLoader: FontLoader {
+ source: "qrc:/qt/qml/path/to/font.ttf"
+ }
+ property string myUrl: "qrc:/qt/qml/path/to/font2.ttf"
+ readonly property FontLoader iconLoader2: FontLoader {
+ source: myUrl
+ }
+}
+
diff --git a/tests/auto/qml/qmltc/QmltcTests/subfolder/code.js b/tests/auto/qml/qmltc/QmltcTests/subfolder/code.js
index a248743d29..7b552e7f67 100644
--- a/tests/auto/qml/qmltc/QmltcTests/subfolder/code.js
+++ b/tests/auto/qml/qmltc/QmltcTests/subfolder/code.js
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
function isGood(value)
{
diff --git a/tests/auto/qml/qmltc/QmltcTests/translations.qml b/tests/auto/qml/qmltc/QmltcTests/translations.qml
index e00d9f5b86..71e9298fd1 100644
--- a/tests/auto/qml/qmltc/QmltcTests/translations.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/translations.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/translationsById.qml b/tests/auto/qml/qmltc/QmltcTests/translationsById.qml
index e3606d9b0f..98fd5cb846 100644
--- a/tests/auto/qml/qmltc/QmltcTests/translationsById.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/translationsById.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml b/tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml
index 7226abbb2e..300af9d31f 100644
--- a/tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml
+++ b/tests/auto/qml/qmltc/QmltcTests/valueTypeListProperty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QtQuick
diff --git a/tests/auto/qml/qmltc/nameconflict.cpp b/tests/auto/qml/qmltc/nameconflict.cpp
index e95272913f..b1fb21977b 100644
--- a/tests/auto/qml/qmltc/nameconflict.cpp
+++ b/tests/auto/qml/qmltc/nameconflict.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "nameconflict.h"
#include <QtCore/qobject.h>
diff --git a/tests/auto/qml/qmltc/nameconflict.h b/tests/auto/qml/qmltc/nameconflict.h
index ea971b5159..64297af4d4 100644
--- a/tests/auto/qml/qmltc/nameconflict.h
+++ b/tests/auto/qml/qmltc/nameconflict.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef NAME_CONFLICT_FLAG
#define NAME_CONFLICT_FLAG
diff --git a/tests/auto/qml/qmltc/tst_qmltc.cpp b/tests/auto/qml/qmltc/tst_qmltc.cpp
index 1fa4030642..ef33cebc00 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.cpp
+++ b/tests/auto/qml/qmltc/tst_qmltc.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qmltc.h"
@@ -21,10 +21,12 @@
#include "qjsvalueassignments.h"
#include "extensiontypebindings.h"
#include "qtbug103956_main.h"
+#include "qtbug120700_main.h"
#include "nonstandardinclude.h"
#include "specialproperties.h"
#include "regexpbindings.h"
#include "aliasassignments.h"
+#include "connections.h"
#include "signalhandlers.h"
#include "javascriptfunctions.h"
@@ -77,12 +79,18 @@
#include "repeatercrash.h"
#include "aliases.h"
#include "inlinecomponentsfromdifferentfiles.h"
+#include "helloexportedworld.h"
+#include "helloexportedworldnofilename.h"
#include "testprivateproperty.h"
#include "singletons.h"
#include "mysignals.h"
#include "namespacedtypes.h"
#include "type.h"
+#include "qmltablemodel.h"
+#include "stringtourl.h"
+#include "signalconnections.h"
+#include "requiredproperties.h"
// Qt:
#include <QtCore/qstring.h>
@@ -147,11 +155,14 @@ void tst_qmltc::initTestCase()
QUrl("qrc:/qt/qml/QmltcTests/regexpBindings.qml"),
QUrl("qrc:/qt/qml/QmltcTests/AliasBase.qml"),
QUrl("qrc:/qt/qml/QmltcTests/aliasAssignments.qml"),
+ QUrl("qrc:/qt/qml/QmltcTests/Connections.qml"),
QUrl("qrc:/qt/qml/QmltcTests/qtbug103956/SubComponent.qml"),
QUrl("qrc:/qt/qml/QmltcTests/qtbug103956/MainComponent.qml"),
QUrl("qrc:/qt/qml/QmltcTests/qtbug103956/qtbug103956_main.qml"),
+ QUrl("qrc:/qt/qml/QmltcTests/qtbug120700_main.qml"),
+
QUrl("qrc:/qt/qml/QmltcTests/signalHandlers.qml"),
QUrl("qrc:/qt/qml/QmltcTests/javaScriptFunctions.qml"),
QUrl("qrc:/qt/qml/QmltcTests/changingBindings.qml"),
@@ -192,6 +203,7 @@ void tst_qmltc::initTestCase()
QUrl("qrc:/qt/qml/QmltcTests/calqlatrBits.qml"),
QUrl("qrc:/qt/qml/QmltcTests/valueTypeListProperty.qml"),
QUrl("qrc:/qt/qml/QmltcTests/appendToQQmlListProperty.qml"),
+ QUrl("qrc:/qt/qml/QmltcTests/requiredProperties.qml"),
};
QQmlEngine e;
@@ -374,7 +386,14 @@ void tst_qmltc::properties()
QCOMPARE(created.intP(), 42);
QCOMPARE(created.realP(), 2.32);
QCOMPARE(created.stringP(), u"hello, world"_s);
- QCOMPARE(created.urlP(), u"https://www.qt.io/"_s);
+ QCOMPARE(created.urlP(), QUrl(u"https://www.qt.io/"_s));
+ QCOMPARE(created.pointP(), QPoint(100, 200));
+ QCOMPARE(created.quatP(), QQuaternion(400, 100, 200, 300));
+ QCOMPARE(created.rectP(), QRectF(100, 200, 300, 400));
+ QCOMPARE(created.sizeP(), QSizeF(100, 200));
+ QCOMPARE(created.vec2dP(), QVector2D(100, 200));
+ QCOMPARE(created.vec3dP(), QVector3D(100, 200, 300));
+ QCOMPARE(created.vec4dP(), QVector4D(100, 200, 300, 400));
QCOMPARE(created.varP(), 42.42);
QCOMPARE(created.boolP(), true);
@@ -818,6 +837,103 @@ void tst_qmltc::visibleAliasMethods()
QCOMPARE(created.firstComponent()->setMe(), true);
}
+// QTBUG-120700
+void tst_qmltc::customInitialization()
+{
+ int valueToTest = 10;
+
+ QQuickItem firstItem;
+ QQuickItem secondItem;
+
+ QQmlEngine e;
+ PREPEND_NAMESPACE(qtbug120700_main)
+ created(&e, {valueToTest} ,nullptr, [valueToTest, &firstItem, &secondItem](auto& component) {
+ component.setSomeComplexValueThatWillBeSet(valueToTest);
+ component.setPropertyFromExtension(static_cast<double>(valueToTest));
+ component.setDefaultedBindable(static_cast<double>(valueToTest));
+ component.setValueTypeList({1, 2, 3, 4});
+ component.setObjectTypeList({&firstItem, &secondItem});
+ component.setExtensionObjectList({&firstItem, &secondItem});
+ component.setCppObjectList({&firstItem, &secondItem});
+ });
+
+ // QTBUG-114403: onValueChanged should have not been triggered
+ // when setting the initial value for the property.
+ // If this is true then the handler was called.
+ QCOMPARE(created.wasSomeValueChanged(), false);
+
+ // someComplexValueThatWillBeSet is set through a binding in the
+ // QML code, but is initialized when the instance is created.
+ // The bindings, which is generally set after the custom
+ // initialization was perfomed, should not overwrite the initial
+ // value that the user provided.
+ // On the other side, someComplexValueThatWillNotBeSet should
+ // still respect the original binding as an initial value for it
+ // was not provided.
+ QCOMPARE(created.someComplexValueThatWillBeSet(), valueToTest);
+ QCOMPARE(created.someComplexValueThatWillNotBeSet(), 5);
+
+ QCOMPARE(created.someValue(), valueToTest);
+ QCOMPARE(created.someValueAlias(), valueToTest);
+ QCOMPARE(created.someValueBinding(), valueToTest + 1);
+ QCOMPARE(created.property("propertyFromExtension").toDouble(), static_cast<double>(valueToTest));
+ QCOMPARE(created.bindableDefaultedBindable().value(), static_cast<double>(valueToTest));
+ QCOMPARE(created.valueTypeList(), QList({1, 2, 3, 4}));
+ QCOMPARE(created.objectTypeList().toList<QList<QQuickItem*>>(), QList({&firstItem, &secondItem}));
+ QCOMPARE(
+ created.property("extensionObjectList").value<QQmlListProperty<QQuickItem>>().toList<QList<QQuickItem*>>(),
+ QList({&firstItem, &secondItem})
+ );
+ QCOMPARE(created.getCppObjectList().toList<QList<QQuickItem*>>(), QList({&firstItem, &secondItem}));
+}
+
+void tst_qmltc::requiredPropertiesInitialization()
+{
+ QQuickItem item{};
+
+ int aliasToInnerThatWillBeMarkedRequired = 10;
+ int aliasToPropertyThatShadows = 42;
+ int aliasToRequiredInner = 11;
+ QQuickItem inheritedRequiredProperty{};
+ int nonRequiredInheritedPropertyThatWillBeMarkedRequired = 12;
+ QList<QQuickItem*> objectList{&item};
+ int primitiveType = 13;
+ int propertyThatWillBeMarkedRequired = 14;
+ int requiredAliasToUnrequiredProperty = 15;
+ double requiredPropertyFromExtension = 16.0;
+ QList<int> valueList{1, 2, 3, 4};
+
+ QQmlEngine e;
+ PREPEND_NAMESPACE(requiredProperties) created(
+ &e,
+ {
+ aliasToInnerThatWillBeMarkedRequired,
+ aliasToPropertyThatShadows,
+ aliasToRequiredInner,
+ &inheritedRequiredProperty,
+ nonRequiredInheritedPropertyThatWillBeMarkedRequired,
+ objectList,
+ primitiveType,
+ propertyThatWillBeMarkedRequired,
+ requiredAliasToUnrequiredProperty,
+ requiredPropertyFromExtension,
+ valueList
+ }
+ );
+
+ QCOMPARE(created.aliasToInnerThatWillBeMarkedRequired(), aliasToInnerThatWillBeMarkedRequired);
+ QCOMPARE(created.aliasToPropertyThatShadows(), aliasToPropertyThatShadows);
+ QCOMPARE(created.aliasToRequiredInner(), aliasToRequiredInner);
+ QCOMPARE(created.getInheritedRequiredProperty(), &inheritedRequiredProperty);
+ QCOMPARE(created.getNonRequiredInheritedPropertyThatWillBeMarkedRequired(), nonRequiredInheritedPropertyThatWillBeMarkedRequired);
+ QCOMPARE(created.objectList().toList<QList<QQuickItem*>>(), objectList);
+ QCOMPARE(created.primitiveType(), primitiveType);
+ QCOMPARE(created.propertyThatWillBeMarkedRequired(), propertyThatWillBeMarkedRequired);
+ QCOMPARE(created.requiredAliasToUnrequiredProperty(), requiredAliasToUnrequiredProperty);
+ QCOMPARE(created.property("requiredPropertyFromExtension").toDouble(), requiredPropertyFromExtension);
+ QCOMPARE(created.valueList(), valueList);
+}
+
// QTBUG-104094
void tst_qmltc::nonStandardIncludesInsideModule()
{
@@ -887,6 +1003,12 @@ void tst_qmltc::aliasAssignments()
}
}
+void tst_qmltc::connections()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(Connections) created(&e);
+}
+
void tst_qmltc::signalHandlers()
{
QQmlEngine e;
@@ -1058,7 +1180,7 @@ void tst_qmltc::propertyAlias_external()
void tst_qmltc::propertyAliasAttribute()
{
QQmlEngine e;
- PREPEND_NAMESPACE(propertyAliasAttributes) fromQmltc(&e);
+ PREPEND_NAMESPACE(propertyAliasAttributes) fromQmltc(&e, {""});
QQmlComponent c(&e);
c.loadUrl(QUrl("qrc:/qt/qml/QmltcTests/propertyAliasAttributes.qml"));
@@ -3204,8 +3326,74 @@ void tst_qmltc::namespacedName()
{
// cmake script should be able to auto-fill the namespace of the generated modules, and to
// replace . with ::
- NamespaceTest::Subfolder::Type *t;
- Q_UNUSED(t);
+ QQmlEngine e;
+ NamespaceTest::Subfolder::Type t(&e);
+ QCOMPARE(t.data(), u"Hello from namespace"_s);
+}
+
+void tst_qmltc::checkExportsAreCompiling()
+{
+ QQmlEngine e;
+ QmltcExportedTests::HelloExportedWorld w(&e);
+ QCOMPARE(w.myString(), u"Hello! I should be exported by qmltc"_s);
+}
+
+void tst_qmltc::checkExportsNoFileName()
+{
+ QQmlEngine e;
+ QmltcExportedNoFileNameTest::HelloExportedWorldNoFileName w(&e);
+ QCOMPARE(w.myString(), u"Hello! I should be exported by qmltc"_s);
+}
+
+#if QT_CONFIG(qml_table_model)
+void tst_qmltc::qmlTableModel()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(QmlTableModel) createdByQmltc(&e);
+ // check that the tableModel is not default constructed
+ QVariant model = createdByQmltc.model();
+ QVERIFY(model.isValid());
+ QQmlTableModel *tableModel = model.value<QQmlTableModel *>();
+ QVERIFY(tableModel);
+ QCOMPARE(tableModel->property("testName").toString(), u"MyTableModel"_s);
+}
+#endif
+
+void tst_qmltc::urlToString()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(stringToUrl) createdByQmltc(&e);
+ // check that the tableModel is not default constructed
+ QUrl first = createdByQmltc.iconLoader()->source();
+ QUrl second = createdByQmltc.iconLoader2()->source();
+ QCOMPARE(first, QUrl("qrc:/qt/qml/path/to/font.ttf"));
+ QCOMPARE(second, QUrl("qrc:/qt/qml/path/to/font2.ttf"));
+}
+
+void tst_qmltc::signalConnections()
+{
+ QQmlEngine e;
+ PREPEND_NAMESPACE(signalConnections) createdByQmltc(&e);
+
+ QVERIFY(createdByQmltc.objectName().isEmpty());
+ createdByQmltc.setCycleFirst(true);
+ QTRY_VERIFY(!createdByQmltc.cycleFirst());
+ QCOMPARE(createdByQmltc.objectName(), QLatin1String("first"));
+
+ createdByQmltc.setObjectName(QLatin1String("none"));
+ createdByQmltc.setCycleEnabled(true);
+ QTRY_VERIFY(!createdByQmltc.cycleEnabled());
+
+ createdByQmltc.setCycleFirst(true);
+ QTRY_VERIFY(!createdByQmltc.cycleFirst());
+ QCOMPARE(createdByQmltc.objectName(), QLatin1String("none"));
+
+ createdByQmltc.setCycleEnabled(true);
+ QTRY_VERIFY(!createdByQmltc.cycleEnabled());
+
+ createdByQmltc.setCycleSecond(true);
+ QTRY_VERIFY(!createdByQmltc.cycleSecond());
+ QCOMPARE(createdByQmltc.objectName(), QLatin1String("second"));
}
QTEST_MAIN(tst_qmltc)
diff --git a/tests/auto/qml/qmltc/tst_qmltc.h b/tests/auto/qml/qmltc/tst_qmltc.h
index af084dcc01..ede6d551a0 100644
--- a/tests/auto/qml/qmltc/tst_qmltc.h
+++ b/tests/auto/qml/qmltc/tst_qmltc.h
@@ -1,7 +1,8 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
+#include <private/qtqmlmodelsglobal_p.h>
using namespace Qt::StringLiterals;
@@ -34,10 +35,13 @@ private slots:
void jsvalueAssignments();
void extensionTypeBindings();
void visibleAliasMethods(); // QTBUG-103956
+ void customInitialization(); // QTBUG-120700
+ void requiredPropertiesInitialization();
void nonStandardIncludesInsideModule(); // QTBUG-104094
void specialProperties();
void regexpBindings();
void aliasAssignments();
+ void connections();
void signalHandlers();
void jsFunctions();
@@ -93,4 +97,12 @@ private slots:
void constSignalParameters();
void cppNamespaces();
void namespacedName();
+ void checkExportsAreCompiling();
+ void checkExportsNoFileName();
+
+#if QT_CONFIG(qml_table_model)
+ void qmlTableModel();
+#endif
+ void urlToString();
+ void signalConnections();
};
diff --git a/tests/auto/qml/qmltc_manual/CMakeLists.txt b/tests/auto/qml/qmltc_manual/CMakeLists.txt
index 8101bcbcea..6f1b065f99 100644
--- a/tests/auto/qml/qmltc_manual/CMakeLists.txt
+++ b/tests/auto/qml/qmltc_manual/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmltc_manual LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -19,9 +25,10 @@ qt_internal_add_test(tst_qmltc_manual
TESTDATA ${test_data}
)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(tst_qmltc_manual
URI "QmltcManualTests"
- AUTO_RESOURCE_PREFIX
QML_FILES
${test_data}
)
diff --git a/tests/auto/qml/qmltc_manual/testclasses.h b/tests/auto/qml/qmltc_manual/testclasses.h
index a3fc9cfc21..879b815f16 100644
--- a/tests/auto/qml/qmltc_manual/testclasses.h
+++ b/tests/auto/qml/qmltc_manual/testclasses.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTCLASSES_H
#define TESTCLASSES_H
diff --git a/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp b/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp
index ca8e0895d7..6e41ff3baa 100644
--- a/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp
+++ b/tests/auto/qml/qmltc_manual/tst_qmltc_manual.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
diff --git a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
index bac445dec8..85c01d0a5f 100644
--- a/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
+++ b/tests/auto/qml/qmltc_qprocess/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmltc_qprocess LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qmltc_qprocess
SOURCES
tst_qmltc_qprocess.cpp
@@ -14,12 +20,14 @@ qt_internal_add_test(tst_qmltc_qprocess
set_source_files_properties(data/SingletonThing.qml data/singletonUncreatable.qml
PROPERTIES QT_QML_SINGLETON_TYPE true)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(tst_qmltc_qprocess
VERSION 1.0
URI QmltcQProcessTests
- AUTO_RESOURCE_PREFIX
SOURCES
cpptypes/testtype.h
+ cpptypes/typewithrequiredproperty.h
DEPENDENCIES
QtQuick/auto
QML_FILES
@@ -33,6 +41,13 @@ qt6_add_qml_module(tst_qmltc_qprocess
data/singletonUncreatable.qml
data/uncreatable.qml
data/invalidSignalHandlers.qml
+ data/QmlBaseFromAnotherModule.qml
+ data/invalidTypeAnnotation.qml
+ data/constructFromString.qml
+ data/unboundRequiredPropertyInInlineComponent.qml
+ data/componentDefinitionInnerRequiredProperty.qml
+ data/componentDefinitionInnerRequiredPropertyFromOutside.qml
+ data/innerLevelRequiredProperty.qml
)
set(common_libraries
diff --git a/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h b/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h
index 81c5f00c84..401a63accc 100644
--- a/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h
+++ b/tests/auto/qml/qmltc_qprocess/cpptypes/testtype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPE_H
#define TESTTYPE_H
diff --git a/tests/auto/qml/qmltc_qprocess/cpptypes/typewithrequiredproperty.h b/tests/auto/qml/qmltc_qprocess/cpptypes/typewithrequiredproperty.h
new file mode 100644
index 0000000000..1b0c69efaa
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/cpptypes/typewithrequiredproperty.h
@@ -0,0 +1,27 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef TYPEWITHREQUIREDPROPERTY_H_
+#define TYPEWITHREQUIREDPROPERTY_H_
+
+#include <QtCore/qobject.h>
+#include <QtCore/qproperty.h>
+#include <QtQml/qqmlregistration.h>
+
+class TypeWithRequiredProperty : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(QString requiredProperty READ requiredProperty WRITE setRequiredProperty REQUIRED)
+
+ QProperty<QString> m_requiredProperty;
+
+public:
+ TypeWithRequiredProperty(QObject *parent = nullptr) : QObject(parent) { }
+
+ QString requiredProperty() const { return m_requiredProperty; }
+ void setRequiredProperty(const QString &s) { m_requiredProperty = s; }
+};
+
+#endif // TYPEWITHREQUIREDPROPERTY_H_
diff --git a/tests/auto/qml/qmltc_qprocess/data/QmlBaseFromAnotherModule.qml b/tests/auto/qml/qmltc_qprocess/data/QmlBaseFromAnotherModule.qml
new file mode 100644
index 0000000000..3c62716105
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/QmlBaseFromAnotherModule.qml
@@ -0,0 +1,13 @@
+import QtQml
+import QtQuick
+import QtQuick.Controls.Basic
+import QtQuick.Window
+
+Item {
+ property ScrollBar myBar: ScrollBar {}
+ function f(a: ScrollBar): ScrollBar {}
+
+ // C++ defined QML types from other modules are fine
+ property Item myItem: Item {}
+ function g(a: Item): Item {}
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredProperty.qml b/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredProperty.qml
new file mode 100644
index 0000000000..638cf9fa1e
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredProperty.qml
@@ -0,0 +1,18 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ Component {
+ id: mycomp
+
+ Item {
+ Rectangle {
+ // Inner required properties cannot be set so this
+ // should produce an error
+ required property bool bar
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredPropertyFromOutside.qml b/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredPropertyFromOutside.qml
new file mode 100644
index 0000000000..56f00edbe9
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/componentDefinitionInnerRequiredPropertyFromOutside.qml
@@ -0,0 +1,18 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QmltcQProcessTests
+
+Item {
+ Component {
+ id: mycomp
+
+ Item {
+ // This introduces an inner required property
+ // without a binding that cannot be set later and should
+ // thus block the compilation.
+ TypeWithRequiredProperty {}
+ }
+ }
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/constructFromString.qml b/tests/auto/qml/qmltc_qprocess/data/constructFromString.qml
new file mode 100644
index 0000000000..76ec189f3d
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/constructFromString.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ property point p: "30,50"
+ property rect p3: "10, 20, 30x50"
+ property size p4: "30x50"
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/innerLevelRequiredProperty.qml b/tests/auto/qml/qmltc_qprocess/data/innerLevelRequiredProperty.qml
new file mode 100644
index 0000000000..8b28418670
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/innerLevelRequiredProperty.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ Item {
+ required property int foo
+ }
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml b/tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml
index 55e3e73c31..44111430f7 100644
--- a/tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml
+++ b/tests/auto/qml/qmltc_qprocess/data/invalidAliasRevision.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
import QmltcQProcessTests
diff --git a/tests/auto/qml/qmltc_qprocess/data/invalidTypeAnnotation.qml b/tests/auto/qml/qmltc_qprocess/data/invalidTypeAnnotation.qml
new file mode 100644
index 0000000000..fb8c8eb198
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/invalidTypeAnnotation.qml
@@ -0,0 +1,20 @@
+import QtQuick
+
+
+Item {
+ function f(): Qt.point {
+
+ }
+
+ function g() {
+
+ }
+
+ function h(a: int, b: Item) {
+
+ }
+
+ function alpha(a: int, b) {}
+ function beta(a: int, b): Item {}
+ function gamma(a: Qt.point, b) {}
+}
diff --git a/tests/auto/qml/qmltc_qprocess/data/unboundRequiredPropertyInInlineComponent.qml b/tests/auto/qml/qmltc_qprocess/data/unboundRequiredPropertyInInlineComponent.qml
new file mode 100644
index 0000000000..3955a228d8
--- /dev/null
+++ b/tests/auto/qml/qmltc_qprocess/data/unboundRequiredPropertyInInlineComponent.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ component InlineComponent: Item { required property int foo }
+
+ InlineComponent {}
+}
diff --git a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
index 7f12f29342..cdbd9695fd 100644
--- a/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
+++ b/tests/auto/qml/qmltc_qprocess/tst_qmltc_qprocess.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
@@ -51,6 +51,14 @@ private slots:
void topLevelComponent();
void dashesInFilename();
void invalidSignalHandlers();
+ void exports();
+ void qmlBaseFromAnotherModule();
+ void invalidTypeAnnotation();
+ void constructFromString();
+ void unboundRequiredPropertyInInlineComponent();
+ void componentDefinitionInnerRequiredProperty();
+ void componentDefinitionInnerRequiredPropertyFromOutside();
+ void innerLevelRequiredProperty();
};
#ifndef TST_QMLTC_QPROCESS_RESOURCES
@@ -92,6 +100,7 @@ QString tst_qmltc_qprocess::runQmltc(const QString &inputFile,
args << u"--resource"_s << resource;
args << u"--header"_s << (m_tmpPath + u"/"_s + QFileInfo(inputFile).baseName() + u".h"_s);
args << u"--impl"_s << (m_tmpPath + u"/"_s + QFileInfo(inputFile).baseName() + u".cpp"_s);
+ args << u"--module"_s << u"QmltcQProcessTestModule"_s;
args << extraArgs;
QString errors;
@@ -144,7 +153,7 @@ void tst_qmltc_qprocess::noBuiltins()
QVERIFY(file.rename(original));
};
- for (QString builtin : { u"builtins.qmltypes"_s, u"jsroot.qmltypes"_s }) {
+ for (QString builtin : { u"jsroot.qmltypes"_s, u"builtins.qmltypes"_s }) {
const auto path = QLibraryInfo::path(QLibraryInfo::QmlImportsPath) + u"/"_s + builtin;
QScopeGuard scope(std::bind(renameBack, path));
@@ -261,5 +270,120 @@ void tst_qmltc_qprocess::invalidSignalHandlers()
}
}
+void tst_qmltc_qprocess::qmlBaseFromAnotherModule()
+{
+ {
+ const auto errors = runQmltc(u"QmlBaseFromAnotherModule.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"QmlBaseFromAnotherModule.qml:6:1: Can't compile the QML property type \"ScrollBar\" to C++ because it lives in \"QtQuick.Controls.Basic\" instead of the current file's \"QmltcQProcessTestModule\" QML module."_s));
+ QVERIFY(errors.contains(
+ u"QmlBaseFromAnotherModule.qml:6:1: Can't compile the QML method return type \"ScrollBar\" to C++ because it lives in \"QtQuick.Controls.Basic\" instead of the current file's \"QmltcQProcessTestModule\" QML module."_s));
+ QVERIFY(errors.contains(
+ u"QmlBaseFromAnotherModule.qml:6:1: Can't compile the QML parameter type \"ScrollBar\" to C++ because it lives in \"QtQuick.Controls.Basic\" instead of the current file's \"QmltcQProcessTestModule\" QML module."_s));
+ // it should not complain about the usages of Item, a C++ defined QML element from another
+ // module
+ QVERIFY(!errors.contains(u"\"Item\""_s));
+ }
+}
+
+void tst_qmltc_qprocess::invalidTypeAnnotation()
+{
+ {
+ const auto errors = runQmltc(u"invalidTypeAnnotation.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"invalidTypeAnnotation.qml:5:17: \"Qt.point\" was not found for the return type of method \"f\"."_s));
+ QVERIFY(errors.contains(
+ u"invalidTypeAnnotation.qml:19:21: \"Qt.point\" was not found for the type of parameter \"a\" in method \"gamma\"."_s));
+ QVERIFY(!errors.contains(u"\"var\""_s));
+ QVERIFY(!errors.contains(u"\"void\""_s));
+ }
+}
+
+static QString fileToString(const QString &path)
+{
+ QFile f(path);
+ if (f.open(QIODevice::ReadOnly))
+ return QString::fromLatin1(f.readAll());
+ return QString();
+}
+
+void tst_qmltc_qprocess::exports()
+{
+ const QString fileName = u"dummy.qml"_s;
+ QStringList extraArgs;
+ extraArgs << "--export"
+ << "MYLIB_EXPORT_MACRO"
+ << "--exportInclude"
+ << "exportheader.h";
+ const auto errors = runQmltc(fileName, true, extraArgs);
+
+ const QString headerName = m_tmpPath + u"/"_s + QFileInfo(fileName).baseName() + u".h"_s;
+ const QString header = fileToString(headerName);
+ const QString implementationName =
+ m_tmpPath + u"/"_s + QFileInfo(fileName).baseName() + u".cpp"_s;
+ const QString implementation = fileToString(implementationName);
+
+ QCOMPARE(errors.size(), 0);
+
+ QVERIFY(header.contains(u"class MYLIB_EXPORT_MACRO dummy : public QObject\n"_s));
+ QVERIFY(!implementation.contains(u"MYLIB_EXPORT_MACRO"_s));
+
+ QVERIFY(header.contains(u"#include \"exportheader.h\"\n"_s));
+ QVERIFY(!implementation.contains(u"exportheader.h"_s));
+}
+
+void tst_qmltc_qprocess::constructFromString()
+{
+ const auto errors = runQmltc(u"constructFromString.qml"_s, false);
+ const QString warningMessage =
+ u"constructFromString.qml:%1:%2: Binding is not supported: Type %3 should be"
+ u" constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a"
+ u" string."_s;
+ QVERIFY(errors.contains(warningMessage.arg(4).arg(23).arg(u"QPointF")));
+ QVERIFY(errors.contains(warningMessage.arg(5).arg(23).arg(u"QRectF")));
+ QVERIFY(errors.contains(warningMessage.arg(6).arg(23).arg(u"QSizeF")));
+}
+
+void tst_qmltc_qprocess::unboundRequiredPropertyInInlineComponent()
+{
+ {
+ const auto errors = runQmltc(u"unboundRequiredPropertyInInlineComponent.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"unboundRequiredPropertyInInlineComponent.qml:9:5: Component is missing required property foo from InlineComponent [required]"_s
+ ));
+ }
+}
+
+void tst_qmltc_qprocess::componentDefinitionInnerRequiredProperty()
+{
+ {
+ const auto errors = runQmltc(u"componentDefinitionInnerRequiredProperty.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"componentDefinitionInnerRequiredProperty.qml:11:13: Component is missing required property bar from here [required]"
+ ));
+ }
+}
+
+void tst_qmltc_qprocess::componentDefinitionInnerRequiredPropertyFromOutside()
+{
+ {
+ const auto errors =
+ runQmltc(u"componentDefinitionInnerRequiredPropertyFromOutside.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"componentDefinitionInnerRequiredPropertyFromOutside.qml:15:13: Component is missing required property requiredProperty from TypeWithRequiredProperty [required]"
+ ));
+ }
+}
+
+void tst_qmltc_qprocess::innerLevelRequiredProperty()
+{
+ {
+ const auto errors = runQmltc(u"innerLevelRequiredProperty.qml"_s, false);
+ QVERIFY(errors.contains(
+ u"innerLevelRequiredProperty.qml:7:5: Component is missing required property foo from here [required]"
+ ));
+ }
+}
+
QTEST_MAIN(tst_qmltc_qprocess)
#include "tst_qmltc_qprocess.moc"
diff --git a/tests/auto/qml/qmltyperegistrar/CMakeLists.txt b/tests/auto/qml/qmltyperegistrar/CMakeLists.txt
index 039f1647db..45669769e4 100644
--- a/tests/auto/qml/qmltyperegistrar/CMakeLists.txt
+++ b/tests/auto/qml/qmltyperegistrar/CMakeLists.txt
@@ -7,12 +7,18 @@
## tst_qmltyperegistrar Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmltyperegistrar LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
add_subdirectory(VersionZero)
add_subdirectory(UnregisteredTypes)
add_subdirectory(foreign)
qt_manual_moc(moc_files OUTPUT_MOC_JSON_FILES json_list noextheader
- INCLUDE_DIRECTORY_TARGETS Qt::Qml)
+ TARGETS Qt6::Qml)
# Dummy target to pass --private-includes to qmltyperegistrar for tst_qmltyperegistrar.
# We want to test that it expects files named foo_p.h appearing in foreign metatypes
@@ -76,9 +82,11 @@ qt_add_library(tst-qmltyperegistrar-with-dashes)
qt_autogen_tools_initial_setup(tst-qmltyperegistrar-with-dashes)
target_link_libraries(tst-qmltyperegistrar-with-dashes PRIVATE Qt::Core Qt::Qml)
qt_enable_autogen_tool(tst-qmltyperegistrar-with-dashes "moc" ON)
+
+qt_policy(SET QTP0001 NEW)
+
qt_add_qml_module(tst-qmltyperegistrar-with-dashes
URI Module-With-Dashes
- AUTO_RESOURCE_PREFIX
SOURCES
foo.cpp foo.h
OUTPUT_DIRECTORY Module-With-Dashes
@@ -90,4 +98,20 @@ qt_internal_add_resource(tst_qmltyperegistrar "resources"
"/"
FILES
duplicatedExports.json
+ missingTypes.json
)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+qt_add_library(tst-qmltyperegistrar-enum-foreign STATIC enum.cpp)
+qt_autogen_tools_initial_setup(tst-qmltyperegistrar-enum-foreign)
+qt_enable_autogen_tool(tst-qmltyperegistrar-enum-foreign "moc" ON)
+target_link_libraries(tst-qmltyperegistrar-enum-foreign PRIVATE Qt::QmlIntegration)
+
+qt_add_library(tst-qmltyperegistrar-enum STATIC)
+qt_autogen_tools_initial_setup(tst-qmltyperegistrar-enum)
+qt_enable_autogen_tool(tst-qmltyperegistrar-enum "moc" ON)
+target_link_libraries(tst-qmltyperegistrar-enum PRIVATE Qt::Qml tst-qmltyperegistrar-enum-foreign)
+
+qt_add_qml_module(tst-qmltyperegistrar-enum URI TstEnum OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/TstEnum)
+qt_autogen_tools_initial_setup(tst-qmltyperegistrar-enumplugin)
+qt_generate_foreign_qml_types(tst-qmltyperegistrar-enum-foreign tst-qmltyperegistrar-enum)
diff --git a/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt b/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt
index cb020e95e0..d469f1e97f 100644
--- a/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt
+++ b/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/CMakeLists.txt
@@ -2,13 +2,15 @@
# SPDX-License-Identifier: BSD-3-Clause
# Use NO_GENERATE_QMLTYPES to avoid static asserts during compilation of the types to be tested, same for NO_PLUGIN
+
+qt_policy(SET QTP0001 NEW)
+
qt_add_qml_module(UnregisteredTypes
STATIC
URI UnregisteredTypes
NO_GENERATE_QMLTYPES
NO_PLUGIN
SOURCES uncreatable.h
- AUTO_RESOURCE_PREFIX
)
qt_enable_autogen_tool(UnregisteredTypes "moc" ON)
diff --git a/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h b/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h
index 9726f4683c..2274f87e3d 100644
--- a/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h
+++ b/tests/auto/qml/qmltyperegistrar/UnregisteredTypes/uncreatable.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef UNCREATABLE_H
#define UNCREATABLE_H
@@ -39,6 +39,39 @@ public:
static SingletonCreatable3 *create(QQmlEngine *, QJSEngine *) { return nullptr; }
};
+class SingletonForeign : public QObject
+{
+ Q_OBJECT
+ SingletonForeign() = delete;
+};
+
+class SingletonLocalCreatable
+{
+ Q_GADGET
+ QML_FOREIGN(SingletonForeign)
+ QML_ELEMENT
+ QML_SINGLETON
+public:
+ static SingletonForeign *create(QQmlEngine *, QJSEngine *) { return nullptr; }
+};
+
+class SingletonLocalUncreatable1
+{
+ Q_GADGET
+ QML_FOREIGN(SingletonForeign)
+ QML_ELEMENT
+ QML_SINGLETON
+ static SingletonForeign *create(QQmlEngine *, QJSEngine *) { return nullptr; }
+};
+
+class SingletonLocalUncreatable2
+{
+ Q_GADGET
+ QML_FOREIGN(SingletonForeign)
+ QML_ELEMENT
+ QML_SINGLETON
+};
+
class SingletonIncreatable : public QObject
{
Q_OBJECT
@@ -184,4 +217,20 @@ class FixingBadUncreatable
QML_FOREIGN(BadUncreatable)
QML_UNCREATABLE("")
};
+
+class SingletonVesion0 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ // is default constructible
+};
+
+class SingletonVesion1 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+ // is default constructible
+};
#endif // UNCREATABLE_H
diff --git a/tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h b/tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h
index a3277e6ab3..0ad477c3cb 100644
--- a/tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h
+++ b/tests/auto/qml/qmltyperegistrar/VersionZero/version_zero_type.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef VERSION_ZERO_TYPE_H
#define VERSION_ZERO_TYPE_H
diff --git a/tests/auto/qml/qmltyperegistrar/duplicatedExports.h b/tests/auto/qml/qmltyperegistrar/duplicatedExports.h
index 5ae2e77551..e72a2f19c9 100644
--- a/tests/auto/qml/qmltyperegistrar/duplicatedExports.h
+++ b/tests/auto/qml/qmltyperegistrar/duplicatedExports.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DUPLICATEDEXPORTS_H
#define DUPLICATEDEXPORTS_H
diff --git a/tests/auto/qml/qmltyperegistrar/enum.cpp b/tests/auto/qml/qmltyperegistrar/enum.cpp
new file mode 100644
index 0000000000..34d2e00ffa
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/enum.cpp
@@ -0,0 +1,5 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "enum.h"
+#include "moc_enum.cpp"
diff --git a/tests/auto/qml/qmltyperegistrar/enum.h b/tests/auto/qml/qmltyperegistrar/enum.h
new file mode 100644
index 0000000000..653c48c79f
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/enum.h
@@ -0,0 +1,40 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef ENUM_NS_HELLO_H
+#define ENUM_NS_HELLO_H
+
+#include <QObject>
+#include <QtQmlIntegration/qqmlintegration.h>
+
+namespace Hello {
+ Q_NAMESPACE
+ QML_NAMED_ELEMENT(World)
+ enum class World {
+ Europe = 2024,
+ };
+ Q_ENUM_NS(World)
+}
+
+namespace Universe {
+ namespace Galaxy {
+ Q_NAMESPACE
+ QML_NAMED_ELEMENT(Solar)
+ enum class Solar {
+ Earth,
+ };
+ Q_ENUM_NS(Solar)
+ }
+
+ class Blackhole {
+ Q_GADGET
+ QML_ELEMENT
+ public:
+ enum SagittariusA {
+ Singularity
+ };
+ Q_ENUM(SagittariusA)
+ };
+}
+
+#endif // ENUM_NS_HELLO_H
diff --git a/tests/auto/qml/qmltyperegistrar/foo.cpp b/tests/auto/qml/qmltyperegistrar/foo.cpp
index ba95235bd6..c5ef8313dc 100644
--- a/tests/auto/qml/qmltyperegistrar/foo.cpp
+++ b/tests/auto/qml/qmltyperegistrar/foo.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "foo.h"
#include <QDebug>
diff --git a/tests/auto/qml/qmltyperegistrar/foo.h b/tests/auto/qml/qmltyperegistrar/foo.h
index 7872c35c17..5af2e11eaa 100644
--- a/tests/auto/qml/qmltyperegistrar/foo.h
+++ b/tests/auto/qml/qmltyperegistrar/foo.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef FOO_H
#define FOO_H
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt b/tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt
index 5334225692..68223ae6a5 100644
--- a/tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt
+++ b/tests/auto/qml/qmltyperegistrar/foreign/CMakeLists.txt
@@ -10,7 +10,8 @@
qt_internal_add_cmake_library(foreign
STATIC
SOURCES
- foreign.cpp foreign.h foreign_p.h
+ foreign.cpp foreign.h
+ private/foreign_p.h
PUBLIC_LIBRARIES
Qt::Core
)
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp b/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
index f78dd47237..1691f5396a 100644
--- a/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "foreign.h"
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign.h b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
index ea78a58432..79ac8074cf 100644
--- a/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
+++ b/tests/auto/qml/qmltyperegistrar/foreign/foreign.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef FOREIGN_H
#define FOREIGN_H
diff --git a/tests/auto/qml/qmltyperegistrar/foreign/foreign_p.h b/tests/auto/qml/qmltyperegistrar/foreign/private/foreign_p.h
index fe7986471f..ed23d78284 100644
--- a/tests/auto/qml/qmltyperegistrar/foreign/foreign_p.h
+++ b/tests/auto/qml/qmltyperegistrar/foreign/private/foreign_p.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef FOREIGN_P_H
#define FOREIGN_P_H
@@ -7,7 +7,6 @@
#include <QtCore/qobject.h>
// qmltyperegistrar will assume this file is reachable under <private/foreign_p.h>
-// It's not true, but this is how it works on actual private headers in Qt.
// See the trick in tst_qmltyperegistrar's CMakeLists.txt to turn on the --private-includes option.
class ForeignPrivate : public QObject
{
diff --git a/tests/auto/qml/qmltyperegistrar/hppheader.hpp b/tests/auto/qml/qmltyperegistrar/hppheader.hpp
index dc82fc8530..4278601a9e 100644
--- a/tests/auto/qml/qmltyperegistrar/hppheader.hpp
+++ b/tests/auto/qml/qmltyperegistrar/hppheader.hpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef HPPHEADER_HPP
#define HPPHEADER_HPP
diff --git a/tests/auto/qml/qmltyperegistrar/missingTypes.json b/tests/auto/qml/qmltyperegistrar/missingTypes.json
new file mode 100644
index 0000000000..dacec11c4c
--- /dev/null
+++ b/tests/auto/qml/qmltyperegistrar/missingTypes.json
@@ -0,0 +1,167 @@
+[
+ {
+ "classes": [
+ {
+ "classInfos": [
+ {
+ "name": "QML.Element",
+ "value": "int"
+ },
+ {
+ "name": "QML.Extended",
+ "value": "QQmlIntForeign"
+ },
+ {
+ "name": "QML.Foreign",
+ "value": "int"
+ }
+ ],
+ "className": "QQmlIntForeign",
+ "gadget": true,
+ "qualifiedClassName": "QQmlIntForeign"
+ },
+ {
+ "classInfos": [
+ {
+ "name": "QML.Element",
+ "value": "auto"
+ }
+ ],
+ "className": "ExcessiveVersion",
+ "object": true,
+ "properties": [
+ {
+ "constant": false,
+ "designable": true,
+ "final": false,
+ "index": 0,
+ "name": "palette",
+ "notify": "paletteChanged",
+ "read": "palette",
+ "required": false,
+ "revision": 1536,
+ "scriptable": true,
+ "stored": true,
+ "type": "int",
+ "user": false,
+ "write": "setPalette"
+ }
+ ],
+ "enums": [
+ {
+ "isClass": false,
+ "isFlag": false,
+ "name": "RestorationMode",
+ "type": "NotAnUnderlyingType",
+ "values": [
+ "RestoreNone",
+ "RestoreBinding",
+ "RestoreValue",
+ "RestoreBindingOrValue"
+ ]
+ }
+ ],
+ "qualifiedClassName": "ExcessiveVersion",
+ "signals": [
+ {
+ "access": "public",
+ "name": "paletteChanged",
+ "returnType": "void",
+ "revision": 1536
+ }
+ ],
+ "superClasses": [
+ {
+ "access": "public",
+ "name": "NotQObject"
+ }
+ ]
+ },
+ {
+ "classInfos": [
+ {
+ "name": "QML.Element",
+ "value": "Versioned"
+ },
+ {
+ "name": "QML.AddedInVersion",
+ "value": "264"
+ }
+ ],
+ "className": "AddedInLateVersion",
+ "object": true,
+ "properties": [
+ {
+ "constant": true,
+ "designable": true,
+ "final": false,
+ "index": 0,
+ "name": "revisioned",
+ "read": "revisioned",
+ "required": false,
+ "revision": 260,
+ "scriptable": true,
+ "stored": true,
+ "type": "NotAPropertyType",
+ "user": false
+ }
+ ],
+ "methods": [
+ {
+ "access": "public",
+ "arguments": [
+ {
+ "type": "NotAnArgumentType"
+ }
+ ],
+ "name": "createAThing",
+ "returnType": "NotAReturnType"
+ }
+ ],
+ "qualifiedClassName": "AddedInLateVersion",
+ "superClasses": [
+ {
+ "access": "public",
+ "name": "NotQObject"
+ }
+ ]
+ },
+ {
+ "classInfos": [
+ {
+ "name": "QML.Foreign",
+ "value": "Invisible"
+ },
+ {
+ "name": "QML.Element",
+ "value": "Invisible"
+ }
+ ],
+ "className": "InvisibleForeign",
+ "gadget": true,
+ "qualifiedClassName": "InvisibleForeign"
+ },
+ {
+ "classInfos": [
+ {
+ "name": "QML.Element",
+ "value": "anonymous"
+ },
+ {
+ "name": "QML.Sequence",
+ "value": "NotQByteArray"
+ },
+ {
+ "name": "QML.Foreign",
+ "value": "std::vector<NotQByteArray>"
+ }
+ ],
+ "className": "NotQByteArrayStdVectorForeign",
+ "gadget": true,
+ "qualifiedClassName": "NotQByteArrayStdVectorForeign"
+ }
+ ],
+ "inputFile": "tst_qmltyperegistrar.h",
+ "outputRevision": 68
+ }
+]
diff --git a/tests/auto/qml/qmltyperegistrar/noextheader b/tests/auto/qml/qmltyperegistrar/noextheader
index 1bad168044..2b3579a34b 100644
--- a/tests/auto/qml/qmltyperegistrar/noextheader
+++ b/tests/auto/qml/qmltyperegistrar/noextheader
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef NOEXTHEADER
#define NOEXTHEADER
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
index a0f9a92b5c..e79e9b84b6 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "tst_qmltyperegistrar.h"
#include <QtTest/qtest.h>
@@ -116,8 +116,8 @@ void tst_qmltyperegistrar::pastMajorVersions()
void tst_qmltyperegistrar::implementsInterfaces()
{
- QVERIFY(qmltypesData.contains("interfaces: [\"Interface\"]"));
- QVERIFY(qmltypesData.contains("interfaces: [\"Interface\", \"Interface2\"]"));
+ QVERIFY(qmltypesData.contains("interfaces: [\"Interface1\"]"));
+ QVERIFY(qmltypesData.contains("interfaces: [\"Interface1\", \"Interface2\"]"));
}
void tst_qmltyperegistrar::namespacedElement()
@@ -145,9 +145,9 @@ void tst_qmltyperegistrar::metaTypesRegistered()
auto verifyMetaType = [](const char *name, const char *className) {
const auto foundMetaType = QMetaType::fromName(name);
- QVERIFY(foundMetaType.isValid());
+ QVERIFY2(foundMetaType.isValid(), name);
QCOMPARE(foundMetaType.name(), name);
- QVERIFY(foundMetaType.metaObject());
+ QVERIFY2(foundMetaType.metaObject(), name);
QCOMPARE(foundMetaType.metaObject()->className(), className);
};
@@ -356,6 +356,12 @@ void tst_qmltyperegistrar::addRemoveVersion()
QCOMPARE(o->property("thing").toInt(), thingAccessible ? 24 : 0);
}
+void tst_qmltyperegistrar::addInMinorVersion()
+{
+ QVERIFY(qmltypesData.contains("exports: [\"QmlTypeRegistrarTest/MinorVersioned 1.5\"]"));
+ QVERIFY(qmltypesData.contains("exports: [\"QmlTypeRegistrarTest/MinorVersioned 1.2\"]"));
+}
+
#ifdef QT_QUICK_LIB
void tst_qmltyperegistrar::foreignRevisionedProperty()
{
@@ -398,23 +404,83 @@ void tst_qmltyperegistrar::duplicateExportWarnings()
MetaTypesJsonProcessor processor(true);
QVERIFY(processor.processTypes({ ":/duplicatedExports.json" }));
processor.postProcessTypes();
- QVector<QJsonObject> types = processor.types();
- QVector<QJsonObject> typesforeign = processor.foreignTypes();
+ QVector<MetaType> types = processor.types();
+ QVector<MetaType> typesforeign = processor.foreignTypes();
r.setTypes(types, typesforeign);
- auto expectWarning = [](QString message) {
- QTest::ignoreMessage(QtWarningMsg, qPrintable(message));
+ const auto expectWarning = [](const char *message) {
+ QTest::ignoreMessage(QtWarningMsg, message);
};
- expectWarning("Warning: ExportedQmlElement was registered multiple times by following Cpp "
- "classes: ExportedQmlElement, ExportedQmlElement2 (added in 1.2), "
- "ExportedQmlElementDifferentVersion (added in 1.0) (removed in 1.7)");
- expectWarning("Warning: SameNameSameExport was registered multiple times by following Cpp "
- "classes: SameNameSameExport, SameNameSameExport2 (added in 1.2), "
- "SameNameSameExportDifferentVersion (added in 1.0)");
+ expectWarning("Warning: duplicatedExports.h:: ExportedQmlElement is registered multiple times "
+ "by the following C++ classes: ExportedQmlElement, ExportedQmlElement2 "
+ "(added in 1.2), ExportedQmlElementDifferentVersion (added in 1.0) "
+ "(removed in 1.7)");
+ expectWarning("Warning: duplicatedExports.h:: SameNameSameExport is registered multiple times "
+ "by the following C++ classes: SameNameSameExport, SameNameSameExport2 "
+ "(added in 1.2), SameNameSameExportDifferentVersion (added in 1.0)");
QString outputData;
QTextStream output(&outputData, QIODeviceBase::ReadWrite);
- r.write(output);
+ r.write(output, "tst_qmltyperegistrar_qmltyperegistrations.cpp");
+}
+
+void tst_qmltyperegistrar::consistencyWarnings()
+{
+ QmlTypeRegistrar r;
+ r.setModuleVersions(QTypeRevision::fromVersion(1, 1), {}, false);
+ QString moduleName = "tstmodule";
+ QString targetNamespace = "tstnamespace";
+ r.setModuleNameAndNamespace(moduleName, targetNamespace);
+
+ MetaTypesJsonProcessor processor(true);
+
+ QVERIFY(processor.processTypes({ ":/missingTypes.json" }));
+ processor.postProcessTypes();
+
+ const auto expectWarning = [](const char *message) {
+ QTest::ignoreMessage(QtWarningMsg, message);
+ };
+
+ expectWarning("Warning: tst_qmltyperegistrar.h:: "
+ "NotQObject is used as base type but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotQObject is used as base type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: Invisible is declared as foreign type, "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotQByteArray is used as sequence value type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotAPropertyType is used as property type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotAnArgumentType is used as argument type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotAReturnType is used as return type "
+ "but cannot be found.");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: NotAnUnderlyingType is used as enum type "
+ "but cannot be found.");
+
+ processor.postProcessForeignTypes();
+
+ QVector<MetaType> types = processor.types();
+ QVector<MetaType> typesforeign = processor.foreignTypes();
+ r.setTypes(types, typesforeign);
+
+ QString outputData;
+ QTextStream output(&outputData, QIODeviceBase::ReadWrite);
+
+ expectWarning("Warning: tst_qmltyperegistrar.h:: AddedInLateVersion is trying to register "
+ "property revisioned with future version 1.4 when module version is only 1.1");
+ expectWarning("Warning: tst_qmltyperegistrar.h:: ExcessiveVersion is trying to register "
+ "property palette with future version 6.0 when module version is only 1.1");
+
+ r.write(output, "tst_qmltyperegistrar_qmltyperegistrations.cpp");
+
+ QTemporaryFile pluginTypes;
+ QVERIFY(pluginTypes.open());
+
+ expectWarning("Warning: tst_qmltyperegistrar.h:: Refusing to generate non-lowercase name "
+ "Invisible for unknown foreign type");
+
+ r.generatePluginTypes(pluginTypes.fileName());
}
void tst_qmltyperegistrar::clonedSignal()
@@ -432,17 +498,17 @@ void tst_qmltyperegistrar::hasIsConstantInParameters()
QVERIFY(qmltypesData.contains(R"( Signal {
name: "mySignal"
Parameter { name: "myObject"; type: "QObject"; isPointer: true }
- Parameter { name: "myConstObject"; type: "QObject"; isPointer: true; isConstant: true }
- Parameter { name: "myConstObject2"; type: "QObject"; isPointer: true; isConstant: true }
+ Parameter { name: "myConstObject"; type: "QObject"; isPointer: true; isTypeConstant: true }
+ Parameter { name: "myConstObject2"; type: "QObject"; isPointer: true; isTypeConstant: true }
Parameter { name: "myObject2"; type: "QObject"; isPointer: true }
- Parameter { name: "myConstObject3"; type: "QObject"; isPointer: true; isConstant: true }
+ Parameter { name: "myConstObject3"; type: "QObject"; isPointer: true; isTypeConstant: true }
}
)"));
QVERIFY(qmltypesData.contains(R"(Signal {
name: "myVolatileSignal"
- Parameter { name: "a"; type: "volatile QObject"; isPointer: true; isConstant: true }
- Parameter { name: "b"; type: "volatile QObject"; isPointer: true; isConstant: true }
+ Parameter { name: "a"; type: "volatile QObject"; isPointer: true; isTypeConstant: true }
+ Parameter { name: "b"; type: "volatile QObject"; isPointer: true; isTypeConstant: true }
Parameter { name: "nonConst"; type: "volatile QObject"; isPointer: true }
}
)"));
@@ -450,70 +516,101 @@ void tst_qmltyperegistrar::hasIsConstantInParameters()
void tst_qmltyperegistrar::uncreatable()
{
+ using namespace QQmlPrivate;
+
// "normal" constructible types
- QVERIFY(QQmlPrivate::QmlMetaType<Creatable>::hasAcceptableCtors());
- QVERIFY(QQmlPrivate::QmlMetaType<Creatable2>::hasAcceptableCtors());
+ QVERIFY(QmlMetaType<Creatable>::hasAcceptableCtors());
+ QVERIFY(QmlMetaType<Creatable2>::hasAcceptableCtors());
// good singletons
- QVERIFY(QQmlPrivate::QmlMetaType<SingletonCreatable>::hasAcceptableSingletonCtors());
- QVERIFY(QQmlPrivate::QmlMetaType<SingletonCreatable2>::hasAcceptableSingletonCtors());
- QVERIFY(QQmlPrivate::QmlMetaType<SingletonCreatable3>::hasAcceptableSingletonCtors());
+ QCOMPARE((singletonConstructionMode<SingletonCreatable, SingletonCreatable>()),
+ SingletonConstructionMode::Factory);
+ QCOMPARE((singletonConstructionMode<SingletonCreatable2, SingletonCreatable2>()),
+ SingletonConstructionMode::Constructor);
+ QCOMPARE((singletonConstructionMode<SingletonCreatable2, SingletonCreatable2>()),
+ SingletonConstructionMode::Constructor);
+ QCOMPARE((singletonConstructionMode<SingletonForeign, SingletonLocalCreatable>()),
+ SingletonConstructionMode::FactoryWrapper);
// bad singletons
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatable>::hasAcceptableSingletonCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatable2>::hasAcceptableSingletonCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatable3>::hasAcceptableSingletonCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatable4>::hasAcceptableSingletonCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<SingletonIncreatableExtended>::hasAcceptableSingletonCtors());
+ QCOMPARE((singletonConstructionMode<SingletonIncreatable, SingletonIncreatable>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonIncreatable2, SingletonIncreatable2>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonIncreatable3, SingletonIncreatable3>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonIncreatable4, SingletonIncreatable4>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonIncreatableExtended,
+ SingletonIncreatableExtended>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonForeign, SingletonLocalUncreatable1>()),
+ SingletonConstructionMode::None);
+ QCOMPARE((singletonConstructionMode<SingletonForeign, SingletonLocalUncreatable2>()),
+ SingletonConstructionMode::None);
#if QT_DEPRECATED_SINCE(6, 4)
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatable needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatable needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatable>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatable2 needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatable2 needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatable2>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatable3 needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatable3 needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatable3>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatable4 needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatable4 needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatable4>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "Singleton SingletonIncreatableExtended needs either a default constructor or, "
- "when adding a default constructor is infeasible, a public static "
- "create(QQmlEngine *, QJSEngine *) method.");
+ "Singleton SingletonIncreatableExtended needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
qmlRegisterTypesAndRevisions<SingletonIncreatableExtended>("A", 1);
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Singleton SingletonForeign needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
+ qmlRegisterTypesAndRevisions<SingletonLocalUncreatable1>("A", 1);
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Singleton SingletonForeign needs to be a concrete class with either a "
+ "default constructor or, when adding a default constructor is infeasible, "
+ "a public static create(QQmlEngine *, QJSEngine *) method.");
+ qmlRegisterTypesAndRevisions<SingletonLocalUncreatable2>("A", 1);
#endif
// QML_UNCREATABLE types
- QVERIFY(!QQmlPrivate::QmlMetaType<BadUncreatable>::hasAcceptableCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<BadUncreatableExtended>::hasAcceptableCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<GoodUncreatable>::hasAcceptableCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<UncreatableNeedsForeign>::hasAcceptableCtors());
- QVERIFY(!QQmlPrivate::QmlMetaType<GoodUncreatableExtended>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<BadUncreatable>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<BadUncreatableExtended>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<GoodUncreatable>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<UncreatableNeedsForeign>::hasAcceptableCtors());
+ QVERIFY(!QmlMetaType<GoodUncreatableExtended>::hasAcceptableCtors());
#if QT_DEPRECATED_SINCE(6, 4)
QTest::ignoreMessage(
QtWarningMsg,
- "BadUncreatable is neither a QObject, nor default- and copy-constructible, "
- "nor uncreatable. You should not use it as a QML type.");
+ "BadUncreatable is neither a default constructible QObject, nor a default- "
+ "and copy-constructible Q_GADGET, nor marked as uncreatable.\n"
+ "You should not use it as a QML type.");
qmlRegisterTypesAndRevisions<BadUncreatable>("A", 1);
QTest::ignoreMessage(
QtWarningMsg,
- "BadUncreatableExtended is neither a QObject, nor default- and copy-constructible, "
- "nor uncreatable. You should not use it as a QML type.");
+ "BadUncreatableExtended is neither a default constructible QObject, nor a default- "
+ "and copy-constructible Q_GADGET, nor marked as uncreatable.\n"
+ "You should not use it as a QML type.");
qmlRegisterTypesAndRevisions<BadUncreatableExtended>("A", 1);
#endif
@@ -537,6 +634,26 @@ void tst_qmltyperegistrar::uncreatable()
qmlRegisterTypesAndRevisions<GoodUncreatableExtended>("A", 1);
}
+void tst_qmltyperegistrar::singletonVersions()
+{
+ QQmlEngine engine;
+ qmlRegisterTypesAndRevisions<SingletonVesion0>("A", 0);
+ qmlRegisterTypesAndRevisions<SingletonVesion1>("B", 1);
+
+ QQmlComponent c(&engine);
+ c.setData("import QtQuick\n"
+ "import A\n"
+ "import B\n"
+ "QtObject {\n"
+ " property QtObject v0: SingletonVesion0\n"
+ " property QtObject v1: SingletonVesion1\n"
+ "}", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> obj(c.create());
+ QVERIFY2(!obj->property("v0").isNull(), "Singleton version 0 is not registered");
+ QVERIFY2(!obj->property("v1").isNull(), "Singleton version 1 is not registered");
+}
+
void tst_qmltyperegistrar::baseVersionInQmltypes()
{
// Since it has no QML_ADDED_IN_VERSION, WithMethod was added in .0 of the current version.
@@ -544,4 +661,428 @@ void tst_qmltyperegistrar::baseVersionInQmltypes()
QVERIFY(qmltypesData.contains("exports: [\"QmlTypeRegistrarTest/WithMethod 1.0\"]"));
}
+void tst_qmltyperegistrar::unconstructibleValueType()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Unconstructible"
+ accessSemantics: "value"
+ exports: ["QmlTypeRegistrarTest/unconstructible 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [256]
+ })"));
+}
+
+void tst_qmltyperegistrar::constructibleValueType()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Constructible"
+ accessSemantics: "value"
+ exports: ["QmlTypeRegistrarTest/constructible 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method {
+ name: "Constructible"
+ isConstructor: true
+ Parameter { name: "i"; type: "int" }
+ }
+ Method { name: "Constructible"; isCloned: true; isConstructor: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::structuredValueType()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Structured"
+ accessSemantics: "value"
+ exports: ["QmlTypeRegistrarTest/structured 1.0"]
+ isStructured: true
+ exportMetaObjectRevisions: [256]
+ Property { name: "i"; type: "int"; index: 0; isFinal: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::anonymousAndUncreatable()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "AnonymousAndUncreatable"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ })"));
+}
+
+void tst_qmltyperegistrar::omitInvisible()
+{
+ // If it cannot resolve the type a QML_FOREIGN refers to, it should not generate anything.
+ QVERIFY(qmltypesData.contains(
+ R"(Component { file: "tst_qmltyperegistrar.h"; name: "Invisible"; accessSemantics: "none" })"));
+}
+
+void tst_qmltyperegistrar::typedEnum()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "TypedEnum"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmlTypeRegistrarTest/TypedEnum 1.0"]
+ exportMetaObjectRevisions: [256]
+ Enum {
+ name: "UChar"
+ type: "quint8"
+ values: ["V0"]
+ }
+ Enum {
+ name: "Int8_T"
+ type: "qint8"
+ values: ["V1"]
+ }
+ Enum {
+ name: "UInt8_T"
+ type: "quint8"
+ values: ["V2"]
+ }
+ Enum {
+ name: "Int16_T"
+ type: "short"
+ values: ["V3"]
+ }
+ Enum {
+ name: "UInt16_T"
+ type: "ushort"
+ values: ["V4"]
+ }
+ Enum {
+ name: "Int32_T"
+ type: "int"
+ values: ["V5"]
+ }
+ Enum {
+ name: "UInt32_T"
+ type: "uint"
+ values: ["V6"]
+ }
+ Enum {
+ name: "S"
+ type: "short"
+ values: ["A", "B", "C"]
+ }
+ Enum {
+ name: "T"
+ type: "ushort"
+ values: ["D", "E", "F"]
+ }
+ Enum {
+ name: "U"
+ type: "qint8"
+ values: ["G", "H", "I"]
+ }
+ Enum {
+ name: "V"
+ type: "quint8"
+ values: ["J", "K", "L"]
+ }
+ })"));
+}
+
+void tst_qmltyperegistrar::listSignal()
+{
+ QVERIFY(qmltypesData.contains(
+ R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "ListSignal"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Signal {
+ name: "objectListHappened"
+ Parameter { type: "QObjectList" }
+ }
+ })"));
+}
+
+void tst_qmltyperegistrar::withNamespace()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Bar"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property {
+ name: "outerBarProp"
+ type: "int"
+ read: "bar"
+ index: 0
+ isReadonly: true
+ isPropertyConstant: true
+ }
+ })"));
+
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Testing::Bar"
+ accessSemantics: "reference"
+ prototype: "Testing::Foo"
+ exports: ["QmlTypeRegistrarTest/Bar 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "barProp"
+ type: "int"
+ read: "bar"
+ index: 0
+ isReadonly: true
+ isPropertyConstant: true
+ }
+ })"));
+
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Testing::Foo"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property {
+ name: "fooProp"
+ type: "int"
+ read: "foo"
+ index: 0
+ isReadonly: true
+ isPropertyConstant: true
+ }
+ })"));
+
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "Testing::Inner::Baz"
+ accessSemantics: "reference"
+ prototype: "Testing::Bar"
+ extension: "Bar"
+ exports: ["QmlTypeRegistrarTest/Baz 1.0"]
+ exportMetaObjectRevisions: [256]
+ attachedType: "Testing::Foo"
+ })"));
+}
+
+void tst_qmltyperegistrar::sequenceRegistration()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "std::vector<QByteArray>"
+ accessSemantics: "sequence"
+ valueType: "QByteArray"
+ })"));
+}
+
+void tst_qmltyperegistrar::valueTypeSelfReference()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "QPersistentModelIndex"
+ accessSemantics: "value"
+ extension: "QPersistentModelIndexValueType"
+ })"));
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "QPersistentModelIndexValueType"
+ accessSemantics: "value"
+ Property { name: "row"; type: "int"; read: "row"; index: 0; isReadonly: true; isFinal: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::foreignNamespaceFromGadget()
+{
+ QQmlEngine engine;
+ {
+ QQmlComponent c(&engine);
+ c.setData(QStringLiteral(R"(
+ import QtQml
+ import QmlTypeRegistrarTest
+ QtObject {
+ objectName: 'b' + NetworkManager.B
+ }
+ )").toUtf8(), QUrl("foreignNamespaceFromGadget.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QCOMPARE(o->objectName(), QStringLiteral("b1"));
+ }
+
+ {
+ QQmlComponent c(&engine);
+ c.setData(QStringLiteral(R"(
+ import QtQml
+ import QmlTypeRegistrarTest
+ QtObject {
+ objectName: 'b' + NotNamespaceForeign.B
+ }
+ )").toUtf8(), QUrl("foreignNamespaceFromGadget2.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QCOMPARE(o->objectName(), QStringLiteral("b1"));
+ }
+}
+
+void tst_qmltyperegistrar::nameExplosion_data()
+{
+ QTest::addColumn<QByteArray>("qml");
+ QTest::addRow("Name1") << QByteArray("import QmlTypeRegistrarTest\nName1{}");
+ QTest::addRow("Name2") << QByteArray("import QmlTypeRegistrarTest\nName2{}");
+ QTest::addRow("NameExplosion") << QByteArray("import QmlTypeRegistrarTest\nNameExplosion{}");
+}
+
+void tst_qmltyperegistrar::nameExplosion()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "NameExplosion"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: [
+ "QmlTypeRegistrarTest/Name1 1.0",
+ "QmlTypeRegistrarTest/Name2 1.0",
+ "QmlTypeRegistrarTest/NameExplosion 1.0"
+ ]
+ exportMetaObjectRevisions: [256]
+ })"));
+
+ QFETCH(QByteArray, qml);
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine);
+
+ c.setData(qml, QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
+
+void tst_qmltyperegistrar::javaScriptExtension()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "JavaScriptExtension"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ extension: "SymbolPrototype"
+ extensionIsJavaScript: true
+ exports: ["QmlTypeRegistrarTest/JavaScriptExtension 1.0"]
+ exportMetaObjectRevisions: [256]
+ })"));
+}
+
+void tst_qmltyperegistrar::relatedAddedInVersion()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "AddedIn1_0"
+ accessSemantics: "reference"
+ prototype: "AddedIn1_5"
+ exports: [
+ "QmlTypeRegistrarTest/AddedIn1_0 1.0",
+ "QmlTypeRegistrarTest/AddedIn1_0 1.5"
+ ]
+ exportMetaObjectRevisions: [256, 261]
+ })"));
+}
+
+void tst_qmltyperegistrar::longNumberTypes()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "LongNumberTypes"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmlTypeRegistrarTest/LongNumberTypes 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property { name: "a"; type: "qlonglong"; index: 0 }
+ Property { name: "b"; type: "qlonglong"; index: 1 }
+ Property { name: "c"; type: "qulonglong"; index: 2 }
+ Property { name: "d"; type: "qulonglong"; index: 3 }
+ })"));
+}
+
+void tst_qmltyperegistrar::enumList() {
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "QList<NetworkManager::NM>"
+ accessSemantics: "sequence"
+ valueType: "NetworkManager::NM"
+ })"));
+}
+
+void tst_qmltyperegistrar::constReturnType()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "ConstInvokable"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmlTypeRegistrarTest/ConstInvokable 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method { name: "getObject"; type: "QObject"; isPointer: true; isTypeConstant: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::usingDeclaration()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "WithMyInt"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmlTypeRegistrarTest/WithMyInt 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property { name: "a"; type: "int"; read: "a"; index: 0; isReadonly: true; isPropertyConstant: true }
+ })"));
+}
+
+void tst_qmltyperegistrar::enumsRegistered()
+{
+ QCOMPARE(QMetaType::fromName("SizeEnums::Unit"), QMetaType::fromType<SizeEnums::Unit>());
+ QCOMPARE(QMetaType::fromName("Local::Flag"), QMetaType::fromType<Local::Flag>());
+ QCOMPARE(QMetaType::fromName("Local::Flags"), QMetaType::fromType<Local::Flags>());
+ QCOMPARE(QMetaType::fromName("ValueTypeWithEnum1::Quality"),
+ QMetaType::fromType<ValueTypeWithEnum1::Quality>());
+ QCOMPARE(QMetaType::fromName("ValueTypeWithEnum2::Quality"),
+ QMetaType::fromType<ValueTypeWithEnum2::Quality>());
+ QCOMPARE(QMetaType::fromName("BaseNamespace::BBB"), QMetaType::fromType<BaseNamespace::BBB>());
+ QCOMPARE(QMetaType::fromName("ExtensionValueType::EEE"),
+ QMetaType::fromType<ExtensionValueType::EEE>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::UChar"), QMetaType::fromType<TypedEnum::UChar>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::Int8_T"), QMetaType::fromType<TypedEnum::Int8_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::UInt8_T"), QMetaType::fromType<TypedEnum::UInt8_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::Int16_T"), QMetaType::fromType<TypedEnum::Int16_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::UInt16_T"), QMetaType::fromType<TypedEnum::UInt16_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::Int32_T"), QMetaType::fromType<TypedEnum::Int32_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::UInt32_T"), QMetaType::fromType<TypedEnum::UInt32_T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::S"), QMetaType::fromType<TypedEnum::S>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::T"), QMetaType::fromType<TypedEnum::T>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::U"), QMetaType::fromType<TypedEnum::U>());
+ QCOMPARE(QMetaType::fromName("TypedEnum::V"), QMetaType::fromType<TypedEnum::V>());
+ QCOMPARE(QMetaType::fromName("NetworkManager::NM"), QMetaType::fromType<NetworkManager::NM>());
+ QCOMPARE(QMetaType::fromName("NotNamespace::Abc"), QMetaType::fromType<NotNamespace::Abc>());
+}
+
+void tst_qmltyperegistrar::doNotDuplicateQtNamespace()
+{
+ QVERIFY(!qmltypesData.contains(R"(file: "qnamespace.h")"));
+}
+
+void tst_qmltyperegistrar::slotsBeforeInvokables()
+{
+ QVERIFY(qmltypesData.contains(R"(Component {
+ file: "tst_qmltyperegistrar.h"
+ name: "SlotsBeforeInvokables"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Method { name: "bar" }
+ Method { name: "foo" }
+ Method { name: "baz" }
+ })"));
+}
+
QTEST_MAIN(tst_qmltyperegistrar)
diff --git a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
index df755472d7..1eff2af024 100644
--- a/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
+++ b/tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h
@@ -1,46 +1,50 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TST_QMLTYPEREGISTRAR_H
#define TST_QMLTYPEREGISTRAR_H
#include "foreign.h"
-#include "foreign_p.h"
+#include "private/foreign_p.h"
-#include <QtQml/qqml.h>
-#include <QtQml/qqmlcomponent.h>
-#include <QtCore/qproperty.h>
-#include <QtCore/qtimeline.h>
-#include <QtCore/qrect.h>
#include <QtQmlTypeRegistrar/private/qqmltyperegistrar_p.h>
-#include <QtCore/qtemporaryfile.h>
#ifdef QT_QUICK_LIB
# include <QtQuick/qquickitem.h>
#endif
-class Interface {};
+#include <QtQml/qqml.h>
+#include <QtQml/qqmlcomponent.h>
+
+#include <QtCore/qabstractitemmodel.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore/qproperty.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qtemporaryfile.h>
+#include <QtCore/qtimeline.h>
+
+class Interface1 {};
class Interface2 {};
class Interface3 {};
QT_BEGIN_NAMESPACE
-Q_DECLARE_INTERFACE(Interface, "io.qt.bugreports.Interface");
+Q_DECLARE_INTERFACE(Interface1, "io.qt.bugreports.Interface1");
Q_DECLARE_INTERFACE(Interface2, "io.qt.bugreports.Interface2");
Q_DECLARE_INTERFACE(Interface3, "io.qt.bugreports.Interface3");
QT_END_NAMESPACE
-class ImplementsInterfaces : public QObject, public Interface
+class ImplementsInterfaces : public QObject, public Interface1
{
Q_OBJECT
QML_ELEMENT
- QML_IMPLEMENTS_INTERFACES(Interface)
+ QML_IMPLEMENTS_INTERFACES(Interface1)
};
-class ImplementsInterfaces2 : public QObject, public Interface, public Interface2
+class ImplementsInterfaces2 : public QObject, public Interface1, public Interface2
{
Q_OBJECT
QML_ELEMENT
- QML_IMPLEMENTS_INTERFACES(Interface Interface2)
+ QML_IMPLEMENTS_INTERFACES(Interface1 Interface2)
};
class ExcessiveVersion : public QObject
@@ -458,6 +462,29 @@ public:
int revisioned() const { return 24; }
};
+class AddedInLateMinorVersion : public QObject
+{
+ Q_OBJECT
+ QML_ADDED_IN_VERSION(1, 5)
+ Q_PROPERTY(int revisioned READ revisioned CONSTANT)
+ QML_NAMED_ELEMENT(MinorVersioned)
+public:
+ AddedInLateMinorVersion(QObject *parent = nullptr) : QObject(parent) {}
+ int revisioned() const { return 123; }
+};
+
+class RemovedInLateMinorVersion : public QObject
+{
+ Q_OBJECT
+ QML_ADDED_IN_VERSION(1, 2)
+ QML_REMOVED_IN_VERSION(1, 4)
+ Q_PROPERTY(int revisioned READ revisioned CONSTANT)
+ QML_NAMED_ELEMENT(MinorVersioned)
+public:
+ RemovedInLateMinorVersion(QObject *parent = nullptr) : QObject(parent) { }
+ int revisioned() const { return 456; }
+};
+
class RemovedInEarlyVersion : public AddedInLateVersion
{
Q_OBJECT
@@ -468,6 +495,23 @@ public:
RemovedInEarlyVersion(QObject *parent = nullptr) : AddedInLateVersion(parent) {}
};
+class AddedIn1_5 : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_ADDED_IN_VERSION(1, 5)
+};
+
+// Slightly absurd. The reason for such a thing may be a change in the versioning
+// scheme of the base class. We still have to retain all of the version information
+// so that you can at least use version 1.5.
+class AddedIn1_0 : public AddedIn1_5
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_ADDED_IN_VERSION(1, 0)
+};
+
class HasResettableProperty : public QObject
{
Q_OBJECT
@@ -501,6 +545,293 @@ signals:
void clonedSignal(int i = 7);
};
+class Unconstructible
+{
+ Q_GADGET
+ QML_VALUE_TYPE(unconstructible)
+ int m_i = 11;
+};
+
+class Constructible
+{
+ Q_GADGET
+ QML_VALUE_TYPE(constructible)
+ QML_CONSTRUCTIBLE_VALUE
+public:
+ Q_INVOKABLE Constructible(int i = 12) : m_i(i) {}
+
+private:
+ int m_i;
+};
+
+class Structured
+{
+ Q_GADGET
+ QML_VALUE_TYPE(structured)
+ QML_STRUCTURED_VALUE
+ Q_PROPERTY(int i MEMBER m_i FINAL)
+
+private:
+ int m_i;
+};
+
+class AnonymousAndUncreatable : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+ QML_UNCREATABLE("Pointless uncreatable message")
+};
+
+class Invisible : public QObject
+{
+};
+
+struct InvisibleForeign
+{
+ Q_GADGET
+ QML_FOREIGN(Invisible)
+ QML_NAMED_ELEMENT(Invisible)
+};
+
+class TypedEnum : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ enum UChar: uchar { V0 = 41 };
+ Q_ENUM(UChar)
+ enum Int8_T: int8_t { V1 = 42 };
+ Q_ENUM(Int8_T)
+ enum UInt8_T: uint8_t { V2 = 43 };
+ Q_ENUM(UInt8_T)
+ enum Int16_T: int16_t { V3 = 44 };
+ Q_ENUM(Int16_T)
+ enum UInt16_T: uint16_t { V4 = 45 };
+ Q_ENUM(UInt16_T)
+ enum Int32_T: int32_t { V5 = 46 };
+ Q_ENUM(Int32_T)
+ enum UInt32_T: uint32_t { V6 = 47 };
+ Q_ENUM(UInt32_T)
+
+ // TODO: We cannot handle 64bit numbers as underlying types for enums.
+ // Luckily, moc generates bad code for those. So we don't have to, for now.
+
+ enum S: qint16 {
+ A, B, C
+ };
+ Q_ENUM(S)
+
+ enum T: quint16 {
+ D, E, F
+ };
+ Q_ENUM(T)
+
+ enum U: qint8 {
+ G, H, I
+ };
+ Q_ENUM(U)
+
+ enum V: quint8 {
+ J, K, L
+ };
+ Q_ENUM(V)
+};
+
+class ListSignal : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+
+Q_SIGNALS:
+ void objectListHappened(const QList<QObject *> &);
+};
+
+class Bar : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int outerBarProp READ bar CONSTANT)
+public:
+ Bar(QObject *parent = nullptr) : QObject(parent) {}
+ int bar() const { return 44; }
+};
+
+namespace Testing {
+
+class Foo : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int fooProp READ foo CONSTANT)
+
+public:
+ int foo() const { return 42; }
+};
+
+class Bar : public Foo
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int barProp READ bar CONSTANT)
+
+public:
+ int bar() const { return 43; }
+};
+
+namespace Inner {
+
+class Baz : public Bar
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+ QML_EXTENDED(::Bar)
+ QML_ATTACHED(Foo)
+
+public:
+ static Foo *qmlAttachedProperties(QObject *) { return new Foo; }
+};
+
+} // namespace Inner
+} // namespace Testing
+
+struct QByteArrayStdVectorForeign
+{
+ Q_GADGET
+ QML_ANONYMOUS
+ QML_SEQUENTIAL_CONTAINER(QByteArray)
+ QML_FOREIGN(std::vector<QByteArray>)
+};
+
+// Anonymous value type for an unknown foreign type
+struct QPersistentModelIndexValueType
+{
+ QPersistentModelIndex v;
+ Q_PROPERTY(int row READ row FINAL)
+ Q_GADGET
+ QML_ANONYMOUS
+ QML_EXTENDED(QPersistentModelIndexValueType)
+ QML_FOREIGN(QPersistentModelIndex)
+
+public:
+ inline int row() const { return v.row(); }
+};
+
+
+namespace NetworkManager {
+Q_NAMESPACE
+
+enum NM { A, B, C};
+Q_ENUM_NS(NM)
+}
+
+struct NMForeign
+{
+ Q_GADGET
+ QML_NAMED_ELEMENT(NetworkManager)
+ QML_FOREIGN_NAMESPACE(NetworkManager)
+};
+
+struct NotNamespace {
+ Q_GADGET
+public:
+ enum Abc {
+ A, B, C, D
+ };
+ Q_ENUM(Abc);
+};
+
+struct NotNamespaceForeign {
+ Q_GADGET
+ QML_FOREIGN_NAMESPACE(NotNamespace)
+ QML_ELEMENT
+};
+
+class NameExplosion : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(Name1)
+ QML_NAMED_ELEMENT(Name2)
+ QML_ELEMENT
+ QML_ANONYMOUS
+};
+
+class JavaScriptExtension : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_CLASSINFO("QML.Extended", "SymbolPrototype")
+ Q_CLASSINFO("QML.ExtensionIsJavaScript", "true")
+};
+
+class LongNumberTypes : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(qint64 a MEMBER m_a)
+ Q_PROPERTY(int64_t b MEMBER m_b)
+ Q_PROPERTY(quint64 c MEMBER m_c)
+ Q_PROPERTY(uint64_t d MEMBER m_d)
+
+ qint64 m_a = 1;
+ int64_t m_b = 2;
+ quint64 m_c = 3;
+ uint64_t m_d = 4;
+};
+
+struct EnumList
+{
+ Q_GADGET
+ QML_ANONYMOUS
+ QML_FOREIGN(QList<NetworkManager::NM>)
+ QML_SEQUENTIAL_CONTAINER(NetworkManager::NM)
+};
+
+class ConstInvokable : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ Q_INVOKABLE const QObject *getObject() { return nullptr; }
+};
+
+using myint = int;
+
+struct IntAlias
+{
+ Q_GADGET
+ QML_FOREIGN(myint)
+ QML_USING(int);
+};
+
+class WithMyInt : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(myint a READ a CONSTANT)
+public:
+ myint a() const { return 10; }
+};
+
+class UsesQtNamespace : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+ Q_PROPERTY(Qt::Key key READ key CONSTANT)
+public:
+ Qt::Key key() const { return Qt::Key_Escape; }
+};
+
+class SlotsBeforeInvokables : public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+public:
+ Q_INVOKABLE void foo() {}
+public Q_SLOTS:
+ void bar() {}
+public:
+ Q_INVOKABLE void baz() {}
+};
+
class tst_qmltyperegistrar : public QObject
{
Q_OBJECT
@@ -537,6 +868,7 @@ private slots:
void methodReturnType();
void hasIsConstantInParameters();
void uncreatable();
+ void singletonVersions();
#ifdef QT_QUICK_LIB
void foreignRevisionedProperty();
@@ -544,11 +876,39 @@ private slots:
void addRemoveVersion_data();
void addRemoveVersion();
+ void addInMinorVersion();
void typeInModuleMajorVersionZero();
void resettableProperty();
void duplicateExportWarnings();
void clonedSignal();
void baseVersionInQmltypes();
+ void unconstructibleValueType();
+ void constructibleValueType();
+ void structuredValueType();
+ void anonymousAndUncreatable();
+ void omitInvisible();
+ void typedEnum();
+ void listSignal();
+ void withNamespace();
+ void sequenceRegistration();
+ void valueTypeSelfReference();
+ void foreignNamespaceFromGadget();
+
+ void nameExplosion_data();
+ void nameExplosion();
+
+ void javaScriptExtension();
+
+ void consistencyWarnings();
+ void relatedAddedInVersion();
+ void longNumberTypes();
+ void enumList();
+ void constReturnType();
+
+ void usingDeclaration();
+ void enumsRegistered();
+ void doNotDuplicateQtNamespace();
+ void slotsBeforeInvokables();
private:
QByteArray qmltypesData;
diff --git a/tests/auto/qml/qqmlanybinding/CMakeLists.txt b/tests/auto/qml/qqmlanybinding/CMakeLists.txt
index 8cdecae3a8..f80acd8187 100644
--- a/tests/auto/qml/qqmlanybinding/CMakeLists.txt
+++ b/tests/auto/qml/qqmlanybinding/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qqmlanybinding Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlanybinding LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp b/tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp
index 9e2ba24969..7e0a1c659a 100644
--- a/tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp
+++ b/tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtCore/QScopedPointer>
@@ -39,7 +39,7 @@ static int getRefCount(const QQmlAnyBinding &binding)
} else {
// this temporarily adds a refcount because we construc a new untypedpropertybinding
// thus -1
- return QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding())->ref - 1;
+ return QPropertyBindingPrivate::get(binding.asUntypedPropertyBinding())->refCount() - 1;
}
}
diff --git a/tests/auto/qml/qqmlanybinding/withbindable.h b/tests/auto/qml/qqmlanybinding/withbindable.h
index 0672532344..322459f991 100644
--- a/tests/auto/qml/qqmlanybinding/withbindable.h
+++ b/tests/auto/qml/qqmlanybinding/withbindable.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef WITH_BINDABLE_H
#define WITH_BINDABLE_H
diff --git a/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt b/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt
index 0570b9a95c..3b02ed09ef 100644
--- a/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt
+++ b/tests/auto/qml/qqmlapplicationengine/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlapplicationengine Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlapplicationengine LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -57,5 +63,12 @@ qt_internal_extend_target(tst_qqmlapplicationengine CONDITION NOT ANDROID AND NO
DEFINES
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
+
add_subdirectory(testapp)
add_subdirectory(androidassets)
+add_dependencies(tst_qqmlapplicationengine testapp)
+
+add_subdirectory(loadFromModuleTranslationsQmlType)
+add_subdirectory(loadFromModuleTranslationsCppType)
+add_dependencies(tst_qqmlapplicationengine i18nLoadFromModuleQmlType)
+add_dependencies(tst_qqmlapplicationengine i18nLoadFromModuleCppType)
diff --git a/tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt b/tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt
index c5d42ed9c4..eca18010ee 100644
--- a/tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt
+++ b/tests/auto/qml/qqmlapplicationengine/androidassets/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_androidassets LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_androidassets
SOURCES
tst_androidassets.cpp
diff --git a/tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp b/tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp
index 7a6774c268..ed55afc693 100644
--- a/tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/androidassets/tst_androidassets.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlapplicationengine.h>
#include <QtTest/qsignalspy.h>
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/CMakeLists.txt b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/CMakeLists.txt
new file mode 100644
index 0000000000..f6fa23e010
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_standard_project_setup(REQUIRES 6.5 I18N_LANGUAGES es)
+
+qt_internal_add_executable(i18nLoadFromModuleCppType
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
+ SOURCES
+ main.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::Qml
+)
+
+qt_add_qml_module(i18nLoadFromModuleCppType
+ URI TranslatedCpp
+ QML_FILES Main.qml
+)
+
+qt_internal_extend_target(i18nLoadFromModuleCppType
+ ENABLE_AUTOGEN_TOOLS
+ uic
+)
+
+qt_add_resources(i18nLoadFromModuleCppType "loadFromModuleCppTypeQmFile"
+ PREFIX
+ /qt/qml/TranslatedCpp/
+ FILES
+ i18n/qml_es.qm
+)
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/Main.qml b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/Main.qml
new file mode 100644
index 0000000000..f1d2010837
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/Main.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ Component.onCompleted: Qt.exit(0)
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.qm b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.qm
new file mode 100644
index 0000000000..e35ee63f89
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.qm
Binary files differ
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.ts b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.ts
new file mode 100644
index 0000000000..f8d478f056
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/i18n/qml_es.ts
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="es_ES">
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="../main.cpp" line="17"/>
+ <source>Hello</source>
+ <translation>Hola</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/main.cpp b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/main.cpp
new file mode 100644
index 0000000000..326a1397dc
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsCppType/main.cpp
@@ -0,0 +1,26 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+ QLocale::setDefault(QLocale(QLocale::Language(qEnvironmentVariableIntValue("qtlang"))));
+ QGuiApplication app(argc, argv);
+ QQmlApplicationEngine engine;
+
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
+ &app, []() { QCoreApplication::exit(-1); },
+ Qt::QueuedConnection);
+ engine.loadFromModule("TranslatedCpp", "Main");
+ app.exec();
+
+ QString expected = qgetenv("LOADFROMMODULE_TEST_EXPECTED_OUTPUT");
+ QString actual = QObject::tr("Hello");
+
+ if (actual == expected)
+ return 0;
+
+ return actual[0].toLatin1();
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/CMakeLists.txt b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/CMakeLists.txt
new file mode 100644
index 0000000000..088648040d
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_standard_project_setup(REQUIRES 6.5 I18N_LANGUAGES fr)
+
+qt_internal_add_executable(i18nLoadFromModuleQmlType
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/"
+ SOURCES
+ main.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::Qml
+)
+
+qt_add_qml_module(i18nLoadFromModuleQmlType
+ URI TranslatedQml
+ QML_FILES Main.qml
+)
+
+qt_internal_extend_target(i18nLoadFromModuleQmlType
+ ENABLE_AUTOGEN_TOOLS
+ uic
+)
+
+qt_add_resources(i18nLoadFromModuleQmlType "loadFromModuleQmlTypeQmFile"
+ PREFIX
+ /qt/qml/TranslatedQml/
+ FILES
+ i18n/qml_fr.qm
+)
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/Main.qml b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/Main.qml
new file mode 100644
index 0000000000..9f8e1984e9
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/Main.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ property string expected: "placeholder"
+ property string actual: qsTr("Hello")
+
+ function f() {
+ if (expected === actual)
+ Qt.exit(0)
+ else
+ Qt.exit(actual.charCodeAt(0))
+ }
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.qm b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.qm
new file mode 100644
index 0000000000..a53cf121a2
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.qm
Binary files differ
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.ts b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.ts
new file mode 100644
index 0000000000..87b46be9ca
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/i18n/qml_fr.ts
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+ <name>Main</name>
+ <message>
+ <location filename="../Main.qml" line="5"/>
+ <source>Hello</source>
+ <translation>Salut</translation>
+ </message>
+</context>
+</TS>
diff --git a/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/main.cpp b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/main.cpp
new file mode 100644
index 0000000000..6f28ec8148
--- /dev/null
+++ b/tests/auto/qml/qqmlapplicationengine/loadFromModuleTranslationsQmlType/main.cpp
@@ -0,0 +1,23 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+
+int main(int argc, char *argv[])
+{
+ QLocale::setDefault(QLocale(QLocale::Language(qEnvironmentVariableIntValue("qtlang"))));
+ QGuiApplication app(argc, argv);
+ QQmlApplicationEngine engine;
+
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
+ &app, []() { QCoreApplication::exit(-1); },
+ Qt::QueuedConnection);
+ engine.loadFromModule("TranslatedQml", "Main");
+
+ QString expected = qgetenv("LOADFROMMODULE_TEST_EXPECTED_OUTPUT");
+ auto *root = engine.rootObjects().first();
+ root->setProperty("expected", expected);
+ root->metaObject()->invokeMethod(root, "f");
+ return app.exec();
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp b/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp
index 468c8428ba..6ccd256cca 100644
--- a/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QCoreApplication>
#include <QQmlApplicationEngine>
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
index 5774b68c32..3bf83d81e1 100644
--- a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
+++ b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlApplicationEngine>
#include <QScopedPointer>
@@ -28,6 +28,8 @@ private slots:
void removeObjectsWhenDestroyed();
void loadTranslation_data();
void loadTranslation();
+ void loadFromModuleTranslation_data();
+ void loadFromModuleTranslation();
void translationChange();
void setInitialProperties();
void failureToLoadTriggersWarningSignal();
@@ -144,7 +146,7 @@ void tst_qqmlapplicationengine::application()
#if QT_CONFIG(process)
QDir::setCurrent(buildDir);
- QProcess *testProcess = new QProcess(this);
+ std::unique_ptr<QProcess> testProcess = std::make_unique<QProcess>(this);
#ifdef Q_OS_QNX
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("QT_FORCE_STDERR_LOGGING", "1"); // QTBUG-76546
@@ -164,7 +166,7 @@ void tst_qqmlapplicationengine::application()
QVERIFY2(QString(testStdErr).endsWith(QString(expectedStdErr)),
QByteArray("\nExpected ending:\n") + expectedStdErr
+ QByteArray("\nActual output:\n") + testStdErr);
- delete testProcess;
+ testProcess.reset();
QDir::setCurrent(srcDir);
#else // process
QSKIP("No process support");
@@ -191,7 +193,7 @@ void tst_qqmlapplicationengine::applicationProperties()
QCoreApplication::setOrganizationName(firstOrganization);
QCoreApplication::setOrganizationDomain(firstDomain);
- QQmlApplicationEngine *test = new QQmlApplicationEngine(testFileUrl("applicationTest.qml"));
+ std::unique_ptr<QQmlApplicationEngine> test = std::make_unique<QQmlApplicationEngine>(testFileUrl("applicationTest.qml"));
QObject* root = test->rootObjects().at(0);
QVERIFY(root);
QCOMPARE(root->property("originalName").toString(), firstName);
@@ -223,8 +225,6 @@ void tst_qqmlapplicationengine::applicationProperties()
QCOMPARE(versionChanged.size(), 1);
QCOMPARE(organizationChanged.size(), 1);
QCOMPARE(domainChanged.size(), 1);
-
- delete test;
}
void tst_qqmlapplicationengine::removeObjectsWhenDestroyed()
@@ -268,6 +268,53 @@ void tst_qqmlapplicationengine::loadTranslation()
QCOMPARE(rootObject->property("translation").toString(), translation);
}
+void tst_qqmlapplicationengine::loadFromModuleTranslation_data()
+{
+ QTest::addColumn<QString>("executable");
+ QTest::addColumn<QLocale::Language>("LANG");
+ QTest::addColumn<QString>("output");
+
+ QString qmlTypeExecutable = "loadFromModuleTranslationsQmlType/i18nLoadFromModuleQmlType";
+ QString cppTypeExecutable = "loadFromModuleTranslationsCppType/i18nLoadFromModuleCppType";
+
+ QTest::newRow("Qml: en -> en") << qmlTypeExecutable << QLocale::English << "Hello";
+ QTest::newRow("Qml: en -> fr") << qmlTypeExecutable << QLocale::French << "Salut";
+ QTest::newRow("Cpp: en -> en") << cppTypeExecutable << QLocale::English << "Hello";
+ QTest::newRow("Cpp: en -> es") << cppTypeExecutable << QLocale::Spanish << "Hola";
+}
+
+void tst_qqmlapplicationengine::loadFromModuleTranslation()
+{
+#if defined(Q_OS_ANDROID)
+ QSKIP("Test doesn't currently run on Android");
+ return;
+#endif
+
+#if QT_CONFIG(process)
+ QFETCH(QString, executable);
+ QFETCH(QLocale::Language, LANG);
+ QFETCH(QString, output);
+
+ QDir::setCurrent(buildDir);
+ QProcess app;
+ auto env = QProcessEnvironment::systemEnvironment();
+ env.insert("qtlang", QString::number(int(LANG)));
+ env.insert("LOADFROMMODULE_TEST_EXPECTED_OUTPUT", output);
+ app.setProcessEnvironment(env);
+ app.start(executable);
+ QVERIFY(app.waitForStarted());
+ QVERIFY(app.waitForFinished());
+
+ auto status = app.exitStatus();
+ auto code = app.exitCode();
+ QVERIFY2(code == 0,
+ QStringLiteral("status: %1, exitCode: %2").arg(status).arg(code).toStdString().c_str());
+ app.kill();
+#else
+ QSKIP("No process support");
+#endif
+}
+
void tst_qqmlapplicationengine::translationChange()
{
if (QLocale().language() == QLocale::SwissGerman) {
diff --git a/tests/auto/qml/qqmlbinding/CMakeLists.txt b/tests/auto/qml/qqmlbinding/CMakeLists.txt
index bcddd51730..0249bb0f25 100644
--- a/tests/auto/qml/qqmlbinding/CMakeLists.txt
+++ b/tests/auto/qml/qqmlbinding/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlbinding Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlbinding LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -22,9 +28,27 @@ qt_internal_add_test(tst_qqmlbinding
Qt::Gui
Qt::GuiPrivate
Qt::QmlPrivate
+ Qt::QmlMetaPrivate
+ Qt::QuickPrivate
+ Qt::QuickTestUtilsPrivate
+ TESTDATA ${test_data}
+)
+
+qt_internal_add_test(tst_qqmlbinding_no_deferred_properties
+ SOURCES
+ tst_qqmlbinding.cpp
+ WithBindableProperties.h
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::QmlPrivate
+ Qt::QmlMetaPrivate
Qt::QuickPrivate
Qt::QuickTestUtilsPrivate
TESTDATA ${test_data}
+ DEFINES
+ QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES
)
set_target_properties(tst_qqmlbinding PROPERTIES
@@ -34,9 +58,13 @@ set_target_properties(tst_qqmlbinding PROPERTIES
_qt_internal_qml_type_registration(tst_qqmlbinding)
+set_target_properties(tst_qqmlbinding_no_deferred_properties PROPERTIES
+ QT_QML_MODULE_URI "test"
+ QT_QML_MODULE_VERSION 1.0
+)
+
+_qt_internal_qml_type_registration(tst_qqmlbinding_no_deferred_properties)
-## Scopes:
-#####################################################################
qt_internal_extend_target(tst_qqmlbinding CONDITION ANDROID OR IOS
DEFINES
@@ -47,3 +75,13 @@ qt_internal_extend_target(tst_qqmlbinding CONDITION NOT ANDROID AND NOT IOS
DEFINES
QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
+
+qt_internal_extend_target(tst_qqmlbinding_no_deferred_properties CONDITION ANDROID OR IOS
+ DEFINES
+ QT_QMLTEST_DATADIR=":/data"
+)
+
+qt_internal_extend_target(tst_qqmlbinding_no_deferred_properties CONDITION NOT ANDROID AND NOT IOS
+ DEFINES
+ QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+)
diff --git a/tests/auto/qml/qqmlbinding/WithBindableProperties.h b/tests/auto/qml/qqmlbinding/WithBindableProperties.h
index 17fa3cd9b3..8837098d81 100644
--- a/tests/auto/qml/qqmlbinding/WithBindableProperties.h
+++ b/tests/auto/qml/qqmlbinding/WithBindableProperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef WithBindableProperties_H
#define WithBindableProperties_H
diff --git a/tests/auto/qml/qqmlbinding/data/bindingOverwriting2.qml b/tests/auto/qml/qqmlbinding/data/bindingOverwriting2.qml
new file mode 100644
index 0000000000..8d15185506
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/bindingOverwriting2.qml
@@ -0,0 +1,21 @@
+pragma ComponentBehavior: Bound
+import QtQuick
+
+ListView {
+ id: list
+ property int i: 0
+
+ model: 1
+ delegate: Item {
+ id: cellRootID
+ required property int index
+ Timer {
+ interval: 1
+ running: true
+ onTriggered: {
+ cellRootID.index = index + 123
+ list.i = cellRootID.index
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/propertiesAttachedToBindingItself.qml b/tests/auto/qml/qqmlbinding/data/propertiesAttachedToBindingItself.qml
new file mode 100644
index 0000000000..98b3aa6606
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/propertiesAttachedToBindingItself.qml
@@ -0,0 +1,18 @@
+import QtQml.Models
+import QtQuick
+
+Instantiator {
+ id: inst
+ model: 1
+ property int check: 0
+
+ delegate: Binding {
+ ListView.delayRemove: true
+ Component.onCompleted: inst.check += 1
+ }
+
+ Component.onCompleted: {
+ if (inst.objectAt(0))
+ inst.check += 2
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml
index 8d89989613..40d4806b8c 100644
--- a/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml
+++ b/tests/auto/qml/qqmlbinding/data/restoreBinding2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQml 2.14
diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml
index 9fd5fc77d0..5742a849b9 100644
--- a/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml
+++ b/tests/auto/qml/qqmlbinding/data/restoreBinding3.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQml 2.14
diff --git a/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml b/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml
index ee183a0d10..e9d90b5e8b 100644
--- a/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml
+++ b/tests/auto/qml/qqmlbinding/data/restoreBinding4.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import QtQml 2.14
diff --git a/tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml b/tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml
new file mode 100644
index 0000000000..251e71f771
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/toggleEnableProperlyRemembersValues.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ id: root
+ property bool enabled: false
+ property var func: function() { return 1 }
+ property var arr: [1, 2]
+ property Binding b: Binding {
+ root.func: function() { return 2 };
+ root.arr: [1, 2, 3]
+ when: root.enabled
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml b/tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml
new file mode 100644
index 0000000000..6245270e14
--- /dev/null
+++ b/tests/auto/qml/qqmlbinding/data/whenEvaluatedEarlyEnough.qml
@@ -0,0 +1,23 @@
+import QtQuick
+
+Item {
+ id: root
+ property bool toggle: true
+ property bool forceEnable: false
+
+ Item {
+ id: item1
+ property int i
+ }
+
+ Item {
+ id: item2
+ }
+
+ Binding {
+ target: root.toggle ? item1 : item2
+ when: root.forceEnable || (root.toggle ? item1 : item2).hasOwnProperty("i")
+ property: "i"
+ value: 42
+ }
+}
diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
index c78763cf5f..b13379a103 100644
--- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
+++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp
@@ -1,13 +1,17 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <qtest.h>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "WithBindableProperties.h"
+
+#include <private/qmlutils_p.h>
+#include <private/qqmlbind_p.h>
+#include <private/qqmlcomponentattached_p.h>
+#include <private/qquickrectangle_p.h>
+
+#include <QtTest/qtest.h>
+
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
-#include <QtQml/private/qqmlbind_p.h>
-#include <QtQml/private/qqmlcomponentattached_p.h>
-#include <QtQuick/private/qquickrectangle_p.h>
-#include <QtQuickTestUtils/private/qmlutils_p.h>
-#include "WithBindableProperties.h"
class tst_qqmlbinding : public QQmlDataTest
{
@@ -38,6 +42,9 @@ private slots:
void intOverflow();
void generalizedGroupedProperties();
void localSignalHandler();
+ void whenEvaluatedEarlyEnough();
+ void propertiesAttachedToBindingItself();
+ void toggleEnableProperlyRemembersValues();
private:
QQmlEngine engine;
@@ -46,6 +53,9 @@ private:
tst_qqmlbinding::tst_qqmlbinding()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
+#ifdef QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES
+ qputenv("QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES", "1");
+#endif
}
void tst_qqmlbinding::binding()
@@ -365,10 +375,6 @@ void tst_qqmlbinding::disabledOnReadonlyProperty()
void tst_qqmlbinding::delayed()
{
-#ifdef Q_OS_ANDROID
- QSKIP("This test crashes on Android. QTBUG-103310");
-#endif
-
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("delayed.qml"));
QScopedPointer<QQuickItem> item {qobject_cast<QQuickItem*>(c.create())};
@@ -455,9 +461,15 @@ void tst_qqmlbinding::bindingOverwriting()
QQmlComponent c(&engine, testFileUrl("bindingOverwriting.qml"));
QScopedPointer<QQuickItem> item {qobject_cast<QQuickItem*>(c.create())};
QVERIFY(item);
+ QCOMPARE(messageHandler.messages().size(), 2);
+
+ QQmlComponent c2(&engine, testFileUrl("bindingOverwriting2.qml"));
+ QScopedPointer<QObject> o(c2.create());
+ QVERIFY(o);
+ QTRY_COMPARE(o->property("i").toInt(), 123);
+ QCOMPARE(messageHandler.messages().size(), 3);
QLoggingCategory::setFilterRules(QString());
- QCOMPARE(messageHandler.messages().size(), 2);
}
void tst_qqmlbinding::bindToQmlComponent()
@@ -593,6 +605,55 @@ void tst_qqmlbinding::localSignalHandler()
QCOMPARE(o->property("output").toString(), QStringLiteral("abc"));
}
+void tst_qqmlbinding::whenEvaluatedEarlyEnough()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("whenEvaluatedEarlyEnough.qml"));
+ QTest::failOnWarning(QRegularExpression(".*"));
+ std::unique_ptr<QObject> root { c.create() };
+ root->setProperty("toggle", false); // should not cause warnings
+ // until "when" is actually true
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg,
+ QRegularExpression(".*QML Binding: Property 'i' does not exist on Item.*"));
+ root->setProperty("forceEnable", true);
+}
+
+void tst_qqmlbinding::propertiesAttachedToBindingItself()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("propertiesAttachedToBindingItself.qml"));
+ QTest::failOnWarning(QRegularExpression(".*"));
+ std::unique_ptr<QObject> root { c.create() };
+ QVERIFY2(root, qPrintable(c.errorString()));
+ // 0 => everything broken; 1 => normal attached properties broken;
+ // 2 => Component.onCompleted broken, 3 => everything works
+ QTRY_COMPARE(root->property("check").toInt(), 3);
+}
+
+void tst_qqmlbinding::toggleEnableProperlyRemembersValues()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("toggleEnableProperlyRemembersValues.qml"));
+ std::unique_ptr<QObject> root { c.create() };
+ QVERIFY2(root, qPrintable(c.errorString()));
+ for (int i = 0; i < 3; ++i) {
+ {
+ QJSManagedValue arr(root->property("arr"), &e);
+ QJSManagedValue func(root->property("func"), &e);
+ QCOMPARE(arr.property("length").toInt(), 2);
+ QCOMPARE(func.call().toInt(), 1);
+ }
+ root->setProperty("enabled", true);
+ {
+ QJSManagedValue arr(root->property("arr"), &e);
+ QJSManagedValue func(root->property("func"), &e);
+ QCOMPARE(arr.property("length").toInt(), 3);
+ QCOMPARE(func.call().toInt(), 2);
+ }
+ root->setProperty("enabled", false);
+ }
+}
+
QTEST_MAIN(tst_qqmlbinding)
#include "tst_qqmlbinding.moc"
diff --git a/tests/auto/qml/qqmlchangeset/CMakeLists.txt b/tests/auto/qml/qqmlchangeset/CMakeLists.txt
index c4038b0eaf..32a20d7edf 100644
--- a/tests/auto/qml/qqmlchangeset/CMakeLists.txt
+++ b/tests/auto/qml/qqmlchangeset/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlchangeset Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlchangeset LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlchangeset
SOURCES
tst_qqmlchangeset.cpp
diff --git a/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp b/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp
index 1aec5dcac3..8712d4953d 100644
--- a/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp
+++ b/tests/auto/qml/qqmlchangeset/tst_qqmlchangeset.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <qrandom.h>
#include <private/qqmlchangeset_p.h>
@@ -94,7 +95,7 @@ public:
bool applyChanges(QVector<int> &list, const QVector<QVector<Signal> > &changes)
{
- foreach (const SignalList &sl, changes) {
+ for (const SignalList &sl : changes) {
if (!applyChanges(list, sl))
return false;
}
@@ -104,7 +105,7 @@ public:
bool applyChanges(QVector<int> &list, const QVector<Signal> &changes)
{
QHash<QQmlChangeSet::MoveKey, int> removedValues;
- foreach (const Signal &signal, changes) {
+ for (const Signal &signal : changes) {
if (signal.isInsert()) {
if (signal.index < 0 || signal.index > list.size()) {
qDebug() << "insert out of range" << signal.index << list.size();
@@ -1133,7 +1134,7 @@ void tst_qqmlchangeset::sequence()
QQmlChangeSet set;
- foreach (const Signal &signal, input) {
+ for (const Signal &signal : std::as_const(input)) {
if (signal.isRemove())
set.remove(signal.index, signal.count);
else if (signal.isInsert())
@@ -1145,11 +1146,11 @@ void tst_qqmlchangeset::sequence()
}
SignalList changes;
- foreach (const QQmlChangeSet::Change &remove, set.removes())
+ for (const QQmlChangeSet::Change &remove : set.removes())
changes << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Change &insert, set.inserts())
+ for (const QQmlChangeSet::Change &insert : set.inserts())
changes << Insert(insert.index, insert.count, insert.moveId, insert.offset);
- foreach (const QQmlChangeSet::Change &change, set.changes())
+ for (const QQmlChangeSet::Change &change : set.changes())
changes << Change(change.index, change.count);
VERIFY_EXPECTED_OUTPUT
@@ -1267,9 +1268,9 @@ void tst_qqmlchangeset::apply()
QQmlChangeSet set;
QQmlChangeSet linearSet;
- foreach (const SignalList &list, input) {
+ for (const SignalList &list : std::as_const(input)) {
QQmlChangeSet intermediateSet;
- foreach (const Signal &signal, list) {
+ for (const Signal &signal : list) {
if (signal.isRemove()) {
intermediateSet.remove(signal.index, signal.count);
linearSet.remove(signal.index, signal.count);
@@ -1285,15 +1286,15 @@ void tst_qqmlchangeset::apply()
}
SignalList changes;
- foreach (const QQmlChangeSet::Change &remove, set.removes())
+ for (const QQmlChangeSet::Change &remove : set.removes())
changes << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Change &insert, set.inserts())
+ for (const QQmlChangeSet::Change &insert : set.inserts())
changes << Insert(insert.index, insert.count, insert.moveId, insert.offset);
SignalList linearChanges;
- foreach (const QQmlChangeSet::Change &remove, linearSet.removes())
+ for (const QQmlChangeSet::Change &remove : linearSet.removes())
linearChanges << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Change &insert, linearSet.inserts())
+ for (const QQmlChangeSet::Change &insert : linearSet.inserts())
linearChanges << Insert(insert.index, insert.count, insert.moveId, insert.offset);
// The output in the failing tests isn't incorrect, merely sub-optimal.
@@ -1328,7 +1329,7 @@ void tst_qqmlchangeset::removeConsecutive()
QFETCH(SignalList, output);
QVector<QQmlChangeSet::Change> removes;
- foreach (const Signal &signal, input) {
+ for (const Signal &signal : std::as_const(input)) {
QVERIFY(signal.isRemove());
removes.append(QQmlChangeSet::Change(signal.index, signal.count, signal.moveId, signal.offset));
}
@@ -1337,7 +1338,7 @@ void tst_qqmlchangeset::removeConsecutive()
set.remove(removes);
SignalList changes;
- foreach (const QQmlChangeSet::Change &remove, set.removes())
+ for (const QQmlChangeSet::Change &remove : set.removes())
changes << Remove(remove.index, remove.count, remove.moveId, remove.offset);
QVERIFY(set.inserts().isEmpty());
QVERIFY(set.changes().isEmpty());
@@ -1368,7 +1369,7 @@ void tst_qqmlchangeset::insertConsecutive()
QFETCH(SignalList, output);
QVector<QQmlChangeSet::Change> inserts;
- foreach (const Signal &signal, input) {
+ for (const Signal &signal : std::as_const(input)) {
QVERIFY(signal.isInsert());
inserts.append(QQmlChangeSet::Change(signal.index, signal.count, signal.moveId, signal.offset));
}
@@ -1377,7 +1378,7 @@ void tst_qqmlchangeset::insertConsecutive()
set.insert(inserts);
SignalList changes;
- foreach (const QQmlChangeSet::Change &insert, set.inserts())
+ for (const QQmlChangeSet::Change &insert : set.inserts())
changes << Insert(insert.index, insert.count, insert.moveId, insert.offset);
QVERIFY(set.removes().isEmpty());
QVERIFY(set.changes().isEmpty());
@@ -1496,9 +1497,9 @@ void tst_qqmlchangeset::random()
}
SignalList output;
- foreach (const QQmlChangeSet::Change &remove, accumulatedSet.removes())
+ for (const QQmlChangeSet::Change &remove : accumulatedSet.removes())
output << Remove(remove.index, remove.count, remove.moveId, remove.offset);
- foreach (const QQmlChangeSet::Change &insert, accumulatedSet.inserts())
+ for (const QQmlChangeSet::Change &insert : accumulatedSet.inserts())
output << Insert(insert.index, insert.count, insert.moveId, insert.offset);
QVector<int> inputList;
diff --git a/tests/auto/qml/qqmlcomponent/CMakeLists.txt b/tests/auto/qml/qqmlcomponent/CMakeLists.txt
index cab87ac08d..874c7f0cc3 100644
--- a/tests/auto/qml/qqmlcomponent/CMakeLists.txt
+++ b/tests/auto/qml/qqmlcomponent/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlcomponent Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlcomponent LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -36,10 +42,13 @@ if(TARGET Qt::QuickControls2)
target_compile_definitions(tst_qqmlcomponent PRIVATE HAS_CONTROLS)
endif()
+qt_policy(SET QTP0001 NEW)
+
qt_add_qml_module(
tst_qqmlcomponent
+ SOURCES
+ lifecyclewatcher.h
URI test
- AUTO_RESOURCE_PREFIX
QML_FILES
"data/TestComponentWithIC.qml"
"data/withAot.qml"
diff --git a/tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml b/tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml
new file mode 100644
index 0000000000..71676a4415
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/complexObjectArgument.qml
@@ -0,0 +1,28 @@
+import QtQml 2.15
+
+QtObject {
+ id: root
+ Component.onCompleted: {
+ function WithPrototype(refMsgSeqNr) {
+ this.init(refMsgSeqNr)
+ };
+
+ WithPrototype.prototype = {
+ init: function(refMsgSeqNr) {
+ this.testObj = {
+ has: function(a) { return a === refMsgSeqNr }
+ }
+
+ this.protocolSubTypeID = 2
+ this.messageControl = 0
+ this.referredMsgSequenceNumber = refMsgSeqNr
+ }
+ };
+
+ let comp = Qt.createComponent("dynamic.qml");
+ let inst1 = comp.createObject(root, { testObj: new Set(), });
+ let inst2 = comp.createObject(root, new WithPrototype(1));
+
+ objectName = inst1.use() + " - " + inst2.use();
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/createObject.qml b/tests/auto/qml/qqmlcomponent/data/createObject.qml
index afd9e71229..c9ca605f8f 100644
--- a/tests/auto/qml/qqmlcomponent/data/createObject.qml
+++ b/tests/auto/qml/qqmlcomponent/data/createObject.qml
@@ -1,5 +1,4 @@
-import QtQuick 2.0
-import QtQuick.Window 2.0
+import QtQuick
Item {
property QtObject qtobjectParent: QtObject { }
diff --git a/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml b/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml
index 3391b3a266..63aeb9415e 100644
--- a/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml
+++ b/tests/auto/qml/qqmlcomponent/data/createObjectWithScript.qml
@@ -11,6 +11,9 @@ Item{
property QtObject badRequired: null
property QtObject goodRequired: null
+ property QtObject bindingAsInitial: null
+ property bool bindingUsed: false
+
Component{
id: a
Rectangle {
@@ -21,7 +24,7 @@ Item{
id: b
Item{
property bool testBool: false
- property int testInt: null
+ property int testInt: { return null; }
property QtObject testObject: null
}
}
@@ -43,6 +46,11 @@ Item{
}
}
+ Component {
+ id: e
+ Rectangle {}
+ }
+
Component.onCompleted: {
root.declarativerectangle = a.createObject(root, {"x":17,"y":17, "color":"white", "border.width":3, "innerRect.border.width": 20});
root.declarativeitem = b.createObject(root, {"x":17,"y":17,"testBool":true,"testInt":17,"testObject":root});
@@ -52,5 +60,9 @@ Item{
root.badRequired = d.createObject(root, { "not_i": 42 });
root.goodRequired = d.createObject(root, { "i": 42 });
+
+ root.bindingAsInitial = e.createObject(root, {color: Qt.binding(() => {
+ root.bindingUsed = true; return '#ff0000'
+ })});
}
}
diff --git a/tests/auto/qml/qqmlcomponent/data/createQmlObject.qml b/tests/auto/qml/qqmlcomponent/data/createQmlObject.qml
index 282ab509f0..480835a5b1 100644
--- a/tests/auto/qml/qqmlcomponent/data/createQmlObject.qml
+++ b/tests/auto/qml/qqmlcomponent/data/createQmlObject.qml
@@ -1,5 +1,4 @@
-import QtQuick 2.0
-import QtQuick.Window 2.0
+import QtQuick
Item {
property QtObject qtobjectParent: QtObject { }
@@ -19,14 +18,14 @@ Item {
property QtObject window_window : null
Component.onCompleted: {
- qtobject_qtobject = Qt.createQmlObject("import QtQuick 2.0; QtObject{}", qtobjectParent);
- qtobject_item = Qt.createQmlObject("import QtQuick 2.0; Item{}", qtobjectParent);
- qtobject_window = Qt.createQmlObject("import QtQuick.Window 2.0; Window{}", qtobjectParent);
- item_qtobject = Qt.createQmlObject("import QtQuick 2.0; QtObject{}", itemParent);
- item_item = Qt.createQmlObject("import QtQuick 2.0; Item{}", itemParent);
- item_window = Qt.createQmlObject("import QtQuick.Window 2.0; Window{}", itemParent);
- window_qtobject = Qt.createQmlObject("import QtQuick 2.0; QtObject{}", windowParent);
- window_item = Qt.createQmlObject("import QtQuick 2.0; Item{}", windowParent);
- window_window = Qt.createQmlObject("import QtQuick.Window 2.0; Window{}", windowParent);
+ qtobject_qtobject = Qt.createQmlObject("import QtQuick; QtObject{}", qtobjectParent);
+ qtobject_item = Qt.createQmlObject("import QtQuick; Item{}", qtobjectParent);
+ qtobject_window = Qt.createQmlObject("import QtQuick; Window{}", qtobjectParent);
+ item_qtobject = Qt.createQmlObject("import QtQuick; QtObject{}", itemParent);
+ item_item = Qt.createQmlObject("import QtQuick; Item{}", itemParent);
+ item_window = Qt.createQmlObject("import QtQuick; Window{}", itemParent);
+ window_qtobject = Qt.createQmlObject("import QtQuick; QtObject{}", windowParent);
+ window_item = Qt.createQmlObject("import QtQuick; Item{}", windowParent);
+ window_window = Qt.createQmlObject("import QtQuick; Window{}", windowParent);
}
}
diff --git a/tests/auto/qml/qqmlcomponent/data/dynamic.qml b/tests/auto/qml/qqmlcomponent/data/dynamic.qml
new file mode 100644
index 0000000000..b9a54d53ff
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/dynamic.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property var testObj
+ function use() { return testObj.has(1) ? 25 : 26; }
+}
diff --git a/tests/auto/qml/qqmlcomponent/data/removeBinding.qml b/tests/auto/qml/qqmlcomponent/data/removeBinding.qml
new file mode 100644
index 0000000000..091f6991be
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/data/removeBinding.qml
@@ -0,0 +1,32 @@
+import QtQml 2.15
+
+QtObject {
+ id: root
+ objectName: "400"
+
+ property Component c: Component {
+ id: customItem
+ QtObject {
+ objectName: root.objectName
+ }
+ }
+
+ property string result: {
+ const properties = {
+ "objectName": "42",
+ }
+ const item = customItem.createObject(root, properties)
+ return item.objectName;
+ }
+
+ property string result2: {
+ const properties = {
+ "objectName": "43",
+ }
+
+ // add some junk argument to trigger the QQmlV4Function overload
+ const item = customItem.createObject(root, properties, 13)
+
+ return item.objectName;
+ }
+}
diff --git a/tests/auto/qml/qqmlcomponent/lifecyclewatcher.h b/tests/auto/qml/qqmlcomponent/lifecyclewatcher.h
new file mode 100644
index 0000000000..e974681d25
--- /dev/null
+++ b/tests/auto/qml/qqmlcomponent/lifecyclewatcher.h
@@ -0,0 +1,24 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef LIFECYCLEWATCHER_H
+#define LIFECYCLEWATCHER_H
+
+#include <QtQml/qqmlparserstatus.h>
+#include <private/qqmlfinalizer_p.h>
+#include <QtCore/qobject.h>
+#include <QtQml/qqml.h>
+
+class LifeCycleWatcher : public QObject, public QQmlParserStatus, public QQmlFinalizerHook
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_INTERFACES(QQmlParserStatus)
+ Q_INTERFACES(QQmlFinalizerHook)
+public:
+ void classBegin() override {states.push_back(1); }
+ void componentComplete() override {states.push_back(2);};
+ void componentFinalized() override { states.push_back(3); }
+ QList<int> states;
+};
+#endif
diff --git a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
index 5203ba9615..ea06a11006 100644
--- a/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
+++ b/tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
@@ -21,7 +21,7 @@
#include <private/qv4executablecompilationunit_p.h>
#include <qcolor.h>
#include <qsignalspy.h>
-
+#include "lifecyclewatcher.h"
#include <algorithm>
using namespace Qt::StringLiterals;
@@ -90,13 +90,6 @@ public slots:
}
};
-static void gc(QQmlEngine &engine)
-{
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
-}
-
class tst_qqmlcomponent : public QQmlDataTest
{
Q_OBJECT
@@ -140,11 +133,16 @@ private slots:
void boundComponent();
void loadFromModule_data();
void loadFromModule();
+ void loadFromModuleLifecycle();
void loadFromModuleThenCreateWithIncubator();
void loadFromModuleFailures_data();
void loadFromModuleFailures();
void loadFromModuleRequired();
void loadFromQrc();
+ void removeBinding();
+ void complexObjectArgument();
+ void bindingEvaluationOrder();
+ void compilationUnitsWithSameUrl();
private:
QQmlEngine engine;
@@ -182,14 +180,12 @@ void tst_qqmlcomponent::loadEmptyUrl()
void tst_qqmlcomponent::qmlIncubateObject()
{
QQmlComponent component(&engine, testFileUrl("incubateObject.qml"));
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object != nullptr);
QCOMPARE(object->property("test1").toBool(), true);
QCOMPARE(object->property("test2").toBool(), false);
QTRY_VERIFY(object->property("test2").toBool());
-
- delete object;
}
void tst_qqmlcomponent::qmlCreateWindow()
@@ -282,7 +278,7 @@ void tst_qqmlcomponent::qmlCreateObjectWithProperties()
QTest::ignoreMessage(
QtMsgType::QtWarningMsg,
QRegularExpression(
- ".*createObjectWithScript.qml:42:13: Required property i was not initialized"));
+ ".*createObjectWithScript.qml:45:13: Required property i was not initialized"));
QQmlComponent component(&engine, testFileUrl("createObjectWithScript.qml"));
QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8());
@@ -342,6 +338,12 @@ void tst_qqmlcomponent::qmlCreateObjectWithProperties()
QCOMPARE(goodRequired->parent(), object.data());
QCOMPARE(goodRequired->property("i").value<int>(), 42);
}
+
+ {
+ QScopedPointer<QObject> bindingAsInitial(object->property("bindingAsInitial").value<QObject *>());
+ QVERIFY(bindingAsInitial);
+ QVERIFY(object->property("bindingUsed").toBool());
+ }
}
void tst_qqmlcomponent::qmlCreateObjectClean()
@@ -390,11 +392,11 @@ void tst_qqmlcomponent::qmlCreateParentReference()
QQmlComponent component(&engine, testFileUrl("createParentReference.qml"));
QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8());
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object != nullptr);
- QVERIFY(QMetaObject::invokeMethod(object, "createChild"));
- delete object;
+ QVERIFY(QMetaObject::invokeMethod(object.get(), "createChild"));
+ object.reset();
engine.setOutputWarningsToStandardError(false);
QCOMPARE(engine.outputWarningsToStandardError(), false);
@@ -416,10 +418,8 @@ void tst_qqmlcomponent::async()
QCOMPARE(watcher.ready, 1);
QCOMPARE(watcher.error, 0);
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object != nullptr);
-
- delete object;
}
void tst_qqmlcomponent::asyncHierarchy()
@@ -437,7 +437,7 @@ void tst_qqmlcomponent::asyncHierarchy()
QCOMPARE(watcher.ready, 1);
QCOMPARE(watcher.error, 0);
- QObject *root = component.create();
+ std::unique_ptr<QObject> root { component.create() };
QVERIFY(root != nullptr);
// ensure that the parent-child relationship hierarchy is correct
@@ -461,8 +461,6 @@ void tst_qqmlcomponent::asyncHierarchy()
// ensure that values and bindings are assigned correctly
QVERIFY(root->property("success").toBool());
-
- delete root;
}
void tst_qqmlcomponent::asyncForceSync()
@@ -1245,12 +1243,14 @@ void tst_qqmlcomponent::boundComponent()
{
QQmlComponent component(&engine, testFileUrl("nestedBoundComponent.qml"));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QVERIFY(component.isBound());
QScopedPointer<QObject> o(component.create());
QVERIFY(!o.isNull());
QQmlComponent *nestedComponent = o->property("c").value<QQmlComponent *>();
QVERIFY(nestedComponent != nullptr);
+ QVERIFY(nestedComponent->isBound());
QObject *nestedObject = o->property("o").value<QObject *>();
QVERIFY(nestedObject != nullptr);
@@ -1269,6 +1269,7 @@ void tst_qqmlcomponent::boundComponent()
{
QQmlComponent component(&engine, testFileUrl("BoundInlineComponent.qml"));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QVERIFY(component.isBound());
QScopedPointer<QObject> o(component.create());
QVERIFY2(!o.isNull(), qPrintable(component.errorString()));
@@ -1282,11 +1283,22 @@ void tst_qqmlcomponent::boundComponent()
{
QQmlComponent component(&engine, testFileUrl("boundInlineComponentUser.qml"));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QVERIFY(!component.isBound());
QScopedPointer<QObject> o(component.create());
QVERIFY(o.isNull());
QVERIFY(component.errorString().contains(
QLatin1String("Cannot instantiate bound inline component in different file")));
+
+ }
+
+ {
+ QQmlComponent component(&engine);
+ QVERIFY(!component.isBound());
+
+ component.setData("pragma ComponentBehavior: Bound\nsyntax error", QUrl());
+ QCOMPARE(component.errorString(), ":2 Syntax error\n"_L1);
+ QVERIFY(!component.isBound());
}
}
@@ -1334,6 +1346,34 @@ void tst_qqmlcomponent::loadFromModule()
name);
}
+void tst_qqmlcomponent::loadFromModuleLifecycle()
+{
+ QQmlEngine engine;
+ QList<int> loadFromModuleOrder;
+ QList<int> plainLoadOrder;
+ const QList<int> expected {1, 2, 3};
+ {
+ QQmlComponent component(&engine);
+ component.loadFromModule("test", "LifeCycleWatcher");
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> root{ component.create() };
+ LifeCycleWatcher *watcher = qobject_cast<LifeCycleWatcher *>(root.get());
+ QVERIFY(watcher);
+ loadFromModuleOrder = watcher->states;
+ QCOMPARE(loadFromModuleOrder, expected);
+ }
+ {
+ QQmlComponent component(&engine);
+ component.setData("import test; LifeCycleWatcher {}", {});
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> root{ component.create() };
+ LifeCycleWatcher *watcher = qobject_cast<LifeCycleWatcher *>(root.get());
+ QVERIFY(watcher);
+ plainLoadOrder = watcher->states;
+ }
+ QCOMPARE(loadFromModuleOrder, plainLoadOrder);
+}
+
struct CallVerifyingIncubtor : QQmlIncubator
{
void setInitialState(QObject *) override { setInitialStateCalled = true; }
@@ -1373,6 +1413,10 @@ void tst_qqmlcomponent::loadFromModuleFailures_data()
QTest::addRow("CppSingleton") << u"QtQuick"_s
<< u"Application"_s
<< u"Application is a singleton, and cannot be loaded"_s;
+ QTest::addRow("passedFileName") << "plainqml"
+ << "Plain.qml"
+ << R"(Type "Plain" from module "plainqml" contains no inline component named "qml". )"
+ R"(To load the type "Plain", drop the ".qml" extension.)";
}
void tst_qqmlcomponent::loadFromModuleFailures()
@@ -1384,7 +1428,11 @@ void tst_qqmlcomponent::loadFromModuleFailures()
QQmlEngine engine;
QQmlComponent component(&engine);
QSignalSpy errorSpy(&component, &QQmlComponent::statusChanged);
+ QSignalSpy progressSpy(&component, &QQmlComponent::progressChanged);
component.loadFromModule(uri, typeName);
+ // verify that we changed the progress correctly to 1
+ QTRY_VERIFY(!progressSpy.isEmpty());
+ QTRY_COMPARE(progressSpy.last().at(0).toDouble(), 1.0);
QVERIFY(!errorSpy.isEmpty());
QCOMPARE(errorSpy.first().first().value<QQmlComponent::Status>(),
QQmlComponent::Error);
@@ -1422,7 +1470,99 @@ void tst_qqmlcomponent::loadFromQrc()
QQmlComponentPrivate *p = QQmlComponentPrivate::get(&component);
QVERIFY(p);
QVERIFY(p->compilationUnit);
- QVERIFY(p->compilationUnit->aotCompiledFunctions);
+ QVERIFY(p->compilationUnit->baseCompilationUnit()->aotCompiledFunctions);
+}
+
+void tst_qqmlcomponent::removeBinding()
+{
+ QQmlEngine e;
+ const QUrl url = testFileUrl("removeBinding.qml");
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + QStringLiteral(":7:27: QML Component: Unsuitable arguments "
+ "passed to createObject(). The first argument "
+ "should be a QObject* or null, and the second "
+ "argument should be a JavaScript object or a "
+ "QVariantMap")));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("result"), QStringLiteral("42"));
+ QCOMPARE(o->property("result2"), QStringLiteral("43"));
+}
+
+void tst_qqmlcomponent::complexObjectArgument()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("complexObjectArgument.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), QStringLiteral("26 - 25"));
+}
+
+void tst_qqmlcomponent::bindingEvaluationOrder()
+{
+ // Note: This test explicitly tests the order in which bindings are
+ // evaluated, which is generally unspecified. This, however, exists
+ // as a regression test for QQmlObjectCreator code that is supposed
+ // to *not* mess with the QmlIR given to it.
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import QtQml
+ QtObject {
+ property var myList: ["dummy"]
+ property int p1: { myList.push("p1"); return 0; }
+ property int p2: { myList.push("p2"); return 0; }
+ })", QUrl());
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ const QList<QVariant> myList = o->property("myList").toList();
+ QCOMPARE(myList.size(), 3);
+ QCOMPARE(myList[0].toString(), u"dummy"_s);
+ QCOMPARE(myList[1].toString(), u"p1"_s);
+ QCOMPARE(myList[2].toString(), u"p2"_s);
+}
+
+void tst_qqmlcomponent::compilationUnitsWithSameUrl()
+{
+ QQmlEngine engine;
+ engine.setUiLanguage("de_CH");
+
+ std::vector<std::unique_ptr<QObject>> objects;
+ for (int i = 0; i < 10; ++i) {
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import QtQml
+ QtObject {
+ function returnThing() : string { return Qt.uiLanguage }
+ }
+ )", QUrl("duplicate.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ std::unique_ptr<QObject> o(component.create());
+ QVERIFY(o.get());
+
+ QString result;
+ QMetaObject::invokeMethod(o.get(), "returnThing", Q_RETURN_ARG(QString, result));
+ QCOMPARE(result, "de_CH");
+
+ objects.push_back(std::move(o));
+ }
+
+ gc(engine);
+
+ for (const auto &o: objects) {
+ QString result;
+ QMetaObject::invokeMethod(o.get(), "returnThing", Q_RETURN_ARG(QString, result));
+ QCOMPARE(result, "de_CH");
+ }
}
QTEST_MAIN(tst_qqmlcomponent)
diff --git a/tests/auto/qml/qqmlconnections/CMakeLists.txt b/tests/auto/qml/qqmlconnections/CMakeLists.txt
index d75c86f417..0e6947370d 100644
--- a/tests/auto/qml/qqmlconnections/CMakeLists.txt
+++ b/tests/auto/qml/qqmlconnections/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlconnections Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlconnections LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -21,6 +27,7 @@ qt_internal_add_test(tst_qqmlconnections
Qt::Gui
Qt::GuiPrivate
Qt::QmlPrivate
+ Qt::QmlMetaPrivate
Qt::QuickPrivate
Qt::QuickTestUtilsPrivate
TESTDATA ${test_data}
diff --git a/tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml b/tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml
new file mode 100644
index 0000000000..921787aa36
--- /dev/null
+++ b/tests/auto/qml/qqmlconnections/data/badSignalHandlerName.qml
@@ -0,0 +1,15 @@
+import QtQml
+
+QtObject {
+ id: root
+ signal _foo
+
+ property int handled: 0
+
+ property Connections c: Connections {
+ target: root
+ function on_Foo() { root.handled += 1 }
+ function on_foo() { root.handled += 2 }
+ }
+}
+
diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
index f23c474907..88441e9dac 100644
--- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
+++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -55,6 +55,7 @@ private slots:
void bindToPropertyWithUnderscoreChangeHandler();
void invalidTarget();
+ void badSignalHandlerName();
private:
QQmlEngine engine;
void prefixes();
@@ -76,26 +77,22 @@ void tst_qqmlconnections::defaultValues()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("test-connection3.qml"));
- QQmlConnections *item = qobject_cast<QQmlConnections*>(c.create());
+ std::unique_ptr<QQmlConnections> item { qobject_cast<QQmlConnections*>(c.create()) };
QVERIFY(item != nullptr);
QVERIFY(!item->target());
-
- delete item;
}
void tst_qqmlconnections::properties()
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("test-connection2.qml"));
- QQmlConnections *item = qobject_cast<QQmlConnections*>(c.create());
+ std::unique_ptr<QQmlConnections> item { qobject_cast<QQmlConnections*>(c.create()) };
QVERIFY(item != nullptr);
QVERIFY(item != nullptr);
- QCOMPARE(item->target(), item);
-
- delete item;
+ QCOMPARE(item->target(), item.get());
}
void tst_qqmlconnections::connection()
@@ -103,7 +100,7 @@ void tst_qqmlconnections::connection()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/test-connection.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(c.create()) };
QVERIFY(item != nullptr);
@@ -112,8 +109,6 @@ void tst_qqmlconnections::connection()
emit item->setWidth(100.);
QCOMPARE(item->width(), 100.);
QCOMPARE(item->property("tested").toBool(), true);
-
- delete item;
}
void tst_qqmlconnections::trimming()
@@ -121,20 +116,18 @@ void tst_qqmlconnections::trimming()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/trimming.qml"));
- QObject *object = c.create();
+ std::unique_ptr<QObject> object { c.create() };
QVERIFY(object != nullptr);
QCOMPARE(object->property("tested").toString(), QString(""));
int index = object->metaObject()->indexOfSignal("testMe(int,QString)");
QMetaMethod method = object->metaObject()->method(index);
- method.invoke(object,
+ method.invoke(object.get(),
Qt::DirectConnection,
Q_ARG(int, 5),
Q_ARG(QString, "worked"));
QCOMPARE(object->property("tested").toString(), QString("worked5"));
-
- delete object;
}
// Confirm that target can be changed by one of our signal handlers
@@ -143,7 +136,7 @@ void tst_qqmlconnections::targetChanged()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/connection-targetchange.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(c.create()) };
QVERIFY(item != nullptr);
QQmlConnections *connections = item->findChild<QQmlConnections*>("connections");
@@ -159,8 +152,6 @@ void tst_qqmlconnections::targetChanged()
QCOMPARE(connections->target(), item2);
// If we don't crash then we're OK
-
- delete item;
}
void tst_qqmlconnections::unknownSignals_data()
@@ -193,7 +184,7 @@ void tst_qqmlconnections::unknownSignals()
QQmlEngine engine;
QQmlComponent c(&engine, url);
- QObject *object = c.create();
+ std::unique_ptr<QObject> object { c.create() };
QVERIFY(object != nullptr);
// check that connection is created (they are all runtime errors)
@@ -202,8 +193,6 @@ void tst_qqmlconnections::unknownSignals()
if (file == "connection-unknownsignals-ignored.qml")
QVERIFY(connections->ignoreUnknownSignals());
-
- delete object;
}
void tst_qqmlconnections::errors_data()
@@ -260,25 +249,21 @@ void tst_qqmlconnections::rewriteErrors()
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/rewriteError-unnamed.qml"));
QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal uses unnamed parameter followed by named parameter.").toLatin1());
- TestObject *obj = qobject_cast<TestObject*>(c.create());
+ std::unique_ptr<TestObject> obj { qobject_cast<TestObject*>(c.create()) };
QVERIFY(obj != nullptr);
obj->unnamedArgumentSignal(1, .5, "hello");
QCOMPARE(obj->ran(), false);
-
- delete obj;
}
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/rewriteError-global.qml"));
QTest::ignoreMessage(QtWarningMsg, (c.url().toString() + ":5:35: QML Connections: Signal parameter \"parseInt\" hides global variable.").toLatin1());
- TestObject *obj = qobject_cast<TestObject*>(c.create());
+ std::unique_ptr<TestObject> obj { qobject_cast<TestObject*>(c.create()) };
QVERIFY(obj != nullptr);
obj->signalWithGlobalName(10);
QCOMPARE(obj->ran(), false);
-
- delete obj;
}
}
@@ -324,26 +309,24 @@ void tst_qqmlconnections::singletonTypeTarget()
QFETCH(QString, prefix);
qmlRegisterSingletonType<MyTestSingletonType>("MyTestSingletonType", 1, 0, "Api", module_api_factory);
QQmlComponent component(&engine, testFileUrl(prefix + "/singletontype-target.qml"));
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object != nullptr);
QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 0);
QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0);
- QMetaObject::invokeMethod(object, "setModuleIntProp");
+ QMetaObject::invokeMethod(object.get(), "setModuleIntProp");
QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 1);
QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0);
- QMetaObject::invokeMethod(object, "setModuleIntProp");
+ QMetaObject::invokeMethod(object.get(), "setModuleIntProp");
QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 2);
QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 0);
// the singleton Type emits otherSignal every 3 times the int property changes.
- QMetaObject::invokeMethod(object, "setModuleIntProp");
+ QMetaObject::invokeMethod(object.get(), "setModuleIntProp");
QCOMPARE(object->property("moduleIntPropChangedCount").toInt(), 3);
QCOMPARE(object->property("moduleOtherSignalCount").toInt(), 1);
-
- delete object;
}
void tst_qqmlconnections::enableDisable_QTBUG_36350()
@@ -351,7 +334,7 @@ void tst_qqmlconnections::enableDisable_QTBUG_36350()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/test-connection.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(c.create()) };
QVERIFY(item != nullptr);
QQmlConnections *connections = item->findChild<QQmlConnections*>("connections");
@@ -370,8 +353,6 @@ void tst_qqmlconnections::enableDisable_QTBUG_36350()
emit item->setWidth(50.);
QCOMPARE(item->width(), 50.);
QCOMPARE(item->property("tested").toBool(), true); //Should have received signal to change property
-
- delete item;
}
void tst_qqmlconnections::disabledAtStart()
@@ -379,17 +360,15 @@ void tst_qqmlconnections::disabledAtStart()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/disabled-at-start.qml"));
- QObject * const object = c.create();
+ std::unique_ptr<QObject> object { c.create() };
QVERIFY(object != nullptr);
QCOMPARE(object->property("tested").toBool(), false);
const int index = object->metaObject()->indexOfSignal("testMe()");
const QMetaMethod method = object->metaObject()->method(index);
- method.invoke(object, Qt::DirectConnection);
+ method.invoke(object.get(), Qt::DirectConnection);
QCOMPARE(object->property("tested").toBool(), false);
-
- delete object;
}
//QTBUG-56499
@@ -398,7 +377,7 @@ void tst_qqmlconnections::clearImplicitTarget()
QFETCH(QString, prefix);
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl(prefix + "/test-connection-implicit.qml"));
- QQuickItem *item = qobject_cast<QQuickItem*>(c.create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(c.create()) };
QVERIFY(item != nullptr);
@@ -415,8 +394,6 @@ void tst_qqmlconnections::clearImplicitTarget()
// target cleared: no longer fire Connections
item->setWidth(150.);
QCOMPARE(item->property("tested").toBool(), false);
-
- delete item;
}
void tst_qqmlconnections::onWithoutASignal()
@@ -485,6 +462,26 @@ void tst_qqmlconnections::invalidTarget()
QTRY_VERIFY(root->objectName().isEmpty());
}
+void tst_qqmlconnections::badSignalHandlerName()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("badSignalHandlerName.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "\"on_foo\" is not a properly capitalized signal handler name. "
+ "\"on_Foo\" would be correct.");
+
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+
+ QCOMPARE(root->property("handled").toInt(), 0);
+ QMetaObject::invokeMethod(root.data(), "_foo");
+ QCOMPARE(root->property("handled").toInt(), 3);
+}
+
+
QTEST_MAIN(tst_qqmlconnections)
#include "tst_qqmlconnections.moc"
diff --git a/tests/auto/qml/qqmlconsole/CMakeLists.txt b/tests/auto/qml/qqmlconsole/CMakeLists.txt
index a4eb33f1df..121b0863d0 100644
--- a/tests/auto/qml/qqmlconsole/CMakeLists.txt
+++ b/tests/auto/qml/qqmlconsole/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlconsole Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlconsole LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlconsole/data/assert.qml b/tests/auto/qml/qqmlconsole/data/assert.qml
index 38a103e233..04ea18a3e5 100644
--- a/tests/auto/qml/qqmlconsole/data/assert.qml
+++ b/tests/auto/qml/qqmlconsole/data/assert.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/data/categorized_logging.qml b/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
index 9593abbaa9..dd03c0c773 100644
--- a/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
+++ b/tests/auto/qml/qqmlconsole/data/categorized_logging.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Pelagicore AG
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
diff --git a/tests/auto/qml/qqmlconsole/data/exception.qml b/tests/auto/qml/qqmlconsole/data/exception.qml
index 769b196c10..d3d022ca22 100644
--- a/tests/auto/qml/qqmlconsole/data/exception.qml
+++ b/tests/auto/qml/qqmlconsole/data/exception.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/data/logging.qml b/tests/auto/qml/qqmlconsole/data/logging.qml
index af1c97ee01..309534615e 100644
--- a/tests/auto/qml/qqmlconsole/data/logging.qml
+++ b/tests/auto/qml/qqmlconsole/data/logging.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/data/profiling.qml b/tests/auto/qml/qqmlconsole/data/profiling.qml
index fc655ab26c..528726b268 100644
--- a/tests/auto/qml/qqmlconsole/data/profiling.qml
+++ b/tests/auto/qml/qqmlconsole/data/profiling.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/data/tracing.qml b/tests/auto/qml/qqmlconsole/data/tracing.qml
index 750e4f5688..52be9d84de 100644
--- a/tests/auto/qml/qqmlconsole/data/tracing.qml
+++ b/tests/auto/qml/qqmlconsole/data/tracing.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
index 4bffdb0dd7..40d849969c 100644
--- a/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
+++ b/tests/auto/qml/qqmlconsole/tst_qqmlconsole.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
#include <QQmlEngine>
@@ -95,7 +95,7 @@ void tst_qqmlconsole::categorized_logging()
QVERIFY(testCategory.isCriticalEnabled());
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY2(object != nullptr, component.errorString().toUtf8());
QVERIFY(messageHandler.messages().contains("qt.test: console.info"));
@@ -131,8 +131,6 @@ void tst_qqmlconsole::categorized_logging()
QString useEmptyCategory = "default: " + QString::fromLatin1("%1:%2: ").arg(testUrl.toString()).arg(42) +
"Error: A QmlLoggingCatgory was provided without a valid name";
QVERIFY(messageHandler.messages().contains(useEmptyCategory));
-
- delete object;
}
void tst_qqmlconsole::tracing()
@@ -147,9 +145,17 @@ void tst_qqmlconsole::tracing()
QTest::ignoreMessage(QtDebugMsg, qPrintable(traceText));
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
+
+ const QString traceText2
+ = QLatin1String("qml: tracing (%1:%2)\nexpression for onCompleted (%1:%3)")
+ .arg(testUrl.toString()).arg(12).arg(16);
+
+ QQmlTestMessageHandler messageHandler;
+ messageHandler.setIncludeCategoriesEnabled(true);
+ std::unique_ptr<QObject> object2 { component.create() };
+ QCOMPARE(messageHandler.messageString(), traceText2);
}
void tst_qqmlconsole::profiling()
@@ -161,9 +167,8 @@ void tst_qqmlconsole::profiling()
QTest::ignoreMessage(QtWarningMsg, "Ignoring console.profileEnd(): the debug service is disabled.");
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
}
void tst_qqmlconsole::testAssert()
@@ -186,9 +191,8 @@ void tst_qqmlconsole::testAssert()
QTest::ignoreMessage(QtCriticalMsg, qPrintable(assert2));
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
}
void tst_qqmlconsole::exception()
@@ -211,9 +215,8 @@ void tst_qqmlconsole::exception()
QTest::ignoreMessage(QtCriticalMsg, qPrintable(exception2));
QQmlComponent component(&engine, testUrl);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
}
QTEST_MAIN(tst_qqmlconsole)
diff --git a/tests/auto/qml/qqmlcontext/CMakeLists.txt b/tests/auto/qml/qqmlcontext/CMakeLists.txt
index c8d5ec6810..b50e3ff7fe 100644
--- a/tests/auto/qml/qqmlcontext/CMakeLists.txt
+++ b/tests/auto/qml/qqmlcontext/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlcontext Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlcontext LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlcontext/data/A.qml b/tests/auto/qml/qqmlcontext/data/A.qml
new file mode 100644
index 0000000000..1a44f005af
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/A.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+B {
+ id: b
+ property int y: 2
+}
diff --git a/tests/auto/qml/qqmlcontext/data/B.qml b/tests/auto/qml/qqmlcontext/data/B.qml
new file mode 100644
index 0000000000..7754728304
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/B.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+C {
+ id: z
+ property int z: 3
+}
diff --git a/tests/auto/qml/qqmlcontext/data/C.qml b/tests/auto/qml/qqmlcontext/data/C.qml
new file mode 100644
index 0000000000..6afd23aa6c
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/C.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ id: outer
+ objectName: "the" + "C"
+}
diff --git a/tests/auto/qml/qqmlcontext/data/destroyContextObject.qml b/tests/auto/qml/qqmlcontext/data/destroyContextObject.qml
new file mode 100644
index 0000000000..7b1f46d7d1
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/destroyContextObject.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property A a: A {}
+}
diff --git a/tests/auto/qml/qqmlcontext/data/gcDeletesContextObject.qml b/tests/auto/qml/qqmlcontext/data/gcDeletesContextObject.qml
new file mode 100644
index 0000000000..a478a587df
--- /dev/null
+++ b/tests/auto/qml/qqmlcontext/data/gcDeletesContextObject.qml
@@ -0,0 +1,5 @@
+import QtQml
+QtObject {
+ property Component c: MyItem {}
+ property QtObject o: c.createObject()
+}
diff --git a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
index 8398f8b9d7..8e726857cc 100644
--- a/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
+++ b/tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
@@ -49,6 +49,10 @@ private slots:
void outerContextObject();
void contextObjectHierarchy();
void destroyContextProperty();
+ void destroyContextObject();
+
+ void numericContextProperty();
+ void gcDeletesContextObject();
private:
QQmlEngine engine;
@@ -92,13 +96,13 @@ void tst_qqmlcontext::resolvedUrl()
// Relative to a deleted parent
{
- QQmlContext *ctxt = new QQmlContext(&engine);
+ std::unique_ptr<QQmlContext> ctxt = std::make_unique<QQmlContext>(&engine);
ctxt->setBaseUrl(QUrl("http://www.qt-project.org/"));
- QQmlContext ctxt2(ctxt);
+ QQmlContext ctxt2(ctxt.get());
QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl("http://www.qt-project.org/main2.qml"));
- delete ctxt; ctxt = nullptr;
+ ctxt.reset();
QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl());
}
@@ -114,58 +118,58 @@ void tst_qqmlcontext::resolvedUrl()
void tst_qqmlcontext::engineMethod()
{
- QQmlEngine *engine = new QQmlEngine;
+ std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>();
- QQmlContext ctxt(engine);
+ QQmlContext ctxt(engine.get());
QQmlContext ctxt2(&ctxt);
QQmlContext ctxt3(&ctxt2);
QQmlContext ctxt4(&ctxt2);
- QCOMPARE(ctxt.engine(), engine);
- QCOMPARE(ctxt2.engine(), engine);
- QCOMPARE(ctxt3.engine(), engine);
- QCOMPARE(ctxt4.engine(), engine);
+ QCOMPARE(ctxt.engine(), engine.get());
+ QCOMPARE(ctxt2.engine(), engine.get());
+ QCOMPARE(ctxt3.engine(), engine.get());
+ QCOMPARE(ctxt4.engine(), engine.get());
- delete engine; engine = nullptr;
+ engine.reset();
- QCOMPARE(ctxt.engine(), engine);
- QCOMPARE(ctxt2.engine(), engine);
- QCOMPARE(ctxt3.engine(), engine);
- QCOMPARE(ctxt4.engine(), engine);
+ QCOMPARE(ctxt.engine(), engine.get());
+ QCOMPARE(ctxt2.engine(), engine.get());
+ QCOMPARE(ctxt3.engine(), engine.get());
+ QCOMPARE(ctxt4.engine(), engine.get());
}
void tst_qqmlcontext::parentContext()
{
- QQmlEngine *engine = new QQmlEngine;
+ std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>();
QCOMPARE(engine->rootContext()->parentContext(), (QQmlContext *)nullptr);
- QQmlContext *ctxt = new QQmlContext(engine);
- QQmlContext *ctxt2 = new QQmlContext(ctxt);
- QQmlContext *ctxt3 = new QQmlContext(ctxt2);
- QQmlContext *ctxt4 = new QQmlContext(ctxt2);
- QQmlContext *ctxt5 = new QQmlContext(ctxt);
- QQmlContext *ctxt6 = new QQmlContext(engine);
- QQmlContext *ctxt7 = new QQmlContext(engine->rootContext());
+ std::unique_ptr<QQmlContext> ctxt = std::make_unique<QQmlContext>(engine.get());
+ std::unique_ptr<QQmlContext> ctxt2 = std::make_unique<QQmlContext>(ctxt.get());
+ std::unique_ptr<QQmlContext> ctxt3 = std::make_unique<QQmlContext>(ctxt2.get());
+ std::unique_ptr<QQmlContext> ctxt4 = std::make_unique<QQmlContext>(ctxt2.get());
+ std::unique_ptr<QQmlContext> ctxt5 = std::make_unique<QQmlContext>(ctxt.get());
+ std::unique_ptr<QQmlContext> ctxt6 = std::make_unique<QQmlContext>(engine.get());
+ std::unique_ptr<QQmlContext> ctxt7 = std::make_unique<QQmlContext>(engine->rootContext());
QCOMPARE(ctxt->parentContext(), engine->rootContext());
- QCOMPARE(ctxt2->parentContext(), ctxt);
- QCOMPARE(ctxt3->parentContext(), ctxt2);
- QCOMPARE(ctxt4->parentContext(), ctxt2);
- QCOMPARE(ctxt5->parentContext(), ctxt);
+ QCOMPARE(ctxt2->parentContext(), ctxt.get());
+ QCOMPARE(ctxt3->parentContext(), ctxt2.get());
+ QCOMPARE(ctxt4->parentContext(), ctxt2.get());
+ QCOMPARE(ctxt5->parentContext(), ctxt.get());
QCOMPARE(ctxt6->parentContext(), engine->rootContext());
QCOMPARE(ctxt7->parentContext(), engine->rootContext());
- delete ctxt2; ctxt2 = nullptr;
+ ctxt2.reset();
QCOMPARE(ctxt->parentContext(), engine->rootContext());
QCOMPARE(ctxt3->parentContext(), (QQmlContext *)nullptr);
QCOMPARE(ctxt4->parentContext(), (QQmlContext *)nullptr);
- QCOMPARE(ctxt5->parentContext(), ctxt);
+ QCOMPARE(ctxt5->parentContext(), ctxt.get());
QCOMPARE(ctxt6->parentContext(), engine->rootContext());
QCOMPARE(ctxt7->parentContext(), engine->rootContext());
- delete engine; engine = nullptr;
+ engine.reset();
QCOMPARE(ctxt->parentContext(), (QQmlContext *)nullptr);
QCOMPARE(ctxt3->parentContext(), (QQmlContext *)nullptr);
@@ -173,13 +177,6 @@ void tst_qqmlcontext::parentContext()
QCOMPARE(ctxt5->parentContext(), (QQmlContext *)nullptr);
QCOMPARE(ctxt6->parentContext(), (QQmlContext *)nullptr);
QCOMPARE(ctxt7->parentContext(), (QQmlContext *)nullptr);
-
- delete ctxt7;
- delete ctxt6;
- delete ctxt5;
- delete ctxt4;
- delete ctxt3;
- delete ctxt;
}
class TestObject : public QObject
@@ -229,11 +226,9 @@ private:
QQmlComponent component(&engine); \
component.setData("import QtQuick 2.0; QtObject { property variant test: " #name " }", QUrl()); \
\
- QObject *obj = component.create(ctxt); \
+ std::unique_ptr<QObject> obj { component.create(ctxt) }; \
\
QCOMPARE(obj->property("test"), value); \
-\
- delete obj; \
}
void tst_qqmlcontext::setContextProperty()
@@ -279,39 +274,33 @@ void tst_qqmlcontext::setContextProperty()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: a }", QUrl());
- QObject *obj = component.create(&ctxt2);
+ std::unique_ptr<QObject> obj { component.create(&ctxt2) };
QCOMPARE(obj->property("test"), QVariant(13));
ctxt.setContextProperty("a", QVariant(19));
QCOMPARE(obj->property("test"), QVariant(19));
-
- delete obj;
}
{
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: b }", QUrl());
- QObject *obj = component.create(&ctxt2);
+ std::unique_ptr<QObject> obj { component.create(&ctxt2) };
QCOMPARE(obj->property("test"), QVariant(8));
ctxt.setContextProperty("b", QVariant(5));
QCOMPARE(obj->property("test"), QVariant(8));
ctxt2.setContextProperty("b", QVariant(1912));
QCOMPARE(obj->property("test"), QVariant(1912));
-
- delete obj;
}
{
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: e.a }", QUrl());
- QObject *obj = component.create(&ctxt2);
+ std::unique_ptr<QObject> obj { component.create(&ctxt2) };
QCOMPARE(obj->property("test"), QVariant(12));
obj1.setA(13);
QCOMPARE(obj->property("test"), QVariant(13));
-
- delete obj;
}
// New context properties
@@ -319,13 +308,11 @@ void tst_qqmlcontext::setContextProperty()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: a }", QUrl());
- QObject *obj = component.create(&ctxt2);
+ std::unique_ptr<QObject> obj { component.create(&ctxt2) };
QCOMPARE(obj->property("test"), QVariant(19));
ctxt2.setContextProperty("a", QVariant(1945));
QCOMPARE(obj->property("test"), QVariant(1945));
-
- delete obj;
}
// Setting an object-variant context property
@@ -337,15 +324,13 @@ void tst_qqmlcontext::setContextProperty()
ctxt.setContextProperty("ctxtProp", QVariant());
QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1: TypeError: Cannot read property 'a' of undefined");
- QObject *obj = component.create(&ctxt);
+ std::unique_ptr<QObject> obj { component.create(&ctxt) };
QVariant v = obj->property("obj");
ctxt.setContextProperty("ctxtProp", v);
QCOMPARE(obj->property("test"), QVariant(10));
-
- delete obj;
}
}
@@ -407,13 +392,11 @@ void tst_qqmlcontext::setContextObject()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant test: a }", QUrl());
- QObject *obj = component.create(&ctxt);
+ std::unique_ptr<QObject> obj { component.create(&ctxt) };
QCOMPARE(obj->property("test"), QVariant(12));
to.setA(14);
QCOMPARE(obj->property("test"), QVariant(14));
-
- delete obj;
}
// Change of context object
@@ -431,19 +414,19 @@ void tst_qqmlcontext::setContextObject()
void tst_qqmlcontext::destruction()
{
- QQmlContext *ctxt = new QQmlContext(&engine);
+ std::unique_ptr<QQmlContext> ctxt = std::make_unique<QQmlContext>(&engine);
QObject obj;
- QQmlEngine::setContextForObject(&obj, ctxt);
- QQmlExpression expr(ctxt, nullptr, "a");
+ QQmlEngine::setContextForObject(&obj, ctxt.get());
+ QQmlExpression expr(ctxt.get(), nullptr, "a");
- QCOMPARE(ctxt, QQmlEngine::contextForObject(&obj));
- QCOMPARE(ctxt, expr.context());
+ QCOMPARE(ctxt.get(), QQmlEngine::contextForObject(&obj));
+ QCOMPARE(ctxt.get(), expr.context());
- delete ctxt; ctxt = nullptr;
+ ctxt.reset();
- QCOMPARE(ctxt, QQmlEngine::contextForObject(&obj));
- QCOMPARE(ctxt, expr.context());
+ QCOMPARE(ctxt.get(), QQmlEngine::contextForObject(&obj));
+ QCOMPARE(ctxt.get(), expr.context());
}
void tst_qqmlcontext::idAsContextProperty()
@@ -451,18 +434,16 @@ void tst_qqmlcontext::idAsContextProperty()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { property variant a; a: QtObject { id: myObject } }", QUrl());
- QObject *obj = component.create();
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get());
QVariant a = obj->property("a");
QCOMPARE(a.userType(), int(QMetaType::QObjectStar));
- QVariant ctxt = qmlContext(obj)->contextProperty("myObject");
+ QVariant ctxt = qmlContext(obj.get())->contextProperty("myObject");
QCOMPARE(ctxt.userType(), int(QMetaType::QObjectStar));
QCOMPARE(a, ctxt);
-
- delete obj;
}
// Internal contexts should be read-only
@@ -471,28 +452,26 @@ void tst_qqmlcontext::readOnlyContexts()
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0; QtObject { id: me }", QUrl());
- QObject *obj = component.create();
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get());
- QQmlContext *context = qmlContext(obj);
+ QQmlContext *context = qmlContext(obj.get());
QVERIFY(context);
- QCOMPARE(qvariant_cast<QObject*>(context->contextProperty("me")), obj);
- QCOMPARE(context->contextObject(), obj);
+ QCOMPARE(qvariant_cast<QObject*>(context->contextProperty("me")), obj.get());
+ QCOMPARE(context->contextObject(), obj.get());
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set property on internal context.");
context->setContextProperty("hello", 12);
QCOMPARE(context->contextProperty("hello"), QVariant());
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set property on internal context.");
- context->setContextProperty("hello", obj);
+ context->setContextProperty("hello", obj.get());
QCOMPARE(context->contextProperty("hello"), QVariant());
QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Cannot set context object for internal context.");
context->setContextObject(nullptr);
- QCOMPARE(context->contextObject(), obj);
-
- delete obj;
+ QCOMPARE(context->contextObject(), obj.get());
}
void tst_qqmlcontext::objectsAndNames()
@@ -624,14 +603,12 @@ void tst_qqmlcontext::refreshExpressionsCrash()
component.setData("import QtQuick 2.0; QtObject { property var binding: deleteCommand.doCommand() }", QUrl());
QVERIFY(component.isReady());
- QObject *o1 = component.create(&ctxt);
+ std::unique_ptr<QObject> o1 { component.create(&ctxt) };
QObject *o2 = component.create(&ctxt);
command.object = o2;
QQmlContextData::get(&ctxt)->refreshExpressions();
-
- delete o1;
}
{
QQmlEngine engine;
@@ -647,13 +624,11 @@ void tst_qqmlcontext::refreshExpressionsCrash()
QVERIFY(component.isReady());
QObject *o1 = component.create(&ctxt);
- QObject *o2 = component.create(&ctxt);
+ std::unique_ptr<QObject> o2 { component.create(&ctxt) };
command.object = o1;
QQmlContextData::get(&ctxt)->refreshExpressions();
-
- delete o2;
}
}
@@ -685,19 +660,15 @@ void tst_qqmlcontext::refreshExpressions()
QQmlContext context(engine.rootContext());
QQmlContext context2(&context);
- QObject *o1 = component.create(&context);
- QObject *o2 = component.create(&context2);
- QObject *o3 = component2.create(&context);
+ std::unique_ptr<QObject> o1 { component.create(&context) };
+ std::unique_ptr<QObject> o2 { component.create(&context2) };
+ std::unique_ptr<QObject> o3 { component2.create(&context) };
QCOMPARE(command.count, 5);
QQmlContextData::get(&context)->refreshExpressions();
QCOMPARE(command.count, 10);
-
- delete o3;
- delete o2;
- delete o1;
}
// Test that updating the root context, only causes expressions in contexts with an
@@ -717,10 +688,10 @@ void tst_qqmlcontext::refreshExpressionsRootContext()
QString warning = component2.url().toString() + QLatin1String(":4: ReferenceError: unresolvedName is not defined");
- QObject *o1 = component.create(&context);
+ std::unique_ptr<QObject> o1 { component.create(&context) };
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- QObject *o2 = component2.create(&context2);
+ std::unique_ptr<QObject> o2 { component2.create(&context2) };
QCOMPARE(command.count, 3);
@@ -728,9 +699,6 @@ void tst_qqmlcontext::refreshExpressionsRootContext()
QQmlContextData::get(engine.rootContext())->refreshExpressions();
QCOMPARE(command.count, 4);
-
- delete o2;
- delete o1;
}
void tst_qqmlcontext::skipExpressionRefresh_qtbug_53431()
@@ -752,10 +720,9 @@ void tst_qqmlcontext::qtbug_22535()
QQmlComponent component(&engine, testFileUrl("qtbug_22535.qml"));
QQmlContext context(engine.rootContext());
- QObject *o = component.create(&context);
+ std::unique_ptr<QObject> o { component.create(&context) };
// Don't crash!
- delete o;
}
void tst_qqmlcontext::evalAfterInvalidate()
@@ -858,7 +825,7 @@ void tst_qqmlcontext::contextLeak()
scriptContext = scriptContextWrapper->as<QV4::QQmlContextWrapper>()->getContext();
}
- engine.collectGarbage();
+ gc(engine);
// Each time a JS file (non-pragma-shared) is imported, we create a QQmlContext(Data) for it.
// Make sure that context does not leak.
@@ -979,6 +946,66 @@ void tst_qqmlcontext::destroyContextProperty()
// TODO: Or are we?
}
+void tst_qqmlcontext::destroyContextObject()
+{
+ QQmlEngine engine;
+ QList<QQmlRefPointer<QQmlContextData>> contexts;
+ QQmlComponent component(&engine, testFileUrl("destroyContextObject.qml"));
+ QScopedPointer<QObject> root(component.create());
+
+ QPointer<QObject> a = root->property("a").value<QObject *>();
+ QVERIFY(a);
+
+ for (QQmlRefPointer<QQmlContextData> context = QQmlData::get(a)->ownContext;
+ context; context = context->parent()) {
+ contexts.append(context);
+ }
+
+ QObject *deleted = a.data();
+ root.reset();
+
+ QVERIFY(a.isNull());
+
+ for (const auto &context : contexts)
+ QVERIFY(context->contextObject() != deleted);
+}
+
+void tst_qqmlcontext::numericContextProperty()
+{
+ QQmlEngine engine;
+ auto context = engine.rootContext();
+ QTest::ignoreMessage(QtWarningMsg, "QQmlContext: Using numbers as context properties will be disallowed in a future Qt version.");
+ context->setContextProperty(QLatin1String("11"), 42);
+ QCOMPARE(context->contextProperty(QLatin1String("11")).toInt(), 42);
+}
+
+void tst_qqmlcontext::gcDeletesContextObject()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("gcDeletesContextObject.qml"));
+
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QVERIFY(!o.isNull());
+
+ QPointer<QObject> contextObject = o->property("o").value<QObject *>();
+ QVERIFY(contextObject != nullptr);
+
+ QQmlData *data = QQmlData::get(contextObject);
+ QVERIFY(data);
+ QQmlRefPointer<QQmlContextData> context = data->ownContext;
+ QVERIFY(context);
+ QCOMPARE(context->contextObject(), contextObject);
+
+ o->setProperty("o", QVariant::fromValue<QObject *>(nullptr));
+ QCOMPARE(o->property("o").value<QObject *>(), nullptr);
+ engine.collectGarbage();
+
+ QTRY_VERIFY(contextObject.isNull());
+ QCOMPARE(context->contextObject(), nullptr);
+}
+
QTEST_MAIN(tst_qqmlcontext)
#include "tst_qqmlcontext.moc"
diff --git a/tests/auto/qml/qqmlcpputils/CMakeLists.txt b/tests/auto/qml/qqmlcpputils/CMakeLists.txt
index 3eb58640c7..ee809e09b5 100644
--- a/tests/auto/qml/qqmlcpputils/CMakeLists.txt
+++ b/tests/auto/qml/qqmlcpputils/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlcpputils Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlcpputils LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlcpputils
SOURCES
tst_qqmlcpputils.cpp
diff --git a/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
index 11d79707d0..d858fd2ff0 100644
--- a/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
+++ b/tests/auto/qml/qqmlcpputils/tst_qqmlcpputils.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <qsignalspy.h>
@@ -35,13 +35,11 @@ public slots:
void tst_qqmlcpputils::fastConnect()
{
{
- MyObject *obj = new MyObject;
- qmlobject_connect(obj, MyObject, SIGNAL(signal1()), obj, MyObject, SLOT(slot1()));
+ std::unique_ptr<MyObject> obj = std::make_unique<MyObject>();
+ qmlobject_connect(obj.get(), MyObject, SIGNAL(signal1()), obj.get(), MyObject, SLOT(slot1()));
obj->signal1();
QCOMPARE(obj->slotCount, 1);
-
- delete obj;
}
{
@@ -53,27 +51,24 @@ void tst_qqmlcpputils::fastConnect()
}
{
- MyObject *obj = new MyObject;
- QSignalSpy spy(obj, SIGNAL(signal2()));
- qmlobject_connect(obj, MyObject, SIGNAL(signal1()), obj, MyObject, SIGNAL(signal2()));
+ std::unique_ptr<MyObject> obj = std::make_unique<MyObject>();
+ QSignalSpy spy(obj.get(), SIGNAL(signal2()));
+ qmlobject_connect(obj.get(), MyObject, SIGNAL(signal1()), obj.get(), MyObject, SIGNAL(signal2()));
obj->signal1();
QCOMPARE(spy.size(), 1);
-
- delete obj;
}
}
void tst_qqmlcpputils::fastCast()
{
{
- QObject *myObj = new MyObject;
- MyObject *obj = qmlobject_cast<MyObject*>(myObj);
+ std::unique_ptr<QObject> myObj = std::make_unique<MyObject>();
+ MyObject *obj = qmlobject_cast<MyObject*>(myObj.get());
QVERIFY(obj);
QCOMPARE(obj->metaObject(), myObj->metaObject());
obj->slot1();
QCOMPARE(obj->slotCount, 1);
- delete myObj;
}
{
diff --git a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
index 705ee6f357..8d8a90e0a7 100644
--- a/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmldelegatemodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldelegatemodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldelegatemodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml b/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml
index a61e94ea6d..5ef502601c 100644
--- a/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml
+++ b/tests/auto/qml/qqmldelegatemodel/data/abstractItemModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml.Models 2.15
import QtQuick 2.15
diff --git a/tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml b/tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml
new file mode 100644
index 0000000000..37e508302e
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/clearCacheDuringInsertion.qml
@@ -0,0 +1,138 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Controls
+import QtQuick.Layouts
+import QtQml.Models
+
+Window {
+ id: root
+ width: 640
+ height: 480
+ visible: true
+ color: "#111111"
+
+ Column {
+ spacing: 1
+ Repeater {
+ model: 1000
+
+ Rectangle {
+ width: 100
+ height: 100
+ color: "grey"
+ DelegateModel {
+ id: delegateModel
+ delegate: Rectangle {
+ width: 100
+ height: 20
+ color: "black"
+ Text {
+ anchors.centerIn: parent
+ text: "Name: " + model.name
+ color: "white"
+ }
+ }
+
+ property int length: 0
+ property var filterAcceptsItem: function(item) { return true; }
+
+ model: ListModel {
+ id: myModel
+
+ ListElement {
+ name: "tomato"
+ classifications: [
+ ListElement { classification: "fruit" },
+ ListElement { classification: "veg" }
+ ]
+ nutritionFacts: [
+ ListElement {
+ calories: "45"
+ }
+ ]
+ }
+
+ ListElement {
+ name: "apple"
+ classifications: [
+ ListElement { classification: "fruit" }
+ ]
+ nutritionFacts: [
+ ListElement {
+ calories: "87"
+ }
+ ]
+ }
+
+ ListElement {
+ name: "broccoli"
+ classifications: [
+ ListElement { classification: "veg" }
+ ]
+ nutritionFacts: [
+ ListElement {
+ calories: "12"
+ }
+ ]
+ }
+
+ ListElement {
+ name: "squash"
+ classifications: [
+ ListElement { classification: "veg" }
+ ]
+ nutritionFacts: [
+ ListElement {
+ calories: "112"
+ }
+ ]
+ }
+ }
+
+ groups: [
+ DelegateModelGroup { id: visibleItems; name: "visible" },
+ DelegateModelGroup { name: "veg" },
+ DelegateModelGroup { name: "fruit"; includeByDefault: true }
+ ]
+
+ function update() {
+
+ // Step 1: Filter items
+ var visible = [];
+ for (var i = 0; i < items.count; ++i) {
+ var item = items.get(i);
+ if (filterAcceptsItem(item.model)) {
+ visible.push(item);
+ }
+ }
+
+ // Step 2: Add all items to the visible group:
+ for (i = 0; i < visible.length; ++i) {
+ items.insert(visible[i], delegateModel.filterOnGroup)
+ }
+ delegateModel.length = visible.length
+ }
+
+ items.onChanged: update()
+ onFilterAcceptsItemChanged: update()
+
+ filterOnGroup: "visible"
+ Component.onCompleted: {
+ for(var i = 0; i < myModel.count; i++) {
+ var temp = 0;
+ var entry = myModel.get(i);
+
+ for (var j = 0; j < entry.classifications.count; j++) {
+ temp = entry.classifications.get(j)
+ items.insert(entry, temp.classification)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml
new file mode 100644
index 0000000000..b01b14f7b8
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/deleteRace.qml
@@ -0,0 +1,50 @@
+import QtQuick
+import QtQml.Models
+
+Item {
+ DelegateModel {
+ id: delegateModel
+ model: ListModel {
+ id: sourceModel
+
+ ListElement { title: "foo" }
+ ListElement { title: "bar" }
+
+ function clear() {
+ if (count > 0)
+ remove(0, count);
+ }
+ }
+
+ groups: [
+ DelegateModelGroup { name: "selectedItems" }
+ ]
+
+ delegate: Text {
+ height: DelegateModel.inSelectedItems ? implicitHeight * 2 : implicitHeight
+ Component.onCompleted: {
+ if (index === 0)
+ DelegateModel.inSelectedItems = true;
+ }
+ }
+
+ Component.onCompleted: {
+ items.create(0)
+ items.create(1)
+ }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: delegateModel
+ }
+
+ Timer {
+ running: true
+ interval: 10
+ onTriggered: sourceModel.clear()
+ }
+
+ property int count: delegateModel.items.count
+}
+
diff --git a/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml b/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml
index 42bf882fda..bcc7a2786a 100644
--- a/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml
+++ b/tests/auto/qml/qqmldelegatemodel/data/integerModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml.Models 2.15
import QtQuick 2.15
diff --git a/tests/auto/qml/qqmldelegatemodel/data/listModel.qml b/tests/auto/qml/qqmldelegatemodel/data/listModel.qml
index f74abb2e9a..b4ea7a283f 100644
--- a/tests/auto/qml/qqmldelegatemodel/data/listModel.qml
+++ b/tests/auto/qml/qqmldelegatemodel/data/listModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml.Models 2.15
import QtQuick 2.15
diff --git a/tests/auto/qml/qqmldelegatemodel/data/modifyObjectUnderConstruction.qml b/tests/auto/qml/qqmldelegatemodel/data/modifyObjectUnderConstruction.qml
new file mode 100644
index 0000000000..f21577e395
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/modifyObjectUnderConstruction.qml
@@ -0,0 +1,18 @@
+import QtQuick
+
+Window {
+ id: window
+ width: 640
+ height: 480
+ visible: true
+ property alias testModel: repeater.model
+
+ Repeater {
+ id: repeater
+ model: 1
+ delegate: Item {
+ Component.onCompleted: repeater.model = 0
+ }
+ }
+}
+
diff --git a/tests/auto/qml/qqmldelegatemodel/data/overriddenModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/overriddenModelData.qml
new file mode 100644
index 0000000000..e392b2e5c9
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/overriddenModelData.qml
@@ -0,0 +1,55 @@
+import QtQml
+
+DelegateModel {
+ id: root
+
+ property ListModel listModel: ListModel {
+ ListElement {
+ modelData: "a"
+ row: "b"
+ column: "c"
+ model: "d"
+ hasModelChildren: "e"
+ index: "f"
+ }
+ }
+
+ property var array: [{
+ modelData: "a",
+ row: "b",
+ column: "c",
+ model: "d",
+ hasModelChildren: "e",
+ index: "f"
+ }]
+
+ property QtObject object: QtObject {
+ property string modelData: "a"
+ property string row: "b"
+ property string column: "c"
+ property string model: "d"
+ property string hasModelChildren: "e"
+ property string index: "f"
+ }
+
+ property int n: -1
+
+ model: {
+ switch (n) {
+ case 0: return listModel
+ case 1: return array
+ case 2: return object
+ }
+ return undefined;
+ }
+
+ delegate: QtObject {
+ required property string modelData
+ required property string row
+ required property string column
+ required property string model
+ required property string hasModelChildren
+ required property string index
+ objectName: [modelData, row, column, model, hasModelChildren, index].join(" ")
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/persistedItemsCache.qml b/tests/auto/qml/qqmldelegatemodel/data/persistedItemsCache.qml
new file mode 100644
index 0000000000..5ae2038e1f
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/persistedItemsCache.qml
@@ -0,0 +1,62 @@
+import QtQuick
+import QtQuick.Window
+import QtQml.Models
+
+Window {
+ id: win
+ visible: true
+ width: 640
+ height: 480
+ property int destroyCount : 0;
+ property int createCount : 0;
+ property alias testListModel: mdl
+
+ DelegateModel {
+ id: visualModel
+ model: ListModel {
+ id: mdl
+ ListElement {
+ name: "a"
+ hidden: false
+ }
+ ListElement {
+ name: "b"
+ hidden: true
+ }
+ ListElement {
+ name: "c"
+ hidden: false
+ }
+ }
+
+ filterOnGroup: "selected"
+
+ groups: [
+ DelegateModelGroup {
+ name: "selected"
+ includeByDefault: true
+ }
+ ]
+
+ delegate: Text {
+ visible: DelegateModel.inSelected
+ property var idx
+ Component.onCompleted: {
+ ++createCount
+ idx = index
+ DelegateModel.inPersistedItems = true
+ DelegateModel.inSelected = !model.hidden
+ }
+ Component.onDestruction: ++destroyCount
+ text: model.name
+ }
+ }
+
+ ListView {
+ id: listView
+ model: visualModel
+ anchors.fill: parent
+ focus: true
+ }
+
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/requiredModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/requiredModelData.qml
new file mode 100644
index 0000000000..467d60dff8
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/requiredModelData.qml
@@ -0,0 +1,50 @@
+import QtQml
+
+DelegateModel {
+ id: root
+
+ property ListModel singularModel: ListModel {
+ ListElement {
+ a: "a"
+ }
+ ListElement {
+ a: "a"
+ }
+ }
+
+ property ListModel listModel: ListModel {
+ ListElement {
+ a: "a"
+ b: "b"
+ }
+ ListElement {
+ a: "a"
+ b: "b"
+ }
+ }
+
+ property var array: [
+ {a: "a", b: "b"}, {a: "b", b: "b"}
+ ]
+
+ property QtObject object: QtObject {
+ property string a: "a"
+ property string b: "b"
+ }
+
+ property int n: -1
+
+ model: {
+ switch (n) {
+ case 0: return singularModel
+ case 1: return listModel
+ case 2: return array
+ case 3: return object
+ }
+ return undefined;
+ }
+
+ delegate: QtObject {
+ required property string a
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/resetModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/resetModelData.qml
new file mode 100644
index 0000000000..1fe6168c79
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/resetModelData.qml
@@ -0,0 +1,16 @@
+import QtQuick
+
+ListView {
+ id: root
+ anchors.fill: parent
+ property bool success: (currentItem?.mydata ?? 0) === 42
+ height: 300
+ width: 200
+
+ delegate: Rectangle {
+ required property var model
+ implicitWidth: 100
+ implicitHeight: 50
+ property var mydata: model?.foo ?? model.bar
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/typedModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/typedModelData.qml
new file mode 100644
index 0000000000..08f1c7d68e
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/typedModelData.qml
@@ -0,0 +1,64 @@
+import QtQml
+
+DelegateModel {
+ id: root
+
+ // useful object as model, int as modelData
+ property ListModel singularModel: ListModel {
+ ListElement {
+ x: 11
+ }
+ ListElement {
+ x: 12
+ }
+ }
+
+ // same, useful, object as model and modelData
+ property ListModel listModel: ListModel {
+ ListElement {
+ x: 13
+ y: 14
+ }
+ ListElement {
+ x: 15
+ y: 16
+ }
+ }
+
+ // useful but different objects as modelData and model
+ // This is how the array accessor works. We can live with it.
+ property var array: [
+ {x: 17, y: 18}, {x: 19, y: 20}
+ ]
+
+ // useful but different objects as modelData and model
+ // This is how the object accessor works. We can live with it.
+ property QtObject object: QtObject {
+ property int x: 21
+ property int y: 22
+ }
+
+ property int n: -1
+
+ model: {
+ switch (n) {
+ case 0: return singularModel
+ case 1: return listModel
+ case 2: return array
+ case 3: return object
+ }
+ return undefined;
+ }
+
+ delegate: QtObject {
+ required property point modelData
+ required property QtObject model
+
+ property real modelX: model.x
+ property real modelDataX: modelData.x
+ property point modelSelf: model
+ property point modelDataSelf: modelData
+ property point modelModelData: model.modelData
+ property point modelAnonymous: model[""]
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/universalModelData.qml b/tests/auto/qml/qqmldelegatemodel/data/universalModelData.qml
new file mode 100644
index 0000000000..f24009f873
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/universalModelData.qml
@@ -0,0 +1,72 @@
+import QtQml
+
+DelegateModel {
+ id: root
+
+ // useful object as model, string as modelData
+ property ListModel singularModel: ListModel {
+ ListElement {
+ a: "a"
+ }
+ ListElement {
+ a: "b"
+ }
+ }
+
+ // same, useful, object as model and modelData
+ property ListModel listModel: ListModel {
+ ListElement {
+ a: "a"
+ b: "a"
+ }
+ ListElement {
+ a: "b"
+ b: "b"
+ }
+ }
+
+ // useful but different objects as modelData and model
+ // This is how the array accessor works. We can live with it.
+ property var array: [
+ {a: "a", b: "a"}, {a: "b", b: "a"}
+ ]
+
+ // string as modelData
+ // object with anonymous string property as model.
+ property var stringList: ["a", "b"]
+
+ // useful but different objects as modelData and model
+ // This is how the object accessor works. We can live with it.
+ property QtObject object: QtObject {
+ property string a: "a"
+ property string b: "a"
+ }
+
+ // number as modelData
+ // object with anonymous number property as model
+ property int n: -1
+
+ model: {
+ switch (n) {
+ case 0: return singularModel
+ case 1: return listModel
+ case 2: return array
+ case 3: return stringList
+ case 4: return object
+ case 5: return n
+ }
+ return undefined;
+ }
+
+ delegate: QtObject {
+ required property var modelData
+ required property var model
+
+ property var modelA: model.a
+ property var modelDataA: modelData.a
+ property var modelSelf: model
+ property var modelDataSelf: modelData
+ property var modelModelData: model.modelData
+ property var modelAnonymous: model[""]
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/data/viewUpdatedOnDelegateChoiceAffectingRoleChange.qml b/tests/auto/qml/qqmldelegatemodel/data/viewUpdatedOnDelegateChoiceAffectingRoleChange.qml
new file mode 100644
index 0000000000..b2367b3a6e
--- /dev/null
+++ b/tests/auto/qml/qqmldelegatemodel/data/viewUpdatedOnDelegateChoiceAffectingRoleChange.qml
@@ -0,0 +1,93 @@
+import QtQuick
+import Qt.labs.qmlmodels
+import QtQml.Models
+
+Item {
+ id: root
+ property bool triggered: false
+ onTriggeredChanged: {
+ rootLM.setProperty(1, "currentRole", "first");
+ }
+ width: 800
+ height: 680
+
+ function verify(): bool {
+ rootLV.currentIndex = 1; // needed for itemAtIndex to work
+ if (root.triggered)
+ return rootLV.itemAtIndex(0).isFirst && rootLV.itemAtIndex(1).isFirst;
+ else
+ return rootLV.itemAtIndex(0).isFirst && !rootLV.itemAtIndex(1).isFirst;
+ }
+
+ ListModel {
+ id: rootLM
+ ListElement {
+ currentRole: "first"
+ firstText: "TEXT_FIRST_1"
+ secondText: "TEXT_SECOND_1"
+ }
+ ListElement {
+ currentRole: "second"
+ firstText: "TEXT_FIRST_2"
+ secondText: "TEXT_SECOND_2"
+ }
+ }
+
+ DelegateModel {
+ id: delModel
+ model: rootLM
+ delegate: DelegateChooser {
+ id: delegateChooser
+ role: "currentRole"
+ DelegateChoice {
+ roleValue: "first"
+ Rectangle {
+ property bool isFirst: true
+ height: 30
+ width: rootLV.width
+ color: "yellow"
+ Text {
+ anchors.centerIn: parent
+ text: firstText + " " + currentRole
+ }
+ }
+ }
+ DelegateChoice {
+ roleValue: "second"
+ Rectangle {
+ property bool isFirst: false
+ height: 30
+ width: rootLV.width
+ color: "red"
+ Text {
+ anchors.centerIn: parent
+ text: secondText + " " + currentRole
+ }
+ }
+ }
+ }
+ }
+
+ TapHandler {
+ // for manual testing
+ onTapped: root.triggered = true
+ }
+
+ Rectangle {
+ width: 200
+ height: 300
+ anchors.centerIn: parent
+ border.color: "black"
+ border.width: 1
+ color: "blue"
+
+ ListView {
+ id: rootLV
+ objectName: "listview"
+ anchors.margins: 30
+ anchors.fill: parent
+ cacheBuffer: 0
+ model: delModel
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
index ca66ddb618..2cacda5513 100644
--- a/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
+++ b/tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp
@@ -1,16 +1,21 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
+#include <QtCore/qjsonobject.h>
#include <QtCore/QConcatenateTablesProxyModel>
#include <QtGui/QStandardItemModel>
#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlapplicationengine.h>
#include <QtQmlModels/private/qqmldelegatemodel_p.h>
+#include <QtQmlModels/private/qqmllistmodel_p.h>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtTest/QSignalSpy>
+#include <forward_list>
+
class tst_QQmlDelegateModel : public QQmlDataTest
{
Q_OBJECT
@@ -19,6 +24,7 @@ public:
tst_QQmlDelegateModel();
private slots:
+ void resettingRolesRespected();
void valueWithoutCallingObjectFirst_data();
void valueWithoutCallingObjectFirst();
void qtbug_86017();
@@ -26,6 +32,16 @@ private slots:
void contextAccessedByHandler();
void redrawUponColumnChange();
void nestedDelegates();
+ void universalModelData();
+ void typedModelData();
+ void requiredModelData();
+ void overriddenModelData();
+ void deleteRace();
+ void persistedItemsStayInCache();
+ void unknownContainersAsModel();
+ void doNotUnrefObjectUnderConstruction();
+ void clearCacheDuringInsertion();
+ void viewUpdatedOnDelegateChoiceAffectingRoleChange();
};
class AbstractItemModel : public QAbstractItemModel
@@ -85,6 +101,61 @@ tst_QQmlDelegateModel::tst_QQmlDelegateModel()
qmlRegisterType<AbstractItemModel>("Test", 1, 0, "AbstractItemModel");
}
+class TableModel : public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ int rowCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return 1;
+ }
+
+ int columnCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return 1;
+ }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ switch (role) {
+ case 0:
+ return QString("foo: %1, %2").arg(index.column()).arg(index.row());
+ case 1:
+ return 42;
+ default:
+ break;
+ }
+
+ return QVariant();
+ }
+
+ Q_INVOKABLE void change() { beginResetModel(); toggle = !toggle; endResetModel(); }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ if (toggle)
+ return { {0, "foo"} };
+ else
+ return { {1, "bar"} };
+ }
+
+ bool toggle = true;
+};
+
+void tst_QQmlDelegateModel::resettingRolesRespected()
+{
+ auto model = std::make_unique<TableModel>();
+ QQmlApplicationEngine engine;
+ engine.setInitialProperties({ {"model", QVariant::fromValue(model.get()) }} );
+ engine.load(testFileUrl("resetModelData.qml"));
+ QTRY_VERIFY(!engine.rootObjects().isEmpty());
+ QObject *root = engine.rootObjects().constFirst();
+ QVERIFY(!root->property("success").toBool());
+ model->change();
+ QTRY_VERIFY(root->property("success").toBool());
+}
+
void tst_QQmlDelegateModel::valueWithoutCallingObjectFirst_data()
{
QTest::addColumn<QUrl>("qmlFileUrl");
@@ -207,6 +278,344 @@ void tst_QQmlDelegateModel::nestedDelegates()
QFAIL("Loader not found");
}
+void tst_QQmlDelegateModel::universalModelData()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("universalModelData.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(o.data());
+ QVERIFY(delegateModel);
+
+ for (int i = 0; i < 6; ++i) {
+ delegateModel->setProperty("n", i);
+ QObject *delegate = delegateModel->object(0);
+ QObject *modelItem = delegate->property("modelSelf").value<QObject *>();
+ QVERIFY(modelItem != nullptr);
+ switch (i) {
+ case 0: {
+ // list model with 1 role
+ QCOMPARE(delegate->property("modelA"), QStringLiteral("a"));
+ QVERIFY(!delegate->property("modelDataA").isValid());
+ QCOMPARE(delegate->property("modelDataSelf"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelModelData"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelAnonymous"), QStringLiteral("a"));
+ break;
+ }
+ case 1: {
+ // list model with 2 roles
+ QCOMPARE(delegate->property("modelA"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelDataA"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelDataSelf"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelModelData"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelAnonymous"), QVariant::fromValue(modelItem));
+ break;
+ }
+ case 2: {
+ // JS array of objects
+ QCOMPARE(delegate->property("modelA"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelDataA"), QStringLiteral("a"));
+
+ // Do the comparison in QVariantMap. The values get converted back and forth a
+ // few times, making any JavaScript equality comparison impossible.
+ // This is only due to test setup, though.
+ const QVariantMap modelData = delegate->property("modelDataSelf").value<QVariantMap>();
+ QVERIFY(!modelData.isEmpty());
+ QCOMPARE(delegate->property("modelModelData").value<QVariantMap>(), modelData);
+ QCOMPARE(delegate->property("modelAnonymous").value<QVariantMap>(), modelData);
+ break;
+ }
+ case 3: {
+ // string list
+ QVERIFY(!delegate->property("modelA").isValid());
+ QVERIFY(!delegate->property("modelDataA").isValid());
+ QCOMPARE(delegate->property("modelDataSelf"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelModelData"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelAnonymous"), QStringLiteral("a"));
+ break;
+ }
+ case 4: {
+ // single object
+ QCOMPARE(delegate->property("modelA"), QStringLiteral("a"));
+ QCOMPARE(delegate->property("modelDataA"), QStringLiteral("a"));
+ QObject *modelData = delegate->property("modelDataSelf").value<QObject *>();
+ QVERIFY(modelData != nullptr);
+ QCOMPARE(delegate->property("modelModelData"), QVariant::fromValue(modelData));
+ QCOMPARE(delegate->property("modelAnonymous"), QVariant::fromValue(modelData));
+ break;
+ }
+ case 5: {
+ // a number
+ QVERIFY(!delegate->property("modelA").isValid());
+ QVERIFY(!delegate->property("modelDataA").isValid());
+ const QVariant modelData = delegate->property("modelDataSelf");
+
+ // This is int on 32bit systems because qsizetype fits into int there.
+ // On 64bit systems it's double because qsizetype doesn't fit into int.
+ if (sizeof(qsizetype) > sizeof(int))
+ QCOMPARE(modelData.metaType(), QMetaType::fromType<double>());
+ else
+ QCOMPARE(modelData.metaType(), QMetaType::fromType<int>());
+
+ QCOMPARE(modelData.value<int>(), 0);
+ QCOMPARE(delegate->property("modelModelData"), modelData);
+ QCOMPARE(delegate->property("modelAnonymous"), modelData);
+ break;
+ }
+ default:
+ QFAIL("wrong model number");
+ break;
+ }
+ }
+
+}
+
+void tst_QQmlDelegateModel::typedModelData()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("typedModelData.qml");
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(o.data());
+ QVERIFY(delegateModel);
+
+ for (int i = 0; i < 4; ++i) {
+ if (i == 0) {
+ for (int j = 0; j < 3; ++j) {
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Could not find any constructor for value type QQmlPointFValueType "
+ "to call with value QVariant(double, 11)");
+ }
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":62:9: Unable to assign double to QPointF"));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":61:9: Unable to assign double to QPointF"));
+ }
+
+ delegateModel->setProperty("n", i);
+ QObject *delegate = delegateModel->object(0);
+ QVERIFY(delegate);
+ const QPointF modelItem = delegate->property("modelSelf").value<QPointF>();
+ switch (i) {
+ case 0: {
+ // list model with 1 role.
+ // Does not work, for the most part, because the model is singular
+ QCOMPARE(delegate->property("modelX"), 11.0);
+ QCOMPARE(delegate->property("modelDataX"), 0.0);
+ QCOMPARE(delegate->property("modelSelf"), QPointF(11.0, 0.0));
+ QCOMPARE(delegate->property("modelDataSelf"), QPointF());
+ QCOMPARE(delegate->property("modelModelData"), QPointF());
+ QCOMPARE(delegate->property("modelAnonymous"), QPointF());
+ break;
+ }
+ case 1: {
+ // list model with 2 roles
+ QCOMPARE(delegate->property("modelX"), 13.0);
+ QCOMPARE(delegate->property("modelDataX"), 13.0);
+ QCOMPARE(delegate->property("modelSelf"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelDataSelf"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelModelData"), QVariant::fromValue(modelItem));
+ QCOMPARE(delegate->property("modelAnonymous"), QVariant::fromValue(modelItem));
+ break;
+ }
+ case 2: {
+ // JS array of objects
+ QCOMPARE(delegate->property("modelX"), 17.0);
+ QCOMPARE(delegate->property("modelDataX"), 17.0);
+
+ const QPointF modelData = delegate->property("modelDataSelf").value<QPointF>();
+ QCOMPARE(modelData, QPointF(17, 18));
+ QCOMPARE(delegate->property("modelSelf"), QVariant::fromValue(modelData));
+ QCOMPARE(delegate->property("modelModelData").value<QPointF>(), modelData);
+ QCOMPARE(delegate->property("modelAnonymous").value<QPointF>(), modelData);
+ break;
+ }
+ case 3: {
+ // single object
+ QCOMPARE(delegate->property("modelX"), 21);
+ QCOMPARE(delegate->property("modelDataX"), 21);
+ const QPointF modelData = delegate->property("modelDataSelf").value<QPointF>();
+ QCOMPARE(modelData, QPointF(21, 22));
+ QCOMPARE(delegate->property("modelSelf"), QVariant::fromValue(modelData));
+ QCOMPARE(delegate->property("modelModelData"), QVariant::fromValue(modelData));
+ QCOMPARE(delegate->property("modelAnonymous"), QVariant::fromValue(modelData));
+ break;
+ }
+ default:
+ QFAIL("wrong model number");
+ break;
+ }
+ }
+
+}
+
+void tst_QQmlDelegateModel::requiredModelData()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("requiredModelData.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(o.data());
+ QVERIFY(delegateModel);
+
+ for (int i = 0; i < 4; ++i) {
+ delegateModel->setProperty("n", i);
+ QObject *delegate = delegateModel->object(0);
+ QVERIFY(delegate);
+ const QVariant a = delegate->property("a");
+ QCOMPARE(a.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(a.toString(), QLatin1String("a"));
+ }
+}
+
+void tst_QQmlDelegateModel::overriddenModelData()
+{
+ QTest::failOnWarning(QRegularExpression(
+ "Final member [^ ]+ is overridden in class [^\\.]+. The override won't be used."));
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("overriddenModelData.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel *>(o.data());
+ QVERIFY(delegateModel);
+
+ for (int i = 0; i < 3; ++i) {
+ delegateModel->setProperty("n", i);
+ QObject *delegate = delegateModel->object(0);
+ QVERIFY(delegate);
+
+ if (i == 1 || i == 2) {
+ // You can actually not override if the model is a QObject or a JavaScript array.
+ // Someone is certainly relying on this.
+ // We need to find a migration mechanism to fix it.
+ QCOMPARE(delegate->objectName(), QLatin1String(" 0 0 e 0"));
+ } else {
+ QCOMPARE(delegate->objectName(), QLatin1String("a b c d e f"));
+ }
+ }
+}
+
+void tst_QQmlDelegateModel::deleteRace()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("deleteRace.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QTRY_COMPARE(o->property("count").toInt(), 2);
+ QTRY_COMPARE(o->property("count").toInt(), 0);
+}
+
+void tst_QQmlDelegateModel::persistedItemsStayInCache()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("persistedItemsCache.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object(component.create());
+ QVERIFY(object);
+ const QVariant properyListModel = object->property("testListModel");
+ QQmlListModel *listModel = qvariant_cast<QQmlListModel *>(properyListModel);
+ QVERIFY(listModel);
+ QTRY_COMPARE(object->property("createCount").toInt(), 3);
+ listModel->clear();
+ QTRY_COMPARE(object->property("destroyCount").toInt(), 3);
+}
+
+Q_DECLARE_SEQUENTIAL_CONTAINER_METATYPE(std::forward_list)
+void tst_QQmlDelegateModel::unknownContainersAsModel()
+{
+ QQmlEngine engine;
+
+ QQmlComponent modelComponent(&engine);
+ modelComponent.setData("import QtQml.Models\nDelegateModel {}\n", QUrl());
+ QCOMPARE(modelComponent.status(), QQmlComponent::Ready);
+
+ QScopedPointer<QObject> o(modelComponent.create());
+ QQmlDelegateModel *delegateModel = qobject_cast<QQmlDelegateModel*>(o.data());
+ QVERIFY(delegateModel);
+
+ QQmlComponent delegateComponent(&engine);
+ delegateComponent.setData("import QtQml\nQtObject { objectName: modelData }\n", QUrl());
+ QCOMPARE(delegateComponent.status(), QQmlComponent::Ready);
+
+ delegateModel->setDelegate(&delegateComponent);
+
+ QList<QJsonObject> json;
+ for (int i = 0; i < 10; ++i)
+ json.append(QJsonObject({{"foo", i}}));
+
+ // Recognized as list
+ delegateModel->setModel(QVariant::fromValue(json));
+ QObject *obj = delegateModel->object(0, QQmlIncubator::Synchronous);
+ QVERIFY(obj);
+ QCOMPARE(delegateModel->count(), 10);
+ QCOMPARE(delegateModel->model().metaType(), QMetaType::fromType<QList<QJsonObject>>());
+
+ QVERIFY(qMetaTypeId<std::forward_list<int>>() > 0);
+ std::forward_list<int> mess;
+ mess.push_front(4);
+ mess.push_front(5);
+ mess.push_front(6);
+
+ // Converted into QVariantList
+ delegateModel->setModel(QVariant::fromValue(mess));
+ obj = delegateModel->object(0, QQmlIncubator::Synchronous);
+ QVERIFY(obj);
+ QCOMPARE(delegateModel->count(), 3);
+ QCOMPARE(delegateModel->model().metaType(), QMetaType::fromType<QVariantList>());
+}
+
+void tst_QQmlDelegateModel::doNotUnrefObjectUnderConstruction()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("modifyObjectUnderConstruction.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object(component.create());
+ QVERIFY(object);
+ QTRY_COMPARE(object->property("testModel").toInt(), 0);
+}
+
+void tst_QQmlDelegateModel::clearCacheDuringInsertion()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("clearCacheDuringInsertion.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object(component.create());
+ QVERIFY(object);
+ QTRY_COMPARE(object->property("testModel").toInt(), 0);
+}
+
+void tst_QQmlDelegateModel::viewUpdatedOnDelegateChoiceAffectingRoleChange()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("viewUpdatedOnDelegateChoiceAffectingRoleChange.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object(component.create());
+ QVERIFY(object);
+ QQuickItem *listview = object->findChild<QQuickItem *>("listview");
+ QVERIFY(listview);
+ QTRY_VERIFY(listview->property("count").toInt() > 0);
+ bool returnedValue = false;
+ QMetaObject::invokeMethod(object.get(), "verify", Q_RETURN_ARG(bool, returnedValue));
+ QVERIFY(returnedValue);
+ returnedValue = false;
+
+ object->setProperty("triggered", "true");
+ QTRY_VERIFY(listview->property("count").toInt() > 0);
+ QMetaObject::invokeMethod(object.get(), "verify", Q_RETURN_ARG(bool, returnedValue));
+ QVERIFY(returnedValue);
+}
+
QTEST_MAIN(tst_QQmlDelegateModel)
#include "tst_qqmldelegatemodel.moc"
diff --git a/tests/auto/qml/qqmldirparser/CMakeLists.txt b/tests/auto/qml/qqmldirparser/CMakeLists.txt
index 0ed28b63ee..d7738c08f8 100644
--- a/tests/auto/qml/qqmldirparser/CMakeLists.txt
+++ b/tests/auto/qml/qqmldirparser/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmldirparser Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmldirparser LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmldirparser/data/versioned-internal/qmldir b/tests/auto/qml/qqmldirparser/data/versioned-internal/qmldir
new file mode 100644
index 0000000000..3a3e606099
--- /dev/null
+++ b/tests/auto/qml/qqmldirparser/data/versioned-internal/qmldir
@@ -0,0 +1,3 @@
+module MyModule
+internal InternalType 1.0 InternalType.qml
+
diff --git a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
index 55b776c6a2..4cbb7aaf47 100644
--- a/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
+++ b/tests/auto/qml/qqmldirparser/tst_qqmldirparser.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QObject>
@@ -60,7 +60,7 @@ namespace {
{
QStringList rv;
- foreach (const QQmlDirParser::Plugin &p, plugins)
+ for (const QQmlDirParser::Plugin &p : plugins)
rv.append(toString(p));
return rv;
@@ -86,7 +86,8 @@ namespace {
{
QStringList rv;
- foreach (const QQmlDirParser::Component &c, components.values())
+ const auto values = components.values();
+ for (const QQmlDirParser::Component &c : values)
rv.append(toString(c));
std::sort(rv.begin(), rv.end());
@@ -97,7 +98,7 @@ namespace {
{
QStringList rv;
- foreach (const QQmlDirParser::Import &c, components)
+ for (const QQmlDirParser::Import &c : components)
rv.append(toString(c));
std::sort(rv.begin(), rv.end());
@@ -115,7 +116,7 @@ namespace {
{
QStringList rv;
- foreach (const QQmlDirParser::Script &s, scripts)
+ for (const QQmlDirParser::Script &s : scripts)
rv.append(toString(s));
return rv;
@@ -421,6 +422,17 @@ void tst_qqmldirparser::parse_data()
<< QStringList()
<< QStringList()
<< false;
+
+ QTest::newRow("versioned-internal")
+ << "versioned-internal/qmldir"
+ << QString()
+ << QStringList()
+ << QStringList()
+ << QStringList()
+ << QStringList({"InternalType|InternalType.qml|1|0|true"})
+ << QStringList()
+ << QStringList()
+ << false;
}
void tst_qqmldirparser::parse()
@@ -435,7 +447,7 @@ void tst_qqmldirparser::parse()
QFETCH(bool, designerSupported);
QFile f(testFile(file));
- f.open(QIODevice::ReadOnly);
+ QVERIFY(f.open(QIODevice::ReadOnly));
QQmlDirParser p;
p.parse(f.readAll());
diff --git a/tests/auto/qml/qqmlecmascript/CMakeLists.txt b/tests/auto/qml/qqmlecmascript/CMakeLists.txt
index f4b4169c82..12cab47a36 100644
--- a/tests/auto/qml/qqmlecmascript/CMakeLists.txt
+++ b/tests/auto/qml/qqmlecmascript/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlecmascript Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlecmascript LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -24,6 +30,7 @@ qt_internal_add_test(tst_qqmlecmascript
Qt::Network
Qt::QmlPrivate
Qt::QuickTestUtilsPrivate
+ Qt::QuickPrivate
TESTDATA ${test_data}
)
diff --git a/tests/auto/qml/qqmlecmascript/data/AssignListPropertyByIndexOnGadget.qml b/tests/auto/qml/qqmlecmascript/data/AssignListPropertyByIndexOnGadget.qml
new file mode 100644
index 0000000000..f8ee283f1e
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/AssignListPropertyByIndexOnGadget.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+import Qt.test
+
+QtObject {
+ property listPropertyAssignment_Gadget gadget
+ property ListPropertyAssignment_Object object: ListPropertyAssignment_Object { }
+
+ Component.onCompleted: {
+ gadget.gadgetStringList = ["Element1", "Element2", "Element3"]
+ gadget.gadgetVariantList = [1, "foo", null, true]
+ object.qobjectStringList = ["Element1", "Element2", "Element3"]
+
+ gadget.gadgetStringList[0] = "Completely new Element"
+ gadget.gadgetVariantList[0] = "Completely new Element"
+ object.qobjectStringList[0] = "Completely new Element"
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml b/tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml
index 9273a52f54..ff7fe4434c 100644
--- a/tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml
+++ b/tests/auto/qml/qqmlecmascript/data/PropertyVarCircularComponent4.qml
@@ -22,7 +22,6 @@ Rectangle {
if (component.status == Component.Ready) {
text.vp = component.createObject(null); // has JavaScript ownership
}
- gc();
}
}
}
diff --git a/tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml b/tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml
index f4307081c5..4e8da872f5 100644
--- a/tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml
+++ b/tests/auto/qml/qqmlecmascript/data/PropertyVarOwnershipComponent.qml
@@ -25,7 +25,6 @@ Rectangle {
if (component.status == Component.Ready) {
textTwo.vp = component.createObject(null); // has JavaScript ownership
}
- gc();
}
function deassignVp() {
diff --git a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.3.qml b/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.3.qml
deleted file mode 100644
index d611e0fe30..0000000000
--- a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.3.qml
+++ /dev/null
@@ -1,12 +0,0 @@
-import QtQuick 2.0
-
-Item {
- property int changeCount: 0
-
- // invalid property name - we don't allow $
- property bool $nameWithDollarsign: false
-
- on$NameWithDollarsignChanged: {
- changeCount = changeCount + 4;
- }
-}
diff --git a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.4.qml b/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.4.qml
deleted file mode 100644
index a6862517c6..0000000000
--- a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlotErrors.4.qml
+++ /dev/null
@@ -1,12 +0,0 @@
-import QtQuick 2.0
-
-Item {
- property int changeCount: 0
-
- property bool _6nameWithUnderscoreNumber: false
-
- // invalid property name - the first character after an underscore must be a letter
- on_6NameWithUnderscoreNumberChanged: {
- changeCount = changeCount + 3;
- }
-}
diff --git a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml b/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml
index f91fb71f1f..9a3141e15a 100644
--- a/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml
+++ b/tests/auto/qml/qqmlecmascript/data/changeslots/propertyChangeSlots.qml
@@ -6,6 +6,8 @@ Item {
property bool normalName: false
property bool _nameWithUnderscore: false
property bool ____nameWithUnderscores: false
+ property bool _6nameWithUnderscoreNumber: false
+ property bool $nameWithDollarsign: false
onNormalNameChanged: {
changeCount = changeCount + 1;
@@ -19,9 +21,20 @@ Item {
changeCount = changeCount + 3;
}
+ on$NameWithDollarsignChanged: {
+ changeCount = changeCount + 4;
+ }
+
+ on_6NameWithUnderscoreNumberChanged: {
+ changeCount = changeCount + 5;
+ }
+
Component.onCompleted: {
normalName = true;
_nameWithUnderscore = true;
____nameWithUnderscores = true;
+ $nameWithDollarsign = true;
+ _6nameWithUnderscoreNumber = true;
}
+
}
diff --git a/tests/auto/qml/qqmlecmascript/data/date.qml b/tests/auto/qml/qqmlecmascript/data/date.qml
index 8e190b1f8f..33644b604d 100644
--- a/tests/auto/qml/qqmlecmascript/data/date.qml
+++ b/tests/auto/qml/qqmlecmascript/data/date.qml
@@ -26,8 +26,12 @@ Item {
function check_value(date, tag, qdt) {
var result = true;
+ if (isNaN(date)) {
+ console.warn("Invalid Date");
+ return false;
+ }
if (date.getFullYear() != 2014) {
- console.warn("Wrong year (" + tag + "):", date.getFullYear(), "!= 2014")
+ console.warn("Wrong year (" + tag + "):", date.getFullYear(), "!= 2014");
result = false;
}
// July; JS's months are Jan 0 to 11 Dec, vs. Qt's 1 to 12.
diff --git a/tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml b/tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml
new file mode 100644
index 0000000000..51c321684e
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/frozenQObject3.qml
@@ -0,0 +1,30 @@
+import QtQml
+import test
+
+QtObject {
+ id: root
+
+ property FrozenObjects a: FrozenObjects { objectName: "a" }
+ property FrozenObjects b: FrozenObjects { objectName: "b" }
+
+ // Create wrappers and immediately discard them
+ objectName: a.getConst().objectName + "/" + b.getNonConst().objectName
+
+ // Create a non-const wrapper and retain it
+ property var objNonConst: a.getNonConst()
+
+ // Create a const wrapper and retain it
+ property var objConst: b.getConst()
+
+ property int gcs: 0
+
+ property Timer t: Timer {
+ interval: 1
+ running: true
+ repeat: true
+ onTriggered: {
+ gc();
+ ++root.gcs;
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/getThis.qml b/tests/auto/qml/qqmlecmascript/data/getThis.qml
index db9854e872..90c51caf4d 100644
--- a/tests/auto/qml/qqmlecmascript/data/getThis.qml
+++ b/tests/auto/qml/qqmlecmascript/data/getThis.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.12
diff --git a/tests/auto/qml/qqmlecmascript/data/lookupsDoNotBypassProxy.qml b/tests/auto/qml/qqmlecmascript/data/lookupsDoNotBypassProxy.qml
new file mode 100644
index 0000000000..321bd21ad8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/lookupsDoNotBypassProxy.qml
@@ -0,0 +1,29 @@
+import QtQml
+
+QtObject {
+ function test_proxy() {
+ let base = {
+ id: 'baseid',
+ name: 'basename',
+ length: 42
+ };
+
+ let handler = {
+ get: function (ao, prop) {
+ return Reflect.get(ao, prop);
+ }
+ };
+
+ let r = new Proxy(base, handler);
+ let validCount = 0;
+ if (r.id === base.id)
+ ++validCount;
+ if (r.length === base.length)
+ ++validCount;
+ if (r.name === base.name)
+ ++validCount;
+ return validCount;
+ }
+
+ property int result: test_proxy()
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml b/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml
new file mode 100644
index 0000000000..9d2ee433fd
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/methodCallOnDerivedSingleton.qml
@@ -0,0 +1,6 @@
+import Qt.test
+import QtQml
+
+QtObject {
+ Component.onCompleted: SingletonInheritanceTest.trackPage("test", {x: 42})
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml b/tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml
index 6f5094de27..5f017c4880 100644
--- a/tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml
+++ b/tests/auto/qml/qqmlecmascript/data/propertyVar.reparent.qml
@@ -16,7 +16,6 @@ Item {
function assignVarProp() {
vp = constructGarbage();
- gc();
}
function deassignVarProp() {
diff --git a/tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml b/tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml
index ecc4892334..144fcc8a93 100644
--- a/tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml
+++ b/tests/auto/qml/qqmlecmascript/data/propertyVarImplicitOwnership.qml
@@ -16,7 +16,6 @@ Item {
function assignCircular() {
vp = constructGarbage();
- gc();
}
function deassignCircular() {
diff --git a/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs3.qml b/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs3.qml
new file mode 100644
index 0000000000..a50c8e0f46
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qmlTypeWrapperArgs3.qml
@@ -0,0 +1,12 @@
+import QtQml
+import Qt.test.singletonWithEnum
+
+QtObject {
+ id: root
+ required property QtObject invokableObject
+
+ Component.onCompleted: {
+ root.invokableObject.method_typeWrapper(Component)
+ root.invokableObject.method_typeWrapper(SingletonWithEnum)
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/qpropertyResetCorrectlyLinked.qml b/tests/auto/qml/qqmlecmascript/data/qpropertyResetCorrectlyLinked.qml
new file mode 100644
index 0000000000..490fec2dc8
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/qpropertyResetCorrectlyLinked.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item {
+ property var val: undefined
+ property var observes: width
+ width: val
+ implicitWidth: 200
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/resetGadget.qml b/tests/auto/qml/qqmlecmascript/data/resetGadget.qml
new file mode 100644
index 0000000000..2bc196da34
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/resetGadget.qml
@@ -0,0 +1,9 @@
+import Qt.test
+
+ResettableGadgetHolder {
+ id: root
+ property bool trigger: false
+ onTriggerChanged: {
+ root.g.value = undefined
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/restoreObserverAfterReset.qml b/tests/auto/qml/qqmlecmascript/data/restoreObserverAfterReset.qml
new file mode 100644
index 0000000000..2933d9b4d5
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/restoreObserverAfterReset.qml
@@ -0,0 +1,20 @@
+import QtQuick
+
+Item {
+ height: undefined
+ implicitHeight: 30
+ property int steps: 0
+
+ Behavior on height {
+ NumberAnimation {
+ duration: 500
+ }
+ }
+
+ onHeightChanged: ++steps
+
+ Component.onCompleted: {
+ height = Qt.binding(() => implicitHeight);
+ implicitHeight = 60;
+ }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml
new file mode 100644
index 0000000000..7d43aa6c05
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.8.qml
@@ -0,0 +1,21 @@
+import Qt.test
+import QtQuick
+
+Item {
+ id: root
+ property int count: 0
+ signal someSignal
+
+ property Item item: Item {
+ id: contextItem
+ function test() {
+ count++;
+ }
+ }
+
+ function itemDestroy() {
+ contextItem.destroy()
+ }
+
+ Component.onCompleted: root.someSignal.connect(contextItem, contextItem.test);
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml
new file mode 100644
index 0000000000..1123edf3f7
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.9.qml
@@ -0,0 +1,30 @@
+import Qt.test
+import QtQuick
+
+MyQmlObject {
+ id: root
+ property int a: 0
+
+ signal someSignal
+
+ function disconnectSignal() {
+ root.someSignal.disconnect(other.MyQmlObject, root.test)
+ }
+
+ function destroyObj() {
+ other.destroy()
+ }
+
+ function test() {
+ other.MyQmlObject.value2++
+ root.a = other.MyQmlObject.value2
+ }
+
+ property MyQmlObject obj
+ obj: MyQmlObject {
+ id: other
+ MyQmlObject.value2: 0
+ }
+
+ Component.onCompleted: root.someSignal.connect(other.MyQmlObject, root.test)
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml
new file mode 100644
index 0000000000..efbbc9fedc
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnect.deletion.qml
@@ -0,0 +1,36 @@
+import Qt.test
+import QtQml
+
+QtObject {
+ id: root
+
+ property int a: 0
+ property int b: 0
+
+ signal someSignal
+
+ function destroyObj() {
+ obj.destroy()
+ }
+
+ function test() {
+ ++a
+ }
+
+ component DestructionReceiver: QtObject {
+ // Has its own context and therefore can receive Component.onDestruction
+ }
+
+ property QtObject obj: QtObject {
+ property QtObject inner: DestructionReceiver {
+ Component.onDestruction: {
+ // The outer obj is already queued for deletion.
+ // We don't want to see this signal delivered.
+ root.someSignal();
+ ++root.b
+ }
+ }
+ }
+
+ Component.onCompleted: someSignal.connect(obj, test)
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml b/tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml
new file mode 100644
index 0000000000..f666945b33
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptConnectSingleton.qml
@@ -0,0 +1,21 @@
+import QtQuick
+import Test
+
+Item {
+ id: root
+
+ property int a: 0
+ signal mySignal
+
+ function test() {
+ MyInheritedQmlObjectSingleton.value++
+ root.a = MyInheritedQmlObjectSingleton.value
+ }
+
+ function disconnectSingleton() {
+ root.mySignal.disconnect(MyInheritedQmlObjectSingleton, root.test)
+ }
+
+ Component.onCompleted: root.mySignal.connect(MyInheritedQmlObjectSingleton,
+ root.test)
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml
new file mode 100644
index 0000000000..9d24fa85ae
--- /dev/null
+++ b/tests/auto/qml/qqmlecmascript/data/scriptDisconnect.5.qml
@@ -0,0 +1,19 @@
+import Qt.test
+import QtQuick
+
+Item {
+ id: root
+ property int count: 0
+ signal someSignal
+ signal disconnectSignal
+
+ property Item item: Item {
+ id: contextItem
+ function test() {
+ count++;
+ }
+ }
+
+ Component.onCompleted: root.someSignal.connect(contextItem, contextItem.test);
+ onDisconnectSignal: { root.someSignal.disconnect(contextItem, contextItem.test); }
+}
diff --git a/tests/auto/qml/qqmlecmascript/data/singletonTest.qml b/tests/auto/qml/qqmlecmascript/data/singletonTest.qml
index b0e951b89a..f4bdcdbed3 100644
--- a/tests/auto/qml/qqmlecmascript/data/singletonTest.qml
+++ b/tests/auto/qml/qqmlecmascript/data/singletonTest.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2013 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Test 1.0
diff --git a/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml b/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml
index 5a5bad5b8c..5d6af4d67c 100644
--- a/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml
+++ b/tests/auto/qml/qqmlecmascript/data/singletonTest2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2013 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Test 1.0
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.cpp b/tests/auto/qml/qqmlecmascript/testtypes.cpp
index 40f5e5cf5c..5f7713392b 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.cpp
+++ b/tests/auto/qml/qqmlecmascript/testtypes.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include "testtypes.h"
#ifndef QT_NO_WIDGETS
# include <QWidget>
@@ -8,6 +9,7 @@
#include <QQmlEngine>
#include <QJSEngine>
#include <QThread>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
class BaseExtensionObject : public QObject
{
@@ -104,7 +106,7 @@ public:
void setWidth(int) { }
};
-void MyQmlObject::v8function(QQmlV4Function *function)
+void MyQmlObject::v8function(QQmlV4FunctionPtr function)
{
function->v4engine()->throwError(QStringLiteral("Exception thrown from within QObject slot"));
}
@@ -393,9 +395,7 @@ void QObjectContainer::children_append(QQmlListProperty<QObject> *prop, QObject
if (that->gcOnAppend) {
QQmlEngine *engine = qmlEngine(that);
- engine->collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(*engine);
}
}
@@ -412,7 +412,7 @@ QObject *QObjectContainer::children_at(QQmlListProperty<QObject> *prop, qsizetyp
void QObjectContainer::children_clear(QQmlListProperty<QObject> *prop)
{
QObjectContainer *that = static_cast<QObjectContainer*>(prop->object);
- foreach (QObject *c, that->dataChildren)
+ for (QObject *c : std::as_const(that->dataChildren))
QObject::disconnect(c, SIGNAL(destroyed(QObject*)), that, SLOT(childDestroyed(QObject*)));
that->dataChildren.clear();
}
@@ -436,6 +436,44 @@ void ClassWithQProperty2::callback()
// Q_UNUSED(this->value.value()); // force evaluation
}
+ListPropertyAssignment_Gadget::ListPropertyAssignment_Gadget() { }
+
+QStringList ListPropertyAssignment_Gadget::gadgetStringList() const
+{
+ return m_gadgetStringList;
+}
+
+void ListPropertyAssignment_Gadget::setGadgetStringList(const QStringList &list)
+{
+ if (m_gadgetStringList == list)
+ return;
+ m_gadgetStringList = list;
+}
+
+QVariantList ListPropertyAssignment_Gadget::gadgetVariantList() const
+{
+ return m_gadgetVariantList;
+}
+
+void ListPropertyAssignment_Gadget::setGadgetVariantList(const QVariantList &list)
+{
+ if (m_gadgetVariantList == list)
+ return;
+ m_gadgetVariantList = list;
+}
+
+ListPropertyAssignment_Object::ListPropertyAssignment_Object(QObject *parent)
+ : QObject{ parent } { }
+
+void ListPropertyAssignment_Object::setQobjectStringList(const QStringList &newList)
+{
+ if (m_qobjectStringList == newList)
+ return;
+ m_qobjectStringList = newList;
+}
+
+bool MetaCallInterceptor::didGetObjectDestroyedCallback = false;
+
void registerTypes()
{
qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObjectAlias");
@@ -542,6 +580,15 @@ void registerTypes()
qmlRegisterType<Receiver>("Qt.test", 1,0, "Receiver");
qmlRegisterType<Sender>("Qt.test", 1,0, "Sender");
qmlRegisterTypesAndRevisions<ReadOnlyBindable>("Qt.test", 1);
+ qmlRegisterTypesAndRevisions<ResettableGadgetHolder>("Qt.test", 1);
+
+ qmlRegisterTypesAndRevisions<ListPropertyAssignment_Gadget>("Qt.test", 1);
+ qmlRegisterTypesAndRevisions<ListPropertyAssignment_Object>("Qt.test", 1);
+
+ qmlRegisterTypesAndRevisions<SingletonRegistrationWrapper>("Qt.test", 1);
+
+ qmlRegisterExtendedType<TypeWithCustomMetaObject, TypeToTriggerProxyMetaObject>(
+ "Qt.test", 1,0, "TypeWithCustomMetaObject");
}
#include "testtypes.moc"
diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h
index ff9dda36d1..cc20437fff 100644
--- a/tests/auto/qml/qqmlecmascript/testtypes.h
+++ b/tests/auto/qml/qqmlecmascript/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
@@ -31,6 +31,7 @@
#include <private/qqmlengine_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <private/qqmlcomponentattached_p.h>
class MyQmlAttachedObject : public QObject
{
@@ -243,7 +244,7 @@ public slots:
void myinvokable(MyQmlObject *o) { myinvokableObject = o; }
void variantMethod(const QVariant &v) { m_variant = v; }
void qjsvalueMethod(const QJSValue &v) { m_qjsvalue = v; }
- void v8function(QQmlV4Function*);
+ void v8function(QQmlV4FunctionPtr);
void registeredFlagMethod(Qt::MouseButtons v) { m_buttons = v; }
QString slotWithReturnValue(const QString &arg) { return arg; }
int resetCount() { return m_resetCount; }
@@ -862,6 +863,17 @@ struct NonRegisteredType
struct CompletelyUnknown;
+class SingletonWithEnum : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(TestEnum)
+public:
+ enum TestEnum {
+ TestValue = 42,
+ TestValue_MinusOne = -1
+ };
+};
+
class MyInvokableObject : public MyInvokableBaseObject
{
Q_OBJECT
@@ -919,7 +931,7 @@ public:
Q_INVOKABLE void method_unknown(NonRegisteredType) { invoke(28); }
- Q_INVOKABLE void method_overload2(QQmlV4Function *v)
+ Q_INVOKABLE void method_overload2(QQmlV4FunctionPtr v)
{
invoke(31);
QV4::Scope scope(v->v4engine());
@@ -955,12 +967,43 @@ public:
invoke(40);
m_actuals << f;
}
+
Q_INVOKABLE void method_qobject(QObject *o)
{
invoke(41);
m_actuals << QVariant::fromValue(o);
}
+ Q_INVOKABLE QQmlComponent *someComponent() { return &m_someComponent; }
+ Q_INVOKABLE void method_component(QQmlComponent *c)
+ {
+ invoke(42);
+ m_actuals << QVariant::fromValue(c);
+ }
+
+ Q_INVOKABLE MyTypeObject *someTypeObject() { return &m_someTypeObject; }
+ Q_INVOKABLE void method_component(MyTypeObject *c)
+ {
+ invoke(43);
+ m_actuals << QVariant::fromValue(c);
+ }
+
+ Q_INVOKABLE void method_component(const QUrl &c)
+ {
+ invoke(44);
+ m_actuals << QVariant::fromValue(c);
+ }
+
+ Q_INVOKABLE void method_typeWrapper(QQmlComponentAttached *attached)
+ {
+ m_actuals << QVariant::fromValue(attached);
+ }
+
+ Q_INVOKABLE void method_typeWrapper(SingletonWithEnum *singleton)
+ {
+ m_actuals << QVariant::fromValue(singleton);
+ }
+
private:
friend class MyInvokableBaseObject;
void invoke(int idx) { if (m_invoked != -1) m_invokedError = true; m_invoked = idx;}
@@ -969,6 +1012,8 @@ private:
QVariantList m_actuals;
QFont m_someFont;
+ QQmlComponent m_someComponent;
+ MyTypeObject m_someTypeObject;
public:
Q_SIGNALS:
@@ -1807,17 +1852,6 @@ public:
QML_DECLARE_TYPEINFO(FallbackBindingsTypeObject, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPEINFO(FallbackBindingsTypeDerived, QML_HAS_ATTACHED_PROPERTIES)
-class SingletonWithEnum : public QObject
-{
- Q_OBJECT
- Q_ENUMS(TestEnum)
-public:
- enum TestEnum {
- TestValue = 42,
- TestValue_MinusOne = -1
- };
-};
-
// Like QtObject, but with default property
class QObjectContainer : public QObject
{
@@ -2000,6 +2034,161 @@ public:
QBindable<int> bindableX() const { return &_xProp; }
};
+class ResettableGadget
+{
+ Q_GADGET
+ Q_PROPERTY(qreal value READ value WRITE setValue RESET resetValue)
+
+ qreal m_value = 0;
+
+public:
+ qreal value() const { return m_value; }
+ void setValue(qreal val) { m_value = val; }
+ void resetValue() { m_value = 42; }
+};
+
+class ResettableGadgetHolder : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(ResettableGadget g READ g WRITE setG NOTIFY gChanged)
+ ResettableGadget m_g;
+
+signals:
+ void gChanged();
+
+public:
+ ResettableGadget g() const { return m_g; }
+ void setG(ResettableGadget newG)
+ {
+ if (m_g.value() == newG.value())
+ return;
+ m_g = newG;
+ Q_EMIT gChanged();
+ }
+};
+
+class ListPropertyAssignment_Gadget
+{
+ Q_GADGET
+ Q_PROPERTY(QStringList gadgetStringList READ gadgetStringList WRITE setGadgetStringList)
+ Q_PROPERTY(QVariantList gadgetVariantList READ gadgetVariantList WRITE setGadgetVariantList)
+ QML_VALUE_TYPE(listPropertyAssignment_Gadget)
+public:
+ ListPropertyAssignment_Gadget();
+ QStringList gadgetStringList() const;
+ void setGadgetStringList(const QStringList &list);
+
+ QVariantList gadgetVariantList() const;
+ void setGadgetVariantList(const QVariantList &list);
+
+private:
+ QStringList m_gadgetStringList;
+ QVariantList m_gadgetVariantList;
+};
+
+class ListPropertyAssignment_Object : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(QStringList qobjectStringList READ qobjectStringList WRITE setQobjectStringList)
+public:
+ explicit ListPropertyAssignment_Object(QObject *parent = nullptr);
+
+ QStringList qobjectStringList() const { return m_qobjectStringList; }
+
+ void setQobjectStringList(const QStringList &newList);
+
+private:
+ QStringList m_qobjectStringList;
+};
+
+class SingletonBase : public QObject {
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE virtual void trackPage(const QString&) {}
+ Q_INVOKABLE virtual void trackPage(const QString&, const QVariantMap&) {}
+
+ bool m_okay = false;
+};
+
+class SingletonImpl : public SingletonBase {
+ Q_OBJECT
+
+public:
+ Q_INVOKABLE virtual void trackPage(const QString&) override {}
+ Q_INVOKABLE virtual void trackPage(const QString&, const QVariantMap&) override
+ {
+ m_okay = true;
+ }
+};
+
+class SingletonRegistrationWrapper {
+ Q_GADGET
+ QML_FOREIGN(SingletonBase)
+ QML_NAMED_ELEMENT(SingletonInheritanceTest)
+ QML_SINGLETON
+
+public:
+ static SingletonBase* create(QQmlEngine*, QJSEngine*) {
+ return new SingletonImpl();
+ }
+
+private:
+ SingletonRegistrationWrapper() = default;
+};
+
+class MetaCallInterceptor : public QObject, public QDynamicMetaObjectData
+{
+ Q_OBJECT
+public:
+ MetaCallInterceptor()
+ {
+ didGetObjectDestroyedCallback = false;
+ }
+
+ void objectDestroyed(QObject *object) override
+ {
+ didGetObjectDestroyedCallback = true;
+
+ // Deletes this meta object
+ QDynamicMetaObjectData::objectDestroyed(object);
+ }
+
+ QMetaObject *toDynamicMetaObject(QObject *) override
+ {
+ return const_cast<QMetaObject *>(&MetaCallInterceptor::staticMetaObject);
+ }
+
+ int metaCall(QObject *o, QMetaObject::Call call, int idx, void **argv) override
+ {
+ return o->qt_metacall(call, idx, argv);
+ }
+
+ static bool didGetObjectDestroyedCallback;
+};
+
+struct TypeToTriggerProxyMetaObject
+{
+ Q_GADGET
+};
+
+class TypeWithCustomMetaObject : public QObject
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(TypeWithCustomMetaObject)
+ QML_EXTENDED_NAMESPACE(TypeToTriggerProxyMetaObject)
+
+public:
+ TypeWithCustomMetaObject()
+ {
+ auto *p = QObjectPrivate::get(this);
+ Q_ASSERT(!p->metaObject);
+ p->metaObject = new MetaCallInterceptor;
+ }
+};
+
void registerTypes();
#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index edb1e9ba80..2d124da279 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2017 Crimson AS <info@crimson.no>
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <QtTest/QtTest>
#include <QtQml/qqmlcomponent.h>
#include <QtQml/qqmlengine.h>
@@ -27,6 +28,8 @@
#include <private/qqmlabstractbinding_p.h>
#include <private/qqmlvaluetypeproxybinding_p.h>
#include <QtCore/private/qproperty_p.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuick/private/qquickitem_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/testhttpserver_p.h>
@@ -376,6 +379,8 @@ private slots:
void qpropertyBindingHandlesUndefinedCorrectly();
void qpropertyBindingHandlesUndefinedWithoutResetCorrectly_data();
void qpropertyBindingHandlesUndefinedWithoutResetCorrectly();
+ void qpropertyBindingRestoresObserverAfterReset();
+ void qpropertyBindingObserverCorrectlyLinkedAfterReset();
void hugeRegexpQuantifiers();
void singletonTypeWrapperLookup();
void getThisObject();
@@ -396,6 +401,7 @@ private slots:
void sequenceConversionMethod();
void proxyIteration();
void proxyHandlerTraps();
+ void lookupsDoNotBypassProxy();
void gcCrashRegressionTest();
void cmpInThrows();
void frozenQObject();
@@ -416,6 +422,13 @@ private slots:
void doNotCrashOnReadOnlyBindable();
+ void resetGadget();
+ void assignListPropertyByIndexOnGadget();
+
+ void methodCallOnDerivedSingleton();
+
+ void proxyMetaObject();
+
private:
// static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
static void verifyContextLifetime(const QQmlRefPointer<QQmlContextData> &ctxt);
@@ -432,14 +445,6 @@ private:
}
};
-static void gc(QQmlEngine &engine)
-{
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
-}
-
-
tst_qqmlecmascript::tst_qqmlecmascript()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
@@ -3127,11 +3132,14 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->invoked(), -1);
QCOMPARE(o->actuals().size(), 0);
- o->reset();
- QVERIFY(EVALUATE_ERROR("object.method_QPointF(object)"));
- QCOMPARE(o->error(), false);
- QCOMPARE(o->invoked(), -1);
- QCOMPARE(o->actuals().size(), 0);
+ // This fails if the QtQml module is loaded but works if it's not.
+ // If QtQml is loaded, QPointF is a structured value type that can be created from any object.
+ //
+ // o->reset();
+ // QVERIFY(EVALUATE_ERROR("object.method_QPointF(object)"));
+ // QCOMPARE(o->error(), false);
+ // QCOMPARE(o->invoked(), -1);
+ // QCOMPARE(o->actuals().size(), 0);
o->reset();
QVERIFY(EVALUATE_VALUE("object.method_QPointF(object.method_get_QPointF())", QV4::Primitive::undefinedValue()));
@@ -3186,6 +3194,17 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->invoked(), -1); // no function got called due to incompatible arguments
}
+ {
+ o->reset();
+ QQmlComponent comp(&qmlengine, testFileUrl("qmlTypeWrapperArgs3.qml"));
+ QScopedPointer<QObject> root {comp.createWithInitialProperties({{"invokableObject", QVariant::fromValue(o)}}) };
+ QVERIFY(root);
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->actuals().size(), 2);
+ QCOMPARE(o->actuals().at(0).metaType(), QMetaType::fromType<QQmlComponentAttached *>());
+ QCOMPARE(o->actuals().at(1).metaType(), QMetaType::fromType<SingletonWithEnum *>());
+ }
+
o->reset();
QVERIFY(EVALUATE_VALUE("object.method_QObject(undefined)", QV4::Primitive::undefinedValue()));
QCOMPARE(o->error(), false);
@@ -3517,6 +3536,27 @@ void tst_qqmlecmascript::callQtInvokables()
QCOMPARE(o->error(), false);
QCOMPARE(o->invoked(), -1);
QCOMPARE(o->actuals(), QVariantList());
+
+ o->reset();
+ QVERIFY(EVALUATE_VALUE("object.method_component(object.someComponent())",
+ QV4::Primitive::undefinedValue()));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 42);
+ QCOMPARE(o->actuals(), QVariantList() << QVariant::fromValue(o->someComponent()));
+
+ o->reset();
+ QVERIFY(EVALUATE_VALUE("object.method_component(object.someTypeObject())",
+ QV4::Primitive::undefinedValue()));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 43);
+ QCOMPARE(o->actuals(), QVariantList() << QVariant::fromValue(o->someTypeObject()));
+
+ o->reset();
+ QVERIFY(EVALUATE_VALUE("object.method_component('qrc:/somewhere/else')",
+ QV4::Primitive::undefinedValue()));
+ QCOMPARE(o->error(), false);
+ QCOMPARE(o->invoked(), 44);
+ QCOMPARE(o->actuals(), QVariantList() << QVariant::fromValue(QUrl("qrc:/somewhere/else")));
}
void tst_qqmlecmascript::resolveClashingProperties()
@@ -3815,6 +3855,82 @@ void tst_qqmlecmascript::scriptConnect()
QScopedPointer<QObject> root { component.create() };
QVERIFY2(root, qPrintable(component.errorString()));
}
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnect.8.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ QCOMPARE(obj.data()->property("count"), 0);
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj.data()->property("count"), 1);
+
+ QMetaObject::invokeMethod(obj.data(), "itemDestroy");
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj.data()->property("count"), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnect.9.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(obj.data());
+
+ QCOMPARE(object->property("a"), 0);
+
+ QMetaObject::invokeMethod(object, "someSignal");
+ QCOMPARE(object->property("a"), 1);
+
+ QMetaObject::invokeMethod(object, "destroyObj", Qt::DirectConnection);
+ QApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ QApplication::processEvents();
+
+ QMetaObject::invokeMethod(object, "someSignal");
+
+ QCOMPARE(object->property("a"), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnectSingleton.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection);
+ QCOMPARE(obj.data()->property("a").toInt(), 1);
+ engine.clearSingletons();
+ QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection);
+ QCOMPARE(obj.data()->property("a").toInt(), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnect.deletion.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(!obj.isNull());
+
+ QCOMPARE(obj->property("a"), 0);
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj->property("a"), 1);
+
+ QCOMPARE(obj->property("b"), 0);
+ QMetaObject::invokeMethod(obj.data(), "destroyObj", Qt::DirectConnection);
+
+ QTRY_COMPARE(obj->property("b"), 1);
+ QCOMPARE(obj->property("a"), 1);
+ }
}
void tst_qqmlecmascript::scriptDisconnect()
@@ -3895,6 +4011,60 @@ void tst_qqmlecmascript::scriptDisconnect()
emit object->argumentSignal(19, "Hello world!", 10.25, MyQmlObject::EnumValue4, Qt::RightButton);
QCOMPARE(object->property("test").toInt(), 3);
}
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptDisconnect.5.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ QCOMPARE(obj.data()->property("count"), 0);
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj.data()->property("count"), 1);
+
+ QMetaObject::invokeMethod(obj.data(), "disconnectSignal");
+
+ QMetaObject::invokeMethod(obj.data(), "someSignal");
+ QCOMPARE(obj.data()->property("count"), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnect.9.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ MyQmlObject *object = qobject_cast<MyQmlObject *>(obj.data());
+
+ QCOMPARE(object->property("a"), 0);
+
+ QMetaObject::invokeMethod(object, "someSignal");
+ QCOMPARE(object->property("a"), 1);
+
+ QMetaObject::invokeMethod(object, "disconnectSignal", Qt::DirectConnection);
+
+ QMetaObject::invokeMethod(object, "someSignal");
+
+ QCOMPARE(object->property("a"), 1);
+ }
+
+ {
+ QQmlComponent component(&engine, testFileUrl("scriptConnectSingleton.qml"));
+
+ QScopedPointer<QObject> obj(component.create());
+ QVERIFY2(obj, qPrintable(component.errorString()));
+ QVERIFY(obj.data() != nullptr);
+
+ QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection);
+ QCOMPARE(obj.data()->property("a").toInt(), 1);
+
+ QMetaObject::invokeMethod(obj.data(), "disconnectSingleton", Qt::DirectConnection);
+ QMetaObject::invokeMethod(obj.data(), "mySignal", Qt::DirectConnection);
+ QCOMPARE(obj.data()->property("a").toInt(), 1);
+ }
}
class OwnershipObject : public QObject
@@ -3923,10 +4093,7 @@ void tst_qqmlecmascript::ownership()
QScopedPointer<QObject> object(component.create(context.data()));
- engine.collectGarbage();
-
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(own.object.isNull());
}
@@ -3940,10 +4107,7 @@ void tst_qqmlecmascript::ownership()
QScopedPointer<QObject> object(component.create(context.data()));
- engine.collectGarbage();
-
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(own.object != nullptr);
}
@@ -4019,9 +4183,7 @@ void tst_qqmlecmascript::ownershipCustomReturnValue()
QVERIFY(source.value != nullptr);
}
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(source.value.isNull());
}
@@ -4052,10 +4214,7 @@ void tst_qqmlecmascript::ownershipRootObject()
QScopedPointer<QObject> object(component.create(context.data()));
QVERIFY2(object, qPrintable(component.errorString()));
- engine.collectGarbage();
-
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(own.object != nullptr);
}
@@ -4080,10 +4239,7 @@ void tst_qqmlecmascript::ownershipConsistency()
QScopedPointer<QObject> object(component.create(context.data()));
QVERIFY2(object, qPrintable(component.errorString()));
- engine.collectGarbage();
-
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(engine);
QVERIFY(own.object != nullptr);
}
@@ -4613,6 +4769,7 @@ void tst_qqmlecmascript::verifyContextLifetime(const QQmlRefPointer<QQmlContextD
}
ctxt->engine()->collectGarbage();
+ QTRY_VERIFY(gcDone(ctxt->engine()));
qml = scripts->get(i);
newContext = qml ? qml->getContext() : nullptr;
QCOMPARE(scriptContext.data(), newContext.data());
@@ -5257,6 +5414,7 @@ void tst_qqmlecmascript::propertyChangeSlots()
QQmlComponent component(&engine, testFileUrl("changeslots/propertyChangeSlots.qml"));
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
+ QCOMPARE(object->property("changeCount"), 15);
// ensure that invalid property names fail properly.
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
@@ -5272,20 +5430,6 @@ void tst_qqmlecmascript::propertyChangeSlots()
QCOMPARE(e2.errors().at(0).toString(), expectedErrorString);
object.reset(e2.create());
QVERIFY(!object);
-
- QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- QQmlComponent e3(&engine, testFileUrl("changeslots/propertyChangeSlotErrors.3.qml"));
- expectedErrorString = e3.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on$NameWithDollarsignChanged\"");
- QCOMPARE(e3.errors().at(0).toString(), expectedErrorString);
- object.reset(e3.create());
- QVERIFY(!object);
-
- QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- QQmlComponent e4(&engine, testFileUrl("changeslots/propertyChangeSlotErrors.4.qml"));
- expectedErrorString = e4.url().toString() + QLatin1String(":9:5: Cannot assign to non-existent property \"on_6NameWithUnderscoreNumberChanged\"");
- QCOMPARE(e4.errors().at(0).toString(), expectedErrorString);
- object.reset(e4.create());
- QVERIFY(!object);
}
void tst_qqmlecmascript::propertyVar_data()
@@ -5453,7 +5597,9 @@ void tst_qqmlecmascript::propertyVarOwnership()
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
QMetaObject::invokeMethod(object.data(), "createComponent");
- engine.collectGarbage();
+ // This test only works if we don't deliver the pending delete later event
+ // that collectGarbage will post before calling runTest
+ gc(engine, GCFlags::DontSendPostedEvents);
QMetaObject::invokeMethod(object.data(), "runTest");
QCOMPARE(object->property("test").toBool(), true);
}
@@ -5469,8 +5615,7 @@ void tst_qqmlecmascript::propertyVarImplicitOwnership()
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
QMetaObject::invokeMethod(object.data(), "assignCircular");
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
- QCoreApplication::processEvents();
+ gc(engine);
QObject *rootObject = object->property("vp").value<QObject*>();
QVERIFY(rootObject != nullptr);
QObject *childObject = rootObject->findChild<QObject*>("text");
@@ -5479,6 +5624,8 @@ void tst_qqmlecmascript::propertyVarImplicitOwnership()
QCOMPARE(childObject->property("textCanary").toInt(), 10);
// Creates a reference to a constructed QObject:
QMetaObject::invokeMethod(childObject, "constructQObject");
+ // Don't send delete later events yet, we do it manually later
+ gc(engine, GCFlags::DontSendPostedEvents);
QPointer<QObject> qobjectGuard(childObject->property("vp").value<QObject*>()); // get the pointer prior to processing deleteLater events.
QVERIFY(!qobjectGuard.isNull());
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
@@ -5497,8 +5644,7 @@ void tst_qqmlecmascript::propertyVarReparent()
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
QMetaObject::invokeMethod(object.data(), "assignVarProp");
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
- QCoreApplication::processEvents();
+ gc(engine);
QObject *rect = object->property("vp").value<QObject*>();
QObject *text = rect->findChild<QObject*>("textOne");
QObject *text2 = rect->findChild<QObject*>("textTwo");
@@ -5512,6 +5658,7 @@ void tst_qqmlecmascript::propertyVarReparent()
QCOMPARE(text2->property("textCanary").toInt(), 12);
// now construct an image which we will reparent.
QMetaObject::invokeMethod(text2, "constructQObject");
+ gc(engine, GCFlags::DontSendPostedEvents);
QObject *image = text2->property("vp").value<QObject*>();
QPointer<QObject> imageGuard(image);
QVERIFY(!imageGuard.isNull());
@@ -5539,8 +5686,7 @@ void tst_qqmlecmascript::propertyVarReparentNullContext()
QScopedPointer<QObject> object(component.create());
QVERIFY2(object, qPrintable(component.errorString()));
QMetaObject::invokeMethod(object.data(), "assignVarProp");
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); // process deleteLater() events from QV8QObjectWrapper.
- QCoreApplication::processEvents();
+ gc(engine);
QObject *rect = object->property("vp").value<QObject*>();
QObject *text = rect->findChild<QObject*>("textOne");
QObject *text2 = rect->findChild<QObject*>("textTwo");
@@ -5554,6 +5700,7 @@ void tst_qqmlecmascript::propertyVarReparentNullContext()
QCOMPARE(text2->property("textCanary").toInt(), 12);
// now construct an image which we will reparent.
QMetaObject::invokeMethod(text2, "constructQObject");
+ gc(engine);
QObject *image = text2->property("vp").value<QObject*>();
QPointer<QObject> imageGuard(image);
QVERIFY(!imageGuard.isNull());
@@ -5780,9 +5927,7 @@ void tst_qqmlecmascript::handleReferenceManagement()
gc(hrmEngine);
QCOMPARE(dtorCount, 0); // second has JS ownership, kept alive by first's reference
object.reset();
- hrmEngine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(hrmEngine);
QCOMPARE(dtorCount, 3);
}
@@ -5799,9 +5944,7 @@ void tst_qqmlecmascript::handleReferenceManagement()
gc(hrmEngine);
QCOMPARE(dtorCount, 2); // both should be cleaned up, since circular references shouldn't keep alive.
object.reset();
- hrmEngine.collectGarbage();
- QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
+ gc(hrmEngine);
QCOMPARE(dtorCount, 3);
}
@@ -7892,7 +8035,7 @@ public:
void init(QV4::ExecutionEngine *v4, QV4::WeakValue *weakRef, bool *resultPtr)
{
- QV4::QObjectWrapper::wrap(v4, this);
+ (void) QV4::QObjectWrapper::wrap(v4, this); // Intentionally drop the wrapper
QQmlEngine::setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);
this->resultPtr = resultPtr;
@@ -7980,12 +8123,9 @@ void tst_qqmlecmascript::onDestructionViaGC()
v4->memoryManager->allocate<QV4::WeakReferenceSentinel>(weakRef.data(), &sentinelResult);
}
gc(engine);
-
+ QVERIFY2(weakRef->isNullOrUndefined(), "The weak value was not cleared");
QVERIFY2(mutatorResult, "We failed to re-assign the weak reference a new value during GC");
- QVERIFY2(!sentinelResult, "The weak value was cleared on first GC run");
- QVERIFY2(!weakRef->isNullOrUndefined(), "The weak value was cleared on first GC run");
- gc(engine);
- QVERIFY2(weakRef->isNullOrUndefined(), "The weak value was not cleared on second gc run");
+ QVERIFY2(sentinelResult, "The weak reference was not cleared properly");
}
struct EventProcessor : public QObject
@@ -8078,7 +8218,9 @@ void tst_qqmlecmascript::qqmldataDestroyed()
QVERIFY2(object, qPrintable(c.errorString()));
// now gc causing the collection of the dynamically constructed object.
engine.collectGarbage();
+ QTRY_VERIFY(gcDone(&engine));
engine.collectGarbage();
+ QTRY_VERIFY(gcDone(&engine));
// now process events to allow deletion (calling qqmldata::destroyed())
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
@@ -9389,6 +9531,32 @@ void tst_qqmlecmascript::qpropertyBindingHandlesUndefinedWithoutResetCorrectly()
QCOMPARE(root->property("value2").toInt(), 2);
}
+void tst_qqmlecmascript::qpropertyBindingRestoresObserverAfterReset()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("restoreObserverAfterReset.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QTRY_COMPARE(o->property("height").toDouble(), 60.0);
+ QVERIFY(o->property("steps").toInt() > 3);
+}
+
+void tst_qqmlecmascript::qpropertyBindingObserverCorrectlyLinkedAfterReset()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("qpropertyResetCorrectlyLinked.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ std::unique_ptr<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->property("width"), 200);
+ auto item = qobject_cast<QQuickItem *>(o.get());
+ auto itemPriv = QQuickItemPrivate::get(item);
+ QBindingStorage *storage = qGetBindingStorage(itemPriv);
+ QPropertyBindingDataPointer ptr { storage->bindingData(&itemPriv->width) };
+ QCOMPARE(ptr.observerCount(), 1);
+}
+
void tst_qqmlecmascript::hugeRegexpQuantifiers()
{
QJSEngine engine;
@@ -9987,6 +10155,17 @@ void tst_qqmlecmascript::proxyHandlerTraps()
QVERIFY(value.isString() && value.toString() == QStringLiteral("SUCCESS"));
}
+void tst_qqmlecmascript::lookupsDoNotBypassProxy()
+{
+ QQmlEngine engine;
+ // we need a component to have a proper compilation to byte code;
+ // otherwise, we don't actually end up with lookups
+ QQmlComponent comp(&engine, testFileUrl("lookupsDoNotBypassProxy.qml"));
+ QVERIFY(comp.isReady());
+ std::unique_ptr<QObject> obj { comp.create() };
+ QCOMPARE(obj->property("result").toInt(), 3);
+}
+
void tst_qqmlecmascript::cmpInThrows()
{
QJSEngine engine;
@@ -10027,6 +10206,9 @@ public:
Q_INVOKABLE void triggerSignal() { emit fooMember2Emitted(&m_fooMember2); }
+ Q_INVOKABLE const FrozenFoo *getConst() { return createFloating(); }
+ Q_INVOKABLE FrozenFoo *getNonConst() { return createFloating(); }
+
FrozenFoo *fooMember() { return &m_fooMember; }
FrozenFoo *fooMember2() { return &m_fooMember2; }
@@ -10036,6 +10218,16 @@ signals:
private:
const FrozenFoo *fooMemberConst() const { return &m_fooMember; }
+ FrozenFoo *createFloating()
+ {
+ if (!m_floating) {
+ m_floating = new FrozenFoo;
+ m_floating->setObjectName(objectName());
+ }
+ return m_floating;
+ }
+
+ FrozenFoo *m_floating = nullptr;
FrozenFoo m_fooMember;
FrozenFoo m_fooMember2;
};
@@ -10058,6 +10250,17 @@ void tst_qqmlecmascript::frozenQObject()
QVERIFY(frozenObjects->property("caughtSignal").toBool());
QCOMPARE(frozenObjects->fooMember()->name(), QStringLiteral("Jane"));
QCOMPARE(frozenObjects->fooMember2()->name(), QStringLiteral("Jane"));
+
+ QQmlComponent component3(&engine, testFileUrl("frozenQObject3.qml"));
+ QScopedPointer<QObject> root3(component3.create());
+ QCOMPARE(root3->objectName(), QLatin1String("a/b"));
+ QVERIFY(root3->property("objConst").value<QObject *>());
+ QVERIFY(root3->property("objNonConst").value<QObject *>());
+
+ QTRY_VERIFY(root3->property("gcs").toInt() > 8);
+
+ QVERIFY(root3->property("objConst").value<QObject *>());
+ QVERIFY(root3->property("objNonConst").value<QObject *>());
}
struct ConstPointer : QObject
@@ -10373,6 +10576,80 @@ void tst_qqmlecmascript::doNotCrashOnReadOnlyBindable()
QCOMPARE(o->property("x").toInt(), 7);
}
+void tst_qqmlecmascript::resetGadget()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("resetGadget.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ auto resettableGadgetHolder = qobject_cast<ResettableGadgetHolder *>(o.get());
+ QVERIFY(resettableGadgetHolder);
+ QCOMPARE(resettableGadgetHolder->g().value(), 0);
+ resettableGadgetHolder->setProperty("trigger", QVariant::fromValue(true));
+ QCOMPARE(resettableGadgetHolder->g().value(), 42);
+}
+
+void tst_qqmlecmascript::assignListPropertyByIndexOnGadget()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFile("AssignListPropertyByIndexOnGadget.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+
+ const auto &gadget = o->property("gadget").value<ListPropertyAssignment_Gadget>();
+ const auto *object = o->property("object").value<ListPropertyAssignment_Object *>();
+ QVERIFY(object);
+
+ QStringList expected{ "Completely new Element", "Element2", "Element3" };
+ QVariantList variants {
+ u"Completely new Element"_s,
+ u"foo"_s,
+ QVariant::fromValue<std::nullptr_t>(nullptr),
+ QVariant::fromValue<bool>(true)
+ };
+
+ QCOMPARE(gadget.gadgetStringList(), expected);
+ QCOMPARE(gadget.gadgetVariantList(), variants);
+ QCOMPARE(object->qobjectStringList(), expected);
+}
+
+void tst_qqmlecmascript::methodCallOnDerivedSingleton()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFile("methodCallOnDerivedSingleton.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ auto singleton = engine.singletonInstance<SingletonBase *>("Qt.test", "SingletonInheritanceTest");
+ QVERIFY(singleton);
+ QVERIFY(singleton->m_okay);
+}
+
+void tst_qqmlecmascript::proxyMetaObject()
+{
+ // Verify that TypeWithCustomMetaObject, that extends another type,
+ // thereby triggering a QQmlProxyMetaObject, is still proxied the
+ // QDynamicMetaObjectData::objectDestroyed callback.
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import QtQuick
+ import QtQml
+ import Qt.test
+ Rectangle {
+ TypeWithCustomMetaObject {}
+ }
+ )", QUrl("testData"));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o);
+ QVERIFY(!MetaCallInterceptor::didGetObjectDestroyedCallback);
+ o.reset(nullptr);
+ QVERIFY(MetaCallInterceptor::didGetObjectDestroyedCallback);
+}
+
QTEST_MAIN(tst_qqmlecmascript)
#include "tst_qqmlecmascript.moc"
diff --git a/tests/auto/qml/qqmlengine/CMakeLists.txt b/tests/auto/qml/qqmlengine/CMakeLists.txt
index 0869fe7ccc..9745f31bdb 100644
--- a/tests/auto/qml/qqmlengine/CMakeLists.txt
+++ b/tests/auto/qml/qqmlengine/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlengine Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlengine LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -34,6 +40,7 @@ qt_add_qml_module(tst_qqmlengine_qml
SOURCES
"declarativelyregistered.h"
"declarativelyregistered.cpp"
+ "variantlistQJsonConversion.h"
RESOURCE_PREFIX
"/"
OUTPUT_DIRECTORY
diff --git a/tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml b/tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml
new file mode 100644
index 0000000000..596ab10ee7
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/bindingInstallUseAfterFree.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Item {
+ visible: false
+
+ property int test: 1
+
+ Component {
+ id: comp
+ Item {
+ width: { width = test * 100 }
+ }
+ }
+
+ Loader {
+ sourceComponent: comp
+ width: 100
+ }
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml
new file mode 100644
index 0000000000..3be706ee29
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/Main.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string s: SingletonA.name
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml
new file mode 100644
index 0000000000..dc3bfd23fd
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonA.qml
@@ -0,0 +1,11 @@
+pragma Singleton
+import QtQuick
+
+Item {
+ readonly property string name: "SingletonA"
+
+ readonly property TestItem itemA: TestItem{}
+
+ property TestItem crossRef: SingletonB.itemB
+ property int testItemInt: crossRef.i
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml
new file mode 100644
index 0000000000..7f0335ee89
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/SingletonB.qml
@@ -0,0 +1,11 @@
+pragma Singleton
+import QtQuick
+
+Item {
+ readonly property string name: "SingletonB"
+
+ readonly property TestItem itemB: TestItem{}
+
+ property TestItem crossRef: SingletonA.itemA
+ property int testItemInt: crossRef.i
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml
new file mode 100644
index 0000000000..81d931f14c
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/TestItem.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int i: 3
+}
diff --git a/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir
new file mode 100644
index 0000000000..8bf691d10d
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/crossReferencingSingletonsDeletion/Module/qmldir
@@ -0,0 +1,3 @@
+module Module
+singleton SingletonA 1.0 SingletonA.qml
+singleton SingletonB 1.0 SingletonB.qml
diff --git a/tests/auto/qml/qqmlengine/data/markCurrentFunctionAsTranslationBinding.qml b/tests/auto/qml/qqmlengine/data/markCurrentFunctionAsTranslationBinding.qml
new file mode 100644
index 0000000000..a16e9c483f
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/markCurrentFunctionAsTranslationBinding.qml
@@ -0,0 +1,7 @@
+import QtQml
+import i18ntest
+
+QtObject {
+ property I18nAware aware: I18nAware {}
+ property string result: aware.text
+}
diff --git a/tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs b/tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs
index fd1080fccb..8f5bdde82a 100644
--- a/tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs
+++ b/tests/auto/qml/qqmlengine/data/nativeModuleImport.mjs
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import { name } from "info.mjs";
diff --git a/tests/auto/qml/qqmlengine/data/nativeModuleImport.qml b/tests/auto/qml/qqmlengine/data/nativeModuleImport.qml
index ae51210944..ffcb0e42ce 100644
--- a/tests/auto/qml/qqmlengine/data/nativeModuleImport.qml
+++ b/tests/auto/qml/qqmlengine/data/nativeModuleImport.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml
diff --git a/tests/auto/qml/qqmlengine/data/variantListQJsonConversion.qml b/tests/auto/qml/qqmlengine/data/variantListQJsonConversion.qml
new file mode 100644
index 0000000000..fd0820a3c5
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/data/variantListQJsonConversion.qml
@@ -0,0 +1,18 @@
+import QtQuick
+import OnlyDeclarative
+
+Item {
+
+ MiscUtils {
+ id: miscUtils
+ }
+
+ Component.onCompleted: {
+ const varlist = miscUtils.createVariantList();
+ const obj = { test: varlist };
+ const listProperty = miscUtils.createQmlListProperty();
+ miscUtils.logArray(varlist);
+ miscUtils.logObject(obj);
+ miscUtils.logArray(listProperty);
+ }
+}
diff --git a/tests/auto/qml/qqmlengine/declarativelyregistered.cpp b/tests/auto/qml/qqmlengine/declarativelyregistered.cpp
index 9893fa0311..4a469c4795 100644
--- a/tests/auto/qml/qqmlengine/declarativelyregistered.cpp
+++ b/tests/auto/qml/qqmlengine/declarativelyregistered.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "declarativelyregistered.h"
diff --git a/tests/auto/qml/qqmlengine/declarativelyregistered.h b/tests/auto/qml/qqmlengine/declarativelyregistered.h
index 98f7250d76..edb783e3aa 100644
--- a/tests/auto/qml/qqmlengine/declarativelyregistered.h
+++ b/tests/auto/qml/qqmlengine/declarativelyregistered.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DECLARATIVELYREGISTERED_H
#define DECLARATIVELYREGISTERED_H
diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
index 895513d822..3c25d29dfb 100644
--- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
+++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QQmlEngine>
#include <QQmlContext>
@@ -36,8 +36,10 @@ public:
private slots:
void initTestCase() override;
void rootContext();
+#if QT_CONFIG(qml_network)
void networkAccessManager();
void synchronousNetworkAccessManager();
+#endif
void baseUrl();
void contextForObject();
void offlineStoragePath();
@@ -67,6 +69,7 @@ private slots:
void cachedGetterLookup_qtbug_75335();
void createComponentOnSingletonDestruction();
void uiLanguage();
+ void markCurrentFunctionAsTranslationBinding();
void executeRuntimeFunction();
void captureQProperty();
void listWrapperAsListReference();
@@ -77,6 +80,9 @@ private slots:
void qtNamespaceInQtObject();
void nativeModuleImport();
void lockedRootObject();
+ void crossReferencingSingletonsDeletion();
+ void bindingInstallUseAfterFree();
+ void variantListQJsonConversion();
public slots:
QObject *createAQObjectForOwnershipTest ()
@@ -149,6 +155,7 @@ void tst_qqmlengine::rootContext()
QVERIFY(!engine.rootContext()->parentContext());
}
+#if QT_CONFIG(qml_network)
class NetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory
{
public:
@@ -164,21 +171,19 @@ public:
void tst_qqmlengine::networkAccessManager()
{
- QQmlEngine *engine = new QQmlEngine;
+ std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>();
// Test QQmlEngine created manager
QPointer<QNetworkAccessManager> manager = engine->networkAccessManager();
QVERIFY(manager != nullptr);
- delete engine;
// Test factory created manager
- engine = new QQmlEngine;
+ engine.reset(new QQmlEngine);
NetworkAccessManagerFactory factory;
engine->setNetworkAccessManagerFactory(&factory);
QCOMPARE(engine->networkAccessManagerFactory(), &factory);
QNetworkAccessManager *engineNam = engine->networkAccessManager(); // calls NetworkAccessManagerFactory::create()
QCOMPARE(engineNam, factory.manager);
- delete engine;
}
class ImmediateReply : public QNetworkReply {
@@ -226,7 +231,7 @@ void tst_qqmlengine::synchronousNetworkAccessManager()
// reply is finished, so should not be in loading state.
QVERIFY(!c.isLoading());
}
-
+#endif
void tst_qqmlengine::baseUrl()
{
@@ -267,7 +272,7 @@ void tst_qqmlengine::baseUrl()
void tst_qqmlengine::contextForObject()
{
- QQmlEngine *engine = new QQmlEngine;
+ std::unique_ptr<QQmlEngine> engine = std::make_unique<QQmlEngine>();
// Test null-object
QVERIFY(!QQmlEngine::contextForObject(nullptr));
@@ -294,7 +299,7 @@ void tst_qqmlengine::contextForObject()
QCOMPARE(QQmlEngine::contextForObject(&object), engine->rootContext());
// Delete context
- delete engine; engine = nullptr;
+ engine.reset();
QVERIFY(!QQmlEngine::contextForObject(&object));
}
@@ -372,10 +377,9 @@ void tst_qqmlengine::clearComponentCache()
// Test "test" property
{
QQmlComponent component(&engine, fileUrl);
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get() != nullptr);
QCOMPARE(obj->property("test").toInt(), 10);
- delete obj;
}
// Modify qml file
@@ -395,10 +399,9 @@ void tst_qqmlengine::clearComponentCache()
// Test cache hit
{
QQmlComponent component(&engine, fileUrl);
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get() != nullptr);
QCOMPARE(obj->property("test").toInt(), 10);
- delete obj;
}
// Clear cache
@@ -407,10 +410,9 @@ void tst_qqmlengine::clearComponentCache()
// Test cache refresh
{
QQmlComponent component(&engine, fileUrl);
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get() != nullptr);
QCOMPARE(obj->property("test").toInt(), 11);
- delete obj;
}
// Regular Synchronous loading will leave us with an event posted
@@ -437,7 +439,7 @@ public:
// There might be JS function objects around that hold a last ref to the compilation unit that's
// keeping the type compilation data (CompilationUnit) around. Let's collect them as well so that
// trim works well.
- engine->collectGarbage();
+ gc(*engine);
engine->trimComponentCache();
}
@@ -496,22 +498,25 @@ void tst_qqmlengine::trimComponentCache_data()
// empty apart from their inherited elements, and those that define new properties.
// For each there are five types of composition: extension, aggregation,
// aggregation via component, property and object-created-via-transient-component.
- foreach (const QString &test, (QStringList() << "EmptyComponent"
- << "VMEComponent"
- << "EmptyExtendEmptyComponent"
- << "VMEExtendEmptyComponent"
- << "EmptyExtendVMEComponent"
- << "VMEExtendVMEComponent"
- << "EmptyAggregateEmptyComponent"
- << "VMEAggregateEmptyComponent"
- << "EmptyAggregateVMEComponent"
- << "VMEAggregateVMEComponent"
- << "EmptyPropertyEmptyComponent"
- << "VMEPropertyEmptyComponent"
- << "EmptyPropertyVMEComponent"
- << "VMEPropertyVMEComponent"
- << "VMETransientEmptyComponent"
- << "VMETransientVMEComponent")) {
+ const QStringList components = {
+ "EmptyComponent",
+ "VMEComponent",
+ "EmptyExtendEmptyComponent",
+ "VMEExtendEmptyComponent",
+ "EmptyExtendVMEComponent",
+ "VMEExtendVMEComponent",
+ "EmptyAggregateEmptyComponent",
+ "VMEAggregateEmptyComponent",
+ "EmptyAggregateVMEComponent",
+ "VMEAggregateVMEComponent",
+ "EmptyPropertyEmptyComponent",
+ "VMEPropertyEmptyComponent",
+ "EmptyPropertyVMEComponent",
+ "VMEPropertyVMEComponent",
+ "VMETransientEmptyComponent",
+ "VMETransientVMEComponent",
+ };
+ for (const QString &test : components) {
// For these cases, we first test that the component instance keeps the components
// referenced, and then that the instantiated object keeps the components referenced
for (int i = 1; i <= 2; ++i) {
@@ -903,7 +908,7 @@ void tst_qqmlengine::qtqmlModule()
QFETCH(QString, expectedError);
QFETCH(QStringList, expectedWarnings);
- foreach (const QString &w, expectedWarnings)
+ for (const QString &w : std::as_const(expectedWarnings))
QTest::ignoreMessage(QtWarningMsg, qPrintable(w));
QQmlEngine e;
@@ -1272,9 +1277,9 @@ void tst_qqmlengine::singletonInstance()
{
// deleted object
- auto dayfly = new Dayfly{};
- auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly);
- delete dayfly;
+ auto dayfly = std::make_unique<Dayfly>();
+ auto id = qmlRegisterSingletonInstance("Vanity", 1, 0, "Dayfly", dayfly.get());
+ dayfly.reset();
QTest::ignoreMessage(QtMsgType::QtWarningMsg, "<Unknown File>: The registered singleton has already been deleted. Ensure that it outlives the engine.");
QObject *instance = engine.singletonInstance<QObject*>(id);
QVERIFY(!instance);
@@ -1378,6 +1383,35 @@ void tst_qqmlengine::uiLanguage()
}
}
+class I18nAwareClass : public QObject {
+ Q_OBJECT
+ QML_NAMED_ELEMENT(I18nAware)
+
+ Q_PROPERTY(QString text READ text NOTIFY textChanged)
+signals:
+ void textChanged();
+public:
+ int counter = 0;
+
+ QString text()
+ {
+ if (auto engine = qmlEngine(this))
+ engine->markCurrentFunctionAsTranslationBinding();
+ return QLatin1String("Hello, %1").arg(QString::number(counter++));
+ }
+};
+
+void tst_qqmlengine::markCurrentFunctionAsTranslationBinding()
+{
+ QQmlEngine engine;
+ qmlRegisterTypesAndRevisions<I18nAwareClass>("i18ntest", 1);
+ QQmlComponent comp(&engine, testFileUrl("markCurrentFunctionAsTranslationBinding.qml"));
+ std::unique_ptr<QObject> root { comp.create() };
+ QCOMPARE(root->property("result"), "Hello, 0");
+ engine.retranslate();
+ QCOMPARE(root->property("result"), "Hello, 1");
+}
+
void tst_qqmlengine::executeRuntimeFunction()
{
QQmlEngine engine;
@@ -1683,6 +1717,42 @@ void tst_qqmlengine::lockedRootObject()
QCOMPARE(o->property("defineProperty2").toBool(), false);
}
+void tst_qqmlengine::crossReferencingSingletonsDeletion()
+{
+ QQmlEngine engine;
+ engine.addImportPath(testFileUrl("crossReferencingSingletonsDeletion").url());
+ QQmlComponent c(&engine, testFileUrl("crossReferencingSingletonsDeletion/Module/Main.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ std::unique_ptr<QObject> o{ c.create() };
+ QVERIFY(o);
+ QCOMPARE(o->property("s").toString(), "SingletonA");
+}
+
+void tst_qqmlengine::bindingInstallUseAfterFree()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("bindingInstallUseAfterFree.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ std::unique_ptr<QObject> o{ c.create() };
+ QVERIFY(o);
+}
+
+void tst_qqmlengine::variantListQJsonConversion()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("variantListQJsonConversion.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, R"(["cpp","variant","list"])");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg, R"({"test":["cpp","variant","list"]})");
+ QTest::ignoreMessage(QtMsgType::QtDebugMsg,
+ R"([{"objectName":"o0"},{"objectName":"o1"},{"objectName":"o2"}])");
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+}
+
QTEST_MAIN(tst_qqmlengine)
#include "tst_qqmlengine.moc"
diff --git a/tests/auto/qml/qqmlengine/variantlistQJsonConversion.h b/tests/auto/qml/qqmlengine/variantlistQJsonConversion.h
new file mode 100644
index 0000000000..edf2174a18
--- /dev/null
+++ b/tests/auto/qml/qqmlengine/variantlistQJsonConversion.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef VARIANTLIST_QJSON_CONVERSION_HPP
+#define VARIANTLIST_QJSON_CONVERSION_HPP
+
+#include "qqmlintegration.h"
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QObject>
+#include <QJsonDocument>
+#include <QDebug>
+#include <private/qjsvalue_p.h>
+#include <private/qqmllistwrapper_p.h>
+#include <private/qv4engine_p.h>
+#include <private/qv4jsonobject_p.h>
+
+class MiscUtils : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ Q_INVOKABLE QVariantList createVariantList() const
+ {
+ return { QString("cpp"), QString("variant"), QString("list") };
+ }
+
+ Q_INVOKABLE QQmlListProperty<QObject> createQmlListProperty()
+ {
+ QV4::ExecutionEngine engine(qmlEngine(this));
+ static QObject objects[] = { QObject{}, QObject{}, QObject{} };
+ objects[0].setObjectName("o0");
+ objects[1].setObjectName("o1");
+ objects[2].setObjectName("o2");
+ static QList<QObject *> list{ &objects[0], &objects[1], &objects[2] };
+ return QQmlListProperty<QObject>(this, &list);
+ }
+
+ Q_INVOKABLE void logArray(const QJsonArray &arr) const
+ {
+ const auto str = QString(QJsonDocument(arr).toJson(QJsonDocument::Compact));
+ qDebug().noquote() << str;
+ }
+
+ Q_INVOKABLE void logObject(const QJsonObject &obj) const
+ {
+ const auto str = QString(QJsonDocument(obj).toJson(QJsonDocument::Compact));
+ qDebug().noquote() << str;
+ }
+};
+
+#endif // VARIANTLIST_QJSON_CONVERSION_HPP
diff --git a/tests/auto/qml/qqmlenginecleanup/CMakeLists.txt b/tests/auto/qml/qqmlenginecleanup/CMakeLists.txt
index d91fc98f8a..87b0874774 100644
--- a/tests/auto/qml/qqmlenginecleanup/CMakeLists.txt
+++ b/tests/auto/qml/qqmlenginecleanup/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlenginecleanup Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlenginecleanup LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml
index 6dfe0d52e8..083e8f2e7c 100644
--- a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml
+++ b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/ModuleType.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.12
diff --git a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp
index c53f9e674b..52ab367d10 100644
--- a/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp
+++ b/tests/auto/qml/qqmlenginecleanup/CustomModuleImport/moduleplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/qml/qqmlenginecleanup/data/TestType.qml b/tests/auto/qml/qqmlenginecleanup/data/TestType.qml
index 9f98ec971f..0699ac894f 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/TestType.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/TestType.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.0
QtObject{property int notJustAStandardQtObject: 10 }
diff --git a/tests/auto/qml/qqmlenginecleanup/data/testFile1.qml b/tests/auto/qml/qqmlenginecleanup/data/testFile1.qml
index 5298dea961..233684633f 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/testFile1.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/testFile1.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlenginecleanup/data/testFile2.qml b/tests/auto/qml/qqmlenginecleanup/data/testFile2.qml
index 0bd2c54e16..02d231d375 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/testFile2.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/testFile2.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlenginecleanup/data/testFile3.qml b/tests/auto/qml/qqmlenginecleanup/data/testFile3.qml
index be95e2ff74..10e2b2888a 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/testFile3.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/testFile3.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlenginecleanup/data/types.qml b/tests/auto/qml/qqmlenginecleanup/data/types.qml
index f726a37404..4de1e6e43d 100644
--- a/tests/auto/qml/qqmlenginecleanup/data/types.qml
+++ b/tests/auto/qml/qqmlenginecleanup/data/types.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.0
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
index c9049c7ca4..04e8389c87 100644
--- a/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
+++ b/tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QObject>
#include <QtQml/qqml.h>
@@ -47,8 +47,8 @@ public:
void tst_qqmlenginecleanup::test_qmlClearTypeRegistrations()
{
//Test for preventing memory leaks is in tests/manual/qmltypememory
- QQmlEngine* engine;
- CleanlyLoadingComponent* component;
+ std::unique_ptr<QQmlEngine> engine;
+ std::unique_ptr<CleanlyLoadingComponent> component;
QUrl testFile = testFileUrl("types.qml");
const auto qmlTypeForTestType = []() {
@@ -60,12 +60,12 @@ void tst_qqmlenginecleanup::test_qmlClearTypeRegistrations()
qmlRegisterType<QObject>("Test", 2, 0, "TestTypeCpp");
QVERIFY(qmlTypeForTestType().isValid());
- engine = new QQmlEngine;
- component = new CleanlyLoadingComponent(engine, testFile);
+ engine = std::make_unique<QQmlEngine>();
+ component = std::make_unique<CleanlyLoadingComponent>(engine.get(), testFile);
QVERIFY(component->isReady());
- delete component;
- delete engine;
+ component.reset();
+ engine.reset();
{
auto cppType = qmlTypeForTestType();
@@ -81,24 +81,21 @@ void tst_qqmlenginecleanup::test_qmlClearTypeRegistrations()
//2nd run verifies that types can reload after a qmlClearTypeRegistrations
qmlRegisterType<QObject>("Test", 2, 0, "TestTypeCpp");
QVERIFY(qmlTypeForTestType().isValid());
- engine = new QQmlEngine;
- component = new CleanlyLoadingComponent(engine, testFile);
+ engine = std::make_unique<QQmlEngine>();
+ component = std::make_unique<CleanlyLoadingComponent>(engine.get(), testFile);
QVERIFY(component->isReady());
- delete component;
- delete engine;
+ component.reset();
+ engine.reset();
qmlClearTypeRegistrations();
QVERIFY(!qmlTypeForTestType().isValid());
//3nd run verifies that TestTypeCpp is no longer registered
- engine = new QQmlEngine;
- component = new CleanlyLoadingComponent(engine, testFile);
+ engine = std::make_unique<QQmlEngine>();
+ component = std::make_unique<CleanlyLoadingComponent>(engine.get(), testFile);
QVERIFY(component->isError());
QCOMPARE(component->errorString(),
testFile.toString() +":8 module \"Test\" is not installed\n");
-
- delete component;
- delete engine;
}
static void cleanState(QQmlEngine **e)
diff --git a/tests/auto/qml/qqmlerror/CMakeLists.txt b/tests/auto/qml/qqmlerror/CMakeLists.txt
index be85347051..11b084e88d 100644
--- a/tests/auto/qml/qqmlerror/CMakeLists.txt
+++ b/tests/auto/qml/qqmlerror/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlerror Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlerror LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp b/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
index b0e8846e59..d4d483fb27 100644
--- a/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
+++ b/tests/auto/qml/qqmlerror/tst_qqmlerror.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlError>
diff --git a/tests/auto/qml/qqmlexpression/CMakeLists.txt b/tests/auto/qml/qqmlexpression/CMakeLists.txt
index 79dccd484d..6adb01b3b1 100644
--- a/tests/auto/qml/qqmlexpression/CMakeLists.txt
+++ b/tests/auto/qml/qqmlexpression/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlexpression Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlexpression LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
index 71c186f3e4..59023391cd 100644
--- a/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
+++ b/tests/auto/qml/qqmlexpression/tst_qqmlexpression.cpp
@@ -1,11 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
-#include <QtQml/qqmlengine.h>
-#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlexpression.h>
+#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlscriptstring.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -20,6 +21,7 @@ private slots:
void syntaxError();
void exception();
void expressionFromDataComponent();
+ void emptyScriptString();
};
class TestObject : public QObject
@@ -121,6 +123,36 @@ void tst_qqmlexpression::expressionFromDataComponent()
QCOMPARE(result.toString(), QStringLiteral("success"));
}
+void tst_qqmlexpression::emptyScriptString()
+{
+ QQmlEngine engine;
+ QQmlContext *context = engine.rootContext();
+ QVERIFY(context);
+ QVERIFY(context->isValid());
+
+ QQmlScriptString empty;
+ QVERIFY(empty.isEmpty());
+
+ QQmlExpression expression(empty, context, this);
+ QCOMPARE(expression.context(), context);
+ QCOMPARE(expression.scopeObject(), this);
+ QCOMPARE(expression.expression(), QString());
+
+ const QVariant result = expression.evaluate();
+ QVERIFY(!result.isValid());
+
+ QQmlComponent c(&engine, testFileUrl("scriptString.qml"));
+ std::unique_ptr<QObject> root { c.create() };
+ TestObject *testObj = qobject_cast<TestObject*>(root.get());
+ QVERIFY(testObj != nullptr);
+
+ QQmlScriptString script = testObj->scriptString();
+ QVERIFY(!script.isEmpty());
+
+ // verify that comparing against an empty script string does not crash
+ QVERIFY(script != empty);
+}
+
QTEST_MAIN(tst_qqmlexpression)
#include "tst_qqmlexpression.moc"
diff --git a/tests/auto/qml/qqmlextensionplugin/CMakeLists.txt b/tests/auto/qml/qqmlextensionplugin/CMakeLists.txt
index de108af085..4a32e3a0e4 100644
--- a/tests/auto/qml/qqmlextensionplugin/CMakeLists.txt
+++ b/tests/auto/qml/qqmlextensionplugin/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlextensionplugin Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlextensionplugin LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlextensionplugin
SOURCES
tst_qqmlextensionplugin.cpp
diff --git a/tests/auto/qml/qqmlextensionplugin/data/dummy.qml b/tests/auto/qml/qqmlextensionplugin/data/dummy.qml
index f8169bd6aa..e555405535 100644
--- a/tests/auto/qml/qqmlextensionplugin/data/dummy.qml
+++ b/tests/auto/qml/qqmlextensionplugin/data/dummy.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
diff --git a/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
index b8e0b01f6d..5f299f7b91 100644
--- a/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
+++ b/tests/auto/qml/qqmlextensionplugin/tst_qqmlextensionplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore>
#include <QtTest>
@@ -75,7 +75,7 @@ void tst_qqmlextensionplugin::iidCheck_data()
files = removeDuplicates(std::move(files));
QTest::addColumn<QString>("filePath");
- foreach (const QString &file, files) {
+ for (const QString &file: std::as_const(files)) {
QFileInfo fileInfo(file);
QTest::newRow(fileInfo.baseName().toLatin1().data()) << fileInfo.absoluteFilePath();
}
diff --git a/tests/auto/qml/qqmlfile/CMakeLists.txt b/tests/auto/qml/qqmlfile/CMakeLists.txt
index c573b53b1a..d8e23f410c 100644
--- a/tests/auto/qml/qqmlfile/CMakeLists.txt
+++ b/tests/auto/qml/qqmlfile/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlfile Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlfile LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlfile
SOURCES
tst_qqmlfile.cpp
diff --git a/tests/auto/qml/qqmlfile/tst_qqmlfile.cpp b/tests/auto/qml/qqmlfile/tst_qqmlfile.cpp
index 3f75a14bf6..3ce87ce048 100644
--- a/tests/auto/qml/qqmlfile/tst_qqmlfile.cpp
+++ b/tests/auto/qml/qqmlfile/tst_qqmlfile.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore>
#include <QtTest>
diff --git a/tests/auto/qml/qqmlfileselector/CMakeLists.txt b/tests/auto/qml/qqmlfileselector/CMakeLists.txt
index d169ffc607..b3dec0ff3d 100644
--- a/tests/auto/qml/qqmlfileselector/CMakeLists.txt
+++ b/tests/auto/qml/qqmlfileselector/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlfileselector Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlfileselector LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml
index d6dd2c9b90..4e09798a84 100644
--- a/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/main.qml
@@ -1,10 +1,8 @@
import QtQuick
import qmldirtest
-Window {
- width: 640
- height: 480
- visible: true
+Item {
+ objectName: Name.name
property color color: mybutton.color
MyButton {
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/Name.js
new file mode 100644
index 0000000000..91ca4f129d
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+linux/Name.js
@@ -0,0 +1 @@
+var name = "linux"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/Name.js
new file mode 100644
index 0000000000..12e5058285
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/+macos/Name.js
@@ -0,0 +1 @@
+var name = "macos"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/Name.js
new file mode 100644
index 0000000000..916a232eb4
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qml/Name.js
@@ -0,0 +1 @@
+var name = "base"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir
index ac68d9097d..a2efdbf27d 100644
--- a/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest/qmldir
@@ -2,4 +2,7 @@ module qmldirtest
MyButton 1.0 qml/MyButton.qml
MyButton 1.0 qml/+linux/MyButton.qml
MyButton 1.0 qml/+macos/MyButton.qml
+Name 1.0 qml/Name.js
+Name 1.0 qml/+linux/Name.js
+Name 1.0 qml/+macos/Name.js
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/MyButton.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/MyButton.qml
new file mode 100644
index 0000000000..5bf632c48d
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/MyButton.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 50
+ color: "yellow"
+}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/Name.js
new file mode 100644
index 0000000000..8591795d37
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+bar/Name.js
@@ -0,0 +1 @@
+var name = "bar"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/MyButton.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/MyButton.qml
new file mode 100644
index 0000000000..cc6eb967da
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/MyButton.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 50
+ color: "blue"
+}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/Name.js
new file mode 100644
index 0000000000..b224ed15ec
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/+foo/Name.js
@@ -0,0 +1 @@
+var name = "foo"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/MyButton.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/MyButton.qml
new file mode 100644
index 0000000000..32db428c4f
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/MyButton.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 50
+ color: "green"
+}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/Name.js b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/Name.js
new file mode 100644
index 0000000000..916a232eb4
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/Name.js
@@ -0,0 +1 @@
+var name = "base"
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/main.qml b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/main.qml
new file mode 100644
index 0000000000..5fb8afc660
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/main.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ objectName: Name.name
+ property color color: mybutton.color
+ MyButton {
+ id: mybutton
+ }
+}
diff --git a/tests/auto/qml/qqmlfileselector/data/qmldirtest2/qmldir b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/qmldir
new file mode 100644
index 0000000000..92fefb9806
--- /dev/null
+++ b/tests/auto/qml/qqmlfileselector/data/qmldirtest2/qmldir
@@ -0,0 +1,5 @@
+module qmldirtest2
+MyButton 1.0 +foo/MyButton.qml
+MyButton 1.0 MyButton.qml
+MyButton 1.0 +bar/MyButton.qml
+Name 1.0 Name.js
diff --git a/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp b/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp
index 46df20378c..98774ffe64 100644
--- a/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp
+++ b/tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 BlackBerry Limited. All rights reserved.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -32,11 +32,9 @@ void tst_qqmlfileselector::basicTest()
selector.setExtraSelectors(QStringList() << "basic");
QQmlComponent component(&engine, testFileUrl("basicTest.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toString(), QString("selected"));
-
- delete object;
}
void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
@@ -72,19 +70,38 @@ void tst_qqmlfileselector::applicationEngineTest()
void tst_qqmlfileselector::qmldirCompatibility()
{
- QQmlApplicationEngine engine;
- engine.addImportPath(dataDirectory());
- engine.load(testFileUrl("qmldirtest/main.qml"));
- QVERIFY(!engine.rootObjects().isEmpty());
- QObject *object = engine.rootObjects().at(0);
- auto color = object->property("color").value<QColor>();
+ {
+ // No error for multiple files with different selectors, and the matching one is chosen
+ // for +macos and +linux selectors.
+ QQmlApplicationEngine engine;
+ engine.addImportPath(dataDirectory());
+ engine.load(testFileUrl("qmldirtest/main.qml"));
+ QVERIFY(!engine.rootObjects().isEmpty());
+ QObject *object = engine.rootObjects().at(0);
+ auto color = object->property("color").value<QColor>();
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
- QCOMPARE(color, QColorConstants::Svg::blue);
+ QCOMPARE(object->objectName(), "linux");
+ QCOMPARE(color, QColorConstants::Svg::blue);
#elif defined(Q_OS_DARWIN)
- QCOMPARE(color, QColorConstants::Svg::yellow);
+ QCOMPARE(object->objectName(), "macos");
+ QCOMPARE(color, QColorConstants::Svg::yellow);
#else
- QCOMPARE(color, QColorConstants::Svg::green);
+ QCOMPARE(object->objectName(), "base");
+ QCOMPARE(color, QColorConstants::Svg::green);
#endif
+ }
+
+ {
+ // If nothing matches, the _base_ file is chosen, not the first or the last one.
+ // This also holds when using the implicit import.
+ QQmlApplicationEngine engine;
+ engine.addImportPath(dataDirectory());
+ engine.load(testFileUrl("qmldirtest2/main.qml"));
+ QVERIFY(!engine.rootObjects().isEmpty());
+ QObject *object = engine.rootObjects().at(0);
+ QCOMPARE(object->property("color").value<QColor>(), QColorConstants::Svg::green);
+ QCOMPARE(object->objectName(), "base");
+ }
}
QTEST_MAIN(tst_qqmlfileselector)
diff --git a/tests/auto/qml/qqmlglobal/CMakeLists.txt b/tests/auto/qml/qqmlglobal/CMakeLists.txt
index ff57005dc3..ce600c7607 100644
--- a/tests/auto/qml/qqmlglobal/CMakeLists.txt
+++ b/tests/auto/qml/qqmlglobal/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlglobal Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlglobal LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlglobal
SOURCES
tst_qqmlglobal.cpp
diff --git a/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp b/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
index 81d61976a3..884ea180a9 100644
--- a/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
+++ b/tests/auto/qml/qqmlglobal/tst_qqmlglobal.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <qqml.h>
diff --git a/tests/auto/qml/qqmlimport/CMakeLists.txt b/tests/auto/qml/qqmlimport/CMakeLists.txt
index 32aeec0966..b8b720f5dc 100644
--- a/tests/auto/qml/qqmlimport/CMakeLists.txt
+++ b/tests/auto/qml/qqmlimport/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlimport Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlimport LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -29,6 +35,7 @@ qt_internal_add_test(tst_qqmlimport
SOURCES
tst_qqmlimport.cpp
LIBRARIES
+ Qt::CorePrivate
Qt::Gui
Qt::Qml
Qt::QmlPrivate
@@ -44,6 +51,21 @@ qt_internal_add_resource(tst_qqmlimport "preferred"
"Preferred.qml"
)
+qt_internal_add_resource(tst_qqmlimport "preferred2"
+ PREFIX
+ "/qqmlimport/ModuleWithPrefer2/"
+ FILES
+ "Preferred.qml"
+ "qmldir"
+)
+
+qt_internal_add_resource(tst_qqmlimport "qtconf"
+ PREFIX
+ "/"
+ FILES
+ "qmlimports.qt.conf"
+)
+
## Scopes:
#####################################################################
diff --git a/tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml b/tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml
index 943ce3309f..960b9b474b 100644
--- a/tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml
+++ b/tests/auto/qml/qqmlimport/MyPluginSupported/MyItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml b/tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml
index 943ce3309f..960b9b474b 100644
--- a/tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml
+++ b/tests/auto/qml/qqmlimport/MyPluginUnsupported/MyItem.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/Preferred.qml b/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/Preferred.qml
new file mode 100644
index 0000000000..a4af255b56
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/Preferred.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ objectName: "wrong"
+}
diff --git a/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/qmldir b/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/qmldir
new file mode 100644
index 0000000000..6b04c0eb5f
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/ModuleWithPrefer2/qmldir
@@ -0,0 +1,3 @@
+module ModuleWithPrefer2
+prefer :/qqmlimport/ModuleWithPrefer2/
+Preferred 1.0 Preferred.qml
diff --git a/tests/auto/qml/qqmlimport/data/MyModuleName/Font.js b/tests/auto/qml/qqmlimport/data/MyModuleName/Font.js
new file mode 100644
index 0000000000..7036c0a739
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/MyModuleName/Font.js
@@ -0,0 +1,4 @@
+.pragma library
+.import QtQuick as QtQuick
+
+var exampleVar = 12;
diff --git a/tests/auto/qml/qqmlimport/data/MyModuleName/qmldir b/tests/auto/qml/qqmlimport/data/MyModuleName/qmldir
new file mode 100644
index 0000000000..43add34163
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/MyModuleName/qmldir
@@ -0,0 +1,2 @@
+module MyModuleName
+Font 0.1 Font.js
diff --git a/tests/auto/qml/qqmlimport/data/fileDotSlashImport.qml b/tests/auto/qml/qqmlimport/data/fileDotSlashImport.qml
new file mode 100644
index 0000000000..83dbd566f3
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/fileDotSlashImport.qml
@@ -0,0 +1,6 @@
+import QtQml
+import 'file://./MyModuleName' as MyModuleName
+
+QtObject {
+ objectName: MyModuleName.Font.exampleVar
+}
diff --git a/tests/auto/qml/qqmlimport/data/noimport/Main.qml b/tests/auto/qml/qqmlimport/data/noimport/Main.qml
new file mode 100644
index 0000000000..d473b43d7b
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/noimport/Main.qml
@@ -0,0 +1,5 @@
+pragma Strict
+
+TheThing {
+ width: 640
+}
diff --git a/tests/auto/qml/qqmlimport/data/noimport/qmldir b/tests/auto/qml/qqmlimport/data/noimport/qmldir
new file mode 100644
index 0000000000..3034edba51
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/noimport/qmldir
@@ -0,0 +1,3 @@
+module noimport
+Main 1.0 Main.qml
+
diff --git a/tests/auto/qml/qqmlimport/data/prefer2.qml b/tests/auto/qml/qqmlimport/data/prefer2.qml
new file mode 100644
index 0000000000..c0727dc13d
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/prefer2.qml
@@ -0,0 +1,3 @@
+import ModuleWithPrefer2
+
+Pickles {}
diff --git a/tests/auto/qml/qqmlimport/data/qualifiedScriptImport.qml b/tests/auto/qml/qqmlimport/data/qualifiedScriptImport.qml
new file mode 100644
index 0000000000..de4b02afbb
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/data/qualifiedScriptImport.qml
@@ -0,0 +1,8 @@
+import QtQuick
+import 'MyModuleName' as MyModuleName
+
+Item {
+ property var a: MyModuleName.Font.exampleVar
+ property var b: Font.SmallCaps
+ property var c: Font.exampleVar
+}
diff --git a/tests/auto/qml/qqmlimport/data/testfile_supported.qml b/tests/auto/qml/qqmlimport/data/testfile_supported.qml
index eb4995bacf..dc20a91d06 100644
--- a/tests/auto/qml/qqmlimport/data/testfile_supported.qml
+++ b/tests/auto/qml/qqmlimport/data/testfile_supported.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import MyPluginSupported 1.0
diff --git a/tests/auto/qml/qqmlimport/data/testfile_unsupported.qml b/tests/auto/qml/qqmlimport/data/testfile_unsupported.qml
index 81156f1624..38ad7ad258 100644
--- a/tests/auto/qml/qqmlimport/data/testfile_unsupported.qml
+++ b/tests/auto/qml/qqmlimport/data/testfile_unsupported.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import MyPluginUnsupported 1.0
diff --git a/tests/auto/qml/qqmlimport/qmldir b/tests/auto/qml/qqmlimport/qmldir
new file mode 100644
index 0000000000..ca29b16cfb
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/qmldir
@@ -0,0 +1,2 @@
+module ModuleWithPrefer2
+Pickles 1.0 Preferred.qml
diff --git a/tests/auto/qml/qqmlimport/qmlimports.qt.conf b/tests/auto/qml/qqmlimport/qmlimports.qt.conf
new file mode 100644
index 0000000000..3a63cc797f
--- /dev/null
+++ b/tests/auto/qml/qqmlimport/qmlimports.qt.conf
@@ -0,0 +1,3 @@
+[Paths]
+Prefix = ""
+QmlImports = ":/a/path", ":/another/path", ":/even/more/path"
diff --git a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
index 38970a3b99..fe14281387 100644
--- a/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
+++ b/tests/auto/qml/qqmlimport/tst_qqmlimport.cpp
@@ -1,23 +1,50 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <private/qmlutils_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qqmlimport_p.h>
-#include <QtCore/qscopeguard.h>
-#include <QtTest/QtTest>
-#include <QQmlApplicationEngine>
-#include <QQmlAbstractUrlInterceptor>
#include <QtQuick/qquickview.h>
#include <QtQuick/qquickitem.h>
-#include <private/qqmlimport_p.h>
-#include <private/qqmlengine_p.h>
-#include <QtQuickTestUtils/private/qmlutils_p.h>
-#include <QQmlComponent>
+
+#include <QtTest/qsignalspy.h>
+
+#include <QtQml/qqmlabstracturlinterceptor.h>
+#include <QtQml/qqmlapplicationengine.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlmoduleregistration.h>
+
+#include <QtCore/qscopeguard.h>
+#include <QtCore/qlibraryinfo.h>
+#include <QtCore/private/qlibraryinfo_p.h>
+
+class TheThing : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(int width MEMBER m_width FINAL)
+
+public:
+ int m_width = 12;
+};
+
+void qml_register_types_noimport()
+{
+ qmlRegisterTypesAndRevisions<TheThing>("noimport", 1);
+ qmlRegisterModule("noimport", 1, 0);
+}
class tst_QQmlImport : public QQmlDataTest
{
Q_OBJECT
public:
- tst_QQmlImport();
+ tst_QQmlImport()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+ , noimportRegistration("noimport", qml_register_types_noimport)
+ {
+ }
private slots:
void importPathOrder();
@@ -34,10 +61,18 @@ private slots:
void importDependenciesPrecedence();
void cleanup();
void envResourceImportPath();
+ void preferResourcePath_data();
void preferResourcePath();
void invalidFileImport_data();
void invalidFileImport();
void implicitWithDependencies();
+ void qualifiedScriptImport();
+ void invalidImportUrl();
+ void registerTypesFromImplicitImport();
+ void containsAllQtConfEntries();
+
+private:
+ QQmlModuleRegistration noimportRegistration;
};
void tst_QQmlImport::cleanup()
@@ -72,12 +107,21 @@ void tst_QQmlImport::envResourceImportPath()
QVERIFY((importPaths.contains(path.startsWith(u':') ? QLatin1String("qrc") + path : path)));
}
+void tst_QQmlImport::preferResourcePath_data()
+{
+ QTest::addColumn<QUrl>("file");
+ QTest::addRow("without qmldir") << testFileUrl("prefer.qml");
+ QTest::addRow("with qmldir") << testFileUrl("prefer2.qml");
+}
+
void tst_QQmlImport::preferResourcePath()
{
+ QFETCH(QUrl, file);
+
QQmlEngine engine;
engine.addImportPath(dataDirectory());
- QQmlComponent component(&engine, testFileUrl("prefer.qml"));
+ QQmlComponent component(&engine, file);
QVERIFY2(component.isReady(), component.errorString().toUtf8());
QScopedPointer<QObject> o(component.create());
QCOMPARE(o->objectName(), "right");
@@ -123,9 +167,62 @@ void tst_QQmlImport::implicitWithDependencies()
QCOMPARE(o->objectName(), QStringLiteral("notARectangle"));
}
+void tst_QQmlImport::qualifiedScriptImport()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("qualifiedScriptImport.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("a"), QVariant::fromValue<double>(12));
+ QCOMPARE(o->property("b"), QVariant::fromValue<int>(3));
+ QCOMPARE(o->property("c"), QVariant());
+}
+
+void tst_QQmlImport::invalidImportUrl()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("fileDotSlashImport.qml");
+ QQmlComponent component(&engine, url);
+ QVERIFY(component.isError());
+ QCOMPARE(
+ component.errorString(),
+ url.toString() + QLatin1String(
+ ":2 Cannot resolve URL for import \"file://./MyModuleName\"\n"));
+}
+
+void tst_QQmlImport::registerTypesFromImplicitImport()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("noimport/Main.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ TheThing *t = qobject_cast<TheThing *>(o.data());
+ QVERIFY(t);
+ QCOMPARE(t->m_width, 640);
+}
+
+void tst_QQmlImport::containsAllQtConfEntries()
+{
+ QString qtConfPath(u":/qmlimports.qt.conf");
+ QLibraryInfoPrivate::setQtconfManualPath(&qtConfPath);
+ QLibraryInfoPrivate::reload();
+ auto cleanup = qScopeGuard([](){
+ QLibraryInfoPrivate::setQtconfManualPath(nullptr);
+ QLibraryInfoPrivate::reload();
+ });
+ QQmlEngine engine;
+ auto importPaths = engine.importPathList();
+ QVERIFY(importPaths.contains(u"qrc:/a/path"));
+ QVERIFY(importPaths.contains(u"qrc:/another/path"));
+ QVERIFY(importPaths.contains(u"qrc:/even/more/path"));
+}
+
void tst_QQmlImport::testDesignerSupported()
{
- QQuickView *window = new QQuickView();
+ std::unique_ptr<QQuickView> window = std::make_unique<QQuickView>();
window->engine()->addImportPath(directory());
window->setSource(testFileUrl("testfile_supported.qml"));
@@ -137,8 +234,7 @@ void tst_QQmlImport::testDesignerSupported()
QQmlImports::setDesignerSupportRequired(true);
//imports are cached so we create a new window
- delete window;
- window = new QQuickView();
+ window = std::make_unique<QQuickView>();
window->engine()->addImportPath(directory());
window->engine()->clearComponentCache();
@@ -154,21 +250,19 @@ void tst_QQmlImport::testDesignerSupported()
QTest::ignoreMessage(QtWarningMsg, warningString.toLocal8Bit());
window->setSource(testFileUrl("testfile_unsupported.qml"));
QVERIFY(!window->errors().isEmpty());
-
- delete window;
}
void tst_QQmlImport::uiFormatLoading()
{
int size = 0;
- QQmlApplicationEngine *test = new QQmlApplicationEngine(testFileUrl("TestForm.ui.qml"));
+ std::unique_ptr<QQmlApplicationEngine> test = std::make_unique<QQmlApplicationEngine>(testFileUrl("TestForm.ui.qml"));
test->addImportPath(directory());
QCOMPARE(test->rootObjects().size(), ++size);
QVERIFY(test->rootObjects()[size -1]);
QVERIFY(test->rootObjects()[size -1]->property("success").toBool());
- QSignalSpy objectCreated(test, SIGNAL(objectCreated(QObject*,QUrl)));
+ QSignalSpy objectCreated(test.get(), SIGNAL(objectCreated(QObject*,QUrl)));
test->load(testFileUrl("TestForm.ui.qml"));
QCOMPARE(objectCreated.size(), size);//one less than rootObjects().size() because we missed the first one
QCOMPARE(test->rootObjects().size(), ++size);
@@ -193,13 +287,6 @@ void tst_QQmlImport::uiFormatLoading()
QCOMPARE(test->rootObjects().size(), ++size);
QVERIFY(test->rootObjects()[size -1]);
QVERIFY(test->rootObjects()[size -1]->property("success").toBool());
-
- delete test;
-}
-
-tst_QQmlImport::tst_QQmlImport()
- : QQmlDataTest(QT_QMLTEST_DATADIR)
-{
}
void tst_QQmlImport::importPathOrder()
@@ -503,6 +590,25 @@ void tst_QQmlImport::registerModuleImport()
qmlUnregisterModuleImport("MyPluginSupported", 2, "QtQuick", 2);
qmlUnregisterModuleImport("MyPluginSupported", 2, "ShadowQuick", 1);
+
+ qmlRegisterTypesAndRevisions<NotItem>("NoQmldir", 2);
+ qmlRegisterModuleImport("NoQmldir", QQmlModuleImportModuleAny, "QtQml", QQmlModuleImportAuto);
+
+ {
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData(R"(
+ import NoQmldir 2.0
+ QtObject {
+ property Item item: Item {}
+ }
+ )", QUrl::fromLocalFile(""));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
+ NotItem *item = object->property("item").value<NotItem *>();
+ QVERIFY(item);
+ }
}
void tst_QQmlImport::importDependenciesPrecedence()
diff --git a/tests/auto/qml/qqmlincubator/CMakeLists.txt b/tests/auto/qml/qqmlincubator/CMakeLists.txt
index 230609bb1d..3a38868e76 100644
--- a/tests/auto/qml/qqmlincubator/CMakeLists.txt
+++ b/tests/auto/qml/qqmlincubator/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlincubator Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlincubator LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlincubator/data/garbageCollection2.qml b/tests/auto/qml/qqmlincubator/data/garbageCollection2.qml
new file mode 100644
index 0000000000..b5ba531ede
--- /dev/null
+++ b/tests/auto/qml/qqmlincubator/data/garbageCollection2.qml
@@ -0,0 +1,12 @@
+import QtQml
+QtObject {
+ property Component comp: Component {
+ QtObject {}
+ }
+
+ property QtObject incubated: {
+ var i = comp.incubateObject(null, {}, Qt.Synchronous);
+ gc();
+ return i.object
+ }
+}
diff --git a/tests/auto/qml/qqmlincubator/testtypes.cpp b/tests/auto/qml/qqmlincubator/testtypes.cpp
index c94ef73c20..4e449a1b5a 100644
--- a/tests/auto/qml/qqmlincubator/testtypes.cpp
+++ b/tests/auto/qml/qqmlincubator/testtypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testtypes.h"
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlincubator/testtypes.h b/tests/auto/qml/qqmlincubator/testtypes.h
index e4c48d9d13..4942957986 100644
--- a/tests/auto/qml/qqmlincubator/testtypes.h
+++ b/tests/auto/qml/qqmlincubator/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
diff --git a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
index 1baf61574e..948dc66e71 100644
--- a/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
+++ b/tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testtypes.h"
#include <QUrl>
@@ -1148,7 +1148,7 @@ void tst_qqmlincubator::garbageCollection()
QQmlComponent component(&engine, testFileUrl("garbageCollection.qml"));
QScopedPointer<QObject> obj(component.create());
- engine.collectGarbage();
+ gc(engine);
std::atomic<bool> b{true};
controller.incubateWhile(&b);
@@ -1166,8 +1166,14 @@ void tst_qqmlincubator::garbageCollection()
incubatorVariant.clear();
// verify incubator is correctly collected now that incubation is complete and all references are gone
- engine.collectGarbage();
+ gc(engine);
QVERIFY(weakIncubatorRef.isNullOrUndefined());
+
+ QQmlComponent component2(&engine, testFileUrl("garbageCollection2.qml"));
+ QVERIFY2(component2.isReady(), qPrintable(component2.errorString()));
+ QScopedPointer<QObject> obj2(component2.create());
+ QVERIFY(!obj2.isNull());
+ QVERIFY(obj2->property("incubated").value<QObject *>() != nullptr);
}
void tst_qqmlincubator::requiredProperties()
diff --git a/tests/auto/qml/qqmlinfo/CMakeLists.txt b/tests/auto/qml/qqmlinfo/CMakeLists.txt
index 32e6c5ebd9..db00af9ea8 100644
--- a/tests/auto/qml/qqmlinfo/CMakeLists.txt
+++ b/tests/auto/qml/qqmlinfo/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlinfo Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlinfo LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlinfo/attached.cpp b/tests/auto/qml/qqmlinfo/attached.cpp
index 5ced27f3c9..88ad5d88dd 100644
--- a/tests/auto/qml/qqmlinfo/attached.cpp
+++ b/tests/auto/qml/qqmlinfo/attached.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "attached.h"
diff --git a/tests/auto/qml/qqmlinfo/attached.h b/tests/auto/qml/qqmlinfo/attached.h
index c719da8bcc..8d4018f88d 100644
--- a/tests/auto/qml/qqmlinfo/attached.h
+++ b/tests/auto/qml/qqmlinfo/attached.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp
index 4908ca210b..ebe1416c7d 100644
--- a/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp
+++ b/tests/auto/qml/qqmlinfo/tst_qqmlinfo.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtTest/qsignalspy.h>
@@ -213,7 +213,7 @@ void tst_qqmlinfo::attachedObject()
{
QQmlComponent component(&engine, testFileUrl("AttachedObject.qml"));
- QSignalSpy warningSpy(&engine, SIGNAL(warnings(const QList<QQmlError> &)));
+ QSignalSpy warningSpy(&engine, SIGNAL(warnings(QList<QQmlError>)));
QVERIFY(warningSpy.isValid());
const QString qmlBindingLoopMessage = "QML Rectangle: Binding loop detected for property \"width\"";
diff --git a/tests/auto/qml/qqmlinstantiator/CMakeLists.txt b/tests/auto/qml/qqmlinstantiator/CMakeLists.txt
index 59280f8c7d..7e453b9671 100644
--- a/tests/auto/qml/qqmlinstantiator/CMakeLists.txt
+++ b/tests/auto/qml/qqmlinstantiator/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlinstantiator Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlinstantiator LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml b/tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml
new file mode 100644
index 0000000000..82d707af37
--- /dev/null
+++ b/tests/auto/qml/qqmlinstantiator/data/listDataDestruction.qml
@@ -0,0 +1,20 @@
+import QtQml
+
+QtObject {
+ id: menu
+
+ Component.onCompleted: dt = new Date();
+ property date dt
+ property Instantiator i: Instantiator {
+ model: {
+ var model = [];
+ var d = menu.dt;
+ model.push({text: "A"});
+ return model;
+ }
+ delegate: QtObject {
+ objectName: modelData.text
+ Component.onCompleted: menu.objectName = objectName
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlinstantiator/data/removeDuringModelChange.qml b/tests/auto/qml/qqmlinstantiator/data/removeDuringModelChange.qml
new file mode 100644
index 0000000000..079e376549
--- /dev/null
+++ b/tests/auto/qml/qqmlinstantiator/data/removeDuringModelChange.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.15
+import QtQml.Models 2.15
+
+Instantiator {
+ delegate: QtObject {
+ function deactivate() {
+ model.active = false;
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlinstantiator/stringmodel.h b/tests/auto/qml/qqmlinstantiator/stringmodel.h
index d9676b9460..2b0c725e05 100644
--- a/tests/auto/qml/qqmlinstantiator/stringmodel.h
+++ b/tests/auto/qml/qqmlinstantiator/stringmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Dmitrii Kosarev aka Kakadu <kakadu.hafanana@gmail.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef STRINGMODEL_H
#define STRINGMODEL_H
diff --git a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp
index 1097c65f02..de7c6645a9 100644
--- a/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp
+++ b/tests/auto/qml/qqmlinstantiator/tst_qqmlinstantiator.cpp
@@ -1,7 +1,8 @@
// Copyright (C) 2016 Research In Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QSignalSpy>
+#include <QSortFilterProxyModel>
#include <QDebug>
#include <QtQml/qqmlengine.h>
@@ -28,12 +29,15 @@ private slots:
void activeModelChangeInteraction();
void intModelChange();
void createAndRemove();
+ void removeDuringModelChange();
void asynchronous_data();
void asynchronous();
void handlerWithParent();
void boundDelegateComponent();
+
+ void listDataDestruction();
};
tst_qqmlinstantiator::tst_qqmlinstantiator()
@@ -306,6 +310,103 @@ void tst_qqmlinstantiator::boundDelegateComponent()
QCOMPARE(b->objectAt(2)->objectName(), QStringLiteral("root3"));
}
+void tst_qqmlinstantiator::listDataDestruction()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("listDataDestruction.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), QLatin1String("A"));
+}
+
+class SingleBoolItemModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ SingleBoolItemModel(QObject *parent = nullptr) : QAbstractListModel(parent) {}
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override
+ {
+ if (parent.isValid())
+ return 0;
+ return 1;
+ }
+
+ QVariant data(const QModelIndex &index, int role) const override
+ {
+ if (index.parent().isValid() || index.row() != 0 || index.column() != 0
+ || role != Qt::UserRole)
+ return QVariant();
+
+ return m_active;
+ }
+
+ bool setData(const QModelIndex &index, const QVariant &value,
+ int role) override {
+ if (index.parent().isValid() || index.row() != 0 || index.column() != 0
+ || role != Qt::UserRole || m_active == value.toBool())
+ return false;
+
+ m_active = value.toBool();
+ Q_EMIT dataChanged(index, index, QList<int>{Qt::UserRole});
+ return true;
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return { {Qt::UserRole, "active"} };
+ }
+
+private:
+ bool m_active = true;
+};
+
+class FilterBoolRoleProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ FilterBoolRoleProxyModel(QObject *parent = nullptr)
+ : QSortFilterProxyModel(parent) {}
+
+ bool filterAcceptsRow(int source_row,
+ const QModelIndex &source_parent) const override
+ {
+ return sourceModel()->index(source_row, 0, source_parent).data(Qt::UserRole).toBool();
+ }
+};
+
+void tst_qqmlinstantiator::removeDuringModelChange()
+{
+ SingleBoolItemModel model;
+
+ FilterBoolRoleProxyModel proxyModel;
+ proxyModel.setSourceModel(&model);
+ proxyModel.setFilterRole(Qt::UserRole);
+ QCOMPARE(proxyModel.rowCount(), 1);
+
+ QQmlEngine engine;
+ const QUrl url(testFileUrl("removeDuringModelChange.qml"));
+ QQmlComponent component(&engine, url);
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY2(!o.isNull(), qPrintable(component.errorString()));
+
+ QQmlInstantiator *instantiator = qobject_cast<QQmlInstantiator *>(o.data());
+
+ instantiator->setModel(QVariant::fromValue(&proxyModel));
+
+ QSignalSpy removedSpy(instantiator, &QQmlInstantiator::objectRemoved);
+ QMetaObject::invokeMethod(instantiator->object(), "deactivate");
+
+ // We should still be alive at this point.
+ QCOMPARE(removedSpy.size(), 1);
+ QCOMPARE(proxyModel.rowCount(), 0);
+}
+
QTEST_MAIN(tst_qqmlinstantiator)
#include "tst_qqmlinstantiator.moc"
diff --git a/tests/auto/qml/qqmlitemmodels/CMakeLists.txt b/tests/auto/qml/qqmlitemmodels/CMakeLists.txt
index 632e98206b..80f210f668 100644
--- a/tests/auto/qml/qqmlitemmodels/CMakeLists.txt
+++ b/tests/auto/qml/qqmlitemmodels/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlitemmodels Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlitemmodels LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlitemmodels/data/modelindex.qml b/tests/auto/qml/qqmlitemmodels/data/modelindex.qml
index 2756f04120..7bf8bfb5a2 100644
--- a/tests/auto/qml/qqmlitemmodels/data/modelindex.qml
+++ b/tests/auto/qml/qqmlitemmodels/data/modelindex.qml
@@ -8,6 +8,7 @@ ItemModelsTest {
property var parent: modelIndex.parent
property var model: modelIndex.model
property var internalId: modelIndex.internalId
+ property var displayData: modelIndex.data(Qt.DisplayRole)
onSignalWithModelIndex: {
isValid = index.valid
@@ -16,5 +17,6 @@ ItemModelsTest {
parent = index.parent
model = index.model
internalId = index.internalId
+ displayData = index.data(Qt.DisplayRole)
}
}
diff --git a/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml b/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml
index 85987bdcac..aa43252100 100644
--- a/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml
+++ b/tests/auto/qml/qqmlitemmodels/data/persistentmodelindex.qml
@@ -8,6 +8,7 @@ ItemModelsTest {
property var parent: persistentModelIndex.parent
property var model: persistentModelIndex.model
property var internalId: persistentModelIndex.internalId
+ property var displayData: persistentModelIndex.data(Qt.DisplayRole)
property var pmi
@@ -18,6 +19,7 @@ ItemModelsTest {
parent = index.parent
model = index.model
internalId = index.internalId
+ displayData = index.data(Qt.DisplayRole)
pmi = createPersistentModelIndex(model.index(0, 0))
}
diff --git a/tests/auto/qml/qqmlitemmodels/qtestmodel.h b/tests/auto/qml/qqmlitemmodels/qtestmodel.h
index 6cbec533b1..6c442b06b7 100644
--- a/tests/auto/qml/qqmlitemmodels/qtestmodel.h
+++ b/tests/auto/qml/qqmlitemmodels/qtestmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef Q_TEST_MODEL_H
#define Q_TEST_MODEL_H
@@ -251,6 +251,8 @@ public:
mutable bool wrongIndex;
struct Node {
+ Q_DISABLE_COPY_MOVE(Node)
+
Node *parent;
QVector<Node *> children;
@@ -261,8 +263,7 @@ public:
~Node()
{
- foreach (Node *n, children)
- delete n;
+ qDeleteAll(children);
}
void addRows(int row, int count)
diff --git a/tests/auto/qml/qqmlitemmodels/testtypes.h b/tests/auto/qml/qqmlitemmodels/testtypes.h
index 57ac9c12d1..3bbd566cd1 100644
--- a/tests/auto/qml/qqmlitemmodels/testtypes.h
+++ b/tests/auto/qml/qqmlitemmodels/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
diff --git a/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp b/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp
index 339a61f996..1182759519 100644
--- a/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp
+++ b/tests/auto/qml/qqmlitemmodels/tst_qqmlitemmodels.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -55,6 +55,7 @@ void tst_qqmlitemmodels::modelIndex()
QCOMPARE(object->property("parent").toModelIndex(), index.parent());
QCOMPARE(object->property("model").value<QAbstractItemModel *>(), index.model());
QCOMPARE(object->property("internalId").toULongLong(), index.internalId());
+ QCOMPARE(object->property("displayData"), index.data(Qt::DisplayRole));
if (i < 3) {
index = model.index(2 + i, 4 - i, index);
@@ -79,6 +80,7 @@ void tst_qqmlitemmodels::persistentModelIndex()
QCOMPARE(object->property("parent").toModelIndex(), index.parent());
QCOMPARE(object->property("model").value<QAbstractItemModel *>(), index.model());
QCOMPARE(object->property("internalId").toULongLong(), index.internalId());
+ QCOMPARE(object->property("displayData"), index.data(Qt::DisplayRole));
if (i < 2) {
index = model.index(2 + i, 4 - i, index);
diff --git a/tests/auto/qml/qqmljsscope/CMakeLists.txt b/tests/auto/qml/qqmljsscope/CMakeLists.txt
index 542d217d8d..be8e136fc8 100644
--- a/tests/auto/qml/qqmljsscope/CMakeLists.txt
+++ b/tests/auto/qml/qqmljsscope/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmljsscope LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt
index 3431398f47..5215159373 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/CMakeLists.txt
@@ -8,9 +8,10 @@ qt_autogen_tools_initial_setup(qqmljsscope_test_module)
target_include_directories(qqmljsscope_test_module PUBLIC cpptypes/)
target_link_libraries(qqmljsscope_test_module PUBLIC Qt::Core Qt::Qml Qt::Gui)
+qt_policy(SET QTP0001 NEW)
+
qt6_add_qml_module(qqmljsscope_test_module
URI QQmlJSScopeTests
- AUTO_RESOURCE_PREFIX
SOURCES
singleton.h singleton.cpp
extensiontypes.h
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h
index f5fbde1b27..82fc3b58d2 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/extensiontypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef EXTENSIONTYPES_H
#define EXTENSIONTYPES_H
@@ -18,6 +18,17 @@ public:
Extension(QObject *parent = nullptr) : QObject(parent) { }
int getCount() const { return 42; }
void setCount(int) { }
+
+ enum EnumFromExtension {
+ ThisIsTheEnumFromExtension,
+ };
+ Q_ENUM(EnumFromExtension)
+ enum FlagFromExtension {
+ ThisIsTheFlagFromExtension,
+ };
+ Q_DECLARE_FLAGS(FlagsFromExtension, FlagFromExtension)
+ Q_FLAG(FlagsFromExtension)
+
Q_SIGNALS:
void countChanged();
};
@@ -41,6 +52,16 @@ public:
Extended(QObject *parent = nullptr) : QObject(parent) { }
double getCount() const { return 0.0; }
void setCount(double) { }
+
+ enum EnumFromExtended {
+ ThisIsTheEnumFromExtended,
+ };
+ Q_ENUM(EnumFromExtended)
+ enum FlagFromExtended {
+ ThisIsTheFlagFromExtended,
+ };
+ Q_DECLARE_FLAGS(FlagsFromExtended, FlagFromExtended)
+ Q_FLAG(FlagsFromExtended)
Q_SIGNALS:
void countChanged();
};
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp
index 280ff6163e..56efc324d3 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "singleton.h"
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h
index 78aa6466d7..a78b85e1d9 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/singleton.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SINGLETON_H
#define SINGLETON_H
diff --git a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h
index 2c812a6d9d..9126cf8f69 100644
--- a/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h
+++ b/tests/auto/qml/qqmljsscope/QQmlJSScopeTests/typewithproperties.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPEWITHPROPERTIES_H
#define TYPEWITHPROPERTIES_H
diff --git a/tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h b/tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h
index c323645f73..514a98881d 100644
--- a/tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h
+++ b/tests/auto/qml/qqmljsscope/QualifiedNamesTests/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
diff --git a/tests/auto/qml/qqmljsscope/data/attachedTypeResolution.qml b/tests/auto/qml/qqmljsscope/data/attachedTypeResolution.qml
new file mode 100644
index 0000000000..d6062be1f6
--- /dev/null
+++ b/tests/auto/qml/qqmljsscope/data/attachedTypeResolution.qml
@@ -0,0 +1,6 @@
+import QtQml
+import QtQuick
+
+Window {
+
+}
diff --git a/tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml b/tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml
new file mode 100644
index 0000000000..52841e323c
--- /dev/null
+++ b/tests/auto/qml/qqmljsscope/data/methodAndSignalSourceLocation.qml
@@ -0,0 +1,16 @@
+import QtQml
+
+QtObject {
+ function f1() { }
+ function f2(a) { }
+ function f3(a: int) { }
+ function f4(a, b) { }
+ function f5(a, b): void { }
+ function f6(a, b, c): void {
+ // Nothing
+ }
+
+ signal s1()
+ signal s2(a: int)
+ signal s3(a: int, b: string)
+}
diff --git a/tests/auto/qml/qqmljsscope/data/ownModuleName.qml b/tests/auto/qml/qqmljsscope/data/ownModuleName.qml
new file mode 100644
index 0000000000..6e43ce6b05
--- /dev/null
+++ b/tests/auto/qml/qqmljsscope/data/ownModuleName.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Item {
+ Item { id: child }
+ component IC: Item {
+ Item {
+ id: childInIC
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmljsscope/data/requiredAlias.qml b/tests/auto/qml/qqmljsscope/data/requiredAlias.qml
new file mode 100644
index 0000000000..77f70dea2b
--- /dev/null
+++ b/tests/auto/qml/qqmljsscope/data/requiredAlias.qml
@@ -0,0 +1,20 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick
+
+Item {
+ id: self
+
+ property int nonRequired
+ property alias sameScopeAlias: self.nonRequired
+ required sameScopeAlias
+
+ property alias innerScopeAlias: inner.nonRequiredInner
+ required innerScopeAlias
+
+ Item {
+ id: inner
+ property int nonRequiredInner
+ }
+}
diff --git a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp
index 09c6601858..05e0b2870a 100644
--- a/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp
+++ b/tests/auto/qml/qqmljsscope/tst_qqmljsscope.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -35,9 +35,9 @@ class tst_qqmljsscope : public QQmlDataTest
{
const QFileInfo fi(url);
QFile f(fi.absoluteFilePath());
- f.open(QIODevice::ReadOnly);
- QByteArray data(fi.size(), Qt::Uninitialized);
- f.read(data.data(), data.size());
+ if (!f.open(QIODevice::ReadOnly))
+ qFatal("Could not open file %s", qPrintable(url));
+ QByteArray data = f.readAll();
return QString::fromUtf8(data);
}
@@ -71,6 +71,7 @@ class tst_qqmljsscope : public QQmlDataTest
logger.setCode(sourceCode);
logger.setSilent(expectErrorsOrWarnings);
QQmlJSScope::Ptr target = QQmlJSScope::create();
+ target->setOwnModuleName(u"HelloModule"_s);
QQmlJSImportVisitor visitor(target, &m_importer, &logger, dataDirectory());
QQmlJSTypeResolver typeResolver { &m_importer };
typeResolver.init(&visitor, document->program);
@@ -92,6 +93,7 @@ private Q_SLOTS:
void signalCreationDifferences();
void allTypesAvailable();
void shadowing();
+ void requiredAlias();
#ifdef LABS_QML_MODELS_PRESENT
void componentWrappedObjects();
@@ -106,9 +108,15 @@ private Q_SLOTS:
void scriptIndices();
void extensions();
void emptyBlockBinding();
- void qualifiedName();
+ void hasOwnEnumerationKeys();
+ void ownModuleName();
void resolvedNonUniqueScopes();
void compilationUnitsAreCompatible();
+ void attachedTypeResolution_data();
+ void attachedTypeResolution();
+ void builtinTypeResolution_data();
+ void builtinTypeResolution();
+ void methodAndSignalSourceLocation();
public:
tst_qqmljsscope()
@@ -160,14 +168,14 @@ void tst_qqmljsscope::orderedBindings()
QCOMPARE(std::distance(pBindingsBegin, pBindingsEnd), 2);
// check that the bindings are properly ordered
- QCOMPARE(pBindingsBegin->bindingType(), QQmlJSMetaPropertyBinding::Object);
- QCOMPARE(std::next(pBindingsBegin)->bindingType(), QQmlJSMetaPropertyBinding::Interceptor);
+ QCOMPARE(pBindingsBegin->bindingType(), QQmlSA::BindingType::Object);
+ QCOMPARE(std::next(pBindingsBegin)->bindingType(), QQmlSA::BindingType::Interceptor);
auto [itemsBindingsBegin, itemsBindingsEnd] = root->ownPropertyBindings(u"items"_s);
QCOMPARE(std::distance(itemsBindingsBegin, itemsBindingsEnd), 2);
- QCOMPARE(itemsBindingsBegin->bindingType(), QQmlJSMetaPropertyBinding::Object);
- QCOMPARE(std::next(itemsBindingsBegin)->bindingType(), QQmlJSMetaPropertyBinding::Object);
+ QCOMPARE(itemsBindingsBegin->bindingType(), QQmlSA::BindingType::Object);
+ QCOMPARE(std::next(itemsBindingsBegin)->bindingType(), QQmlSA::BindingType::Object);
QCOMPARE(itemsBindingsBegin->objectType()->baseTypeName(), u"Item"_s);
QCOMPARE(std::next(itemsBindingsBegin)->objectType()->baseTypeName(), u"Text"_s);
@@ -184,8 +192,8 @@ void tst_qqmljsscope::signalCreationDifferences()
const auto conflicting = root->ownMethods(u"conflictingPropertyChanged"_s);
QCOMPARE(conflicting.size(), 2);
- QCOMPARE(conflicting[0].methodType(), QQmlJSMetaMethod::Signal);
- QCOMPARE(conflicting[1].methodType(), QQmlJSMetaMethod::Signal);
+ QCOMPARE(conflicting[0].methodType(), QQmlJSMetaMethodType::Signal);
+ QCOMPARE(conflicting[1].methodType(), QQmlJSMetaMethodType::Signal);
const QQmlJSMetaMethod *explicitMethod = nullptr;
if (conflicting[0].isImplicitQmlPropertyChangeSignal())
@@ -204,7 +212,7 @@ void tst_qqmljsscope::allTypesAvailable()
QQmlJSImporter importer { importPaths, /* resource file mapper */ nullptr };
const auto imported = importer.importModule(u"QtQml"_s);
- QCOMPARE(imported.context(), QQmlJSScope::ContextualTypes::QML);
+ QCOMPARE(imported.context(), QQmlJS::ContextualTypes::QML);
const auto types = imported.types();
QVERIFY(types.contains(u"$internal$.QObject"_s));
QVERIFY(types.contains(u"QtObject"_s));
@@ -235,6 +243,16 @@ void tst_qqmljsscope::shadowing()
QCOMPARE(methods[u"method_shadowed"_s].parameterNames().size(), 0);
}
+void tst_qqmljsscope::requiredAlias()
+{
+ QQmlJSScope::ConstPtr root = run(u"requiredAlias.qml"_s);
+ QVERIFY(root);
+
+ // Check whether aliases marked as required are required
+ QVERIFY(root->isPropertyRequired("sameScopeAlias"));
+ QVERIFY(root->isPropertyRequired("innerScopeAlias"));
+}
+
#ifdef LABS_QML_MODELS_PRESENT
void tst_qqmljsscope::componentWrappedObjects()
{
@@ -302,7 +320,7 @@ void tst_qqmljsscope::groupedProperties()
const auto getBindingsWithinGroup =
[&](QMultiHash<QString, QQmlJSMetaPropertyBinding> *bindings, qsizetype index) -> void {
const auto &binding = anchorBindings[index];
- QCOMPARE(binding.bindingType(), QQmlJSMetaPropertyBinding::GroupProperty);
+ QCOMPARE(binding.bindingType(), QQmlSA::BindingType::GroupProperty);
auto anchorScope = binding.groupType();
QVERIFY(anchorScope);
*bindings = anchorScope->ownPropertyBindings();
@@ -316,14 +334,14 @@ void tst_qqmljsscope::groupedProperties()
QMultiHash<QString, QQmlJSMetaPropertyBinding> bindingsOfType;
getBindingsWithinGroup(&bindingsOfType, 0);
QCOMPARE(bindingsOfType.size(), 2);
- QCOMPARE(value(bindingsOfType, u"left"_s).bindingType(), QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(value(bindingsOfType, u"left"_s).bindingType(), QQmlSA::BindingType::Script);
QCOMPARE(value(bindingsOfType, u"leftMargin"_s).bindingType(),
- QQmlJSMetaPropertyBinding::NumberLiteral);
+ QQmlSA::BindingType::NumberLiteral);
QMultiHash<QString, QQmlJSMetaPropertyBinding> bindingsOfBaseType;
getBindingsWithinGroup(&bindingsOfBaseType, 1);
QCOMPARE(bindingsOfBaseType.size(), 1);
- QCOMPARE(value(bindingsOfBaseType, u"top"_s).bindingType(), QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(value(bindingsOfBaseType, u"top"_s).bindingType(), QQmlSA::BindingType::Script);
}
void tst_qqmljsscope::descriptiveNameOfNull()
@@ -337,8 +355,10 @@ void tst_qqmljsscope::descriptiveNameOfNull()
property.setPropertyName(u"foo"_s);
property.setTypeName(u"baz"_s);
QQmlJSRegisterContent unscoped = QQmlJSRegisterContent::create(
- stored, property, QQmlJSRegisterContent::ScopeProperty, QQmlJSScope::ConstPtr());
- QCOMPARE(unscoped.descriptiveName(), u"bar of (invalid type)::foo with type baz"_s);
+ property, QQmlJSRegisterContent::InvalidLookupIndex,
+ QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ScopeProperty,
+ QQmlJSScope::ConstPtr()).storedIn(stored);
+ QCOMPARE(unscoped.descriptiveName(), u"(invalid type)::foo with type baz (stored as bar)"_s);
}
void tst_qqmljsscope::groupedPropertiesConsistency()
@@ -363,8 +383,8 @@ void tst_qqmljsscope::groupedPropertiesConsistency()
// The binding order in QQmlJSScope case is "reversed": first come
// bindings on the leaf type, followed by the bindings on the base type
- QCOMPARE(fontBindings[0].bindingType(), QQmlJSMetaPropertyBinding::GroupProperty);
- QCOMPARE(fontBindings[1].bindingType(), QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(fontBindings[0].bindingType(), QQmlSA::BindingType::GroupProperty);
+ QCOMPARE(fontBindings[1].bindingType(), QQmlSA::BindingType::Script);
}
}
@@ -378,7 +398,7 @@ void tst_qqmljsscope::groupedPropertySyntax()
// The binding order in QQmlJSScope case is "reversed": first come
// bindings on the leaf type, followed by the bindings on the base type
- QCOMPARE(fontBindings[0].bindingType(), QQmlJSMetaPropertyBinding::GroupProperty);
+ QCOMPARE(fontBindings[0].bindingType(), QQmlSA::BindingType::GroupProperty);
auto fontScope = fontBindings[0].groupType();
QVERIFY(fontScope);
QCOMPARE(fontScope->accessSemantics(), QQmlJSScope::AccessSemantics::Value);
@@ -390,9 +410,8 @@ void tst_qqmljsscope::groupedPropertySyntax()
return bindings.value(key, QQmlJSMetaPropertyBinding(QQmlJS::SourceLocation {}));
};
- QCOMPARE(value(subbindings, u"pixelSize"_s).bindingType(),
- QQmlJSMetaPropertyBinding::NumberLiteral);
- QCOMPARE(value(subbindings, u"bold"_s).bindingType(), QQmlJSMetaPropertyBinding::BoolLiteral);
+ QCOMPARE(value(subbindings, u"pixelSize"_s).bindingType(), QQmlSA::BindingType::NumberLiteral);
+ QCOMPARE(value(subbindings, u"bold"_s).bindingType(), QQmlSA::BindingType::BoolLiteral);
}
void tst_qqmljsscope::attachedProperties()
@@ -407,7 +426,7 @@ void tst_qqmljsscope::attachedProperties()
const auto getBindingsWithinAttached =
[&](QMultiHash<QString, QQmlJSMetaPropertyBinding> *bindings, qsizetype index) -> void {
const auto &binding = keysBindings[index];
- QCOMPARE(binding.bindingType(), QQmlJSMetaPropertyBinding::AttachedProperty);
+ QCOMPARE(binding.bindingType(), QQmlSA::BindingType::AttachedProperty);
auto keysScope = binding.attachingType();
QVERIFY(keysScope);
QCOMPARE(keysScope->accessSemantics(), QQmlJSScope::AccessSemantics::Reference);
@@ -422,23 +441,21 @@ void tst_qqmljsscope::attachedProperties()
QMultiHash<QString, QQmlJSMetaPropertyBinding> bindingsOfType;
getBindingsWithinAttached(&bindingsOfType, 0);
QCOMPARE(bindingsOfType.size(), 2);
- QCOMPARE(value(bindingsOfType, u"enabled"_s).bindingType(),
- QQmlJSMetaPropertyBinding::BoolLiteral);
- QCOMPARE(value(bindingsOfType, u"forwardTo"_s).bindingType(),
- QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(value(bindingsOfType, u"enabled"_s).bindingType(), QQmlSA::BindingType::BoolLiteral);
+ QCOMPARE(value(bindingsOfType, u"forwardTo"_s).bindingType(), QQmlSA::BindingType::Script);
QMultiHash<QString, QQmlJSMetaPropertyBinding> bindingsOfBaseType;
getBindingsWithinAttached(&bindingsOfBaseType, 1);
QCOMPARE(bindingsOfBaseType.size(), 1);
- QCOMPARE(value(bindingsOfBaseType, u"priority"_s).bindingType(),
- QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(value(bindingsOfBaseType, u"priority"_s).bindingType(), QQmlSA::BindingType::Script);
}
inline QString getScopeName(const QQmlJSScope::ConstPtr &scope)
{
Q_ASSERT(scope);
QQmlJSScope::ScopeType type = scope->scopeType();
- if (type == QQmlJSScope::GroupedPropertyScope || type == QQmlJSScope::AttachedPropertyScope)
+ if (type == QQmlSA::ScopeType::GroupedPropertyScope
+ || type == QQmlSA::ScopeType::AttachedPropertyScope)
return scope->internalName();
return scope->baseTypeName();
}
@@ -507,7 +524,7 @@ void tst_qqmljsscope::scriptIndices()
QmlIR::Document document(false); // we need QmlIR information here
QQmlJSScope::ConstPtr root = run(u"functionAndBindingIndices.qml"_s, &document);
QVERIFY(root);
- QVERIFY(document.javaScriptCompilationUnit.unitData());
+ QVERIFY(document.javaScriptCompilationUnit->unitData());
// compare QQmlJSScope and QmlIR:
@@ -537,8 +554,9 @@ void tst_qqmljsscope::scriptIndices()
const auto suitableScope = [](const QQmlJSScope::ConstPtr &scope) {
const auto type = scope->scopeType();
- return type == QQmlJSScope::QMLScope || type == QQmlJSScope::GroupedPropertyScope
- || type == QQmlJSScope::AttachedPropertyScope;
+ return type == QQmlSA::ScopeType::QMLScope
+ || type == QQmlSA::ScopeType::GroupedPropertyScope
+ || type == QQmlSA::ScopeType::AttachedPropertyScope;
};
QList<QQmlJSScope::ConstPtr> queue;
@@ -550,7 +568,7 @@ void tst_qqmljsscope::scriptIndices()
if (suitableScope(current)) {
const auto methods = current->ownMethods();
for (const auto &method : methods) {
- if (method.methodType() == QQmlJSMetaMethod::Signal)
+ if (method.methodType() == QQmlJSMetaMethodType::Signal)
continue;
QString name = method.methodName();
auto relativeIndex = method.jsFunctionIndex();
@@ -563,7 +581,7 @@ void tst_qqmljsscope::scriptIndices()
const auto bindings = current->ownPropertyBindings();
for (const auto &binding : bindings) {
- if (binding.bindingType() != QQmlJSMetaPropertyBinding::Script)
+ if (binding.bindingType() != QQmlSA::BindingType::Script)
continue;
QString name = binding.propertyName();
auto relativeIndex = binding.scriptIndex();
@@ -674,28 +692,50 @@ void tst_qqmljsscope::emptyBlockBinding()
QVERIFY(root->hasOwnPropertyBindings(u"y"_s));
}
-void tst_qqmljsscope::qualifiedName()
+void tst_qqmljsscope::hasOwnEnumerationKeys()
{
- QQmlJSScope::ConstPtr root = run(u"qualifiedName.qml"_s);
+ QQmlJSScope::ConstPtr root = run(u"extensions.qml"_s);
QVERIFY(root);
+ QQmlJSScope::ConstPtr extendedDerived = root->childScopes().front();
+ QVERIFY(extendedDerived);
+ // test that enumeration keys from base cannot be found
+ QVERIFY(!extendedDerived->hasOwnEnumerationKey(u"ThisIsTheEnumFromExtended"_s));
+ QVERIFY(!extendedDerived->hasOwnEnumerationKey(u"ThisIsTheFlagFromExtended"_s));
+
+ QQmlJSScope::ConstPtr extended = extendedDerived->baseType();
+ QVERIFY(extended);
+
+ QVERIFY(extended->hasOwnEnumerationKey(u"ThisIsTheEnumFromExtended"_s));
+ QVERIFY(extended->hasOwnEnumerationKey(u"ThisIsTheFlagFromExtended"_s));
+ QVERIFY(!extended->hasOwnEnumerationKey(u"ThisIsTheEnumFromExtension"_s));
+ QVERIFY(!extended->hasOwnEnumerationKey(u"ThisIsTheFlagFromExtension"_s));
+}
- auto qualifiedNameOf = [](const QQmlJSScope::ConstPtr &ptr) -> QString {
- if (ptr->baseType())
- return ptr->baseType()->qualifiedName();
- else
- return u""_s;
- };
-
- QCOMPARE(root->childScopes().size(), 4);
- QQmlJSScope::ConstPtr b = root->childScopes()[0];
- QQmlJSScope::ConstPtr d = root->childScopes()[1];
- QQmlJSScope::ConstPtr qualifiedA = root->childScopes()[2];
- QQmlJSScope::ConstPtr qualifiedB = root->childScopes()[3];
-
- QCOMPARE(qualifiedNameOf(b), "QualifiedNamesTests/B 5.0-6.0");
- QCOMPARE(qualifiedNameOf(d), "QualifiedNamesTests/D 6.0");
- QCOMPARE(qualifiedNameOf(qualifiedA), "QualifiedNamesTests/A 5.0");
- QCOMPARE(qualifiedNameOf(qualifiedB), "QualifiedNamesTests/B 5.0-6.0");
+void tst_qqmljsscope::ownModuleName()
+{
+ const QString moduleName = u"HelloModule"_s;
+ QQmlJSScope::ConstPtr root = run(u"ownModuleName.qml"_s);
+ QVERIFY(root);
+ QCOMPARE(root->moduleName(), moduleName);
+ QCOMPARE(root->ownModuleName(), moduleName);
+
+ QCOMPARE(root->childScopes().size(), 2);
+ QQmlJSScope::ConstPtr child = root->childScopes().front();
+ QVERIFY(child);
+ // only root and inline components have own module names, but the child should be able to query
+ // its component's module Name via moduleName()
+ QCOMPARE(child->ownModuleName(), QString());
+ QCOMPARE(child->moduleName(), moduleName);
+
+ QQmlJSScope::ConstPtr ic = root->childScopes()[1];
+ QVERIFY(ic);
+ QCOMPARE(ic->ownModuleName(), moduleName);
+ QCOMPARE(ic->moduleName(), moduleName);
+
+ QQmlJSScope::ConstPtr icChild = ic->childScopes().front();
+ QVERIFY(icChild);
+ QCOMPARE(icChild->ownModuleName(), QString());
+ QCOMPARE(icChild->moduleName(), moduleName);
}
void tst_qqmljsscope::resolvedNonUniqueScopes()
@@ -711,32 +751,32 @@ void tst_qqmljsscope::resolvedNonUniqueScopes()
{
auto topLevelBindings = root->propertyBindings(u"Component"_s);
QCOMPARE(topLevelBindings.size(), 1);
- QCOMPARE(topLevelBindings[0].bindingType(), QQmlJSMetaPropertyBinding::AttachedProperty);
+ QCOMPARE(topLevelBindings[0].bindingType(), QQmlSA::BindingType::AttachedProperty);
auto componentScope = topLevelBindings[0].attachingType();
auto componentBindings = componentScope->ownPropertyBindings();
QCOMPARE(componentBindings.size(), 2);
auto onCompletedBinding = value(componentBindings, u"onCompleted"_s);
QVERIFY(onCompletedBinding.isValid());
- QCOMPARE(onCompletedBinding.bindingType(), QQmlJSMetaPropertyBinding::Script);
- QCOMPARE(onCompletedBinding.scriptKind(), QQmlJSMetaPropertyBinding::Script_SignalHandler);
+ QCOMPARE(onCompletedBinding.bindingType(), QQmlSA::BindingType::Script);
+ QCOMPARE(onCompletedBinding.scriptKind(), QQmlSA::ScriptBindingKind::SignalHandler);
auto onDestructionBinding = value(componentBindings, u"onDestruction"_s);
QVERIFY(onDestructionBinding.isValid());
- QCOMPARE(onDestructionBinding.bindingType(), QQmlJSMetaPropertyBinding::Script);
+ QCOMPARE(onDestructionBinding.bindingType(), QQmlSA::BindingType::Script);
QCOMPARE(onDestructionBinding.scriptKind(),
- QQmlJSMetaPropertyBinding::Script_SignalHandler);
+ QQmlSA::ScriptBindingKind::SignalHandler);
}
{
auto topLevelBindings = root->propertyBindings(u"p"_s);
QCOMPARE(topLevelBindings.size(), 1);
- QCOMPARE(topLevelBindings[0].bindingType(), QQmlJSMetaPropertyBinding::GroupProperty);
+ QCOMPARE(topLevelBindings[0].bindingType(), QQmlSA::BindingType::GroupProperty);
auto pScope = topLevelBindings[0].groupType();
auto pBindings = pScope->ownPropertyBindings();
QCOMPARE(pBindings.size(), 1);
auto onXChangedBinding = value(pBindings, u"onXChanged"_s);
QVERIFY(onXChangedBinding.isValid());
- QCOMPARE(onXChangedBinding.bindingType(), QQmlJSMetaPropertyBinding::Script);
- QCOMPARE(onXChangedBinding.scriptKind(), QQmlJSMetaPropertyBinding::Script_SignalHandler);
+ QCOMPARE(onXChangedBinding.bindingType(), QQmlSA::BindingType::Script);
+ QCOMPARE(onXChangedBinding.scriptKind(), QQmlSA::ScriptBindingKind::SignalHandler);
}
}
@@ -777,8 +817,8 @@ void tst_qqmljsscope::compilationUnitsAreCompatible()
QmlIR::Document document(false); // we need QmlIR information here
QVERIFY(run(url, &document));
- QVERIFY(document.javaScriptCompilationUnit.unitData());
- getRuntimeInfoFromCompilationUnit(document.javaScriptCompilationUnit.unitData(),
+ QVERIFY(document.javaScriptCompilationUnit->unitData());
+ getRuntimeInfoFromCompilationUnit(document.javaScriptCompilationUnit->unitData(),
cachegenFunctions);
if (QTest::currentTestFailed())
return;
@@ -791,5 +831,162 @@ void tst_qqmljsscope::compilationUnitsAreCompatible()
QCOMPARE(uint(cachegenFunctions[i]->nameIndex), uint(componentFunctions[i]->nameIndex));
}
+void tst_qqmljsscope::attachedTypeResolution_data()
+{
+ QTest::addColumn<bool>("creatable");
+ QTest::addColumn<QString>("moduleName");
+ QTest::addColumn<QString>("typeName");
+ QTest::addColumn<QString>("attachedTypeName");
+ QTest::addColumn<QString>("propertyOnSelf");
+ QTest::addColumn<QString>("propertyOnAttached");
+
+ QTest::addRow("ListView") << true
+ << "QtQuick"
+ << "ListView"
+ << "QQuickListViewAttached"
+ << "orientation"
+ << "";
+ QTest::addRow("Keys") << false
+ << "QtQuick"
+ << "Keys"
+ << "QQuickKeysAttached"
+ << "priority"
+ << "priority";
+}
+
+class TestPass : public QQmlSA::ElementPass
+{
+public:
+ TestPass(QQmlSA::PassManager *manager) : QQmlSA::ElementPass(manager) { }
+ bool shouldRun(const QQmlSA::Element &) override { return true; }
+ void run(const QQmlSA::Element &) override { }
+};
+
+using PassManagerPtr = std::unique_ptr<
+ QQmlSA::PassManager, decltype(&QQmlSA::PassManagerPrivate::deletePassManager)>;
+
+void tst_qqmljsscope::attachedTypeResolution()
+{
+ QFETCH(bool, creatable);
+ QFETCH(QString, moduleName);
+ QFETCH(QString, typeName);
+ QFETCH(QString, attachedTypeName);
+ QFETCH(QString, propertyOnSelf);
+ QFETCH(QString, propertyOnAttached);
+
+ std::unique_ptr<QQmlJSLogger> logger = std::make_unique<QQmlJSLogger>();
+ QFile qmlFile("data/attachedTypeResolution.qml");
+ if (!qmlFile.open(QIODevice::ReadOnly | QIODevice::Text))
+ QSKIP("Unable to open qml file");
+
+ logger->setCode(qmlFile.readAll());
+ logger->setFileName(QString(qmlFile.filesystemFileName().string().c_str()));
+ QQmlJSImporter importer{ { "data" }, nullptr, true };
+ QStringList defaultImportPaths =
+ QStringList{ QLibraryInfo::path(QLibraryInfo::QmlImportsPath) };
+ importer.setImportPaths(defaultImportPaths);
+ QQmlJSTypeResolver resolver(&importer);
+ const auto &implicitImportDirectory = QQmlJSImportVisitor::implicitImportDirectory(
+ logger->fileName(), importer.resourceFileMapper());
+ QQmlJSImportVisitor v{
+ QQmlJSScope::create(), &importer, logger.get(), implicitImportDirectory, {}
+ };
+
+ PassManagerPtr manager(
+ QQmlSA::PassManagerPrivate::createPassManager(&v, &resolver),
+ &QQmlSA::PassManagerPrivate::deletePassManager);
+
+ TestPass pass{ manager.get() };
+ const auto &resolved = pass.resolveType(moduleName, typeName);
+
+ QVERIFY(!resolved.isNull());
+ const auto &attachedType = pass.resolveAttached(moduleName, typeName);
+ QVERIFY(!attachedType.isNull());
+ QCOMPARE(attachedType.name(), attachedTypeName);
+
+ if (propertyOnAttached != "") {
+ QEXPECT_FAIL("Keys", "Keys and QQuickKeysAttached have the same properties", Continue);
+ QVERIFY(!resolved.hasProperty(propertyOnAttached));
+ QVERIFY(attachedType.hasProperty(propertyOnAttached));
+ }
+ if (propertyOnSelf != "") {
+ QEXPECT_FAIL("Keys", "Keys and QQuickKeysAttached have the same properties", Continue);
+ QVERIFY(!attachedType.hasProperty(propertyOnSelf));
+ }
+
+ if (creatable)
+ QVERIFY(resolved.hasProperty(propertyOnSelf));
+}
+
+
+
+void tst_qqmljsscope::builtinTypeResolution_data()
+{
+ QTest::addColumn<bool>("valid");
+ QTest::addColumn<QString>("typeName");
+
+ QTest::addRow("global_QtObject") << true << "Qt";
+ QTest::addRow("function") << true << "function";
+ QTest::addRow("Array") << true << "Array";
+ QTest::addRow("invalid") << false << "foobar";
+ QTest::addRow("Number") << true << "Number";
+ QTest::addRow("bool") << true << "bool";
+ QTest::addRow("QString") << true << "QString";
+}
+
+void tst_qqmljsscope::builtinTypeResolution()
+{
+ QFETCH(bool, valid);
+ QFETCH(QString, typeName);
+
+ QQmlJSImporter importer{ { "data" }, nullptr, true };
+ QStringList defaultImportPaths =
+ QStringList{ QLibraryInfo::path(QLibraryInfo::QmlImportsPath) };
+ importer.setImportPaths(defaultImportPaths);
+ QQmlJSTypeResolver resolver(&importer);
+ const auto &implicitImportDirectory = QQmlJSImportVisitor::implicitImportDirectory({}, nullptr);
+ QQmlJSLogger logger;
+ QQmlJSImportVisitor v{
+ QQmlJSScope::create(), &importer, &logger, implicitImportDirectory, {}
+ };
+
+ PassManagerPtr manager(
+ QQmlSA::PassManagerPrivate::createPassManager(&v, &resolver),
+ &QQmlSA::PassManagerPrivate::deletePassManager);
+
+ TestPass pass{ manager.get() };
+ auto element = pass.resolveBuiltinType(typeName);
+ QCOMPARE(element.isNull(), !valid);
+}
+
+void tst_qqmljsscope::methodAndSignalSourceLocation()
+{
+ QmlIR::Document document(false);
+ auto jsscope = run(u"methodAndSignalSourceLocation.qml"_s, false);
+
+ std::array<std::array<int, 9>, 2> offsetsByLineEnding = {
+ std::array{ 29, 51, 74, 102, 128, 160, 219, 235, 257 }, // 1 char line endings
+ std::array{ 32, 55, 79, 108, 135, 168, 231, 248, 271 } // 2 char line endinds
+ };
+
+ // Try to detect the size of line endings as they lead to different source locations
+ auto offset1 = jsscope->methods("f1")[0].sourceLocation().offset;
+ QVERIFY(offset1 == 29 || offset1 == 32);
+ bool oneCharEndings = offset1 == 29;
+ std::array<int, 9> &offsets = oneCharEndings ? offsetsByLineEnding[0] : offsetsByLineEnding[1];
+
+ using namespace QQmlJS;
+ QCOMPARE(jsscope->methods("f1")[0].sourceLocation(), SourceLocation(offsets[0], 17, 4, 5));
+ QCOMPARE(jsscope->methods("f2")[0].sourceLocation(), SourceLocation(offsets[1], 18, 5, 5));
+ QCOMPARE(jsscope->methods("f3")[0].sourceLocation(), SourceLocation(offsets[2], 23, 6, 5));
+ QCOMPARE(jsscope->methods("f4")[0].sourceLocation(), SourceLocation(offsets[3], 21, 7, 5));
+ QCOMPARE(jsscope->methods("f5")[0].sourceLocation(), SourceLocation(offsets[4], 27, 8, 5));
+ QCOMPARE(jsscope->methods("f6")[0].sourceLocation(), SourceLocation(offsets[5], oneCharEndings ? 53 : 55, 9, 5));
+
+ QCOMPARE(jsscope->methods("s1")[0].sourceLocation(), SourceLocation(offsets[6], 11, 13, 5));
+ QCOMPARE(jsscope->methods("s2")[0].sourceLocation(), SourceLocation(offsets[7], 17, 14, 5));
+ QCOMPARE(jsscope->methods("s3")[0].sourceLocation(), SourceLocation(offsets[8], 28, 15, 5));
+}
+
QTEST_MAIN(tst_qqmljsscope)
#include "tst_qqmljsscope.moc"
diff --git a/tests/auto/qml/qqmllanguage/CMakeLists.txt b/tests/auto/qml/qqmllanguage/CMakeLists.txt
index e07f741bf6..9fff8f2118 100644
--- a/tests/auto/qml/qqmllanguage/CMakeLists.txt
+++ b/tests/auto/qml/qqmllanguage/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllanguage Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllanguage LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -27,6 +33,8 @@ qt_internal_add_test(tst_qqmllanguage
TESTDATA ${test_data}
)
+add_subdirectory(testhelper)
+
#### Keys ignored in scope 1:.:.:qqmllanguage.pro:<TRUE>:
# OTHER_FILES = "data/readonlyObjectProperty.qml"
# QML_IMPORT_NAME = "StaticTest"
diff --git a/tests/auto/qml/qqmllanguage/data/AliasHolder.qml b/tests/auto/qml/qqmllanguage/data/AliasHolder.qml
new file mode 100644
index 0000000000..42aed6ed26
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/AliasHolder.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property alias strokeStyle: path.restoreMode
+ property Binding p: Binding { id: path }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnumSelfReference.qml b/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnumSelfReference.qml
new file mode 100644
index 0000000000..0ec43bf7aa
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/CompositeTypeWithEnumSelfReference.qml
@@ -0,0 +1,8 @@
+import QtQml
+import Test
+
+QtObject {
+ enum A { B, C, D }
+ property int e: CompositeTypeWithEnumSelfReference.C
+ property int f: CompositeTypeWithEnumSelfReference.A.D
+}
diff --git a/tests/auto/qml/qqmllanguage/data/Comps/IconPropertiesGroup.qml b/tests/auto/qml/qqmllanguage/data/Comps/IconPropertiesGroup.qml
new file mode 100644
index 0000000000..232c755bfb
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/Comps/IconPropertiesGroup.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+QtObject {
+ function dothing() { console.log("do") }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/Comps/OverlayDrawer.qml b/tests/auto/qml/qqmllanguage/data/Comps/OverlayDrawer.qml
new file mode 100644
index 0000000000..713c760a04
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/Comps/OverlayDrawer.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property IconPropertiesGroup handleOpenIcon: IconPropertiesGroup {}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/Comps/qmldir b/tests/auto/qml/qqmllanguage/data/Comps/qmldir
new file mode 100644
index 0000000000..0a68a376f6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/Comps/qmldir
@@ -0,0 +1,4 @@
+module Comps
+OverlayDrawer 254.0 OverlayDrawer.qml
+IconPropertiesGroup 254.0 IconPropertiesGroup.qml
+
diff --git a/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml b/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml
new file mode 100644
index 0000000000..134eacf913
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/DeepAliasOnIC.qml
@@ -0,0 +1,27 @@
+import QtQml
+
+QtObject {
+ id: root
+ objectName: "theRoot"
+
+ component ObjectWithColor: QtObject {
+ property string color
+ property var varvar
+ }
+
+ property ObjectWithColor border: ObjectWithColor {
+ objectName: root.objectName
+ color: root.trueBorderColor
+ varvar: root.trueBorderVarvar
+ }
+
+ readonly property rect readonlyRect: ({x: 12, y: 13, width: 14, height: 15})
+
+ property alias borderObjectName: root.border.objectName
+ property alias borderColor: root.border.color
+ property alias borderVarvar: root.border.varvar
+ property alias readonlyRectX: root.readonlyRect.x
+
+ property string trueBorderColor: "green"
+ property var trueBorderVarvar: 1234
+}
diff --git a/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml
new file mode 100644
index 0000000000..f549e851a3
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired1.qml
@@ -0,0 +1,6 @@
+pragma Singleton
+import QtQml
+
+QtObject {
+ required property int i
+}
diff --git a/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml
new file mode 100644
index 0000000000..1f9e7e3a42
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/SingletonWithRequired2.qml
@@ -0,0 +1,8 @@
+pragma Singleton
+import QtQml
+
+QtObject {
+ property QtObject o: QtObject {
+ required property int i
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir
new file mode 100644
index 0000000000..46e397ca76
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/SingletonWithRequiredProperties/qmldir
@@ -0,0 +1,4 @@
+module SingletonWithRequiredProperties
+
+singleton SingletonWithRequired1 1.0 SingletonWithRequired1.qml
+singleton SingletonWithRequired2 1.0 SingletonWithRequired2.qml
diff --git a/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml
new file mode 100644
index 0000000000..6186faa00b
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle1.qml
@@ -0,0 +1,15 @@
+import QtQml
+
+QtObject {
+ id: self
+ property QtObject b
+ property Component c
+ function a() : TypeAnnotationCycle2 { return c.createObject() as TypeAnnotationCycle2 }
+
+ Component.onCompleted: {
+ c = Qt.createComponent("TypeAnnotationCycle2.qml");
+ let v = a();
+ v.addTypeAnnotationCycle1(self as TypeAnnotationCycle1);
+ b = v.b;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml
new file mode 100644
index 0000000000..9e3ffa86d2
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/TypeAnnotationCycle2.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property QtObject b
+ function addTypeAnnotationCycle1(c: TypeAnnotationCycle1) { b = c; }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/UIToolBar.qml b/tests/auto/qml/qqmllanguage/data/UIToolBar.qml
new file mode 100644
index 0000000000..08a22d2492
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/UIToolBar.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ id: root
+ signal doneClicked()
+ signal foo()
+
+ onObjectNameChanged: foo()
+ Component.onCompleted: root.foo.connect(root.doneClicked)
+}
diff --git a/tests/auto/qml/qqmllanguage/data/alias.16.qml b/tests/auto/qml/qqmllanguage/data/alias.16.qml
index 4637aec58f..335d240003 100644
--- a/tests/auto/qml/qqmllanguage/data/alias.16.qml
+++ b/tests/auto/qml/qqmllanguage/data/alias.16.qml
@@ -2,7 +2,7 @@ import QtQuick 2.0
import QtQuick.Window 2.0
Window {
- visible: true
+ visible: false
property alias list: repeater.model
diff --git a/tests/auto/qml/qqmllanguage/data/aliasWriter.qml b/tests/auto/qml/qqmllanguage/data/aliasWriter.qml
new file mode 100644
index 0000000000..4001c2af34
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/aliasWriter.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+AliasHolder {
+ strokeStyle: 1
+}
diff --git a/tests/auto/qml/qqmllanguage/data/ambiguousComponents.qml b/tests/auto/qml/qqmllanguage/data/ambiguousComponents.qml
new file mode 100644
index 0000000000..64c31b46d6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/ambiguousComponents.qml
@@ -0,0 +1,16 @@
+import QtQuick
+import Comps as Comps
+
+Comps.OverlayDrawer {
+ id: self
+
+ property var dothing
+
+ Component.onCompleted: dothing = handleOpenIcon.dothing
+
+ function dodo() { dothing() }
+
+ function testInstanceOf() : bool {
+ return self instanceof Comps.OverlayDrawer
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/asCastToInlineComponent.qml b/tests/auto/qml/qqmllanguage/data/asCastToInlineComponent.qml
new file mode 100644
index 0000000000..428ccd5eef
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/asCastToInlineComponent.qml
@@ -0,0 +1,16 @@
+import QtQml
+
+QtObject {
+ id: root
+
+ component MyItem: QtObject {
+ property int value: 10
+ onValueChanged: root.objectName = "value: " + value
+ }
+
+ property Instantiator i: Instantiator {
+ id: loader
+ delegate: MyItem {}
+ onObjectChanged: (loader.object as MyItem).value = 20
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/asValueType.qml b/tests/auto/qml/qqmllanguage/data/asValueType.qml
new file mode 100644
index 0000000000..b51dc9c6ec
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/asValueType.qml
@@ -0,0 +1,20 @@
+pragma ValueTypeBehavior: Addressable
+import QtQml
+import StaticTest
+
+QtObject {
+ property var a
+ property rect b: a as rect
+ property bool c: a instanceof rect
+ property bool d: ({x: 10, y: 20}) instanceof point
+ property var e: ({x: 10, y: 20}) as point
+ property var f: "red" as withString
+ property var g: "green" as string
+ property rect bb
+ property var p: bb as size;
+ property var q: this as size;
+ property var r: ({}) as size;
+ property var s: 11 as size;
+ property var t: Component as size;
+ property var u: Qt as size;
+}
diff --git a/tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml b/tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml
new file mode 100644
index 0000000000..777ada3848
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/asValueTypeGood.qml
@@ -0,0 +1,35 @@
+pragma ValueTypeBehavior: Assertable
+import QtQml as Q
+import StaticTest as S
+
+Q.QtObject {
+ property var a
+ property rect b: a as Q.rect
+ property bool c: a instanceof Q.rect
+ property bool d: ({x: 10, y: 20}) instanceof Q.point
+ property var e: ({x: 10, y: 20}) as Q.point
+ property var f: "red" as S.withString
+ property var g: "green" as Q.string
+
+ property var h: new S.withString("red")
+ property var i: {
+ let p = new Q.point;
+ p.x = 10
+ p.y = 20
+ return p
+ }
+
+ property var j: 4.0 as Q.int
+ property var k: (4.5 / 1.5) as Q.int
+ property var l: 5 as Q.double
+ property var m: "something" as Q.var
+ property var n: 1 as Q.bool
+ property var o: Infinity as Q.int
+
+ property var p: b as Q.size;
+ property var q: this as Q.size;
+ property var r: ({}) as Q.size;
+ property var s: 11 as Q.size;
+ property var t: Q.Component as Q.size;
+ property var u: Q.Qt as Q.size;
+}
diff --git a/tests/auto/qml/qqmllanguage/data/badICAnnotation.qml b/tests/auto/qml/qqmllanguage/data/badICAnnotation.qml
new file mode 100644
index 0000000000..6f0db53f2a
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/badICAnnotation.qml
@@ -0,0 +1,25 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ function doStuff(status: Binding.NotAnInlineComponent) : int {
+ return status
+ }
+
+ function doStuff2(status: InlineComponentBase.IC) : QtObject {
+ return status
+ }
+
+ function doStuff3(status: InlineComponentBase.NotIC) : QtObject {
+ return status
+ }
+
+ property InlineComponentBase.IC ic: InlineComponentBase.IC {}
+
+ property int a: doStuff(5)
+ property QtObject b: doStuff2(ic)
+ property QtObject c: doStuff3(ic)
+ property QtObject d: doStuff2(self)
+}
+
diff --git a/tests/auto/qml/qqmllanguage/data/SingletonTest.qml b/tests/auto/qml/qqmllanguage/data/badSingleton/SingletonTest.qml
index 70e1671754..70e1671754 100644
--- a/tests/auto/qml/qqmllanguage/data/SingletonTest.qml
+++ b/tests/auto/qml/qqmllanguage/data/badSingleton/SingletonTest.qml
diff --git a/tests/auto/qml/qqmllanguage/data/qmldir b/tests/auto/qml/qqmllanguage/data/badSingleton/qmldir
index c946de657c..c946de657c 100644
--- a/tests/auto/qml/qqmllanguage/data/qmldir
+++ b/tests/auto/qml/qqmllanguage/data/badSingleton/qmldir
diff --git a/tests/auto/qml/qqmllanguage/data/qtbug_85932.qml b/tests/auto/qml/qqmllanguage/data/badSingleton/qtbug_85932.qml
index aa21558220..aa21558220 100644
--- a/tests/auto/qml/qqmllanguage/data/qtbug_85932.qml
+++ b/tests/auto/qml/qqmllanguage/data/badSingleton/qtbug_85932.qml
diff --git a/tests/auto/qml/qqmllanguage/data/corpseInQmlList.qml b/tests/auto/qml/qqmllanguage/data/corpseInQmlList.qml
new file mode 100644
index 0000000000..dc0e145064
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/corpseInQmlList.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ property var b;
+
+ function returnList(a: QtObject) : list<QtObject> {
+ return [a]
+ }
+
+ function setB(a: QtObject) {
+ b = { b: returnList(a) }
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml b/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml
new file mode 100644
index 0000000000..50eaa7c3e2
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/deepAliasOnICUser.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+DeepAliasOnIC {
+ borderObjectName: "theLeaf"
+ borderColor: "black"
+ borderVarvar: "mauve"
+}
+
+
diff --git a/tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml b/tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml
new file mode 100644
index 0000000000..f5ae62406b
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/deepAliasOnReadonly.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+DeepAliasOnIC {
+ readonlyRectX: 55
+}
diff --git a/tests/auto/qml/qqmllanguage/data/derivedFromUnexposedBase.qml b/tests/auto/qml/qqmllanguage/data/derivedFromUnexposedBase.qml
new file mode 100644
index 0000000000..b508474a36
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/derivedFromUnexposedBase.qml
@@ -0,0 +1,6 @@
+import Test
+
+DerivedFromUnexposedBase {
+ group.value: 42
+ groupGadget.value: 42
+}
diff --git a/tests/auto/qml/qqmllanguage/data/dynamicGroupPropertyRejected.qml b/tests/auto/qml/qqmllanguage/data/dynamicGroupPropertyRejected.qml
new file mode 100644
index 0000000000..2fffea25c6
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/dynamicGroupPropertyRejected.qml
@@ -0,0 +1,5 @@
+import Test
+
+DerivedFromUnexposedBase {
+ dynamic.value: "This should fail"
+}
diff --git a/tests/auto/qml/qqmllanguage/data/enumPropsManyUnderlyingTypes.qml b/tests/auto/qml/qqmllanguage/data/enumPropsManyUnderlyingTypes.qml
new file mode 100644
index 0000000000..b713d2aa24
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/enumPropsManyUnderlyingTypes.qml
@@ -0,0 +1,10 @@
+import Test
+
+EnumPropsManyUnderlyingTypes {
+ si8prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ ui8prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ si16prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ ui16prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ si64prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+ ui64prop: EnumPropsManyUnderlyingTypes.ResolvedValue
+}
diff --git a/tests/auto/qml/qqmllanguage/data/enumScopes.qml b/tests/auto/qml/qqmllanguage/data/enumScopes.qml
new file mode 100644
index 0000000000..c71872387f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/enumScopes.qml
@@ -0,0 +1,16 @@
+import QtQml 2.15
+import EnumScopeTest 1.0
+
+QtObject {
+ property NonSingleton n: NonSingleton {
+ id: nonSingleton
+ }
+
+ property bool singletonUnscoped: Singleton.enumProperty === Singleton.EnumValue2
+ property bool singletonScoped: Singleton.enumProperty === Singleton.EnumType.EnumValue2
+ property bool nonSingletonUnscoped: nonSingleton.enumProperty === NonSingleton.EnumValue2
+ property bool nonSingletonScoped: nonSingleton.enumProperty === NonSingleton.EnumType.EnumValue2
+
+ property int singletonScopedValue: EnumProviderSingleton.Expected.Value
+ property int singletonUnscopedValue: EnumProviderSingleton.Value
+}
diff --git a/tests/auto/qml/qqmllanguage/data/inlineComponentWithImplicitComponent.qml b/tests/auto/qml/qqmllanguage/data/inlineComponentWithImplicitComponent.qml
new file mode 100644
index 0000000000..902dfb501d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/inlineComponentWithImplicitComponent.qml
@@ -0,0 +1,27 @@
+import QtQml
+
+QtObject {
+ component C1: QtObject {
+ property Component comp: null
+ }
+
+ component C2: C1 {
+ comp: QtObject {
+ objectName: "green"
+ }
+ }
+
+ component C3: C1 {
+ comp: Component {
+ QtObject {
+ objectName: "blue"
+ }
+ }
+ }
+
+ property QtObject c1: C1 {}
+ property QtObject c2: C2 {}
+ property QtObject c3: C3 {}
+
+ objectName: c2.comp.createObject().objectName + " " + c3.comp.createObject().objectName
+}
diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt
index d76f18ba89..5ddb8a2e6d 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.1.errors.txt
@@ -1 +1 @@
-5:5:Invalid grouped property access: Property "o" with type "QVariant", which is not a value type
+5:7:Cannot assign to non-existent property "blah"
diff --git a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt
index 9a0422753f..ced96fba83 100644
--- a/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt
+++ b/tests/auto/qml/qqmllanguage/data/invalidGroupedProperty.3.errors.txt
@@ -1 +1 @@
-4:5:Invalid grouped property access: Property "customType" with type "MyCustomVariantType", which is not a value type
+4:5:Invalid grouped property access: Property "customType" with type "MyCustomVariantType", which is neither a value nor an object type
diff --git a/tests/auto/qml/qqmllanguage/data/invokableCtors.qml b/tests/auto/qml/qqmllanguage/data/invokableCtors.qml
new file mode 100644
index 0000000000..35a8d7bf08
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/invokableCtors.qml
@@ -0,0 +1,12 @@
+import QtQml as QQ
+import Test as VV
+
+QQ.QtObject {
+ property QQ.QtObject oo: new QQ.QtObject()
+ property QQ.QtObject pp: new QQ.QtObject(oo)
+ property VV.vv v: new VV.vv("green")
+
+ property VV.InvokableSingleton i: new VV.InvokableSingleton(5, oo)
+ property VV.InvokableExtended k: new VV.InvokableExtended()
+ property VV.InvokableUncreatable l: new VV.InvokableUncreatable()
+}
diff --git a/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_interpreter.qml b/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_interpreter.qml
new file mode 100644
index 0000000000..460d4667f8
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_interpreter.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ id: self
+ property int a: 3
+ property var result
+ Component.onCompleted: {
+ var sum = 0
+ let f = function() {
+ return self.notthere ?? self.a
+ }
+
+ // Not enough times for the jit to kick in (should run on the interpreter)
+ for (let i = 0; i < 1; i++) {
+ sum = sum + f()
+ }
+ result = sum
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_jit.qml b/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_jit.qml
new file mode 100644
index 0000000000..43c82f436c
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/isNullOrUndefined_jit.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQml
+
+QtObject {
+ id: self
+ property int a: 3
+ property int result
+ Component.onCompleted: {
+ var sum = 0
+ let f = function() {
+ return self.notthere ?? self.a
+ }
+
+ // Enough times for the jit to kick in (should run on the jit)
+ for (let i = 0; i < 50; i++) {
+ sum = sum + f()
+ }
+ result = sum
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/jitExceptions.qml b/tests/auto/qml/qqmllanguage/data/jitExceptions.qml
new file mode 100644
index 0000000000..c5e11af31d
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/jitExceptions.qml
@@ -0,0 +1,16 @@
+import QtQml
+
+QtObject {
+ function burn() {
+ return control.font
+ }
+
+ Component.onCompleted: {
+ for (var a = 0; a < 10; ++a) {
+ try { burn() } catch(e) {}
+ }
+
+ burn();
+ }
+
+}
diff --git a/tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml b/tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml
new file mode 100644
index 0000000000..5bd563a288
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/jsonArrayProperty.qml
@@ -0,0 +1,191 @@
+import QtQml
+import TypeWithQJsonArrayProperty
+
+TypeWithQJsonArrayProperty {
+ function jsArray() { return [1, 2, 3] }
+
+ jsonArray: jsArray()
+
+ property list<int> concatenatedJsonArray: jsonArray.concat([4, 5, 6])
+ property list<int> concatenatedJsArray: jsArray().concat([4, 5, 6])
+
+ property bool entriesMatch: {
+ var iterator = jsonArray.entries();
+ for (var [index, element] of jsArray().entries()) {
+ var v = iterator.next().value;
+ if (index !== v[0] || element !== v[1]) {
+ console.log(index, v[0], element, v[1]);
+ return false;
+ }
+ }
+
+ var iterator = jsArray().entries();
+ for (var [index, element] of jsonArray.entries()) {
+ var v = iterator.next().value;
+ if (index !== v[0] || element !== v[1]) {
+ console.log(index, v[0], element, v[1]);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property bool jsonArrayEvery: jsonArray.every(element => element != 0)
+ property bool jsArrayEvery: jsArray().every(element => element != 0)
+
+ property list<int> jsonArrayFiltered: jsonArray.filter(element => element > 2)
+ property list<int> jsArrayFiltered: jsArray().filter(element => element > 2)
+
+ property int jsonArrayFind: jsonArray.find(element => element === 2)
+ property int jsArrayFind: jsArray().find(element => element === 2)
+
+ property int jsonArrayFindIndex: jsonArray.findIndex(element => element === 1)
+ property int jsArrayFindIndex: jsArray().findIndex(element => element === 1)
+
+ property string jsonArrayForEach
+ property string jsArrayForEach
+
+ property bool jsonArrayIncludes: jsonArray.includes(3)
+ property bool jsArrayIncludes: jsArray().includes(3)
+
+ property int jsonArrayIndexOf: jsonArray.indexOf(2)
+ property int jsArrayIndexOf: jsArray().indexOf(2)
+
+ property string jsonArrayJoin: jsonArray.join()
+ property string jsArrayJoin: jsArray().join()
+
+ property bool keysMatch: {
+ var iterator = jsonArray.keys();
+ for (var index of jsArray().keys()) {
+ var v = iterator.next().value;
+ if (index !== v) {
+ console.log(index, v);
+ return false;
+ }
+ }
+
+ var iterator = jsArray().keys();
+ for (var index of jsonArray.keys()) {
+ var v = iterator.next().value;
+ if (index !== v) {
+ console.log(index, v);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property int jsonArrayLastIndexOf: jsonArray.lastIndexOf(1)
+ property int jsArrayLastIndexOf: jsArray().lastIndexOf(1)
+
+ property list<string> jsonArrayMap: jsonArray.map(element => element.toString())
+ property list<string> jsArrayMap: jsArray().map(element => element.toString())
+
+ property int jsonArrayReduce: jsonArray.reduce((acc, element) => acc - element, 40)
+ property int jsArrayReduce: jsArray().reduce((acc, element) => acc - element, 40)
+
+ property string jsonArrayReduceRight: jsonArray.reduceRight((acc, element) => acc + element.toString(), "")
+ property string jsArrayReduceRight: jsArray().reduceRight((acc, element) => acc + element.toString(), "")
+
+ property list<int> jsonArraySlice: jsonArray.slice(0, 1)
+ property list<int> jsArraySlice: jsArray().slice(0, 1)
+
+ property bool jsonArraySome: jsonArray.some(element => element === 1)
+ property bool jsArraySome: jsArray().some(element => element === 1)
+
+ property string stringifiedLocaleJsonArray: jsonArray.toLocaleString()
+ property string stringifiedLocaleJsArray: jsArray().toLocaleString()
+
+ property string stringifiedJsonArray: jsonArray.toString()
+ property string stringifiedJsArray: jsArray().toString()
+
+ property bool valuesMatch: {
+ var iterator = jsonArray.values();
+ for (var obj of jsArray().values()) {
+ var v = iterator.next().value;
+ if (obj !== v) {
+ console.log(obj, v);
+ return false;
+ }
+ }
+
+ var iterator = jsArray().values();
+ for (var obj of jsonArray.values()) {
+ var v = iterator.next().value;
+ if (obj !== v) {
+ console.log(obj, v);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // In-place mutation methods.
+ // Set by onCompleted if mutating jsonArray and then accessing it
+ // respects the mutation and the mutation behaves as for an array.
+ property bool jsonArrayWasCopiedWithin: false
+ property bool jsonArrayWasFilled: false
+ property bool jsonArrayWasPopped: false
+ property bool jsonArrayWasPushed: false
+ property bool jsonArrayWasReversed: false
+ property bool jsonArrayWasShifted: false
+ property bool jsonArrayWasSpliced: false
+ property bool jsonArrayWasUnshifted: false
+ property bool jsonArrayWasSorted: false
+
+ Component.onCompleted: {
+ function equals(lhs, rhs) {
+ return lhs.toString() === rhs.toString()
+ }
+
+ jsonArray.forEach(element => jsonArrayForEach += "-" + element + "-");
+ jsArray().forEach(element => jsArrayForEach += "-" + element + "-");
+
+ var array = jsArray()
+
+ jsonArray.copyWithin(1, 0, 1)
+ array.copyWithin(1, 0, 1)
+ jsonArrayWasCopiedWithin = equals(jsonArray, array)
+
+ jsonArray.fill(7, 0, 1)
+ array.fill(7, 0, 1)
+ jsonArrayWasFilled = equals(jsonArray, array)
+
+ jsonArray.pop()
+ array.pop()
+ jsonArrayWasPopped = equals(jsonArray, array)
+
+ jsonArray.push(23)
+ jsonArray.push(11)
+ jsonArray.push(54)
+ jsonArray.push(42)
+ array.push(23)
+ array.push(11)
+ array.push(54)
+ array.push(42)
+ jsonArrayWasPushed = equals(jsonArray, array)
+
+ jsonArray.reverse()
+ array.reverse()
+ jsonArrayWasReversed = equals(jsonArray, array)
+
+ jsonArray.shift()
+ array.shift()
+ jsonArrayWasShifted = equals(jsonArray, array)
+
+ jsonArray.splice(2, 1, [1, 2], 7, [1, 5])
+ array.splice(2, 1, [1, 2], 7, [1, 5])
+ jsonArrayWasSpliced = equals(jsonArray, array)
+
+ jsonArray.unshift(4, 71)
+ array.unshift(4, 71)
+ jsonArrayWasUnshifted = equals(jsonArray, array)
+
+ jsonArray.sort()
+ array.sort()
+ jsonArrayWasSorted = equals(jsonArray, array)
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/longConversion.qml b/tests/auto/qml/qqmllanguage/data/longConversion.qml
new file mode 100644
index 0000000000..fd9a9518ee
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/longConversion.qml
@@ -0,0 +1,28 @@
+import QtQml
+import Test
+
+QtObject {
+ property bool testProp: GetterObject.getFalse()
+ property bool testQProp: GetterObject.getQFalse()
+
+ property bool fromLocal
+ property bool fromQLocal
+
+ property bool fromBoolean
+ property bool fromQBoolean
+
+ Component.onCompleted: {
+ let l = GetterObject.getFalse();
+ fromLocal = l;
+
+ let b = Boolean(l);
+ fromBoolean = b;
+
+ let ql = GetterObject.getQFalse();
+ fromQLocal = ql;
+
+
+ let qb = Boolean(ql);
+ fromQBoolean = qb;
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/manuallyCallSignalHandler.qml b/tests/auto/qml/qqmllanguage/data/manuallyCallSignalHandler.qml
new file mode 100644
index 0000000000..1ee71e5fd2
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/manuallyCallSignalHandler.qml
@@ -0,0 +1,11 @@
+import QtQml
+
+QtObject {
+ Component.onDestruction: {
+ console.log("evil!");
+ }
+
+ Component.onCompleted: {
+ Component.onDestruction()
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/nestedVectors.qml b/tests/auto/qml/qqmllanguage/data/nestedVectors.qml
new file mode 100644
index 0000000000..0bcea52133
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/nestedVectors.qml
@@ -0,0 +1,27 @@
+import Test
+import QtQml
+
+NestedVectors {
+ id: self
+
+ property var list1
+
+ Component.onCompleted: {
+ list1 = self.getList()
+
+ let list2 = []
+ let data1 = []
+ data1.push(2)
+ data1.push(3)
+ data1.push(4)
+
+ let data2 = []
+ data2.push(5)
+ data2.push(6)
+
+ list2.push(data1)
+ list2.push(data2)
+
+ self.setList(list2)
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml
index acd5463a3c..ac5622f9fb 100644
--- a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml
+++ b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.1.qml
@@ -10,7 +10,7 @@ Item {
}
}
- property bool expectNull: null
+ property bool expectNull: { return null; }
function setExpectNull(b) {
success = false;
diff --git a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml
index ed0e0d10f0..3c18739c32 100644
--- a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml
+++ b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.2.qml
@@ -10,7 +10,7 @@ Item {
}
}
- property bool expectNull: null
+ property bool expectNull: { return null; }
function setExpectNull(b) {
success = false;
diff --git a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml
index f5e94ba715..e2e560199f 100644
--- a/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml
+++ b/tests/auto/qml/qqmllanguage/data/objectDeletionNotify.3.qml
@@ -10,7 +10,7 @@ Item {
}
}
- property bool expectNull: null
+ property bool expectNull: { return null; }
function setExpectNull(b) {
success = false;
diff --git a/tests/auto/qml/qqmllanguage/data/objectInList.qml b/tests/auto/qml/qqmllanguage/data/objectInList.qml
new file mode 100644
index 0000000000..53c8c3cdd1
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/objectInList.qml
@@ -0,0 +1,17 @@
+import QtQml
+
+QtObject {
+ objectName: "parent"
+ property list<QtObject> child
+ property Component c: QtObject { objectName: "child" }
+
+ function doCreate() {
+ child.push(c.createObject(null));
+ }
+
+ Component.onCompleted: {
+ // Extra function call so that the created object cannot be on the stack
+ doCreate();
+ gc();
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/objectMethodClone.qml b/tests/auto/qml/qqmllanguage/data/objectMethodClone.qml
new file mode 100644
index 0000000000..e21179ea14
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/objectMethodClone.qml
@@ -0,0 +1,23 @@
+import QtQml
+
+QtObject {
+ id: window
+
+ property int doneClicks: 0
+
+ property UIToolBar t1: UIToolBar {
+ objectName: window.objectName
+ onDoneClicked: window.doneClicks++
+ }
+
+ property UIToolBar t2: UIToolBar {
+ objectName: window.objectName
+ onDoneClicked: window.doneClicks++
+ }
+
+ property Timer timer: Timer {
+ interval: 10
+ running: true
+ onTriggered: window.objectName = "bar"
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml b/tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml
new file mode 100644
index 0000000000..32765895a0
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/optimizedSequenceShift.qml
@@ -0,0 +1,14 @@
+import QtQml
+
+QtObject {
+ id: root
+
+ property int changes: 0
+
+ property list<int> numbers: [1, 2, 3, 4, 5]
+ onNumbersChanged: ++changes
+
+ property var one: numbers.shift.bind([1,2,3])()
+
+ Component.onCompleted: root.numbers.shift()
+}
diff --git a/tests/auto/qml/qqmllanguage/data/optionalChainCallOnNullProperty.qml b/tests/auto/qml/qqmllanguage/data/optionalChainCallOnNullProperty.qml
new file mode 100644
index 0000000000..00029e3953
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/optionalChainCallOnNullProperty.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ id: root
+ property QtObject target: null
+
+ Component.onCompleted: {
+ target?.destroy( )
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/overrideDefaultProperty.qml b/tests/auto/qml/qqmllanguage/data/overrideDefaultProperty.qml
new file mode 100644
index 0000000000..69f9316c51
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/overrideDefaultProperty.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ property list<var> data: []
+ Item {}
+}
diff --git a/tests/auto/qml/qqmllanguage/data/retainThis.qml b/tests/auto/qml/qqmllanguage/data/retainThis.qml
new file mode 100644
index 0000000000..7a372ee236
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/retainThis.qml
@@ -0,0 +1,49 @@
+import QmlOtherThis
+import QtQml
+
+QtObject {
+ property var cppMethod: objA.greet
+ property var cppMethod2: objA.sum
+
+ property Greeter a: Greeter { id: objA; objectName: "objA" }
+ property Greeter b: Greeter { id: objB; objectName: "objB" }
+
+ function doCall() {
+ cppMethod.call(objB)
+ cppMethod2(5, 6)
+ }
+
+ property var cppMethod3;
+ function doRetrieve(g) {
+ cppMethod3 = g.greet;
+ }
+
+ function doCall2() {
+ cppMethod3();
+ }
+
+ property Greeter c: Greeter {
+ id: objC
+ objectName: "objC"
+
+ property var cppMethod: objC.sum
+
+ function doCall() {
+ cppMethod(7, 7)
+ }
+ }
+
+ Component.onCompleted: {
+ doCall();
+ doCall();
+
+ doRetrieve(objA);
+ doCall2();
+ doRetrieve(objB);
+ doCall2();
+
+ objC.doCall();
+ objC.cppMethod = objB.sum;
+ objC.doCall();
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/signatureEnforced.qml b/tests/auto/qml/qqmllanguage/data/signatureEnforced.qml
index e2ddd75b55..ec00d5d2b3 100644
--- a/tests/auto/qml/qqmllanguage/data/signatureEnforced.qml
+++ b/tests/auto/qml/qqmllanguage/data/signatureEnforced.qml
@@ -8,7 +8,7 @@ QtObject {
property withLength withLength: 5
function a(r: rect) {
- r.x = 77 // does not write back
+ r.x = 77 // does write back, but this is an evil thing to do.
}
function b(s: string) : int {
@@ -28,8 +28,11 @@ QtObject {
property int n: c(99) // creates a withLength
property int o: rect.y
+ function bad(b: int) { return b }
+
Component.onCompleted: {
a(rect)
d(rect)
+ bad(15)
}
}
diff --git a/tests/auto/qml/qqmllanguage/data/signatureIgnored.qml b/tests/auto/qml/qqmllanguage/data/signatureIgnored.qml
index 0e9d0f42dc..bdb373040d 100644
--- a/tests/auto/qml/qqmllanguage/data/signatureIgnored.qml
+++ b/tests/auto/qml/qqmllanguage/data/signatureIgnored.qml
@@ -1,6 +1,6 @@
+pragma FunctionSignatureBehavior: Ignored
import StaticTest
import QtQml
-
QtObject {
property rect rect: ({ x: 12, y: 13 })
property withLength withLength: 5
diff --git a/tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml b/tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml
index 5359157b31..b86477e40a 100644
--- a/tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml
+++ b/tests/auto/qml/qqmllanguage/data/singleton/RegisteredCompositeSingletonType.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
pragma Singleton
diff --git a/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js b/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js
index 6e28624bb0..50ed2b0e66 100644
--- a/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js
+++ b/tests/auto/qml/qqmllanguage/data/singleton/js/jspragma.js
@@ -1,5 +1,5 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
.pragma library
diff --git a/tests/auto/qml/qqmllanguage/data/singletonTest17.qml b/tests/auto/qml/qqmllanguage/data/singletonTest17.qml
index 4a987e31c0..7c7bffa4ac 100644
--- a/tests/auto/qml/qqmllanguage/data/singletonTest17.qml
+++ b/tests/auto/qml/qqmllanguage/data/singletonTest17.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2013 BlackBerry Limited. All rights reserved.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import org.qtproject.Test 1.0
diff --git a/tests/auto/qml/qqmllanguage/data/typedObjectList.qml b/tests/auto/qml/qqmllanguage/data/typedObjectList.qml
new file mode 100644
index 0000000000..7e6f6e8dd9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/typedObjectList.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ property var b;
+ property Component c: QtObject {}
+
+ function returnList(a: Component) : list<Component> { return [a] }
+
+ Component.onCompleted: b = { b: returnList(c) }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/unregisteredValueTypeConversion.qml b/tests/auto/qml/qqmllanguage/data/unregisteredValueTypeConversion.qml
new file mode 100644
index 0000000000..70484d3f0e
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/unregisteredValueTypeConversion.qml
@@ -0,0 +1,10 @@
+import QtQml
+import Test
+
+UnregisteredValueTypeHandler {
+ Component.onCompleted: {
+ consume(produce())
+ consume(produceDerived())
+ consume(produceGadgeted())
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/data/variantObjectList.qml b/tests/auto/qml/qqmllanguage/data/variantObjectList.qml
new file mode 100644
index 0000000000..9ec7d4f90f
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/variantObjectList.qml
@@ -0,0 +1,17 @@
+import QtQml
+import People
+
+QtObject {
+ id: root
+
+ property QtObject b: QtObject { id: g1; objectName: "Leo Hodges" }
+ property QtObject c: QtObject { id: g2; objectName: "Jack Smith" }
+ property QtObject d: QtObject { id: g3; objectName: "Anne Brown" }
+
+ property Component pc: Component {
+ id: partyComp
+ BirthdayParty {}
+ }
+
+ property BirthdayParty q: partyComp.createObject(root, { guests: [g1, g2, g3] })
+}
diff --git a/tests/auto/qml/qqmllanguage/testhelper/CMakeLists.txt b/tests/auto/qml/qqmllanguage/testhelper/CMakeLists.txt
new file mode 100644
index 0000000000..6a58889335
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/testhelper/CMakeLists.txt
@@ -0,0 +1,13 @@
+qt_policy(SET QTP0001 NEW)
+qt_add_library(tst_qqmllanguage_qmlmodule STATIC)
+qt_autogen_tools_initial_setup(tst_qqmllanguage_qmlmodule)
+qt_add_qml_module(tst_qqmllanguage_qmlmodule
+ URI testhelper
+ VERSION 1.0
+ SOURCES
+ "declarativelyregistered.h"
+ "declarativelyregistered.cpp"
+)
+
+qt_autogen_tools_initial_setup(tst_qqmllanguage_qmlmoduleplugin)
+target_link_libraries(tst_qqmllanguage PRIVATE tst_qqmllanguage_qmlmoduleplugin)
diff --git a/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.cpp b/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.cpp
new file mode 100644
index 0000000000..24fcd83d42
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.cpp
@@ -0,0 +1,7 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+#include "declarativelyregistered.h"
+
+PurelyDeclarativeSingleton::PurelyDeclarativeSingleton() = default;
+
+#include "moc_declarativelyregistered.cpp"
diff --git a/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.h b/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.h
new file mode 100644
index 0000000000..4845cc68b9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/testhelper/declarativelyregistered.h
@@ -0,0 +1,20 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#ifndef DECLARATIVELYREGISTERED_LANGUAGE_H
+#define DECLARATIVELYREGISTERED_LANGUAGE_H
+
+#include <QtCore/qobject.h>
+#include <QtQml/qqmlregistration.h>
+
+class PurelyDeclarativeSingleton : public QObject
+{
+ Q_OBJECT
+ QML_SINGLETON
+ QML_ELEMENT
+public:
+ PurelyDeclarativeSingleton();
+};
+
+
+#endif
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index f571429b07..526cca4b5b 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include "testtypes.h"
#include <private/qv4qmlcontext_p.h>
@@ -55,6 +56,8 @@ void registerTypes()
qmlRegisterTypeNotAvailable("Test",1,0,"UnavailableType", "UnavailableType is unavailable for testing");
+ qmlRegisterTypesAndRevisions<DerivedFromUnexposedBase>("Test", 1);
+
qmlRegisterType<MyQmlObject>("Test.Version",1,0,"MyQmlObject");
qmlRegisterType<MyTypeObject>("Test.Version",1,0,"MyTypeObject");
qmlRegisterType<MyTypeObject>("Test.Version",2,0,"MyTypeObject");
@@ -92,6 +95,8 @@ void registerTypes()
qmlRegisterType<MyArrayBufferTestClass>("Test", 1, 0, "MyArrayBufferTestClass");
+ qmlRegisterTypesAndRevisions<EnumPropsManyUnderlyingTypes>("Test", 1);
+
qmlRegisterType<LazyDeferredSubObject>("Test", 1, 0, "LazyDeferredSubObject");
qmlRegisterType<DeferredProperties>("Test", 1, 0, "DeferredProperties");
qmlRegisterType<ImmediateProperties>("Test", 1, 0, "ImmediateProperties");
@@ -148,6 +153,35 @@ void registerTypes()
qmlRegisterTypesAndRevisions<BaseValueType>("ValueTypes", 1);
qmlRegisterTypesAndRevisions<DerivedValueType>("ValueTypes", 1);
+ qmlRegisterTypesAndRevisions<GetterObject>("Test", 1);
+
+ qmlRegisterNamespaceAndRevisions(&TypedEnums::staticMetaObject, "TypedEnums", 1);
+ qmlRegisterTypesAndRevisions<ObjectWithEnums>("TypedEnums", 1);
+ qmlRegisterTypesAndRevisions<GadgetWithEnums>("TypedEnums", 1);
+
+ QMetaType::registerConverter<UnregisteredValueDerivedType, UnregisteredValueBaseType>();
+ qmlRegisterTypesAndRevisions<UnregisteredValueTypeHandler>("Test", 1);
+
+ qmlRegisterTypesAndRevisions<Greeter>("QmlOtherThis", 1);
+ qmlRegisterTypesAndRevisions<BirthdayParty>("People", 1);
+ qmlRegisterTypesAndRevisions<AttachedInCtor>("Test", 1);
+
+ qmlRegisterTypesAndRevisions<ByteArrayReceiver>("Test", 1);
+
+ qmlRegisterTypesAndRevisions<Counter>("Test", 1);
+
+ qmlRegisterTypesAndRevisions<Singleton>("EnumScopeTest", 1);
+ qmlRegisterTypesAndRevisions<NonSingleton>("EnumScopeTest", 1);
+ qmlRegisterTypesAndRevisions<EnumProviderSingletonQml>("EnumScopeTest", 1);
+
+ qmlRegisterTypesAndRevisions<TypeWithQJsonArrayProperty>("TypeWithQJsonArrayProperty", 1);
+ qmlRegisterTypesAndRevisions<
+ InvokableSingleton,
+ InvokableExtended,
+ InvokableUncreatable,
+ InvokableValueType
+ >("Test", 1);
+ qmlRegisterTypesAndRevisions<NestedVectors>("Test", 1);
}
QVariant myCustomVariantTypeConverter(const QString &data)
@@ -170,7 +204,7 @@ void CustomBinding::componentComplete()
{
Q_ASSERT(m_target);
- foreach (const QV4::CompiledData::Binding *binding, bindings) {
+ for (const QV4::CompiledData::Binding *binding : std::as_const(bindings)) {
QString name = compilationUnit->stringAt(binding->propertyNameIndex);
int bindingId = binding->value.compiledScriptIndex;
@@ -248,3 +282,19 @@ UncreatableSingleton *UncreatableSingleton::instance()
static UncreatableSingleton instance;
return &instance;
}
+
+QT_BEGIN_NAMESPACE
+const QMetaObject *QtPrivate::MetaObjectForType<FakeDynamicObject *, void>::metaObjectFunction(const QMetaTypeInterface *)
+{
+ static auto ptr = []{
+ QMetaObjectBuilder builder(&FakeDynamicObject::staticMetaObject);
+ builder.setFlags(DynamicMetaObject);
+ auto mo = builder.toMetaObject();
+ QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, [mo]() {
+ delete mo;
+ });
+ return mo;
+ }();
+ return ptr;
+}
+QT_END_NAMESPACE
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 0777ed103d..ce6abf3504 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -1,11 +1,12 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
#include <QtCore/qobject.h>
#include <QtCore/qrect.h>
#include <QtCore/qdatetime.h>
+#include <QtCore/qjsonarray.h>
#include <QtGui/qtransform.h>
#include <QtGui/qcolor.h>
#include <QtGui/qvector2d.h>
@@ -18,6 +19,8 @@
#include <QtQml/qqmlpropertyvaluesource.h>
#include <QtQml/qqmlscriptstring.h>
#include <QtQml/qqmlproperty.h>
+
+#include <private/qqmlcomponentattached_p.h>
#include <private/qqmlcustomparser_p.h>
QVariant myCustomVariantTypeConverter(const QString &data);
@@ -42,6 +45,77 @@ struct MyCustomVariantType
};
Q_DECLARE_METATYPE(MyCustomVariantType);
+
+class Group : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int value MEMBER value)
+
+public:
+ Group(QObject *parent = nullptr) : QObject(parent) {}
+ int value = 0;
+};
+
+
+struct GroupGadget
+{
+ Q_GADGET
+
+ Q_PROPERTY(int value MEMBER value)
+
+public:
+ friend bool operator==(GroupGadget g1, GroupGadget g2) { return g1.value == g2.value; }
+ friend bool operator!=(GroupGadget g1, GroupGadget g2) { return !(g1 == g2); }
+ int value = 0;
+};
+
+struct FakeDynamicObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString value MEMBER value)
+
+public:
+ FakeDynamicObject() {}
+ QString value;
+};
+
+QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+// don't do this at home – we override the meta-object which QMetaType collects for
+// FakeDynamicObject* properties
+template<>
+struct MetaObjectForType<FakeDynamicObject *, void>
+{
+ static const QMetaObject *metaObjectFunction(const QMetaTypeInterface *);
+};
+}
+QT_END_NAMESPACE
+
+class UnexposedBase : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Group *group MEMBER group)
+ Q_PROPERTY(GroupGadget groupGadget MEMBER groupGadget)
+ Q_PROPERTY(FakeDynamicObject *dynamic MEMBER dynamic)
+public:
+ UnexposedBase(QObject *parent = nullptr) : QObject(parent)
+ {
+ group = new Group(this);
+ }
+ Group *group;
+ GroupGadget groupGadget;
+ FakeDynamicObject *dynamic = nullptr;
+};
+
+class DerivedFromUnexposedBase : public UnexposedBase
+{
+ Q_OBJECT
+ QML_ELEMENT
+};
+
+
class MyAttachedObject : public QObject
{
Q_OBJECT
@@ -1292,6 +1366,40 @@ public:
}
};
+class EnumPropsManyUnderlyingTypes : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ enum si8 : qint8 { ResolvedValue = 1};
+ enum ui8 : quint8 {};
+ enum si16 : qint16 {};
+ enum ui16 : quint16 {};
+ enum ui64 : qint64 {};
+ enum si64 : quint64 {};
+ Q_ENUM(si8)
+ Q_ENUM(ui8)
+ Q_ENUM(si16)
+ Q_ENUM(ui16)
+ Q_ENUM(si64)
+ Q_ENUM(ui64)
+
+
+ Q_PROPERTY(si8 si8prop MEMBER si8prop)
+ Q_PROPERTY(ui8 ui8prop MEMBER ui8prop)
+ Q_PROPERTY(si16 si16prop MEMBER si16prop)
+ Q_PROPERTY(ui16 ui16prop MEMBER ui16prop)
+ Q_PROPERTY(si64 si64prop MEMBER si64prop)
+ Q_PROPERTY(ui64 ui64prop MEMBER ui64prop)
+
+ si8 si8prop = si8(0);
+ ui8 ui8prop = ui8(0);
+ si16 si16prop = si16(0);
+ ui16 ui16prop = ui16(0);
+ si64 si64prop = si64(0);
+ ui64 ui64prop = ui64(0);
+};
+
Q_DECLARE_METATYPE(MyEnum2Class::EnumB)
Q_DECLARE_METATYPE(MyEnum1Class::EnumA)
Q_DECLARE_METATYPE(Qt::TextFormat)
@@ -1547,6 +1655,7 @@ class BareSingleton : public QObject
Q_OBJECT
QML_SINGLETON
QML_ELEMENT
+ QML_ADDED_IN_VERSION(1, 0)
public:
BareSingleton(QObject *parent = nullptr) : QObject(parent)
@@ -1560,6 +1669,7 @@ class UncreatableSingleton : public QObject
Q_OBJECT
QML_SINGLETON
QML_ELEMENT
+ QML_ADDED_IN_VERSION(1, 0)
public:
static UncreatableSingleton *instance();
@@ -2386,6 +2496,32 @@ public:
}
};
+
+struct ForeignNamespace
+{
+ Q_GADGET
+public:
+ enum Abc { A, B, C, D };
+ Q_ENUM(Abc)
+};
+
+class ForeignNamespaceForeign
+{
+ Q_GADGET
+ QML_ELEMENT
+ QML_FOREIGN_NAMESPACE(ForeignNamespace)
+};
+
+class LeakingForeignNamespaceForeign : public QObject, public ForeignNamespaceForeign
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ enum AnotherAbc { D, C, B, A };
+ Q_ENUM(AnotherAbc)
+};
+
struct ValueTypeWithLength
{
Q_GADGET
@@ -2405,4 +2541,506 @@ private:
int m_length = 19;
};
+struct ValueTypeWithString
+{
+ Q_GADGET
+ QML_VALUE_TYPE(withString)
+ QML_CONSTRUCTIBLE_VALUE
+
+public:
+ Q_INVOKABLE ValueTypeWithString(const QString &v = QString()) : m_string(v) {}
+ QString toString() const { return m_string; }
+
+private:
+ QString m_string;
+};
+
+class GetterObject : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+public:
+ explicit GetterObject(QObject *parent = nullptr) : QObject{parent} {}
+
+ // always returns a 0 as uint64_t
+ Q_INVOKABLE uint64_t getFalse() const { return 0; }
+ Q_INVOKABLE uint64_t getTrue() const { return 1; }
+
+ Q_INVOKABLE quint64 getQFalse() const { return 0; }
+ Q_INVOKABLE quint64 getQTrue() const { return 1; }
+};
+
+class EnumProviderSingleton : public QObject {
+ Q_OBJECT
+
+public:
+ enum class Expected {
+ Value = 42
+ };
+ Q_ENUM(Expected)
+
+ EnumProviderSingleton(QObject* parent = nullptr) : QObject(parent) {}
+};
+
+class EnumProviderSingletonQml {
+ Q_GADGET
+ QML_FOREIGN(EnumProviderSingleton)
+ QML_NAMED_ELEMENT(EnumProviderSingleton)
+ QML_SINGLETON
+
+public:
+ static EnumProviderSingleton* create(QQmlEngine*, QJSEngine*) {
+ return new EnumProviderSingleton();
+ }
+
+private:
+ EnumProviderSingletonQml() = default;
+};
+
+
+
+namespace TypedEnums {
+Q_NAMESPACE
+QML_ELEMENT
+
+enum E8S : qint8 {
+ E8SA = std::numeric_limits<qint8>::min(),
+ E8SB = -5,
+ E8SC = -1,
+ E8SD = 0,
+ E8SE = 1,
+ E8SF = 5,
+ E8SG = std::numeric_limits<qint8>::max(),
+};
+Q_ENUM_NS(E8S);
+
+enum E8U : quint8 {
+ E8UA = 0,
+ E8UB = 1,
+ E8UC = 5,
+ E8UD = 1 << 7,
+ E8UE = std::numeric_limits<quint8>::max(),
+};
+Q_ENUM_NS(E8U);
+
+enum E16S : qint16 {
+ E16SA = std::numeric_limits<qint16>::min(),
+ E16SB = -5,
+ E16SC = -1,
+ E16SD = 0,
+ E16SE = 1,
+ E16SF = 5,
+ E16SG = std::numeric_limits<qint16>::max(),
+};
+Q_ENUM_NS(E16S);
+
+enum E16U : quint16 {
+ E16UA = 0,
+ E16UB = 1,
+ E16UC = 5,
+ E16UD = 1 << 15,
+ E16UE = std::numeric_limits<quint16>::max(),
+};
+Q_ENUM_NS(E16U);
+
+enum E32S : qint32 {
+ E32SA = std::numeric_limits<qint32>::min(),
+ E32SB = -5,
+ E32SC = -1,
+ E32SD = 0,
+ E32SE = 1,
+ E32SF = 5,
+ E32SG = std::numeric_limits<qint32>::max(),
+};
+Q_ENUM_NS(E32S);
+
+enum E32U : quint32 {
+ E32UA = 0,
+ E32UB = 1,
+ E32UC = 5,
+ E32UD = 1u << 31,
+ E32UE = std::numeric_limits<quint32>::max(),
+};
+Q_ENUM_NS(E32U);
+
+enum E64S : qint64 {
+ E64SA = std::numeric_limits<qint64>::min(),
+ E64SB = -5,
+ E64SC = -1,
+ E64SD = 0,
+ E64SE = 1,
+ E64SF = 5,
+ E64SG = std::numeric_limits<qint64>::max(),
+};
+Q_ENUM_NS(E64S);
+
+enum E64U : quint64 {
+ E64UA = 0,
+ E64UB = 1,
+ E64UC = 5,
+ E64UD = 1ull << 63,
+ E64UE = std::numeric_limits<quint64>::max(),
+};
+Q_ENUM_NS(E64U);
+}
+
+class GadgetWithEnums
+{
+ Q_GADGET
+ QML_VALUE_TYPE(gadgetWithEnums)
+ Q_PROPERTY(TypedEnums::E8S e8s MEMBER m_e8s);
+ Q_PROPERTY(TypedEnums::E8U e8u MEMBER m_e8u);
+ Q_PROPERTY(TypedEnums::E16S e16s MEMBER m_e16s);
+ Q_PROPERTY(TypedEnums::E16U e16u MEMBER m_e16u);
+ Q_PROPERTY(TypedEnums::E32S e32s MEMBER m_e32s);
+ Q_PROPERTY(TypedEnums::E32U e32u MEMBER m_e32u);
+ Q_PROPERTY(TypedEnums::E64S e64s MEMBER m_e64s);
+ Q_PROPERTY(TypedEnums::E64U e64u MEMBER m_e64u);
+public:
+ TypedEnums::E8S m_e8s = {};
+ TypedEnums::E8U m_e8u = {};
+ TypedEnums::E16S m_e16s = {};
+ TypedEnums::E16U m_e16u = {};
+ TypedEnums::E32S m_e32s = {};
+ TypedEnums::E32U m_e32u = {};
+ TypedEnums::E64S m_e64s = {};
+ TypedEnums::E64U m_e64u = {};
+private:
+ friend bool operator==(const GadgetWithEnums &a, const GadgetWithEnums &b)
+ {
+ return a.m_e8s == b.m_e8s && a.m_e8u == b.m_e8u && a.m_e16s == b.m_e16s
+ && a.m_e16u == b.m_e16u && a.m_e32s == b.m_e32s && a.m_e32u == b.m_e32u
+ && a.m_e64s == b.m_e64s && a.m_e64u == b.m_e64u;
+ }
+ friend bool operator!=(const GadgetWithEnums &a, const GadgetWithEnums &b)
+ {
+ return !(a == b);
+ }
+};
+
+class ObjectWithEnums : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ Q_PROPERTY(TypedEnums::E8S e8s MEMBER m_e8s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E8U e8u MEMBER m_e8u NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E16S e16s MEMBER m_e16s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E16U e16u MEMBER m_e16u NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E32S e32s MEMBER m_e32s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E32U e32u MEMBER m_e32u NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E64S e64s MEMBER m_e64s NOTIFY changed);
+ Q_PROPERTY(TypedEnums::E64U e64u MEMBER m_e64u NOTIFY changed);
+ Q_PROPERTY(GadgetWithEnums g MEMBER m_g NOTIFY changed);
+public:
+ ObjectWithEnums(QObject *parent = nullptr) : QObject(parent) {}
+ TypedEnums::E8S m_e8s = {};
+ TypedEnums::E8U m_e8u = {};
+ TypedEnums::E16S m_e16s = {};
+ TypedEnums::E16U m_e16u = {};
+ TypedEnums::E32S m_e32s = {};
+ TypedEnums::E32U m_e32u = {};
+ TypedEnums::E64S m_e64s = {};
+ TypedEnums::E64U m_e64u = {};
+ GadgetWithEnums m_g;
+Q_SIGNALS:
+ void changed();
+};
+
+struct UnregisteredValueBaseType
+{
+ int foo = 12;
+};
+
+struct UnregisteredValueDerivedType: public UnregisteredValueBaseType
+{
+ int bar = 13;
+};
+
+struct GadgetedValueBaseType
+{
+ Q_GADGET
+ int foo = 12;
+};
+
+struct GadgetedValueDerivedType: public GadgetedValueBaseType
+{
+ Q_GADGET
+ int bar = 13;
+};
+
+class UnregisteredValueTypeHandler: public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ int consumed = 0;
+ int gadgeted = 0;
+
+public slots:
+ UnregisteredValueBaseType produce() { return UnregisteredValueBaseType(); }
+ UnregisteredValueDerivedType produceDerived() { return UnregisteredValueDerivedType(); }
+ void consume(UnregisteredValueBaseType) { ++consumed; }
+
+ GadgetedValueDerivedType produceGadgeted() { return GadgetedValueDerivedType(); }
+ void consume(GadgetedValueBaseType) { ++gadgeted; }
+};
+
+class Greeter : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ Greeter(QObject *parent = nullptr) : QObject(parent) {}
+
+ Q_INVOKABLE void greet()
+ {
+ qDebug().noquote() << objectName() << "says hello";
+ }
+
+ Q_INVOKABLE void sum(int a, int b)
+ {
+ qDebug().noquote() << objectName() << QString("says %1 + %2 = %3").arg(a).arg(b).arg(a + b);
+ }
+};
+
+class Attachment : public QObject {
+ Q_OBJECT
+public:
+ Attachment(QObject *parent = nullptr) : QObject(parent) {}
+};
+
+class AttachedInCtor : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_ATTACHED(Attachment)
+
+public:
+ AttachedInCtor(QObject *parent = nullptr)
+ : QObject(parent)
+ {
+ attached = qmlAttachedPropertiesObject<AttachedInCtor>(this, true);
+ }
+
+ static Attachment *qmlAttachedProperties(QObject *object) {
+ return new Attachment(object);
+ }
+
+ QObject *attached = nullptr;
+};
+
+class BirthdayParty : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<QObject> guests READ guests)
+ Q_CLASSINFO("DefaultProperty", "guests")
+ QML_ELEMENT
+
+public:
+ using QObject::QObject;
+ QQmlListProperty<QObject> guests() { return {this, &m_guests}; }
+ qsizetype guestCount() const { return m_guests.count(); }
+ QObject *guest(qsizetype i) const { return m_guests.at(i); }
+
+private:
+ QList<QObject *> m_guests;
+};
+
+class ByteArrayReceiver : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+
+public:
+ QList<QByteArray> byteArrays;
+
+ Q_INVOKABLE void byteArrayTest(const QByteArray &ba)
+ {
+ byteArrays.push_back(ba);
+ }
+};
+
+class CounterAttachedBaseType: public QObject
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+ Q_PROPERTY (int value READ value NOTIFY valueChanged)
+
+public:
+ CounterAttachedBaseType(QObject *parent = nullptr) : QObject(parent) {}
+
+ int value() { return m_value; }
+ Q_SIGNAL void valueChanged();
+
+protected:
+ int m_value = 98;
+};
+
+
+class CounterAttachedType: public CounterAttachedBaseType
+{
+ Q_OBJECT
+ QML_ANONYMOUS
+
+public:
+ CounterAttachedType(QObject *parent = nullptr) : CounterAttachedBaseType(parent) {}
+
+ Q_INVOKABLE void increase() {
+ ++m_value;
+ Q_EMIT valueChanged();
+ }
+};
+
+class Counter : public QObject
+{
+ Q_OBJECT
+ QML_ATTACHED(CounterAttachedBaseType)
+ QML_ELEMENT
+
+public:
+ static CounterAttachedBaseType *qmlAttachedProperties(QObject *o)
+ {
+ return new CounterAttachedType(o);
+ }
+};
+
+
+class Singleton: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(EnumType enumProperty READ enumProperty CONSTANT)
+ Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
+ QML_ELEMENT
+ QML_SINGLETON
+public:
+ explicit Singleton(QObject* parent = nullptr) : QObject(parent) {}
+ enum class EnumType {
+ EnumValue1,
+ EnumValue2
+ };
+ Q_ENUM(EnumType);
+ EnumType enumProperty() const {
+ return EnumType::EnumValue2;
+ }
+};
+
+class NonSingleton: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(EnumType enumProperty READ enumProperty CONSTANT)
+ Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
+ QML_ELEMENT
+public:
+ explicit NonSingleton(QObject* parent = nullptr) : QObject(parent) {}
+ enum class EnumType {
+ EnumValue1,
+ EnumValue2
+ };
+ Q_ENUM(EnumType);
+ EnumType enumProperty() const {
+ return EnumType::EnumValue2;
+ }
+};
+
+class TypeWithQJsonArrayProperty : public QObject {
+ Q_OBJECT
+ QML_ELEMENT
+
+ Q_PROPERTY(QJsonArray jsonArray READ jsonArray WRITE setJsonArray NOTIFY jsonArrayChanged)
+
+public:
+ TypeWithQJsonArrayProperty(QObject *parent = nullptr) : QObject(parent) {}
+
+ const QJsonArray& jsonArray() { return m_jsonArray; }
+ void setJsonArray(const QJsonArray& a) { m_jsonArray = a; }
+
+signals:
+ void jsonArrayChanged();
+
+private:
+ QJsonArray m_jsonArray;
+};
+
+class InvokableSingleton : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_SINGLETON
+public:
+ InvokableSingleton() = default;
+ Q_INVOKABLE InvokableSingleton(int a, QObject *parent) : QObject(parent), m_a(a) {}
+
+ int m_a = 0;
+};
+
+class InvokableExtension : public QObject
+{
+ Q_OBJECT
+public:
+ Q_INVOKABLE InvokableExtension(QObject *parent = nullptr) : QObject(parent) {}
+};
+
+class InvokableExtended : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_EXTENDED(InvokableExtension)
+
+public:
+ Q_INVOKABLE InvokableExtended() = default;
+};
+
+class InvokableUncreatable : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+ QML_UNCREATABLE("no")
+
+public:
+ Q_INVOKABLE InvokableUncreatable() = default;
+};
+
+class InvokableValueType
+{
+ Q_GADGET
+ QML_VALUE_TYPE(vv)
+public:
+ Q_INVOKABLE InvokableValueType() = default;
+ Q_INVOKABLE InvokableValueType(const QString &s) : m_s(s) {}
+ QString m_s;
+};
+
+class NestedVectors : public QObject
+{
+ Q_OBJECT
+ QML_ELEMENT
+public:
+ NestedVectors(QObject *parent = nullptr) : QObject(parent)
+ {
+ std::vector<int> data;
+ data.push_back(1);
+ data.push_back(2);
+ data.push_back(3);
+ m_list.push_back(data);
+ data.clear();
+ data.push_back(4);
+ data.push_back(5);
+ m_list.push_back(data);
+ }
+
+ Q_INVOKABLE std::vector<std::vector<int>> getList()
+ {
+ return m_list;
+ }
+
+ Q_INVOKABLE void setList(std::vector<std::vector<int>> list)
+ {
+ m_list = list;
+ }
+
+private:
+ std::vector<std::vector<int>> m_list;
+};
+
#endif // TESTTYPES_H
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index fee65fcb17..2212a40eee 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -37,7 +38,7 @@
#include <deque>
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
#include <unistd.h>
#endif
@@ -47,7 +48,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlCheckTypes, QML_CHECK_TYPES)
static inline bool isCaseSensitiveFileSystem(const QString &path) {
Q_UNUSED(path);
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
return pathconf(path.toLatin1().constData(), _PC_CASE_SENSITIVE);
#elif defined(Q_OS_WIN)
return false;
@@ -248,6 +249,8 @@ private slots:
void compositeSingletonSelectors();
void compositeSingletonRegistered();
void compositeSingletonCircular();
+ void compositeSingletonRequiredProperties();
+ void compositeSingletonRequiredProperties_data();
void singletonsHaveContextAndEngine();
@@ -316,6 +319,7 @@ private slots:
void inlineComponentFoundBeforeOtherImports();
void inlineComponentDuplicateNameError();
void inlineComponentWithAliasInstantiatedWithNewProperties();
+ void inlineComponentWithImplicitComponent();
void selfReference();
void selfReferencingSingleton();
@@ -358,6 +362,8 @@ private slots:
void hangOnWarning();
+ void groupPropertyFromNonExposedBaseClass();
+
void listEnumConversion();
void deepInlineComponentScriptBinding();
@@ -402,10 +408,62 @@ private slots:
void importPrecedence();
void nullIsNull();
void multiRequired();
+ void isNullOrUndefined();
void objectAndGadgetMethodCallsRejectThisObject();
void objectAndGadgetMethodCallsAcceptThisObject();
+ void asValueType();
+ void asValueTypeGood();
+
+ void longConversion();
+
+ void enumPropsManyUnderylingTypes();
+
+ void typedEnums_data();
+ void typedEnums();
+
+ void objectMethodClone();
+ void unregisteredValueTypeConversion();
+ void retainThis();
+
+ void variantObjectList();
+ void jitExceptions();
+
+ void attachedInCtor();
+ void byteArrayConversion();
+ void propertySignalNames_data();
+ void propertySignalNames();
+ void signalNames_data();
+ void signalNames();
+
+ void callMethodOfAttachedDerived();
+
+ void multiVersionSingletons();
+ void typeAnnotationCycle();
+ void corpseInQmlList();
+ void objectInQmlListAndGc();
+ void asCastToInlineComponent();
+ void deepAliasOnICOrReadonly();
+
+ void optionalChainCallOnNullProperty();
+
+ void ambiguousComponents();
+
+ void writeNumberToEnumAlias();
+ void badInlineComponentAnnotation();
+ void manuallyCallSignalHandler();
+ void overrideDefaultProperty();
+ void enumScopes();
+
+ void typedObjectList();
+ void invokableCtors();
+
+ void jsonArrayPropertyBehavesLikeAnArray();
+
+ void nestedVectors();
+ void optimizedSequenceShift();
+
private:
QQmlEngine engine;
QStringList defaultImportPathList;
@@ -492,11 +550,11 @@ void tst_qqmllanguage::insertedSemicolon()
QQmlComponent component(&engine, testFileUrl(file));
- QScopedPointer<QObject> object;
+ std::unique_ptr<QObject> object;
if(create) {
object.reset(component.create());
- QVERIFY(object.isNull());
+ QVERIFY(object.get());
}
VERIFY_ERRORS(errorFile.toLatin1().constData());
@@ -1381,13 +1439,13 @@ void tst_qqmllanguage::rootItemIsComponent()
QtWarningMsg,
QRegularExpression(
".*/rootItemIsComponent\\.qml:3:1: Using a Component as the root of "
- "a qmldocument is deprecated: types defined in qml documents are automatically "
- "wrapped into Components when needed\\."));
+ "a QML document is deprecated: types defined in qml documents are "
+ "automatically wrapped into Components when needed\\."));
QTest::ignoreMessage(
QtWarningMsg,
QRegularExpression(
".*/EvilComponentType\\.qml:3:1: Using a Component as the root of a "
- "qmldocument is deprecated: types defined in qml documents are automatically "
+ "QML document is deprecated: types defined in qml documents are automatically "
"wrapped into Components when needed\\."));
QTest::ignoreMessage(
QtWarningMsg,
@@ -1707,8 +1765,8 @@ void tst_qqmllanguage::propertyValueSource()
QVERIFY(object != nullptr);
QList<QObject *> valueSources;
- QObjectList allChildren = object->findChildren<QObject*>();
- foreach (QObject *child, allChildren) {
+ const QObjectList allChildren = object->findChildren<QObject*>();
+ for (QObject *child : allChildren) {
if (qobject_cast<QQmlPropertyValueSource *>(child))
valueSources.append(child);
}
@@ -1728,8 +1786,8 @@ void tst_qqmllanguage::propertyValueSource()
QVERIFY(object != nullptr);
QList<QObject *> valueSources;
- QObjectList allChildren = object->findChildren<QObject*>();
- foreach (QObject *child, allChildren) {
+ const QObjectList allChildren = object->findChildren<QObject*>();
+ for (QObject *child : allChildren) {
if (qobject_cast<QQmlPropertyValueSource *>(child))
valueSources.append(child);
}
@@ -2039,7 +2097,7 @@ void tst_qqmllanguage::aliasProperties()
MyQmlObject *o = qvariant_cast<MyQmlObject*>(v);
QCOMPARE(o->value(), 10);
- delete o;
+ delete o; //intentional delete
v = object->property("otherAlias");
QCOMPARE(v.typeId(), qMetaTypeId<MyQmlObject *>());
@@ -2074,7 +2132,7 @@ void tst_qqmllanguage::aliasProperties()
QObject *alias = qvariant_cast<QObject *>(object->property("aliasedObject"));
QCOMPARE(alias, object2);
- delete object1;
+ delete object1; //intentional delete
QObject *alias2 = object.data(); // "Random" start value
int status = -1;
@@ -2583,7 +2641,7 @@ void tst_qqmllanguage::scriptStringWithoutSourceCode()
Q_ASSERT(td);
QVERIFY(!td->backupSourceCode().isValid());
- QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit = td->compilationUnit();
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = td->compilationUnit();
readOnlyQmlUnit.reset(compilationUnit->unitData());
Q_ASSERT(readOnlyQmlUnit);
QV4::CompiledData::Unit *qmlUnit = reinterpret_cast<QV4::CompiledData::Unit *>(malloc(readOnlyQmlUnit->unitSize));
@@ -2863,7 +2921,8 @@ void tst_qqmllanguage::testType(const QString& qml, const QString& type, const Q
if (type.isEmpty()) {
QVERIFY(component.isError());
QString actualerror;
- foreach (const QQmlError e, component.errors()) {
+ const auto errors = component.errors();
+ for (const QQmlError &e : errors) {
if (!actualerror.isEmpty())
actualerror.append("; ");
actualerror.append(e.description());
@@ -3861,6 +3920,7 @@ void tst_qqmllanguage::initTestCase()
qmlRegisterType(testFileUrl("invalidRoot.1.qml"), "Test", 1, 0, "RegisteredCompositeType3");
qmlRegisterType(testFileUrl("CompositeTypeWithEnum.qml"), "Test", 1, 0, "RegisteredCompositeTypeWithEnum");
qmlRegisterType(testFileUrl("CompositeTypeWithAttachedProperty.qml"), "Test", 1, 0, "RegisteredCompositeTypeWithAttachedProperty");
+ qmlRegisterType(testFileUrl("CompositeTypeWithEnumSelfReference.qml"), "Test", 1, 0, "CompositeTypeWithEnumSelfReference");
// Registering the TestType class in other modules should have no adverse effects
qmlRegisterType<TestType>("org.qtproject.TestPre", 1, 0, "Test");
@@ -3889,6 +3949,7 @@ void tst_qqmllanguage::initTestCase()
// Register a Composite Singleton.
qmlRegisterSingletonType(testFileUrl("singleton/RegisteredCompositeSingletonType.qml"), "org.qtproject.Test", 1, 0, "RegisteredSingleton");
+ qmlRegisterType(testFileUrl("Comps/OverlayDrawer.qml"), "Comps", 2, 0, "OverlayDrawer");
}
void tst_qqmllanguage::aliasPropertyChangeSignals()
@@ -4036,6 +4097,17 @@ void tst_qqmllanguage::registeredCompositeTypeWithEnum()
QCOMPARE(o->property("enumValue0").toInt(), static_cast<int>(MyCompositeBaseType::EnumValue0));
QCOMPARE(o->property("enumValue42").toInt(), static_cast<int>(MyCompositeBaseType::EnumValue42));
QCOMPARE(o->property("enumValue15").toInt(), static_cast<int>(MyCompositeBaseType::ScopedCompositeEnum::EnumValue15));
+
+ {
+ QQmlComponent component(&engine);
+ component.setData("import Test\nCompositeTypeWithEnumSelfReference {}", QUrl());
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(o != nullptr);
+
+ QCOMPARE(o->property("e").toInt(), 1);
+ QCOMPARE(o->property("f").toInt(), 2);
+ }
}
// QTBUG-43581
@@ -4212,7 +4284,8 @@ void tst_qqmllanguage::lowercaseEnumRuntime()
QQmlComponent component(&engine, testFileUrl(file));
VERIFY_ERRORS(0);
- delete component.create();
+ std::unique_ptr<QObject> root { component.create() };
+ QVERIFY(root);
}
void tst_qqmllanguage::lowercaseEnumCompileTime_data()
@@ -4229,7 +4302,8 @@ void tst_qqmllanguage::lowercaseEnumCompileTime()
QQmlComponent component(&engine, testFileUrl(file));
VERIFY_ERRORS(0);
- delete component.create();
+ std::unique_ptr<QObject> root { component.create() };
+ QVERIFY(root);
}
void tst_qqmllanguage::scopedEnum()
@@ -4473,7 +4547,6 @@ void tst_qqmllanguage::groupAssignmentFailure()
{
auto ep = std::make_unique<QQmlEngine>();
QTest::failOnWarning("QQmlComponent: Component destroyed while completion pending");
- QTest::ignoreMessage(QtMsgType::QtWarningMsg, QRegularExpression(".*Invalid property assignment: url expected - Assigning null to incompatible properties in QML is deprecated. This will become a compile error in future versions of Qt..*"));
QQmlComponent component(ep.get(), testFileUrl("groupFailure.qml"));
QScopedPointer<QObject> o(component.create());
QVERIFY(!o);
@@ -4844,6 +4917,36 @@ void tst_qqmllanguage::compositeSingletonCircular()
QCOMPARE(o->property("value").toInt(), 2);
}
+void tst_qqmllanguage::compositeSingletonRequiredProperties()
+{
+ QFETCH(QString, warning);
+ QFETCH(QString, singletonName);
+ QQmlEngine engine;
+ engine.addImportPath(dataDirectory());
+ {
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(warning));
+ std::unique_ptr<QObject> singleton {engine.singletonInstance<QObject *>(
+ "SingletonWithRequiredProperties",
+ singletonName
+ )};
+ QVERIFY(!singleton);
+ }
+}
+
+void tst_qqmllanguage::compositeSingletonRequiredProperties_data()
+{
+ QTest::addColumn<QString>("warning");
+ QTest::addColumn<QString>("singletonName");
+
+ QString warning1 = testFileUrl("SingletonWithRequiredProperties/SingletonWithRequired1.qml").toString()
+ + ":5:5: Required property i was not initialized";
+ QString warning2 = testFileUrl("SingletonWithRequiredProperties/SingletonWithRequired2.qml").toString()
+ + ":6:9: Required property i was not initialized";
+
+ QTest::addRow("toplevelRequired") << warning1 << "SingletonWithRequired1";
+ QTest::addRow("subObjectRequired") << warning2 << "SingletonWithRequired2";
+}
+
void tst_qqmllanguage::singletonsHaveContextAndEngine()
{
QObject *qmlSingleton = nullptr;
@@ -5348,24 +5451,30 @@ void tst_qqmllanguage::namespacedPropertyTypes()
void tst_qqmllanguage::qmlTypeCanBeResolvedByName_data()
{
QTest::addColumn<QUrl>("componentUrl");
+ QTest::addColumn<QString>("name");
// Built-in C++ types
- QTest::newRow("C++ - Anonymous") << testFileUrl("quickTypeByName_anon.qml");
- QTest::newRow("C++ - Named") << testFileUrl("quickTypeByName_named.qml");
+ QTest::newRow("C++ - Anonymous") << testFileUrl("quickTypeByName_anon.qml")
+ << QStringLiteral("QtQuick/Item");
+ QTest::newRow("C++ - Named") << testFileUrl("quickTypeByName_named.qml")
+ << QStringLiteral("QtQuick/Item");
// Composite types with a qmldir
- QTest::newRow("QML - Anonymous - qmldir") << testFileUrl("compositeTypeByName_anon_qmldir.qml");
- QTest::newRow("QML - Named - qmldir") << testFileUrl("compositeTypeByName_named_qmldir.qml");
+ QTest::newRow("QML - Anonymous - qmldir") << testFileUrl("compositeTypeByName_anon_qmldir.qml")
+ << QStringLiteral("SimpleType");
+ QTest::newRow("QML - Named - qmldir") << testFileUrl("compositeTypeByName_named_qmldir.qml")
+ << QStringLiteral("SimpleType");
}
void tst_qqmllanguage::qmlTypeCanBeResolvedByName()
{
QFETCH(QUrl, componentUrl);
+ QFETCH(QString, name);
QQmlEngine engine;
QQmlComponent component(&engine, componentUrl);
VERIFY_ERRORS(0);
- QTest::ignoreMessage(QtMsgType::QtWarningMsg, "[object Object]"); // a bit crude, but it will do
+ QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(name));
QScopedPointer<QObject> o(component.create());
QVERIFY(!o.isNull());
@@ -5654,6 +5763,9 @@ void tst_qqmllanguage::retrieveQmlTypeId()
QVERIFY(qmlTypeId("Test", 1, 0, "MyExtendedUncreateableBaseClass") >= 0);
QVERIFY(qmlTypeId("Test", 1, 0, "MyUncreateableBaseClass") >= 0);
QVERIFY(qmlTypeId("Test", 1, 0, "MyTypeObjectSingleton") >= 0);
+
+ // Must also work for declaratively registered types whose module wasn't imported so far
+ QVERIFY(qmlTypeId("testhelper", 1, 0, "PurelyDeclarativeSingleton") >= 0);
}
void tst_qqmllanguage::polymorphicFunctionLookup()
@@ -5749,7 +5861,7 @@ void tst_qqmllanguage::selfReference()
const QMetaObject *metaObject = o->metaObject();
QMetaProperty selfProperty = metaObject->property(metaObject->indexOfProperty("self"));
- QCOMPARE(selfProperty.metaType().id(), compilationUnit->typeIds.id.id());
+ QCOMPARE(selfProperty.metaType().id(), compilationUnit->metaType().id());
QByteArray typeName = selfProperty.typeName();
QVERIFY(typeName.endsWith('*'));
@@ -5758,7 +5870,7 @@ void tst_qqmllanguage::selfReference()
QMetaMethod selfFunction = metaObject->method(metaObject->indexOfMethod("returnSelf()"));
QVERIFY(selfFunction.isValid());
- QCOMPARE(selfFunction.returnType(), compilationUnit->typeIds.id.id());
+ QCOMPARE(selfFunction.returnType(), compilationUnit->metaType().id());
QMetaMethod selfSignal;
@@ -5772,7 +5884,7 @@ void tst_qqmllanguage::selfReference()
QVERIFY(selfSignal.isValid());
QCOMPARE(selfSignal.parameterCount(), 1);
- QCOMPARE(selfSignal.parameterType(0), compilationUnit->typeIds.id.id());
+ QCOMPARE(selfSignal.parameterType(0), compilationUnit->metaType().id());
}
void tst_qqmllanguage::selfReferencingSingleton()
@@ -5809,10 +5921,10 @@ void tst_qqmllanguage::listContainingDeletedObject()
QVERIFY(root);
auto cmp = root->property("a").value<QQmlComponent*>();
- auto o = cmp->create();
+ std::unique_ptr<QObject> o { cmp->create() };
- QMetaObject::invokeMethod(root.get(), "doAssign", Q_ARG(QVariant, QVariant::fromValue(o)));
- delete o;
+ QMetaObject::invokeMethod(root.get(), "doAssign", Q_ARG(QVariant, QVariant::fromValue(o.get())));
+ o.reset();
QMetaObject::invokeMethod(root.get(), "use");
}
@@ -6096,6 +6208,17 @@ void tst_qqmllanguage::inlineComponentWithAliasInstantiatedWithNewProperties()
QCOMPARE(root->property("result").toString(), "Bar");
}
+void tst_qqmllanguage::inlineComponentWithImplicitComponent()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("inlineComponentWithImplicitComponent.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(root);
+
+ QCOMPARE(root->objectName(), "green blue"_L1);
+}
+
struct QJSValueConvertible {
Q_GADGET
@@ -6392,23 +6515,15 @@ void tst_qqmllanguage::extendedSingleton()
void tst_qqmllanguage::qtbug_85932()
{
- QString warning1 = QLatin1String("%1:10:9: id is not unique").arg(testFileUrl("SingletonTest.qml").toString());
- QString warning2 = QLatin1String("%1:4: Error: Due to the preceding error(s), Singleton \"SingletonTest\" could not be loaded.").arg(testFileUrl("qtbug_85932.qml").toString());
-
- QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(warning1));
- QTest::ignoreMessage(QtMsgType::QtWarningMsg, qPrintable(warning2));
-
QQmlEngine engine;
- QList<QQmlError> allWarnings;
- QObject::connect(&engine, &QQmlEngine::warnings, [&allWarnings](const QList<QQmlError> &warnings) {
- allWarnings.append(warnings);
- });
- QQmlComponent c(&engine, testFileUrl("qtbug_85932.qml"));
- QScopedPointer<QObject> obj(c.create());
- QTRY_COMPARE(allWarnings.size(), 2);
- QCOMPARE(allWarnings.at(0).toString(), warning1);
- QCOMPARE(allWarnings.at(1).toString(), warning2);
+ QQmlComponent c(&engine, testFileUrl("badSingleton/qtbug_85932.qml"));
+ QVERIFY(c.isError());
+
+ const QString error = c.errorString();
+ QVERIFY(error.contains(QLatin1String("Type SingletonTest unavailable")));
+ QVERIFY(error.contains(QLatin1String("%1:10 id is not unique")
+ .arg(testFileUrl("badSingleton/SingletonTest.qml").toString())));
}
void tst_qqmllanguage::multiExtension()
@@ -6758,15 +6873,22 @@ void tst_qqmllanguage::bareInlineComponent()
if (type.elementName() == QStringLiteral("Tab1")) {
QVERIFY(type.module().isEmpty());
tab1Found = true;
- const auto ics = type.priv()->objectIdToICType;
- QVERIFY(ics.size() > 0);
- for (const QQmlType &ic : ics)
- QVERIFY(ic.containingType() == type);
+
+ const QQmlType leftTab = QQmlMetaType::inlineComponentType(type, "LeftTab");
+ QUrl leftUrl = leftTab.sourceUrl();
+ leftUrl.setFragment(QString());
+ QCOMPARE(leftUrl, type.sourceUrl());
+
+ const QQmlType rightTab = QQmlMetaType::inlineComponentType(type, "RightTab");
+ QUrl rightUrl = rightTab.sourceUrl();
+ rightUrl.setFragment(QString());
+ QCOMPARE(rightUrl, type.sourceUrl());
}
}
QVERIFY(tab1Found);
}
+#if QT_CONFIG(qml_debug)
struct DummyDebugger : public QV4::Debugging::Debugger
{
bool pauseAtNextOpportunity() const final { return false; }
@@ -6775,6 +6897,9 @@ struct DummyDebugger : public QV4::Debugging::Debugger
void leavingFunction(const QV4::ReturnedValue &) final { }
void aboutToThrow() final { }
};
+#else
+using DummyDebugger = QV4::Debugging::Debugger; // it's already dummy
+#endif
void tst_qqmllanguage::hangOnWarning()
{
@@ -6792,6 +6917,25 @@ void tst_qqmllanguage::hangOnWarning()
QVERIFY(object != nullptr);
}
+void tst_qqmllanguage::groupPropertyFromNonExposedBaseClass()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("derivedFromUnexposedBase.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ auto root = qobject_cast<DerivedFromUnexposedBase *>(o.get());
+ QVERIFY(root);
+ QVERIFY(root->group);
+ QCOMPARE(root->group->value, 42);
+ QCOMPARE(root->groupGadget.value, 42);
+
+ c.loadUrl(testFileUrl("dynamicGroupPropertyRejected.qml"));
+ QVERIFY(c.isError());
+ QVERIFY2(c.errorString().contains("Unsupported grouped property access"), qPrintable(c.errorString()));
+}
+
void tst_qqmllanguage::listEnumConversion()
{
QQmlEngine e;
@@ -7424,6 +7568,33 @@ LeakingForeignerForeign {
QVERIFY(o->property("anotherAbc").isValid());
QVERIFY(!o->property("abc").isValid());
}
+
+ {
+ QQmlComponent c(&engine);
+ c.setData(R"(
+import StaticTest
+import QtQml
+QtObject {
+ objectName: 'b' + ForeignNamespaceForeign.B
+})", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->objectName(), "b1");
+ }
+ {
+ QQmlComponent c(&engine);
+ c.setData(R"(
+import StaticTest
+import QtQml
+QtObject {
+ objectName: 'b' + LeakingForeignNamespaceForeign.B
+})", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o);
+ QCOMPARE(o->objectName(), "b2");
+ }
}
void tst_qqmllanguage::attachedOwnProperties()
@@ -7711,12 +7882,20 @@ void tst_qqmllanguage::functionSignatureEnforcement()
QCOMPARE(ignored->property("m").toInt(), 77);
QCOMPARE(ignored->property("n").toInt(), 67);
- QQmlComponent c2(&engine, testFileUrl("signatureEnforced.qml"));
+ const QUrl url2 = testFileUrl("signatureEnforced.qml");
+ QQmlComponent c2(&engine, url2);
QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
+ QTest::ignoreMessage(
+ QtCriticalMsg,
+ qPrintable(url2.toString() + u":36: 15 should be coerced to void because the function "
+ "called is insufficiently annotated. The original value "
+ "is retained. "
+ "This will change in a future version of Qt."_s));
+
QScopedPointer<QObject> enforced(c2.create());
QCOMPARE(enforced->property("l").toInt(), 2); // strlen("no")
- QCOMPARE(enforced->property("m").toInt(), 12);
+ QCOMPARE(enforced->property("m").toInt(), 77);
QCOMPARE(enforced->property("n").toInt(), 99);
QCOMPARE(enforced->property("o").toInt(), 77);
}
@@ -7766,6 +7945,30 @@ void tst_qqmllanguage::multiRequired()
qPrintable(url.toString() + ":5 Required property description was not initialized\n"));
}
+// QTBUG-111088
+void tst_qqmllanguage::isNullOrUndefined()
+{
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("isNullOrUndefined_interpreter.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVariant result = o.data()->property("result");
+ QVERIFY(result.isValid());
+ QCOMPARE(result.toInt(), 3);
+ }
+
+ {
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("isNullOrUndefined_jit.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVariant result = o.data()->property("result");
+ QVERIFY(result.isValid());
+ QCOMPARE(result.toInt(), 150);
+ }
+}
+
void tst_qqmllanguage::objectAndGadgetMethodCallsRejectThisObject()
{
QQmlEngine engine;
@@ -7810,6 +8013,15 @@ void tst_qqmllanguage::objectAndGadgetMethodCallsAcceptThisObject()
QQmlComponent c(&engine, testFileUrl("objectAndGadgetMethodCallsAcceptThisObject.qml"));
QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ // Explicitly retrieve the metaobject for the Qt singleton so that the proxy data is created.
+ // This way the inheritance analysis we do when figuring out what toString() means is somewhat
+ // more interesting. Also, we get a deterministic result for Qt.toString().
+ const QQmlType qtType = QQmlMetaType::qmlType(QStringLiteral("Qt"), QString(), QTypeRevision());
+ QVERIFY(qtType.isValid());
+ const QMetaObject *qtMeta = qtType.metaObject();
+ QVERIFY(qtMeta);
+ QCOMPARE(QString::fromUtf8(qtMeta->className()), QLatin1String("Qt"));
+
QTest::ignoreMessage(
QtWarningMsg, QRegularExpression(
"objectAndGadgetMethodCallsAcceptThisObject.qml:16: Error: "
@@ -7840,7 +8052,7 @@ void tst_qqmllanguage::objectAndGadgetMethodCallsAcceptThisObject()
QCOMPARE(o->property("goodString2"), QStringLiteral("27"));
QCOMPARE(o->property("goodString3"), QStringLiteral("28"));
- QVERIFY(o->property("goodString4").value<QString>().startsWith("QtObject"_L1));
+ QVERIFY(o->property("goodString4").value<QString>().startsWith("Qt("_L1));
QCOMPARE(o->property("badString2"), QString());
QCOMPARE(o->property("badInt"), 0);
@@ -7849,6 +8061,906 @@ void tst_qqmllanguage::objectAndGadgetMethodCallsAcceptThisObject()
QCOMPARE(o->property("goodInt3"), 5);
}
+void tst_qqmllanguage::longConversion()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("longConversion.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ for (const char *prop : {
+ "testProp",
+ "testQProp",
+ "fromLocal",
+ "fromQLocal",
+ "fromBoolean",
+ "fromQBoolean"}) {
+ const QVariant val = o->property(prop);
+ QVERIFY(val.isValid());
+ QCOMPARE(val.metaType(), QMetaType::fromType<bool>());
+ QVERIFY(!val.toBool());
+ }
+}
+
+void tst_qqmllanguage::enumPropsManyUnderylingTypes()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("enumPropsManyUnderlyingTypes.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ auto *enumObject = qobject_cast<EnumPropsManyUnderlyingTypes *>(o.get());
+ QCOMPARE(enumObject->si8prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->ui8prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->si16prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->ui16prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->si64prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+ QCOMPARE(enumObject->ui64prop, EnumPropsManyUnderlyingTypes::ResolvedValue);
+}
+
+void tst_qqmllanguage::asValueType()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("asValueType.qml");
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Could not find any constructor for value type QQmlRectFValueType "
+ "to call with value undefined");
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":7:5: Unable to assign [undefined] to QRectF"_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":10: Coercing a value to QML/point using a type "
+ "assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":14: Coercing between incompatible value types mistakenly "
+ "yields null rather than undefined. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent this."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":15: Coercing from instances of object types to value "
+ "types mistakenly yields null rather than undefined. Add "
+ "'pragma ValueTypeBehavior: Assertable' to prevent "
+ "this."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":16: Coercing a value to QML/size using a type "
+ "assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":11: Coercing a value to StaticTest/withString using a "
+ "type assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ "Could not find any constructor for value type QQmlSizeFValueType to call "
+ "with value 11");
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":18: Coercing a value to QML/size using a type "
+ "assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":19: Coercing a value to QML/size using a type "
+ "assertion. This behavior is deprecated. Add 'pragma "
+ "ValueTypeBehavior: Assertable' to prevent it."_L1));
+
+ QScopedPointer<QObject> o(c.create());
+
+ QCOMPARE(o->property("a"), QVariant());
+ QCOMPARE(o->property("b").value<QRectF>(), QRectF());
+ QVERIFY(!o->property("c").toBool());
+
+ const QRectF rect(1, 2, 3, 4);
+ o->setProperty("a", QVariant(rect));
+ QCOMPARE(o->property("b").value<QRectF>(), rect);
+ QVERIFY(o->property("c").toBool());
+
+ QVERIFY(!o->property("d").toBool());
+ const QPointF point = o->property("e").value<QPointF>();
+ QCOMPARE(point.x(), 10.0);
+ QCOMPARE(point.y(), 20.0);
+
+ const ValueTypeWithString withString = o->property("f").value<ValueTypeWithString>();
+ QCOMPARE(withString.toString(), u"red");
+
+ const QVariant string = o->property("g");
+ QCOMPARE(string.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(string.toString(), u"green");
+
+ const QVariant p = o->property("p");
+ QCOMPARE(p.metaType(), QMetaType::fromType<std::nullptr_t>());
+
+ const QVariant q = o->property("q");
+ QCOMPARE(q.metaType(), QMetaType::fromType<std::nullptr_t>());
+
+ const QVariant r = o->property("r");
+ QCOMPARE(r.metaType(), QMetaType::fromType<QSizeF>());
+ QCOMPARE(r.value<QSizeF>(), QSizeF());
+
+ const QVariant s = o->property("s");
+ QCOMPARE(s.metaType(), QMetaType());
+
+ const QVariant t = o->property("t");
+ QCOMPARE(t.metaType(), QMetaType::fromType<QSizeF>());
+ QCOMPARE(t.value<QSizeF>(), QSizeF());
+
+ const QVariant u = o->property("u");
+ QCOMPARE(u.metaType(), QMetaType::fromType<QSizeF>());
+ QCOMPARE(u.value<QSizeF>(), QSizeF());
+}
+
+void tst_qqmllanguage::asValueTypeGood()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("asValueTypeGood.qml");
+ QQmlComponent c(&engine, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + ":7:5: Unable to assign [undefined] to QRectF"_L1));
+ QScopedPointer<QObject> o(c.create());
+
+ QCOMPARE(o->property("a"), QVariant());
+ QCOMPARE(o->property("b").value<QRectF>(), QRectF());
+ QVERIFY(!o->property("c").toBool());
+
+ const QRectF rect(1, 2, 3, 4);
+ o->setProperty("a", QVariant(rect));
+ QCOMPARE(o->property("b").value<QRectF>(), rect);
+ QVERIFY(o->property("c").toBool());
+
+ QVERIFY(!o->property("d").toBool());
+ QVERIFY(!o->property("e").isValid());
+ QVERIFY(!o->property("f").isValid());
+
+ const QVariant string = o->property("g");
+ QCOMPARE(string.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(string.toString(), u"green");
+
+ const ValueTypeWithString withString = o->property("h").value<ValueTypeWithString>();
+ QCOMPARE(withString.toString(), u"red");
+
+ const QPointF point = o->property("i").value<QPointF>();
+ QCOMPARE(point.x(), 10.0);
+ QCOMPARE(point.y(), 20.0);
+
+ const QVariant j = o->property("j");
+ QCOMPARE(j.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(j.toInt(), 4);
+
+ QVERIFY(!o->property("k").isValid());
+ QVERIFY(!o->property("l").isValid());
+
+ const QVariant m = o->property("m");
+ QCOMPARE(m.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(m.toString(), u"something");
+
+ QVERIFY(!o->property("n").isValid());
+ QVERIFY(!o->property("o").isValid());
+ QVERIFY(!o->property("p").isValid());
+ QVERIFY(!o->property("q").isValid());
+ QVERIFY(!o->property("r").isValid());
+ QVERIFY(!o->property("s").isValid());
+ QVERIFY(!o->property("t").isValid());
+ QVERIFY(!o->property("u").isValid());
+}
+
+void tst_qqmllanguage::typedEnums_data()
+{
+ QTest::addColumn<QString>("property");
+ QTest::addColumn<double>("value");
+ const QMetaObject *mo = &TypedEnums::staticMetaObject;
+ for (int i = 0, end = mo->enumeratorCount(); i != end; ++i) {
+ const QMetaEnum e = mo->enumerator(i);
+ for (int k = 0, end = e.keyCount(); k != end; ++k) {
+ QTest::addRow("%s::%s", e.name(), e.key(k))
+ << QString::fromLatin1(e.name()).toLower()
+ << double(e.value(k));
+ }
+ }
+}
+void tst_qqmllanguage::typedEnums()
+{
+ QFETCH(QString, property);
+ QFETCH(double, value);
+ QQmlEngine e;
+ const QString qml = QLatin1String(R"(
+ import QtQml
+ import TypedEnums
+ ObjectWithEnums {
+ property real input: %2
+ %1: input
+ g.%1: input
+ property real output1: %1
+ property real output2: g.%1
+ }
+ )").arg(property).arg(value, 0, 'f');
+ QQmlComponent c(&engine);
+ c.setData(qml.toUtf8(), QUrl("enums.qml"_L1));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ // TODO: This silently fails for quint32, qint64 and quint64 because QMetaEnum cannot encode
+ // such values either. For the 64bit values we'll also need a better type than double
+ // inside QML.
+ QEXPECT_FAIL("E32U::E32UD", "Not supported", Abort);
+ QEXPECT_FAIL("E32U::E32UE", "Not supported", Abort);
+ QEXPECT_FAIL("E64U::E64UE", "Not supported", Abort);
+
+ QCOMPARE(o->property("output1").toDouble(), value);
+ QCOMPARE(o->property("output2").toDouble(), value);
+}
+
+void tst_qqmllanguage::objectMethodClone()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("objectMethodClone.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QTRY_COMPARE(o->property("doneClicks").toInt(), 2);
+}
+
+void tst_qqmllanguage::unregisteredValueTypeConversion()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("unregisteredValueTypeConversion.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ UnregisteredValueTypeHandler *handler = qobject_cast<UnregisteredValueTypeHandler *>(o.data());
+ Q_ASSERT(handler);
+ QCOMPARE(handler->consumed, 2);
+ QCOMPARE(handler->gadgeted, 1);
+}
+
+void tst_qqmllanguage::retainThis()
+{
+ QQmlEngine e;
+ const QUrl url = testFileUrl("retainThis.qml");
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ const QString warning = u"Calling C++ methods with 'this' objects different "
+ "from the one they were retrieved from is broken, due to "
+ "historical reasons. The original object is used as 'this' "
+ "object. You can allow the given 'this' object to be used "
+ "by setting 'pragma NativeMethodBehavior: AcceptThisObject'"_s;
+
+ // Both cases objA because we retain the thisObject.
+ for (int i = 0; i < 2; ++i) {
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":12: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objA says hello");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":13: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objA says 5 + 6 = 11");
+ }
+
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":22: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objA says hello");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":22: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objB says hello");
+
+ QTest::ignoreMessage(QtDebugMsg, "objC says 7 + 7 = 14");
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(url.toString() + u":32: "_s + warning));
+ QTest::ignoreMessage(QtDebugMsg, "objB says 7 + 7 = 14");
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
+
+void tst_qqmllanguage::variantObjectList()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("variantObjectList.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ BirthdayParty *party = o->property("q").value<BirthdayParty *>();
+ QCOMPARE(party->guestCount(), 3);
+ QCOMPARE(party->guest(0)->objectName(), "Leo Hodges");
+ QCOMPARE(party->guest(1)->objectName(), "Jack Smith");
+ QCOMPARE(party->guest(2)->objectName(), "Anne Brown");
+}
+
+void tst_qqmllanguage::jitExceptions()
+{
+ QQmlEngine e;
+ const QUrl url = testFileUrl("jitExceptions.qml");
+ QQmlComponent c(&e, testFileUrl("jitExceptions.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(url.toString() + u":5: ReferenceError: control is not defined"_s));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
+
+void tst_qqmllanguage::attachedInCtor()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e);
+ c.setData(R"(
+ import Test
+ AttachedInCtor {}
+ )", QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ AttachedInCtor *a = qobject_cast<AttachedInCtor *>(o.data());
+ QVERIFY(a->attached);
+ QCOMPARE(a->attached, qmlAttachedPropertiesObject<AttachedInCtor>(a, false));
+}
+
+void tst_qqmllanguage::byteArrayConversion()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e);
+ c.setData(R"(
+ import Test
+ import QtQml
+ ByteArrayReceiver {
+ Component.onCompleted: {
+ byteArrayTest([1, 2, 3]);
+ byteArrayTest(Array.from('456'));
+ }
+ }
+ )", QUrl());
+
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ ByteArrayReceiver *receiver = qobject_cast<ByteArrayReceiver *>(o.data());
+ QVERIFY(receiver);
+ QCOMPARE(receiver->byteArrays.length(), 2);
+ QCOMPARE(receiver->byteArrays[0], QByteArray("\1\2\3"));
+ QCOMPARE(receiver->byteArrays[1], QByteArray("\4\5\6"));
+}
+void tst_qqmllanguage::propertySignalNames_data()
+{
+ QTest::addColumn<QString>("propertyName");
+ QTest::addColumn<QString>("propertyChangedSignal");
+ QTest::addColumn<QString>("propertyChangedHandler");
+ QTest::addRow("helloWorld") << u"helloWorld"_s << u"helloWorldChanged"_s
+ << u"onHelloWorldChanged"_s;
+ QTest::addRow("$helloWorld") << u"$helloWorld"_s << u"$helloWorldChanged"_s
+ << u"on$HelloWorldChanged"_s;
+ QTest::addRow("_helloWorld") << u"_helloWorld"_s << u"_helloWorldChanged"_s
+ << u"on_HelloWorldChanged"_s;
+ QTest::addRow("_") << u"_"_s << u"_Changed"_s << u"on_Changed"_s;
+ QTest::addRow("$") << u"$"_s << u"$Changed"_s << u"on$Changed"_s;
+ QTest::addRow("ä") << u"ä"_s << u"äChanged"_s << u"onÄChanged"_s;
+ QTest::addRow("___123a") << u"___123a"_s << u"___123aChanged"_s << u"on___123AChanged"_s;
+}
+void tst_qqmllanguage::propertySignalNames()
+{
+ QFETCH(QString, propertyName);
+ QFETCH(QString, propertyChangedSignal);
+ QFETCH(QString, propertyChangedHandler);
+ QQmlEngine e;
+ QQmlComponent c(&e);
+ c.setData(uR"(
+import QtQuick
+Item {
+ property int %1: 456
+ property bool success: false
+ function f() { %1 = 123; }
+ function g() { %2(); }
+ %3: success = true
+})"_s.arg(propertyName, propertyChangedSignal, propertyChangedHandler)
+ .toUtf8(),
+ QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o != nullptr);
+ const QMetaObject *metaObject = o->metaObject();
+ auto signalIndex =
+ metaObject->indexOfSignal(propertyChangedSignal.append("()").toStdString().c_str());
+ QVERIFY(signalIndex > -1);
+ auto signal = metaObject->method(signalIndex);
+ QVERIFY(signal.isValid());
+ QSignalSpy changeSignal(o.data(), signal);
+ QMetaObject::invokeMethod(o.data(), "f");
+ QCOMPARE(o->property(propertyName.toStdString().c_str()), 123);
+ QVERIFY(changeSignal.size() == 1);
+ QCOMPARE(o->property("success"), true);
+ QMetaObject::invokeMethod(o.data(), "g");
+ QVERIFY(changeSignal.size() == 2);
+}
+void tst_qqmllanguage::signalNames_data()
+{
+ QTest::addColumn<QString>("signalName");
+ QTest::addColumn<QString>("handlerName");
+ QTest::addRow("helloWorld") << u"helloWorld"_s << u"onHelloWorld"_s;
+ QTest::addRow("$helloWorld") << u"$helloWorld"_s << u"on$HelloWorld"_s;
+ QTest::addRow("_helloWorld") << u"_helloWorld"_s << u"on_HelloWorld"_s;
+ QTest::addRow("_") << u"_"_s << u"on_"_s;
+ QTest::addRow("aUmlaut") << u"ä"_s << u"onÄ"_s;
+ QTest::addRow("___123a") << u"___123a"_s << u"on___123A"_s;
+}
+void tst_qqmllanguage::signalNames()
+{
+ QFETCH(QString, signalName);
+ QFETCH(QString, handlerName);
+ QQmlEngine e;
+ QQmlComponent c(&e);
+ c.setData(uR"(
+import QtQuick
+Item {
+ signal %1()
+ property bool success: false
+ function f() { %1(); }
+ %2: success = true
+})"_s.arg(signalName, handlerName)
+ .toUtf8(),
+ QUrl());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(o != nullptr);
+ const QMetaObject *metaObject = o->metaObject();
+ auto signalIndex = metaObject->indexOfSignal(signalName.append("()").toStdString().c_str());
+ QVERIFY(signalIndex > -1);
+ auto signal = metaObject->method(signalIndex);
+ QVERIFY(signal.isValid());
+ QSignalSpy changeSignal(o.data(), signal);
+ signal.invoke(o.data());
+ QVERIFY(changeSignal.size() == 1);
+ QCOMPARE(o->property("success"), true);
+ QMetaObject::invokeMethod(o.data(), "f");
+ QVERIFY(changeSignal.size() == 2);
+}
+
+void tst_qqmllanguage::callMethodOfAttachedDerived()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine);
+ c.setData(R"(
+ import QtQml
+ import Test
+
+ QtObject {
+ Component.onCompleted: Counter.increase()
+ property int v: Counter.value
+ }
+ )", QUrl());
+
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("v").toInt(), 99);
+}
+
+void tst_qqmllanguage::multiVersionSingletons()
+{
+ qmlRegisterTypesAndRevisions<BareSingleton>("MultiVersionSingletons", 11);
+ qmlRegisterTypesAndRevisions<UncreatableSingleton>("MultiVersionSingletons", 11);
+ QQmlEngine engine;
+
+ for (const char *name : { "BareSingleton", "UncreatableSingleton"}) {
+ const int id1 = qmlTypeId("MultiVersionSingletons", 1, 0, name);
+ const int id2 = qmlTypeId("MultiVersionSingletons", 11, 0, name);
+ QVERIFY(id1 != id2);
+ const QJSValue value1 = engine.singletonInstance<QJSValue>(id1);
+ const QJSValue value2 = engine.singletonInstance<QJSValue>(id2);
+ QVERIFY(value1.strictlyEquals(value2));
+ }
+}
+
+void tst_qqmllanguage::typeAnnotationCycle()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("TypeAnnotationCycle1.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->property("b").value<QObject*>(), o.data());
+}
+
+void tst_qqmllanguage::corpseInQmlList()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("corpseInQmlList.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QScopedPointer<QObject> a(new QObject);
+ QMetaObject::invokeMethod(o.data(), "setB", Q_ARG(QObject *, a.data()));
+
+ QJSValue b = o->property("b").value<QJSValue>();
+ QQmlListProperty<QObject> list
+ = qjsvalue_cast<QQmlListProperty<QObject>>(b.property(QStringLiteral("b")));
+
+ QCOMPARE(list.count(&list), 1);
+ QCOMPARE(list.at(&list, 0), a.data());
+
+ a.reset();
+
+ b = o->property("b").value<QJSValue>();
+ list = qjsvalue_cast<QQmlListProperty<QObject>>(b.property(QStringLiteral("b")));
+
+ QCOMPARE(list.count(&list), 1);
+ QCOMPARE(list.at(&list, 0), nullptr);
+
+ // The list itself is still alive:
+
+ list.append(&list, o.data());
+ QCOMPARE(list.count(&list), 2);
+ QCOMPARE(list.at(&list, 0), nullptr);
+ QCOMPARE(list.at(&list, 1), o.data());
+
+ list.replace(&list, 0, o.data());
+ QCOMPARE(list.count(&list), 2);
+ QCOMPARE(list.at(&list, 0), o.data());
+ QCOMPARE(list.at(&list, 1), o.data());
+
+ list.removeLast(&list);
+ QCOMPARE(list.count(&list), 1);
+ QCOMPARE(list.at(&list, 0), o.data());
+
+ list.clear(&list);
+ QCOMPARE(list.count(&list), 0);
+}
+
+void tst_qqmllanguage::objectInQmlListAndGc()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("objectInList.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ // Process the deletion event
+ QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
+ QCoreApplication::processEvents();
+
+ QQmlListProperty<QObject> children = o->property("child").value<QQmlListProperty<QObject>>();
+ QCOMPARE(children.count(&children), 1);
+ QObject *child = children.at(&children, 0);
+ QVERIFY(child);
+ QCOMPARE(child->objectName(), QLatin1String("child"));
+}
+
+void tst_qqmllanguage::asCastToInlineComponent()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("asCastToInlineComponent.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+ QCOMPARE(o->objectName(), QLatin1String("value: 20"));
+}
+
+void tst_qqmllanguage::deepAliasOnICOrReadonly()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("deepAliasOnICUser.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("borderColor").toString(), QLatin1String("black"));
+ QCOMPARE(o->property("borderObjectName").toString(), QLatin1String("theLeaf"));
+
+ const QVariant var = o->property("borderVarvar");
+ QCOMPARE(var.metaType(), QMetaType::fromType<QString>());
+ QCOMPARE(var.toString(), QLatin1String("mauve"));
+
+ QQmlComponent c2(&engine, testFileUrl("deepAliasOnReadonly.qml"));
+ QVERIFY(c2.isError());
+ QVERIFY(c2.errorString().contains(
+ QLatin1String(
+ "Invalid property assignment: \"readonlyRectX\" is a read-only property")));
+}
+
+void tst_qqmllanguage::optionalChainCallOnNullProperty()
+{
+ QTest::failOnWarning(QRegularExpression(".*Cannot call method 'destroy' of null.*"));
+
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("optionalChainCallOnNullProperty.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+}
+
+void tst_qqmllanguage::ambiguousComponents()
+{
+ auto e1 = std::make_unique<QQmlEngine>();
+ e1->addImportPath(dataDirectory());
+ bool isInstanceOf = false;
+
+ {
+ QQmlComponent c(e1.get());
+ c.loadUrl(testFileUrl("ambiguousComponents.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QTest::ignoreMessage(QtDebugMsg, "do");
+ QMetaObject::invokeMethod(o.data(), "dodo");
+
+ QMetaObject::invokeMethod(o.data(), "testInstanceOf", Q_RETURN_ARG(bool, isInstanceOf));
+ QVERIFY(isInstanceOf);
+ }
+
+ QQmlEngine e2;
+ e2.addImportPath(dataDirectory());
+ QQmlComponent c2(&e2);
+ c2.loadUrl(testFileUrl("ambiguousComponents.qml"));
+ QVERIFY2(c2.isReady(), qPrintable(c2.errorString()));
+
+ QScopedPointer<QObject> o2(c2.create());
+ QTest::ignoreMessage(QtDebugMsg, "do");
+ QMetaObject::invokeMethod(o2.data(), "dodo");
+
+ isInstanceOf = false;
+ QMetaObject::invokeMethod(o2.data(), "testInstanceOf", Q_RETURN_ARG(bool, isInstanceOf));
+ QVERIFY(isInstanceOf);
+
+ e1.reset();
+
+ // We can still invoke the function. This means its CU belongs to e2.
+ QTest::ignoreMessage(QtDebugMsg, "do");
+ QMetaObject::invokeMethod(o2.data(), "dodo");
+
+ isInstanceOf = false;
+ QMetaObject::invokeMethod(o2.data(), "testInstanceOf", Q_RETURN_ARG(bool, isInstanceOf));
+ QVERIFY(isInstanceOf);
+}
+
+void tst_qqmllanguage::writeNumberToEnumAlias()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("aliasWriter.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("strokeStyle").toInt(), 1);
+}
+
+void tst_qqmllanguage::badInlineComponentAnnotation()
+{
+ QQmlEngine engine;
+ const QUrl url = testFileUrl("badICAnnotation.qml");
+ QQmlComponent c(&engine, testFileUrl("badICAnnotation.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(
+ QtCriticalMsg,
+ qPrintable(url.toString() + ":20: 5 should be coerced to void because the function "
+ "called is insufficiently annotated. The original "
+ "value is retained. This will change in a future "
+ "version of Qt."));
+ QTest::ignoreMessage(
+ QtCriticalMsg,
+ QRegularExpression(":22: IC\\([^\\)]+\\) should be coerced to void because the "
+ "function called is insufficiently annotated. The original "
+ "value is retained. This will change in a future version of "
+ "Qt\\."));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("a").toInt(), 5);
+
+ QObject *ic = o->property("ic").value<QObject *>();
+ QVERIFY(ic);
+
+ QCOMPARE(o->property("b").value<QObject *>(), ic);
+ QCOMPARE(o->property("c").value<QObject *>(), ic);
+ QCOMPARE(o->property("d").value<QObject *>(), nullptr);
+}
+
+void tst_qqmllanguage::manuallyCallSignalHandler()
+{
+ // TODO: This test verifies the absence of regression legacy behavior. See QTBUG-120573
+ // Once we can get rid of the legacy behavior, delete this test!
+
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("manuallyCallSignalHandler.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ for (int i = 0; i < 10; ++i) {
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(
+ "Property 'onDestruction' of object QQmlComponentAttached\\(0x[0-9a-f]+\\) is a signal "
+ "handler\\. You should not call it directly\\. Make it a proper function and call that "
+ "or emit the signal\\."));
+ QTest::ignoreMessage(QtDebugMsg, "evil!");
+ QScopedPointer<QObject> o(c.create());
+ QTest::ignoreMessage(QtDebugMsg, "evil!");
+ }
+}
+
+void tst_qqmllanguage::overrideDefaultProperty()
+{
+ QQmlEngine e;
+ const QUrl url = testFileUrl("overrideDefaultProperty.qml");
+
+ // Should not crash here!
+
+ QQmlComponent c(&e, url);
+ QVERIFY(c.isError());
+ QCOMPARE(c.errorString(),
+ url.toString() + QLatin1String(":5 Cannot assign object to list property \"data\"\n"));
+}
+
+void tst_qqmllanguage::enumScopes()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("enumScopes.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("singletonUnscoped"), false);
+ QCOMPARE(o->property("singletonScoped"), true);
+ QCOMPARE(o->property("nonSingletonUnscoped"), false);
+ QCOMPARE(o->property("nonSingletonScoped"), true);
+
+ QCOMPARE(o->property("singletonScopedValue").toInt(), int(EnumProviderSingleton::Expected::Value));
+ QCOMPARE(o->property("singletonUnscopedValue").toInt(), int(EnumProviderSingleton::Expected::Value));
+}
+
+void tst_qqmllanguage::typedObjectList()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("typedObjectList.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QJSValue b = o->property("b").value<QJSValue>();
+ auto list = qjsvalue_cast<QQmlListProperty<QQmlComponent>>(b.property(QStringLiteral("b")));
+
+ QCOMPARE(list.count(&list), 1);
+ QVERIFY(list.at(&list, 0) != nullptr);
+}
+
+void tst_qqmllanguage::jsonArrayPropertyBehavesLikeAnArray() {
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("jsonArrayProperty.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("concatenatedJsonArray"), o->property("concatenatedJsArray"));
+ QVERIFY(o->property("entriesMatch").toBool());
+ QCOMPARE(o->property("jsonArrayEvery"), o->property("jsArrayEvery"));
+ QCOMPARE(o->property("jsonArrayFiltered"), o->property("jsArrayFiltered"));
+ QCOMPARE(o->property("jsonArrayFind"), o->property("jsArrayFind"));
+ QCOMPARE(o->property("jsonArrayFindIndex"), o->property("jsArrayFindIndex"));
+ QCOMPARE(o->property("jsonArrayForEach"), o->property("jsArrayForEach"));
+ QCOMPARE(o->property("jsonArrayIncludes"), o->property("jsArrayIncludes"));
+ QCOMPARE(o->property("jsonArrayIndexOf"), o->property("jsArrayIndexOf"));
+ QCOMPARE(o->property("jsonArrayJoin"), o->property("jsArrayJoin"));
+ QVERIFY(o->property("keysMatch").toBool());
+ QCOMPARE(o->property("jsonArrayLastIndexOf"), o->property("jsArrayLastIndexOf"));
+ QCOMPARE(o->property("jsonArrayMap"), o->property("jsArrayMap"));
+ QCOMPARE(o->property("jsonArrayReduce"), o->property("jsArrayReduce"));
+ QCOMPARE(o->property("jsonArrayReduceRight"), o->property("jsArrayReduceRight"));
+ QCOMPARE(o->property("jsonArraySlice"), o->property("jsArraySlice"));
+ QCOMPARE(o->property("jsonArraySome"), o->property("jsArraySome"));
+ QCOMPARE(o->property("stringifiedLocaleJsonArray"), o->property("stringifiedLocaleJsArray"));
+ QCOMPARE(o->property("stringifiedJsonArray"), o->property("stringifiedJsArray"));
+ QVERIFY(o->property("valuesMatch").toBool());
+
+ QVERIFY(o->property("jsonArrayWasCopiedWithin").toBool());
+ QVERIFY(o->property("jsonArrayWasFilled").toBool());
+ QVERIFY(o->property("jsonArrayWasPopped").toBool());
+ QVERIFY(o->property("jsonArrayWasPushed").toBool());
+ QVERIFY(o->property("jsonArrayWasReversed").toBool());
+ QVERIFY(o->property("jsonArrayWasShifted").toBool());
+ QVERIFY(o->property("jsonArrayWasSpliced").toBool());
+ QVERIFY(o->property("jsonArrayWasUnshifted").toBool());
+ QVERIFY(o->property("jsonArrayWasSorted").toBool());
+}
+
+void tst_qqmllanguage::invokableCtors()
+{
+ QQmlEngine e;
+
+ const QUrl url = testFileUrl("invokableCtors.qml");
+
+ QQmlComponent c(&e, url);
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ const QString urlString = url.toString();
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(
+ urlString + ":9: You are calling a Q_INVOKABLE constructor of "
+ "InvokableSingleton which is a singleton in QML."));
+
+ // Extended types look like types without any constructors.
+ // Therefore they aren't even FunctionObjects.
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(
+ urlString + ":10: TypeError: Type error"));
+
+ QTest::ignoreMessage(QtWarningMsg, qPrintable(
+ urlString + ":11: You are calling a Q_INVOKABLE constructor of "
+ "InvokableUncreatable which is uncreatable in QML."));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QObject *oo = qvariant_cast<QObject *>(o->property("oo"));
+ QVERIFY(oo);
+ QObject *pp = qvariant_cast<QObject *>(o->property("pp"));
+ QVERIFY(pp);
+ QCOMPARE(pp->parent(), oo);
+
+ InvokableValueType vv = qvariant_cast<InvokableValueType>(o->property("v"));
+ QCOMPARE(vv.m_s, "green");
+
+ InvokableSingleton *i = qvariant_cast<InvokableSingleton *>(o->property("i"));
+ QVERIFY(i);
+ QCOMPARE(i->m_a, 5);
+ QCOMPARE(i->parent(), oo);
+
+ QVariant k = o->property("k");
+ QCOMPARE(k.metaType(), QMetaType::fromType<InvokableExtended *>());
+ QCOMPARE(k.value<InvokableExtended *>(), nullptr);
+
+ InvokableUncreatable *l = qvariant_cast<InvokableUncreatable *>(o->property("l"));
+ QVERIFY(l);
+}
+
+void tst_qqmllanguage::nestedVectors()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("nestedVectors.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ NestedVectors *n = qobject_cast<NestedVectors *>(o.data());
+ QVERIFY(n);
+
+ const std::vector<std::vector<int>> expected1 { { 1, 2, 3 }, { 4, 5 } };
+ const QVariant list1 = n->property("list1");
+ QCOMPARE(list1.metaType(), QMetaType::fromType<std::vector<std::vector<int>>>());
+ QCOMPARE(list1.value<std::vector<std::vector<int>>>(), expected1);
+
+ const std::vector<std::vector<int>> expected2 { { 2, 3, 4 }, { 5, 6 } };
+ QCOMPARE(n->getList(), expected2);
+}
+
+void tst_qqmllanguage::optimizedSequenceShift()
+{
+ QQmlEngine e;
+ QQmlComponent c(&e, testFileUrl("optimizedSequenceShift.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("changes").toInt(), 2);
+
+ const QVariant one = o->property("one");
+ QCOMPARE(one.metaType(), QMetaType::fromType<int>());
+ QCOMPARE(one.toInt(), 1);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"
diff --git a/tests/auto/qml/qqmllistcompositor/CMakeLists.txt b/tests/auto/qml/qqmllistcompositor/CMakeLists.txt
index c05b97f6d2..b6999900ba 100644
--- a/tests/auto/qml/qqmllistcompositor/CMakeLists.txt
+++ b/tests/auto/qml/qqmllistcompositor/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllistcompositor Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllistcompositor LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmllistcompositor
SOURCES
tst_qqmllistcompositor.cpp
diff --git a/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp b/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp
index 2d02cac9f8..c10ceafeae 100644
--- a/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp
+++ b/tests/auto/qml/qqmllistcompositor/tst_qqmllistcompositor.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <private/qqmllistcompositor_p.h>
@@ -179,7 +180,7 @@ void tst_qqmllistcompositor::find()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
compositor.find(startGroup, startIndex);
@@ -241,7 +242,7 @@ void tst_qqmllistcompositor::findInsertPosition()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QQmlListCompositor::insert_iterator it = compositor.findInsertPosition(group, index);
@@ -499,7 +500,7 @@ void tst_qqmllistcompositor::clearFlags()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Remove> removes;
@@ -681,7 +682,7 @@ void tst_qqmllistcompositor::setFlags()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Insert> inserts;
@@ -968,7 +969,7 @@ void tst_qqmllistcompositor::move()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Remove> removes;
@@ -1202,7 +1203,7 @@ void tst_qqmllistcompositor::listItemsInserted()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Insert> inserts;
@@ -1338,7 +1339,7 @@ void tst_qqmllistcompositor::listItemsRemoved()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Remove> removes;
@@ -1532,7 +1533,7 @@ void tst_qqmllistcompositor::listItemsMoved()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Remove> removes;
@@ -1612,7 +1613,7 @@ void tst_qqmllistcompositor::listItemsChanged()
compositor.setGroupCount(4);
compositor.setDefaultGroups(VisibleFlag | C::DefaultFlag);
- foreach (const Range &range, ranges)
+ for (const Range &range : std::as_const(ranges))
compositor.append(range.list, range.index, range.count, range.flags);
QVector<C::Change> changes;
diff --git a/tests/auto/qml/qqmllistmodel/CMakeLists.txt b/tests/auto/qml/qqmllistmodel/CMakeLists.txt
index 7c689e643c..133a2dce5d 100644
--- a/tests/auto/qml/qqmllistmodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmllistmodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllistmodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllistmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmllistmodel/data/nestedLists.qml b/tests/auto/qml/qqmllistmodel/data/nestedLists.qml
new file mode 100644
index 0000000000..4aea6f1ae1
--- /dev/null
+++ b/tests/auto/qml/qqmllistmodel/data/nestedLists.qml
@@ -0,0 +1,37 @@
+import QtQuick
+
+Item {
+ id: mainWindow
+
+ function load(data) {
+ model.clear()
+ for (var i = 0; i < data.length; i++)
+ model.append(data[i])
+ }
+
+ ListModel {
+ id: model
+ }
+
+ Repeater {
+ objectName: "topLevel"
+ model: model
+ Item {
+ objectName: _headline
+ Repeater {
+ objectName: "month"
+ model: _weeks
+ Item {
+ objectName: index
+ Repeater {
+ objectName: "week"
+ model: _week
+ Item {
+ objectName: _day
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
index e522f280a3..d738a7f68d 100644
--- a/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
+++ b/tests/auto/qml/qqmllistmodel/tst_qqmllistmodel.cpp
@@ -1,13 +1,15 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQuick/private/qquickanimation_p.h>
#include <QtQuick/private/qquicklistview_p.h>
+#include <QtQuick/private/qquickrepeater_p.h>
#include <QtQml/private/qqmlengine_p.h>
#include <QtQmlModels/private/qqmllistmodel_p.h>
#include <QtQml/private/qqmlexpression_p.h>
+#include <QtQml/private/qqmlsignalnames_p.h>
#include <QQmlComponent>
#include <QtCore/qtimer.h>
@@ -119,6 +121,7 @@ private slots:
void objectOwnershipFlip();
void enumsInListElement();
void protectQObjectFromGC();
+ void nestedLists();
};
bool tst_qqmllistmodel::compareVariantList(const QVariantList &testList, QVariant object)
@@ -248,8 +251,8 @@ void tst_qqmllistmodel::static_types()
QVERIFY(!component.isError());
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
if (error.isEmpty()) {
QVariant actual = obj->property("test");
@@ -257,8 +260,6 @@ void tst_qqmllistmodel::static_types()
QCOMPARE(actual, value);
QCOMPARE(actual.toString(), value.toString());
}
-
- delete obj;
}
void tst_qqmllistmodel::static_i18n_data()
@@ -319,15 +320,13 @@ void tst_qqmllistmodel::static_i18n()
QVERIFY(!component.isError());
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
QVariant actual = obj->property("test");
QCOMPARE(actual, value);
QCOMPARE(actual.toString(), value.toString());
-
- delete obj;
}
void tst_qqmllistmodel::dynamic_i18n_data()
@@ -368,16 +367,15 @@ void tst_qqmllistmodel::dynamic_i18n()
QVERIFY(!component.isError());
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
QVariant actual = obj->property("test");
QCOMPARE(actual, value);
QCOMPARE(actual.toString(), value.toString());
-
- delete obj;
}
+
void tst_qqmllistmodel::static_nestedElements()
{
QFETCH(int, elementCount);
@@ -406,14 +404,12 @@ void tst_qqmllistmodel::static_nestedElements()
QQmlComponent component(&engine);
component.setData(componentStr.toUtf8(), QUrl::fromLocalFile(""));
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
QVariant count = obj->property("count");
QCOMPARE(count.typeId(), QMetaType::Int);
QCOMPARE(count.toInt(), elementCount);
-
- delete obj;
}
void tst_qqmllistmodel::static_nestedElements_data()
@@ -606,8 +602,8 @@ void tst_qqmllistmodel::enumerate()
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("enumerate.qml"));
QVERIFY(!component.isError());
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(component.create()) };
+ QVERIFY(item);
QLatin1String expectedStrings[] = {
QLatin1String("val1=1Y"),
@@ -638,8 +634,6 @@ void tst_qqmllistmodel::enumerate()
}
QCOMPARE(matchCount, expectedStringCount);
-
- delete item;
}
void tst_qqmllistmodel::error_data()
@@ -779,9 +773,9 @@ void tst_qqmllistmodel::get()
component.setData(
"import QtQuick 2.0\n"
"ListModel {}\n", QUrl());
- QQmlListModel *model = qobject_cast<QQmlListModel*>(component.create());
+ std::unique_ptr<QQmlListModel> model { qobject_cast<QQmlListModel*>(component.create()) };
model->setDynamicRoles(dynamicRoles);
- engine.rootContext()->setContextProperty("model", model);
+ engine.rootContext()->setContextProperty("model", model.get());
RUNEXPR("model.append({roleA: 100})");
RUNEXPR("model.append({roleA: 200, roleB: 400})");
@@ -789,12 +783,12 @@ void tst_qqmllistmodel::get()
RUNEXPR("model.append({roleC: {} })");
RUNEXPR("model.append({roleD: [ { a:1, b:2 }, { c: 3 } ] })");
- QSignalSpy spy(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
- QQmlExpression expr(engine.rootContext(), model, expression);
+ QSignalSpy spy(model.get(), SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
+ QQmlExpression expr(engine.rootContext(), model.get(), expression);
expr.evaluate();
QVERIFY(!expr.hasError());
- int role = roleFromName(model, roleName);
+ int role = roleFromName(model.get(), roleName);
QVERIFY(role >= 0);
if (roleValue.typeId() == QMetaType::QVariantList) {
@@ -810,8 +804,6 @@ void tst_qqmllistmodel::get()
QCOMPARE(spyResult.at(0).value<QModelIndex>(), model->index(index, 0, QModelIndex()));
QCOMPARE(spyResult.at(1).value<QModelIndex>(), model->index(index, 0, QModelIndex())); // only 1 item is modified at a time
QCOMPARE(spyResult.at(2).value<QVector<int> >(), (QVector<int>() << role));
-
- delete model;
}
void tst_qqmllistmodel::get_data()
@@ -857,11 +849,11 @@ void tst_qqmllistmodel::get_nested()
component.setData(
"import QtQuick 2.0\n"
"ListModel {}", QUrl());
- QQmlListModel *model = qobject_cast<QQmlListModel*>(component.create());
+ std::unique_ptr<QQmlListModel> model { qobject_cast<QQmlListModel*>(component.create()) };
model->setDynamicRoles(dynamicRoles);
QVERIFY(component.errorString().isEmpty());
QQmlListModel *childModel;
- engine.rootContext()->setContextProperty("model", model);
+ engine.rootContext()->setContextProperty("model", model.get());
RUNEXPR("model.append({ listRoleA: [\n"
"{ roleA: 100 },\n"
@@ -908,16 +900,16 @@ void tst_qqmllistmodel::get_nested()
for (int i=0; i<testData.size(); i++) {
int outerListIndex = testData[i].first;
QString outerListRoleName = testData[i].second;
- int outerListRole = roleFromName(model, outerListRoleName);
+ int outerListRole = roleFromName(model.get(), outerListRoleName);
QVERIFY(outerListRole >= 0);
childModel = qobject_cast<QQmlListModel*>(model->data(outerListIndex, outerListRole).value<QObject*>());
QVERIFY(childModel);
QString extendedExpression = QString("get(%1).%2.%3").arg(outerListIndex).arg(outerListRoleName).arg(expression);
- QQmlExpression expr(engine.rootContext(), model, extendedExpression);
+ QQmlExpression expr(engine.rootContext(), model.get(), extendedExpression);
- QSignalSpy spy(childModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ QSignalSpy spy(childModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
expr.evaluate();
QVERIFY(!expr.hasError());
@@ -935,8 +927,6 @@ void tst_qqmllistmodel::get_nested()
QCOMPARE(spyResult.at(1).value<QModelIndex>(), childModel->index(index, 0, QModelIndex())); // only 1 item is modified at a time
QCOMPARE(spyResult.at(2).value<QVector<int> >(), (QVector<int>() << role));
}
-
- delete model;
}
void tst_qqmllistmodel::get_nested_data()
@@ -949,16 +939,14 @@ void tst_qqmllistmodel::crash_model_with_multiple_roles()
{
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("multipleroles.qml"));
- QObject *rootItem = component.create();
+ std::unique_ptr<QObject> rootItem { component.create() };
QVERIFY(component.errorString().isEmpty());
- QVERIFY(rootItem != nullptr);
+ QVERIFY(rootItem);
QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
QVERIFY(model != nullptr);
// used to cause a crash
model->setProperty(0, "black", true);
-
- delete rootItem;
}
void tst_qqmllistmodel::crash_model_with_unknown_roles()
@@ -983,22 +971,19 @@ void tst_qqmllistmodel::crash_model_with_dynamic_roles()
// setting a dynamic role to a QObject value, then triggering dtor
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("dynamicroles.qml"));
- QObject *rootItem = component.create();
+ std::unique_ptr<QObject> rootItem { component.create() };
qWarning() << component.errorString();
QVERIFY(component.errorString().isEmpty());
- QVERIFY(rootItem != 0);
+ QVERIFY(rootItem.get() != 0);
QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
QVERIFY(model != 0);
QMetaObject::invokeMethod(model, "appendNewElement");
- QObject *testObj = new QObject;
- model->setProperty(0, "obj", QVariant::fromValue<QObject*>(testObj));
- delete testObj;
+ model->setProperty(0, "obj", QVariant::fromValue<QObject*>(std::make_unique<QObject>().get()));
- // delete the root item, which will cause the model dtor to run
- // previously, this would crash as it attempted to delete testObj.
- delete rootItem;
+ // Let root item go out of scope to let the model dtor run.
+ // Previously, this would crash as it attempted to delete the already-deleted temporary QObject.
}
{
@@ -1006,22 +991,18 @@ void tst_qqmllistmodel::crash_model_with_dynamic_roles()
// DynamicRoleModelNode::updateValues() to trigger unsafe qobject_cast
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("dynamicroles.qml"));
- QObject *rootItem = component.create();
+ std::unique_ptr<QObject> rootItem { component.create() };
qWarning() << component.errorString();
QVERIFY(component.errorString().isEmpty());
- QVERIFY(rootItem != 0);
+ QVERIFY(rootItem.get() != 0);
QQmlListModel *model = rootItem->findChild<QQmlListModel*>("listModel");
QVERIFY(model != 0);
QMetaObject::invokeMethod(model, "appendNewElement");
- QObject *testObj = new QObject;
- model->setProperty(0, "obj", QVariant::fromValue<QObject*>(testObj));
- delete testObj;
+ model->setProperty(0, "obj", QVariant::fromValue<QObject*>(std::make_unique<QObject>().get()));
QMetaObject::invokeMethod(model, "setElementAgain");
-
- delete rootItem;
}
{
@@ -1098,21 +1079,21 @@ void tst_qqmllistmodel::property_changes()
expr.evaluate();
QVERIFY2(!expr.hasError(), qPrintable(expr.error().toString()));
- QString signalHandler = "on" + QString(roleName[0].toUpper()) + roleName.mid(1, roleName.size()) + "Changed:";
+ QString signalHandler = QQmlSignalNames::propertyNameToChangedHandlerName(roleName);
QString qml = "import QtQuick 2.0\n"
"Connections {\n"
"property bool gotSignal: false\n"
"target: model.get(" + QString::number(listIndex) + ")\n"
- + signalHandler + " gotSignal = true\n"
+ + signalHandler + ": gotSignal = true\n"
"}\n";
QQmlComponent component(&engine);
component.setData(qml.toUtf8(), QUrl::fromLocalFile(""));
engine.rootContext()->setContextProperty("model", &model);
- QObject *connectionsObject = component.create();
+ std::unique_ptr<QObject> connectionsObject { component.create() };
QVERIFY2(component.errorString().isEmpty(), qPrintable(component.errorString()));
- QSignalSpy spyItemsChanged(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ QSignalSpy spyItemsChanged(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
expr.setExpression(script_change);
expr.evaluate();
@@ -1132,8 +1113,6 @@ void tst_qqmllistmodel::property_changes()
expr.setExpression(testExpression);
QCOMPARE(expr.evaluate().toBool(), true);
-
- delete connectionsObject;
}
void tst_qqmllistmodel::property_changes_data()
@@ -1354,10 +1333,8 @@ void tst_qqmllistmodel::empty_element_warning()
component.setData(qml.toUtf8(), QUrl::fromLocalFile(QString("dummy.qml")));
QVERIFY(!component.isError());
- QObject *obj = component.create();
- QVERIFY(obj != nullptr);
-
- delete obj;
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj);
}
void tst_qqmllistmodel::datetime_data()
@@ -1549,6 +1526,8 @@ void tst_qqmllistmodel::modify_through_delegate()
" ListElement { name: \"Doe\"; age: 33 }\n"
" }\n"
" ListView {\n"
+ " height: 100\n" \
+ " width: 100\n" \
" model: testModel\n"
" delegate: Item {\n"
" Component.onCompleted: model.age = 18;\n"
@@ -1929,6 +1908,154 @@ void tst_qqmllistmodel::protectQObjectFromGC()
}
}
+static QVariantList createLast7Days()
+{
+ QVariantList last7DaysList;
+ for (int i = 0; i < 7; i++) {
+ QVariantMap map;
+ map.insert("_day", i);
+ last7DaysList.append(map);
+ }
+ return last7DaysList;
+}
+
+static QVariantList createWeekChartModels()
+{
+ QVariantList list;
+ for (int i = 0; i < 4; i++) {
+ QVariantMap map;
+ map.insert("_week", createLast7Days());
+ list.append(map);
+ }
+ return list;
+}
+
+static QVariantList createVariantModel()
+{
+ QVariantMap element1;
+ element1.insert("_headline", "Element 1");
+ element1.insert("_weeks", createWeekChartModels());
+
+ QVariantMap element2;
+ element2.insert("_headline", "Element 2");
+ element2.insert("_weeks", createWeekChartModels());
+
+ QVariantMap element3;
+ element3.insert("_headline", "Element 3");
+ element3.insert("_weeks", createWeekChartModels());
+
+ QVariantList list;
+ list.append(element1);
+ list.append(element2);
+ list.append(element3);
+
+ return list;
+}
+
+class Day : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int _day READ _day CONSTANT)
+public:
+ Day(int day, QObject *parent = nullptr) : QObject(parent), day(day) {}
+ int _day() const { return day; }
+private:
+ int day = 0;
+};
+
+class Week : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Day> _week READ _week)
+public:
+ Week(QObject *parent = nullptr) : QObject(parent)
+ {
+ for (int i = 0; i < 7; ++i)
+ week.append(new Day(i, this));
+ }
+
+ QQmlListProperty<Day> _week() { return QQmlListProperty<Day>(this, &week); }
+
+private:
+ QList<Day *> week;
+};
+
+class Month : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QQmlListProperty<Week> _weeks READ _weeks)
+ Q_PROPERTY(QString _headline READ _headline CONSTANT)
+public:
+
+ Month(int i, QObject *parent = nullptr)
+ : QObject(parent)
+ , headline(QLatin1String("Element ") + QString::number(i))
+ {
+ for (int i = 0; i < 4; ++i)
+ weeks.append(new Week(this));
+ }
+
+ QQmlListProperty<Week> _weeks() { return QQmlListProperty<Week>(this, &weeks); }
+ QString _headline() const { return headline; }
+
+private:
+ QList<Week *> weeks;
+ QString headline;
+};
+
+static void verifyLists(const QVariantList &list, QQuickRepeater *topLevel)
+{
+ QVERIFY(topLevel);
+ QCOMPARE(topLevel->count(), 3);
+
+ for (int month = 0; month < 3; ++month) {
+ const QVariantMap monthData = list[month].toMap();
+ const QQuickItem *monthItem = topLevel->itemAt(month);
+ QCOMPARE(monthItem->objectName(), monthData["_headline"].toString());
+ const QQuickRepeater *monthRepeater = monthItem->findChild<QQuickRepeater *>("month");
+ QVERIFY(monthRepeater);
+ QCOMPARE(monthRepeater->count(), 4);
+ const QVariantList weekList = monthData["_weeks"].toList();
+ for (int week = 0; week < 4; ++week) {
+ const QVariantList weekData = weekList[week].toMap()["_week"].toList();
+ const QQuickItem *weekItem = monthRepeater->itemAt(week);
+ QCOMPARE(weekItem->objectName(), QString::number(week));
+ const QQuickRepeater *weekRepeater = weekItem->findChild<QQuickRepeater *>("week");
+ QVERIFY(weekRepeater);
+ QCOMPARE(weekRepeater->count(), 7);
+ for (int day = 0; day < 7; ++day) {
+ const QVariantMap dayData = weekData[day].toMap();
+ const QQuickItem *dayItem = weekRepeater->itemAt(day);
+ QCOMPARE(dayItem->objectName(), dayData["_day"]);
+ }
+ }
+ }
+}
+
+void tst_qqmllistmodel::nestedLists()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("nestedLists.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+
+ QQuickRepeater *topLevel = o->findChild<QQuickRepeater *>("topLevel");
+
+ const QVariantList list = createVariantModel();
+ QMetaObject::invokeMethod(o.data(), "load", Q_ARG(QVariant, QVariant::fromValue(list)));
+ verifyLists(list, topLevel);
+
+ const QObjectList objects {
+ new Month(1, o.data()),
+ new Month(2, o.data()),
+ new Month(3, o.data())
+ };
+
+ QMetaObject::invokeMethod(o.data(), "load", Q_ARG(QVariant, QVariant::fromValue(objects)));
+ verifyLists(list, topLevel);
+}
+
QTEST_MAIN(tst_qqmllistmodel)
#include "tst_qqmllistmodel.moc"
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt b/tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt
index ac77f65b68..93d597e687 100644
--- a/tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt
+++ b/tests/auto/qml/qqmllistmodelworkerscript/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllistmodelworkerscript Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllistmodelworkerscript LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
index 4875602314..93f18ea8d5 100644
--- a/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
+++ b/tests/auto/qml/qqmllistmodelworkerscript/tst_qqmllistmodelworkerscript.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquicktext_p.h>
@@ -55,7 +56,7 @@ public:
private:
int roleFromName(const QQmlListModel *model, const QString &roleName);
- QQuickItem *createWorkerTest(QQmlEngine *eng, QQmlComponent *component, QQmlListModel *model);
+ std::unique_ptr<QQuickItem> createWorkerTest(QQmlEngine *eng, QQmlComponent *component, QQmlListModel *model);
void waitForWorker(QQuickItem *item);
static bool compareVariantList(const QVariantList &testList, QVariant object);
@@ -134,9 +135,9 @@ int tst_qqmllistmodelworkerscript::roleFromName(const QQmlListModel *model, cons
return model->roleNames().key(roleName.toUtf8(), -1);
}
-QQuickItem *tst_qqmllistmodelworkerscript::createWorkerTest(QQmlEngine *eng, QQmlComponent *component, QQmlListModel *model)
+std::unique_ptr<QQuickItem> tst_qqmllistmodelworkerscript::createWorkerTest(QQmlEngine *eng, QQmlComponent *component, QQmlListModel *model)
{
- QQuickItem *item = qobject_cast<QQuickItem*>(component->create());
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(component->create()) };
QQmlEngine::setContextForObject(model, eng->rootContext());
if (item)
item->setProperty("model", QVariant::fromValue(model));
@@ -326,15 +327,16 @@ void tst_qqmllistmodelworkerscript::dynamic_worker()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("model.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
QSignalSpy spyCount(&model, SIGNAL(countChanged()));
if (script[0] == QLatin1Char('{') && script[script.size()-1] == QLatin1Char('}'))
script = script.mid(1, script.size() - 2);
QVariantList operations;
- foreach (const QString &s, script.split(';')) {
+ const QStringList statements = script.split(';');
+ for (const QString &s : statements) {
if (!s.isEmpty())
operations << s;
}
@@ -342,15 +344,15 @@ void tst_qqmllistmodelworkerscript::dynamic_worker()
if (isValidErrorMessage(warning, dynamicRoles))
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, operations)));
- waitForWorker(item);
- QCOMPARE(QQmlProperty(item, "result").read().toInt(), result);
+ waitForWorker(item.get());
+ QCOMPARE(QQmlProperty(item.get(), "result").read().toInt(), result);
if (model.count() > 0)
QVERIFY(spyCount.size() > 0);
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -377,13 +379,14 @@ void tst_qqmllistmodelworkerscript::dynamic_worker_sync()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("model.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
if (script[0] == QLatin1Char('{') && script[script.size()-1] == QLatin1Char('}'))
script = script.mid(1, script.size() - 2);
QVariantList operations;
- foreach (const QString &s, script.split(';')) {
+ const QStringList statements = script.split(';');
+ for (const QString &s : statements) {
if (!s.isEmpty())
operations << s;
}
@@ -393,14 +396,14 @@ void tst_qqmllistmodelworkerscript::dynamic_worker_sync()
// execute a set of commands on the worker list model, then check the
// changes are reflected in the list model in the main thread
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, operations.mid(0, operations.size()-1))));
- waitForWorker(item);
+ waitForWorker(item.get());
QQmlExpression e(eng.rootContext(), &model, operations.last().toString());
QCOMPARE(e.evaluate().toInt(), result);
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -440,25 +443,25 @@ void tst_qqmllistmodelworkerscript::get_worker()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("model.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
// Add some values like get() test
- RUNEVAL(item, "model.append({roleA: 100})");
- RUNEVAL(item, "model.append({roleA: 200, roleB: 400})");
- RUNEVAL(item, "model.append({roleA: 200, roleB: 400})");
- RUNEVAL(item, "model.append({roleC: {} })");
- RUNEVAL(item, "model.append({roleD: [ { a:1, b:2 }, { c: 3 } ] })");
+ RUNEVAL(item.get(), "model.append({roleA: 100})");
+ RUNEVAL(item.get(), "model.append({roleA: 200, roleB: 400})");
+ RUNEVAL(item.get(), "model.append({roleA: 200, roleB: 400})");
+ RUNEVAL(item.get(), "model.append({roleC: {} })");
+ RUNEVAL(item.get(), "model.append({roleD: [ { a:1, b:2 }, { c: 3 } ] })");
int role = roleFromName(&model, roleName);
QVERIFY(role >= 0);
- QSignalSpy spy(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ QSignalSpy spy(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
// in the worker thread, change the model data and call sync()
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, QStringList(expression))));
- waitForWorker(item);
+ waitForWorker(item.get());
// see if we receive the model changes in the main thread's model
if (roleValue.typeId() == QMetaType::QVariantList) {
@@ -474,8 +477,6 @@ void tst_qqmllistmodelworkerscript::get_worker()
QCOMPARE(spyResult.at(0).value<QModelIndex>(), model.index(index, 0, QModelIndex()));
QCOMPARE(spyResult.at(1).value<QModelIndex>(), model.index(index, 0, QModelIndex())); // only 1 item is modified at a time
QVERIFY(spyResult.at(2).value<QVector<int> >().contains(role));
-
- delete item;
}
void tst_qqmllistmodelworkerscript::get_worker_data()
@@ -570,18 +571,18 @@ void tst_qqmllistmodelworkerscript::property_changes_worker()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("model.qml"));
QVERIFY2(component.errorString().isEmpty(), component.errorString().toUtf8());
- QQuickItem *item = createWorkerTest(&engine, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&engine, &component, &model);
+ QVERIFY(item);
QQmlExpression expr(engine.rootContext(), &model, script_setup);
expr.evaluate();
- QVERIFY2(!expr.hasError(), QTest::toString(expr.error().toString()));
+ QVERIFY2(!expr.hasError(), qPrintable(expr.error().toString()));
- QSignalSpy spyItemsChanged(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)));
+ QSignalSpy spyItemsChanged(&model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QList<int>)));
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, QStringList(script_change))));
- waitForWorker(item);
+ waitForWorker(item.get());
// test itemsChanged() is emitted correctly
if (itemsChanged) {
@@ -592,7 +593,7 @@ void tst_qqmllistmodelworkerscript::property_changes_worker()
QCOMPARE(spyItemsChanged.size(), 0);
}
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -617,12 +618,12 @@ void tst_qqmllistmodelworkerscript::worker_sync()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("workersync.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
QCOMPARE(model.count(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "addItem0"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItem0"));
QCOMPARE(model.count(), 2);
QVariant childData = model.data(0, 0);
@@ -633,39 +634,39 @@ void tst_qqmllistmodelworkerscript::worker_sync()
QSignalSpy spyModelInserted(&model, SIGNAL(rowsInserted(QModelIndex,int,int)));
QSignalSpy spyChildInserted(childModel, SIGNAL(rowsInserted(QModelIndex,int,int)));
- QVERIFY(QMetaObject::invokeMethod(item, "addItemViaWorker"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItemViaWorker"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 2);
QCOMPARE(childModel->count(), 1);
QCOMPARE(spyModelInserted.size(), 0);
QCOMPARE(spyChildInserted.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 2);
QCOMPARE(childModel->count(), 2);
QCOMPARE(spyModelInserted.size(), 0);
QCOMPARE(spyChildInserted.size(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "addItemViaWorker"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItemViaWorker"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 2);
QCOMPARE(childModel->count(), 2);
QCOMPARE(spyModelInserted.size(), 0);
QCOMPARE(spyChildInserted.size(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 2);
QCOMPARE(childModel->count(), 3);
QCOMPARE(spyModelInserted.size(), 0);
QCOMPARE(spyChildInserted.size(), 2);
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -682,53 +683,51 @@ void tst_qqmllistmodelworkerscript::worker_remove_element()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("workerremoveelement.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
QSignalSpy spyModelRemoved(&model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
QCOMPARE(model.count(), 0);
QCOMPARE(spyModelRemoved.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "addItem"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItem"));
QCOMPARE(model.count(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "removeItemViaWorker"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "removeItemViaWorker"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 1);
QCOMPARE(spyModelRemoved.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 0);
QCOMPARE(spyModelRemoved.size(), 1);
- delete item;
+ item.reset();
qApp->processEvents();
{
//don't crash if model was deleted earlier
- QQmlListModel* model = new QQmlListModel;
+ std::unique_ptr<QQmlListModel> model = std::make_unique<QQmlListModel>();
model->setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("workerremoveelement.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, model.get());
+ QVERIFY(item);
- QVERIFY(QMetaObject::invokeMethod(item, "addItem"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addItem"));
QCOMPARE(model->count(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "removeItemViaWorker"));
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- delete model;
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "removeItemViaWorker"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ model.reset();
qApp->processEvents(); //must not crash here
- waitForWorker(item);
-
- delete item;
+ waitForWorker(item.get());
}
}
@@ -745,31 +744,31 @@ void tst_qqmllistmodelworkerscript::worker_remove_list()
model.setDynamicRoles(dynamicRoles);
QQmlEngine eng;
QQmlComponent component(&eng, testFileUrl("workerremovelist.qml"));
- QQuickItem *item = createWorkerTest(&eng, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&eng, &component, &model);
+ QVERIFY(item);
QSignalSpy spyModelRemoved(&model, SIGNAL(rowsRemoved(QModelIndex,int,int)));
QCOMPARE(model.count(), 0);
QCOMPARE(spyModelRemoved.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "addList"));
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "addList"));
QCOMPARE(model.count(), 1);
- QVERIFY(QMetaObject::invokeMethod(item, "removeListViaWorker"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "removeListViaWorker"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 1);
QCOMPARE(spyModelRemoved.size(), 0);
- QVERIFY(QMetaObject::invokeMethod(item, "doSync"));
- waitForWorker(item);
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "doSync"));
+ waitForWorker(item.get());
QCOMPARE(model.count(), 0);
QCOMPARE(spyModelRemoved.size(), 1);
- delete item;
+ item.reset();
qApp->processEvents();
}
@@ -792,8 +791,8 @@ void tst_qqmllistmodelworkerscript::dynamic_role()
model.setDynamicRoles(true);
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("model.qml"));
- QQuickItem *item = createWorkerTest(&engine, &component, &model);
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item = createWorkerTest(&engine, &component, &model);
+ QVERIFY(item);
QQmlExpression preExp(engine.rootContext(), &model, preamble);
QCOMPARE(preExp.evaluate().toInt(), 0);
@@ -801,21 +800,22 @@ void tst_qqmllistmodelworkerscript::dynamic_role()
if (script[0] == QLatin1Char('{') && script[script.size()-1] == QLatin1Char('}'))
script = script.mid(1, script.size() - 2);
QVariantList operations;
- foreach (const QString &s, script.split(';')) {
+ const QStringList statements = script.split(';');
+ for (const QString &s : statements) {
if (!s.isEmpty())
operations << s;
}
// execute a set of commands on the worker list model, then check the
// changes are reflected in the list model in the main thread
- QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker",
+ QVERIFY(QMetaObject::invokeMethod(item.get(), "evalExpressionViaWorker",
Q_ARG(QVariant, operations.mid(0, operations.size()-1))));
- waitForWorker(item);
+ waitForWorker(item.get());
QQmlExpression e(engine.rootContext(), &model, operations.last().toString());
QCOMPARE(e.evaluate().toInt(), result);
- delete item;
+ item.reset();
qApp->processEvents();
}
diff --git a/tests/auto/qml/qqmllistreference/CMakeLists.txt b/tests/auto/qml/qqmllistreference/CMakeLists.txt
index 3286531a45..0fa70259b2 100644
--- a/tests/auto/qml/qqmllistreference/CMakeLists.txt
+++ b/tests/auto/qml/qqmllistreference/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllistreference Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllistreference LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmllistreference/data/consoleLogSyntheticList.qml b/tests/auto/qml/qqmllistreference/data/consoleLogSyntheticList.qml
new file mode 100644
index 0000000000..9d2fd3e0b2
--- /dev/null
+++ b/tests/auto/qml/qqmllistreference/data/consoleLogSyntheticList.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ function createList() : list<QtObject> { return [self] }
+ Component.onCompleted: console.log(createList())
+}
diff --git a/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml b/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml
new file mode 100644
index 0000000000..35c8d66dad
--- /dev/null
+++ b/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.7
+import Test
+
+Item {
+ id: root
+
+ TestItem {
+ id: testItem
+ }
+
+ Component.onCompleted : {
+ testItem.data.push(null);
+ testItem.data.length = 5;
+ testItem.data.unshift(null);
+
+ var state = Qt.createQmlObject( "import QtQuick 2.7; State{ name: 'MyState' }", root, "dynamicState" );
+ root.states.length = 5;
+ root.states.push(null);
+ root.states.unshift(state);
+ }
+}
diff --git a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
index 049ffb2d72..76711a00e6 100644
--- a/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
+++ b/tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QUrl>
@@ -58,6 +58,9 @@ private slots:
void jsArrayMethods();
void jsArrayMethodsWithParams_data();
void jsArrayMethodsWithParams();
+ void listIgnoresNull_data() { modeData(); }
+ void listIgnoresNull();
+ void consoleLogSyntheticList();
};
class TestType : public QObject
@@ -73,12 +76,18 @@ public:
SyntheticClearAndReplace,
SyntheticRemoveLast,
SyntheticRemoveLastAndReplace,
- AutomaticPointer
+ AutomaticPointer,
+ IgnoreNullValues,
};
static void append(QQmlListProperty<TestType> *p, TestType *v) {
reinterpret_cast<QList<TestType *> *>(p->data)->append(v);
}
+ static void appendNoNullValues(QQmlListProperty<TestType> *p, TestType *v) {
+ if (!v)
+ return;
+ reinterpret_cast<QList<TestType *> *>(p->data)->append(v);
+ }
static qsizetype count(QQmlListProperty<TestType> *p) {
return reinterpret_cast<QList<TestType *> *>(p->data)->size();
}
@@ -121,6 +130,10 @@ public:
case AutomaticPointer:
property = QQmlListProperty<TestType>(this, &data);
break;
+ case IgnoreNullValues:
+ property = QQmlListProperty<TestType>(this, &data, appendNoNullValues, count, at, clear,
+ replace, removeLast);
+ break;
}
}
@@ -142,6 +155,7 @@ void tst_qqmllistreference::modeData()
QTest::addRow("SyntheticClearAndReplace") << TestType::SyntheticClearAndReplace;
QTest::addRow("SyntheticRemoveLast") << TestType::SyntheticRemoveLast;
QTest::addRow("SyntheticRemoveLastAndReplace") << TestType::SyntheticRemoveLastAndReplace;
+ QTest::addRow("IgnoreNullValues") << TestType::IgnoreNullValues;
}
void tst_qqmllistreference::initTestCase()
@@ -1036,6 +1050,50 @@ void tst_qqmllistreference::jsArrayMethodsWithParams()
QCOMPARE(object->property("listPropertyLastIndexOf"), object->property("jsArrayLastIndexOf"));
}
+/*!
+ Some of our list implementations ignore attempts to append a null object.
+ This should result in warnings or type errors, and not crash our wrapper
+ code.
+*/
+void tst_qqmllistreference::listIgnoresNull()
+{
+ QFETCH(const TestType::Mode, mode);
+ static TestType::Mode globalMode;
+ globalMode = mode;
+ struct TestItem : public TestType
+ {
+ TestItem() : TestType(globalMode) {}
+ };
+
+ const auto id = qmlRegisterType<TestItem>("Test", 1, 0, "TestItem");
+ const auto unregister = qScopeGuard([id]{
+ QQmlPrivate::qmlunregister(QQmlPrivate::TypeRegistration, id);
+ });
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("listIgnoresNull.qml"));
+
+ // For lists that don't append null values, creating the component shouldn't crash
+ // in the onCompleted handler, but generate type errors and warnings.
+ if (mode == TestType::IgnoreNullValues) {
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".* QML TestItem: List didn't append all objects$"));
+ QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".* TypeError: List doesn't append null objects$"));
+ }
+ QScopedPointer<QObject> object( component.create() );
+ QVERIFY(object != nullptr);
+}
+
+void tst_qqmllistreference::consoleLogSyntheticList()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("consoleLogSyntheticList.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QTest::ignoreMessage(
+ QtDebugMsg, QRegularExpression("\\[QObject_QML_[0-9]+\\(0x[0-9a-f]+\\)\\]"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+}
+
QTEST_MAIN(tst_qqmllistreference)
#include "tst_qqmllistreference.moc"
diff --git a/tests/auto/qml/qqmllocale/CMakeLists.txt b/tests/auto/qml/qqmllocale/CMakeLists.txt
index 8603fe454d..beca01f955 100644
--- a/tests/auto/qml/qqmllocale/CMakeLists.txt
+++ b/tests/auto/qml/qqmllocale/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmllocale Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmllocale LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
index 3349f5f9b6..a7ddf79ad5 100644
--- a/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
+++ b/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp
@@ -1,9 +1,11 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
+#include <private/qqmllocale_p.h>
+
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlcomponent.h>
@@ -457,9 +459,10 @@ void tst_qqmllocale::toString_data()
const QDateTime midnight2000(QDate(2000, 1, 1), QTime(0, 0));
// 12 AM might not exist in this timezone (some timezones have transitions at midnight).
if (midnight2000.isValid()) {
- functionCallScript = "locale.toString(new Date(2000, 1, 1))";
- QTest::newRow(qPrintable(functionCallScript)) << "en_AU" << functionCallScript
- << QLatin1String("Tuesday, 1 February 2000 12:00:00 AM ") + midnight2000.timeZoneAbbreviation() << QString();
+ functionCallScript = "locale.toString(new Date(2000, 0, 1))";
+ const QLocale locale("en_AU");
+ QTest::newRow(qPrintable(functionCallScript)) << locale.name() << functionCallScript
+ << locale.toString(midnight2000, QLocale::LongFormat) << QString();
}
functionCallScript = "locale.toString(new Date(2022, 7, 16), [])";
@@ -475,10 +478,12 @@ void tst_qqmllocale::toString_data()
QTest::newRow(qPrintable(functionCallScript)) << "ar" << functionCallScript << "١٦" << QString();
functionCallScript = "locale.toString(new Date(2022, 7, 16), Locale.ShortFormat)";
- QTest::newRow(qPrintable(functionCallScript)) << "en_AU" << functionCallScript << "16/8/22 12:00 AM" << QString();
+ QTest::newRow(qPrintable(functionCallScript))
+ << "en_AU" << functionCallScript << "16/8/22 12:00 am" << QString();
functionCallScript = "locale.toString(new Date(2022, 7, 16, 1, 23, 4), Locale.ShortFormat)";
- QTest::newRow(qPrintable(functionCallScript)) << "en_AU" << functionCallScript << "16/8/22 1:23 AM" << QString();
+ QTest::newRow(qPrintable(functionCallScript))
+ << "en_AU" << functionCallScript << "16/8/22 1:23 am" << QString();
}
void tst_qqmllocale::toString()
@@ -544,7 +549,7 @@ void tst_qqmllocale::weekDays()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("weekDays");
- QCOMPARE(val.userType(), qMetaTypeId<QJSValue>());
+ QCOMPARE(val.metaType(), QMetaType::fromType<QList<QQmlLocale::DayOfWeek>>());
QList<QVariant> qmlDays = val.toList();
QList<Qt::DayOfWeek> days = QLocale(locale).weekdays();
@@ -584,7 +589,7 @@ void tst_qqmllocale::uiLanguages()
Q_ARG(QVariant, QVariant(locale)));
QVariant val = obj->property("uiLanguages");
- QCOMPARE(val.userType(), qMetaTypeId<QJSValue>());
+ QCOMPARE(val.metaType(), QMetaType::fromType<QStringList>());
QList<QVariant> qmlLangs = val.toList();
QStringList langs = QLocale(locale).uiLanguages();
@@ -763,7 +768,15 @@ void tst_qqmllocale::testFunctionCall()
STOP_ON_FAILURE
QVERIFY(evaluationResult.canConvert<QString>());
STOP_ON_FAILURE
- QCOMPARE(evaluationResult.toString(), expectedResult);
+
+ // We're not interested in whether the spaces in the date/time format
+ // are breaking or non-breaking.
+ const QString resultWithBreakingSpaces
+ = evaluationResult.toString().replace(u'\u202f', u' ');
+ const QString expectedWithBreakingSpaces
+ = expectedResult.replace(u'\u202f', u' ');
+
+ QCOMPARE(resultWithBreakingSpaces, expectedWithBreakingSpaces);
STOP_ON_FAILURE
} else {
QVERIFY(qmlExpression.hasError());
diff --git a/tests/auto/qml/qqmlmetaobject/CMakeLists.txt b/tests/auto/qml/qqmlmetaobject/CMakeLists.txt
index 9895bb04fb..6f77e030e6 100644
--- a/tests/auto/qml/qqmlmetaobject/CMakeLists.txt
+++ b/tests/auto/qml/qqmlmetaobject/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlmetaobject Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlmetaobject LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
index d945f460eb..0516140667 100644
--- a/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
+++ b/tests/auto/qml/qqmlmetaobject/tst_qqmlmetaobject.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtCore/QScopedPointer>
diff --git a/tests/auto/qml/qqmlmetatype/CMakeLists.txt b/tests/auto/qml/qqmlmetatype/CMakeLists.txt
index 7a5b47b571..2ab974ca91 100644
--- a/tests/auto/qml/qqmlmetatype/CMakeLists.txt
+++ b/tests/auto/qml/qqmlmetatype/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlmetatype Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlmetatype LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlmetatype/data/Components/App.qml b/tests/auto/qml/qqmlmetatype/data/Components/App.qml
index 57b2b4520a..693cffea40 100644
--- a/tests/auto/qml/qqmlmetatype/data/Components/App.qml
+++ b/tests/auto/qml/qqmlmetatype/data/Components/App.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.0
diff --git a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
index c1bac33d87..04c2a5bfdb 100644
--- a/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
+++ b/tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qstandardpaths.h>
#include <qtest.h>
@@ -51,6 +51,9 @@ private slots:
void enumsInRecursiveImport();
void revertValueTypeAnimation();
+
+ void clearPropertyCaches();
+ void builtins();
};
class TestType : public QObject
@@ -724,6 +727,115 @@ void tst_qqmlmetatype::revertValueTypeAnimation()
QCOMPARE(o->property("pointSize").toDouble(), 12.0);
}
+void tst_qqmlmetatype::clearPropertyCaches()
+{
+ qmlClearTypeRegistrations();
+ qmlRegisterType<TestType>("ClearPropertyCaches", 1, 0, "A");
+ QQmlPropertyCache::ConstPtr oldCache = QQmlMetaType::propertyCache(&TestType::staticMetaObject);
+ QVERIFY(oldCache);
+ qmlClearTypeRegistrations();
+ qmlRegisterType<TestType>("ClearPropertyCaches", 1, 0, "B");
+ QQmlPropertyCache::ConstPtr newCache = QQmlMetaType::propertyCache(&TestType::staticMetaObject);
+ QVERIFY(oldCache.data() != newCache.data());
+}
+
+template<typename T>
+void checkBuiltinBaseType()
+{
+ const QQmlType type = QQmlMetaType::qmlType(QMetaType::fromType<T>());
+ QVERIFY(type.isValid());
+ QCOMPARE(type.typeId(), QMetaType::fromType<T>());
+ QCOMPARE(type.qListTypeId(), QMetaType::fromType<QList<T>>());
+}
+
+template<typename T>
+void checkBuiltinListType()
+{
+ const QQmlType listType = QQmlMetaType::qmlListType(QMetaType::fromType<QList<T>>());
+ QVERIFY(listType.isValid());
+ QVERIFY(listType.isSequentialContainer());
+ QCOMPARE(listType.typeId(), QMetaType::fromType<T>());
+ QCOMPARE(listType.qListTypeId(), QMetaType::fromType<QList<T>>());
+ QCOMPARE(listType.listMetaSequence().valueMetaType(), QMetaType::fromType<T>());
+}
+
+template<typename... T>
+void checkBuiltinTypes()
+{
+ (checkBuiltinBaseType<T>(), ...);
+ (checkBuiltinListType<T>(), ...);
+}
+
+template<typename T>
+void checkNamedBuiltin(const QString &name)
+{
+ const QQmlType expected = QQmlMetaType::qmlType(QMetaType::fromType<T>());
+ const QQmlType actual = QQmlMetaType::qmlType("QML/" + name, QTypeRevision::fromVersion(1, 0));
+ if (actual != expected) {
+ qWarning() << Q_FUNC_INFO << "looking for" << name;
+ qWarning() << "found" << actual.module() << actual.elementName() << actual.version()
+ << actual.typeId();
+ qWarning() << "expected" << expected.module() << expected.elementName()
+ << expected.version() << expected.typeId();
+ QFAIL("mismatch");
+ }
+}
+
+template<typename T>
+void checkObjectBuiltin(const QString &name)
+{
+ const QQmlType objectType = QQmlMetaType::qmlType(QMetaType::fromType<T *>());
+ QVERIFY(objectType.isValid());
+ QCOMPARE(objectType.typeId(), QMetaType::fromType<T *>());
+ QCOMPARE(objectType.qListTypeId(), QMetaType::fromType<QQmlListProperty<T>>());
+
+ const QQmlType listType = QQmlMetaType::qmlListType(QMetaType::fromType<QQmlListProperty<T>>());
+ QVERIFY(listType.isValid());
+ QCOMPARE(listType.typeId(), QMetaType::fromType<T *>());
+ QCOMPARE(listType.qListTypeId(), QMetaType::fromType<QQmlListProperty<T>>());
+
+ checkNamedBuiltin<T *>(name);
+}
+
+void tst_qqmlmetatype::builtins()
+{
+ qmlClearTypeRegistrations();
+ QQmlEngine engine; // registers the builtins
+
+ checkBuiltinTypes<
+ QVariant, QJSValue, qint8, quint8, short, ushort, int, uint, qlonglong, qulonglong, float,
+ double, QChar, QString, bool, QDateTime, QDate, QTime, QUrl, QByteArray>();
+
+ checkNamedBuiltin<QVariant>("var");
+ checkNamedBuiltin<QVariant>("variant");
+ checkNamedBuiltin<int>("int");
+ checkNamedBuiltin<double>("double");
+ checkNamedBuiltin<double>("real");
+ checkNamedBuiltin<QString>("string");
+ checkNamedBuiltin<bool>("bool");
+ checkNamedBuiltin<QDateTime>("date");
+ checkNamedBuiltin<QUrl>("url");
+
+#if QT_CONFIG(regularexpression)
+ checkBuiltinBaseType<QRegularExpression>();
+ checkBuiltinListType<QRegularExpression>();
+ checkNamedBuiltin<QRegularExpression>("regexp");
+#endif
+
+ // Can't retrieve this one by metatype
+ const QQmlType voidType = QQmlMetaType::qmlType("QML/void", QTypeRevision::fromVersion(1, 0));
+ QVERIFY(voidType.isValid());
+ QCOMPARE(voidType.typeId(), QMetaType());
+ QCOMPARE(voidType.qListTypeId(), QMetaType());
+
+ // No separate list types
+ checkBuiltinBaseType<std::nullptr_t>();
+ checkBuiltinBaseType<QVariantMap>();
+
+ checkObjectBuiltin<QObject>("QtObject");
+ checkObjectBuiltin<QQmlComponent>("Component");
+}
+
QTEST_MAIN(tst_qqmlmetatype)
#include "tst_qqmlmetatype.moc"
diff --git a/tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt b/tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt
index 1d536afd24..4508ae3986 100644
--- a/tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt
+++ b/tests/auto/qml/qqmlmoduleplugin/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlmoduleplugin Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlmoduleplugin LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt b/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt
index ee68ebdfe0..56373ba3f4 100644
--- a/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt
+++ b/tests/auto/qml/qqmlmoduleplugin/data/implicit2/implicitQmldir.2.errors.txt
@@ -1,2 +1,2 @@
1:-1:a component declaration requires two or three arguments, but 4 were provided
-2:-1:internal types require 2 arguments, but 3 were provided
+2:-1:invalid version bar, expected <major>.<minor>
diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp
index b97fdf7cff..c60161f424 100644
--- a/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp
index cecc074946..000a75375f 100644
--- a/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp
index 5922ca34f5..5ffd28dcbb 100644
--- a/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
index 4400c11996..858b2b4704 100644
--- a/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp
index 8f20900838..00be65b599 100644
--- a/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp b/tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp
index 9d8c110db6..519b567c1d 100644
--- a/tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/optionalPlugin/optionalPlugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
index 9b54f3946a..7061c5a8c1 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
index eaa76e08d4..0ca3603267 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp
index d5906611b7..c97824112e 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
index db158e6b6d..1ac6e8902f 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
index f1043b4b72..4dbc3c15bb 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
index 410d2c483a..3e5ae31d62 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
index 2142ac604d..dcf9ed676a 100644
--- a/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
index c9cd28fc83..84b795d165 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
index 698e5f2692..26d9977f7d 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
index e49d1c1a28..c8620cbe5e 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
index 96d01191fd..3e4987f9b1 100644
--- a/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp
index 4383325d93..40eebfe3bb 100644
--- a/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp
index 3e851c1df3..644719cebf 100644
--- a/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
index d8de79dcfd..590f10dced 100644
--- a/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
#include <QDebug>
diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp
index ef55650a31..160f8f5ac6 100644
--- a/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp
index d50de5242c..39f7f86acf 100644
--- a/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QStringList>
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
diff --git a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
index a4901aebad..67e1591b8b 100644
--- a/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
+++ b/tests/auto/qml/qqmlmoduleplugin/tst_qqmlmoduleplugin.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <qdir.h>
#include <QtQml/qqmlengine.h>
@@ -16,7 +17,7 @@
#include <QtQuickShapes/private/qquickshapesglobal_p.h>
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
// For _PC_CASE_SENSITIVE
#include <unistd.h>
#endif
@@ -130,7 +131,9 @@ void registerStaticPlugin(const char *uri)
PluginType::metaData.append(char(QT_VERSION_MAJOR));
PluginType::metaData.append(char(QT_VERSION_MINOR));
PluginType::metaData.append(char(qPluginArchRequirements()));
+#if QT_CONFIG(cborstreamwriter)
PluginType::metaData.append(QCborValue(QCborMap::fromJsonObject(md)).toCbor());
+#endif
auto rawMetaDataFunctor = []() -> QPluginMetaData {
return {reinterpret_cast<const uchar *>(PluginType::metaData.constData()), size_t(PluginType::metaData.size())};
@@ -207,13 +210,13 @@ void tst_qqmlmoduleplugin::importsPlugin()
QTest::ignoreMessage(QtWarningMsg, qPrintable(QString("import%1 worked").arg(suffix)));
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(qmlFile));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toInt(),123);
- delete object;
}
void tst_qqmlmoduleplugin::importsPlugin_data()
@@ -239,9 +242,9 @@ void tst_qqmlmoduleplugin::incorrectPluginCase()
QString expectedError = QLatin1String("module \"org.qtproject.WrongCase\" plugin \"PluGin\" not found");
-#if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
+#if defined(Q_OS_DARWIN) || defined(Q_OS_WIN32)
bool caseSensitive = true;
-#if defined(Q_OS_MAC)
+#if defined(Q_OS_DARWIN)
int res = pathconf(QDir::currentPath().toLatin1().constData(), _PC_CASE_SENSITIVE);
if (res == -1)
QSKIP("Could not establish case sensitivity of file system");
@@ -282,12 +285,12 @@ void tst_qqmlmoduleplugin::importPluginWithQmlFile()
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestPluginWithQmlFile' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(QStringLiteral("pluginWithQmlFile.qml")));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
- delete object;
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
}
void tst_qqmlmoduleplugin::remoteImportWithQuotedUrl()
@@ -300,12 +303,12 @@ void tst_qqmlmoduleplugin::remoteImportWithQuotedUrl()
component.setData(qml.toUtf8(), QUrl());
QTRY_COMPARE(component.status(), QQmlComponent::Ready);
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QCOMPARE(object->property("width").toInt(), 300);
- QVERIFY(object != nullptr);
- delete object;
+ QVERIFY(object.get() != nullptr);
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
}
@@ -323,12 +326,12 @@ void tst_qqmlmoduleplugin::remoteImportWithUnquotedUri()
QTRY_COMPARE(component.status(), QQmlComponent::Ready);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("width").toInt(), 300);
- delete object;
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
}
@@ -368,20 +371,18 @@ void tst_qqmlmoduleplugin::importsMixedQmlCppPlugin()
{
QQmlComponent component(&engine, testFileUrl(QStringLiteral("importsMixedQmlCppPlugin.qml")));
- QObject *o = component.create();
- QVERIFY2(o != nullptr, msgComponentError(component, &engine));
+ std::unique_ptr<QObject> o { component.create() };
+ QVERIFY2(o.get() != nullptr, msgComponentError(component, &engine));
QCOMPARE(o->property("test").toBool(), true);
- delete o;
}
{
QQmlComponent component(&engine, testFileUrl(QStringLiteral("importsMixedQmlCppPlugin.2.qml")));
- QObject *o = component.create();
- QVERIFY2(o != nullptr, msgComponentError(component, &engine));
+ std::unique_ptr<QObject> o { component.create() };
+ QVERIFY2(o.get() != nullptr, msgComponentError(component, &engine));
QCOMPARE(o->property("test").toBool(), true);
QCOMPARE(o->property("test2").toBool(), true);
- delete o;
}
@@ -444,9 +445,8 @@ void tst_qqmlmoduleplugin::implicitQmldir()
QList<QQmlError> errors = component.errors();
VERIFY_ERRORS(errorFileName.toLatin1().constData());
QTest::ignoreMessage(QtWarningMsg, "QQmlComponent: Component is not ready");
- QObject *obj = component.create();
- QVERIFY(!obj);
- delete obj;
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(!obj.get());
}
void tst_qqmlmoduleplugin::importsNested_data()
@@ -481,17 +481,17 @@ void tst_qqmlmoduleplugin::importsNested()
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlNestedPluginType' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFile(file));
- QObject *obj = component.create();
+ std::unique_ptr<QObject> obj { component.create() };
if (errorFile.isEmpty()) {
if (qgetenv("DEBUG") != "" && !component.errors().isEmpty())
qWarning() << "Unexpected Errors:" << component.errors();
- QVERIFY(obj);
- delete obj;
+ QVERIFY(obj.get());
+ obj.reset();
} else {
QList<QQmlError> errors = component.errors();
VERIFY_ERRORS(errorFile.toLatin1().constData());
- QVERIFY(!obj);
+ QVERIFY(!obj.get());
}
}
@@ -684,13 +684,13 @@ void tst_qqmlmoduleplugin::importsChildPlugin()
QTest::ignoreMessage(QtWarningMsg, "child import worked");
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(QStringLiteral("child.qml")));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toInt(),123);
- delete object;
}
void tst_qqmlmoduleplugin::importsChildPlugin2()
@@ -701,13 +701,13 @@ void tst_qqmlmoduleplugin::importsChildPlugin2()
QTest::ignoreMessage(QtWarningMsg, "child import2 worked");
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(QStringLiteral("child2.qml")));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toInt(),123);
- delete object;
}
void tst_qqmlmoduleplugin::importsChildPlugin21()
@@ -718,13 +718,13 @@ void tst_qqmlmoduleplugin::importsChildPlugin21()
QTest::ignoreMessage(QtWarningMsg, "child import2.1 worked");
QTest::ignoreMessage(QtWarningMsg, "Module 'org.qtproject.AutoTestQmlPluginType.ChildPlugin' does not contain a module identifier directive - it cannot be protected from external registrations.");
QQmlComponent component(&engine, testFileUrl(QStringLiteral("child21.qml")));
- foreach (QQmlError err, component.errors())
+ const auto errors = component.errors();
+ for (const QQmlError &err : errors)
qWarning() << err;
VERIFY_ERRORS(0);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(object->property("value").toInt(),123);
- delete object;
}
void tst_qqmlmoduleplugin::parallelPluginImport()
@@ -780,10 +780,9 @@ void tst_qqmlmoduleplugin::multiSingleton()
engine.addImportPath(m_importsDirectory);
QQmlComponent component(&engine, testFileUrl("multiSingleton.qml"));
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object.get() != nullptr);
QCOMPARE(obj.objectName(), QLatin1String("first"));
- delete object;
}
void tst_qqmlmoduleplugin::optionalPlugin()
diff --git a/tests/auto/qml/qqmlnotifier/CMakeLists.txt b/tests/auto/qml/qqmlnotifier/CMakeLists.txt
index 44bd62ed9c..f91c1411e3 100644
--- a/tests/auto/qml/qqmlnotifier/CMakeLists.txt
+++ b/tests/auto/qml/qqmlnotifier/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlnotifier Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlnotifier LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
index e3171496d8..501aa472bc 100644
--- a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
+++ b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research In Motion
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
#include <QQmlEngine>
diff --git a/tests/auto/qml/qqmlobjectmodel/CMakeLists.txt b/tests/auto/qml/qqmlobjectmodel/CMakeLists.txt
index c54e195b26..aea2cae6dd 100644
--- a/tests/auto/qml/qqmlobjectmodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmlobjectmodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlobjectmodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlobjectmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlobjectmodel
SOURCES
tst_qqmlobjectmodel.cpp
diff --git a/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp b/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp
index d007f4d024..95a05ebf44 100644
--- a/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp
+++ b/tests/auto/qml/qqmlobjectmodel/tst_qqmlobjectmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQmlModels/private/qqmlobjectmodel_p.h>
#include <QtQmlModels/private/qqmlchangeset_p.h>
#include <QtTest/qsignalspy.h>
diff --git a/tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt b/tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt
index f01d281ed3..b6ecc6bc0f 100644
--- a/tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt
+++ b/tests/auto/qml/qqmlopenmetaobject/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlopenmetaobject Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlopenmetaobject LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmlopenmetaobject
SOURCES
tst_qqmlopenmetaobject.cpp
diff --git a/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp b/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
index 2432282f8c..a3ccda0a1a 100644
--- a/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
+++ b/tests/auto/qml/qqmlopenmetaobject/tst_qqmlopenmetaobject.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <private/qqmlopenmetaobject_p.h>
diff --git a/tests/auto/qml/qqmlparser/CMakeLists.txt b/tests/auto/qml/qqmlparser/CMakeLists.txt
index 48e1a97f44..faa241bb5e 100644
--- a/tests/auto/qml/qqmlparser/CMakeLists.txt
+++ b/tests/auto/qml/qqmlparser/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlparser Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlparser LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
index adad96b864..62f67e548f 100644
--- a/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
+++ b/tests/auto/qml/qqmlparser/tst_qqmlparser.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <private/qqmljsengine_p.h>
#include <private/qqmljsparser_p.h>
@@ -34,6 +34,10 @@ private slots:
void codeLocationsWithContinuationStringLiteral_data();
void noSubstitutionTemplateLiteral();
void templateLiteral();
+ void numericSeparator_data();
+ void numericSeparator();
+ void invalidNumericSeparator_data();
+ void invalidNumericSeparator();
void leadingSemicolonInClass();
void templatedReadonlyProperty();
void qmlImportInJS();
@@ -243,15 +247,13 @@ QStringList tst_qqmlparser::findFiles(const QDir &d)
QStringList rv;
- QStringList files = d.entryList(QStringList() << QLatin1String("*.qml") << QLatin1String("*.js"),
- QDir::Files);
- foreach (const QString &file, files) {
+ const QStringList files = d.entryList(
+ QStringList() << QLatin1String("*.qml") << QLatin1String("*.js"), QDir::Files);
+ for (const QString &file : files)
rv << d.absoluteFilePath(file);
- }
- QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
- QDir::NoSymLinks);
- foreach (const QString &dir, dirs) {
+ const QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
+ for (const QString &dir : dirs) {
QDir sub = d;
sub.cd(dir);
rv << findFiles(sub);
@@ -277,7 +279,7 @@ void tst_qqmlparser::qmlParser_data()
files << findFiles(QDir(examples));
files << findFiles(QDir(tests));
- foreach (const QString &file, files)
+ for (const QString &file : std::as_const(files))
QTest::newRow(qPrintable(file)) << file;
}
#endif
@@ -498,6 +500,74 @@ void tst_qqmlparser::templateLiteral()
QVERIFY(e);
}
+void tst_qqmlparser::numericSeparator_data() {
+ QTest::addColumn<QString>("code");
+ QTest::addColumn<double>("expected_value");
+
+ QTest::newRow("Separator in decimal literal") << "1_000_000_000" << 1000000000.0;
+ QTest::newRow("Separator in fractional part") << "1000.22_33" << 1000.2233;
+ QTest::newRow("Separator in exponent part") << "1e1_0_0" << std::pow(10, 100);
+ QTest::newRow("Separator in positive exponent part") << "1e+1_0_0" << 1e100;
+ QTest::newRow("Separator in negative exponent part") << "1e-1_0_0" << 1e-100;
+ QTest::newRow("Separator in binary literal with b prefix") << "0b1010_0001_1000_0101" << static_cast<double>(0b1010000110000101);
+ QTest::newRow("Separator in binary literal with B prefix") << "0B01_10_01_10" << static_cast<double>(0b01100110);
+ QTest::newRow("Separator in octal literal with o prefix") << "0o1234_5670" << static_cast<double>(012345670);
+ QTest::newRow("Separator in octal literal with O prefix") << "0O7777_0000" << static_cast<double>(077770000);
+ QTest::newRow("Separator in hex literal with x prefix") << "0xA0_B0_C0" << static_cast<double>(0xA0B0C0);
+ QTest::newRow("Separator in hex literal with X prefix") << "0X1000_AAAA" << static_cast<double>(0x1000AAAA);
+}
+
+void tst_qqmlparser::numericSeparator() {
+ using namespace QQmlJS;
+
+ QFETCH(QString, code);
+ QFETCH(double, expected_value);
+
+ QQmlJS::Engine engine;
+
+ QQmlJS::Lexer lexer(&engine);
+ lexer.setCode(code, 1);
+
+ QQmlJS::Parser parser(&engine);
+ QVERIFY(parser.parseExpression());
+
+ AST::ExpressionNode *expression = parser.expression();
+ QVERIFY(expression);
+
+ auto *literal = QQmlJS::AST::cast<QQmlJS::AST::NumericLiteral *>(expression);
+ QVERIFY(literal);
+
+ QCOMPARE(literal->value, expected_value);
+ QCOMPARE(literal->firstSourceLocation().begin(), 0u);
+ QCOMPARE(literal->lastSourceLocation().end(), quint32(code.size()));
+}
+
+void tst_qqmlparser::invalidNumericSeparator_data() {
+ QTest::addColumn<QString>("code");
+ QTest::addColumn<QString>("error");
+
+ QTest::newRow("Trailing numeric separator") << "1_" << "A trailing numeric separator is not allowed in numeric literals";
+ QTest::newRow("Multiple numeric separators") << "1__2" << "There can be at most one numeric separator between digits";
+}
+
+void tst_qqmlparser::invalidNumericSeparator() {
+ using namespace QQmlJS;
+
+ QFETCH(QString, code);
+ QFETCH(QString, error);
+
+ QQmlJS::Engine engine;
+
+ QQmlJS::Lexer lexer(&engine);
+ lexer.setCode(code, 1);
+
+ QQmlJS::Parser parser(&engine);
+ QVERIFY(!parser.parseExpression());
+
+ QVERIFY(lexer.errorCode() != Lexer::NoError);
+ QCOMPARE(lexer.errorMessage(), error);
+}
+
void tst_qqmlparser::leadingSemicolonInClass()
{
QQmlJS::Engine engine;
diff --git a/tests/auto/qml/qqmlpromise/CMakeLists.txt b/tests/auto/qml/qqmlpromise/CMakeLists.txt
index b12da35bab..749963fc12 100644
--- a/tests/auto/qml/qqmlpromise/CMakeLists.txt
+++ b/tests/auto/qml/qqmlpromise/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlpromise Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlpromise LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml b/tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml
index 18e141f787..9846777d97 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-empty-input.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml b/tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml
index be6651a3c3..103263aca6 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-invoke-then-method.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml b/tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml
index 1345fbc6d7..8f0ce78006 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-noniterable-input.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml b/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml
index 380026c485..eef8065713 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-last.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml b/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml
index e4bee826fa..b3be71243e 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-reject-reject-is-mid.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml b/tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml
index 7088aa935c..d6c37bee1d 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-all-resolve.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml b/tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml
index c924b476d9..9a5f2d0331 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-async-reject-with-value.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml b/tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml
index c7d9536bdb..7767aa49eb 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-async-resolve-with-value.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml b/tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml
index e494983ae6..f8e5a3c32c 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-executor-function-extensible.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml b/tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml
index 541b884303..321506c483 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-executor-reject.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml b/tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml
index baafee07a1..800db1144c 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-executor-resolve.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml b/tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml
index 806d276f51..22f066b2bd 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-executor-throw-exception.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-get-length.qml b/tests/auto/qml/qqmlpromise/data/promise-get-length.qml
index 96d48b42fb..cf0648025b 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-get-length.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-get-length.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml b/tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml
index 454930f06b..c6e9dce72b 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-race-empty-input.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml
index 84f85f19dc..76d344eb3b 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st-in-executor-function.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml
index b537af12a3..847911cc9f 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-1st.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml
index 498c3fa778..d7d5fbd06e 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-race-resolve-2nd.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.4
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml b/tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml
index 5dc5abcb27..003c2ef102 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-reject-catch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml b/tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml
index 6d09642842..30a08d5004 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-reject-with-value.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml
index 46700fe77e..88005b62e6 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-function-length.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml
index 383c827741..1327d91e5f 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-is-a-function.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml
index 7d31972633..f71000d0dd 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-array.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml
index aefe25bfc1..1571b3a837 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-empty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml
index 7ba5352431..62b70828fd 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-promise.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml
index 52842dde76..08cb4d62df 100644
--- a/tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml
+++ b/tests/auto/qml/qqmlpromise/data/promise-resolve-with-value.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml b/tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml
index 07d607ca99..eaa5c89717 100644
--- a/tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-fulfilled-non-callable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml b/tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml
index 876a953b7e..be31f1a4f2 100644
--- a/tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-reject-chaining.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml b/tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml
index 37c046d823..908149b1e6 100644
--- a/tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-reject-non-callable.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml b/tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml
index bb525fab7b..780e75660f 100644
--- a/tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-resolve-chaining.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml b/tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml
index 7075fc8a41..778bd085d8 100644
--- a/tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml
+++ b/tests/auto/qml/qqmlpromise/data/then-resolve-multiple-then.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
QtObject {
diff --git a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
index 2e00729dbc..c6c7767d44 100644
--- a/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
+++ b/tests/auto/qml/qqmlpromise/tst_qqmlpromise.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QString>
#include <QtTest>
#include <QQmlEngine>
diff --git a/tests/auto/qml/qqmlproperty/CMakeLists.txt b/tests/auto/qml/qqmlproperty/CMakeLists.txt
index 0d41159fb3..7148289318 100644
--- a/tests/auto/qml/qqmlproperty/CMakeLists.txt
+++ b/tests/auto/qml/qqmlproperty/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlproperty Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlproperty LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlproperty/data/invalidateQPropertyChangeTriggers.qml b/tests/auto/qml/qqmlproperty/data/invalidateQPropertyChangeTriggers.qml
new file mode 100644
index 0000000000..bfa832c1c8
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/invalidateQPropertyChangeTriggers.qml
@@ -0,0 +1,50 @@
+import QtQml
+
+QtObject {
+ id: root
+ objectName: column.text
+
+ property Component c: Component {
+ id: comp
+ QtObject { }
+ }
+
+ property QtObject rectItem: null
+
+ property bool running: false
+
+ property Timer t: Timer {
+ id: column
+ interval: 200
+ running: root.running
+ repeat: true
+
+ property string text: {
+ let item = root.rectItem
+ let result = rectItem ? rectItem.objectName : "Create Object"
+ return result
+ }
+
+ onTriggered: {
+ let rectItem = root.rectItem
+
+ // If rectItem exists destory it.
+ if (rectItem) {
+ rectItem.destroy()
+ return
+ }
+
+ // Otherwise create a new object
+ let newRectItem = comp.createObject(column, {})
+
+
+ // Setting the objectName before setting root.rectItem seems to work.
+ // newRectItem.width = 1200
+ root.rectItem = newRectItem
+
+ // But setting the objectName after setting root.rectItem seems to
+ // cause the issue.
+ newRectItem.objectName = "1300"
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/data/listAssignmentSignals.qml b/tests/auto/qml/qqmlproperty/data/listAssignmentSignals.qml
new file mode 100644
index 0000000000..8a2c68ab5d
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/listAssignmentSignals.qml
@@ -0,0 +1,13 @@
+import QtQuick 2.0
+
+Item {
+ property int signalCounter: 0
+ property list<QtObject> sourceList: [ QtObject{}, QtObject{}, QtObject{} ]
+ property list<QtObject> targetList1: sourceList
+
+ onTargetList1Changed: signalCounter++
+
+ function assignList() {
+ targetList1 = sourceList
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/data/propertyStartsWithOn.qml b/tests/auto/qml/qqmlproperty/data/propertyStartsWithOn.qml
new file mode 100644
index 0000000000..0ced54a9ca
--- /dev/null
+++ b/tests/auto/qml/qqmlproperty/data/propertyStartsWithOn.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+QtObject {
+ id: root
+ property int onlineStatus
+ property Binding b: Binding {
+ root.onlineStatus: 12
+ }
+}
diff --git a/tests/auto/qml/qqmlproperty/interfaces.h b/tests/auto/qml/qqmlproperty/interfaces.h
index 7ca15214d4..e8f08d06fc 100644
--- a/tests/auto/qml/qqmlproperty/interfaces.h
+++ b/tests/auto/qml/qqmlproperty/interfaces.h
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef INTERFACES_H
#define INTERFACES_H
diff --git a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
index 88c34f0e22..2635af705b 100644
--- a/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
+++ b/tests/auto/qml/qqmlproperty/tst_qqmlproperty.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "interfaces.h"
#include <qtest.h>
@@ -30,8 +30,15 @@ class MyQmlObject : public QObject
{
Q_OBJECT
Q_PROPERTY(QPoint pointProperty MEMBER m_point)
+ Q_PROPERTY(QString a READ objectName NOTIFY somethingHappened)
+ Q_PROPERTY(QString b READ objectName NOTIFY somethingHappened)
public:
- MyQmlObject(QObject *parent = nullptr) : QObject(parent) {}
+ MyQmlObject(QObject *parent = nullptr) : QObject(parent) {
+ connect(this, &QObject::objectNameChanged, this, &MyQmlObject::somethingHappened);
+ }
+
+signals:
+ void somethingHappened();
private:
QPoint m_point;
@@ -217,6 +224,13 @@ private slots:
void bindToNonQObjectTarget();
void assignVariantList();
+
+ void listAssignmentSignals();
+
+ void invalidateQPropertyChangeTriggers();
+
+ void propertyStartsWithOn();
+
private:
QQmlEngine engine;
};
@@ -355,6 +369,7 @@ void tst_qqmlproperty::registeredCompositeTypeProperty()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("registeredCompositeTypeProperty.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
QScopedPointer<QObject> obj(component.create());
QVERIFY(obj);
@@ -2416,9 +2431,13 @@ void tst_qqmlproperty::initFlags_data()
const QString names[] = {
QStringLiteral("foo"),
+ QStringLiteral("aChanged"),
QStringLiteral("self.foo"),
+ QStringLiteral("self.aChanged"),
QStringLiteral("onFoo"),
+ QStringLiteral("onAChanged"),
QStringLiteral("self.onFoo"),
+ QStringLiteral("self.onAChanged"),
QStringLiteral("bar"),
QStringLiteral("self.bar"),
QStringLiteral("abar"),
@@ -2453,15 +2472,15 @@ void tst_qqmlproperty::initFlags()
QQmlEngine engine;
QQmlComponent c(&engine);
c.setData(R"(
- import QtQml
- QtObject {
+ import Test
+ MyQmlObject {
id: self
signal foo()
property int bar: 12
property alias abar: self.bar
}
)", QUrl());
- QVERIFY(c.isReady());
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
QScopedPointer<QObject> o(c.create());
QVERIFY(!o.isNull());
@@ -2471,7 +2490,9 @@ void tst_qqmlproperty::initFlags()
passObject ? o.data() : nullptr, name, context, flags);
const bool usesId = name.startsWith(QStringLiteral("self."));
- const bool hasSignal = name.endsWith(QStringLiteral("foo"));
+ const bool hasSignal = name.endsWith(QStringLiteral("foo"))
+ || name.endsWith(QStringLiteral("aChanged"));
+
if (!passObject && !usesId) {
QVERIFY(!property.isValid());
} else if (passObject && usesId) {
@@ -2486,10 +2507,14 @@ void tst_qqmlproperty::initFlags()
QVERIFY(property.isProperty());
QCOMPARE(property.name(), usesId ? name.mid(strlen("self.")) : name);
QCOMPARE(property.propertyMetaType(), QMetaType::fromType<int>());
- } else {
+ } else if (name.endsWith(QStringLiteral("oo"))) { // 'onFoo' or 'foo'
QVERIFY(property.isSignalProperty());
QCOMPARE(property.name(), QStringLiteral("onFoo"));
QVERIFY(!property.propertyMetaType().isValid());
+ } else {
+ QVERIFY(property.isSignalProperty());
+ QCOMPARE(property.name(), QStringLiteral("onSomethingHappened"));
+ QVERIFY(!property.propertyMetaType().isValid());
}
}
@@ -2544,6 +2569,58 @@ void tst_qqmlproperty::assignVariantList()
QCOMPARE(holder->doubleList(), doubleList);
}
+void tst_qqmlproperty::listAssignmentSignals()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("listAssignmentSignals.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+
+ QCOMPARE(root->property("signalCounter").toInt(), 1);
+ QMetaObject::invokeMethod(root.get(), "assignList");
+ QCOMPARE(root->property("signalCounter").toInt(), 2);
+}
+
+void tst_qqmlproperty::invalidateQPropertyChangeTriggers()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("invalidateQPropertyChangeTriggers.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+
+ QStringList names;
+ QObject::connect(root.data(), &QObject::objectNameChanged, [&](const QString &name) {
+ if (names.length() == 10)
+ root->setProperty("running", false);
+ else
+ names.append(name);
+ });
+
+ root->setProperty("running", true);
+ QTRY_VERIFY(!root->property("running").toBool());
+
+ QCOMPARE(names, (QStringList {
+ u""_s, u"1300"_s, u"Create Object"_s,
+ u""_s, u"1300"_s, u"Create Object"_s,
+ u""_s, u"1300"_s, u"Create Object"_s,
+ u""_s
+ }));
+}
+
+void tst_qqmlproperty::propertyStartsWithOn()
+{
+ QTest::failOnWarning("\"onlineStatus\" is not a properly capitalized signal handler name. "
+ "\"onLineStatus\" would be correct.");
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("propertyStartsWithOn.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(!root.isNull());
+ QCOMPARE(root->property("onlineStatus").toInt(), 12);
+}
+
QTEST_MAIN(tst_qqmlproperty)
#include "tst_qqmlproperty.moc"
diff --git a/tests/auto/qml/qqmlpropertycache/CMakeLists.txt b/tests/auto/qml/qqmlpropertycache/CMakeLists.txt
index 8a7ffd2d9d..6dcb042dab 100644
--- a/tests/auto/qml/qqmlpropertycache/CMakeLists.txt
+++ b/tests/auto/qml/qqmlpropertycache/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlpropertycache Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlpropertycache LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlpropertycache/data/duplicateIdsAndGeneralizedGroupProperties.qml b/tests/auto/qml/qqmlpropertycache/data/duplicateIdsAndGeneralizedGroupProperties.qml
new file mode 100644
index 0000000000..2dd2cd8e21
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/duplicateIdsAndGeneralizedGroupProperties.qml
@@ -0,0 +1,64 @@
+import QtQuick 2.15
+
+Item {
+ component First : Item {
+ Item {
+ id: a
+ }
+
+ states: [
+ State {
+ name: "test1"
+
+ PropertyChanges {
+ a.enabled: false
+ }
+ }
+ ]
+ }
+
+ component Second : Item {
+ QtObject {
+ id: a
+ property bool enabled: true
+ }
+
+ states: [
+ State {
+ name: "test2"
+
+ PropertyChanges {
+ a.enabled: false
+ }
+ }
+ ]
+
+ property Component cc: Item {
+ Item { id: a }
+
+ states: [
+ State {
+ name: "test3"
+
+ PropertyChanges {
+ a.enabled: false
+ }
+ }
+ ]
+ }
+ }
+
+ First { id: first }
+ Second { id: second }
+ property Item third: second.cc.createObject();
+
+ Component.onCompleted: {
+ console.log(1, first.data[0].enabled, second.data[0].enabled, third.data[0].enabled);
+ first.state = "test1";
+ console.log(2, first.data[0].enabled, second.data[0].enabled, third.data[0].enabled);
+ second.state = "test2";
+ console.log(3, first.data[0].enabled, second.data[0].enabled, third.data[0].enabled);
+ third.state = "test3";
+ console.log(4, first.data[0].enabled, second.data[0].enabled, third.data[0].enabled);
+ }
+}
diff --git a/tests/auto/qml/qqmlpropertycache/data/overriddenSignal.qml b/tests/auto/qml/qqmlpropertycache/data/overriddenSignal.qml
new file mode 100644
index 0000000000..c948d47a1b
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/overriddenSignal.qml
@@ -0,0 +1,36 @@
+import QtQml
+import Test.PropertyCache
+
+QtObject {
+ id: root
+
+ property BaseObject obj: null
+ property Connections connection: Connections {
+ target: obj
+ function onPropertyAChanged() { ++root.a }
+ }
+ onObjChanged: {
+ connection.target = obj // Make sure this takes effect before sending the signal
+ obj.propertyAChanged()
+ }
+
+ property BaseObject obj2: null
+ property Connections connection2: Connections {
+ target: obj2
+ function onSignalA() { ++root.b }
+ }
+ onObj2Changed: {
+ connection2.target = obj2 // Make sure this takes effect before sending the signal
+ obj2.signalA();
+ }
+
+ property BaseObject theObj: BaseObject {}
+ Component.onCompleted: {
+ // Make sure the change signals are triggered also initially
+ obj = theObj;
+ obj2 = theObj;
+ }
+
+ property int a: 0
+ property int b: 0
+}
diff --git a/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal.qml b/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal.qml
new file mode 100644
index 0000000000..b8fee08978
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal.qml
@@ -0,0 +1,8 @@
+import QtQml
+import Test.PropertyCache
+
+BaseObject {
+ property int callCount: 0
+ function signalA() { ++callCount }
+ Component.onCompleted: signalA()
+}
diff --git a/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal2.qml b/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal2.qml
new file mode 100644
index 0000000000..cbf1cfe037
--- /dev/null
+++ b/tests/auto/qml/qqmlpropertycache/data/qmlOverriddenSignal2.qml
@@ -0,0 +1,6 @@
+import QtQml
+import Test.PropertyCache
+
+BaseObject {
+ signal propertyAChanged
+}
diff --git a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
index cfea7c0da1..6af2a3e371 100644
--- a/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
+++ b/tests/auto/qml/qqmlpropertycache/tst_qqmlpropertycache.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <private/qqmlpropertycache_p.h>
@@ -8,6 +8,7 @@
#include <QtQml/qqmlcomponent.h>
#include <private/qmetaobjectbuilder_p.h>
#include <private/qqmlcontextdata_p.h>
+#include <private/qqmlpropertycachecreator_p.h>
#include <QCryptographicHash>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -34,6 +35,8 @@ private slots:
void derivedGadgetMethod();
void restrictRegistrationVersion();
void rejectOverriddenFinal();
+ void overriddenSignals();
+ void duplicateIdsAndGeneralizedGroupProperties();
private:
QQmlEngine engine;
@@ -164,6 +167,19 @@ Q_SIGNALS:
void signalB();
};
+class OverriddenSignal : public BaseObject
+{
+ Q_OBJECT
+public:
+ OverriddenSignal(QObject *parent = nullptr) : BaseObject(parent) {}
+
+ Q_INVOKABLE void propertyAChanged() { ++propertyAChangedCalled; }
+ int propertyAChangedCalled = 0;
+
+Q_SIGNALS:
+ void signalA();
+};
+
const QQmlPropertyData *cacheProperty(const QQmlPropertyCache::ConstPtr &cache, const char *name)
{
return cache->property(QLatin1String(name), nullptr, nullptr);
@@ -707,4 +723,70 @@ void tst_qqmlpropertycache::rejectOverriddenFinal()
QCOMPARE(o->property("c").toInt(), 0);
}
+void tst_qqmlpropertycache::overriddenSignals()
+{
+ qmlRegisterTypesAndRevisions<BaseObject>("Test.PropertyCache", 3);
+ QQmlEngine engine;
+
+ QQmlComponent c1(&engine, testFileUrl("overriddenSignal.qml"));
+ QVERIFY2(!c1.isError(), qPrintable(c1.errorString()));
+
+ QScopedPointer<QObject> o(c1.create());
+
+ // the propertyAChanged _signal_ is sent once (initially).
+ QCOMPARE(o->property("a").toInt(), 1);
+
+ // signalA() is invoked once as signal, and the other time as method since both are C++.
+ QCOMPARE(o->property("b").toInt(), 1);
+
+ OverriddenSignal *derived = new OverriddenSignal(o.data());
+
+ // Does call our overridden method, since that is defined in C++
+ QCOMPARE(derived->propertyAChangedCalled, 0);
+ o->setProperty("obj", QVariant::fromValue(derived));
+ QCOMPARE(derived->propertyAChangedCalled, 1);
+
+ o->setProperty("obj2", QVariant::fromValue(derived));
+
+ // the propertyAChanged _signal_ is sent once (initially).
+ QCOMPARE(o->property("a").toInt(), 1);
+
+ // We get to receive both signalA() signals since we only match by name.
+ QCOMPARE(o->property("b").toInt(), 2);
+
+ // We shouldn't be allowed to define such things in QML, though.
+
+ const QUrl c2Url = testFileUrl("qmlOverriddenSignal.qml");
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(c2Url.toString() + QLatin1String(
+ ":6:14: Duplicate method name: "
+ "invalid override of property change signal or superclass signal")));
+ QQmlComponent c2(&engine, c2Url);
+ // Should be an error, but we can't enforce it yet.
+
+ const QUrl c3Url = testFileUrl("qmlOverriddenSignal2.qml");
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ qPrintable(c3Url.toString() + QLatin1String(
+ ":5:12: Duplicate signal name: "
+ "invalid override of property change signal or superclass signal")));
+ QQmlComponent c3(&engine, c3Url);
+ // Should be an error, but we can't enforce it yet.
+}
+
+void tst_qqmlpropertycache::duplicateIdsAndGeneralizedGroupProperties()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("duplicateIdsAndGeneralizedGroupProperties.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QTest::ignoreMessage(QtDebugMsg, "1 true true true");
+ QTest::ignoreMessage(QtDebugMsg, "2 false true true");
+ QTest::ignoreMessage(QtDebugMsg, "3 false false true");
+ QTest::ignoreMessage(QtDebugMsg, "4 false false false");
+
+ QScopedPointer<QObject> o(c.create());
+}
+
QTEST_MAIN(tst_qqmlpropertycache)
diff --git a/tests/auto/qml/qqmlpropertymap/CMakeLists.txt b/tests/auto/qml/qqmlpropertymap/CMakeLists.txt
index bb314ba006..2a7bd742fa 100644
--- a/tests/auto/qml/qqmlpropertymap/CMakeLists.txt
+++ b/tests/auto/qml/qqmlpropertymap/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlpropertymap Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlpropertymap LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
index 689202346c..2d91a8502d 100644
--- a/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
+++ b/tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQml/qqmlengine.h>
@@ -346,9 +346,8 @@ void tst_QQmlPropertyMap::controlledWrite()
component.setData(qmlSource, QUrl::fromLocalFile(""));
QVERIFY(component.isReady());
- QObject *obj = component.create();
- QVERIFY(obj);
- delete obj;
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get());
QCOMPARE(map.value(QLatin1String("key1")), QVariant("HELLO WORLD"));
QCOMPARE(map.value(QLatin1String("key2")), QVariant("Goodbye"));
@@ -364,8 +363,7 @@ void tst_QQmlPropertyMap::crashBug()
QQmlComponent c(&engine);
c.setData("import QtQuick 2.0\nBinding { target: map; property: \"myProp\"; value: 10 + 23 }",QUrl());
- QObject *obj = c.create(&context);
- delete obj;
+ std::unique_ptr<QObject> obj { c.create(&context) };
}
void tst_QQmlPropertyMap::QTBUG_17868()
@@ -378,10 +376,9 @@ void tst_QQmlPropertyMap::QTBUG_17868()
map.insert("key", 1);
QQmlComponent c(&engine);
c.setData("import QtQuick 2.0\nItem {property bool error:false; Component.onCompleted: {try{ map.keys(); }catch(e) {error=true;}}}",QUrl());
- QObject *obj = c.create(&context);
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { c.create(&context) };
+ QVERIFY(obj.get());
QVERIFY(!obj->property("error").toBool());
- delete obj;
}
@@ -434,17 +431,14 @@ void tst_QQmlPropertyMap::QTBUG_31226()
" Timer { interval: 5; running: true; onTriggered: { myProp = qmlPropertyMap.greeting; } }\n"
"}",
QUrl());
- QObject *obj = c.create(&context);
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { c.create(&context) };
+ QVERIFY(obj.get());
QQmlPropertyMap *qmlPropertyMap = obj->findChild<QQmlPropertyMap*>(QString("qmlPropertyMap"));
QVERIFY(qmlPropertyMap);
qmlPropertyMap->insert("greeting", QString("Hello world!"));
QTRY_COMPARE(obj->property("myProp").toString(), QString("Hello world!"));
-
- delete obj;
-
}
void tst_QQmlPropertyMap::QTBUG_29836()
@@ -461,13 +455,10 @@ void tst_QQmlPropertyMap::QTBUG_29836()
" Timer { interval: 5; running: true; onTriggered: enhancedMap.testSlot() }\n"
"}",
QUrl());
- QObject *obj = c.create(&context);
- QVERIFY(obj);
+ std::unique_ptr<QObject> obj { c.create(&context) };
+ QVERIFY(obj.get());
QTRY_COMPARE(map.testSlotCalled(), true);
-
- delete obj;
-
}
void tst_QQmlPropertyMap::QTBUG_35233()
diff --git a/tests/auto/qml/qqmlqt/CMakeLists.txt b/tests/auto/qml/qqmlqt/CMakeLists.txt
index f43c12d907..31f86d8877 100644
--- a/tests/auto/qml/qqmlqt/CMakeLists.txt
+++ b/tests/auto/qml/qqmlqt/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlqt Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlqt LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlqt/data/qtbug_125495.qml b/tests/auto/qml/qqmlqt/data/qtbug_125495.qml
new file mode 100644
index 0000000000..88f9cb259f
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/qtbug_125495.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+ property font fontProperty: Qt.font({ styleName: "Some Style" });
+}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 5ba1f6f848..8139ec48d7 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <private/qqmlengine_p.h>
@@ -27,7 +27,8 @@
#include <QTimeZone>
#include <QtQuickTestUtils/private/qmlutils_p.h>
-#include <private/qglobal_p.h>
+#include <private/qtenvironmentvariables_p.h> // for qTzSet()
+#include <private/qqmlengine_p.h>
class tst_qqmlqt : public QQmlDataTest
{
@@ -56,8 +57,10 @@ private slots:
void alpha();
void tint();
void color();
+#if QT_CONFIG(desktopservices)
void openUrlExternally();
void openUrlExternally_pragmaLibrary();
+#endif
void md5();
void createComponent();
void createComponent_pragmaLibrary();
@@ -82,6 +85,8 @@ private slots:
void timeRoundtrip_data();
void timeRoundtrip();
+ void fontSetsStyleName();
+
private:
QQmlEngine engine;
};
@@ -612,6 +617,7 @@ public slots:
void noteCall(const QUrl &url) { called++; last = url; }
};
+#if QT_CONFIG(desktopservices)
void tst_qqmlqt::openUrlExternally()
{
MyUrlHandler handler;
@@ -658,6 +664,7 @@ void tst_qqmlqt::openUrlExternally_pragmaLibrary()
QCOMPARE(handler.called,2);
QCOMPARE(handler.last, htmlTestFile);
}
+#endif
void tst_qqmlqt::md5()
{
@@ -805,7 +812,7 @@ void tst_qqmlqt::dateTimeFormatting()
<< component.url().toString() + ":40: TypeError: Passing incompatible arguments to C++ functions from JavaScript is not allowed."
<< component.url().toString() + ":43: TypeError: Passing incompatible arguments to C++ functions from JavaScript is not allowed.";
- foreach (const QString &warning, warnings)
+ for (const QString &warning : std::as_const(warnings))
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
warnings.clear();
@@ -820,7 +827,7 @@ void tst_qqmlqt::dateTimeFormatting()
<< "Could not convert argument 1 at"
<< "expression for err_dateTime2@";
- foreach (const QString &warning, warnings)
+ for (const QString &warning : std::as_const(warnings))
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(warning));
QScopedPointer<QObject> object(component.createWithInitialProperties({
@@ -833,7 +840,7 @@ void tst_qqmlqt::dateTimeFormatting()
QVERIFY(inputProperties.size() > 0);
QVariant result;
- foreach(const QString &prop, inputProperties) {
+ for (const QString &prop : std::as_const(inputProperties)) {
QVERIFY(QMetaObject::invokeMethod(object.data(), method.toUtf8().constData(),
Q_RETURN_ARG(QVariant, result),
Q_ARG(QVariant, prop)));
@@ -1280,12 +1287,13 @@ void tst_qqmlqt::later_data()
void tst_qqmlqt::later()
{
+ QQmlEngine engine;
QFETCH(QString, function);
QFETCH(QStringList, expectedWarnings);
QFETCH(QStringList, propNames);
QFETCH(QVariantList, values);
- foreach (const QString &w, expectedWarnings)
+ for (const QString &w : std::as_const(expectedWarnings))
QTest::ignoreMessage(QtWarningMsg, qPrintable(w));
QQmlComponent component(&engine, testFileUrl("later.qml"));
@@ -1300,7 +1308,7 @@ void tst_qqmlqt::later()
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
QCoreApplication::processEvents();
} else if (propNames.at(i) == QLatin1String("collectGarbage")) {
- engine.collectGarbage();
+ gc(engine, GCFlags::DontSendPostedEvents);
} else {
QCOMPARE(root->property(qPrintable(propNames.at(i))), values.at(i));
}
@@ -1463,6 +1471,18 @@ void tst_qqmlqt::timeRoundtrip()
QCOMPARE(tp.m_getTime, tp.m_putTime);
}
+void tst_qqmlqt::fontSetsStyleName() {
+ QQmlComponent component(&engine, testFileUrl("qtbug_125495.qml"));
+
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(object != nullptr);
+
+ QFont f;
+ f.setStyleName("Some Style");
+
+ QCOMPARE(qvariant_cast<QFont>(object->property("fontProperty")), f);
+}
+
QTEST_MAIN(tst_qqmlqt)
#include "tst_qqmlqt.moc"
diff --git a/tests/auto/qml/qqmlsettings/CMakeLists.txt b/tests/auto/qml/qqmlsettings/CMakeLists.txt
index fab4502c65..a444324120 100644
--- a/tests/auto/qml/qqmlsettings/CMakeLists.txt
+++ b/tests/auto/qml/qqmlsettings/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlsettings_labs Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlsettings_labs LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlsettings/data/aliases.qml b/tests/auto/qml/qqmlsettings/data/aliases.qml
index 25ca431a6d..21bc558799 100644
--- a/tests/auto/qml/qqmlsettings/data/aliases.qml
+++ b/tests/auto/qml/qqmlsettings/data/aliases.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.1
import QtQuick 2.2
import Qt.labs.settings 1.0
diff --git a/tests/auto/qml/qqmlsettings/data/basic.qml b/tests/auto/qml/qqmlsettings/data/basic.qml
index ce02d65a87..64520b33f2 100644
--- a/tests/auto/qml/qqmlsettings/data/basic.qml
+++ b/tests/auto/qml/qqmlsettings/data/basic.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Qt.labs.settings 1.0
Settings {
diff --git a/tests/auto/qml/qqmlsettings/data/categories.qml b/tests/auto/qml/qqmlsettings/data/categories.qml
index c333ec17eb..a6407f9cb2 100644
--- a/tests/auto/qml/qqmlsettings/data/categories.qml
+++ b/tests/auto/qml/qqmlsettings/data/categories.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Qt.labs.settings 1.0
Settings {
diff --git a/tests/auto/qml/qqmlsettings/data/cpp-aliases.qml b/tests/auto/qml/qqmlsettings/data/cpp-aliases.qml
index 0ee95641c4..84f8923705 100644
--- a/tests/auto/qml/qqmlsettings/data/cpp-aliases.qml
+++ b/tests/auto/qml/qqmlsettings/data/cpp-aliases.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.1
import QtQuick 2.2
import Qt.labs.settings 1.0
diff --git a/tests/auto/qml/qqmlsettings/data/siblings.qml b/tests/auto/qml/qqmlsettings/data/siblings.qml
index 548a0869da..962cbc128b 100644
--- a/tests/auto/qml/qqmlsettings/data/siblings.qml
+++ b/tests/auto/qml/qqmlsettings/data/siblings.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
import Qt.labs.settings 1.0
diff --git a/tests/auto/qml/qqmlsettings/data/types.qml b/tests/auto/qml/qqmlsettings/data/types.qml
index fc2209375d..eec4bb709b 100644
--- a/tests/auto/qml/qqmlsettings/data/types.qml
+++ b/tests/auto/qml/qqmlsettings/data/types.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.1
import QtQuick 2.2
import Qt.labs.settings 1.0
diff --git a/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp b/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp
index 88d8c58e2c..46ab2be3c9 100644
--- a/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp
+++ b/tests/auto/qml/qqmlsettings/tst_qqmlsettings.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtCore/QCoreApplication>
#include <QtCore/QScopedPointer>
diff --git a/tests/auto/qml/qqmlsqldatabase/CMakeLists.txt b/tests/auto/qml/qqmlsqldatabase/CMakeLists.txt
index 7537a92803..92809d0963 100644
--- a/tests/auto/qml/qqmlsqldatabase/CMakeLists.txt
+++ b/tests/auto/qml/qqmlsqldatabase/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlsqldatabase Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlsqldatabase LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml b/tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml
index fbd770740d..74226808f2 100644
--- a/tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml
+++ b/tests/auto/qml/qqmlsqldatabase/data/changeVersion.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
import QtQuick.LocalStorage 2.0
diff --git a/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp b/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp
index 67c44684a4..0269756225 100644
--- a/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp
+++ b/tests/auto/qml/qqmlsqldatabase/tst_qqmlsqldatabase.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
@@ -164,9 +165,9 @@ void tst_qqmlsqldatabase::testQml_cleanopen()
engine->collectGarbage();
- foreach (QString dbname, QSqlDatabase::connectionNames()) {
+ const QStringList connectionNames = QSqlDatabase::connectionNames();
+ for (const QString &dbname : connectionNames)
QSqlDatabase::removeDatabase(dbname);
- }
}
void tst_qqmlsqldatabase::totalDatabases()
diff --git a/tests/auto/qml/qqmltablemodel/CMakeLists.txt b/tests/auto/qml/qqmltablemodel/CMakeLists.txt
index ebd3e94835..8edd052e3c 100644
--- a/tests/auto/qml/qqmltablemodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmltablemodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmltablemodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltablemodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmltablemodel/data/TestModel.qml b/tests/auto/qml/qqmltablemodel/data/TestModel.qml
index a862af35d2..2b41837bac 100644
--- a/tests/auto/qml/qqmltablemodel/data/TestModel.qml
+++ b/tests/auto/qml/qqmltablemodel/data/TestModel.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/TestUtils.js b/tests/auto/qml/qqmltablemodel/data/TestUtils.js
index 83ac1b80a8..f6a5d4bb20 100644
--- a/tests/auto/qml/qqmltablemodel/data/TestUtils.js
+++ b/tests/auto/qml/qqmltablemodel/data/TestUtils.js
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
function testModelRoleDataProvider(index, role, cellData) {
switch (role) {
diff --git a/tests/auto/qml/qqmltablemodel/data/common.qml b/tests/auto/qml/qqmltablemodel/data/common.qml
index 7e9f46dd6f..1b3b8b5846 100644
--- a/tests/auto/qml/qqmltablemodel/data/common.qml
+++ b/tests/auto/qml/qqmltablemodel/data/common.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.13
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/complex.qml b/tests/auto/qml/qqmltablemodel/data/complex.qml
index 9075a6a26f..41c69d44f4 100644
--- a/tests/auto/qml/qqmltablemodel/data/complex.qml
+++ b/tests/auto/qml/qqmltablemodel/data/complex.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.13
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml b/tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml
index a1d9463665..dcdfd42a28 100644
--- a/tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml
+++ b/tests/auto/qml/qqmltablemodel/data/dataAndSetData.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/empty.qml b/tests/auto/qml/qqmltablemodel/data/empty.qml
index 77c0021ee6..164a38b9d1 100644
--- a/tests/auto/qml/qqmltablemodel/data/empty.qml
+++ b/tests/auto/qml/qqmltablemodel/data/empty.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml b/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml
index c08525bc95..d20650f3be 100644
--- a/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml
+++ b/tests/auto/qml/qqmltablemodel/data/intAndDouble.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml b/tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml
index bb278ff9d1..60f502d4b1 100644
--- a/tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml
+++ b/tests/auto/qml/qqmltablemodel/data/omitTableModelColumnIndex.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml b/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml
index 04c76098dd..847a89667f 100644
--- a/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml
+++ b/tests/auto/qml/qqmltablemodel/data/setDataThroughDelegate.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml b/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml
index 884427d24b..f5ece4bcf3 100644
--- a/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml
+++ b/tests/auto/qml/qqmltablemodel/data/setRowsMultipleTimes.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.12
import Qt.labs.qmlmodels 1.0
diff --git a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
index cd6eb3e9c5..f2eec6e79c 100644
--- a/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
+++ b/tests/auto/qml/qqmltablemodel/tst_qqmltablemodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QtTest/qsignalspy.h>
diff --git a/tests/auto/qml/qqmltimer/CMakeLists.txt b/tests/auto/qml/qqmltimer/CMakeLists.txt
index 1853a545d7..88d596be85 100644
--- a/tests/auto/qml/qqmltimer/CMakeLists.txt
+++ b/tests/auto/qml/qqmltimer/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmltimer Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltimer LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qqmltimer
SOURCES
tst_qqmltimer.cpp
@@ -15,6 +21,7 @@ qt_internal_add_test(tst_qqmltimer
Qt::Gui
Qt::GuiPrivate
Qt::QmlPrivate
+ Qt::QmlMetaPrivate
Qt::QuickPrivate
)
diff --git a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp
index 736907d5f0..495f7044f6 100644
--- a/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp
+++ b/tests/auto/qml/qqmltimer/tst_qqmltimer.cpp
@@ -1,14 +1,18 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-#include <QtTest/QSignalSpy>
-#include <qtest.h>
-#include <QtQml/qqmlengine.h>
-#include <QtQml/qqmlcomponent.h>
-#include <QtQml/private/qqmltimer_p.h>
-#include <QtQuick/qquickitem.h>
-#include <QDebug>
-#include <QtCore/QPauseAnimation>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <private/qabstractanimation_p.h>
+#include <private/qqmltimer_p.h>
+
+#include <QtQuick/qquickitem.h>
+
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlengine.h>
+
+#include <QtTest/qsignalspy.h>
+#include <QtTest/qtest.h>
+
+#include <QtCore/qpauseanimation.h>
void consistentWait(int ms)
{
@@ -69,7 +73,8 @@ void tst_qqmltimer::notRepeating()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
+ std::unique_ptr<QObject> o { component.create() };
+ QQmlTimer *timer = qobject_cast<QQmlTimer*>(o.get());
QVERIFY(timer != nullptr);
QVERIFY(timer->isRunning());
QVERIFY(!timer->isRepeating());
@@ -91,12 +96,12 @@ void tst_qqmltimer::notRepeatingStart()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100 }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer.get());
QVERIFY(!timer->isRunning());
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
consistentWait(200);
QCOMPARE(helper.count, 0);
@@ -107,8 +112,6 @@ void tst_qqmltimer::notRepeatingStart()
consistentWait(200);
QCOMPARE(helper.count, 1);
QVERIFY(!timer->isRunning());
-
- delete timer;
}
void tst_qqmltimer::repeat()
@@ -116,11 +119,11 @@ void tst_qqmltimer::repeat()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; repeat: true; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
QCOMPARE(helper.count, 0);
consistentWait(200);
@@ -138,7 +141,7 @@ void tst_qqmltimer::repeat()
QCOMPARE(helper.count, oldCount);
QVERIFY(!timer->isRunning());
- QSignalSpy spy(timer, SIGNAL(repeatChanged()));
+ QSignalSpy spy(timer.get(), SIGNAL(repeatChanged()));
timer->setRepeating(false);
QVERIFY(!timer->isRepeating());
@@ -149,8 +152,6 @@ void tst_qqmltimer::repeat()
timer->setRepeating(true);
QCOMPARE(spy.size(),2);
-
- delete timer;
}
void tst_qqmltimer::triggeredOnStart()
@@ -158,12 +159,12 @@ void tst_qqmltimer::triggeredOnStart()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
QVERIFY(timer->triggeredOnStart());
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
consistentWait(1);
QCOMPARE(helper.count, 1);
consistentWait(200);
@@ -172,7 +173,7 @@ void tst_qqmltimer::triggeredOnStart()
QCOMPARE(helper.count, 2);
QVERIFY(!timer->isRunning());
- QSignalSpy spy(timer, SIGNAL(triggeredOnStartChanged()));
+ QSignalSpy spy(timer.get(), SIGNAL(triggeredOnStartChanged()));
timer->setTriggeredOnStart(false);
QVERIFY(!timer->triggeredOnStart());
@@ -183,8 +184,6 @@ void tst_qqmltimer::triggeredOnStart()
timer->setTriggeredOnStart(true);
QCOMPARE(spy.size(),2);
-
- delete timer;
}
void tst_qqmltimer::triggeredOnStartRepeat()
@@ -192,11 +191,11 @@ void tst_qqmltimer::triggeredOnStartRepeat()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 100; running: true; triggeredOnStart: true; repeat: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
consistentWait(1);
QCOMPARE(helper.count, 1);
@@ -206,8 +205,6 @@ void tst_qqmltimer::triggeredOnStartRepeat()
consistentWait(200);
QVERIFY(helper.count > oldCount);
QVERIFY(timer->isRunning());
-
- delete timer;
}
void tst_qqmltimer::noTriggerIfNotRunning()
@@ -221,12 +218,10 @@ void tst_qqmltimer::noTriggerIfNotRunning()
"property Timer timer2: Timer { interval: 10; running: true; onTriggered: t1.running=false }"
"}"
), QUrl::fromLocalFile(""));
- QObject *item = component.create();
- QVERIFY(item != nullptr);
+ std::unique_ptr<QObject> item { component.create() };
+ QVERIFY(item);
consistentWait(200);
QCOMPARE(item->property("ok").toBool(), true);
-
- delete item;
}
void tst_qqmltimer::changeDuration()
@@ -234,11 +229,11 @@ void tst_qqmltimer::changeDuration()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 200; repeat: true; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
QCOMPARE(helper.count, 0);
consistentWait(500);
@@ -250,7 +245,7 @@ void tst_qqmltimer::changeDuration()
QCOMPARE(helper.count, 3);
QVERIFY(timer->isRunning());
- QSignalSpy spy(timer, SIGNAL(intervalChanged()));
+ QSignalSpy spy(timer.get(), SIGNAL(intervalChanged()));
timer->setInterval(200);
QCOMPARE(timer->interval(), 200);
@@ -261,8 +256,6 @@ void tst_qqmltimer::changeDuration()
timer->setInterval(300);
QCOMPARE(spy.size(),2);
-
- delete timer;
}
void tst_qqmltimer::restart()
@@ -270,11 +263,11 @@ void tst_qqmltimer::restart()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 1000; repeat: true; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
- QVERIFY(timer != nullptr);
+ std::unique_ptr<QQmlTimer> timer { qobject_cast<QQmlTimer*>(component.create()) };
+ QVERIFY(timer);
TimerHelper helper;
- connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
+ connect(timer.get(), SIGNAL(triggered()), &helper, SLOT(timeout()));
QCOMPARE(helper.count, 0);
consistentWait(1200);
@@ -290,8 +283,6 @@ void tst_qqmltimer::restart()
QCOMPARE(helper.count, 2);
QVERIFY(timer->isRunning());
-
- delete timer;
}
void tst_qqmltimer::restartFromTriggered()
@@ -356,14 +347,12 @@ void tst_qqmltimer::parentProperty()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQuick 2.0\nItem { Timer { objectName: \"timer\"; running: parent.visible } }"), QUrl::fromLocalFile(""));
- QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
- QVERIFY(item != nullptr);
+ std::unique_ptr<QQuickItem> item { qobject_cast<QQuickItem*>(component.create()) };
+ QVERIFY(item);
QQmlTimer *timer = item->findChild<QQmlTimer*>("timer");
QVERIFY(timer != nullptr);
QVERIFY(timer->isRunning());
-
- delete timer;
}
void tst_qqmltimer::stopWhenEventPosted()
@@ -371,7 +360,8 @@ void tst_qqmltimer::stopWhenEventPosted()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 200; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
+ std::unique_ptr<QObject> o { component.create() };
+ QQmlTimer *timer = qobject_cast<QQmlTimer*>(o.get());
TimerHelper helper;
connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
@@ -395,7 +385,8 @@ void tst_qqmltimer::restartWhenEventPosted()
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData(QByteArray("import QtQml 2.0\nTimer { interval: 200; running: true }"), QUrl::fromLocalFile(""));
- QQmlTimer *timer = qobject_cast<QQmlTimer*>(component.create());
+ std::unique_ptr<QObject> o { component.create() };
+ QQmlTimer *timer = qobject_cast<QQmlTimer*>(o.get());
TimerHelper helper;
connect(timer, SIGNAL(triggered()), &helper, SLOT(timeout()));
diff --git a/tests/auto/qml/qqmltranslation/CMakeLists.txt b/tests/auto/qml/qqmltranslation/CMakeLists.txt
index 86198e7867..12d98b95a9 100644
--- a/tests/auto/qml/qqmltranslation/CMakeLists.txt
+++ b/tests/auto/qml/qqmltranslation/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmltranslation Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltranslation LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmltranslation/data/jstranslation.qml b/tests/auto/qml/qqmltranslation/data/jstranslation.qml
index 7adde019fa..cca8bfa9e8 100644
--- a/tests/auto/qml/qqmltranslation/data/jstranslation.qml
+++ b/tests/auto/qml/qqmltranslation/data/jstranslation.qml
@@ -17,4 +17,5 @@ QtObject {
property string singular2: Js.singular2()
property string plural: Js.plural()
property string plural2: Js.plural2()
+ property string emptyContext: Js.emptyContext()
}
diff --git a/tests/auto/qml/qqmltranslation/data/pragmacontext.qml b/tests/auto/qml/qqmltranslation/data/pragmacontext.qml
new file mode 100644
index 0000000000..e158cfe4bf
--- /dev/null
+++ b/tests/auto/qml/qqmltranslation/data/pragmacontext.qml
@@ -0,0 +1,8 @@
+import QtQml 2.12
+
+pragma Translator: contextSetWithPragma
+
+QtObject {
+ property string german1: qsTr("English in translation")
+ property string german2: qsTranslate("setContext","English in translation")
+}
diff --git a/tests/auto/qml/qqmltranslation/data/pragmacontextstringliteral.qml b/tests/auto/qml/qqmltranslation/data/pragmacontextstringliteral.qml
new file mode 100644
index 0000000000..31a3d0e009
--- /dev/null
+++ b/tests/auto/qml/qqmltranslation/data/pragmacontextstringliteral.qml
@@ -0,0 +1,8 @@
+import QtQml 2.12
+
+pragma Translator: "contextSetWithPragmaStringLiteral"
+
+QtObject {
+ property string german1: qsTr("English in translation")
+ property string german2: qsTranslate("setContext","English in translation")
+}
diff --git a/tests/auto/qml/qqmltranslation/data/translation.js b/tests/auto/qml/qqmltranslation/data/translation.js
index 11117fd36e..5269926604 100644
--- a/tests/auto/qml/qqmltranslation/data/translation.js
+++ b/tests/auto/qml/qqmltranslation/data/translation.js
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
function basic() {
return qsTr("hello")
@@ -58,3 +58,7 @@ function plural2() {
return qsTr("%n duck(s)", "", 2)
return "";
}
+
+function emptyContext() {
+ return qsTranslate("", "hello")
+}
diff --git a/tests/auto/qml/qqmltranslation/data/translation.qml b/tests/auto/qml/qqmltranslation/data/translation.qml
index b96471c9dd..127b5cb5b4 100644
--- a/tests/auto/qml/qqmltranslation/data/translation.qml
+++ b/tests/auto/qml/qqmltranslation/data/translation.qml
@@ -1,8 +1,8 @@
import QtQuick 2.0
-
+// The translation data starts at line == 4. QCoreApplication::translate() tolerates this.
QtObject {
objectName: "test"
-
+ property string emptyContext: qsTranslate("", "hello")
property string basic: qsTr("hello")
property string basic2: qsTranslate("CustomContext", "goodbye")
property string basic3: if (objectName.length > 0) qsTr("hello")
diff --git a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
index f78bd3ac76..69dbd6179b 100644
--- a/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
+++ b/tests/auto/qml/qqmltranslation/tst_qqmltranslation.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -24,6 +24,8 @@ private slots:
void idTranslation();
void translationChange();
void preferJSContext();
+ void pragmaContext();
+ void pragmaContextStringLiteral();
void listModel();
};
@@ -50,11 +52,11 @@ void tst_qqmltranslation::translation()
QQmlEngine engine;
QQmlComponent component(&engine, testFile);
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
if (verifyCompiledData) {
- QQmlContext *context = qmlContext(object);
+ QQmlContext *context = qmlContext(object.get());
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine());
QQmlRefPointer<QQmlTypeData> typeData = engine->typeLoader.getType(context->baseUrl());
QVERIFY(!typeData->backupSourceCode().isValid());
@@ -66,7 +68,9 @@ void tst_qqmltranslation::translation()
<< QStringLiteral("basic2")
<< QStringLiteral("disambiguation")
<< QStringLiteral("disambiguation2")
- << QStringLiteral("singular") << QStringLiteral("plural");
+ << QStringLiteral("singular")
+ << QStringLiteral("plural")
+ << QStringLiteral("emptyContext");
const QV4::CompiledData::Object *rootObject
= compilationUnit->qmlData->objectAt(/*root object*/0);
@@ -100,9 +104,9 @@ void tst_qqmltranslation::translation()
QCOMPARE(object->property("singular2").toString(), QLatin1String("1 canard"));
QCOMPARE(object->property("plural").toString(), QLatin1String("2 canards"));
QCOMPARE(object->property("plural2").toString(), QLatin1String("2 canards"));
+ QCOMPARE(object->property("emptyContext").toString(), QLatin1String("hello"));
QCoreApplication::removeTranslator(&translator);
- delete object;
}
void tst_qqmltranslation::idTranslation()
@@ -113,11 +117,11 @@ void tst_qqmltranslation::idTranslation()
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("idtranslation.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
{
- QQmlContext *context = qmlContext(object);
+ QQmlContext *context = qmlContext(object.get());
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(context->engine());
QQmlRefPointer<QQmlTypeData> typeData = engine->typeLoader.getType(context->baseUrl());
QVERIFY(!typeData->backupSourceCode().isValid());
@@ -144,7 +148,6 @@ void tst_qqmltranslation::idTranslation()
QCOMPARE(object->property("idTranslation3").toString(), QLatin1String("bonjour tout le monde"));
QCoreApplication::removeTranslator(&translator);
- delete object;
}
class CppTranslationBase : public QQuickItem
@@ -174,6 +177,12 @@ class DummyTranslator : public QTranslator
return QString::fromUtf8("Deutsch in mylibrary");
if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "nested_js_translation"))
return QString::fromUtf8("Deutsch in Setzung");
+ if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "contextSetWithPragma"))
+ return QString::fromUtf8("Deutsch in Setzung pragma");
+ if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "contextSetWithPragmaStringLiteral"))
+ return QString::fromUtf8("Deutsch in Setzung pragma string literal");
+ if (!qstrcmp(sourceText, "English in translation") && !qstrcmp(context, "setContext"))
+ return QString::fromUtf8("Deutsch in Setzung set");
if (!qstrcmp(sourceText, "soup"))
return QString::fromUtf8("Suppe");
if (!qstrcmp(sourceText, "fish"))
@@ -245,6 +254,42 @@ void tst_qqmltranslation::preferJSContext()
QCoreApplication::removeTranslator(&translator);
}
+void tst_qqmltranslation::pragmaContext()
+{
+ DummyTranslator translator;
+ QCoreApplication::installTranslator(&translator);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("pragmacontext.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("german1").toString(),
+ QStringLiteral("Deutsch in Setzung pragma"));
+ QCOMPARE(object->property("german2").toString(),
+ QStringLiteral("Deutsch in Setzung set"));
+
+ QCoreApplication::removeTranslator(&translator);
+}
+
+void tst_qqmltranslation::pragmaContextStringLiteral()
+{
+ DummyTranslator translator;
+ QCoreApplication::installTranslator(&translator);
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("pragmacontextstringliteral.qml"));
+ QScopedPointer<QObject> object(component.create());
+ QVERIFY(!object.isNull());
+
+ QCOMPARE(object->property("german1").toString(),
+ QStringLiteral("Deutsch in Setzung pragma string literal"));
+ QCOMPARE(object->property("german2").toString(),
+ QStringLiteral("Deutsch in Setzung set"));
+
+ QCoreApplication::removeTranslator(&translator);
+}
+
void tst_qqmltranslation::listModel()
{
QQmlEngine engine;
diff --git a/tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt b/tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt
index 7c55146ddc..f260ca8287 100644
--- a/tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmltreemodeltotablemodel/CMakeLists.txt
@@ -5,6 +5,12 @@
## tst_qqmltreemodeltotablemodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltreemodeltotablemodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp b/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp
index 58587da79c..7cf077f265 100644
--- a/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp
+++ b/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testmodel.h"
@@ -129,3 +129,31 @@ bool TestModel::insertRows(int position, int rows, const QModelIndex &parent)
endInsertRows();
return true;
}
+
+void insertColumnsRecursive(TreeItem *item, int cols)
+{
+ int pos = item->m_entries.size();
+ for (int col = 0; col < cols; col++)
+ item->m_entries << QVariant(QString("%1, %2 (inserted)").arg(pos + col).arg(col));
+ for (auto child : item->m_childItems)
+ insertColumnsRecursive(child, cols);
+}
+
+bool TestModel::insertColumns(int position, int cols, const QModelIndex &parent)
+{
+ if (!parent.isValid()) {
+ qWarning() << "Cannot insert columns on an invalid parent!";
+ return false;
+ }
+
+ beginInsertColumns(parent, position, position + cols - 1);
+ TreeItem *parentItem = treeItem(parent);
+
+ TreeItem *item = m_rootItem.data();
+
+ insertColumnsRecursive(item, cols);
+ m_columnCount += cols;
+
+ endInsertColumns();
+ return true;
+}
diff --git a/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h b/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h
index f886c56d4a..c67410d5f1 100644
--- a/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h
+++ b/tests/auto/qml/qqmltreemodeltotablemodel/testmodel.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTMODEL_H
#define TESTMODEL_H
@@ -38,6 +38,7 @@ public:
QModelIndex parent(const QModelIndex &index) const override;
bool insertRows(int position, int rows, const QModelIndex &parent) override;
+ bool insertColumns(int position, int rows, const QModelIndex &parent) override;
private:
QScopedPointer<TreeItem> m_rootItem;
diff --git a/tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp b/tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp
index cd9aed4b30..47bbf1440b 100644
--- a/tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp
+++ b/tests/auto/qml/qqmltreemodeltotablemodel/tst_qqmltreemodeltotablemodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/qtest.h>
#include <QAbstractItemModelTester>
diff --git a/tests/auto/qml/qqmltypeloader/CMakeLists.txt b/tests/auto/qml/qqmltypeloader/CMakeLists.txt
index d20449579e..1bf4da34f9 100644
--- a/tests/auto/qml/qqmltypeloader/CMakeLists.txt
+++ b/tests/auto/qml/qqmltypeloader/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmltypeloader Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmltypeloader LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp
index e0ff775cb5..b1726f190f 100644
--- a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp
+++ b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "plugin.h"
diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h
index dfaafe278f..2a5a1b2a4e 100644
--- a/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h
+++ b/tests/auto/qml/qqmltypeloader/SlowImport/plugin.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SLOW_PLUGIN_H
#define SLOW_PLUGIN_H
diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp b/tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp
index 910f3eaeb6..c17da49e93 100644
--- a/tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp
+++ b/tests/auto/qml/qqmltypeloader/SlowImport/slow.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "slow.h"
diff --git a/tests/auto/qml/qqmltypeloader/SlowImport/slow.h b/tests/auto/qml/qqmltypeloader/SlowImport/slow.h
index e9f6341e5a..c3ec73bc53 100644
--- a/tests/auto/qml/qqmltypeloader/SlowImport/slow.h
+++ b/tests/auto/qml/qqmltypeloader/SlowImport/slow.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef SLOWSTUFF_H
#define SLOWSTUFF_H
diff --git a/tests/auto/qml/qqmltypeloader/data/GenericView.qml b/tests/auto/qml/qqmltypeloader/data/GenericView.qml
index 2a708d425d..0f90ef26da 100644
--- a/tests/auto/qml/qqmltypeloader/data/GenericView.qml
+++ b/tests/auto/qml/qqmltypeloader/data/GenericView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Slow 1.0
diff --git a/tests/auto/qml/qqmltypeloader/data/Intercept.qml b/tests/auto/qml/qqmltypeloader/data/Intercept.qml
index 57290832ea..d0de7e04ec 100644
--- a/tests/auto/qml/qqmltypeloader/data/Intercept.qml
+++ b/tests/auto/qml/qqmltypeloader/data/Intercept.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
import Fast 1.0
diff --git a/tests/auto/qml/qqmltypeloader/data/NiceView.qml b/tests/auto/qml/qqmltypeloader/data/NiceView.qml
index cb73650551..4f1782000a 100644
--- a/tests/auto/qml/qqmltypeloader/data/NiceView.qml
+++ b/tests/auto/qml/qqmltypeloader/data/NiceView.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmltypeloader/data/doesExist.qml b/tests/auto/qml/qqmltypeloader/data/doesExist.qml
new file mode 100644
index 0000000000..54531c4bdc
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/doesExist.qml
@@ -0,0 +1,2 @@
+import QtQml
+QtObject {}
diff --git a/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/a.qml b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/a.qml
new file mode 100644
index 0000000000..8fc36a40da
--- /dev/null
+++ b/tests/auto/qml/qqmltypeloader/data/imports/multisingletonmodule/a.qml
@@ -0,0 +1,3 @@
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qqmltypeloader/data/load_synchronous.qml b/tests/auto/qml/qqmltypeloader/data/load_synchronous.qml
index 10e1784ff1..c22a880fbd 100644
--- a/tests/auto/qml/qqmltypeloader/data/load_synchronous.qml
+++ b/tests/auto/qml/qqmltypeloader/data/load_synchronous.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
diff --git a/tests/auto/qml/qqmltypeloader/data/test_intercept.qml b/tests/auto/qml/qqmltypeloader/data/test_intercept.qml
index cd6a726f9b..930d481f7b 100644
--- a/tests/auto/qml/qqmltypeloader/data/test_intercept.qml
+++ b/tests/auto/qml/qqmltypeloader/data/test_intercept.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmltypeloader/data/test_load_complete.qml b/tests/auto/qml/qqmltypeloader/data/test_load_complete.qml
index 6cba31c434..95439b8308 100644
--- a/tests/auto/qml/qqmltypeloader/data/test_load_complete.qml
+++ b/tests/auto/qml/qqmltypeloader/data/test_load_complete.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmltypeloader/declarativetesttype.h b/tests/auto/qml/qqmltypeloader/declarativetesttype.h
index 5a33f25be5..b767342951 100644
--- a/tests/auto/qml/qqmltypeloader/declarativetesttype.h
+++ b/tests/auto/qml/qqmltypeloader/declarativetesttype.h
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef DECLARATIVETESTTYPE_H
#define DECLARATIVETESTTYPE_H
diff --git a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
index 89e208f441..7828a869e1 100644
--- a/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
+++ b/tests/auto/qml/qqmltypeloader/tst_qqmltypeloader.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtQml/qqmlengine.h>
@@ -38,6 +38,7 @@ private slots:
void redirect();
void qmlSingletonWithinModule();
void multiSingletonModule();
+ void multiSingletonModuleNoWarning();
void implicitComponentModule();
void customDiskCachePath();
void qrcRootPathUrl();
@@ -47,6 +48,7 @@ private slots:
void circularDependency();
void declarativeCppAndQmlDir();
void signalHandlersAreCompatible();
+ void loadTypeOnShutdown();
private:
void checkSingleton(const QString & dataDirectory);
@@ -62,19 +64,18 @@ void tst_QQMLTypeLoader::testLoadComplete()
#ifdef Q_OS_ANDROID
QSKIP("Loading dynamic plugins does not work on Android");
#endif
- QQuickView *window = new QQuickView();
+ std::unique_ptr<QQuickView> window = std::make_unique<QQuickView>();
window->engine()->addImportPath(QT_TESTCASE_BUILDDIR);
qDebug() << window->engine()->importPathList();
window->setGeometry(0,0,240,320);
window->setSource(testFileUrl("test_load_complete.qml"));
window->show();
- QVERIFY(QTest::qWaitForWindowExposed(window));
+ QVERIFY(QTest::qWaitForWindowExposed(window.get()));
QObject *rootObject = window->rootObject();
QTRY_VERIFY(rootObject != nullptr);
QTRY_COMPARE(rootObject->property("created").toInt(), 2);
QTRY_COMPARE(rootObject->property("loaded").toInt(), 2);
- delete window;
}
void tst_QQMLTypeLoader::loadComponentSynchronously()
@@ -92,7 +93,7 @@ void tst_QQMLTypeLoader::trimCache()
QQmlEngine engine;
QQmlTypeLoader &loader = QQmlEnginePrivate::get(&engine)->typeLoader;
QVector<QQmlTypeData *> releaseLater;
- QVector<QV4::ExecutableCompilationUnit *> releaseCompilationUnitLater;
+ QVector<QV4::CompiledData::CompilationUnit *> releaseCompilationUnitLater;
for (int i = 0; i < 256; ++i) {
QUrl url = testFileUrl("trim_cache.qml");
url.setQuery(QString::number(i));
@@ -534,6 +535,18 @@ void tst_QQMLTypeLoader::multiSingletonModule()
checkCleanCacheLoad(QLatin1String("multiSingletonModule"));
}
+void tst_QQMLTypeLoader::multiSingletonModuleNoWarning()
+{
+ // Should not warn about a "cyclic" dependency between the singletons
+ QTest::failOnWarning(QRegularExpression(".*"));
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("imports/multisingletonmodule/a.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+}
+
void tst_QQMLTypeLoader::implicitComponentModule()
{
#ifdef Q_OS_ANDROID
@@ -673,7 +686,7 @@ static void getCompilationUnitAndRuntimeInfo(QQmlRefPointer<QV4::ExecutableCompi
QVERIFY(!typeData->isError()); // this returns
}
- unit = typeData->compilationUnit();
+ unit = engine->handle()->executableCompilationUnit(typeData->compilationUnit());
QVERIFY(unit);
// the QmlIR::Document is deleted once loader.getType() is complete, so
@@ -724,6 +737,49 @@ void tst_QQMLTypeLoader::signalHandlersAreCompatible()
QVERIFY(unitFromCachegen->url() != unitFromTypeCompiler->url());
}
+void tst_QQMLTypeLoader::loadTypeOnShutdown()
+{
+ bool dead1 = false;
+ bool dead2 = false;
+
+ {
+ QQmlEngine engine;
+ auto good = new QQmlComponent(
+ &engine, testFileUrl("doesExist.qml"),
+ QQmlComponent::CompilationMode::Asynchronous, &engine);
+ QObject::connect(
+ good, &QQmlComponent::statusChanged, &engine,
+ [&](QQmlComponent::Status) {
+
+ // Must not call this if the engine is already dead.
+ QVERIFY(engine.rootContext());
+
+ });
+
+ QObject::connect(good, &QQmlComponent::destroyed, good, [&]() { dead1 = true; });
+ QVERIFY(good->isLoading());
+
+ auto bad = new QQmlComponent(
+ &engine, testFileUrl("doesNotExist.qml"),
+ QQmlComponent::CompilationMode::Asynchronous, &engine);
+ QObject::connect(
+ bad, &QQmlComponent::statusChanged, &engine,
+ [&](QQmlComponent::Status) {
+
+ // Must not call this if the engine is already dead.
+ // Must also not leak memory from the events the error produces.
+ QVERIFY(engine.rootContext());
+
+ });
+
+ QObject::connect(bad, &QQmlComponent::destroyed, bad, [&]() { dead2 = true; });
+ QVERIFY(bad->isLoading());
+ }
+
+ QVERIFY(dead1);
+ QVERIFY(dead2);
+}
+
QTEST_MAIN(tst_QQMLTypeLoader)
#include "tst_qqmltypeloader.moc"
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt b/tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt
index 156022bac1..93460d72a9 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt
+++ b/tests/auto/qml/qqmlvaluetypeproviders/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlvaluetypeproviders Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlvaluetypeproviders LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml
index 95a588d1bd..6081d460b8 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/changedSignal.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 basysKom GmbH, opensource@basyskom.com.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml
index d6707e37cd..e2c39d2d72 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/recursiveWriteBack.qml
@@ -3,11 +3,16 @@ import Test
MyTypeObject {
property list<structured> l: [{i : 21}, {c: 22}, {p: {x: 199, y: 222}}]
+ property int aa: 5
Component.onCompleted: {
l[2].i = 4
l[1].p.x = 88
l[0].sizes[1].width = 19
structured.p.x = 76
+
+ var sizesDetached = l[0].sizesDetached();
+ sizesDetached[1].width = 12;
+ aa = sizesDetached[1].width;
}
}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml b/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml
index 6a42a4f1a8..abd6f6af08 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml
+++ b/tests/auto/qml/qqmlvaluetypeproviders/data/structuredValueTypes.qml
@@ -40,7 +40,22 @@ MyTypeObject {
r2 = {x: 9, y: 10, width: 11, height: 12};
c3 = 99;
b2 = {i: 11, c: 15, p: {x: 4} }
-
+ acceptConstructible(object)
c4 = {foo: 11};
}
+
+ barren: ({i: 17})
+ function changeBarren() { barren = "foos" }
+
+ property QtObject object: QtObject {}
+ property constructible fromObject: object
+ property int listResult: acceptConstructibles([Qt.resolvedUrl("foo/bar.baz"), fromObject, 12])
+
+ property var insanity: ({})
+ property structured fromInsanity: acceptStructured(insanity)
+
+ property rect newItemPadding
+ function updatePadding() {
+ setEffectPadding(newItemPadding);
+ }
}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp
index 1746957872..fd85c117e1 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.cpp
@@ -1,11 +1,16 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testtypes.h"
+QList<Padding::LogEntry> Padding::log;
+
void registerTypes()
{
qmlRegisterType<MyTypeObject>("Test", 1, 0, "MyTypeObject");
qmlRegisterTypesAndRevisions<ConstructibleValueType>("Test", 1);
qmlRegisterTypesAndRevisions<ConstructibleFromQReal>("Test", 1);
qmlRegisterTypesAndRevisions<StructuredValueType>("Test", 1);
+ qmlRegisterTypesAndRevisions<ForeignAnonymousStructuredValueType>("Test", 1);
+ qmlRegisterTypesAndRevisions<Padding>("Test", 1);
+ qmlRegisterTypesAndRevisions<MyItem>("Test", 1);
}
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
index ca1d1b2b7a..8130ea2912 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypeproviders/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
@@ -33,6 +33,8 @@ struct ConstructibleValueType
public:
ConstructibleValueType() = default;
Q_INVOKABLE ConstructibleValueType(int foo) : m_foo(foo) {}
+ Q_INVOKABLE ConstructibleValueType(QObject *) : m_foo(67) {}
+ Q_INVOKABLE ConstructibleValueType(const QUrl &) : m_foo(68) {}
int foo() const { return m_foo; }
@@ -96,6 +98,8 @@ public:
const QList<QSizeF> &sizes() const { return m_sizes; }
void setSizes(const QList<QSizeF> &sizes) { m_sizes = sizes; }
+ Q_INVOKABLE QList<QSizeF> sizesDetached() const { return m_sizes; }
+
private:
friend bool operator==(const StructuredValueType &a, const StructuredValueType &b)
@@ -109,6 +113,35 @@ private:
QList<QSizeF> m_sizes = { QSizeF(1, 1), QSizeF(2, 2) };
};
+struct BarrenValueType
+{
+ Q_GADGET
+ Q_PROPERTY(int i READ i WRITE setI)
+
+public:
+ BarrenValueType() = default;
+ Q_INVOKABLE BarrenValueType(const QString &) : m_i(25) {}
+
+ int i() const { return m_i; }
+ void setI(int newI) { m_i = newI; }
+
+private:
+ friend bool operator==(const BarrenValueType &a, const BarrenValueType &b)
+ {
+ return a.m_i == b.m_i;
+ }
+
+ int m_i = 0;
+};
+
+struct ForeignAnonymousStructuredValueType
+{
+ Q_GADGET
+ QML_ANONYMOUS
+ QML_FOREIGN(BarrenValueType)
+ QML_STRUCTURED_VALUE
+};
+
class MyTypeObject : public QObject
{
Q_OBJECT
@@ -133,6 +166,7 @@ class MyTypeObject : public QObject
Q_PROPERTY(QVariant variant READ variant NOTIFY changed)
Q_PROPERTY(ConstructibleValueType constructible READ constructible WRITE setConstructible NOTIFY constructibleChanged)
Q_PROPERTY(StructuredValueType structured READ structured WRITE setStructured NOTIFY structuredChanged)
+ Q_PROPERTY(BarrenValueType barren READ barren WRITE setBarren NOTIFY barrenChanged)
Q_PROPERTY(QDateTime aDateTime READ aDateTime WRITE setADateTime NOTIFY aDateTimeChanged)
Q_PROPERTY(QDate aDate READ aDate WRITE setADate NOTIFY aDateChanged)
@@ -275,7 +309,7 @@ public:
{
return m_aDate;
}
- void setADate(const QDate &newADate)
+ void setADate(QDate newADate)
{
if (m_aDate == newADate)
return;
@@ -287,7 +321,7 @@ public:
{
return m_aTime;
}
- void setATime(const QTime &newATime)
+ void setATime(QTime newATime)
{
if (m_aTime == newATime)
return;
@@ -307,6 +341,47 @@ public:
emit aVariantChanged();
}
+ BarrenValueType barren() const
+ {
+ return m_barren;
+ }
+
+ void setBarren(const BarrenValueType &newBarren)
+ {
+ if (m_barren == newBarren)
+ return;
+ m_barren = newBarren;
+ emit barrenChanged();
+ }
+
+ Q_INVOKABLE void acceptConstructible(const ConstructibleValueType &a)
+ {
+ setAVariant(QVariant::fromValue(a));
+ }
+
+ Q_INVOKABLE int acceptConstructibles(const QList<ConstructibleValueType> &constructibles)
+ {
+ int result = 0;
+ for (const auto &c: constructibles) {
+ result += c.foo();
+ }
+ return result;
+ }
+
+ Q_INVOKABLE StructuredValueType acceptStructured(const StructuredValueType &a)
+ {
+ return a;
+ }
+
+ Q_INVOKABLE void setEffectPadding(const QRect &r)
+ {
+ m_hasEffectPadding = true;
+ m_effectPadding = r;
+ }
+
+ bool hasEffectPadding() const { return m_hasEffectPadding; }
+ QRectF effectPadding() const { return m_effectPadding; }
+
signals:
void changed();
void runScript();
@@ -319,6 +394,8 @@ signals:
void aTimeChanged();
void aVariantChanged();
+ void barrenChanged();
+
public slots:
QSize method() { return QSize(13, 14); }
private:
@@ -329,6 +406,139 @@ private:
QDate m_aDate;
QTime m_aTime;
QVariant m_aVariant;
+ BarrenValueType m_barren;
+ QRectF m_effectPadding;
+ bool m_hasEffectPadding = false;
+};
+
+class Padding
+{
+ Q_GADGET
+
+ Q_PROPERTY(int left READ left WRITE setLeft)
+ Q_PROPERTY(int right READ right WRITE setRight)
+
+ QML_VALUE_TYPE(padding)
+ QML_STRUCTURED_VALUE
+
+public:
+ enum LogType {
+ DefaultCtor,
+ CopyCtor,
+ MoveCtor,
+ CopyAssign,
+ MoveAssign,
+ InvokableCtor,
+ CustomCtor,
+ Invalid,
+ };
+
+ Q_ENUM(LogType);
+
+ struct LogEntry {
+ LogType type = Invalid;
+ int left = 0;
+ int right = 0;
+
+ friend QDebug operator<<(QDebug &debug, const LogEntry &self)
+ {
+ return debug << self.type << " " << self.left << " " << self.right;
+ }
+ };
+
+ static QList<LogEntry> log;
+
+ void doLog(LogType type) {
+ log.append({
+ type, m_left, m_right
+ });
+ }
+
+ Padding()
+ {
+ doLog(DefaultCtor);
+ }
+
+ Padding(const Padding &other)
+ : m_left(other.m_left)
+ , m_right(other.m_right)
+ {
+ doLog(CopyCtor);
+ }
+
+ Padding(Padding &&other)
+ : m_left(other.m_left)
+ , m_right(other.m_right)
+ {
+ doLog(MoveCtor);
+ }
+
+ Padding(int left, int right)
+ : m_left( left )
+ , m_right( right )
+ {
+ doLog(CustomCtor);
+ }
+
+ Padding &operator=(const Padding &other) {
+ if (this != &other) {
+ m_left = other.m_left;
+ m_right = other.m_right;
+ }
+ doLog(CopyAssign);
+ return *this;
+ }
+
+ Padding &operator=(Padding &&other) {
+ if (this != &other) {
+ m_left = other.m_left;
+ m_right = other.m_right;
+ }
+ doLog(MoveAssign);
+ return *this;
+ }
+
+ Q_INVOKABLE Padding(int padding )
+ : m_left( padding )
+ , m_right( padding )
+ {
+ doLog(InvokableCtor);
+ }
+
+ void setLeft(int padding) { m_left = padding; }
+ int left() const { return m_left; }
+
+ void setRight(int padding) { m_right = padding; }
+ int right() const { return m_right; }
+
+private:
+ int m_left = 0;
+ int m_right = 0;
+};
+
+class MyItem : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(Padding padding READ padding WRITE setPadding NOTIFY paddingChanged)
+ QML_ELEMENT
+
+public:
+ void setPadding(const Padding &padding)
+ {
+ if (padding.left() == m_padding.left() && padding.right() == m_padding.right())
+ return;
+
+ m_padding = padding;
+ emit paddingChanged();
+ }
+
+ const Padding &padding() const{ return m_padding; }
+
+signals:
+ void paddingChanged();
+
+private:
+ Padding m_padding{ 17, 17 };
};
void registerTypes();
diff --git a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
index 5a36c6edd3..da7e14411d 100644
--- a/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
+++ b/tests/auto/qml/qqmlvaluetypeproviders/tst_qqmlvaluetypeproviders.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -41,6 +41,7 @@ private slots:
void structured();
void recursive();
void date();
+ void constructors();
};
void tst_qqmlvaluetypeproviders::initTestCase()
@@ -253,7 +254,6 @@ void tst_qqmlvaluetypeproviders::structured()
" with value [object Object]",
"Could not find any constructor for value type ConstructibleValueType to call"
" with value QVariant(QJSValue, )",
- "Could not convert QLocale(English, Latin, Australia) to double for property y",
"Could not find any constructor for value type ConstructibleValueType to call"
" with value [object Object]",
"Could not find any constructor for value type ConstructibleValueType to call"
@@ -292,8 +292,16 @@ void tst_qqmlvaluetypeproviders::structured()
QCOMPARE(o->property("c3").value<ConstructibleValueType>(), ConstructibleValueType(99));
QCOMPARE(o->property("c4").value<ConstructibleValueType>(), ConstructibleValueType(0));
- QCOMPARE(o->property("ps").value<QList<QPointF>>(),
- QList<QPointF>({QPointF(1, 2), QPointF(3, 4), QPointF(55, 0)}));
+ const QList<QPointF> actual = o->property("ps").value<QList<QPointF>>();
+ const QList<QPointF> expected = {
+ QPointF(1, 2), QPointF(3, 4), QPointF(55, std::numeric_limits<double>::quiet_NaN())
+ };
+ QCOMPARE(actual.size(), expected.size());
+ QCOMPARE(actual[0], expected[0]);
+ QCOMPARE(actual[1], expected[1]);
+ QCOMPARE(actual[2].x(), expected[2].x());
+ QVERIFY(std::isnan(actual[2].y()));
+
QCOMPARE(o->property("ss").value<QList<QSizeF>>(),
QList<QSizeF>({QSizeF(5, 6), QSizeF(7, 8), QSizeF(-1, 99)}));
QCOMPARE(o->property("cs").value<QList<ConstructibleValueType>>(),
@@ -343,6 +351,112 @@ void tst_qqmlvaluetypeproviders::structured()
ConstructibleFromQReal(-112.5));
QCOMPARE(o->property("cr7").value<ConstructibleFromQReal>(),
ConstructibleFromQReal(50));
+
+ BarrenValueType barren;
+ barren.setI(17);
+ QCOMPARE(o->property("barren").value<BarrenValueType>(), barren);
+
+ QMetaObject::invokeMethod(o.data(), "changeBarren");
+ QCOMPARE(o->property("barren").value<BarrenValueType>(), BarrenValueType(QString()));
+
+ QCOMPARE(o->property("fromObject").value<ConstructibleValueType>(),
+ ConstructibleValueType(nullptr));
+ QCOMPARE(o->property("aVariant").value<ConstructibleValueType>(),
+ ConstructibleValueType(nullptr));
+
+ QCOMPARE(o->property("listResult").toInt(), 12 + 67 + 68);
+
+
+ // You can store all kinds of insanity in a VariantObject, but we generally don't.
+ // Since we cannot rule out the possibility of there being such VariantObjects, we need to test
+ // their conversions.
+
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), StructuredValueType());
+
+ QV4::Scope scope(e.handle());
+ QV4::ScopedString name(scope, scope.engine->newString("insanity"));
+
+ QObject *po = o.data();
+ QV4::ScopedObject js(
+ scope, scope.engine->metaTypeToJS(QMetaType::fromType<MyTypeObject *>(), &po));
+
+ const QVariantHash hash {
+ {"i", 12},
+ {"c", QUrl("http://example.com")},
+ {"p", QVariantMap {
+ {"x", 17},
+ {"y", 18}
+ }}
+ };
+ QV4::ScopedValue hashValue(
+ scope, e.handle()->newVariantObject(QMetaType::fromType<QVariantHash>(), &hash));
+
+ js->put(name, hashValue);
+
+ StructuredValueType fromHash;
+ fromHash.setI(12);
+ fromHash.setC(ConstructibleValueType(QUrl()));
+ fromHash.setP(QPointF(17, 18));
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), fromHash);
+
+ const QVariantMap map {
+ {"i", 13},
+ {"c", QVariant::fromValue(po) },
+ {"p", QVariantMap {
+ {"x", 19},
+ {"y", 20}
+ }}
+ };
+ QV4::ScopedValue mapValue(
+ scope, e.handle()->newVariantObject(QMetaType::fromType<QVariantMap>(), &map));
+ js->put(name, mapValue);
+
+ StructuredValueType fromMap;
+ fromMap.setI(13);
+ fromMap.setC(ConstructibleValueType(po));
+ fromMap.setP(QPointF(19, 20));
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), fromMap);
+
+ BarrenValueType immediate;
+ immediate.setI(14);
+ QV4::ScopedValue immediateValue(
+ scope, e.handle()->newVariantObject(QMetaType::fromType<BarrenValueType>(), &immediate));
+ js->put(name, immediateValue);
+
+ StructuredValueType fromImmediate;
+ fromImmediate.setI(14);
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), fromImmediate);
+
+ QQmlComponent c2(&e);
+ c2.setData(
+ "import QtQml; QtObject { property int i: 99; property point p: ({x: 3, y: 4}) }", QUrl());
+ QVERIFY(c2.isReady());
+ QScopedPointer<QObject> o2(c2.create());
+ QVERIFY(!o2.isNull());
+ QObject *object = o2.data();
+ QV4::ScopedValue objectValue(
+ scope, e.handle()->newVariantObject(QMetaType::fromType<QObject *>(), &object));
+ js->put(name, objectValue);
+
+ StructuredValueType fromObject;
+ fromObject.setI(99);
+ fromObject.setP(QPointF(3, 4));
+
+ QCOMPARE(o->property("fromInsanity").value<StructuredValueType>(), fromObject);
+
+ const MyTypeObject *m = static_cast<const MyTypeObject *>(po);
+ QVERIFY(!m->hasEffectPadding());
+ QMetaObject::invokeMethod(po, "updatePadding");
+ QVERIFY(m->hasEffectPadding());
+ QCOMPARE(m->effectPadding(), QRectF());
+ po->setProperty("newItemPadding", QRectF(1, 2, 3, 4));
+ QMetaObject::invokeMethod(po, "updatePadding");
+ QVERIFY(m->hasEffectPadding());
+ QCOMPARE(m->effectPadding(), QRectF(1, 2, 3, 4));
}
void tst_qqmlvaluetypeproviders::recursive()
@@ -363,6 +477,9 @@ void tst_qqmlvaluetypeproviders::recursive()
MyTypeObject *m = qobject_cast<MyTypeObject *>(o.data());
QCOMPARE(m->structured().p().x(), 76);
+
+ // Recursive write back into a list detached from the property.
+ QCOMPARE(m->property("aa").toInt(), 12);
}
void tst_qqmlvaluetypeproviders::date()
@@ -379,6 +496,72 @@ void tst_qqmlvaluetypeproviders::date()
QCOMPARE(o->property("aVariant").value<QDateTime>().time().minute(), 44);
}
+void tst_qqmlvaluetypeproviders::constructors()
+{
+
+ QQmlEngine e;
+
+ {
+ const auto guard = qScopeGuard([]() { Padding::log.clear(); });
+ QQmlComponent component(&e);
+ component.setData("import Test\nMyItem { padding : 50 }", QUrl());
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+ MyItem *item = qobject_cast<MyItem *>(o.data());
+ QVERIFY(item);
+ QCOMPARE(item->padding().left(), 50);
+ QCOMPARE(item->padding().right(), 50);
+
+ QCOMPARE(Padding::log.length(), 3);
+
+ // Created by default ctor of MyItem
+ QCOMPARE(Padding::log[0].type, Padding::CustomCtor);
+ QCOMPARE(Padding::log[0].left, 17);
+ QCOMPARE(Padding::log[0].right, 17);
+
+ // Created by assignment of integer
+ QCOMPARE(Padding::log[1].type, Padding::InvokableCtor);
+ QCOMPARE(Padding::log[1].left, 50);
+ QCOMPARE(Padding::log[1].right, 50);
+
+ // In MyItem::setPadding()
+ QCOMPARE(Padding::log[2].type, Padding::CopyAssign);
+ QCOMPARE(Padding::log[2].left, 50);
+ QCOMPARE(Padding::log[2].right, 50);
+ }
+
+ {
+ const auto guard = qScopeGuard([]() { Padding::log.clear(); });
+ QQmlComponent component(&e);
+ component.setData("import Test\nMyItem { padding: ({ left: 10, right: 20 }) }", QUrl());
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> o(component.create());
+ QVERIFY(!o.isNull());
+ MyItem *item = qobject_cast<MyItem *>(o.data());
+ QVERIFY(item);
+ QCOMPARE(item->padding().left(), 10);
+ QCOMPARE(item->padding().right(), 20);
+
+ QCOMPARE(Padding::log.length(), 3);
+
+ // Created by default ctor of MyItem
+ QCOMPARE(Padding::log[0].type, Padding::CustomCtor);
+ QCOMPARE(Padding::log[0].left, 17);
+ QCOMPARE(Padding::log[0].right, 17);
+
+ // Preparing for setting properties of structured value
+ QCOMPARE(Padding::log[1].type, Padding::DefaultCtor);
+ QCOMPARE(Padding::log[1].left, 0);
+ QCOMPARE(Padding::log[1].right, 0);
+
+ // In MyItem::setPadding()
+ QCOMPARE(Padding::log[2].type, Padding::CopyAssign);
+ QCOMPARE(Padding::log[2].left, 10);
+ QCOMPARE(Padding::log[2].right, 20);
+ }
+}
+
QTEST_MAIN(tst_qqmlvaluetypeproviders)
#include "tst_qqmlvaluetypeproviders.moc"
diff --git a/tests/auto/qml/qqmlvaluetypes/CMakeLists.txt b/tests/auto/qml/qqmlvaluetypes/CMakeLists.txt
index fd4bbc1c3f..e167aade13 100644
--- a/tests/auto/qml/qqmlvaluetypes/CMakeLists.txt
+++ b/tests/auto/qml/qqmlvaluetypes/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlvaluetypes Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlvaluetypes LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlvaluetypes/data/constructors.qml b/tests/auto/qml/qqmlvaluetypes/data/constructors.qml
new file mode 100644
index 0000000000..d94d6d8ad4
--- /dev/null
+++ b/tests/auto/qml/qqmlvaluetypes/data/constructors.qml
@@ -0,0 +1,14 @@
+import QtQuick as Q
+
+Q.QtObject {
+ property var point: new Q.point()
+ property var size: new Q.size()
+ property var rect: new Q.rect()
+ property var color: new Q.color()
+ property var vector2d: new Q.vector2d()
+ property var vector3d: new Q.vector3d()
+ property var vector4d: new Q.vector4d()
+ property var quaternion: new Q.quaternion()
+ property var matrix4x4: new Q.matrix4x4()
+ property var font: new Q.font()
+}
diff --git a/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml b/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml
index c28901956d..1827b57ca9 100644
--- a/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml
+++ b/tests/auto/qml/qqmlvaluetypes/data/matrix4x4_invokables.qml
@@ -1,4 +1,4 @@
-import QtQuick 2.0
+import QtQuick
Item {
property bool success: false
@@ -6,6 +6,7 @@ Item {
property variant m1: Qt.matrix4x4(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4)
property variant m2: Qt.matrix4x4(5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8)
property variant m3: Qt.matrix4x4(123,22,6,42,55,54,67,77,777,1,112,22,55,6696,77,777)
+ property matrix4x4 m4: PlanarTransform.fromAffineMatrix(1, 2, 3, 4, 5, 6)
property variant v1: Qt.vector4d(1,2,3,4)
property variant v2: Qt.vector3d(1,2,3)
property real factor: 2.23
@@ -101,6 +102,7 @@ Item {
if (m1.transposed() != Qt.matrix4x4(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4)) success = false;
if (m1.fuzzyEquals(m2)) success = false;
if (!m1.fuzzyEquals(m2, 10)) success = false;
+ if (m4 != Qt.matrix4x4(1, 3, 0, 5, 2, 4, 0, 6, 0, 0, 1, 0, 0, 0, 0, 1)) success = false;
if (!testTransformation()) success = false;
if (!testMatrixMapping()) success = false;
}
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.cpp b/tests/auto/qml/qqmlvaluetypes/testtypes.cpp
index 4344445514..d6304bf086 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "testtypes.h"
void registerTypes()
diff --git a/tests/auto/qml/qqmlvaluetypes/testtypes.h b/tests/auto/qml/qqmlvaluetypes/testtypes.h
index 2c431c64af..19cfc25d23 100644
--- a/tests/auto/qml/qqmlvaluetypes/testtypes.h
+++ b/tests/auto/qml/qqmlvaluetypes/testtypes.h
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TESTTYPES_H
#define TESTTYPES_H
diff --git a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
index 1f9dfb7fd4..ea521053ae 100644
--- a/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
+++ b/tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -78,6 +78,7 @@ private slots:
void writeBackOnFunctionCall();
void valueTypeConversions();
void readReferenceOnGetOwnProperty();
+ void constructors();
private:
QQmlEngine engine;
@@ -93,30 +94,26 @@ void tst_qqmlvaluetypes::point()
{
{
QQmlComponent component(&engine, testFileUrl("point_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("p_x").toInt(), 10);
QCOMPARE(object->property("p_y").toInt(), 4);
QCOMPARE(object->property("copy"), QVariant(QPoint(10, 4)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("point_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->point(), QPoint(11, 12));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("point_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QPoint(10, 4)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -129,8 +126,6 @@ void tst_qqmlvaluetypes::point()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("pointEqualsPointf").toBool(), true);
-
- delete object;
}
}
@@ -138,30 +133,26 @@ void tst_qqmlvaluetypes::pointf()
{
{
QQmlComponent component(&engine, testFileUrl("pointf_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(float(object->property("p_x").toDouble()), float(11.3));
QCOMPARE(float(object->property("p_y").toDouble()), float(-10.9));
QCOMPARE(object->property("copy"), QVariant(QPointF(11.3, -10.9)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("pointf_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->pointf(), QPointF(6.8, 9.3));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("pointf_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QPointF(11.3, -10.9)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -174,8 +165,6 @@ void tst_qqmlvaluetypes::pointf()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("pointfEqualsPoint").toBool(), true);
-
- delete object;
}
}
@@ -183,30 +172,26 @@ void tst_qqmlvaluetypes::size()
{
{
QQmlComponent component(&engine, testFileUrl("size_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("s_width").toInt(), 1912);
QCOMPARE(object->property("s_height").toInt(), 1913);
QCOMPARE(object->property("copy"), QVariant(QSize(1912, 1913)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("size_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->size(), QSize(13, 88));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("size_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QSize(1912, 1913)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -219,8 +204,6 @@ void tst_qqmlvaluetypes::size()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("sizeEqualsSizef").toBool(), true);
-
- delete object;
}
}
@@ -228,30 +211,26 @@ void tst_qqmlvaluetypes::sizef()
{
{
QQmlComponent component(&engine, testFileUrl("sizef_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(float(object->property("s_width").toDouble()), float(0.1));
QCOMPARE(float(object->property("s_height").toDouble()), float(100923.2));
QCOMPARE(object->property("copy"), QVariant(QSizeF(0.1, 100923.2)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("sizef_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->sizef(), QSizeF(44.3, 92.8));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("sizef_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QSizeF(0.1, 100923)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -264,8 +243,6 @@ void tst_qqmlvaluetypes::sizef()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("sizefEqualsSize").toBool(), true);
-
- delete object;
}
}
@@ -299,9 +276,9 @@ void tst_qqmlvaluetypes::locale()
QCOMPARE(object->property("textDirection").toInt(), int(locale.textDirection()));
QCOMPARE(object->property("uiLanguages").toStringList(), locale.uiLanguages());
QList<Qt::DayOfWeek> weekDays;
- foreach (const QVariant &weekDay, object->property("weekDays").toList()) {
+ const QVariantList weekDaysProperty = object->property("weekDays").toList();
+ for (const QVariant &weekDay : weekDaysProperty)
weekDays.append(Qt::DayOfWeek(weekDay.toInt()));
- }
QCOMPARE(weekDays, locale.weekdays());
QCOMPARE(object->property("zeroDigit").toString().at(0), locale.zeroDigit());
#endif // im
@@ -311,29 +288,25 @@ void tst_qqmlvaluetypes::locale()
void tst_qqmlvaluetypes::qmlproperty()
{
QQmlComponent component(&engine, testFileUrl("qmlproperty_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
- QCOMPARE(object->property("colorPropertyObject").value<QObject *>(), object);
+ QCOMPARE(object->property("colorPropertyObject").value<QObject *>(), object.get());
QCOMPARE(object->property("colorPropertyName").toString(), "color");
QCOMPARE(object->property("invalidPropertyObject").value<QObject *>(), nullptr);
QCOMPARE(object->property("invalidPropertyName").toString(), "");
-
- delete object;
}
void tst_qqmlvaluetypes::sizereadonly()
{
{
QQmlComponent component(&engine, testFileUrl("sizereadonly_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("s_width").toInt(), 1912);
QCOMPARE(object->property("s_height").toInt(), 1913);
QCOMPARE(object->property("copy"), QVariant(QSize(1912, 1913)));
-
- delete object;
}
{
@@ -357,12 +330,10 @@ void tst_qqmlvaluetypes::sizereadonly()
{
QQmlComponent component(&engine, testFileUrl("sizereadonly_writeerror4.qml"));
- QObject *object = component.create();
+ std::unique_ptr<QObject> object { component.create() };
QVERIFY(object);
QCOMPARE(object->property("sizereadonly").toSize(), QSize(1912, 1913));
-
- delete object;
}
}
@@ -370,8 +341,8 @@ void tst_qqmlvaluetypes::rect()
{
{
QQmlComponent component(&engine, testFileUrl("rect_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("r_x").toInt(), 2);
QCOMPARE(object->property("r_y").toInt(), 3);
@@ -382,24 +353,20 @@ void tst_qqmlvaluetypes::rect()
QCOMPARE(object->property("r_top").toInt(), 3);
QCOMPARE(object->property("r_bottom").toInt(), 104);
QCOMPARE(object->property("copy"), QVariant(QRect(2, 3, 109, 102)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("rect_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect(), QRect(1234, 7, 56, 63));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("rect_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QRect(2, 3, 109, 102)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -412,8 +379,6 @@ void tst_qqmlvaluetypes::rect()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("rectEqualsRectf").toBool(), true);
-
- delete object;
}
}
@@ -421,8 +386,8 @@ void tst_qqmlvaluetypes::rectf()
{
{
QQmlComponent component(&engine, testFileUrl("rectf_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(float(object->property("r_x").toDouble()), float(103.8));
QCOMPARE(float(object->property("r_y").toDouble()), float(99.2));
@@ -433,24 +398,20 @@ void tst_qqmlvaluetypes::rectf()
QCOMPARE(float(object->property("r_top").toDouble()), float(99.2));
QCOMPARE(float(object->property("r_bottom").toDouble()), float(176.8));
QCOMPARE(object->property("copy"), QVariant(QRectF(103.8, 99.2, 88.1, 77.6)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("rectf_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rectf(), QRectF(70.1, -113.2, 80924.8, 99.2));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("rectf_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QRectF(103.8, 99.2, 88.1, 77.6)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -463,8 +424,6 @@ void tst_qqmlvaluetypes::rectf()
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
QCOMPARE(object->property("rectfEqualsRect").toBool(), true);
-
- delete object;
}
}
@@ -472,30 +431,26 @@ void tst_qqmlvaluetypes::vector2d()
{
{
QQmlComponent component(&engine, testFileUrl("vector2d_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_x").toDouble(), (float)32.88);
QCOMPARE((float)object->property("v_y").toDouble(), (float)1.3);
QCOMPARE(object->property("copy"), QVariant(QVector2D(32.88f, 1.3f)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector2d_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->vector2(), QVector2D(-0.3f, -12.9f));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector2d_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QVector2D(32.88, 1.3)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -506,16 +461,13 @@ void tst_qqmlvaluetypes::vector2d()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector2d_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
- delete object;
}
}
@@ -523,31 +475,27 @@ void tst_qqmlvaluetypes::vector3d()
{
{
QQmlComponent component(&engine, testFileUrl("vector3d_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_x").toDouble(), (float)23.88);
QCOMPARE((float)object->property("v_y").toDouble(), (float)3.1);
QCOMPARE((float)object->property("v_z").toDouble(), (float)4.3);
QCOMPARE(object->property("copy"), QVariant(QVector3D(23.88f, 3.1f, 4.3f)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector3d_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->vector(), QVector3D(-0.3f, -12.9f, 907.4f));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector3d_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QVector3D(23.88, 3.1, 4.3)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -559,16 +507,13 @@ void tst_qqmlvaluetypes::vector3d()
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
QCOMPARE(object->property("equalsOther").toBool(), false);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector3d_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
- delete object;
}
}
@@ -576,32 +521,28 @@ void tst_qqmlvaluetypes::vector4d()
{
{
QQmlComponent component(&engine, testFileUrl("vector4d_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_x").toDouble(), (float)54.2);
QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
QCOMPARE((float)object->property("v_w").toDouble(), (float)4.3);
QCOMPARE(object->property("copy"), QVariant(QVector4D(54.2f, 23.88f, 3.1f, 4.3f)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector4d_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->vector4(), QVector4D(-0.3f, -12.9f, 907.4f, 88.5f));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector4d_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QVector4D(54.2, 23.88, 3.1, 4.3)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -612,16 +553,13 @@ void tst_qqmlvaluetypes::vector4d()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("vector4d_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
- delete object;
}
}
@@ -629,32 +567,28 @@ void tst_qqmlvaluetypes::quaternion()
{
{
QQmlComponent component(&engine, testFileUrl("quaternion_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_scalar").toDouble(), (float)4.3);
QCOMPARE((float)object->property("v_x").toDouble(), (float)54.2);
QCOMPARE((float)object->property("v_y").toDouble(), (float)23.88);
QCOMPARE((float)object->property("v_z").toDouble(), (float)3.1);
QCOMPARE(object->property("copy"), QVariant(QQuaternion(4.3f, 54.2f, 23.88f, 3.1f)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("quaternion_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->quaternion(), QQuaternion(88.5f, -0.3f, -12.9f, 907.4f));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("quaternion_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QQuaternion(4.3, 54.2, 23.88, 3.1)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -665,16 +599,13 @@ void tst_qqmlvaluetypes::quaternion()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("quaternion_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
- delete object;
}
}
@@ -682,8 +613,8 @@ void tst_qqmlvaluetypes::matrix4x4()
{
{
QQmlComponent component(&engine, testFileUrl("matrix4x4_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE((float)object->property("v_m11").toDouble(), (float)1);
QCOMPARE((float)object->property("v_m12").toDouble(), (float)2);
@@ -706,27 +637,23 @@ void tst_qqmlvaluetypes::matrix4x4()
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16)));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("matrix4x4_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->matrix(), QMatrix4x4(11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34,
41, 42, 43, 44));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("matrix4x4_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QMatrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)");
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -737,16 +664,13 @@ void tst_qqmlvaluetypes::matrix4x4()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("matrix4x4_invokables.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("success").toBool(), true);
- delete object;
}
}
@@ -754,9 +678,9 @@ void tst_qqmlvaluetypes::font()
{
{
QQmlComponent component(&engine, testFileUrl("font_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
QVERIFY2(component.isReady(), qPrintable(component.errorString()));
- QVERIFY(object != nullptr);
+ QVERIFY(object);
QCOMPARE(object->property("f_family").toString(), object->font().family());
QCOMPARE(object->property("f_bold").toBool(), object->font().bold());
@@ -783,14 +707,12 @@ void tst_qqmlvaluetypes::font()
QCOMPARE(object->property("f_wordSpacing").toDouble(), object->font().wordSpacing());
QCOMPARE(object->property("copy"), QVariant(object->font()));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("font_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QFont font;
font.setFamily("Helvetica");
@@ -815,46 +737,38 @@ void tst_qqmlvaluetypes::font()
QCOMPARE(f.capitalization(), font.capitalization());
QCOMPARE(f.letterSpacing(), font.letterSpacing());
QCOMPARE(f.wordSpacing(), font.wordSpacing());
-
- delete object;
}
// Test pixelSize
{
QQmlComponent component(&engine, testFileUrl("font_write.2.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().pixelSize(), 10);
-
- delete object;
}
// Test pixelSize and pointSize
{
QQmlComponent component(&engine, testFileUrl("font_write.3.qml"));
QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size.");
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().pixelSize(), 10);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("font_write.4.qml"));
QTest::ignoreMessage(QtWarningMsg, "Both point size and pixel size set. Using pixel size.");
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().pixelSize(), 10);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("font_write.5.qml"));
- QObject *object = qobject_cast<QObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { qobject_cast<QObject *>(component.create()) };
+ QVERIFY(object);
MyTypeObject *object1 = object->findChild<MyTypeObject *>("object1");
QVERIFY(object1 != nullptr);
MyTypeObject *object2 = object->findChild<MyTypeObject *>("object2");
@@ -862,14 +776,12 @@ void tst_qqmlvaluetypes::font()
QCOMPARE(object1->font().pixelSize(), 19);
QCOMPARE(object2->font().pointSize(), 14);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("font_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QString tostring = QLatin1String("QFont(") + object->font().toString() + QLatin1Char(')');
QCOMPARE(object->property("tostring").toString(), tostring);
@@ -880,8 +792,6 @@ void tst_qqmlvaluetypes::font()
QCOMPARE(object->property("equalsPoint").toBool(), false);
QCOMPARE(object->property("equalsRect").toBool(), false);
QCOMPARE(object->property("equalsSelf").toBool(), true);
-
- delete object;
}
}
@@ -889,8 +799,8 @@ void tst_qqmlvaluetypes::color()
{
{
QQmlComponent component(&engine, testFileUrl("color_read.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(float(object->property("v_r").toDouble()), 0.2f);
QCOMPARE(float(object->property("v_g").toDouble()), 0.88f);
@@ -916,14 +826,12 @@ void tst_qqmlvaluetypes::color()
comparison.setBlueF(0.6f);
comparison.setAlphaF(0.34f);
QCOMPARE(object->property("copy"), QVariant(comparison));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("color_write.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QColor newColor;
newColor.setRedF(0.5f);
@@ -931,38 +839,32 @@ void tst_qqmlvaluetypes::color()
newColor.setBlueF(0.3f);
newColor.setAlphaF(0.7f);
QCOMPARE(object->color(), newColor);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("color_write_HSV.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QColor newColor;
newColor.setHsvF(0.43f, 0.77f, 0.88f, 0.7f);
QCOMPARE(object->color(), newColor);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("color_write_HSL.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QColor newColor;
newColor.setHslF(0.43f, 0.74f, 0.54f, 0.7f);
QCOMPARE(object->color(), newColor);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("color_compare.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QColor comparison;
comparison.setRedF(0.2f);
comparison.setGreenF(0.88f);
@@ -990,8 +892,6 @@ void tst_qqmlvaluetypes::color()
QCOMPARE(object->property("equalsColorRHS").toBool(), object->property("equalsColor").toBool());
QCOMPARE(object->property("colorEqualsCopy").toBool(), true);
QCOMPARE(object->property("copyEqualsColor").toBool(), object->property("colorEqualsCopy").toBool());
-
- delete object;
}
}
@@ -1001,8 +901,8 @@ void tst_qqmlvaluetypes::bindingAssignment()
// binding declaration
{
QQmlComponent component(&engine, testFileUrl("bindingAssignment.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 10);
QCOMPARE(object->rect().y(), 15);
@@ -1011,8 +911,6 @@ void tst_qqmlvaluetypes::bindingAssignment()
QCOMPARE(object->rect().x(), 92);
QCOMPARE(object->rect().y(), 97);
-
- delete object;
}
// function assignment should fail without crashing
@@ -1022,12 +920,11 @@ void tst_qqmlvaluetypes::bindingAssignment()
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
QQmlComponent component(&engine, testFileUrl("bindingAssignment.2.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 5);
object->setProperty("value", QVariant(92));
QCOMPARE(object->rect().x(), 5);
- delete object;
}
}
@@ -1035,42 +932,36 @@ void tst_qqmlvaluetypes::bindingAssignment()
void tst_qqmlvaluetypes::bindingRead()
{
QQmlComponent component(&engine, testFileUrl("bindingRead.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("value").toInt(), 2);
object->setRect(QRect(19, 3, 88, 2));
QCOMPARE(object->property("value").toInt(), 19);
-
- delete object;
}
// Test static values can assign to value types
void tst_qqmlvaluetypes::staticAssignment()
{
QQmlComponent component(&engine, testFileUrl("staticAssignment.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 9);
-
- delete object;
}
// Test scripts can read/write value types
void tst_qqmlvaluetypes::scriptAccess()
{
QQmlComponent component(&engine, testFileUrl("scriptAccess.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->property("valuePre").toInt(), 2);
QCOMPARE(object->rect().x(), 19);
QCOMPARE(object->property("valuePost").toInt(), 19);
-
- delete object;
}
// Test that assigning a constant from script removes any binding
@@ -1078,8 +969,8 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
{
{
QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 10);
@@ -1094,14 +985,12 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
object->setProperty("value", QVariant(92));
QCOMPARE(object->rect().x(), 42);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.2.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 10);
@@ -1116,16 +1005,14 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
object->setProperty("value", QVariant(92));
QCOMPARE(object->rect(), QRect(10, 10, 10, 10));
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("autoBindingRemoval.3.qml"));
QString warning = component.url().toString() + ":6:5: Unable to assign [undefined] to QRect";
QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
object->setProperty("value", QVariant(QRect(9, 22, 33, 44)));
@@ -1138,8 +1025,6 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
object->setProperty("value", QVariant(QRect(19, 3, 4, 8)));
QCOMPARE(object->rect(), QRect(44, 22, 33, 44));
-
- delete object;
}
}
@@ -1147,12 +1032,10 @@ void tst_qqmlvaluetypes::autoBindingRemoval()
void tst_qqmlvaluetypes::valueSources()
{
QQmlComponent component(&engine, testFileUrl("valueSources.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 3345);
-
- delete object;
}
static void checkNoErrors(QQmlComponent& component)
@@ -1170,17 +1053,15 @@ static void checkNoErrors(QQmlComponent& component)
void tst_qqmlvaluetypes::valueInterceptors()
{
QQmlComponent component(&engine, testFileUrl("valueInterceptors.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
checkNoErrors(component);
- QVERIFY(object != nullptr);
+ QVERIFY(object);
QCOMPARE(object->rect().x(), 13);
object->setProperty("value", 99);
QCOMPARE(object->rect().x(), 112);
-
- delete object;
}
// Test that you can't assign a binding to the "root" value type, and a sub-property
@@ -1192,11 +1073,10 @@ void tst_qqmlvaluetypes::bindingConflict()
#define CPP_TEST(type, v) \
{ \
- type *t = new type; \
+ std::unique_ptr<type> t = std::make_unique<type>(); \
QVariant value(v); \
t->setValue(value); \
QCOMPARE(t->value(), value); \
- delete t; \
}
// Test that accessing a reference to a valuetype after the owning object is deleted
@@ -1205,87 +1085,76 @@ void tst_qqmlvaluetypes::deletedObject()
{
QQmlComponent component(&engine, testFileUrl("deletedObject.qml"));
QTest::ignoreMessage(QtDebugMsg, "Test: 2");
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
- QObject *dObject = qvariant_cast<QObject *>(object->property("object"));
- QVERIFY(dObject != nullptr);
- delete dObject;
+ std::unique_ptr<QObject> dObject { qvariant_cast<QObject *>(object->property("object")) };
+ QVERIFY(dObject);
+ dObject.reset();
QTest::ignoreMessage(QtDebugMsg, "Test: undefined");
object->emitRunScript();
-
- delete object;
}
// Test that value types can be assigned to another value type property in a binding
void tst_qqmlvaluetypes::bindingVariantCopy()
{
QQmlComponent component(&engine, testFileUrl("bindingVariantCopy.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
-
- delete object;
}
// Test that value types can be assigned to another value type property in script
void tst_qqmlvaluetypes::scriptVariantCopy()
{
QQmlComponent component(&engine, testFileUrl("scriptVariantCopy.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->rect(), QRect(2, 3, 109, 102));
object->emitRunScript();
QCOMPARE(object->rect(), QRect(19, 33, 5, 99));
-
- delete object;
}
void tst_qqmlvaluetypes::enums()
{
{
QQmlComponent component(&engine, testFileUrl("enums.1.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("enums.2.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("enums.3.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("enums.4.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("enums.5.qml"));
- MyTypeObject *object = qobject_cast<MyTypeObject *>(component.create());
- QVERIFY(object != nullptr);
+ std::unique_ptr<MyTypeObject> object { qobject_cast<MyTypeObject *>(component.create()) };
+ QVERIFY(object);
QCOMPARE(object->font().capitalization(), QFont::AllUppercase);
- delete object;
}
}
@@ -1295,83 +1164,73 @@ void tst_qqmlvaluetypes::conflictingBindings()
{
{
QQmlComponent component(&engine, testFileUrl("conflicting.1.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("conflicting.2.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 6);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("conflicting.3.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 24);
- QMetaObject::invokeMethod(object, "toggle");
+ QMetaObject::invokeMethod(object.get(), "toggle");
QCOMPARE(qvariant_cast<QFont>(object->property("font")).pixelSize(), 12);
-
- delete object;
}
}
void tst_qqmlvaluetypes::returnValues()
{
QQmlComponent component(&engine, testFileUrl("returnValues.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test1").toBool(), true);
QCOMPARE(object->property("test2").toBool(), true);
QCOMPARE(object->property("size").toSize(), QSize(13, 14));
-
- delete object;
}
void tst_qqmlvaluetypes::varAssignment()
{
QQmlComponent component(&engine, testFileUrl("varAssignment.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("x").toInt(), 1);
QCOMPARE(object->property("y").toInt(), 2);
QCOMPARE(object->property("z").toInt(), 3);
-
- delete object;
}
// Test bindings splice together correctly
@@ -1379,77 +1238,63 @@ void tst_qqmlvaluetypes::bindingsSpliceCorrectly()
{
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.1.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.2.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.3.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.4.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
{
QQmlComponent component(&engine, testFileUrl("bindingsSpliceCorrectly.5.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
}
void tst_qqmlvaluetypes::nonValueTypeComparison()
{
QQmlComponent component(&engine, testFileUrl("nonValueTypeComparison.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test1").toBool(), true);
QCOMPARE(object->property("test2").toBool(), true);
-
- delete object;
}
void tst_qqmlvaluetypes::initializeByWrite()
{
QQmlComponent component(&engine, testFileUrl("initializeByWrite.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QCOMPARE(object->property("test").toBool(), true);
-
- delete object;
}
void tst_qqmlvaluetypes::groupedInterceptors_data()
@@ -1483,8 +1328,8 @@ void tst_qqmlvaluetypes::groupedInterceptors()
QFETCH(QColor, expectedFinalColor);
QQmlComponent component(&engine, testFileUrl(qmlfile));
- QObject *object = component.create();
- QVERIFY2(object != nullptr, qPrintable(component.errorString()));
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY2(object.get(), qPrintable(component.errorString()));
QColor initialColor = object->property("color").value<QColor>();
QVERIFY(fuzzyCompare(initialColor.redF(), expectedInitialColor.redF()));
@@ -1499,8 +1344,6 @@ void tst_qqmlvaluetypes::groupedInterceptors()
QVERIFY(fuzzyCompare(finalColor.greenF(), expectedFinalColor.greenF()));
QVERIFY(fuzzyCompare(finalColor.blueF(), expectedFinalColor.blueF()));
QVERIFY(fuzzyCompare(finalColor.alphaF(), expectedFinalColor.alphaF()));
-
- delete object;
}
struct MyDesk
@@ -1990,6 +1833,28 @@ void tst_qqmlvaluetypes::readReferenceOnGetOwnProperty()
QVERIFY(o->property("allo").toBool());
}
+void tst_qqmlvaluetypes::constructors()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("constructors.qml"));
+ QVERIFY2(c.isReady(), qPrintable(c.errorString()));
+
+ QScopedPointer<QObject> o(c.create());
+ QVERIFY(!o.isNull());
+
+ QCOMPARE(o->property("point"), QVariant(QPointF()));
+ QCOMPARE(o->property("size"), QVariant(QSizeF()));
+ QCOMPARE(o->property("rect"), QVariant(QRectF()));
+ QCOMPARE(o->property("color"), QVariant(QColor()));
+ QCOMPARE(o->property("vector2d"), QVariant(QVector2D()));
+ QCOMPARE(o->property("vector3d"), QVariant(QVector3D()));
+ QCOMPARE(o->property("vector4d"), QVariant(QVector4D()));
+ QCOMPARE(o->property("quaternion"), QVariant(QQuaternion()));
+ QCOMPARE(o->property("matrix4x4"), QVariant(QMatrix4x4()));
+ QCOMPARE(o->property("font"), QVariant(QFont()));
+
+}
+
#undef CHECK_TYPE_IS_NOT_VALUETYPE
QTEST_MAIN(tst_qqmlvaluetypes)
diff --git a/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt b/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt
index 529840c484..3d93585812 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt
+++ b/tests/auto/qml/qqmlxmlhttprequest/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qqmlxmlhttprequest Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlxmlhttprequest LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect
index 6dba52d2de..15274c5e58 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.collection.allprop.expect
@@ -1,13 +1,13 @@
PROPFIND /container/ HTTP/1.1
-Depth: 1
-Content-Length: 95
-Connection: Keep-Alive, Upgrade, HTTP2-Settings
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-Accept-Language: en-US,*
-Content-type:i application/xml; charset="utf-8"
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+depth: 1
+content-length: 95
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+content-type:i application/xml; charset="utf-8"
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect
index dc7217d45c..f7bb57ad89 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/propfind.file.expect
@@ -1,12 +1,12 @@
PROPFIND /file HTTP/1.1
-Content-Length: 192
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-Accept-Language: en-US,*
-Content-type: text/xml; charset="utf-8"
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+content-length: 192
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+content-type: text/xml; charset="utf-8"
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml
index 5c47a27420..624cdc4a41 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.collection.allprop.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml
index dbb57b3b1b..5249ad84c1 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.response.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml
index ecc3627060..eb1dd53a97 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/WebDAV/sendPropfind.responseXML.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort.expect b/tests/auto/qml/qqmlxmlhttprequest/data/abort.expect
index 97c1661851..90e15895a6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort.expect
@@ -1,11 +1,11 @@
PUT /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 10
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: text/plain;charset=UTF-8
+content-length: 10
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
Test Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort.qml b/tests/auto/qml/qqmlxmlhttprequest/data/abort.qml
index c8d8382c8f..f07ba2dbc6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort.qml
@@ -13,32 +13,25 @@ QtObject {
var x = new XMLHttpRequest;
x.open("GET", urlDummy);
x.setRequestHeader("Test-header", "TestValue");
- x.setRequestHeader("Accept-Language", "en-US");
x.send();
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
seenDone = true;
- } else if (x.readyState == XMLHttpRequest.UNSENT) {
+ else if (x.readyState == XMLHttpRequest.UNSENT)
didNotSeeUnsent = false;
- }
}
x.abort();
- if (x.readyState == XMLHttpRequest.UNSENT) {
+ if (x.readyState == XMLHttpRequest.UNSENT)
endStateUnsent = true;
- }
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.open("PUT", url);
- x.setRequestHeader("Accept-Language", "en-US");
x.send("Test Data\n");
}
}
-
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml b/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml
index 7fcbc9367a..5933c3062d 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort_opened.qml
@@ -21,14 +21,10 @@ QtObject {
readyState = true;
x.open("PUT", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
x.abort();
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -53,8 +49,6 @@ QtObject {
}
}
-
x.send()
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml b/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml
index 0a85c6b16f..36febc41dc 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/abort_unsent.qml
@@ -21,9 +21,7 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -43,13 +41,10 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
-
x.send()
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml b/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml
index a9066093d4..cf38ca22df 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/getAllResponseHeaders.qml
@@ -31,9 +31,7 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -43,7 +41,11 @@ QtObject {
openedException = true;
}
- var headers = "connection: close\r\ncontent-type: text/html; charset=UTF-8\r\ntest-header: TestValue\r\nmultitest-header: TestValue, SecondTestValue\r\ncontent-length: 11";
+ var headers = [ "connection: close",
+ "content-type: text/html; charset=UTF-8",
+ "test-header: TestValue",
+ "multitest-header: TestValue, SecondTestValue",
+ "content-length: 11" ].join("\r\n");
// Test to the end
x.onreadystatechange = function() {
@@ -52,7 +54,7 @@ QtObject {
headersReceivedHeader = (x.getAllResponseHeaders() == headers);
} else if (x.readyState == XMLHttpRequest.DONE) {
- doneState = headersReceivedState && true;
+ doneState = headersReceivedState;
doneHeader = (x.getAllResponseHeaders() == headers);
dataOK = (x.responseText == "QML Rocks!\n");
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect
index 2270e7f3aa..299bfd4689 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.expect
@@ -1,8 +1,8 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml
index 0219d7b2fc..02c1b6ef47 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/getResponseHeader.qml
@@ -37,9 +37,7 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -56,15 +54,20 @@ QtObject {
headersReceivedNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
headersReceivedValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
- headersReceivedMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
- headersReceivedCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
+ headersReceivedMultiValidHeader =
+ (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
+ headersReceivedCookieHeader =
+ (x.getResponseHeader("Set-Cookie") == ""
+ && x.getResponseHeader("Set-Cookie2") == "");
} else if (x.readyState == XMLHttpRequest.DONE) {
- doneState = headersReceivedState && true;
+ doneState = headersReceivedState;
doneNullHeader = (x.getResponseHeader("Nonexistant-header") == "");
doneValidHeader = (x.getResponseHeader("Test-HEAder") == "TestValue");
- doneMultiValidHeader = (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
- doneCookieHeader = (x.getResponseHeader("Set-Cookie") == "" && x.getResponseHeader("Set-Cookie2") == "");
+ doneMultiValidHeader =
+ (x.getResponseHeader("MultiTest-HEAder") == "TestValue, SecondTestValue");
+ doneCookieHeader = (x.getResponseHeader("Set-Cookie") == ""
+ && x.getResponseHeader("Set-Cookie2") == "");
dataOK = (x.responseText == "QML Rocks!\n");
}
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js b/tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js
index adb7269310..4c592bc8de 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/noqmlcontext.js
@@ -1,11 +1,9 @@
(function(url, resultCollector) {
var x = new XMLHttpRequest;
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
resultCollector.responseText = x.responseText
- }
}
x.send()
})
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open.qml b/tests/auto/qml/qqmlxmlhttprequest/data/open.qml
index 6e7681dfb4..26934fabe9 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open.qml
@@ -20,9 +20,7 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -42,13 +40,10 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
-
x.send()
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect b/tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect
index 2270e7f3aa..299bfd4689 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open_network.expect
@@ -1,8 +1,8 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml b/tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml
index 3c73141954..24711de2b3 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open_sync.qml
@@ -7,7 +7,6 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("GET", url, false);
- x.setRequestHeader("Accept-Language", "en-US");
x.send();
responseText = x.responseText;
}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml b/tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml
index 4eaef536b3..f22118a1b0 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open_user.qml
@@ -20,9 +20,7 @@ QtObject {
readyState = true;
x.open("GET", url, true, "username", "password");
- x.setRequestHeader("Accept-Language","en-US");
-
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -42,13 +40,10 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
-
x.send()
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml b/tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml
index b8ce5361f3..b62b09097e 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/open_username.qml
@@ -21,7 +21,7 @@ QtObject {
x.open("GET", url, true, "sampleusername", "password");
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.qml b/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.qml
new file mode 100644
index 0000000000..922147bc4e
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.qml
@@ -0,0 +1,20 @@
+import QtQuick
+
+QtObject {
+ property string url
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ let xhr = new XMLHttpRequest;
+ xhr.open("GET", url);
+ xhr.overrideMimeType('text/xml');
+
+ // Test to the end
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === XMLHttpRequest.DONE)
+ dataOK = xhr.responseXML !== null;
+ }
+
+ xhr.send();
+ }
+}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.reply b/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.reply
new file mode 100644
index 0000000000..fed050b72d
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/overrideMimeType.reply
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Connection: close
+Content-Type: text/plain
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml b/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
index b9f0ab6e66..15503d1bc6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receiveBinaryData.qml
@@ -4,6 +4,7 @@ QtObject {
property string url
property int readSize: 0
property int status: 0
+ id: object
Component.onCompleted: {
@@ -13,7 +14,7 @@ QtObject {
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE) {
- status = request.status;
+ object.status = request.status;
var arrayBuffer = request.response;
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect b/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect
index 35d28ec76d..d18a95c7dd 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_binary_data.expect
@@ -1,8 +1,8 @@
GET /gml_logo.png HTTP/1.1
-Accept-Language: en-US,*
-Content-Type: image/png
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: image/png
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect
index 9784ba4a80..0df27ead2c 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect
@@ -1,8 +1,8 @@
GET /json.data HTTP/1.1
-Accept-Language: en-US,*
-Content-Type: application/jsonrequest
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: application/jsonrequest
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml b/tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml
index 4b216d9c85..cf06b6fda6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/responseText.qml
@@ -22,8 +22,6 @@ QtObject {
unsent = (x.responseText == "");
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
opened = (x.responseText == "");
// Test to the end
@@ -40,8 +38,6 @@ QtObject {
dataOK = (x.responseText == expectedText);
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
reset = (x.responseText == "");
}
}
@@ -51,4 +47,3 @@ QtObject {
sent = (x.responseText == "");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/responseURL.qml b/tests/auto/qml/qqmlxmlhttprequest/data/responseURL.qml
new file mode 100644
index 0000000000..3a35dcc882
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/responseURL.qml
@@ -0,0 +1,21 @@
+import QtQuick 2.0
+
+QtObject {
+ property string url
+ property string expectedURL
+
+ property bool dataOK: false
+
+ Component.onCompleted: {
+ var x = new XMLHttpRequest;
+ x.open("GET", url);
+
+ // Test to the end
+ x.onreadystatechange = function() {
+ if (x.readyState === XMLHttpRequest.DONE)
+ dataOK = (x.responseURL === expectedURL);
+ }
+
+ x.send()
+ }
+}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml
index 65ce90853d..1a3a5285c0 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_alreadySent.qml
@@ -7,13 +7,11 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("GET", "testdocument.html");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send();
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect
index 64bd2b3818..708aa1a7f0 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.expect
@@ -1,11 +1,11 @@
POST /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 13
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: text/plain;charset=UTF-8
+content-length: 13
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
My Sent Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml
index 57203433c0..2f794650ba 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.1.qml
@@ -2,19 +2,16 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect
index 2bf3b5a081..bb82e8ba74 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.10.expect
@@ -1,11 +1,11 @@
OPTIONS /testdocument.html HTTP/1.1
-Accept-Language: en-US,*
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 13
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: text/plain;charset=UTF-8
+content-length: 13
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
My Sent Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect
index 7132819c72..341fb36f2a 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.expect
Binary files differ
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml
index 25584a662b..136243bbb2 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.11.qml
@@ -2,19 +2,16 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
var data = new Uint8Array([1, 2, 3, 0, 3, 2, 1, 10])
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml
index e63d58fdb6..e3d55889d6 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.2.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml
index cfd67a6a72..eaf5a057ae 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.3.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "text/plain;charset=latin1");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect
index 270ee838d9..75e6758f14 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.expect
@@ -1,11 +1,11 @@
POST /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Content-Type: charset=UTF-8;text/plain
-Content-Length: 13
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: charset=UTF-8;text/plain
+content-length: 13
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
My Sent Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml
index 808fb3a18d..e65982e6cf 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.4.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "charset=UTF-8;text/plain");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml
index c8735173d3..b3c24a5328 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.5.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "charset=latin1;text/plain");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect
index f6c8083875..02062e905b 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.expect
@@ -1,11 +1,11 @@
PUT /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Content-Type: text/plain;charset=UTF-8
-Content-Length: 13
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+content-type: text/plain;charset=UTF-8
+content-length: 13
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
My Sent Data
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml
index ee6a9caa06..345d486669 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.6.qml
@@ -2,19 +2,16 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("PUT", url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml
index 003a912818..a378624803 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.7.qml
@@ -2,23 +2,19 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("POST", url);
x.setRequestHeader("Content-Type", "text/plain");
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
x.send("My Sent Data\n");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect
index bcd7e79fc1..c580208eca 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.8.expect
@@ -1,8 +1,8 @@
OPTIONS / HTTP/1.1
-Content-Length: 0
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-Accept-Language: en-US,*
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+content-length: 0
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect
index 2d4f2c3146..3a7ae3730d 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_data.9.expect
@@ -1,8 +1,8 @@
OPTIONS /testdocument.html HTTP/1.1
-Content-Length: 0
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-Accept-Language: en-US,*
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+content-length: 0
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml
index 336971c919..38fd3800d8 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData.qml
@@ -9,19 +9,14 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open(reqType, url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
- if (reqType == "HEAD" || reqType == "DELETE")
- dataOK = (x.responseText == "");
- else
- dataOK = (x.responseText == "QML Rocks!\n");
- }
+ let expect = reqType == "HEAD" || reqType == "DELETE" ? "" : "QML Rocks!\n";
+ if (x.readyState == XMLHttpRequest.DONE)
+ dataOK = (x.responseText == expect);
}
x.send("Data To Ignore");
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect
index 7d96c00101..feca475b75 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_DELETE.expect
@@ -1,8 +1,8 @@
DELETE /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect
index 2270e7f3aa..299bfd4689 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_GET.expect
@@ -1,8 +1,8 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect
index 064cf1b6b7..fa757aeac3 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_ignoreData_HEAD.expect
@@ -1,8 +1,8 @@
HEAD /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect
index 55f7f7dceb..d6ff9854a5 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.expect
@@ -1,13 +1,13 @@
PATCH /qqmlxmlhttprequest.cpp HTTP/1.1
-Accept-Language: en-US
-If-Match: "ETagNumber"
-Content-Type: application/example
-Content-Length: 247
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+if-match: "ETagNumber"
+content-type: application/example
+content-length: 247
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
--- a/qqmlxmlhttprequest.cpp
+++ b/qqmlxmlhttprequest.cpp
@@ -15,4 +15,3 @@ Host: {{ServerHostUrl}}
- } else if (m_method == QLatin1String("OPTIONS")) {
+ } else if (m_method == QLatin1String("OPTIONS") ||
+ (m_method == QLatin1String("PATCH"))) {
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml
index 35a629fc92..d7d57b445c 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/send_patch.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2017 Canonical Limited and/or its subsidiary(-ies).
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
@@ -12,7 +12,6 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
x.open("PATCH", url);
- x.setRequestHeader("Accept-Language","en-US");
x.setRequestHeader("If-Match","\"ETagNumber\"");
// Test to the end
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect
index 003e54f33c..29d2d22030 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.expect
@@ -1,10 +1,10 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Test-header: value
-Test-header2: value,value2
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+test-header: value
+test-header2: value,value2
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml
index 4229584af2..1490d0f108 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader.qml
@@ -2,14 +2,11 @@ import QtQuick 2.0
QtObject {
property string url
-
property bool dataOK: false
Component.onCompleted: {
var x = new XMLHttpRequest;
-
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
x.setRequestHeader("Test-header", "value");
x.setRequestHeader("Test-header2", "value");
@@ -25,5 +22,3 @@ QtObject {
x.send();
}
}
-
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml
index e03f73431a..015682b5d5 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_caseInsensitive.qml
@@ -9,12 +9,10 @@ QtObject {
var x = new XMLHttpRequest;
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
-
x.setRequestHeader("Test-header", "value");
- //Setting headers with just different cases
- //will be treated as the same header, and accepted
- //as the last setting.
+
+ // Setting headers differing only in case will treat them as one header,
+ // and the values are joined with a comma.
x.setRequestHeader("Test-hEADEr2", "value");
x.setRequestHeader("Test-header2", "value2");
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml
index cd047cf8dd..23a3c42fcc 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_illegalName.qml
@@ -21,11 +21,9 @@ QtObject {
readyState = true;
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
-
x.setRequestHeader(header, "Value");
- if (x.readyState == XMLHttpRequest.OPENED)
+ if (x.readyState == XMLHttpRequest.OPENED)
openedState = true;
try {
@@ -45,14 +43,10 @@ QtObject {
// Test to the end
x.onreadystatechange = function() {
- if (x.readyState == XMLHttpRequest.DONE) {
+ if (x.readyState == XMLHttpRequest.DONE)
dataOK = (x.responseText == "QML Rocks!\n");
- }
}
-
x.send()
}
}
-
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml
index 49888fdac8..2f37006de9 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/setRequestHeader_sent.qml
@@ -8,9 +8,7 @@ QtObject {
Component.onCompleted: {
var x = new XMLHttpRequest;
-
x.open("GET", url);
- x.setRequestHeader("Accept-Language","en-US");
// Test to the end
x.onreadystatechange = function() {
@@ -29,4 +27,3 @@ QtObject {
}
}
}
-
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/status.expect b/tests/auto/qml/qqmlxmlhttprequest/data/status.expect
index 2270e7f3aa..299bfd4689 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/status.expect
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/status.expect
@@ -1,8 +1,8 @@
GET /testdocument.html HTTP/1.1
-Accept-Language: en-US
-Connection: Keep-Alive{{Ignore}}
-HTTP2-Settings: {{Ignore}}
-Accept-Encoding: {{Ignore}}
-User-Agent: Mozilla/5.0
-Host: {{ServerHostUrl}}
+accept-language: {{Ignore}}
+connection: Keep-Alive{{Ignore}}
+http2-settings: {{Ignore}}
+accept-encoding: {{Ignore}}
+user-agent: Mozilla/5.0
+host: {{ServerHostUrl}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/status.qml b/tests/auto/qml/qqmlxmlhttprequest/data/status.qml
index 94908f63c0..ed7268d6b3 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/status.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/status.qml
@@ -30,8 +30,6 @@ QtObject {
}
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
try {
var a = x.status;
} catch (e) {
@@ -54,8 +52,6 @@ QtObject {
dataOK = (x.responseText == "QML Rocks!\n");
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
try {
var a = x.status;
} catch (e) {
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml b/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml
index b47a0f1af0..cbc15b47f0 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/statusText.qml
@@ -27,8 +27,6 @@ QtObject {
}
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
try {
var a = x.statusText;
} catch (e) {
@@ -51,8 +49,6 @@ QtObject {
dataOK = (x.responseText == "QML Rocks!\n") && (x.response == "QML Rocks!\n");
x.open("GET", url);
- x.setRequestHeader("Accept-Language", "en-US");
-
try {
var a = x.statusText;
} catch (e) {
diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/text.expect b/tests/auto/qml/qqmlxmlhttprequest/data/text.expect
new file mode 100644
index 0000000000..2b4314273f
--- /dev/null
+++ b/tests/auto/qml/qqmlxmlhttprequest/data/text.expect
@@ -0,0 +1,6 @@
+GET /text.xml HTTP/1.1
+host: {{ServerHostUrl}}
+connection: Keep-Alive{{Ignore}}
+accept-encoding: {{Ignore}}
+accept-language: {{Ignore}}
+user-agent: {{Ignore}}
diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
index 6517c58670..f908633193 100644
--- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
+++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -75,6 +75,7 @@ private slots:
void statusText_data();
void responseText();
void responseText_data();
+ void responseURL();
void responseXML_invalid();
void invalidMethodUsage();
void redirects();
@@ -89,6 +90,8 @@ private slots:
void sendFileRequestNoRead();
#endif
+ void overrideMime();
+
// WebDAV
void sendPropfind();
void sendPropfind_data();
@@ -637,8 +640,6 @@ void tst_qqmlxmlhttprequest::send_options()
void tst_qqmlxmlhttprequest::send_options_data()
{
- if (QLocale::system() != QLocale(QLocale::English, QLocale::UnitedStates))
- QSKIP("Test is locale dependent");
QTest::addColumn<QString>("url_suffix");
QTest::addColumn<QString>("file_expected");
QTest::addColumn<QString>("file_qml");
@@ -863,8 +864,6 @@ void tst_qqmlxmlhttprequest::getAllResponseHeaders_args()
void tst_qqmlxmlhttprequest::getBinaryData()
{
- if (QLocale::system() != QLocale(QLocale::English, QLocale::UnitedStates))
- QSKIP("Test is locale dependent");
TestHTTPServer server;
QVERIFY2(server.listen(), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("receive_binary_data.expect"),
@@ -877,15 +876,13 @@ void tst_qqmlxmlhttprequest::getBinaryData()
object->setProperty("url", server.urlString("/gml_logo.png"));
component.completeCreate();
- QFileInfo fileInfo("data/qml_logo.png");
+ const QFileInfo fileInfo(testFile("qml_logo.png"));
QTRY_COMPARE(object->property("readSize").toInt(), fileInfo.size());
QCOMPARE(object->property("status").toInt(), 200);
}
void tst_qqmlxmlhttprequest::getJsonData()
{
- if (QLocale::system() != QLocale(QLocale::English, QLocale::UnitedStates))
- QSKIP("Test is locale dependent");
TestHTTPServer server;
QVERIFY2(server.listen(), qPrintable(server.errorString()));
QVERIFY(server.wait(testFileUrl("receive_json_data.expect"),
@@ -1025,6 +1022,64 @@ void tst_qqmlxmlhttprequest::responseText_data()
QTest::newRow("Internal server error") << testFileUrl("status.500.reply") << testFileUrl("testdocument.html") << "QML Rocks!\n";
}
+
+void tst_qqmlxmlhttprequest::responseURL()
+{
+ // 200 OK
+ {
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("status.expect"),
+ testFileUrl("status.200.reply"),
+ testFileUrl("testdocument.html")));
+
+ QQmlComponent component(engine.get(), testFileUrl("responseURL.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/testdocument.html"));
+ object->setProperty("expectedURL", server.urlString("/testdocument.html"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool());
+ }
+
+ // 200 OK with the exclude fragment flag set
+ {
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("status.expect"),
+ testFileUrl("status.200.reply"),
+ testFileUrl("testdocument.html")));
+
+ QQmlComponent component(engine.get(), testFileUrl("responseURL.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/testdocument.html#fragment"));
+ object->setProperty("expectedURL", server.urlString("/testdocument.html"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool());
+ }
+
+ // 302 Found
+ {
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ server.addRedirect("redirect.html", server.urlString("/redirecttarget.html"));
+ server.serveDirectory(dataDirectory());
+
+ QQmlComponent component(engine.get(), testFileUrl("responseURL.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/redirect.html"));
+ object->setProperty("expectedURL", server.urlString("/redirecttarget.html"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool());
+ }
+}
+
+
void tst_qqmlxmlhttprequest::nonUtf8()
{
QFETCH(QString, fileName);
@@ -1076,7 +1131,7 @@ void tst_qqmlxmlhttprequest::doFileRequest(std::function<void(QObject *component
QTemporaryFile writeFile;
QTemporaryFile readFile;
- writeFile.open();
+ QVERIFY(writeFile.open());
writeFile.close();
QVERIFY(readFile.open());
@@ -1242,8 +1297,6 @@ void tst_qqmlxmlhttprequest::sendFileRequestNoRead() {
void tst_qqmlxmlhttprequest::sendPropfind()
{
- if (QLocale::system() != QLocale(QLocale::English, QLocale::UnitedStates))
- QSKIP("Test is locale dependent");
const QString prefix = "WebDAV//";
QFETCH(QString, qml);
@@ -1277,14 +1330,17 @@ void tst_qqmlxmlhttprequest::sendPropfind_data()
QTest::addColumn<QString>("replyHeader");
QTest::addColumn<QString>("replyBody");
- QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). Get response with responseXML.")
+ QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). "
+ "Get response with responseXML.")
<< "sendPropfind.responseXML.qml" << "/file" << "propfind.file.expect"
<< "propfind.file.reply.header" << "propfind.file.reply.body";
- QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). Get response with response.")
+ QTest::newRow("Send PROPFIND for file (bigbox, author, DingALing, Random properties). "
+ "Get response with response.")
<< "sendPropfind.response.qml" << "/file" << "propfind.file.expect"
<< "propfind.file.reply.header" << "propfind.file.reply.body";
QTest::newRow("Send PROPFIND \"allprop\" request for collection.")
- << "sendPropfind.collection.allprop.qml" << "/container/" << "propfind.collection.allprop.expect"
+ << "sendPropfind.collection.allprop.qml" << "/container/"
+ << "propfind.collection.allprop.expect"
<< "propfind.file.reply.header" << "propfind.collection.allprop.reply.body";
}
@@ -1323,7 +1379,6 @@ void tst_qqmlxmlhttprequest::redirects()
QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/redirect.html"));
- object->setProperty("expectedText", "");
component.completeCreate();
QTRY_VERIFY(object->property("done").toBool());
@@ -1340,7 +1395,6 @@ void tst_qqmlxmlhttprequest::redirects()
QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/redirect.html"));
- object->setProperty("expectedText", "");
component.completeCreate();
QTRY_VERIFY(object->property("done").toBool());
@@ -1357,7 +1411,6 @@ void tst_qqmlxmlhttprequest::redirects()
QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
QVERIFY(!object.isNull());
object->setProperty("url", server.urlString("/redirect.html"));
- object->setProperty("expectedText", "");
component.completeCreate();
for (int ii = 0; ii < 60; ++ii) {
@@ -1489,6 +1542,26 @@ void tst_qqmlxmlhttprequest::stateChangeCallingContext()
QTRY_VERIFY(object->property("success").toBool());
}
+void tst_qqmlxmlhttprequest::overrideMime()
+{
+ // overrideMimeType.reply sets the Content-Type to text/plain
+ // overrideMimeType.qml overrides it to text/xml and checks the responseXML property.
+
+ TestHTTPServer server;
+ QVERIFY2(server.listen(), qPrintable(server.errorString()));
+ QVERIFY(server.wait(testFileUrl("text.expect"),
+ testFileUrl("overrideMimeType.reply"),
+ testFileUrl("text.xml")));
+
+ QQmlComponent component(engine.get(), testFileUrl("overrideMimeType.qml"));
+ QScopedPointer<QObject> object(component.beginCreate(engine.get()->rootContext()));
+ QVERIFY(!object.isNull());
+ object->setProperty("url", server.urlString("/text.xml"));
+ component.completeCreate();
+
+ QTRY_VERIFY(object->property("dataOK").toBool());
+}
+
QTEST_MAIN(tst_qqmlxmlhttprequest)
#include "tst_qqmlxmlhttprequest.moc"
diff --git a/tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt b/tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt
index d0a8270faa..96ae64cd8d 100644
--- a/tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt
+++ b/tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qqmlxmllistmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
data/*)
diff --git a/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp b/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp
index 0745853e02..bb6e59cb17 100644
--- a/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp
+++ b/tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtQmlXmlListModel/private/qqmlxmllistmodel_p.h>
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -321,14 +321,12 @@ void tst_QQmlXmlListModel::headers()
QTRY_COMPARE_WITH_TIMEOUT(qvariant_cast<QQmlXmlListModel::Status>(model->property("status")),
QQmlXmlListModel::Error, 10000);
- QVariantMap expectedHeaders;
- expectedHeaders["Accept"] = "application/xml,*/*";
+ QLatin1String expectedAcceptHeader = "application/xml,*/*"_L1;
- QCOMPARE(factory.lastSentHeaders.size(), expectedHeaders.size());
- for (auto it = expectedHeaders.cbegin(), end = expectedHeaders.cend(); it != end; ++it) {
- QVERIFY(factory.lastSentHeaders.contains(it.key()));
- QCOMPARE(factory.lastSentHeaders[it.key()].toString(), it.value().toString());
- }
+ QCOMPARE(factory.lastSentHeaders.size(), 1);
+ QVariant acceptHeader = factory.lastSentHeaders["accept"];
+ QVERIFY(acceptHeader.isValid());
+ QCOMPARE(acceptHeader.toString(), expectedAcceptHeader);
}
void tst_QQmlXmlListModel::source()
@@ -435,8 +433,8 @@ void tst_QQmlXmlListModel::reload()
QVERIFY(model != nullptr);
QTRY_COMPARE(model->rowCount(), 9);
- QSignalSpy spyInsert(model.get(), SIGNAL(rowsInserted(QModelIndex, int, int)));
- QSignalSpy spyRemove(model.get(), SIGNAL(rowsRemoved(QModelIndex, int, int)));
+ QSignalSpy spyInsert(model.get(), SIGNAL(rowsInserted(QModelIndex,int,int)));
+ QSignalSpy spyRemove(model.get(), SIGNAL(rowsRemoved(QModelIndex,int,int)));
QSignalSpy spyCount(model.get(), SIGNAL(countChanged()));
// reload multiple times to test the xml query aborting
QMetaObject::invokeMethod(model.get(), "reload");
diff --git a/tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt b/tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt
index 37bd47de3a..39abeacbdf 100644
--- a/tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt
+++ b/tests/auto/qml/qquickfolderlistmodel/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickfolderlistmodel Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickfolderlistmodel LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
index 6209e62a8f..f246e1af6d 100644
--- a/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
+++ b/tests/auto/qml/qquickfolderlistmodel/tst_qquickfolderlistmodel.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
diff --git a/tests/auto/qml/qquickworkerscript/CMakeLists.txt b/tests/auto/qml/qquickworkerscript/CMakeLists.txt
index 9ba3446659..e96fc74300 100644
--- a/tests/auto/qml/qquickworkerscript/CMakeLists.txt
+++ b/tests/auto/qml/qquickworkerscript/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickworkerscript Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickworkerscript LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
index 966aac6aaf..e209c3cdde 100644
--- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
+++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtCore/qdebug.h>
#include <QtCore/qtimer.h>
@@ -102,21 +102,20 @@ void tst_QQuickWorkerScript::messaging()
QFETCH(QVariant, value);
QQmlComponent component(&m_engine, testFileUrl("worker.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QVariant response = mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>();
+ QVariant response = mo->property(mo->indexOfProperty("response")).read(worker.get()).value<QVariant>();
if (response.userType() == qMetaTypeId<QJSValue>())
response = response.value<QJSValue>().toVariant();
QCOMPARE(response, value);
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::messaging_data()
@@ -142,29 +141,28 @@ void tst_QQuickWorkerScript::messaging_sendQObjectList()
// js values.
QQmlComponent component(&m_engine, testFileUrl("worker.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QVariantList objects;
for (int i=0; i<3; i++)
objects << QVariant::fromValue(new QObject(this));
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, QVariant::fromValue(objects))));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, QVariant::fromValue(objects))));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QVariantList result = mo->property(mo->indexOfProperty("response")).read(worker).value<QVariantList>();
+ QVariantList result = mo->property(mo->indexOfProperty("response")).read(worker.get()).value<QVariantList>();
QCOMPARE(result, (QVariantList() << QVariant() << QVariant() << QVariant()));
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::messaging_sendJsObject()
{
QQmlComponent component(&m_engine, testFileUrl("worker.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
// Properties are in alphabetical order to enable string-based comparison after
// QVariant roundtrip, since the properties will be stored in a QVariantMap.
@@ -175,26 +173,24 @@ void tst_QQuickWorkerScript::messaging_sendJsObject()
map.insert("name", "zyz");
map.insert("spell power", 3101);
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, QVariant::fromValue(map))));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, QVariant::fromValue(map))));
+ waitForEchoMessage(worker.get());
QVariant result = QVariant::fromValue(false);
- QVERIFY(QMetaObject::invokeMethod(worker, "compareLiteralResponse", Qt::DirectConnection,
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "compareLiteralResponse", Qt::DirectConnection,
Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, jsObject)));
QVERIFY(result.toBool());
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::messaging_sendExternalObject()
{
QQmlComponent component(&m_engine, testFileUrl("externalObjectWorker.qml"));
- QObject *obj = component.create();
- QVERIFY(obj);
- QMetaObject::invokeMethod(obj, "testExternalObject");
+ std::unique_ptr<QObject> obj { component.create() };
+ QVERIFY(obj.get());
+ QMetaObject::invokeMethod(obj.get(), "testExternalObject");
QTest::qWait(100); // shouldn't crash.
- delete obj;
}
void tst_QQuickWorkerScript::script_with_pragma()
@@ -202,35 +198,33 @@ void tst_QQuickWorkerScript::script_with_pragma()
QVariant value(100);
QQmlComponent component(&m_engine, testFileUrl("worker_pragma.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>(), value);
+ QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker.get()).value<QVariant>(), value);
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::script_included()
{
QQmlComponent component(&m_engine, testFileUrl("worker_include.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QString value("Hello");
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).toString(), value + " World");
+ QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker.get()).toString(), value + " World");
qApp->processEvents();
- delete worker;
}
static QString qquickworkerscript_lastWarning;
@@ -245,69 +239,65 @@ void tst_QQuickWorkerScript::scriptError_onLoad()
QQmlComponent component(&m_engine, testFileUrl("worker_error_onLoad.qml"));
QtMessageHandler previousMsgHandler = qInstallMessageHandler(qquickworkerscript_warningsHandler);
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QTRY_COMPARE(qquickworkerscript_lastWarning,
testFileUrl("script_error_onLoad.js").toString() + QLatin1String(":3:10: SyntaxError: Expected token `,'"));
qInstallMessageHandler(previousMsgHandler);
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::scriptError_onCall()
{
QQmlComponent component(&m_engine, testFileUrl("worker_error_onCall.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QtMessageHandler previousMsgHandler = qInstallMessageHandler(qquickworkerscript_warningsHandler);
QVariant value;
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
QTRY_COMPARE(qquickworkerscript_lastWarning,
testFileUrl("script_error_onCall.js").toString() + QLatin1String(":4: ReferenceError: getData is not defined"));
qInstallMessageHandler(previousMsgHandler);
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::script_function()
{
QQmlComponent component(&m_engine, testFileUrl("worker_function.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QString value("Hello");
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).toString(), value + " World");
+ QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker.get()).toString(), value + " World");
qApp->processEvents();
- delete worker;
}
void tst_QQuickWorkerScript::script_var()
{
QQmlComponent component(&m_engine, testFileUrl("worker_var.qml"));
- QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create());
- QVERIFY(worker != nullptr);
+ std::unique_ptr<QQuickWorkerScript> worker { qobject_cast<QQuickWorkerScript*>(component.create()) };
+ QVERIFY(worker);
QString value("Hello");
- QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
- waitForEchoMessage(worker);
+ QVERIFY(QMetaObject::invokeMethod(worker.get(), "testSend", Q_ARG(QVariant, value)));
+ waitForEchoMessage(worker.get());
const QMetaObject *mo = worker->metaObject();
- QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).toString(), value + " World");
+ QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker.get()).toString(), value + " World");
qApp->processEvents();
- delete worker;
}
// Rapidly create and destroy worker scripts to test resources are being disposed
@@ -317,9 +307,8 @@ void tst_QQuickWorkerScript::stressDispose()
for (int ii = 0; ii < 100; ++ii) {
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("stressDispose.qml"));
- QObject *o = component.create();
- QVERIFY(o);
- delete o;
+ std::unique_ptr<QObject> o { component.create() };
+ QVERIFY(o.get());
}
}
diff --git a/tests/auto/qml/qrcqml/CMakeLists.txt b/tests/auto/qml/qrcqml/CMakeLists.txt
index de081545cb..c793f1363c 100644
--- a/tests/auto/qml/qrcqml/CMakeLists.txt
+++ b/tests/auto/qml/qrcqml/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qrcqml Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qrcqml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qrcqml
SOURCES
tst_qrcqml.cpp
diff --git a/tests/auto/qml/qrcqml/tst_qrcqml.cpp b/tests/auto/qml/qrcqml/tst_qrcqml.cpp
index 5f77083c4e..a9be307c23 100644
--- a/tests/auto/qml/qrcqml/tst_qrcqml.cpp
+++ b/tests/auto/qml/qrcqml/tst_qrcqml.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QObject>
@@ -59,10 +59,9 @@ void tst_qrcqml::basicLoad()
QQmlEngine e;
QQmlComponent c(&e, QUrl(url));
QVERIFY(c.isReady());
- QObject* o = c.create();
- QVERIFY(o);
+ std::unique_ptr<QObject> o { c.create() };
+ QVERIFY(o.get());
QCOMPARE(o->property("tokenProperty").toString(), token);
- delete o;
}
void tst_qrcqml::qrcImport_data()
@@ -88,10 +87,9 @@ void tst_qrcqml::qrcImport()
e.addImportPath(importPath);
QQmlComponent c(&e, QUrl("qrc:///importtest.qml"));
QVERIFY(c.isReady());
- QObject *o = c.create();
- QVERIFY(o);
+ std::unique_ptr<QObject> o { c.create() };
+ QVERIFY(o.get());
QCOMPARE(o->property("tokenProperty").toString(), token);
- delete o;
}
QTEST_MAIN(tst_qrcqml)
diff --git a/tests/auto/qml/qtqmlmodules/CMakeLists.txt b/tests/auto/qml/qtqmlmodules/CMakeLists.txt
index 59033ae690..a6ae2ec9f7 100644
--- a/tests/auto/qml/qtqmlmodules/CMakeLists.txt
+++ b/tests/auto/qml/qtqmlmodules/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qtqmlmodules Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qtqmlmodules LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp b/tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp
index 88fd0e6bc0..62637c97ff 100644
--- a/tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp
+++ b/tests/auto/qml/qtqmlmodules/tst_qtqmlmodules.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Research in Motion.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QDebug>
@@ -23,33 +23,27 @@ void tst_qtqmlmodules::baseTypes()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("base.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
-
- delete object;
}
void tst_qtqmlmodules::modelsTypes()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("models.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
-
- delete object;
}
void tst_qtqmlmodules::unavailableTypes()
{
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("unavailable.qml"));
- QObject *object = component.create();
- QVERIFY(object != nullptr);
+ std::unique_ptr<QObject> object { component.create() };
+ QVERIFY(object);
QVERIFY(object->property("success").toBool());
-
- delete object;
}
QTEST_MAIN(tst_qtqmlmodules)
diff --git a/tests/auto/qml/qv4assembler/CMakeLists.txt b/tests/auto/qml/qv4assembler/CMakeLists.txt
index dfac16468a..8ae3c891d5 100644
--- a/tests/auto/qml/qv4assembler/CMakeLists.txt
+++ b/tests/auto/qml/qv4assembler/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4assembler Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4assembler LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qv4assembler/data/crash.qml b/tests/auto/qml/qv4assembler/data/crash.qml
index ffae69b321..b083497a70 100644
--- a/tests/auto/qml/qv4assembler/data/crash.qml
+++ b/tests/auto/qml/qv4assembler/data/crash.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
import Crash 1.0
diff --git a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
index 7e9e070fa6..4be0acd73e 100644
--- a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
+++ b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#if QT_CONFIG(process)
diff --git a/tests/auto/qml/qv4estable/CMakeLists.txt b/tests/auto/qml/qv4estable/CMakeLists.txt
new file mode 100644
index 0000000000..01d2663a04
--- /dev/null
+++ b/tests/auto/qml/qv4estable/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## tst_qv4estable Test:
+#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4estable LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qv4estable
+ SOURCES
+ tst_qv4estable.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::Qml
+ Qt::QmlPrivate
+)
+
+## Scopes:
+#####################################################################
diff --git a/tests/auto/qml/qv4estable/tst_qv4estable.cpp b/tests/auto/qml/qv4estable/tst_qv4estable.cpp
new file mode 100644
index 0000000000..7d137ae7d2
--- /dev/null
+++ b/tests/auto/qml/qv4estable/tst_qv4estable.cpp
@@ -0,0 +1,40 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <qtest.h>
+#include <private/qv4estable_p.h>
+
+class tst_qv4estable : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void checkRemoveAvoidsHeapBufferOverflow();
+};
+
+// QTBUG-123999
+void tst_qv4estable::checkRemoveAvoidsHeapBufferOverflow()
+{
+ QV4::ESTable estable;
+
+ // Fill the ESTable with values so it is at max capacity.
+ QCOMPARE_EQ(estable.m_capacity, 8U);
+ for (uint i = 0; i < estable.m_capacity; ++i) {
+ estable.set(QV4::Value::fromUInt32(i), QV4::Value::fromUInt32(i));
+ }
+ // Our |m_keys| array should now contain eight values.
+ // > [v0, v1, v2, v3, v4, v5, v6, v7]
+ for (uint i = 0; i < estable.m_capacity; ++i) {
+ QVERIFY(estable.m_keys[i].sameValueZero(QV4::Value::fromUInt32(i)));
+ }
+ QCOMPARE_EQ(estable.m_capacity, 8U);
+ QCOMPARE_EQ(estable.m_size, 8U);
+
+ // Remove the first item from the set to verify that asan does not trip.
+ // Relies on the CI platform propagating asan flag to all tests.
+ estable.remove(QV4::Value::fromUInt32(0));
+}
+
+QTEST_MAIN(tst_qv4estable)
+
+#include "tst_qv4estable.moc"
diff --git a/tests/auto/qml/qv4identifiertable/CMakeLists.txt b/tests/auto/qml/qv4identifiertable/CMakeLists.txt
index 5c785b0b74..c0350d6ef7 100644
--- a/tests/auto/qml/qv4identifiertable/CMakeLists.txt
+++ b/tests/auto/qml/qv4identifiertable/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4identifiertable Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4identifiertable LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qv4identifiertable
SOURCES
tst_qv4identifiertable.cpp
diff --git a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
index a3f5c4bb70..6222f20c10 100644
--- a/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
+++ b/tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp
@@ -1,6 +1,6 @@
// Copyright (C) 2019 The Qt Company Ltd.
// Copyright (C) 2016 basysKom GmbH.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
diff --git a/tests/auto/qml/qv4mm/CMakeLists.txt b/tests/auto/qml/qv4mm/CMakeLists.txt
index bfafd5819c..7c8a52038e 100644
--- a/tests/auto/qml/qv4mm/CMakeLists.txt
+++ b/tests/auto/qml/qv4mm/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4mm Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4mm LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/qml/qv4mm/data/createdestroy.qml b/tests/auto/qml/qv4mm/data/createdestroy.qml
index fd8a8cb2a2..5cc689b1ea 100644
--- a/tests/auto/qml/qv4mm/data/createdestroy.qml
+++ b/tests/auto/qml/qv4mm/data/createdestroy.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
diff --git a/tests/auto/qml/qv4mm/data/createobjects.qml b/tests/auto/qml/qv4mm/data/createobjects.qml
index 4163d34d34..bd1897e04e 100644
--- a/tests/auto/qml/qv4mm/data/createobjects.qml
+++ b/tests/auto/qml/qv4mm/data/createobjects.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2020 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQml 2.2
diff --git a/tests/auto/qml/qv4mm/data/simpleObject.qml b/tests/auto/qml/qv4mm/data/simpleObject.qml
new file mode 100644
index 0000000000..8fc36a40da
--- /dev/null
+++ b/tests/auto/qml/qv4mm/data/simpleObject.qml
@@ -0,0 +1,3 @@
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qv4mm/data/storeLocal.qml b/tests/auto/qml/qv4mm/data/storeLocal.qml
new file mode 100644
index 0000000000..8d48a8b23c
--- /dev/null
+++ b/tests/auto/qml/qv4mm/data/storeLocal.qml
@@ -0,0 +1,34 @@
+import QtQml
+
+QtObject {
+ id: root
+ property bool wasNotMarkedBefore: false
+ property bool wasMarkedAfter: false
+ property int result: -2
+ function f() {
+ let a = [1, 2, 3];
+ function inner() {
+ a = [4, 5, 6];
+ }
+ __forceJit(inner);
+ __setupGC();
+ root.wasNotMarkedBefore = !__isMarked(a);
+ inner();
+ root.wasMarkedAfter = __isMarked(a);
+ return a[0];
+ }
+ Component.onCompleted: {
+ if (!__forceJit(f)) {
+ root.result = -1;
+ return;
+ }
+ if (f() !== 4)
+ root.result = 1;
+ else if (!wasNotMarkedBefore)
+ root.result = 2;
+ else if (!wasMarkedAfter)
+ root.result = 3;
+ else
+ root.result = 0; // success
+ }
+}
diff --git a/tests/auto/qml/qv4mm/tst_qv4mm.cpp b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
index e5f8951825..7714beb3c7 100644
--- a/tests/auto/qml/qv4mm/tst_qv4mm.cpp
+++ b/tests/auto/qml/qv4mm/tst_qv4mm.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 basysKom GmbH.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QQmlEngine>
@@ -9,6 +9,15 @@
#include <private/qv4mm_p.h>
#include <private/qv4qobjectwrapper_p.h>
#include <private/qjsvalue_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qv4identifiertable_p.h>
+#include <private/qv4arraydata_p.h>
+#include <private/qqmlcomponentattached_p.h>
+#include <private/qv4mapobject_p.h>
+#include <private/qv4setobject_p.h>
+#if QT_CONFIG(qml_jit)
+#include <private/qv4baselinejit_p.h>
+#endif
#include <QtQuickTestUtils/private/qmlutils_p.h>
@@ -23,22 +32,153 @@ public:
private slots:
void gcStats();
+ void arrayDataWriteBarrierInteraction();
+ void persistentValueMarking_data();
+ void persistentValueMarking();
void multiWrappedQObjects();
void accessParentOnDestruction();
void cleanInternalClasses();
void createObjectsOnDestruction();
+ void sharedInternalClassDataMarking();
+ void gcTriggeredInOnDestroyed();
+ void weakValuesAssignedAfterThePhaseThatShouldHandleWeakValues();
+ void mapAndSetKeepValuesAlive();
+ void jittedStoreLocalMarksValue();
};
tst_qv4mm::tst_qv4mm()
: QQmlDataTest(QT_QMLTEST_DATADIR)
{
+ QV4::ExecutionEngine engine;
+ QV4::Scope scope(engine.rootContext());
}
void tst_qv4mm::gcStats()
{
QLoggingCategory::setFilterRules("qt.qml.gc.*=true");
QQmlEngine engine;
- engine.collectGarbage();
+ gc(engine);
+ QLoggingCategory::setFilterRules("qt.qml.gc.*=false");
+}
+
+void tst_qv4mm::arrayDataWriteBarrierInteraction()
+{
+ QV4::ExecutionEngine engine;
+ QCOMPARE(engine.memoryManager->gcBlocked, QV4::MemoryManager::Unblocked);
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::Object *unprotectedObject = engine.newObject();
+ QV4::Scope scope(&engine);
+ QV4::ScopedArrayObject array(scope, engine.newArrayObject());
+ constexpr int initialCapacity = 8; // compare qv4arraydata.cpp
+ for (int i = 0; i < initialCapacity; ++i) {
+ array->push_back(unprotectedObject->asReturnedValue());
+ }
+ QVERIFY(!unprotectedObject->isMarked());
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+
+ // initialize gc
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::MarkGlobalObject) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ array->push_back(QV4::Value::fromUInt32(42));
+ QVERIFY(!unprotectedObject->isMarked());
+ // we should have pushed the new arraydata on the mark stack
+ // so if we call drain...
+ engine.memoryManager->markStack()->drain();
+ // the unprotectedObject should have been marked
+ QVERIFY(unprotectedObject->isMarked());
+}
+
+enum PVSetOption {
+ CopyCtor,
+ ValueCtor,
+ ObjectCtor,
+ ReturnedValueCtor,
+ WeakValueAssign,
+ ObjectAssign,
+};
+
+void tst_qv4mm::persistentValueMarking_data()
+{
+ QTest::addColumn<PVSetOption>("setOption");
+
+ QTest::addRow("copy") << CopyCtor;
+ QTest::addRow("valueCtor") << ValueCtor;
+ QTest::addRow("ObjectCtor") << ObjectCtor;
+ QTest::addRow("ReturnedValueCtor") << ReturnedValueCtor;
+ QTest::addRow("WeakValueAssign") << WeakValueAssign;
+ QTest::addRow("ObjectAssign") << ObjectAssign;
+}
+
+void tst_qv4mm::persistentValueMarking()
+{
+ QFETCH(PVSetOption, setOption);
+ QV4::ExecutionEngine engine;
+ QV4::PersistentValue persistentOrigin; // used for copy ctor
+ QV4::Heap::Object *unprotectedObject = engine.newObject();
+ {
+ QV4::Scope scope(engine.rootContext());
+ QV4::ScopedObject object {scope, unprotectedObject};
+ persistentOrigin.set(&engine, object);
+ QVERIFY(!unprotectedObject->isMarked());
+ }
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::MarkGlobalObject) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QVERIFY(engine.isGCOngoing);
+ QVERIFY(!unprotectedObject->isMarked());
+ switch (setOption) {
+ case CopyCtor: {
+ QV4::PersistentValue persistentCopy(persistentOrigin);
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ case ValueCtor: {
+ QV4::Value val = QV4::Value::fromHeapObject(unprotectedObject);
+ QV4::PersistentValue persistent(&engine, val);
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ case ObjectCtor: {
+ QV4::Scope scope(&engine);
+ QV4::ScopedObject o(scope, unprotectedObject);
+ // scoped object without scan shouldn't result in marking
+ QVERIFY(!unprotectedObject->isMarked());
+ QV4::PersistentValue persistent(&engine, o.getPointer());
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ case ReturnedValueCtor: {
+ QV4::PersistentValue persistent(&engine, unprotectedObject->asReturnedValue());
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ case WeakValueAssign: {
+ QV4::WeakValue wv;
+ wv.set(&engine, unprotectedObject);
+ QVERIFY(!unprotectedObject->isMarked());
+ QV4::PersistentValue persistent;
+ persistent = wv;
+ break;
+ }
+ case ObjectAssign: {
+ QV4::Scope scope(&engine);
+ QV4::ScopedObject o(scope, unprotectedObject);
+ // scoped object without scan shouldn't result in marking
+ QVERIFY(!unprotectedObject->isMarked());
+ QV4::PersistentValue persistent;
+ persistent = o;
+ QVERIFY(unprotectedObject->isMarked());
+ break;
+ }
+ }
}
void tst_qv4mm::multiWrappedQObjects()
@@ -48,7 +188,7 @@ void tst_qv4mm::multiWrappedQObjects()
{
QObject object;
for (int i = 0; i < 10; ++i)
- QV4::QObjectWrapper::wrap(i % 2 ? &engine1 : &engine2, &object);
+ QV4::QObjectWrapper::ensureWrapper(i % 2 ? &engine1 : &engine2, &object);
QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
@@ -62,27 +202,27 @@ void tst_qv4mm::multiWrappedQObjects()
// The additional WeakValue from m_multiplyWrappedQObjects hasn't been moved
// to m_pendingFreedObjectWrapperValue yet. It's still alive after all.
- engine1.memoryManager->runGC();
+ gc(engine1);
QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 1);
// engine2 doesn't own the object as engine1 was the first to wrap it above.
// Therefore, no effect here.
- engine2.memoryManager->runGC();
+ gc(engine2);
QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
}
// Clears m_pendingFreedObjectWrapperValue. Now it's really dead.
- engine1.memoryManager->runGC();
+ gc(engine1);
QCOMPARE(engine1.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
- engine2.memoryManager->runGC();
+ gc(engine2);
QCOMPARE(engine2.memoryManager->m_pendingFreedObjectWrapperValue.size(), 0);
}
void tst_qv4mm::accessParentOnDestruction()
{
- QLoggingCategory::setFilterRules("qt.qml.gc.*=false");
QQmlEngine engine;
+
QQmlComponent component(&engine, testFileUrl("createdestroy.qml"));
std::unique_ptr<QObject> obj(component.create());
QVERIFY(obj);
@@ -91,6 +231,9 @@ void tst_qv4mm::accessParentOnDestruction()
QTRY_VERIFY(!timer->property("running").toBool());
QCOMPARE(obj->property("iterations").toInt(), 100);
QCOMPARE(obj->property("creations").toInt(), 100);
+ gc(engine); // ensure incremental gc has finished, and collected all objects
+ // TODO: investigaet whether we really need two gc rounds for incremental gc
+ gc(engine); // ensure incremental gc has finished, and collected all objects
QCOMPARE(obj->property("destructions").toInt(), 100);
}
@@ -181,7 +324,11 @@ void tst_qv4mm::cleanInternalClasses()
}
// Make sure that all dangling ICs are actually gone.
- scope.engine->memoryManager->runGC();
+ gc(engine);
+ // NOTE: If we allocate new ICs during gc (potentially triggered on alloc),
+ // then they will survive the previous gc call
+ // run gc again to ensure that a full gc cycle happens
+ gc(engine);
// Now the GC has removed the ICs we originally added by adding properties.
QVERIFY(prevIC->d()->transitions.empty() || prevIC->d()->transitions.front().lookup == nullptr);
@@ -197,8 +344,8 @@ void tst_qv4mm::cleanInternalClasses()
void tst_qv4mm::createObjectsOnDestruction()
{
- QLoggingCategory::setFilterRules("qt.qml.gc.*=false");
QQmlEngine engine;
+
QQmlComponent component(&engine, testFileUrl("createobjects.qml"));
std::unique_ptr<QObject> obj(component.create());
QVERIFY(obj);
@@ -206,6 +353,383 @@ void tst_qv4mm::createObjectsOnDestruction()
QCOMPARE(obj->property("ok").toBool(), true);
}
+void tst_qv4mm::sharedInternalClassDataMarking()
+{
+ QV4::ExecutionEngine engine;
+ QV4::Scope scope(engine.rootContext());
+ QV4::ScopedObject object(scope, engine.newObject());
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::String *s = engine.newString(QString::fromLatin1("test"));
+ QV4::PropertyKey id = engine.identifierTable->asPropertyKeyImpl(s);
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!id.asStringOrSymbol()->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::MarkGlobalObject) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ // simulate partial marking caused by drain due mark stack running out of space
+ // and running out of time during drain phase for complete marking
+ // the last part is necessary for us to find not-already marked name/value pair to put into
+ // the object
+
+ QVERIFY(engine.memoryManager->markStack()->isEmpty());
+ QVERIFY(!id.asStringOrSymbol()->isMarked());
+ {
+
+ // for simplcity's sake we create a new PropertyKey - if gc were actually ongoing that would
+ // already mark it. In practice we would need to retrieve an existing one from an unmarked
+ // object, and then make that object unreachable afterwards.
+ object->put(id, QV4::Value::fromUInt32(42));
+ engine.memoryManager->markStack()->drain();
+ QVERIFY(id.asStringOrSymbol()->isMarked());
+ }
+ gc(engine);
+ // sanity check that we still can lookup the value
+ QV4::ScopedString s2(scope, engine.newString(QString::fromLatin1("test")));
+ auto val = QV4::Value::fromReturnedValue(object->get(s2->toPropertyKey()));
+ QCOMPARE(val.toUInt32(), 42u);
+}
+
+void tst_qv4mm::gcTriggeredInOnDestroyed()
+{
+ QQmlEngine engine;
+ QV4::ExecutionEngine &v4 = *engine.handle();
+
+ QPointer<QObject> testObject = new QObject; // unparented, will be deleted
+ auto cleanup = qScopeGuard([&]() {
+ if (testObject)
+ testObject->deleteLater();
+ });
+
+ QQmlComponent component(&engine, testFileUrl("simpleObject.qml"));
+ auto toBeCollected = component.create();
+ QVERIFY(toBeCollected);
+ QJSEngine::setObjectOwnership(toBeCollected, QJSEngine::JavaScriptOwnership);
+ QV4::QObjectWrapper::ensureWrapper(&v4, toBeCollected);
+ QVERIFY(qmlEngine(toBeCollected));
+ QQmlComponentAttached *attached = QQmlComponent::qmlAttachedProperties(toBeCollected);
+ QVERIFY(attached);
+
+
+ QV4::Scope scope(v4.rootContext());
+ QCOMPARE(v4.memoryManager->gcBlocked, QV4::MemoryManager::Unblocked);
+
+
+
+ // let the gc run up to CallDestroyObjects
+ auto sm = v4.memoryManager->gcStateMachine.get();
+ sm->reset();
+ v4.memoryManager->gcBlocked = QV4::MemoryManager::NormalBlocked;
+ while (sm->state != QV4::GCState::CallDestroyObjects && sm->state != QV4::GCState::Invalid) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QCOMPARE(sm->state, QV4::GCState::CallDestroyObjects);
+
+ QV4::ScopedValue val(scope);
+ bool calledOnDestroyed = false;
+ auto con = connect(attached, &QQmlComponentAttached::destruction, this, [&]() {
+ calledOnDestroyed = true;
+ // we trigger uncommon code paths:
+ // create ObjectWrapper in destroyed hadnler
+ auto ddata = QQmlData::get(testObject.get(), false);
+ QVERIFY(!ddata); // we don't have ddata yet (otherwise we'd already have an object wrapper)
+ val = QV4::QObjectWrapper::wrap(&v4, testObject.get());
+ QJSEngine::setObjectOwnership(testObject, QJSEngine::JavaScriptOwnership);
+
+ // and also try to trigger a force gc completion
+ bool gcComplete = v4.memoryManager->tryForceGCCompletion();
+ QVERIFY(!gcComplete);
+ });
+ while (!calledOnDestroyed && sm->state != QV4::GCState::Invalid) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QVERIFY(!QTest::currentTestFailed());
+ QObject::disconnect(con);
+ QVERIFY(calledOnDestroyed);
+
+ bool gcComplete = v4.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ val = QV4::Value::undefinedValue(); // no longer keep a reference on the stack
+ QCOMPARE(sm->state, QV4::GCState::Invalid);
+ QVERIFY(testObject); // must not have be deleted, referenced by val
+
+ gc(v4); // run another gc cycle
+ QVERIFY(!testObject); // now collcted by gc
+}
+void tst_qv4mm::weakValuesAssignedAfterThePhaseThatShouldHandleWeakValues()
+{
+ QObject testObject;
+ QV4::ExecutionEngine v4;
+
+ QCOMPARE(v4.memoryManager->gcBlocked, QV4::MemoryManager::Unblocked);
+
+
+
+ // let the gc run up to CallDestroyObjects
+ auto sm = v4.memoryManager->gcStateMachine.get();
+ sm->reset();
+ v4.memoryManager->gcBlocked = QV4::MemoryManager::NormalBlocked;
+
+
+ // run just before the sweeping face
+ while (sm->state != QV4::GCState::DoSweep && sm->state != QV4::GCState::Invalid) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QCOMPARE(sm->state, QV4::GCState::DoSweep);
+
+ {
+ // simulate code accessing the object wrapper for an object
+ QV4::Scope scope(v4.rootContext());
+ QV4::ScopedValue value(scope);
+ value = QV4::QObjectWrapper::wrap(&v4, &testObject);
+ // let it go out of scope before any stack re-scanning could happen
+ }
+
+ bool gcComplete = v4.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+
+ auto ddata = QQmlData::get(&testObject);
+ QVERIFY(ddata);
+ if (ddata->jsWrapper.isUndefined()) {
+ // it's in principle valid for the wrapper to be reset, though the current
+ // implementation doesn't do it, and it requires some care
+ qWarning("Double-check the handling of weak values and object wrappers in the gc");
+ return;
+ }
+ QVERIFY(ddata->jsWrapper.valueRef()->heapObject()->inUse());
+}
+
+void tst_qv4mm::mapAndSetKeepValuesAlive()
+{
+ {
+ QJSEngine jsEngine;
+ QV4::ExecutionEngine &engine = *jsEngine.handle();
+
+ QV4::Scope scope(&engine);
+ auto map = jsEngine.evaluate("new Map()");
+ QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object
+ QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map);
+
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::String *key = engine.newString(QString::fromLatin1("key"));
+ QV4::Heap::String *value = engine.newString(QString::fromLatin1("value"));
+ QV4::Value values[2] = { QV4::Value::fromHeapObject(key), QV4::Value::fromHeapObject(value) };
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!key->isMarked());
+ QVERIFY(!value->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::HandleQObjectWrappers) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QV4::MapPrototype::method_set(afunction.getPointer(), &thisObject, values, 2);
+
+ // check that we can still insert primitve values - they don't get marked
+ // but they also should not casue any corrpution - note that a weak map
+ // only accepts object keys
+ values[0] = QV4::Value::fromInt32(12);
+ values[1] = QV4::Value::fromInt32(13);
+ QV4::MapPrototype::method_set(afunction.getPointer(), &thisObject, values, 2);
+
+ QVERIFY(key->isMarked());
+ QVERIFY(value->isMarked());
+ bool gcComplete = engine.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ QVERIFY(key->inUse());
+ QVERIFY(value->inUse());
+ gc(engine);
+ QCOMPARE(map.property("size").toInt(), 2);
+ }
+ {
+ QJSEngine jsEngine;
+ QV4::ExecutionEngine &engine = *jsEngine.handle();
+
+ QV4::Scope scope(&engine);
+ auto map = jsEngine.evaluate("new WeakMap()");
+ QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object
+ QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map);
+
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::Object *key = engine.newObject();
+ QV4::Heap::String *value = engine.newString(QString::fromLatin1("value"));
+ QV4::Value values[2] = { QV4::Value::fromHeapObject(key), QV4::Value::fromHeapObject(value) };
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!key->isMarked());
+ QVERIFY(!value->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::HandleQObjectWrappers) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QV4::WeakMapPrototype::method_set(afunction.getPointer(), &thisObject, values, 2);
+ QVERIFY(!engine.hasException);
+ QVERIFY(key->isMarked());
+ QVERIFY(value->isMarked());
+ bool gcComplete = engine.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ QVERIFY(key->inUse());
+ QVERIFY(value->inUse());
+ gc(engine);
+ QCOMPARE(map.property("size").toInt(), 0);
+ }
+ {
+ QJSEngine jsEngine;
+ QV4::ExecutionEngine &engine = *jsEngine.handle();
+
+ QV4::Scope scope(&engine);
+ auto map = jsEngine.evaluate("new Set()");
+ QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object
+ QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map);
+
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::Object *key = engine.newObject();
+ QV4::Value values[1] = { QV4::Value::fromHeapObject(key) };
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!key->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::HandleQObjectWrappers) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QV4::SetPrototype::method_add(afunction.getPointer(), &thisObject, values, 1);
+ values[0] = QV4::Value::fromInt32(13);
+ QV4::SetPrototype::method_add(afunction.getPointer(), &thisObject, values, 1);
+ QVERIFY(!engine.hasException);
+ QVERIFY(key->isMarked());
+ bool gcComplete = engine.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ QVERIFY(key->inUse());
+ gc(engine);
+ QCOMPARE(map.property("size").toInt(), 2);
+ }
+ {
+ QJSEngine jsEngine;
+ QV4::ExecutionEngine &engine = *jsEngine.handle();
+
+ QV4::Scope scope(&engine);
+ auto map = jsEngine.evaluate("new WeakSet()");
+ QV4::ScopedFunctionObject afunction(scope, engine.memoryManager->alloc<QV4::FunctionObject>()); // hack, we just need about any function object
+ QV4::Value thisObject = QJSValuePrivate::asReturnedValue(&map);
+
+ QVERIFY(!engine.memoryManager->gcBlocked);
+ // no scoped classes, as that would defeat the point of the test
+ // we block the gc instead so that the allocation can't trigger the gc
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::InCriticalSection;
+ QV4::Heap::Object *key = engine.newObject();
+ QV4::Value values[1] = { QV4::Value::fromHeapObject(key) };
+ engine.memoryManager->gcBlocked = QV4::MemoryManager::Unblocked;
+ QVERIFY(!key->isMarked());
+
+ auto sm = engine.memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::HandleQObjectWrappers) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+ QV4::WeakSetPrototype::method_add(afunction.getPointer(), &thisObject, values, 1);
+ QVERIFY(!engine.hasException);
+ QVERIFY(key->isMarked());
+ bool gcComplete = engine.memoryManager->tryForceGCCompletion();
+ QVERIFY(gcComplete);
+ QVERIFY(key->inUse());
+ gc(engine);
+ QCOMPARE(map.property("size").toInt(), 0);
+ }
+}
+
+QV4::ReturnedValue method_force_jit(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
+{
+#if QT_CONFIG(qml_jit)
+ auto *v4 =b->engine();
+
+ Q_ASSERT(argc == 1);
+ QV4::Scope scope(v4);
+ QV4::Scoped<QV4::JavaScriptFunctionObject> functionObject(scope, argv[0]);
+ auto *func = static_cast<QV4::Heap::JavaScriptFunctionObject *>(functionObject->heapObject())->function;
+ Q_ASSERT(func);
+ func->interpreterCallCount = std::numeric_limits<int>::max();
+ if (!v4->canJIT(func))
+ return QV4::StaticValue::fromBoolean(false).asReturnedValue();
+ QV4::JIT::BaselineJIT(func).generate();
+ return QV4::StaticValue::fromBoolean(true).asReturnedValue();
+#else
+ return QV4::StaticValue::fromBoolean(false).asReturnedValue();
+#endif
+}
+
+QV4::ReturnedValue method_setup_gc_for_test(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *, int)
+{
+ auto *v4 =b->engine();
+ auto *mm = v4->memoryManager;
+ mm->runFullGC();
+
+ auto sm = v4->memoryManager->gcStateMachine.get();
+ sm->reset();
+ while (sm->state != QV4::GCState::MarkGlobalObject) {
+ QV4::GCStateInfo& stateInfo = sm->stateInfoMap[int(sm->state)];
+ sm->state = stateInfo.execute(sm, sm->stateData);
+ }
+
+ return QV4::Encode::undefined();
+}
+
+QV4::ReturnedValue method_is_marked(const QV4::FunctionObject *, const QV4::Value *, const QV4::Value *argv, int argc)
+{
+ Q_ASSERT(argc == 1);
+
+ auto h = argv[0].heapObject();
+ Q_ASSERT(h);
+ return QV4::Encode(h->isMarked());
+}
+
+void tst_qv4mm::jittedStoreLocalMarksValue()
+{
+ QQmlEngine engine;
+
+ auto *v4 = engine.handle();
+ auto globalObject = v4->globalObject;
+ globalObject->defineDefaultProperty(QStringLiteral("__setupGC"), method_setup_gc_for_test);
+ globalObject->defineDefaultProperty(QStringLiteral("__forceJit"), method_force_jit);
+ globalObject->defineDefaultProperty(QStringLiteral("__isMarked"), method_is_marked);
+
+ QQmlComponent comp(&engine, testFileUrl("storeLocal.qml"));
+ QVERIFY(comp.isReady());
+ std::unique_ptr<QObject> root {comp.create()};
+
+ QVERIFY(root);
+ bool ok = false;
+ int result = root->property("result").toInt(&ok);
+ QVERIFY(ok);
+ if (result == -1)
+ QSKIP("Could not run JIT");
+ QCOMPARE(result, 0);
+}
+
QTEST_MAIN(tst_qv4mm)
#include "tst_qv4mm.moc"
diff --git a/tests/auto/qml/qv4regexp/CMakeLists.txt b/tests/auto/qml/qv4regexp/CMakeLists.txt
index bdaf5e52e4..6f2c47c4b2 100644
--- a/tests/auto/qml/qv4regexp/CMakeLists.txt
+++ b/tests/auto/qml/qv4regexp/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qv4regexp Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4regexp LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qv4regexp
SOURCES
tst_qv4regexp.cpp
diff --git a/tests/auto/qml/qv4regexp/tst_qv4regexp.cpp b/tests/auto/qml/qv4regexp/tst_qv4regexp.cpp
index 534fa53956..99a91a9b0f 100644
--- a/tests/auto/qml/qv4regexp/tst_qv4regexp.cpp
+++ b/tests/auto/qml/qv4regexp/tst_qv4regexp.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2019 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QtQml/qjsengine.h>
diff --git a/tests/auto/qml/qv4urlobject/CMakeLists.txt b/tests/auto/qml/qv4urlobject/CMakeLists.txt
new file mode 100644
index 0000000000..f255413d84
--- /dev/null
+++ b/tests/auto/qml/qv4urlobject/CMakeLists.txt
@@ -0,0 +1,26 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Generated from qv4urlobject.pro.
+
+#####################################################################
+## tst_qv4urlobject Test:
+#####################################################################
+
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qv4urlobject LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_test(tst_qv4urlobject
+ SOURCES
+ tst_qv4urlobject.cpp
+ LIBRARIES
+ Qt::Gui
+ Qt::Qml
+ Qt::QmlPrivate
+)
+
+## Scopes:
+#####################################################################
diff --git a/tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp b/tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp
new file mode 100644
index 0000000000..992d1ef808
--- /dev/null
+++ b/tests/auto/qml/qv4urlobject/tst_qv4urlobject.cpp
@@ -0,0 +1,153 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <qtest.h>
+#include <QtQml/qjsengine.h>
+
+class tst_urlobject : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void searchParams_set();
+ void searchParams_nullUrlPointer();
+ void urlObject_search();
+ void urlObject_search_data();
+ void urlObject_href();
+ void urlObject_href_data();
+};
+
+void tst_urlobject::searchParams_set()
+{
+ QJSEngine engine;
+ QJSValue result =
+ engine.evaluate(QLatin1String("var url = new URL(\"http://www.google.com/search\");"
+ "url.href"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search");
+
+ result = engine.evaluate(QLatin1String("url.toString()"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search");
+
+ result = engine.evaluate(QLatin1String("url.searchParams.set(\"q\", \"value\");"
+ "url.href;"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search?q=value");
+
+ result = engine.evaluate(QLatin1String("url.toString()"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search?q=value");
+
+ result = engine.evaluate(QLatin1String("url.searchParams.set(\"t\", \"otherValue\");"
+ "url.href;"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search?q=value&t=otherValue");
+
+ result = engine.evaluate(QLatin1String("url.toString()"));
+ QVERIFY(!result.isError());
+ QCOMPARE(result.toString(), "http://www.google.com/search?q=value&t=otherValue");
+}
+
+void tst_urlobject::searchParams_nullUrlPointer()
+{
+ QJSEngine engine;
+ QJSValue result = engine.evaluate(QLatin1String("let params = new URLSearchParams();"
+ "params.set(\"foo\", \"bar\");"));
+ QVERIFY(!result.isError());
+}
+
+void tst_urlobject::urlObject_search()
+{
+ QFETCH(QString, test);
+ QFETCH(QString, expected);
+
+ QJSEngine engine;
+
+ QCOMPARE(engine.evaluate(test).toString(), expected);
+}
+
+void tst_urlobject::urlObject_search_data()
+{
+ QTest::addColumn<QString>("test");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("base case")
+ << "var url = new URL(\"http://www.google.com/search?q=123\");"
+ "url.search"
+ << "?q=123";
+ QTest::newRow("space")
+ << "var url = new URL(\"http://www.google.com/search?a=b ~\");"
+ "url.search"
+ << "?a=b%20~";
+ QTest::newRow("empty search")
+ << "var url = new URL(\"http://www.google.com/search?\");"
+ "url.search"
+ << "";
+ QTest::newRow("no search")
+ << "var url = new URL(\"http://www.google.com/search\");"
+ "url.search"
+ << "";
+ QTest::newRow("Question mark")
+ // the embedded ""'s break trigraph sequences:
+ << "var url = new URL(\"http://www.google.com/search?""?=?\");"
+ "url.search"
+ << "?""?=?";
+ QTest::newRow("equal sign")
+ << "var url = new URL(\"http://www.google.com/search?a==&b=!\");"
+ "url.search"
+ << "?a==&b=!";
+ QTest::newRow("percent sign")
+ << "var url = new URL(\"http://www.google.com/search?a=%20\");"
+ "url.search"
+ << "?a=%20";
+ QTest::newRow("multiple key-value pairs")
+ << "var url = new URL(\"http://www.google.com/search?a=b&c=d\");"
+ "url.search"
+ << "?a=b&c=d";
+ QTest::newRow("unreserved")
+ << "var url = new URL(\"http://www.google.com/search?a=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~\");"
+ "url.search"
+ << "?a=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~";
+ QTest::newRow("reserved + illegal")
+ << "var url = new URL(\"http://google.com/search/?a=!*();:@&=+$,/?#[]\");"
+ "url.search"
+ << "?a=!*();:@&=+$,/?";
+ QTest::newRow("unicode (U+327D)")
+ << "var url = new URL(\"http://google.com/search/?a=㉽\");"
+ "url.search"
+ << "?a=%E3%89%BD";
+ QTest::newRow("backslash")
+ // The JS string in the C++ source ends in 4 backslashes.
+ // The C++ compiler turns that into 2 backslashes.
+ // QV4 receives source code containing a string literal ending in two backslashes.
+ // The resulting JS string ends in a single backslash.
+ << "var url = new URL('http://google.com/search/?q=\\\\');"
+ "url.search"
+ << "?q=\\";
+}
+
+void tst_urlobject::urlObject_href()
+{
+ QFETCH(QString, test);
+ QFETCH(QString, expected);
+
+ QJSEngine engine;
+
+ QCOMPARE(engine.evaluate(test).toString(), expected);
+}
+
+void tst_urlobject::urlObject_href_data()
+{
+ QTest::addColumn<QString>("test");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("QTBUG-110454")
+ << "var url = new URL(\"https://example.com/?a=b ~\");"
+ "url.href"
+ << "https://example.com/?a=b%20~";
+}
+
+QTEST_MAIN(tst_urlobject)
+
+#include "tst_qv4urlobject.moc"
diff --git a/tests/auto/qml/qwidgetsinqml/CMakeLists.txt b/tests/auto/qml/qwidgetsinqml/CMakeLists.txt
index 4daa98889a..d2374997f2 100644
--- a/tests/auto/qml/qwidgetsinqml/CMakeLists.txt
+++ b/tests/auto/qml/qwidgetsinqml/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qwidgetsinqml Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qwidgetsinqml LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qwidgetsinqml
SOURCES
tst_qwidgetsinqml.cpp
@@ -15,6 +21,8 @@ qt_internal_add_test(tst_qwidgetsinqml
Qt::GuiPrivate
Qt::Qml
Qt::Widgets
+ Qt::QuickTestUtilsPrivate
+ TESTDATA "dummy_imports.qml"
)
## Scopes:
diff --git a/tests/auto/qml/qwidgetsinqml/dummy_imports.qml b/tests/auto/qml/qwidgetsinqml/dummy_imports.qml
new file mode 100644
index 0000000000..afe2b33adf
--- /dev/null
+++ b/tests/auto/qml/qwidgetsinqml/dummy_imports.qml
@@ -0,0 +1,7 @@
+// This file exists for the sole purpose for qmlimportscanner to find
+// which modules it needs to extract for deployment.
+// Otherwise, it fails to find the imports that are expressed in C++.
+
+import QtQml
+
+QtObject { }
diff --git a/tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp b/tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp
index 15236c20d8..12058fbba2 100644
--- a/tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp
+++ b/tests/auto/qml/qwidgetsinqml/tst_qwidgetsinqml.cpp
@@ -1,10 +1,11 @@
// Copyright (C) 2018 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QQmlEngine>
#include <QtQml>
#include <QWidget>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
class tst_QWidgetsInQml : public QObject
{
@@ -20,13 +21,6 @@ private slots:
void widgetAsDefaultPropertyKeptDuringCreation();
};
-static void gc(QQmlEngine &engine)
-{
- engine.collectGarbage();
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
- QCoreApplication::processEvents();
-}
-
// Like QtObject, but with default property
class QObjectContainer : public QObject
{
@@ -40,7 +34,8 @@ public:
{}
QQmlListProperty<QObject> data() {
- return QQmlListProperty<QObject>(this, 0, children_append, children_count, children_at, children_clear);
+ return QQmlListProperty<QObject>(
+ this, nullptr, children_append, children_count, children_at, children_clear);
}
static void children_append(QQmlListProperty<QObject> *prop, QObject *o)
@@ -58,12 +53,12 @@ public:
}
}
- static int children_count(QQmlListProperty<QObject> *prop)
+ static qsizetype children_count(QQmlListProperty<QObject> *prop)
{
return static_cast<QObjectContainer*>(prop->object)->dataChildren.count();
}
- static QObject *children_at(QQmlListProperty<QObject> *prop, int index)
+ static QObject *children_at(QQmlListProperty<QObject> *prop, qsizetype index)
{
return static_cast<QObjectContainer*>(prop->object)->dataChildren.at(index);
}
@@ -71,7 +66,7 @@ public:
static void children_clear(QQmlListProperty<QObject> *prop)
{
QObjectContainer *that = static_cast<QObjectContainer*>(prop->object);
- foreach (QObject *c, that->dataChildren)
+ for (QObject *c : std::as_const(that->dataChildren))
QObject::disconnect(c, SIGNAL(destroyed(QObject*)), that, SLOT(childDestroyed(QObject*)));
that->dataChildren.clear();
}
diff --git a/tests/auto/qml/registrationmacros/CMakeLists.txt b/tests/auto/qml/registrationmacros/CMakeLists.txt
index 3f2b7411ac..4cae044adf 100644
--- a/tests/auto/qml/registrationmacros/CMakeLists.txt
+++ b/tests/auto/qml/registrationmacros/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_registrationmacros LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_registrationmacros
SOURCES
tst_registrationmacros.cpp
diff --git a/tests/auto/qml/registrationmacros/tst_registrationmacros.cpp b/tests/auto/qml/registrationmacros/tst_registrationmacros.cpp
index 77798af24f..a94e045277 100644
--- a/tests/auto/qml/registrationmacros/tst_registrationmacros.cpp
+++ b/tests/auto/qml/registrationmacros/tst_registrationmacros.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <QObject>
diff --git a/tests/auto/qml/registrationmacros/types.cpp b/tests/auto/qml/registrationmacros/types.cpp
index 4ca801e7f7..57d565c525 100644
--- a/tests/auto/qml/registrationmacros/types.cpp
+++ b/tests/auto/qml/registrationmacros/types.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "types.h"
bool Test::check() const
diff --git a/tests/auto/qml/registrationmacros/types.h b/tests/auto/qml/registrationmacros/types.h
index 3c365cc2fd..5579edd2d3 100644
--- a/tests/auto/qml/registrationmacros/types.h
+++ b/tests/auto/qml/registrationmacros/types.h
@@ -1,5 +1,5 @@
// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef TYPES_H
#define TYPES_H
diff --git a/tests/auto/qml/v4misc/CMakeLists.txt b/tests/auto/qml/v4misc/CMakeLists.txt
index 81ae948cf1..1390fe9e0f 100644
--- a/tests/auto/qml/v4misc/CMakeLists.txt
+++ b/tests/auto/qml/v4misc/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_v4misc Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_v4misc LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_v4misc
SOURCES
tst_v4misc.cpp
diff --git a/tests/auto/qml/v4misc/tst_v4misc.cpp b/tests/auto/qml/v4misc/tst_v4misc.cpp
index 201bdb2f95..956b87d5f2 100644
--- a/tests/auto/qml/v4misc/tst_v4misc.cpp
+++ b/tests/auto/qml/v4misc/tst_v4misc.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <qtest.h>
#include <private/qv4instr_moth_p.h>