aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml')
-rw-r--r--src/qml/.prev_CMakeLists.txt622
-rw-r--r--src/qml/CMakeLists.txt633
-rw-r--r--src/qml/Qt6QmlBuildInternals.cmake174
-rw-r--r--src/qml/Qt6QmlMacros.cmake610
-rw-r--r--src/qml/common/qv4compileddata_p.h100
-rw-r--r--src/qml/common/qv4stringtoarrayindex_p.h2
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp39
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h2
-rw-r--r--src/qml/compiler/qv4compiler.cpp14
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/configure.cmake189
-rw-r--r--src/qml/debugger/qqmldebugserviceinterfaces_p.h6
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc2
-rw-r--r--src/qml/inlinecomponentutils_p.h10
-rw-r--r--src/qml/jsapi/qjsengine.cpp143
-rw-r--r--src/qml/jsapi/qjsengine.h10
-rw-r--r--src/qml/jsapi/qjsengine_p.h15
-rw-r--r--src/qml/jsapi/qjsvalue.cpp464
-rw-r--r--src/qml/jsapi/qjsvalue.h9
-rw-r--r--src/qml/jsapi/qjsvalue_p.h223
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp6
-rw-r--r--src/qml/jsruntime/jsruntime.pri8
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp53
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h27
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp30
-rw-r--r--src/qml/jsruntime/qv4engine.cpp199
-rw-r--r--src/qml/jsruntime/qv4engine_p.h14
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp115
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h85
-rw-r--r--src/qml/jsruntime/qv4global_p.h1
-rw-r--r--src/qml/jsruntime/qv4include.cpp8
-rw-r--r--src/qml/jsruntime/qv4include_p.h4
-rw-r--r--src/qml/jsruntime/qv4managed.cpp3
-rw-r--r--src/qml/jsruntime/qv4managed_p.h1
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp4
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h2
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp116
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h18
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp90
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h26
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp118
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference.cpp115
-rw-r--r--src/qml/jsruntime/qv4resolvedtypereference_p.h145
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp38
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp2
-rw-r--r--src/qml/jsruntime/qv4sparsearray_p.h2
-rw-r--r--src/qml/jsruntime/qv4string.cpp46
-rw-r--r--src/qml/jsruntime/qv4string_p.h32
-rw-r--r--src/qml/jsruntime/qv4symbol.cpp5
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp24
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h4
-rw-r--r--src/qml/jsruntime/qv4urlobject.cpp689
-rw-r--r--src/qml/jsruntime/qv4urlobject_p.h214
-rw-r--r--src/qml/memory/qv4mm_p.h20
-rw-r--r--src/qml/parser/qqmljs.g19
-rw-r--r--src/qml/parser/qqmljsast_p.h14
-rw-r--r--src/qml/parser/qqmljsglobal_p.h28
-rw-r--r--src/qml/parser/qqmljslexer.cpp37
-rw-r--r--src/qml/qml.pro2
-rw-r--r--src/qml/qml/ftw/qfieldlist_p.h118
-rw-r--r--src/qml/qml/ftw/qflagpointer_p.h152
-rw-r--r--src/qml/qml/ftw/qhashedstring.cpp2
-rw-r--r--src/qml/qml/ftw/qlazilyallocated_p.h67
-rw-r--r--src/qml/qml/ftw/qlinkedstringhash_p.h2
-rw-r--r--src/qml/qml/ftw/qqmlthread.cpp22
-rw-r--r--src/qml/qml/ftw/qstringhash_p.h74
-rw-r--r--src/qml/qml/qml.pri5
-rw-r--r--src/qml/qml/qqml.cpp161
-rw-r--r--src/qml/qml/qqml.h273
-rw-r--r--src/qml/qml/qqmlabstractbinding_p.h31
-rw-r--r--src/qml/qml/qqmlapplicationengine.cpp32
-rw-r--r--src/qml/qml/qqmlapplicationengine.h1
-rw-r--r--src/qml/qml/qqmlapplicationengine_p.h2
-rw-r--r--src/qml/qml/qqmlbinding.cpp91
-rw-r--r--src/qml/qml/qqmlbinding_p.h32
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp36
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h28
-rw-r--r--src/qml/qml/qqmlcomponent.cpp52
-rw-r--r--src/qml/qml/qqmlcomponent.h1
-rw-r--r--src/qml/qml/qqmlcomponent_p.h7
-rw-r--r--src/qml/qml/qqmlcomponentattached_p.h30
-rw-r--r--src/qml/qml/qqmlcontext.cpp548
-rw-r--r--src/qml/qml/qqmlcontext.h2
-rw-r--r--src/qml/qml/qqmlcontext_p.h336
-rw-r--r--src/qml/qml/qqmlcontextdata.cpp366
-rw-r--r--src/qml/qml/qqmlcontextdata_p.h432
-rw-r--r--src/qml/qml/qqmlcustomparser.cpp12
-rw-r--r--src/qml/qml/qqmldata_p.h47
-rw-r--r--src/qml/qml/qqmldatablob.cpp30
-rw-r--r--src/qml/qml/qqmldatablob_p.h1
-rw-r--r--src/qml/qml/qqmlengine.cpp284
-rw-r--r--src/qml/qml/qqmlengine.h20
-rw-r--r--src/qml/qml/qqmlengine_p.h59
-rw-r--r--src/qml/qml/qqmlexpression.cpp41
-rw-r--r--src/qml/qml/qqmlexpression.h2
-rw-r--r--src/qml/qml/qqmlexpression_p.h4
-rw-r--r--src/qml/qml/qqmlextensionplugin.cpp10
-rw-r--r--src/qml/qml/qqmlextensionplugin.h1
-rw-r--r--src/qml/qml/qqmlfileselector.cpp69
-rw-r--r--src/qml/qml/qqmlfileselector.h6
-rw-r--r--src/qml/qml/qqmlguardedcontextdata_p.h131
-rw-r--r--src/qml/qml/qqmlimport.cpp418
-rw-r--r--src/qml/qml/qqmlimport_p.h40
-rw-r--r--src/qml/qml/qqmlincubator.cpp21
-rw-r--r--src/qml/qml/qqmlincubator_p.h2
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp51
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h56
-rw-r--r--src/qml/qml/qqmllocale.cpp2
-rw-r--r--src/qml/qml/qqmllocale_p.h2
-rw-r--r--src/qml/qml/qqmlloggingcategory_p.h4
-rw-r--r--src/qml/qml/qqmlmetaobject.cpp8
-rw-r--r--src/qml/qml/qqmlmetatype.cpp321
-rw-r--r--src/qml/qml/qqmlmetatype_p.h44
-rw-r--r--src/qml/qml/qqmlmetatypedata.cpp55
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h32
-rw-r--r--src/qml/qml/qqmlmoduleregistration.cpp20
-rw-r--r--src/qml/qml/qqmlmoduleregistration.h7
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp194
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h32
-rw-r--r--src/qml/qml/qqmlparserstatus.cpp2
-rw-r--r--src/qml/qml/qqmlprivate.h120
-rw-r--r--src/qml/qml/qqmlproperty.cpp59
-rw-r--r--src/qml/qml/qqmlproperty_p.h25
-rw-r--r--src/qml/qml/qqmlpropertybinding.cpp123
-rw-r--r--src/qml/qml/qqmlpropertybinding_p.h91
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp91
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h53
-rw-r--r--src/qml/qml/qqmlpropertycachecreator.cpp7
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h72
-rw-r--r--src/qml/qml/qqmlpropertycachevector_p.h17
-rw-r--r--src/qml/qml/qqmlpropertydata_p.h47
-rw-r--r--src/qml/qml/qqmlpropertyresolver.cpp1
-rw-r--r--src/qml/qml/qqmlpropertyvalidator.cpp25
-rw-r--r--src/qml/qml/qqmlscriptblob.cpp1
-rw-r--r--src/qml/qml/qqmlscriptdata.cpp70
-rw-r--r--src/qml/qml/qqmlscriptdata_p.h5
-rw-r--r--src/qml/qml/qqmltype.cpp51
-rw-r--r--src/qml/qml/qqmltype_p.h18
-rw-r--r--src/qml/qml/qqmltype_p_p.h9
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp102
-rw-r--r--src/qml/qml/qqmltypecompiler_p.h2
-rw-r--r--src/qml/qml/qqmltypedata.cpp70
-rw-r--r--src/qml/qml/qqmltypedata_p.h7
-rw-r--r--src/qml/qml/qqmltypeloader.cpp45
-rw-r--r--src/qml/qml/qqmltypeloader_p.h3
-rw-r--r--src/qml/qml/qqmltypemodule.cpp24
-rw-r--r--src/qml/qml/qqmltypemodule_p.h15
-rw-r--r--src/qml/qml/qqmltypemodule_p_p.h6
-rw-r--r--src/qml/qml/qqmltypemoduleversion.cpp32
-rw-r--r--src/qml/qml/qqmltypemoduleversion_p.h21
-rw-r--r--src/qml/qml/qqmltypenamecache.cpp8
-rw-r--r--src/qml/qml/qqmltypenotavailable_p.h2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp22
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp7
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h15
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp2
-rw-r--r--src/qml/qml/qqmlvme.cpp2
-rw-r--r--src/qml/qml/qqmlvme_p.h2
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp43
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h7
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp40
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp71
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h2
-rw-r--r--src/qml/qmldirparser/qqmldirparser.cpp51
-rw-r--r--src/qml/qmldirparser/qqmldirparser_p.h15
-rw-r--r--src/qml/types/qqmlbind.cpp33
-rw-r--r--src/qml/types/qqmlbind_p.h5
-rw-r--r--src/qml/types/qqmlconnections.cpp6
-rw-r--r--src/qml/types/qqmlconnections_p.h5
-rw-r--r--src/qml/types/qqmltimer_p.h1
171 files changed, 7897 insertions, 4220 deletions
diff --git a/src/qml/.prev_CMakeLists.txt b/src/qml/.prev_CMakeLists.txt
new file mode 100644
index 0000000000..eea934fc64
--- /dev/null
+++ b/src/qml/.prev_CMakeLists.txt
@@ -0,0 +1,622 @@
+# Generated from qml.pro.
+
+#####################################################################
+## Qml Module:
+#####################################################################
+
+qt_add_module(Qml
+ GENERATE_METATYPES
+ PLUGIN_TYPES qmltooling
+ SOURCES
+ ../3rdparty/masm/assembler/*.h
+ ../3rdparty/masm/assembler/ARMv7Assembler.cpp
+ ../3rdparty/masm/assembler/LinkBuffer.cpp
+ ../3rdparty/masm/disassembler/ARM64/A64DOpcode.cpp ../3rdparty/masm/disassembler/ARM64/A64DOpcode.h
+ ../3rdparty/masm/disassembler/ARM64Disassembler.cpp
+ ../3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp ../3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h
+ ../3rdparty/masm/disassembler/ARMv7Disassembler.cpp
+ ../3rdparty/masm/disassembler/Disassembler.cpp
+ ../3rdparty/masm/disassembler/Mips32Disassembler.cpp
+ ../3rdparty/masm/disassembler/UDis86Disassembler.cpp
+ ../3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp ../3rdparty/masm/disassembler/mips32/Mips32Opcode.h
+ ../3rdparty/masm/stubs/Options.cpp
+ ../3rdparty/masm/stubs/WTFStubs.cpp ../3rdparty/masm/stubs/WTFStubs.h
+ ../3rdparty/masm/stubs/wtf/FastAllocBase.h
+ ../3rdparty/masm/stubs/wtf/FastMalloc.h
+ ../3rdparty/masm/stubs/wtf/Noncopyable.h
+ ../3rdparty/masm/stubs/wtf/OwnPtr.h
+ ../3rdparty/masm/stubs/wtf/PassOwnPtr.h
+ ../3rdparty/masm/stubs/wtf/PassRefPtr.h
+ ../3rdparty/masm/stubs/wtf/RefCounted.h
+ ../3rdparty/masm/stubs/wtf/RefPtr.h
+ ../3rdparty/masm/stubs/wtf/TypeTraits.h
+ ../3rdparty/masm/stubs/wtf/UnusedParam.h
+ ../3rdparty/masm/stubs/wtf/Vector.h
+ ../3rdparty/masm/stubs/yarr/YarrUnicodeProperties.cpp
+ ../3rdparty/masm/wtf/*.h
+ ../3rdparty/masm/wtf/FilePrintStream.cpp ../3rdparty/masm/wtf/FilePrintStream.h
+ ../3rdparty/masm/wtf/OSAllocator.h
+ ../3rdparty/masm/wtf/PageAllocation.h
+ ../3rdparty/masm/wtf/PageAllocationAligned.cpp ../3rdparty/masm/wtf/PageAllocationAligned.h
+ ../3rdparty/masm/wtf/PageBlock.cpp ../3rdparty/masm/wtf/PageBlock.h
+ ../3rdparty/masm/wtf/PageReservation.h
+ ../3rdparty/masm/wtf/PrintStream.cpp ../3rdparty/masm/wtf/PrintStream.h
+ ../3rdparty/masm/wtf/RawPointer.h
+ ../3rdparty/masm/yarr/Yarr.h
+ ../3rdparty/masm/yarr/YarrCanonicalizeUCS2.cpp ../3rdparty/masm/yarr/YarrCanonicalizeUCS2.h
+ ../3rdparty/masm/yarr/YarrCanonicalizeUnicode.cpp
+ ../3rdparty/masm/yarr/YarrInterpreter.cpp ../3rdparty/masm/yarr/YarrInterpreter.h
+ ../3rdparty/masm/yarr/YarrJIT.cpp ../3rdparty/masm/yarr/YarrJIT.h
+ ../3rdparty/masm/yarr/YarrParser.h
+ ../3rdparty/masm/yarr/YarrPattern.cpp ../3rdparty/masm/yarr/YarrPattern.h
+ ../3rdparty/masm/yarr/YarrSyntaxChecker.cpp ../3rdparty/masm/yarr/YarrSyntaxChecker.h
+ ../3rdparty/masm/yarr/YarrUnicodeProperties.h
+ common/qqmlapiversion_p.h
+ common/qqmljsdiagnosticmessage_p.h
+ common/qqmljsfixedpoolarray_p.h
+ common/qqmljsmemorypool_p.h
+ common/qqmljssourcelocation_p.h
+ common/qv4alloca_p.h
+ common/qv4calldata_p.h
+ common/qv4compileddata_p.h
+ common/qv4staticvalue_p.h
+ common/qv4stringtoarrayindex_p.h
+ compiler/qqmlirbuilder.cpp compiler/qqmlirbuilder_p.h
+ compiler/qv4bytecodegenerator.cpp compiler/qv4bytecodegenerator_p.h
+ compiler/qv4bytecodehandler.cpp compiler/qv4bytecodehandler_p.h
+ compiler/qv4codegen.cpp compiler/qv4codegen_p.h
+ compiler/qv4compiler.cpp compiler/qv4compiler_p.h
+ compiler/qv4compilercontext.cpp compiler/qv4compilercontext_p.h
+ compiler/qv4compilercontrolflow_p.h
+ compiler/qv4compilerglobal_p.h
+ compiler/qv4compilerscanfunctions.cpp compiler/qv4compilerscanfunctions_p.h
+ compiler/qv4instr_moth.cpp compiler/qv4instr_moth_p.h
+ compiler/qv4util_p.h
+ debugger/qqmldebug.h
+ debugger/qqmldebugconnector_p.h
+ debugger/qqmldebugserviceinterfaces_p.h
+ debugger/qqmldebugstatesdelegate_p.h
+ debugger/qqmlprofiler_p.h
+ inlinecomponentutils_p.h
+ jsapi/qjsengine.cpp jsapi/qjsengine.h jsapi/qjsengine_p.h
+ jsapi/qjsvalue.cpp jsapi/qjsvalue.h jsapi/qjsvalue_p.h
+ jsapi/qjsvalueiterator.cpp jsapi/qjsvalueiterator.h jsapi/qjsvalueiterator_p.h
+ jsruntime/qv4argumentsobject.cpp jsruntime/qv4argumentsobject_p.h
+ jsruntime/qv4arraybuffer.cpp jsruntime/qv4arraybuffer_p.h
+ jsruntime/qv4arraydata.cpp jsruntime/qv4arraydata_p.h
+ jsruntime/qv4arrayiterator.cpp jsruntime/qv4arrayiterator_p.h
+ jsruntime/qv4arrayobject.cpp jsruntime/qv4arrayobject_p.h
+ jsruntime/qv4atomics.cpp jsruntime/qv4atomics_p.h
+ jsruntime/qv4booleanobject.cpp jsruntime/qv4booleanobject_p.h
+ jsruntime/qv4compilationunitmapper.cpp jsruntime/qv4compilationunitmapper_p.h
+ jsruntime/qv4context.cpp jsruntime/qv4context_p.h
+ jsruntime/qv4dataview.cpp jsruntime/qv4dataview_p.h
+ jsruntime/qv4dateobject.cpp jsruntime/qv4dateobject_p.h
+ jsruntime/qv4debugging_p.h
+ jsruntime/qv4engine.cpp jsruntime/qv4engine_p.h
+ jsruntime/qv4enginebase_p.h
+ jsruntime/qv4errorobject.cpp jsruntime/qv4errorobject_p.h
+ jsruntime/qv4estable.cpp jsruntime/qv4estable_p.h
+ jsruntime/qv4executableallocator.cpp jsruntime/qv4executableallocator_p.h
+ jsruntime/qv4executablecompilationunit.cpp jsruntime/qv4executablecompilationunit_p.h
+ jsruntime/qv4function.cpp jsruntime/qv4function_p.h
+ jsruntime/qv4functionobject.cpp jsruntime/qv4functionobject_p.h
+ jsruntime/qv4functiontable_p.h
+ jsruntime/qv4generatorobject.cpp jsruntime/qv4generatorobject_p.h
+ jsruntime/qv4global_p.h
+ jsruntime/qv4globalobject.cpp jsruntime/qv4globalobject_p.h
+ jsruntime/qv4identifier.cpp jsruntime/qv4identifier_p.h
+ jsruntime/qv4identifiertable.cpp jsruntime/qv4identifiertable_p.h
+ jsruntime/qv4include.cpp jsruntime/qv4include_p.h
+ jsruntime/qv4internalclass.cpp jsruntime/qv4internalclass_p.h
+ jsruntime/qv4iterator.cpp jsruntime/qv4iterator_p.h
+ jsruntime/qv4jscall_p.h
+ jsruntime/qv4jsonobject.cpp jsruntime/qv4jsonobject_p.h
+ jsruntime/qv4lookup.cpp jsruntime/qv4lookup_p.h
+ jsruntime/qv4managed.cpp jsruntime/qv4managed_p.h
+ jsruntime/qv4mapiterator.cpp jsruntime/qv4mapiterator_p.h
+ jsruntime/qv4mapobject.cpp jsruntime/qv4mapobject_p.h
+ jsruntime/qv4math_p.h
+ jsruntime/qv4mathobject.cpp jsruntime/qv4mathobject_p.h
+ jsruntime/qv4memberdata.cpp jsruntime/qv4memberdata_p.h
+ jsruntime/qv4module.cpp jsruntime/qv4module_p.h
+ jsruntime/qv4numberobject.cpp jsruntime/qv4numberobject_p.h
+ jsruntime/qv4object.cpp jsruntime/qv4object_p.h
+ jsruntime/qv4objectiterator.cpp jsruntime/qv4objectiterator_p.h
+ jsruntime/qv4objectproto.cpp jsruntime/qv4objectproto_p.h
+ jsruntime/qv4persistent.cpp jsruntime/qv4persistent_p.h
+ jsruntime/qv4profiling_p.h
+ jsruntime/qv4promiseobject.cpp jsruntime/qv4promiseobject_p.h
+ jsruntime/qv4property_p.h
+ jsruntime/qv4propertykey.cpp jsruntime/qv4propertykey_p.h
+ jsruntime/qv4proxy.cpp jsruntime/qv4proxy_p.h
+ jsruntime/qv4qmlcontext.cpp jsruntime/qv4qmlcontext_p.h
+ jsruntime/qv4qobjectwrapper.cpp jsruntime/qv4qobjectwrapper_p.h
+ jsruntime/qv4reflect.cpp jsruntime/qv4reflect_p.h
+ jsruntime/qv4regexp.cpp jsruntime/qv4regexp_p.h
+ jsruntime/qv4regexpobject.cpp jsruntime/qv4regexpobject_p.h
+ jsruntime/qv4resolvedtypereference.cpp jsruntime/qv4resolvedtypereference_p.h
+ jsruntime/qv4runtime.cpp jsruntime/qv4runtime_p.h
+ jsruntime/qv4runtimeapi_p.h
+ jsruntime/qv4runtimecodegen.cpp jsruntime/qv4runtimecodegen_p.h
+ jsruntime/qv4scopedvalue_p.h
+ jsruntime/qv4script.cpp jsruntime/qv4script_p.h
+ jsruntime/qv4setiterator.cpp jsruntime/qv4setiterator_p.h
+ jsruntime/qv4setobject.cpp jsruntime/qv4setobject_p.h
+ jsruntime/qv4sparsearray.cpp jsruntime/qv4sparsearray_p.h
+ jsruntime/qv4stackframe.cpp jsruntime/qv4stackframe_p.h
+ jsruntime/qv4string.cpp jsruntime/qv4string_p.h
+ jsruntime/qv4stringiterator.cpp jsruntime/qv4stringiterator_p.h
+ jsruntime/qv4stringobject.cpp jsruntime/qv4stringobject_p.h
+ jsruntime/qv4symbol.cpp jsruntime/qv4symbol_p.h
+ jsruntime/qv4typedarray.cpp jsruntime/qv4typedarray_p.h
+ jsruntime/qv4urlobject.cpp jsruntime/qv4urlobject_p.h
+ jsruntime/qv4value.cpp jsruntime/qv4value_p.h
+ jsruntime/qv4variantobject.cpp jsruntime/qv4variantobject_p.h
+ jsruntime/qv4vme_moth.cpp jsruntime/qv4vme_moth_p.h
+ jsruntime/qv4vtable_p.h
+ memory/qv4heap_p.h
+ memory/qv4mm.cpp memory/qv4mm_p.h
+ memory/qv4mmdefs_p.h
+ memory/qv4writebarrier_p.h
+ parser/qqmljsast.cpp parser/qqmljsast_p.h
+ parser/qqmljsastfwd_p.h
+ parser/qqmljsastvisitor.cpp parser/qqmljsastvisitor_p.h
+ parser/qqmljsengine_p.cpp parser/qqmljsengine_p.h
+ parser/qqmljsglobal_p.h
+ parser/qqmljskeywords_p.h
+ parser/qqmljslexer.cpp parser/qqmljslexer_p.h
+ qml/ftw/qbitfield_p.h
+ qml/ftw/qfieldlist_p.h
+ qml/ftw/qfinitestack_p.h
+ qml/ftw/qflagpointer_p.h
+ qml/ftw/qhashedstring.cpp qml/ftw/qhashedstring_p.h
+ qml/ftw/qintrusivelist.cpp qml/ftw/qintrusivelist_p.h
+ qml/ftw/qlazilyallocated_p.h
+ qml/ftw/qlinkedstringhash_p.h
+ qml/ftw/qpodvector_p.h
+ qml/ftw/qprimefornumbits_p.h
+ qml/ftw/qqmlnullablevalue_p.h
+ qml/ftw/qqmlrefcount_p.h
+ qml/ftw/qqmlthread.cpp qml/ftw/qqmlthread_p.h
+ qml/ftw/qrecursionwatcher_p.h
+ qml/ftw/qrecyclepool_p.h
+ qml/ftw/qstringhash_p.h
+ qml/qqml.cpp qml/qqml.h
+ qml/qqmlabstractbinding.cpp qml/qqmlabstractbinding_p.h
+ qml/qqmlabstracturlinterceptor.cpp qml/qqmlabstracturlinterceptor.h
+ qml/qqmlapplicationengine.cpp qml/qqmlapplicationengine.h qml/qqmlapplicationengine_p.h
+ qml/qqmlbinding.cpp qml/qqmlbinding_p.h
+ qml/qqmlboundsignal.cpp qml/qqmlboundsignal_p.h
+ qml/qqmlboundsignalexpressionpointer_p.h
+ qml/qqmlcleanup.cpp qml/qqmlcleanup_p.h
+ qml/qqmlcomponent.cpp qml/qqmlcomponent.h qml/qqmlcomponent_p.h
+ qml/qqmlcomponentattached_p.h
+ qml/qqmlcontext.cpp qml/qqmlcontext.h qml/qqmlcontext_p.h
+ qml/qqmlcustomparser.cpp qml/qqmlcustomparser_p.h
+ qml/qqmldata_p.h
+ qml/qqmldatablob.cpp qml/qqmldatablob_p.h
+ qml/qqmldelayedcallqueue.cpp qml/qqmldelayedcallqueue_p.h
+ qml/qqmldirdata.cpp qml/qqmldirdata_p.h
+ qml/qqmlengine.cpp qml/qqmlengine.h qml/qqmlengine_p.h
+ qml/qqmlenumdata_p.h
+ qml/qqmlenumvalue_p.h
+ qml/qqmlerror.cpp qml/qqmlerror.h
+ qml/qqmlexpression.cpp qml/qqmlexpression.h qml/qqmlexpression_p.h
+ qml/qqmlextensioninterface.h
+ qml/qqmlextensionplugin.cpp qml/qqmlextensionplugin.h qml/qqmlextensionplugin_p.h
+ qml/qqmlfile.cpp qml/qqmlfile.h
+ qml/qqmlfileselector.cpp qml/qqmlfileselector.h qml/qqmlfileselector_p.h
+ qml/qqmlglobal.cpp qml/qqmlglobal_p.h
+ qml/qqmlguard_p.h
+ qml/qqmlimport.cpp qml/qqmlimport_p.h
+ qml/qqmlincubator.cpp qml/qqmlincubator.h qml/qqmlincubator_p.h
+ qml/qqmlinfo.cpp qml/qqmlinfo.h
+ qml/qqmlirloader.cpp qml/qqmlirloader_p.h
+ qml/qqmljavascriptexpression.cpp qml/qqmljavascriptexpression_p.h
+ qml/qqmllist.cpp qml/qqmllist.h qml/qqmllist_p.h
+ qml/qqmllistwrapper.cpp qml/qqmllistwrapper_p.h
+ qml/qqmlloggingcategory.cpp qml/qqmlloggingcategory_p.h
+ qml/qqmlmetaobject.cpp qml/qqmlmetaobject_p.h
+ qml/qqmlmetatype.cpp qml/qqmlmetatype_p.h
+ qml/qqmlmetatypedata.cpp qml/qqmlmetatypedata_p.h
+ qml/qqmlmoduleregistration.cpp qml/qqmlmoduleregistration.h
+ qml/qqmlnetworkaccessmanagerfactory.cpp qml/qqmlnetworkaccessmanagerfactory.h
+ qml/qqmlnotifier.cpp qml/qqmlnotifier_p.h
+ qml/qqmlobjectcreator.cpp qml/qqmlobjectcreator_p.h
+ qml/qqmlobjectorgadget.cpp qml/qqmlobjectorgadget_p.h
+ qml/qqmlopenmetaobject.cpp qml/qqmlopenmetaobject_p.h
+ qml/qqmlparserstatus.cpp qml/qqmlparserstatus.h
+ qml/qqmlplatform.cpp qml/qqmlplatform_p.h
+ qml/qqmlprivate.h
+ qml/qqmlproperty.cpp qml/qqmlproperty.h qml/qqmlproperty_p.h
+ qml/qqmlpropertybinding.cpp qml/qqmlpropertybinding_p.h
+ qml/qqmlpropertycache.cpp qml/qqmlpropertycache_p.h
+ qml/qqmlpropertycachecreator.cpp qml/qqmlpropertycachecreator_p.h
+ qml/qqmlpropertycachemethodarguments_p.h
+ qml/qqmlpropertycachevector_p.h
+ qml/qqmlpropertydata_p.h
+ qml/qqmlpropertyindex_p.h
+ qml/qqmlpropertyresolver.cpp qml/qqmlpropertyresolver_p.h
+ qml/qqmlpropertyvalidator.cpp qml/qqmlpropertyvalidator_p.h
+ qml/qqmlpropertyvalueinterceptor.cpp qml/qqmlpropertyvalueinterceptor_p.h
+ qml/qqmlpropertyvaluesource.cpp qml/qqmlpropertyvaluesource.h
+ qml/qqmlproxymetaobject.cpp qml/qqmlproxymetaobject_p.h
+ qml/qqmlscriptblob.cpp qml/qqmlscriptblob_p.h
+ qml/qqmlscriptdata.cpp qml/qqmlscriptdata_p.h
+ qml/qqmlscriptstring.cpp qml/qqmlscriptstring.h qml/qqmlscriptstring_p.h
+ qml/qqmlsourcecoordinate_p.h
+ qml/qqmlstaticmetaobject.cpp qml/qqmlstaticmetaobject_p.h
+ qml/qqmlstringconverters.cpp qml/qqmlstringconverters_p.h
+ qml/qqmltype.cpp qml/qqmltype_p.h
+ qml/qqmltype_p_p.h
+ qml/qqmltypecompiler.cpp qml/qqmltypecompiler_p.h
+ qml/qqmltypedata.cpp qml/qqmltypedata_p.h
+ qml/qqmltypeloader.cpp qml/qqmltypeloader_p.h
+ qml/qqmltypeloaderqmldircontent.cpp qml/qqmltypeloaderqmldircontent_p.h
+ qml/qqmltypeloaderthread.cpp qml/qqmltypeloaderthread_p.h
+ qml/qqmltypemodule.cpp qml/qqmltypemodule_p.h
+ qml/qqmltypemodule_p_p.h
+ qml/qqmltypemoduleversion.cpp qml/qqmltypemoduleversion_p.h
+ qml/qqmltypenamecache.cpp qml/qqmltypenamecache_p.h
+ qml/qqmltypenotavailable.cpp qml/qqmltypenotavailable_p.h
+ qml/qqmltypewrapper.cpp qml/qqmltypewrapper_p.h
+ qml/qqmlvaluetype.cpp qml/qqmlvaluetype_p.h
+ qml/qqmlvaluetypeproxybinding.cpp qml/qqmlvaluetypeproxybinding_p.h
+ qml/qqmlvaluetypewrapper.cpp
+ qml/qqmlvme.cpp qml/qqmlvme_p.h
+ qml/qqmlvmemetaobject.cpp qml/qqmlvmemetaobject_p.h
+ qml/v8/qqmlbuiltinfunctions.cpp qml/v8/qqmlbuiltinfunctions_p.h
+ qml/v8/qv4domerrors.cpp qml/v8/qv4domerrors_p.h
+ qml/v8/qv4sqlerrors.cpp qml/v8/qv4sqlerrors_p.h
+ qmldirparser/qqmldirparser.cpp qmldirparser/qqmldirparser_p.h
+ qtqmlcompilerglobal.h qtqmlcompilerglobal_p.h
+ qtqmlglobal.h qtqmlglobal_p.h
+ types/qqmlbind.cpp types/qqmlbind_p.h
+ types/qqmlconnections.cpp types/qqmlconnections_p.h
+ util/qqmlpropertymap.cpp util/qqmlpropertymap.h
+ DEFINES
+ BUILDING_QT__
+ ENABLE_ASSEMBLER_WX_EXCLUSIVE=1
+ ENABLE_DFG_JIT=0
+ ENABLE_DFG_JIT_UTILITY_METHODS=1
+ ENABLE_JIT_CONSTANT_BLINDING=0
+ ENABLE_LLINT=0
+ JS_EXPORT_PRIVATE=""
+ QT_NO_FOREACH
+ QT_NO_INTEGER_EVENT_COORDINATES
+ QT_NO_URL_CAST_FROM_STRING
+ WTFInvokeCrashHook=qmlWTFInvokeCrashHook
+ WTFReportAssertionFailure=qmlWTFReportAssertionFailure
+ WTFReportAssertionFailureWithMessage=qmlWTFReportAssertionFailureWithMessage
+ WTFReportBacktrace=qmlWTFReportBacktrace
+ WTF_EXPORT_PRIVATE=""
+ INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_BINARY_DIR}/compiler
+ ${CMAKE_CURRENT_BINARY_DIR}/jsruntime
+ ${CMAKE_CURRENT_BINARY_DIR}/memory
+ ${CMAKE_CURRENT_BINARY_DIR}/qmldirparser
+ ../3rdparty/masm
+ ../3rdparty/masm/assembler
+ ../3rdparty/masm/disassembler
+ ../3rdparty/masm/disassembler/udis86
+ ../3rdparty/masm/jit
+ ../3rdparty/masm/runtime
+ ../3rdparty/masm/stubs
+ ../3rdparty/masm/stubs/runtime
+ ../3rdparty/masm/stubs/wtf
+ ../3rdparty/masm/wtf
+ .generated
+ compiler
+ debugger
+ jsruntime
+ memory
+ qmldirparser
+ LIBRARIES
+ Qt::CorePrivate
+ PUBLIC_LIBRARIES
+ Qt::Core
+ PRIVATE_MODULE_INTERFACE
+ Qt::CorePrivate
+)
+
+# QLALR Grammars:
+qt_process_qlalr(
+ Qml
+ parser/qqmljs.g
+ ""
+)
+
+#### Keys ignored in scope 1:.:.:qml.pro:<TRUE>:
+# QMLTYPES_FILENAME = "plugins.qmltypes"
+# QMLTYPES_INSTALL_DIR = "$$[QT_INSTALL_QML]/QtQml"
+# QML_IMPORT_NAME = "QtQml"
+# QML_IMPORT_VERSION = "$$QT_VERSION"
+
+## Scopes:
+#####################################################################
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_network
+ SOURCES
+ qml/qqmltypeloadernetworkreplyproxy.cpp qml/qqmltypeloadernetworkreplyproxy_p.h
+ PUBLIC_LIBRARIES
+ Qt::Network
+)
+
+qt_extend_target(Qml CONDITION MSVC AND (TEST_architecture_arch STREQUAL "i386")
+ LINK_OPTIONS
+ "/BASE:0x66000000"
+)
+
+qt_extend_target(Qml CONDITION MSVC
+ DEFINES
+ _CRT_SECURE_NO_WARNINGS
+)
+
+qt_extend_target(Qml CONDITION WIN32 AND NOT WINRT
+ SOURCES
+ ../3rdparty/masm/wtf/OSAllocatorWin.cpp
+ PUBLIC_LIBRARIES
+ shell32
+)
+
+#### Keys ignored in scope 6:.:.:qml.pro:solaris-cc_x_:
+# QMAKE_CXXFLAGS_RELEASE = "--O2"
+
+qt_extend_target(Qml CONDITION GCC AND (TEST_architecture_arch STREQUAL "mips")
+ COMPILE_OPTIONS
+ -fno-reorder-blocks
+)
+
+qt_extend_target(Qml CONDITION EXISTS "qqml_enable_gcov"
+ LIBRARIES
+ gcov
+ COMPILE_OPTIONS
+ -fno-elide-constructors
+ -fprofile-arcs
+ -ftest-coverage
+)
+
+qt_extend_target(Qml CONDITION release AND MSVC AND (QT_CL_MAJOR_VERSION EQUAL 19) AND (QT_CL_MINOR_VERSION EQUAL 00) AND (QT_CL_PATCH_VERSION GREATER 24212)
+ COMPILE_OPTIONS
+ -d2SSAOptimizer-
+)
+
+#### Keys ignored in scope 10:.:.:qml.pro:ICC:
+# WERROR = "-ww2415"
+
+#### Keys ignored in scope 11:.:.:qml.pro:(QT_CLANG_MAJOR_VERSION GREATER 3) OR (QT_CLANG_MINOR_VERSION GREATER 3) OR (QT_APPLE_CLANG_MAJOR_VERSION GREATER 5) OR ( (QT_APPLE_CLANG_MAJOR_VERSION EQUAL 5) AND (QT_APPLE_CLANG_MINOR_VERSION GREATER 0) ):
+# WERROR = "-Wno-error=unused-const-variable"
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_jit
+ SOURCES
+ jit/qv4assemblercommon.cpp jit/qv4assemblercommon_p.h
+ jit/qv4baselineassembler.cpp jit/qv4baselineassembler_p.h
+ jit/qv4baselinejit.cpp jit/qv4baselinejit_p.h
+ INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_BINARY_DIR}/jit
+ jit
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_animation
+ SOURCES
+ animations/qabstractanimationjob.cpp animations/qabstractanimationjob_p.h
+ animations/qanimationgroupjob.cpp animations/qanimationgroupjob_p.h
+ animations/qanimationjobutil_p.h
+ animations/qcontinuinganimationgroupjob.cpp animations/qcontinuinganimationgroupjob_p.h
+ animations/qparallelanimationgroupjob.cpp animations/qparallelanimationgroupjob_p.h
+ animations/qpauseanimationjob.cpp animations/qpauseanimationjob_p.h
+ animations/qsequentialanimationgroupjob.cpp animations/qsequentialanimationgroupjob_p.h
+ types/qqmltimer.cpp types/qqmltimer_p.h
+ INCLUDE_DIRECTORIES
+ animations
+)
+
+#### Keys ignored in scope 17:.:common:common/common.pri:NOT build_pass:
+# compile_hash_contents = "// Generated file, DO NOT EDIT" "$${LITERAL_HASH}define QML_COMPILE_HASH "$$QML_COMPILE_HASH"" "$${LITERAL_HASH}define QML_COMPILE_HASH_LENGTH $$str_size($$QML_COMPILE_HASH)"
+# tag = <EMPTY>
+# tagFile = "$$PWD/../../.tag"
+
+#### Keys ignored in scope 18:.:common:common/common.pri:EXISTS _ss_tagFile:
+# QMAKE_INTERNAL_INCLUDED_FILES = "$$tagFile"
+# tag = "$$cat($$tagFile, singleline)"
+
+#### Keys ignored in scope 19:.:common:common/common.pri:NOT tag___equals____ss_{LITERAL_DOLLAR}Format AND %H_ss_{LITERAL_DOLLAR}:
+# QML_COMPILE_HASH = "$$tag"
+
+#### Keys ignored in scope 21:.:common:common/common.pri:EXISTS _ss_PWD/../../.git:
+# QML_COMPILE_HASH = "$$commit"
+# commit = "$$system(git rev-parse HEAD)"
+
+qt_extend_target(Qml CONDITION GCC AND QT_COMPILER_VERSION_MAJOR STREQUAL 5
+ COMPILE_OPTIONS
+ -fno-strict-aliasing
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_debug
+ SOURCES
+ debugger/qqmlabstractprofileradapter.cpp debugger/qqmlabstractprofileradapter_p.h
+ debugger/qqmlconfigurabledebugservice_p.h
+ debugger/qqmldebug.cpp
+ debugger/qqmldebugconnector.cpp
+ debugger/qqmldebugpluginmanager_p.h
+ debugger/qqmldebugserver_p.h
+ debugger/qqmldebugserverconnection_p.h
+ debugger/qqmldebugservice.cpp debugger/qqmldebugservice_p.h
+ debugger/qqmldebugservicefactory_p.h
+ debugger/qqmldebugserviceinterfaces.cpp
+ debugger/qqmlprofiler.cpp
+ debugger/qqmlprofilerdefinitions_p.h
+ jsruntime/qv4profiling.cpp
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_sequence_object
+ SOURCES
+ jsruntime/qv4sequenceobject.cpp jsruntime/qv4sequenceobject_p.h
+)
+
+qt_extend_target(Qml CONDITION UNIX
+ SOURCES
+ jsruntime/qv4compilationunitmapper_unix.cpp
+ jsruntime/qv4functiontable_unix.cpp
+)
+
+qt_extend_target(Qml CONDITION WIN32
+ SOURCES
+ jsruntime/qv4compilationunitmapper_win.cpp
+ DEFINES
+ NOMINMAX
+)
+
+qt_extend_target(Qml CONDITION (TEST_architecture_arch STREQUAL "x86_64") AND WIN32 AND NOT WINRT
+ SOURCES
+ jsruntime/qv4functiontable_win64.cpp
+)
+
+qt_extend_target(Qml CONDITION WIN32 AND (WINRT OR NOT (TEST_architecture_arch STREQUAL "x86_64"))
+ SOURCES
+ jsruntime/qv4functiontable_noop.cpp
+)
+
+qt_extend_target(Qml CONDITION valgrind
+ DEFINES
+ V4_USE_VALGRIND
+)
+
+qt_extend_target(Qml CONDITION heaptrack
+ DEFINES
+ V4_USE_HEAPTRACK
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_xml_http_request
+ SOURCES
+ qml/qqmlxmlhttprequest.cpp qml/qqmlxmlhttprequest_p.h
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_locale
+ SOURCES
+ qml/qqmllocale.cpp qml/qqmllocale_p.h
+)
+
+qt_extend_target(Qml CONDITION ANDROID
+ DEFINES
+ LIBS_SUFFIX="_${CMAKE_SYSTEM_PROCESSOR}.so"
+)
+
+qt_extend_target(Qml CONDITION hpux-_x_ OR solaris-_x_ OR (QT_FEATURE_clock_gettime AND linux-_x_)
+ LIBRARIES
+ rt
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_itemmodel
+ SOURCES
+ types/qqmlmodelindexvaluetype.cpp types/qqmlmodelindexvaluetype_p.h
+)
+
+qt_extend_target(Qml CONDITION disassembler AND ((TEST_architecture_arch STREQUAL "i386") OR (TEST_architecture_arch STREQUAL "x86_64"))
+ DEFINES
+ WTF_USE_UDIS86=1
+)
+
+qt_extend_target(Qml CONDITION (TEST_architecture_arch STREQUAL "arm") AND disassembler
+ DEFINES
+ WTF_USE_ARMV7_DISASSEMBLER=1
+)
+
+qt_extend_target(Qml CONDITION (TEST_architecture_arch STREQUAL "arm64") AND disassembler
+ DEFINES
+ WTF_USE_ARM64_DISASSEMBLER=1
+)
+
+qt_extend_target(Qml CONDITION (TEST_architecture_arch STREQUAL "mips") AND disassembler
+ DEFINES
+ WTF_USE_MIPS32_DISASSEMBLER=1
+)
+
+qt_extend_target(Qml CONDITION NOT disassembler
+ DEFINES
+ WTF_USE_UDIS86=0
+)
+
+qt_extend_target(Qml CONDITION CMAKE_BUILD_TYPE STREQUAL Release
+ DEFINES
+ NDEBUG
+)
+
+qt_extend_target(Qml CONDITION GCC AND QT_COMPILER_VERSION_MAJOR STRGREATER 6 AND NOT CLANG AND NOT ICC
+ COMPILE_OPTIONS
+ -Wno-expansion-to-defined
+)
+
+#### Keys ignored in scope 65:.:../3rdparty/masm:../3rdparty/masm/masm-defs.pri:(QT_COMPILER_VERSION_MAJOR STRGREATER 6):
+# QMAKE_CXXFLAGS_WARN_ON = "-Wno-expansion-to-defined"
+
+qt_extend_target(Qml CONDITION WINRT
+ SOURCES
+ ../3rdparty/masm/wtf/OSAllocatorWinRT.cpp
+)
+
+qt_extend_target(Qml CONDITION INTEGRITY
+ SOURCES
+ ../3rdparty/masm/wtf/OSAllocatorIntegrity.cpp
+)
+
+qt_extend_target(Qml CONDITION UNIX AND NOT INTEGRITY AND NOT WINRT
+ SOURCES
+ ../3rdparty/masm/wtf/OSAllocatorPosix.cpp
+)
+
+qt_extend_target(Qml CONDITION DEFINES___contains___WTF_USE_UDIS86=1
+ SOURCES
+ ../3rdparty/masm/disassembler/udis86/udis86.c
+ ../3rdparty/masm/disassembler/udis86/udis86_decode.c
+ ../3rdparty/masm/disassembler/udis86/udis86_input.c
+ ../3rdparty/masm/disassembler/udis86/udis86_itab_holder.c
+ ../3rdparty/masm/disassembler/udis86/udis86_syn.c
+ ../3rdparty/masm/disassembler/udis86/udis86_syn-att.c
+ ../3rdparty/masm/disassembler/udis86/udis86_syn-intel.c
+)
+
+#### Keys ignored in scope 73:.:../3rdparty/masm:../3rdparty/masm/masm.pri:DEFINES___contains___WTF_USE_UDIS86=1:
+# ITAB = "$$PWD/disassembler/udis86/optable.xml"
+# QMAKE_EXTRA_COMPILERS = "udis86"
+# QMAKE_EXTRA_TARGETS = "udis86_tab_cfile"
+# udis86.CONFIG = "no_link"
+# udis86.commands = "python" "$$PWD/disassembler/udis86/itab.py" "${QMAKE_FILE_IN}"
+# udis86.input = "ITAB"
+# udis86.output = "udis86_itab.h"
+# udis86_tab_cfile.depends = "udis86_itab.h"
+# udis86_tab_cfile.target = "$$OUT_PWD/udis86_itab.c"
+
+#### Keys ignored in scope 75:.:../3rdparty/masm:../3rdparty/masm/masm.pri:(CMAKE_BUILD_TYPE STREQUAL Debug):
+# GENERATEDDIR = "$$GENERATEDDIR/debug"
+
+#### Keys ignored in scope 76:.:../3rdparty/masm:../3rdparty/masm/masm.pri:else:
+# GENERATEDDIR = "$$GENERATEDDIR/release"
+
+qt_extend_target(Qml CONDITION (NOT c++11 AND NOT ICC) AND (CLANG)
+ COMPILE_OPTIONS
+ -Wno-c++0x-extensions
+ -Wno-c++11-extensions
+)
+
+qt_extend_target(Qml CONDITION (((NOT c++11 AND NOT ICC) AND (NOT (CLANG))) AND (GCC)) AND ((QT_COMPILER_VERSION_MAJOR STRGREATER 4) OR (QT_COMPILER_VERSION_MINOR STRGREATER 5))
+ COMPILE_OPTIONS
+ -Wno-c++0x-compat
+)
+
+
+qt_create_tracepoints(Qml qtqml.tracepoints)
+qt_add_docs(Qml
+ doc/qtqml.qdocconf
+)
+
+
+set_target_properties(Qml PROPERTIES
+ QT_QML_MODULE_INSTALL_QMLTYPES TRUE
+ QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_URI QtQml
+ QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/QtQml"
+)
+
+qt6_qml_type_registration(Qml)
diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt
new file mode 100644
index 0000000000..df85a87c69
--- /dev/null
+++ b/src/qml/CMakeLists.txt
@@ -0,0 +1,633 @@
+# Generated from qml.pro.
+
+#####################################################################
+## Qml Module:
+#####################################################################
+
+qt_add_module(Qml
+ GENERATE_METATYPES
+ PLUGIN_TYPES qmltooling
+ SOURCES
+ # ../3rdparty/masm/assembler/*.h special case remove
+ ../3rdparty/masm/assembler/ARMv7Assembler.cpp
+ ../3rdparty/masm/assembler/LinkBuffer.cpp
+ ../3rdparty/masm/disassembler/ARM64/A64DOpcode.cpp ../3rdparty/masm/disassembler/ARM64/A64DOpcode.h
+ ../3rdparty/masm/disassembler/ARM64Disassembler.cpp
+ ../3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp ../3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.h
+ ../3rdparty/masm/disassembler/ARMv7Disassembler.cpp
+ ../3rdparty/masm/disassembler/Disassembler.cpp
+ ../3rdparty/masm/disassembler/Mips32Disassembler.cpp
+ ../3rdparty/masm/disassembler/UDis86Disassembler.cpp
+ ../3rdparty/masm/disassembler/mips32/Mips32Opcode.cpp ../3rdparty/masm/disassembler/mips32/Mips32Opcode.h
+ ../3rdparty/masm/stubs/Options.cpp
+ ../3rdparty/masm/stubs/WTFStubs.cpp ../3rdparty/masm/stubs/WTFStubs.h
+ ../3rdparty/masm/stubs/wtf/FastAllocBase.h
+ ../3rdparty/masm/stubs/wtf/FastMalloc.h
+ ../3rdparty/masm/stubs/wtf/Noncopyable.h
+ ../3rdparty/masm/stubs/wtf/OwnPtr.h
+ ../3rdparty/masm/stubs/wtf/PassOwnPtr.h
+ ../3rdparty/masm/stubs/wtf/PassRefPtr.h
+ ../3rdparty/masm/stubs/wtf/RefCounted.h
+ ../3rdparty/masm/stubs/wtf/RefPtr.h
+ ../3rdparty/masm/stubs/wtf/TypeTraits.h
+ ../3rdparty/masm/stubs/wtf/UnusedParam.h
+ ../3rdparty/masm/stubs/wtf/Vector.h
+ ../3rdparty/masm/stubs/yarr/YarrUnicodeProperties.cpp
+ # ../3rdparty/masm/wtf/*.h special case remove
+ ../3rdparty/masm/wtf/FilePrintStream.cpp ../3rdparty/masm/wtf/FilePrintStream.h
+ ../3rdparty/masm/wtf/OSAllocator.h
+ ../3rdparty/masm/wtf/PageAllocation.h
+ ../3rdparty/masm/wtf/PageAllocationAligned.cpp ../3rdparty/masm/wtf/PageAllocationAligned.h
+ ../3rdparty/masm/wtf/PageBlock.cpp ../3rdparty/masm/wtf/PageBlock.h
+ ../3rdparty/masm/wtf/PageReservation.h
+ ../3rdparty/masm/wtf/PrintStream.cpp ../3rdparty/masm/wtf/PrintStream.h
+ ../3rdparty/masm/wtf/RawPointer.h
+ ../3rdparty/masm/yarr/Yarr.h
+ ../3rdparty/masm/yarr/YarrCanonicalizeUCS2.cpp ../3rdparty/masm/yarr/YarrCanonicalizeUCS2.h
+ ../3rdparty/masm/yarr/YarrCanonicalizeUnicode.cpp
+ ../3rdparty/masm/yarr/YarrInterpreter.cpp ../3rdparty/masm/yarr/YarrInterpreter.h
+ ../3rdparty/masm/yarr/YarrJIT.cpp ../3rdparty/masm/yarr/YarrJIT.h
+ ../3rdparty/masm/yarr/YarrParser.h
+ ../3rdparty/masm/yarr/YarrPattern.cpp ../3rdparty/masm/yarr/YarrPattern.h
+ ../3rdparty/masm/yarr/YarrSyntaxChecker.cpp ../3rdparty/masm/yarr/YarrSyntaxChecker.h
+ ../3rdparty/masm/yarr/YarrUnicodeProperties.h
+ common/qqmlapiversion_p.h
+ common/qqmljsdiagnosticmessage_p.h
+ common/qqmljsfixedpoolarray_p.h
+ common/qqmljsmemorypool_p.h
+ common/qqmljssourcelocation_p.h
+ common/qv4alloca_p.h
+ common/qv4calldata_p.h
+ common/qv4compileddata_p.h
+ common/qv4staticvalue_p.h
+ common/qv4stringtoarrayindex_p.h
+ compiler/qqmlirbuilder.cpp compiler/qqmlirbuilder_p.h
+ compiler/qv4bytecodegenerator.cpp compiler/qv4bytecodegenerator_p.h
+ compiler/qv4bytecodehandler.cpp compiler/qv4bytecodehandler_p.h
+ compiler/qv4codegen.cpp compiler/qv4codegen_p.h
+ compiler/qv4compiler.cpp compiler/qv4compiler_p.h
+ compiler/qv4compilercontext.cpp compiler/qv4compilercontext_p.h
+ compiler/qv4compilercontrolflow_p.h
+ compiler/qv4compilerglobal_p.h
+ compiler/qv4compilerscanfunctions.cpp compiler/qv4compilerscanfunctions_p.h
+ compiler/qv4instr_moth.cpp compiler/qv4instr_moth_p.h
+ compiler/qv4util_p.h
+ debugger/qqmldebug.h
+ debugger/qqmldebugconnector_p.h
+ debugger/qqmldebugserviceinterfaces_p.h
+ debugger/qqmldebugstatesdelegate_p.h
+ debugger/qqmlprofiler_p.h
+ inlinecomponentutils_p.h
+ jsapi/qjsengine.cpp jsapi/qjsengine.h jsapi/qjsengine_p.h
+ jsapi/qjsvalue.cpp jsapi/qjsvalue.h jsapi/qjsvalue_p.h
+ jsapi/qjsvalueiterator.cpp jsapi/qjsvalueiterator.h jsapi/qjsvalueiterator_p.h
+ jsruntime/qv4argumentsobject.cpp jsruntime/qv4argumentsobject_p.h
+ jsruntime/qv4arraybuffer.cpp jsruntime/qv4arraybuffer_p.h
+ jsruntime/qv4arraydata.cpp jsruntime/qv4arraydata_p.h
+ jsruntime/qv4arrayiterator.cpp jsruntime/qv4arrayiterator_p.h
+ jsruntime/qv4arrayobject.cpp jsruntime/qv4arrayobject_p.h
+ jsruntime/qv4atomics.cpp jsruntime/qv4atomics_p.h
+ jsruntime/qv4booleanobject.cpp jsruntime/qv4booleanobject_p.h
+ jsruntime/qv4compilationunitmapper.cpp jsruntime/qv4compilationunitmapper_p.h
+ jsruntime/qv4context.cpp jsruntime/qv4context_p.h
+ jsruntime/qv4dataview.cpp jsruntime/qv4dataview_p.h
+ jsruntime/qv4dateobject.cpp jsruntime/qv4dateobject_p.h
+ jsruntime/qv4debugging_p.h
+ jsruntime/qv4engine.cpp jsruntime/qv4engine_p.h
+ jsruntime/qv4enginebase_p.h
+ jsruntime/qv4errorobject.cpp jsruntime/qv4errorobject_p.h
+ jsruntime/qv4estable.cpp jsruntime/qv4estable_p.h
+ jsruntime/qv4executableallocator.cpp jsruntime/qv4executableallocator_p.h
+ jsruntime/qv4executablecompilationunit.cpp jsruntime/qv4executablecompilationunit_p.h
+ jsruntime/qv4function.cpp jsruntime/qv4function_p.h
+ jsruntime/qv4functionobject.cpp jsruntime/qv4functionobject_p.h
+ jsruntime/qv4functiontable_p.h
+ jsruntime/qv4generatorobject.cpp jsruntime/qv4generatorobject_p.h
+ jsruntime/qv4global_p.h
+ jsruntime/qv4globalobject.cpp jsruntime/qv4globalobject_p.h
+ jsruntime/qv4identifier.cpp jsruntime/qv4identifier_p.h
+ jsruntime/qv4identifiertable.cpp jsruntime/qv4identifiertable_p.h
+ jsruntime/qv4include.cpp jsruntime/qv4include_p.h
+ jsruntime/qv4internalclass.cpp jsruntime/qv4internalclass_p.h
+ jsruntime/qv4iterator.cpp jsruntime/qv4iterator_p.h
+ jsruntime/qv4jscall_p.h
+ jsruntime/qv4jsonobject.cpp jsruntime/qv4jsonobject_p.h
+ jsruntime/qv4lookup.cpp jsruntime/qv4lookup_p.h
+ jsruntime/qv4managed.cpp jsruntime/qv4managed_p.h
+ jsruntime/qv4mapiterator.cpp jsruntime/qv4mapiterator_p.h
+ jsruntime/qv4mapobject.cpp jsruntime/qv4mapobject_p.h
+ jsruntime/qv4math_p.h
+ jsruntime/qv4mathobject.cpp jsruntime/qv4mathobject_p.h
+ jsruntime/qv4memberdata.cpp jsruntime/qv4memberdata_p.h
+ jsruntime/qv4module.cpp jsruntime/qv4module_p.h
+ jsruntime/qv4numberobject.cpp jsruntime/qv4numberobject_p.h
+ jsruntime/qv4object.cpp jsruntime/qv4object_p.h
+ jsruntime/qv4objectiterator.cpp jsruntime/qv4objectiterator_p.h
+ jsruntime/qv4objectproto.cpp jsruntime/qv4objectproto_p.h
+ jsruntime/qv4persistent.cpp jsruntime/qv4persistent_p.h
+ jsruntime/qv4profiling_p.h
+ jsruntime/qv4promiseobject.cpp jsruntime/qv4promiseobject_p.h
+ jsruntime/qv4property_p.h
+ jsruntime/qv4propertykey.cpp jsruntime/qv4propertykey_p.h
+ jsruntime/qv4proxy.cpp jsruntime/qv4proxy_p.h
+ jsruntime/qv4qmlcontext.cpp jsruntime/qv4qmlcontext_p.h
+ jsruntime/qv4qobjectwrapper.cpp jsruntime/qv4qobjectwrapper_p.h
+ jsruntime/qv4reflect.cpp jsruntime/qv4reflect_p.h
+ jsruntime/qv4regexp.cpp jsruntime/qv4regexp_p.h
+ jsruntime/qv4regexpobject.cpp jsruntime/qv4regexpobject_p.h
+ jsruntime/qv4resolvedtypereference.cpp jsruntime/qv4resolvedtypereference_p.h
+ jsruntime/qv4runtime.cpp jsruntime/qv4runtime_p.h
+ jsruntime/qv4runtimeapi_p.h
+ jsruntime/qv4runtimecodegen.cpp jsruntime/qv4runtimecodegen_p.h
+ jsruntime/qv4scopedvalue_p.h
+ jsruntime/qv4script.cpp jsruntime/qv4script_p.h
+ jsruntime/qv4setiterator.cpp jsruntime/qv4setiterator_p.h
+ jsruntime/qv4setobject.cpp jsruntime/qv4setobject_p.h
+ jsruntime/qv4sparsearray.cpp jsruntime/qv4sparsearray_p.h
+ jsruntime/qv4stackframe.cpp jsruntime/qv4stackframe_p.h
+ jsruntime/qv4string.cpp jsruntime/qv4string_p.h
+ jsruntime/qv4stringiterator.cpp jsruntime/qv4stringiterator_p.h
+ jsruntime/qv4stringobject.cpp jsruntime/qv4stringobject_p.h
+ jsruntime/qv4symbol.cpp jsruntime/qv4symbol_p.h
+ jsruntime/qv4typedarray.cpp jsruntime/qv4typedarray_p.h
+ jsruntime/qv4urlobject.cpp jsruntime/qv4urlobject_p.h
+ jsruntime/qv4value.cpp jsruntime/qv4value_p.h
+ jsruntime/qv4variantobject.cpp jsruntime/qv4variantobject_p.h
+ jsruntime/qv4vme_moth.cpp jsruntime/qv4vme_moth_p.h
+ jsruntime/qv4vtable_p.h
+ memory/qv4heap_p.h
+ memory/qv4mm.cpp memory/qv4mm_p.h
+ memory/qv4mmdefs_p.h
+ memory/qv4writebarrier_p.h
+ parser/qqmljsast.cpp parser/qqmljsast_p.h
+ parser/qqmljsastfwd_p.h
+ parser/qqmljsastvisitor.cpp parser/qqmljsastvisitor_p.h
+ parser/qqmljsengine_p.cpp parser/qqmljsengine_p.h
+ parser/qqmljsglobal_p.h
+ parser/qqmljskeywords_p.h
+ parser/qqmljslexer.cpp parser/qqmljslexer_p.h
+ qml/ftw/qbitfield_p.h
+ qml/ftw/qfieldlist_p.h
+ qml/ftw/qfinitestack_p.h
+ qml/ftw/qflagpointer_p.h
+ qml/ftw/qhashedstring.cpp qml/ftw/qhashedstring_p.h
+ qml/ftw/qintrusivelist.cpp qml/ftw/qintrusivelist_p.h
+ qml/ftw/qlazilyallocated_p.h
+ qml/ftw/qlinkedstringhash_p.h
+ qml/ftw/qpodvector_p.h
+ qml/ftw/qprimefornumbits_p.h
+ qml/ftw/qqmlnullablevalue_p.h
+ qml/ftw/qqmlrefcount_p.h
+ qml/ftw/qqmlthread.cpp qml/ftw/qqmlthread_p.h
+ qml/ftw/qrecursionwatcher_p.h
+ qml/ftw/qrecyclepool_p.h
+ qml/ftw/qstringhash_p.h
+ qml/qqml.cpp qml/qqml.h
+ qml/qqmlabstractbinding.cpp qml/qqmlabstractbinding_p.h
+ qml/qqmlabstracturlinterceptor.cpp qml/qqmlabstracturlinterceptor.h
+ qml/qqmlapplicationengine.cpp qml/qqmlapplicationengine.h qml/qqmlapplicationengine_p.h
+ qml/qqmlbinding.cpp qml/qqmlbinding_p.h
+ qml/qqmlboundsignal.cpp qml/qqmlboundsignal_p.h
+ qml/qqmlboundsignalexpressionpointer_p.h
+ qml/qqmlcleanup.cpp qml/qqmlcleanup_p.h
+ qml/qqmlcomponent.cpp qml/qqmlcomponent.h qml/qqmlcomponent_p.h
+ qml/qqmlcomponentattached_p.h
+ qml/qqmlcontext.cpp qml/qqmlcontext.h qml/qqmlcontext_p.h
+ qml/qqmlcontextdata.cpp qml/qqmlcontextdata_p.h
+ qml/qqmlcustomparser.cpp qml/qqmlcustomparser_p.h
+ qml/qqmldata_p.h
+ qml/qqmldatablob.cpp qml/qqmldatablob_p.h
+ qml/qqmldelayedcallqueue.cpp qml/qqmldelayedcallqueue_p.h
+ qml/qqmldirdata.cpp qml/qqmldirdata_p.h
+ qml/qqmlengine.cpp qml/qqmlengine.h qml/qqmlengine_p.h
+ qml/qqmlenumdata_p.h
+ qml/qqmlenumvalue_p.h
+ qml/qqmlerror.cpp qml/qqmlerror.h
+ qml/qqmlexpression.cpp qml/qqmlexpression.h qml/qqmlexpression_p.h
+ qml/qqmlextensioninterface.h
+ qml/qqmlextensionplugin.cpp qml/qqmlextensionplugin.h qml/qqmlextensionplugin_p.h
+ qml/qqmlfile.cpp qml/qqmlfile.h
+ qml/qqmlfileselector.cpp qml/qqmlfileselector.h qml/qqmlfileselector_p.h
+ qml/qqmlglobal.cpp qml/qqmlglobal_p.h
+ qml/qqmlguard_p.h
+ qml/qqmlguardedcontextdata_p.h
+ qml/qqmlimport.cpp qml/qqmlimport_p.h
+ qml/qqmlincubator.cpp qml/qqmlincubator.h qml/qqmlincubator_p.h
+ qml/qqmlinfo.cpp qml/qqmlinfo.h
+ qml/qqmlirloader.cpp qml/qqmlirloader_p.h
+ qml/qqmljavascriptexpression.cpp qml/qqmljavascriptexpression_p.h
+ qml/qqmllist.cpp qml/qqmllist.h qml/qqmllist_p.h
+ qml/qqmllistwrapper.cpp qml/qqmllistwrapper_p.h
+ qml/qqmlloggingcategory.cpp qml/qqmlloggingcategory_p.h
+ qml/qqmlmetaobject.cpp qml/qqmlmetaobject_p.h
+ qml/qqmlmetatype.cpp qml/qqmlmetatype_p.h
+ qml/qqmlmetatypedata.cpp qml/qqmlmetatypedata_p.h
+ qml/qqmlmoduleregistration.cpp qml/qqmlmoduleregistration.h
+ qml/qqmlnetworkaccessmanagerfactory.cpp qml/qqmlnetworkaccessmanagerfactory.h
+ qml/qqmlnotifier.cpp qml/qqmlnotifier_p.h
+ qml/qqmlobjectcreator.cpp qml/qqmlobjectcreator_p.h
+ qml/qqmlobjectorgadget.cpp qml/qqmlobjectorgadget_p.h
+ qml/qqmlopenmetaobject.cpp qml/qqmlopenmetaobject_p.h
+ qml/qqmlparserstatus.cpp qml/qqmlparserstatus.h
+ qml/qqmlplatform.cpp qml/qqmlplatform_p.h
+ qml/qqmlprivate.h
+ qml/qqmlproperty.cpp qml/qqmlproperty.h qml/qqmlproperty_p.h
+ qml/qqmlpropertybinding.cpp qml/qqmlpropertybinding_p.h
+ qml/qqmlpropertycache.cpp qml/qqmlpropertycache_p.h
+ qml/qqmlpropertycachecreator.cpp qml/qqmlpropertycachecreator_p.h
+ qml/qqmlpropertycachemethodarguments_p.h
+ qml/qqmlpropertycachevector_p.h
+ qml/qqmlpropertydata_p.h
+ qml/qqmlpropertyindex_p.h
+ qml/qqmlpropertyresolver.cpp qml/qqmlpropertyresolver_p.h
+ qml/qqmlpropertyvalidator.cpp qml/qqmlpropertyvalidator_p.h
+ qml/qqmlpropertyvalueinterceptor.cpp qml/qqmlpropertyvalueinterceptor_p.h
+ qml/qqmlpropertyvaluesource.cpp qml/qqmlpropertyvaluesource.h
+ qml/qqmlproxymetaobject.cpp qml/qqmlproxymetaobject_p.h
+ qml/qqmlscriptblob.cpp qml/qqmlscriptblob_p.h
+ qml/qqmlscriptdata.cpp qml/qqmlscriptdata_p.h
+ qml/qqmlscriptstring.cpp qml/qqmlscriptstring.h qml/qqmlscriptstring_p.h
+ qml/qqmlsourcecoordinate_p.h
+ qml/qqmlstaticmetaobject.cpp qml/qqmlstaticmetaobject_p.h
+ qml/qqmlstringconverters.cpp qml/qqmlstringconverters_p.h
+ qml/qqmltype.cpp qml/qqmltype_p.h
+ qml/qqmltype_p_p.h
+ qml/qqmltypecompiler.cpp qml/qqmltypecompiler_p.h
+ qml/qqmltypedata.cpp qml/qqmltypedata_p.h
+ qml/qqmltypeloader.cpp qml/qqmltypeloader_p.h
+ qml/qqmltypeloaderqmldircontent.cpp qml/qqmltypeloaderqmldircontent_p.h
+ qml/qqmltypeloaderthread.cpp qml/qqmltypeloaderthread_p.h
+ qml/qqmltypemodule.cpp qml/qqmltypemodule_p.h
+ qml/qqmltypemodule_p_p.h
+ qml/qqmltypemoduleversion.cpp qml/qqmltypemoduleversion_p.h
+ qml/qqmltypenamecache.cpp qml/qqmltypenamecache_p.h
+ qml/qqmltypenotavailable.cpp qml/qqmltypenotavailable_p.h
+ qml/qqmltypewrapper.cpp qml/qqmltypewrapper_p.h
+ qml/qqmlvaluetype.cpp qml/qqmlvaluetype_p.h
+ qml/qqmlvaluetypeproxybinding.cpp qml/qqmlvaluetypeproxybinding_p.h
+ qml/qqmlvaluetypewrapper.cpp
+ qml/qqmlvme.cpp qml/qqmlvme_p.h
+ qml/qqmlvmemetaobject.cpp qml/qqmlvmemetaobject_p.h
+ qml/v8/qqmlbuiltinfunctions.cpp qml/v8/qqmlbuiltinfunctions_p.h
+ qml/v8/qv4domerrors.cpp qml/v8/qv4domerrors_p.h
+ qml/v8/qv4sqlerrors.cpp qml/v8/qv4sqlerrors_p.h
+ qmldirparser/qqmldirparser.cpp qmldirparser/qqmldirparser_p.h
+ qtqmlcompilerglobal.h qtqmlcompilerglobal_p.h
+ qtqmlglobal.h qtqmlglobal_p.h
+ types/qqmlbind.cpp types/qqmlbind_p.h
+ types/qqmlconnections.cpp types/qqmlconnections_p.h
+ util/qqmlpropertymap.cpp util/qqmlpropertymap.h
+ DEFINES
+ BUILDING_QT__
+ ENABLE_ASSEMBLER_WX_EXCLUSIVE=1
+ ENABLE_DFG_JIT=0
+ ENABLE_DFG_JIT_UTILITY_METHODS=1
+ ENABLE_JIT_CONSTANT_BLINDING=0
+ ENABLE_LLINT=0
+ JS_EXPORT_PRIVATE= # special case
+ QT_NO_FOREACH
+ QT_NO_INTEGER_EVENT_COORDINATES
+ QT_NO_URL_CAST_FROM_STRING
+ WTFInvokeCrashHook=qmlWTFInvokeCrashHook
+ WTFReportAssertionFailure=qmlWTFReportAssertionFailure
+ WTFReportAssertionFailureWithMessage=qmlWTFReportAssertionFailureWithMessage
+ WTFReportBacktrace=qmlWTFReportBacktrace
+ WTF_EXPORT_PRIVATE= # special case
+ INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_BINARY_DIR}/compiler
+ ${CMAKE_CURRENT_BINARY_DIR}/jsruntime
+ ${CMAKE_CURRENT_BINARY_DIR}/memory
+ ${CMAKE_CURRENT_BINARY_DIR}/qmldirparser
+ ../3rdparty/masm
+ ../3rdparty/masm/assembler
+ ../3rdparty/masm/disassembler
+ ../3rdparty/masm/disassembler/udis86
+ ../3rdparty/masm/jit
+ ../3rdparty/masm/runtime
+ ../3rdparty/masm/stubs
+ ../3rdparty/masm/stubs/runtime
+ ../3rdparty/masm/stubs/wtf
+ ../3rdparty/masm/wtf
+ .generated
+ compiler
+ debugger
+ jsruntime
+ memory
+ qmldirparser
+ LIBRARIES
+ Qt::CorePrivate
+ PUBLIC_LIBRARIES
+ Qt::Core
+ PRIVATE_MODULE_INTERFACE
+ Qt::CorePrivate
+)
+
+# special case begin remove the block, handled manually
+# QLALR Grammars:
+#qt_process_qlalr(
+# Qml
+# parser/qqmljs.g
+# ""
+#)
+
+qt_declarative_write_tag_header(Qml)
+set(_qt_qlalr_flags "--no-debug" "--qt")
+qt_process_qlalr(Qml "${CMAKE_CURRENT_SOURCE_DIR}/parser/qqmljs.g" "${_qt_qlalr_flags}")
+qt_declarative_generate_reg_exp_jit_tables(Qml)
+# special case end
+
+#### Keys ignored in scope 1:.:.:qml.pro:<TRUE>:
+# QMLTYPES_FILENAME = "plugins.qmltypes"
+# QMLTYPES_INSTALL_DIR = "$$[QT_INSTALL_QML]/QtQml"
+# QML_IMPORT_NAME = "QtQml"
+# QML_IMPORT_VERSION = "$$QT_VERSION"
+
+## Scopes:
+#####################################################################
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_network
+ SOURCES
+ qml/qqmltypeloadernetworkreplyproxy.cpp qml/qqmltypeloadernetworkreplyproxy_p.h
+ PUBLIC_LIBRARIES
+ Qt::Network
+)
+
+qt_extend_target(Qml CONDITION MSVC AND (TEST_architecture_arch STREQUAL "i386")
+ LINK_OPTIONS
+ "/BASE:0x66000000"
+)
+
+qt_extend_target(Qml CONDITION MSVC
+ DEFINES
+ _CRT_SECURE_NO_WARNINGS
+)
+
+qt_extend_target(Qml CONDITION WIN32 AND NOT WINRT
+ SOURCES
+ ../3rdparty/masm/wtf/OSAllocatorWin.cpp
+ PUBLIC_LIBRARIES
+ shell32
+)
+
+#### Keys ignored in scope 6:.:.:qml.pro:solaris-cc_x_:
+# QMAKE_CXXFLAGS_RELEASE = "--O2"
+
+qt_extend_target(Qml CONDITION GCC AND (TEST_architecture_arch STREQUAL "mips")
+ COMPILE_OPTIONS
+ -fno-reorder-blocks
+)
+
+qt_extend_target(Qml CONDITION EXISTS "qqml_enable_gcov"
+ LIBRARIES
+ gcov
+ COMPILE_OPTIONS
+ -fno-elide-constructors
+ -fprofile-arcs
+ -ftest-coverage
+)
+
+qt_extend_target(Qml CONDITION release AND MSVC AND (QT_CL_MAJOR_VERSION EQUAL 19) AND (QT_CL_MINOR_VERSION EQUAL 00) AND (QT_CL_PATCH_VERSION GREATER 24212)
+ COMPILE_OPTIONS
+ -d2SSAOptimizer-
+)
+
+#### Keys ignored in scope 10:.:.:qml.pro:ICC:
+# WERROR = "-ww2415"
+
+#### Keys ignored in scope 11:.:.:qml.pro:(QT_CLANG_MAJOR_VERSION GREATER 3) OR (QT_CLANG_MINOR_VERSION GREATER 3) OR (QT_APPLE_CLANG_MAJOR_VERSION GREATER 5) OR ( (QT_APPLE_CLANG_MAJOR_VERSION EQUAL 5) AND (QT_APPLE_CLANG_MINOR_VERSION GREATER 0) ):
+# WERROR = "-Wno-error=unused-const-variable"
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_jit
+ SOURCES
+ jit/qv4assemblercommon.cpp jit/qv4assemblercommon_p.h
+ jit/qv4baselineassembler.cpp jit/qv4baselineassembler_p.h
+ jit/qv4baselinejit.cpp jit/qv4baselinejit_p.h
+ INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_BINARY_DIR}/jit
+ jit
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_animation
+ SOURCES
+ animations/qabstractanimationjob.cpp animations/qabstractanimationjob_p.h
+ animations/qanimationgroupjob.cpp animations/qanimationgroupjob_p.h
+ animations/qanimationjobutil_p.h
+ animations/qcontinuinganimationgroupjob.cpp animations/qcontinuinganimationgroupjob_p.h
+ animations/qparallelanimationgroupjob.cpp animations/qparallelanimationgroupjob_p.h
+ animations/qpauseanimationjob.cpp animations/qpauseanimationjob_p.h
+ animations/qsequentialanimationgroupjob.cpp animations/qsequentialanimationgroupjob_p.h
+ types/qqmltimer.cpp types/qqmltimer_p.h
+ INCLUDE_DIRECTORIES
+ animations
+)
+
+#### Keys ignored in scope 17:.:common:common/common.pri:NOT build_pass:
+# compile_hash_contents = "// Generated file, DO NOT EDIT" "$${LITERAL_HASH}define QML_COMPILE_HASH "$$QML_COMPILE_HASH"" "$${LITERAL_HASH}define QML_COMPILE_HASH_LENGTH $$str_size($$QML_COMPILE_HASH)"
+# tag = <EMPTY>
+# tagFile = "$$PWD/../../.tag"
+
+#### Keys ignored in scope 18:.:common:common/common.pri:EXISTS _ss_tagFile:
+# QMAKE_INTERNAL_INCLUDED_FILES = "$$tagFile"
+# tag = "$$cat($$tagFile, singleline)"
+
+#### Keys ignored in scope 19:.:common:common/common.pri:NOT tag___equals____ss_{LITERAL_DOLLAR}Format AND %H_ss_{LITERAL_DOLLAR}:
+# QML_COMPILE_HASH = "$$tag"
+
+#### Keys ignored in scope 21:.:common:common/common.pri:EXISTS _ss_PWD/../../.git:
+# QML_COMPILE_HASH = "$$commit"
+# commit = "$$system(git rev-parse HEAD)"
+
+qt_extend_target(Qml CONDITION GCC AND QT_COMPILER_VERSION_MAJOR STREQUAL 5
+ COMPILE_OPTIONS
+ -fno-strict-aliasing
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_debug
+ SOURCES
+ debugger/qqmlabstractprofileradapter.cpp debugger/qqmlabstractprofileradapter_p.h
+ debugger/qqmlconfigurabledebugservice_p.h
+ debugger/qqmldebug.cpp
+ debugger/qqmldebugconnector.cpp
+ debugger/qqmldebugpluginmanager_p.h
+ debugger/qqmldebugserver_p.h
+ debugger/qqmldebugserverconnection_p.h
+ debugger/qqmldebugservice.cpp debugger/qqmldebugservice_p.h
+ debugger/qqmldebugservicefactory_p.h
+ debugger/qqmldebugserviceinterfaces.cpp
+ debugger/qqmlprofiler.cpp
+ debugger/qqmlprofilerdefinitions_p.h
+ jsruntime/qv4profiling.cpp
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_sequence_object
+ SOURCES
+ jsruntime/qv4sequenceobject.cpp jsruntime/qv4sequenceobject_p.h
+)
+
+qt_extend_target(Qml CONDITION UNIX
+ SOURCES
+ jsruntime/qv4compilationunitmapper_unix.cpp
+ jsruntime/qv4functiontable_unix.cpp
+)
+
+qt_extend_target(Qml CONDITION WIN32
+ SOURCES
+ jsruntime/qv4compilationunitmapper_win.cpp
+ DEFINES
+ NOMINMAX
+)
+
+qt_extend_target(Qml CONDITION (TEST_architecture_arch STREQUAL "x86_64") AND WIN32 AND NOT WINRT
+ SOURCES
+ jsruntime/qv4functiontable_win64.cpp
+)
+
+qt_extend_target(Qml CONDITION WIN32 AND (WINRT OR NOT (TEST_architecture_arch STREQUAL "x86_64"))
+ SOURCES
+ jsruntime/qv4functiontable_noop.cpp
+)
+
+qt_extend_target(Qml CONDITION valgrind
+ DEFINES
+ V4_USE_VALGRIND
+)
+
+qt_extend_target(Qml CONDITION heaptrack
+ DEFINES
+ V4_USE_HEAPTRACK
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_xml_http_request
+ SOURCES
+ qml/qqmlxmlhttprequest.cpp qml/qqmlxmlhttprequest_p.h
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_locale
+ SOURCES
+ qml/qqmllocale.cpp qml/qqmllocale_p.h
+)
+
+qt_extend_target(Qml CONDITION ANDROID
+ DEFINES
+ LIBS_SUFFIX="_${CMAKE_SYSTEM_PROCESSOR}.so"
+)
+
+qt_extend_target(Qml CONDITION hpux-_x_ OR solaris-_x_ OR (QT_FEATURE_clock_gettime AND linux-_x_)
+ LIBRARIES
+ rt
+)
+
+qt_extend_target(Qml CONDITION QT_FEATURE_qml_itemmodel
+ SOURCES
+ types/qqmlmodelindexvaluetype.cpp types/qqmlmodelindexvaluetype_p.h
+)
+
+qt_extend_target(Qml CONDITION disassembler AND ((TEST_architecture_arch STREQUAL "i386") OR (TEST_architecture_arch STREQUAL "x86_64"))
+ DEFINES
+ WTF_USE_UDIS86=1
+)
+
+qt_extend_target(Qml CONDITION (TEST_architecture_arch STREQUAL "arm") AND disassembler
+ DEFINES
+ WTF_USE_ARMV7_DISASSEMBLER=1
+)
+
+qt_extend_target(Qml CONDITION (TEST_architecture_arch STREQUAL "arm64") AND disassembler
+ DEFINES
+ WTF_USE_ARM64_DISASSEMBLER=1
+)
+
+qt_extend_target(Qml CONDITION (TEST_architecture_arch STREQUAL "mips") AND disassembler
+ DEFINES
+ WTF_USE_MIPS32_DISASSEMBLER=1
+)
+
+qt_extend_target(Qml CONDITION NOT disassembler
+ DEFINES
+ WTF_USE_UDIS86=0
+)
+
+qt_extend_target(Qml CONDITION CMAKE_BUILD_TYPE STREQUAL Release
+ DEFINES
+ NDEBUG
+)
+
+qt_extend_target(Qml CONDITION GCC AND QT_COMPILER_VERSION_MAJOR STRGREATER 6 AND NOT CLANG AND NOT ICC
+ COMPILE_OPTIONS
+ -Wno-expansion-to-defined
+)
+
+#### Keys ignored in scope 65:.:../3rdparty/masm:../3rdparty/masm/masm-defs.pri:(QT_COMPILER_VERSION_MAJOR STRGREATER 6):
+# QMAKE_CXXFLAGS_WARN_ON = "-Wno-expansion-to-defined"
+
+qt_extend_target(Qml CONDITION WINRT
+ SOURCES
+ ../3rdparty/masm/wtf/OSAllocatorWinRT.cpp
+)
+
+qt_extend_target(Qml CONDITION INTEGRITY
+ SOURCES
+ ../3rdparty/masm/wtf/OSAllocatorIntegrity.cpp
+)
+
+qt_extend_target(Qml CONDITION UNIX AND NOT INTEGRITY AND NOT WINRT
+ SOURCES
+ ../3rdparty/masm/wtf/OSAllocatorPosix.cpp
+)
+
+qt_extend_target(Qml CONDITION DEFINES___contains___WTF_USE_UDIS86=1
+ SOURCES
+ ../3rdparty/masm/disassembler/udis86/udis86.c
+ ../3rdparty/masm/disassembler/udis86/udis86_decode.c
+ ../3rdparty/masm/disassembler/udis86/udis86_input.c
+ ../3rdparty/masm/disassembler/udis86/udis86_itab_holder.c
+ ../3rdparty/masm/disassembler/udis86/udis86_syn.c
+ ../3rdparty/masm/disassembler/udis86/udis86_syn-att.c
+ ../3rdparty/masm/disassembler/udis86/udis86_syn-intel.c
+)
+
+#### Keys ignored in scope 73:.:../3rdparty/masm:../3rdparty/masm/masm.pri:DEFINES___contains___WTF_USE_UDIS86=1:
+# ITAB = "$$PWD/disassembler/udis86/optable.xml"
+# QMAKE_EXTRA_COMPILERS = "udis86"
+# QMAKE_EXTRA_TARGETS = "udis86_tab_cfile"
+# udis86.CONFIG = "no_link"
+# udis86.commands = "python" "$$PWD/disassembler/udis86/itab.py" "${QMAKE_FILE_IN}"
+# udis86.input = "ITAB"
+# udis86.output = "udis86_itab.h"
+# udis86_tab_cfile.depends = "udis86_itab.h"
+# udis86_tab_cfile.target = "$$OUT_PWD/udis86_itab.c"
+
+#### Keys ignored in scope 75:.:../3rdparty/masm:../3rdparty/masm/masm.pri:(CMAKE_BUILD_TYPE STREQUAL Debug):
+# GENERATEDDIR = "$$GENERATEDDIR/debug"
+
+#### Keys ignored in scope 76:.:../3rdparty/masm:../3rdparty/masm/masm.pri:else:
+# GENERATEDDIR = "$$GENERATEDDIR/release"
+
+qt_extend_target(Qml CONDITION (NOT c++11 AND NOT ICC) AND (CLANG)
+ COMPILE_OPTIONS
+ -Wno-c++0x-extensions
+ -Wno-c++11-extensions
+)
+
+qt_extend_target(Qml CONDITION (((NOT c++11 AND NOT ICC) AND (NOT (CLANG))) AND (GCC)) AND ((QT_COMPILER_VERSION_MAJOR STRGREATER 4) OR (QT_COMPILER_VERSION_MINOR STRGREATER 5))
+ COMPILE_OPTIONS
+ -Wno-c++0x-compat
+)
+
+
+qt_create_tracepoints(Qml qtqml.tracepoints)
+qt_add_docs(Qml
+ doc/qtqml.qdocconf
+)
+
+
+set_target_properties(Qml PROPERTIES
+ QT_QML_MODULE_INSTALL_QMLTYPES TRUE
+ QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_URI QtQml
+ QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/QtQml"
+)
+
+qt6_qml_type_registration(Qml)
+
+include(Qt6QmlBuildInternals.cmake) # special case
diff --git a/src/qml/Qt6QmlBuildInternals.cmake b/src/qml/Qt6QmlBuildInternals.cmake
new file mode 100644
index 0000000000..a17cae8bf8
--- /dev/null
+++ b/src/qml/Qt6QmlBuildInternals.cmake
@@ -0,0 +1,174 @@
+#
+# QtDeclarative Specific extensions
+#
+
+include_guard(GLOBAL)
+
+# This function creates a CMake target for qml modules. It will also make
+# sure that if no C++ source are present, that qml files show up in the project
+# in an IDE. Finally, it will also create a custom ${target}_qmltypes which
+# can be used to generate the respective plugin.qmltypes file.
+#
+# CPP_PLUGIN: Whether this qml module has any c++ source files.
+# URI: Module's uri.
+# TARGET_PATH: Expected installation path for the Qml Module. Equivalent
+# to the module's URI where '.' is replaced with '/'. Use this to override the
+# default substitution pattern.
+# VERSION: Version of the qml module
+# QML_PLUGINDUMP_DEPENDENCIES: Path to a dependencies.json file to be consumed
+# with the ${target}_qmltypes target (optional)
+# SKIP_TYPE_REGISTRATION: All qml files are expected to be registered by the
+# c++ plugin code.
+#
+function(qt_add_qml_module target)
+
+ set(qml_module_optional_args
+ GENERATE_QMLTYPES
+ DESIGNER_SUPPORTED
+ DO_NOT_INSTALL
+ SKIP_TYPE_REGISTRATION
+ )
+
+ set(qml_module_single_args
+ URI
+ TARGET_PATH
+ VERSION
+ QML_PLUGINDUMP_DEPENDENCIES
+ CLASSNAME
+ )
+
+ set(qml_module_multi_args
+ IMPORTS
+ TYPEINFO
+ DEPENDENCIES
+ )
+
+ qt_parse_all_arguments(arg "qt_add_qml_module"
+ "${__qt_add_plugin_optional_args};${qml_module_optional_args}"
+ "${__qt_add_plugin_single_args};${qml_module_single_args}"
+ "${__qt_add_plugin_multi_args};${qml_module_multi_args}" ${ARGN})
+
+ if (NOT arg_URI)
+ message(FATAL_ERROR "qt_add_qml_module called without specifying the module's uri. Please specify one using the URI parameter.")
+ endif()
+
+ set(target_path ${arg_TARGET_PATH})
+
+ if (NOT arg_VERSION)
+ message(FATAL_ERROR "qt_add_qml_module called without specifying the module's import version. Please specify one using the VERSION parameter.")
+ endif()
+
+ if (NOT arg_TARGET_PATH)
+ string(REPLACE "." "/" arg_TARGET_PATH ${arg_URI})
+ endif()
+
+ qt_remove_args(plugin_args
+ ARGS_TO_REMOVE
+ ${target}
+ ${qml_module_multi_args}
+ ${qml_module_single_args}
+ ALL_ARGS
+ ${__qt_add_plugin_optional_args}
+ ${__qt_add_plugin_single_args}
+ ${qml_module_single_args}
+ ${__qt_add_plugin_multi_args}
+ ${qml_module_multi_args}
+ ARGS
+ ${ARGV}
+ )
+
+ # If we have no sources, but qml files, create a custom target so the
+ # qml file will be visibile in an IDE.
+ if (arg_SOURCES)
+ qt_add_plugin(${target}
+ TYPE
+ qml_plugin
+ QML_TARGET_PATH
+ "${arg_TARGET_PATH}"
+ ${plugin_args}
+ )
+ endif()
+
+
+ if (arg_CPP_PLUGIN)
+ set(no_create_option DO_NOT_CREATE_TARGET)
+ endif()
+
+ if (arg_CLASSNAME)
+ set(classname_arg CLASSNAME ${arg_CLASSNAME})
+ endif()
+
+ if (arg_DESIGNER_SUPPORTED)
+ set(designer_supported_arg DESIGNER_SUPPORTED)
+ endif()
+
+ if (arg_SKIP_TYPE_REGISTRATION)
+ set(skip_registration_arg SKIP_TYPE_REGISTRATION)
+ endif()
+
+ if (arg_GENERATE_QMLTYPES)
+ set(generate_qmltypes_arg GENERATE_QMLTYPES)
+ endif()
+
+ qt_path_join(qml_module_install_dir ${QT_INSTALL_DIR} "${INSTALL_QMLDIR}/${arg_TARGET_PATH}")
+
+ qt6_add_qml_module(${target}
+ ${designer_supported_arg}
+ ${no_create_option}
+ ${skip_registration_arg}
+ ${classname_arg}
+ ${generate_qmltypes_arg}
+ RESOURCE_PREFIX "/qt-project.org/imports"
+ TARGET_PATH ${arg_TARGET_PATH}
+ URI ${arg_URI}
+ VERSION ${arg_VERSION}
+ QML_FILES ${arg_QML_FILES}
+ IMPORTS "${arg_IMPORTS}"
+ TYPEINFO "${arg_TYPEINFO}"
+ DO_NOT_INSTALL_METADATA
+ DO_NOT_CREATE_TARGET
+ INSTALL_QML_FILES
+ INSTALL_LOCATION "${qml_module_install_dir}"
+ DEPENDENCIES ${arg_DEPENDENCIES}
+ RESOURCE_EXPORT "${INSTALL_CMAKE_NAMESPACE}${target}Targets"
+ )
+
+ get_target_property(qmldir_file ${target} QT_QML_MODULE_QMLDIR_FILE)
+ get_target_property(plugin_types ${target} QT_QML_MODULE_PLUGIN_TYPES_FILE)
+ set(files_to_install)
+ if (EXISTS ${plugin_types})
+ list(APPEND files_to_install ${plugin_types})
+ qt_copy_or_install(FILES ${plugin_types}
+ DESTINATION "${qml_module_install_dir}"
+ )
+
+ if(QT_WILL_INSTALL)
+ # plugin.qmltypes when present should also be copied to the
+ # cmake binary dir when doing prefix builds
+ file(COPY ${plugin_types}
+ DESTINATION "${QT_BUILD_DIR}/${INSTALL_QMLDIR}/${arg_TARGET_PATH}"
+ )
+ endif()
+ endif()
+
+ list(APPEND files_to_install ${qmldir_file})
+ if (QT_WILL_INSTALL)
+ install(FILES ${files_to_install} DESTINATION ${qml_module_install_dir})
+ endif()
+
+ set(copy_destination "${QT_BUILD_DIR}/${INSTALL_QMLDIR}/${arg_TARGET_PATH}")
+ foreach(file IN LISTS files_to_install)
+ get_filename_component(file_name "${file}" NAME)
+ add_custom_command(TARGET ${target} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${file}"
+ "${copy_destination}/${file_name}"
+ COMMENT "Copying ${file} to ${copy_destination}"
+ )
+ endforeach()
+endfunction()
+
+function(add_qml_module)
+ qt_add_qml_module(${ARGV})
+endfunction()
+
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
new file mode 100644
index 0000000000..9a7fdb6fda
--- /dev/null
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -0,0 +1,610 @@
+#
+# Q6QmlMacros
+#
+
+#
+# Create a Qml Module. Arguments:
+#
+# URI: Declares the module identifier of the module. The module identifier is
+# the (dotted URI notation) identifier for the module, which must match the
+# module's install path. (REQUIRED)
+#
+# VERSION: The module's version. (REQUIRED)
+#
+# TARGET_PATH: Overwrite the generated target path. By default the target path
+# is generated from the URI by replacing the '.' with a '/'. However, under
+# certain circumstance this may not be enough. Use this argument to provide
+# a replacement. (OPTIONAL)
+#
+# RESOURCE_PREFIX: Resource Prefix to be used when generating a static library.
+# When building a static library, the qmldir file is embedded into the library
+# using rcc. It is is also used by the Qt Quick Compiler to embed compiled
+# Qml files into a shared or static library. If none is supplied we will
+# generate the following prefix: /org.qt-project/imports/${target_path}.
+# (OPTIONAL)
+#
+# OUTPUT_DIRECTORY: If the module is not to be build under
+# ${CMAKE_CURRENT_BINARY_DIR}. This ensures the qmldir file is copied to the
+# right location. (OPTIONAL)
+#
+# INSTALL_LOCATION: Intended installation directory for this module. If no
+# value is supplied, the default installation path will be ${INSTALL_QMLDIR}.
+# (OPTIONAL).
+#
+# DO_NOT_INSTALL_METADATA: When present, will not install the supporting files.
+#
+# INSTALL_QML_FILES: When present, will install the qml files along side the
+# plugin.
+#
+# SOURCES: List of C++ sources. (OPTIONAL)
+#
+# DEPENDENCIES: List of QML Module dependencies and their versions. The module
+# and its version must be separated via a slash(/). E.g. QtQuick/2.0
+#
+# QML_FILES: List of Qml files. See qt6_target_qml_files for more information
+# on how to specify additional properties on qml files. (OPTIONAL)
+#
+# CLASSNAME: Provides the class name of the C++ plugin used by the module. This
+# information is required for all the QML modules that depend on a C++ plugin
+# for additional functionality. Qt Quick applications built with static
+# linking cannot resolve the module imports without this information.
+# (REQUIRED for static targets)
+#
+# DESIGNER_SUPPORTED: Specify this argument if the plugin is supported by Qt
+# Quick Designer. By default, the plugin will not be supported. (OPTIONAL)
+#
+# TYPEINFO: Path to a file which declares a type description file for the module
+# that can be read by QML tools such as Qt Creator to access information about
+# the types defined by the module's plugins. (OPTIONAL)
+#
+# IMPORTS: List of other Qml Modules that this module imports. (OPTIONAL)
+#
+# RESOURCE_EXPORT: In static builds, when Qml files are processed via the Qt
+# Quick Compiler generate a separate static library that will be linked in
+# as an Interface. Supply an output variable to perform any custom actions
+# on these extra generated targets.
+#
+# SKIP_TYPE_REGISTRATION: When present will cause the generated qmldir file
+# to not list any qml types. These are expected to be registered by the
+# c++ plugin code instead.
+#
+
+function(qt6_add_qml_module target)
+
+ set(args_optional
+ GENERATE_QMLTYPES
+ DESIGNER_SUPPORTED
+ DO_NOT_INSTALL_METADATA
+ SKIP_TYPE_REGISTRATION
+ INSTALL_QML_FILES
+ )
+
+ if (QT_BUILDING_QT)
+ list(APPEND args_optional DO_NOT_CREATE_TARGET)
+ endif()
+
+ set(args_single
+ RESOURCE_PREFIX
+ URI
+ TARGET_PATH
+ VERSION
+ OUTPUT_DIRECTORY
+ INSTALL_LOCATION
+ CLASSNAME
+ TYPEINFO
+ RESOURCE_EXPORT
+ )
+
+ set(args_multi
+ SOURCES
+ QML_FILES
+ IMPORTS
+ DEPENDENCIES
+ )
+
+ cmake_parse_arguments(arg
+ "${args_optional}"
+ "${args_single}"
+ "${args_multi}"
+ ${ARGN}
+ )
+
+ if (NOT arg_URI)
+ message(FATAL_ERROR "qt6_add_qml_module called without a module URI. Please specify one using the URI argument.")
+ endif()
+
+ if (NOT arg_VERSION)
+ message(FATAL_ERROR "qt6_add_qml_module called without a module version. Please specify one using the VERSION argument.")
+ endif()
+
+ if (NOT "${arg_VERSION}" MATCHES "[0-9]+\\.[0-9]+")
+ message(FATAL_ERROR "qt6_add_qml_module called with an invalid version argument: '${arg_VERSION}'. Expected version style: VersionMajor.VersionMinor.")
+ endif()
+
+ if (NOT BUILD_SHARED_LIBS AND NOT arg_CLASSNAME)
+ message(FATAL_ERROR "qt6_add_qml_module Static builds of Qml modules require a class name, none was provided. Please specify one using the CLASSNAME argument.")
+ endif()
+
+ if (arg_DO_NOT_CREATE_TARGET AND NOT TARGET ${target})
+ message(FATAL_ERROR "qt6_add_qml_module called with DO_NOT_CREATE_TARGET, but the given target '${target}' is not a cmake target")
+ endif()
+
+ if (arg_DO_NOT_CREATE_TARGET)
+ get_target_property(target_type ${target} TYPE)
+ if (target_type STREQUAL "STATIC_LIBRARY")
+ set(is_static TRUE)
+ elseif(target_type STREQUAL "MODULE_LIBRARY")
+ set(is_static FALSE)
+ else()
+ message(FATAL_ERROR "qt6_add_qml_module called with DO_NOT_CREATE_TARGET, but target '${target}' is neither a static or a module library.")
+ endif()
+ else()
+ if(NOT BUILD_SHARED_LIBS)
+ add_library(${target} STATIC)
+ set(is_static TRUE)
+ else()
+ add_library(${target} MODULE)
+ set(is_static FALSE)
+ endif()
+ endif()
+
+ if (NOT arg_TARGET_PATH)
+ string(REPLACE "." "/" arg_TARGET_PATH ${arg_URI})
+ endif()
+
+ if (NOT arg_RESOURCE_PREFIX)
+ set(arg_RESOURCE_PREFIX "/org.qt-project/imports")
+ endif()
+
+ if (NOT arg_INSTALL_LOCATION)
+ set(arg_INSTALL_LOCATION "${INSTALL_QMLDIR}/${arg_TARGET_PATH}")
+ endif()
+ if (DEFINED QT_WILL_INSTALL AND NOT QT_WILL_INSTALL
+ AND NOT IS_ABSOLUTE "${arg_INSTALL_LOCATION}")
+ set(arg_INSTALL_LOCATION "${QT_BUILD_DIR}/${arg_INSTALL_LOCATION}")
+ endif()
+
+ set_target_properties(${target}
+ PROPERTIES
+ QT_QML_MODULE_TARGET_PATH ${arg_TARGET_PATH}
+ QT_QML_MODULE_URI ${arg_URI}
+ QT_RESOURCE_PREFIX ${arg_RESOURCE_PREFIX}/${arg_TARGET_PATH}
+ QT_QML_MODULE_VERSION ${arg_VERSION}
+ QT_QML_MODULE_INSTALL_DIR ${arg_INSTALL_LOCATION}
+ QT_QML_MODULE_RESOURCE_EXPORT "${arg_RESOURCE_EXPORT}"
+ )
+
+ if (arg_OUTPUT_DIRECTORY AND NOT DO_NOT_CREATE_TARGET)
+ set_target_properties(${target}
+ PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY ${arg_OUTPUT_DIRECTORY}
+ ARCHIVE_OUTPUT_DIRECTORY ${arg_OUTPUT_DIRECTORY}
+ )
+ endif()
+ if (arg_OUTPUT_DIRECTORY)
+ set(target_output_dir ${arg_OUTPUT_DIRECTORY})
+ else()
+ if(is_static)
+ get_target_property(target_output_dir ${target} ARCHIVE_OUTPUT_DIRECTORY)
+ else()
+ get_target_property(target_output_dir ${target} LIBRARY_OUTPUT_DIRECTORY)
+ endif()
+ endif()
+
+ if (arg_INSTALL_QML_FILES)
+ set_target_properties(${target} PROPERTIES QT_QML_MODULE_INSTALL_QML_FILES TRUE)
+ endif()
+
+ if (arg_SKIP_TYPE_REGISTRATION)
+ set_target_properties(${target} PROPERTIES QT_QML_MODULE_SKIP_TYPE_REGISTRATION TRUE)
+ endif()
+
+ if (arg_SOURCES)
+ target_sources(${target} PRIVATE ${arg_SOURCES})
+ endif()
+
+ # Tracker so we can generate unique resource names for multiple
+ # target_qml_files() calls.
+ set_target_properties(${target} PROPERTIES QT6_QML_MODULE_ADD_QML_FILES_COUNT 1)
+
+ # Generate qmldir file
+ set(qmldir_file "${CMAKE_CURRENT_BINARY_DIR}/qmldir")
+ set_target_properties(${target} PROPERTIES QT_QML_MODULE_QMLDIR_FILE ${qmldir_file})
+ set(qmldir_file_contents "module ${arg_URI}\n")
+ string(APPEND qmldir_file_contents "plugin ${target}\n")
+ if (arg_CLASSNAME)
+ string(APPEND qmldir_file_contents "classname ${arg_CLASSNAME}\n")
+ endif()
+ if (arg_DESIGNER_SUPPORTED)
+ string(APPEND qmldir_file_contents "designersupported\n")
+ endif()
+ if (arg_TYPEINFO)
+ string(APPEND qmldir_file_contents "typeinfo ${arg_TYPEINFO}\n")
+ else()
+ # This always need to be written out since at the moment we have cases
+ # where qmltyperegistrar is not run with the plugin but on a module
+ # e.g: src/qml generates the qmltypes for src/imports/qtqml.
+ # When this has been fixed/standardized we should move this to
+ # qt6_qml_type_registration() so that it is written out when the
+ # plugins.qmltypes is actually generated.
+ string(APPEND qmldir_file_contents "typeinfo plugins.qmltypes\n")
+ endif()
+ foreach(import IN LISTS arg_IMPORTS)
+ string(APPEND qmldir_file_contents "import ${import}\n")
+ endforeach()
+
+ foreach(dependency IN LISTS arg_DEPENDENCIES)
+ string(FIND ${dependency} "/" slash_position REVERSE)
+ if (slash_position EQUAL -1)
+ message(FATAL_ERROR "Dependencies should follow the format 'ModuleName/VersionMajor.VersionMinor'")
+ endif()
+ string(SUBSTRING ${dependency} 0 ${slash_position} dep_module)
+ math(EXPR slash_position "${slash_position} + 1")
+ string(SUBSTRING ${dependency} ${slash_position} -1 dep_version)
+ if (NOT dep_version MATCHES "[0-9]+\\.[0-9]+")
+ message(FATAL_ERROR "Invalid module dependency version number. Expected VersionMajor.VersionMinor.")
+ endif()
+ string(APPEND qmldir_file_contents "depends ${dep_module} ${dep_version}\n")
+ endforeach()
+
+ file(WRITE ${qmldir_file} ${qmldir_file_contents})
+
+ # Process qml files
+ if (arg_QML_FILES)
+ qt6_target_qml_files(${target} FILES ${arg_QML_FILES})
+ endif()
+
+ # Embed qmldir in static builds
+ if (is_static)
+ string(REPLACE "/" "_" qmldir_resource_name ${arg_TARGET_PATH})
+ string(APPEND qmldir_resource_name "_qmldir")
+
+ set_source_files_properties("${qmldir_file}"
+ PROPERTIES QT_RESOURCE_ALIAS "qmldir"
+ )
+
+ set(resource_target "Foo")
+ QT6_ADD_RESOURCES(${target} ${qmldir_resource_name}
+ PREFIX ${target_resource_prefix}
+ FILES "${qmldir_file}"
+ OUTPUT_TARGETS resource_targets
+ )
+
+ if (resource_targets AND arg_RESOURCE_EXPORT)
+ install(TARGETS ${resource_targets}
+ EXPORT "${arg_RESOURCE_EXPORT}"
+ DESTINATION ${arg_INSTALL_LOCATION}
+ )
+ endif()
+ else()
+ # Copy QMLDIR file to build directory
+ add_custom_command(TARGET ${target} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${qmldir_file}
+ ${target_output_dir}
+ )
+
+ # Install QMLDIR file
+ if (NOT DO_NOT_INSTALL_METADATA)
+ install(FILES ${qmldir_file}
+ DESTINATION ${arg_INSTALL_LOCATION}
+ )
+ endif()
+ endif()
+
+ # Install and Copy plugin.qmltypes if exists
+ set(target_plugin_qmltypes "${CMAKE_CURRENT_SOURCE_DIR}/plugins.qmltypes")
+ if (EXISTS ${target_plugin_qmltypes})
+ set_target_properties(${target}
+ PROPERTIES QT_QML_MODULE_PLUGIN_TYPES_FILE "${target_plugin_qmltypes}"
+ )
+ file(APPEND ${qmldir_file} "typeinfo plugins.qmltypes\n")
+ if (NOT arg_DO_NOT_INSTALL_METADATA)
+ install(FILES ${target_plugin_qmltypes}
+ DESTINATION ${arg_INSTALL_LOCATION}
+ )
+ endif()
+
+ add_custom_command(TARGET ${target} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${target_plugin_qmltypes}
+ ${target_output_dir}
+ )
+ endif()
+
+ # Copy/Install type info file
+ if (EXISTS ${arg_TYPEINFO})
+ if (NOT arg_DO_NOT_INSTALL_METADATA)
+ install(FILES ${arg_TYPEINFO}
+ DESTINATION ${arg_INSTALL_LOCATION}
+ )
+ endif()
+
+ add_custom_command(TARGET ${target} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy
+ ${arg_TYPEINFO}
+ ${target_output_dir}
+ )
+ endif()
+
+ # Generate meta types data
+ if (arg_GENERATE_QMLTYPES)
+ qt6_qml_type_registration(${target})
+ endif()
+endfunction()
+
+
+#
+# Add Qml files (.qml,.js,.mjs) to a Qml module. This will also append the
+# qml files to the qmldir file of the module. Two source file properties can
+# be used to control the generated qmldir entry.
+#
+# QT_QML_SOURCE_VERSION: Version for this qml file. If not present the module
+# version will be used.
+# QT_QML_SOURCE_TYPENAME: Override the file's type name. If not present the
+# type name will be deduced using the file's basename.
+# QT_QML_SINGLETON_TYPE: Set to true if this qml file contains a singleton
+# type.
+# QT_QML_INTERNAL_TYPE: When set to true, the type specified by
+# QT_QML_SOURCE_TYPENAME will not be available to users of this module.
+# QT_QML_SKIP_QMLDIR_ENTRY: When set to true, no qmldir entry will be created for
+# the source file. Useful if a file needs to be installed (like a private JS
+# file) but does not expose a public type.
+#
+# e.g.:
+# set_source_files_properties(my_qml_file.qml
+# PROPERTIES
+# QT_QML_SOURCE_VERSION 2.0
+# QT_QML_SOURCE_TYPENAME MyQmlFile
+#
+# qt6_target_qml_files(my_qml_module
+# FILES
+# my_qml_file.qml
+# )
+#
+# Will produce the following entry in the qmldir file
+#
+# MyQmlFile 2.0 my_qml_file.qml
+#
+#
+function(qt6_target_qml_files target)
+
+ cmake_parse_arguments(arg "" "" "FILES" ${ARGN})
+ get_target_property(resource_count ${target} QT6_QML_MODULE_ADD_QML_FILES_COUNT)
+ get_target_property(qmldir_file ${target} QT_QML_MODULE_QMLDIR_FILE)
+ get_target_property(install_qml_files ${target} QT_QML_MODULE_INSTALL_QML_FILES)
+ if (NOT qmldir_file)
+ message(FATAL_ERROR "qt6_target_qml_file: ${target} is not a Qml module")
+ endif()
+
+ if (NOT arg_FILES)
+ return()
+ endif()
+ math(EXPR new_count "${resource_count} + 1")
+ set_target_properties(${target} PROPERTIES QT6_QML_MODULE_ADD_QML_FILES_COUNT ${new_count})
+
+ qt6_add_resources(${target} "qml_files${new_count}"
+ FILES ${arg_FILES}
+ OUTPUT_TARGETS resource_targets
+ )
+ get_target_property(skip_type_registration ${target} QT_QML_MODULE_SKIP_TYPE_REGISTRATION)
+ get_target_property(target_resource_export ${target} QT_QML_MODULE_RESOURCE_EXPORT)
+ get_target_property(qml_module_install_dir ${target} QT_QML_MODULE_INSTALL_DIR)
+ if (resource_targets)
+ install(TARGETS ${resource_targets}
+ EXPORT "${target_resource_export}"
+ DESTINATION ${qm_module_install_dir}
+ )
+ endif()
+
+ set(file_contents "")
+ foreach(qml_file IN LISTS arg_FILES)
+ if (install_qml_files)
+ if (NOT QT_WILL_INSTALL)
+ file(COPY "${qml_file}" DESTINATION "${qml_module_install_dir}")
+ else()
+ install(FILES "${qml_file}" DESTINATION "${qml_module_install_dir}")
+ endif()
+ endif()
+
+ if (skip_type_registration AND qml_file MATCHES "\\.qml$")
+ continue()
+ endif()
+
+ get_source_file_property(qml_file_skip_qmldir ${qml_file} QT_QML_SKIP_QMLDIR_ENTRY)
+ if (qml_file_skip_qmldir)
+ continue()
+ endif()
+
+ get_source_file_property(qml_file_version ${qml_file} QT_QML_SOURCE_VERSION)
+ get_source_file_property(qml_file_typename ${qml_file} QT_QML_SOURCE_TYPENAME)
+ get_source_file_property(qml_file_singleton ${qml_file} QT_QML_SINGLETON_TYPE)
+ get_source_file_property(qml_file_internal ${qml_file} QT_QML_INTERNAL_TYPE)
+ get_target_property(qml_module_version ${target} QT_QML_MODULE_VERSION)
+
+ if (NOT qml_file_version)
+ set(qml_file_version ${qml_module_version})
+ endif()
+
+ if (NOT qml_file_typename)
+ get_filename_component(qml_file_typename ${qml_file} NAME_WLE)
+ endif()
+
+ if (qml_file_singleton)
+ string(APPEND file_contents "[singleton] ")
+ endif()
+
+ string(APPEND file_contents "${qml_file_typename} ${qml_file_version} ${qml_file}\n")
+
+ if (qml_file_internal)
+ string(APPEND file_contents "internal ${qml_file_typename} ${qml_file}\n")
+ endif()
+
+ endforeach()
+ file(APPEND ${qmldir_file} ${file_contents})
+endfunction()
+
+function(qt6_qml_type_registration target)
+
+ get_target_property(import_name ${target} QT_QML_MODULE_URI)
+ if (NOT import_name)
+ message(FATAL_ERROR "Target ${target} is not a QML module")
+ endif()
+
+ cmake_parse_arguments(args "COPY_OVER_INSTALL" "INSTALL_DIR" "" ${ARGN})
+
+ set(meta_types_args)
+ if (QT_BUILDING_QT AND NOT QT_WILL_INSTALL)
+ set(arg_COPY_OVER_INSTALL TRUE)
+ endif()
+ if (arg_INSTALL_DIR)
+ list(APPEND meta_types_args INSTALL_DIR "${arg_INSTALL_DIR}")
+ endif()
+ if (arg_COPY_OVER_INSTALL)
+ list(APPEND meta_types_args COPY_OVER_INSTALL)
+ endif()
+
+ qt6_generate_meta_types_json_file(${target} ${meta_types_args})
+
+ get_target_property(import_version ${target} QT_QML_MODULE_VERSION)
+ get_target_property(target_source_dir ${target} SOURCE_DIR)
+ get_target_property(target_binary_dir ${target} BINARY_DIR)
+ get_target_property(target_metatypes_file ${target} INTERFACE_QT_META_TYPES_BUILD_FILE)
+ if (NOT target_metatypes_file)
+ message(FATAL_ERROR "Target ${target} does not have a meta types file")
+ endif()
+
+ # Extract major and minor version
+ if (NOT import_version MATCHES "[0-9]+\\.[0-9]+")
+ message(FATAL_ERROR "Invalid module dependency version number. Expected VersionMajor.VersionMinor.")
+ endif()
+ #string(FIND "${import_version}" "." dot_location)
+ #string(SUBSTRING ${import_version} 0 ${dot_location} major_version)
+ #math(EXPR dot_location "${dot_location}+1")
+ #string(SUBSTRING ${import_version} ${dot_location} -1 minor_version)
+ string(REPLACE "." ";" import_version_split "${import_version}")
+ list(LENGTH import_version_split import_version_split_length)
+ if(import_version_split_length GREATER 0)
+ list(GET import_version_split 0 major_version)
+ endif()
+ if(import_version_split_length GREATER 1)
+ list(GET import_version_split 1 minor_version)
+ endif()
+
+ # check if plugins.qmltypes is already defined
+ get_target_property(target_plugin_qmltypes ${target} QT_QML_MODULE_PLUGIN_TYPES_FILE)
+ if (target_plugin_qmltypes)
+ message(FATAL_ERROR "Target ${target} already has a plugins.qmltypes set.")
+ endif()
+
+ set(cmd_args)
+ set(plugin_types_file ${target_binary_dir}/plugins.qmltypes)
+ set_target_properties(${target} PROPERTIES
+ QT_QML_MODULE_PLUGIN_TYPES_FILE ${plugin_types_file}
+ )
+ list(APPEND cmd_args
+ --generate-qmltypes=${plugin_types_file}
+ --import-name=${import_name}
+ --major-version=${major_version}
+ --minor-version=${minor_version}
+ )
+
+ # Run a script to recursively evaluate all the metatypes.json files in order
+ # to collect all foreign types.
+ string(TOLOWER "${target}_qmltyperegistrations.cpp" type_registration_cpp_file_name)
+ set(foreign_types_file "${target_binary_dir}/qmltypes/foreign_types.txt")
+ set(type_registration_cpp_file "${target_binary_dir}/${type_registration_cpp_file_name}")
+
+ set(dependency_file_cpp "${target_binary_dir}/qmltypes/${type_registration_cpp_file_name}.d")
+ file(RELATIVE_PATH cpp_file_name "${${CMAKE_PROJECT_NAME}_BINARY_DIR}" "${type_registration_cpp_file}")
+
+ set (use_dep_files FALSE)
+ if (CMAKE_GENERATOR STREQUAL "Ninja" OR CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
+ set(use_dep_files TRUE)
+ endif()
+
+ # Enable evaluation of metatypes.json source interfaces
+ set_target_properties(${target} PROPERTIES QT_CONSUMES_METATYPES TRUE)
+ set(genex_list "$<REMOVE_DUPLICATES:$<FILTER:$<TARGET_PROPERTY:${target},SOURCES>,INCLUDE,metatypes.json$>>")
+ set(genex_main "$<JOIN:${genex_list},$<COMMA>>")
+ file(GENERATE OUTPUT "${foreign_types_file}"
+ CONTENT "$<IF:$<BOOL:${genex_list}>,--foreign-types=${genex_main},\n>"
+ )
+
+ list(APPEND cmd_args
+ "@${foreign_types_file}"
+ )
+
+ set(dependencies_json_file "${target_source_dir}/dependencies.json")
+ if (EXISTS ${dependencies_json_file})
+ list(APPEND cmd_args --dependencies=${dependencies_json_file})
+ endif()
+
+ if (TARGET ${target}Private)
+ list(APPEND cmd_args --private-includes)
+ endif()
+
+ get_target_property(target_metatypes_json_file ${target} INTERFACE_QT_META_TYPES_BUILD_FILE)
+ if (NOT target_metatypes_json_file)
+ message(FATAL_ERROR "Need target metatypes.json file")
+ endif()
+
+ set(registration_cpp_file_dep_args)
+ if (use_dep_files)
+ set(registration_cpp_file_dep_args DEPFILE ${dependency_file_cpp})
+ file(GENERATE OUTPUT "${dependency_file_cpp}"
+ CONTENT "${cpp_file_name}: $<IF:$<BOOL:${genex_list}>,\\\n$<JOIN:${genex_list}, \\\n>, \\\n>"
+ )
+ endif()
+
+ set(extra_env_command)
+ if (WIN32)
+ file(TO_NATIVE_PATH "${${PROJECT_NAME}_BINARY_DIR}/bin$<SEMICOLON>${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}$<SEMICOLON>%PATH%" env_path_native)
+ set(extra_env_command COMMAND set PATH=${env_path_native})
+ endif()
+ add_custom_command(OUTPUT ${type_registration_cpp_file}
+ DEPENDS
+ ${foreign_types_file}
+ ${target_metatypes_json_file}
+ ${QT_CMAKE_EXPORT_NAMESPACE}::qmltyperegistrar
+ ${extra_env_command}
+ COMMAND
+ $<TARGET_FILE:${QT_CMAKE_EXPORT_NAMESPACE}::qmltyperegistrar>
+ ${cmd_args}
+ -o ${type_registration_cpp_file}
+ ${target_metatypes_json_file}
+ ${registration_cpp_file_dep_args}
+ COMMENT "Automatic QML type registration for target ${target}"
+ )
+
+ target_sources(${target} PRIVATE ${type_registration_cpp_file})
+ set_source_files_properties(${type_registration_cpp_file} PROPERTIES
+ SKIP_AUTOGEN ON
+ )
+
+ # Only install qml types if necessary
+ get_target_property(install_qmltypes ${target} QT_QML_MODULE_INSTALL_QMLTYPES)
+ if (install_qmltypes)
+ get_target_property(qml_install_dir ${target} QT_QML_MODULE_INSTALL_DIR)
+ if(NOT arg_COPY_OVER_INSTALL)
+ install(FILES ${plugin_types_file} DESTINATION ${qml_install_dir})
+ else()
+ # For regular modules that have not been declared using
+ # qt_add_qml_module (e.g: src/quick)
+ if (DEFINED QT_WILL_INSTALL AND NOT QT_WILL_INSTALL
+ AND NOT IS_ABSOLUTE "${qml_install_dir}")
+ set(qml_install_dir "${QT_BUILD_DIR}/${qml_install_dir}")
+ endif()
+ add_custom_command(TARGET ${target} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ "${plugin_types_file}"
+ "${qml_install_dir}/plugins.qmltypes"
+ COMMENT "Copying ${plugin_types_file} to ${qml_install_dir}"
+ )
+ endif()
+ endif()
+
+ target_include_directories(${target} PRIVATE
+ $<TARGET_PROPERTY:Qt::QmlPrivate,INTERFACE_INCLUDE_DIRECTORIES>
+ )
+endfunction()
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index a5a1cf8969..7d44126b13 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -57,6 +57,8 @@
#include <QtCore/qvector.h>
#include <QtCore/qstringlist.h>
#include <QtCore/qhash.h>
+#include <QtCore/qversionnumber.h>
+#include <QtCore/qlocale.h>
#if QT_CONFIG(temporaryfile)
#include <QtCore/qsavefile.h>
@@ -65,6 +67,7 @@
#include <private/qendian_p.h>
#include <private/qv4staticvalue_p.h>
#include <functional>
+#include <limits.h>
QT_BEGIN_NAMESPACE
@@ -75,7 +78,7 @@ QT_BEGIN_NAMESPACE
// Also change the comment behind the number to describe the latest change. This has the added
// benefit that if another patch changes the version too, it will result in a merge conflict, and
// not get removed silently.
-#define QV4_DATA_STRUCTURE_VERSION 0x29// support additional required property features
+#define QV4_DATA_STRUCTURE_VERSION 0x30// support additional required property features
class QIODevice;
class QQmlTypeNameCache;
@@ -195,39 +198,14 @@ struct JSClass
};
static_assert(sizeof(JSClass) == 4, "JSClass structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
-// This data structure is intended to be binary compatible with QStringData/QStaticStringData on
-// 64-bit and 32-bit little-endian architectures, in all directions. So the same structure mapped
-// from a file must be castable to a QStringData regardless of the pointer size. With the first
-// few fields that's easy, they're always 32-bit. However the offset field of QArrayData is a
-// ptrdiff_t and thus variable in size.
-// On 64-bit systems compilers enforce an 8-byte alignment and thus place it at offset 16, while
-// on 32-bit systems offset 12 is sufficient. Therefore the two values don't overlap and contain
-// the same value.
struct String
{
- qint32_le refcount; // -1
qint32_le size;
- quint32_le allocAndCapacityReservedFlag; // 0
- quint32_le offsetOn32Bit;
- quint64_le offsetOn64Bit;
- // uint16 strdata[]
static int calculateSize(const QString &str) {
return (sizeof(String) + (str.length() + 1) * sizeof(quint16) + 7) & ~0x7;
}
};
-static_assert(sizeof(String) == 24, "String structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
-
-// Ensure compatibility with QString
-static_assert(offsetof(QArrayData, ref) == offsetof(String, refcount), "refcount must be at the same location");
-static_assert(offsetof(QArrayData, size) == offsetof(String, size), "size must be at the same location");
-static_assert(offsetof(String, offsetOn64Bit) == 16, "offset must be at 8-byte aligned location");
-static_assert(offsetof(String, offsetOn32Bit) == 12, "offset must be at 4-byte aligned location");
-#if QT_POINTER_SIZE == 8
-static_assert(offsetof(QArrayData, offset) == offsetof(String, offsetOn64Bit), "offset must be at the same location");
-#else
-static_assert(offsetof(QArrayData, offset) == offsetof(String, offsetOn32Bit), "offset must be at the same location");
-#endif
struct CodeOffsetToLine {
quint32_le codeOffset;
@@ -472,7 +450,8 @@ struct Binding
IsBindingToAlias = 0x40,
IsDeferredBinding = 0x80,
IsCustomParserBinding = 0x100,
- IsFunctionExpression = 0x200
+ IsFunctionExpression = 0x200,
+ IsPropertyObserver = 0x400
};
union {
@@ -498,7 +477,8 @@ struct Binding
|| type == Type_GroupProperty)
return false;
if (flags & IsSignalHandlerExpression
- || flags & IsSignalHandlerObject)
+ || flags & IsSignalHandlerObject
+ || flags & IsPropertyObserver)
return false;
return true;
}
@@ -508,7 +488,7 @@ struct Binding
bool isSignalHandler() const
{
- if (flags & IsSignalHandlerExpression || flags & IsSignalHandlerObject) {
+ if (flags & IsSignalHandlerExpression || flags & IsSignalHandlerObject || flags & IsPropertyObserver) {
Q_ASSERT(!isValueBinding());
Q_ASSERT(!isAttachedProperty());
Q_ASSERT(!isGroupProperty());
@@ -692,6 +672,11 @@ struct Property
builtinTypeOrTypeNameIndex = nameIndex;
isBuiltinType = false;
}
+
+ int customType() const
+ {
+ return isBuiltinType ? -1 : builtinTypeOrTypeNameIndex;
+ }
};
static_assert(sizeof(Property) == 12, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
@@ -905,14 +890,16 @@ struct Import
quint32_le uriIndex;
quint32_le qualifierIndex;
- qint32_le majorVersion;
- qint32_le minorVersion;
-
Location location;
+ QTypeRevision version;
+ quint16_le reserved;
- Import() { type = 0; uriIndex = 0; qualifierIndex = 0; majorVersion = 0; minorVersion = 0; }
+ Import()
+ {
+ type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0;
+ }
};
-static_assert(sizeof(Import) == 24, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_assert(sizeof(Import) == 20, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
struct QmlUnit
{
@@ -1016,14 +1003,13 @@ struct Unit
const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
const quint32_le offset = offsetTable[idx];
const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
+ Q_ASSERT(str->size >= 0);
if (str->size == 0)
return QString();
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- if (flags & StaticData) {
- const QStringDataPtr holder = { const_cast<QStringData *>(reinterpret_cast<const QStringData*>(str)) };
- return QString(holder);
- }
const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
+ if (flags & StaticData)
+ return QString::fromRawData(characters, str->size);
return QString(characters, str->size);
#else
const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
@@ -1308,6 +1294,44 @@ public:
Heap::Module *module() const { return m_module; }
void setModule(Heap::Module *module) { m_module = module; }
+ QString bindingValueAsString(const CompiledData::Binding *binding) const
+ {
+ using namespace CompiledData;
+ switch (binding->type) {
+ case Binding::Type_Script:
+ case Binding::Type_String:
+ return stringAt(binding->stringIndex);
+ case Binding::Type_Null:
+ return QStringLiteral("null");
+ case Binding::Type_Boolean:
+ return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
+ case Binding::Type_Number:
+ return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
+ case Binding::Type_Invalid:
+ return QString();
+ case Binding::Type_TranslationById:
+ case Binding::Type_Translation:
+ return stringAt(data->translations()[binding->value.translationDataIndex].stringIndex);
+ default:
+ break;
+ }
+ return QString();
+ }
+
+ QString bindingValueAsScriptString(const CompiledData::Binding *binding) const
+ {
+ return (binding->type == CompiledData::Binding::Type_String)
+ ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
+ : bindingValueAsString(binding);
+ }
+
+ double bindingValueAsNumber(const CompiledData::Binding *binding) const
+ {
+ if (binding->type != CompiledData::Binding::Type_Number)
+ return 0.0;
+ return constants[binding->value.constantValueIndex].doubleValue();
+ }
+
private:
QString m_fileName; // initialized from data->sourceFileIndex
QString m_finalUrlString; // initialized from data->finalUrlIndex
diff --git a/src/qml/common/qv4stringtoarrayindex_p.h b/src/qml/common/qv4stringtoarrayindex_p.h
index 61bd988d1e..d4b064f865 100644
--- a/src/qml/common/qv4stringtoarrayindex_p.h
+++ b/src/qml/common/qv4stringtoarrayindex_p.h
@@ -65,6 +65,8 @@ inline uint charToUInt(const char *ch) { return static_cast<unsigned char>(*ch);
template <typename T>
uint stringToArrayIndex(const T *ch, const T *end)
{
+ if (ch == end)
+ return std::numeric_limits<uint>::max();
uint i = charToUInt(ch) - '0';
if (i > 9)
return std::numeric_limits<uint>::max();
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 89f99e21cd..bc979a81e0 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -407,11 +407,7 @@ void ScriptDirectivesCollector::importModule(const QString &uri, const QString &
QV4::CompiledData::Import *import = engine->pool()->New<QV4::CompiledData::Import>();
import->type = QV4::CompiledData::Import::ImportLibrary;
import->uriIndex = jsGenerator->registerString(uri);
- int vmaj;
- int vmin;
- IRBuilder::extractVersion(QStringRef(&version), &vmaj, &vmin);
- import->majorVersion = vmaj;
- import->minorVersion = vmin;
+ import->version = IRBuilder::extractVersion(QStringRef(&version));
import->qualifierIndex = jsGenerator->registerString(module);
import->location.line = lineNumber;
import->location.column = column;
@@ -758,16 +754,10 @@ bool IRBuilder::visit(QQmlJS::AST::UiImport *node)
}
if (node->version) {
- import->majorVersion = node->version->majorVersion;
- import->minorVersion = node->version->minorVersion;
- } else if (import->type == QV4::CompiledData::Import::ImportLibrary) {
- recordError(node->importIdToken, QCoreApplication::translate("QQmlParser","Library import requires a version"));
- return false;
+ import->version = node->version->version;
} else {
- // For backward compatibility in how the imports are loaded we
- // must otherwise initialize the major and minor version to -1.
- import->majorVersion = -1;
- import->minorVersion = -1;
+ // Otherwise initialize the major and minor version to invalid to signal "latest".
+ import->version = QTypeRevision();
}
import->location.line = node->importToken.startLine;
@@ -1061,22 +1051,15 @@ QStringRef IRBuilder::asStringRef(QQmlJS::AST::Node *node)
return textRefAt(node->firstSourceLocation(), node->lastSourceLocation());
}
-void IRBuilder::extractVersion(const QStringRef &string, int *maj, int *min)
+QTypeRevision IRBuilder::extractVersion(const QStringRef &string)
{
- *maj = -1; *min = -1;
-
- if (!string.isEmpty()) {
-
- int dot = string.indexOf(QLatin1Char('.'));
+ if (string.isEmpty())
+ return QTypeRevision();
- if (dot < 0) {
- *maj = string.toInt();
- *min = 0;
- } else {
- *maj = string.left(dot).toInt();
- *min = string.mid(dot + 1).toInt();
- }
- }
+ const int dot = string.indexOf(QLatin1Char('.'));
+ return (dot < 0)
+ ? QTypeRevision::fromMajorVersion(string.toInt())
+ : QTypeRevision::fromVersion(string.left(dot).toInt(), string.mid(dot + 1).toInt());
}
QStringRef IRBuilder::textRefAt(const QQmlJS::SourceLocation &first, const QQmlJS::SourceLocation &last) const
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 9629a73199..254d21001b 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -498,7 +498,7 @@ public:
static QString asString(QQmlJS::AST::UiQualifiedId *node);
QStringRef asStringRef(QQmlJS::AST::Node *node);
- static void extractVersion(const QStringRef &string, int *maj, int *min);
+ static QTypeRevision extractVersion(const QStringRef &string);
QStringRef textRefAt(const QQmlJS::SourceLocation &loc) const
{ return QStringRef(&sourceCode, loc.offset, loc.length); }
QStringRef textRefAt(const QQmlJS::SourceLocation &first,
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index acc4b02e96..0c0a005689 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -47,6 +48,7 @@
#include <private/qml_compile_hash_p.h>
#include <private/qqmlirbuilder_p.h>
#include <QCryptographicHash>
+#include <QtEndian>
// Efficient implementation that takes advantage of powers of two.
static inline size_t roundUpToMultipleOf(size_t divisor, size_t x)
@@ -108,19 +110,11 @@ void QV4::Compiler::StringTableGenerator::serialize(CompiledData::Unit *unit)
QV4::CompiledData::String *s = reinterpret_cast<QV4::CompiledData::String *>(stringData);
Q_ASSERT(reinterpret_cast<uintptr_t>(s) % alignof(QV4::CompiledData::String) == 0);
- s->refcount = -1;
+ Q_ASSERT(qstr.length() >= 0);
s->size = qstr.length();
- s->allocAndCapacityReservedFlag = 0;
- s->offsetOn32Bit = sizeof(QV4::CompiledData::String);
- s->offsetOn64Bit = sizeof(QV4::CompiledData::String);
ushort *uc = reinterpret_cast<ushort *>(reinterpret_cast<char *>(s) + sizeof(*s));
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- memcpy(uc, qstr.constData(), s->size * sizeof(ushort));
-#else
- for (int i = 0; i < s->size; ++i)
- uc[i] = qToLittleEndian<ushort>(qstr.at(i).unicode());
-#endif
+ qToLittleEndian<ushort>(qstr.constData(), s->size, uc);
uc[s->size] = 0;
stringData += QV4::CompiledData::String::calculateSize(qstr);
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index c0dd696b8a..254e1c46e9 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -348,7 +348,7 @@ QT_BEGIN_NAMESPACE
#endif
#endif
-#define MOTH_INSTR_ALIGN_MASK (Q_ALIGNOF(QV4::Moth::Instr) - 1)
+#define MOTH_INSTR_ALIGN_MASK (alignof(QV4::Moth::Instr) - 1)
#define MOTH_INSTR_ENUM(I) I, I##_Wide,
#define MOTH_INSTR_SIZE(I) (sizeof(QV4::Moth::Instr::instr_##I))
diff --git a/src/qml/configure.cmake b/src/qml/configure.cmake
new file mode 100644
index 0000000000..00936ff53c
--- /dev/null
+++ b/src/qml/configure.cmake
@@ -0,0 +1,189 @@
+
+
+#### Inputs
+
+
+
+#### Libraries
+
+
+
+#### Tests
+
+# cxx14_make_unique
+qt_config_compile_test(cxx14_make_unique
+ LABEL "C++14 make_unique()"
+ CODE
+"
+#include <memory>
+
+int main(int argc, char **argv)
+{
+ (void)argc; (void)argv;
+ /* BEGIN TEST: */
+std::unique_ptr<int> ptr = std::make_unique<int>();
+ /* END TEST: */
+ return 0;
+}
+")
+
+# pointer_32bit
+qt_config_compile_test(pointer_32bit
+ LABEL "32bit pointers"
+ CODE
+"
+
+
+int main(int argc, char **argv)
+{
+ (void)argc; (void)argv;
+ /* BEGIN TEST: */
+static_assert(sizeof(void *) == 4, \"fail\");
+ /* END TEST: */
+ return 0;
+}
+")
+
+# pointer_64bit
+qt_config_compile_test(pointer_64bit
+ LABEL "64bit pointers"
+ CODE
+"
+
+
+int main(int argc, char **argv)
+{
+ (void)argc; (void)argv;
+ /* BEGIN TEST: */
+static_assert(sizeof(void *) == 8, \"fail\");
+ /* END TEST: */
+ return 0;
+}
+")
+
+# arm_thumb
+qt_config_compile_test(arm_thumb
+ LABEL "THUMB mode on ARM"
+ CODE
+"
+
+
+int main(int argc, char **argv)
+{
+ (void)argc; (void)argv;
+ /* BEGIN TEST: */
+#if defined(thumb2) || defined(__thumb2__)
+# define THUMB_OK
+#elif (defined(__thumb) || defined(__thumb__)) && __TARGET_ARCH_THUMB-0 == 4
+# define THUMB_OK
+#elif defined(__ARM_ARCH_ISA_THUMB) && __ARM_ARCH_ISA_THUMB == 2
+// clang 3.5 and later will set this if the core supports the Thumb-2 ISA.
+# define THUMB_OK
+#else
+# error \"fail\"
+#endif
+ /* END TEST: */
+ return 0;
+}
+")
+
+# arm_fp
+qt_config_compile_test(arm_fp
+ LABEL "Sufficiently recent FPU on ARM"
+ CODE
+"
+
+
+int main(int argc, char **argv)
+{
+ (void)argc; (void)argv;
+ /* BEGIN TEST: */
+// if !defined(__ARM_FP) we might be on MSVC or we might have a device
+// without an FPU.
+// TODO: The latter case is not supported, but the test still succeeds.
+#if defined(__ARM_FP) && (__ARM_FP <= 0x04)
+# error \"fail\"
+#endif
+ /* END TEST: */
+ return 0;
+}
+")
+
+
+
+#### Features
+
+qt_feature("cxx14_make_unique" PRIVATE
+ LABEL "C++14 make_unique"
+ CONDITION QT_FEATURE_cxx14 OR TEST_cxx14_make_unique
+)
+qt_feature("qml-network" PUBLIC
+ SECTION "QML"
+ LABEL "QML network support"
+ PURPOSE "Provides network transparency."
+ CONDITION QT_FEATURE_network
+)
+# On arm and arm64 we need a specialization of cacheFlush() for each OS to be enabeled. Therefore the config white list. Also Mind that e.g. x86_32 has arch.x86_64 but 32bit pointers. Therefore the checks for architecture and pointer size. Finally, ios and tvos can technically use the JIT but Apple does not allow it. Therefore, it's disabled by default.
+qt_feature("qml-jit" PRIVATE
+ SECTION "QML"
+ LABEL "QML just-in-time compiler"
+ PURPOSE "Provides a JIT for QML and JavaScript"
+ AUTODETECT NOT IOS AND NOT TVOS
+ CONDITION ( ( ( TEST_architecture_arch STREQUAL i386 ) AND TEST_pointer_32bit AND QT_FEATURE_sse2 ) OR ( ( TEST_architecture_arch STREQUAL x86_64 ) AND TEST_pointer_64bit AND QT_FEATURE_sse2 ) OR ( ( TEST_architecture_arch STREQUAL arm ) AND TEST_pointer_32bit AND TEST_arm_fp AND TEST_arm_thumb AND ( LINUX OR IOS OR TVOS OR QNX ) ) OR ( ( TEST_architecture_arch STREQUAL arm64 ) AND TEST_pointer_64bit AND TEST_arm_fp AND ( LINUX OR IOS OR TVOS OR QNX OR INTEGRITY ) ) )
+)
+qt_feature("qml-debug" PUBLIC
+ SECTION "QML"
+ LABEL "QML debugging and profiling support"
+ PURPOSE "Provides infrastructure and plugins for debugging and profiling."
+)
+qt_feature("qml-profiler" PRIVATE
+ SECTION "QML"
+ LABEL "Command line QML Profiler"
+ PURPOSE "Supports retrieving QML tracing data from an application."
+ CONDITION ( QT_FEATURE_commandlineparser ) AND ( QT_FEATURE_qml_debug ) AND ( QT_FEATURE_qml_network AND QT_FEATURE_localserver ) AND ( QT_FEATURE_xmlstreamwriter )
+)
+qt_feature("qml-preview" PRIVATE
+ SECTION "QML"
+ LABEL "Command line QML Preview tool"
+ PURPOSE "Updates QML documents in your application live as you change them on disk"
+ CONDITION ( QT_FEATURE_commandlineparser ) AND ( QT_FEATURE_filesystemwatcher ) AND ( QT_FEATURE_qml_network AND QT_FEATURE_localserver ) AND ( QT_FEATURE_process ) AND ( QT_FEATURE_qml_debug )
+)
+qt_feature("qml-devtools" PRIVATE
+ SECTION "QML"
+ LABEL "QML Development Tools"
+ PURPOSE "Provides the QmlDevtools library and various utilities."
+)
+qt_feature("qml-sequence-object" PRIVATE
+ SECTION "QML"
+ LABEL "QML sequence object"
+ PURPOSE "Supports mapping sequence types into QML."
+)
+qt_feature("qml-xml-http-request" PRIVATE
+ SECTION "QML"
+ LABEL "QML XML http request"
+ PURPOSE "Provides support for sending XML http requests."
+ CONDITION ( QT_FEATURE_xmlstreamreader ) AND ( QT_FEATURE_qml_network )
+)
+qt_feature("qml-locale" PRIVATE
+ SECTION "QML"
+ LABEL "QML Locale"
+ PURPOSE "Provides support for locales in QML."
+)
+qt_feature("qml-animation" PRIVATE
+ SECTION "QML"
+ LABEL "QML Animations"
+ PURPOSE "Provides support for animations and timers in QML."
+ CONDITION QT_FEATURE_animation
+)
+qt_feature("qml-worker-script" PRIVATE
+ SECTION "QML"
+ LABEL "QML WorkerScript"
+ PURPOSE "Enables the use of threads in QML."
+ CONDITION QT_FEATURE_thread
+)
+qt_feature("qml-itemmodel" PRIVATE
+ SECTION "QML"
+ LABEL "QML Item Model"
+ PURPOSE "Provides the item model for item views in QML"
+ CONDITION QT_FEATURE_itemmodel
+)
diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
index b259e047a1..df1ed68c7b 100644
--- a/src/qml/debugger/qqmldebugserviceinterfaces_p.h
+++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h
@@ -107,7 +107,8 @@ class QQmlNativeDebugService {};
class QQmlDebugTranslationService {
public:
virtual QString foundElidedText(QObject *, const QString &, const QString &) {return {};}
- virtual void foundTranslationBinding(QQmlTranslationBinding *, QObject *, QQmlContextData *) {}
+ virtual void foundTranslationBinding(QQmlTranslationBinding *, QObject *,
+ const QQmlRefPointer<QQmlContextData> &) {}
};
#else
@@ -175,7 +176,8 @@ public:
static const QString s_key;
virtual QString foundElidedText(QObject *qQuickTextObject, const QString &layoutText, const QString &elideText) = 0;
- virtual void foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject, QQmlContextData *contextData) = 0;
+ virtual void foundTranslationBinding(QQmlTranslationBinding *binding, QObject *scopeObject,
+ const QQmlRefPointer<QQmlContextData> &contextData) = 0;
protected:
friend class QQmlDebugConnector;
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index 0dec7fd66d..9dfb7837e5 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -303,7 +303,7 @@ In particular, QML currently supports:
\li \c {std::vector<bool>}
\endlist
-and all registered QList, QVector, QQueue, QStack, QSet, QLinkedList, std::list,
+and all registered QList, QVector, QQueue, QStack, QSet, std::list,
std::vector that contain a type marked with \l Q_DECLARE_METATYPE.
These sequence types are implemented directly in terms of the underlying C++
diff --git a/src/qml/inlinecomponentutils_p.h b/src/qml/inlinecomponentutils_p.h
index 99b28349cd..ae436d53b0 100644
--- a/src/qml/inlinecomponentutils_p.h
+++ b/src/qml/inlinecomponentutils_p.h
@@ -51,7 +51,7 @@
//
#include <private/qv4compileddata_p.h>
-#include <private/qv4executablecompilationunit_p.h>
+#include <private/qv4resolvedtypereference_p.h>
namespace icutils {
struct Node {
@@ -88,10 +88,12 @@ void fillAdjacencyListForInlineComponents(ObjectContainer *objectContainer, Adja
const CompiledObject *obj = objectContainer->objectAt(ic.objectIndex);
QV4::ResolvedTypeReference *currentICTypeRef = objectContainer->resolvedType(ic.nameIndex);
auto createEdgeFromTypeRef = [&](QV4::ResolvedTypeReference *targetTypeRef) {
- if (targetTypeRef && targetTypeRef->type.isInlineComponentType()) {
- if (targetTypeRef->type.containingType() == currentICTypeRef->type.containingType()) {
+ if (targetTypeRef) {
+ const auto targetType = targetTypeRef->type();
+ if (targetType.isInlineComponentType()
+ && targetType.containingType() == currentICTypeRef->type().containingType()) {
auto icIt = std::find_if(allICs.cbegin(), allICs.cend(), [&](const QV4::CompiledData::InlineComponent &icSearched){
- return int(icSearched.objectIndex) == targetTypeRef->type.inlineComponentObjectId();
+ return int(icSearched.objectIndex) == targetType.inlineComponentObjectId();
});
Q_ASSERT(icIt != allICs.cend());
Node& target = nodes[i];
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index 6946a64d11..65b65f1b21 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -451,10 +451,7 @@ void QJSEngine::installExtensions(QJSEngine::Extensions extensions, const QJSVal
}
QV4::Scope scope(m_v4Engine);
- QV4::ScopedObject obj(scope);
- QV4::Value *val = QJSValuePrivate::getValue(&object);
- if (val)
- obj = val;
+ QV4::ScopedObject obj(scope, QJSValuePrivate::asReturnedValue(&object));
if (!obj)
obj = scope.engine->globalObject;
@@ -548,9 +545,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
if (v4->isInterrupted.loadAcquire())
result = v4->newErrorObject(QStringLiteral("Interrupted"));
- QJSValue retval(v4, result->asReturnedValue());
-
- return retval;
+ return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
}
/*!
@@ -578,18 +573,17 @@ QJSValue QJSEngine::importModule(const QString &fileName)
const QUrl url = urlForFileName(QFileInfo(fileName).canonicalFilePath());
auto moduleUnit = m_v4Engine->loadModule(url);
if (m_v4Engine->hasException)
- return QJSValue(m_v4Engine, m_v4Engine->catchException());
+ return QJSValuePrivate::fromReturnedValue(m_v4Engine->catchException());
QV4::Scope scope(m_v4Engine);
QV4::Scoped<QV4::Module> moduleNamespace(scope, moduleUnit->instantiate(m_v4Engine));
if (m_v4Engine->hasException)
- return QJSValue(m_v4Engine, m_v4Engine->catchException());
+ return QJSValuePrivate::fromReturnedValue(m_v4Engine->catchException());
moduleUnit->evaluate();
if (!m_v4Engine->isInterrupted.loadAcquire())
- return QJSValue(m_v4Engine, moduleNamespace->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(moduleNamespace->asReturnedValue());
- return QJSValue(
- m_v4Engine,
+ return QJSValuePrivate::fromReturnedValue(
m_v4Engine->newErrorObject(QStringLiteral("Interrupted"))->asReturnedValue());
}
@@ -605,7 +599,7 @@ QJSValue QJSEngine::newObject()
{
QV4::Scope scope(m_v4Engine);
QV4::ScopedValue v(scope, m_v4Engine->newObject());
- return QJSValue(m_v4Engine, v->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(v->asReturnedValue());
}
/*!
@@ -647,7 +641,7 @@ QJSValue QJSEngine::newErrorObject(QJSValue::ErrorType errorType, const QString
case QJSValue::NoError:
return QJSValue::UndefinedValue;
}
- return QJSValue(m_v4Engine, error->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(error->asReturnedValue());
}
/*!
@@ -662,7 +656,7 @@ QJSValue QJSEngine::newArray(uint length)
if (length < 0x1000)
array->arrayReserve(length);
array->setArrayLengthUnchecked(length);
- return QJSValue(m_v4Engine, array.asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(array.asReturnedValue());
}
/*!
@@ -695,7 +689,7 @@ QJSValue QJSEngine::newQObject(QObject *object)
QQmlEngine::setObjectOwnership(object, QQmlEngine::JavaScriptOwnership);
}
QV4::ScopedValue v(scope, QV4::QObjectWrapper::wrap(v4, object));
- return QJSValue(v4, v->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(v->asReturnedValue());
}
/*!
@@ -716,7 +710,7 @@ QJSValue QJSEngine::newQMetaObject(const QMetaObject* metaObject) {
QV4::ExecutionEngine *v4 = m_v4Engine;
QV4::Scope scope(v4);
QV4::ScopedValue v(scope, QV4::QMetaObjectWrapper::create(v4, metaObject));
- return QJSValue(v4, v->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(v->asReturnedValue());
}
/*! \fn template <typename T> QJSValue QJSEngine::newQMetaObject()
@@ -743,7 +737,7 @@ QJSValue QJSEngine::globalObject() const
{
QV4::Scope scope(m_v4Engine);
QV4::ScopedValue v(scope, m_v4Engine->globalObject);
- return QJSValue(m_v4Engine, v->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(v->asReturnedValue());
}
/*!
@@ -754,7 +748,7 @@ QJSValue QJSEngine::create(int type, const void *ptr)
{
QV4::Scope scope(m_v4Engine);
QV4::ScopedValue v(scope, scope.engine->metaTypeToJS(type, ptr));
- return QJSValue(m_v4Engine, v->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(v->asReturnedValue());
}
/*!
@@ -763,118 +757,57 @@ QJSValue QJSEngine::create(int type, const void *ptr)
*/
bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
{
- QV4::ExecutionEngine *v4 = QJSValuePrivate::engine(&value);
- QV4::Value scratch;
- QV4::Value *val = QJSValuePrivate::valueForData(&value, &scratch);
- if (v4) {
- QV4::Scope scope(v4);
- QV4::ScopedValue v(scope, *val);
- return scope.engine->metaTypeFromJS(v, type, ptr);
- }
-
- if (!val) {
- QVariant *variant = QJSValuePrivate::getVariant(&value);
- Q_ASSERT(variant);
-
- if (variant->userType() == QMetaType::QString) {
- QString string = variant->toString();
- // have a string based value without engine. Do conversion manually
- if (type == QMetaType::Bool) {
- *reinterpret_cast<bool*>(ptr) = string.length() != 0;
- return true;
- }
- if (type == QMetaType::QString) {
- *reinterpret_cast<QString*>(ptr) = string;
- return true;
- }
- double d = QV4::RuntimeHelpers::stringToNumber(string);
- switch (type) {
- case QMetaType::Int:
- *reinterpret_cast<int*>(ptr) = QV4::Value::toInt32(d);
- return true;
- case QMetaType::UInt:
- *reinterpret_cast<uint*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(ptr) = QV4::Value::toInteger(d);
- return true;
- case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(ptr) = QV4::Value::toInteger(d);
- return true;
- case QMetaType::Double:
- *reinterpret_cast<double*>(ptr) = d;
- return true;
- case QMetaType::Float:
- *reinterpret_cast<float*>(ptr) = d;
- return true;
- case QMetaType::Short:
- *reinterpret_cast<short*>(ptr) = QV4::Value::toInt32(d);
- return true;
- case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- case QMetaType::Char:
- *reinterpret_cast<char*>(ptr) = QV4::Value::toInt32(d);
- return true;
- case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- case QMetaType::QChar:
- *reinterpret_cast<QChar*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- default:
- return false;
- }
- } else {
- return QMetaType::convert(&variant->data_ptr(), variant->userType(), ptr, type);
+ if (const QString *string = QJSValuePrivate::asQString(&value)) {
+ // have a string based value without engine. Do conversion manually
+ if (type == QMetaType::Bool) {
+ *reinterpret_cast<bool*>(ptr) = string->length() != 0;
+ return true;
}
- }
-
- Q_ASSERT(val);
-
- switch (type) {
- case QMetaType::Bool:
- *reinterpret_cast<bool*>(ptr) = val->toBoolean();
+ if (type == QMetaType::QString) {
+ *reinterpret_cast<QString*>(ptr) = *string;
return true;
+ }
+ double d = QV4::RuntimeHelpers::stringToNumber(*string);
+ switch (type) {
case QMetaType::Int:
- *reinterpret_cast<int*>(ptr) = val->toInt32();
+ *reinterpret_cast<int*>(ptr) = QV4::Value::toInt32(d);
return true;
case QMetaType::UInt:
- *reinterpret_cast<uint*>(ptr) = val->toUInt32();
+ *reinterpret_cast<uint*>(ptr) = QV4::Value::toUInt32(d);
return true;
case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(ptr) = val->toInteger();
+ *reinterpret_cast<qlonglong*>(ptr) = QV4::Value::toInteger(d);
return true;
case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(ptr) = val->toInteger();
+ *reinterpret_cast<qulonglong*>(ptr) = QV4::Value::toInteger(d);
return true;
case QMetaType::Double:
- *reinterpret_cast<double*>(ptr) = val->toNumber();
- return true;
- case QMetaType::QString:
- *reinterpret_cast<QString*>(ptr) = val->toQStringNoThrow();
+ *reinterpret_cast<double*>(ptr) = d;
return true;
case QMetaType::Float:
- *reinterpret_cast<float*>(ptr) = val->toNumber();
+ *reinterpret_cast<float*>(ptr) = d;
return true;
case QMetaType::Short:
- *reinterpret_cast<short*>(ptr) = val->toInt32();
+ *reinterpret_cast<short*>(ptr) = QV4::Value::toInt32(d);
return true;
case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(ptr) = val->toUInt16();
+ *reinterpret_cast<unsigned short*>(ptr) = QV4::Value::toUInt32(d);
return true;
case QMetaType::Char:
- *reinterpret_cast<char*>(ptr) = val->toInt32();
+ *reinterpret_cast<char*>(ptr) = QV4::Value::toInt32(d);
return true;
case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(ptr) = val->toUInt16();
+ *reinterpret_cast<unsigned char*>(ptr) = QV4::Value::toUInt32(d);
return true;
case QMetaType::QChar:
- *reinterpret_cast<QChar*>(ptr) = val->toUInt16();
+ *reinterpret_cast<QChar*>(ptr) = QV4::Value::toUInt32(d);
return true;
default:
return false;
+ }
}
+
+ return QV4::ExecutionEngine::metaTypeFromJS(QJSValuePrivate::asReturnedValue(&value), type, ptr);
}
/*! \fn template <typename T> QJSValue QJSEngine::toScriptValue(const T &value)
@@ -991,7 +924,7 @@ void QJSEngine::throwError(QJSValue::ErrorType errorType, const QString &message
{
QV4::Scope scope(m_v4Engine);
QJSValue error = newErrorObject(errorType, message);
- QV4::ScopedObject e(scope, QJSValuePrivate::getValue(&error));
+ QV4::ScopedObject e(scope, QJSValuePrivate::asReturnedValue(&error));
if (!e)
return;
m_v4Engine->throwError(e);
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index 31229e1f20..16919454e7 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -133,7 +133,8 @@ private:
static bool convertV2(const QJSValue &value, int type, void *ptr);
- friend inline bool qjsvalue_cast_helper(const QJSValue &, int, void *);
+ template<typename T>
+ friend inline T qjsvalue_cast(const QJSValue &);
protected:
QJSEngine(QJSEnginePrivate &dd, QObject *parent = nullptr);
@@ -146,18 +147,13 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QJSEngine::Extensions)
-inline bool qjsvalue_cast_helper(const QJSValue &value, int type, void *ptr)
-{
- return QJSEngine::convertV2(value, type, ptr);
-}
-
template<typename T>
T qjsvalue_cast(const QJSValue &value)
{
T t;
const int id = qMetaTypeId<T>();
- if (qjsvalue_cast_helper(value, id, &t))
+ if (QJSEngine::convertV2(value, id, &t))
return t;
else if (value.isVariant())
return qvariant_cast<T>(value.toVariant());
diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h
index 7866a5bdda..0aff6595b6 100644
--- a/src/qml/jsapi/qjsengine_p.h
+++ b/src/qml/jsapi/qjsengine_p.h
@@ -53,6 +53,7 @@
#include <QtCore/private/qobject_p.h>
#include <QtCore/qmutex.h>
+#include <QtCore/qproperty.h>
#include "qjsengine.h"
#include "private/qtqmlglobal_p.h"
#include <private/qqmlmetatype_p.h>
@@ -107,11 +108,11 @@ public:
// Shared by QQmlEngine
mutable QRecursiveMutex mutex;
- QString uiLanguage;
+ QProperty<QString> uiLanguage;
// These methods may be called from the QML loader thread
- inline QQmlPropertyCache *cache(QObject *obj, int minorVersion = -1);
- inline QQmlPropertyCache *cache(const QMetaObject *, int minorVersion = -1);
+ inline QQmlPropertyCache *cache(QObject *obj, QTypeRevision version = QTypeRevision());
+ inline QQmlPropertyCache *cache(const QMetaObject *obj, QTypeRevision version = QTypeRevision());
};
QJSEnginePrivate::Locker::Locker(const QJSEngine *e)
@@ -161,14 +162,14 @@ and deleted before the loader thread has a chance to use or reference it. This
can't currently happen as the cache holds a reference to the
QQmlPropertyCache until the QQmlEngine is destroyed.
*/
-QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, int minorVersion)
+QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, QTypeRevision version)
{
if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
return nullptr;
Locker locker(this);
const QMetaObject *mo = obj->metaObject();
- return QQmlMetaType::propertyCache(mo, minorVersion);
+ return QQmlMetaType::propertyCache(mo, version);
}
/*!
@@ -180,12 +181,12 @@ exist for the lifetime of the QQmlEngine.
The returned cache is not referenced, so if it is to be stored, call addref().
*/
-QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, int minorVersion)
+QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, QTypeRevision version)
{
Q_ASSERT(metaObject);
Locker locker(this);
- return QQmlMetaType::propertyCache(metaObject, minorVersion);
+ return QQmlMetaType::propertyCache(metaObject, version);
}
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index b40bc1f18b..1122700334 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -191,41 +191,29 @@ using namespace QV4;
/*!
Constructs a new QJSValue with a boolean \a value.
*/
-QJSValue::QJSValue(bool value)
+QJSValue::QJSValue(bool value) : d(QV4::Encode(value))
{
- QJSValuePrivate::setVariant(this, QVariant(value));
-}
-
-/*!
- \internal
-*/
-QJSValue::QJSValue(ExecutionEngine *e, quint64 val)
-{
- QJSValuePrivate::setValue(this, e, val);
}
/*!
Constructs a new QJSValue with a number \a value.
*/
-QJSValue::QJSValue(int value)
+QJSValue::QJSValue(int value) : d(QV4::Encode(value))
{
- QJSValuePrivate::setVariant(this, QVariant(value));
}
/*!
Constructs a new QJSValue with a number \a value.
*/
-QJSValue::QJSValue(uint value)
+QJSValue::QJSValue(uint value) : d(QV4::Encode(value))
{
- QJSValuePrivate::setVariant(this, QVariant((double)value));
}
/*!
Constructs a new QJSValue with a number \a value.
*/
-QJSValue::QJSValue(double value)
+QJSValue::QJSValue(double value) : d(QV4::Encode(value))
{
- QJSValuePrivate::setVariant(this, QVariant(value));
}
/*!
@@ -233,17 +221,14 @@ QJSValue::QJSValue(double value)
*/
QJSValue::QJSValue(const QString& value)
{
- QJSValuePrivate::setVariant(this, QVariant(value));
+ QJSValuePrivate::setString(this, QString(value));
}
/*!
Constructs a new QJSValue with a special \a value.
*/
-QJSValue::QJSValue(SpecialValue value)
- : d(0)
+QJSValue::QJSValue(SpecialValue value) : d(value == NullValue ? QV4::Encode::null() : 0)
{
- if (value == NullValue)
- QJSValuePrivate::setVariant(this, QVariant::fromValue(nullptr));
}
/*!
@@ -251,7 +236,7 @@ QJSValue::QJSValue(SpecialValue value)
*/
QJSValue::QJSValue(const QLatin1String &value)
{
- QJSValuePrivate::setVariant(this, QVariant(value));
+ QJSValuePrivate::setString(this, QString(value));
}
/*!
@@ -260,7 +245,7 @@ QJSValue::QJSValue(const QLatin1String &value)
#ifndef QT_NO_CAST_FROM_ASCII
QJSValue::QJSValue(const char *value)
{
- QJSValuePrivate::setVariant(this, QVariant(QString::fromUtf8(value)));
+ QJSValuePrivate::setString(this, QString(QString::fromUtf8(value)));
}
#endif
@@ -271,15 +256,12 @@ QJSValue::QJSValue(const char *value)
true), then only a reference to the underlying object is copied into
the new script value (i.e., the object itself is not copied).
*/
-QJSValue::QJSValue(const QJSValue& other)
- : d(0)
+QJSValue::QJSValue(const QJSValue &other) : d(0)
{
- QV4::Value *v = QJSValuePrivate::getValue(&other);
- if (v) {
- QJSValuePrivate::setValue(this, QJSValuePrivate::engine(&other), *v);
- } else if (QVariant *v = QJSValuePrivate::getVariant(&other)) {
- QJSValuePrivate::setVariant(this, *v);
- }
+ if (const QString *string = QJSValuePrivate::asQString(&other))
+ QJSValuePrivate::setString(this, *string);
+ else
+ QJSValuePrivate::setValue(this, QJSValuePrivate::asReturnedValue(&other));
}
/*!
@@ -310,11 +292,7 @@ QJSValue::~QJSValue()
*/
bool QJSValue::isBool() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (val)
- return val->isBoolean();
- QVariant *variant = QJSValuePrivate::getVariant(this);
- return variant && variant->userType() == QMetaType::Bool;
+ return QV4::Value::fromReturnedValue(d).isBoolean();
}
/*!
@@ -325,27 +303,7 @@ bool QJSValue::isBool() const
*/
bool QJSValue::isNumber() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (val)
- return val->isNumber();
- QVariant *variant = QJSValuePrivate::getVariant(this);
- if (!variant)
- return false;
-
- switch (variant->userType()) {
- case QMetaType::Double:
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Long:
- case QMetaType::ULong:
- case QMetaType::Short:
- case QMetaType::UShort:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- return true;
- default:
- return false;
- }
+ return QV4::Value::fromReturnedValue(d).isNumber();
}
/*!
@@ -354,14 +312,7 @@ bool QJSValue::isNumber() const
*/
bool QJSValue::isNull() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (val)
- return val->isNull();
- QVariant *variant = QJSValuePrivate::getVariant(this);
- if (!variant)
- return false;
- const int type = variant->userType();
- return type == QMetaType::Nullptr || type == QMetaType::VoidStar;
+ return QV4::Value::fromReturnedValue(d).isNull();
}
/*!
@@ -372,24 +323,27 @@ bool QJSValue::isNull() const
*/
bool QJSValue::isString() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (val)
- return val->isString();
- QVariant *variant = QJSValuePrivate::getVariant(this);
- return variant && variant->userType() == QMetaType::QString;
+ if (QJSValuePrivate::asQString(this))
+ return true;
+
+ // String is managed
+ return QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)).isString();
}
/*!
- Returns true if this QJSValue is of the primitive type Undefined;
- otherwise returns false.
+ Returns true if this QJSValue is of the primitive type Undefined or if the managed value
+ has been cleared (by deleting the engine). Otherwise returns false.
*/
bool QJSValue::isUndefined() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (val)
- return val->isUndefined();
- QVariant *variant = QJSValuePrivate::getVariant(this);
- return !variant || variant->userType() == QMetaType::UnknownType || variant->userType() == QMetaType::Void;
+ if (QJSValuePrivate::asQString(this))
+ return false;
+ QV4::Value v = QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this));
+ if (v.isUndefined())
+ return true;
+ if (!v.isManaged())
+ return false;
+ return v.managed() == nullptr;
}
/*!
@@ -400,10 +354,7 @@ bool QJSValue::isUndefined() const
*/
bool QJSValue::isError() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (!val)
- return false;
- return val->as<ErrorObject>();
+ return QJSValuePrivate::asManagedType<ErrorObject>(this);
}
/*!
@@ -415,10 +366,7 @@ bool QJSValue::isError() const
*/
QJSValue::ErrorType QJSValue::errorType() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (!val)
- return NoError;
- QV4::ErrorObject *error = val->as<ErrorObject>();
+ const QV4::ErrorObject *error = QJSValuePrivate::asManagedType<ErrorObject>(this);
if (!error)
return NoError;
switch (error->d()->errorType) {
@@ -449,10 +397,7 @@ QJSValue::ErrorType QJSValue::errorType() const
*/
bool QJSValue::isArray() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (!val)
- return false;
- return val->as<ArrayObject>();
+ return QJSValuePrivate::asManagedType<ArrayObject>(this);
}
/*!
@@ -466,10 +411,7 @@ bool QJSValue::isArray() const
*/
bool QJSValue::isObject() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (!val)
- return false;
- return val->as<QV4::Object>();
+ return QJSValuePrivate::asManagedType<QV4::Object>(this);
}
/*!
@@ -480,10 +422,7 @@ bool QJSValue::isObject() const
*/
bool QJSValue::isCallable() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (!val)
- return false;
- return val->as<FunctionObject>();
+ return QJSValuePrivate::asManagedType<FunctionObject>(this);
}
/*!
@@ -494,10 +433,7 @@ bool QJSValue::isCallable() const
*/
bool QJSValue::isVariant() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (!val)
- return false;
- return val->as<QV4::VariantObject>();
+ return QJSValuePrivate::asManagedType<QV4::VariantObject>(this);
}
/*!
@@ -514,27 +450,22 @@ bool QJSValue::isVariant() const
*/
QString QJSValue::toString() const
{
- QV4::Value scratch;
- QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
-
- if (!val) {
- QVariant *variant = QJSValuePrivate::getVariant(this);
- Q_ASSERT(variant);
- if (variant->userType() == QMetaType::QVariantMap)
- return QStringLiteral("[object Object]");
- else if (variant->userType() == QMetaType::QVariantList) {
- const QVariantList list = variant->toList();
- QString result;
- for (int i = 0; i < list.count(); ++i) {
- if (i > 0)
- result.append(QLatin1Char(','));
- result.append(list.at(i).toString());
- }
- return result;
- }
- return variant->toString();
+ if (const QString *string = QJSValuePrivate::asQString(this))
+ return *string;
+
+ return QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this)).toQStringNoThrow();
+}
+
+template<typename T>
+T caughtResult(const QJSValue *v, T (QV4::Value::*convert)() const)
+{
+ const T result = (QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(v)).*convert)();
+ QV4::ExecutionEngine *engine = QJSValuePrivate::engine(v);
+ if (engine && engine->hasException) {
+ engine->catchException();
+ return T();
}
- return val->toQStringNoThrow();
+ return result;
}
/*!
@@ -551,28 +482,10 @@ QString QJSValue::toString() const
*/
double QJSValue::toNumber() const
{
- QV4::Value scratch;
- QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
-
- if (!val) {
- QVariant *variant = QJSValuePrivate::getVariant(this);
- Q_ASSERT(variant);
-
- if (variant->userType() == QMetaType::QString)
- return RuntimeHelpers::stringToNumber(variant->toString());
- else if (variant->canConvert<double>())
- return variant->value<double>();
- else
- return std::numeric_limits<double>::quiet_NaN();
- }
+ if (const QString *string = QJSValuePrivate::asQString(this))
+ return RuntimeHelpers::stringToNumber(*string);
- double dbl = val->toNumber();
- QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
- if (engine && engine->hasException) {
- engine->catchException();
- return 0;
- }
- return dbl;
+ return caughtResult<double>(this, &QV4::Value::toNumber);
}
/*!
@@ -589,24 +502,10 @@ double QJSValue::toNumber() const
*/
bool QJSValue::toBool() const
{
- QV4::Value scratch;
- QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
-
- if (!val) {
- QVariant *variant = QJSValuePrivate::getVariant(this);
- if (variant->userType() == QMetaType::QString)
- return variant->toString().length() > 0;
- else
- return variant->toBool();
- }
+ if (const QString *string = QJSValuePrivate::asQString(this))
+ return string->length() > 0;
- bool b = val->toBoolean();
- QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
- if (engine && engine->hasException) {
- engine->catchException();
- return false;
- }
- return b;
+ return caughtResult<bool>(this, &QV4::Value::toBoolean);
}
/*!
@@ -623,24 +522,10 @@ bool QJSValue::toBool() const
*/
qint32 QJSValue::toInt() const
{
- QV4::Value scratch;
- QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
-
- if (!val) {
- QVariant *variant = QJSValuePrivate::getVariant(this);
- if (variant->userType() == QMetaType::QString)
- return QV4::Value::toInt32(RuntimeHelpers::stringToNumber(variant->toString()));
- else
- return variant->toInt();
- }
+ if (const QString *string = QJSValuePrivate::asQString(this))
+ return QV4::Value::toInt32(RuntimeHelpers::stringToNumber(*string));
- qint32 i = val->toInt32();
- QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
- if (engine && engine->hasException) {
- engine->catchException();
- return 0;
- }
- return i;
+ return caughtResult<qint32>(this, &QV4::Value::toInt32);
}
/*!
@@ -657,24 +542,10 @@ qint32 QJSValue::toInt() const
*/
quint32 QJSValue::toUInt() const
{
- QV4::Value scratch;
- QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
-
- if (!val) {
- QVariant *variant = QJSValuePrivate::getVariant(this);
- if (variant->userType() == QMetaType::QString)
- return QV4::Value::toUInt32(RuntimeHelpers::stringToNumber(variant->toString()));
- else
- return variant->toUInt();
- }
+ if (const QString *string = QJSValuePrivate::asQString(this))
+ return QV4::Value::toUInt32(RuntimeHelpers::stringToNumber(*string));
- quint32 u = val->toUInt32();
- QV4::ExecutionEngine *engine = QJSValuePrivate::engine(this);
- if (engine && engine->hasException) {
- engine->catchException();
- return 0;
- }
- return u;
+ return caughtResult<quint32>(this, &QV4::Value::toUInt32);
}
/*!
@@ -701,29 +572,29 @@ quint32 QJSValue::toUInt() const
*/
QVariant QJSValue::toVariant() const
{
- QVariant *variant = QJSValuePrivate::getVariant(this);
- if (variant)
- return *variant;
-
- QV4::Value scratch;
- QV4::Value *val = QJSValuePrivate::valueForData(this, &scratch);
- Q_ASSERT(val);
-
- if (QV4::Object *o = val->as<QV4::Object>())
- return o->engine()->toVariant(*val, /*typeHint*/ -1, /*createJSValueForObjects*/ false);
-
- if (String *s = val->stringValue())
- return QVariant(s->toQString());
- if (val->isBoolean())
- return QVariant(val->booleanValue());
- if (val->isNumber()) {
- if (val->isInt32())
- return QVariant(val->integerValue());
- return QVariant(val->asDouble());
- }
- if (val->isNull())
+ if (const QString *string = QJSValuePrivate::asQString(this))
+ return QVariant(*string);
+
+ QV4::Value val = QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(this));
+ if (val.isUndefined())
+ return QVariant();
+ if (val.isNull())
return QVariant(QMetaType::Nullptr, nullptr);
- Q_ASSERT(val->isUndefined());
+ if (val.isBoolean())
+ return QVariant(val.booleanValue());
+ if (val.isInt32()) // Includes doubles that can be losslessly casted to int
+ return QVariant(val.integerValue());
+ if (val.isNumber())
+ return QVariant(val.doubleValue());
+
+ Q_ASSERT(val.isManaged());
+
+ if (val.isString())
+ return QVariant(val.toQString());
+ if (QV4::Managed *m = val.as<QV4::Managed>())
+ return m->engine()->toVariant(val, /*typeHint*/ -1, /*createJSValueForObjects*/ false);
+
+ Q_ASSERT(false);
return QVariant();
}
@@ -742,13 +613,9 @@ QVariant QJSValue::toVariant() const
\sa isCallable(), callWithInstance(), callAsConstructor()
*/
-QJSValue QJSValue::call(const QJSValueList &args)
+QJSValue QJSValue::call(const QJSValueList &args) const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (!val)
- return QJSValue();
-
- FunctionObject *f = val->as<FunctionObject>();
+ const FunctionObject *f = QJSValuePrivate::asManagedType<FunctionObject>(this);
if (!f)
return QJSValue();
@@ -763,7 +630,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
return QJSValue();
}
- jsCallData->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i));
+ jsCallData->args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
}
ScopedValue result(scope, f->call(jsCallData));
@@ -772,7 +639,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
if (engine->isInterrupted.loadAcquire())
result = engine->newErrorObject(QStringLiteral("Interrupted"));
- return QJSValue(engine, result->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
}
/*!
@@ -795,13 +662,9 @@ QJSValue QJSValue::call(const QJSValueList &args)
\sa call()
*/
-QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList &args)
+QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList &args) const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (!val)
- return QJSValue();
-
- FunctionObject *f = val->as<FunctionObject>();
+ const FunctionObject *f = QJSValuePrivate::asManagedType<FunctionObject>(this);
if (!f)
return QJSValue();
@@ -815,13 +678,13 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
}
JSCallData jsCallData(scope, args.size());
- *jsCallData->thisObject = QJSValuePrivate::convertedToValue(engine, instance);
+ *jsCallData->thisObject = QJSValuePrivate::convertToReturnedValue(engine, instance);
for (int i = 0; i < args.size(); ++i) {
if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
return QJSValue();
}
- jsCallData->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i));
+ jsCallData->args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
}
ScopedValue result(scope, f->call(jsCallData));
@@ -830,7 +693,7 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
if (engine->isInterrupted.loadAcquire())
result = engine->newErrorObject(QStringLiteral("Interrupted"));
- return QJSValue(engine, result->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
}
/*!
@@ -851,13 +714,9 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
\sa call(), QJSEngine::newObject()
*/
-QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
+QJSValue QJSValue::callAsConstructor(const QJSValueList &args) const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (!val)
- return QJSValue();
-
- FunctionObject *f = val->as<FunctionObject>();
+ const FunctionObject *f = QJSValuePrivate::asManagedType<FunctionObject>(this);
if (!f)
return QJSValue();
@@ -871,7 +730,7 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
return QJSValue();
}
- jsCallData->args[i] = QJSValuePrivate::convertedToValue(engine, args.at(i));
+ jsCallData->args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
}
ScopedValue result(scope, f->callAsConstructor(jsCallData));
@@ -880,7 +739,7 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
if (engine->isInterrupted.loadAcquire())
result = engine->newErrorObject(QStringLiteral("Interrupted"));
- return QJSValue(engine, result->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
}
#ifdef QT_DEPRECATED
@@ -915,13 +774,13 @@ QJSValue QJSValue::prototype() const
if (!engine)
return QJSValue();
QV4::Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this)->as<QV4::Object>());
+ ScopedObject o(scope, QJSValuePrivate::asManagedType<QV4::Object>(this));
if (!o)
return QJSValue();
ScopedObject p(scope, o->getPrototypeOf());
if (!p)
return QJSValue(NullValue);
- return QJSValue(o->internalClass()->engine, p.asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(p.asReturnedValue());
}
/*!
@@ -942,14 +801,11 @@ void QJSValue::setPrototype(const QJSValue& prototype)
if (!engine)
return;
Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this));
+ ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
if (!o)
return;
- QV4::Value scratch;
- QV4::Value *val = QJSValuePrivate::valueForData(&prototype, &scratch);
- if (!val)
- return;
- if (val->isNull()) {
+ QV4::Value val = QV4::Value::fromReturnedValue(QJSValuePrivate::asReturnedValue(&prototype));
+ if (val.isNull()) {
o->setPrototypeOf(nullptr);
return;
}
@@ -980,12 +836,11 @@ QJSValue& QJSValue::operator=(const QJSValue& other)
QJSValuePrivate::free(this);
d = 0;
- QV4::Value *v = QJSValuePrivate::getValue(&other);
- if (v) {
- QJSValuePrivate::setValue(this, QJSValuePrivate::engine(&other), *v);
- } else if (QVariant *v = QJSValuePrivate::getVariant(&other)) {
- QJSValuePrivate::setVariant(this, *v);
- }
+ if (const QString *string = QJSValuePrivate::asQString(&other))
+ QJSValuePrivate::setString(this, *string);
+ else
+ QJSValuePrivate::setValue(this, QJSValuePrivate::asReturnedValue(&other));
+
return *this;
}
@@ -1031,23 +886,17 @@ static bool js_equal(const QString &string, const QV4::Value &value)
*/
bool QJSValue::equals(const QJSValue& other) const
{
- QV4::Value s1, s2;
- QV4::Value *v = QJSValuePrivate::valueForData(this, &s1);
- QV4::Value *ov = QJSValuePrivate::valueForData(&other, &s2);
-
- if (!v) {
- QVariant *variant = QJSValuePrivate::getVariant(this);
- Q_ASSERT(variant);
- if (!ov)
- return *variant == *QJSValuePrivate::getVariant(&other);
- if (variant->userType() == QMetaType::QVariantMap || variant->userType() == QMetaType::QVariantList)
- return false;
- return js_equal(variant->toString(), *ov);
- }
- if (!ov)
- return other.equals(*this);
+ if (const QString *string = QJSValuePrivate::asQString(this)) {
+ if (const QString *otherString = QJSValuePrivate::asQString(&other))
+ return *string == *otherString;
+ return js_equal(*string, QJSValuePrivate::asReturnedValue(&other));
+ }
+
+ if (const QString *otherString = QJSValuePrivate::asQString(&other))
+ return js_equal(*otherString, QJSValuePrivate::asReturnedValue(this));
- return Runtime::CompareEqual::call(*v, *ov);
+ return Runtime::CompareEqual::call(QJSValuePrivate::asReturnedValue(this),
+ QJSValuePrivate::asReturnedValue(&other));
}
/*!
@@ -1074,25 +923,22 @@ bool QJSValue::equals(const QJSValue& other) const
*/
bool QJSValue::strictlyEquals(const QJSValue& other) const
{
- QV4::Value s1, s2;
- QV4::Value *v = QJSValuePrivate::valueForData(this, &s1);
- QV4::Value *ov = QJSValuePrivate::valueForData(&other, &s2);
-
- if (!v) {
- QVariant *variant = QJSValuePrivate::getVariant(this);
- Q_ASSERT(variant);
- if (!ov)
- return *variant == *QJSValuePrivate::getVariant(&other);
- if (variant->userType() == QMetaType::QVariantMap || variant->userType() == QMetaType::QVariantList)
- return false;
- if (String *s = ov->stringValue())
- return variant->toString() == s->toQString();
+ if (const QString *string = QJSValuePrivate::asQString(this)) {
+ if (const QString *otherString = QJSValuePrivate::asQString(&other))
+ return *string == *otherString;
+ if (const String *s = QJSValuePrivate::asManagedType<String>(&other))
+ return *string == s->toQString();
return false;
}
- if (!ov)
- return other.strictlyEquals(*this);
- return RuntimeHelpers::strictEqual(*v, *ov);
+ if (const QString *otherString = QJSValuePrivate::asQString(&other)) {
+ if (const String *s = QJSValuePrivate::asManagedType<String>(this))
+ return *otherString == s->toQString();
+ return false;
+ }
+
+ return RuntimeHelpers::strictEqual(QJSValuePrivate::asReturnedValue(this),
+ QJSValuePrivate::asReturnedValue(&other));
}
/*!
@@ -1119,7 +965,7 @@ QJSValue QJSValue::property(const QString& name) const
return QJSValue();
QV4::Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this));
+ ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
if (!o)
return QJSValue();
@@ -1128,7 +974,7 @@ QJSValue QJSValue::property(const QString& name) const
if (engine->hasException)
result = engine->catchException();
- return QJSValue(engine, result->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
}
/*!
@@ -1167,14 +1013,14 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
return QJSValue();
QV4::Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this));
+ ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
if (!o)
return QJSValue();
QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax()) : o->get(arrayIndex));
if (engine->hasException)
engine->catchException();
- return QJSValue(engine, result->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
}
/*!
@@ -1199,7 +1045,7 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value)
return;
Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this));
+ ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
if (!o)
return;
@@ -1209,7 +1055,7 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value)
}
ScopedString s(scope, engine->newString(name));
- QV4::ScopedValue v(scope, QJSValuePrivate::convertedToValue(engine, value));
+ QV4::ScopedValue v(scope, QJSValuePrivate::convertToReturnedValue(engine, value));
o->put(s->toPropertyKey(), v);
if (engine->hasException)
engine->catchException();
@@ -1253,7 +1099,7 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
return;
Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this));
+ ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
if (!o)
return;
@@ -1262,7 +1108,7 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
return;
}
- QV4::ScopedValue v(scope, QJSValuePrivate::convertedToValue(engine, value));
+ QV4::ScopedValue v(scope, QJSValuePrivate::convertToReturnedValue(engine, value));
PropertyKey id = arrayIndex != UINT_MAX ? PropertyKey::fromArrayIndex(arrayIndex) : engine->id_uintMax()->propertyKey();
o->put(id, v);
if (engine->hasException)
@@ -1296,7 +1142,7 @@ bool QJSValue::deleteProperty(const QString &name)
return false;
Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this));
+ ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
if (!o)
return false;
@@ -1317,7 +1163,7 @@ bool QJSValue::hasProperty(const QString &name) const
return false;
Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this));
+ ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
if (!o)
return false;
@@ -1338,7 +1184,7 @@ bool QJSValue::hasOwnProperty(const QString &name) const
return false;
Scope scope(engine);
- ScopedObject o(scope, QJSValuePrivate::getValue(this));
+ ScopedObject o(scope, QJSValuePrivate::asReturnedValue(this));
if (!o)
return false;
@@ -1362,7 +1208,7 @@ QObject *QJSValue::toQObject() const
if (!engine)
return nullptr;
QV4::Scope scope(engine);
- QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, QJSValuePrivate::getValue(this));
+ QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, QJSValuePrivate::asReturnedValue(this));
if (!wrapper)
return nullptr;
@@ -1383,7 +1229,7 @@ const QMetaObject *QJSValue::toQMetaObject() const
if (!engine)
return nullptr;
QV4::Scope scope(engine);
- QV4::Scoped<QV4::QMetaObjectWrapper> wrapper(scope, QJSValuePrivate::getValue(this));
+ QV4::Scoped<QV4::QMetaObjectWrapper> wrapper(scope, QJSValuePrivate::asReturnedValue(this));
if (!wrapper)
return nullptr;
@@ -1400,12 +1246,8 @@ const QMetaObject *QJSValue::toQMetaObject() const
*/
QDateTime QJSValue::toDateTime() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- if (val) {
- QV4::DateObject *date = val->as<DateObject>();
- if (date)
- return date->toQDateTime();
- }
+ if (const QV4::DateObject *date = QJSValuePrivate::asManagedType<DateObject>(this))
+ return date->toQDateTime();
return QDateTime();
}
@@ -1415,8 +1257,7 @@ QDateTime QJSValue::toDateTime() const
*/
bool QJSValue::isDate() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- return val && val->as<DateObject>();
+ return QJSValuePrivate::asManagedType<DateObject>(this);
}
/*!
@@ -1425,8 +1266,7 @@ bool QJSValue::isDate() const
*/
bool QJSValue::isRegExp() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- return val && val->as<RegExpObject>();
+ return QJSValuePrivate::asManagedType<RegExpObject>(this);
}
/*!
@@ -1440,8 +1280,7 @@ bool QJSValue::isRegExp() const
*/
bool QJSValue::isQObject() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- return val && val->as<QV4::QObjectWrapper>() != nullptr;
+ return QJSValuePrivate::asManagedType<QV4::QObjectWrapper>(this);
}
/*!
@@ -1454,8 +1293,7 @@ bool QJSValue::isQObject() const
*/
bool QJSValue::isQMetaObject() const
{
- QV4::Value *val = QJSValuePrivate::getValue(this);
- return val && val->as<QV4::QMetaObjectWrapper>() != nullptr;
+ return QJSValuePrivate::asManagedType<QV4::QMetaObjectWrapper>(this);
}
QT_END_NAMESPACE
diff --git a/src/qml/jsapi/qjsvalue.h b/src/qml/jsapi/qjsvalue.h
index 2f95e0ff31..091f353291 100644
--- a/src/qml/jsapi/qjsvalue.h
+++ b/src/qml/jsapi/qjsvalue.h
@@ -144,22 +144,21 @@ public:
bool deleteProperty(const QString &name);
bool isCallable() const;
- QJSValue call(const QJSValueList &args = QJSValueList()); // ### Qt6: Make const
- QJSValue callWithInstance(const QJSValue &instance, const QJSValueList &args = QJSValueList()); // ### Qt6: Make const
- QJSValue callAsConstructor(const QJSValueList &args = QJSValueList()); // ### Qt6: Make const
+ QJSValue call(const QJSValueList &args = QJSValueList()) const;
+ QJSValue callWithInstance(const QJSValue &instance, const QJSValueList &args = QJSValueList()) const;
+ QJSValue callAsConstructor(const QJSValueList &args = QJSValueList()) const;
ErrorType errorType() const;
#ifdef QT_DEPRECATED
QT_DEPRECATED QJSEngine *engine() const;
#endif
- QJSValue(QV4::ExecutionEngine *e, quint64 val);
private:
friend class QJSValuePrivate;
// force compile error, prevent QJSValue(bool) to be called
QJSValue(void *) Q_DECL_EQ_DELETE;
- mutable quintptr d;
+ quint64 d;
};
QT_END_NAMESPACE
diff --git a/src/qml/jsapi/qjsvalue_p.h b/src/qml/jsapi/qjsvalue_p.h
index 2faffffbae..5533682144 100644
--- a/src/qml/jsapi/qjsvalue_p.h
+++ b/src/qml/jsapi/qjsvalue_p.h
@@ -64,132 +64,181 @@
QT_BEGIN_NAMESPACE
+// QJSValue::d is a QV4::ReturnedValue, but we don't want to expose that in the public header.
+// We use the lower bits of the managed pointer to hide a QString* or a QV4::Value* in there.
+Q_STATIC_ASSERT(sizeof(QV4::ReturnedValue) == sizeof(quint64));
+Q_STATIC_ASSERT(alignof(QV4::Value) >= 4);
+Q_STATIC_ASSERT(alignof(QString) >= 4);
+
+enum PointerMask: quintptr {
+ IsV4Value = 0x0,
+ IsString = 0x1
+};
+
class Q_AUTOTEST_EXPORT QJSValuePrivate
{
+ static const QV4::Value *managedValue(const QV4::Value &v)
+ {
+ const quintptr m = quintptr(v.m());
+ return (m & IsString) ? nullptr : reinterpret_cast<QV4::Value *>(m);
+ }
+
+ static const QString *qstring(const QV4::Value &v)
+ {
+ const quintptr m = quintptr(v.m());
+ return (m & IsString) ? reinterpret_cast<QString *>(m & ~IsString) : nullptr;
+ }
+
+ static QV4::ReturnedValue encode(const QString &string)
+ {
+ const quintptr m = quintptr(new QString(string)) | IsString;
+ return encodeRawValue(m);
+ }
+
+ static QV4::ReturnedValue encode(const QV4::Value &managedValue)
+ {
+ QV4::Value *m = managedValue.as<QV4::Managed>()->engine()
+ ->memoryManager->m_persistentValues->allocate();
+ *m = managedValue;
+ return encodeRawValue(quintptr(m));
+ }
+
+ static QV4::ReturnedValue encodeRawValue(quintptr m)
+ {
+ return QV4::Value::fromHeapObject(reinterpret_cast<QV4::Heap::Base *>(m)).asReturnedValue();
+ }
+
+protected:
+ // Only for the test. You're not supposed to subclass QJSValuePrivate otherwise.
+ static void setRawValue(QJSValue *jsval, QV4::Value *m)
+ {
+ jsval->d = encodeRawValue(quintptr(m));
+ }
+
public:
- static inline QV4::Value *getValue(const QJSValue *jsval)
+ static QJSValue fromReturnedValue(QV4::ReturnedValue d)
{
- if (jsval->d & 3)
- return nullptr;
- return reinterpret_cast<QV4::Value *>(jsval->d);
+ QJSValue result;
+ setValue(&result, d);
+ return result;
}
- static inline QVariant *getVariant(const QJSValue *jsval)
+ template<typename T>
+ static const T *asManagedType(const QJSValue *jsval)
{
- if (jsval->d & 1)
- return reinterpret_cast<QVariant *>(jsval->d & ~3);
+ const QV4::Value v = QV4::Value::fromReturnedValue(jsval->d);
+ if (!v.isManaged())
+ return nullptr;
+ if (const QV4::Value *value = managedValue(v))
+ return value->as<T>();
return nullptr;
}
- static inline void setRawValue(QJSValue *jsval, QV4::Value *v)
+ static QV4::ReturnedValue asPrimitiveType(const QJSValue *jsval)
{
- jsval->d = reinterpret_cast<quintptr>(v);
+ const QV4::Value v = QV4::Value::fromReturnedValue(jsval->d);
+ return v.isManaged() ? QV4::Encode::undefined() : v.asReturnedValue();
}
- static inline void setVariant(QJSValue *jsval, const QVariant &v) {
- QVariant *val = new QVariant(v);
- jsval->d = reinterpret_cast<quintptr>(val) | 1;
+ // Beware: This only returns a non-null string if the QJSValue actually holds one.
+ // QV4::Strings are kept as managed values. Retrieve those with getValue().
+ static const QString *asQString(const QJSValue *jsval)
+ {
+ const QV4::Value v = QV4::Value::fromReturnedValue(jsval->d);
+ return v.isManaged() ? qstring(v) : nullptr;
}
- static inline void setValue(QJSValue *jsval, QV4::ExecutionEngine *engine, const QV4::Value &v) {
- QV4::Value *value = engine->memoryManager->m_persistentValues->allocate();
- *value = v;
- jsval->d = reinterpret_cast<quintptr>(value);
+ static QV4::ReturnedValue asReturnedValue(const QJSValue *jsval)
+ {
+ const QV4::Value v = QV4::Value::fromReturnedValue(jsval->d);
+ if (!v.isManaged())
+ return v.asReturnedValue();
+
+ if (const QV4::Value *value = managedValue(v))
+ return value->asReturnedValue();
+
+ return QV4::Encode::undefined();
}
- static inline void setValue(QJSValue *jsval, QV4::ExecutionEngine *engine, QV4::ReturnedValue v) {
- QV4::Value *value = engine->memoryManager->m_persistentValues->allocate();
- *value = v;
- jsval->d = reinterpret_cast<quintptr>(value);
+ static void setString(QJSValue *jsval, const QString &s)
+ {
+ jsval->d = encode(s);
}
- static QV4::ReturnedValue convertedToValue(QV4::ExecutionEngine *e, const QJSValue &jsval)
+ static void setValue(QJSValue *jsval, const QV4::Value &v)
{
- QV4::Value *v = getValue(&jsval);
- if (!v) {
- QVariant *variant = getVariant(&jsval);
- v = e->memoryManager->m_persistentValues->allocate();
- *v = variant ? e->fromVariant(*variant) : QV4::Encode::undefined();
- jsval.d = reinterpret_cast<quintptr>(v);
- delete variant;
+ jsval->d = v.isManaged() ? encode(v) : v.asReturnedValue();
+ }
+
+ // Moves any QString onto the V4 heap, changing the value to reflect that.
+ static void manageStringOnV4Heap(QV4::ExecutionEngine *e, QJSValue *jsval)
+ {
+ if (const QString *string = asQString(jsval)) {
+ jsval->d = encode(e->newString(*string)->asReturnedValue());
+ delete string;
}
+ }
+
+ // Converts any QString on the fly, involving an allocation.
+ // Does not change the value.
+ static QV4::ReturnedValue convertToReturnedValue(QV4::ExecutionEngine *e,
+ const QJSValue &jsval)
+ {
+ if (const QString *string = asQString(&jsval))
+ return e->newString(*string)->asReturnedValue();
+ if (const QV4::Value *val = asManagedType<QV4::Managed>(&jsval)) {
+ if (QV4::PersistentValueStorage::getEngine(val) == e)
+ return val->asReturnedValue();
- if (QV4::PersistentValueStorage::getEngine(v) != e) {
qWarning("JSValue can't be reassigned to another engine.");
return QV4::Encode::undefined();
}
-
- return v->asReturnedValue();
+ return jsval.d;
}
- static QV4::Value *valueForData(const QJSValue *jsval, QV4::Value *scratch)
+ static QV4::ExecutionEngine *engine(const QJSValue *jsval)
{
- QV4::Value *v = getValue(jsval);
- if (v)
- return v;
- v = scratch;
- QVariant *variant = getVariant(jsval);
- if (!variant) {
- *v = QV4::Encode::undefined();
- return v;
- }
-
- switch (variant->userType()) {
- case QMetaType::UnknownType:
- case QMetaType::Void:
- *v = QV4::Encode::undefined();
- break;
- case QMetaType::Nullptr:
- case QMetaType::VoidStar:
- *v = QV4::Encode::null();
- break;
- case QMetaType::Bool:
- *v = QV4::Encode(variant->toBool());
- break;
- case QMetaType::Double:
- *v = QV4::Encode(variant->toDouble());
- break;
- case QMetaType::Int:
- case QMetaType::Short:
- case QMetaType::UShort:
- case QMetaType::Char:
- case QMetaType::UChar:
- *v = QV4::Encode(variant->toInt());
- break;
- case QMetaType::UInt:
- *v = QV4::Encode(variant->toUInt());
- break;
- default:
+ const QV4::Value v = QV4::Value::fromReturnedValue(jsval->d);
+ if (!v.isManaged())
return nullptr;
- }
- return v;
- }
- static QV4::ExecutionEngine *engine(const QJSValue *jsval) {
- QV4::Value *v = getValue(jsval);
- return v ? QV4::PersistentValueStorage::getEngine(v) : nullptr;
+ if (const QV4::Value *m = managedValue(v))
+ return QV4::PersistentValueStorage::getEngine(m);
+
+ return nullptr;
}
- static inline bool checkEngine(QV4::ExecutionEngine *e, const QJSValue &jsval) {
+ static bool checkEngine(QV4::ExecutionEngine *e, const QJSValue &jsval)
+ {
QV4::ExecutionEngine *v4 = engine(&jsval);
return !v4 || v4 == e;
}
- static inline void free(QJSValue *jsval) {
- if (QV4::Value *v = QJSValuePrivate::getValue(jsval)) {
- if (QV4::ExecutionEngine *e = engine(jsval)) {
- if (QJSEngine *jsEngine = e->jsEngine()) {
- if (jsEngine->thread() != QThread::currentThread()) {
- QMetaObject::invokeMethod(
- jsEngine, [v](){ QV4::PersistentValueStorage::free(v); });
- return;
- }
+ static void free(QJSValue *jsval)
+ {
+ QV4::Value v = QV4::Value::fromReturnedValue(jsval->d);
+ if (!v.isManaged())
+ return;
+
+ if (const QString *m = qstring(v)) {
+ delete m;
+ return;
+ }
+
+ // We need a mutable value for free(). It needs to write to the actual memory.
+ Q_ASSERT(!(quintptr(v.m()) & IsString));
+ QV4::Value *m = reinterpret_cast<QV4::Value *>(v.m());
+ Q_ASSERT(m); // Otherwise it would have been undefined, that is !v.isManaged() above.
+ if (QV4::ExecutionEngine *e = QV4::PersistentValueStorage::getEngine(m)) {
+ if (QJSEngine *jsEngine = e->jsEngine()) {
+ if (jsEngine->thread() != QThread::currentThread()) {
+ QMetaObject::invokeMethod(
+ jsEngine, [m](){ QV4::PersistentValueStorage::free(m); });
+ return;
}
}
- QV4::PersistentValueStorage::free(v);
- } else if (QVariant *v = QJSValuePrivate::getVariant(jsval)) {
- delete v;
}
+ QV4::PersistentValueStorage::free(m);
}
};
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index 076b90c5f2..360a39aea3 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -58,12 +58,12 @@ void QJSValueIteratorPrivate::init(const QJSValue &v)
QV4::ExecutionEngine *e = QJSValuePrivate::engine(&v);
if (!e)
return;
- QV4::Object *o = QJSValuePrivate::getValue(&v)->objectValue();
+ const QV4::Object *o = QJSValuePrivate::asManagedType<QV4::Object>(&v);
if (!o)
return;
engine = e;
- object = o;
+ object.set(e, o->asReturnedValue());
iterator.reset(o->ownPropertyKeys(object.valueRef()));
next();
}
@@ -209,7 +209,7 @@ QJSValue QJSValueIterator::value() const
scope.engine->catchException();
return QJSValue();
}
- return QJSValue(scope.engine, val->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(val->asReturnedValue());
}
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index 32acc6affc..adea21969d 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -59,10 +59,12 @@ SOURCES += \
$$PWD/qv4module.cpp \
$$PWD/qv4promiseobject.cpp \
$$PWD/qv4runtime.cpp \
+ $$PWD/qv4urlobject.cpp \
$$PWD/qv4value.cpp \
$$PWD/qv4compilationunitmapper.cpp \
$$PWD/qv4executablecompilationunit.cpp \
- $$PWD/qv4executableallocator.cpp
+ $$PWD/qv4executableallocator.cpp \
+ $$PWD/qv4resolvedtypereference.cpp
qtConfig(qml-debug): SOURCES += $$PWD/qv4profiling.cpp
@@ -134,11 +136,13 @@ HEADERS += \
$$PWD/qv4module_p.h \
$$PWD/qv4promiseobject_p.h \
$$PWD/qv4runtime_p.h \
+ $$PWD/qv4urlobject_p.h \
$$PWD/qv4value_p.h \
$$PWD/qv4compilationunitmapper_p.h \
$$PWD/qv4executablecompilationunit_p.h \
$$PWD/qv4functiontable_p.h \
- $$PWD/qv4runtimeapi_p.h
+ $$PWD/qv4runtimeapi_p.h \
+ $$PWD/qv4resolvedtypereference_p.h
qtConfig(qml-sequence-object) {
HEADERS += \
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
index a99ec16943..a2fac21b29 100644
--- a/src/qml/jsruntime/qv4arraybuffer.cpp
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -127,13 +127,17 @@ ReturnedValue ArrayBufferCtor::method_isView(const FunctionObject *, const Value
void Heap::SharedArrayBuffer::init(size_t length)
{
Object::init();
+ QPair<QTypedArrayData<char> *, char *> pair;
if (length < UINT_MAX)
- data = QTypedArrayData<char>::allocate(length + 1);
- if (!data) {
+ pair = QTypedArrayData<char>::allocate(length + 1);
+ if (!pair.first) {
+ new (&d) QArrayDataPointer<char>();
internalClass->engine->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
return;
}
- data->size = int(length);
+ auto data = new (&d) QArrayDataPointer<char>{ pair.first, pair.second, uint(length) };
+
+ // can't use appendInitialize() because we want to set the terminating '\0'
memset(data->data(), 0, length + 1);
isShared = true;
}
@@ -141,41 +145,24 @@ void Heap::SharedArrayBuffer::init(size_t length)
void Heap::SharedArrayBuffer::init(const QByteArray& array)
{
Object::init();
- data = const_cast<QByteArray&>(array).data_ptr();
- data->ref.ref();
+ new (&d) QArrayDataPointer<char>(*const_cast<QByteArray &>(array).data_ptr());
isShared = true;
}
void Heap::SharedArrayBuffer::destroy()
{
- if (data && !data->ref.deref())
- QTypedArrayData<char>::deallocate(data);
+ data().~QArrayDataPointer();
Object::destroy();
}
QByteArray ArrayBuffer::asByteArray() const
{
- QByteArrayDataPtr ba = { d()->data };
- ba.ptr->ref.ref();
- return QByteArray(ba);
+ return QByteArray(d()->data());
}
-void ArrayBuffer::detach() {
- if (!d()->data->ref.isShared())
- return;
-
- QTypedArrayData<char> *oldData = d()->data;
-
- d()->data = QTypedArrayData<char>::allocate(oldData->size + 1);
- if (!d()->data) {
- engine()->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
- return;
- }
-
- memcpy(d()->data->data(), oldData->data(), oldData->size + 1);
-
- if (!oldData->ref.deref())
- QTypedArrayData<char>::deallocate(oldData);
+void ArrayBuffer::detach()
+{
+ d()->data().detach();
}
@@ -200,7 +187,7 @@ ReturnedValue SharedArrayBufferPrototype::method_get_byteLength(const FunctionOb
if (!a || a->isDetachedBuffer() || !a->isSharedArrayBuffer())
return b->engine()->throwTypeError();
- return Encode(a->d()->data->size);
+ return Encode(a->d()->data()->size);
}
ReturnedValue SharedArrayBufferPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
@@ -217,12 +204,12 @@ ReturnedValue SharedArrayBufferPrototype::slice(const FunctionObject *b, const V
double start = argc > 0 ? argv[0].toInteger() : 0;
double end = (argc < 2 || argv[1].isUndefined()) ?
- a->d()->data->size : argv[1].toInteger();
+ a->d()->data()->size : argv[1].toInteger();
if (scope.hasException())
return QV4::Encode::undefined();
- double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size);
- double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size);
+ double first = (start < 0) ? qMax(a->d()->data()->size + start, 0.) : qMin(start, (double)a->d()->data()->size);
+ double final = (end < 0) ? qMax(a->d()->data()->size + end, 0.) : qMin(end, (double)a->d()->data()->size);
const FunctionObject *constructor = a->speciesConstructor(scope, shared ? scope.engine->sharedArrayBufferCtor() : scope.engine->arrayBufferCtor());
if (!constructor)
@@ -231,13 +218,13 @@ ReturnedValue SharedArrayBufferPrototype::slice(const FunctionObject *b, const V
double newLen = qMax(final - first, 0.);
ScopedValue argument(scope, QV4::Encode(newLen));
QV4::Scoped<SharedArrayBuffer> newBuffer(scope, constructor->callAsConstructor(argument, 1));
- if (!newBuffer || newBuffer->d()->data->size < (int)newLen ||
+ if (!newBuffer || newBuffer->d()->data()->size < newLen ||
newBuffer->isDetachedBuffer() || (newBuffer->isSharedArrayBuffer() != shared) ||
newBuffer->sameValue(*a) ||
a->isDetachedBuffer())
return scope.engine->throwTypeError();
- memcpy(newBuffer->d()->data->data(), a->d()->data->data() + (uint)first, newLen);
+ memcpy(newBuffer->d()->data()->data(), a->d()->data()->data() + (uint)first, newLen);
return newBuffer->asReturnedValue();
}
@@ -265,7 +252,7 @@ ReturnedValue ArrayBufferPrototype::method_get_byteLength(const FunctionObject *
if (!a || a->isDetachedBuffer() || a->isSharedArrayBuffer())
return f->engine()->throwTypeError();
- return Encode(a->d()->data->size);
+ return Encode(a->d()->data()->size);
}
ReturnedValue ArrayBufferPrototype::method_slice(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
diff --git a/src/qml/jsruntime/qv4arraybuffer_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index 8344fa2554..1873c41261 100644
--- a/src/qml/jsruntime/qv4arraybuffer_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -52,6 +52,7 @@
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
+#include <QtCore/qarraydatapointer.h>
QT_BEGIN_NAMESPACE
@@ -71,12 +72,14 @@ struct Q_QML_PRIVATE_EXPORT SharedArrayBuffer : Object {
void init(size_t length);
void init(const QByteArray& array);
void destroy();
- QTypedArrayData<char> *data;
+ std::aligned_storage_t<sizeof(QArrayDataPointer<char>), alignof(QArrayDataPointer<char>)> d;
+ const QArrayDataPointer<char> &data() const { return *reinterpret_cast<const QArrayDataPointer<char> *>(&d); }
+ QArrayDataPointer<char> &data() { return *reinterpret_cast<QArrayDataPointer<char> *>(&d); }
bool isShared;
- uint byteLength() const { return data ? data->size : 0; }
+ uint byteLength() const { return data().size; }
- bool isDetachedBuffer() const { return !data; }
+ bool isDetachedBuffer() const { return data().isNull(); }
bool isSharedArrayBuffer() const { return isShared; }
};
@@ -90,9 +93,7 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : SharedArrayBuffer {
isShared = false;
}
void detachArrayBuffer() {
- if (data && !data->ref.deref())
- QTypedArrayData<char>::deallocate(data);
- data = nullptr;
+ data().clear();
}
};
@@ -124,11 +125,11 @@ struct Q_QML_PRIVATE_EXPORT SharedArrayBuffer : Object
QByteArray asByteArray() const;
uint byteLength() const { return d()->byteLength(); }
- char *data() { Q_ASSERT(d()->data); return d()->data->data(); }
- const char *constData() { Q_ASSERT(d()->data); return d()->data->data(); }
+ char *data() { return d()->data()->data(); }
+ const char *constData() { return d()->data()->data(); }
- bool isShared() { return d()->data->ref.isShared(); }
- bool isDetachedBuffer() const { return !d()->data; }
+ bool isShared() { return d()->data()->isShared(); }
+ bool isDetachedBuffer() const { return d()->data().isNull(); }
bool isSharedArrayBuffer() const { return d()->isShared; }
};
@@ -140,11 +141,11 @@ struct Q_QML_PRIVATE_EXPORT ArrayBuffer : SharedArrayBuffer
QByteArray asByteArray() const;
uint byteLength() const { return d()->byteLength(); }
- char *data() { detach(); return d()->data ? d()->data->data() : nullptr; }
+ char *data() { if (d()->data().needsDetach()) detach(); return d()->data().data(); }
// ### is that detach needed?
- const char *constData() { detach(); return d()->data ? d()->data->data() : nullptr; }
+ const char *constData() const { return d()->data().data(); }
- bool isShared() { return d()->data && d()->data->ref.isShared(); }
+ bool isShared() { return d()->data()->isShared(); }
void detach();
void detachArrayBuffer() { d()->detachArrayBuffer(); }
};
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
index 5ab8cf2dcb..bb1acb963e 100644
--- a/src/qml/jsruntime/qv4dataview.cpp
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -85,7 +85,7 @@ ReturnedValue DataViewCtor::virtualCallAsConstructor(const FunctionObject *f, co
if (buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- uint bufferLength = buffer->d()->data->size;
+ uint bufferLength = buffer->d()->data()->size;
if (offset > bufferLength)
return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range"));
@@ -197,7 +197,7 @@ ReturnedValue DataViewPrototype::method_getChar(const FunctionObject *b, const V
return e->throwRangeError(QStringLiteral("index out of range"));
idx += v->d()->byteOffset;
- T t = T(v->d()->buffer->data->data()[idx]);
+ T t = T(v->d()->buffer->data()->data()[idx]);
return Encode((int)t);
}
@@ -221,8 +221,8 @@ ReturnedValue DataViewPrototype::method_get(const FunctionObject *b, const Value
bool littleEndian = argc < 2 ? false : argv[1].toBoolean();
T t = littleEndian
- ? qFromLittleEndian<T>((uchar *)v->d()->buffer->data->data() + idx)
- : qFromBigEndian<T>((uchar *)v->d()->buffer->data->data() + idx);
+ ? qFromLittleEndian<T>((uchar *)v->d()->buffer->data()->data() + idx)
+ : qFromBigEndian<T>((uchar *)v->d()->buffer->data()->data() + idx);
return Encode(t);
}
@@ -252,8 +252,8 @@ ReturnedValue DataViewPrototype::method_getFloat(const FunctionObject *b, const
float f;
} u;
u.i = littleEndian
- ? qFromLittleEndian<uint>((uchar *)v->d()->buffer->data->data() + idx)
- : qFromBigEndian<uint>((uchar *)v->d()->buffer->data->data() + idx);
+ ? qFromLittleEndian<uint>((uchar *)v->d()->buffer->data()->data() + idx)
+ : qFromBigEndian<uint>((uchar *)v->d()->buffer->data()->data() + idx);
return Encode(u.f);
} else {
Q_ASSERT(sizeof(T) == 8);
@@ -262,8 +262,8 @@ ReturnedValue DataViewPrototype::method_getFloat(const FunctionObject *b, const
double d;
} u;
u.i = littleEndian
- ? qFromLittleEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx)
- : qFromBigEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx);
+ ? qFromLittleEndian<quint64>((uchar *)v->d()->buffer->data()->data() + idx)
+ : qFromBigEndian<quint64>((uchar *)v->d()->buffer->data()->data() + idx);
return Encode(u.d);
}
}
@@ -288,7 +288,7 @@ ReturnedValue DataViewPrototype::method_setChar(const FunctionObject *b, const V
return e->throwRangeError(QStringLiteral("index out of range"));
idx += v->d()->byteOffset;
- v->d()->buffer->data->data()[idx] = (char)val;
+ v->d()->buffer->data()->data()[idx] = (char)val;
RETURN_UNDEFINED();
}
@@ -316,9 +316,9 @@ ReturnedValue DataViewPrototype::method_set(const FunctionObject *b, const Value
if (littleEndian)
- qToLittleEndian<T>(val, (uchar *)v->d()->buffer->data->data() + idx);
+ qToLittleEndian<T>(val, (uchar *)v->d()->buffer->data()->data() + idx);
else
- qToBigEndian<T>(val, (uchar *)v->d()->buffer->data->data() + idx);
+ qToBigEndian<T>(val, (uchar *)v->d()->buffer->data()->data() + idx);
RETURN_UNDEFINED();
}
@@ -352,9 +352,9 @@ ReturnedValue DataViewPrototype::method_setFloat(const FunctionObject *b, const
} u;
u.f = val;
if (littleEndian)
- qToLittleEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx);
+ qToLittleEndian(u.i, (uchar *)v->d()->buffer->data()->data() + idx);
else
- qToBigEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx);
+ qToBigEndian(u.i, (uchar *)v->d()->buffer->data()->data() + idx);
} else {
Q_ASSERT(sizeof(T) == 8);
union {
@@ -363,9 +363,9 @@ ReturnedValue DataViewPrototype::method_setFloat(const FunctionObject *b, const
} u;
u.d = val;
if (littleEndian)
- qToLittleEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx);
+ qToLittleEndian(u.i, (uchar *)v->d()->buffer->data()->data() + idx);
else
- qToBigEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx);
+ qToBigEndian(u.i, (uchar *)v->d()->buffer->data()->data() + idx);
}
RETURN_UNDEFINED();
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 680ccc02a8..51e63f3608 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -91,6 +91,7 @@
#include "qv4proxy_p.h"
#include "qv4stackframe_p.h"
#include "qv4atomics_p.h"
+#include "qv4urlobject_p.h"
#if QT_CONFIG(qml_sequence_object)
#include "qv4sequenceobject_p.h"
@@ -165,8 +166,23 @@ static void saveJSValue(QDataStream &stream, const void *data)
if (jsv->isUndefined())
isNullOrUndefined |= 0x2;
stream << isNullOrUndefined;
- if (!isNullOrUndefined)
- reinterpret_cast<const QJSValue*>(data)->toVariant().save(stream);
+ if (!isNullOrUndefined) {
+ const QVariant v = reinterpret_cast<const QJSValue*>(data)->toVariant();
+ switch (v.userType()) {
+ case QMetaType::Bool:
+ case QMetaType::Double:
+ case QMetaType::Int:
+ case QMetaType::QString:
+ v.save(stream);
+ break;
+ default:
+ qWarning() << "QDataStream::operator<< was to save a non-trivial QJSValue."
+ << "This is not supported anymore, please stream a QVariant instead.";
+ QVariant().save(stream);
+ break;
+ }
+
+ }
}
static void restoreJSValue(QDataStream &stream, void *data)
@@ -183,7 +199,25 @@ static void restoreJSValue(QDataStream &stream, void *data)
} else {
QVariant v;
v.load(stream);
- QJSValuePrivate::setVariant(jsv, v);
+
+ switch (v.userType()) {
+ case QMetaType::Bool:
+ *jsv = QJSValue(v.toBool());
+ break;
+ case QMetaType::Double:
+ *jsv = QJSValue(v.toDouble());
+ break;
+ case QMetaType::Int:
+ *jsv = QJSValue(v.toInt());
+ break;
+ case QMetaType::QString:
+ *jsv = QJSValue(v.toString());
+ break;
+ default:
+ qWarning() << "QDataStream::operator>> to restore a non-trivial QJSValue."
+ << "This is not supported anymore, please stream a QVariant instead.";
+ break;
+ }
}
}
@@ -617,6 +651,13 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
ic = newInternalClass(StringIteratorPrototype::staticVTable(), iteratorPrototype());
jsObjects[StringIteratorProto] = memoryManager->allocObject<StringIteratorPrototype>(ic);
+ //
+ // url
+ //
+
+ jsObjects[Url_Ctor] = memoryManager->allocate<UrlCtor>(global);
+ jsObjects[UrlProto] = memoryManager->allocate<UrlPrototype>();
+
str = newString(QStringLiteral("get [Symbol.species]"));
jsObjects[GetSymbolSpecies] = FunctionObject::createBuiltinFunction(this, str, ArrayPrototype::method_get_species, 0);
@@ -638,6 +679,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype())->init(this, syntaxErrorCtor());
static_cast<TypeErrorPrototype *>(typeErrorPrototype())->init(this, typeErrorCtor());
static_cast<URIErrorPrototype *>(uRIErrorPrototype())->init(this, uRIErrorCtor());
+ static_cast<UrlPrototype *>(urlPrototype())->init(this, urlCtor());
static_cast<IteratorPrototype *>(iteratorPrototype())->init(this);
static_cast<ForInIteratorPrototype *>(forInIteratorPrototype())->init(this);
@@ -727,6 +769,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
globalObject->defineDefaultProperty(QStringLiteral("TypeError"), *typeErrorCtor());
globalObject->defineDefaultProperty(QStringLiteral("URIError"), *uRIErrorCtor());
globalObject->defineDefaultProperty(QStringLiteral("Promise"), *promiseCtor());
+ globalObject->defineDefaultProperty(QStringLiteral("URL"), *urlCtor());
globalObject->defineDefaultProperty(QStringLiteral("SharedArrayBuffer"), *sharedArrayBufferCtor());
globalObject->defineDefaultProperty(QStringLiteral("ArrayBuffer"), *arrayBufferCtor());
@@ -1009,11 +1052,6 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re)
return memoryManager->allocate<RegExpObject>(re);
}
-Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
-{
- return memoryManager->allocate<RegExpObject>(re);
-}
-
#if QT_CONFIG(regularexpression)
Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &re)
{
@@ -1021,6 +1059,11 @@ Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegularExpression &r
}
#endif
+Heap::UrlObject *ExecutionEngine::newUrlObject()
+{
+ return memoryManager->allocate<UrlObject>();
+}
+
Heap::Object *ExecutionEngine::newErrorObject(const Value &value)
{
return ErrorObject::create<ErrorObject>(this, value, errorCtor());
@@ -1165,13 +1208,13 @@ QObject *ExecutionEngine::qmlScopeObject() const
return ctx->qml()->scopeObject;
}
-QQmlContextData *ExecutionEngine::callingQmlContext() const
+QQmlRefPointer<QQmlContextData> ExecutionEngine::callingQmlContext() const
{
Heap::QmlContext *ctx = qmlContext();
if (!ctx)
return nullptr;
- return ctx->qml()->context->contextData();
+ return ctx->qml()->context;
}
StackTrace ExecutionEngine::stackTrace(int frameLimit) const
@@ -1428,11 +1471,9 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError()
typedef QSet<QV4::Heap::Object *> V4ObjectSet;
static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects);
-static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &value);
+static QObject *qtObjectFromJS(const QV4::Value &value);
static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects = nullptr);
-static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &value,
- const QByteArray &targetType,
- void **result);
+static bool convertToNativeQObject(const QV4::Value &value, const QByteArray &targetType, void **result);
static QV4::ReturnedValue variantListToJS(QV4::ExecutionEngine *v4, const QVariantList &lst);
static QV4::ReturnedValue sequentialIterableToJS(QV4::ExecutionEngine *v4, const QSequentialIterable &lst);
static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVariantMap &vmap);
@@ -1463,7 +1504,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return QVariant::fromValue(QV4::JsonObject::toJsonValue(value));
if (typeHint == qMetaTypeId<QJSValue>())
- return QVariant::fromValue(QJSValue(e, value.asReturnedValue()));
+ return QVariant::fromValue(QJSValuePrivate::fromReturnedValue(value.asReturnedValue()));
if (value.as<QV4::Object>()) {
QV4::ScopedObject object(scope, value);
@@ -1574,16 +1615,13 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
QV4::ScopedObject o(scope, value);
Q_ASSERT(o);
- if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>()) {
#if QT_CONFIG(regularexpression)
- if (typeHint != QMetaType::QRegExp)
- return re->toQRegularExpression();
+ if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>())
+ return re->toQRegularExpression();
#endif
- return re->toQRegExp();
- }
if (createJSValueForObjects)
- return QVariant::fromValue(QJSValue(scope.engine, o->asReturnedValue()));
+ return QVariant::fromValue(QJSValuePrivate::fromReturnedValue(o->asReturnedValue()));
return objectToVariant(e, o, visitedObjects);
}
@@ -1689,8 +1727,6 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(ptr), QTime(0, 0, 0), Qt::UTC)));
case QMetaType::QTime:
return QV4::Encode(newDateObjectFromTime(*reinterpret_cast<const QTime *>(ptr)));
- case QMetaType::QRegExp:
- return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr)));
#if QT_CONFIG(regularexpression)
case QMetaType::QRegularExpression:
return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegularExpression *>(ptr)));
@@ -1743,8 +1779,8 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
return QV4::Encode::null();
}
} else if (type == qMetaTypeId<QJSValue>()) {
- const QJSValue *value = reinterpret_cast<const QJSValue *>(ptr);
- return QJSValuePrivate::convertedToValue(this, *value);
+ return QJSValuePrivate::convertToReturnedValue(
+ this, *reinterpret_cast<const QJSValue *>(ptr));
} else if (type == qMetaTypeId<QList<QObject *> >()) {
// XXX Can this be made more by using Array as a prototype and implementing
// directly against QList<QObject*>?
@@ -2093,94 +2129,93 @@ void ExecutionEngine::setExtensionData(int index, Deletable *data)
// Converts a JS value to a meta-type.
// data must point to a place that can store a value of the given type.
// Returns true if conversion succeeded, false otherwise.
-bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
+bool ExecutionEngine::metaTypeFromJS(const Value &value, int type, void *data)
{
// check if it's one of the types we know
switch (QMetaType::Type(type)) {
case QMetaType::Bool:
- *reinterpret_cast<bool*>(data) = value->toBoolean();
+ *reinterpret_cast<bool*>(data) = value.toBoolean();
return true;
case QMetaType::Int:
- *reinterpret_cast<int*>(data) = value->toInt32();
+ *reinterpret_cast<int*>(data) = value.toInt32();
return true;
case QMetaType::UInt:
- *reinterpret_cast<uint*>(data) = value->toUInt32();
+ *reinterpret_cast<uint*>(data) = value.toUInt32();
return true;
case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(data) = qlonglong(value->toInteger());
+ *reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger());
return true;
case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(data) = qulonglong(value->toInteger());
+ *reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger());
return true;
case QMetaType::Double:
- *reinterpret_cast<double*>(data) = value->toNumber();
+ *reinterpret_cast<double*>(data) = value.toNumber();
return true;
case QMetaType::QString:
- if (value->isUndefined() || value->isNull())
+ if (value.isUndefined() || value.isNull())
*reinterpret_cast<QString*>(data) = QString();
else
- *reinterpret_cast<QString*>(data) = value->toQString();
+ *reinterpret_cast<QString*>(data) = value.toQString();
return true;
case QMetaType::QByteArray:
- if (const ArrayBuffer *ab = value->as<ArrayBuffer>())
+ if (const ArrayBuffer *ab = value.as<ArrayBuffer>())
*reinterpret_cast<QByteArray*>(data) = ab->asByteArray();
else
*reinterpret_cast<QByteArray*>(data) = QByteArray();
return true;
case QMetaType::Float:
- *reinterpret_cast<float*>(data) = value->toNumber();
+ *reinterpret_cast<float*>(data) = value.toNumber();
return true;
case QMetaType::Short:
- *reinterpret_cast<short*>(data) = short(value->toInt32());
+ *reinterpret_cast<short*>(data) = short(value.toInt32());
return true;
case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(data) = value->toUInt16();
+ *reinterpret_cast<unsigned short*>(data) = value.toUInt16();
return true;
case QMetaType::Char:
- *reinterpret_cast<char*>(data) = char(value->toInt32());
+ *reinterpret_cast<char*>(data) = char(value.toInt32());
return true;
case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->toInt32());
+ *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32());
return true;
case QMetaType::QChar:
- if (String *s = value->stringValue()) {
+ if (String *s = value.stringValue()) {
QString str = s->toQString();
*reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
} else {
- *reinterpret_cast<QChar*>(data) = QChar(ushort(value->toUInt16()));
+ *reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16()));
}
return true;
case QMetaType::QDateTime:
- if (const QV4::DateObject *d = value->as<DateObject>()) {
+ if (const QV4::DateObject *d = value.as<DateObject>()) {
*reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
return true;
} break;
case QMetaType::QDate:
- if (const QV4::DateObject *d = value->as<DateObject>()) {
+ if (const QV4::DateObject *d = value.as<DateObject>()) {
*reinterpret_cast<QDate *>(data) = d->toQDateTime().date();
return true;
} break;
- case QMetaType::QRegExp:
- if (const QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
- *reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
- return true;
- } break;
#if QT_CONFIG(regularexpression)
case QMetaType::QRegularExpression:
- if (const QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
+ if (const QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) {
*reinterpret_cast<QRegularExpression *>(data) = r->toQRegularExpression();
return true;
} break;
#endif
case QMetaType::QObjectStar: {
- const QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
- if (qobjectWrapper || value->isNull()) {
- *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(this, *value);
+ if (value.isNull()) {
+ *reinterpret_cast<QObject* *>(data) = nullptr;
return true;
- } break;
+ }
+ if (value.as<QV4::QObjectWrapper>()) {
+ *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(value);
+ return true;
+ }
+ break;
}
case QMetaType::QStringList: {
- const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
+ const QV4::ArrayObject *a = value.as<QV4::ArrayObject>();
if (a) {
*reinterpret_cast<QStringList *>(data) = a->toQStringList();
return true;
@@ -2188,33 +2223,45 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
break;
}
case QMetaType::QVariantList: {
- const QV4::ArrayObject *a = value->as<QV4::ArrayObject>();
+ const QV4::ArrayObject *a = value.as<QV4::ArrayObject>();
if (a) {
- *reinterpret_cast<QVariantList *>(data) = toVariant(*a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
+ *reinterpret_cast<QVariantList *>(data) = a->engine()->toVariant(
+ *a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
return true;
}
break;
}
case QMetaType::QVariantMap: {
- const QV4::Object *o = value->as<QV4::Object>();
+ const QV4::Object *o = value.as<QV4::Object>();
if (o) {
- *reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(o);
+ *reinterpret_cast<QVariantMap *>(data) = o->engine()->variantMapFromJS(o);
return true;
}
break;
}
case QMetaType::QVariant:
- *reinterpret_cast<QVariant*>(data) = toVariant(*value, /*typeHint*/-1, /*createJSValueForObjects*/false);
+ if (const QV4::Managed *m = value.as<QV4::Managed>())
+ *reinterpret_cast<QVariant*>(data) = m->engine()->toVariant(value, /*typeHint*/-1, /*createJSValueForObjects*/false);
+ else if (value.isNull())
+ *reinterpret_cast<QVariant*>(data) = QVariant::fromValue(nullptr);
+ else if (value.isUndefined())
+ *reinterpret_cast<QVariant*>(data) = QVariant();
+ else if (value.isBoolean())
+ *reinterpret_cast<QVariant*>(data) = QVariant(value.booleanValue());
+ else if (value.isInteger())
+ *reinterpret_cast<QVariant*>(data) = QVariant(value.integerValue());
+ else if (value.isDouble())
+ *reinterpret_cast<QVariant*>(data) = QVariant(value.doubleValue());
return true;
case QMetaType::QJsonValue:
- *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(*value);
+ *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
return true;
case QMetaType::QJsonObject: {
- *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value->as<Object>());
+ *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value.as<Object>());
return true;
}
case QMetaType::QJsonArray: {
- const QV4::ArrayObject *a = value->as<ArrayObject>();
+ const QV4::ArrayObject *a = value.as<ArrayObject>();
if (a) {
*reinterpret_cast<QJsonArray *>(data) = JsonObject::toJsonArray(a);
return true;
@@ -2226,7 +2273,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
}
{
- const QQmlValueTypeWrapper *vtw = value->as<QQmlValueTypeWrapper>();
+ const QQmlValueTypeWrapper *vtw = value.as<QQmlValueTypeWrapper>();
if (vtw && vtw->typeId() == type) {
return vtw->toGadget(data);
}
@@ -2254,18 +2301,18 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
// Try to use magic; for compatibility with qjsvalue_cast.
QByteArray name = QMetaType::typeName(type);
- if (convertToNativeQObject(this, *value, name, reinterpret_cast<void* *>(data)))
+ if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(data)))
return true;
- if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
+ if (value.as<QV4::VariantObject>() && name.endsWith('*')) {
int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = value->as<QV4::VariantObject>()->d()->data();
+ QVariant &var = value.as<QV4::VariantObject>()->d()->data();
if (valueType == var.userType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
return true;
- } else if (Object *o = value->objectValue()) {
+ } else if (Object *o = value.objectValue()) {
// Look in the prototype chain.
- QV4::Scope scope(this);
+ QV4::Scope scope(o->engine());
QV4::ScopedObject proto(scope, o->getPrototypeOf());
while (proto) {
bool canCast = false;
@@ -2276,7 +2323,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
else if (proto->as<QV4::QObjectWrapper>()) {
QByteArray className = name.left(name.size()-1);
QV4::ScopedObject p(scope, proto.getPointer());
- if (QObject *qobject = qtObjectFromJS(this, p))
+ if (QObject *qobject = qtObjectFromJS(p))
canCast = qobject->qt_metacast(className) != nullptr;
}
if (canCast) {
@@ -2290,22 +2337,22 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data)
proto = proto->getPrototypeOf();
}
}
- } else if (value->isNull() && name.endsWith('*')) {
+ } else if (value.isNull() && name.endsWith('*')) {
*reinterpret_cast<void* *>(data) = nullptr;
return true;
} else if (type == qMetaTypeId<QJSValue>()) {
- *reinterpret_cast<QJSValue*>(data) = QJSValue(this, value->asReturnedValue());
+ QJSValuePrivate::setValue(reinterpret_cast<QJSValue*>(data), value.asReturnedValue());
return true;
}
return false;
}
-static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &value, const QByteArray &targetType, void **result)
+static bool convertToNativeQObject(const QV4::Value &value, const QByteArray &targetType, void **result)
{
if (!targetType.endsWith('*'))
return false;
- if (QObject *qobject = qtObjectFromJS(e, value)) {
+ if (QObject *qobject = qtObjectFromJS(value)) {
int start = targetType.startsWith("const ") ? 6 : 0;
QByteArray className = targetType.mid(start, targetType.size()-start-1);
if (void *instance = qobject->qt_metacast(className)) {
@@ -2316,12 +2363,12 @@ static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::Value &va
return false;
}
-static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::Value &value)
+static QObject *qtObjectFromJS(const QV4::Value &value)
{
if (!value.isObject())
return nullptr;
- QV4::Scope scope(engine);
+ QV4::Scope scope(value.as<QV4::Managed>()->engine());
QV4::Scoped<QV4::VariantObject> v(scope, value);
if (v) {
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index efe44a324c..ebf2fcd55a 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -240,6 +240,7 @@ public:
MapIteratorProto,
ArrayIteratorProto,
StringIteratorProto,
+ UrlProto,
Object_Ctor,
String_Ctor,
@@ -267,6 +268,7 @@ public:
WeakMap_Ctor,
Map_Ctor,
IntrinsicTypedArray_Ctor,
+ Url_Ctor,
GetSymbolSpecies,
@@ -307,6 +309,10 @@ public:
FunctionObject *weakMapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + WeakMap_Ctor); }
FunctionObject *mapCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + Map_Ctor); }
FunctionObject *intrinsicTypedArrayCtor() const { return reinterpret_cast<FunctionObject *>(jsObjects + IntrinsicTypedArray_Ctor); }
+ FunctionObject *urlCtor() const
+ {
+ return reinterpret_cast<FunctionObject *>(jsObjects + Url_Ctor);
+ }
FunctionObject *typedArrayCtors;
FunctionObject *getSymbolSpecies() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetSymbolSpecies); }
@@ -354,6 +360,7 @@ public:
Object *mapIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + MapIteratorProto); }
Object *arrayIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + ArrayIteratorProto); }
Object *stringIteratorPrototype() const { return reinterpret_cast<Object *>(jsObjects + StringIteratorProto); }
+ Object *urlPrototype() const { return reinterpret_cast<Object *>(jsObjects + UrlProto); }
EvalFunction *evalFunction() const { return reinterpret_cast<EvalFunction *>(jsObjects + Eval_Function); }
FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
@@ -579,11 +586,12 @@ public:
Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
Heap::RegExpObject *newRegExpObject(RegExp *re);
- Heap::RegExpObject *newRegExpObject(const QRegExp &re);
#if QT_CONFIG(regularexpression)
Heap::RegExpObject *newRegExpObject(const QRegularExpression &re);
#endif
+ Heap::UrlObject *newUrlObject();
+
Heap::Object *newErrorObject(const Value &value);
Heap::Object *newErrorObject(const QString &message);
Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
@@ -609,7 +617,7 @@ public:
Heap::QmlContext *qmlContext() const;
QObject *qmlScopeObject() const;
- QQmlContextData *callingQmlContext() const;
+ QQmlRefPointer<QQmlContextData> callingQmlContext() const;
StackTrace stackTrace(int frameLimit = -1) const;
@@ -648,7 +656,7 @@ public:
QVariantMap variantMapFromJS(const QV4::Object *o);
- bool metaTypeFromJS(const Value *value, int type, void *data);
+ static bool metaTypeFromJS(const Value &value, int type, void *data);
QV4::ReturnedValue metaTypeToJS(int type, const void *data);
int maxJSStackSize() const;
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index 29e1c6dbf7..47357bea49 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -54,6 +54,7 @@
#include <private/qml_compile_hash_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/inlinecomponentutils_p.h>
+#include <private/qv4resolvedtypereference_p.h>
#include <QtQml/qqmlfile.h>
#include <QtQml/qqmlpropertymap.h>
@@ -410,8 +411,9 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
metaTypeId = compilationUnit->metaTypeId;
listMetaTypeId = compilationUnit->listMetaTypeId;
} else {
- metaTypeId = typeRef->type.typeId();
- listMetaTypeId = typeRef->type.qListTypeId();
+ const auto type = typeRef->type();
+ metaTypeId = type.typeId();
+ listMetaTypeId = type.qListTypeId();
}
}
@@ -449,7 +451,8 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
inlineComponentData[lastICRoot].totalBindingCount += obj->nBindings;
if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
- if (typeRef->type.isValid() && typeRef->type.parserStatusCast() != -1)
+ const auto type = typeRef->type();
+ if (type.isValid() && type.parserStatusCast() != -1)
++inlineComponentData[lastICRoot].totalParserStatusCount;
++inlineComponentData[lastICRoot].totalObjectCount;
@@ -457,9 +460,8 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
// if the type is an inline component type, we have to extract the information from it
// This requires that inline components are visited in the correct order
auto icRoot = compilationUnit->icRoot;
- if (typeRef->type.isInlineComponentType()) {
- icRoot = typeRef->type.inlineComponendId();
- }
+ if (type.isInlineComponentType())
+ icRoot = type.inlineComponentId();
QScopedValueRollback<int> rollback {compilationUnit->icRoot, icRoot};
inlineComponentData[lastICRoot].totalBindingCount += compilationUnit->totalBindingsCount();
inlineComponentData[lastICRoot].totalParserStatusCount += compilationUnit->totalParserStatusCount();
@@ -478,14 +480,14 @@ void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngi
}
bindingCount += obj->nBindings;
if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
- if (typeRef->type.isValid() && typeRef->type.parserStatusCast() != -1)
+ const auto type = typeRef->type();
+ if (type.isValid() && type.parserStatusCast() != -1)
++parserStatusCount;
++objectCount;
if (const auto compilationUnit = typeRef->compilationUnit()) {
auto icRoot = compilationUnit->icRoot;
- if (typeRef->type.isInlineComponentType()) {
- icRoot = typeRef->type.inlineComponendId();
- }
+ if (type.isInlineComponentType())
+ icRoot = type.inlineComponentId();
QScopedValueRollback<int> rollback {compilationUnit->icRoot, icRoot};
bindingCount += compilationUnit->totalBindingsCount();
parserStatusCount += compilationUnit->totalParserStatusCount();
@@ -798,69 +800,6 @@ bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorSt
});
}
-/*!
-Returns the property cache, if one alread exists. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
-{
- if (type.isValid())
- return typePropertyCache;
- else
- return m_compilationUnit->rootPropertyCache();
-}
-
-/*!
-Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
-{
- if (typePropertyCache) {
- return typePropertyCache;
- } else if (type.isValid()) {
- typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion);
- return typePropertyCache;
- } else {
- Q_ASSERT(m_compilationUnit);
- return m_compilationUnit->rootPropertyCache();
- }
-}
-
-bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
-{
- if (type.isValid() && !type.isInlineComponentType()) {
- bool ok = false;
- hash->addData(createPropertyCache(engine)->checksum(&ok));
- return ok;
- }
- if (!m_compilationUnit)
- return false;
- hash->addData(m_compilationUnit->data->md5Checksum,
- sizeof(m_compilationUnit->data->md5Checksum));
- return true;
-}
-
-template <typename T>
-bool qtTypeInherits(const QMetaObject *mo) {
- while (mo) {
- if (mo == &T::staticMetaObject)
- return true;
- mo = mo->superClass();
- }
- return false;
-}
-
-void ResolvedTypeReference::doDynamicTypeCheck()
-{
- const QMetaObject *mo = nullptr;
- if (typePropertyCache)
- mo = typePropertyCache->firstCppMetaObject();
- else if (type.isValid())
- mo = type.metaObject();
- else if (m_compilationUnit)
- mo = m_compilationUnit->rootPropertyCache()->firstCppMetaObject();
- isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
-}
-
bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
{
for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
@@ -874,24 +813,8 @@ bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *e
QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Binding *binding) const
{
using namespace CompiledData;
+#if QT_CONFIG(translation)
switch (binding->type) {
- case Binding::Type_Script:
- case Binding::Type_String:
- return stringAt(binding->stringIndex);
- case Binding::Type_Null:
- return QStringLiteral("null");
- case Binding::Type_Boolean:
- return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
- case Binding::Type_Number:
- return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
- case Binding::Type_Invalid:
- return QString();
-#if !QT_CONFIG(translation)
- case Binding::Type_TranslationById:
- case Binding::Type_Translation:
- return stringAt(
- data->translations()[binding->value.translationDataIndex].stringIndex);
-#else
case Binding::Type_TranslationById: {
const TranslationData &translation
= data->translations()[binding->value.translationDataIndex];
@@ -912,19 +835,11 @@ QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Bind
return QCoreApplication::translate(contextUtf8.constData(), text.constData(),
comment.constData(), translation.number);
}
-#endif
default:
break;
}
- return QString();
-}
-
-QString ExecutableCompilationUnit::bindingValueAsScriptString(
- const CompiledData::Binding *binding) const
-{
- return (binding->type == CompiledData::Binding::Type_String)
- ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
- : bindingValueAsString(binding);
+#endif
+ return CompilationUnit::bindingValueAsString(binding);
}
bool ExecutableCompilationUnit::verifyHeader(
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index 7bfb68da9d..410316e160 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -90,7 +90,7 @@ namespace QV4 {
typedef QVector<QQmlPropertyData*> BindingPropertyData;
class CompilationUnitMapper;
-struct ResolvedTypeReference;
+class ResolvedTypeReference;
// map from name index
// While this could be a hash, a map is chosen here to provide a stable
// order, which is used to calculating a check-sum on dependent meta-objects.
@@ -182,8 +182,8 @@ public:
CompositeMetaTypeIds typeIdsForComponent(int objectid = 0) const;
- int metaTypeId = -1;
- int listMetaTypeId = -1;
+ QMetaType metaTypeId;
+ QMetaType listMetaTypeId;
bool isRegisteredWithEngine = false;
QHash<int, InlineComponentData> inlineComponentData;
@@ -279,17 +279,9 @@ public:
bool saveToDisk(const QUrl &unitUrl, QString *errorString);
QString bindingValueAsString(const CompiledData::Binding *binding) const;
- QString bindingValueAsScriptString(const CompiledData::Binding *binding) const;
- double bindingValueAsNumber(const CompiledData::Binding *binding) const
- {
- if (binding->type != CompiledData::Binding::Type_Number)
- return 0.0;
- return constants[binding->value.constantValueIndex].doubleValue();
- }
static bool verifyHeader(const CompiledData::Unit *unit, QDateTime expectedSourceTimeStamp,
QString *errorString);
-
protected:
quint32 totalStringCount() const
{ return data->stringTableSize; }
@@ -323,77 +315,6 @@ private:
bool includeDefaultExport = true) const;
};
-struct ResolvedTypeReference
-{
-public:
- ResolvedTypeReference()
- : m_compilationUnit(nullptr)
- , m_stronglyReferencesCompilationUnit(true)
- , majorVersion(0)
- , minorVersion(0)
- , isFullyDynamicType(false)
- {}
-
- ~ResolvedTypeReference()
- {
- if (m_stronglyReferencesCompilationUnit && m_compilationUnit)
- m_compilationUnit->release();
- }
-
- QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit() { return m_compilationUnit; }
- void setCompilationUnit(QQmlRefPointer<QV4::ExecutableCompilationUnit> unit)
- {
- if (m_compilationUnit == unit.data())
- return;
- if (m_stronglyReferencesCompilationUnit) {
- if (m_compilationUnit)
- m_compilationUnit->release();
- m_compilationUnit = unit.take();
- } else {
- m_compilationUnit = unit.data();
- }
- }
-
- bool referencesCompilationUnit() const { return m_stronglyReferencesCompilationUnit; }
- void setReferencesCompilationUnit(bool doReference)
- {
- if (doReference == m_stronglyReferencesCompilationUnit)
- return;
- m_stronglyReferencesCompilationUnit = doReference;
- if (!m_compilationUnit)
- return;
- if (doReference) {
- m_compilationUnit->addref();
- } else if (m_compilationUnit->count() == 1) {
- m_compilationUnit->release();
- m_compilationUnit = nullptr;
- } else {
- m_compilationUnit->release();
- }
- }
-
- QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
- QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
- bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
-
- void doDynamicTypeCheck();
-
- QQmlType type;
- QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
-private:
- Q_DISABLE_COPY_MOVE(ResolvedTypeReference)
-
- QV4::ExecutableCompilationUnit *m_compilationUnit;
- bool m_stronglyReferencesCompilationUnit;
-
-public:
- int majorVersion;
- int minorVersion;
- // Types such as QQmlPropertyMap can add properties dynamically at run-time and
- // therefore cannot have a property cache installed when instantiated.
- bool isFullyDynamicType;
-};
-
IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
{
auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index c6a737b467..7234a3456f 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -141,6 +141,7 @@ namespace Heap {
struct ArgumentsObject;
struct QObjectWrapper;
struct RegExpObject;
+ struct UrlObject;
struct RegExp;
struct EvalFunction;
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 92face6f94..17512cf4ff 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -208,9 +208,9 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons
if (!argc)
RETURN_UNDEFINED();
- QQmlContextData *context = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
- if ((!context || !context->isJSContext) && scope.engine->qmlEngine())
+ if ((!context || !context->isJSContext()) && scope.engine->qmlEngine())
RETURN_RESULT(scope.engine->throwError(QString::fromUtf8("Qt.include(): Can only be called from JavaScript files")));
QV4::ScopedValue callbackFunction(scope, QV4::Value::undefinedValue());
@@ -218,8 +218,8 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons
callbackFunction = argv[1];
QUrl url(scope.engine->resolvedUrl(argv[0].toQStringNoThrow()));
- if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor())
- url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
+ if (const QQmlEngine *qmlEngine = scope.engine->qmlEngine())
+ url = qmlEngine->interceptUrl(url, QQmlAbstractUrlInterceptor::JavaScriptFile);
QString localFile = QQmlFile::urlToLocalFileOrQrc(url);
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 70ccfbf223..9d0a17a5cc 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -53,11 +53,11 @@
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
-
-#include <private/qqmlcontext_p.h>
+#include <QtCore/qpointer.h>
#include <private/qv4value_p.h>
#include <private/qv4context_p.h>
+#include <private/qv4persistent_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index d51b03d90b..8a0e5509c4 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -105,6 +105,9 @@ QString Managed::className() const
case Type_MathObject:
s = "Math";
break;
+ case Type_UrlObject:
+ s = "URL";
+ break;
case Type_ExecutionContext:
s = "__ExecutionContext";
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 4f22dc7330..910eb3a5a1 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -144,6 +144,7 @@ public:
Type_JsonObject,
Type_MathObject,
Type_ProxyObject,
+ Type_UrlObject,
Type_ExecutionContext,
Type_InternalClass,
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index f4901e3e4d..dea3019ef4 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -64,7 +64,7 @@ struct Page {
Value values[1]; // Really kEntriesPerPage, but keep the compiler happy
};
-Page *getPage(Value *val) {
+Page *getPage(const Value *val) {
return reinterpret_cast<Page *>(reinterpret_cast<quintptr>(val) & ~((quintptr)(WTF::pageSize() - 1)));
}
@@ -245,7 +245,7 @@ void PersistentValueStorage::mark(MarkStack *markStack)
}
}
-ExecutionEngine *PersistentValueStorage::getEngine(Value *v)
+ExecutionEngine *PersistentValueStorage::getEngine(const Value *v)
{
return getPage(v)->header.engine;
}
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index 55e8eefcb7..79e8e50790 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -83,7 +83,7 @@ struct Q_QML_EXPORT PersistentValueStorage
Iterator begin() { return Iterator(firstPage, 0); }
Iterator end() { return Iterator(nullptr, 0); }
- static ExecutionEngine *getEngine(Value *v);
+ static ExecutionEngine *getEngine(const Value *v);
ExecutionEngine *engine;
void *firstPage;
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index e2d3b98ff6..9863edead0 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -64,23 +64,25 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QQmlContextWrapper);
DEFINE_MANAGED_VTABLE(QmlContext);
-void Heap::QQmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject)
+void Heap::QQmlContextWrapper::init(QQmlRefPointer<QQmlContextData> context, QObject *scopeObject)
{
Object::init();
- this->context = new QQmlContextDataRef(context);
+ this->context = context.take();
this->scopeObject.init(scopeObject);
}
void Heap::QQmlContextWrapper::destroy()
{
- delete context;
+ context->release();
+ context = nullptr;
scopeObject.destroy();
Object::destroy();
}
-static OptionalReturnedValue searchContextProperties(QV4::ExecutionEngine *v4, QQmlContextData *context, String *name,
- bool *hasProperty, Value *base, QV4::Lookup *lookup,
- QV4::Lookup *originalLookup, QQmlEnginePrivate *ep)
+static OptionalReturnedValue searchContextProperties(
+ QV4::ExecutionEngine *v4, const QQmlRefPointer<QQmlContextData> &context, String *name,
+ bool *hasProperty, Value *base, QV4::Lookup *lookup, QV4::Lookup *originalLookup,
+ QQmlEnginePrivate *ep)
{
const QV4::IdentifierHash &properties = context->propertyNames();
if (properties.count() == 0)
@@ -91,7 +93,7 @@ static OptionalReturnedValue searchContextProperties(QV4::ExecutionEngine *v4, Q
if (propertyIdx == -1)
return OptionalReturnedValue();
- if (propertyIdx < context->idValueCount) {
+ if (propertyIdx < context->numIdValues()) {
if (hasProperty)
*hasProperty = true;
@@ -104,16 +106,16 @@ static OptionalReturnedValue searchContextProperties(QV4::ExecutionEngine *v4, Q
}
if (ep->propertyCapture)
- ep->propertyCapture->captureProperty(&context->idValues[propertyIdx].bindings);
- return OptionalReturnedValue(QV4::QObjectWrapper::wrap(v4, context->idValues[propertyIdx]));
+ ep->propertyCapture->captureProperty(context->idValueBindings(propertyIdx));
+ return OptionalReturnedValue(QV4::QObjectWrapper::wrap(v4, context->idValue(propertyIdx)));
}
QQmlContextPrivate *cp = context->asQQmlContextPrivate();
if (ep->propertyCapture)
- ep->propertyCapture->captureProperty(context->asQQmlContext(), -1, propertyIdx + cp->notifyIndex);
+ ep->propertyCapture->captureProperty(context->asQQmlContext(), -1, propertyIdx + cp->notifyIndex());
- const QVariant &value = cp->propertyValues.at(propertyIdx);
+ const QVariant &value = cp->propertyValue(propertyIdx);
if (hasProperty)
*hasProperty = true;
if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
@@ -122,7 +124,7 @@ static OptionalReturnedValue searchContextProperties(QV4::ExecutionEngine *v4, Q
QQmlContextPrivate::context_at);
return OptionalReturnedValue(QmlListWrapper::create(v4, prop, qMetaTypeId<QQmlListProperty<QObject> >()));
}
- return OptionalReturnedValue(v4->fromVariant(cp->propertyValues.at(propertyIdx)));
+ return OptionalReturnedValue(v4->fromVariant(cp->propertyValue(propertyIdx)));
}
ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *resource, PropertyKey id, const Value *receiver, bool *hasProperty, Value *base, Lookup *lookup)
@@ -133,7 +135,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
QV4::ExecutionEngine *v4 = resource->engine();
QV4::Scope scope(v4);
- if (v4->callingQmlContext() != *resource->d()->context) {
+ if (v4->callingQmlContext().data() != resource->d()->context) {
if (resource->d()->module) {
Scoped<Module> module(scope, resource->d()->module);
bool hasProp = false;
@@ -158,8 +160,8 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
// It's possible we could delay the calculation of the "actual" context (in the case
// of sub contexts) until it is definitely needed.
- QQmlContextData *context = resource->getContext();
- QQmlContextData *expressionContext = context;
+ QQmlRefPointer<QQmlContextData> context = resource->getContext();
+ QQmlRefPointer<QQmlContextData> expressionContext = context;
if (!context) {
if (hasProperty)
@@ -211,9 +213,9 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
return result->asReturnedValue();
}
- if (context->imports && name->startsWithUpper()) {
+ if (context->imports() && name->startsWithUpper()) {
// Search for attached properties, enums and imported scripts
- QQmlTypeNameCache::Result r = context->imports->query(name, QQmlImport::AllowRecursion);
+ QQmlTypeNameCache::Result r = context->imports()->query(name, QQmlImport::AllowRecursion);
if (r.isValid()) {
if (hasProperty)
@@ -224,7 +226,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupScript;
return lookup->qmlContextPropertyGetter(lookup, v4, base);
}
- QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
+ QV4::ScopedObject scripts(scope, context->importedScripts().valueRef());
if (scripts)
return scripts->get(r.scriptIndex);
return QV4::Encode::null();
@@ -241,7 +243,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
).heapObject());
} else {
QJSValue singleton = e->singletonInstance<QJSValue>(r.type);
- QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, singleton));
+ QV4::ScopedObject o(scope, QJSValuePrivate::asReturnedValue(&singleton));
lookup->qmlContextSingletonLookup.singleton = o->d();
}
lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupSingleton;
@@ -250,7 +252,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
}
result = QQmlTypeWrapper::create(v4, scopeObject, r.type);
} else if (r.importNamespace) {
- result = QQmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace);
+ result = QQmlTypeWrapper::create(v4, scopeObject, context->imports(), r.importNamespace);
}
if (lookup) {
lookup->qmlTypeLookup.qmlTypeWrapper = static_cast<Heap::Object*>(result->heapObject());
@@ -268,7 +270,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
decltype(lookup->qmlContextPropertyGetter) contextGetterFunction = QQmlContextWrapper::lookupContextObjectProperty;
// minor optimization so we don't potentially try two property lookups on the same object
- if (scopeObject == context->contextObject) {
+ if (scopeObject == context->contextObject()) {
scopeObject = nullptr;
contextGetterFunction = QQmlContextWrapper::lookupScopeObjectProperty;
}
@@ -310,22 +312,24 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
// Search context object
- if (context->contextObject) {
+ if (QObject *contextObject = context->contextObject()) {
bool hasProp = false;
QQmlPropertyData *propertyData = nullptr;
- result = QV4::QObjectWrapper::getQmlProperty(v4, context, context->contextObject,
- name, QV4::QObjectWrapper::CheckRevision, &hasProp, &propertyData);
+ result = QV4::QObjectWrapper::getQmlProperty(v4, context, contextObject,
+ name, QV4::QObjectWrapper::CheckRevision,
+ &hasProp, &propertyData);
if (hasProp) {
if (hasProperty)
*hasProperty = true;
if (base)
- *base = QV4::QObjectWrapper::wrap(v4, context->contextObject);
+ *base = QV4::QObjectWrapper::wrap(v4, contextObject);
if (propertyData) {
if (lookup) {
- QQmlData *ddata = QQmlData::get(context->contextObject, false);
+ QQmlData *ddata = QQmlData::get(contextObject, false);
if (ddata && ddata->propertyCache) {
- ScopedValue val(scope, base ? *base : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, context->contextObject)));
+ ScopedValue val(scope, base ? *base
+ : Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, contextObject)));
const QObjectWrapper *That = static_cast<const QObjectWrapper *>(val->objectValue());
lookup->qobjectLookup.ic = That->internalClass();
lookup->qobjectLookup.propertyCache = ddata->propertyCache;
@@ -342,7 +346,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
}
}
- context = context->parent;
+ context = context->parent();
// As the hierarchy of contexts is not stable, we can't do accelerated lookups beyond
// the immediate QML context (of the .qml file).
@@ -370,7 +374,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
return result->asReturnedValue();
}
- expressionContext->unresolvedNames = true;
+ expressionContext->setUnresolvedNames(true);
return Encode::undefined();
}
@@ -402,8 +406,8 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val
// It's possible we could delay the calculation of the "actual" context (in the case
// of sub contexts) until it is definitely needed.
- QQmlContextData *context = wrapper->getContext();
- QQmlContextData *expressionContext = context;
+ QQmlRefPointer<QQmlContextData> context = wrapper->getContext();
+ QQmlRefPointer<QQmlContextData> expressionContext = context;
if (!context)
return false;
@@ -419,7 +423,7 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val
if (properties.count()) {
const int propertyIndex = properties.value(name);
if (propertyIndex != -1) {
- if (propertyIndex < context->idValueCount) {
+ if (propertyIndex < context->numIdValues()) {
v4->throwError(QLatin1String("left-hand side of assignment operator is not an lvalue"));
return false;
}
@@ -434,14 +438,15 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val
scopeObject = nullptr;
// Search context object
- if (context->contextObject &&
- QV4::QObjectWrapper::setQmlProperty(v4, context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, value))
+ if (context->contextObject() &&
+ QV4::QObjectWrapper::setQmlProperty(v4, context, context->contextObject(), name,
+ QV4::QObjectWrapper::CheckRevision, value))
return true;
- context = context->parent;
+ context = context->parent();
}
- expressionContext->unresolvedNames = true;
+ expressionContext->setUnresolvedNames(true);
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
@@ -502,11 +507,11 @@ ReturnedValue QQmlContextWrapper::lookupScript(Lookup *l, ExecutionEngine *engin
if (!qmlContext)
return QV4::Encode::null();
- QQmlContextData *context = qmlContext->qmlContext();
+ QQmlRefPointer<QQmlContextData> context = qmlContext->qmlContext();
if (!context)
return QV4::Encode::null();
- QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
+ QV4::ScopedObject scripts(scope, context->importedScripts().valueRef());
if (!scripts)
return QV4::Encode::null();
return scripts->get(l->qmlContextScriptLookup.scriptIndex);
@@ -527,7 +532,7 @@ ReturnedValue QQmlContextWrapper::lookupIdObject(Lookup *l, ExecutionEngine *eng
if (!qmlContext)
return QV4::Encode::null();
- QQmlContextData *context = qmlContext->qmlContext();
+ QQmlRefPointer<QQmlContextData> context = qmlContext->qmlContext();
if (!context)
return QV4::Encode::null();
@@ -535,9 +540,9 @@ ReturnedValue QQmlContextWrapper::lookupIdObject(Lookup *l, ExecutionEngine *eng
const int objectId = l->qmlContextIdObjectLookup.objectId;
if (qmlEngine->propertyCapture)
- qmlEngine->propertyCapture->captureProperty(&context->idValues[objectId].bindings);
+ qmlEngine->propertyCapture->captureProperty(context->idValueBindings(objectId));
- return QV4::QObjectWrapper::wrap(engine, context->idValues[objectId]);
+ return QV4::QObjectWrapper::wrap(engine, context->idValue(objectId));
}
ReturnedValue QQmlContextWrapper::lookupScopeObjectProperty(Lookup *l, ExecutionEngine *engine, Value *base)
@@ -576,11 +581,11 @@ ReturnedValue QQmlContextWrapper::lookupContextObjectProperty(Lookup *l, Executi
if (!qmlContext)
return QV4::Encode::undefined();
- QQmlContextData *context = qmlContext->qmlContext();
+ QQmlRefPointer<QQmlContextData> context = qmlContext->qmlContext();
if (!context)
return QV4::Encode::undefined();
- QObject *contextObject = context->contextObject;
+ QObject *contextObject = context->contextObject();
if (!contextObject)
return QV4::Encode::undefined();
@@ -621,11 +626,11 @@ ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, Exec
if (!qmlContext)
return QV4::Encode::undefined();
- QQmlContextData *context = qmlContext->qmlContext();
+ QQmlRefPointer<QQmlContextData> context = qmlContext->qmlContext();
if (!context)
return QV4::Encode::undefined();
- QQmlContextData *expressionContext = context;
+ QQmlRefPointer<QQmlContextData> expressionContext = context;
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->qmlEngine());
@@ -635,18 +640,19 @@ ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, Exec
ScopedValue result(scope);
- for (context = context->parent; context; context = context->parent) {
+ for (context = context->parent(); context; context = context->parent()) {
if (auto property = searchContextProperties(engine, context, name, nullptr, base, nullptr, nullptr, ep))
return *property;
// Search context object
- if (context->contextObject) {
+ if (QObject *contextObject = context->contextObject()) {
bool hasProp = false;
- result = QV4::QObjectWrapper::getQmlProperty(engine, context, context->contextObject,
- name, QV4::QObjectWrapper::CheckRevision, &hasProp);
+ result = QV4::QObjectWrapper::getQmlProperty(
+ engine, context, contextObject, name,
+ QV4::QObjectWrapper::CheckRevision, &hasProp);
if (hasProp) {
if (base)
- *base = QV4::QObjectWrapper::wrap(engine, context->contextObject);
+ *base = QV4::QObjectWrapper::wrap(engine, contextObject);
return result->asReturnedValue();
}
@@ -658,7 +664,7 @@ ReturnedValue QQmlContextWrapper::lookupInParentContextHierarchy(Lookup *l, Exec
if (hasProp)
return result->asReturnedValue();
- expressionContext->unresolvedNames = true;
+ expressionContext->setUnresolvedNames(true);
return Encode::undefined();
}
@@ -692,11 +698,15 @@ void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContex
this->activation.set(internalClass->engine, qml->d());
}
-Heap::QmlContext *QmlContext::create(ExecutionContext *parent, QQmlContextData *context, QObject *scopeObject)
+Heap::QmlContext *QmlContext::create(
+ ExecutionContext *parent, QQmlRefPointer<QQmlContextData> context,
+ QObject *scopeObject)
{
Scope scope(parent);
- Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocate<QQmlContextWrapper>(context, scopeObject));
+ Scoped<QQmlContextWrapper> qml(
+ scope, scope.engine->memoryManager->allocate<QQmlContextWrapper>(
+ std::move(context), scopeObject));
Heap::QmlContext *c = scope.engine->memoryManager->alloc<QmlContext>(parent, qml);
Q_ASSERT(c->vtable() == staticVTable());
return c;
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index e3e7239fe5..ba7c5da146 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -56,7 +56,7 @@
#include <private/qv4object_p.h>
#include <private/qv4context_p.h>
-#include <private/qqmlcontext_p.h>
+#include <private/qqmlcontextdata_p.h>
QT_BEGIN_NAMESPACE
@@ -72,10 +72,11 @@ namespace Heap {
DECLARE_HEAP_OBJECT(QQmlContextWrapper, Object) {
DECLARE_MARKOBJECTS(QQmlContextWrapper);
- void init(QQmlContextData *context, QObject *scopeObject);
+ void init(QQmlRefPointer<QQmlContextData> context, QObject *scopeObject);
void destroy();
- QQmlContextDataRef *context;
+ // This has to be a plain pointer because object needs to be a POD type.
+ QQmlContextData *context;
QQmlQPointer<QObject> scopeObject;
};
@@ -97,7 +98,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
V4_INTERNALCLASS(QmlContextWrapper)
inline QObject *getScopeObject() const { return d()->scopeObject; }
- inline QQmlContextData *getContext() const { return *d()->context; }
+ inline QQmlRefPointer<QQmlContextData> getContext() const { return d()->context; }
static ReturnedValue getPropertyAndBase(const QQmlContextWrapper *resource, PropertyKey id, const Value *receiver,
bool *hasProperty, Value *base, Lookup *lookup = nullptr);
@@ -120,13 +121,16 @@ struct Q_QML_EXPORT QmlContext : public ExecutionContext
V4_MANAGED(QmlContext, ExecutionContext)
V4_INTERNALCLASS(QmlContext)
- static Heap::QmlContext *create(QV4::ExecutionContext *parent, QQmlContextData *context, QObject *scopeObject);
+ static Heap::QmlContext *create(
+ QV4::ExecutionContext *parent, QQmlRefPointer<QQmlContextData> context,
+ QObject *scopeObject);
QObject *qmlScope() const {
return d()->qml()->scopeObject;
}
- QQmlContextData *qmlContext() const {
- return *d()->qml()->context;
+
+ QQmlRefPointer<QQmlContextData> qmlContext() const {
+ return d()->qml()->context;
}
};
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 66b79aa0e8..4366a6932d 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -170,7 +170,7 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object
} else if (property.propType() == qMetaTypeId<QJSValue>()) {
QJSValue v;
property.readProperty(object, &v);
- return QJSValuePrivate::convertedToValue(v4, v);
+ return QJSValuePrivate::convertToReturnedValue(v4, v);
} else if (property.isQVariant()) {
QVariant v;
property.readProperty(object, &v);
@@ -212,13 +212,17 @@ void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
engine->functionPrototype()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
}
-QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const
+QQmlPropertyData *QObjectWrapper::findProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext, String *name,
+ RevisionMode revisionMode, QQmlPropertyData *local) const
{
QObject *o = d()->object();
return findProperty(engine, o, qmlContext, name, revisionMode, local);
}
-QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QObject *o, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local)
+QQmlPropertyData *QObjectWrapper::findProperty(
+ ExecutionEngine *engine, QObject *o, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ String *name, RevisionMode revisionMode, QQmlPropertyData *local)
{
Q_UNUSED(revisionMode);
@@ -285,13 +289,14 @@ static OptionalReturnedValue getDestroyOrToStringMethod(ExecutionEngine *v4, Str
return OptionalReturnedValue(QV4::QObjectMethod::create(global, qobj, index));
}
-static OptionalReturnedValue getPropertyFromImports(ExecutionEngine *v4, String *name, QQmlContextData *qmlContext, QObject *qobj,
- bool *hasProperty = nullptr)
+static OptionalReturnedValue getPropertyFromImports(
+ ExecutionEngine *v4, String *name, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ QObject *qobj, bool *hasProperty = nullptr)
{
- if (!qmlContext || !qmlContext->imports)
+ if (!qmlContext || !qmlContext->imports())
return OptionalReturnedValue();
- QQmlTypeNameCache::Result r = qmlContext->imports->query(name);
+ QQmlTypeNameCache::Result r = qmlContext->imports()->query(name);
if (hasProperty)
*hasProperty = true;
@@ -304,15 +309,17 @@ static OptionalReturnedValue getPropertyFromImports(ExecutionEngine *v4, String
} else if (r.type.isValid()) {
return OptionalReturnedValue(QQmlTypeWrapper::create(v4, qobj,r.type, Heap::QQmlTypeWrapper::ExcludeEnums));
} else if (r.importNamespace) {
- return OptionalReturnedValue(QQmlTypeWrapper::create(v4, qobj, qmlContext->imports, r.importNamespace,
- Heap::QQmlTypeWrapper::ExcludeEnums));
+ return OptionalReturnedValue(QQmlTypeWrapper::create(
+ v4, qobj, qmlContext->imports(), r.importNamespace,
+ Heap::QQmlTypeWrapper::ExcludeEnums));
}
Q_UNREACHABLE();
return OptionalReturnedValue();
}
-ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *name, QObjectWrapper::RevisionMode revisionMode,
- bool *hasProperty, bool includeImports) const
+ReturnedValue QObjectWrapper::getQmlProperty(
+ const QQmlRefPointer<QQmlContextData> &qmlContext, String *name,
+ QObjectWrapper::RevisionMode revisionMode, bool *hasProperty, bool includeImports) const
{
// Keep this code in sync with ::virtualResolveLookupGetter
@@ -355,7 +362,10 @@ ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String
return getProperty(v4, d()->object(), result);
}
-ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty, QQmlPropertyData **property)
+ReturnedValue QObjectWrapper::getQmlProperty(
+ QV4::ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty,
+ QQmlPropertyData **property)
{
if (QQmlData::wasDeleted(object)) {
if (hasProperty)
@@ -415,8 +425,9 @@ ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlC
}
-bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name,
- QObjectWrapper::RevisionMode revisionMode, const Value &value)
+bool QObjectWrapper::setQmlProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext, QObject *object,
+ String *name, QObjectWrapper::RevisionMode revisionMode, const Value &value)
{
if (QQmlData::wasDeleted(object))
return false;
@@ -462,7 +473,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
}
} else {
// binding assignment.
- QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> callingQmlContext = scope.engine->callingQmlContext();
QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f);
@@ -519,7 +530,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
} else if (value.isUndefined() && property->propType() == QMetaType::QJsonValue) {
PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined));
} else if (!newBinding && property->propType() == qMetaTypeId<QJSValue>()) {
- PROPERTY_STORE(QJSValue, QJSValue(scope.engine, value.asReturnedValue()));
+ PROPERTY_STORE(QJSValue, QJSValuePrivate::fromReturnedValue(value.asReturnedValue()));
} else if (value.isUndefined() && property->propType() != qMetaTypeId<QQmlScriptString>()) {
QString error = QLatin1String("Cannot assign [undefined] to ");
if (!QMetaType::typeName(property->propType()))
@@ -561,7 +572,7 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
else
v = scope.engine->toVariant(value, property->propType());
- QQmlContextData *callingQmlContext = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
const char *valueType = (v.userType() == QMetaType::UnknownType)
? "an unknown type"
@@ -702,7 +713,7 @@ QV4::ReturnedValue QObjectWrapper::virtualGet(const Managed *m, PropertyKey id,
const QObjectWrapper *that = static_cast<const QObjectWrapper*>(m);
Scope scope(that);
ScopedString n(scope, id.asStringOrSymbol());
- QQmlContextData *qmlContext = that->engine()->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = that->engine()->callingQmlContext();
return that->getQmlProperty(qmlContext, n, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
@@ -718,7 +729,7 @@ bool QObjectWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value,
if (scope.engine->hasException || QQmlData::wasDeleted(that->d()->object()))
return false;
- QQmlContextData *qmlContext = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = scope.engine->callingQmlContext();
if (!setQmlProperty(scope.engine, qmlContext, that->d()->object(), name, QV4::QObjectWrapper::IgnoreRevision, value)) {
QQmlData *ddata = QQmlData::get(that->d()->object());
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
@@ -744,7 +755,7 @@ PropertyAttributes QObjectWrapper::virtualGetOwnProperty(const Managed *m, Prope
if (!QQmlData::wasDeleted(thatObject)) {
Scope scope(m);
ScopedString n(scope, id.asStringOrSymbol());
- QQmlContextData *qmlContext = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = scope.engine->callingQmlContext();
QQmlPropertyData local;
if (that->findProperty(scope.engine, qmlContext, n, IgnoreRevision, &local)
|| n->equals(scope.engine->id_destroy()) || n->equals(scope.engine->id_toString())) {
@@ -848,7 +859,7 @@ ReturnedValue QObjectWrapper::virtualResolveLookupGetter(const Object *object, E
const QObjectWrapper *This = static_cast<const QObjectWrapper *>(object);
ScopedString name(scope, id.asStringOrSymbol());
- QQmlContextData *qmlContext = engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = engine->callingQmlContext();
QObject * const qobj = This->d()->object();
@@ -1168,7 +1179,7 @@ void QObjectWrapper::destroyObject(bool lastCall)
if (ddata) {
if (!h->object()->parent() && !ddata->indestructible) {
if (ddata && ddata->ownContext) {
- Q_ASSERT(ddata->ownContext == ddata->context);
+ Q_ASSERT(ddata->ownContext.data() == ddata->context);
ddata->ownContext->emitDestruction();
ddata->ownContext = nullptr;
ddata->context = nullptr;
@@ -1287,11 +1298,16 @@ static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index
: QString());
}
- qWarning() << QLatin1String("Passing incompatible arguments to C++ functions from "
- "JavaScript is dangerous and deprecated.");
- qWarning() << QLatin1String("This will throw a JavaScript TypeError in future "
- "releases of Qt!");
+ const bool is_signal =
+ object.metaObject()->method(index).methodType() == QMetaMethod::Signal;
+ if (is_signal) {
+ qWarning() << "Passing incomatible arguments to signals is not supported.";
+ } else {
+ return engine->throwTypeError(
+ QLatin1String("Passing incompatible arguments to C++ functions from "
+ "JavaScript is not allowed."));
+ }
}
}
QVarLengthArray<void *, 9> argData(args.count());
@@ -1388,11 +1404,10 @@ static int MatchScore(const QV4::Value &actual, int conversionType)
}
} else if (actual.as<QV4::RegExpObject>()) {
switch (conversionType) {
- case QMetaType::QRegExp:
#if QT_CONFIG(regularexpression)
case QMetaType::QRegularExpression:
-#endif
return 0;
+#endif
default:
return 10;
}
@@ -1563,6 +1578,18 @@ static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQ
return engine->throwError(error);
}
+ if (args[0] < callArgs->argc()) {
+ Q_ASSERT(!engine->stackTrace().isEmpty());
+
+ const StackFrame frame = engine->stackTrace().first();
+ qWarning().noquote() << frame.function + QLatin1Char('@') + frame.source
+ + (frame.line > 0 ? (QLatin1Char(':') + QString::number(frame.line))
+ : QString());
+
+ qWarning().noquote() << QStringLiteral("Too many arguments, ignoring %1")
+ .arg(callArgs->argc() - args[0]);
+ }
+
return CallMethod(object, data.coreIndex(), returnType, args[0], args + 1, engine, callArgs, callType);
} else {
@@ -1775,7 +1802,8 @@ bool CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const Q
bool queryEngine = false;
if (callType == qMetaTypeId<QJSValue>()) {
- qjsValuePtr = new (&allocData) QJSValue(scope.engine, value.asReturnedValue());
+ qjsValuePtr = new (&allocData) QJSValue;
+ QJSValuePrivate::setValue(qjsValuePtr, value.asReturnedValue());
type = qMetaTypeId<QJSValue>();
} else if (callType == QMetaType::Int) {
intValue = quint32(value.toInt32());
@@ -1932,7 +1960,9 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
QV4::Scope scope(engine);
if (type == qMetaTypeId<QJSValue>()) {
- return QJSValuePrivate::convertedToValue(scope.engine, *qjsValuePtr);
+ // The QJSValue can be passed around via dataPtr()
+ QJSValuePrivate::manageStringOnV4Heap(engine, qjsValuePtr);
+ return QJSValuePrivate::asReturnedValue(qjsValuePtr);
} else if (type == QMetaType::Int) {
return QV4::Encode(int(intValue));
} else if (type == QMetaType::UInt) {
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index ac9cad2bdb..6d12271eb8 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -165,10 +165,19 @@ struct Q_QML_EXPORT QObjectWrapper : public Object
QObject *object() const { return d()->object(); }
- ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = nullptr, bool includeImports = false) const;
- static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = nullptr, QQmlPropertyData **property = nullptr);
-
- static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value);
+ ReturnedValue getQmlProperty(
+ const QQmlRefPointer<QQmlContextData> &qmlContext, String *name,
+ RevisionMode revisionMode, bool *hasProperty = nullptr,
+ bool includeImports = false) const;
+ \
+ static ReturnedValue getQmlProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = nullptr,
+ QQmlPropertyData **property = nullptr);
+
+ static bool setQmlProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ QObject *object, String *name, RevisionMode revisionMode, const Value &value);
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object);
static void markWrapper(QObject *object, MarkStack *markStack);
@@ -193,8 +202,13 @@ protected:
static bool virtualIsEqualTo(Managed *that, Managed *o);
static ReturnedValue create(ExecutionEngine *engine, QObject *object);
- static QQmlPropertyData *findProperty(ExecutionEngine *engine, QObject *o, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local);
- QQmlPropertyData *findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
+ static QQmlPropertyData *findProperty(
+ ExecutionEngine *engine, QObject *o, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ String *name, RevisionMode revisionMode, QQmlPropertyData *local);
+
+ QQmlPropertyData *findProperty(
+ ExecutionEngine *engine, const QQmlRefPointer<QQmlContextData> &qmlContext,
+ String *name, RevisionMode revisionMode, QQmlPropertyData *local) const;
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver);
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index a8a37cda37..73122fbf75 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -49,7 +49,6 @@
#include "private/qlocale_tools_p.h"
#include <QtCore/QDebug>
-#include <QtCore/qregexp.h>
#if QT_CONFIG(regularexpression)
#include <QtCore/qregularexpression.h>
#endif
@@ -60,8 +59,6 @@
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
-
using namespace QV4;
DEFINE_OBJECT_VTABLE(RegExpObject);
@@ -84,57 +81,40 @@ void Heap::RegExpObject::init(QV4::RegExp *value)
o->initProperties();
}
-// Converts a QRegExp to a JS RegExp.
-// The conversion is not 100% exact since ECMA regexp and QRegExp
-// have different semantics/flags, but we try to do our best.
-void Heap::RegExpObject::init(const QRegExp &re)
-{
- Object::init();
-
- // Convert the pattern to a ECMAScript pattern.
- QString pattern = QT_PREPEND_NAMESPACE(qt_regexp_toCanonical)(re.pattern(), re.patternSyntax());
- if (re.isMinimal()) {
- QString ecmaPattern;
- int len = pattern.length();
- ecmaPattern.reserve(len);
- int i = 0;
- const QChar *wc = pattern.unicode();
- bool inBracket = false;
- while (i < len) {
- QChar c = wc[i++];
- ecmaPattern += c;
- switch (c.unicode()) {
- case '?':
- case '+':
- case '*':
- case '}':
- if (!inBracket)
- ecmaPattern += QLatin1Char('?');
- break;
- case '\\':
- if (i < len)
- ecmaPattern += wc[i++];
- break;
- case '[':
- inBracket = true;
- break;
- case ']':
- inBracket = false;
- break;
- default:
- break;
- }
+static QString minimalPattern(const QString &pattern)
+{
+ QString ecmaPattern;
+ int len = pattern.length();
+ ecmaPattern.reserve(len);
+ int i = 0;
+ const QChar *wc = pattern.unicode();
+ bool inBracket = false;
+ while (i < len) {
+ QChar c = wc[i++];
+ ecmaPattern += c;
+ switch (c.unicode()) {
+ case '?':
+ case '+':
+ case '*':
+ case '}':
+ if (!inBracket)
+ ecmaPattern += QLatin1Char('?');
+ break;
+ case '\\':
+ if (i < len)
+ ecmaPattern += wc[i++];
+ break;
+ case '[':
+ inBracket = true;
+ break;
+ case ']':
+ inBracket = false;
+ break;
+ default:
+ break;
}
- pattern = ecmaPattern;
}
-
- Scope scope(internalClass->engine);
- Scoped<QV4::RegExpObject> o(scope, this);
-
- uint flags = (re.caseSensitivity() == Qt::CaseInsensitive ? CompiledData::RegExp::RegExp_IgnoreCase : CompiledData::RegExp::RegExp_NoFlags);
- o->d()->value.set(scope.engine, QV4::RegExp::create(scope.engine, pattern, flags));
-
- o->initProperties();
+ return ecmaPattern;
}
#if QT_CONFIG(regularexpression)
@@ -148,10 +128,16 @@ void Heap::RegExpObject::init(const QRegularExpression &re)
Scope scope(internalClass->engine);
Scoped<QV4::RegExpObject> o(scope, this);
- const uint flags = (re.patternOptions() & QRegularExpression::CaseInsensitiveOption)
- ? CompiledData::RegExp::RegExp_IgnoreCase
- : CompiledData::RegExp::RegExp_NoFlags;
- o->d()->value.set(scope.engine, QV4::RegExp::create(scope.engine, re.pattern(), flags));
+ QRegularExpression::PatternOptions options = re.patternOptions();
+ uint flags = (options & QRegularExpression::CaseInsensitiveOption)
+ ? CompiledData::RegExp::RegExp_IgnoreCase
+ : CompiledData::RegExp::RegExp_NoFlags;
+ if (options & QRegularExpression::MultilineOption)
+ flags |= CompiledData::RegExp::RegExp_Multiline;
+ QString pattern = re.pattern();
+ if (options & QRegularExpression::InvertedGreedinessOption)
+ pattern = minimalPattern(pattern);
+ o->d()->value.set(scope.engine, QV4::RegExp::create(scope.engine, pattern, flags));
o->initProperties();
}
#endif
@@ -163,26 +149,18 @@ void RegExpObject::initProperties()
Q_ASSERT(value());
}
-// Converts a JS RegExp to a QRegExp.
-// The conversion is not 100% exact since ECMA regexp and QRegExp
-// have different semantics/flags, but we try to do our best.
-QRegExp RegExpObject::toQRegExp() const
-{
- Qt::CaseSensitivity caseSensitivity = (value()->flags & CompiledData::RegExp::RegExp_IgnoreCase) ? Qt::CaseInsensitive : Qt::CaseSensitive;
- return QRegExp(*value()->pattern, caseSensitivity, QRegExp::RegExp2);
-}
-
#if QT_CONFIG(regularexpression)
// Converts a JS RegExp to a QRegularExpression.
// The conversion is not 100% exact since ECMA regexp and QRegularExpression
// have different semantics/flags, but we try to do our best.
QRegularExpression RegExpObject::toQRegularExpression() const
{
- QRegularExpression::PatternOptions caseSensitivity
- = (value()->flags & CompiledData::RegExp::RegExp_IgnoreCase)
- ? QRegularExpression::CaseInsensitiveOption
- : QRegularExpression::NoPatternOption;
- return QRegularExpression(*value()->pattern, caseSensitivity);
+ QRegularExpression::PatternOptions options = QRegularExpression::NoPatternOption;
+ if (value()->flags & CompiledData::RegExp::RegExp_IgnoreCase)
+ options |= QRegularExpression::CaseInsensitiveOption;
+ if (value()->flags & CompiledData::RegExp::RegExp_Multiline)
+ options |= QRegularExpression::MultilineOption;
+ return QRegularExpression(*value()->pattern, options);
}
#endif
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index b94889e9f0..8b26d06579 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -80,7 +80,6 @@ DECLARE_HEAP_OBJECT(RegExpObject, Object) {
void init();
void init(QV4::RegExp *value);
- void init(const QRegExp &re);
#if QT_CONFIG(regularexpression)
void init(const QRegularExpression &re);
#endif
@@ -140,7 +139,6 @@ struct Q_QML_PRIVATE_EXPORT RegExpObject: Object {
return setProperty(Index_LastIndex, Value::fromInt32(index));
}
- QRegExp toQRegExp() const;
#if QT_CONFIG(regularexpression)
QRegularExpression toQRegularExpression() const;
#endif
diff --git a/src/qml/jsruntime/qv4resolvedtypereference.cpp b/src/qml/jsruntime/qv4resolvedtypereference.cpp
new file mode 100644
index 0000000000..d81f512391
--- /dev/null
+++ b/src/qml/jsruntime/qv4resolvedtypereference.cpp
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4resolvedtypereference_p.h"
+
+#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/qqmlpropertymap.h>
+#include <QtCore/qcryptographichash.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+template <typename T>
+bool qtTypeInherits(const QMetaObject *mo) {
+ while (mo) {
+ if (mo == &T::staticMetaObject)
+ return true;
+ mo = mo->superClass();
+ }
+ return false;
+}
+
+void ResolvedTypeReference::doDynamicTypeCheck()
+{
+ const QMetaObject *mo = nullptr;
+ if (m_typePropertyCache)
+ mo = m_typePropertyCache->firstCppMetaObject();
+ else if (m_type.isValid())
+ mo = m_type.metaObject();
+ else if (m_compilationUnit)
+ mo = m_compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ m_isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
+}
+
+/*!
+Returns the property cache, if one alread exists. The cache is not referenced.
+*/
+QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
+{
+ if (m_type.isValid())
+ return m_typePropertyCache;
+ else
+ return m_compilationUnit->rootPropertyCache();
+}
+
+/*!
+Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
+*/
+QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
+{
+ if (m_typePropertyCache) {
+ return m_typePropertyCache;
+ } else if (m_type.isValid()) {
+ m_typePropertyCache = QQmlEnginePrivate::get(engine)->cache(m_type.metaObject(), m_version);
+ return m_typePropertyCache;
+ } else {
+ Q_ASSERT(m_compilationUnit);
+ return m_compilationUnit->rootPropertyCache();
+ }
+}
+
+bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
+{
+ if (m_type.isValid() && !m_type.isInlineComponentType()) {
+ bool ok = false;
+ hash->addData(createPropertyCache(engine)->checksum(&ok));
+ return ok;
+ }
+ if (!m_compilationUnit)
+ return false;
+ hash->addData(m_compilationUnit->data->md5Checksum,
+ sizeof(m_compilationUnit->data->md5Checksum));
+ return true;
+}
+
+} // namespace QV4
+
+QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4resolvedtypereference_p.h b/src/qml/jsruntime/qv4resolvedtypereference_p.h
new file mode 100644
index 0000000000..7e8bedad62
--- /dev/null
+++ b/src/qml/jsruntime/qv4resolvedtypereference_p.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4RESOLVEDTYPEREFERNCE_P_H
+#define QV4RESOLVEDTYPEREFERNCE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/private/qtqmlglobal_p.h>
+#include <QtQml/private/qqmlrefcount_p.h>
+#include <QtQml/private/qqmlpropertycache_p.h>
+#include <QtQml/private/qqmltype_p.h>
+#include <QtQml/private/qv4executablecompilationunit_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCryptographicHash;
+namespace QV4 {
+
+class ResolvedTypeReference
+{
+ Q_DISABLE_COPY_MOVE(ResolvedTypeReference)
+public:
+ ResolvedTypeReference() = default;
+ ~ResolvedTypeReference()
+ {
+ if (m_stronglyReferencesCompilationUnit && m_compilationUnit)
+ m_compilationUnit->release();
+ }
+
+ QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
+ QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
+
+ void doDynamicTypeCheck();
+
+ QQmlType type() const { return m_type; }
+ void setType(QQmlType type) { m_type = std::move(type); }
+
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit() { return m_compilationUnit; }
+ void setCompilationUnit(QQmlRefPointer<QV4::ExecutableCompilationUnit> unit)
+ {
+ if (m_compilationUnit == unit.data())
+ return;
+ if (m_stronglyReferencesCompilationUnit) {
+ if (m_compilationUnit)
+ m_compilationUnit->release();
+ m_compilationUnit = unit.take();
+ } else {
+ m_compilationUnit = unit.data();
+ }
+ }
+
+ bool referencesCompilationUnit() const { return m_stronglyReferencesCompilationUnit; }
+ void setReferencesCompilationUnit(bool doReference)
+ {
+ if (doReference == m_stronglyReferencesCompilationUnit)
+ return;
+ m_stronglyReferencesCompilationUnit = doReference;
+ if (!m_compilationUnit)
+ return;
+ if (doReference) {
+ m_compilationUnit->addref();
+ } else if (m_compilationUnit->count() == 1) {
+ m_compilationUnit->release();
+ m_compilationUnit = nullptr;
+ } else {
+ m_compilationUnit->release();
+ }
+ }
+
+ QQmlRefPointer<QQmlPropertyCache> typePropertyCache() const { return m_typePropertyCache; }
+ void setTypePropertyCache(QQmlRefPointer<QQmlPropertyCache> cache)
+ {
+ m_typePropertyCache = std::move(cache);
+ }
+
+ QTypeRevision version() const { return m_version; }
+ void setVersion(QTypeRevision version) { m_version = version; }
+
+ bool isFullyDynamicType() const { return m_isFullyDynamicType; }
+ void setFullyDynamicType(bool fullyDynamic) { m_isFullyDynamicType = fullyDynamic; }
+
+private:
+ QQmlType m_type;
+ QQmlRefPointer<QQmlPropertyCache> m_typePropertyCache;
+ QV4::ExecutableCompilationUnit *m_compilationUnit = nullptr;
+
+ QTypeRevision m_version = QTypeRevision::zero();
+ // Types such as QQmlPropertyMap can add properties dynamically at run-time and
+ // therefore cannot have a property cache installed when instantiated.
+ bool m_isFullyDynamicType = false;
+ bool m_stronglyReferencesCompilationUnit = true;
+};
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif // QV4RESOLVEDTYPEREFERNCE_P_H
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 5a1b27fda6..ee42342bf2 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -80,7 +80,6 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
#if QT_CONFIG(qml_itemmodel)
#define FOREACH_QML_SEQUENCE_TYPE_FOR_ITEMMODEL(F) \
F(QModelIndex, QModelIndex, QModelIndexList, QModelIndex()) \
- F(QModelIndex, QModelIndexVector, QVector<QModelIndex>, QModelIndex()) \
F(QModelIndex, QModelIndexStdVector, std::vector<QModelIndex>, QModelIndex()) \
F(QItemSelectionRange, QItemSelectionRange, QItemSelection, QItemSelectionRange())
#else
@@ -88,9 +87,6 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
#endif
#define FOREACH_QML_SEQUENCE_TYPE(F) \
- F(int, IntVector, QVector<int>, 0) \
- F(qreal, RealVector, QVector<qreal>, 0.0) \
- F(bool, BoolVector, QVector<bool>, false) \
F(int, IntStdVector, std::vector<int>, 0) \
F(qreal, RealStdVector, std::vector<qreal>, 0.0) \
F(bool, BoolStdVector, std::vector<bool>, false) \
@@ -99,10 +95,8 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
F(bool, Bool, QList<bool>, false) \
F(QString, String, QList<QString>, QString()) \
F(QString, QString, QStringList, QString()) \
- F(QString, StringVector, QVector<QString>, QString()) \
F(QString, StringStdVector, std::vector<QString>, QString()) \
F(QUrl, Url, QList<QUrl>, QUrl()) \
- F(QUrl, UrlVector, QVector<QUrl>, QUrl()) \
F(QUrl, UrlStdVector, std::vector<QUrl>, QUrl()) \
FOREACH_QML_SEQUENCE_TYPE_FOR_ITEMMODEL(F)
@@ -377,24 +371,8 @@ public:
++arrayIndex;
if (attrs)
*attrs = QV4::Attr_Data;
-
- // TODO: Replace the container->at() below with operator[] in Qt6!
- // TODO: But _not_ in Qt5!
- //
- // gcc 5.3.1 as shipped on RHEL 7.6 includes a copy of basic_string<char>
- // into QtQml, when it sees a std::vector::at(). The basic_string symbols
- // are publicly visible and preferred over the ones from libstdc++ when
- // building user code. Therefore, removing this at() breaks binary
- // compatibility. We _do_ want to remove it in Qt6, though.
- //
- // The exact mechanism is that at() checks its argument and can throw an
- // out_of_range exception. The construction of this exception then triggers
- // some string manipulation that uses the std::basic_string symbols. Clearly,
- // this is a compiler bug. And clearly, we don't want the check as we can't
- // catch the exception anyway.
-
if (pd)
- pd->value = convertElementToValue(s->engine(), s->d()->container->at(index));
+ pd->value = convertElementToValue(s->engine(), (*s->d()->container)[index]);
return PropertyKey::fromArrayIndex(index);
}
@@ -672,12 +650,6 @@ void Heap::QQmlSequence<Container>::init(QObject *object, int propertyIndex, boo
namespace QV4 {
-typedef QQmlSequence<QVector<int> > QQmlIntVectorList;
-DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntVectorList);
-typedef QQmlSequence<QVector<qreal> > QQmlRealVectorList;
-DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlRealVectorList);
-typedef QQmlSequence<QVector<bool> > QQmlBoolVectorList;
-DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlBoolVectorList);
typedef QQmlSequence<std::vector<int> > QQmlIntStdVectorList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntStdVectorList);
typedef QQmlSequence<std::vector<qreal> > QQmlRealStdVectorList;
@@ -688,23 +660,17 @@ typedef QQmlSequence<QStringList> QQmlQStringList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQStringList);
typedef QQmlSequence<QList<QString> > QQmlStringList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringList);
-typedef QQmlSequence<QVector<QString> > QQmlStringVectorList;
-DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringVectorList);
typedef QQmlSequence<std::vector<QString> > QQmlStringStdVectorList;
-DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringStdVectorList);
typedef QQmlSequence<QList<int> > QQmlIntList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlIntList);
+DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlStringStdVectorList);
typedef QQmlSequence<QList<QUrl> > QQmlUrlList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlList);
-typedef QQmlSequence<QVector<QUrl> > QQmlUrlVectorList;
-DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlVectorList);
typedef QQmlSequence<std::vector<QUrl> > QQmlUrlStdVectorList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlUrlStdVectorList);
#if QT_CONFIG(qml_itemmodel)
typedef QQmlSequence<QModelIndexList> QQmlQModelIndexList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexList);
-typedef QQmlSequence<QVector<QModelIndex> > QQmlQModelIndexVectorList;
-DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexVectorList);
typedef QQmlSequence<std::vector<QModelIndex> > QQmlQModelIndexStdVectorList;
DEFINE_OBJECT_TEMPLATE_VTABLE(QQmlQModelIndexStdVectorList);
typedef QQmlSequence<QItemSelection> QQmlQItemSelectionRangeList;
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 8930c9a94d..7457e724e2 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -359,7 +359,7 @@ static inline void qMapDeallocate(SparseArrayNode *node, int alignment)
SparseArrayNode *SparseArray::createNode(uint sl, SparseArrayNode *parent, bool left)
{
- SparseArrayNode *node = static_cast<SparseArrayNode *>(qMapAllocate(sizeof(SparseArrayNode), Q_ALIGNOF(SparseArrayNode)));
+ SparseArrayNode *node = static_cast<SparseArrayNode *>(qMapAllocate(sizeof(SparseArrayNode), alignof(SparseArrayNode)));
Q_CHECK_PTR(node);
node->p = (quintptr)parent;
diff --git a/src/qml/jsruntime/qv4sparsearray_p.h b/src/qml/jsruntime/qv4sparsearray_p.h
index c1e50c8dcf..248fcdb02f 100644
--- a/src/qml/jsruntime/qv4sparsearray_p.h
+++ b/src/qml/jsruntime/qv4sparsearray_p.h
@@ -147,7 +147,7 @@ struct Q_QML_EXPORT SparseArray
SparseArray();
~SparseArray() {
if (root())
- freeTree(header.left, Q_ALIGNOF(SparseArrayNode));
+ freeTree(header.left, alignof(SparseArrayNode));
}
SparseArray(const SparseArray &other);
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 223f4a4769..fc004a2ce0 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -91,18 +91,14 @@ bool String::virtualIsEqualTo(Managed *t, Managed *o)
void Heap::String::init(const QString &t)
{
- Base::init();
-
+ QString mutableText(t);
+ StringOrSymbol::init(mutableText.data_ptr());
subtype = String::StringType_Unknown;
-
- text = const_cast<QString &>(t).data_ptr();
- text->ref.ref();
}
void Heap::ComplexString::init(String *l, String *r)
{
- Base::init();
-
+ StringOrSymbol::init();
subtype = String::StringType_AddedString;
left = l;
@@ -125,7 +121,7 @@ void Heap::ComplexString::init(String *l, String *r)
void Heap::ComplexString::init(Heap::String *ref, int from, int len)
{
Q_ASSERT(ref->length() >= from + len);
- Base::init();
+ StringOrSymbol::init();
subtype = String::StringType_SubString;
@@ -136,11 +132,11 @@ void Heap::ComplexString::init(Heap::String *ref, int from, int len)
void Heap::StringOrSymbol::destroy()
{
- if (text) {
- internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(-text->size) * (int)sizeof(QChar));
- if (!text->ref.deref())
- QStringData::deallocate(text);
+ if (subtype < Heap::String::StringType_AddedString) {
+ internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(
+ qptrdiff(-text()->size) * qptrdiff(sizeof(QChar)));
}
+ text().~QStringPrivate();
Base::destroy();
}
@@ -164,27 +160,27 @@ uint String::toUInt(bool *ok) const
void String::createPropertyKeyImpl() const
{
- if (!d()->text)
+ if (d()->subtype >= Heap::String::StringType_AddedString)
d()->simplifyString();
- Q_ASSERT(d()->text);
+ Q_ASSERT(d()->subtype < Heap::String::StringType_AddedString);
engine()->identifierTable->asPropertyKey(this);
}
void Heap::String::simplifyString() const
{
- Q_ASSERT(!text);
+ Q_ASSERT(subtype >= StringType_AddedString);
int l = length();
QString result(l, Qt::Uninitialized);
QChar *ch = const_cast<QChar *>(result.constData());
append(this, ch);
- text = result.data_ptr();
- text->ref.ref();
+ text() = result.data_ptr();
const ComplexString *cs = static_cast<const ComplexString *>(this);
identifier = PropertyKey::invalid();
cs->left = cs->right = nullptr;
- internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(qptrdiff(text->size) * (qptrdiff)sizeof(QChar));
+ internalClass->engine->memoryManager->changeUnmanagedHeapSizeUsage(
+ qptrdiff(text().size) * qptrdiff(sizeof(QChar)));
subtype = StringType_Unknown;
}
@@ -206,7 +202,7 @@ bool Heap::String::startsWithUpper() const
offset = cs->from;
}
Q_ASSERT(str->subtype < Heap::String::StringType_Complex);
- return str->text->size > offset && QChar::isUpper(str->text->data()[offset]);
+ return str->text().size > offset && QChar::isUpper(str->text().data()[offset]);
}
void Heap::String::append(const String *data, QChar *ch)
@@ -228,21 +224,21 @@ void Heap::String::append(const String *data, QChar *ch)
memcpy(ch, cs->left->toQString().constData() + cs->from, cs->len*sizeof(QChar));
ch += cs->len;
} else {
- memcpy(static_cast<void *>(ch), static_cast<const void *>(item->text->data()), item->text->size * sizeof(QChar));
- ch += item->text->size;
+ memcpy(static_cast<void *>(ch), item->text().data(), item->text().size * sizeof(QChar));
+ ch += item->text().size;
}
}
}
void Heap::StringOrSymbol::createHashValue() const
{
- if (!text) {
+ if (subtype >= StringType_AddedString) {
Q_ASSERT(internalClass->vtable->isString);
static_cast<const Heap::String *>(this)->simplifyString();
}
- Q_ASSERT(text);
- const QChar *ch = reinterpret_cast<const QChar *>(text->data());
- const QChar *end = ch + text->size;
+ Q_ASSERT(subtype < StringType_AddedString);
+ const QChar *ch = reinterpret_cast<const QChar *>(text().data());
+ const QChar *end = ch + text().size;
stringHash = QV4::String::calculateHashValue(ch, end, &subtype);
}
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index 52fe09cd72..d5d11ef660 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -77,7 +77,18 @@ struct Q_QML_PRIVATE_EXPORT StringOrSymbol : Base
StringType_Complex = StringType_AddedString
};
- mutable QStringData *text;
+ void init() {
+ Base::init();
+ new (&textStorage) QStringPrivate;
+ }
+
+ void init(QStringPrivate text)
+ {
+ Base::init();
+ new (&textStorage) QStringPrivate(std::move(text));
+ }
+
+ mutable std::aligned_storage<sizeof(QStringPrivate), alignof(QStringPrivate)>::type textStorage;
mutable PropertyKey identifier;
mutable uint subtype;
mutable uint stringHash;
@@ -85,12 +96,11 @@ struct Q_QML_PRIVATE_EXPORT StringOrSymbol : Base
static void markObjects(Heap::Base *that, MarkStack *markStack);
void destroy();
+ QStringPrivate &text() const { return *reinterpret_cast<QStringPrivate *>(&textStorage); }
+
inline QString toQString() const {
- if (!text)
- return QString();
- QStringDataPtr ptr = { text };
- text->ref.ref();
- return QString(ptr);
+ QStringPrivate dd = text();
+ return QString(std::move(dd));
}
void createHashValue() const;
inline unsigned hashValue() const {
@@ -113,14 +123,12 @@ struct Q_QML_PRIVATE_EXPORT String : StringOrSymbol {
void simplifyString() const;
int length() const;
std::size_t retainedTextSize() const {
- return subtype >= StringType_Complex ? 0 : (std::size_t(text->size) * sizeof(QChar));
+ return subtype >= StringType_Complex ? 0 : (std::size_t(text().size) * sizeof(QChar));
}
inline QString toQString() const {
if (subtype >= StringType_Complex)
simplifyString();
- QStringDataPtr ptr = { text };
- text->ref.ref();
- return QString(ptr);
+ return StringOrSymbol::toQString();
}
inline bool isEqualTo(const String *other) const {
if (this == other)
@@ -158,7 +166,7 @@ Q_STATIC_ASSERT(std::is_trivial< ComplexString >::value);
inline
int String::length() const {
- return text ? text->size : static_cast<const ComplexString *>(this)->len;
+ return subtype < StringType_AddedString ? text().size : static_cast<const ComplexString *>(this)->len;
}
}
@@ -252,7 +260,7 @@ public:
}
if (subtype)
- *subtype = (charToUInt(ch) == '@') ? Heap::StringOrSymbol::StringType_Symbol : Heap::StringOrSymbol::StringType_Regular;
+ *subtype = (ch != end && charToUInt(ch) == '@') ? Heap::StringOrSymbol::StringType_Symbol : Heap::StringOrSymbol::StringType_Regular;
return h;
}
};
diff --git a/src/qml/jsruntime/qv4symbol.cpp b/src/qml/jsruntime/qv4symbol.cpp
index 004a9938e2..be6d821c14 100644
--- a/src/qml/jsruntime/qv4symbol.cpp
+++ b/src/qml/jsruntime/qv4symbol.cpp
@@ -50,10 +50,9 @@ DEFINE_OBJECT_VTABLE(SymbolObject);
void Heap::Symbol::init(const QString &s)
{
Q_ASSERT(s.at(0) == QLatin1Char('@'));
- identifier = PropertyKey::fromStringOrSymbol(this);
QString desc(s);
- text = desc.data_ptr();
- text->ref.ref();
+ StringOrSymbol::init(desc.data_ptr());
+ identifier = PropertyKey::fromStringOrSymbol(this);
}
void Heap::SymbolCtor::init(QV4::ExecutionContext *scope)
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
index d03b67aa27..f425c6c87f 100644
--- a/src/qml/jsruntime/qv4typedarray.cpp
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -338,8 +338,8 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
array->d()->byteLength = destByteLength;
array->d()->byteOffset = 0;
- const char *src = buffer->d()->data->data() + typedArray->d()->byteOffset;
- char *dest = newBuffer->d()->data->data();
+ const char *src = buffer->d()->data()->data() + typedArray->d()->byteOffset;
+ char *dest = newBuffer->d()->data()->data();
// check if src and new type have the same size. In that case we can simply memcpy the data
if (srcElementSize == destElementSize) {
@@ -420,7 +420,7 @@ ReturnedValue TypedArrayCtor::virtualCallAsConstructor(const FunctionObject *f,
array->d()->byteOffset = 0;
uint idx = 0;
- char *b = newBuffer->d()->data->data();
+ char *b = newBuffer->d()->data()->data();
ScopedValue val(scope);
while (idx < l) {
val = o->get(idx);
@@ -480,7 +480,7 @@ ReturnedValue TypedArray::virtualGet(const Managed *m, PropertyKey id, const Val
if (hasProperty)
*hasProperty = true;
- return a->d()->type->read(a->d()->buffer->data->data() + byteOffset);
+ return a->d()->type->read(a->d()->buffer->data()->data() + byteOffset);
}
bool TypedArray::virtualHasProperty(const Managed *m, PropertyKey id)
@@ -538,7 +538,7 @@ bool TypedArray::virtualPut(Managed *m, PropertyKey id, const Value &value, Valu
Value v = Value::fromReturnedValue(value.convertedToNumber());
if (scope.hasException() || a->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- a->d()->type->write(a->d()->buffer->data->data() + byteOffset, v);
+ a->d()->type->write(a->d()->buffer->data()->data() + byteOffset, v);
return true;
}
@@ -569,7 +569,7 @@ bool TypedArray::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Prop
uint bytesPerElement = a->d()->type->bytesPerElement;
uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
Q_ASSERT(byteOffset + bytesPerElement <= (uint)a->d()->buffer->byteLength());
- a->d()->type->write(a->d()->buffer->data->data() + byteOffset, v);
+ a->d()->type->write(a->d()->buffer->data()->data() + byteOffset, v);
}
return true;
}
@@ -713,7 +713,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_copyWithin(const FunctionObje
if (from != to) {
int elementSize = O->d()->type->bytesPerElement;
- char *data = O->d()->buffer->data->data() + O->d()->byteOffset;
+ char *data = O->d()->buffer->data()->data() + O->d()->byteOffset;
memmove(data + to*elementSize, data + from*elementSize, count*elementSize);
}
@@ -749,7 +749,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_every(const FunctionObject *b
ScopedValue r(scope);
Value *arguments = scope.alloc(3);
- const char *data = v->d()->buffer->data->data();
+ const char *data = v->d()->buffer->data()->data();
uint bytesPerElement = v->d()->type->bytesPerElement;
uint byteOffset = v->d()->byteOffset;
@@ -803,7 +803,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_fill(const FunctionObject *b,
if (scope.hasException() || v->d()->buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- char *data = v->d()->buffer->data->data();
+ char *data = v->d()->buffer->data()->data();
uint bytesPerElement = v->d()->type->bytesPerElement;
uint byteOffset = v->d()->byteOffset;
@@ -1422,7 +1422,7 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b,
uint idx = 0;
if (buffer->isDetachedBuffer())
return scope.engine->throwTypeError();
- char *b = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
+ char *b = buffer->d()->data()->data() + a->d()->byteOffset + offset*elementSize;
ScopedValue val(scope);
while (idx < l) {
val = o->get(idx);
@@ -1451,8 +1451,8 @@ ReturnedValue IntrinsicTypedArrayPrototype::method_set(const FunctionObject *b,
if (offset > aLength || l > aLength - offset)
RETURN_RESULT(scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range")));
- char *dest = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
- const char *src = srcBuffer->d()->data->data() + srcTypedArray->d()->byteOffset;
+ char *dest = buffer->d()->data()->data() + a->d()->byteOffset + offset*elementSize;
+ const char *src = srcBuffer->d()->data()->data() + srcTypedArray->d()->byteOffset;
if (srcTypedArray->d()->type == a->d()->type) {
// same type of typed arrays, use memmove (as srcbuffer and buffer could be the same)
memmove(dest, src, srcTypedArray->d()->byteLength);
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
index 65656e3389..e590083bc3 100644
--- a/src/qml/jsruntime/qv4typedarray_p.h
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -156,8 +156,8 @@ struct Q_QML_PRIVATE_EXPORT TypedArray : Object
return d()->byteLength/d()->type->bytesPerElement;
}
- QTypedArrayData<char> *arrayData() {
- return d()->buffer->data;
+ QArrayDataPointer<char> *arrayData() {
+ return &d()->buffer->data();
}
Heap::TypedArray::Type arrayType() const {
diff --git a/src/qml/jsruntime/qv4urlobject.cpp b/src/qml/jsruntime/qv4urlobject.cpp
new file mode 100644
index 0000000000..15e827680e
--- /dev/null
+++ b/src/qml/jsruntime/qv4urlobject.cpp
@@ -0,0 +1,689 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4urlobject_p.h"
+
+#include <QtCore/QUrl>
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(UrlObject);
+DEFINE_OBJECT_VTABLE(UrlCtor);
+
+void Heap::UrlCtor::init(QV4::ExecutionContext *scope)
+{
+ Heap::FunctionObject::init(scope, QLatin1String("URL"));
+}
+
+void UrlPrototype::init(ExecutionEngine *engine, Object *ctor)
+{
+ Q_UNUSED(ctor)
+
+ Scope scope(engine);
+ ScopedObject o(scope);
+
+ defineDefaultProperty(QLatin1String("toString"), method_getHref);
+ defineDefaultProperty(QLatin1String("toJSON"), method_getHref);
+
+ defineAccessorProperty(QLatin1String("hash"), method_getHash, method_setHash);
+ defineAccessorProperty(QLatin1String("host"), method_getHost, method_setHost);
+ defineAccessorProperty(QLatin1String("hostname"), method_getHostname, method_setHostname);
+ defineAccessorProperty(QLatin1String("href"), method_getHref, method_setHref);
+ defineAccessorProperty(QLatin1String("origin"), method_getOrigin, nullptr);
+ defineAccessorProperty(QLatin1String("password"), method_getPassword, method_setPassword);
+ defineAccessorProperty(QLatin1String("pathname"), method_getPathname, method_setPathname);
+ defineAccessorProperty(QLatin1String("port"), method_getPort, method_setPort);
+ defineAccessorProperty(QLatin1String("protocol"), method_getProtocol, method_setProtocol);
+ defineAccessorProperty(QLatin1String("search"), method_getSearch, method_setSearch);
+ defineAccessorProperty(QLatin1String("username"), method_getUsername, method_setUsername);
+}
+
+bool UrlObject::setHash(QString hash)
+{
+ if (hash.startsWith(QLatin1Char('#')))
+ hash = hash.mid(1);
+
+ QUrl url = toQUrl();
+ url.setFragment(hash);
+
+ if (!url.isValid())
+ return false;
+
+ d()->hash.set(engine(), engine()->newString(url.fragment()));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+
+ return true;
+}
+
+bool UrlObject::setHostname(QString host)
+{
+ QUrl url = toQUrl();
+ url.setHost(host);
+
+ if (!url.isValid())
+ return false;
+
+ d()->hostname.set(engine(), engine()->newString(url.host()));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+
+ updateOrigin();
+ updateHost();
+
+ return true;
+}
+
+bool UrlObject::setHost(QString hostname)
+{
+ int port = -1;
+
+ if (hostname.contains(QLatin1Char(':'))) {
+ const QStringList list = hostname.split(QLatin1Char(':'));
+ hostname = list[0];
+ port = list[1].toInt();
+ }
+
+ QUrl url = toQUrl();
+ url.setHost(hostname);
+ url.setPort(port);
+
+ if (!url.isValid())
+ return false;
+
+ if (url.port() != -1)
+ d()->port.set(engine(), engine()->newString(QString::number(url.port())));
+
+ d()->hostname.set(engine(), engine()->newString(url.host()));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+
+ updateOrigin();
+ updateHost();
+
+ return true;
+}
+
+bool UrlObject::setHref(QString href)
+{
+ QUrl url(href);
+
+ if (!url.isValid() || url.isRelative())
+ return false;
+
+ d()->hash.set(engine(), engine()->newString(url.fragment()));
+ d()->hostname.set(engine(), engine()->newString(url.host()));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+ d()->password.set(engine(), engine()->newString(url.password()));
+ d()->pathname.set(engine(), engine()->newString(url.path()));
+ d()->port.set(engine(),
+ engine()->newString(url.port() == -1 ? QLatin1String("")
+ : QString::number(url.port())));
+ d()->protocol.set(engine(), engine()->newString(url.scheme()));
+ d()->search.set(engine(), engine()->newString(url.query()));
+ d()->username.set(engine(), engine()->newString(url.userName()));
+
+ updateOrigin();
+ updateHost();
+
+ return true;
+}
+
+bool UrlObject::setPassword(QString password)
+{
+ QUrl url = toQUrl();
+ url.setPassword(password);
+
+ if (!url.isValid())
+ return false;
+
+ d()->password.set(engine(), engine()->newString(url.password()));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+
+ return true;
+}
+
+bool UrlObject::setPathname(QString pathname)
+{
+ QUrl url = toQUrl();
+ url.setPath(pathname);
+
+ if (!url.isValid())
+ return false;
+
+ d()->pathname.set(engine(), engine()->newString(url.path()));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+
+ return true;
+}
+
+bool UrlObject::setPort(QString port)
+{
+ QUrl url = toQUrl();
+ url.setPort(port.isEmpty() ? -1 : port.toInt());
+
+ if (!url.isValid())
+ return false;
+
+ d()->port.set(engine(),
+ engine()->newString(url.port() == -1 ? QLatin1String("")
+ : QString::number(url.port())));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+
+ updateOrigin();
+ updateHost();
+
+ return true;
+}
+
+bool UrlObject::setProtocol(QString protocol)
+{
+ QUrl url = toQUrl();
+ url.setScheme(protocol);
+
+ if (!url.isValid())
+ return false;
+
+ d()->protocol.set(engine(), engine()->newString(url.scheme()));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+
+ updateOrigin();
+ updateHost();
+
+ return true;
+}
+
+bool UrlObject::setSearch(QString search)
+{
+ QUrl url = toQUrl();
+
+ if (search.startsWith(QLatin1Char('?')))
+ search = search.mid(1);
+
+ url.setQuery(search);
+
+ if (!url.isValid())
+ return false;
+
+ d()->search.set(engine(), engine()->newString(url.query()));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+
+ return true;
+}
+
+bool UrlObject::setUsername(QString username)
+{
+ QUrl url = toQUrl();
+ url.setUserName(username);
+
+ if (!url.isValid())
+ return false;
+
+ d()->username.set(engine(), engine()->newString(url.userName()));
+ d()->href.set(engine(), engine()->newString(url.toString()));
+
+ return true;
+}
+
+QUrl UrlObject::toQUrl() const
+{
+ return QUrl(href());
+}
+
+void UrlObject::updateOrigin()
+{
+ QUrl url = toQUrl();
+
+ QString proto = url.scheme();
+
+ // A blob's origin is the origin of the URL that it points to
+ if (proto == QLatin1String("blob")) {
+ url = QUrl(url.path());
+ proto = url.scheme();
+ }
+
+ QString origin;
+ if (proto == QLatin1String("http") || proto == QLatin1String("https")
+ || proto == QLatin1String("ftp")) {
+ origin = QLatin1String("%1://%2").arg(url.scheme(), url.host());
+
+ if (url.port() != -1)
+ origin.append(QLatin1String(":") + QString::number(url.port()));
+ }
+
+ d()->origin.set(engine(), engine()->newString(origin));
+}
+
+void UrlObject::updateHost()
+{
+ QUrl url = toQUrl();
+
+ QString host = url.host();
+
+ if (url.port() != -1)
+ host.append(QLatin1String(":") + QString::number(url.port()));
+
+ d()->host.set(engine(), engine()->newString(host));
+}
+
+ReturnedValue UrlPrototype::method_getHash(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->hash()));
+}
+
+ReturnedValue UrlPrototype::method_setHash(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ if (stringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ r->setHash(stringValue->toQString());
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlPrototype::method_getHost(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->host()));
+}
+
+ReturnedValue UrlPrototype::method_setHost(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ if (stringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ QString host = stringValue->toQString();
+ if (!r->setHost(host))
+ return v4->throwTypeError(QLatin1String("Invalid host: %1").arg(host));
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlPrototype::method_getHostname(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->hostname()));
+}
+
+ReturnedValue UrlPrototype::method_setHostname(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ if (stringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ QString hostname = stringValue->toQString();
+ if (!r->setHostname(hostname))
+ return v4->throwTypeError(QLatin1String("Invalid hostname: %1").arg(hostname));
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlPrototype::method_getHref(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->href()));
+}
+
+ReturnedValue UrlPrototype::method_setHref(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ if (stringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ QString href = stringValue->toQString();
+ if (!r->setHref(href))
+ return v4->throwTypeError(QLatin1String("Invalid URL: %1").arg(href));
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlPrototype::method_getOrigin(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->origin()));
+}
+
+ReturnedValue UrlPrototype::method_getPassword(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->password()));
+}
+
+ReturnedValue UrlPrototype::method_setPassword(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ if (stringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ r->setPassword(stringValue->toQString());
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlPrototype::method_getPathname(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->pathname()));
+}
+
+ReturnedValue UrlPrototype::method_setPathname(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ if (stringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ r->setPathname(stringValue->toQString());
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlPrototype::method_getPort(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->port()));
+}
+
+ReturnedValue UrlPrototype::method_setPort(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ QString port;
+
+ if (stringValue != nullptr)
+ port = stringValue->toQString();
+ else if (arg->isInt32())
+ port = QString::number(arg->toInt32());
+ else
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ if (!r->setPort(port))
+ return v4->throwTypeError(QLatin1String("Invalid port: %1").arg(port));
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlPrototype::method_getProtocol(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->protocol()));
+}
+
+ReturnedValue UrlPrototype::method_setProtocol(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ if (stringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ r->setProtocol(stringValue->toQString());
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlPrototype::method_getSearch(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->search()));
+}
+
+ReturnedValue UrlPrototype::method_setSearch(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ if (stringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ r->setSearch(stringValue->toQString());
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlPrototype::method_getUsername(const FunctionObject *b, const Value *thisObject,
+ const Value *, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ return Encode(v4->newString(r->username()));
+}
+
+ReturnedValue UrlPrototype::method_setUsername(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int)
+{
+ ExecutionEngine *v4 = b->engine();
+ Scope scope(v4);
+
+ ScopedValue arg(scope, argv[0]);
+ String *stringValue = arg->stringValue();
+
+ if (stringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+
+ r->setUsername(stringValue->toQString());
+
+ return Encode::undefined();
+}
+
+ReturnedValue UrlCtor::virtualCallAsConstructor(const FunctionObject *that, const Value *argv,
+ int argc, const Value *newTarget)
+{
+ ExecutionEngine *v4 = that->engine();
+
+ if (argc < 1 || argc > 2)
+ return v4->throwError(QLatin1String("Invalid amount of arguments"));
+
+ Scope scope(v4);
+
+ ScopedValue arg1(scope, argv[0]);
+ String *arg1StringValue = arg1->stringValue();
+
+ if (arg1StringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ QString arg1String = arg1StringValue->toQString();
+ QString urlString;
+
+ if (argc == 2) {
+ ScopedValue arg2(scope, argv[1]);
+ String *arg2StringValue = arg2->stringValue();
+
+ if (arg2StringValue == nullptr)
+ return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
+
+ QUrl url = QUrl(arg2StringValue->toQString());
+ QUrl relativeUrl = QUrl(arg1String);
+
+ QString baseUrlPath = url.path();
+ QString relativePath = relativeUrl.path();
+
+ // If the base URL contains a path the last section of it is discarded
+ int lastSlash = baseUrlPath.lastIndexOf(QLatin1Char('/'));
+ if (lastSlash != -1)
+ baseUrlPath.truncate(lastSlash);
+
+ if (!relativePath.startsWith(QLatin1Char('/')))
+ relativePath = relativePath.prepend(QLatin1Char('/'));
+
+ url.setPath(baseUrlPath + relativePath);
+ url.setFragment(relativeUrl.fragment());
+ url.setQuery(relativeUrl.query());
+
+ urlString = url.toString();
+ } else {
+ urlString = arg1String;
+ }
+
+ ReturnedValue o = Encode(v4->newUrlObject());
+
+ if (!newTarget)
+ return o;
+
+ ScopedObject obj(scope, o);
+ obj->setProtoFromNewTarget(newTarget);
+
+ UrlObject *urlObject = obj->as<UrlObject>();
+
+ if (!urlObject->setHref(urlString))
+ return v4->throwTypeError(QLatin1String("Invalid URL: %1").arg(urlString));
+
+ return obj->asReturnedValue();
+}
diff --git a/src/qml/jsruntime/qv4urlobject_p.h b/src/qml/jsruntime/qv4urlobject_p.h
new file mode 100644
index 0000000000..bc066818b6
--- /dev/null
+++ b/src/qml/jsruntime/qv4urlobject_p.h
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4URLOBJECT_P_H
+#define QV4URLOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qv4object_p.h"
+#include "qv4functionobject_p.h"
+
+#include <QtCore/QString>
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+namespace Heap {
+// clang-format off
+#define UrlObjectMembers(class, Member) \
+ Member(class, Pointer, String *, hash) \
+ Member(class, Pointer, String *, host) \
+ Member(class, Pointer, String *, hostname) \
+ Member(class, Pointer, String *, href) \
+ Member(class, Pointer, String *, origin) \
+ Member(class, Pointer, String *, password) \
+ Member(class, Pointer, String *, pathname) \
+ Member(class, Pointer, String *, port) \
+ Member(class, Pointer, String *, protocol) \
+ Member(class, Pointer, String *, search) \
+ Member(class, Pointer, String *, username)
+// clang-format on
+
+DECLARE_HEAP_OBJECT(UrlObject, Object)
+{
+ DECLARE_MARKOBJECTS(UrlObject);
+ void init() { Object::init(); }
+};
+
+struct UrlCtor : FunctionObject
+{
+ void init(QV4::ExecutionContext *scope);
+};
+}
+
+struct UrlObject : Object
+{
+ V4_OBJECT2(UrlObject, Object)
+ Q_MANAGED_TYPE(UrlObject)
+ V4_PROTOTYPE(urlPrototype)
+
+ QString hash() const { return QLatin1String("#") + d()->hash->toQString(); }
+ bool setHash(QString hash);
+
+ QString host() const { return d()->host->toQString(); }
+ bool setHost(QString host);
+
+ QString hostname() const { return d()->hostname->toQString(); }
+ bool setHostname(QString hostname);
+
+ QString href() const { return d()->href->toQString(); }
+ bool setHref(QString href);
+
+ QString origin() const { return d()->origin->toQString(); }
+
+ QString password() const { return d()->password->toQString(); }
+ bool setPassword(QString password);
+
+ QString pathname() const { return d()->pathname->toQString(); }
+ bool setPathname(QString pathname);
+
+ QString port() const { return d()->port->toQString(); }
+ bool setPort(QString port);
+
+ QString protocol() const { return d()->protocol->toQString(); }
+ bool setProtocol(QString protocol);
+
+ QString search() const { return QLatin1String("?") + d()->search->toQString(); }
+ bool setSearch(QString search);
+
+ QString username() const { return d()->username->toQString(); }
+ bool setUsername(QString username);
+
+private:
+ QUrl toQUrl() const;
+ void updateOrigin();
+ void updateHost();
+};
+
+template<>
+inline const UrlObject *Value::as() const
+{
+ return isManaged() && m()->internalClass->vtable->type == Managed::Type_UrlObject
+ ? static_cast<const UrlObject *>(this)
+ : nullptr;
+}
+
+struct UrlCtor : FunctionObject
+{
+ V4_OBJECT2(UrlCtor, FunctionObject)
+
+ static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv,
+ int argc, const Value *);
+};
+
+struct UrlPrototype : Object
+{
+ V4_PROTOTYPE(objectPrototype)
+
+ void init(ExecutionEngine *engine, Object *ctor);
+
+ static ReturnedValue method_getHash(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setHash(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getHost(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setHost(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getHostname(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setHostname(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getHref(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setHref(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getOrigin(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getPassword(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setPassword(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getPathname(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setPathname(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getPort(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setPort(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getProtocol(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setProtocol(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getSearch(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setSearch(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+
+ static ReturnedValue method_getUsername(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+ static ReturnedValue method_setUsername(const FunctionObject *, const Value *thisObject,
+ const Value *argv, int argc);
+};
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QV4URLOBJECT_P_H
diff --git a/src/qml/memory/qv4mm_p.h b/src/qml/memory/qv4mm_p.h
index 6dfdd81cb2..74a760d093 100644
--- a/src/qml/memory/qv4mm_p.h
+++ b/src/qml/memory/qv4mm_p.h
@@ -212,46 +212,46 @@ public:
}
template <typename ManagedType, typename Arg1>
- typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
+ typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 &&arg1)
{
typename ManagedType::Data *o = reinterpret_cast<typename ManagedType::Data *>(allocString(unmanagedSize));
o->internalClass.set(engine, ManagedType::defaultInternalClass(engine));
Q_ASSERT(o->internalClass && o->internalClass->vtable);
- o->init(arg1);
+ o->init(std::forward<Arg1>(arg1));
return o;
}
template <typename ObjectType, typename... Args>
- typename ObjectType::Data *allocObject(Heap::InternalClass *ic, Args... args)
+ typename ObjectType::Data *allocObject(Heap::InternalClass *ic, Args&&... args)
{
typename ObjectType::Data *d = allocateObject<ObjectType>(ic);
- d->init(args...);
+ d->init(std::forward<Args>(args)...);
return d;
}
template <typename ObjectType, typename... Args>
- typename ObjectType::Data *allocObject(InternalClass *ic, Args... args)
+ typename ObjectType::Data *allocObject(InternalClass *ic, Args&&... args)
{
typename ObjectType::Data *d = allocateObject<ObjectType>(ic);
- d->init(args...);
+ d->init(std::forward<Args>(args)...);
return d;
}
template <typename ObjectType, typename... Args>
- typename ObjectType::Data *allocate(Args... args)
+ typename ObjectType::Data *allocate(Args&&... args)
{
Scope scope(engine);
Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
- t->d_unchecked()->init(args...);
+ t->d_unchecked()->init(std::forward<Args>(args)...);
return t->d();
}
template <typename ManagedType, typename... Args>
- typename ManagedType::Data *alloc(Args... args)
+ typename ManagedType::Data *alloc(Args&&... args)
{
Scope scope(engine);
Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
- t->d_unchecked()->init(args...);
+ t->d_unchecked()->init(std::forward<Args>(args)...);
return t->d();
}
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index e4b7198b30..67f9cc7581 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -835,7 +835,15 @@ UiImport: UiImportHead Semicolon;
UiVersionSpecifier: T_VERSION_NUMBER T_DOT T_VERSION_NUMBER;
/.
case $rule_number: {
- auto version = new (pool) AST::UiVersionSpecifier(sym(1).dval, sym(3).dval);
+ const int major = sym(1).dval;
+ const int minor = sym(3).dval;
+ if (!QTypeRevision::isValidSegment(major) || !QTypeRevision::isValidSegment(minor)) {
+ diagnostic_messages.append(
+ compileError(loc(1),
+ QLatin1String("Invalid version. Version numbers must be >= 0 and < 255.")));
+ return false;
+ }
+ auto version = new (pool) AST::UiVersionSpecifier(major, minor);
version->majorToken = loc(1);
version->minorToken = loc(3);
sym(1).UiVersionSpecifier = version;
@@ -846,7 +854,14 @@ UiVersionSpecifier: T_VERSION_NUMBER T_DOT T_VERSION_NUMBER;
UiVersionSpecifier: T_VERSION_NUMBER;
/.
case $rule_number: {
- auto version = new (pool) AST::UiVersionSpecifier(sym(1).dval, 0);
+ const int major = sym(1).dval;
+ if (!QTypeRevision::isValidSegment(major)) {
+ diagnostic_messages.append(
+ compileError(loc(1),
+ QLatin1String("Invalid major version. Version numbers must be >= 0 and < 255.")));
+ return false;
+ }
+ auto version = new (pool) AST::UiVersionSpecifier(sym(1).dval);
version->majorToken = loc(1);
sym(1).UiVersionSpecifier = version;
} break;
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index 9eba432e69..8c1d8a2510 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -57,6 +57,7 @@
#include <private/qqmljsmemorypool_p.h>
#include <QtCore/qstring.h>
+#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
@@ -646,7 +647,15 @@ class QML_PARSER_EXPORT UiVersionSpecifier : public Node
public:
QQMLJS_DECLARE_AST_NODE(UiVersionSpecifier)
- UiVersionSpecifier(int majorum, int minorum) : majorVersion(majorum), minorVersion(minorum) { kind = K; }
+ UiVersionSpecifier(int majorum) : version(QTypeRevision::fromMajorVersion(majorum))
+ {
+ kind = K;
+ }
+
+ UiVersionSpecifier(int majorum, int minorum) : version(QTypeRevision::fromVersion(majorum, minorum))
+ {
+ kind = K;
+ }
void accept0(BaseVisitor *visitor) override;
@@ -658,8 +667,7 @@ public:
}
// attributes:
- int majorVersion;
- int minorVersion;
+ QTypeRevision version;
SourceLocation majorToken;
SourceLocation minorToken;
};
diff --git a/src/qml/parser/qqmljsglobal_p.h b/src/qml/parser/qqmljsglobal_p.h
index bf8155c6ec..e7937ebc3b 100644
--- a/src/qml/parser/qqmljsglobal_p.h
+++ b/src/qml/parser/qqmljsglobal_p.h
@@ -52,29 +52,17 @@
#include <QtCore/qglobal.h>
-#ifdef QT_CREATOR
-
-# ifdef QDECLARATIVEJS_BUILD_DIR
-# define QML_PARSER_EXPORT Q_DECL_EXPORT
-# elif QML_BUILD_STATIC_LIB
+#ifndef QT_STATIC
+# if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
+ // QmlDevTools is a static library
# define QML_PARSER_EXPORT
+# elif defined(QT_BUILD_QML_LIB)
+# define QML_PARSER_EXPORT Q_DECL_EXPORT
# else
# define QML_PARSER_EXPORT Q_DECL_IMPORT
-# endif // QQMLJS_BUILD_DIR
-
-#else // !QT_CREATOR
-# ifndef QT_STATIC
-# if defined(QT_BUILD_QMLDEVTOOLS_LIB) || defined(QT_QMLDEVTOOLS_LIB)
- // QmlDevTools is a static library
-# define QML_PARSER_EXPORT
-# elif defined(QT_BUILD_QML_LIB)
-# define QML_PARSER_EXPORT Q_DECL_EXPORT
-# else
-# define QML_PARSER_EXPORT Q_DECL_IMPORT
-# endif
-# else
-# define QML_PARSER_EXPORT
# endif
-#endif // QT_CREATOR
+#else
+# define QML_PARSER_EXPORT
+#endif
#endif // QQMLJSGLOBAL_P_H
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index 243fc5bd30..4f694447bb 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -1538,9 +1538,10 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
setError(QCoreApplication::translate("QQmlParser","Imported file must be a script"));
return false;
}
+ lex();
} else if (_tokenKind == T_IDENTIFIER) {
- // .import T_IDENTIFIER (. T_IDENTIFIER)* T_VERSION_NUMBER . T_VERSION_NUMBER as T_IDENTIFIER
+ // .import T_IDENTIFIER (. T_IDENTIFIER)* (T_VERSION_NUMBER (. T_VERSION_NUMBER)?)? as T_IDENTIFIER
while (true) {
if (!isUriToken(_tokenKind)) {
setError(QCoreApplication::translate("QQmlParser","Invalid module URI"));
@@ -1566,31 +1567,27 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
}
}
- if (_tokenKind != T_VERSION_NUMBER) {
- setError(QCoreApplication::translate("QQmlParser","Module import requires a version"));
- return false; // expected the module version number
- }
-
- version = tokenText();
- lex();
- if (_tokenKind != T_DOT) {
- setError(QCoreApplication::translate( "QQmlParser", "Module import requires a minor version (missing dot)"));
- return false; // expected the module version number
- }
- version += QLatin1Char('.');
-
- lex();
- if (_tokenKind != T_VERSION_NUMBER) {
- setError(QCoreApplication::translate( "QQmlParser", "Module import requires a minor version (missing number)"));
- return false; // expected the module version number
+ if (_tokenKind == T_VERSION_NUMBER) {
+ version = tokenText();
+ lex();
+ if (_tokenKind == T_DOT) {
+ version += QLatin1Char('.');
+ lex();
+ if (_tokenKind != T_VERSION_NUMBER) {
+ setError(QCoreApplication::translate(
+ "QQmlParser", "Incomplete version number (dot but no minor)"));
+ return false; // expected the module version number
+ }
+ version += tokenText();
+ lex();
+ }
}
- version += tokenText();
}
//
// recognize the mandatory `as' followed by the module name
//
- if (! (lex() == T_AS && tokenStartLine() == lineNumber)) {
+ if (! (_tokenKind == T_AS && tokenStartLine() == lineNumber)) {
if (fileImport)
setError(QCoreApplication::translate("QQmlParser", "File import requires a qualifier"));
else
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index e39a8319b6..7bb3547ee9 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -71,7 +71,7 @@ MODULE_PLUGIN_TYPES = \
QMLTYPES_FILENAME = plugins.qmltypes
QMLTYPES_INSTALL_DIR = $$[QT_INSTALL_QML]/QtQml
QML_IMPORT_NAME = QtQml
-IMPORT_VERSION = 2.$$QT_MINOR_VERSION
+QML_IMPORT_VERSION = $$QT_VERSION
CONFIG += qmltypes install_qmltypes install_metatypes
load(qt_module)
diff --git a/src/qml/qml/ftw/qfieldlist_p.h b/src/qml/qml/ftw/qfieldlist_p.h
index 2bf07fb20d..66602daab2 100644
--- a/src/qml/qml/ftw/qfieldlist_p.h
+++ b/src/qml/qml/ftw/qfieldlist_p.h
@@ -52,11 +52,12 @@
//
#include <QtCore/qglobal.h>
+#include <QtCore/qtaggedpointer.h>
#include <private/qflagpointer_p.h>
// QForwardFieldList is a super simple linked list that can only prepend
-template<class N, N *N::*nextMember>
+template<class N, N *N::*nextMember, typename Tag = QtPrivate::TagInfo<N>>
class QForwardFieldList
{
public:
@@ -72,17 +73,10 @@ public:
static inline N *next(N *v);
- inline bool flag() const;
- inline void setFlag();
- inline void clearFlag();
- inline void setFlagValue(bool);
-
- inline bool flag2() const;
- inline void setFlag2();
- inline void clearFlag2();
- inline void setFlag2Value(bool);
+ inline Tag tag() const;
+ inline void setTag(Tag t);
private:
- QFlagPointer<N> _first;
+ QTaggedPointer<N, Tag> _first;
};
// QFieldList is a simple linked list, that can append and prepend and also
@@ -108,8 +102,10 @@ public:
inline void insertAfter(N *, QFieldList<N, nextMember> &);
inline void copyAndClear(QFieldList<N, nextMember> &);
- inline void copyAndClearAppend(QForwardFieldList<N, nextMember> &);
- inline void copyAndClearPrepend(QForwardFieldList<N, nextMember> &);
+ template <typename Tag>
+ inline void copyAndClearAppend(QForwardFieldList<N, nextMember, Tag> &);
+ template <typename Tag>
+ inline void copyAndClearPrepend(QForwardFieldList<N, nextMember, Tag> &);
static inline N *next(N *v);
@@ -124,21 +120,21 @@ private:
quint32 _count:31;
};
-template<class N, N *N::*nextMember>
-QForwardFieldList<N, nextMember>::QForwardFieldList()
+template<class N, N *N::*nextMember, typename Tag>
+QForwardFieldList<N, nextMember, Tag>::QForwardFieldList()
{
}
-template<class N, N *N::*nextMember>
-N *QForwardFieldList<N, nextMember>::first() const
+template<class N, N *N::*nextMember, typename Tag>
+N *QForwardFieldList<N, nextMember, Tag>::first() const
{
- return *_first;
+ return _first.data();
}
-template<class N, N *N::*nextMember>
-N *QForwardFieldList<N, nextMember>::takeFirst()
+template<class N, N *N::*nextMember, typename Tag>
+N *QForwardFieldList<N, nextMember, Tag>::takeFirst()
{
- N *value = *_first;
+ N *value = _first.data();
if (value) {
_first = next(value);
value->*nextMember = nullptr;
@@ -146,85 +142,49 @@ N *QForwardFieldList<N, nextMember>::takeFirst()
return value;
}
-template<class N, N *N::*nextMember>
-void QForwardFieldList<N, nextMember>::prepend(N *v)
+template<class N, N *N::*nextMember, typename Tag>
+void QForwardFieldList<N, nextMember, Tag>::prepend(N *v)
{
Q_ASSERT(v->*nextMember == nullptr);
- v->*nextMember = *_first;
+ v->*nextMember = _first.data();
_first = v;
}
-template<class N, N *N::*nextMember>
-bool QForwardFieldList<N, nextMember>::isEmpty() const
+template<class N, N *N::*nextMember, typename Tag>
+bool QForwardFieldList<N, nextMember, Tag>::isEmpty() const
{
return _first.isNull();
}
-template<class N, N *N::*nextMember>
-bool QForwardFieldList<N, nextMember>::isOne() const
+template<class N, N *N::*nextMember, typename Tag>
+bool QForwardFieldList<N, nextMember, Tag>::isOne() const
{
- return *_first && _first->*nextMember == 0;
+ return _first.data() && _first->*nextMember == 0;
}
-template<class N, N *N::*nextMember>
-bool QForwardFieldList<N, nextMember>::isMany() const
+template<class N, N *N::*nextMember, typename Tag>
+bool QForwardFieldList<N, nextMember, Tag>::isMany() const
{
- return *_first && _first->*nextMember != 0;
+ return _first.data() && _first->*nextMember != 0;
}
-template<class N, N *N::*nextMember>
-N *QForwardFieldList<N, nextMember>::next(N *v)
+template<class N, N *N::*nextMember, typename Tag>
+N *QForwardFieldList<N, nextMember, Tag>::next(N *v)
{
Q_ASSERT(v);
return v->*nextMember;
}
-template<class N, N *N::*nextMember>
-bool QForwardFieldList<N, nextMember>::flag() const
-{
- return _first.flag();
-}
-
-template<class N, N *N::*nextMember>
-void QForwardFieldList<N, nextMember>::setFlag()
-{
- _first.setFlag();
-}
-
-template<class N, N *N::*nextMember>
-void QForwardFieldList<N, nextMember>::clearFlag()
-{
- _first.clearFlag();
-}
-
-template<class N, N *N::*nextMember>
-void QForwardFieldList<N, nextMember>::setFlagValue(bool v)
-{
- _first.setFlagValue(v);
-}
-
-template<class N, N *N::*nextMember>
-bool QForwardFieldList<N, nextMember>::flag2() const
-{
- return _first.flag2();
-}
-
-template<class N, N *N::*nextMember>
-void QForwardFieldList<N, nextMember>::setFlag2()
+template<class N, N *N::*nextMember, typename Tag>
+Tag QForwardFieldList<N, nextMember, Tag>::tag() const
{
- _first.setFlag2();
+ return _first.tag();
}
-template<class N, N *N::*nextMember>
-void QForwardFieldList<N, nextMember>::clearFlag2()
-{
- _first.clearFlag2();
-}
-
-template<class N, N *N::*nextMember>
-void QForwardFieldList<N, nextMember>::setFlag2Value(bool v)
+template<class N, N *N::*nextMember, typename Tag>
+void QForwardFieldList<N, nextMember, Tag>::setTag(Tag t)
{
- _first.setFlag2Value(v);
+ _first.setTag(t);
}
template<class N, N *N::*nextMember>
@@ -380,7 +340,8 @@ void QFieldList<N, nextMember>::copyAndClear(QFieldList<N, nextMember> &o)
}
template<class N, N *N::*nextMember>
-void QFieldList<N, nextMember>::copyAndClearAppend(QForwardFieldList<N, nextMember> &o)
+template <typename Tag>
+void QFieldList<N, nextMember>::copyAndClearAppend(QForwardFieldList<N, nextMember, Tag> &o)
{
_first = 0;
_last = 0;
@@ -389,7 +350,8 @@ void QFieldList<N, nextMember>::copyAndClearAppend(QForwardFieldList<N, nextMemb
}
template<class N, N *N::*nextMember>
-void QFieldList<N, nextMember>::copyAndClearPrepend(QForwardFieldList<N, nextMember> &o)
+template <typename Tag>
+void QFieldList<N, nextMember>::copyAndClearPrepend(QForwardFieldList<N, nextMember, Tag> &o)
{
_first = nullptr;
_last = nullptr;
diff --git a/src/qml/qml/ftw/qflagpointer_p.h b/src/qml/qml/ftw/qflagpointer_p.h
index a10e57aeca..5cdf973352 100644
--- a/src/qml/qml/ftw/qflagpointer_p.h
+++ b/src/qml/qml/ftw/qflagpointer_p.h
@@ -66,43 +66,6 @@ template <> struct QFlagPointerAlignment<void>
};
}
-template<typename T>
-class QFlagPointer {
-public:
- inline QFlagPointer();
- inline QFlagPointer(T *);
- inline QFlagPointer(const QFlagPointer<T> &o);
-
- inline bool isNull() const;
-
- inline bool flag() const;
- inline void setFlag();
- inline void clearFlag();
- inline void setFlagValue(bool);
-
- inline bool flag2() const;
- inline void setFlag2();
- inline void clearFlag2();
- inline void setFlag2Value(bool);
-
- inline QFlagPointer<T> &operator=(const QFlagPointer &o);
- inline QFlagPointer<T> &operator=(T *);
-
- inline T *operator->() const;
- inline T *operator*() const;
-
- inline T *data() const;
-
- inline explicit operator bool() const;
-
-private:
- quintptr ptr_value = 0;
-
- static const quintptr FlagBit = 0x1;
- static const quintptr Flag2Bit = 0x2;
- static const quintptr FlagsMask = FlagBit | Flag2Bit;
-};
-
template<typename T, typename T2>
class QBiPointer {
public:
@@ -135,121 +98,6 @@ private:
static const quintptr FlagsMask = FlagBit | Flag2Bit;
};
-template<typename T>
-QFlagPointer<T>::QFlagPointer()
-{
-}
-
-template<typename T>
-QFlagPointer<T>::QFlagPointer(T *v)
-: ptr_value(quintptr(v))
-{
- Q_STATIC_ASSERT_X(Q_ALIGNOF(T) >= 4, "Type T does not have sufficient alignment");
- Q_ASSERT((ptr_value & FlagsMask) == 0);
-}
-
-template<typename T>
-QFlagPointer<T>::QFlagPointer(const QFlagPointer<T> &o)
-: ptr_value(o.ptr_value)
-{
-}
-
-template<typename T>
-bool QFlagPointer<T>::isNull() const
-{
- return 0 == (ptr_value & (~FlagsMask));
-}
-
-template<typename T>
-bool QFlagPointer<T>::flag() const
-{
- return ptr_value & FlagBit;
-}
-
-template<typename T>
-void QFlagPointer<T>::setFlag()
-{
- ptr_value |= FlagBit;
-}
-
-template<typename T>
-void QFlagPointer<T>::clearFlag()
-{
- ptr_value &= ~FlagBit;
-}
-
-template<typename T>
-void QFlagPointer<T>::setFlagValue(bool v)
-{
- if (v) setFlag();
- else clearFlag();
-}
-
-template<typename T>
-bool QFlagPointer<T>::flag2() const
-{
- return ptr_value & Flag2Bit;
-}
-
-template<typename T>
-void QFlagPointer<T>::setFlag2()
-{
- ptr_value|= Flag2Bit;
-}
-
-template<typename T>
-void QFlagPointer<T>::clearFlag2()
-{
- ptr_value &= ~Flag2Bit;
-}
-
-template<typename T>
-void QFlagPointer<T>::setFlag2Value(bool v)
-{
- if (v) setFlag2();
- else clearFlag2();
-}
-
-template<typename T>
-QFlagPointer<T> &QFlagPointer<T>::operator=(const QFlagPointer &o)
-{
- ptr_value = o.ptr_value;
- return *this;
-}
-
-template<typename T>
-QFlagPointer<T> &QFlagPointer<T>::operator=(T *o)
-{
- Q_ASSERT((quintptr(o) & FlagsMask) == 0);
-
- ptr_value = quintptr(o) | (ptr_value & FlagsMask);
- return *this;
-}
-
-template<typename T>
-T *QFlagPointer<T>::operator->() const
-{
- return (T *)(ptr_value & ~FlagsMask);
-}
-
-template<typename T>
-T *QFlagPointer<T>::operator*() const
-{
- return (T *)(ptr_value & ~FlagsMask);
-}
-
-template<typename T>
-T *QFlagPointer<T>::data() const
-{
- return (T *)(ptr_value & ~FlagsMask);
-}
-
-template<typename T>
-QFlagPointer<T>::operator bool() const
-{
- return data() != nullptr;
-}
-
template<typename T, typename T2>
QBiPointer<T, T2>::QBiPointer()
{
diff --git a/src/qml/qml/ftw/qhashedstring.cpp b/src/qml/qml/ftw/qhashedstring.cpp
index 6c58ab87f4..4553fa9359 100644
--- a/src/qml/qml/ftw/qhashedstring.cpp
+++ b/src/qml/qml/ftw/qhashedstring.cpp
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
// Copy of QString's qMemCompare
bool QHashedString::compare(const QChar *lhs, const QChar *rhs, int length)
{
- Q_ASSERT(lhs && rhs);
+ Q_ASSERT((lhs && rhs) || !length);
const quint16 *a = (const quint16 *)lhs;
const quint16 *b = (const quint16 *)rhs;
diff --git a/src/qml/qml/ftw/qlazilyallocated_p.h b/src/qml/qml/ftw/qlazilyallocated_p.h
index 9073e41558..2bac84afb3 100644
--- a/src/qml/qml/ftw/qlazilyallocated_p.h
+++ b/src/qml/qml/ftw/qlazilyallocated_p.h
@@ -52,12 +52,11 @@
//
#include <QtCore/qglobal.h>
-
-#include <private/qflagpointer_p.h>
+#include <QtCore/qtaggedpointer.h>
QT_BEGIN_NAMESPACE
-template<typename T>
+template<typename T, typename Tag = typename QtPrivate::TagInfo<T>::TagType>
class QLazilyAllocated {
public:
inline QLazilyAllocated();
@@ -70,73 +69,59 @@ public:
inline T &value();
inline const T &value() const;
- inline bool flag() const;
- inline void setFlag();
- inline void clearFlag();
- inline void setFlagValue(bool);
+ inline Tag tag() const;
+ inline void setTag(Tag t);
private:
- mutable QFlagPointer<T> d;
+ mutable QTaggedPointer<T, Tag> d;
};
-template<typename T>
-QLazilyAllocated<T>::QLazilyAllocated()
+template<typename T, typename Tag>
+QLazilyAllocated<T, Tag>::QLazilyAllocated()
{
}
-template<typename T>
-QLazilyAllocated<T>::~QLazilyAllocated()
+template<typename T, typename Tag>
+QLazilyAllocated<T, Tag>::~QLazilyAllocated()
{
- delete *d;
+ delete d.data();
}
-template<typename T>
-bool QLazilyAllocated<T>::isAllocated() const
+template<typename T, typename Tag>
+bool QLazilyAllocated<T, Tag>::isAllocated() const
{
return !d.isNull();
}
-template<typename T>
-T &QLazilyAllocated<T>::value()
+template<typename T, typename Tag>
+T &QLazilyAllocated<T, Tag>::value()
{
if (d.isNull()) d = new T;
- return *(*d);
+ return *d;
}
-template<typename T>
-const T &QLazilyAllocated<T>::value() const
+template<typename T, typename Tag>
+const T &QLazilyAllocated<T, Tag>::value() const
{
if (d.isNull()) d = new T;
- return *(*d);
-}
-
-template<typename T>
-T *QLazilyAllocated<T>::operator->() const
-{
return *d;
}
-template<typename T>
-bool QLazilyAllocated<T>::flag() const
-{
- return d.flag();
-}
-
-template<typename T>
-void QLazilyAllocated<T>::setFlag()
+template<typename T, typename Tag>
+T *QLazilyAllocated<T, Tag>::operator->() const
{
- d.setFlag();
+ return d.data();
}
-template<typename T>
-void QLazilyAllocated<T>::clearFlag()
+template<typename T, typename Tag>
+Tag QLazilyAllocated<T, Tag>::tag() const
{
- d.clearFlag();
+ return d.tag();
}
-template<typename T>
-void QLazilyAllocated<T>::setFlagValue(bool v)
+template<typename T, typename Tag>
+void QLazilyAllocated<T, Tag>::setTag(Tag t)
{
- d.setFlagValue(v);
+ d.setTag(t);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/ftw/qlinkedstringhash_p.h b/src/qml/qml/ftw/qlinkedstringhash_p.h
index 67ced7fbbf..495d78ea2f 100644
--- a/src/qml/qml/ftw/qlinkedstringhash_p.h
+++ b/src/qml/qml/ftw/qlinkedstringhash_p.h
@@ -223,7 +223,7 @@ public:
{
if (auto *node = iter.node()) {
QHashedString key(node->key());
- while ((node = static_cast<typename QLinkedStringHash<T>::Node *>(*node->next))) {
+ while ((node = static_cast<typename QLinkedStringHash<T>::Node *>(node->next.data()))) {
if (node->equals(key))
return QLinkedStringHash<T>::iterator(node);
}
diff --git a/src/qml/qml/ftw/qqmlthread.cpp b/src/qml/qml/ftw/qqmlthread.cpp
index 7d2ad354d6..0f7726ef65 100644
--- a/src/qml/qml/ftw/qqmlthread.cpp
+++ b/src/qml/qml/ftw/qqmlthread.cpp
@@ -188,13 +188,7 @@ void QQmlThreadPrivate::threadEvent()
lock();
for (;;) {
- if (m_shutdown) {
- quit();
- wakeOne();
- unlock();
-
- return;
- } else if (!threadList.isEmpty()) {
+ if (!threadList.isEmpty()) {
m_threadProcessing = true;
QQmlThread::Message *message = threadList.first();
@@ -206,6 +200,12 @@ void QQmlThreadPrivate::threadEvent()
lock();
delete threadList.takeFirst();
+ } else if (m_shutdown) {
+ quit();
+ wakeOne();
+ unlock();
+
+ return;
} else {
wakeOne();
@@ -242,6 +242,7 @@ void QQmlThread::shutdown()
d->lock();
Q_ASSERT(!d->m_shutdown);
+ d->m_shutdown = true;
for (;;) {
if (d->mainSync || !d->mainList.isEmpty()) {
d->unlock();
@@ -254,13 +255,10 @@ void QQmlThread::shutdown()
}
}
- d->m_shutdown = true;
- if (QCoreApplication::closingDown()) {
+ if (QCoreApplication::closingDown())
d->quit();
- } else {
+ else
d->triggerThreadEvent();
- d->wait();
- }
d->unlock();
d->QThread::wait();
diff --git a/src/qml/qml/ftw/qstringhash_p.h b/src/qml/qml/ftw/qstringhash_p.h
index f9435b4919..125e160500 100644
--- a/src/qml/qml/ftw/qstringhash_p.h
+++ b/src/qml/qml/ftw/qstringhash_p.h
@@ -54,25 +54,32 @@
#include <private/qhashedstring_p.h>
#include <private/qprimefornumbits_p.h>
-#include <QtCore/qglobal.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qtaggedpointer.h>
QT_BEGIN_NAMESPACE
+static inline QString::DataPointer &mutableStringData(const QHashedString &key)
+{
+ return const_cast<QHashedString &>(key).data_ptr();
+}
+
class QStringHashData;
class QStringHashNode
{
public:
QStringHashNode()
- : ckey(nullptr)
{
}
QStringHashNode(const QHashedString &key)
: length(key.length()), hash(key.hash()), symbolId(0)
+ , arrayData(mutableStringData(key).d_ptr())
+ , strData(mutableStringData(key).data())
{
- strData = const_cast<QHashedString &>(key).data_ptr();
+ arrayData->ref();
setQString(true);
- strData->ref.ref();
}
QStringHashNode(const QHashedCStringRef &key)
@@ -81,49 +88,61 @@ public:
}
QStringHashNode(const QStringHashNode &o)
- : length(o.length), hash(o.hash), symbolId(o.symbolId), ckey(o.ckey)
+ : length(o.length), hash(o.hash), symbolId(o.symbolId), arrayData(o.arrayData)
{
setQString(o.isQString());
- if (isQString()) { strData->ref.ref(); }
+ if (isQString()) {
+ strData = o.strData;
+ arrayData->ref();
+ } else {
+ ckey = o.ckey;
+ }
}
~QStringHashNode()
{
- if (isQString()) { if (!strData->ref.deref()) free(strData); }
+ if (isQString() && !arrayData->deref())
+ QTypedArrayData<ushort>::deallocate(arrayData);
}
- QFlagPointer<QStringHashNode> next;
+ enum Tag {
+ NodeIsCString,
+ NodeIsQString
+ };
+
+ QTaggedPointer<QStringHashNode, Tag> next;
qint32 length = 0;
quint32 hash = 0;
quint32 symbolId = 0;
+ QTypedArrayData<ushort> *arrayData = nullptr;
union {
- const char *ckey;
- QStringData *strData;
+ const char *ckey = nullptr;
+ ushort *strData;
};
inline QHashedString key() const
{
- if (isQString())
- return QHashedString(QString((QChar *)strData->data(), length), hash);
+ if (isQString()) {
+ arrayData->ref();
+ return QHashedString(QString(QStringPrivate(arrayData, strData, length)), hash);
+ }
return QHashedString(QString::fromLatin1(ckey, length), hash);
}
- bool isQString() const { return next.flag(); }
- void setQString(bool v) { if (v) next.setFlag(); else next.clearFlag(); }
+ bool isQString() const { return next.tag() == NodeIsQString; }
+ void setQString(bool v) { if (v) next.setTag(NodeIsQString); else next.setTag(NodeIsCString); }
- inline char *cStrData() const { return (char *)ckey; }
- inline quint16 *utf16Data() const { return (quint16 *)strData->data(); }
+ inline qsizetype size() const { return length; }
+ inline const char *cStrData() const { return ckey; }
+ inline const quint16 *utf16Data() const { return strData; }
inline bool equals(const QV4::Value &string) const {
QString s = string.toQStringNoThrow();
if (isQString()) {
- QStringDataPtr dd;
- dd.ptr = strData;
- strData->ref.ref();
- return QString(dd) == s;
+ return QStringView(utf16Data(), length) == s;
} else {
return QLatin1String(cStrData(), length) == s;
}
@@ -133,10 +152,7 @@ public:
if (length != string->d()->length() || hash != string->hashValue())
return false;
if (isQString()) {
- QStringDataPtr dd;
- dd.ptr = strData;
- strData->ref.ref();
- return QString(dd) == string->toQString();
+ return QStringView(utf16Data(), length) == string->toQString();
} else {
return QLatin1String(cStrData(), length) == string->toQString();
}
@@ -510,8 +526,9 @@ void QStringHash<T>::initializeNode(Node *node, const QHashedString &key)
{
node->length = key.length();
node->hash = key.hash();
- node->strData = const_cast<QHashedString &>(key).data_ptr();
- node->strData->ref.ref();
+ node->arrayData = mutableStringData(key).d_ptr();
+ node->strData = mutableStringData(key).data();
+ node->arrayData->ref();
node->setQString(true);
}
@@ -547,10 +564,11 @@ typename QStringHash<T>::Node *QStringHash<T>::takeNode(const Node &o)
Node *rv = nodePool->nodes + nodePool->used++;
rv->length = o.length;
rv->hash = o.hash;
+ rv->arrayData = o.arrayData;
if (o.isQString()) {
rv->strData = o.strData;
- rv->strData->ref.ref();
rv->setQString(true);
+ rv->arrayData->ref();
} else {
rv->ckey = o.ckey;
}
@@ -700,7 +718,7 @@ typename QStringHash<T>::Node *QStringHash<T>::findNode(const K &key) const
typename HashedForm<K>::Type hashedKey(hashedString(key));
while (node && !node->equals(hashedKey))
- node = (*node->next);
+ node = node->next.data();
return (Node *)node;
}
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index a16f3d4167..6cca897e08 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -17,6 +17,7 @@ SOURCES += \
$$PWD/qqmlcomponent.cpp \
$$PWD/qqmlincubator.cpp \
$$PWD/qqmlcontext.cpp \
+ $$PWD/qqmlcontextdata.cpp \
$$PWD/qqmlcustomparser.cpp \
$$PWD/qqmlpropertyvaluesource.cpp \
$$PWD/qqmlpropertyvalueinterceptor.cpp \
@@ -53,6 +54,7 @@ SOURCES += \
$$PWD/qqmlfile.cpp \
$$PWD/qqmlplatform.cpp \
$$PWD/qqmlbinding.cpp \
+ $$PWD/qqmlpropertybinding.cpp \
$$PWD/qqmlabstracturlinterceptor.cpp \
$$PWD/qqmlapplicationengine.cpp \
$$PWD/qqmllistwrapper.cpp \
@@ -112,6 +114,8 @@ HEADERS += \
$$PWD/qqmlinfo.h \
$$PWD/qqmlproperty_p.h \
$$PWD/qqmlcontext_p.h \
+ $$PWD/qqmlcontextdata_p.h \
+ $$PWD/qqmlguardedcontextdata_p.h \
$$PWD/qqmltypeloader_p.h \
$$PWD/qqmllist.h \
$$PWD/qqmllist_p.h \
@@ -145,6 +149,7 @@ HEADERS += \
$$PWD/qqmlfile.h \
$$PWD/qqmlplatform_p.h \
$$PWD/qqmlbinding_p.h \
+ $$PWD/qqmlpropertybinding_p.h \
$$PWD/qqmlextensionplugin_p.h \
$$PWD/qqmlabstracturlinterceptor.h \
$$PWD/qqmlapplicationengine_p.h \
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index fe4e2f4e55..28b48e2eee 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -62,23 +62,24 @@ void qmlClearTypeRegistrations() // Declared in qqml.h
//From qqml.h
bool qmlProtectModule(const char *uri, int majVersion)
{
- return QQmlMetaType::protectModule(QString::fromUtf8(uri), majVersion);
+ return QQmlMetaType::protectModule(QString::fromUtf8(uri),
+ QTypeRevision::fromMajorVersion(majVersion));
}
//From qqml.h
void qmlRegisterModule(const char *uri, int versionMajor, int versionMinor)
{
- QQmlMetaType::registerModule(uri, versionMajor, versionMinor);
+ QQmlMetaType::registerModule(uri, QTypeRevision::fromVersion(versionMajor, versionMinor));
}
//From qqml.h
int qmlTypeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
{
- return QQmlMetaType::typeId(uri, versionMajor, versionMinor, qmlName);
+ return QQmlMetaType::typeId(uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName);
}
// From qqmlprivate.h
-QObject *QQmlPrivate::RegisterSingletonFunctor::operator()(QQmlEngine *qeng, QJSEngine *)
+QObject *QQmlPrivate::SingletonFunctor::operator()(QQmlEngine *qeng, QJSEngine *)
{
if (!m_object) {
QQmlError error;
@@ -104,9 +105,9 @@ QObject *QQmlPrivate::RegisterSingletonFunctor::operator()(QQmlEngine *qeng, QJS
return m_object;
};
-static QVector<int> availableRevisions(const QMetaObject *metaObject)
+static QVector<QTypeRevision> availableRevisions(const QMetaObject *metaObject)
{
- QVector<int> revisions;
+ QVector<QTypeRevision> revisions;
if (!metaObject)
return revisions;
const int propertyOffset = metaObject->propertyOffset();
@@ -115,7 +116,7 @@ static QVector<int> availableRevisions(const QMetaObject *metaObject)
propertyIndex < propertyEnd; ++propertyIndex) {
const QMetaProperty property = metaObject->property(propertyIndex);
if (int revision = property.revision())
- revisions.append(revision);
+ revisions.append(QTypeRevision::fromEncodedVersion(revision));
}
const int methodOffset = metaObject->methodOffset();
const int methodCount = metaObject->methodCount();
@@ -123,7 +124,7 @@ static QVector<int> availableRevisions(const QMetaObject *metaObject)
methodIndex < methodEnd; ++methodIndex) {
const QMetaMethod method = metaObject->method(methodIndex);
if (int revision = method.revision())
- revisions.append(revision);
+ revisions.append(QTypeRevision::fromEncodedVersion(revision));
}
// Need to also check parent meta objects, as their revisions are inherited.
@@ -133,6 +134,54 @@ static QVector<int> availableRevisions(const QMetaObject *metaObject)
return revisions;
}
+template<typename Registration>
+void assignVersions(Registration *registration, QTypeRevision revision,
+ QTypeRevision defaultVersion)
+{
+ const quint8 majorVersion = revision.hasMajorVersion() ? revision.majorVersion()
+ : defaultVersion.majorVersion();
+ registration->version = revision.hasMinorVersion()
+ ? QTypeRevision::fromVersion(majorVersion, revision.minorVersion())
+ : QTypeRevision::fromMajorVersion(majorVersion);
+ registration->revision = revision;
+}
+
+static QVector<QTypeRevision> prepareRevisions(const QMetaObject *metaObject, QTypeRevision added)
+{
+ auto revisions = availableRevisions(metaObject);
+ revisions.append(added);
+ return revisions;
+}
+
+static void uniqueRevisions(QVector<QTypeRevision> *revisions, QTypeRevision defaultVersion,
+ QTypeRevision added)
+{
+ bool revisionsHaveMajorVersions = false;
+ for (QTypeRevision revision : QVector<QTypeRevision>(*revisions)) { // yes, copy
+ // allow any minor version for each explicitly specified past major one
+ if (revision.hasMajorVersion()) {
+ revisionsHaveMajorVersions = true;
+ if (revision.majorVersion() < defaultVersion.majorVersion())
+ revisions->append(QTypeRevision::fromVersion(revision.majorVersion(), 254));
+ }
+ }
+
+ if (revisionsHaveMajorVersions) {
+ if (!added.hasMajorVersion()) {
+ // If added in unspecified major version, assume default one.
+ revisions->append(QTypeRevision::fromVersion(defaultVersion.majorVersion(),
+ added.minorVersion()));
+ } else if (added.majorVersion() < defaultVersion.majorVersion()) {
+ // If added in past major version, add .0 of default version.
+ revisions->append(QTypeRevision::fromVersion(defaultVersion.majorVersion(), 0));
+ }
+ }
+
+ std::sort(revisions->begin(), revisions->end());
+ const auto it = std::unique(revisions->begin(), revisions->end());
+ revisions->erase(it, revisions->end());
+}
+
/*
This method is "over generalized" to allow us to (potentially) register more types of things in
the future without adding exported symbols.
@@ -157,15 +206,14 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
? QString()
: QString::fromUtf8(classInfo(type.classInfoMetaObject, "QML.UncreatableReason"));
RegisterType revisionRegistration = {
- 1,
+ 0,
type.typeId,
type.listId,
creatable ? type.objectSize : 0,
nullptr,
noCreateReason,
type.uri,
- type.versionMajor,
- -1,
+ type.version,
nullptr,
type.metaObject,
type.attachedPropertiesFunction,
@@ -176,28 +224,26 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
type.extensionObjectCreate,
type.extensionMetaObject,
nullptr,
- -1
+ QTypeRevision()
};
- const int added = intClassInfo(type.classInfoMetaObject, "QML.AddedInMinorVersion", 0);
- const int removed = intClassInfo(type.classInfoMetaObject, "QML.RemovedInMinorVersion", -1);
+ const QTypeRevision added = revisionClassInfo(
+ type.classInfoMetaObject, "QML.AddedInVersion",
+ QTypeRevision::fromMinorVersion(0));
+ const QTypeRevision removed = revisionClassInfo(
+ type.classInfoMetaObject, "QML.RemovedInVersion");
- auto revisions = availableRevisions(type.metaObject);
- revisions.append(qMax(added, 0));
+ auto revisions = prepareRevisions(type.metaObject, added);
if (type.attachedPropertiesMetaObject)
revisions += availableRevisions(type.attachedPropertiesMetaObject);
+ uniqueRevisions(&revisions, type.version, added);
- std::sort(revisions.begin(), revisions.end());
- const auto it = std::unique(revisions.begin(), revisions.end());
- revisions.erase(it, revisions.end());
-
- const bool typeWasRemoved = removed >= added;
- for (int revision : revisions) {
+ for (QTypeRevision revision : revisions) {
if (revision < added)
continue;
// When removed, we still add revisions, but anonymous ones
- if (typeWasRemoved && revision >= removed) {
+ if (removed.isValid() && !(revision < removed)) {
revisionRegistration.elementName = nullptr;
revisionRegistration.create = nullptr;
} else {
@@ -205,12 +251,11 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
revisionRegistration.create = creatable ? type.create : nullptr;
}
- // Equivalent of qmlRegisterRevision<T, revision>(...)
- revisionRegistration.versionMinor = revision;
- revisionRegistration.revision = revision;
+ assignVersions(&revisionRegistration, revision, type.version);
revisionRegistration.customParser = type.customParserFactory();
-
- qmlregister(TypeRegistration, &revisionRegistration);
+ const int id = qmlregister(TypeRegistration, &revisionRegistration);
+ if (type.qmlTypeIds)
+ type.qmlTypeIds->append(id);
}
break;
}
@@ -219,52 +264,43 @@ int QQmlPrivate::qmlregister(RegistrationType type, void *data)
= *reinterpret_cast<RegisterSingletonTypeAndRevisions *>(data);
const char *elementName = classElementName(type.classInfoMetaObject);
RegisterSingletonType revisionRegistration = {
- QmlCurrentSingletonTypeRegistrationVersion,
+ 0,
type.uri,
- type.versionMajor,
- -1,
+ type.version,
elementName,
-
- type.scriptApi,
nullptr,
+ type.qObjectApi,
type.instanceMetaObject,
type.typeId,
- -1,
-
- type.generalizedQobjectApi
+ QTypeRevision()
};
- const int added = intClassInfo(type.classInfoMetaObject, "QML.AddedInMinorVersion", 0);
- const int removed = intClassInfo(type.classInfoMetaObject, "QML.RemovedInMinorVersion", -1);
+ const QTypeRevision added = revisionClassInfo(
+ type.classInfoMetaObject, "QML.AddedInVersion",
+ QTypeRevision::fromMinorVersion(0));
+ const QTypeRevision removed = revisionClassInfo(
+ type.classInfoMetaObject, "QML.RemovedInVersion");
- auto revisions = availableRevisions(type.instanceMetaObject);
- revisions.append(qMax(added, 0));
+ auto revisions = prepareRevisions(type.instanceMetaObject, added);
+ uniqueRevisions(&revisions, type.version, added);
- std::sort(revisions.begin(), revisions.end());
- const auto it = std::unique(revisions.begin(), revisions.end());
- revisions.erase(it, revisions.end());
-
- const bool typeWasRemoved = removed >= added;
- for (int revision : qAsConst(revisions)) {
+ for (QTypeRevision revision : qAsConst(revisions)) {
if (revision < added)
continue;
// When removed, we still add revisions, but anonymous ones
- if (typeWasRemoved && revision >= removed) {
+ if (removed.isValid() && !(revision < removed)) {
revisionRegistration.typeName = nullptr;
- revisionRegistration.scriptApi = nullptr;
- revisionRegistration.generalizedQobjectApi = nullptr;
+ revisionRegistration.qObjectApi = nullptr;
} else {
revisionRegistration.typeName = elementName;
- revisionRegistration.scriptApi = type.scriptApi;
- revisionRegistration.generalizedQobjectApi = type.generalizedQobjectApi;
+ revisionRegistration.qObjectApi = type.qObjectApi;
}
- // Equivalent of qmlRegisterRevision<T, revision>(...)
- revisionRegistration.versionMinor = revision;
- revisionRegistration.revision = revision;
-
- qmlregister(SingletonRegistration, &revisionRegistration);
+ assignVersions(&revisionRegistration, revision, type.version);
+ const int id = qmlregister(SingletonRegistration, &revisionRegistration);
+ if (type.qmlTypeIds)
+ type.qmlTypeIds->append(id);
}
break;
}
@@ -325,21 +361,20 @@ void QQmlPrivate::qmlunregister(RegistrationType type, quintptr data)
namespace QQmlPrivate {
template<>
void qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>(
- const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject)
+ const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject,
+ QVector<int> *qmlTypeIds)
{
using T = QQmlTypeNotAvailable;
- QML_GETTYPENAMES
-
RegisterTypeAndRevisions type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T>>(),
0,
nullptr,
uri,
- versionMajor,
+ QTypeRevision::fromMajorVersion(versionMajor),
&QQmlTypeNotAvailable::staticMetaObject,
classInfoMetaObject,
@@ -351,7 +386,7 @@ namespace QQmlPrivate {
StaticCastSelector<T, QQmlPropertyValueSource>::cast(),
StaticCastSelector<T, QQmlPropertyValueInterceptor>::cast(),
- nullptr, nullptr, qmlCreateCustomParser<T>
+ nullptr, nullptr, qmlCreateCustomParser<T>, qmlTypeIds
};
qmlregister(TypeAndRevisionsRegistration, &type);
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 4adf100a1f..76a4740101 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -44,6 +44,7 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qmetaobject.h>
+#include <QtCore/qversionnumber.h>
#define QML_VERSION 0x020000
#define QML_VERSION_STR "2.0"
@@ -85,13 +86,19 @@
enum class QmlIsSingleton {yes = true}; \
template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlSingleton; \
template<typename T, typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QVector<int> *);
#define QML_ADDED_IN_MINOR_VERSION(VERSION) \
- Q_CLASSINFO("QML.AddedInMinorVersion", #VERSION)
+ Q_CLASSINFO("QML.AddedInVersion", Q_REVISION(VERSION))
+
+#define QML_ADDED_IN_VERSION(MAJOR, MINOR) \
+ Q_CLASSINFO("QML.AddedInVersion", Q_REVISION(MAJOR, MINOR))
#define QML_REMOVED_IN_MINOR_VERSION(VERSION) \
- Q_CLASSINFO("QML.RemovedInMinorVersion", #VERSION)
+ Q_CLASSINFO("QML.RemovedInVersion", Q_REVISION(VERSION))
+
+#define QML_REMOVED_IN_VERSION(MAJOR, MINOR) \
+ Q_CLASSINFO("QML.RemovedInVersion", Q_REVISION(MAJOR, MINOR))
#define QML_ATTACHED(ATTACHED_TYPE) \
Q_CLASSINFO("QML.Attached", #ATTACHED_TYPE) \
@@ -104,21 +111,21 @@
using QmlExtendedType = EXTENDED_TYPE; \
template<class, class> friend struct QML_PRIVATE_NAMESPACE::QmlExtended; \
template<typename T, typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QVector<int> *);
#define QML_FOREIGN(FOREIGN_TYPE) \
Q_CLASSINFO("QML.Foreign", #FOREIGN_TYPE) \
using QmlForeignType = FOREIGN_TYPE; \
template<class, class> friend struct QML_PRIVATE_NAMESPACE::QmlResolved; \
template<typename T, typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QVector<int> *);
#define QML_INTERFACE \
Q_CLASSINFO("QML.Element", "anonymous") \
enum class QmlIsInterface {yes = true}; \
template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlInterface; \
template<typename T, typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor);
+ friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QVector<int> *);
#define QML_UNAVAILABLE \
QML_FOREIGN(QQmlTypeNotAvailable)
@@ -149,18 +156,16 @@ QQmlCustomParser *qmlCreateCustomParser();
template<typename T>
int qmlRegisterAnonymousType(const char *uri, int versionMajor)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterType type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
0,
nullptr,
QString(),
- uri, versionMajor, 0, nullptr, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, 0), nullptr, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -172,7 +177,7 @@ int qmlRegisterAnonymousType(const char *uri, int versionMajor)
nullptr, nullptr,
nullptr,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -192,18 +197,16 @@ int Q_QML_EXPORT qmlRegisterTypeNotAvailable(const char *uri, int versionMajor,
template<typename T>
int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterType type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T>>(),
0,
nullptr,
reason,
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -215,7 +218,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
nullptr, nullptr,
nullptr,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -224,18 +227,16 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
template<typename T, int metaObjectRevision>
int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterType type = {
- 1,
+ 0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
0,
nullptr,
reason,
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -247,7 +248,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
nullptr, nullptr,
nullptr,
- metaObjectRevision
+ QTypeRevision::fromMinorVersion(metaObjectRevision)
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -256,8 +257,6 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin
template<typename T, typename E>
int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason)
{
- QML_GETTYPENAMES
-
QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>();
const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>();
if (!attached) {
@@ -268,13 +267,13 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
QQmlPrivate::RegisterType type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
0,
nullptr,
reason,
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
attached,
attachedMetaObject,
@@ -286,7 +285,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
QQmlPrivate::createParent<E>, &E::staticMetaObject,
nullptr,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -295,8 +294,6 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
template<typename T, typename E, int metaObjectRevision>
int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason)
{
- QML_GETTYPENAMES
-
QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>();
const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>();
if (!attached) {
@@ -305,15 +302,15 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
}
QQmlPrivate::RegisterType type = {
- 1,
+ 0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
0,
nullptr,
reason,
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
attached,
attachedMetaObject,
@@ -325,7 +322,7 @@ int qmlRegisterExtendedUncreatableType(const char *uri, int versionMajor, int ve
QQmlPrivate::createParent<E>, &E::staticMetaObject,
nullptr,
- metaObjectRevision
+ QTypeRevision::fromMinorVersion(metaObjectRevision)
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -336,17 +333,15 @@ Q_QML_EXPORT int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaO
template<typename T>
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterType type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
sizeof(T), QQmlPrivate::createInto<T>,
QString(),
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -358,7 +353,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
nullptr, nullptr,
nullptr,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -367,17 +362,15 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
template<typename T, int metaObjectRevision>
int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterType type = {
- 1,
+ 0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
sizeof(T), QQmlPrivate::createInto<T>,
QString(),
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -389,7 +382,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
nullptr, nullptr,
nullptr,
- metaObjectRevision
+ QTypeRevision::fromMinorVersion(metaObjectRevision)
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -398,17 +391,15 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c
template<typename T, int metaObjectRevision>
int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterType type = {
- 1,
+ 0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
sizeof(T), QQmlPrivate::createInto<T>,
QString(),
- uri, versionMajor, versionMinor, nullptr, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), nullptr, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -420,7 +411,7 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor)
nullptr, nullptr,
nullptr,
- metaObjectRevision
+ QTypeRevision::fromMinorVersion(metaObjectRevision)
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -429,18 +420,16 @@ int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor)
template<typename T, typename E>
int qmlRegisterExtendedType(const char *uri, int versionMajor)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterType type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
0,
nullptr,
QString(),
- uri, versionMajor, 0, nullptr, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, 0), nullptr, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -452,7 +441,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor)
QQmlPrivate::createParent<E>, &E::staticMetaObject,
nullptr,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -471,8 +460,6 @@ template<typename T, typename E>
int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
const char *qmlName)
{
- QML_GETTYPENAMES
-
QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>();
const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>();
if (!attached) {
@@ -483,12 +470,12 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
QQmlPrivate::RegisterType type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
sizeof(T), QQmlPrivate::createInto<T>,
QString(),
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
attached,
attachedMetaObject,
@@ -500,7 +487,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor,
QQmlPrivate::createParent<E>, &E::staticMetaObject,
nullptr,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -517,14 +504,14 @@ int qmlRegisterInterface(const char *typeName)
QByteArray listName("QQmlListProperty<" + name + '>');
QQmlPrivate::RegisterInterface qmlInterface = {
- 1,
+ 0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
qobject_interface_iid<T *>(),
"",
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::InterfaceRegistration, &qmlInterface);
@@ -534,16 +521,14 @@ int qmlRegisterInterface(const char *typeName)
template<typename T>
int qmlRegisterInterface(const char *uri, int versionMajor)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterInterface qmlInterface = {
- 1,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T>>(listName.constData()),
+ 0,
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
qobject_interface_iid<T *>(),
uri,
- versionMajor
+ QTypeRevision::fromVersion(versionMajor, 0)
};
return QQmlPrivate::qmlregister(QQmlPrivate::InterfaceRegistration, &qmlInterface);
@@ -553,17 +538,15 @@ template<typename T>
int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
const char *qmlName, QQmlCustomParser *parser)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterType type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
sizeof(T), QQmlPrivate::createInto<T>,
QString(),
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -575,7 +558,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
nullptr, nullptr,
parser,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -585,17 +568,15 @@ template<typename T, int metaObjectRevision>
int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
const char *qmlName, QQmlCustomParser *parser)
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterType type = {
- 1,
+ 0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
sizeof(T), QQmlPrivate::createInto<T>,
QString(),
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
QQmlPrivate::attachedPropertiesFunc<T>(),
QQmlPrivate::attachedPropertiesMetaObject<T>(),
@@ -607,7 +588,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor,
nullptr, nullptr,
parser,
- metaObjectRevision
+ QTypeRevision::fromMinorVersion(metaObjectRevision)
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -617,8 +598,6 @@ template<typename T, typename E>
int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int versionMinor,
const char *qmlName, QQmlCustomParser *parser)
{
- QML_GETTYPENAMES
-
QQmlAttachedPropertiesFunc attached = QQmlPrivate::attachedPropertiesFunc<E>();
const QMetaObject * attachedMetaObject = QQmlPrivate::attachedPropertiesMetaObject<E>();
if (!attached) {
@@ -629,12 +608,12 @@ int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int version
QQmlPrivate::RegisterType type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T *>(),
+ QMetaType::fromType<QQmlListProperty<T> >(),
sizeof(T), QQmlPrivate::createInto<T>,
QString(),
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
attached,
attachedMetaObject,
@@ -646,7 +625,7 @@ int qmlRegisterCustomExtendedType(const char *uri, int versionMajor, int version
QQmlPrivate::createParent<E>, &E::staticMetaObject,
parser,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -709,27 +688,29 @@ inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versi
QQmlPrivate::RegisterSingletonType api = {
0,
- uri, versionMajor, versionMinor, typeName,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), typeName,
- callback, nullptr, nullptr, 0, 0, {}
+ callback, nullptr, nullptr, QMetaType(), QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api);
}
-enum { QmlCurrentSingletonTypeRegistrationVersion = 3 };
template <typename T>
-inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName,
- QObject *(*callback)(QQmlEngine *, QJSEngine *))
+inline int qmlRegisterSingletonType(
+ const char *uri, int versionMajor, int versionMinor, const char *typeName,
+ QObject *(*callback)(QQmlEngine *, QJSEngine *))
{
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterSingletonType api = {
- QmlCurrentSingletonTypeRegistrationVersion,
-
- uri, versionMajor, versionMinor, typeName,
-
- nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, callback
+ 0,
+ uri,
+ QTypeRevision::fromVersion(versionMajor, versionMinor),
+ typeName,
+ nullptr,
+ callback,
+ &T::staticMetaObject,
+ QMetaType::fromType<T *>(),
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api);
@@ -740,15 +721,16 @@ template <typename T, typename F, typename std::enable_if<std::is_convertible<F,
inline int qmlRegisterSingletonType(const char *uri, int versionMajor, int versionMinor, const char *typeName,
F&& callback)
{
-
- QML_GETTYPENAMES
-
QQmlPrivate::RegisterSingletonType api = {
- QmlCurrentSingletonTypeRegistrationVersion,
-
- uri, versionMajor, versionMinor, typeName,
-
- nullptr, nullptr, &T::staticMetaObject, qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, callback
+ 0,
+ uri,
+ QTypeRevision::fromVersion(versionMajor, versionMinor),
+ typeName,
+ nullptr,
+ callback,
+ &T::staticMetaObject,
+ QMetaType::fromType<T *>(),
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &api);
@@ -763,7 +745,7 @@ inline auto qmlRegisterSingletonInstance(const char *uri, int versionMajor, int
const char *typeName, T *cppObject) -> typename std::enable_if<std::is_base_of<QObject, T>::value, int>::type
#endif
{
- QQmlPrivate::RegisterSingletonFunctor registrationFunctor;
+ QQmlPrivate::SingletonFunctor registrationFunctor;
registrationFunctor.m_object = cppObject;
return qmlRegisterSingletonType<T>(uri, versionMajor, versionMinor, typeName, registrationFunctor);
}
@@ -777,10 +759,10 @@ inline int qmlRegisterSingletonType(const QUrl &url, const char *uri, int versio
}
QQmlPrivate::RegisterCompositeSingletonType type = {
+ 0,
url,
uri,
- versionMajor,
- versionMinor,
+ QTypeRevision::fromVersion(versionMajor, versionMinor),
qmlName
};
@@ -796,10 +778,10 @@ inline int qmlRegisterType(const QUrl &url, const char *uri, int versionMajor, i
}
QQmlPrivate::RegisterCompositeType type = {
+ 0,
url,
uri,
- versionMajor,
- versionMinor,
+ QTypeRevision::fromVersion(versionMajor, versionMinor),
qmlName
};
@@ -811,60 +793,67 @@ struct QmlTypeAndRevisionsRegistration;
template<class T, class Resolved, class Extended>
struct QmlTypeAndRevisionsRegistration<T, Resolved, Extended, false, false> {
- static void registerTypeAndRevisions(const char *uri, int versionMajor)
+ static void registerTypeAndRevisions(const char *uri, int versionMajor,
+ QVector<int> *qmlTypeIds)
{
QQmlPrivate::qmlRegisterTypeAndRevisions<Resolved, Extended>(
- uri, versionMajor, &T::staticMetaObject);
+ uri, versionMajor, &T::staticMetaObject, qmlTypeIds);
}
};
template<class T, class Resolved>
struct QmlTypeAndRevisionsRegistration<T, Resolved, void, true, false> {
- static void registerTypeAndRevisions(const char *uri, int versionMajor)
+ static void registerTypeAndRevisions(const char *uri, int versionMajor,
+ QVector<int> *qmlTypeIds)
{
QQmlPrivate::qmlRegisterSingletonAndRevisions<Resolved>(
- uri, versionMajor, &T::staticMetaObject);
+ uri, versionMajor, &T::staticMetaObject, qmlTypeIds);
}
};
template<class T, class Resolved>
struct QmlTypeAndRevisionsRegistration<T, Resolved, void, false, true> {
- static void registerTypeAndRevisions(const char *uri, int versionMajor)
+ static void registerTypeAndRevisions(const char *uri, int versionMajor,
+ QVector<int> *qmlTypeIds)
{
- qmlRegisterInterface<Resolved>(uri, versionMajor);
+ const int id = qmlRegisterInterface<Resolved>(uri, versionMajor);
+ if (qmlTypeIds)
+ qmlTypeIds->append(id);
}
};
template<typename T = void, typename... Args>
-void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor);
+void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor,
+ QVector<int> *qmlTypeIds = nullptr);
template<typename T, typename... Args>
-void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor)
+void qmlRegisterTypesAndRevisions(const char *uri, int versionMajor, QVector<int> *qmlTypeIds)
{
QmlTypeAndRevisionsRegistration<
T, typename QQmlPrivate::QmlResolved<T>::Type,
typename QQmlPrivate::QmlExtended<T>::Type,
QQmlPrivate::QmlSingleton<T>::Value,
QQmlPrivate::QmlInterface<T>::Value>
- ::registerTypeAndRevisions(uri, versionMajor);
- qmlRegisterTypesAndRevisions<Args...>(uri, versionMajor);
+ ::registerTypeAndRevisions(uri, versionMajor, qmlTypeIds);
+ qmlRegisterTypesAndRevisions<Args...>(uri, versionMajor, qmlTypeIds);
}
template<>
-inline void qmlRegisterTypesAndRevisions<>(const char *, int) {}
+inline void qmlRegisterTypesAndRevisions<>(const char *, int, QVector<int> *) {}
inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject,
- const char *uri, int versionMajor)
+ const char *uri, int versionMajor,
+ QVector<int> *qmlTypeIds = nullptr)
{
QQmlPrivate::RegisterTypeAndRevisions type = {
0,
- 0,
- 0,
+ QMetaType(),
+ QMetaType(),
0,
nullptr,
uri,
- versionMajor,
+ QTypeRevision::fromMajorVersion(versionMajor),
metaObject,
metaObject,
@@ -879,7 +868,8 @@ inline void qmlRegisterNamespaceAndRevisions(const QMetaObject *metaObject,
nullptr,
nullptr,
- &qmlCreateCustomParser<void>
+ &qmlCreateCustomParser<void>,
+ qmlTypeIds
};
qmlregister(QQmlPrivate::TypeAndRevisionsRegistration, &type);
@@ -889,7 +879,4 @@ int Q_QML_EXPORT qmlTypeId(const char *uri, int versionMajor, int versionMinor,
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QObject)
-Q_DECLARE_METATYPE(QVariant)
-
#endif // QQML_H
diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h
index fc53be3e7b..96bb0da269 100644
--- a/src/qml/qml/qqmlabstractbinding_p.h
+++ b/src/qml/qml/qqmlabstractbinding_p.h
@@ -92,7 +92,7 @@ public:
inline QQmlAbstractBinding *nextBinding() const;
inline bool canUseAccessor() const
- { return m_nextBinding.flag2(); }
+ { return m_nextBinding.tag().testFlag(CanUseAccessor); }
struct RefCount {
RefCount() {}
@@ -103,6 +103,20 @@ public:
};
RefCount ref;
+ enum TargetTag {
+ NoTargetTag = 0x0,
+ UpdatingBinding = 0x1,
+ BindingEnabled = 0x2
+ };
+ Q_DECLARE_FLAGS(TargetTags, TargetTag)
+
+ enum NextBindingTag {
+ NoBindingTag = 0x0,
+ AddedToObject = 0x1,
+ CanUseAccessor = 0x2
+ };
+ Q_DECLARE_FLAGS(NextBindingTags, NextBindingTag)
+
protected:
friend class QQmlData;
friend class QQmlValueTypeProxyBinding;
@@ -116,24 +130,23 @@ protected:
QQmlPropertyIndex m_targetIndex;
// Pointer is the target object to which the binding binds
- // flag1 is the updating flag
- // flag2 is the enabled flag
- QFlagPointer<QObject> m_target;
+ QTaggedPointer<QObject, TargetTags> m_target;
// Pointer to the next binding in the linked list of bindings.
- // flag1 is used for addedToObject
- // flag2 indicates if an accessor is can be used (i.e. there is no interceptor on the target)
- QFlagPointer<QQmlAbstractBinding> m_nextBinding;
+ QTaggedPointer<QQmlAbstractBinding, NextBindingTags> m_nextBinding;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlAbstractBinding::TargetTags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlAbstractBinding::NextBindingTags)
+
void QQmlAbstractBinding::setAddedToObject(bool v)
{
- m_nextBinding.setFlagValue(v);
+ m_nextBinding.setTag(m_nextBinding.tag().setFlag(AddedToObject, v));
}
bool QQmlAbstractBinding::isAddedToObject() const
{
- return m_nextBinding.flag();
+ return m_nextBinding.tag().testFlag(AddedToObject);
}
QQmlAbstractBinding *QQmlAbstractBinding::nextBinding() const
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
index 6ee03b39e5..a2976b59c3 100644
--- a/src/qml/qml/qqmlapplicationengine.cpp
+++ b/src/qml/qml/qqmlapplicationengine.cpp
@@ -81,7 +81,8 @@ void QQmlApplicationEnginePrivate::init()
else
delete qtTranslator;
#endif
- new QQmlFileSelector(q,q);
+ auto *selector = new QQmlFileSelector(q,q);
+ selector->setExtraSelectors(extraFileSelectors);
QCoreApplication::instance()->setProperty("__qml_using_qqmlapplicationengine", QVariant(true));
}
@@ -94,7 +95,7 @@ void QQmlApplicationEnginePrivate::_q_loadTranslations()
Q_Q(QQmlApplicationEngine);
QScopedPointer<QTranslator> translator(new QTranslator);
- if (!uiLanguage.isEmpty()) {
+ if (!uiLanguage.value().isEmpty()) {
QLocale locale(uiLanguage);
if (translator->load(locale, QLatin1String("qml"), QLatin1String("_"), translationsDirectory, QLatin1String(".qm"))) {
if (activeTranslator)
@@ -113,6 +114,11 @@ void QQmlApplicationEnginePrivate::startLoad(const QUrl &url, const QByteArray &
{
Q_Q(QQmlApplicationEngine);
+ if (!isInitialized) {
+ init();
+ isInitialized = true;
+ }
+
if (url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("qrc")) {
QFileInfo fi(QQmlFile::urlToLocalFileOrQrc(url));
translationsDirectory = fi.path() + QLatin1String("/i18n");
@@ -225,8 +231,6 @@ void QQmlApplicationEnginePrivate::finishLoad(QQmlComponent *c)
QQmlApplicationEngine::QQmlApplicationEngine(QObject *parent)
: QQmlEngine(*(new QQmlApplicationEnginePrivate(this)), parent)
{
- Q_D(QQmlApplicationEngine);
- d->init();
QJSEnginePrivate::addToDebugServer(this);
}
@@ -310,6 +314,26 @@ void QQmlApplicationEngine::setInitialProperties(const QVariantMap &initialPrope
}
/*!
+ Sets the \a extraFileSelectors to be passed to the internal QQmlFileSelector
+ used for resolving URLs to local files. The \a extraFileSelectors are applied
+ when the first QML file is loaded. Setting them afterwards has no effect.
+
+ \sa QQmlFileSelector
+ \sa QFileSelector::setExtraSelectors
+ \since 6.0
+*/
+void QQmlApplicationEngine::setExtraFileSelectors(const QStringList &extraFileSelectors)
+{
+ Q_D(QQmlApplicationEngine);
+ if (d->isInitialized) {
+ qWarning() << "QQmlApplicationEngine::setExtraFileSelectors()"
+ << "called after loading QML files. This has no effect.";
+ } else {
+ d->extraFileSelectors = extraFileSelectors;
+ }
+}
+
+/*!
Loads the QML given in \a data. The object tree defined by \a data is
instantiated immediately.
diff --git a/src/qml/qml/qqmlapplicationengine.h b/src/qml/qml/qqmlapplicationengine.h
index 37f75d5068..7faa51892e 100644
--- a/src/qml/qml/qqmlapplicationengine.h
+++ b/src/qml/qml/qqmlapplicationengine.h
@@ -67,6 +67,7 @@ public Q_SLOTS:
void load(const QUrl &url);
void load(const QString &filePath);
void setInitialProperties(const QVariantMap &initialProperties);
+ void setExtraFileSelectors(const QStringList &extraFileSelectors);
void loadData(const QByteArray &data, const QUrl &url = QUrl());
Q_SIGNALS:
diff --git a/src/qml/qml/qqmlapplicationengine_p.h b/src/qml/qml/qqmlapplicationengine_p.h
index 86f492510f..4568f7cfbb 100644
--- a/src/qml/qml/qqmlapplicationengine_p.h
+++ b/src/qml/qml/qqmlapplicationengine_p.h
@@ -74,9 +74,11 @@ public:
void finishLoad(QQmlComponent *component);
QList<QObject *> objects;
QVariantMap initialProperties;
+ QStringList extraFileSelectors;
QString translationsDirectory;
#if QT_CONFIG(translation)
QScopedPointer<QTranslator> activeTranslator;
+ bool isInitialized = false;
#endif
};
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index b9566d5862..7de94fe3d5 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -57,6 +57,7 @@
#include <private/qv4qobjectwrapper_p.h>
#include <private/qv4variantobject_p.h>
#include <private/qv4jscall_p.h>
+#include <private/qjsvalue_p.h>
#include <qtqml_tracepoints_p.h>
@@ -80,19 +81,19 @@ QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QQmlScr
QString url;
QV4::Function *runtimeFunction = nullptr;
- QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context);
+ QQmlRefPointer<QQmlContextData> ctxtdata = QQmlContextData::get(scriptPrivate->context);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine());
- if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit) {
+ if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit()) {
url = ctxtdata->urlString();
if (scriptPrivate->bindingId != QQmlBinding::Invalid)
- runtimeFunction = ctxtdata->typeCompilationUnit->runtimeFunctions.at(scriptPrivate->bindingId);
+ runtimeFunction = ctxtdata->typeCompilationUnit()->runtimeFunctions.at(scriptPrivate->bindingId);
}
b->setNotifyOnValueChanged(true);
b->QQmlJavaScriptExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
b->setScopeObject(obj ? obj : scriptPrivate->scope);
- QV4::ExecutionEngine *v4 = b->context()->engine->handle();
+ QV4::ExecutionEngine *v4 = b->engine()->handle();
if (runtimeFunction) {
QV4::Scope scope(v4);
QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(v4->rootContext(), ctxtdata, b->scopeObject()));
@@ -120,8 +121,9 @@ void QQmlBinding::setSourceLocation(const QQmlSourceLocation &location)
}
-QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString &str, QObject *obj,
- QQmlContextData *ctxt, const QString &url, quint16 lineNumber)
+QQmlBinding *QQmlBinding::create(
+ const QQmlPropertyData *property, const QString &str, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt, const QString &url, quint16 lineNumber)
{
QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
@@ -134,8 +136,9 @@ QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, const QString
return b;
}
-QQmlBinding *QQmlBinding::create(const QQmlPropertyData *property, QV4::Function *function,
- QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope)
+QQmlBinding *QQmlBinding::create(
+ const QQmlPropertyData *property, QV4::Function *function, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt, QV4::ExecutionContext *scope)
{
QQmlBinding *b = newBinding(QQmlEnginePrivate::get(ctxt), property);
@@ -154,14 +157,9 @@ QQmlBinding::~QQmlBinding()
delete m_sourceLocation;
}
-void QQmlBinding::setNotifyOnValueChanged(bool v)
-{
- QQmlJavaScriptExpression::setNotifyOnValueChanged(v);
-}
-
void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
{
- if (!enabledFlag() || !context() || !context()->isValid())
+ if (!enabledFlag() || !hasValidContext())
return;
// Check that the target has not been deleted
@@ -182,15 +180,15 @@ void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
DeleteWatcher watcher(this);
- QQmlEngine *engine = context()->engine;
- QV4::Scope scope(engine->handle());
+ QQmlEngine *qmlEngine = engine();
+ QV4::Scope scope(qmlEngine->handle());
if (canUseAccessor())
flags.setFlag(QQmlPropertyData::BypassInterceptor);
Q_TRACE_SCOPE(QQmlBinding, engine, function() ? function()->name()->toQString() : QString(),
sourceLocation().sourceFile, sourceLocation().line, sourceLocation().column);
- QQmlBindingProfiler prof(QQmlEnginePrivate::get(engine)->profiler, function());
+ QQmlBindingProfiler prof(QQmlEnginePrivate::get(qmlEngine)->profiler, function());
doUpdate(watcher, flags, scope);
if (!watcher.wasDeleted())
@@ -199,7 +197,7 @@ void QQmlBinding::update(QQmlPropertyData::WriteFlags flags)
QV4::ReturnedValue QQmlBinding::evaluate(bool *isUndefined)
{
- QV4::ExecutionEngine *v4 = context()->engine->handle();
+ QV4::ExecutionEngine *v4 = engine()->handle();
int argc = 0;
const QV4::Value *argv = nullptr;
const QV4::Value *thisObject = nullptr;
@@ -234,7 +232,7 @@ protected:
QQmlPropertyData *pd = nullptr;
getPropertyData(&pd, nullptr);
QQmlBinding *thisPtr = this;
- pd->writeProperty(*m_target, &thisPtr, flags);
+ pd->writeProperty(m_target.data(), &thisPtr, flags);
}
};
@@ -265,7 +263,7 @@ protected:
}
if (hasError()) {
- if (!delayedError()->addError(ep)) ep->warning(this->error(context()->engine));
+ if (!delayedError()->addError(ep)) ep->warning(this->error(engine()));
} else {
clearError();
}
@@ -388,7 +386,10 @@ private:
const QV4::CompiledData::Binding *m_binding;
};
-QQmlBinding *QQmlBinding::createTranslationBinding(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, const QV4::CompiledData::Binding *binding, QObject *obj, QQmlContextData *ctxt)
+QQmlBinding *QQmlBinding::createTranslationBinding(
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
+ const QV4::CompiledData::Binding *binding, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt)
{
QQmlTranslationBinding *b = new QQmlTranslationBinding(unit, binding);
@@ -409,8 +410,8 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
const QV4::Value &result,
bool isUndefined, QQmlPropertyData::WriteFlags flags)
{
- QQmlEngine *engine = context()->engine;
- QV4::ExecutionEngine *v4engine = engine->handle();
+ QQmlEngine *qmlEngine = engine();
+ QV4::ExecutionEngine *v4engine = qmlEngine->handle();
int type = valueTypeData.isValid() ? valueTypeData.propType() : core.propType();
@@ -455,9 +456,10 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
return false;
}
- QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, QVariant::fromValue(
- QJSValue(v4engine, result.asReturnedValue())),
- context(), flags);
+ QQmlPropertyPrivate::writeValueProperty(
+ m_target.data(), core, valueTypeData,
+ QVariant::fromValue(QJSValuePrivate::fromReturnedValue(result.asReturnedValue())),
+ context(), flags);
} else if (isUndefined) {
const QLatin1String typeName(QMetaType::typeName(type)
? QMetaType::typeName(type)
@@ -484,7 +486,7 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
if (QObject *o = *(QObject *const *)value.constData()) {
valueType = o->metaObject()->className();
- QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
+ QQmlMetaObject propertyMetaObject = QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate::get(qmlEngine), type);
if (!propertyMetaObject.isNull())
propertyType = propertyMetaObject.className();
}
@@ -514,13 +516,13 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
QVariant QQmlBinding::evaluate()
{
- QQmlEngine *engine = context()->engine;
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
+ QQmlEngine *qmlEngine = engine();
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine);
ep->referenceScarceResources();
bool isUndefined = false;
- QV4::Scope scope(engine->handle());
+ QV4::Scope scope(qmlEngine->handle());
QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
ep->dereferenceScarceResources();
@@ -528,18 +530,6 @@ QVariant QQmlBinding::evaluate()
return scope.engine->toVariant(result, qMetaTypeId<QList<QObject*> >());
}
-QString QQmlBinding::expressionIdentifier() const
-{
- if (auto f = function()) {
- QString url = f->sourceFile();
- uint lineNumber = f->compiledFunction->location.line;
- uint columnNumber = f->compiledFunction->location.column;
- return url + QString::asprintf(":%u:%u", lineNumber, columnNumber);
- }
-
- return QStringLiteral("[native code]");
-}
-
void QQmlBinding::expressionChanged()
{
update();
@@ -556,10 +546,10 @@ void QQmlBinding::setEnabled(bool e, QQmlPropertyData::WriteFlags flags)
setEnabledFlag(e);
setNotifyOnValueChanged(e);
- m_nextBinding.setFlag2(); // Always use accessors, only not when:
+ m_nextBinding.setTag(m_nextBinding.tag().setFlag(CanUseAccessor)); // Always use accessors, only not when:
if (auto interceptorMetaObject = QQmlInterceptorMetaObject::get(targetObject())) {
if (!m_targetIndex.isValid() || interceptorMetaObject->intercepts(m_targetIndex))
- m_nextBinding.clearFlag2();
+ m_nextBinding.setTag(m_nextBinding.tag().setFlag(CanUseAccessor, false));
}
if (e && !wasEnabled)
@@ -616,9 +606,9 @@ bool QQmlBinding::setTarget(QObject *object, const QQmlPropertyData &core, const
}
m_targetIndex = QQmlPropertyIndex(coreIndex, valueTypeIndex);
- QQmlData *data = QQmlData::get(*m_target, true);
+ QQmlData *data = QQmlData::get(m_target.data(), true);
if (!data->propertyCache) {
- data->propertyCache = QQmlEnginePrivate::get(context()->engine)->cache(m_target->metaObject());
+ data->propertyCache = QQmlEnginePrivate::get(engine())->cache(m_target->metaObject());
data->propertyCache->addref();
}
@@ -629,11 +619,11 @@ void QQmlBinding::getPropertyData(QQmlPropertyData **propertyData, QQmlPropertyD
{
Q_ASSERT(propertyData);
- QQmlData *data = QQmlData::get(*m_target, false);
+ QQmlData *data = QQmlData::get(m_target.data(), false);
Q_ASSERT(data);
if (Q_UNLIKELY(!data->propertyCache)) {
- data->propertyCache = QQmlEnginePrivate::get(context()->engine)->cache(m_target->metaObject());
+ data->propertyCache = QQmlEnginePrivate::get(engine())->cache(m_target->metaObject());
data->propertyCache->addref();
}
@@ -720,8 +710,9 @@ protected:
}
} else if (auto variant = result.as<QV4::VariantObject>()) {
QVariant value = variant->d()->data();
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context());
- resultMo = QQmlPropertyPrivate::rawMetaObjectForType(ep, value.userType());
+ QQmlEngine *qmlEngine = engine();
+ resultMo = QQmlPropertyPrivate::rawMetaObjectForType(
+ qmlEngine ? QQmlEnginePrivate::get(qmlEngine) : nullptr, value.userType());
if (resultMo.isNull())
return slowWrite(*pd, vtpd, result, isUndefined, flags);
resultObject = *static_cast<QObject *const *>(value.constData());
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index 7f96b4df9f..bf73c24c9e 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -76,19 +76,26 @@ public:
typedef QExplicitlySharedDataPointer<QQmlBinding> Ptr;
static QQmlBinding *create(const QQmlPropertyData *, const QQmlScriptString &, QObject *, QQmlContext *);
- static QQmlBinding *create(const QQmlPropertyData *, const QString &, QObject *, QQmlContextData *,
- const QString &url = QString(), quint16 lineNumber = 0);
- static QQmlBinding *create(const QQmlPropertyData *property, QV4::Function *function,
- QObject *obj, QQmlContextData *ctxt, QV4::ExecutionContext *scope);
- static QQmlBinding *createTranslationBinding(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, const QV4::CompiledData::Binding *binding,
- QObject *obj, QQmlContextData *ctxt);
+
+ static QQmlBinding *create(
+ const QQmlPropertyData *, const QString &, QObject *,
+ const QQmlRefPointer<QQmlContextData> &, const QString &url = QString(),
+ quint16 lineNumber = 0);
+
+ static QQmlBinding *create(
+ const QQmlPropertyData *property, QV4::Function *function, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt, QV4::ExecutionContext *scope);
+
+ static QQmlBinding *createTranslationBinding(
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
+ const QV4::CompiledData::Binding *binding, QObject *obj,
+ const QQmlRefPointer<QQmlContextData> &ctxt);
+
~QQmlBinding() override;
void setTarget(const QQmlProperty &);
bool setTarget(QObject *, const QQmlPropertyData &, const QQmlPropertyData *valueType);
- void setNotifyOnValueChanged(bool);
-
void refresh() override;
void setEnabled(bool, QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding) override;
@@ -102,7 +109,6 @@ public:
QVariant evaluate();
- QString expressionIdentifier() const override;
void expressionChanged() override;
QQmlSourceLocation sourceLocation() const override;
@@ -147,22 +153,22 @@ private:
bool QQmlBinding::updatingFlag() const
{
- return m_target.flag();
+ return m_target.tag().testFlag(UpdatingBinding);
}
void QQmlBinding::setUpdatingFlag(bool v)
{
- m_target.setFlagValue(v);
+ m_target.setTag(m_target.tag().setFlag(UpdatingBinding, v));
}
bool QQmlBinding::enabledFlag() const
{
- return m_target.flag2();
+ return m_target.tag().testFlag(BindingEnabled);
}
void QQmlBinding::setEnabledFlag(bool v)
{
- m_target.setFlag2Value(v);
+ m_target.setTag(m_target.tag().setFlag(BindingEnabled, v));
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index b347bb3829..e87f691203 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -64,11 +64,10 @@
QT_BEGIN_NAMESPACE
-QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
- QQmlContextData *ctxt, QObject *scope, const QString &expression,
- const QString &fileName, quint16 line, quint16 column,
- const QString &handlerName,
- const QString &parameterString)
+QQmlBoundSignalExpression::QQmlBoundSignalExpression(
+ QObject *target, int index, const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope,
+ const QString &expression, const QString &fileName, quint16 line, quint16 column,
+ const QString &handlerName, const QString &parameterString)
: QQmlJavaScriptExpression(),
m_index(index),
m_target(target)
@@ -105,8 +104,9 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
setupFunction(context, f->function());
}
-QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scopeObject,
- QV4::Function *function, QV4::ExecutionContext *scope)
+QQmlBoundSignalExpression::QQmlBoundSignalExpression(
+ QObject *target, int index, const QQmlRefPointer<QQmlContextData> &ctxt,
+ QObject *scopeObject, QV4::Function *function, QV4::ExecutionContext *scope)
: QQmlJavaScriptExpression(),
m_index(index),
m_target(target)
@@ -114,7 +114,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
// It's important to call init first, because m_index gets remapped in case of cloned signals.
init(ctxt, scopeObject);
- QV4::ExecutionEngine *engine = ctxt->engine->handle();
+ QV4::ExecutionEngine *engine = ctxt->engine()->handle();
// If the function is marked as having a nested function, then the user wrote:
// onSomeSignal: function() { /*....*/ }
@@ -141,7 +141,7 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
setupFunction(qmlContext, function);
}
-void QQmlBoundSignalExpression::init(QQmlContextData *ctxt, QObject *scope)
+void QQmlBoundSignalExpression::init(const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope)
{
setNotifyOnValueChanged(false);
setContext(ctxt);
@@ -177,7 +177,7 @@ QString QQmlBoundSignalExpression::expression() const
// Changes made here may need to be made there and vice versa.
void QQmlBoundSignalExpression::evaluate(void **a)
{
- Q_ASSERT (context() && engine());
+ Q_ASSERT (engine());
if (!expressionFunctionValid())
return;
@@ -202,10 +202,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
// for several cases (such as QVariant type and QObject-derived types)
//args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
if (type == qMetaTypeId<QJSValue>()) {
- if (QV4::Value *v4Value = QJSValuePrivate::valueForData(reinterpret_cast<QJSValue *>(a[ii + 1]), &jsCall->args[ii]))
- jsCall->args[ii] = *v4Value;
- else
- jsCall->args[ii] = QV4::Encode::undefined();
+ jsCall->args[ii] = QJSValuePrivate::asReturnedValue(reinterpret_cast<QJSValue *>(a[ii + 1]));
} else if (type == QMetaType::QVariant) {
jsCall->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
} else if (type == QMetaType::Int) {
@@ -228,7 +225,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
void QQmlBoundSignalExpression::evaluate(const QList<QVariant> &args)
{
- Q_ASSERT (context() && engine());
+ Q_ASSERT (engine());
if (!expressionFunctionValid())
return;
@@ -411,4 +408,13 @@ QQmlBoundSignalExpressionPointer &QQmlBoundSignalExpressionPointer::take(QQmlBou
return *this;
}
+QQmlPropertyObserver::QQmlPropertyObserver(QQmlBoundSignalExpression *expr)
+ : QPropertyObserver([](QPropertyObserver *self, void *) {
+ auto This = static_cast<QQmlPropertyObserver*>(self);
+ This->expression->evaluate(QList<QVariant>());
+ })
+{
+ expression.take(expr);
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index d1ec67210e..71a3e90b7f 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -66,15 +66,14 @@ QT_BEGIN_NAMESPACE
class Q_QML_PRIVATE_EXPORT QQmlBoundSignalExpression : public QQmlJavaScriptExpression, public QQmlRefCount
{
public:
- QQmlBoundSignalExpression(QObject *target, int index,
- QQmlContextData *ctxt, QObject *scope, const QString &expression,
- const QString &fileName, quint16 line, quint16 column,
- const QString &handlerName = QString(),
- const QString &parameterString = QString());
+ QQmlBoundSignalExpression(
+ QObject *target, int index, const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope,
+ const QString &expression, const QString &fileName, quint16 line, quint16 column,
+ const QString &handlerName = QString(), const QString &parameterString = QString());
- QQmlBoundSignalExpression(QObject *target, int index,
- QQmlContextData *ctxt, QObject *scopeObject, QV4::Function *function,
- QV4::ExecutionContext *scope = nullptr);
+ QQmlBoundSignalExpression(
+ QObject *target, int index, const QQmlRefPointer<QQmlContextData> &ctxt,
+ QObject *scopeObject, QV4::Function *function, QV4::ExecutionContext *scope = nullptr);
// inherited from QQmlJavaScriptExpression.
QString expressionIdentifier() const override;
@@ -87,12 +86,10 @@ public:
QString expression() const;
QObject *target() const { return m_target; }
- QQmlEngine *engine() const { return context() ? context()->engine : nullptr; }
-
private:
~QQmlBoundSignalExpression() override;
- void init(QQmlContextData *ctxt, QObject *scope);
+ void init(const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope);
bool expressionFunctionValid() const { return function() != nullptr; }
@@ -129,6 +126,15 @@ private:
QQmlBoundSignalExpressionPointer m_expression;
};
+class QQmlPropertyObserver : public QPropertyObserver
+{
+public:
+ QQmlPropertyObserver(QQmlBoundSignalExpression *expr);
+
+private:
+ QQmlBoundSignalExpressionPointer expression;
+};
+
QT_END_NAMESPACE
#endif // QQMLBOUNDSIGNAL_P_H
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 9ee4fdbe41..64e2c9a90e 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -521,6 +521,10 @@ QQmlComponent::QQmlComponent(QQmlEngine *engine, QObject *parent)
{
Q_D(QQmlComponent);
d->engine = engine;
+ QObject::connect(engine, &QObject::destroyed, this, [d]() {
+ d->state.creator.reset();
+ d->engine = nullptr;
+ });
}
/*!
@@ -635,7 +639,7 @@ void QQmlComponent::setData(const QByteArray &data, const QUrl &url)
QQmlContext *QQmlComponent::creationContext() const
{
Q_D(const QQmlComponent);
- if(d->creationContext)
+ if (!d->creationContext.isNull())
return d->creationContext->asQQmlContext();
return qmlContext(this);
@@ -879,15 +883,11 @@ QObject *QQmlComponent::createWithInitialProperties(const QVariantMap& initialPr
QObject *QQmlComponent::beginCreate(QQmlContext *publicContext)
{
Q_D(QQmlComponent);
-
Q_ASSERT(publicContext);
- QQmlContextData *context = QQmlContextData::get(publicContext);
-
- return d->beginCreate(context);
+ return d->beginCreate(QQmlContextData::get(publicContext));
}
-QObject *
-QQmlComponentPrivate::beginCreate(QQmlContextData *context)
+QObject *QQmlComponentPrivate::beginCreate(QQmlRefPointer<QQmlContextData> context)
{
Q_Q(QQmlComponent);
if (!context) {
@@ -900,7 +900,7 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
return nullptr;
}
- if (context->engine != engine) {
+ if (context->engine() != engine) {
qWarning("QQmlComponent: Must create component in context from the same QQmlEngine");
return nullptr;
}
@@ -930,7 +930,7 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
enginePriv->referenceScarceResources();
QObject *rv = nullptr;
- state.creator.reset(new QQmlObjectCreator(context, compilationUnit, creationContext));
+ state.creator.reset(new QQmlObjectCreator(std::move(context), compilationUnit, creationContext));
rv = state.creator->create(start);
if (!rv)
state.errors = state.creator->errors;
@@ -963,8 +963,9 @@ void QQmlComponentPrivate::beginDeferred(QQmlEnginePrivate *enginePriv,
ConstructionState *state = new ConstructionState;
state->completePending = true;
- QQmlContextData *creationContext = nullptr;
- state->creator.reset(new QQmlObjectCreator(deferredData->context->parent, deferredData->compilationUnit, creationContext));
+ state->creator.reset(new QQmlObjectCreator(
+ deferredData->context->parent(), deferredData->compilationUnit,
+ QQmlRefPointer<QQmlContextData>()));
if (!state->creator->populateDeferredProperties(object, deferredData))
state->errors << state->creator->errors;
@@ -1082,16 +1083,16 @@ void QQmlComponentPrivate::completeCreate()
}
QQmlComponentAttached::QQmlComponentAttached(QObject *parent)
-: QObject(parent), prev(nullptr), next(nullptr)
+: QObject(parent), m_prev(nullptr), m_next(nullptr)
{
}
QQmlComponentAttached::~QQmlComponentAttached()
{
- if (prev) *prev = next;
- if (next) next->prev = prev;
- prev = nullptr;
- next = nullptr;
+ if (m_prev) *m_prev = m_next;
+ if (m_next) m_next->m_prev = m_prev;
+ m_prev = nullptr;
+ m_next = nullptr;
}
/*!
@@ -1107,12 +1108,12 @@ QQmlComponentAttached *QQmlComponent::qmlAttachedProperties(QObject *obj)
QQmlEnginePrivate *p = QQmlEnginePrivate::get(engine);
if (p->activeObjectCreator) { // XXX should only be allowed during begin
- a->add(p->activeObjectCreator->componentAttachment());
+ a->insertIntoList(p->activeObjectCreator->componentAttachment());
} else {
QQmlData *d = QQmlData::get(obj);
Q_ASSERT(d);
Q_ASSERT(d->context);
- a->add(&d->context->componentAttached);
+ d->context->addComponentAttached(a);
}
return a;
@@ -1138,24 +1139,23 @@ QQmlComponentAttached *QQmlComponent::qmlAttachedProperties(QObject *obj)
\sa QQmlIncubator
*/
-void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
- QQmlContext *forContext)
+void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context, QQmlContext *forContext)
{
Q_D(QQmlComponent);
if (!context)
context = d->engine->rootContext();
- QQmlContextData *contextData = QQmlContextData::get(context);
- QQmlContextData *forContextData = contextData;
- if (forContext) forContextData = QQmlContextData::get(forContext);
+ QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
+ QQmlRefPointer<QQmlContextData> forContextData =
+ forContext ? QQmlContextData::get(forContext) : contextData;
if (!contextData->isValid()) {
qWarning("QQmlComponent: Cannot create a component in an invalid context");
return;
}
- if (contextData->engine != d->engine) {
+ if (contextData->engine() != d->engine) {
qWarning("QQmlComponent: Must create component in context from the same QQmlEngine");
return;
}
@@ -1209,8 +1209,8 @@ void QQmlComponentPrivate::incubateObject(
QQmlIncubator *incubationTask,
QQmlComponent *component,
QQmlEngine *engine,
- QQmlContextData *context,
- QQmlContextData *forContext)
+ const QQmlRefPointer<QQmlContextData> &context,
+ const QQmlRefPointer<QQmlContextData> &forContext)
{
QQmlIncubatorPrivate *incubatorPriv = QQmlIncubatorPrivate::get(incubationTask);
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h
index cb5d5a787c..9a4ea711f3 100644
--- a/src/qml/qml/qqmlcomponent.h
+++ b/src/qml/qml/qqmlcomponent.h
@@ -71,6 +71,7 @@ class Q_QML_EXPORT QQmlComponent : public QObject
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QUrl url READ url CONSTANT)
QML_NAMED_ELEMENT(Component)
+ QML_ADDED_IN_VERSION(2, 0)
QML_ATTACHED(QQmlComponentAttached)
Q_CLASSINFO("QML.Builtin", "QML")
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index a919eb45c0..cc938371a1 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -61,6 +61,7 @@
#include "qqml.h"
#include <private/qqmlobjectcreator_p.h>
#include <private/qqmltypedata_p.h>
+#include <private/qqmlguardedcontextdata_p.h>
#include <QtCore/QString>
#include <QtCore/QStringList>
@@ -84,7 +85,7 @@ public:
void loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous);
- QObject *beginCreate(QQmlContextData *);
+ QObject *beginCreate(QQmlRefPointer<QQmlContextData>);
void completeCreate();
void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate, RequiredProperties &requiredProperties);
static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v, RequiredProperties &requiredProperties, QObject *createdComponent);
@@ -94,8 +95,8 @@ public:
QQmlIncubator *incubationTask,
QQmlComponent *component,
QQmlEngine *engine,
- QQmlContextData *context,
- QQmlContextData *forContext);
+ const QQmlRefPointer<QQmlContextData> &context,
+ const QQmlRefPointer<QQmlContextData> &forContext);
QQmlRefPointer<QQmlTypeData> typeData;
void typeDataReady(QQmlTypeData *) override;
diff --git a/src/qml/qml/qqmlcomponentattached_p.h b/src/qml/qml/qqmlcomponentattached_p.h
index 8ecd9da17d..b94d474d1f 100644
--- a/src/qml/qml/qqmlcomponentattached_p.h
+++ b/src/qml/qml/qqmlcomponentattached_p.h
@@ -66,28 +66,38 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentAttached : public QObject
// when registering QQmlComponent, but we cannot #include it from qqmlcomponent.h. Therefore we
// force an anonymous type registration here.
QML_ANONYMOUS
+ QML_ADDED_IN_VERSION(2, 0)
public:
QQmlComponentAttached(QObject *parent = nullptr);
~QQmlComponentAttached();
- void add(QQmlComponentAttached **a) {
- prev = a; next = *a; *a = this;
- if (next) next->prev = &next;
+ void insertIntoList(QQmlComponentAttached **listHead)
+ {
+ m_prev = listHead;
+ m_next = *listHead;
+ *listHead = this;
+ if (m_next)
+ m_next->m_prev = &m_next;
}
- void rem() {
- if (next) next->prev = prev;
- *prev = next;
- next = nullptr; prev = nullptr;
+
+ void removeFromList()
+ {
+ *m_prev = m_next;
+ if (m_next)
+ m_next->m_prev = m_prev;
+ m_next = nullptr;
+ m_prev = nullptr;
}
- QQmlComponentAttached **prev;
- QQmlComponentAttached *next;
+
+ QQmlComponentAttached *next() const { return m_next; }
Q_SIGNALS:
void completed();
void destruction();
private:
- friend class QQmlContextData;
+ QQmlComponentAttached **m_prev;
+ QQmlComponentAttached *m_next;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 9157bb95c3..a67eeeecc9 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -55,11 +55,6 @@
QT_BEGIN_NAMESPACE
-QQmlContextPrivate::QQmlContextPrivate()
-: data(nullptr), notifyIndex(-1)
-{
-}
-
/*!
\class QQmlContext
\brief The QQmlContext class defines a context within a QML engine.
@@ -157,13 +152,8 @@ QQmlContextPrivate::QQmlContextPrivate()
/*! \internal */
QQmlContext::QQmlContext(QQmlEngine *e, bool)
-: QObject(*(new QQmlContextPrivate))
+ : QObject(*(new QQmlContextPrivate(this, nullptr, e)))
{
- Q_D(QQmlContext);
- d->data = new QQmlContextData(this);
- ++d->data->refCount;
-
- d->data->engine = e;
}
/*!
@@ -171,13 +161,10 @@ QQmlContext::QQmlContext(QQmlEngine *e, bool)
QObject \a parent.
*/
QQmlContext::QQmlContext(QQmlEngine *engine, QObject *parent)
-: QObject(*(new QQmlContextPrivate), parent)
+ : QObject(*(new QQmlContextPrivate(
+ this, engine ? QQmlContextData::get(engine->rootContext()).data() : nullptr)),
+ parent)
{
- Q_D(QQmlContext);
- d->data = new QQmlContextData(this);
- ++d->data->refCount;
-
- d->data->setParent(engine?QQmlContextData::get(engine->rootContext()):nullptr);
}
/*!
@@ -185,24 +172,18 @@ QQmlContext::QQmlContext(QQmlEngine *engine, QObject *parent)
QObject \a parent.
*/
QQmlContext::QQmlContext(QQmlContext *parentContext, QObject *parent)
-: QObject(*(new QQmlContextPrivate), parent)
+ : QObject(*(new QQmlContextPrivate(
+ this, parentContext ? QQmlContextData::get(parentContext).data() : nullptr)),
+ parent)
{
- Q_D(QQmlContext);
- d->data = new QQmlContextData(this);
- ++d->data->refCount;
-
- d->data->setParent(parentContext?QQmlContextData::get(parentContext):nullptr);
}
/*!
\internal
*/
-QQmlContext::QQmlContext(QQmlContextData *data)
-: QObject(*(new QQmlContextPrivate), nullptr)
+QQmlContext::QQmlContext(QQmlContextPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
{
- Q_D(QQmlContext);
- d->data = data;
- // don't add a refcount here, as the data owns this context
}
/*!
@@ -215,10 +196,7 @@ QQmlContext::QQmlContext(QQmlContextData *data)
QQmlContext::~QQmlContext()
{
Q_D(QQmlContext);
-
- d->data->publicContext = nullptr;
- if (!--d->data->refCount)
- d->data->destroy();
+ d->m_data->clearPublicContext();
}
/*!
@@ -230,7 +208,7 @@ QQmlContext::~QQmlContext()
bool QQmlContext::isValid() const
{
Q_D(const QQmlContext);
- return d->data && d->data->isValid();
+ return d->m_data->isValid();
}
/*!
@@ -240,7 +218,7 @@ bool QQmlContext::isValid() const
QQmlEngine *QQmlContext::engine() const
{
Q_D(const QQmlContext);
- return d->data->engine;
+ return d->m_data->engine();
}
/*!
@@ -250,7 +228,10 @@ QQmlEngine *QQmlContext::engine() const
QQmlContext *QQmlContext::parentContext() const
{
Q_D(const QQmlContext);
- return d->data->parent?d->data->parent->asQQmlContext():nullptr;
+
+ if (QQmlRefPointer<QQmlContextData> parent = d->m_data->parent())
+ return parent->asQQmlContext();
+ return nullptr;
}
/*!
@@ -259,7 +240,7 @@ QQmlContext *QQmlContext::parentContext() const
QObject *QQmlContext::contextObject() const
{
Q_D(const QQmlContext);
- return d->data->contextObject;
+ return d->m_data->contextObject();
}
/*!
@@ -269,19 +250,19 @@ void QQmlContext::setContextObject(QObject *object)
{
Q_D(QQmlContext);
- QQmlContextData *data = d->data;
+ QQmlRefPointer<QQmlContextData> data = d->m_data;
- if (data->isInternal) {
+ if (data->isInternal()) {
qWarning("QQmlContext: Cannot set context object for internal context.");
return;
}
- if (!isValid()) {
+ if (!data->isValid()) {
qWarning("QQmlContext: Cannot set context object on invalid context.");
return;
}
- data->contextObject = object;
+ data->setContextObject(object);
data->refreshExpressions();
}
@@ -291,31 +272,30 @@ void QQmlContext::setContextObject(QObject *object)
void QQmlContext::setContextProperty(const QString &name, const QVariant &value)
{
Q_D(QQmlContext);
- if (d->notifyIndex == -1)
- d->notifyIndex = QMetaObjectPrivate::absoluteSignalCount(&QQmlContext::staticMetaObject);
+ if (d->notifyIndex() == -1)
+ d->setNotifyIndex(QMetaObjectPrivate::absoluteSignalCount(&QQmlContext::staticMetaObject));
- QQmlContextData *data = d->data;
+ QQmlRefPointer<QQmlContextData> data = d->m_data;
- if (data->isInternal) {
+ if (data->isInternal()) {
qWarning("QQmlContext: Cannot set property on internal context.");
return;
}
- if (!isValid()) {
+ if (!data->isValid()) {
qWarning("QQmlContext: Cannot set property on invalid context.");
return;
}
- QV4::IdentifierHash &properties = data->detachedPropertyNames();
- int idx = properties.value(name);
+ QV4::IdentifierHash *properties = data->detachedPropertyNames();
+ int idx = properties->value(name);
if (idx == -1) {
- properties.add(name, data->idValueCount + d->propertyValues.count());
- d->propertyValues.append(value);
-
+ properties->add(name, data->numIdValues() + d->numPropertyValues());
+ d->appendPropertyValue(value);
data->refreshExpressions();
} else {
- d->propertyValues[idx] = value;
- QMetaObject::activate(this, d->notifyIndex, idx, nullptr);
+ d->setPropertyValue(idx, value);
+ QMetaObject::activate(this, d->notifyIndex(), idx, nullptr);
}
if (auto *obj = qvariant_cast<QObject *>(value)) {
@@ -350,20 +330,15 @@ void QQmlContext::setContextProperties(const QVector<PropertyPair> &properties)
{
Q_D(const QQmlContext);
- QQmlContextData *data = d->data;
-
- QQmlJavaScriptExpression *expressions = data->expressions;
- QQmlContextData *childContexts = data->childContexts;
-
- data->expressions = nullptr;
- data->childContexts = nullptr;
+ QQmlRefPointer<QQmlContextData> data = d->m_data;
+ QQmlJavaScriptExpression *expressions = data->takeExpressions();
+ QQmlRefPointer<QQmlContextData> childContexts = data->takeChildContexts();
for (const auto &property : properties)
setContextProperty(property.name, property.value);
- data->expressions = expressions;
- data->childContexts = childContexts;
-
+ data->setExpressions(expressions);
+ data->setChildContexts(childContexts);
data->refreshExpressions();
}
@@ -389,28 +364,27 @@ QVariant QQmlContext::contextProperty(const QString &name) const
QVariant value;
int idx = -1;
- QQmlContextData *data = d->data;
+ QQmlRefPointer<QQmlContextData> data = d->m_data;
- const QV4::IdentifierHash &properties = data->propertyNames();
+ const QV4::IdentifierHash properties = data->propertyNames();
if (properties.count())
idx = properties.value(name);
if (idx == -1) {
- if (data->contextObject) {
- QObject *obj = data->contextObject;
+ if (QObject *obj = data->contextObject()) {
QQmlPropertyData local;
QQmlPropertyData *property =
- QQmlPropertyCache::property(data->engine, obj, name, data, local);
+ QQmlPropertyCache::property(data->engine(), obj, name, data, local);
if (property) value = obj->metaObject()->property(property->coreIndex()).read(obj);
}
if (!value.isValid() && parentContext())
value = parentContext()->contextProperty(name);
} else {
- if (idx >= d->propertyValues.count())
- value = QVariant::fromValue(data->idValues[idx - d->propertyValues.count()].data());
+ if (idx >= d->numPropertyValues())
+ value = QVariant::fromValue(data->idValue(idx - d->numPropertyValues()));
else
- value = d->propertyValues[idx];
+ value = d->propertyValue(idx);
}
return value;
@@ -427,7 +401,7 @@ QString QQmlContext::nameForObject(QObject *object) const
{
Q_D(const QQmlContext);
- return d->data->findObjectId(object);
+ return d->m_data->findObjectId(object);
}
/*!
@@ -439,38 +413,9 @@ QString QQmlContext::nameForObject(QObject *object) const
QUrl QQmlContext::resolvedUrl(const QUrl &src)
{
Q_D(QQmlContext);
- return d->data->resolvedUrl(src);
-}
-
-QUrl QQmlContextData::resolvedUrl(const QUrl &src)
-{
- QUrl resolved;
- if (src.isRelative() && !src.isEmpty()) {
- QQmlContextData *ctxt = this;
- do {
- if (ctxt->url().isValid())
- break;
- else
- ctxt = ctxt->parent;
- } while (ctxt);
-
- if (ctxt)
- resolved = ctxt->url().resolved(src);
- else if (engine)
- resolved = engine->baseUrl().resolved(src);
- } else {
- resolved = src;
- }
-
- if (resolved.isEmpty()) //relative but no ctxt
- return resolved;
-
- if (engine && engine->urlInterceptor())
- resolved = engine->urlInterceptor()->intercept(resolved, QQmlAbstractUrlInterceptor::UrlString);
- return resolved;
+ return d->m_data->resolvedUrl(src);
}
-
/*!
Explicitly sets the url resolvedUrl() will use for relative references to \a baseUrl.
@@ -482,9 +427,8 @@ QUrl QQmlContextData::resolvedUrl(const QUrl &src)
void QQmlContext::setBaseUrl(const QUrl &baseUrl)
{
Q_D(QQmlContext);
-
- d->data->baseUrl = baseUrl;
- d->data->baseUrlString = baseUrl.toString();
+ d->m_data->setBaseUrl(baseUrl);
+ d->m_data->setBaseUrlString(baseUrl.toString());
}
/*!
@@ -494,14 +438,7 @@ void QQmlContext::setBaseUrl(const QUrl &baseUrl)
QUrl QQmlContext::baseUrl() const
{
Q_D(const QQmlContext);
- const QQmlContextData* data = d->data;
- while (data && data->url().isEmpty())
- data = data->parent;
-
- if (data)
- return data->url();
- else
- return QUrl();
+ return d->m_data->baseUrl();
}
int QQmlContextPrivate::context_count(QQmlListProperty<QObject> *prop)
@@ -510,11 +447,10 @@ int QQmlContextPrivate::context_count(QQmlListProperty<QObject> *prop)
QQmlContextPrivate *d = QQmlContextPrivate::get(context);
int contextProperty = (int)(quintptr)prop->data;
- if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) {
+ if (d->propertyValue(contextProperty).userType() != qMetaTypeId<QList<QObject*> >())
return 0;
- } else {
- return ((const QList<QObject> *)d->propertyValues.at(contextProperty).constData())->count();
- }
+ else
+ return ((const QList<QObject> *)d->propertyValue(contextProperty).constData())->count();
}
QObject *QQmlContextPrivate::context_at(QQmlListProperty<QObject> *prop, int index)
@@ -523,384 +459,40 @@ QObject *QQmlContextPrivate::context_at(QQmlListProperty<QObject> *prop, int ind
QQmlContextPrivate *d = QQmlContextPrivate::get(context);
int contextProperty = (int)(quintptr)prop->data;
- if (d->propertyValues.at(contextProperty).userType() != qMetaTypeId<QList<QObject*> >()) {
+ if (d->propertyValue(contextProperty).userType() != qMetaTypeId<QList<QObject*> >())
return nullptr;
- } else {
- return ((const QList<QObject*> *)d->propertyValues.at(contextProperty).constData())->at(index);
- }
+ else
+ return ((const QList<QObject*> *)d->propertyValue(contextProperty).constData())->at(index);
}
void QQmlContextPrivate::dropDestroyedQObject(const QString &name, QObject *destroyed)
{
- if (!data->isValid())
+ if (!m_data->isValid())
return;
- const int idx = data->propertyNames().value(name);
+ const int idx = m_data->propertyNames().value(name);
Q_ASSERT(idx >= 0);
- if (qvariant_cast<QObject *>(propertyValues[idx]) != destroyed)
+ if (qvariant_cast<QObject *>(propertyValue(idx)) != destroyed)
return;
- propertyValues[idx] = QVariant::fromValue<QObject *>(nullptr);
- QMetaObject::activate(q_func(), notifyIndex, idx, nullptr);
-}
-
-
-QQmlContextData::QQmlContextData()
- : QQmlContextData(nullptr)
-{
-}
-
-QQmlContextData::QQmlContextData(QQmlContext *ctxt)
- : engine(nullptr), isInternal(false), isJSContext(false),
- isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
- stronglyReferencedByParent(false), hasExtraObject(false), publicContext(ctxt), incubator(nullptr), componentObjectIndex(-1),
- contextObject(nullptr), nextChild(nullptr), prevChild(nullptr),
- expressions(nullptr), contextObjects(nullptr), idValues(nullptr), idValueCount(0),
- componentAttached(nullptr)
-{
-}
-
-void QQmlContextData::emitDestruction()
-{
- if (!hasEmittedDestruction) {
- hasEmittedDestruction = true;
-
- // Emit the destruction signal - must be emitted before invalidate so that the
- // context is still valid if bindings or resultant expression evaluation requires it
- if (engine) {
- while (componentAttached) {
- QQmlComponentAttached *a = componentAttached;
- componentAttached = a->next;
- if (componentAttached) componentAttached->prev = &componentAttached;
-
- a->next = nullptr;
- a->prev = nullptr;
-
- emit a->destruction();
- }
-
- QQmlContextData * child = childContexts;
- while (child) {
- child->emitDestruction();
- child = child->nextChild;
- }
- }
- }
-}
-
-void QQmlContextData::invalidate()
-{
- emitDestruction();
-
- while (childContexts) {
- Q_ASSERT(childContexts != this);
- if (childContexts->stronglyReferencedByParent && !--childContexts->refCount)
- childContexts->destroy();
- else
- childContexts->invalidate();
- }
-
- if (prevChild) {
- *prevChild = nextChild;
- if (nextChild) nextChild->prevChild = prevChild;
- nextChild = nullptr;
- prevChild = nullptr;
- }
-
- importedScripts.clear();
-
- engine = nullptr;
- parent = nullptr;
-}
-
-void QQmlContextData::clearContextRecursively()
-{
- clearContext();
-
- for (auto ctxIt = childContexts; ctxIt; ctxIt = ctxIt->nextChild)
- ctxIt->clearContextRecursively();
-}
-
-void QQmlContextData::clearContext()
-{
- emitDestruction();
-
- QQmlJavaScriptExpression *expression = expressions;
- while (expression) {
- QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
-
- expression->m_prevExpression = nullptr;
- expression->m_nextExpression = nullptr;
-
- expression->setContext(nullptr);
-
- expression = nextExpression;
- }
- expressions = nullptr;
-}
-
-void QQmlContextData::destroy()
-{
- Q_ASSERT(refCount == 0);
- linkedContext = nullptr;
-
- // avoid recursion
- ++refCount;
- if (engine)
- invalidate();
-
- Q_ASSERT(refCount == 1);
- clearContext();
- Q_ASSERT(refCount == 1);
-
- while (contextObjects) {
- QQmlData *co = contextObjects;
- contextObjects = contextObjects->nextContextObject;
-
- if (co->context == this)
- co->context = nullptr;
- co->outerContext = nullptr;
- co->nextContextObject = nullptr;
- co->prevContextObject = nullptr;
- }
- Q_ASSERT(refCount == 1);
-
- QQmlGuardedContextData *contextGuard = contextGuards;
- while (contextGuard) {
- QQmlGuardedContextData *next = contextGuard->m_next;
- contextGuard->m_next = nullptr;
- contextGuard->m_prev = nullptr;
- contextGuard->m_contextData = nullptr;
- contextGuard = next;
- }
- contextGuards = nullptr;
- Q_ASSERT(refCount == 1);
-
- delete [] idValues;
- idValues = nullptr;
-
- Q_ASSERT(refCount == 1);
- if (publicContext) {
- // the QQmlContext destructor will remove one ref again
- ++refCount;
- delete publicContext;
- }
-
- Q_ASSERT(refCount == 1);
- --refCount;
- Q_ASSERT(refCount == 0);
-
- delete this;
-}
-
-void QQmlContextData::setParent(QQmlContextData *p, bool stronglyReferencedByParent)
-{
- if (p == parent)
- return;
- if (p) {
- Q_ASSERT(!parent);
- parent = p;
- this->stronglyReferencedByParent = stronglyReferencedByParent;
- if (stronglyReferencedByParent)
- ++refCount; // balanced in QQmlContextData::invalidate()
- engine = p->engine;
- nextChild = p->childContexts;
- if (nextChild) nextChild->prevChild = &nextChild;
- prevChild = &p->childContexts;
- p->childContexts = this;
- }
-}
-
-void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
-{
- QQmlJavaScriptExpression::DeleteWatcher w(expression);
-
- if (expression->m_nextExpression)
- refreshExpressionsRecursive(expression->m_nextExpression);
-
- if (!w.wasDeleted())
- expression->refresh();
-}
-
-QQmlContextData::~QQmlContextData()
-{
-}
-
-static inline bool expressions_to_run(QQmlContextData *ctxt, bool isGlobalRefresh)
-{
- return ctxt->expressions && (!isGlobalRefresh || ctxt->unresolvedNames);
-}
-
-void QQmlContextData::refreshExpressionsRecursive(bool isGlobal)
-{
- // For efficiency, we try and minimize the number of guards we have to create
- if (expressions_to_run(this, isGlobal) && (nextChild || childContexts)) {
- QQmlGuardedContextData guard(this);
-
- if (childContexts)
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- if (guard.isNull()) return;
-
- if (nextChild)
- nextChild->refreshExpressionsRecursive(isGlobal);
-
- if (guard.isNull()) return;
-
- if (expressions_to_run(this, isGlobal))
- refreshExpressionsRecursive(expressions);
-
- } else if (expressions_to_run(this, isGlobal)) {
-
- refreshExpressionsRecursive(expressions);
-
- } else if (nextChild && childContexts) {
-
- QQmlGuardedContextData guard(this);
-
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- if (!guard.isNull() && nextChild)
- nextChild->refreshExpressionsRecursive(isGlobal);
-
- } else if (nextChild) {
-
- nextChild->refreshExpressionsRecursive(isGlobal);
-
- } else if (childContexts) {
-
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- }
-}
-
-// Refreshes all expressions that could possibly depend on this context. Refreshing flushes all
-// context-tree dependent caches in the expressions, and should occur every time the context tree
-// *structure* (not values) changes.
-void QQmlContextData::refreshExpressions()
-{
- bool isGlobal = (parent == nullptr);
-
- // For efficiency, we try and minimize the number of guards we have to create
- if (expressions_to_run(this, isGlobal) && childContexts) {
- QQmlGuardedContextData guard(this);
-
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- if (!guard.isNull() && expressions_to_run(this, isGlobal))
- refreshExpressionsRecursive(expressions);
-
- } else if (expressions_to_run(this, isGlobal)) {
-
- refreshExpressionsRecursive(expressions);
-
- } else if (childContexts) {
-
- childContexts->refreshExpressionsRecursive(isGlobal);
-
- }
-}
-
-void QQmlContextData::addObject(QQmlData *data)
-{
- if (data->outerContext) {
- if (data->nextContextObject)
- data->nextContextObject->prevContextObject = data->prevContextObject;
- if (data->prevContextObject)
- *data->prevContextObject = data->nextContextObject;
- else if (data->outerContext->contextObjects == data)
- data->outerContext->contextObjects = data->nextContextObject;
- }
-
- data->outerContext = this;
-
- data->nextContextObject = contextObjects;
- if (data->nextContextObject)
- data->nextContextObject->prevContextObject = &data->nextContextObject;
- data->prevContextObject = &contextObjects;
- contextObjects = data;
-}
-
-void QQmlContextData::setIdProperty(int idx, QObject *obj)
-{
- idValues[idx] = obj;
- idValues[idx].context = this;
-}
-
-QString QQmlContextData::findObjectId(const QObject *obj) const
-{
- const QV4::IdentifierHash &properties = propertyNames();
- if (propertyNameCache.isEmpty())
- return QString();
-
- for (int ii = 0; ii < idValueCount; ii++) {
- if (idValues[ii] == obj)
- return properties.findId(ii);
- }
-
- if (publicContext) {
- QQmlContextPrivate *p = QQmlContextPrivate::get(publicContext);
- for (int ii = 0; ii < p->propertyValues.count(); ++ii)
- if (p->propertyValues.at(ii) == QVariant::fromValue(const_cast<QObject *>(obj)))
- return properties.findId(ii);
- }
-
- if (linkedContext)
- return linkedContext->findObjectId(obj);
- return QString();
-}
-
-QQmlContext *QQmlContextData::asQQmlContext()
-{
- if (!publicContext)
- publicContext = new QQmlContext(this);
- return publicContext;
-}
-
-QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
-{
- return QQmlContextPrivate::get(asQQmlContext());
-}
-
-void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int subComponentIndex)
-{
- typeCompilationUnit = unit;
- componentObjectIndex = subComponentIndex == -1 ? /*root object*/0 : subComponentIndex;
- Q_ASSERT(!idValues);
- idValueCount = typeCompilationUnit->objectAt(componentObjectIndex)->nNamedObjectsInComponent;
- idValues = new ContextGuard[idValueCount];
-}
-
-const QV4::IdentifierHash &QQmlContextData::propertyNames() const
-{
- if (propertyNameCache.isEmpty()) {
- if (typeCompilationUnit)
- propertyNameCache = typeCompilationUnit->namedObjectsPerComponent(componentObjectIndex);
- else
- propertyNameCache = QV4::IdentifierHash(engine->handle());
- }
- return propertyNameCache;
-}
-
-QV4::IdentifierHash &QQmlContextData::detachedPropertyNames()
-{
- propertyNames();
- propertyNameCache.detach();
- return propertyNameCache;
+ setPropertyValue(idx, QVariant::fromValue<QObject *>(nullptr));
+ QMetaObject::activate(q_func(), notifyIndex(), idx, nullptr);
}
-QUrl QQmlContextData::url() const
+void QQmlContextPrivate::emitDestruction()
{
- if (typeCompilationUnit)
- return typeCompilationUnit->finalUrl();
- return baseUrl;
+ m_data->emitDestruction();
}
-QString QQmlContextData::urlString() const
+// m_data is owned by the public context. When the public context is reset to nullptr, it will be
+// deref'd. It's OK to pass a half-created publicContext here. We will not dereference it during
+// construction.
+QQmlContextPrivate::QQmlContextPrivate(
+ QQmlContext *publicContext, QQmlContextData *parent, QQmlEngine *engine) :
+ m_data(new QQmlContextData(QQmlContextData::OwnedByPublicContext, publicContext,
+ parent, engine))
{
- if (typeCompilationUnit)
- return typeCompilationUnit->finalUrlString();
- return baseUrlString;
+ Q_ASSERT(publicContext != nullptr);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h
index 7ed70c7619..f12a94ef9d 100644
--- a/src/qml/qml/qqmlcontext.h
+++ b/src/qml/qml/qqmlcontext.h
@@ -100,7 +100,7 @@ private:
friend class QQmlComponentPrivate;
friend class QQmlScriptPrivate;
friend class QQmlContextData;
- QQmlContext(QQmlContextData *);
+ QQmlContext(QQmlContextPrivate &dd, QObject *parent = nullptr);
QQmlContext(QQmlEngine *, bool);
Q_DISABLE_COPY(QQmlContext)
};
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index f93393a11b..e1b2e9d41d 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -51,342 +51,74 @@
// We mean it.
//
-#include "qqmlcontext.h"
+#include <QtCore/qlist.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qpointer.h>
+#include <QtQml/qqmlcontext.h>
+#include <QtQml/qqmllist.h>
-#include "qqmldata_p.h"
-#include "qqmltypenamecache_p.h"
-#include "qqmlnotifier_p.h"
-#include "qqmllist.h"
-
-#include <QtCore/qhash.h>
-#include <QtQml/qjsvalue.h>
-#include <QtCore/qset.h>
-
-#include <private/qobject_p.h>
-#include <private/qflagpointer_p.h>
-#include <private/qqmlguard_p.h>
-
-#include <private/qv4executablecompilationunit_p.h>
-#include <private/qv4identifier_p.h>
+#include <QtCore/private/qobject_p.h>
+#include <QtCore/qtaggedpointer.h>
+#include <QtQml/private/qqmlrefcount_p.h>
QT_BEGIN_NAMESPACE
-class QQmlContext;
-class QQmlExpression;
-class QQmlEngine;
-class QQmlExpression;
-class QQmlExpressionPrivate;
-class QQmlJavaScriptExpression;
class QQmlContextData;
-class QQmlGuardedContextData;
-class QQmlIncubatorPrivate;
class QQmlContextPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QQmlContext)
public:
- QQmlContextPrivate();
-
- QQmlContextData *data;
-
- QList<QVariant> propertyValues;
- int notifyIndex;
-
static QQmlContextPrivate *get(QQmlContext *context) {
return static_cast<QQmlContextPrivate *>(QObjectPrivate::get(context));
}
+
static QQmlContext *get(QQmlContextPrivate *context) {
return static_cast<QQmlContext *>(context->q_func());
}
- // Only used for debugging
- QList<QPointer<QObject> > instances;
-
static int context_count(QQmlListProperty<QObject> *);
static QObject *context_at(QQmlListProperty<QObject> *, int);
void dropDestroyedQObject(const QString &name, QObject *destroyed);
-};
-
-class QQmlComponentAttached;
-
-class Q_QML_PRIVATE_EXPORT QQmlContextData
-{
-public:
- QQmlContextData();
- QQmlContextData(QQmlContext *);
- void emitDestruction();
- void clearContext();
- void clearContextRecursively();
- void invalidate();
-
- inline bool isValid() const {
- return engine && (!isInternal || !contextObject || !QObjectPrivate::get(contextObject)->wasDeleted);
- }
-
- // My parent context and engine
- QQmlContextData *parent = nullptr;
- QQmlEngine *engine;
-
- void setParent(QQmlContextData *, bool stronglyReferencedByParent = false);
- void refreshExpressions();
-
- void addObject(QQmlData *data);
-
- QUrl resolvedUrl(const QUrl &);
-
- // My containing QQmlContext. If isInternal is true this owns publicContext.
- // If internal is false publicContext owns this.
- QQmlContext *asQQmlContext();
- QQmlContextPrivate *asQQmlContextPrivate();
- quint32 refCount = 0;
- quint32 isInternal:1;
- quint32 isJSContext:1;
- quint32 isPragmaLibraryContext:1;
- quint32 unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name
- quint32 hasEmittedDestruction:1;
- quint32 isRootObjectInCreation:1;
- quint32 stronglyReferencedByParent:1;
- quint32 hasExtraObject:1; // used in QQmlDelegateModelItem::dataForObject to find the corresponding QQmlDelegateModelItem of an object
- quint32 dummy:24;
- QQmlContext *publicContext;
- union {
- // The incubator that is constructing this context if any
- QQmlIncubatorPrivate *incubator;
- // a pointer to extra data, currently only used in QQmlDelegateModel
- QObject *extraObject;
- };
+ int notifyIndex() const { return m_notifyIndex; }
+ void setNotifyIndex(int notifyIndex) { m_notifyIndex = notifyIndex; }
- // Compilation unit for contexts that belong to a compiled type.
- QQmlRefPointer<QV4::ExecutableCompilationUnit> typeCompilationUnit;
+ int numPropertyValues() const { return m_propertyValues.count(); }
+ void appendPropertyValue(const QVariant &value) { m_propertyValues.append(value); }
+ void setPropertyValue(int index, const QVariant &value) { m_propertyValues[index] = value; }
+ QVariant propertyValue(int index) const { return m_propertyValues[index]; }
- // object index in CompiledData::Unit to component that created this context
- int componentObjectIndex;
-
- void initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int subComponentIndex);
-
- // flag indicates whether the context owns the cache (after mutation) or not.
- mutable QV4::IdentifierHash propertyNameCache;
- const QV4::IdentifierHash &propertyNames() const;
- QV4::IdentifierHash &detachedPropertyNames();
-
- // Context object
- QObject *contextObject;
-
- // Any script blocks that exist on this context
- QV4::PersistentValue importedScripts; // This is a JS Array
-
- QUrl baseUrl;
- QString baseUrlString;
-
- QUrl url() const;
- QString urlString() const;
-
- // List of imports that apply to this context
- QQmlRefPointer<QQmlTypeNameCache> imports;
-
- // My children
- QQmlContextData *childContexts = nullptr;
-
- // My peers in parent's childContexts list
- QQmlContextData *nextChild;
- QQmlContextData **prevChild;
-
- // Expressions that use this context
- QQmlJavaScriptExpression *expressions;
-
- // Doubly-linked list of objects that are owned by this context
- QQmlData *contextObjects;
-
- // Doubly-linked list of context guards (XXX merge with contextObjects)
- QQmlGuardedContextData *contextGuards = nullptr;
-
- // id guards
- struct ContextGuard : public QQmlGuard<QObject>
+ QList<QPointer<QObject>> instances() const { return m_instances; }
+ void appendInstance(QObject *instance) { m_instances.append(instance); }
+ void cleanInstances()
{
- inline ContextGuard();
- inline ContextGuard &operator=(QObject *obj);
- inline void objectDestroyed(QObject *) override;
-
- inline bool wasSet() const;
-
- QFlagPointer<QQmlContextData> context;
- QQmlNotifier bindings;
- };
- ContextGuard *idValues;
- int idValueCount;
- void setIdProperty(int, QObject *);
-
- // Linked contexts. this owns linkedContext.
- QQmlContextDataRef linkedContext;
-
- // Linked list of uses of the Component attached property in this
- // context
- QQmlComponentAttached *componentAttached;
-
- // Return the outermost id for obj, if any.
- QString findObjectId(const QObject *obj) const;
-
- static QQmlContextData *get(QQmlContext *context) {
- return QQmlContextPrivate::get(context)->data;
+ for (auto it = m_instances.begin(); it != m_instances.end();
+ it->isNull() ? (it = m_instances.erase(it)) : ++it) {}
}
-private:
- friend class QQmlContextDataRef;
- friend class QQmlContext; // needs to do manual refcounting :/
- void refreshExpressionsRecursive(bool isGlobal);
- void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
- ~QQmlContextData();
- void destroy();
-};
-
-
-class QQmlGuardedContextData
-{
-public:
- inline QQmlGuardedContextData() = default;
- inline QQmlGuardedContextData(QQmlContextData *data)
- { setContextData(data); }
- inline ~QQmlGuardedContextData()
- { clear(); }
-
- inline QQmlContextData *contextData() const
- { return m_contextData; }
- inline void setContextData(QQmlContextData *);
-
- inline bool isNull() const { return !m_contextData; }
-
- inline operator QQmlContextData*() const { return m_contextData; }
- inline QQmlContextData* operator->() const { return m_contextData; }
- inline QQmlGuardedContextData &operator=(QQmlContextData *d) {
- setContextData(d); return *this;
- }
+ void emitDestruction();
private:
- QQmlGuardedContextData &operator=(const QQmlGuardedContextData &) = delete;
- QQmlGuardedContextData(const QQmlGuardedContextData &) = delete;
friend class QQmlContextData;
- inline void clear();
-
- QQmlContextData *m_contextData = nullptr;
- QQmlGuardedContextData *m_next = nullptr;
- QQmlGuardedContextData **m_prev = nullptr;
-};
-
-
-void QQmlGuardedContextData::setContextData(QQmlContextData *contextData)
- {
- if (m_contextData == contextData)
- return;
- clear();
-
- if (contextData) {
- m_contextData = contextData;
- m_next = contextData->contextGuards;
- if (m_next) m_next->m_prev = &m_next;
- m_prev = &contextData->contextGuards;
- contextData->contextGuards = this;
- }
-}
-
-void QQmlGuardedContextData::clear()
-{
- if (m_prev) {
- *m_prev = m_next;
- if (m_next) m_next->m_prev = m_prev;
- m_contextData = nullptr;
- m_next = nullptr;
- m_prev = nullptr;
- }
-}
-
-QQmlContextDataRef::QQmlContextDataRef()
- : m_contextData(nullptr)
-{
-}
-
-QQmlContextDataRef::QQmlContextDataRef(const QQmlContextDataRef &other)
- : m_contextData(other.m_contextData)
-{
- if (m_contextData)
- ++m_contextData->refCount;
-}
-
-QQmlContextDataRef::QQmlContextDataRef(QQmlContextData *data)
- : m_contextData(data)
-{
- if (m_contextData)
- ++m_contextData->refCount;
-}
-
-QQmlContextDataRef::~QQmlContextDataRef()
-{
- clear();
-}
-
-void QQmlContextDataRef::setContextData(QQmlContextData *contextData)
-{
- if (m_contextData == contextData)
- return;
- clear();
-
- if (contextData) {
- m_contextData = contextData;
- ++m_contextData->refCount;
- }
-}
-
-QQmlContextData *QQmlContextDataRef::contextData() const
-{
- return m_contextData;
-}
-
-void QQmlContextDataRef::clear()
-{
- if (m_contextData && !--m_contextData->refCount)
- m_contextData->destroy();
- m_contextData = nullptr;
-}
+ QQmlContextPrivate(QQmlContextData *data) : m_data(data) {}
+ QQmlContextPrivate(QQmlContext *publicContext, QQmlContextData *parent,
+ QQmlEngine *engine = nullptr);
-QQmlContextDataRef &
-QQmlContextDataRef::operator=(QQmlContextData *d)
-{
- setContextData(d);
- return *this;
-}
-
-QQmlContextDataRef &
-QQmlContextDataRef::operator=(const QQmlContextDataRef &other)
-{
- setContextData(other.m_contextData);
- return *this;
-}
+ // Intentionally a bare pointer. QQmlContextData knows whether it owns QQmlContext or vice
+ // versa. If QQmlContext is the owner, QQmlContextData keeps an extra ref for its publicContext.
+ // The publicContext ref is released when doing QQmlContextData::setPublicContext(nullptr).
+ QQmlContextData *m_data;
-QQmlContextData::ContextGuard::ContextGuard()
-: context(nullptr)
-{
-}
-
-QQmlContextData::ContextGuard &QQmlContextData::ContextGuard::operator=(QObject *obj)
-{
- QQmlGuard<QObject>::operator=(obj);
- context.setFlag();
- bindings.notify(); // For alias connections
- return *this;
-}
+ QList<QVariant> m_propertyValues;
+ int m_notifyIndex = -1;
-void QQmlContextData::ContextGuard::objectDestroyed(QObject *)
-{
- if (context->contextObject && !QObjectPrivate::get(context->contextObject)->wasDeleted)
- bindings.notify();
-}
-
-bool QQmlContextData::ContextGuard::wasSet() const
-{
- return context.flag();
-}
+ // Only used for debugging
+ QList<QPointer<QObject>> m_instances;
+};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontextdata.cpp b/src/qml/qml/qqmlcontextdata.cpp
new file mode 100644
index 0000000000..33be23b14d
--- /dev/null
+++ b/src/qml/qml/qqmlcontextdata.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlcontextdata_p.h"
+
+#include <QtQml/qqmlengine.h>
+#include <QtQml/private/qqmlcomponentattached_p.h>
+#include <QtQml/private/qqmljavascriptexpression_p.h>
+#include <QtQml/private/qqmlguardedcontextdata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QUrl QQmlContextData::resolvedUrl(const QUrl &src)
+{
+ QUrl resolved;
+ if (src.isRelative() && !src.isEmpty()) {
+ QQmlRefPointer<QQmlContextData> ctxt = this;
+ do {
+ if (ctxt->url().isValid())
+ break;
+ else
+ ctxt = ctxt->parent();
+ } while (ctxt);
+
+ if (ctxt)
+ resolved = ctxt->url().resolved(src);
+ else if (m_engine)
+ resolved = m_engine->baseUrl().resolved(src);
+ } else {
+ resolved = src;
+ }
+
+ if (resolved.isEmpty()) //relative but no ctxt
+ return resolved;
+
+ return m_engine ? m_engine->interceptUrl(resolved, QQmlAbstractUrlInterceptor::UrlString)
+ : resolved;
+}
+
+void QQmlContextData::emitDestruction()
+{
+ if (!m_hasEmittedDestruction) {
+ m_hasEmittedDestruction = true;
+
+ // Emit the destruction signal - must be emitted before invalidate so that the
+ // context is still valid if bindings or resultant expression evaluation requires it
+ if (m_engine) {
+ while (m_componentAttacheds) {
+ QQmlComponentAttached *attached = m_componentAttacheds;
+ attached->removeFromList();
+ emit attached->destruction();
+ }
+
+ for (QQmlContextData *child = m_childContexts; child; child = child->m_nextChild)
+ child->emitDestruction();
+ }
+ }
+}
+
+void QQmlContextData::invalidate()
+{
+ emitDestruction();
+
+ while (m_childContexts) {
+ Q_ASSERT(m_childContexts != this);
+ m_childContexts->invalidate();
+ }
+
+ if (m_prevChild) {
+ *m_prevChild = m_nextChild;
+ if (m_nextChild) m_nextChild->m_prevChild = m_prevChild;
+ m_nextChild = nullptr;
+ m_prevChild = nullptr;
+ }
+
+ m_importedScripts.clear();
+
+ m_engine = nullptr;
+ clearParent();
+}
+
+void QQmlContextData::clearContextRecursively()
+{
+ clearContext();
+
+ for (auto ctxIt = m_childContexts; ctxIt; ctxIt = ctxIt->m_nextChild)
+ ctxIt->clearContextRecursively();
+}
+
+void QQmlContextData::clearContext()
+{
+ emitDestruction();
+
+ QQmlJavaScriptExpression *expression = m_expressions;
+ while (expression) {
+ QQmlJavaScriptExpression *nextExpression = expression->m_nextExpression;
+
+ expression->m_prevExpression = nullptr;
+ expression->m_nextExpression = nullptr;
+
+ expression->setContext(nullptr);
+
+ expression = nextExpression;
+ }
+ m_expressions = nullptr;
+}
+
+QQmlContextData::~QQmlContextData()
+{
+ Q_ASSERT(refCount() == 0);
+ m_linkedContext = nullptr;
+
+ // avoid recursion
+ addref();
+ if (m_engine)
+ invalidate();
+
+ Q_ASSERT(refCount() == 1);
+ clearContext();
+ Q_ASSERT(refCount() == 1);
+
+ while (m_ownedObjects) {
+ QQmlData *co = m_ownedObjects;
+ m_ownedObjects = m_ownedObjects->nextContextObject;
+
+ if (co->context == this)
+ co->context = nullptr;
+ co->outerContext = nullptr;
+ co->nextContextObject = nullptr;
+ co->prevContextObject = nullptr;
+ }
+ Q_ASSERT(refCount() == 1);
+
+ QQmlGuardedContextData *contextGuard = m_contextGuards;
+ while (contextGuard) {
+ QQmlGuardedContextData *next = contextGuard->next();
+ next->reset();
+ contextGuard = next;
+ }
+ m_contextGuards = nullptr;
+ Q_ASSERT(refCount() == 1);
+
+ delete [] m_idValues;
+ m_idValues = nullptr;
+
+ Q_ASSERT(refCount() == 1);
+ if (m_publicContext)
+ delete m_publicContext;
+
+ Q_ASSERT(refCount() == 1);
+}
+
+void QQmlContextData::refreshExpressionsRecursive(QQmlJavaScriptExpression *expression)
+{
+ QQmlJavaScriptExpression::DeleteWatcher w(expression);
+
+ if (expression->m_nextExpression)
+ refreshExpressionsRecursive(expression->m_nextExpression);
+
+ if (!w.wasDeleted())
+ expression->refresh();
+}
+
+void QQmlContextData::refreshExpressionsRecursive(bool isGlobal)
+{
+ // For efficiency, we try and minimize the number of guards we have to create
+ if (hasExpressionsToRun(isGlobal) && (m_nextChild || m_childContexts)) {
+ QQmlGuardedContextData guard(this);
+
+ if (m_childContexts)
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+
+ if (guard.isNull()) return;
+
+ if (m_nextChild)
+ m_nextChild->refreshExpressionsRecursive(isGlobal);
+
+ if (guard.isNull()) return;
+
+ if (hasExpressionsToRun(isGlobal))
+ refreshExpressionsRecursive(m_expressions);
+
+ } else if (hasExpressionsToRun(isGlobal)) {
+ refreshExpressionsRecursive(m_expressions);
+ } else if (m_nextChild && m_childContexts) {
+ QQmlGuardedContextData guard(this);
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+ if (!guard.isNull() && m_nextChild)
+ m_nextChild->refreshExpressionsRecursive(isGlobal);
+ } else if (m_nextChild) {
+ m_nextChild->refreshExpressionsRecursive(isGlobal);
+ } else if (m_childContexts) {
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+ }
+}
+
+// Refreshes all expressions that could possibly depend on this context. Refreshing flushes all
+// context-tree dependent caches in the expressions, and should occur every time the context tree
+// *structure* (not values) changes.
+void QQmlContextData::refreshExpressions()
+{
+ bool isGlobal = (m_parent == nullptr);
+
+ // For efficiency, we try and minimize the number of guards we have to create
+ if (hasExpressionsToRun(isGlobal) && m_childContexts) {
+ QQmlGuardedContextData guard(this);
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+ if (!guard.isNull() && hasExpressionsToRun(isGlobal))
+ refreshExpressionsRecursive(m_expressions);
+ } else if (hasExpressionsToRun(isGlobal)) {
+ refreshExpressionsRecursive(m_expressions);
+ } else if (m_childContexts) {
+ m_childContexts->refreshExpressionsRecursive(isGlobal);
+ }
+}
+
+void QQmlContextData::addOwnedObject(QQmlData *data)
+{
+ if (data->outerContext) {
+ if (data->nextContextObject)
+ data->nextContextObject->prevContextObject = data->prevContextObject;
+ if (data->prevContextObject)
+ *data->prevContextObject = data->nextContextObject;
+ else if (data->outerContext->m_ownedObjects == data)
+ data->outerContext->m_ownedObjects = data->nextContextObject;
+ }
+
+ data->outerContext = this;
+
+ data->nextContextObject = m_ownedObjects;
+ if (data->nextContextObject)
+ data->nextContextObject->prevContextObject = &data->nextContextObject;
+ data->prevContextObject = &m_ownedObjects;
+ m_ownedObjects = data;
+}
+
+void QQmlContextData::setIdValue(int idx, QObject *obj)
+{
+ m_idValues[idx] = obj;
+ m_idValues[idx].setContext(this);
+}
+
+QString QQmlContextData::findObjectId(const QObject *obj) const
+{
+ const QV4::IdentifierHash &properties = propertyNames();
+ if (m_propertyNameCache.isEmpty())
+ return QString();
+
+ for (int ii = 0; ii < m_idValueCount; ii++) {
+ if (m_idValues[ii] == obj)
+ return properties.findId(ii);
+ }
+
+ if (m_publicContext) {
+ QQmlContextPrivate *p = QQmlContextPrivate::get(m_publicContext);
+ for (int ii = 0; ii < p->numPropertyValues(); ++ii)
+ if (p->propertyValue(ii) == QVariant::fromValue(const_cast<QObject *>(obj)))
+ return properties.findId(ii);
+ }
+
+ if (m_linkedContext)
+ return m_linkedContext->findObjectId(obj);
+ return QString();
+}
+
+QQmlContext *QQmlContextData::asQQmlContext()
+{
+ if (!m_publicContext)
+ m_publicContext = new QQmlContext(*new QQmlContextPrivate(this));
+ return m_publicContext;
+}
+
+QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
+{
+ return QQmlContextPrivate::get(asQQmlContext());
+}
+
+void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int subComponentIndex)
+{
+ m_typeCompilationUnit = unit;
+ m_componentObjectIndex = subComponentIndex == -1 ? /*root object*/0 : subComponentIndex;
+ Q_ASSERT(!m_idValues);
+ m_idValueCount = m_typeCompilationUnit->objectAt(m_componentObjectIndex)
+ ->nNamedObjectsInComponent;
+ m_idValues = new ContextGuard[m_idValueCount];
+}
+
+void QQmlContextData::addComponentAttached(QQmlComponentAttached *attached)
+{
+ attached->insertIntoList(&m_componentAttacheds);
+}
+
+void QQmlContextData::addExpression(QQmlJavaScriptExpression *expression)
+{
+ expression->insertIntoList(&m_expressions);
+}
+
+QV4::IdentifierHash QQmlContextData::propertyNames() const
+{
+ if (m_propertyNameCache.isEmpty()) {
+ if (m_typeCompilationUnit)
+ m_propertyNameCache = m_typeCompilationUnit->namedObjectsPerComponent(m_componentObjectIndex);
+ else
+ m_propertyNameCache = QV4::IdentifierHash(m_engine->handle());
+ }
+ return m_propertyNameCache;
+}
+
+QV4::IdentifierHash *QQmlContextData::detachedPropertyNames()
+{
+ propertyNames();
+ m_propertyNameCache.detach();
+ return &m_propertyNameCache;
+}
+
+QUrl QQmlContextData::url() const
+{
+ if (m_typeCompilationUnit)
+ return m_typeCompilationUnit->finalUrl();
+ return m_baseUrl;
+}
+
+QString QQmlContextData::urlString() const
+{
+ if (m_typeCompilationUnit)
+ return m_typeCompilationUnit->finalUrlString();
+ return m_baseUrlString;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlcontextdata_p.h b/src/qml/qml/qqmlcontextdata_p.h
new file mode 100644
index 0000000000..ccefd3a05b
--- /dev/null
+++ b/src/qml/qml/qqmlcontextdata_p.h
@@ -0,0 +1,432 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLCONTEXTDATA_P_H
+#define QQMLCONTEXTDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/private/qqmlglobal_p.h>
+#include <QtQml/private/qqmlcontext_p.h>
+#include <QtQml/private/qqmlguard_p.h>
+#include <QtQml/private/qqmltypenamecache_p.h>
+#include <QtQml/private/qv4identifier_p.h>
+#include <QtQml/private/qv4executablecompilationunit_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlComponentAttached;
+class QQmlGuardedContextData;
+class QQmlJavaScriptExpression;
+class QQmlIncubatorPrivate;
+
+class Q_QML_PRIVATE_EXPORT QQmlContextData
+{
+public:
+ static QQmlRefPointer<QQmlContextData> createRefCounted(
+ const QQmlRefPointer<QQmlContextData> &parent)
+ {
+ return QQmlRefPointer<QQmlContextData>(new QQmlContextData(RefCounted, nullptr, parent),
+ QQmlRefPointer<QQmlContextData>::Adopt);
+ }
+
+ // Owned by the parent. When the parent is reset to nullptr, it will be deref'd.
+ static QQmlRefPointer<QQmlContextData> createChild(
+ const QQmlRefPointer<QQmlContextData> &parent)
+ {
+ Q_ASSERT(!parent.isNull());
+ return QQmlRefPointer<QQmlContextData>(new QQmlContextData(OwnedByParent, nullptr, parent));
+ }
+
+ void addref() const { ++m_refCount; }
+ void release() const { if (--m_refCount == 0) delete this; }
+ int count() const { return m_refCount; }
+ int refCount() const { return m_refCount; }
+
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> typeCompilationUnit() const
+ {
+ return m_typeCompilationUnit;
+ }
+ void initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit,
+ int subComponentIndex);
+
+ static QQmlRefPointer<QQmlContextData> get(QQmlContext *context) {
+ return QQmlContextPrivate::get(context)->m_data;
+ }
+
+ void emitDestruction();
+ void clearContext();
+ void clearContextRecursively();
+ void invalidate();
+
+ bool isValid() const
+ {
+ return m_engine && (!m_isInternal || !m_contextObject
+ || !QObjectPrivate::get(m_contextObject)->wasDeleted);
+ }
+
+ bool isInternal() const { return m_isInternal; }
+ void setInternal(bool isInternal) { m_isInternal = isInternal; }
+
+ bool isJSContext() const { return m_isJSContext; }
+ void setJSContext(bool isJSContext) { m_isJSContext = isJSContext; }
+
+ bool isPragmaLibraryContext() const { return m_isPragmaLibraryContext; }
+ void setPragmaLibraryContext(bool library) { m_isPragmaLibraryContext = library; }
+
+ QQmlRefPointer<QQmlContextData> parent() const { return m_parent; }
+ void clearParent()
+ {
+ if (!m_parent)
+ return;
+
+ m_parent = nullptr;
+ if (m_ownedByParent) {
+ m_ownedByParent = false;
+ release();
+ }
+ }
+
+ void refreshExpressions();
+
+ void addOwnedObject(QQmlData *ownedObject);
+ QQmlData *ownedObjects() const { return m_ownedObjects; }
+ void setOwnedObjects(QQmlData *ownedObjects) { m_ownedObjects = ownedObjects; }
+
+ QUrl resolvedUrl(const QUrl &);
+
+ // My containing QQmlContext. If isInternal is true this owns publicContext.
+ // If internal is false publicContext owns this.
+ QQmlContext *asQQmlContext();
+ QQmlContextPrivate *asQQmlContextPrivate();
+
+ QObject *contextObject() const { return m_contextObject; }
+ void setContextObject(QObject *contextObject) { m_contextObject = contextObject; }
+
+ QQmlEngine *engine() const { return m_engine; }
+ void setEngine(QQmlEngine *engine) { m_engine = engine; }
+
+ QQmlContext *publicContext() const { return m_publicContext; }
+ void clearPublicContext()
+ {
+ if (!m_publicContext)
+ return;
+
+ m_publicContext = nullptr;
+ if (m_ownedByPublicContext) {
+ m_ownedByPublicContext = false;
+ release();
+ }
+ }
+
+ QV4::IdentifierHash propertyNames() const;
+ QV4::IdentifierHash *detachedPropertyNames();
+
+ void setExpressions(QQmlJavaScriptExpression *expressions) { m_expressions = expressions; }
+ QQmlJavaScriptExpression *takeExpressions()
+ {
+ QQmlJavaScriptExpression *expressions = m_expressions;
+ m_expressions = nullptr;
+ return expressions;
+ }
+
+ void setChildContexts(const QQmlRefPointer<QQmlContextData> &childContexts)
+ {
+ m_childContexts = childContexts.data();
+ }
+ QQmlRefPointer<QQmlContextData> childContexts() const { return m_childContexts; }
+ QQmlRefPointer<QQmlContextData> takeChildContexts()
+ {
+ QQmlRefPointer<QQmlContextData> childContexts = m_childContexts;
+ m_childContexts = nullptr;
+ return childContexts;
+ }
+ QQmlRefPointer<QQmlContextData> nextChild() const { return m_nextChild; }
+
+ int numIdValues() const { return m_idValueCount; }
+ void setIdValue(int index, QObject *idValue);
+ bool isIdValueSet(int index) const { return m_idValues[index].wasSet(); }
+ QQmlNotifier *idValueBindings(int index) const { return m_idValues[index].bindings(); }
+ QObject *idValue(int index) const { return m_idValues[index].data(); }
+
+ // Return the outermost id for obj, if any.
+ QString findObjectId(const QObject *obj) const;
+
+ // url() and urlString() prefer the CU's URL over explicitly set baseUrls. They
+ // don't search the context hierarchy.
+ // baseUrl() and baseUrlString() search the context hierarchy and prefer explicit
+ // base URLs over CU Urls.
+
+ QUrl url() const;
+ QString urlString() const;
+
+ void setBaseUrlString(const QString &baseUrlString) { m_baseUrlString = baseUrlString; }
+ QString baseUrlString() const
+ {
+ for (const QQmlContextData *data = this; data; data = data->m_parent) {
+ if (!data->m_baseUrlString.isEmpty())
+ return data->m_baseUrlString;
+ if (data->m_typeCompilationUnit)
+ return data->m_typeCompilationUnit->finalUrlString();
+ }
+ return QString();
+ }
+
+ void setBaseUrl(const QUrl &baseUrl) { m_baseUrl = baseUrl; }
+ QUrl baseUrl() const
+ {
+ for (const QQmlContextData *data = this; data; data = data->m_parent) {
+ if (!data->m_baseUrl.isEmpty())
+ return data->m_baseUrl;
+ if (data->m_typeCompilationUnit)
+ return data->m_typeCompilationUnit->finalUrl();
+ }
+ return QUrl();
+ }
+
+ QQmlRefPointer<QQmlTypeNameCache> imports() const { return m_imports; }
+ void setImports(const QQmlRefPointer<QQmlTypeNameCache> &imports) { m_imports = imports; }
+
+ QQmlIncubatorPrivate *incubator() const { return m_hasExtraObject ? nullptr : m_incubator; }
+ void setIncubator(QQmlIncubatorPrivate *incubator)
+ {
+ Q_ASSERT(!m_hasExtraObject || m_extraObject == nullptr);
+ m_hasExtraObject = false;
+ m_incubator = incubator;
+ }
+
+ QObject *extraObject() const { return m_hasExtraObject ? m_extraObject : nullptr; }
+ void setExtraObject(QObject *extraObject)
+ {
+ Q_ASSERT(m_hasExtraObject || m_incubator == nullptr);
+ m_hasExtraObject = true;
+ m_extraObject = extraObject;
+ }
+
+ bool isRootObjectInCreation() const { return m_isRootObjectInCreation; }
+ void setRootObjectInCreation(bool rootInCreation) { m_isRootObjectInCreation = rootInCreation; }
+
+ QV4::PersistentValue importedScripts() const { return m_importedScripts; }
+ void setImportedScripts(const QV4::PersistentValue &scripts) { m_importedScripts = scripts; }
+
+ QQmlRefPointer<QQmlContextData> linkedContext() const { return m_linkedContext; }
+ void setLinkedContext(const QQmlRefPointer<QQmlContextData> &context) { m_linkedContext = context; }
+
+ bool hasUnresolvedNames() const { return m_unresolvedNames; }
+ void setUnresolvedNames(bool hasUnresolvedNames) { m_unresolvedNames = hasUnresolvedNames; }
+
+ QQmlComponentAttached *componentAttacheds() const { return m_componentAttacheds; }
+ void addComponentAttached(QQmlComponentAttached *attached);
+
+ void addExpression(QQmlJavaScriptExpression *expression);
+
+private:
+ friend class QQmlGuardedContextData;
+ friend class QQmlContextPrivate;
+
+ enum Ownership {
+ RefCounted,
+ OwnedByParent,
+ OwnedByPublicContext
+ };
+
+ // id guards
+ struct ContextGuard : public QQmlGuard<QObject>
+ {
+ enum Tag {
+ NoTag,
+ ObjectWasSet
+ };
+
+ inline ContextGuard() : m_context(nullptr) {}
+ inline ContextGuard &operator=(QObject *obj);
+ inline void objectDestroyed(QObject *) override;
+
+ inline bool wasSet() const;
+
+ QQmlNotifier *bindings() { return &m_bindings; }
+ void setContext(const QQmlRefPointer<QQmlContextData> &context)
+ {
+ m_context = context.data();
+ }
+
+ private:
+ // Not refcounted, as it always belongs to the QQmlContextData.
+ QTaggedPointer<QQmlContextData, Tag> m_context;
+ QQmlNotifier m_bindings;
+ };
+
+ // It's OK to pass a half-created publicContext here. We will not dereference it during
+ // construction.
+ QQmlContextData(
+ Ownership ownership, QQmlContext *publicContext,
+ const QQmlRefPointer<QQmlContextData> &parent, QQmlEngine *engine = nullptr)
+ : m_parent(parent.data()),
+ m_engine(engine ? engine : (parent.isNull() ? nullptr : parent->engine())),
+ m_isInternal(false), m_isJSContext(false), m_isPragmaLibraryContext(false),
+ m_unresolvedNames(false), m_hasEmittedDestruction(false), m_isRootObjectInCreation(false),
+ m_ownedByParent(ownership == OwnedByParent),
+ m_ownedByPublicContext(ownership == OwnedByPublicContext), m_hasExtraObject(false),
+ m_dummy(0), m_publicContext(publicContext), m_incubator(nullptr)
+ {
+ Q_ASSERT(!m_ownedByParent || !m_ownedByPublicContext);
+ if (!m_parent)
+ return;
+
+ m_nextChild = m_parent->m_childContexts;
+ if (m_nextChild)
+ m_nextChild->m_prevChild = &m_nextChild;
+ m_prevChild = &m_parent->m_childContexts;
+ m_parent->m_childContexts = this;
+ }
+
+ ~QQmlContextData();
+
+ bool hasExpressionsToRun(bool isGlobalRefresh) const
+ {
+ return m_expressions && (!isGlobalRefresh || m_unresolvedNames);
+ }
+
+ void refreshExpressionsRecursive(bool isGlobal);
+ void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
+
+ // My parent context and engine
+ QQmlContextData *m_parent = nullptr;
+ QQmlEngine *m_engine = nullptr;
+
+ mutable quint32 m_refCount = 1;
+ quint32 m_isInternal:1;
+ quint32 m_isJSContext:1;
+ quint32 m_isPragmaLibraryContext:1;
+ quint32 m_unresolvedNames:1; // True if expressions in this context failed to resolve a toplevel name
+ quint32 m_hasEmittedDestruction:1;
+ quint32 m_isRootObjectInCreation:1;
+ quint32 m_ownedByParent:1;
+ quint32 m_ownedByPublicContext:1;
+ quint32 m_hasExtraObject:1; // used in QQmlDelegateModelItem::dataForObject to find the corresponding QQmlDelegateModelItem of an object
+ quint32 m_dummy:23;
+ QQmlContext *m_publicContext = nullptr;
+
+ union {
+ // The incubator that is constructing this context if any
+ QQmlIncubatorPrivate *m_incubator;
+ // a pointer to extra data, currently only used in QQmlDelegateModel
+ QObject *m_extraObject;
+ };
+
+ // Compilation unit for contexts that belong to a compiled type.
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> m_typeCompilationUnit;
+
+ // object index in CompiledData::Unit to component that created this context
+ int m_componentObjectIndex = -1;
+
+ // flag indicates whether the context owns the cache (after mutation) or not.
+ mutable QV4::IdentifierHash m_propertyNameCache;
+
+ // Context object
+ QObject *m_contextObject = nullptr;
+
+ // Any script blocks that exist on this context
+ QV4::PersistentValue m_importedScripts; // This is a JS Array
+
+ QUrl m_baseUrl;
+ QString m_baseUrlString;
+
+ // List of imports that apply to this context
+ QQmlRefPointer<QQmlTypeNameCache> m_imports;
+
+ // My children, not refcounted as that would create cyclic references
+ QQmlContextData *m_childContexts = nullptr;
+
+ // My peers in parent's childContexts list; not refcounted
+ QQmlContextData *m_nextChild = nullptr;
+ QQmlContextData **m_prevChild = nullptr;
+
+ // Expressions that use this context
+ QQmlJavaScriptExpression *m_expressions = nullptr;
+
+ // Doubly-linked list of objects that are owned by this context
+ QQmlData *m_ownedObjects = nullptr;
+
+ // Doubly-linked list of context guards (XXX merge with contextObjects)
+ QQmlGuardedContextData *m_contextGuards = nullptr;
+
+ ContextGuard *m_idValues = nullptr;
+ int m_idValueCount = 0;
+
+ // Linked contexts. this owns linkedContext.
+ QQmlRefPointer<QQmlContextData> m_linkedContext;
+
+ // Linked list of uses of the Component attached property in this context
+ QQmlComponentAttached *m_componentAttacheds = nullptr;
+};
+
+QQmlContextData::ContextGuard &QQmlContextData::ContextGuard::operator=(QObject *obj)
+{
+ QQmlGuard<QObject>::operator=(obj);
+ m_context.setTag(ObjectWasSet);
+ m_bindings.notify(); // For alias connections
+ return *this;
+}
+
+void QQmlContextData::ContextGuard::objectDestroyed(QObject *)
+{
+ if (QObject *contextObject = m_context->contextObject()) {
+ if (!QObjectPrivate::get(contextObject)->wasDeleted)
+ m_bindings.notify();
+ }
+}
+
+bool QQmlContextData::ContextGuard::wasSet() const
+{
+ return m_context.tag() == ObjectWasSet;
+}
+
+QT_END_NAMESPACE
+
+#endif // QQMLCONTEXTDATA_P_H
diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp
index 5e6e1187e2..b0df4f26dc 100644
--- a/src/qml/qml/qqmlcustomparser.cpp
+++ b/src/qml/qml/qqmlcustomparser.cpp
@@ -109,12 +109,6 @@ void QQmlCustomParser::error(const QV4::CompiledData::Location &location, const
exceptions << error;
}
-struct StaticQtMetaObject : public QObject
-{
- static const QMetaObject *get()
- { return &staticQtMetaObject; }
-};
-
/*!
If \a script is a simple enumeration expression (eg. Text.AlignLeft),
returns the integer equivalent (eg. 1), and sets \a ok to true.
@@ -150,12 +144,12 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
if (imports.isT1()) {
QQmlImportNamespace *ns = nullptr;
- if (!imports.asT1()->resolveType(scope, &type, nullptr, nullptr, &ns))
+ if (!imports.asT1()->resolveType(scope, &type, nullptr, &ns))
return -1;
if (!type.isValid() && ns != nullptr) {
dot = nextDot(dot);
if (dot == -1 || !imports.asT1()->resolveType(QString::fromUtf8(script.left(dot)),
- &type, nullptr, nullptr, nullptr)) {
+ &type, nullptr, nullptr)) {
return -1;
}
}
@@ -184,7 +178,7 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const
}
QByteArray enumValue = script.mid(dot + 1);
- const QMetaObject *mo = StaticQtMetaObject::get();
+ const QMetaObject *mo = &Qt::staticMetaObject;
int i = mo->enumeratorCount();
while (i--) {
int v = mo->enumerator(i).keyToValue(enumValue.constData(), ok);
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index ee31cb38d9..f850746d92 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -74,6 +74,7 @@ class QQmlContextData;
class QQmlNotifier;
class QQmlDataExtended;
class QQmlNotifierEndpoint;
+class QQmlPropertyObserver;
namespace QV4 {
class ExecutableCompilationUnit;
@@ -82,34 +83,6 @@ struct Binding;
}
}
-// This is declared here because QQmlData below needs it and this file
-// in turn is included from qqmlcontext_p.h.
-class QQmlContextData;
-class Q_QML_PRIVATE_EXPORT QQmlContextDataRef
-{
-public:
- inline QQmlContextDataRef();
- inline QQmlContextDataRef(QQmlContextData *);
- inline QQmlContextDataRef(const QQmlContextDataRef &);
- inline ~QQmlContextDataRef();
-
- inline QQmlContextData *contextData() const;
- inline void setContextData(QQmlContextData *);
-
- inline bool isNull() const { return !m_contextData; }
-
- inline operator QQmlContextData*() const { return m_contextData; }
- inline QQmlContextData* operator->() const { return m_contextData; }
- inline QQmlContextDataRef &operator=(QQmlContextData *d);
- inline QQmlContextDataRef &operator=(const QQmlContextDataRef &other);
-
-private:
-
- inline void clear();
-
- QQmlContextData *m_contextData;
-};
-
// This class is structured in such a way, that simply zero'ing it is the
// default state for elemental object allocations. This is crucial in the
// workings of the QQmlInstruction::CreateSimpleObject instruction.
@@ -195,14 +168,15 @@ public:
bool signalHasEndpoint(int index) const;
void disconnectNotifiers();
- // The context that created the C++ object
+ // The context that created the C++ object; not refcounted to prevent cycles
QQmlContextData *context = nullptr;
- // The outermost context in which this object lives
+ // The outermost context in which this object lives; not refcounted to prevent cycles
QQmlContextData *outerContext = nullptr;
- QQmlContextDataRef ownContext;
+ QQmlRefPointer<QQmlContextData> ownContext;
QQmlAbstractBinding *bindings;
QQmlBoundSignal *signalHandlers;
+ std::vector<QQmlPropertyObserver> propertyObservers;
// Linked list for QQmlContext::contextObjects
QQmlData *nextContextObject;
@@ -226,14 +200,19 @@ public:
~DeferredData();
unsigned int deferredIdx;
QMultiHash<int, const QV4::CompiledData::Binding *> bindings;
- QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;//Not always the same as the other compilation unit
- QQmlContextData *context;//Could be either context or outerContext
+
+ // Not always the same as the other compilation unit
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
+
+ // Could be either context or outerContext
+ QQmlRefPointer<QQmlContextData> context;
Q_DISABLE_COPY(DeferredData);
};
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
QVector<DeferredData *> deferredData;
- void deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &, QQmlContextData *);
+ void deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &,
+ const QQmlRefPointer<QQmlContextData> &);
void releaseDeferredData();
QV4::WeakValue jsWrapper;
diff --git a/src/qml/qml/qqmldatablob.cpp b/src/qml/qml/qqmldatablob.cpp
index b22e46b69c..fb8bd63bf1 100644
--- a/src/qml/qml/qqmldatablob.cpp
+++ b/src/qml/qml/qqmldatablob.cpp
@@ -105,9 +105,8 @@ QQmlDataBlob::QQmlDataBlob(const QUrl &url, Type type, QQmlTypeLoader *manager)
m_inCallback(false), m_isDone(false)
{
//Set here because we need to get the engine from the manager
- if (m_typeLoader->engine() && m_typeLoader->engine()->urlInterceptor())
- m_url = m_typeLoader->engine()->urlInterceptor()->intercept(m_url,
- (QQmlAbstractUrlInterceptor::DataType)m_type);
+ if (const QQmlEngine *qmlEngine = m_typeLoader->engine())
+ m_url = qmlEngine->interceptUrl(m_url, (QQmlAbstractUrlInterceptor::DataType)m_type);
}
/*! \internal */
@@ -290,7 +289,18 @@ void QQmlDataBlob::setError(const QList<QQmlError> &errors)
Q_ASSERT(status() != Error);
Q_ASSERT(m_errors.isEmpty());
- m_errors = errors; // Must be set before the m_data fence
+ // m_errors must be set before the m_data fence
+ m_errors.reserve(errors.count());
+ for (const QQmlError &error : errors) {
+ if (error.url().isEmpty()) {
+ QQmlError mutableError = error;
+ mutableError.setUrl(url());
+ m_errors.append(mutableError);
+ } else {
+ m_errors.append(error);
+ }
+ }
+
m_data.setStatus(Error);
if (dumpErrors()) {
@@ -314,18 +324,6 @@ void QQmlDataBlob::setError(const QQmlJS::DiagnosticMessage &error)
setError(e);
}
-void QQmlDataBlob::setError(const QVector<QQmlError> &errors)
-{
- QList<QQmlError> finalErrors;
- finalErrors.reserve(errors.count());
- for (const auto &error : errors) {
- QQmlError e = error;
- e.setUrl(url());
- finalErrors << e;
- }
- setError(finalErrors);
-}
-
void QQmlDataBlob::setError(const QString &description)
{
QQmlError e;
diff --git a/src/qml/qml/qqmldatablob_p.h b/src/qml/qml/qqmldatablob_p.h
index cc066d29a1..17db8f2dfe 100644
--- a/src/qml/qml/qqmldatablob_p.h
+++ b/src/qml/qml/qqmldatablob_p.h
@@ -132,7 +132,6 @@ protected:
void setError(const QQmlError &);
void setError(const QList<QQmlError> &errors);
void setError(const QQmlJS::DiagnosticMessage &error);
- void setError(const QVector<QQmlError> &errors);
void setError(const QString &description);
void addDependency(QQmlDataBlob *);
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 5823ff8963..97cbfc1342 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -62,7 +62,6 @@
#include <private/qqmlboundsignal_p.h>
#include <private/qqmljsdiagnosticmessage_p.h>
#include <QtCore/qstandardpaths.h>
-#include <QtCore/qsettings.h>
#include <QtCore/qmetaobject.h>
#include <QDebug>
#include <QtCore/qcoreapplication.h>
@@ -75,7 +74,6 @@
#if QT_CONFIG(qml_network)
#include "qqmlnetworkaccessmanagerfactory.h"
#include <QNetworkAccessManager>
-#include <QtNetwork/qnetworkconfigmanager.h>
#endif
#include <private/qobject_p.h>
@@ -113,13 +111,13 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
QQmlPrivate::RegisterType type = {
0,
- 0,
- 0,
+ QMetaType(),
+ QMetaType(),
0,
nullptr,
reason,
- uri, versionMajor, versionMinor, qmlName, &staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &staticMetaObject,
QQmlAttachedPropertiesFunc(),
nullptr,
@@ -131,7 +129,7 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
nullptr, nullptr,
nullptr,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
@@ -196,35 +194,6 @@ int qmlRegisterUncreatableMetaObject(const QMetaObject &staticMetaObject,
bool QQmlEnginePrivate::qml_debugging_enabled = false;
bool QQmlEnginePrivate::s_designerMode = false;
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-void QQmlEnginePrivate::registerQuickTypes()
-{
- // Don't add anything here. These are only for backwards compatibility.
- // Also, don't use qmlRegisterTypesAndRevisions as that will auto-add future revisions.
-
- const char uri[] = "QtQuick";
-
- qmlRegisterType<QQmlComponent>(uri, 2, 0, "Component");
- qmlRegisterType<QObject>(uri, 2, 0, "QtObject");
- qmlRegisterType<QQmlBind>(uri, 2, 0, "Binding");
- qmlRegisterType<QQmlBind, 8>(uri, 2, 8, "Binding");
- qmlRegisterCustomType<QQmlConnections>(uri, 2, 0, "Connections", new QQmlConnectionsParser);
-
- // Connections revision 3 was added in QtQml 2.3, but only in QtQuick 2.7.
- qmlRegisterCustomType<QQmlConnections, 3>(uri, 2, 7, "Connections", new QQmlConnectionsParser);
-
-#if QT_CONFIG(qml_animation)
- qmlRegisterType<QQmlTimer>(uri, 2, 0,"Timer");
-#endif
- qmlRegisterType<QQmlLoggingCategory>(uri, 2, 8, "LoggingCategory");
- qmlRegisterType<QQmlLoggingCategory, 12>(uri, 2, 12, "LoggingCategory");
-#if QT_CONFIG(qml_locale)
- // Locale was added in QtQuick 2.0 and in QtQml 2.2
- qmlRegisterUncreatableType<QQmlLocale>(uri, 2, 0, "Locale", QQmlEngine::tr("Locale cannot be instantiated. Use Qt.locale()"));
-#endif
-}
-#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-
bool QQmlEnginePrivate::designerMode()
{
return s_designerMode;
@@ -656,7 +625,7 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
#if QT_CONFIG(qml_network)
networkAccessManager(nullptr), networkAccessManagerFactory(nullptr),
#endif
- urlInterceptor(nullptr), scarceResourcesRefCount(0), importDatabase(e), typeLoader(e),
+ scarceResourcesRefCount(0), importDatabase(e), typeLoader(e),
uniqueId(1), incubatorCount(0), incubationController(nullptr)
{
}
@@ -695,20 +664,21 @@ void QQmlPrivate::qdeclarativeelement_destructor(QObject *o)
{
if (QQmlData *d = QQmlData::get(o)) {
if (d->ownContext) {
- for (QQmlContextData *lc = d->ownContext->linkedContext; lc; lc = lc->linkedContext) {
+ for (QQmlRefPointer<QQmlContextData> lc = d->ownContext->linkedContext().data(); lc;
+ lc = lc->linkedContext()) {
lc->invalidate();
- if (lc->contextObject == o)
- lc->contextObject = nullptr;
+ if (lc->contextObject() == o)
+ lc->setContextObject(nullptr);
}
d->ownContext->invalidate();
- if (d->ownContext->contextObject == o)
- d->ownContext->contextObject = nullptr;
+ if (d->ownContext->contextObject() == o)
+ d->ownContext->setContextObject(nullptr);
d->ownContext = nullptr;
d->context = nullptr;
}
- if (d->outerContext && d->outerContext->contextObject == o)
- d->outerContext->contextObject = nullptr;
+ if (d->outerContext && d->outerContext->contextObject() == o)
+ d->outerContext->setContextObject(nullptr);
// Mark this object as in the process of deletion to
// prevent it resolving in bindings
@@ -879,10 +849,10 @@ void QQmlData::setQueuedForDeletion(QObject *object)
if (object) {
if (QQmlData *ddata = QQmlData::get(object)) {
if (ddata->ownContext) {
- Q_ASSERT(ddata->ownContext == ddata->context);
+ Q_ASSERT(ddata->ownContext.data() == ddata->context);
ddata->context->emitDestruction();
- if (ddata->ownContext->contextObject == object)
- ddata->ownContext->contextObject = nullptr;
+ if (ddata->ownContext->contextObject() == object)
+ ddata->ownContext->setContextObject(nullptr);
ddata->ownContext = nullptr;
ddata->context = nullptr;
}
@@ -1012,7 +982,7 @@ QQmlEngine::~QQmlEngine()
// Emit onDestruction signals for the root context before
// we destroy the contexts, engine, Singleton Types etc. that
// may be required to handle the destruction signal.
- QQmlContextData::get(rootContext())->emitDestruction();
+ QQmlContextPrivate::get(rootContext())->emitDestruction();
// clean up all singleton type instances which we own.
// we do this here and not in the private dtor since otherwise a crash can
@@ -1107,32 +1077,62 @@ QQmlContext *QQmlEngine::rootContext() const
return d->rootContext;
}
+#if QT_DEPRECATED_SINCE(6, 0)
/*!
\internal
+ \deprecated
This API is private for 5.1
- Sets the \a urlInterceptor to be used when resolving URLs in QML.
+ Returns the last QQmlAbstractUrlInterceptor. It must not be modified outside
+ the GUI thread.
+*/
+QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor() const
+{
+ Q_D(const QQmlEngine);
+ return d->urlInterceptors.last();
+}
+#endif
+
+/*!
+ Adds a \a urlInterceptor to be used when resolving URLs in QML.
This also applies to URLs used for loading script files and QML types.
- This should not be modifed while the engine is loading files, or URL
- selection may be inconsistent.
+ The URL interceptors should not be modifed while the engine is loading files,
+ or URL selection may be inconsistent. Multiple URL interceptors, when given,
+ will be called in the order they were added for each URL.
+
+ QQmlEngine does not take ownership of the interceptor and won't delete it.
*/
-void QQmlEngine::setUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
+void QQmlEngine::addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
{
Q_D(QQmlEngine);
- d->urlInterceptor = urlInterceptor;
+ d->urlInterceptors.append(urlInterceptor);
}
/*!
- \internal
- This API is private for 5.1
+ Remove a \a urlInterceptor that was previously added using
+ \l addUrlInterceptor. The URL interceptors should not be modifed while the
+ engine is loading files, or URL selection may be inconsistent.
- Returns the current QQmlAbstractUrlInterceptor. It must not be modified outside
- the GUI thread.
+ This does not delete the interceptor, but merely removes it from the engine.
+ You can re-use it on the same or a different engine afterwards.
*/
-QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor() const
+void QQmlEngine::removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor)
+{
+ Q_D(QQmlEngine);
+ d->urlInterceptors.removeOne(urlInterceptor);
+}
+
+/*!
+ Run the current URL interceptors on the given \a url of the given \a type and
+ return the result.
+ */
+QUrl QQmlEngine::interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const
{
Q_D(const QQmlEngine);
- return d->urlInterceptor;
+ QUrl result = url;
+ for (QQmlAbstractUrlInterceptor *interceptor : d->urlInterceptors)
+ result = interceptor->intercept(result, type);
+ return result;
}
void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index)
@@ -1360,7 +1360,7 @@ void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
QObject* example:
\code
class MySingleton : public QObject {
- Q_OBJECT
+ \Q_OBJECT
// Register as default constructed singleton.
QML_ELEMENT
@@ -1422,10 +1422,10 @@ QJSValue QQmlEngine::singletonInstance<QJSValue>(int qmlTypeId)
void QQmlEngine::retranslate()
{
Q_D(QQmlEngine);
- QQmlContextData *context = QQmlContextData::get(d->rootContext)->childContexts;
- while (context) {
+ for (QQmlRefPointer<QQmlContextData> context
+ = QQmlContextData::get(d->rootContext)->childContexts();
+ context; context = context->nextChild()) {
context->refreshExpressions();
- context = context->nextChild;
}
}
@@ -1469,10 +1469,10 @@ void QQmlEngine::setContextForObject(QObject *object, QQmlContext *context)
return;
}
- QQmlContextData *contextData = QQmlContextData::get(context);
+ QQmlRefPointer<QQmlContextData> contextData = QQmlContextData::get(context);
Q_ASSERT(data->context == nullptr);
- data->context = contextData;
- contextData->addObject(data);
+ data->context = contextData.data();
+ contextData->addOwnedObject(data);
}
/*!
@@ -1576,7 +1576,7 @@ void qmlExecuteDeferred(QObject *object)
QQmlData *data = QQmlData::get(object);
if (data && !data->deferredData.isEmpty() && !data->wasDeleted(object)) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine());
QQmlComponentPrivate::DeferredState state;
QQmlComponentPrivate::beginDeferred(ep, object, &state);
@@ -1598,7 +1598,7 @@ QQmlEngine *qmlEngine(const QObject *obj)
QQmlData *data = QQmlData::get(obj, false);
if (!data || !data->context)
return nullptr;
- return data->context->engine;
+ return data->context->engine();
}
static QObject *resolveAttachedProperties(QQmlAttachedPropertiesFunc pf, QQmlData *data,
@@ -1786,7 +1786,9 @@ void QQmlData::NotifyList::layout()
todo = nullptr;
}
-void QQmlData::deferData(int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *context)
+void QQmlData::deferData(
+ int objectIndex, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QQmlRefPointer<QQmlContextData> &context)
{
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
deferData->deferredIdx = objectIndex;
@@ -1880,8 +1882,8 @@ void QQmlData::destroyed(QObject *object)
nextContextObject->prevContextObject = prevContextObject;
if (prevContextObject)
*prevContextObject = nextContextObject;
- else if (outerContext && outerContext->contextObjects == this)
- outerContext->contextObjects = nextContextObject;
+ else if (outerContext && outerContext->ownedObjects() == this)
+ outerContext->setOwnedObjects(nextContextObject);
QQmlAbstractBinding *binding = bindings;
while (binding) {
@@ -2229,7 +2231,6 @@ void QQmlEngine::addPluginPath(const QString& path)
d->importDatabase.addPluginPath(path);
}
-
/*!
Returns the list of directories where the engine searches for
native plugins for imported modules (referenced in the \c qmldir file).
@@ -2273,7 +2274,7 @@ void QQmlEngine::setPluginPathList(const QStringList &paths)
bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
{
Q_D(QQmlEngine);
- return d->importDatabase.importDynamicPlugin(filePath, uri, QString(), -1, errors);
+ return d->importDatabase.importDynamicPlugin(filePath, uri, QString(), QTypeRevision(), errors);
}
#endif
@@ -2330,17 +2331,6 @@ QString QQmlEngine::offlineStorageDatabaseFilePath(const QString &databaseName)
return d->offlineStorageDatabaseDirectory() + QLatin1String(md5.result().toHex());
}
-// #### Qt 6: Remove this function, it exists only for binary compatibility.
-/*!
- * \internal
- */
-bool QQmlEngine::addNamedBundle(const QString &name, const QString &fileName)
-{
- Q_UNUSED(name)
- Q_UNUSED(fileName)
- return false;
-}
-
QString QQmlEnginePrivate::offlineStorageDatabaseDirectory() const
{
Q_Q(const QQmlEngine);
@@ -2385,67 +2375,100 @@ int QQmlEnginePrivate::listType(int t) const
static QQmlPropertyCache *propertyCacheForPotentialInlineComponentType(int t, const QHash<int, QV4::ExecutableCompilationUnit *>::const_iterator &iter) {
- if (t != (*iter)->metaTypeId) {
+ if (t != (*iter)->metaTypeId.id()) {
// this is an inline component, and what we have in the iterator is currently the parent compilation unit
for (auto &&icDatum: (*iter)->inlineComponentData)
- if (icDatum.typeIds.id == t)
+ if (icDatum.typeIds.id.id() == t)
return (*iter)->propertyCaches.at(icDatum.objectIndex);
}
return (*iter)->rootPropertyCache().data();
}
+/*!
+ * \internal
+ *
+ * Look up by type's baseMetaObject.
+ */
QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
{
- Locker locker(this);
- auto iter = m_compositeTypes.constFind(t);
- if (iter != m_compositeTypes.cend()) {
- return propertyCacheForPotentialInlineComponentType(t, iter);
- } else {
- QQmlType type = QQmlMetaType::qmlType(t);
- return QQmlMetaObject(type.baseMetaObject());
- }
+ if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t))
+ return QQmlMetaObject(composite);
+
+ QQmlType type = QQmlMetaType::qmlType(t);
+ return QQmlMetaObject(type.baseMetaObject());
}
+/*!
+ * \internal
+ *
+ * Look up by type's metaObject.
+ */
QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
{
- Locker locker(this);
- auto iter = m_compositeTypes.constFind(t);
- if (iter != m_compositeTypes.cend()) {
- return propertyCacheForPotentialInlineComponentType(t, iter);
- } else {
- QQmlType type = QQmlMetaType::qmlType(t);
- return QQmlMetaObject(type.metaObject());
- }
+ if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t))
+ return QQmlMetaObject(composite);
+
+ QQmlType type = QQmlMetaType::qmlType(t);
+ return QQmlMetaObject(type.metaObject());
}
+/*!
+ * \internal
+ *
+ * Look up by type's metaObject and version.
+ */
QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
{
- Locker locker(this);
- auto iter = m_compositeTypes.constFind(t);
- if (iter != m_compositeTypes.cend()) {
- return propertyCacheForPotentialInlineComponentType(t, iter);
- } else {
- QQmlType type = QQmlMetaType::qmlType(t);
- locker.unlock();
- return type.isValid() ? cache(type.metaObject()) : nullptr;
- }
+ if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t))
+ return composite;
+
+ QQmlType type = QQmlMetaType::qmlType(t);
+ return type.isValid() ? cache(type.metaObject(), type.version()) : nullptr;
}
-QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, int minorVersion)
+/*!
+ * \internal
+ *
+ * Look up by type's baseMetaObject and unspecified/any version.
+ * TODO: Is this correct? Passing a plain QTypeRevision() rather than QTypeRevision::zero() or
+ * the actual type's version seems strange. The behavior has been in place for a while.
+ */
+QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
+{
+ if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t))
+ return composite;
+
+ QQmlType type = QQmlMetaType::qmlType(t);
+ return type.isValid() ? cache(type.baseMetaObject(), QTypeRevision()) : nullptr;
+}
+
+/*!
+ * \internal
+ *
+ * Look up by QQmlType and version. We only fall back to lookup by metaobject if the type
+ * has no revisiononed attributes here. Unspecified versions are interpreted as "any".
+ */
+QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t, QTypeRevision version)
+{
+ if (QQmlPropertyCache *composite = findPropertyCacheInCompositeTypes(t))
+ return composite;
+
+ QQmlType type = QQmlMetaType::qmlType(t);
+ if (!type.isValid())
+ return nullptr;
+
+ return type.containsRevisionedAttributes()
+ ? QQmlMetaType::propertyCache(type, version)
+ : cache(type.metaObject(), version);
+}
+
+QQmlPropertyCache *QQmlEnginePrivate::findPropertyCacheInCompositeTypes(int t) const
{
Locker locker(this);
auto iter = m_compositeTypes.constFind(t);
- if (iter != m_compositeTypes.cend()) {
- return propertyCacheForPotentialInlineComponentType(t, iter);
- } else {
- QQmlType type = QQmlMetaType::qmlType(t);
- locker.unlock();
-
- if (minorVersion >= 0)
- return type.isValid() ? cache(type, minorVersion) : nullptr;
- else
- return type.isValid() ? cache(type.baseMetaObject()) : nullptr;
- }
+ return (iter == m_compositeTypes.constEnd())
+ ? nullptr
+ : propertyCacheForPotentialInlineComponentType(t, iter);
}
void QQmlEnginePrivate::registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit)
@@ -2455,10 +2478,9 @@ void QQmlEnginePrivate::registerInternalCompositeType(QV4::ExecutableCompilation
Locker locker(this);
// The QQmlCompiledData is not referenced here, but it is removed from this
// hash in the QQmlCompiledData destructor
- m_compositeTypes.insert(compilationUnit->metaTypeId, compilationUnit);
- for (auto &&data: compilationUnit->inlineComponentData) {
- m_compositeTypes.insert(data.typeIds.id, compilationUnit);
- }
+ m_compositeTypes.insert(compilationUnit->metaTypeId.id(), compilationUnit);
+ for (auto &&data: compilationUnit->inlineComponentData)
+ m_compositeTypes.insert(data.typeIds.id.id(), compilationUnit);
}
void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit)
@@ -2466,9 +2488,9 @@ void QQmlEnginePrivate::unregisterInternalCompositeType(QV4::ExecutableCompilati
compilationUnit->isRegisteredWithEngine = false;
Locker locker(this);
- m_compositeTypes.remove(compilationUnit->metaTypeId);
+ m_compositeTypes.remove(compilationUnit->metaTypeId.id());
for (auto&& icDatum: compilationUnit->inlineComponentData)
- m_compositeTypes.remove(icDatum.typeIds.id);
+ m_compositeTypes.remove(icDatum.typeIds.id.id());
}
QV4::ExecutableCompilationUnit *QQmlEnginePrivate::obtainExecutableCompilationUnit(int typeId)
@@ -2498,7 +2520,7 @@ QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type)
// should behave identically to QML singleton types.
q->setContextForObject(o, new QQmlContext(q->rootContext(), q));
}
- singletonInstances.insert(type, value);
+ singletonInstances.convertAndInsert(v4engine(), type, &value);
} else if (siinfo->qobjectCallback) {
QObject *o = siinfo->qobjectCallback(q, q);
@@ -2516,12 +2538,12 @@ QJSValue QQmlEnginePrivate::singletonInstance<QJSValue>(const QQmlType &type)
// should behave identically to QML singleton types.
q->setContextForObject(o, new QQmlContext(q->rootContext(), q));
value = q->newQObject(o);
- singletonInstances.insert(type, value);
+ singletonInstances.convertAndInsert(v4engine(), type, &value);
} else if (!siinfo->url.isEmpty()) {
QQmlComponent component(q, siinfo->url, QQmlComponent::PreferSynchronous);
QObject *o = component.beginCreate(q->rootContext());
value = q->newQObject(o);
- singletonInstances.insert(type, value);
+ singletonInstances.convertAndInsert(v4engine(), type, &value);
component.completeCreate();
}
diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h
index 31fe3a1849..e301082064 100644
--- a/src/qml/qml/qqmlengine.h
+++ b/src/qml/qml/qqmlengine.h
@@ -46,11 +46,10 @@
#include <QtQml/qjsengine.h>
#include <QtQml/qqml.h>
#include <QtQml/qqmlerror.h>
+#include <QtQml/qqmlabstracturlinterceptor.h>
QT_BEGIN_NAMESPACE
-class QQmlAbstractUrlInterceptor;
-
class Q_QML_EXPORT QQmlImageProviderBase
{
public:
@@ -112,7 +111,9 @@ public:
void setPluginPathList(const QStringList &paths);
void addPluginPath(const QString& dir);
- bool addNamedBundle(const QString &name, const QString &fileName);
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED bool addNamedBundle(const QString &, const QString &) { return false; }
+#endif
#if QT_CONFIG(library)
bool importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors);
@@ -125,8 +126,17 @@ public:
QNetworkAccessManager *networkAccessManager() const;
#endif
- void setUrlInterceptor(QQmlAbstractUrlInterceptor* urlInterceptor);
- QQmlAbstractUrlInterceptor* urlInterceptor() const;
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED void setUrlInterceptor(QQmlAbstractUrlInterceptor* urlInterceptor)
+ {
+ addUrlInterceptor(urlInterceptor);
+ }
+ QT_DEPRECATED QQmlAbstractUrlInterceptor *urlInterceptor() const;
+#endif
+
+ void addUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
+ void removeUrlInterceptor(QQmlAbstractUrlInterceptor *urlInterceptor);
+ QUrl interceptUrl(const QUrl &url, QQmlAbstractUrlInterceptor::DataType type) const;
void addImageProvider(const QString &id, QQmlImageProviderBase *);
QQmlImageProviderBase *imageProvider(const QString &id) const;
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index 263c69e2d8..f8b8b187a5 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -59,7 +59,7 @@
#include "qqml.h"
#include "qqmlvaluetype_p.h"
#include "qqmlcontext.h"
-#include "qqmlcontext_p.h"
+#include "qqmlcontextdata_p.h"
#include "qqmlexpression.h"
#include "qqmlproperty_p.h"
#include "qqmlmetatype_p.h"
@@ -67,6 +67,7 @@
#include <private/qrecyclepool_p.h>
#include <private/qfieldlist_p.h>
#include <private/qv4engine_p.h>
+#include <private/qjsvalue_p.h>
#include <QtCore/qlist.h>
#include <QtCore/qpair.h>
@@ -105,6 +106,7 @@ struct QObjectForeign {
Q_GADGET
QML_FOREIGN(QObject)
QML_NAMED_ELEMENT(QtObject)
+ QML_ADDED_IN_VERSION(2, 0)
Q_CLASSINFO("QML.Root", "QML")
};
@@ -177,8 +179,7 @@ public:
QHash<QString,QSharedPointer<QQmlImageProviderBase> > imageProviders;
QSharedPointer<QQmlImageProviderBase> imageProvider(const QString &providerId) const;
-
- QQmlAbstractUrlInterceptor* urlInterceptor;
+ QList<QQmlAbstractUrlInterceptor *> urlInterceptors;
int scarceResourcesRefCount;
void referenceScarceResources();
@@ -204,7 +205,7 @@ public:
QIntrusiveList<Incubator, &Incubator::next> incubatorList;
unsigned int incubatorCount;
QQmlIncubationController *incubationController;
- void incubate(QQmlIncubator &, QQmlContextData *);
+ void incubate(QQmlIncubator &, const QQmlRefPointer<QQmlContextData> &);
// These methods may be called from any thread
inline bool isEngineThread() const;
@@ -216,7 +217,7 @@ public:
QString offlineStorageDatabaseDirectory() const;
// These methods may be called from the loader thread
- inline QQmlPropertyCache *cache(const QQmlType &, int);
+ inline QQmlPropertyCache *cache(const QQmlType &, QTypeRevision version);
using QJSEnginePrivate::cache;
// These methods may be called from the loader thread
@@ -228,7 +229,8 @@ public:
QQmlMetaObject rawMetaObjectForType(int) const;
QQmlMetaObject metaObjectForType(int) const;
QQmlPropertyCache *propertyCacheForType(int);
- QQmlPropertyCache *rawPropertyCacheForType(int, int minorVersion = -1);
+ QQmlPropertyCache *rawPropertyCacheForType(int);
+ QQmlPropertyCache *rawPropertyCacheForType(int, QTypeRevision version);
void registerInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
void unregisterInternalCompositeType(QV4::ExecutableCompilationUnit *compilationUnit);
QV4::ExecutableCompilationUnit *obtainExecutableCompilationUnit(int typeId);
@@ -253,16 +255,13 @@ public:
inline static QQmlEnginePrivate *get(QQmlEngine *e);
inline static const QQmlEnginePrivate *get(const QQmlEngine *e);
inline static QQmlEnginePrivate *get(QQmlContext *c);
- inline static QQmlEnginePrivate *get(QQmlContextData *c);
+ inline static QQmlEnginePrivate *get(const QQmlRefPointer<QQmlContextData> &c);
inline static QQmlEngine *get(QQmlEnginePrivate *p);
inline static QQmlEnginePrivate *get(QV4::ExecutionEngine *e);
static QList<QQmlError> qmlErrorFromDiagnostics(const QString &fileName, const QList<QQmlJS::DiagnosticMessage> &diagnosticMessages);
static void defineModule();
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- static void registerQuickTypes();
-#endif
static bool designerMode();
static void activateDesignerMode();
@@ -287,7 +286,20 @@ public:
}
private:
- QHash<QQmlType, QJSValue> singletonInstances;
+ class SingletonInstances : private QHash<QQmlType, QJSValue>
+ {
+ public:
+ void convertAndInsert(QV4::ExecutionEngine *engine, const QQmlType &type, QJSValue *value)
+ {
+ QJSValuePrivate::manageStringOnV4Heap(engine, value);
+ insert(type, *value);
+ }
+
+ using QHash<QQmlType, QJSValue>::value;
+ using QHash<QQmlType, QJSValue>::take;
+ };
+
+ SingletonInstances singletonInstances;
QHash<int, QQmlGadgetPtrWrapper *> cachedValueTypeInstances;
// These members must be protected by a QQmlEnginePrivate::Locker as they are required by
@@ -301,6 +313,7 @@ private:
void doDeleteInEngineThread();
void cleanupScarceResources();
+ QQmlPropertyCache *findPropertyCacheInCompositeTypes(int t) const;
};
/*
@@ -399,15 +412,13 @@ Returns a QQmlPropertyCache for \a type with \a minorVersion.
The returned cache is not referenced, so if it is to be stored, call addref().
*/
-QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, int minorVersion)
+QQmlPropertyCache *QQmlEnginePrivate::cache(const QQmlType &type, QTypeRevision version)
{
Q_ASSERT(type.isValid());
-
- if (minorVersion == -1 || !type.containsRevisionedAttributes())
- return cache(type.metaObject(), minorVersion);
+ Q_ASSERT(type.containsRevisionedAttributes());
Locker locker(this);
- return QQmlMetaType::propertyCache(type, minorVersion);
+ return QQmlMetaType::propertyCache(type, version);
}
QV4::ExecutionEngine *QQmlEnginePrivate::getV4Engine(QQmlEngine *e)
@@ -431,14 +442,24 @@ const QQmlEnginePrivate *QQmlEnginePrivate::get(const QQmlEngine *e)
return e ? e->d_func() : nullptr;
}
+template<typename Context>
+QQmlEnginePrivate *contextEngine(const Context &context)
+{
+ if (!context)
+ return nullptr;
+ if (QQmlEngine *engine = context->engine())
+ return QQmlEnginePrivate::get(engine);
+ return nullptr;
+}
+
QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContext *c)
{
- return (c && c->engine()) ? QQmlEnginePrivate::get(c->engine()) : nullptr;
+ return contextEngine(c);
}
-QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContextData *c)
+QQmlEnginePrivate *QQmlEnginePrivate::get(const QQmlRefPointer<QQmlContextData> &c)
{
- return (c && c->engine) ? QQmlEnginePrivate::get(c->engine) : nullptr;
+ return contextEngine(c);
}
QQmlEngine *QQmlEnginePrivate::get(QQmlEnginePrivate *p)
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index f6a5afb891..5864c3245c 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -63,7 +63,8 @@ QQmlExpressionPrivate::~QQmlExpressionPrivate()
{
}
-void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QObject *me)
+void QQmlExpressionPrivate::init(const QQmlRefPointer<QQmlContextData> &ctxt, const QString &expr,
+ QObject *me)
{
expression = expr;
@@ -72,10 +73,11 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QOb
expressionFunctionValid = false;
}
-void QQmlExpressionPrivate::init(QQmlContextData *ctxt, QV4::Function *runtimeFunction, QObject *me)
+void QQmlExpressionPrivate::init(const QQmlRefPointer<QQmlContextData> &ctxt,
+ QV4::Function *runtimeFunction, QObject *me)
{
expressionFunctionValid = true;
- QV4::ExecutionEngine *engine = ctxt->engine->handle();
+ QV4::ExecutionEngine *engine = ctxt->engine()->handle();
QV4::Scope scope(engine);
QV4::Scoped<QV4::QmlContext> qmlContext(scope, QV4::QmlContext::create(engine->rootContext(), ctxt, me));
setupFunction(qmlContext, runtimeFunction);
@@ -144,20 +146,24 @@ QQmlExpression::QQmlExpression(const QQmlScriptString &script, QQmlContext *ctxt
if (!ctxt && (!scriptPrivate->context || !scriptPrivate->context->isValid()))
return;
- QQmlContextData *evalCtxtData = QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context);
+ QQmlRefPointer<QQmlContextData> evalCtxtData
+ = QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context);
QObject *scopeObject = scope ? scope : scriptPrivate->scope;
QV4::Function *runtimeFunction = nullptr;
if (scriptPrivate->context) {
- QQmlContextData *ctxtdata = QQmlContextData::get(scriptPrivate->context);
+ QQmlRefPointer<QQmlContextData> ctxtdata = QQmlContextData::get(scriptPrivate->context);
QQmlEnginePrivate *engine = QQmlEnginePrivate::get(scriptPrivate->context->engine());
- if (engine && ctxtdata && !ctxtdata->urlString().isEmpty() && ctxtdata->typeCompilationUnit) {
+ if (engine
+ && ctxtdata
+ && !ctxtdata->urlString().isEmpty()
+ && ctxtdata->typeCompilationUnit()) {
d->url = ctxtdata->urlString();
d->line = scriptPrivate->lineNumber;
d->column = scriptPrivate->columnNumber;
if (scriptPrivate->bindingId != QQmlBinding::Invalid)
- runtimeFunction = ctxtdata->typeCompilationUnit->runtimeFunctions.at(scriptPrivate->bindingId);
+ runtimeFunction = ctxtdata->typeCompilationUnit()->runtimeFunctions.at(scriptPrivate->bindingId);
}
}
@@ -175,10 +181,8 @@ QQmlExpression::QQmlExpression(const QQmlScriptString &script, QQmlContext *ctxt
If specified, the \a scope object's properties will also be in scope during
the expression's execution.
*/
-QQmlExpression::QQmlExpression(QQmlContext *ctxt,
- QObject *scope,
- const QString &expression,
- QObject *parent)
+QQmlExpression::QQmlExpression(QQmlContext *ctxt, QObject *scope, const QString &expression,
+ QObject *parent)
: QObject(*new QQmlExpressionPrivate, parent)
{
Q_D(QQmlExpression);
@@ -188,12 +192,10 @@ QQmlExpression::QQmlExpression(QQmlContext *ctxt,
/*!
\internal
*/
-QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope,
- const QString &expression)
-: QObject(*new QQmlExpressionPrivate, nullptr)
+QQmlExpression::QQmlExpression(QQmlExpressionPrivate &dd, QObject *parent) : QObject(dd, parent)
{
- Q_D(QQmlExpression);
- d->init(ctxt, expression, scope);
+// Q_D(QQmlExpression);
+// d->init(QQmlContextData::get(ctxt), expression, scope);
}
/*!
@@ -210,7 +212,7 @@ QQmlExpression::~QQmlExpression()
QQmlEngine *QQmlExpression::engine() const
{
Q_D(const QQmlExpression);
- return d->context()?d->context()->engine:nullptr;
+ return d->engine();
}
/*!
@@ -220,8 +222,7 @@ QQmlEngine *QQmlExpression::engine() const
QQmlContext *QQmlExpression::context() const
{
Q_D(const QQmlExpression);
- QQmlContextData *data = d->context();
- return data?data->asQQmlContext():nullptr;
+ return d->publicContext();
}
/*!
@@ -265,7 +266,7 @@ QVariant QQmlExpressionPrivate::value(bool *isUndefined)
{
Q_Q(QQmlExpression);
- if (!context() || !context()->isValid()) {
+ if (!hasValidContext()) {
qWarning("QQmlExpression: Attempted to evaluate an expression in an invalid context");
return QVariant();
}
diff --git a/src/qml/qml/qqmlexpression.h b/src/qml/qml/qqmlexpression.h
index 0eceeb12e1..c9719aec52 100644
--- a/src/qml/qml/qqmlexpression.h
+++ b/src/qml/qml/qqmlexpression.h
@@ -90,7 +90,7 @@ Q_SIGNALS:
void valueChanged();
private:
- QQmlExpression(QQmlContextData *, QObject *, const QString &);
+ QQmlExpression(QQmlExpressionPrivate &dd, QObject *parent);
Q_DISABLE_COPY(QQmlExpression)
Q_DECLARE_PRIVATE(QQmlExpression)
diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h
index da10b31b2c..3df839a6a2 100644
--- a/src/qml/qml/qqmlexpression_p.h
+++ b/src/qml/qml/qqmlexpression_p.h
@@ -70,8 +70,8 @@ public:
QQmlExpressionPrivate();
~QQmlExpressionPrivate() override;
- void init(QQmlContextData *, const QString &, QObject *);
- void init(QQmlContextData *, QV4::Function *runtimeFunction, QObject *);
+ void init(const QQmlRefPointer<QQmlContextData> &, const QString &, QObject *);
+ void init(const QQmlRefPointer<QQmlContextData> &, QV4::Function *runtimeFunction, QObject *);
QVariant value(bool *isUndefined = nullptr);
diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp
index 7a62c967e7..f779199b74 100644
--- a/src/qml/qml/qqmlextensionplugin.cpp
+++ b/src/qml/qml/qqmlextensionplugin.cpp
@@ -117,6 +117,16 @@ QUrl QQmlExtensionPlugin::baseUrl() const
}
/*!
+ \since 6.0
+
+ Override this method to unregister types manually registered in registerTypes.
+*/
+void QQmlExtensionPlugin::unregisterTypes()
+{
+
+}
+
+/*!
\internal
*/
diff --git a/src/qml/qml/qqmlextensionplugin.h b/src/qml/qml/qqmlextensionplugin.h
index ef7ff422cd..78371106bd 100644
--- a/src/qml/qml/qqmlextensionplugin.h
+++ b/src/qml/qml/qqmlextensionplugin.h
@@ -64,6 +64,7 @@ public:
QUrl baseUrl() const;
void registerTypes(const char *uri) override = 0;
+ virtual void unregisterTypes();
void initializeEngine(QQmlEngine *engine, const char *uri) override;
private:
diff --git a/src/qml/qml/qqmlfileselector.cpp b/src/qml/qml/qqmlfileselector.cpp
index 32dce8b4bc..aaddfa628c 100644
--- a/src/qml/qml/qqmlfileselector.cpp
+++ b/src/qml/qml/qqmlfileselector.cpp
@@ -39,15 +39,16 @@
#include <QtCore/QFileSelector>
#include <QtQml/QQmlAbstractUrlInterceptor>
+#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/private/qqmlapplicationengine_p.h>
#include <qobjectdefs.h>
#include "qqmlfileselector.h"
#include "qqmlfileselector_p.h"
+#include "qqmlengine_p.h"
#include <QDebug>
QT_BEGIN_NAMESPACE
-typedef QHash<QQmlAbstractUrlInterceptor*, QQmlFileSelector*> interceptorSelectorMap;
-Q_GLOBAL_STATIC(interceptorSelectorMap, interceptorInstances);
/*!
\class QQmlFileSelector
\since 5.2
@@ -104,8 +105,7 @@ QQmlFileSelector::QQmlFileSelector(QQmlEngine* engine, QObject* parent)
{
Q_D(QQmlFileSelector);
d->engine = engine;
- interceptorInstances()->insert(d->myInstance.data(), this);
- d->engine->setUrlInterceptor(d->myInstance.data());
+ d->engine->addUrlInterceptor(d->myInstance.data());
}
/*!
@@ -114,11 +114,10 @@ QQmlFileSelector::QQmlFileSelector(QQmlEngine* engine, QObject* parent)
QQmlFileSelector::~QQmlFileSelector()
{
Q_D(QQmlFileSelector);
- if (d->engine && QQmlFileSelector::get(d->engine) == this) {
- d->engine->setUrlInterceptor(nullptr);
+ if (d->engine) {
+ d->engine->removeUrlInterceptor(d->myInstance.data());
d->engine = nullptr;
}
- interceptorInstances()->remove(d->myInstance.data());
}
/*!
@@ -173,35 +172,50 @@ void QQmlFileSelector::setSelector(QFileSelector *selector)
Use this when extra selectors are all you need to avoid having to create your own
QFileSelector instance.
*/
-void QQmlFileSelector::setExtraSelectors(QStringList &strings)
-{
- Q_D(QQmlFileSelector);
- d->selector->setExtraSelectors(strings);
-}
-
-
-/*!
- Adds extra selectors contained in \a strings to the current QFileSelector being used.
- Use this when extra selectors are all you need to avoid having to create your own
- QFileSelector instance.
-*/
void QQmlFileSelector::setExtraSelectors(const QStringList &strings)
{
Q_D(QQmlFileSelector);
d->selector->setExtraSelectors(strings);
}
+#if QT_DEPRECATED_SINCE(6, 0)
/*!
+ \deprecated
Gets the QQmlFileSelector currently active on the target \a engine.
+
+ This method is deprecated. You should not retrieve the files selector from an
+ engine after setting it. It may be in use.
+
+ If the \a engine passed here is a QQmlApplicationEngine that hasn't loaded any
+ QML files, yet, it will be initialized. Any later calls to
+ QQmlApplicationEngine::setExtraFileSelectors() will have no effect.
+
+ \sa QQmlApplicationEngine
*/
QQmlFileSelector* QQmlFileSelector::get(QQmlEngine* engine)
{
- //Since I think we still can't use dynamic_cast inside Qt...
- QQmlAbstractUrlInterceptor* current = engine->urlInterceptor();
- if (current && interceptorInstances()->contains(current))
- return interceptorInstances()->value(current);
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(engine);
+
+ if (qobject_cast<QQmlApplicationEngine *>(engine)) {
+ auto *appEnginePrivate = static_cast<QQmlApplicationEnginePrivate *>(enginePrivate);
+ if (!appEnginePrivate->isInitialized) {
+ appEnginePrivate->init();
+ appEnginePrivate->isInitialized = true;
+ }
+ }
+
+ const QUrl nonEmptyInvalid(QLatin1String(":"));
+ for (QQmlAbstractUrlInterceptor *interceptor : enginePrivate->urlInterceptors) {
+ const QUrl result = interceptor->intercept(
+ nonEmptyInvalid, QQmlAbstractUrlInterceptor::UrlString);
+ if (result.scheme() == QLatin1String("type")
+ && result.path() == QLatin1String("fileselector")) {
+ return static_cast<QQmlFileSelectorInterceptor *>(interceptor)->d->q_func();
+ }
+ }
return nullptr;
}
+#endif
/*!
\internal
@@ -216,9 +230,12 @@ QQmlFileSelectorInterceptor::QQmlFileSelectorInterceptor(QQmlFileSelectorPrivate
*/
QUrl QQmlFileSelectorInterceptor::intercept(const QUrl &path, DataType type)
{
- if ( type == QQmlAbstractUrlInterceptor::QmldirFile ) //Don't intercept qmldir files, to prevent double interception
- return path;
- return d->selector->select(path);
+ if (!path.isEmpty() && !path.isValid())
+ return QUrl(QLatin1String("type:fileselector"));
+
+ return type == QQmlAbstractUrlInterceptor::QmldirFile
+ ? path // Don't intercept qmldir files, to prevent double interception
+ : d->selector->select(path);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlfileselector.h b/src/qml/qml/qqmlfileselector.h
index 9b70e3936d..0aeea6775f 100644
--- a/src/qml/qml/qqmlfileselector.h
+++ b/src/qml/qml/qqmlfileselector.h
@@ -58,9 +58,11 @@ public:
~QQmlFileSelector() override;
QFileSelector *selector() const Q_DECL_NOTHROW;
void setSelector(QFileSelector *selector);
- void setExtraSelectors(QStringList &strings); // TODO Qt6: remove
void setExtraSelectors(const QStringList &strings);
- static QQmlFileSelector* get(QQmlEngine*);
+
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED static QQmlFileSelector *get(QQmlEngine*);
+#endif
private:
Q_DISABLE_COPY(QQmlFileSelector)
diff --git a/src/qml/qml/qqmlguardedcontextdata_p.h b/src/qml/qml/qqmlguardedcontextdata_p.h
new file mode 100644
index 0000000000..0b24c04305
--- /dev/null
+++ b/src/qml/qml/qqmlguardedcontextdata_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLGUARDEDCONTEXTDATA_P_H
+#define QQMLGUARDEDCONTEXTDATA_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQml/private/qqmlglobal_p.h>
+#include <QtQml/private/qqmlcontextdata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlGuardedContextData
+{
+ Q_DISABLE_COPY(QQmlGuardedContextData);
+public:
+ QQmlGuardedContextData() = default;
+ ~QQmlGuardedContextData() { unlink(); }
+
+ QQmlGuardedContextData(QQmlGuardedContextData &&) = default;
+ QQmlGuardedContextData &operator=(QQmlGuardedContextData &&) = default;
+
+ QQmlGuardedContextData(QQmlRefPointer<QQmlContextData> data)
+ {
+ setContextData(std::move(data));
+ }
+
+ QQmlGuardedContextData &operator=(QQmlRefPointer<QQmlContextData> d)
+ {
+ setContextData(std::move(d));
+ return *this;
+ }
+
+ QQmlRefPointer<QQmlContextData> contextData() const { return m_contextData; }
+ void setContextData(QQmlRefPointer<QQmlContextData> contextData)
+ {
+ if (m_contextData.data() == contextData.data())
+ return;
+ unlink();
+
+ if (contextData) {
+ m_contextData = std::move(contextData);
+ m_next = m_contextData->m_contextGuards;
+ if (m_next)
+ m_next->m_prev = &m_next;
+
+ m_contextData->m_contextGuards = this;
+ m_prev = &m_contextData->m_contextGuards;
+ }
+ }
+
+ bool isNull() const { return !m_contextData; }
+
+ operator const QQmlRefPointer<QQmlContextData> &() const { return m_contextData; }
+ QQmlContextData &operator*() const { return m_contextData.operator*(); }
+ QQmlContextData *operator->() const { return m_contextData.operator->(); }
+
+ QQmlGuardedContextData *next() const { return m_next; }
+
+ void reset()
+ {
+ m_contextData = nullptr;
+ m_next = nullptr;
+ m_prev = nullptr;
+ }
+
+private:
+ void unlink()
+ {
+ if (m_prev) {
+ *m_prev = m_next;
+ if (m_next)
+ m_next->m_prev = m_prev;
+ reset();
+ }
+ }
+
+ QQmlRefPointer<QQmlContextData> m_contextData;
+ QQmlGuardedContextData *m_next = nullptr;
+ QQmlGuardedContextData **m_prev = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLGUARDEDCONTEXTDATA_P_H
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index c3f6a9057d..08e43c1341 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -161,9 +161,17 @@ void qmlClearEnginePlugins()
#if QT_CONFIG(library)
for (auto &plugin : qAsConst(*plugins)) {
QPluginLoader* loader = plugin.loader;
- if (loader && !loader->unload())
- qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString()));
- delete loader;
+ if (loader) {
+ auto extensionPlugin = qobject_cast<QQmlExtensionPlugin *>(loader->instance());
+ if (extensionPlugin) {
+ extensionPlugin->unregisterTypes();
+ }
+#ifndef Q_OS_MACOS
+ if (!loader->unload())
+ qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString()));
+ delete loader;
+#endif
+ }
}
#endif
plugins->clear();
@@ -213,12 +221,12 @@ public:
QQmlImportNamespace *importNamespace(const QString &prefix) const;
bool addLibraryImport(const QString& uri, const QString &prefix,
- int vmaj, int vmin, const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete,
+ QTypeRevision version, const QString &qmldirIdentifier,
+ const QString &qmldirUrl, bool incomplete,
QQmlImportDatabase *database,
QList<QQmlError> *errors);
- bool addFileImport(const QString &uri, const QString &prefix,
- int vmaj, int vmin,
+ bool addFileImport(const QString &uri, const QString &prefix, QTypeRevision version,
bool isImplicitImport, bool incomplete, QQmlImportDatabase *database,
QList<QQmlError> *errors);
@@ -227,7 +235,7 @@ public:
QQmlImportDatabase *database,
QList<QQmlError> *errors);
- bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor,
+ bool resolveType(const QHashedStringRef &type, QTypeRevision *version_return,
QQmlType *type_return, QList<QQmlError> *errors,
QQmlType::RegistrationType registrationType,
bool *typeRecursionDetected = nullptr);
@@ -247,14 +255,13 @@ public:
QQmlTypeLoader *typeLoader;
static QQmlImports::LocalQmldirResult locateLocalQmldir(
- const QString &uri, int vmaj, int vmin, QQmlImportDatabase *database,
+ const QString &uri, QTypeRevision version, QQmlImportDatabase *database,
QString *outQmldirFilePath, QString *outUrl);
- static bool validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, int vmaj, int vmin,
- QList<QQmlError> *errors);
+ static bool validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri,
+ QTypeRevision version, QList<QQmlError> *errors);
- bool importExtension(const QString &absoluteFilePath, const QString &uri,
- int vmaj, int vmin,
+ bool importExtension(const QString &absoluteFilePath, const QString &uri, QTypeRevision version,
QQmlImportDatabase *database,
const QQmlTypeLoaderQmldirContent &qmldir,
QList<QQmlError> *errors);
@@ -264,10 +271,10 @@ public:
QString resolvedUri(const QString &dir_arg, QQmlImportDatabase *database);
- QQmlImportInstance *addImportToNamespace(QQmlImportNamespace *nameSpace,
- const QString &uri, const QString &url,
- int vmaj, int vmin, QV4::CompiledData::Import::ImportType type,
- QList<QQmlError> *errors, bool lowPrecedence = false);
+ QQmlImportInstance *addImportToNamespace(QQmlImportNamespace *nameSpace, const QString &uri,
+ const QString &url, QTypeRevision version,
+ QV4::CompiledData::Import::ImportType type,
+ QList<QQmlError> *errors, bool lowPrecedence = false);
bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris,
const QString &qmldirPath, QList<QQmlError> *errors);
@@ -344,9 +351,9 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const
for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
const QQmlImportInstance *import = set.imports.at(ii);
- QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion);
+ QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->version);
if (module) {
- cache->m_anonymousImports.append(QQmlTypeModuleVersion(module, import->minversion));
+ cache->m_anonymousImports.append(QQmlTypeModuleVersion(module, import->version));
}
}
@@ -360,10 +367,10 @@ void QQmlImports::populateCache(QQmlTypeNameCache *cache) const
for (int ii = set.imports.count() - 1; ii >= 0; --ii) {
const QQmlImportInstance *import = set.imports.at(ii);
- QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion);
+ QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->version);
if (module) {
QQmlImportRef &typeimport = cache->m_namedImports[set.prefix];
- typeimport.modules.append(QQmlTypeModuleVersion(module, import->minversion));
+ typeimport.modules.append(QQmlTypeModuleVersion(module, import->version));
}
}
}
@@ -395,36 +402,35 @@ void findCompositeSingletons(const QQmlImportNamespace &set, QList<QQmlImports::
const QQmlDirComponents &components = import->qmlDirComponents;
- const int importMajorVersion = import->majversion;
- const int importMinorVersion = import->minversion;
- auto shouldSkipSingleton = [importMajorVersion, importMinorVersion](int singletonMajorVersion, int singletonMinorVersion) -> bool {
- return importMajorVersion != -1 &&
- (singletonMajorVersion > importMajorVersion || (singletonMajorVersion == importMajorVersion && singletonMinorVersion > importMinorVersion));
+ const QTypeRevision importVersion = import->version;
+ auto shouldSkipSingleton = [importVersion](QTypeRevision singletonVersion) -> bool {
+ return importVersion.hasMajorVersion() &&
+ (singletonVersion.majorVersion() > importVersion.majorVersion()
+ || (singletonVersion.majorVersion() == importVersion.majorVersion()
+ && singletonVersion.minorVersion() > importVersion.minorVersion()));
};
ConstIterator cend = components.constEnd();
for (ConstIterator cit = components.constBegin(); cit != cend; ++cit) {
if (cit->singleton && excludeBaseUrl(import->url, cit->fileName, baseUrl.toString())) {
- if (shouldSkipSingleton(cit->majorVersion, cit->minorVersion))
+ if (shouldSkipSingleton(cit->version))
continue;
QQmlImports::CompositeSingletonReference ref;
ref.typeName = cit->typeName;
ref.prefix = set.prefix;
- ref.majorVersion = cit->majorVersion;
- ref.minorVersion = cit->minorVersion;
+ ref.version = cit->version;
resultList.append(ref);
}
}
- if (QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->majversion)) {
+ if (QQmlTypeModule *module = QQmlMetaType::typeModule(import->uri, import->version)) {
module->walkCompositeSingletons([&resultList, &set, &shouldSkipSingleton](const QQmlType &singleton) {
- if (shouldSkipSingleton(singleton.majorVersion(), singleton.minorVersion()))
+ if (shouldSkipSingleton(singleton.version()))
return;
QQmlImports::CompositeSingletonReference ref;
ref.typeName = singleton.elementName();
ref.prefix = set.prefix;
- ref.majorVersion = singleton.majorVersion();
- ref.minorVersion = singleton.minorVersion();
+ ref.version = singleton.version();
resultList.append(ref);
});
}
@@ -461,9 +467,9 @@ QList<QQmlImports::CompositeSingletonReference> QQmlImports::resolvedCompositeSi
if (lhs.typeName != rhs.typeName)
return lhs.typeName < rhs.typeName;
- return lhs.majorVersion != rhs.majorVersion
- ? lhs.majorVersion < rhs.majorVersion
- : lhs.minorVersion < rhs.minorVersion;
+ return lhs.version.majorVersion() != rhs.version.majorVersion()
+ ? lhs.version.majorVersion() < rhs.version.majorVersion()
+ : lhs.version.minorVersion() < rhs.version.minorVersion();
});
return compositeSingletons;
@@ -532,7 +538,8 @@ static QString joinStringRefs(const QVector<QStringRef> &refs, const QChar &sep)
- base/QtQml.2/Models/qmldir
- base/QtQml/Models/qmldir
*/
-QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin)
+QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringList &basePaths,
+ QTypeRevision version)
{
const QVector<QStringRef> parts = uri.splitRef(Dot, Qt::SkipEmptyParts);
@@ -540,8 +547,21 @@ QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringLi
// fully & partially versioned parts + 1 unversioned for each base path
qmlDirPathsPaths.reserve(basePaths.count() * (2 * parts.count() + 1));
- for (int version = FullyVersioned; version <= Unversioned; ++version) {
- const QString ver = versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version));
+ for (int versionMode = FullyVersioned; versionMode <= Unversioned; ++versionMode) {
+ switch (versionMode) {
+ case FullyVersioned:
+ if (!version.hasMinorVersion())
+ continue;
+ break;
+ case PartiallyVersioned:
+ if (!version.hasMajorVersion())
+ continue;
+ break;
+ default:
+ break;
+ }
+
+ const QString ver = versionString(version, QQmlImports::ImportVersion(versionMode));
for (const QString &path : basePaths) {
QString dir = path;
@@ -551,7 +571,7 @@ QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringLi
// append to the end
qmlDirPathsPaths += dir + joinStringRefs(parts, Slash) + ver + Slash_qmldir;
- if (version != Unversioned) {
+ if (versionMode != Unversioned) {
// insert in the middle
for (int index = parts.count() - 2; index >= 0; --index) {
qmlDirPathsPaths += dir + joinStringRefs(parts.mid(0, index + 1), Slash)
@@ -565,14 +585,14 @@ QStringList QQmlImports::completeQmldirPaths(const QString &uri, const QStringLi
return qmlDirPathsPaths;
}
-QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
+QString QQmlImports::versionString(QTypeRevision version, ImportVersion versionMode)
{
- if (version == QQmlImports::FullyVersioned) {
+ if (versionMode == QQmlImports::FullyVersioned) {
// extension with fully encoded version number (eg. MyModule.3.2)
- return QString::asprintf(".%d.%d", vmaj, vmin);
- } else if (version == QQmlImports::PartiallyVersioned) {
+ return QString::asprintf(".%d.%d", version.majorVersion(), version.minorVersion());
+ } else if (versionMode == QQmlImports::PartiallyVersioned) {
// extension with encoded version major (eg. MyModule.3)
- return QString::asprintf(".%d", vmaj);
+ return QString::asprintf(".%d", version.majorVersion());
} // else extension without version number (eg. MyModule)
return QString();
}
@@ -591,7 +611,7 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
\sa addFileImport(), addLibraryImport
*/
bool QQmlImports::resolveType(const QHashedStringRef &type,
- QQmlType *type_return, int *vmaj, int *vmin,
+ QQmlType *type_return, QTypeRevision *version_return,
QQmlImportNamespace** ns_return, QList<QQmlError> *errors,
QQmlType::RegistrationType registrationType,
bool *typeRecursionDetected) const
@@ -603,7 +623,7 @@ bool QQmlImports::resolveType(const QHashedStringRef &type,
return true;
}
if (type_return) {
- if (d->resolveType(type, vmaj, vmin, type_return, errors, registrationType,
+ if (d->resolveType(type, version_return, type_return, errors, registrationType,
typeRecursionDetected)) {
if (qmlImportTrace()) {
#define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \
@@ -627,7 +647,9 @@ bool QQmlImports::resolveType(const QHashedStringRef &type,
return false;
}
-bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoaderQmldirContent &qmldir, QQmlImportNamespace *nameSpace, QList<QQmlError> *errors)
+bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl,
+ const QQmlTypeLoaderQmldirContent &qmldir,
+ QQmlImportNamespace *nameSpace, QList<QQmlError> *errors)
{
Q_ASSERT(resolvedUrl.endsWith(Slash));
url = resolvedUrl;
@@ -648,24 +670,27 @@ bool QQmlImportInstance::setQmldirContent(const QString &resolvedUrl, const QQml
}
}
- qmlDirScripts = getVersionedScripts(scripts, majversion, minversion);
+ qmlDirScripts = getVersionedScripts(scripts, version);
}
return true;
}
-QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qmldirscripts, int vmaj, int vmin)
+QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qmldirscripts,
+ QTypeRevision version)
{
QMap<QString, QQmlDirParser::Script> versioned;
for (QList<QQmlDirParser::Script>::const_iterator sit = qmldirscripts.constBegin();
sit != qmldirscripts.constEnd(); ++sit) {
// Only include scripts that match our requested version
- if (((vmaj == -1) || (sit->majorVersion == vmaj)) &&
- ((vmin == -1) || (sit->minorVersion <= vmin))) {
+ if ((!version.hasMajorVersion() || (sit->version.majorVersion() == version.majorVersion()))
+ && (!version.hasMinorVersion()
+ || (sit->version.minorVersion() <= version.minorVersion()))) {
// Load the highest version that matches
QMap<QString, QQmlDirParser::Script>::iterator vit = versioned.find(sit->nameSpace);
- if (vit == versioned.end() || (vit->minorVersion < sit->minorVersion)) {
+ if (vit == versioned.end()
+ || (vit->version.minorVersion() < sit->version.minorVersion())) {
versioned.insert(sit->nameSpace, *sit);
}
}
@@ -685,30 +710,27 @@ QQmlDirScripts QQmlImportInstance::getVersionedScripts(const QQmlDirScripts &qml
If the return pointer is 0, the corresponding search is not done.
*/
bool QQmlImports::resolveType(QQmlImportNamespace *ns, const QHashedStringRef &type,
- QQmlType *type_return, int *vmaj, int *vmin,
+ QQmlType *type_return, QTypeRevision *version_return,
QQmlType::RegistrationType registrationType) const
{
- return ns->resolveType(d->typeLoader, type, vmaj, vmin, type_return, nullptr, nullptr, registrationType);
+ return ns->resolveType(d->typeLoader, type, version_return, type_return, nullptr, nullptr,
+ registrationType);
}
bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
- int *vmajor, int *vminor, QQmlType *type_return, QString *base,
- bool *typeRecursionDetected,
+ QTypeRevision *version_return, QQmlType *type_return,
+ QString *base, bool *typeRecursionDetected,
QQmlType::RegistrationType registrationType,
QQmlImport::RecursionRestriction recursionRestriction,
QList<QQmlError> *errors) const
{
- if (majversion >= 0 && minversion >= 0) {
- QQmlType t = QQmlMetaType::qmlType(type, uri, majversion, minversion);
- if (t.isValid()) {
- if (vmajor)
- *vmajor = majversion;
- if (vminor)
- *vminor = minversion;
- if (type_return)
- *type_return = t;
- return true;
- }
+ QQmlType t = QQmlMetaType::qmlType(type, uri, version);
+ if (t.isValid()) {
+ if (version_return)
+ *version_return = version;
+ if (type_return)
+ *type_return = t;
+ return true;
}
const QString typeStr = type.toString();
@@ -764,14 +786,16 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
break;
}
- // importing version -1 means import ALL versions
- if ((majversion == -1) ||
- (implicitlyImported && c.internal) || // allow the implicit import of internal types
- (c.majorVersion == majversion && c.minorVersion <= minversion)) {
+ // importing invalid version means import ALL versions
+ if (!version.hasMajorVersion() || (implicitlyImported && c.internal)
+ // allow the implicit import of internal types
+ || (c.version.majorVersion() == version.majorVersion()
+ && c.version.minorVersion() <= version.minorVersion())) {
// Is this better than the previous candidate?
- if ((candidate == end) ||
- (c.majorVersion > candidate->majorVersion) ||
- ((c.majorVersion == candidate->majorVersion) && (c.minorVersion > candidate->minorVersion))) {
+ if ((candidate == end)
+ || (c.version.majorVersion() > candidate->version.majorVersion())
+ || ((c.version.majorVersion() == candidate->version.majorVersion())
+ && (c.version.minorVersion() > candidate->version.minorVersion()))) {
if (base) {
componentUrl = resolveLocalUrl(QString(url + c.typeName + dotqml_string), c.fileName);
if (c.internal) {
@@ -799,12 +823,9 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
if (!base) // ensure we have a componentUrl
componentUrl = resolveLocalUrl(QString(url + candidate->typeName + dotqml_string), candidate->fileName);
QQmlType returnType = QQmlMetaType::typeForUrl(componentUrl, type, isCompositeSingleton,
- nullptr, candidate->majorVersion,
- candidate->minorVersion);
- if (vmajor)
- *vmajor = candidate->majorVersion;
- if (vminor)
- *vminor = candidate->minorVersion;
+ nullptr, candidate->version);
+ if (version_return)
+ *version_return = candidate->version;
if (type_return)
*type_return = returnType;
return returnType.isValid();
@@ -856,14 +877,14 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader, const QHashedSt
return false;
}
-bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor,
+bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, QTypeRevision *version_return,
QQmlType *type_return, QList<QQmlError> *errors,
QQmlType::RegistrationType registrationType,
bool *typeRecursionDetected)
{
const QVector<QHashedStringRef> splitName = type.split(Dot);
auto resolveTypeInNamespace = [&](QHashedStringRef unqualifiedtype, QQmlImportNamespace *nameSpace, QList<QQmlError> *errors) -> bool {
- if (nameSpace->resolveType(typeLoader, unqualifiedtype, vmajor, vminor, type_return, &base, errors,
+ if (nameSpace->resolveType(typeLoader, unqualifiedtype, version_return, type_return, &base, errors,
registrationType, typeRecursionDetected))
return true;
if (nameSpace->imports.count() == 1 && !nameSpace->imports.at(0)->isLibrary && type_return && nameSpace != &unqualifiedset) {
@@ -976,7 +997,7 @@ QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const
}
bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
- int *vmajor, int *vminor, QQmlType *type_return,
+ QTypeRevision *version_return, QQmlType *type_return,
QString *base, QList<QQmlError> *errors,
QQmlType::RegistrationType registrationType,
bool *typeRecursionDetected)
@@ -996,13 +1017,13 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS
}
for (int i=0; i<imports.count(); ++i) {
const QQmlImportInstance *import = imports.at(i);
- if (import->resolveType(typeLoader, type, vmajor, vminor, type_return, base,
+ if (import->resolveType(typeLoader, type, version_return, type_return, base,
typeRecursionDetected, registrationType, recursionRestriction, errors)) {
if (qmlCheckTypes()) {
// check for type clashes
for (int j = i+1; j<imports.count(); ++j) {
const QQmlImportInstance *import2 = imports.at(j);
- if (import2->resolveType(typeLoader, type, vmajor, vminor, nullptr, base,
+ if (import2->resolveType(typeLoader, type, version_return, nullptr, base,
nullptr, registrationType)) {
if (errors) {
QString u1 = import->url;
@@ -1029,9 +1050,11 @@ bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedS
error.setDescription(QQmlImportDatabase::tr("is ambiguous. Found in %1 and in %2").arg(u1).arg(u2));
} else {
error.setDescription(QQmlImportDatabase::tr("is ambiguous. Found in %1 in version %2.%3 and %4.%5")
- .arg(u1)
- .arg(import->majversion).arg(import->minversion)
- .arg(import2->majversion).arg(import2->minversion));
+ .arg(u1)
+ .arg(import->version.majorVersion())
+ .arg(import->version.minorVersion())
+ .arg(import2->version.majorVersion())
+ .arg(import2->version.minorVersion()));
}
errors->prepend(error);
}
@@ -1088,18 +1111,19 @@ QQmlImportNamespace *QQmlImportsPrivate::findQualifiedNamespace(const QHashedStr
QtQml.Models, \a vmaj is 2, and \a vmin is 0, this method returns the following:
[QtQml.Models.2.0, QtQml.2.0.Models, QtQml.Models.2, QtQml.2.Models, QtQml.Models]
*/
-static QStringList versionUriList(const QString &uri, int vmaj, int vmin)
+static QStringList versionUriList(const QString &uri, QTypeRevision version)
{
QStringList result;
- for (int version = QQmlImports::FullyVersioned; version <= QQmlImports::Unversioned; ++version) {
+ for (int mode = QQmlImports::FullyVersioned; mode <= QQmlImports::Unversioned; ++mode) {
int index = uri.length();
do {
QString versionUri = uri;
- versionUri.insert(index, QQmlImports::versionString(vmaj, vmin, static_cast<QQmlImports::ImportVersion>(version)));
+ versionUri.insert(index, QQmlImports::versionString(
+ version, QQmlImports::ImportVersion(mode)));
result += versionUri;
index = uri.lastIndexOf(Dot, index - 1);
- } while (index > 0 && version != QQmlImports::Unversioned);
+ } while (index > 0 && mode != QQmlImports::Unversioned);
}
return result;
}
@@ -1164,8 +1188,7 @@ Import an extension defined by a qmldir file.
\a qmldirFilePath is a raw file path.
*/
bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
- const QString &uri,
- int vmaj, int vmin,
+ const QString &uri, QTypeRevision version,
QQmlImportDatabase *database,
const QQmlTypeLoaderQmldirContent &qmldir,
QList<QQmlError> *errors)
@@ -1190,13 +1213,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
if (qmldirPluginCount == 0)
return true;
- if (database->qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(qmldirFilePath)) {
- if ((vmaj >= 0 && vmin >= 0)
- ? !QQmlMetaType::isModule(uri, vmaj, vmin)
- : !QQmlMetaType::isAnyModule(uri)) {
- QQmlMetaType::qmlRegisterModuleTypes(uri, vmaj);
- }
- } else {
+ if (!database->qmlDirFilesForWhichPluginsHaveBeenLoaded.contains(qmldirFilePath)) {
// First search for listed qmldir plugins dynamically. If we cannot resolve them all, we continue
// searching static plugins that has correct metadata uri. Note that since we only know the uri
// for a static plugin, and not the filename, we cannot know which static plugin belongs to which
@@ -1218,7 +1235,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name);
if (!resolvedFilePath.isEmpty()) {
dynamicPluginsFound++;
- if (!database->importDynamicPlugin(resolvedFilePath, uri, typeNamespace, vmaj, errors)) {
+ if (!database->importDynamicPlugin(resolvedFilePath, uri, typeNamespace, version, errors)) {
if (errors) {
// XXX TODO: should we leave the import plugin error alone?
// Here, we pop it off the top and coalesce it into this error's message.
@@ -1243,7 +1260,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
// versioned to unversioned, we need to compare with differnt version strings. If a module
// has several plugins, they must all have the same version. Start by populating pluginPairs
// with relevant plugins to cut the list short early on:
- const QStringList versionUris = versionUriList(uri, vmaj, vmin);
+ const QStringList versionUris = versionUriList(uri, version);
QVector<StaticPluginPair> pluginPairs;
if (!populatePluginPairVector(pluginPairs, uri, versionUris, qmldirFilePath, errors))
return false;
@@ -1255,7 +1272,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
if (versionUri == metaTagUri.toString()) {
staticPluginsFound++;
QObject *instance = pair.first.instance();
- if (!database->importStaticPlugin(instance, basePath, uri, typeNamespace, vmaj, errors)) {
+ if (!database->importStaticPlugin(instance, basePath, uri, typeNamespace, version, errors)) {
if (errors) {
QQmlError poppedError = errors->takeFirst();
QQmlError error;
@@ -1358,11 +1375,9 @@ and fills in outQmldirFilePath and outQmldirUrl appropriately. Otherwise return
false.
*/
QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir(
- const QString &uri, int vmaj, int vmin, QQmlImportDatabase *database,
+ const QString &uri, QTypeRevision version, QQmlImportDatabase *database,
QString *outQmldirFilePath, QString *outQmldirPathUrl)
{
- Q_ASSERT(vmaj >= 0 && vmin >= 0); // Versions are always specified for libraries
-
// Check cache first
QQmlImportDatabase::QmldirCache *cacheHead = nullptr;
@@ -1372,7 +1387,7 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir(
cacheHead = *cachePtr;
QQmlImportDatabase::QmldirCache *cache = cacheHead;
while (cache) {
- if (cache->versionMajor == vmaj && cache->versionMinor == vmin) {
+ if (cache->version == version) {
*outQmldirFilePath = cache->qmldirFilePath;
*outQmldirPathUrl = cache->qmldirPathUrl;
return cache->qmldirFilePath.isEmpty() ? QQmlImports::QmldirNotFound
@@ -1383,20 +1398,21 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir(
}
}
- QQmlTypeLoader &typeLoader = QQmlEnginePrivate::get(database->engine)->typeLoader;
+ QQmlEnginePrivate *enginePrivate = QQmlEnginePrivate::get(database->engine);
+ QQmlTypeLoader &typeLoader = enginePrivate->typeLoader;
+ const bool hasInterceptors = !enginePrivate->urlInterceptors.isEmpty();
// Interceptor might redirect remote files to local ones.
- QQmlAbstractUrlInterceptor *interceptor = typeLoader.engine()->urlInterceptor();
QStringList localImportPaths = database->importPathList(
- interceptor ? QQmlImportDatabase::LocalOrRemote : QQmlImportDatabase::Local);
+ hasInterceptors ? QQmlImportDatabase::LocalOrRemote : QQmlImportDatabase::Local);
// Search local import paths for a matching version
const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(
- uri, localImportPaths, vmaj, vmin);
+ uri, localImportPaths, version);
bool pathTurnedRemote = false;
for (QString qmldirPath : qmlDirPaths) {
- if (interceptor) {
- const QUrl intercepted = interceptor->intercept(
+ if (hasInterceptors) {
+ const QUrl intercepted = database->engine->interceptUrl(
QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath),
QQmlAbstractUrlInterceptor::QmldirFile);
qmldirPath = QQmlFile::urlToLocalFileOrQrc(intercepted);
@@ -1414,8 +1430,7 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir(
url = QUrl::fromLocalFile(absolutePath.toString()).toString();
QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache;
- cache->versionMajor = vmaj;
- cache->versionMinor = vmin;
+ cache->version = version;
cache->qmldirFilePath = absoluteFilePath;
cache->qmldirPathUrl = url;
cache->next = cacheHead;
@@ -1429,19 +1444,19 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir(
}
QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache;
- cache->versionMajor = vmaj;
- cache->versionMinor = vmin;
+ cache->version = version;
cache->next = cacheHead;
database->qmldirCache.insert(uri, cache);
return pathTurnedRemote ? QQmlImports::QmldirInterceptedToRemote : QQmlImports::QmldirNotFound;
}
-bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir, const QString &uri, int vmaj, int vmin,
+bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent &qmldir,
+ const QString &uri, QTypeRevision version,
QList<QQmlError> *errors)
{
- int lowest_min = INT_MAX;
- int highest_min = INT_MIN;
+ quint8 lowest_min = std::numeric_limits<quint8>::max();
+ quint8 highest_min = 0;
typedef QQmlDirComponents::const_iterator ConstIterator;
const QQmlDirComponents &components = qmldir.components();
@@ -1449,21 +1464,20 @@ bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent
ConstIterator cend = components.constEnd();
for (ConstIterator cit = components.constBegin(); cit != cend; ++cit) {
for (ConstIterator cit2 = components.constBegin(); cit2 != cit; ++cit2) {
- if ((cit2->typeName == cit->typeName) &&
- (cit2->majorVersion == cit->majorVersion) &&
- (cit2->minorVersion == cit->minorVersion)) {
+ if (cit2->typeName == cit->typeName && cit2->version == cit->version) {
// This entry clashes with a predecessor
QQmlError error;
error.setDescription(QQmlImportDatabase::tr("\"%1\" version %2.%3 is defined more than once in module \"%4\"")
- .arg(cit->typeName).arg(cit->majorVersion).arg(cit->minorVersion).arg(uri));
+ .arg(cit->typeName).arg(cit->version.majorVersion())
+ .arg(cit->version.minorVersion()).arg(uri));
errors->prepend(error);
return false;
}
}
- if (cit->majorVersion == vmaj) {
- lowest_min = qMin(lowest_min, cit->minorVersion);
- highest_min = qMax(highest_min, cit->minorVersion);
+ if (cit->version.majorVersion() == version.majorVersion()) {
+ lowest_min = qMin(lowest_min, cit->version.minorVersion());
+ highest_min = qMax(highest_min, cit->version.minorVersion());
}
}
@@ -1473,27 +1487,27 @@ bool QQmlImportsPrivate::validateQmldirVersion(const QQmlTypeLoaderQmldirContent
SConstIterator send = scripts.constEnd();
for (SConstIterator sit = scripts.constBegin(); sit != send; ++sit) {
for (SConstIterator sit2 = scripts.constBegin(); sit2 != sit; ++sit2) {
- if ((sit2->nameSpace == sit->nameSpace) &&
- (sit2->majorVersion == sit->majorVersion) &&
- (sit2->minorVersion == sit->minorVersion)) {
+ if (sit2->nameSpace == sit->nameSpace && sit2->version == sit->version) {
// This entry clashes with a predecessor
QQmlError error;
error.setDescription(QQmlImportDatabase::tr("\"%1\" version %2.%3 is defined more than once in module \"%4\"")
- .arg(sit->nameSpace).arg(sit->majorVersion).arg(sit->minorVersion).arg(uri));
+ .arg(sit->nameSpace).arg(sit->version.majorVersion())
+ .arg(sit->version.minorVersion()).arg(uri));
errors->prepend(error);
return false;
}
}
- if (sit->majorVersion == vmaj) {
- lowest_min = qMin(lowest_min, sit->minorVersion);
- highest_min = qMax(highest_min, sit->minorVersion);
+ if (sit->version.majorVersion() == version.majorVersion()) {
+ lowest_min = qMin(lowest_min, sit->version.minorVersion());
+ highest_min = qMax(highest_min, sit->version.minorVersion());
}
}
- if (lowest_min > vmin || highest_min < vmin) {
+ if (lowest_min > version.minorVersion() || highest_min < version.minorVersion()) {
QQmlError error;
- error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin));
+ error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed")
+ .arg(uri).arg(version.majorVersion()).arg(version.minorVersion()));
errors->prepend(error);
return false;
}
@@ -1520,10 +1534,9 @@ QQmlImportNamespace *QQmlImportsPrivate::importNamespace(const QString &prefix)
return nameSpace;
}
-QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace *nameSpace,
- const QString &uri, const QString &url, int vmaj, int vmin,
- QV4::CompiledData::Import::ImportType type,
- QList<QQmlError> *errors, bool lowPrecedence)
+QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(
+ QQmlImportNamespace *nameSpace, const QString &uri, const QString &url, QTypeRevision version,
+ QV4::CompiledData::Import::ImportType type, QList<QQmlError> *errors, bool lowPrecedence)
{
Q_ASSERT(nameSpace);
Q_ASSERT(errors);
@@ -1534,8 +1547,7 @@ QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace
import->uri = uri;
import->url = url;
import->localDirectoryPath = QQmlFile::urlToLocalFileOrQrc(url);
- import->majversion = vmaj;
- import->minversion = vmin;
+ import->version = version;
import->isLibrary = (type == QV4::CompiledData::Import::ImportLibrary);
if (lowPrecedence)
@@ -1546,10 +1558,10 @@ QQmlImportInstance *QQmlImportsPrivate::addImportToNamespace(QQmlImportNamespace
return import;
}
-bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &prefix,
- int vmaj, int vmin, const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete,
- QQmlImportDatabase *database,
- QList<QQmlError> *errors)
+bool QQmlImportsPrivate::addLibraryImport(
+ const QString& uri, const QString &prefix, QTypeRevision version,
+ const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete,
+ QQmlImportDatabase *database, QList<QQmlError> *errors)
{
Q_ASSERT(database);
Q_ASSERT(errors);
@@ -1557,7 +1569,9 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre
QQmlImportNamespace *nameSpace = importNamespace(prefix);
Q_ASSERT(nameSpace);
- QQmlImportInstance *inserted = addImportToNamespace(nameSpace, uri, qmldirUrl, vmaj, vmin, QV4::CompiledData::Import::ImportLibrary, errors);
+ QQmlImportInstance *inserted = addImportToNamespace(
+ nameSpace, uri, qmldirUrl, version,
+ QV4::CompiledData::Import::ImportLibrary, errors);
Q_ASSERT(inserted);
if (!incomplete) {
@@ -1568,7 +1582,7 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre
return false;
if (qmldir.hasContent()) {
- if (!importExtension(qmldir.pluginLocation(), uri, vmaj, vmin, database, qmldir, errors))
+ if (!importExtension(qmldir.pluginLocation(), uri, version, database, qmldir, errors))
return false;
if (!inserted->setQmldirContent(qmldirUrl, qmldir, nameSpace, errors))
@@ -1577,18 +1591,26 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre
}
// Ensure that we are actually providing something
- if ((vmaj < 0) || (vmin < 0) || !QQmlMetaType::isModule(uri, vmaj, vmin)) {
+ if (!QQmlMetaType::isModule(uri, version)) {
if (inserted->qmlDirComponents.isEmpty() && inserted->qmlDirScripts.isEmpty()) {
QQmlError error;
- if (QQmlMetaType::isAnyModule(uri))
- error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin));
- else
- error.setDescription(QQmlImportDatabase::tr("module \"%1\" is not installed").arg(uri));
+ if (QQmlMetaType::isAnyModule(uri)) {
+ error.setDescription(QQmlImportDatabase::tr(
+ "module \"%1\" version %2.%3 is not installed")
+ .arg(uri).arg(version.majorVersion())
+ .arg(version.hasMinorVersion()
+ ? QString::number(version.minorVersion())
+ : QLatin1String("x")));
+ } else {
+ error.setDescription(QQmlImportDatabase::tr("module \"%1\" is not installed")
+ .arg(uri));
+ }
errors->prepend(error);
return false;
- } else if ((vmaj >= 0) && (vmin >= 0) && qmldir.hasContent()) {
+ } else if (version.hasMajorVersion() && version.hasMinorVersion()
+ && qmldir.hasContent()) {
// Verify that the qmldir content is valid for this version
- if (!validateQmldirVersion(qmldir, uri, vmaj, vmin, errors))
+ if (!validateQmldirVersion(qmldir, uri, version, errors))
return false;
}
}
@@ -1597,10 +1619,9 @@ bool QQmlImportsPrivate::addLibraryImport(const QString& uri, const QString &pre
return true;
}
-bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix,
- int vmaj, int vmin,
- bool isImplicitImport, bool incomplete, QQmlImportDatabase *database,
- QList<QQmlError> *errors)
+bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix, QTypeRevision version,
+ bool isImplicitImport, bool incomplete,
+ QQmlImportDatabase *database, QList<QQmlError> *errors)
{
Q_ASSERT(errors);
@@ -1613,10 +1634,8 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
QString qmldirUrl = resolveLocalUrl(base, importUri + (importUri.endsWith(Slash)
? String_qmldir
: Slash_qmldir));
- if (QQmlAbstractUrlInterceptor *interceptor = typeLoader->engine()->urlInterceptor()) {
- qmldirUrl = interceptor->intercept(QUrl(qmldirUrl),
- QQmlAbstractUrlInterceptor::QmldirFile).toString();
- }
+ qmldirUrl = typeLoader->engine()->interceptUrl(
+ QUrl(qmldirUrl), QQmlAbstractUrlInterceptor::QmldirFile).toString();
QString qmldirIdentifier;
if (QQmlFile::isLocalFile(qmldirUrl)) {
@@ -1676,7 +1695,9 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
}
}
- QQmlImportInstance *inserted = addImportToNamespace(nameSpace, importUri, url, vmaj, vmin, QV4::CompiledData::Import::ImportFile, errors, isImplicitImport);
+ QQmlImportInstance *inserted = addImportToNamespace(
+ nameSpace, importUri, url, version, QV4::CompiledData::Import::ImportFile,
+ errors, isImplicitImport);
Q_ASSERT(inserted);
if (!incomplete && !qmldirIdentifier.isEmpty()) {
@@ -1685,7 +1706,7 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
return false;
if (qmldir.hasContent()) {
- if (!importExtension(qmldir.pluginLocation(), importUri, vmaj, vmin, database, qmldir, errors))
+ if (!importExtension(qmldir.pluginLocation(), importUri, version, database, qmldir, errors))
return false;
if (!inserted->setQmldirContent(url, qmldir, nameSpace, errors))
@@ -1709,26 +1730,27 @@ bool QQmlImportsPrivate::updateQmldirContent(const QString &uri, const QString &
return false;
if (qmldir.hasContent()) {
- int vmaj = import->majversion;
- int vmin = import->minversion;
- if (!importExtension(qmldir.pluginLocation(), uri, vmaj, vmin, database, qmldir, errors))
+ QTypeRevision version = import->version;
+ if (!importExtension(qmldir.pluginLocation(), uri, version, database, qmldir, errors))
return false;
if (import->setQmldirContent(qmldirUrl, qmldir, nameSpace, errors)) {
if (import->qmlDirComponents.isEmpty() && import->qmlDirScripts.isEmpty()) {
// The implicit import qmldir can be empty, and plugins have no extra versions
- if (uri != QLatin1String(".") && !QQmlMetaType::isModule(uri, vmaj, vmin)) {
+ if (uri != QLatin1String(".") && !QQmlMetaType::isModule(uri, version)) {
QQmlError error;
- if (QQmlMetaType::isAnyModule(uri))
- error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri).arg(vmaj).arg(vmin));
- else
+ if (QQmlMetaType::isAnyModule(uri)) {
+ error.setDescription(QQmlImportDatabase::tr("module \"%1\" version %2.%3 is not installed")
+ .arg(uri).arg(version.majorVersion()).arg(version.minorVersion()));
+ } else {
error.setDescription(QQmlImportDatabase::tr("module \"%1\" is not installed").arg(uri));
+ }
errors->prepend(error);
return false;
}
- } else if ((vmaj >= 0) && (vmin >= 0)) {
+ } else if (version.hasMajorVersion() && version.hasMinorVersion()) {
// Verify that the qmldir content is valid for this version
- if (!validateQmldirVersion(qmldir, uri, vmaj, vmin, errors))
+ if (!validateQmldirVersion(qmldir, uri, version, errors))
return false;
}
return true;
@@ -1762,7 +1784,8 @@ bool QQmlImports::addImplicitImport(QQmlImportDatabase *importDb, QList<QQmlErro
<< ")::addImplicitImport";
bool incomplete = !isLocal(baseUrl());
- return d->addFileImport(QLatin1String("."), QString(), -1, -1, true, incomplete, importDb, errors);
+ return d->addFileImport(QLatin1String("."), QString(), QTypeRevision(), true, incomplete,
+ importDb, errors);
}
/*!
@@ -1773,8 +1796,7 @@ bool QQmlImports::addInlineComponentImport(QQmlImportInstance *const importInsta
importInstance->url = importUrl.toString();
importInstance->uri = name;
importInstance->isInlineComponent = true;
- importInstance->majversion = 0;
- importInstance->minversion = 0;
+ importInstance->version = QTypeRevision::zero();
importInstance->containingType = containingType;
d->unqualifiedset.imports.push_back(importInstance);
d->unqualifiedset.setNeedsSorting(true);
@@ -1803,7 +1825,7 @@ bool QQmlImports::addInlineComponentImport(QQmlImportInstance *const importInsta
filled appropriately.
*/
bool QQmlImports::addFileImport(QQmlImportDatabase *importDb,
- const QString& uri, const QString& prefix, int vmaj, int vmin,
+ const QString& uri, const QString& prefix, QTypeRevision version,
bool incomplete, QList<QQmlError> *errors)
{
Q_ASSERT(importDb);
@@ -1811,13 +1833,13 @@ bool QQmlImports::addFileImport(QQmlImportDatabase *importDb,
if (qmlImportTrace())
qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) << ')' << "::addFileImport: "
- << uri << ' ' << vmaj << '.' << vmin << " as " << prefix;
+ << uri << ' ' << version << " as " << prefix;
- return d->addFileImport(uri, prefix, vmaj, vmin, false, incomplete, importDb, errors);
+ return d->addFileImport(uri, prefix, version, false, incomplete, importDb, errors);
}
bool QQmlImports::addLibraryImport(QQmlImportDatabase *importDb,
- const QString &uri, const QString &prefix, int vmaj, int vmin,
+ const QString &uri, const QString &prefix, QTypeRevision version,
const QString &qmldirIdentifier, const QString& qmldirUrl, bool incomplete, QList<QQmlError> *errors)
{
Q_ASSERT(importDb);
@@ -1825,9 +1847,9 @@ bool QQmlImports::addLibraryImport(QQmlImportDatabase *importDb,
if (qmlImportTrace())
qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) << ')' << "::addLibraryImport: "
- << uri << ' ' << vmaj << '.' << vmin << " as " << prefix;
+ << uri << ' ' << version << " as " << prefix;
- return d->addLibraryImport(uri, prefix, vmaj, vmin, qmldirIdentifier, qmldirUrl, incomplete, importDb, errors);
+ return d->addLibraryImport(uri, prefix, version, qmldirIdentifier, qmldirUrl, incomplete, importDb, errors);
}
bool QQmlImports::updateQmldirContent(QQmlImportDatabase *importDb,
@@ -1845,10 +1867,10 @@ bool QQmlImports::updateQmldirContent(QQmlImportDatabase *importDb,
}
QQmlImports::LocalQmldirResult QQmlImports::locateLocalQmldir(
- QQmlImportDatabase *importDb, const QString &uri, int vmaj, int vmin,
+ QQmlImportDatabase *importDb, const QString &uri, QTypeRevision version,
QString *qmldirFilePath, QString *url)
{
- return d->locateLocalQmldir(uri, vmaj, vmin, importDb, qmldirFilePath, url);
+ return d->locateLocalQmldir(uri, version, importDb, qmldirFilePath, url);
}
bool QQmlImports::isLocal(const QString &url)
@@ -2157,19 +2179,21 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths)
\internal
*/
static bool registerPluginTypes(QObject *instance, const QString &basePath, const QString &uri,
- const QString &typeNamespace, int vmaj, QList<QQmlError> *errors)
+ const QString &typeNamespace, QTypeRevision version,
+ QList<QQmlError> *errors)
{
if (qmlImportTrace())
qDebug().nospace() << "QQmlImportDatabase::registerPluginTypes: " << uri << " from " << basePath;
- if (!QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors))
+ if (!QQmlMetaType::registerPluginTypes(instance, basePath, uri, typeNamespace, version, errors))
return false;
- if (vmaj >= 0 && !typeNamespace.isEmpty() && !QQmlMetaType::protectModule(uri, vmaj)) {
+ if (version.hasMajorVersion() && !typeNamespace.isEmpty()
+ && !QQmlMetaType::protectModule(uri, version)) {
QQmlError error;
error.setDescription(
QString::fromLatin1("Cannot protect module %1 %2 as it was never registered")
- .arg(uri).arg(vmaj));
+ .arg(uri).arg(version.majorVersion()));
errors->append(error);
return false;
}
@@ -2180,8 +2204,9 @@ static bool registerPluginTypes(QObject *instance, const QString &basePath, cons
/*!
\internal
*/
-bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &basePath,
- const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors)
+bool QQmlImportDatabase::importStaticPlugin(
+ QObject *instance, const QString &basePath, const QString &uri,
+ const QString &typeNamespace, QTypeRevision version, QList<QQmlError> *errors)
{
// Dynamic plugins are differentiated by their filepath. For static plugins we
// don't have that information so we use their address as key instead.
@@ -2204,7 +2229,7 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
plugin.loader = nullptr;
plugins->insert(uniquePluginID, plugin);
- if (!registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors))
+ if (!registerPluginTypes(instance, basePath, uri, typeNamespace, version, errors))
return false;
}
@@ -2224,8 +2249,9 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
/*!
\internal
*/
-bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QString &uri,
- const QString &typeNamespace, int vmaj, QList<QQmlError> *errors)
+bool QQmlImportDatabase::importDynamicPlugin(
+ const QString &filePath, const QString &uri, const QString &typeNamespace,
+ QTypeRevision version, QList<QQmlError> *errors)
{
QFileInfo fileInfo(filePath);
const QString absoluteFilePath = fileInfo.absoluteFilePath();
@@ -2279,7 +2305,7 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr
plugins->insert(absoluteFilePath, plugin);
// Continue with shared code path for dynamic and static plugins:
- if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, vmaj, errors))
+ if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, version, errors))
return false;
}
}
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 594eae7bb4..f7f5c32bf4 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -81,8 +81,7 @@ struct QQmlImportInstance
QString url; // the base path of the import
QString localDirectoryPath; // the base path of the import if it's a local file
QQmlType containingType; // points to the containing type for inline components
- int majversion; // the major version imported
- int minversion; // the minor version imported
+ QTypeRevision version; // the version imported
bool isLibrary; // true means that this is not a file import
bool implicitlyImported = false;
bool isInlineComponent = false;
@@ -92,10 +91,11 @@ struct QQmlImportInstance
bool setQmldirContent(const QString &resolvedUrl, const QQmlTypeLoaderQmldirContent &qmldir,
QQmlImportNamespace *nameSpace, QList<QQmlError> *errors);
- static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts, int vmaj, int vmin);
+ static QQmlDirScripts getVersionedScripts(const QQmlDirScripts &qmldirscripts,
+ QTypeRevision version);
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
- int *vmajor, int *vminor, QQmlType* type_return,
+ QTypeRevision *version_return, QQmlType* type_return,
QString *base = nullptr, bool *typeRecursionDetected = nullptr,
QQmlType::RegistrationType = QQmlType::AnyRegistrationType,
QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion,
@@ -113,7 +113,7 @@ public:
QQmlImportInstance *findImport(const QString &uri) const;
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
- int *vmajor, int *vminor, QQmlType* type_return,
+ QTypeRevision *version_return, QQmlType* type_return,
QString *base = nullptr, QList<QQmlError> *errors = nullptr,
QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType,
bool *typeRecursionDeteced = nullptr);
@@ -145,14 +145,14 @@ public:
bool resolveType(const QHashedStringRef &type,
QQmlType *type_return,
- int *version_major, int *version_minor,
+ QTypeRevision *version_return,
QQmlImportNamespace **ns_return,
QList<QQmlError> *errors = nullptr,
QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType,
bool *typeRecursionDetected = nullptr) const;
bool resolveType(QQmlImportNamespace *,
const QHashedStringRef& type,
- QQmlType *type_return, int *version_major, int *version_minor,
+ QQmlType *type_return, QTypeRevision *version_return,
QQmlType::RegistrationType registrationType
= QQmlType::AnyRegistrationType) const;
@@ -161,11 +161,11 @@ public:
bool addInlineComponentImport(QQmlImportInstance *const importInstance, const QString &name, const QUrl importUrl, QQmlType containingType);
bool addFileImport(QQmlImportDatabase *,
- const QString& uri, const QString& prefix, int vmaj, int vmin, bool incomplete,
- QList<QQmlError> *errors);
+ const QString& uri, const QString& prefix, QTypeRevision version,
+ bool incomplete, QList<QQmlError> *errors);
bool addLibraryImport(QQmlImportDatabase *importDb,
- const QString &uri, const QString &prefix, int vmaj, int vmin,
+ const QString &uri, const QString &prefix, QTypeRevision version,
const QString &qmldirIdentifier, const QString &qmldirUrl, bool incomplete, QList<QQmlError> *errors);
bool updateQmldirContent(QQmlImportDatabase *importDb,
@@ -179,7 +179,7 @@ public:
};
LocalQmldirResult locateLocalQmldir(
- QQmlImportDatabase *, const QString &uri, int vmaj, int vmin,
+ QQmlImportDatabase *, const QString &uri, QTypeRevision version,
QString *qmldirFilePath, QString *url);
void populateCache(QQmlTypeNameCache *cache) const;
@@ -197,14 +197,14 @@ public:
{
QString typeName;
QString prefix;
- int majorVersion;
- int minorVersion;
+ QTypeRevision version;
};
QList<CompositeSingletonReference> resolvedCompositeSingletons() const;
- static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths, int vmaj, int vmin);
- static QString versionString(int vmaj, int vmin, ImportVersion version);
+ static QStringList completeQmldirPaths(const QString &uri, const QStringList &basePaths,
+ QTypeRevision version);
+ static QString versionString(QTypeRevision version, ImportVersion importVersion);
static bool isLocal(const QString &url);
static bool isLocal(const QUrl &url);
@@ -227,7 +227,9 @@ public:
~QQmlImportDatabase();
#if QT_CONFIG(library)
- bool importDynamicPlugin(const QString &filePath, const QString &uri, const QString &importNamespace, int vmaj, QList<QQmlError> *errors);
+ bool importDynamicPlugin(const QString &filePath, const QString &uri,
+ const QString &importNamespace, QTypeRevision version,
+ QList<QQmlError> *errors);
bool removeDynamicPlugin(const QString &filePath);
QStringList dynamicPlugins() const;
#endif
@@ -250,13 +252,13 @@ private:
const QString &qmldirPath, const QString &qmldirPluginPath,
const QString &baseName);
bool importStaticPlugin(QObject *instance, const QString &basePath, const QString &uri,
- const QString &typeNamespace, int vmaj, QList<QQmlError> *errors);
+ const QString &typeNamespace, QTypeRevision version,
+ QList<QQmlError> *errors);
void clearDirCache();
void finalizePlugin(QObject *instance, const QString &path, const QString &uri);
struct QmldirCache {
- int versionMajor;
- int versionMinor;
+ QTypeRevision version;
QString qmldirFilePath;
QString qmldirPathUrl;
QmldirCache *next;
diff --git a/src/qml/qml/qqmlincubator.cpp b/src/qml/qml/qqmlincubator.cpp
index 0ad013e90b..1f41934c3c 100644
--- a/src/qml/qml/qqmlincubator.cpp
+++ b/src/qml/qml/qqmlincubator.cpp
@@ -45,7 +45,8 @@
#include "qqmlobjectcreator_p.h"
#include <private/qqmlcomponent_p.h>
-void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
+void QQmlEnginePrivate::incubate(
+ QQmlIncubator &i, const QQmlRefPointer<QQmlContextData> &forContext)
{
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> p(i.d);
@@ -59,13 +60,13 @@ void QQmlEnginePrivate::incubate(QQmlIncubator &i, QQmlContextData *forContext)
// Need to find the first constructing context and see if it is asynchronous
QExplicitlySharedDataPointer<QQmlIncubatorPrivate> parentIncubator;
- QQmlContextData *cctxt = forContext;
+ QQmlRefPointer<QQmlContextData> cctxt = forContext;
while (cctxt) {
- if (!cctxt->hasExtraObject && cctxt->incubator) {
- parentIncubator = cctxt->incubator;
+ if (QQmlIncubatorPrivate *incubator = cctxt->incubator()) {
+ parentIncubator = incubator;
break;
}
- cctxt = cctxt->parent;
+ cctxt = cctxt->parent();
}
if (parentIncubator && parentIncubator->isAsynchronous) {
@@ -149,8 +150,8 @@ void QQmlIncubatorPrivate::clear()
}
enginePriv = nullptr;
if (!rootContext.isNull()) {
- if (!rootContext->hasExtraObject)
- rootContext->incubator = nullptr;
+ if (rootContext->incubator())
+ rootContext->setIncubator(nullptr);
rootContext = nullptr;
}
@@ -360,10 +361,8 @@ void QQmlIncubatorPrivate::incubate(QQmlInstantiationInterrupt &i)
if (watcher.hasRecursed())
return;
- QQmlContextData *ctxt = nullptr;
- ctxt = creator->finalize(i);
- if (ctxt) {
- rootContext = ctxt;
+ if (creator->finalize(i)) {
+ rootContext = creator->rootContext();
progress = QQmlIncubatorPrivate::Completed;
goto finishIncubate;
}
diff --git a/src/qml/qml/qqmlincubator_p.h b/src/qml/qml/qqmlincubator_p.h
index a674ff274f..b178c6aa29 100644
--- a/src/qml/qml/qqmlincubator_p.h
+++ b/src/qml/qml/qqmlincubator_p.h
@@ -46,7 +46,7 @@
#include <private/qqmlvme_p.h>
#include <private/qrecursionwatcher_p.h>
#include <private/qqmlengine_p.h>
-#include <private/qqmlcontext_p.h>
+#include <private/qqmlguardedcontextdata_p.h>
//
// W A R N I N G
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 6a9ef06159..0f83baa893 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -115,9 +115,21 @@ QQmlJavaScriptExpression::~QQmlJavaScriptExpression()
m_scopeObject.asT2()->_s = nullptr;
}
+QString QQmlJavaScriptExpression::expressionIdentifier() const
+{
+ if (auto f = function()) {
+ QString url = f->sourceFile();
+ uint lineNumber = f->compiledFunction->location.line;
+ uint columnNumber = f->compiledFunction->location.column;
+ return url + QString::asprintf(":%u:%u", lineNumber, columnNumber);
+ }
+
+ return QStringLiteral("[native code]");
+}
+
void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v)
{
- activeGuards.setFlagValue(v);
+ activeGuards.setTag(v ? NotifyOnValueChanged : NoGuardTag);
if (!v)
clearActiveGuards();
}
@@ -134,7 +146,7 @@ QQmlSourceLocation QQmlJavaScriptExpression::sourceLocation() const
return QQmlSourceLocation();
}
-void QQmlJavaScriptExpression::setContext(QQmlContextData *context)
+void QQmlJavaScriptExpression::setContext(const QQmlRefPointer<QQmlContextData> &context)
{
if (m_prevExpression) {
*m_prevExpression = m_nextExpression;
@@ -144,15 +156,10 @@ void QQmlJavaScriptExpression::setContext(QQmlContextData *context)
m_nextExpression = nullptr;
}
- m_context = context;
+ m_context = context.data();
- if (context) {
- m_nextExpression = context->expressions;
- if (m_nextExpression)
- m_nextExpression->m_prevExpression = &m_nextExpression;
- m_prevExpression = &context->expressions;
- context->expressions = this;
- }
+ if (context)
+ context->addExpression(this);
}
QV4::Function *QQmlJavaScriptExpression::function() const
@@ -166,7 +173,7 @@ void QQmlJavaScriptExpression::refresh()
QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
{
- QV4::ExecutionEngine *v4 = m_context->engine->handle();
+ QV4::ExecutionEngine *v4 = m_context->engine()->handle();
QV4::Scope scope(v4);
QV4::JSCallData jsCall(scope);
@@ -175,7 +182,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined)
{
- Q_ASSERT(m_context && m_context->engine);
+ Q_ASSERT(m_context && m_context->engine());
QV4::Function *v4Function = function();
if (!v4Function) {
@@ -184,14 +191,14 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
return QV4::Encode::undefined();
}
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine);
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_context->engine());
// All code that follows must check with watcher before it accesses data members
// incase we have been deleted.
DeleteWatcher watcher(this);
Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty());
- QQmlPropertyCapture capture(m_context->engine, this, &watcher);
+ QQmlPropertyCapture capture(m_context->engine(), this, &watcher);
QQmlPropertyCapture *lastPropertyCapture = ep->propertyCapture;
ep->propertyCapture = notifyOnValueChanged() ? &capture : nullptr;
@@ -200,7 +207,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
if (notifyOnValueChanged())
capture.guards.copyAndClearPrepend(activeGuards);
- QV4::ExecutionEngine *v4 = m_context->engine->handle();
+ QV4::ExecutionEngine *v4 = m_context->engine()->handle();
callData->thisObject = v4->globalObject;
if (scopeObject()) {
QV4::ReturnedValue scope = QV4::QObjectWrapper::wrap(v4, scopeObject());
@@ -337,10 +344,11 @@ QQmlDelayedError *QQmlJavaScriptExpression::delayedError()
}
QV4::ReturnedValue
-QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObject,
- const QString &code, const QString &filename, quint16 line)
+QQmlJavaScriptExpression::evalFunction(
+ const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scopeObject,
+ const QString &code, const QString &filename, quint16 line)
{
- QQmlEngine *engine = ctxt->engine;
+ QQmlEngine *engine = ctxt->engine();
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4 = engine->handle();
@@ -367,10 +375,11 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
return result->asReturnedValue();
}
-void QQmlJavaScriptExpression::createQmlBinding(QQmlContextData *ctxt, QObject *qmlScope,
- const QString &code, const QString &filename, quint16 line)
+void QQmlJavaScriptExpression::createQmlBinding(
+ const QQmlRefPointer<QQmlContextData> &ctxt, QObject *qmlScope, const QString &code,
+ const QString &filename, quint16 line)
{
- QQmlEngine *engine = ctxt->engine;
+ QQmlEngine *engine = ctxt->engine();
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4 = engine->handle();
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index eecee08062..f90b399b0a 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -52,6 +52,7 @@
//
#include <QtCore/qglobal.h>
+#include <QtCore/qtaggedpointer.h>
#include <QtQml/qqmlerror.h>
#include <private/qqmlengine_p.h>
@@ -102,7 +103,7 @@ public:
QQmlJavaScriptExpression();
virtual ~QQmlJavaScriptExpression();
- virtual QString expressionIdentifier() const = 0;
+ virtual QString expressionIdentifier() const;
virtual void expressionChanged() = 0;
QV4::ReturnedValue evaluate(bool *isUndefined);
@@ -118,10 +119,21 @@ public:
virtual QQmlSourceLocation sourceLocation() const;
- bool isValid() const { return context() != nullptr; }
+ bool hasContext() const { return m_context != nullptr; }
+ bool hasValidContext() const { return m_context && m_context->isValid(); }
+ QQmlContext *publicContext() const { return m_context ? m_context->asQQmlContext() : nullptr; }
- QQmlContextData *context() const { return m_context; }
- void setContext(QQmlContextData *context);
+ QQmlRefPointer<QQmlContextData> context() const { return m_context; }
+ void setContext(const QQmlRefPointer<QQmlContextData> &context);
+
+ void insertIntoList(QQmlJavaScriptExpression **listHead)
+ {
+ m_nextExpression = *listHead;
+ if (m_nextExpression)
+ m_nextExpression->m_prevExpression = &m_nextExpression;
+ m_prevExpression = listHead;
+ *listHead = this;
+ }
QV4::Function *function() const;
@@ -146,11 +158,16 @@ public:
void clearActiveGuards();
QQmlDelayedError *delayedError();
- static QV4::ReturnedValue evalFunction(QQmlContextData *ctxt, QObject *scope,
- const QString &code, const QString &filename,
- quint16 line);
+ static QV4::ReturnedValue evalFunction(
+ const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope, const QString &code,
+ const QString &filename, quint16 line);
+
+ QQmlEngine *engine() const { return m_context ? m_context->engine() : nullptr; }
+ bool hasUnresolvedNames() const { return m_context && m_context->hasUnresolvedNames(); }
+
protected:
- void createQmlBinding(QQmlContextData *ctxt, QObject *scope, const QString &code, const QString &filename, quint16 line);
+ void createQmlBinding(const QQmlRefPointer<QQmlContextData> &ctxt, QObject *scope,
+ const QString &code, const QString &filename, quint16 line);
void setupFunction(QV4::ExecutionContext *qmlContext, QV4::Function *f);
void setCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit);
@@ -159,10 +176,16 @@ protected:
// activeGuards:flag1 - notifyOnValueChanged
// activeGuards:flag2 - useSharedContext
QBiPointer<QObject, DeleteWatcher> m_scopeObject;
- QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> activeGuards;
- void setTranslationsCaptured(bool captured) { m_error.setFlagValue(captured); }
- bool translationsCaptured() const { return m_error.flag(); }
+ enum GuardTag {
+ NoGuardTag,
+ NotifyOnValueChanged
+ };
+
+ QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next, GuardTag> activeGuards;
+
+ void setTranslationsCaptured(bool captured) { if (captured) m_error.setTag(TranslationsCaptured); else m_error.setTag(NoTag); }
+ bool translationsCaptured() const { return m_error.tag() == TranslationsCaptured; }
private:
friend class QQmlContextData;
@@ -170,10 +193,17 @@ private:
friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
friend class QQmlTranslationBinding;
+ enum Tag {
+ NoTag,
+ TranslationsCaptured
+ };
+
// m_error:flag1 translationsCapturedDuringEvaluation
- QFlagPointer<QQmlDelayedError> m_error;
+ QTaggedPointer<QQmlDelayedError> m_error;
+ // Not refcounted as the context will clear the expressions when destructed.
QQmlContextData *m_context;
+
QQmlJavaScriptExpression **m_prevExpression;
QQmlJavaScriptExpression *m_nextExpression;
@@ -232,7 +262,7 @@ bool QQmlJavaScriptExpression::DeleteWatcher::wasDeleted() const
bool QQmlJavaScriptExpression::notifyOnValueChanged() const
{
- return activeGuards.flag();
+ return activeGuards.tag() == NotifyOnValueChanged;
}
QObject *QQmlJavaScriptExpression::scopeObject() const
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 7af6af276a..bc227ad713 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -835,7 +835,7 @@ QV4::ReturnedValue QQmlLocale::locale(ExecutionEngine *engine, const QString &lo
{
QLocale qlocale;
if (!localeName.isEmpty())
- qlocale = localeName;
+ qlocale = QLocale(localeName);
return wrap(engine, qlocale);
}
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index 1d6fdb12a7..d7bff5a1b7 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -96,7 +96,7 @@ class Q_QML_PRIVATE_EXPORT QQmlLocale
Q_GADGET
QML_NAMED_ELEMENT(Locale)
QML_UNCREATABLE("Locale cannot be instantiated. Use Qt.locale().")
- QML_ADDED_IN_MINOR_VERSION(2)
+ QML_ADDED_IN_VERSION(2, 2)
public:
~QQmlLocale();
diff --git a/src/qml/qml/qqmlloggingcategory_p.h b/src/qml/qml/qqmlloggingcategory_p.h
index c7377528b4..9cee029a9b 100644
--- a/src/qml/qml/qqmlloggingcategory_p.h
+++ b/src/qml/qml/qqmlloggingcategory_p.h
@@ -66,9 +66,9 @@ class QQmlLoggingCategory : public QObject, public QQmlParserStatus
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QString name READ name WRITE setName)
- Q_PROPERTY(DefaultLogLevel defaultLogLevel READ defaultLogLevel WRITE setDefaultLogLevel REVISION 12)
+ Q_PROPERTY(DefaultLogLevel defaultLogLevel READ defaultLogLevel WRITE setDefaultLogLevel REVISION(2, 12))
QML_NAMED_ELEMENT(LoggingCategory)
- QML_ADDED_IN_MINOR_VERSION(8)
+ QML_ADDED_IN_VERSION(2, 8)
public:
enum DefaultLogLevel {
diff --git a/src/qml/qml/qqmlmetaobject.cpp b/src/qml/qml/qqmlmetaobject.cpp
index a967f46b12..a87865fd81 100644
--- a/src/qml/qml/qqmlmetaobject.cpp
+++ b/src/qml/qml/qqmlmetaobject.cpp
@@ -44,12 +44,6 @@
QT_BEGIN_NAMESPACE
-struct StaticQtMetaObject : public QObject
-{
- static const QMetaObject *get()
- { return &staticQtMetaObject; }
-};
-
static bool isNamedEnumeratorInScope(const QMetaObject *resolvedMetaObject, const QByteArray &scope,
const QByteArray &name)
{
@@ -74,7 +68,7 @@ static bool isNamedEnumerator(const QMetaObject *metaObj, const QByteArray &scop
}
if (scope == "Qt")
- return isNamedEnumeratorInScope(StaticQtMetaObject::get(), scope, name);
+ return isNamedEnumeratorInScope(&Qt::staticMetaObject, scope, name);
if (isNamedEnumeratorInScope(metaObj, scope, name))
return true;
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index b2a769cab4..a90c85cac7 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -92,13 +92,8 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data,
d->typeId = type.typeId;
d->listId = type.listId;
d->isSetup = true;
- d->version_min = 0;
- if (type.version > 0) {
- d->module = QString::fromUtf8(type.uri);
- d->version_maj = type.versionMajor;
- } else {
- d->version_maj = 0;
- }
+ d->module = QString::fromUtf8(type.uri);
+ d->version = type.version;
data->registerType(d);
return d;
}
@@ -110,28 +105,20 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el
data->registerType(d);
d->setName(QString::fromUtf8(type.uri), elementName);
- d->version_maj = type.versionMajor;
- d->version_min = type.versionMinor;
-
- if (type.qobjectApi || (type.version >= 3 && type.generalizedQobjectApi)) {
- if (type.version >= 1) // static metaobject added in version 1
- d->baseMetaObject = type.instanceMetaObject;
- if (type.version >= 2) // typeId added in version 2
- d->typeId = type.typeId;
- if (type.version >= 2) // revisions added in version 2
- d->revision = type.revision;
+ d->version = type.version;
+
+ if (type.qObjectApi) {
+ d->baseMetaObject = type.instanceMetaObject;
+ d->typeId = type.typeId;
+ d->revision = type.revision;
}
d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo;
d->extraData.sd->singletonInstanceInfo->scriptCallback = type.scriptApi;
- if (type.version >= 3) {
- d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.generalizedQobjectApi;
- } else {
- d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qobjectApi;
- }
+ d->extraData.sd->singletonInstanceInfo->qobjectCallback = type.qObjectApi;
d->extraData.sd->singletonInstanceInfo->typeName = QString::fromUtf8(type.typeName);
d->extraData.sd->singletonInstanceInfo->instanceMetaObject
- = ((type.qobjectApi || (type.version >= 3 && type.generalizedQobjectApi) ) && type.version >= 1) ? type.instanceMetaObject : nullptr;
+ = type.qObjectApi ? type.instanceMetaObject : nullptr;
return d;
}
@@ -143,10 +130,8 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el
data->registerType(d);
d->setName(QString::fromUtf8(type.uri), elementName);
- d->version_maj = type.versionMajor;
- d->version_min = type.versionMinor;
- if (type.version >= 1) // revisions added in version 1
- d->revision = type.revision;
+ d->version = type.version;
+ d->revision = type.revision;
d->typeId = type.typeId;
d->listId = type.listId;
d->extraData.cd->allocationSize = type.objectSize;
@@ -181,8 +166,7 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el
auto *d = new QQmlTypePrivate(QQmlType::CompositeType);
data->registerType(d);
d->setName(QString::fromUtf8(type.uri), elementName);
- d->version_maj = type.versionMajor;
- d->version_min = type.versionMinor;
+ d->version = type.version;
d->extraData.fd->url = QQmlTypeLoader::normalize(type.url);
return d;
@@ -195,8 +179,7 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el
data->registerType(d);
d->setName(QString::fromUtf8(type.uri), elementName);
- d->version_maj = type.versionMajor;
- d->version_min = type.versionMinor;
+ d->version = type.version;
d->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo;
d->extraData.sd->singletonInstanceInfo->url = QQmlTypeLoader::normalize(type.url);
@@ -272,35 +255,32 @@ void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
}
}
-void QQmlMetaType::qmlInsertModuleRegistration(const QString &uri, int majorVersion,
- void (*registerFunction)())
+void QQmlMetaType::qmlInsertModuleRegistration(const QString &uri, void (*registerFunction)())
{
- const QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion);
QQmlMetaTypeDataPtr data;
- if (data->moduleTypeRegistrationFunctions.contains(versionedUri))
- qFatal("Cannot add multiple registrations for %s %d", qPrintable(uri), majorVersion);
+ if (data->moduleTypeRegistrationFunctions.contains(uri))
+ qFatal("Cannot add multiple registrations for %s", qPrintable(uri));
else
- data->moduleTypeRegistrationFunctions.insert(versionedUri, registerFunction);
+ data->moduleTypeRegistrationFunctions.insert(uri, registerFunction);
}
-void QQmlMetaType::qmlRemoveModuleRegistration(const QString &uri, int majorVersion)
+void QQmlMetaType::qmlRemoveModuleRegistration(const QString &uri)
{
- const QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion);
QQmlMetaTypeDataPtr data;
if (!data.isValid())
return; // shutdown/deletion race. Not a problem.
- if (!data->moduleTypeRegistrationFunctions.contains(versionedUri))
- qFatal("Cannot remove multiple registrations for %s %d", qPrintable(uri), majorVersion);
+ if (!data->moduleTypeRegistrationFunctions.contains(uri))
+ qFatal("Cannot remove multiple registrations for %s", qPrintable(uri));
else
- data->moduleTypeRegistrationFunctions.remove(versionedUri);
+ data->moduleTypeRegistrationFunctions.remove(uri);
}
-bool QQmlMetaType::qmlRegisterModuleTypes(const QString &uri, int majorVersion)
+bool QQmlMetaType::qmlRegisterModuleTypes(const QString &uri)
{
QQmlMetaTypeDataPtr data;
- return data->registerModuleTypes(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
+ return data->registerModuleTypes(uri);
}
/*!
@@ -333,11 +313,14 @@ void QQmlMetaType::clearTypeRegistrations()
data->undeletableTypes.clear();
}
-int QQmlMetaType::registerAutoParentFunction(const QQmlPrivate::RegisterAutoParent &autoparent)
+int QQmlMetaType::registerAutoParentFunction(const QQmlPrivate::RegisterAutoParent &function)
{
+ if (function.structVersion > 0)
+ qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
+
QQmlMetaTypeDataPtr data;
- data->parentFunctions.append(autoparent.function);
+ data->parentFunctions.append(function.function);
return data->parentFunctions.count() - 1;
}
@@ -350,22 +333,19 @@ void QQmlMetaType::unregisterAutoParentFunction(const QQmlPrivate::AutoParentFun
QQmlType QQmlMetaType::registerInterface(const QQmlPrivate::RegisterInterface &type)
{
- if (type.version > 1)
+ if (type.structVersion > 0)
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
QQmlMetaTypeDataPtr data;
QQmlTypePrivate *priv = createQQmlType(data, type);
Q_ASSERT(priv);
- data->idToType.insert(priv->typeId, priv);
- data->idToType.insert(priv->listId, priv);
- if (data->interfaces.size() <= type.typeId)
- data->interfaces.resize(type.typeId + 16);
- if (data->lists.size() <= type.listId)
- data->lists.resize(type.listId + 16);
- data->interfaces.setBit(type.typeId, true);
- data->lists.setBit(type.listId, true);
+ data->idToType.insert(priv->typeId.id(), priv);
+ data->idToType.insert(priv->listId.id(), priv);
+
+ data->interfaces.insert(type.typeId.id());
+ data->lists.insert(type.listId.id());
return QQmlType(priv);
}
@@ -386,7 +366,7 @@ QString registrationTypeString(QQmlType::RegistrationType typeType)
// NOTE: caller must hold a QMutexLocker on "data"
bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *data,
- const char *uri, const QString &typeName, int majorVersion)
+ const char *uri, const QString &typeName, QTypeRevision version)
{
if (!typeName.isEmpty()) {
if (typeName.at(0).isLower()) {
@@ -407,14 +387,14 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da
if (uri && !typeName.isEmpty()) {
QString nameSpace = QString::fromUtf8(uri);
- QQmlMetaTypeData::VersionedUri versionedUri;
- versionedUri.uri = nameSpace;
- versionedUri.majorVersion = majorVersion;
+ QQmlMetaTypeData::VersionedUri versionedUri(nameSpace, version);
if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)){
if (qqtm->isLocked()){
QString failure(QCoreApplication::translate("qmlRegisterType",
"Cannot install %1 '%2' into protected module '%3' version '%4'"));
- data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType)).arg(typeName).arg(nameSpace).arg(majorVersion));
+ data->recordTypeRegFailure(failure.arg(registrationTypeString(typeType))
+ .arg(typeName).arg(nameSpace)
+ .arg(version.majorVersion()));
return false;
}
}
@@ -424,9 +404,9 @@ bool checkRegistration(QQmlType::RegistrationType typeType, QQmlMetaTypeData *da
}
// NOTE: caller must hold a QMutexLocker on "data"
-QQmlTypeModule *getTypeModule(const QHashedString &uri, int majorVersion, QQmlMetaTypeData *data)
+QQmlTypeModule *getTypeModule(const QHashedString &uri, QTypeRevision version, QQmlMetaTypeData *data)
{
- QQmlMetaTypeData::VersionedUri versionedUri(uri, majorVersion);
+ QQmlMetaTypeData::VersionedUri versionedUri(uri, version);
QQmlTypeModule *module = data->uriToModule.value(versionedUri);
if (!module) {
module = new QQmlTypeModule(versionedUri.uri, versionedUri.majorVersion);
@@ -446,24 +426,20 @@ void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data)
if (type->baseMetaObject)
data->metaObjectToType.insert(type->baseMetaObject, type);
- if (type->typeId) {
- data->idToType.insert(type->typeId, type);
- if (data->objects.size() <= type->typeId)
- data->objects.resize(type->typeId + 16);
- data->objects.setBit(type->typeId, true);
+ if (type->typeId.isValid()) {
+ data->idToType.insert(type->typeId.id(), type);
+ data->objects.insert(type->typeId.id());
}
- if (type->listId) {
- if (data->lists.size() <= type->listId)
- data->lists.resize(type->listId + 16);
- data->lists.setBit(type->listId, true);
- data->idToType.insert(type->listId, type);
+ if (type->listId.isValid()) {
+ data->idToType.insert(type->listId.id(), type);
+ data->lists.insert(type->listId.id());
}
if (!type->module.isEmpty()) {
const QHashedString &mod = type->module;
- QQmlTypeModule *module = getTypeModule(mod, type->version_maj, data);
+ QQmlTypeModule *module = getTypeModule(mod, type->version, data);
Q_ASSERT(module);
module->add(type);
}
@@ -471,27 +447,33 @@ void addTypeToData(QQmlTypePrivate *type, QQmlMetaTypeData *data)
QQmlType QQmlMetaType::registerType(const QQmlPrivate::RegisterType &type)
{
+ if (type.structVersion > 0)
+ qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
+
QQmlMetaTypeDataPtr data;
QString elementName = QString::fromUtf8(type.elementName);
- if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.versionMajor))
+ if (!checkRegistration(QQmlType::CppType, data, type.uri, elementName, type.version))
return QQmlType();
QQmlTypePrivate *priv = createQQmlType(data, elementName, type);
addTypeToData(priv, data);
- if (!type.typeId)
- data->idToType.insert(priv->typeId, priv);
+ if (!type.typeId.isValid())
+ data->idToType.insert(priv->typeId.id(), priv);
return QQmlType(priv);
}
QQmlType QQmlMetaType::registerSingletonType(const QQmlPrivate::RegisterSingletonType &type)
{
+ if (type.structVersion > 0)
+ qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
+
QQmlMetaTypeDataPtr data;
QString typeName = QString::fromUtf8(type.typeName);
- if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.versionMajor))
+ if (!checkRegistration(QQmlType::SingletonType, data, type.uri, typeName, type.version))
return QQmlType();
QQmlTypePrivate *priv = createQQmlType(data, typeName, type);
@@ -503,6 +485,9 @@ QQmlType QQmlMetaType::registerSingletonType(const QQmlPrivate::RegisterSingleto
QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type)
{
+ if (type.structVersion > 0)
+ qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
+
// Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type.
QQmlMetaTypeDataPtr data;
@@ -511,7 +496,7 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe
if (*(type.uri) == '\0')
fileImport = true;
if (!checkRegistration(QQmlType::CompositeSingletonType, data, fileImport ? nullptr : type.uri,
- typeName, type.versionMajor)) {
+ typeName, type.version)) {
return QQmlType();
}
@@ -526,6 +511,9 @@ QQmlType QQmlMetaType::registerCompositeSingletonType(const QQmlPrivate::Registe
QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterCompositeType &type)
{
+ if (type.structVersion > 0)
+ qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
+
// Assumes URL is absolute and valid. Checking of user input should happen before the URL enters type.
QQmlMetaTypeDataPtr data;
@@ -533,7 +521,7 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit
bool fileImport = false;
if (*(type.uri) == '\0')
fileImport = true;
- if (!checkRegistration(QQmlType::CompositeType, data, fileImport?nullptr:type.uri, typeName, type.versionMajor))
+ if (!checkRegistration(QQmlType::CompositeType, data, fileImport?nullptr:type.uri, typeName, type.version))
return QQmlType();
QQmlTypePrivate *priv = createQQmlType(data, typeName, type);
@@ -545,26 +533,50 @@ QQmlType QQmlMetaType::registerCompositeType(const QQmlPrivate::RegisterComposit
return QQmlType(priv);
}
+
+
+template <typename T>
+struct QQmlMetaTypeInterface : QtPrivate::QMetaTypeInterface
+{
+ const QByteArray name;
+ QQmlMetaTypeInterface(const QByteArray &name)
+ : QMetaTypeInterface {
+ /*.revision=*/ 0,
+ /*.size=*/ sizeof(T),
+ /*.alignment=*/ alignof(T),
+ /*.flags=*/ QtPrivate::QMetaTypeTypeFlags<T>::Flags,
+ /*.metaObject=*/ nullptr,
+ /*.name=*/ name.constData(),
+ /*.typeId=*/ 0,
+ /*.ref=*/ { Q_BASIC_ATOMIC_INITIALIZER(0) },
+ /*.deleteSelf=*/ [](QMetaTypeInterface *self) {
+ delete static_cast<QQmlMetaTypeInterface *>(self);
+ },
+ /*.defaultCtr=*/ [](const QMetaTypeInterface *, void *addr) { new (addr) T(); },
+ /*.copyCtr=*/ [](const QMetaTypeInterface *, void *addr, const void *other) {
+ new (addr) T(*reinterpret_cast<const T *>(other));
+ },
+ /*.moveCtr=*/ [](const QMetaTypeInterface *, void *addr, void *other) {
+ new (addr) T(std::move(*reinterpret_cast<T *>(other)));
+ },
+ /*.dtor=*/ [](const QMetaTypeInterface *, void *addr) {
+ reinterpret_cast<T *>(addr)->~T();
+ },
+ /*.legacyRegisterOp=*/ nullptr
+ }
+ , name(name) { }
+};
+
CompositeMetaTypeIds QQmlMetaType::registerInternalCompositeType(const QByteArray &className)
{
QByteArray ptr = className + '*';
QByteArray lst = "QQmlListProperty<" + className + '>';
- int ptr_type = QMetaType::registerNormalizedType(ptr,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct,
- sizeof(QObject*),
- static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
- nullptr);
- int lst_type = QMetaType::registerNormalizedType(lst,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct,
- sizeof(QQmlListProperty<QObject>),
- static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<QObject> >::Flags),
- static_cast<QMetaObject*>(nullptr));
+ QMetaType ptr_type(new QQmlMetaTypeInterface<QObject*>(ptr));
+ QMetaType lst_type(new QQmlMetaTypeInterface<QQmlListProperty<QObject>>(lst));
QQmlMetaTypeDataPtr data;
- data->qmlLists.insert(lst_type, ptr_type);
+ data->qmlLists.insert(lst_type.id(), ptr_type.id());
return {ptr_type, lst_type};
}
@@ -572,16 +584,13 @@ CompositeMetaTypeIds QQmlMetaType::registerInternalCompositeType(const QByteArra
void QQmlMetaType::unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds)
{
QQmlMetaTypeDataPtr data;
- data->qmlLists.remove(typeIds.listId);
-
- QMetaType::unregisterType(typeIds.id);
- QMetaType::unregisterType(typeIds.listId);
+ data->qmlLists.remove(typeIds.listId.id());
}
int QQmlMetaType::registerUnitCacheHook(
const QQmlPrivate::RegisterQmlUnitCacheHook &hookRegistration)
{
- if (hookRegistration.version > 0)
+ if (hookRegistration.structVersion > 0)
qFatal("qmlRegisterType(): Cannot mix incompatible QML versions.");
QQmlMetaTypeDataPtr data;
@@ -589,40 +598,37 @@ int QQmlMetaType::registerUnitCacheHook(
return 0;
}
-bool QQmlMetaType::protectModule(const QString &uri, int majVersion)
+bool QQmlMetaType::protectModule(const QString &uri, QTypeRevision version)
{
QQmlMetaTypeDataPtr data;
- QQmlMetaTypeData::VersionedUri versionedUri;
- versionedUri.uri = uri;
- versionedUri.majorVersion = majVersion;
-
- if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0)) {
+ if (QQmlTypeModule* qqtm = data->uriToModule.value(
+ QQmlMetaTypeData::VersionedUri(uri, version), nullptr)) {
qqtm->lock();
return true;
}
return false;
}
-void QQmlMetaType::registerModule(const char *uri, int versionMajor, int versionMinor)
+void QQmlMetaType::registerModule(const char *uri, QTypeRevision version)
{
QQmlMetaTypeDataPtr data;
- QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data);
+ QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), version, data);
Q_ASSERT(module);
- module->addMinorVersion(versionMinor);
+ module->addMinorVersion(version.minorVersion());
}
-int QQmlMetaType::typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
+int QQmlMetaType::typeId(const char *uri, QTypeRevision version, const char *qmlName)
{
QQmlMetaTypeDataPtr data;
- QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), versionMajor, data);
+ QQmlTypeModule *module = getTypeModule(QString::fromUtf8(uri), version, data);
if (!module)
return -1;
- QQmlType type = module->type(QHashedStringRef(QString::fromUtf8(qmlName)), versionMinor);
+ QQmlType type = module->type(QHashedStringRef(QString::fromUtf8(qmlName)), version);
if (!type.isValid())
return -1;
@@ -636,12 +642,12 @@ void QQmlMetaType::registerUndeletableType(const QQmlType &dtype)
}
static bool namespaceContainsRegistrations(const QQmlMetaTypeData *data, const QString &uri,
- int majorVersion)
+ QTypeRevision version)
{
// Has any type previously been installed to this namespace?
QHashedString nameSpace(uri);
for (const QQmlType &type : data->types) {
- if (type.module() == nameSpace && type.majorVersion() == majorVersion)
+ if (type.module() == nameSpace && type.version().majorVersion() == version.majorVersion())
return true;
}
@@ -668,8 +674,8 @@ public:
bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePath,
- const QString &uri, const QString &typeNamespace, int vmaj,
- QList<QQmlError> *errors)
+ const QString &uri, const QString &typeNamespace,
+ QTypeRevision version, QList<QQmlError> *errors)
{
if (!typeNamespace.isEmpty() && typeNamespace != uri) {
// This is an 'identified' module
@@ -690,7 +696,7 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat
QQmlMetaTypeRegistrationFailureRecorder failureRecorder(data, &failures);
if (!typeNamespace.isEmpty()) {
// This is an 'identified' module
- if (namespaceContainsRegistrations(data, typeNamespace, vmaj)) {
+ if (namespaceContainsRegistrations(data, typeNamespace, version)) {
// Other modules have already installed to this namespace
if (errors) {
QQmlError error;
@@ -732,7 +738,7 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat
iface->registerTypes(moduleId);
}
- data->registerModuleTypes(QQmlMetaTypeData::VersionedUri(uri, vmaj));
+ data->registerModuleTypes(uri);
if (!failures.isEmpty()) {
if (errors) {
@@ -763,7 +769,7 @@ bool QQmlMetaType::registerPluginTypes(QObject *instance, const QString &basePat
QQmlType QQmlMetaType::typeForUrl(const QString &urlString,
const QHashedStringRef &qualifiedType,
bool isCompositeSingleton, QList<QQmlError> *errors,
- int majorVersion, int minorVersion)
+ QTypeRevision version)
{
// ### unfortunate (costly) conversion
const QUrl url = QQmlTypeLoader::normalize(QUrl(urlString));
@@ -808,11 +814,10 @@ QQmlType QQmlMetaType::typeForUrl(const QString &urlString,
const QQmlType::RegistrationType registrationType = isCompositeSingleton
? QQmlType::CompositeSingletonType
: QQmlType::CompositeType;
- if (checkRegistration(registrationType, data, nullptr, typeName, majorVersion)) {
+ if (checkRegistration(registrationType, data, nullptr, typeName, version)) {
auto *priv = new QQmlTypePrivate(registrationType);
priv->setName(QString(), typeName);
- priv->version_maj = majorVersion;
- priv->version_min = minorVersion;
+ priv->version = version;
if (isCompositeSingleton) {
priv->extraData.sd->singletonInstanceInfo = new QQmlType::SingletonInstanceInfo;
@@ -865,14 +870,12 @@ bool QQmlMetaType::isAnyModule(const QString &uri)
/*
Returns true if a module \a uri of this version is installed and locked;
*/
-bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion)
+bool QQmlMetaType::isLockedModule(const QString &uri, QTypeRevision version)
{
QQmlMetaTypeDataPtr data;
- QQmlMetaTypeData::VersionedUri versionedUri;
- versionedUri.uri = uri;
- versionedUri.majorVersion = majVersion;
- if (QQmlTypeModule* qqtm = data->uriToModule.value(versionedUri, 0))
+ if (QQmlTypeModule* qqtm = data->uriToModule.value(
+ QQmlMetaTypeData::VersionedUri(uri, version), nullptr))
return qqtm->isLocked();
return false;
}
@@ -884,24 +887,28 @@ bool QQmlMetaType::isLockedModule(const QString &uri, int majVersion)
So if only 4.7 and 4.9 have been registered, 4.7,4.8, and 4.9 are valid, but not 4.6 nor 4.10.
*/
-bool QQmlMetaType::isModule(const QString &module, int versionMajor, int versionMinor)
+bool QQmlMetaType::isModule(const QString &module, QTypeRevision version)
{
- Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
+ if (!version.hasMajorVersion())
+ return isAnyModule(module);
+
QQmlMetaTypeDataPtr data;
// first, check Types
- QQmlTypeModule *tm =
- data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, versionMajor));
- if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
- return true;
+ if (QQmlTypeModule *tm
+ = data->uriToModule.value(QQmlMetaTypeData::VersionedUri(module, version))) {
+ return !version.hasMinorVersion()
+ || (tm->minimumMinorVersion() <= version.minorVersion()
+ && tm->maximumMinorVersion() >= version.minorVersion());
+ }
return false;
}
-QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, int majorVersion)
+QQmlTypeModule *QQmlMetaType::typeModule(const QString &uri, QTypeRevision version)
{
QQmlMetaTypeDataPtr data;
- return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, majorVersion));
+ return data->uriToModule.value(QQmlMetaTypeData::VersionedUri(uri, version));
}
QList<QQmlPrivate::AutoParentFunction> QQmlMetaType::parentFunctions()
@@ -926,9 +933,8 @@ bool QQmlMetaType::isQObject(int userType)
{
if (userType == QMetaType::QObjectStar)
return true;
-
QQmlMetaTypeDataPtr data;
- return userType >= 0 && userType < data->objects.size() && data->objects.testBit(userType);
+ return data->objects.contains(userType);
}
/*
@@ -941,8 +947,8 @@ int QQmlMetaType::listType(int id)
if (iter != data->qmlLists.cend())
return *iter;
QQmlTypePrivate *type = data->idToType.value(id);
- if (type && type->listId == id)
- return type->typeId;
+ if (type && type->listId.id() == id)
+ return type->typeId.id();
else
return 0;
}
@@ -1042,9 +1048,9 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
QQmlMetaTypeDataPtr data;
if (data->qmlLists.contains(userType))
return List;
- else if (userType < data->objects.size() && data->objects.testBit(userType))
+ else if (data->objects.contains(userType))
return Object;
- else if (userType < data->lists.size() && data->lists.testBit(userType))
+ else if (data->lists.contains(userType))
return List;
else
return Unknown;
@@ -1056,7 +1062,7 @@ QQmlMetaType::TypeCategory QQmlMetaType::typeCategory(int userType)
bool QQmlMetaType::isInterface(int userType)
{
const QQmlMetaTypeDataPtr data;
- return userType >= 0 && userType < data->interfaces.size() && data->interfaces.testBit(userType);
+ return data->interfaces.contains(userType);
}
const char *QQmlMetaType::interfaceIId(int userType)
@@ -1069,7 +1075,7 @@ const char *QQmlMetaType::interfaceIId(int userType)
}
QQmlType type(typePrivate);
- if (type.isInterface() && type.typeId() == userType)
+ if (type.isInterface() && type.typeId().id() == userType)
return type.interfaceIId();
else
return nullptr;
@@ -1077,10 +1083,10 @@ const char *QQmlMetaType::interfaceIId(int userType)
bool QQmlMetaType::isList(int userType)
{
- const QQmlMetaTypeDataPtr data;
+ QQmlMetaTypeDataPtr data;
if (data->qmlLists.contains(userType))
return true;
- return userType >= 0 && userType < data->lists.size() && data->lists.testBit(userType);
+ return data->lists.contains(userType);
}
/*!
@@ -1120,7 +1126,7 @@ QQmlMetaType::StringConverter QQmlMetaType::customStringConverter(int type)
Returns the type (if any) of URI-qualified named \a qualifiedName and version specified
by \a version_major and \a version_minor.
*/
-QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, int version_major, int version_minor)
+QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, QTypeRevision version)
{
int slash = qualifiedName.indexOf(QLatin1Char('/'));
if (slash <= 0)
@@ -1129,23 +1135,22 @@ QQmlType QQmlMetaType::qmlType(const QString &qualifiedName, int version_major,
QHashedStringRef module(qualifiedName.constData(), slash);
QHashedStringRef name(qualifiedName.constData() + slash + 1, qualifiedName.length() - slash - 1);
- return qmlType(name, module, version_major, version_minor);
+ return qmlType(name, module, version);
}
/*!
Returns the type (if any) of \a name in \a module and version specified
by \a version_major and \a version_minor.
*/
-QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int version_major, int version_minor)
+QQmlType QQmlMetaType::qmlType(const QHashedStringRef &name, const QHashedStringRef &module,
+ QTypeRevision version)
{
- Q_ASSERT(version_major >= 0 && version_minor >= 0);
const QQmlMetaTypeDataPtr data;
QQmlMetaTypeData::Names::ConstIterator it = data->nameToType.constFind(name);
while (it != data->nameToType.cend() && it.key() == name) {
QQmlType t(*it);
- // XXX version_major<0 just a kludge for QQmlPropertyPrivate::initProperty
- if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor))
+ if (module.isEmpty() || t.availableInVersion(module, version))
return t;
++it;
}
@@ -1168,15 +1173,15 @@ QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject)
by \a version_major and \a version_minor in module specified by \a uri. Returns null if no
type is registered.
*/
-QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor)
+QQmlType QQmlMetaType::qmlType(const QMetaObject *metaObject, const QHashedStringRef &module,
+ QTypeRevision version)
{
- Q_ASSERT(version_major >= 0 && version_minor >= 0);
const QQmlMetaTypeDataPtr data;
QQmlMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.constFind(metaObject);
while (it != data->metaObjectToType.cend() && it.key() == metaObject) {
QQmlType t(*it);
- if (version_major < 0 || module.isEmpty() || t.availableInVersion(module, version_major,version_minor))
+ if (module.isEmpty() || t.availableInVersion(module, version))
return t;
++it;
}
@@ -1195,7 +1200,7 @@ QQmlType QQmlMetaType::qmlType(int typeId, TypeIdCategory category)
if (category == TypeIdCategory::MetaType) {
QQmlTypePrivate *type = data->idToType.value(typeId);
- if (type && type->typeId == typeId)
+ if (type && type->typeId.id() == typeId)
return QQmlType(type);
} else if (category == TypeIdCategory::QmlType) {
QQmlType type = data->types.value(typeId);
@@ -1226,16 +1231,16 @@ QQmlType QQmlMetaType::qmlType(const QUrl &unNormalizedUrl, bool includeNonFileI
return QQmlType();
}
-QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject, int minorVersion)
+QQmlPropertyCache *QQmlMetaType::propertyCache(const QMetaObject *metaObject, QTypeRevision version)
{
QQmlMetaTypeDataPtr data; // not const: the cache is created on demand
- return data->propertyCache(metaObject, minorVersion);
+ return data->propertyCache(metaObject, version);
}
-QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, int minorVersion)
+QQmlPropertyCache *QQmlMetaType::propertyCache(const QQmlType &type, QTypeRevision version)
{
QQmlMetaTypeDataPtr data; // not const: the cache is created on demand
- return data->propertyCache(type, minorVersion);
+ return data->propertyCache(type, version);
}
void QQmlMetaType::unregisterType(int typeIndex)
@@ -1250,7 +1255,7 @@ void QQmlMetaType::unregisterType(int typeIndex)
removeQQmlTypePrivate(data->metaObjectToType, d);
for (auto & module : data->uriToModule)
module->remove(d);
- data->clearPropertyCachesForMinorVersion(typeIndex);
+ data->clearPropertyCachesForVersion(typeIndex);
data->types[typeIndex] = QQmlType();
data->undeletableTypes.remove(type);
}
@@ -1282,7 +1287,7 @@ void QQmlMetaType::freeUnusedTypesAndCaches()
for (auto &module : data->uriToModule)
module->remove(d);
- data->clearPropertyCachesForMinorVersion(d->index);
+ data->clearPropertyCachesForVersion(d->index);
*it = QQmlType();
} else {
++it;
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 0c5bc043c4..28d647520d 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -65,11 +65,9 @@ namespace QV4 { class ExecutableCompilationUnit; }
struct CompositeMetaTypeIds
{
- int id = -1;
- int listId = -1;
- CompositeMetaTypeIds() = default;
- CompositeMetaTypeIds(int id, int listId) : id(id), listId(listId) {}
- bool isValid() const { return id != -1 && listId != -1; }
+ QMetaType id;
+ QMetaType listId;
+ bool isValid() const { return id.isValid() && listId.isValid(); }
};
class Q_QML_PRIVATE_EXPORT QQmlMetaType
@@ -81,20 +79,20 @@ public:
static QQmlType registerCompositeSingletonType(const QQmlPrivate::RegisterCompositeSingletonType &type);
static QQmlType registerCompositeType(const QQmlPrivate::RegisterCompositeType &type);
static bool registerPluginTypes(QObject *instance, const QString &basePath,
- const QString &uri, const QString &typeNamespace, int vmaj,
- QList<QQmlError> *errors);
+ const QString &uri, const QString &typeNamespace,
+ QTypeRevision version, QList<QQmlError> *errors);
static QQmlType typeForUrl(const QString &urlString, const QHashedStringRef& typeName,
bool isCompositeSingleton, QList<QQmlError> *errors,
- int majorVersion = -1, int minorVersion = -1);
+ QTypeRevision version = QTypeRevision());
static void unregisterType(int type);
static CompositeMetaTypeIds registerInternalCompositeType(const QByteArray &className);
static void unregisterInternalCompositeType(const CompositeMetaTypeIds &typeIds);
- static void registerModule(const char *uri, int versionMajor, int versionMinor);
- static bool protectModule(const QString &uri, int majVersion);
+ static void registerModule(const char *uri, QTypeRevision version);
+ static bool protectModule(const QString &uri, QTypeRevision version);
- static int typeId(const char *uri, int versionMajor, int versionMinor, const char *qmlName);
+ static int typeId(const char *uri, QTypeRevision version, const char *qmlName);
static void registerUndeletableType(const QQmlType &dtype);
@@ -108,15 +106,16 @@ public:
QmlType
};
- static QQmlType qmlType(const QString &qualifiedName, int, int);
- static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, int, int);
+ static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version);
+ static QQmlType qmlType(const QHashedStringRef &name, const QHashedStringRef &module, QTypeRevision version);
static QQmlType qmlType(const QMetaObject *);
- static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, int version_major, int version_minor);
+ static QQmlType qmlType(const QMetaObject *metaObject, const QHashedStringRef &module, QTypeRevision version);
static QQmlType qmlType(int typeId, TypeIdCategory category = TypeIdCategory::MetaType);
static QQmlType qmlType(const QUrl &unNormalizedUrl, bool includeNonFileImports = false);
- static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion = -1);
- static QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion);
+ static QQmlPropertyCache *propertyCache(const QMetaObject *metaObject,
+ QTypeRevision version = QTypeRevision());
+ static QQmlPropertyCache *propertyCache(const QQmlType &type, QTypeRevision version);
static void freeUnusedTypesAndCaches();
@@ -150,9 +149,9 @@ public:
static StringConverter customStringConverter(int);
static bool isAnyModule(const QString &uri);
- static bool isLockedModule(const QString &uri, int majorVersion);
- static bool isModule(const QString &module, int versionMajor, int versionMinor);
- static QQmlTypeModule *typeModule(const QString &uri, int majorVersion);
+ static bool isLockedModule(const QString &uri, QTypeRevision version);
+ static bool isModule(const QString &module, QTypeRevision version);
+ static QQmlTypeModule *typeModule(const QString &uri, QTypeRevision version);
static QList<QQmlPrivate::AutoParentFunction> parentFunctions();
@@ -197,11 +196,10 @@ public:
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd);
- static void qmlInsertModuleRegistration(const QString &uri, int majorVersion,
- void (*registerFunction)());
- static void qmlRemoveModuleRegistration(const QString &uri, int majorVersion);
+ static void qmlInsertModuleRegistration(const QString &uri, void (*registerFunction)());
+ static void qmlRemoveModuleRegistration(const QString &uri);
- static bool qmlRegisterModuleTypes(const QString &uri, int majorVersion);
+ static bool qmlRegisterModuleTypes(const QString &uri);
static int qmlRegisteredListTypeCount();
};
diff --git a/src/qml/qml/qqmlmetatypedata.cpp b/src/qml/qml/qqmlmetatypedata.cpp
index ed885eaa97..a34a0c1ae4 100644
--- a/src/qml/qml/qqmlmetatypedata.cpp
+++ b/src/qml/qml/qqmlmetatypedata.cpp
@@ -78,9 +78,9 @@ void QQmlMetaTypeData::registerType(QQmlTypePrivate *priv)
priv->release();
}
-bool QQmlMetaTypeData::registerModuleTypes(const QQmlMetaTypeData::VersionedUri &versionedUri)
+bool QQmlMetaTypeData::registerModuleTypes(const QString &uri)
{
- auto function = moduleTypeRegistrationFunctions.constFind(versionedUri);
+ auto function = moduleTypeRegistrationFunctions.constFind(uri);
if (function != moduleTypeRegistrationFunctions.constEnd()) {
(*function)();
return true;
@@ -88,28 +88,28 @@ bool QQmlMetaTypeData::registerModuleTypes(const QQmlMetaTypeData::VersionedUri
return false;
}
-QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForMinorVersion(int index, int minorVersion) const
+QQmlPropertyCache *QQmlMetaTypeData::propertyCacheForVersion(int index, QTypeRevision version) const
{
return (index < typePropertyCaches.length())
- ? typePropertyCaches.at(index).value(minorVersion).data()
+ ? typePropertyCaches.at(index).value(version).data()
: nullptr;
}
-void QQmlMetaTypeData::setPropertyCacheForMinorVersion(int index, int minorVersion,
- QQmlPropertyCache *cache)
+void QQmlMetaTypeData::setPropertyCacheForVersion(int index, QTypeRevision version,
+ QQmlPropertyCache *cache)
{
if (index >= typePropertyCaches.length())
typePropertyCaches.resize(index + 1);
- typePropertyCaches[index][minorVersion] = cache;
+ typePropertyCaches[index][version] = cache;
}
-void QQmlMetaTypeData::clearPropertyCachesForMinorVersion(int index)
+void QQmlMetaTypeData::clearPropertyCachesForVersion(int index)
{
if (index < typePropertyCaches.length())
typePropertyCaches[index].clear();
}
-QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, int minorVersion)
+QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject, QTypeRevision version)
{
if (QQmlPropertyCache *rv = propertyCaches.value(metaObject))
return rv;
@@ -119,29 +119,36 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QMetaObject *metaObject
propertyCaches.insert(metaObject, rv);
return rv;
}
- QQmlPropertyCache *super = propertyCache(metaObject->superClass(), minorVersion);
- QQmlPropertyCache *rv = super->copyAndAppend(metaObject, minorVersion);
+ QQmlPropertyCache *super = propertyCache(metaObject->superClass(), version);
+ QQmlPropertyCache *rv = super->copyAndAppend(metaObject, version);
propertyCaches.insert(metaObject, rv);
return rv;
}
-QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int minorVersion)
+QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, QTypeRevision version)
{
Q_ASSERT(type.isValid());
- if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), minorVersion))
+ if (QQmlPropertyCache *pc = propertyCacheForVersion(type.index(), version))
return pc;
QVector<QQmlType> types;
- int maxMinorVersion = 0;
+ quint8 maxMinorVersion = 0;
const QMetaObject *metaObject = type.metaObject();
+ const QTypeRevision combinedVersion = version.hasMajorVersion()
+ ? version
+ : (version.hasMinorVersion()
+ ? QTypeRevision::fromVersion(type.version().majorVersion(),
+ version.minorVersion())
+ : type.version());
+
while (metaObject) {
- QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), type.majorVersion(), minorVersion);
+ QQmlType t = QQmlMetaType::qmlType(metaObject, type.module(), combinedVersion);
if (t.isValid()) {
- maxMinorVersion = qMax(maxMinorVersion, t.minorVersion());
+ maxMinorVersion = qMax(maxMinorVersion, t.version().minorVersion());
types << t;
} else {
types << QQmlType();
@@ -150,12 +157,14 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
metaObject = metaObject->superClass();
}
- if (QQmlPropertyCache *pc = propertyCacheForMinorVersion(type.index(), maxMinorVersion)) {
- setPropertyCacheForMinorVersion(type.index(), minorVersion, pc);
+ const QTypeRevision maxVersion = QTypeRevision::fromVersion(combinedVersion.majorVersion(),
+ maxMinorVersion);
+ if (QQmlPropertyCache *pc = propertyCacheForVersion(type.index(), maxVersion)) {
+ setPropertyCacheForVersion(type.index(), maxVersion, pc);
return pc;
}
- QQmlPropertyCache *raw = propertyCache(type.metaObject(), minorVersion);
+ QQmlPropertyCache *raw = propertyCache(type.metaObject(), combinedVersion);
bool hasCopied = false;
@@ -164,7 +173,7 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
if (!currentType.isValid())
continue;
- int rev = currentType.metaObjectRevision();
+ QTypeRevision rev = currentType.metaObjectRevision();
int moIndex = types.count() - 1 - ii;
if (raw->allowedRevision(moIndex) != rev) {
@@ -222,13 +231,13 @@ QQmlPropertyCache *QQmlMetaTypeData::propertyCache(const QQmlType &type, int min
}
#endif
- setPropertyCacheForMinorVersion(type.index(), minorVersion, raw);
+ setPropertyCacheForVersion(type.index(), version, raw);
if (hasCopied)
raw->release();
- if (minorVersion != maxMinorVersion)
- setPropertyCacheForMinorVersion(type.index(), maxMinorVersion, raw);
+ if (version != maxVersion)
+ setPropertyCacheForVersion(type.index(), maxVersion, raw);
return raw;
}
diff --git a/src/qml/qml/qqmlmetatypedata_p.h b/src/qml/qml/qqmlmetatypedata_p.h
index e51d4ca1a4..322ead084a 100644
--- a/src/qml/qml/qqmlmetatypedata_p.h
+++ b/src/qml/qml/qqmlmetatypedata_p.h
@@ -57,7 +57,6 @@
#include <QtCore/qset.h>
#include <QtCore/qvector.h>
-#include <QtCore/qbitarray.h>
QT_BEGIN_NAMESPACE
@@ -83,29 +82,28 @@ struct QQmlMetaTypeData
MetaObjects metaObjectToType;
typedef QHash<int, QQmlMetaType::StringConverter> StringConverters;
StringConverters stringConverters;
- QVector<QHash<int, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches;
+ QVector<QHash<QTypeRevision, QQmlRefPointer<QQmlPropertyCache>>> typePropertyCaches;
struct VersionedUri {
- VersionedUri()
- : majorVersion(0) {}
- VersionedUri(const QHashedString &uri, int majorVersion)
- : uri(uri), majorVersion(majorVersion) {}
+ VersionedUri() : majorVersion(0) {}
+ VersionedUri(const QHashedString &uri, QTypeRevision version)
+ : uri(uri), majorVersion(version.majorVersion()) {}
bool operator==(const VersionedUri &other) const {
return other.majorVersion == majorVersion && other.uri == uri;
}
QHashedString uri;
- int majorVersion;
+ quint8 majorVersion;
};
typedef QHash<VersionedUri, QQmlTypeModule *> TypeModules;
TypeModules uriToModule;
- QHash<VersionedUri, void (*)()> moduleTypeRegistrationFunctions;
- bool registerModuleTypes(const VersionedUri &versionedUri);
+ QHash<QString, void (*)()> moduleTypeRegistrationFunctions;
+ bool registerModuleTypes(const QString &uri);
- QBitArray objects;
- QBitArray interfaces;
- QBitArray lists;
+ QSet<int> interfaces;
+ QSet<int> objects;
+ QSet<int> lists;
QList<QQmlPrivate::AutoParentFunction> parentFunctions;
QVector<QQmlPrivate::QmlUnitCacheLookupFunction> lookupCachedQmlUnit;
@@ -114,12 +112,12 @@ struct QQmlMetaTypeData
QHash<const QMetaObject *, QQmlPropertyCache *> propertyCaches;
- QQmlPropertyCache *propertyCacheForMinorVersion(int index, int minorVersion) const;
- void setPropertyCacheForMinorVersion(int index, int minorVersion, QQmlPropertyCache *cache);
- void clearPropertyCachesForMinorVersion(int index);
+ QQmlPropertyCache *propertyCacheForVersion(int index, QTypeRevision version) const;
+ void setPropertyCacheForVersion(int index, QTypeRevision version, QQmlPropertyCache *cache);
+ void clearPropertyCachesForVersion(int index);
- QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, int minorVersion);
- QQmlPropertyCache *propertyCache(const QQmlType &type, int minorVersion);
+ QQmlPropertyCache *propertyCache(const QMetaObject *metaObject, QTypeRevision version);
+ QQmlPropertyCache *propertyCache(const QQmlType &type, QTypeRevision version);
void setTypeRegistrationFailures(QStringList *failures)
{
diff --git a/src/qml/qml/qqmlmoduleregistration.cpp b/src/qml/qml/qqmlmoduleregistration.cpp
index b7bc3555a6..422a5c0551 100644
--- a/src/qml/qml/qqmlmoduleregistration.cpp
+++ b/src/qml/qml/qqmlmoduleregistration.cpp
@@ -39,27 +39,33 @@
#include <QtQml/private/qqmlmetatype_p.h>
#include <QtQml/qqmlmoduleregistration.h>
+#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
struct QQmlModuleRegistrationPrivate
{
const QString uri;
- const int majorVersion;
};
+QQmlModuleRegistration::QQmlModuleRegistration(const char *uri, void (*registerFunction)()) :
+ d(new QQmlModuleRegistrationPrivate { QString::fromUtf8(uri) })
+{
+ QQmlMetaType::qmlInsertModuleRegistration(d->uri, registerFunction);
+}
+
+#if QT_DEPRECATED_SINCE(6, 0)
QQmlModuleRegistration::QQmlModuleRegistration(
- const char *uri, int majorVersion,
- void (*registerFunction)()) :
- d(new QQmlModuleRegistrationPrivate { QString::fromUtf8(uri), majorVersion })
+ const char *uri, int majorVersion, void (*registerFunction)()) :
+ QQmlModuleRegistration(uri, registerFunction)
{
- QQmlMetaType::qmlInsertModuleRegistration(d->uri, d->majorVersion,
- registerFunction);
+ Q_UNUSED(majorVersion);
}
+#endif
QQmlModuleRegistration::~QQmlModuleRegistration()
{
- QQmlMetaType::qmlRemoveModuleRegistration(d->uri, d->majorVersion);
+ QQmlMetaType::qmlRemoveModuleRegistration(d->uri);
delete d;
}
diff --git a/src/qml/qml/qqmlmoduleregistration.h b/src/qml/qml/qqmlmoduleregistration.h
index 6f553a2823..3db535faa0 100644
--- a/src/qml/qml/qqmlmoduleregistration.h
+++ b/src/qml/qml/qqmlmoduleregistration.h
@@ -49,9 +49,14 @@ class Q_QML_EXPORT QQmlModuleRegistration
{
Q_DISABLE_COPY_MOVE(QQmlModuleRegistration)
public:
- QQmlModuleRegistration(const char *uri, int majorVersion, void (*registerFunction)());
+ QQmlModuleRegistration(const char *uri, void (*registerFunction)());
~QQmlModuleRegistration();
+#if QT_DEPRECATED_SINCE(6, 0)
+ QT_DEPRECATED_X("Use registration without major version")
+ QQmlModuleRegistration(const char *uri, int majorVersion, void (*registerFunction)());
+#endif
+
private:
QQmlModuleRegistrationPrivate *d = nullptr;
};
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 3ca89924f9..cbf243b9c1 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -59,6 +59,8 @@
#include <private/qqmlsourcecoordinate_p.h>
#include <private/qjsvalue_p.h>
#include <private/qv4generatorobject_p.h>
+#include <private/qv4resolvedtypereference_p.h>
+#include <private/qqmlpropertybinding_p.h>
#include <QScopedValueRollback>
@@ -67,8 +69,11 @@
QT_USE_NAMESPACE
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *creationContext,
- QQmlIncubatorPrivate *incubator)
+QQmlObjectCreator::QQmlObjectCreator(
+ QQmlRefPointer<QQmlContextData> parentContext,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QQmlRefPointer<QQmlContextData> &creationContext,
+ QQmlIncubatorPrivate *incubator)
: phase(Startup)
, compilationUnit(compilationUnit)
, propertyCaches(&compilationUnit->propertyCaches)
@@ -76,7 +81,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
, topLevelCreator(true)
, incubator(incubator)
{
- init(parentContext);
+ init(std::move(parentContext));
sharedState->componentAttached = nullptr;
sharedState->allCreatedBindings.allocate(compilationUnit->totalBindingsCount());
@@ -95,7 +100,10 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
}
}
-QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState)
+QQmlObjectCreator::QQmlObjectCreator(
+ QQmlRefPointer<QQmlContextData> parentContext,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ QQmlObjectCreatorSharedState *inheritedSharedState)
: phase(Startup)
, compilationUnit(compilationUnit)
, propertyCaches(&compilationUnit->propertyCaches)
@@ -103,13 +111,13 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, const QQmlR
, topLevelCreator(false)
, incubator(nullptr)
{
- init(parentContext);
+ init(std::move(parentContext));
}
-void QQmlObjectCreator::init(QQmlContextData *providedParentContext)
+void QQmlObjectCreator::init(QQmlRefPointer<QQmlContextData> providedParentContext)
{
- parentContext = providedParentContext;
- engine = parentContext->engine;
+ parentContext = std::move(providedParentContext);
+ engine = parentContext->engine();
v4 = engine->handle();
if (compilationUnit && !compilationUnit->engine)
@@ -142,7 +150,7 @@ QQmlObjectCreator::~QQmlObjectCreator()
}
while (sharedState->componentAttached) {
QQmlComponentAttached *a = sharedState->componentAttached;
- a->rem();
+ a->removeFromList();
}
}
}
@@ -151,7 +159,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
{
if (phase == CreatingObjectsPhase2) {
phase = ObjectsCreated;
- return context->contextObject;
+ return context->contextObject();
}
Q_ASSERT(phase == Startup);
phase = CreatingObjects;
@@ -171,16 +179,15 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
}
}
- context = new QQmlContextData;
- context->isInternal = true;
- context->imports = compilationUnit->typeNameCache;
+ context = QQmlContextData::createRefCounted(parentContext);
+ context->setInternal(true);
+ context->setImports(compilationUnit->typeNameCache);
context->initFromTypeCompilationUnit(compilationUnit, subComponentIndex);
- context->setParent(parentContext);
if (!sharedState->rootContext) {
sharedState->rootContext = context;
- sharedState->rootContext->incubator = incubator;
- sharedState->rootContext->isRootObjectInCreation = true;
+ sharedState->rootContext->setIncubator(incubator);
+ sharedState->rootContext->setRootObjectInCreation(true);
}
QV4::Scope scope(v4);
@@ -191,14 +198,14 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
if (subComponentIndex == -1 && compilationUnit->dependentScripts.count()) {
QV4::ScopedObject scripts(scope, v4->newArrayObject(compilationUnit->dependentScripts.count()));
- context->importedScripts.set(v4, scripts);
+ context->setImportedScripts(QV4::PersistentValue(v4, scripts.asReturnedValue()));
QV4::ScopedValue v(scope);
for (int i = 0; i < compilationUnit->dependentScripts.count(); ++i) {
QQmlRefPointer<QQmlScriptData> s = compilationUnit->dependentScripts.at(i);
scripts->put(i, (v = s->scriptValueForContext(context)));
}
} else if (sharedState->creationContext) {
- context->importedScripts = sharedState->creationContext->importedScripts;
+ context->setImportedScripts(sharedState->creationContext->importedScripts());
}
QObject *instance = createInstance(objectToCreate, parent, /*isContextObject*/true);
@@ -221,18 +228,18 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
if (instance) {
if (QQmlEngineDebugService *service
= QQmlDebugConnector::service<QQmlEngineDebugService>()) {
- if (!parentContext->isInternal)
- parentContext->asQQmlContextPrivate()->instances.append(instance);
+ if (!parentContext->isInternal())
+ parentContext->asQQmlContextPrivate()->appendInstance(instance);
service->objectCreated(engine, instance);
- } else if (!parentContext->isInternal && QQmlDebugConnector::service<QV4DebugService>()) {
- parentContext->asQQmlContextPrivate()->instances.append(instance);
+ } else if (!parentContext->isInternal() && QQmlDebugConnector::service<QV4DebugService>()) {
+ parentContext->asQQmlContextPrivate()->appendInstance(instance);
}
}
return instance;
}
-void QQmlObjectCreator::beginPopulateDeferred(QQmlContextData *newContext)
+void QQmlObjectCreator::beginPopulateDeferred(const QQmlRefPointer<QQmlContextData> &newContext)
{
context = newContext;
sharedState->rootContext = newContext;
@@ -449,8 +456,7 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
string.replace(QLatin1String("%2f"), QLatin1String("/"), Qt::CaseInsensitive);
QUrl value = string.isEmpty() ? QUrl() : compilationUnit->finalUrl().resolved(QUrl(string));
// Apply URL interceptor
- if (engine->urlInterceptor())
- value = engine->urlInterceptor()->intercept(value, QQmlAbstractUrlInterceptor::UrlString);
+ value = engine->interceptUrl(value, QQmlAbstractUrlInterceptor::UrlString);
property->writeProperty(_qobject, &value, propertyWriteFlags);
}
break;
@@ -618,9 +624,6 @@ void QQmlObjectCreator::setPropertyValue(const QQmlPropertyData *property, const
property->writeProperty(_qobject, &vec, propertyWriteFlags);
}
break;
- case QMetaType::QRegExp:
- assertOrNull(!"not possible");
- break;
default: {
// generate single literal value assignment to a list property if required
if (property->propType() == qMetaTypeId<QList<qreal> >()) {
@@ -742,7 +745,10 @@ void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
- QQmlPropertyData *property = binding->propertyNameIndex != 0 ? _propertyCache->property(stringAt(binding->propertyNameIndex), _qobject, context) : defaultProperty;
+ QQmlPropertyData *property = binding->propertyNameIndex != 0
+ ? _propertyCache->property(stringAt(binding->propertyNameIndex),
+ _qobject, context)
+ : defaultProperty;
if (property)
bindingSkipList |= (1 << property->coreIndex());
}
@@ -808,9 +814,10 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
Q_ASSERT(stringAt(compilationUnit->objectAt(binding->value.objectIndex)->inheritedTypeNameIndex).isEmpty());
QV4::ResolvedTypeReference *tr = resolvedType(binding->propertyNameIndex);
Q_ASSERT(tr);
- QQmlType attachedType = tr->type;
+ QQmlType attachedType = tr->type();
if (!attachedType.isValid()) {
- QQmlTypeNameCache::Result res = context->imports->query(stringAt(binding->propertyNameIndex));
+ QQmlTypeNameCache::Result res = context->imports()->query(
+ stringAt(binding->propertyNameIndex));
if (res.isValid())
attachedType = res.type;
else
@@ -899,14 +906,32 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
QQmlPropertyPrivate::removeBinding(_bindingTarget, QQmlPropertyIndex(bindingProperty->coreIndex()));
if (binding->type == QV4::CompiledData::Binding::Type_Script || binding->isTranslationBinding()) {
- if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression) {
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || binding->flags & QV4::CompiledData::Binding::IsPropertyObserver) {
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
int signalIndex = _propertyCache->methodIndexToSignalIndex(bindingProperty->coreIndex());
- QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
- QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(_bindingTarget, signalIndex,
- context, _scopeObject, runtimeFunction, currentQmlContext());
-
- bs->takeExpression(expr);
+ QQmlBoundSignalExpression *expr = new QQmlBoundSignalExpression(
+ _bindingTarget, signalIndex, context,
+ _scopeObject, runtimeFunction, currentQmlContext());
+
+ if (bindingProperty->isQProperty()) {
+ auto &observer = QQmlData::get(_scopeObject)->propertyObservers.emplace_back(expr);
+ void *argv[] = { &observer };
+ _bindingTarget->qt_metacall(QMetaObject::RegisterQPropertyObserver, bindingProperty->coreIndex(), argv);
+ } else {
+ QQmlBoundSignal *bs = new QQmlBoundSignal(_bindingTarget, signalIndex, _scopeObject, engine);
+ bs->takeExpression(expr);
+ }
+ } else if (bindingProperty->isQProperty()) {
+ QUntypedPropertyBinding qmlBinding;
+ if (binding->isTranslationBinding()) {
+ qmlBinding = QQmlTranslationPropertyBinding::create(bindingProperty, compilationUnit, binding);
+ } else {
+ QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
+ qmlBinding = QQmlPropertyBinding::create(bindingProperty, runtimeFunction, _scopeObject, context, currentQmlContext());
+ }
+ void *argv[] = { &qmlBinding };
+ _bindingTarget->qt_metacall(QMetaObject::SetQPropertyBinding, bindingProperty->coreIndex(), argv);
} else {
// When writing bindings to grouped properties implemented as value types,
// such as point.x: { someExpression; }, then the binding is installed on
@@ -921,10 +946,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
subprop = bindingProperty;
}
if (binding->isTranslationBinding()) {
- qmlBinding = QQmlBinding::createTranslationBinding(compilationUnit, binding, _scopeObject, context);
+ qmlBinding = QQmlBinding::createTranslationBinding(
+ compilationUnit, binding, _scopeObject, context);
} else {
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex];
- qmlBinding = QQmlBinding::create(targetProperty, runtimeFunction, _scopeObject, context, currentQmlContext());
+ qmlBinding = QQmlBinding::create(targetProperty, runtimeFunction, _scopeObject,
+ context, currentQmlContext());
}
auto bindingTarget = _bindingTarget;
@@ -966,10 +993,12 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
QQmlPropertyValueSource *vs = reinterpret_cast<QQmlPropertyValueSource *>(reinterpret_cast<char *>(createdSubObject) + valueSourceCast);
QObject *target = createdSubObject->parent();
QQmlProperty prop;
- if (_valueTypeProperty)
- prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, bindingProperty, context);
- else
+ if (_valueTypeProperty) {
+ prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty,
+ bindingProperty, context);
+ } else {
prop = QQmlPropertyPrivate::restore(target, *bindingProperty, nullptr, context);
+ }
vs->setTarget(prop);
return true;
}
@@ -991,15 +1020,19 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
// we can't have aliasses on subproperties of value types, so:
QQmlPropertyData targetPropertyData = *data->propertyCache->property(propIndex.coreIndex());
- auto prop = QQmlPropertyPrivate::restore(target, targetPropertyData, nullptr, context);
+ auto prop = QQmlPropertyPrivate::restore(
+ target, targetPropertyData, nullptr, context);
vi->setTarget(prop);
propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
} else {
QQmlProperty prop;
- if (_valueTypeProperty)
- prop = QQmlPropertyPrivate::restore(target, *_valueTypeProperty, bindingProperty, context);
- else
- prop = QQmlPropertyPrivate::restore(target, *bindingProperty, nullptr, context);
+ if (_valueTypeProperty) {
+ prop = QQmlPropertyPrivate::restore(
+ target, *_valueTypeProperty, bindingProperty, context);
+ } else {
+ prop = QQmlPropertyPrivate::restore(
+ target, *bindingProperty, nullptr, context);
+ }
vi->setTarget(prop);
propertyIndex = QQmlPropertyPrivate::propertyIndex(prop);
}
@@ -1069,7 +1102,7 @@ bool QQmlObjectCreator::setPropertyBinding(const QQmlPropertyData *bindingProper
_vmeMetaObject->setVMEProperty(bindingProperty->coreIndex(), wrappedObject);
} else {
QJSValue value;
- QJSValuePrivate::setValue(&value, v4, wrappedObject);
+ QJSValuePrivate::setValue(&value, wrappedObject);
argv[0] = &value;
QMetaObject::metacall(_qobject, QMetaObject::WriteProperty, bindingProperty->coreIndex(), argv);
}
@@ -1145,12 +1178,7 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location,
void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const
{
if (object->id >= 0)
- context->setIdProperty(object->id, instance);
-}
-
-void QQmlObjectCreator::createQmlContext()
-{
- _qmlContext->setM(QV4::QmlContext::create(v4->rootContext(), context, _scopeObject));
+ context->setIdValue(object->id, instance);
}
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
@@ -1180,8 +1208,8 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
} else {
QV4::ResolvedTypeReference *typeRef = resolvedType(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
- installPropertyCache = !typeRef->isFullyDynamicType;
- QQmlType type = typeRef->type;
+ installPropertyCache = !typeRef->isFullyDynamicType();
+ const QQmlType type = typeRef->type();
if (type.isValid() && !type.isInlineComponentType()) {
typeName = type.qmlTypeName();
@@ -1206,10 +1234,10 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
customParser = type.customParser();
- if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation) {
+ if (sharedState->rootContext && sharedState->rootContext->isRootObjectInCreation()) {
QQmlData *ddata = QQmlData::get(instance, /*create*/true);
ddata->rootObjectInCreation = true;
- sharedState->rootContext->isRootObjectInCreation = false;
+ sharedState->rootContext->setRootObjectInCreation(false);
}
sharedState->allCreatedObjects.push(instance);
@@ -1219,13 +1247,11 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
typeName = compilationUnit->fileName();
// compilation unit is shared between root type and its inline component types
// so isSingleton errorneously returns true for inline components
- if (compilationUnit->unitData()->isSingleton() && !type.isInlineComponentType())
- {
+ if (compilationUnit->unitData()->isSingleton() && !type.isInlineComponentType()) {
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
return nullptr;
}
-
if (!type.isInlineComponentType()) {
QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data());
instance = subCreator.create();
@@ -1234,7 +1260,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
return nullptr;
}
} else {
- int subObjectId = type.inlineComponendId();
+ int subObjectId = type.inlineComponentId();
QScopedValueRollback<int> rollback {compilationUnit->icRoot, subObjectId};
QQmlObjectCreator subCreator(context, compilationUnit, sharedState.data());
instance = subCreator.create(subObjectId, nullptr, nullptr, CreationFlags::InlineComponent);
@@ -1271,21 +1297,22 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
const bool isInlineComponent = obj->flags & QV4::CompiledData::Object::IsInlineComponentRoot;
if (static_cast<quint32>(index) == /*root object*/0 || ddata->rootObjectInCreation || isInlineComponent) {
if (ddata->context) {
- Q_ASSERT(ddata->context != context);
+ Q_ASSERT(ddata->context != context.data());
Q_ASSERT(ddata->outerContext);
- Q_ASSERT(ddata->outerContext != context);
- QQmlContextData *c = ddata->context;
- while (c->linkedContext) c = c->linkedContext;
- c->linkedContext = context;
+ Q_ASSERT(ddata->outerContext != context.data());
+ QQmlRefPointer<QQmlContextData> c = ddata->context;
+ while (QQmlRefPointer<QQmlContextData> linked = c->linkedContext())
+ c = linked;
+ c->setLinkedContext(context);
} else {
- ddata->context = context;
+ ddata->context = context.data();
}
ddata->ownContext = ddata->context;
} else if (!ddata->context) {
- ddata->context = context;
+ ddata->context = context.data();
}
- context->addObject(ddata);
+ context->addOwnedObject(ddata);
if (parserStatus) {
parserStatus->classBegin();
@@ -1299,7 +1326,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
// Register the context object in the context early on in order for pending binding
// initialization to find it available.
if (isContextObject)
- context->contextObject = instance;
+ context->setContextObject(instance);
if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
customParser->engine = QQmlEnginePrivate::get(engine);
@@ -1374,7 +1401,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
return ok ? instance : nullptr;
}
-QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
+bool QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interrupt)
{
Q_ASSERT(phase == ObjectsCreated || phase == Finalizing);
phase = Finalizing;
@@ -1396,12 +1423,13 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
if (!b->isValueTypeProxy()) {
QQmlBinding *binding = static_cast<QQmlBinding*>(b.data());
if (!binding->hasError() && !binding->hasDependencies()
- && binding->context() && !binding->context()->unresolvedNames)
+ && binding->hasContext() && !binding->hasUnresolvedNames()) {
b->removeFromObject();
+ }
}
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return nullptr;
+ return false;
}
if (QQmlVME::componentCompleteEnabled()) { // the qml designer does the component complete later
@@ -1415,7 +1443,7 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
}
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return nullptr;
+ return false;
}
}
@@ -1427,27 +1455,27 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
}
if (watcher.hasRecursed())
- return nullptr;
+ return false;
}
sharedState->finalizeCallbacks.clear();
while (sharedState->componentAttached) {
QQmlComponentAttached *a = sharedState->componentAttached;
- a->rem();
+ a->removeFromList();
QQmlData *d = QQmlData::get(a->parent());
Q_ASSERT(d);
Q_ASSERT(d->context);
- a->add(&d->context->componentAttached);
+ d->context->addComponentAttached(a);
if (QQmlVME::componentCompleteEnabled())
emit a->completed();
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
- return nullptr;
+ return false;
}
phase = Done;
- return sharedState->rootContext;
+ return true;
}
void QQmlObjectCreator::clear()
@@ -1465,7 +1493,7 @@ void QQmlObjectCreator::clear()
while (sharedState->componentAttached) {
QQmlComponentAttached *a = sharedState->componentAttached;
- a->rem();
+ a->removeFromList();
}
phase = Done;
@@ -1560,9 +1588,9 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
while (alias->aliasToLocalAlias)
alias = _compiledObject->aliasesBegin() + alias->localAliasIndex;
Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
- if (!context->idValues->wasSet())
+ if (!context->isIdValueSet(0)) // TODO: Do we really want 0 here?
continue;
- QObject *target = context->idValues[alias->targetObjectId].data();
+ QObject *target = context->idValue(alias->targetObjectId);
if (!target)
continue;
QQmlData *targetDData = QQmlData::get(target, /*create*/false);
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index bca450addb..0b14ec6603 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -57,6 +57,7 @@
#include <private/qrecursionwatcher_p.h>
#include <private/qqmlprofiler_p.h>
#include <private/qv4qmlcontext_p.h>
+#include <private/qqmlguardedcontextdata_p.h>
#include <qpointer.h>
@@ -90,8 +91,8 @@ class RequiredProperties : public QHash<QQmlPropertyData*, RequiredPropertyInfo>
struct QQmlObjectCreatorSharedState : public QSharedData
{
- QQmlContextData *rootContext;
- QQmlContextData *creationContext;
+ QQmlRefPointer<QQmlContextData> rootContext;
+ QQmlRefPointer<QQmlContextData> creationContext;
QFiniteStack<QQmlAbstractBinding::Ptr> allCreatedBindings;
QFiniteStack<QQmlParserStatus*> allParserStatusCallbacks;
QFiniteStack<QPointer<QObject> > allCreatedObjects;
@@ -108,38 +109,48 @@ class Q_QML_PRIVATE_EXPORT QQmlObjectCreator
{
Q_DECLARE_TR_FUNCTIONS(QQmlObjectCreator)
public:
- QQmlObjectCreator(QQmlContextData *parentContext, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlContextData *creationContext, QQmlIncubatorPrivate *incubator = nullptr);
+ QQmlObjectCreator(QQmlRefPointer<QQmlContextData> parentContext,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QQmlRefPointer<QQmlContextData> &creationContext,
+ QQmlIncubatorPrivate *incubator = nullptr);
~QQmlObjectCreator();
enum CreationFlags { NormalObject = 1, InlineComponent = 2 };
- QObject *create(int subComponentIndex = -1, QObject *parent = nullptr, QQmlInstantiationInterrupt *interrupt = nullptr, int flags = NormalObject);
+ QObject *create(int subComponentIndex = -1, QObject *parent = nullptr,
+ QQmlInstantiationInterrupt *interrupt = nullptr, int flags = NormalObject);
bool populateDeferredProperties(QObject *instance, const QQmlData::DeferredData *deferredData);
- void beginPopulateDeferred(QQmlContextData *context);
+ void beginPopulateDeferred(const QQmlRefPointer<QQmlContextData> &context);
void populateDeferredBinding(const QQmlProperty &qmlProperty, int deferredIndex,
const QV4::CompiledData::Binding *binding);
void finalizePopulateDeferred();
- QQmlContextData *finalize(QQmlInstantiationInterrupt &interrupt);
+ bool finalize(QQmlInstantiationInterrupt &interrupt);
void clear();
+ QQmlRefPointer<QQmlContextData> rootContext() const { return sharedState->rootContext; }
QQmlComponentAttached **componentAttachment() { return &sharedState->componentAttached; }
QList<QQmlEnginePrivate::FinalizeCallback> *finalizeCallbacks() { return &sharedState->finalizeCallbacks; }
QList<QQmlError> errors;
- QQmlContextData *parentContextData() const { return parentContext.contextData(); }
+ QQmlRefPointer<QQmlContextData> parentContextData() const
+ {
+ return parentContext.contextData();
+ }
QFiniteStack<QPointer<QObject> > &allCreatedObjects() { return sharedState->allCreatedObjects; }
RequiredProperties &requiredProperties() {return sharedState->requiredProperties;}
bool componentHadRequiredProperties() const {return sharedState->hadRequiredProperties;}
private:
- QQmlObjectCreator(QQmlContextData *contextData, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, QQmlObjectCreatorSharedState *inheritedSharedState);
+ QQmlObjectCreator(QQmlRefPointer<QQmlContextData> contextData,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ QQmlObjectCreatorSharedState *inheritedSharedState);
- void init(QQmlContextData *parentContext);
+ void init(QQmlRefPointer<QQmlContextData> parentContext);
QObject *createInstance(int index, QObject *parent = nullptr, bool isContextObject = false);
@@ -162,7 +173,6 @@ private:
void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const;
inline QV4::QmlContext *currentQmlContext();
- Q_NEVER_INLINE void createQmlContext();
QV4::ResolvedTypeReference *resolvedType(int id) const
{
return compilationUnit->resolvedType(id);
@@ -182,7 +192,7 @@ private:
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
const QV4::CompiledData::Unit *qmlUnit;
QQmlGuardedContextData parentContext;
- QQmlContextData *context;
+ QQmlRefPointer<QQmlContextData> context;
const QQmlPropertyCacheVector *propertyCaches;
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
bool topLevelCreator;
diff --git a/src/qml/qml/qqmlparserstatus.cpp b/src/qml/qml/qqmlparserstatus.cpp
index b8f4bb8c19..cd45e6668b 100644
--- a/src/qml/qml/qqmlparserstatus.cpp
+++ b/src/qml/qml/qqmlparserstatus.cpp
@@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE
\code
class MyObject : public QObject, public QQmlParserStatus
{
- Q_OBJECT
+ \Q_OBJECT
Q_INTERFACES(QQmlParserStatus)
public:
diff --git a/src/qml/qml/qqmlprivate.h b/src/qml/qml/qqmlprivate.h
index d6a9e73763..259deb5f32 100644
--- a/src/qml/qml/qqmlprivate.h
+++ b/src/qml/qml/qqmlprivate.h
@@ -63,24 +63,11 @@
#include <QtCore/qvariant.h>
#include <QtCore/qurl.h>
#include <QtCore/qpointer.h>
+#include <QtCore/qversionnumber.h>
#include <QtCore/qmetaobject.h>
#include <QtCore/qdebug.h>
-#define QML_GETTYPENAMES \
- const char *className = T::staticMetaObject.className(); \
- const int nameLen = int(strlen(className)); \
- QVarLengthArray<char,48> pointerName(nameLen+2); \
- memcpy(pointerName.data(), className, size_t(nameLen)); \
- pointerName[nameLen] = '*'; \
- pointerName[nameLen+1] = '\0'; \
- const int listLen = int(strlen("QQmlListProperty<")); \
- QVarLengthArray<char,64> listName(listLen + nameLen + 2); \
- memcpy(listName.data(), "QQmlListProperty<", size_t(listLen)); \
- memcpy(listName.data()+listLen, className, size_t(nameLen)); \
- listName[listLen+nameLen] = '>'; \
- listName[listLen+nameLen+1] = '\0';
-
QT_BEGIN_NAMESPACE
class QQmlPropertyValueInterceptor;
@@ -343,17 +330,16 @@ namespace QQmlPrivate
typedef AutoParentResult (*AutoParentFunction)(QObject *object, QObject *parent);
struct RegisterType {
- int version;
+ int structVersion;
- int typeId;
- int listId;
+ QMetaType typeId;
+ QMetaType listId;
int objectSize;
void (*create)(void *);
QString noCreationReason;
const char *uri;
- int versionMajor;
- int versionMinor;
+ QTypeRevision version;
const char *elementName;
const QMetaObject *metaObject;
@@ -369,20 +355,20 @@ namespace QQmlPrivate
QQmlCustomParser *customParser;
- int revision;
+ QTypeRevision revision;
// If this is extended ensure "version" is bumped!!!
};
struct RegisterTypeAndRevisions {
- int version;
+ int structVersion;
- int typeId;
- int listId;
+ QMetaType typeId;
+ QMetaType listId;
int objectSize;
void (*create)(void *);
const char *uri;
- int versionMajor;
+ QTypeRevision version;
const QMetaObject *metaObject;
const QMetaObject *classInfoMetaObject;
@@ -398,69 +384,69 @@ namespace QQmlPrivate
const QMetaObject *extensionMetaObject;
QQmlCustomParser *(*customParserFactory)();
+ QVector<int> *qmlTypeIds;
};
struct RegisterInterface {
- int version;
+ int structVersion;
- int typeId;
- int listId;
+ QMetaType typeId;
+ QMetaType listId;
const char *iid;
const char *uri;
- int versionMajor;
+ QTypeRevision version;
};
struct RegisterAutoParent {
- int version;
+ int structVersion;
AutoParentFunction function;
};
struct RegisterSingletonType {
- int version;
+ int structVersion;
const char *uri;
- int versionMajor;
- int versionMinor;
+ QTypeRevision version;
const char *typeName;
QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *);
- QObject *(*qobjectApi)(QQmlEngine *, QJSEngine *);
- const QMetaObject *instanceMetaObject; // new in version 1
- int typeId; // new in version 2
- int revision; // new in version 2
- std::function<QObject*(QQmlEngine *, QJSEngine *)> generalizedQobjectApi; // new in version 3
- // If this is extended ensure "version" is bumped!!!
+ std::function<QObject*(QQmlEngine *, QJSEngine *)> qObjectApi;
+
+ const QMetaObject *instanceMetaObject;
+ QMetaType typeId;
+ QTypeRevision revision;
};
struct RegisterSingletonTypeAndRevisions {
- int version;
+ int structVersion;
const char *uri;
- int versionMajor;
+ QTypeRevision version;
+
+ std::function<QObject*(QQmlEngine *, QJSEngine *)> qObjectApi;
- QJSValue (*scriptApi)(QQmlEngine *, QJSEngine *);
const QMetaObject *instanceMetaObject;
const QMetaObject *classInfoMetaObject;
- int typeId;
- std::function<QObject*(QQmlEngine *, QJSEngine *)> generalizedQobjectApi; // new in version 3
+ QMetaType typeId;
+ QVector<int> *qmlTypeIds;
};
struct RegisterCompositeType {
+ int structVersion;
QUrl url;
const char *uri;
- int versionMajor;
- int versionMinor;
+ QTypeRevision version;
const char *typeName;
};
struct RegisterCompositeSingletonType {
+ int structVersion;
QUrl url;
const char *uri;
- int versionMajor;
- int versionMinor;
+ QTypeRevision version;
const char *typeName;
};
@@ -472,7 +458,7 @@ namespace QQmlPrivate
typedef const CachedQmlUnit *(*QmlUnitCacheLookupFunction)(const QUrl &url);
struct RegisterQmlUnitCacheHook {
- int version;
+ int structVersion;
QmlUnitCacheLookupFunction lookupCachedQmlUnit;
};
@@ -490,7 +476,7 @@ namespace QQmlPrivate
int Q_QML_EXPORT qmlregister(RegistrationType, void *);
void Q_QML_EXPORT qmlunregister(RegistrationType, quintptr);
- struct Q_QML_EXPORT RegisterSingletonFunctor
+ struct Q_QML_EXPORT SingletonFunctor
{
QObject *operator()(QQmlEngine *, QJSEngine *);
@@ -516,11 +502,13 @@ namespace QQmlPrivate
return metaObject->classInfo(indexOfOwnClassInfo(metaObject, key)).value();
}
- inline int intClassInfo(const QMetaObject *metaObject, const char *key, int defaultValue = 0)
+ inline QTypeRevision revisionClassInfo(const QMetaObject *metaObject, const char *key,
+ QTypeRevision defaultValue = QTypeRevision())
{
const int index = indexOfOwnClassInfo(metaObject, key);
return (index == -1) ? defaultValue
- : QByteArray(metaObject->classInfo(index).value()).toInt();
+ : QTypeRevision::fromEncodedVersion(
+ QByteArray(metaObject->classInfo(index).value()).toInt());
}
inline bool boolClassInfo(const QMetaObject *metaObject, const char *key,
@@ -597,23 +585,22 @@ namespace QQmlPrivate
template<typename T>
void qmlRegisterSingletonAndRevisions(const char *uri, int versionMajor,
- const QMetaObject *classInfoMetaObject)
+ const QMetaObject *classInfoMetaObject,
+ QVector<int> *qmlTypeIds)
{
- QML_GETTYPENAMES
-
RegisterSingletonTypeAndRevisions api = {
0,
uri,
- versionMajor,
+ QTypeRevision::fromMajorVersion(versionMajor),
- nullptr,
+ Constructors<T>::createSingletonInstance,
&T::staticMetaObject,
classInfoMetaObject,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- Constructors<T>::createSingletonInstance
+ QMetaType::fromType<T *>(),
+ qmlTypeIds
};
qmlregister(SingletonAndRevisionsRegistration, &api);
@@ -621,19 +608,18 @@ namespace QQmlPrivate
template<typename T, typename E>
void qmlRegisterTypeAndRevisions(const char *uri, int versionMajor,
- const QMetaObject *classInfoMetaObject)
+ const QMetaObject *classInfoMetaObject,
+ QVector<int> *qmlTypeIds)
{
- QML_GETTYPENAMES
-
RegisterTypeAndRevisions type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()),
- qRegisterNormalizedMetaType<QQmlListProperty<T> >(listName.constData()),
+ QMetaType::fromType<T*>(),
+ QMetaType::fromType<QQmlListProperty<T>>(),
int(sizeof(T)),
Constructors<T>::createInto,
uri,
- versionMajor,
+ QTypeRevision::fromMajorVersion(versionMajor),
&T::staticMetaObject,
classInfoMetaObject,
@@ -648,7 +634,8 @@ namespace QQmlPrivate
ExtendedType<E>::createParent,
ExtendedType<E>::staticMetaObject,
- &qmlCreateCustomParser<T>
+ &qmlCreateCustomParser<T>,
+ qmlTypeIds
};
qmlregister(TypeAndRevisionsRegistration, &type);
@@ -656,7 +643,8 @@ namespace QQmlPrivate
template<>
void Q_QML_EXPORT qmlRegisterTypeAndRevisions<QQmlTypeNotAvailable, void>(
- const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject);
+ const char *uri, int versionMajor, const QMetaObject *classInfoMetaObject,
+ QVector<int> *qmlTypeIds);
} // namespace QQmlPrivate
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 8521de6ab3..3824a7fb6d 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -163,7 +163,6 @@ QQmlProperty::QQmlProperty(QObject *obj, QQmlContext *ctxt)
QQmlProperty::QQmlProperty(QObject *obj, QQmlEngine *engine)
: d(new QQmlPropertyPrivate)
{
- d->context = nullptr;
d->engine = engine;
d->initDefault(obj);
}
@@ -205,7 +204,11 @@ QQmlProperty::QQmlProperty(QObject *obj, const QString &name, QQmlContext *ctxt)
d->context = ctxt?QQmlContextData::get(ctxt):nullptr;
d->engine = ctxt?ctxt->engine():nullptr;
d->initProperty(obj, name);
- if (!isValid()) { d->object = nullptr; d->context = nullptr; d->engine = nullptr; }
+ if (!isValid()) {
+ d->object = nullptr;
+ d->context = nullptr;
+ d->engine = nullptr;
+ }
}
/*!
@@ -216,19 +219,23 @@ QQmlProperty::QQmlProperty(QObject *obj, const QString &name, QQmlContext *ctxt)
QQmlProperty::QQmlProperty(QObject *obj, const QString &name, QQmlEngine *engine)
: d(new QQmlPropertyPrivate)
{
- d->context = nullptr;
d->engine = engine;
d->initProperty(obj, name);
- if (!isValid()) { d->object = nullptr; d->context = nullptr; d->engine = nullptr; }
+ if (!isValid()) {
+ d->object = nullptr;
+ d->context = nullptr;
+ d->engine = nullptr;
+ }
}
-QQmlProperty QQmlPropertyPrivate::create(QObject *target, const QString &propertyName, QQmlContextData *context)
+QQmlProperty QQmlPropertyPrivate::create(QObject *target, const QString &propertyName,
+ const QQmlRefPointer<QQmlContextData> &context)
{
QQmlProperty result;
auto d = new QQmlPropertyPrivate;
result.d = d;
d->context = context;
- d->engine = context ? context->engine : nullptr;
+ d->engine = context ? context->engine() : nullptr;
d->initProperty(target, propertyName);
if (!result.isValid()) {
d->object = nullptr;
@@ -238,23 +245,21 @@ QQmlProperty QQmlPropertyPrivate::create(QObject *target, const QString &propert
return result;
}
-QQmlPropertyPrivate::QQmlPropertyPrivate()
-: context(nullptr), engine(nullptr), object(nullptr), isNameCached(false)
+QQmlRefPointer<QQmlContextData> QQmlPropertyPrivate::effectiveContext() const
{
-}
-
-QQmlContextData *QQmlPropertyPrivate::effectiveContext() const
-{
- if (context) return context;
- else if (engine) return QQmlContextData::get(engine->rootContext());
- else return nullptr;
+ if (context)
+ return context;
+ else if (engine)
+ return QQmlContextData::get(engine->rootContext());
+ else
+ return nullptr;
}
void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
{
if (!obj) return;
- QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context?context->imports:nullptr;
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache = context ? context->imports() : nullptr;
QObject *currentObject = obj;
QVector<QStringRef> path;
@@ -974,7 +979,7 @@ void QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
if (expr) {
int signalIndex = QQmlPropertyPrivate::get(that)->signalIndex();
QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, signalIndex, that.d->object,
- expr->context()->engine);
+ expr->engine());
signal->takeExpression(expr);
}
}
@@ -1097,7 +1102,8 @@ QVariant QQmlPropertyPrivate::readValueProperty()
}
// helper function to allow assignment / binding to QList<QUrl> properties.
-QVariant QQmlPropertyPrivate::resolvedUrlSequence(const QVariant &value, QQmlContextData *context)
+QVariant QQmlPropertyPrivate::resolvedUrlSequence(
+ const QVariant &value, const QQmlRefPointer<QQmlContextData> &context)
{
QList<QUrl> urls;
if (value.userType() == qMetaTypeId<QUrl>()) {
@@ -1186,7 +1192,8 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
const QQmlPropertyData &core,
const QQmlPropertyData &valueTypeData,
const QVariant &value,
- QQmlContextData *context,QQmlPropertyData::WriteFlags flags)
+ const QQmlRefPointer<QQmlContextData> &context,
+ QQmlPropertyData::WriteFlags flags)
{
// Remove any existing bindings on this property
if (!(flags & QQmlPropertyData::DontRemoveBinding) && object)
@@ -1201,7 +1208,7 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
};
QQmlGadgetPtrWrapper *wrapper = context
- ? QQmlGadgetPtrWrapper::instance(context->engine, core.propType())
+ ? QQmlGadgetPtrWrapper::instance(context->engine(), core.propType())
: nullptr;
if (wrapper) {
doWrite(wrapper);
@@ -1217,10 +1224,9 @@ QQmlPropertyPrivate::writeValueProperty(QObject *object,
return rv;
}
-bool QQmlPropertyPrivate::write(QObject *object,
- const QQmlPropertyData &property,
- const QVariant &value, QQmlContextData *context,
- QQmlPropertyData::WriteFlags flags)
+bool QQmlPropertyPrivate::write(
+ QObject *object, const QQmlPropertyData &property, const QVariant &value,
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData::WriteFlags flags)
{
const int propertyType = property.propType();
const int variantType = value.userType();
@@ -1647,14 +1653,15 @@ QQmlPropertyIndex QQmlPropertyPrivate::propertyIndex(const QQmlProperty &that)
QQmlProperty
QQmlPropertyPrivate::restore(QObject *object, const QQmlPropertyData &data,
- const QQmlPropertyData *valueTypeData, QQmlContextData *ctxt)
+ const QQmlPropertyData *valueTypeData,
+ const QQmlRefPointer<QQmlContextData> &ctxt)
{
QQmlProperty prop;
prop.d = new QQmlPropertyPrivate;
prop.d->object = object;
prop.d->context = ctxt;
- prop.d->engine = ctxt ? ctxt->engine : nullptr;
+ prop.d->engine = ctxt ? ctxt->engine() : nullptr;
prop.d->core = data;
if (valueTypeData)
diff --git a/src/qml/qml/qqmlproperty_p.h b/src/qml/qml/qqmlproperty_p.h
index 8abd83d7b4..5e357d77c0 100644
--- a/src/qml/qml/qqmlproperty_p.h
+++ b/src/qml/qml/qqmlproperty_p.h
@@ -57,9 +57,10 @@
#include <private/qobject_p.h>
#include <private/qtqmlglobal_p.h>
#include <private/qqmlrefcount_p.h>
-#include <private/qqmlcontext_p.h>
+#include <private/qqmlcontextdata_p.h>
#include <private/qqmlboundsignalexpressionpointer_p.h>
#include <private/qqmlpropertydata_p.h>
+#include <private/qqmlpropertyindex_p.h>
QT_BEGIN_NAMESPACE
@@ -67,11 +68,12 @@ class QQmlContext;
class QQmlEnginePrivate;
class QQmlJavaScriptExpression;
class QQmlMetaObject;
+class QQmlAbstractBinding;
class Q_QML_PRIVATE_EXPORT QQmlPropertyPrivate : public QQmlRefCount
{
public:
- QQmlContextData *context;
+ QQmlRefPointer<QQmlContextData> context;
QPointer<QQmlEngine> engine;
QPointer<QObject> object;
@@ -81,14 +83,14 @@ public:
bool isNameCached:1;
QString nameCache;
- QQmlPropertyPrivate();
+ QQmlPropertyPrivate() : isNameCached(false) {}
QQmlPropertyIndex encodedIndex() const
{ return encodedIndex(core, valueTypeData); }
static QQmlPropertyIndex encodedIndex(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData)
{ return QQmlPropertyIndex(core.coreIndex(), valueTypeData.coreIndex()); }
- inline QQmlContextData *effectiveContext() const;
+ QQmlRefPointer<QQmlContextData> effectiveContext() const;
void initProperty(QObject *obj, const QString &name);
void initDefault(QObject *obj);
@@ -106,10 +108,11 @@ public:
const QVariant &value, int flags);
static bool writeValueProperty(QObject *,
const QQmlPropertyData &, const QQmlPropertyData &valueTypeData,
- const QVariant &, QQmlContextData *,
+ const QVariant &, const QQmlRefPointer<QQmlContextData> &,
QQmlPropertyData::WriteFlags flags = {});
static bool write(QObject *, const QQmlPropertyData &, const QVariant &,
- QQmlContextData *, QQmlPropertyData::WriteFlags flags = {});
+ const QQmlRefPointer<QQmlContextData> &,
+ QQmlPropertyData::WriteFlags flags = {});
static void findAliasTarget(QObject *, QQmlPropertyIndex, QObject **, QQmlPropertyIndex *);
enum BindingFlag {
@@ -126,7 +129,8 @@ public:
static void removeBinding(QQmlAbstractBinding *b);
static QQmlAbstractBinding *binding(QObject *, QQmlPropertyIndex index);
- static QQmlProperty restore(QObject *, const QQmlPropertyData &, const QQmlPropertyData *, QQmlContextData *);
+ static QQmlProperty restore(QObject *, const QQmlPropertyData &, const QQmlPropertyData *,
+ const QQmlRefPointer<QQmlContextData> &);
int signalIndex() const;
@@ -146,8 +150,11 @@ public:
int type = 0, int *types = nullptr);
static void flushSignal(const QObject *sender, int signal_index);
- static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *context);
- static QQmlProperty create(QObject *target, const QString &propertyName, QQmlContextData *context);
+ static QVariant resolvedUrlSequence(
+ const QVariant &value, const QQmlRefPointer<QQmlContextData> &context);
+ static QQmlProperty create(
+ QObject *target, const QString &propertyName,
+ const QQmlRefPointer<QQmlContextData> &context);
};
diff --git a/src/qml/qml/qqmlpropertybinding.cpp b/src/qml/qml/qqmlpropertybinding.cpp
new file mode 100644
index 0000000000..9fffafa649
--- /dev/null
+++ b/src/qml/qml/qqmlpropertybinding.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpropertybinding_p.h"
+
+#include <private/qpropertybinding_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QUntypedPropertyBinding QQmlPropertyBinding::create(const QQmlPropertyData *pd, QV4::Function *function,
+ QObject *obj, const QQmlRefPointer<QQmlContextData> &ctxt,
+ QV4::ExecutionContext *scope)
+{
+ auto binding = new QQmlPropertyBinding(QMetaType(pd->propType()));
+ binding->setNotifyOnValueChanged(true);
+ binding->setContext(ctxt);
+ binding->setScopeObject(obj);
+ binding->setupFunction(scope, function);
+ return QUntypedPropertyBinding(QPropertyBindingPrivatePtr(binding));
+}
+
+void QQmlPropertyBinding::expressionChanged()
+{
+ markDirtyAndNotifyObservers();
+}
+
+QQmlPropertyBinding::QQmlPropertyBinding(const QMetaType &mt)
+ : QPropertyBindingPrivate(mt,
+ [this](const QMetaType &metaType, void *dataPtr) -> QUntypedPropertyBinding::BindingEvaluationResult {
+ return evaluateAndReturnTrueIfChanged(metaType, dataPtr);
+ }, QPropertyBindingSourceLocation())
+{
+}
+
+QUntypedPropertyBinding::BindingEvaluationResult QQmlPropertyBinding::evaluateAndReturnTrueIfChanged(const QMetaType &metaType, void *dataPtr)
+{
+ QQmlEngine *engine = context()->engine();
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
+ ep->referenceScarceResources();
+
+ bool isUndefined = false;
+
+ QV4::Scope scope(engine->handle());
+ QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(&isUndefined));
+
+ ep->dereferenceScarceResources();
+
+ if (hasError()) {
+ QPropertyBindingError error(QPropertyBindingError::UnknownError);
+ error.setDescription(delayedError()->error().description());
+ return error;
+ }
+
+ QVariant resultVariant(scope.engine->toVariant(result, metaType.id()));
+
+ int compareResult = 0;
+ if (QMetaType::compare(dataPtr, resultVariant.constData(), metaType.id(), &compareResult)
+ && compareResult == 0)
+ return false;
+ QMetaType::destruct(metaType.id(), dataPtr);
+ QMetaType::construct(metaType.id(), dataPtr, resultVariant.constData());
+ return true;
+}
+
+QUntypedPropertyBinding QQmlTranslationPropertyBinding::create(const QQmlPropertyData *pd, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
+{
+ auto translationBinding = [compilationUnit, binding](const QMetaType &metaType, void *dataPtr) {
+ // Create a dependency to the uiLanguage
+ QJSEnginePrivate::get(compilationUnit->engine)->uiLanguage.value();
+
+ QVariant resultVariant(compilationUnit->bindingValueAsString(binding));
+ if (metaType.id() != QMetaType::QString)
+ resultVariant.convert(metaType.id());
+
+ int compareResult = 0;
+ if (QMetaType::compare(dataPtr, resultVariant.constData(), metaType.id(), &compareResult)
+ && compareResult == 0)
+ return false;
+ QMetaType::destruct(metaType.id(), dataPtr);
+ QMetaType::construct(metaType.id(), dataPtr, resultVariant.constData());
+ return true;
+ };
+
+ return QUntypedPropertyBinding(QMetaType(pd->propType()), translationBinding, QPropertyBindingSourceLocation());
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertybinding_p.h b/src/qml/qml/qqmlpropertybinding_p.h
new file mode 100644
index 0000000000..5097f40e6f
--- /dev/null
+++ b/src/qml/qml/qqmlpropertybinding_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROPERTYBINDING_P_H
+#define QQMLPROPERTYBINDING_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qproperty.h>
+#include <private/qpropertybinding_p.h>
+
+#include "qqmlpropertydata_p.h"
+#include "qqmljavascriptexpression_p.h"
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPropertyBinding : public QQmlJavaScriptExpression,
+ public QPropertyBindingPrivate
+{
+public:
+ static QUntypedPropertyBinding create(const QQmlPropertyData *pd, QV4::Function *function,
+ QObject *obj, const QQmlRefPointer<QQmlContextData> &ctxt,
+ QV4::ExecutionContext *scope);
+
+ virtual void expressionChanged();
+
+private:
+ QQmlPropertyBinding(const QMetaType &metaType);
+
+ QUntypedPropertyBinding::BindingEvaluationResult evaluateAndReturnTrueIfChanged(const QMetaType &metaType,
+ void *dataPtr);
+};
+
+class QQmlTranslationPropertyBinding
+{
+public:
+ static QUntypedPropertyBinding create(const QQmlPropertyData *pd,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
+ const QV4::CompiledData::Binding *binding);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROPERTYBINDING_P_H
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 0e5534fc04..72226a452d 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -76,6 +76,7 @@ static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p)
flags.setIsResettable(p.isResettable());
flags.setIsFinal(p.isFinal());
flags.setIsRequired(p.isRequired());
+ flags.setIsQProperty(p.isQProperty());
if (p.isEnumType())
flags.type = QQmlPropertyData::Flags::EnumType;
@@ -83,13 +84,11 @@ static QQmlPropertyData::Flags fastFlagsForProperty(const QMetaProperty &p)
return flags;
}
-// Flags that do depend on the property's QMetaProperty::userType() and thus are slow to
-// load
-static void flagsForPropertyType(int propType, QQmlPropertyData::Flags &flags)
+// Flags that do depend on the property's QMetaType
+static void flagsForPropertyType(QMetaType metaType, QQmlPropertyData::Flags &flags)
{
- Q_ASSERT(propType != -1);
-
- if (propType == QMetaType::QObjectStar) {
+ int propType = metaType.id();
+ if (metaType.flags() & QMetaType::PointerToQObject) {
flags.type = QQmlPropertyData::Flags::QObjectDerivedType;
} else if (propType == QMetaType::QVariant) {
flags.type = QQmlPropertyData::Flags::QVariantType;
@@ -101,8 +100,7 @@ static void flagsForPropertyType(int propType, QQmlPropertyData::Flags &flags)
flags.type = QQmlPropertyData::Flags::QJSValueType;
} else {
QQmlMetaType::TypeCategory cat = QQmlMetaType::typeCategory(propType);
-
- if (cat == QQmlMetaType::Object || QMetaType::typeFlags(propType) & QMetaType::PointerToQObject)
+ if (cat == QQmlMetaType::Object)
flags.type = QQmlPropertyData::Flags::QObjectDerivedType;
else if (cat == QQmlMetaType::List)
flags.type = QQmlPropertyData::Flags::QListType;
@@ -121,17 +119,17 @@ QQmlPropertyData::Flags
QQmlPropertyData::flagsForProperty(const QMetaProperty &p)
{
auto flags = fastFlagsForProperty(p);
- flagsForPropertyType(p.userType(), flags);
+ flagsForPropertyType(p.metaType(), flags);
return flags;
}
static void populate(QQmlPropertyData *data, const QMetaProperty &p)
{
- Q_ASSERT(p.revision() <= Q_INT16_MAX);
+ Q_ASSERT(p.revision() <= std::numeric_limits<quint16>::max());
data->setCoreIndex(p.propertyIndex());
data->setNotifyIndex(QMetaObjectPrivate::signalIndex(p.notifySignal()));
data->setFlags(fastFlagsForProperty(p));
- data->setRevision(p.revision());
+ data->setRevision(QTypeRevision::fromEncodedVersion(p.revision()));
}
void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
@@ -154,8 +152,9 @@ void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
void QQmlPropertyData::load(const QMetaProperty &p)
{
populate(this, p);
- setPropType(p.userType());
- flagsForPropertyType(propType(), m_flags);
+ QMetaType type = p.metaType();
+ setPropType(type.id());
+ flagsForPropertyType(type, m_flags);
}
void QQmlPropertyData::load(const QMetaMethod &m)
@@ -183,8 +182,8 @@ void QQmlPropertyData::load(const QMetaMethod &m)
if (m.attributes() & QMetaMethod::Cloned)
m_flags.setIsCloned(true);
- Q_ASSERT(m.revision() <= Q_INT16_MAX);
- setRevision(m.revision());
+ Q_ASSERT(m.revision() <= std::numeric_limits<quint16>::max());
+ setRevision(QTypeRevision::fromEncodedVersion(m.revision()));
}
void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
@@ -212,14 +211,14 @@ QQmlPropertyCache::QQmlPropertyCache()
/*!
Creates a new QQmlPropertyCache of \a metaObject.
*/
-QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject, int metaObjectRevision)
+QQmlPropertyCache::QQmlPropertyCache(const QMetaObject *metaObject, QTypeRevision metaObjectRevision)
: QQmlPropertyCache()
{
Q_ASSERT(metaObject);
update(metaObject);
- if (metaObjectRevision > 0) {
+ if (metaObjectRevision.isValid() && metaObjectRevision != QTypeRevision::zero()) {
// Set the revision of the meta object that this cache describes to be
// 'metaObjectRevision'. This is useful when constructing a property cache
// from a type that was created directly in C++, and not through QML. For such
@@ -291,14 +290,15 @@ QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int meth
This is different from QMetaMethod::methodIndex().
*/
void QQmlPropertyCache::appendProperty(const QString &name, QQmlPropertyData::Flags flags,
- int coreIndex, int propType, int minorVersion, int notifyIndex)
+ int coreIndex, int propType, QTypeRevision version,
+ int notifyIndex)
{
QQmlPropertyData data;
data.setPropType(propType);
data.setCoreIndex(coreIndex);
data.setNotifyIndex(notifyIndex);
data.setFlags(flags);
- data.setTypeMinorVersion(minorVersion);
+ data.setTypeVersion(version);
QQmlPropertyData *old = findNamedProperty(name);
if (old)
@@ -433,12 +433,12 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
QQmlPropertyData::Flags methodFlags,
QQmlPropertyData::Flags signalFlags)
{
- return copyAndAppend(metaObject, -1, propertyFlags, methodFlags, signalFlags);
+ return copyAndAppend(metaObject, QTypeRevision(), propertyFlags, methodFlags, signalFlags);
}
QQmlPropertyCache *
QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
- int typeMinorVersion,
+ QTypeRevision typeVersion,
QQmlPropertyData::Flags propertyFlags,
QQmlPropertyData::Flags methodFlags,
QQmlPropertyData::Flags signalFlags)
@@ -452,13 +452,13 @@ QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
QMetaObjectPrivate::get(metaObject)->signalCount +
QMetaObjectPrivate::get(metaObject)->propertyCount);
- rv->append(metaObject, typeMinorVersion, propertyFlags, methodFlags, signalFlags);
+ rv->append(metaObject, typeVersion, propertyFlags, methodFlags, signalFlags);
return rv;
}
void QQmlPropertyCache::append(const QMetaObject *metaObject,
- int typeMinorVersion,
+ QTypeRevision typeVersion,
QQmlPropertyData::Flags propertyFlags,
QQmlPropertyData::Flags methodFlags,
QQmlPropertyData::Flags signalFlags)
@@ -467,7 +467,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
bool dynamicMetaObject = isDynamicMetaObject(metaObject);
- allowedRevisionCache.append(0);
+ allowedRevisionCache.append(QTypeRevision::zero());
int methodCount = metaObject->methodCount();
Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4);
@@ -612,7 +612,7 @@ void QQmlPropertyCache::append(const QMetaObject *metaObject,
data->setFlags(propertyFlags);
data->lazyLoad(p);
- data->setTypeMinorVersion(typeMinorVersion);
+ data->setTypeVersion(typeVersion);
data->m_flags.setIsDirect(!dynamicMetaObject);
@@ -662,7 +662,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->setPropType(QMetaType::type(retTy));
} else {
auto metaProperty = mo->property(data->coreIndex());
- data->setPropType(QMetaType::type(metaProperty.typeName()));
+ data->setPropType(metaProperty.metaType().id());
}
if (!data->isFunction()) {
@@ -686,7 +686,7 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->setPropType(registerResult == -1 ? QMetaType::UnknownType : registerResult);
}
}
- flagsForPropertyType(data->propType(), data->m_flags);
+ flagsForPropertyType(QMetaType(data->propType()), data->m_flags);
}
}
@@ -697,7 +697,7 @@ void QQmlPropertyCache::updateRecur(const QMetaObject *metaObject)
updateRecur(metaObject->superClass());
- append(metaObject, -1);
+ append(metaObject, QTypeRevision());
}
void QQmlPropertyCache::update(const QMetaObject *metaObject)
@@ -745,7 +745,7 @@ void QQmlPropertyCache::invalidate(const QMetaObject *metaObject)
methodIndexCacheStart = parent()->methodIndexCache.count() + parent()->methodIndexCacheStart;
signalHandlerIndexCacheStart = parent()->signalHandlerIndexCache.count() + parent()->signalHandlerIndexCacheStart;
stringCache.linkAndReserve(parent()->stringCache, reserve);
- append(metaObject, -1);
+ append(metaObject, QTypeRevision());
} else {
propertyIndexCacheStart = 0;
methodIndexCacheStart = 0;
@@ -754,7 +754,9 @@ void QQmlPropertyCache::invalidate(const QMetaObject *metaObject)
}
}
-QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it, QObject *object, QQmlContextData *context) const
+QQmlPropertyData *QQmlPropertyCache::findProperty(
+ StringCache::ConstIterator it, QObject *object,
+ const QQmlRefPointer<QQmlContextData> &context) const
{
QQmlData *data = (object ? QQmlData::get(object) : nullptr);
const QQmlVMEMetaObject *vmemo = nullptr;
@@ -767,11 +769,11 @@ QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it,
namespace {
-inline bool contextHasNoExtensions(QQmlContextData *context)
+inline bool contextHasNoExtensions(const QQmlRefPointer<QQmlContextData> &context)
{
// This context has no extension if its parent is the engine's rootContext,
// which has children but no imports
- return (!context->parent || !context->parent->imports);
+ return (!context->parent() || !context->parent()->imports());
}
inline int maximumIndexForProperty(QQmlPropertyData *prop, const int methodCount, const int signalCount, const int propertyCount)
@@ -783,7 +785,9 @@ inline int maximumIndexForProperty(QQmlPropertyData *prop, const int methodCount
}
-QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *vmemo, QQmlContextData *context) const
+QQmlPropertyData *QQmlPropertyCache::findProperty(
+ StringCache::ConstIterator it, const QQmlVMEMetaObject *vmemo,
+ const QQmlRefPointer<QQmlContextData> &context) const
{
StringCache::ConstIterator end = stringCache.end();
@@ -797,7 +801,7 @@ QQmlPropertyData *QQmlPropertyCache::findProperty(StringCache::ConstIterator it,
if (vmemo && context && !contextHasNoExtensions(context)) {
// Find the meta-object that corresponds to the supplied context
do {
- if (vmemo->ctxt == context)
+ if (vmemo->ctxt.contextData().data() == context.data())
break;
vmemo = vmemo->parentVMEMetaObject();
@@ -1008,7 +1012,7 @@ static inline QByteArray qQmlPropertyCacheToString(const QV4::String *string)
template<typename T>
QQmlPropertyData *
qQmlPropertyCacheProperty(QJSEngine *engine, QObject *obj, T name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData &local)
{
QQmlPropertyCache *cache = nullptr;
@@ -1041,21 +1045,21 @@ qQmlPropertyCacheProperty(QJSEngine *engine, QObject *obj, T name,
QQmlPropertyData *
QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QV4::String *name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData &local)
{
return qQmlPropertyCacheProperty<const QV4::String *>(engine, obj, name, context, local);
}
QQmlPropertyData *
QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QStringRef &name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData &local)
{
return qQmlPropertyCacheProperty<const QStringRef &>(engine, obj, name, context, local);
}
QQmlPropertyData *
QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QLatin1String &name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context, QQmlPropertyData &local)
{
return qQmlPropertyCacheProperty<const QLatin1String &>(engine, obj, name, context, local);
}
@@ -1066,13 +1070,10 @@ static inline const QMetaObjectPrivate *priv(const uint* data)
static inline const QByteArray stringData(const QMetaObject *mo, int index)
{
- Q_ASSERT(priv(mo->d.data)->revision >= 7);
- const QByteArrayDataPtr data = { const_cast<QByteArrayData*>(&mo->d.stringdata[index]) };
- Q_ASSERT(data.ptr->ref.isStatic());
- Q_ASSERT(data.ptr->alloc == 0);
- Q_ASSERT(data.ptr->capacityReserved == 0);
- Q_ASSERT(data.ptr->size >= 0);
- return data;
+ uint offset = mo->d.stringdata[2*index];
+ uint length = mo->d.stringdata[2*index + 1];
+ const char *string = reinterpret_cast<const char *>(mo->d.stringdata) + offset;
+ return QByteArray::fromRawData(string, length);
}
bool QQmlPropertyCache::isDynamicMetaObject(const QMetaObject *mo)
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index a5340cec37..43ffb0fb36 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -60,6 +60,7 @@
#include <private/qlinkedstringhash_p.h>
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qvector.h>
+#include <QtCore/qversionnumber.h>
#include <private/qv4value_p.h>
#include <private/qqmlpropertydata_p.h>
@@ -80,7 +81,7 @@ class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount
{
public:
QQmlPropertyCache();
- QQmlPropertyCache(const QMetaObject *, int metaObjectRevision = 0);
+ QQmlPropertyCache(const QMetaObject *, QTypeRevision metaObjectRevision = QTypeRevision::zero());
~QQmlPropertyCache() override;
void update(const QMetaObject *);
@@ -92,7 +93,8 @@ public:
QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
- QQmlPropertyCache *copyAndAppend(const QMetaObject *, int typeMinorVersion,
+ QQmlPropertyCache *copyAndAppend(
+ const QMetaObject *, QTypeRevision typeVersion,
QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
@@ -100,7 +102,7 @@ public:
QQmlPropertyCache *copyAndReserve(int propertyCount,
int methodCount, int signalCount, int enumCount);
void appendProperty(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
- int propType, int revision, int notifyIndex);
+ int propType, QTypeRevision revision, int notifyIndex);
void appendSignal(const QString &, QQmlPropertyData::Flags, int coreIndex,
const int *types = nullptr, const QList<QByteArray> &names = QList<QByteArray>());
void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex, int returnType,
@@ -112,7 +114,8 @@ public:
const QMetaObject *firstCppMetaObject() const;
template<typename K>
- QQmlPropertyData *property(const K &key, QObject *object, QQmlContextData *context) const
+ QQmlPropertyData *property(const K &key, QObject *object,
+ const QQmlRefPointer<QQmlContextData> &context) const
{
return findProperty(stringCache.find(key), object, context);
}
@@ -134,14 +137,15 @@ public:
inline bool isAllowedInRevision(QQmlPropertyData *) const;
static QQmlPropertyData *property(QJSEngine *, QObject *, const QStringRef &,
- QQmlContextData *, QQmlPropertyData &);
+ const QQmlRefPointer<QQmlContextData> &, QQmlPropertyData &);
static QQmlPropertyData *property(QJSEngine *, QObject *, const QLatin1String &,
- QQmlContextData *, QQmlPropertyData &);
+ const QQmlRefPointer<QQmlContextData> &, QQmlPropertyData &);
static QQmlPropertyData *property(QJSEngine *, QObject *, const QV4::String *,
- QQmlContextData *, QQmlPropertyData &);
+ const QQmlRefPointer<QQmlContextData> &, QQmlPropertyData &);
static QQmlPropertyData *property(QJSEngine *engine, QObject *obj, const QString &name,
- QQmlContextData *context, QQmlPropertyData &local)
+ const QQmlRefPointer<QQmlContextData> &context,
+ QQmlPropertyData &local)
{
return property(engine, obj, QStringRef(&name), context, local);
}
@@ -174,8 +178,8 @@ public:
QByteArray checksum(bool *ok);
- int allowedRevision(int index) const { return allowedRevisionCache[index]; }
- void setAllowedRevision(int index, int allowed) { allowedRevisionCache[index] = allowed; }
+ QTypeRevision allowedRevision(int index) const { return allowedRevisionCache[index]; }
+ void setAllowedRevision(int index, QTypeRevision allowed) { allowedRevisionCache[index] = allowed; }
private:
friend class QQmlEnginePrivate;
@@ -187,7 +191,7 @@ private:
inline QQmlPropertyCache *copy(int reserve);
- void append(const QMetaObject *, int typeMinorVersion,
+ void append(const QMetaObject *, QTypeRevision typeVersion,
QQmlPropertyData::Flags propertyFlags = QQmlPropertyData::Flags(),
QQmlPropertyData::Flags methodFlags = QQmlPropertyData::Flags(),
QQmlPropertyData::Flags signalFlags = QQmlPropertyData::Flags());
@@ -196,10 +200,12 @@ private:
typedef QVector<QQmlPropertyData> IndexCache;
typedef QLinkedStringMultiHash<QPair<int, QQmlPropertyData *> > StringCache;
- typedef QVector<int> AllowedRevisionCache;
+ typedef QVector<QTypeRevision> AllowedRevisionCache;
- QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *, QQmlContextData *) const;
- QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *, QQmlContextData *) const;
+ QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *,
+ const QQmlRefPointer<QQmlContextData> &) const;
+ QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *,
+ const QQmlRefPointer<QQmlContextData> &) const;
QQmlPropertyData *ensureResolved(QQmlPropertyData*) const;
@@ -352,8 +358,23 @@ QQmlPropertyCache::overrideData(QQmlPropertyData *data) const
bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const
{
- return (data->metaObjectOffset() == -1 && data->revision() == 0) ||
- (allowedRevisionCache[data->metaObjectOffset()] >= data->revision());
+ const QTypeRevision requested = data->revision();
+ const int offset = data->metaObjectOffset();
+ if (offset == -1 && requested == QTypeRevision::zero())
+ return true;
+
+ Q_ASSERT(offset >= 0);
+ Q_ASSERT(offset < allowedRevisionCache.length());
+ const QTypeRevision allowed = allowedRevisionCache[data->metaObjectOffset()];
+
+ if (requested.hasMajorVersion()) {
+ if (requested.majorVersion() > allowed.majorVersion())
+ return false;
+ if (requested.majorVersion() < allowed.majorVersion())
+ return true;
+ }
+
+ return !requested.hasMinorVersion() || requested.minorVersion() <= allowed.minorVersion();
}
int QQmlPropertyCache::propertyCount() const
diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp
index 36581bda4e..f132fb2d78 100644
--- a/src/qml/qml/qqmlpropertycachecreator.cpp
+++ b/src/qml/qml/qqmlpropertycachecreator.cpp
@@ -119,9 +119,12 @@ QQmlRefPointer<QQmlPropertyCache> QQmlBindingInstantiationContext::instantiating
{
if (instantiatingProperty) {
if (instantiatingProperty->isQObject()) {
- return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType(), instantiatingProperty->typeMinorVersion());
+ // rawPropertyCacheForType assumes a given unspecified version means "any version".
+ // There is another overload that takes no version, which we shall not use here.
+ return enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType(),
+ instantiatingProperty->typeVersion());
} else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(instantiatingProperty->propType())) {
- return enginePrivate->cache(vtmo, instantiatingProperty->typeMinorVersion());
+ return enginePrivate->cache(vtmo, instantiatingProperty->typeVersion());
}
}
return QQmlRefPointer<QQmlPropertyCache>();
diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h
index 6b02d6fb98..b98ebebed3 100644
--- a/src/qml/qml/qqmlpropertycachecreator_p.h
+++ b/src/qml/qml/qqmlpropertycachecreator_p.h
@@ -197,7 +197,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects()
const auto &ic = allICs[nodeIt->index];
QV4::ResolvedTypeReference *typeRef = objectContainer->resolvedType(ic.nameIndex);
Q_ASSERT(propertyCaches->at(ic.objectIndex) == nullptr);
- Q_ASSERT(typeRef->typePropertyCache.isNull()); // not set yet
+ Q_ASSERT(typeRef->typePropertyCache().isNull()); // not set yet
QByteArray icTypeName { objectContainer->stringAt(ic.nameIndex).toUtf8() };
QScopedValueRollback<QByteArray> nameChange {typeClassName, icTypeName};
@@ -206,8 +206,8 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjects()
if (diag.isValid()) {
return diag;
}
- typeRef->typePropertyCache = propertyCaches->at(ic.objectIndex);
- Q_ASSERT(!typeRef->typePropertyCache.isNull());
+ typeRef->setTypePropertyCache(propertyCaches->at(ic.objectIndex));
+ Q_ASSERT(!typeRef->typePropertyCache().isNull());
}
return buildMetaObjectRecursively(/*root object*/0, context, VMEMetaObjectIsRequired::Maybe);
@@ -226,7 +226,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::buildMetaObjectRecur
|| obj->signalCount() != 0 || obj->functionCount() != 0 || obj->enumCount() != 0
|| (((obj->flags & QV4::CompiledData::Object::IsComponent)
|| (objectIndex == 0 && isAddressable(objectContainer->url())))
- && !objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType);
+ && !objectContainer->resolvedType(obj->inheritedTypeNameIndex)->isFullyDynamicType());
if (!needVMEMetaObject) {
auto binding = obj->bindingsBegin();
@@ -305,10 +305,9 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine
return context.instantiatingPropertyCache(enginePrivate);
} else if (obj->inheritedTypeNameIndex != 0) {
auto *typeRef = objectContainer->resolvedType(obj->inheritedTypeNameIndex);
- QQmlType qmltype = typeRef->type;
Q_ASSERT(typeRef);
- if (typeRef->isFullyDynamicType) {
+ if (typeRef->isFullyDynamicType()) {
if (obj->propertyCount() > 0 || obj->aliasCount() > 0) {
*error = qQmlCompileError(obj->location, QQmlPropertyCacheCreatorBase::tr("Fully dynamic types cannot declare new properties."));
return nullptr;
@@ -328,7 +327,7 @@ inline QQmlRefPointer<QQmlPropertyCache> QQmlPropertyCacheCreator<ObjectContaine
auto *typeRef = objectContainer->resolvedType(
context.instantiatingBinding->propertyNameIndex);
Q_ASSERT(typeRef);
- QQmlType qmltype = typeRef->type;
+ QQmlType qmltype = typeRef->type();
if (!qmltype.isValid()) {
imports->resolveType(stringAt(context.instantiatingBinding->propertyNameIndex),
&qmltype, nullptr, nullptr, nullptr);
@@ -368,16 +367,11 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
cache->_dynamicClassName = newClassName;
- int varPropCount = 0;
-
QQmlPropertyResolver resolver(baseTypeCache);
auto p = obj->propertiesBegin();
auto pend = obj->propertiesEnd();
for ( ; p != pend; ++p) {
- if (p->builtinType() == QV4::CompiledData::BuiltinType::Var)
- varPropCount++;
-
bool notInRevision = false;
QQmlPropertyData *d = resolver.property(stringAt(p->nameIndex), &notInRevision);
if (d && d->isFinal())
@@ -539,7 +533,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
pend = obj->propertiesEnd();
for ( ; p != pend; ++p, ++propertyIdx) {
int propertyType = 0;
- int propertTypeMinorVersion = 0;
+ QTypeRevision propertyTypeVersion = QTypeRevision::zero();
QQmlPropertyData::Flags propertyFlags;
const QV4::CompiledData::BuiltinType type = p->builtinType();
@@ -558,7 +552,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
QQmlType qmltype;
bool selfReference = false;
- if (!imports->resolveType(stringAt(p->builtinTypeOrTypeNameIndex), &qmltype, nullptr, nullptr, nullptr,
+ if (!imports->resolveType(stringAt(p->builtinTypeOrTypeNameIndex), &qmltype, nullptr, nullptr,
nullptr, QQmlType::AnyRegistrationType, &selfReference)) {
return qQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Invalid property type"));
}
@@ -568,7 +562,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
if (qmltype.isComposite() || qmltype.isInlineComponentType()) {
CompositeMetaTypeIds typeIds;
if (qmltype.isInlineComponentType()) {
- auto objectId = qmltype.inlineComponendId();
+ auto objectId = qmltype.inlineComponentId();
auto containingType = qmltype.containingType();
if (containingType.isValid()) {
auto icType = containingType.lookupInlineComponentById(objectId);
@@ -591,16 +585,16 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
}
if (p->isList) {
- propertyType = typeIds.listId;
+ propertyType = typeIds.listId.id();
} else {
- propertyType = typeIds.id;
+ propertyType = typeIds.id.id();
}
} else {
if (p->isList) {
- propertyType = qmltype.qListTypeId();
+ propertyType = qmltype.qListTypeId().id();
} else {
- propertyType = qmltype.typeId();
- propertTypeMinorVersion = qmltype.minorVersion();
+ propertyType = qmltype.typeId().id();
+ propertyTypeVersion = qmltype.version();
}
}
@@ -618,7 +612,7 @@ inline QQmlError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObject(int
if (!obj->defaultPropertyIsAlias && propertyIdx == obj->indexOfDefaultPropertyOrAlias)
cache->_defaultPropertyName = propertyName;
cache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- propertyType, propertTypeMinorVersion, effectiveSignalIndex);
+ propertyType, propertyTypeVersion, effectiveSignalIndex);
effectiveSignalIndex++;
}
@@ -642,15 +636,15 @@ inline int QQmlPropertyCacheCreator<ObjectContainer>::metaTypeForParameter(const
*customTypeName = typeName;
QQmlType qmltype;
bool selfReference = false;
- if (!imports->resolveType(typeName, &qmltype, nullptr, nullptr, nullptr, nullptr, QQmlType::AnyRegistrationType,
- &selfReference))
+ if (!imports->resolveType(typeName, &qmltype, nullptr, nullptr, nullptr,
+ QQmlType::AnyRegistrationType, &selfReference))
return QMetaType::UnknownType;
if (!qmltype.isComposite())
- return qmltype.typeId();
+ return qmltype.typeId().id();
if (selfReference)
- return objectContainer->typeIdsForComponent().id;
+ return objectContainer->typeIdsForComponent().id.id();
QQmlRefPointer<QQmlTypeData> tdata = enginePrivate->typeLoader.getType(qmltype.sourceUrl());
Q_ASSERT(tdata);
@@ -658,7 +652,7 @@ inline int QQmlPropertyCacheCreator<ObjectContainer>::metaTypeForParameter(const
auto compilationUnit = tdata->compilationUnit();
- return compilationUnit->metaTypeId;
+ return compilationUnit->metaTypeId.id();
}
template <typename ObjectContainer>
@@ -675,7 +669,7 @@ public:
private:
void appendAliasPropertiesInMetaObjectsWithinComponent(const CompiledObject &component, int firstObjectIndex, QQmlEnginePrivate *enginePriv);
- QQmlError propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *rev, QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv);
+ QQmlError propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv);
void collectObjectsWithAliasesRecursively(int objectIndex, QVector<int> *objectsWithAliases) const;
@@ -786,8 +780,10 @@ inline void QQmlPropertyCacheAliasCreator<ObjectContainer>::collectObjectsWithAl
}
template <typename ObjectContainer>
-inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type, int *minorVersion,
- QQmlPropertyData::Flags *propertyFlags, QQmlEnginePrivate *enginePriv)
+inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataForAlias(
+ const CompiledObject &component, const QV4::CompiledData::Alias &alias, int *type,
+ QTypeRevision *version, QQmlPropertyData::Flags *propertyFlags,
+ QQmlEnginePrivate *enginePriv)
{
*type = 0;
bool writable = false;
@@ -819,7 +815,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
lastAlias = targetAlias;
} while (lastAlias->aliasToLocalAlias);
- return propertyDataForAlias(component, *lastAlias, type, minorVersion, propertyFlags, enginePriv);
+ return propertyDataForAlias(component, *lastAlias, type, version, propertyFlags, enginePriv);
}
const int targetObjectIndex = objectForId(component, alias.targetObjectId);
@@ -837,12 +833,13 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::propertyDataFor
QQmlPropertyCacheCreatorBase::tr("Invalid alias target"));
}
- if (typeRef->type.isValid())
- *type = typeRef->type.typeId();
+ const auto referencedType = typeRef->type();
+ if (referencedType.isValid())
+ *type = referencedType.typeId().id();
else
- *type = typeRef->compilationUnit()->metaTypeId;
+ *type = typeRef->compilationUnit()->metaTypeId.id();
- *minorVersion = typeRef->minorVersion;
+ *version = typeRef->version();
propertyFlags->type = QQmlPropertyData::Flags::QObjectDerivedType;
} else {
@@ -921,9 +918,10 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesTo
Q_ASSERT(alias->flags & QV4::CompiledData::Alias::Resolved);
int type = 0;
- int minorVersion = 0;
+ QTypeRevision version = QTypeRevision::zero();
QQmlPropertyData::Flags propertyFlags;
- QQmlError error = propertyDataForAlias(component, *alias, &type, &minorVersion, &propertyFlags, enginePriv);
+ QQmlError error = propertyDataForAlias(component, *alias, &type, &version,
+ &propertyFlags, enginePriv);
if (error.isValid())
return error;
@@ -933,7 +931,7 @@ inline QQmlError QQmlPropertyCacheAliasCreator<ObjectContainer>::appendAliasesTo
propertyCache->_defaultPropertyName = propertyName;
propertyCache->appendProperty(propertyName, propertyFlags, effectivePropertyIndex++,
- type, minorVersion, effectiveSignalIndex++);
+ type, version, effectiveSignalIndex++);
}
return QQmlError();
diff --git a/src/qml/qml/qqmlpropertycachevector_p.h b/src/qml/qml/qqmlpropertycachevector_p.h
index 1dff7c61a6..2e09423206 100644
--- a/src/qml/qml/qqmlpropertycachevector_p.h
+++ b/src/qml/qml/qqmlpropertycachevector_p.h
@@ -54,16 +54,23 @@
#include <private/qflagpointer_p.h>
#include <private/qqmlpropertycache_p.h>
+#include <QtCore/qtaggedpointer.h>
+
QT_BEGIN_NAMESPACE
class QQmlPropertyCacheVector
{
public:
+ enum Tag {
+ NoTag,
+ CacheNeedsVMEMetaObject
+ };
+
QQmlPropertyCacheVector() {}
QQmlPropertyCacheVector(QQmlPropertyCacheVector &&other)
: data(std::move(other.data)) {}
QQmlPropertyCacheVector &operator=(QQmlPropertyCacheVector &&other) {
- QVector<QFlagPointer<QQmlPropertyCache>> moved(std::move(other.data));
+ QVector<QTaggedPointer<QQmlPropertyCache, Tag>> moved(std::move(other.data));
data.swap(moved);
return *this;
}
@@ -80,7 +87,7 @@ public:
data.clear();
}
- void append(QQmlPropertyCache *cache) { cache->addref(); data.append(cache); }
+ void append(QQmlPropertyCache *cache) { cache->addref(); data.append(QTaggedPointer<QQmlPropertyCache, Tag>(cache)); }
QQmlPropertyCache *at(int index) const { return data.at(index).data(); }
void set(int index, const QQmlRefPointer<QQmlPropertyCache> &replacement) {
if (QQmlPropertyCache *oldCache = data.at(index).data()) {
@@ -92,11 +99,11 @@ public:
replacement->addref();
}
- void setNeedsVMEMetaObject(int index) { data[index].setFlag(); }
- bool needsVMEMetaObject(int index) const { return data.at(index).flag(); }
+ void setNeedsVMEMetaObject(int index) { data[index].setTag(CacheNeedsVMEMetaObject); }
+ bool needsVMEMetaObject(int index) const { return data.at(index).tag() == CacheNeedsVMEMetaObject; }
private:
Q_DISABLE_COPY(QQmlPropertyCacheVector)
- QVector<QFlagPointer<QQmlPropertyCache>> data;
+ QVector<QTaggedPointer<QQmlPropertyCache, Tag>> data;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertydata_p.h b/src/qml/qml/qqmlpropertydata_p.h
index 7f70c34854..697c995706 100644
--- a/src/qml/qml/qqmlpropertydata_p.h
+++ b/src/qml/qml/qqmlpropertydata_p.h
@@ -53,6 +53,7 @@
#include <private/qobject_p.h>
#include <QtCore/qglobal.h>
+#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
@@ -96,7 +97,7 @@ public:
// b when type equals FunctionType. For that reason, the semantic meaning of the bit is
// overloaded, and the accessor functions are used to get the correct value
//
- // Moreover, isSignalHandler, isOverload and isCloned and isConstructor make only sense
+ // Moreover, isSignalHandler, isOverload and isCloned make only sense
// for functions, too (and could at a later point be reused for flags that only make sense
// for non-functions)
//
@@ -110,7 +111,7 @@ public:
unsigned isSignalHandler : 1; // Function is a signal handler
unsigned isOverload : 1; // Function is an overload of another function
unsigned isRequiredORisCloned : 1; // Has REQUIRED flag OR The function was marked as cloned
- unsigned isConstructor : 1; // The function was marked is a constructor
+ unsigned isConstructorORisQProperty : 1; // The function was marked is a constructor OR property is backed by QProperty<T>
unsigned isDirect : 1; // Exists on a C++ QMetaObject
unsigned isOverridden : 1; // Is overridden by a extension property
public:
@@ -155,6 +156,10 @@ public:
isOverridden = b;
}
+ void setIsQProperty(bool b) {
+ isConstructorORisQProperty = b;
+ }
+
void setIsDirect(bool b) {
isDirect = b;
}
@@ -203,7 +208,7 @@ public:
void setIsConstructor(bool b) {
Q_ASSERT(type == FunctionType);
- isConstructor = b;
+ isConstructorORisQProperty = b;
}
};
@@ -248,10 +253,11 @@ public:
bool isOverload() const { return m_flags.isOverload; }
void setOverload(bool onoff) { m_flags.isOverload = onoff; }
bool isCloned() const { return isFunction() && m_flags.isRequiredORisCloned; }
- bool isConstructor() const { return m_flags.isConstructor; }
+ bool isConstructor() const { return m_flags.isConstructorORisQProperty; }
+ bool isQProperty() const { return m_flags.isConstructorORisQProperty; }
bool hasOverride() const { return overrideIndex() >= 0; }
- bool hasRevision() const { return revision() != 0; }
+ bool hasRevision() const { return revision() != QTypeRevision::zero(); }
bool isFullyResolved() const { return !m_flags.notFullyResolved; }
@@ -290,12 +296,8 @@ public:
m_coreIndex = qint16(idx);
}
- quint8 revision() const { return m_revision; }
- void setRevision(quint8 rev)
- {
- Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
- m_revision = quint8(rev);
- }
+ QTypeRevision revision() const { return m_revision; }
+ void setRevision(QTypeRevision revision) { m_revision = revision; }
/* If a property is a C++ type, then we store the minor
* version of this type.
@@ -315,12 +317,8 @@ public:
*
*/
- quint8 typeMinorVersion() const { return m_typeMinorVersion; }
- void setTypeMinorVersion(quint8 rev)
- {
- Q_ASSERT(rev <= std::numeric_limits<quint8>::max());
- m_typeMinorVersion = quint8(rev);
- }
+ QTypeRevision typeVersion() const { return m_typeVersion; }
+ void setTypeVersion(QTypeRevision typeVersion) { m_typeVersion = typeVersion; }
QQmlPropertyCacheMethodArguments *arguments() const { return m_arguments; }
void setArguments(QQmlPropertyCacheMethodArguments *args) { m_arguments = args; }
@@ -412,22 +410,25 @@ private:
qint16 m_notifyIndex = -1;
qint16 m_overrideIndex = -1;
- quint8 m_revision = 0;
- quint8 m_typeMinorVersion = 0;
qint16 m_metaObjectOffset = -1;
+ quint16 m_reserved = 0;
+
+ QTypeRevision m_revision = QTypeRevision::zero();
+ QTypeRevision m_typeVersion = QTypeRevision::zero();
QQmlPropertyCacheMethodArguments *m_arguments = nullptr;
StaticMetaCallFunction m_staticMetaCallFunction = nullptr;
};
#if QT_POINTER_SIZE == 4
- Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 24);
+ Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 28);
#else // QT_POINTER_SIZE == 8
- Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 32);
+ Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 40);
#endif
bool QQmlPropertyData::operator==(const QQmlPropertyData &other) const
{
+ Q_UNUSED(m_reserved)
return flags() == other.flags() &&
propType() == other.propType() &&
coreIndex() == other.coreIndex() &&
@@ -445,7 +446,7 @@ QQmlPropertyData::Flags::Flags()
, isSignalHandler(false)
, isOverload(false)
, isRequiredORisCloned(false)
- , isConstructor(false)
+ , isConstructorORisQProperty(false)
, isOverridden(false)
, type(OtherType)
, notFullyResolved(false)
@@ -463,7 +464,7 @@ bool QQmlPropertyData::Flags::operator==(const QQmlPropertyData::Flags &other) c
isSignalHandler == other.isSignalHandler &&
isRequiredORisCloned == other.isRequiredORisCloned &&
type == other.type &&
- isConstructor == other.isConstructor &&
+ isConstructorORisQProperty == other.isConstructorORisQProperty &&
notFullyResolved == other.notFullyResolved &&
overrideIndexIsProperty == other.overrideIndexIsProperty;
}
diff --git a/src/qml/qml/qqmlpropertyresolver.cpp b/src/qml/qml/qqmlpropertyresolver.cpp
index 90eaca0b90..396f2876b9 100644
--- a/src/qml/qml/qqmlpropertyresolver.cpp
+++ b/src/qml/qml/qqmlpropertyresolver.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qqmlpropertyresolver_p.h"
+#include <private/qqmlcontextdata_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertyvalidator.cpp b/src/qml/qml/qqmlpropertyvalidator.cpp
index 3587609301..d7afffeaf9 100644
--- a/src/qml/qml/qqmlpropertyvalidator.cpp
+++ b/src/qml/qml/qqmlpropertyvalidator.cpp
@@ -117,8 +117,9 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
QQmlCustomParser *customParser = nullptr;
if (auto typeRef = resolvedType(obj->inheritedTypeNameIndex)) {
- if (typeRef->type.isValid())
- customParser = typeRef->type.customParser();
+ const auto type = typeRef->type();
+ if (type.isValid())
+ customParser = type.customParser();
}
QList<const QV4::CompiledData::Binding*> customBindings;
@@ -190,9 +191,16 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
if (notInRevision) {
QString typeName = stringAt(obj->inheritedTypeNameIndex);
- auto *objectType = resolvedType(obj->inheritedTypeNameIndex);
- if (objectType && objectType->type.isValid()) {
- return recordError(binding->location, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(name).arg(objectType->type.module()).arg(objectType->majorVersion).arg(objectType->minorVersion));
+ if (auto *objectType = resolvedType(obj->inheritedTypeNameIndex)) {
+ const auto type = objectType->type();
+ if (type.isValid()) {
+ const auto version = objectType->version();
+ return recordError(binding->location,
+ tr("\"%1.%2\" is not available in %3 %4.%5.")
+ .arg(typeName).arg(name).arg(type.module())
+ .arg(version.majorVersion())
+ .arg(version.minorVersion()));
+ }
} else {
return recordError(binding->location, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name));
}
@@ -212,7 +220,7 @@ QVector<QQmlError> QQmlPropertyValidator::validateObject(
if (name.constData()->isUpper() && !binding->isAttachedProperty()) {
QQmlType type;
QQmlImportNamespace *typeNamespace = nullptr;
- imports.resolveType(stringAt(binding->propertyNameIndex), &type, nullptr, nullptr, &typeNamespace);
+ imports.resolveType(stringAt(binding->propertyNameIndex), &type, nullptr, &typeNamespace);
if (typeNamespace)
return recordError(binding->location, tr("Invalid use of namespace"));
return recordError(binding->location, tr("Invalid attached object assignment"));
@@ -588,7 +596,6 @@ QQmlError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache *prope
}
}
break;
- case QMetaType::QRegExp:
case QMetaType::QRegularExpression:
return warnOrError(tr("Invalid property assignment: regular expression expected; use /pattern/ syntax"));
default: {
@@ -744,8 +751,8 @@ QQmlError QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *propert
// We want to use the raw metaObject here as the raw metaobject is the
// actual property type before we applied any extensions that might
// effect the properties on the type, but don't effect assignability
- // Using -1 for the minor version ensures that we get the raw metaObject.
- QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(propType, -1);
+ // Not passing a version ensures that we get the raw metaObject.
+ QQmlPropertyCache *propertyMetaObject = enginePrivate->rawPropertyCacheForType(propType);
if (propertyMetaObject) {
// Will be true if the assigned type inherits propertyMetaObject
diff --git a/src/qml/qml/qqmlscriptblob.cpp b/src/qml/qml/qqmlscriptblob.cpp
index dac21f7ee7..14ed501131 100644
--- a/src/qml/qml/qqmlscriptblob.cpp
+++ b/src/qml/qml/qqmlscriptblob.cpp
@@ -42,6 +42,7 @@
#include <private/qqmlscriptblob_p.h>
#include <private/qqmlscriptdata_p.h>
#include <private/qqmlsourcecoordinate_p.h>
+#include <private/qqmlcontextdata_p.h>
#include <private/qv4runtimecodegen_p.h>
#include <private/qv4script_p.h>
diff --git a/src/qml/qml/qqmlscriptdata.cpp b/src/qml/qml/qqmlscriptdata.cpp
index ae268ca904..50ec0e20cd 100644
--- a/src/qml/qml/qqmlscriptdata.cpp
+++ b/src/qml/qml/qqmlscriptdata.cpp
@@ -55,78 +55,82 @@ QQmlScriptData::QQmlScriptData()
{
}
-QQmlContextData *QQmlScriptData::qmlContextDataForContext(QQmlContextData *parentQmlContextData)
+QQmlRefPointer<QQmlContextData> QQmlScriptData::qmlContextDataForContext(
+ const QQmlRefPointer<QQmlContextData> &parentQmlContextData)
{
- Q_ASSERT(parentQmlContextData && parentQmlContextData->engine);
+ Q_ASSERT(parentQmlContextData && parentQmlContextData->engine());
if (m_precompiledScript->isESModule())
return nullptr;
- auto qmlContextData = new QQmlContextData();
+ QQmlRefPointer<QQmlContextData> qmlContextData = m_precompiledScript->isSharedLibrary()
+ ? QQmlContextData::createRefCounted(QQmlRefPointer<QQmlContextData>())
+ : QQmlContextData::createRefCounted(parentQmlContextData);
- qmlContextData->isInternal = true;
- qmlContextData->isJSContext = true;
+ qmlContextData->setInternal(true);
+ qmlContextData->setJSContext(true);
if (m_precompiledScript->isSharedLibrary())
- qmlContextData->isPragmaLibraryContext = true;
+ qmlContextData->setPragmaLibraryContext(true);
else
- qmlContextData->isPragmaLibraryContext = parentQmlContextData->isPragmaLibraryContext;
- qmlContextData->baseUrl = url;
- qmlContextData->baseUrlString = urlString;
+ qmlContextData->setPragmaLibraryContext(parentQmlContextData->isPragmaLibraryContext());
+ qmlContextData->setBaseUrl(url);
+ qmlContextData->setBaseUrlString(urlString);
// For backward compatibility, if there are no imports, we need to use the
// imports from the parent context. See QTBUG-17518.
if (!typeNameCache->isEmpty()) {
- qmlContextData->imports = typeNameCache;
+ qmlContextData->setImports(typeNameCache);
} else if (!m_precompiledScript->isSharedLibrary()) {
- qmlContextData->imports = parentQmlContextData->imports;
- qmlContextData->importedScripts = parentQmlContextData->importedScripts;
+ qmlContextData->setImports(parentQmlContextData->imports());
+ qmlContextData->setImportedScripts(parentQmlContextData->importedScripts());
}
- if (!m_precompiledScript->isSharedLibrary()) {
- qmlContextData->setParent(parentQmlContextData);
- } else {
- qmlContextData->engine = parentQmlContextData->engine; // Fix for QTBUG-21620
- }
+ if (m_precompiledScript->isSharedLibrary())
+ qmlContextData->setEngine(parentQmlContextData->engine()); // Fix for QTBUG-21620
- QV4::ExecutionEngine *v4 = parentQmlContextData->engine->handle();
+ QV4::ExecutionEngine *v4 = parentQmlContextData->engine()->handle();
QV4::Scope scope(v4);
QV4::ScopedObject scriptsArray(scope);
- if (qmlContextData->importedScripts.isNullOrUndefined()) {
+ if (qmlContextData->importedScripts().isNullOrUndefined()) {
scriptsArray = v4->newArrayObject(scripts.count());
- qmlContextData->importedScripts.set(v4, scriptsArray);
+ qmlContextData->setImportedScripts(
+ QV4::PersistentValue(v4, scriptsArray.asReturnedValue()));
} else {
- scriptsArray = qmlContextData->importedScripts.valueRef();
+ scriptsArray = qmlContextData->importedScripts().valueRef();
}
QV4::ScopedValue v(scope);
- for (int ii = 0; ii < scripts.count(); ++ii)
- scriptsArray->put(ii, (v = scripts.at(ii)->scriptData()->scriptValueForContext(qmlContextData)));
+ for (int ii = 0; ii < scripts.count(); ++ii) {
+ v = scripts.at(ii)->scriptData()->scriptValueForContext(qmlContextData.data());
+ scriptsArray->put(ii, v);
+ }
return qmlContextData;
}
-QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parentQmlContextData)
+QV4::ReturnedValue QQmlScriptData::scriptValueForContext(
+ const QQmlRefPointer<QQmlContextData> &parentQmlContextData)
{
if (m_loaded)
return m_value.value();
- Q_ASSERT(parentQmlContextData && parentQmlContextData->engine);
- QV4::ExecutionEngine *v4 = parentQmlContextData->engine->handle();
+ Q_ASSERT(parentQmlContextData && parentQmlContextData->engine());
+ QV4::ExecutionEngine *v4 = parentQmlContextData->engine()->handle();
QV4::Scope scope(v4);
if (!hasEngine()) {
- addToEngine(parentQmlContextData->engine);
+ addToEngine(parentQmlContextData->engine());
addref();
}
- QQmlContextDataRef qmlContextData = qmlContextDataForContext(parentQmlContextData);
QV4::Scoped<QV4::QmlContext> qmlExecutionContext(scope);
- if (qmlContextData)
- qmlExecutionContext =
- QV4::QmlContext::create(v4->rootContext(), qmlContextData, /* scopeObject: */ nullptr);
+ if (auto qmlContextData = qmlContextDataForContext(parentQmlContextData)) {
+ qmlExecutionContext = QV4::QmlContext::create(v4->rootContext(), std::move(qmlContextData),
+ /* scopeObject: */ nullptr);
+ }
QV4::Scoped<QV4::Module> module(scope, m_precompiledScript->instantiate(v4));
if (module) {
- if (qmlContextData) {
+ if (qmlExecutionContext) {
module->d()->scope->outer.set(v4, qmlExecutionContext->d());
qmlExecutionContext->d()->qml()->module.set(v4, module->d());
}
@@ -141,7 +145,7 @@ QV4::ReturnedValue QQmlScriptData::scriptValueForContext(QQmlContextData *parent
}
QV4::ScopedValue value(scope);
- if (qmlContextData)
+ if (qmlExecutionContext)
value = qmlExecutionContext->d()->qml();
else if (module)
value = module->d();
diff --git a/src/qml/qml/qqmlscriptdata_p.h b/src/qml/qml/qqmlscriptdata_p.h
index 80b65b699c..abbafc33c2 100644
--- a/src/qml/qml/qqmlscriptdata_p.h
+++ b/src/qml/qml/qqmlscriptdata_p.h
@@ -85,7 +85,7 @@ public:
QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
QVector<QQmlRefPointer<QQmlScriptBlob>> scripts;
- QV4::ReturnedValue scriptValueForContext(QQmlContextData *parentCtxt);
+ QV4::ReturnedValue scriptValueForContext(const QQmlRefPointer<QQmlContextData> &parentCtxt);
QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit() const { return m_precompiledScript; }
@@ -96,7 +96,8 @@ private:
friend class QQmlScriptBlob;
void initialize(QQmlEngine *);
- QQmlContextData *qmlContextDataForContext(QQmlContextData *parentQmlContextData);
+ QQmlRefPointer<QQmlContextData> qmlContextDataForContext(
+ const QQmlRefPointer<QQmlContextData> &parentQmlContextData);
bool m_loaded;
QQmlRefPointer<QV4::ExecutableCompilationUnit> m_precompiledScript;
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
index 96a35b0fe9..b02df4a3e4 100644
--- a/src/qml/qml/qqmltype.cpp
+++ b/src/qml/qml/qqmltype.cpp
@@ -53,7 +53,7 @@
QT_BEGIN_NAMESPACE
QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type)
- : regType(type), iid(nullptr), typeId(0), listId(0), revision(0),
+ : regType(type), iid(nullptr), revision(QTypeRevision::zero()),
containsRevisionedAttributes(false), baseMetaObject(nullptr),
index(-1), isSetup(false), isEnumFromCacheSetup(false), isEnumFromBaseSetup(false),
haveSuperType(false)
@@ -132,34 +132,33 @@ QHashedString QQmlType::module() const
return d->module;
}
-int QQmlType::majorVersion() const
+QTypeRevision QQmlType::version() const
{
if (!d)
- return -1;
- return d->version_maj;
+ return QTypeRevision();
+ return d->version;
}
-int QQmlType::minorVersion() const
+bool QQmlType::availableInVersion(QTypeRevision version) const
{
if (!d)
- return -1;
- return d->version_min;
-}
+ return false;
-bool QQmlType::availableInVersion(int vmajor, int vminor) const
-{
- Q_ASSERT(vmajor >= 0 && vminor >= 0);
- if (!d)
+ if (!version.hasMajorVersion())
+ return true;
+
+ if (version.majorVersion() != d->version.majorVersion())
return false;
- return vmajor == d->version_maj && vminor >= d->version_min;
+
+ return !version.hasMinorVersion() || version.minorVersion() >= d->version.minorVersion();
}
-bool QQmlType::availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const
+bool QQmlType::availableInVersion(const QHashedStringRef &module, QTypeRevision version) const
{
- Q_ASSERT(vmajor >= 0 && vminor >= 0);
- if (!d)
+ if (!d || module != d->module)
return false;
- return module == d->module && vmajor == d->version_maj && vminor >= d->version_min;
+
+ return availableInVersion(version);
}
QQmlType QQmlTypePrivate::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
@@ -592,14 +591,14 @@ bool QQmlType::isQJSValueSingleton() const
return d && d->regType == SingletonType && d->extraData.sd->singletonInstanceInfo->scriptCallback;
}
-int QQmlType::typeId() const
+QMetaType QQmlType::typeId() const
{
- return d ? d->typeId : -1;
+ return d ? d->typeId : QMetaType{};
}
-int QQmlType::qListTypeId() const
+QMetaType QQmlType::qListTypeId() const
{
- return d ? d->listId : -1;
+ return d ? d->listId : QMetaType{};
}
const QMetaObject *QQmlType::metaObject() const
@@ -629,9 +628,9 @@ bool QQmlType::containsRevisionedAttributes() const
return d->containsRevisionedAttributes;
}
-int QQmlType::metaObjectRevision() const
+QTypeRevision QQmlType::metaObjectRevision() const
{
- return d ? d->revision : -1;
+ return d ? d->revision : QTypeRevision();
}
QQmlAttachedPropertiesFunc QQmlType::attachedPropertiesFunction(QQmlEnginePrivate *engine) const
@@ -699,7 +698,7 @@ bool QQmlType::isInlineComponentType() const {
return d ? d->regType == QQmlType::InlineComponentType : false;
}
-int QQmlType::inlineComponendId() const {
+int QQmlType::inlineComponentId() const {
bool ok = false;
if (d->regType == QQmlType::RegistrationType::InlineComponentType) {
Q_ASSERT(d->extraData.id->objectId != -1);
@@ -714,7 +713,7 @@ QUrl QQmlType::sourceUrl() const
auto url = d ? d->sourceUrl() : QUrl();
if (url.isValid() && d->regType == QQmlType::RegistrationType::InlineComponentType && d->extraData.id->objectId) {
Q_ASSERT(url.hasFragment());
- url.setFragment(QString::number(inlineComponendId()));
+ url.setFragment(QString::number(inlineComponentId()));
}
return url;
}
@@ -882,7 +881,7 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scope
return -1;
}
-int QQmlType::inlineComponentObjectId()
+int QQmlType::inlineComponentObjectId() const
{
if (!isInlineComponentType())
return -1;
diff --git a/src/qml/qml/qqmltype_p.h b/src/qml/qml/qqmltype_p.h
index 387baa74bb..7f224b3f60 100644
--- a/src/qml/qml/qqmltype_p.h
+++ b/src/qml/qml/qqmltype_p.h
@@ -60,6 +60,7 @@
#include <QtQml/qjsvalue.h>
#include <QtCore/qobject.h>
+#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
@@ -98,11 +99,10 @@ public:
QString elementName() const;
QHashedString module() const;
- int majorVersion() const;
- int minorVersion() const;
+ QTypeRevision version() const;
- bool availableInVersion(int vmajor, int vminor) const;
- bool availableInVersion(const QHashedStringRef &module, int vmajor, int vminor) const;
+ bool availableInVersion(QTypeRevision version) const;
+ bool availableInVersion(const QHashedStringRef &module, QTypeRevision version) const;
QObject *create() const;
void create(QObject **, void **, size_t) const;
@@ -124,12 +124,12 @@ public:
bool isQObjectSingleton() const;
bool isQJSValueSingleton() const;
- int typeId() const;
- int qListTypeId() const;
+ QMetaType typeId() const;
+ QMetaType qListTypeId() const;
const QMetaObject *metaObject() const;
const QMetaObject *baseMetaObject() const;
- int metaObjectRevision() const;
+ QTypeRevision metaObjectRevision() const;
bool containsRevisionedAttributes() const;
QQmlAttachedPropertiesFunc attachedPropertiesFunction(QQmlEnginePrivate *engine) const;
@@ -146,7 +146,7 @@ public:
int index() const;
bool isInlineComponentType() const;
- int inlineComponendId() const;
+ int inlineComponentId() const;
struct Q_QML_PRIVATE_EXPORT SingletonInstanceInfo
{
@@ -170,7 +170,7 @@ public:
int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &, bool *ok) const;
int scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &, const QByteArray &, bool *ok) const;
int scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &, const QStringRef &, bool *ok) const;
- int inlineComponentObjectId();
+ int inlineComponentObjectId() const;
void setInlineComponentObjectId(int id) const; // TODO: const setters are BAD
const QQmlTypePrivate *priv() const { return d.data(); }
diff --git a/src/qml/qml/qqmltype_p_p.h b/src/qml/qml/qqmltype_p_p.h
index 43344827db..c94ac8c130 100644
--- a/src/qml/qml/qqmltype_p_p.h
+++ b/src/qml/qml/qqmltype_p_p.h
@@ -157,11 +157,10 @@ public:
QHashedString module;
QString name;
QString elementName;
- int version_maj;
- int version_min;
- int typeId;
- int listId;
- int revision;
+ QMetaType typeId;
+ QMetaType listId;
+ QTypeRevision version;
+ QTypeRevision revision;
mutable bool containsRevisionedAttributes;
mutable QQmlType superType;
const QMetaObject *baseMetaObject;
diff --git a/src/qml/qml/qqmltypecompiler.cpp b/src/qml/qml/qqmltypecompiler.cpp
index 058bf8848c..65b9213954 100644
--- a/src/qml/qml/qqmltypecompiler.cpp
+++ b/src/qml/qml/qqmltypecompiler.cpp
@@ -71,7 +71,7 @@ QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile()
for (auto it = resolvedTypes->constBegin(), end = resolvedTypes->constEnd();
it != end; ++it) {
- QQmlCustomParser *customParser = (*it)->type.customParser();
+ QQmlCustomParser *customParser = (*it)->type().customParser();
if (customParser)
customParsers.insert(it.key(), customParser);
}
@@ -264,7 +264,7 @@ QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scrip
return object->bindingAsString(document, scriptIndex);
}
-void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion)
+void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier, QTypeRevision version)
{
const quint32 moduleIdx = registerString(module);
const quint32 qualifierIdx = registerString(qualifier);
@@ -279,8 +279,7 @@ void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier
auto pool = memoryPool();
QV4::CompiledData::Import *import = pool->New<QV4::CompiledData::Import>();
import->type = QV4::CompiledData::Import::ImportLibrary;
- import->majorVersion = majorVersion;
- import->minorVersion = minorVersion;
+ import->version = version;
import->uriIndex = moduleIdx;
import->qualifierIndex = qualifierIdx;
document->imports.append(import);
@@ -333,45 +332,55 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
QHash<QString, QStringList> customSignals;
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
- QString propertyName = stringAt(binding->propertyNameIndex);
+ const QString bindingPropertyName = stringAt(binding->propertyNameIndex);
// Attached property?
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex);
auto *typeRef = resolvedType(binding->propertyNameIndex);
- QQmlType type = typeRef ? typeRef->type : QQmlType();
+ QQmlType type = typeRef ? typeRef->type() : QQmlType();
if (!type.isValid())
- imports->resolveType(propertyName, &type, nullptr, nullptr, nullptr);
+ imports->resolveType(bindingPropertyName, &type, nullptr, nullptr, nullptr);
const QMetaObject *attachedType = type.attachedPropertiesType(enginePrivate);
if (!attachedType)
COMPILE_EXCEPTION(binding, tr("Non-existent attached object"));
QQmlPropertyCache *cache = compiler->enginePrivate()->cache(attachedType);
- if (!convertSignalHandlerExpressionsToFunctionDeclarations(attachedObj, propertyName, cache))
+ if (!convertSignalHandlerExpressionsToFunctionDeclarations(attachedObj, bindingPropertyName, cache))
return false;
continue;
}
- if (!QmlIR::IRBuilder::isSignalPropertyName(propertyName))
+ if (!QmlIR::IRBuilder::isSignalPropertyName(bindingPropertyName))
continue;
QQmlPropertyResolver resolver(propertyCache);
- Q_ASSERT(propertyName.startsWith(QLatin1String("on")));
- propertyName.remove(0, 2);
+ Q_ASSERT(bindingPropertyName.startsWith(QLatin1String("on")));
+ QString signalNameCandidate = bindingPropertyName;
+ signalNameCandidate.remove(0, 2);
// Note that the property name could start with any alpha or '_' or '$' character,
// so we need to do the lower-casing of the first alpha character.
- for (int firstAlphaIndex = 0; firstAlphaIndex < propertyName.size(); ++firstAlphaIndex) {
- if (propertyName.at(firstAlphaIndex).isUpper()) {
- propertyName[firstAlphaIndex] = propertyName.at(firstAlphaIndex).toLower();
+ for (int firstAlphaIndex = 0; firstAlphaIndex < signalNameCandidate.size(); ++firstAlphaIndex) {
+ if (signalNameCandidate.at(firstAlphaIndex).isUpper()) {
+ signalNameCandidate[firstAlphaIndex] = signalNameCandidate.at(firstAlphaIndex).toLower();
break;
}
}
+ QString qPropertyName;
+ if (signalNameCandidate.endsWith(QLatin1String("Changed")))
+ qPropertyName = signalNameCandidate.mid(0, signalNameCandidate.length() - static_cast<int>(strlen("Changed")));
+
QList<QString> parameters;
bool notInRevision = false;
- QQmlPropertyData *signal = resolver.signal(propertyName, &notInRevision);
+ QQmlPropertyData * const signal = resolver.signal(signalNameCandidate, &notInRevision);
+ QQmlPropertyData * const signalPropertyData = resolver.property(signalNameCandidate, /*notInRevision ptr*/nullptr);
+ QQmlPropertyData * const qPropertyData = !qPropertyName.isEmpty() ? resolver.property(qPropertyName) : nullptr;
+ QString finalSignalHandlerPropertyName = signalNameCandidate;
+ uint flags = QV4::CompiledData::Binding::IsSignalHandlerExpression;
+
if (signal) {
int sigIndex = propertyCache->methodIndexToSignalIndex(signal->coreIndex());
sigIndex = propertyCache->originalClone(sigIndex);
@@ -390,18 +399,24 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
}
parameters += param;
}
+ } else if (!signalPropertyData && qPropertyData && qPropertyData->isQProperty()) {
+ finalSignalHandlerPropertyName = qPropertyName;
+ flags = QV4::CompiledData::Binding::IsPropertyObserver;
} else {
if (notInRevision) {
// Try assinging it as a property later
- if (resolver.property(propertyName, /*notInRevision ptr*/nullptr))
+ if (signalPropertyData)
continue;
const QString &originalPropertyName = stringAt(binding->propertyNameIndex);
auto *typeRef = resolvedType(obj->inheritedTypeNameIndex);
- const QQmlType type = typeRef ? typeRef->type : QQmlType();
+ const QQmlType type = typeRef ? typeRef->type() : QQmlType();
if (type.isValid()) {
- COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(typeName).arg(originalPropertyName).arg(type.module()).arg(type.majorVersion()).arg(type.minorVersion()));
+ COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.")
+ .arg(typeName).arg(originalPropertyName).arg(type.module())
+ .arg(type.version().majorVersion())
+ .arg(type.version().minorVersion()));
} else {
COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(originalPropertyName));
}
@@ -422,11 +437,9 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
}
}
- QHash<QString, QStringList>::ConstIterator entry = customSignals.constFind(propertyName);
- if (entry == customSignals.constEnd() && propertyName.endsWith(QLatin1String("Changed"))) {
- QString alternateName = propertyName.mid(0, propertyName.length() - static_cast<int>(strlen("Changed")));
- entry = customSignals.constFind(alternateName);
- }
+ QHash<QString, QStringList>::ConstIterator entry = customSignals.constFind(signalNameCandidate);
+ if (entry == customSignals.constEnd() && !qPropertyName.isEmpty())
+ entry = customSignals.constFind(qPropertyName);
if (entry == customSignals.constEnd()) {
// Can't find even a custom signal, then just don't do anything and try
@@ -488,8 +501,8 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
functionDeclaration->rbraceToken = foe->node->lastSourceLocation();
}
foe->node = functionDeclaration;
- binding->propertyNameIndex = compiler->registerString(propertyName);
- binding->flags |= QV4::CompiledData::Binding::IsSignalHandlerExpression;
+ binding->propertyNameIndex = compiler->registerString(finalSignalHandlerPropertyName);
+ binding->flags |= flags;
}
return true;
}
@@ -514,7 +527,8 @@ bool QQmlEnumTypeResolver::resolveEnumBindings()
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject
+ || binding->flags & QV4::CompiledData::Binding::IsPropertyObserver)
continue;
if (binding->type != QV4::CompiledData::Binding::Type_Script)
@@ -537,12 +551,6 @@ bool QQmlEnumTypeResolver::resolveEnumBindings()
return true;
}
-struct StaticQtMetaObject : public QObject
-{
- static const QMetaObject *get()
- { return &staticQtMetaObject; }
-};
-
bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, const QStringRef &enumName, int enumValue, bool isQtObject)
{
if (enumName.length() > 0 && enumName[0].isLower() && !isQtObject) {
@@ -611,7 +619,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
bool ok = false;
auto *tr = resolvedType(obj->inheritedTypeNameIndex);
- if (type.isValid() && tr && tr->type == type) {
+ if (type.isValid() && tr && tr->type() == type) {
// When these two match, we can short cut the search
QMetaProperty mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex());
QMetaEnum menum = mprop.enumerator();
@@ -633,7 +641,7 @@ bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(const QmlIR::Object *obj,
value = type.enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok);
} else {
QByteArray enumName = enumValue.toUtf8();
- const QMetaObject *metaObject = StaticQtMetaObject::get();
+ const QMetaObject *metaObject = &Qt::staticMetaObject;
for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) {
QMetaEnum e = metaObject->enumerator(ii);
value = e.keyToValue(enumName.constData(), &ok);
@@ -662,7 +670,7 @@ int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, const QStringRef &e
return type.enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue.constData(), enumValue.length()), ok);
}
- const QMetaObject *mo = StaticQtMetaObject::get();
+ const QMetaObject *mo = &Qt::staticMetaObject;
int i = mo->enumeratorCount();
const QByteArray ba = enumValue.toUtf8();
while (i--) {
@@ -811,8 +819,9 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
Q_ASSERT(tr);
const QMetaObject *firstMetaObject = nullptr;
- if (tr->type.isValid())
- firstMetaObject = tr->type.metaObject();
+ const auto type = tr->type();
+ if (type.isValid())
+ firstMetaObject = type.metaObject();
else if (const auto compilationUnit = tr->compilationUnit())
firstMetaObject = compilationUnit->rootPropertyCache()->firstCppMetaObject();
if (isUsableComponent(firstMetaObject))
@@ -829,7 +838,12 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
if (!pd || !pd->isQObject())
continue;
- QQmlPropertyCache *pc = enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeMinorVersion());
+ // If the version is given, use it and look up by QQmlType.
+ // Otherwise, make sure we look up by metaobject.
+ // TODO: Is this correct?
+ QQmlPropertyCache *pc = pd->typeVersion().hasMinorVersion()
+ ? enginePrivate->rawPropertyCacheForType(pd->propType(), pd->typeVersion())
+ : enginePrivate->rawPropertyCacheForType(pd->propType());
const QMetaObject *mo = pc ? pc->firstCppMetaObject() : nullptr;
while (mo) {
if (mo == &QQmlComponent::staticMetaObject)
@@ -845,7 +859,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
Q_ASSERT(componentType.isValid());
const QString qualifier = QStringLiteral("QmlInternals");
- compiler->addImport(componentType.module(), qualifier, componentType.majorVersion(), componentType.minorVersion());
+ compiler->addImport(componentType.module(), qualifier, componentType.version());
QmlIR::Object *syntheticComponent = pool->New<QmlIR::Object>();
syntheticComponent->init(pool, compiler->registerString(qualifier + QLatin1Char('.') + componentType.elementName()), compiler->registerString(QString()));
@@ -854,9 +868,8 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) {
auto typeRef = new QV4::ResolvedTypeReference;
- typeRef->type = componentType;
- typeRef->majorVersion = componentType.majorVersion();
- typeRef->minorVersion = componentType.minorVersion();
+ typeRef->setType(componentType);
+ typeRef->setVersion(componentType.version());
insertResolvedType(syntheticComponent->inheritedTypeNameIndex, typeRef);
}
@@ -901,7 +914,7 @@ bool QQmlComponentAndAliasResolver::resolve()
if (obj->inheritedTypeNameIndex) {
auto *tref = resolvedType(obj->inheritedTypeNameIndex);
Q_ASSERT(tref);
- if (tref->type.metaObject() == &QQmlComponent::staticMetaObject)
+ if (tref->type().metaObject() == &QQmlComponent::staticMetaObject)
isExplicitComponent = true;
}
if (!isExplicitComponent) {
@@ -1318,7 +1331,8 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
}
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
- || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject
+ || binding->flags & QV4::CompiledData::Binding::IsPropertyObserver)
continue;
if (!pd) {
diff --git a/src/qml/qml/qqmltypecompiler_p.h b/src/qml/qml/qqmltypecompiler_p.h
index 057dd012c6..883fbf0d68 100644
--- a/src/qml/qml/qqmltypecompiler_p.h
+++ b/src/qml/qml/qqmltypecompiler_p.h
@@ -125,7 +125,7 @@ public:
QString bindingAsString(const QmlIR::Object *object, int scriptIndex) const;
- void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion);
+ void addImport(const QString &module, const QString &qualifier, QTypeRevision version);
QV4::ResolvedTypeReference *resolvedType(int id) const
{
diff --git a/src/qml/qml/qqmltypedata.cpp b/src/qml/qml/qqmltypedata.cpp
index fc1d0cfbcf..fea0062242 100644
--- a/src/qml/qml/qqmltypedata.cpp
+++ b/src/qml/qml/qqmltypedata.cpp
@@ -182,8 +182,8 @@ bool QQmlTypeData::tryLoadFromDiskCache()
const QV4::CompiledData::Import *import = m_compiledData->importAt(i);
if (m_compiledData->stringAt(import->uriIndex) == QLatin1String(".")
&& import->qualifierIndex == 0
- && import->majorVersion == -1
- && import->minorVersion == -1) {
+ && !import->version.hasMajorVersion()
+ && !import->version.hasMinorVersion()) {
QList<QQmlError> errors;
auto pendingImport = std::make_shared<PendingImport>(this, import);
if (!fetchQmldir(qmldirUrl, pendingImport, 1, &errors)) {
@@ -213,9 +213,9 @@ bool QQmlTypeData::tryLoadFromDiskCache()
QQmlType containingType;
auto containingTypeName = finalUrl().fileName().split(QLatin1Char('.')).first();
- int major = -1, minor = -1;
+ QTypeRevision version;
QQmlImportNamespace *ns = nullptr;
- m_importCache.resolveType(containingTypeName, &containingType, &major, &minor, &ns);
+ m_importCache.resolveType(containingTypeName, &containingType, &version, &ns);
for (auto&& ic: ics) {
QString const nameString = m_compiledData->stringAt(ic.nameIndex);
QByteArray const name = nameString.toUtf8();
@@ -658,9 +658,9 @@ void QQmlTypeData::continueLoadFromIR()
{
QQmlType containingType;
auto containingTypeName = finalUrl().fileName().split(QLatin1Char('.')).first();
- int major = -1, minor = -1;
+ QTypeRevision version;
QQmlImportNamespace *ns = nullptr;
- m_importCache.resolveType(containingTypeName, &containingType, &major, &minor, &ns);
+ m_importCache.resolveType(containingTypeName, &containingType, &version, &ns);
for (auto const& object: m_document->objects) {
for (auto it = object->inlineComponentsBegin(); it != object->inlineComponentsEnd(); ++it) {
QString const nameString = m_document->stringAt(it->nameIndex);
@@ -686,8 +686,7 @@ void QQmlTypeData::continueLoadFromIR()
// This qmldir is for the implicit import
auto implicitImport = std::make_shared<PendingImport>();
implicitImport->uri = QLatin1String(".");
- implicitImport->majorVersion = -1;
- implicitImport->minorVersion = -1;
+ implicitImport->version = QTypeRevision();
QList<QQmlError> errors;
if (!fetchQmldir(qmldirUrl, implicitImport, 1, &errors)) {
@@ -831,11 +830,8 @@ void QQmlTypeData::resolveTypes()
typeName = csRef.typeName;
}
- int majorVersion = csRef.majorVersion > -1 ? csRef.majorVersion : -1;
- int minorVersion = csRef.minorVersion > -1 ? csRef.minorVersion : -1;
-
- if (!resolveType(typeName, majorVersion, minorVersion, ref, -1, -1, true,
- QQmlType::CompositeSingletonType))
+ QTypeRevision version = csRef.version;
+ if (!resolveType(typeName, version, ref, -1, -1, true, QQmlType::CompositeSingletonType))
return;
if (ref.type.isCompositeSingleton()) {
@@ -859,14 +855,13 @@ void QQmlTypeData::resolveTypes()
const bool reportErrors = unresolvedRef->errorWhenNotFound;
- int majorVersion = -1;
- int minorVersion = -1;
+ QTypeRevision version;
const QString name = stringAt(unresolvedRef.key());
bool *selfReferenceDetection = unresolvedRef->needsCreation ? nullptr : &ref.selfReference;
- if (!resolveType(name, majorVersion, minorVersion, ref, unresolvedRef->location.line,
+ if (!resolveType(name, version, ref, unresolvedRef->location.line,
unresolvedRef->location.column, reportErrors,
QQmlType::AnyRegistrationType, selfReferenceDetection) && reportErrors)
return;
@@ -886,8 +881,7 @@ void QQmlTypeData::resolveTypes()
}
}
}
- ref.majorVersion = majorVersion;
- ref.minorVersion = minorVersion;
+ ref.version = version;
ref.location.line = unresolvedRef->location.line;
ref.location.column = unresolvedRef->location.column;
@@ -934,49 +928,47 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches(
objectId = qmlType.containingType().lookupInlineComponentIdByName(QString::fromUtf8(qmlType.typeName()));
qmlType.setInlineComponentObjectId(objectId);
} else {
- objectId = resolvedType->type.inlineComponendId();
+ objectId = resolvedType->type.inlineComponentId();
}
Q_ASSERT(objectId != -1);
- ref->typePropertyCache = resolvedType->typeData->compilationUnit()->propertyCaches.at(objectId);
- ref->type = qmlType;
- Q_ASSERT(ref->type.isInlineComponentType());
+ ref->setTypePropertyCache(resolvedType->typeData->compilationUnit()->propertyCaches.at(objectId));
+ ref->setType(qmlType);
+ Q_ASSERT(ref->type().isInlineComponentType());
}
} else if (resolvedType->type.isInlineComponentType()) {
// Inline component, defined in the file we are currently compiling
if (!m_inlineComponentToCompiledData.contains(resolvedType.key())) {
- ref->type = qmlType;
+ ref->setType(qmlType);
if (qmlType.isValid()) {
// this is required for inline components in singletons
- auto typeID = qmlType.lookupInlineComponentById(qmlType.inlineComponendId()).typeId();
+ auto type = qmlType.lookupInlineComponentById(qmlType.inlineComponentId()).typeId();
+ auto typeID = type.isValid() ? type.id() : -1;
auto exUnit = engine->obtainExecutableCompilationUnit(typeID);
if (exUnit) {
ref->setCompilationUnit(exUnit);
- ref->typePropertyCache = engine->propertyCacheForType(typeID);
+ ref->setTypePropertyCache(engine->propertyCacheForType(typeID));
}
}
} else {
ref->setCompilationUnit(m_inlineComponentToCompiledData[resolvedType.key()]);
- ref->typePropertyCache = m_inlineComponentToCompiledData[resolvedType.key()]->rootPropertyCache();
+ ref->setTypePropertyCache(m_inlineComponentToCompiledData[resolvedType.key()]->rootPropertyCache());
}
} else if (qmlType.isValid() && !resolvedType->selfReference) {
- ref->type = qmlType;
- Q_ASSERT(ref->type.isValid());
+ ref->setType(qmlType);
+ Q_ASSERT(ref->type().isValid());
- if (resolvedType->needsCreation && !ref->type.isCreatable()) {
- QString reason = ref->type.noCreationReason();
+ if (resolvedType->needsCreation && !qmlType.isCreatable()) {
+ QString reason = qmlType.noCreationReason();
if (reason.isEmpty())
reason = tr("Element is not creatable.");
return qQmlCompileError(resolvedType->location, reason);
}
- if (ref->type.containsRevisionedAttributes()) {
- ref->typePropertyCache = engine->cache(ref->type,
- resolvedType->minorVersion);
- }
+ if (qmlType.containsRevisionedAttributes())
+ ref->setTypePropertyCache(engine->cache(qmlType, resolvedType->version));
}
- ref->majorVersion = resolvedType->majorVersion;
- ref->minorVersion = resolvedType->minorVersion;
+ ref->setVersion(resolvedType->version);
ref->doDynamicTypeCheck();
resolvedTypeCache->insert(resolvedType.key(), ref.take());
}
@@ -984,7 +976,7 @@ QQmlError QQmlTypeData::buildTypeResolutionCaches(
return noError;
}
-bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &minorVersion,
+bool QQmlTypeData::resolveType(const QString &typeName, QTypeRevision &version,
TypeReference &ref, int lineNumber, int columnNumber,
bool reportErrors, QQmlType::RegistrationType registrationType,
bool *typeRecursionDetected)
@@ -992,7 +984,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &
QQmlImportNamespace *typeNamespace = nullptr;
QList<QQmlError> errors;
- bool typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion,
+ bool typeFound = m_importCache.resolveType(typeName, &ref.type, &version,
&typeNamespace, &errors, registrationType,
typeRecursionDetected);
if (!typeNamespace && !typeFound && !m_implicitImportLoaded) {
@@ -1000,7 +992,7 @@ bool QQmlTypeData::resolveType(const QString &typeName, int &majorVersion, int &
if (loadImplicitImport()) {
// Try again to find the type
errors.clear();
- typeFound = m_importCache.resolveType(typeName, &ref.type, &majorVersion, &minorVersion,
+ typeFound = m_importCache.resolveType(typeName, &ref.type, &version,
&typeNamespace, &errors, registrationType,
typeRecursionDetected);
} else {
diff --git a/src/qml/qml/qqmltypedata_p.h b/src/qml/qml/qqmltypedata_p.h
index 906a0ee171..c3b0faa5b4 100644
--- a/src/qml/qml/qqmltypedata_p.h
+++ b/src/qml/qml/qqmltypedata_p.h
@@ -62,12 +62,11 @@ class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob
public:
struct TypeReference
{
- TypeReference() : majorVersion(0), minorVersion(0), needsCreation(true) {}
+ TypeReference() : version(QTypeRevision::zero()), needsCreation(true) {}
QV4::CompiledData::Location location;
QQmlType type;
- int majorVersion;
- int minorVersion;
+ QTypeRevision version;
QQmlRefPointer<QQmlTypeData> typeData;
bool selfReference = false;
QString prefix; // used by CompositeSingleton types
@@ -134,7 +133,7 @@ private:
const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
void createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
const QV4::ResolvedTypeReferenceMap &resolvedTypeCache);
- bool resolveType(const QString &typeName, int &majorVersion, int &minorVersion,
+ bool resolveType(const QString &typeName, QTypeRevision &version,
TypeReference &ref, int lineNumber = -1, int columnNumber = -1,
bool reportErrors = true,
QQmlType::RegistrationType registrationType = QQmlType::AnyRegistrationType,
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 1d66e756fa..c8e5054f87 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -488,8 +488,7 @@ QQmlTypeLoader::Blob::PendingImport::PendingImport(QQmlTypeLoader::Blob *blob, c
type = static_cast<QV4::CompiledData::Import::ImportType>(quint32(import->type));
uri = blob->stringAt(import->uriIndex);
qualifier = blob->stringAt(import->qualifierIndex);
- majorVersion = import->majorVersion;
- minorVersion = import->minorVersion;
+ version = import->version;
location = import->location;
}
@@ -579,12 +578,13 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo
QString qmldirUrl;
const QQmlImports::LocalQmldirResult qmldirResult = m_importCache.locateLocalQmldir(
- importDatabase, import->uri, import->majorVersion, import->minorVersion,
+ importDatabase, import->uri, import->version,
&qmldirFilePath, &qmldirUrl);
if (qmldirResult == QQmlImports::QmldirFound) {
// This is a local library import
- if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion,
- import->minorVersion, qmldirFilePath, qmldirUrl, false, errors))
+ if (!m_importCache.addLibraryImport(
+ importDatabase, import->uri, import->qualifier,
+ import->version, qmldirFilePath, qmldirUrl, false, errors))
return false;
if (!loadImportDependencies(import, qmldirFilePath, errors))
@@ -606,44 +606,48 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo
} else if (
// Major version of module already registered:
// We believe that the registration is complete.
- QQmlMetaType::typeModule(import->uri, import->majorVersion)
+ QQmlMetaType::typeModule(import->uri, import->version)
// Otherwise, try to register further module types.
|| (qmldirResult != QQmlImports::QmldirInterceptedToRemote
- && QQmlMetaType::qmlRegisterModuleTypes(import->uri, import->majorVersion))
+ && QQmlMetaType::qmlRegisterModuleTypes(import->uri))
// Otherwise, there is no way to register any further types.
// Try with any module of that name.
|| QQmlMetaType::isAnyModule(import->uri)) {
if (!m_importCache.addLibraryImport(
- importDatabase, import->uri, import->qualifier, import->majorVersion,
- import->minorVersion, QString(), QString(), false, errors)) {
+ importDatabase, import->uri, import->qualifier, import->version,
+ QString(), QString(), false, errors)) {
return false;
}
} else {
// We haven't yet resolved this import
m_unresolvedImports << import;
- QQmlAbstractUrlInterceptor *interceptor = typeLoader()->engine()->urlInterceptor();
+ const QQmlEngine *engine = typeLoader()->engine();
+ const bool hasInterceptors
+ = !(QQmlEnginePrivate::get(engine)->urlInterceptors.isEmpty());
// Query any network import paths for this library.
// Interceptor might redirect local paths.
QStringList remotePathList = importDatabase->importPathList(
- interceptor ? QQmlImportDatabase::LocalOrRemote
- : QQmlImportDatabase::Remote);
+ hasInterceptors ? QQmlImportDatabase::LocalOrRemote
+ : QQmlImportDatabase::Remote);
if (!remotePathList.isEmpty()) {
// Add this library and request the possible locations for it
- if (!m_importCache.addLibraryImport(importDatabase, import->uri, import->qualifier, import->majorVersion,
- import->minorVersion, QString(), QString(), true, errors))
+ if (!m_importCache.addLibraryImport(
+ importDatabase, import->uri, import->qualifier, import->version,
+ QString(), QString(), true, errors))
return false;
// Probe for all possible locations
int priority = 0;
- const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(import->uri, remotePathList, import->majorVersion, import->minorVersion);
+ const QStringList qmlDirPaths = QQmlImports::completeQmldirPaths(
+ import->uri, remotePathList, import->version);
for (const QString &qmldirPath : qmlDirPaths) {
- if (interceptor) {
- QUrl url = interceptor->intercept(
+ if (hasInterceptors) {
+ QUrl url = engine->interceptUrl(
QQmlImports::urlFromLocalFileOrQrcOrUrl(qmldirPath),
QQmlAbstractUrlInterceptor::QmldirFile);
if (!QQmlFile::isLocalFile(url)
@@ -672,8 +676,8 @@ bool QQmlTypeLoader::Blob::addImport(QQmlTypeLoader::Blob::PendingImportPtr impo
incomplete = true;
}
- if (!m_importCache.addFileImport(importDatabase, import->uri, import->qualifier, import->majorVersion,
- import->minorVersion, incomplete, errors))
+ if (!m_importCache.addFileImport(importDatabase, import->uri, import->qualifier,
+ import->version, incomplete, errors))
return false;
if (incomplete) {
@@ -712,8 +716,7 @@ bool QQmlTypeLoader::Blob::loadImportDependencies(PendingImportPtr currentImport
auto dependencyImport = std::make_shared<PendingImport>();
dependencyImport->uri = implicitImports;
dependencyImport->qualifier = currentImport->qualifier;
- dependencyImport->majorVersion = currentImport->majorVersion;
- dependencyImport->minorVersion = currentImport->minorVersion;
+ dependencyImport->version = currentImport->version;
if (!addImport(dependencyImport, errors))
return false;
}
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index adecf61896..a1ba2967e3 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -97,8 +97,7 @@ public:
QString uri;
QString qualifier;
- int majorVersion = -1;
- int minorVersion = -1;
+ QTypeRevision version;
QV4::CompiledData::Location location;
diff --git a/src/qml/qml/qqmltypemodule.cpp b/src/qml/qml/qqmltypemodule.cpp
index 9d6f269030..e6bf796d74 100644
--- a/src/qml/qml/qqmltypemodule.cpp
+++ b/src/qml/qml/qqmltypemodule.cpp
@@ -45,7 +45,7 @@
QT_BEGIN_NAMESPACE
-QQmlTypeModule::QQmlTypeModule(const QString &module, int majorVersion)
+QQmlTypeModule::QQmlTypeModule(const QString &module, quint8 majorVersion)
: d(new QQmlTypeModulePrivate(module, majorVersion))
{
}
@@ -61,23 +61,23 @@ QString QQmlTypeModule::module() const
return d->module;
}
-int QQmlTypeModule::majorVersion() const
+quint8 QQmlTypeModule::majorVersion() const
{
// No need to lock. d->majorVersion is const
return d->majorVersion;
}
-int QQmlTypeModule::minimumMinorVersion() const
+quint8 QQmlTypeModule::minimumMinorVersion() const
{
return d->minMinorVersion.loadRelaxed();
}
-int QQmlTypeModule::maximumMinorVersion() const
+quint8 QQmlTypeModule::maximumMinorVersion() const
{
return d->maxMinorVersion.loadRelaxed();
}
-void QQmlTypeModule::addMinorVersion(int version)
+void QQmlTypeModule::addMinorVersion(quint8 version)
{
for (int oldVersion = d->minMinorVersion.loadRelaxed();
oldVersion > version && !d->minMinorVersion.testAndSetOrdered(oldVersion, version);
@@ -93,16 +93,16 @@ void QQmlTypeModule::addMinorVersion(int version)
void QQmlTypeModule::add(QQmlTypePrivate *type)
{
QMutexLocker lock(&d->mutex);
- addMinorVersion(type->version_min);
+ addMinorVersion(type->version.minorVersion());
QList<QQmlTypePrivate *> &list = d->typeHash[type->elementName];
for (int ii = 0; ii < list.count(); ++ii) {
QQmlTypePrivate *in_list = list.at(ii);
Q_ASSERT(in_list);
- if (in_list->version_min < type->version_min) {
+ if (in_list->version.minorVersion() < type->version.minorVersion()) {
list.insert(ii, type);
return;
- } else if (in_list->version_min == type->version_min) {
+ } else if (in_list->version.minorVersion() == type->version.minorVersion()) {
list[ii] = type;
return;
}
@@ -137,26 +137,26 @@ void QQmlTypeModule::lock()
d->locked.storeRelaxed(1);
}
-QQmlType QQmlTypeModule::type(const QHashedStringRef &name, int minor) const
+QQmlType QQmlTypeModule::type(const QHashedStringRef &name, QTypeRevision version) const
{
QMutexLocker lock(&d->mutex);
QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
if (types) {
for (int ii = 0; ii < types->count(); ++ii)
- if (types->at(ii)->version_min <= minor)
+ if (types->at(ii)->version.minorVersion() <= version.minorVersion())
return QQmlType(types->at(ii));
}
return QQmlType();
}
-QQmlType QQmlTypeModule::type(const QV4::String *name, int minor) const
+QQmlType QQmlTypeModule::type(const QV4::String *name, QTypeRevision version) const
{
QMutexLocker lock(&d->mutex);
QList<QQmlTypePrivate *> *types = d->typeHash.value(name);
if (types) {
for (int ii = 0; ii < types->count(); ++ii)
- if (types->at(ii)->version_min <= minor)
+ if (types->at(ii)->version.minorVersion() <= version.minorVersion())
return QQmlType(types->at(ii));
}
diff --git a/src/qml/qml/qqmltypemodule_p.h b/src/qml/qml/qqmltypemodule_p.h
index b84a91b5db..d3149567a3 100644
--- a/src/qml/qml/qqmltypemodule_p.h
+++ b/src/qml/qml/qqmltypemodule_p.h
@@ -53,6 +53,7 @@
#include <QtQml/qtqmlglobal.h>
#include <QtCore/qstring.h>
+#include <QtCore/qversionnumber.h>
#include <functional>
@@ -72,7 +73,7 @@ class QQmlTypeModulePrivate;
class QQmlTypeModule
{
public:
- QQmlTypeModule(const QString &uri = QString(), int majorVersion = 0);
+ QQmlTypeModule(const QString &uri = QString(), quint8 majorVersion = 0);
~QQmlTypeModule();
void add(QQmlTypePrivate *);
@@ -82,14 +83,14 @@ public:
void lock();
QString module() const;
- int majorVersion() const;
+ quint8 majorVersion() const;
- void addMinorVersion(int minorVersion);
- int minimumMinorVersion() const;
- int maximumMinorVersion() const;
+ void addMinorVersion(quint8 minorVersion);
+ quint8 minimumMinorVersion() const;
+ quint8 maximumMinorVersion() const;
- QQmlType type(const QHashedStringRef &, int) const;
- QQmlType type(const QV4::String *, int) const;
+ QQmlType type(const QHashedStringRef &, QTypeRevision version) const;
+ QQmlType type(const QV4::String *, QTypeRevision version) const;
void walkCompositeSingletons(const std::function<void(const QQmlType &)> &callback) const;
diff --git a/src/qml/qml/qqmltypemodule_p_p.h b/src/qml/qml/qqmltypemodule_p_p.h
index b1dab1c4a0..5d4d2e458a 100644
--- a/src/qml/qml/qqmltypemodule_p_p.h
+++ b/src/qml/qml/qqmltypemodule_p_p.h
@@ -62,15 +62,15 @@ QT_BEGIN_NAMESPACE
class QQmlTypeModulePrivate
{
public:
- QQmlTypeModulePrivate(QString module, int majorVersion) :
+ QQmlTypeModulePrivate(QString module, quint8 majorVersion) :
module(std::move(module)), majorVersion(majorVersion)
{}
const QString module;
- const int majorVersion = 0;
+ const quint8 majorVersion = 0;
// Can only ever decrease
- QAtomicInt minMinorVersion = std::numeric_limits<int>::max();
+ QAtomicInt minMinorVersion = std::numeric_limits<quint8>::max();
// Can only ever increase
QAtomicInt maxMinorVersion = 0;
diff --git a/src/qml/qml/qqmltypemoduleversion.cpp b/src/qml/qml/qqmltypemoduleversion.cpp
index bbbfa1a7b6..932ff7f503 100644
--- a/src/qml/qml/qqmltypemoduleversion.cpp
+++ b/src/qml/qml/qqmltypemoduleversion.cpp
@@ -39,9 +39,6 @@
#include "qqmltypemoduleversion_p.h"
-#include <private/qqmltype_p.h>
-#include <private/qqmltypemodule_p.h>
-
QT_BEGIN_NAMESPACE
QQmlTypeModuleVersion::QQmlTypeModuleVersion()
@@ -49,11 +46,10 @@ QQmlTypeModuleVersion::QQmlTypeModuleVersion()
{
}
-QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, int minor)
- : m_module(module), m_minor(minor)
+QQmlTypeModuleVersion::QQmlTypeModuleVersion(QQmlTypeModule *module, QTypeRevision version)
+ : m_module(module), m_minor(version.minorVersion())
{
Q_ASSERT(m_module);
- Q_ASSERT(m_minor >= 0);
}
QQmlTypeModuleVersion::QQmlTypeModuleVersion(const QQmlTypeModuleVersion &o)
@@ -68,28 +64,4 @@ QQmlTypeModuleVersion &QQmlTypeModuleVersion::operator=(const QQmlTypeModuleVers
return *this;
}
-QQmlTypeModule *QQmlTypeModuleVersion::module() const
-{
- return m_module;
-}
-
-int QQmlTypeModuleVersion::minorVersion() const
-{
- return m_minor;
-}
-
-QQmlType QQmlTypeModuleVersion::type(const QHashedStringRef &name) const
-{
- if (!m_module)
- return QQmlType();
- return m_module->type(name, m_minor);
-}
-
-QQmlType QQmlTypeModuleVersion::type(const QV4::String *name) const
-{
- if (!m_module)
- return QQmlType();
- return m_module->type(name, m_minor);
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypemoduleversion_p.h b/src/qml/qml/qqmltypemoduleversion_p.h
index 20f4709ecb..c5379b2158 100644
--- a/src/qml/qml/qqmltypemoduleversion_p.h
+++ b/src/qml/qml/qqmltypemoduleversion_p.h
@@ -52,6 +52,9 @@
//
#include <QtQml/qtqmlglobal.h>
+#include <QtQml/private/qqmltype_p.h>
+#include <QtQml/private/qqmltypemodule_p.h>
+#include <QtCore/qversionnumber.h>
QT_BEGIN_NAMESPACE
@@ -67,19 +70,23 @@ class QQmlTypeModuleVersion
{
public:
QQmlTypeModuleVersion();
- QQmlTypeModuleVersion(QQmlTypeModule *, int);
+ QQmlTypeModuleVersion(QQmlTypeModule *, QTypeRevision);
QQmlTypeModuleVersion(const QQmlTypeModuleVersion &);
QQmlTypeModuleVersion &operator=(const QQmlTypeModuleVersion &);
- QQmlTypeModule *module() const;
- int minorVersion() const;
-
- QQmlType type(const QHashedStringRef &) const;
- QQmlType type(const QV4::String *) const;
+ template<typename String>
+ QQmlType type(String name) const
+ {
+ if (!m_module)
+ return QQmlType();
+ return m_module->type(name, QTypeRevision::isValidSegment(m_minor)
+ ? QTypeRevision::fromMinorVersion(m_minor)
+ : QTypeRevision());
+ }
private:
QQmlTypeModule *m_module;
- int m_minor;
+ quint8 m_minor;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp
index 1015403226..45333668e3 100644
--- a/src/qml/qml/qqmltypenamecache.cpp
+++ b/src/qml/qml/qqmltypenamecache.cpp
@@ -101,7 +101,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name)
QQmlImportNamespace *typeNamespace = nullptr;
QList<QQmlError> errors;
QQmlType t;
- bool typeFound = m_imports.resolveType(name, &t, nullptr, nullptr, &typeNamespace, &errors);
+ bool typeFound = m_imports.resolveType(name, &t, nullptr, &typeNamespace, &errors);
if (typeFound) {
return Result(t);
}
@@ -129,7 +129,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name,
QQmlImportNamespace *typeNamespace = nullptr;
QList<QQmlError> errors;
QQmlType t;
- bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, nullptr, &typeNamespace, &errors);
+ bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, &typeNamespace, &errors);
if (typeFound) {
return Result(t);
}
@@ -155,7 +155,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, QQml
QList<QQmlError> errors;
QQmlType t;
bool typeRecursionDetected = false;
- bool typeFound = m_imports.resolveType(typeName, &t, nullptr, nullptr, &typeNamespace, &errors,
+ bool typeFound = m_imports.resolveType(typeName, &t, nullptr, &typeNamespace, &errors,
QQmlType::AnyRegistrationType,
recursionRestriction == QQmlImport::AllowRecursion ? &typeRecursionDetected : nullptr);
if (typeFound) {
@@ -191,7 +191,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, cons
QQmlImportNamespace *typeNamespace = nullptr;
QList<QQmlError> errors;
QQmlType t;
- bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, nullptr, &typeNamespace, &errors);
+ bool typeFound = m_imports.resolveType(qualifiedTypeName, &t, nullptr, &typeNamespace, &errors);
if (typeFound) {
return Result(t);
}
diff --git a/src/qml/qml/qqmltypenotavailable_p.h b/src/qml/qml/qqmltypenotavailable_p.h
index d8427f2961..dbd37ace2a 100644
--- a/src/qml/qml/qqmltypenotavailable_p.h
+++ b/src/qml/qml/qqmltypenotavailable_p.h
@@ -58,8 +58,8 @@ QT_BEGIN_NAMESPACE
class QQmlTypeNotAvailable : public QObject {
Q_OBJECT
QML_NAMED_ELEMENT(TypeNotAvailable)
+ QML_ADDED_IN_VERSION(2, 15)
QML_UNCREATABLE("Type not available.")
- QML_ADDED_IN_MINOR_VERSION(15)
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index fa5d36503d..da76659ef4 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -183,7 +183,7 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons
if (hasProperty)
*hasProperty = true;
- QQmlContextData *context = v4->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = v4->callingQmlContext();
QObject *object = w->d()->object;
QQmlType type = w->d()->type();
@@ -233,7 +233,7 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons
QJSValue scriptSingleton = e->singletonInstance<QJSValue>(type);
if (!scriptSingleton.isUndefined()) {
// NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable.
- QV4::ScopedObject o(scope, QJSValuePrivate::convertedToValue(v4, scriptSingleton));
+ QV4::ScopedObject o(scope, QJSValuePrivate::asReturnedValue(&scriptSingleton));
if (!!o)
return o->get(name);
}
@@ -283,10 +283,10 @@ ReturnedValue QQmlTypeWrapper::virtualGet(const Managed *m, PropertyKey id, cons
if (r.type.isValid()) {
return create(scope.engine, object, r.type, w->d()->mode);
} else if (r.scriptIndex != -1) {
- QV4::ScopedObject scripts(scope, context->importedScripts.valueRef());
+ QV4::ScopedObject scripts(scope, context->importedScripts().valueRef());
return scripts->get(r.scriptIndex);
} else if (r.importNamespace) {
- return create(scope.engine, object, context->imports, r.importNamespace);
+ return create(scope.engine, object, context->imports(), r.importNamespace);
}
return QV4::Encode::undefined();
@@ -329,7 +329,7 @@ bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value,
return false;
ScopedString name(scope, id.asStringOrSymbol());
- QQmlContextData *context = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
QQmlType type = w->d()->type();
if (type.isValid() && !type.isSingleton() && w->d()->object) {
@@ -349,7 +349,7 @@ bool QQmlTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &value,
} else {
QJSValue scriptSingleton = e->singletonInstance<QJSValue>(type);
if (!scriptSingleton.isUndefined()) {
- QV4::ScopedObject apiprivate(scope, QJSValuePrivate::convertedToValue(scope.engine, scriptSingleton));
+ QV4::ScopedObject apiprivate(scope, QJSValuePrivate::asReturnedValue(&scriptSingleton));
if (!apiprivate) {
QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"');
scope.engine->throwError(error);
@@ -407,9 +407,9 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const
if (!wrapperObject)
return engine->throwTypeError();
- const int myTypeId = typeWrapper->d()->type().typeId();
+ const QMetaType myTypeId = typeWrapper->d()->type().typeId();
QQmlMetaObject myQmlType;
- if (myTypeId == 0) {
+ if (!myTypeId.isValid()) {
// we're a composite type; a composite type cannot be equal to a
// non-composite object instance (Rectangle{} is never an instance of
// CustomRectangle)
@@ -420,9 +420,9 @@ ReturnedValue QQmlTypeWrapper::virtualInstanceOf(const Object *typeObject, const
QQmlRefPointer<QQmlTypeData> td = qenginepriv->typeLoader.getType(typeWrapper->d()->type().sourceUrl());
ExecutableCompilationUnit *cu = td->compilationUnit();
- myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId);
+ myQmlType = qenginepriv->metaObjectForType(cu->metaTypeId.id());
} else {
- myQmlType = qenginepriv->metaObjectForType(myTypeId);
+ myQmlType = qenginepriv->metaObjectForType(myTypeId.id());
}
const QMetaObject *theirType = wrapperObject->metaObject();
@@ -440,7 +440,7 @@ ReturnedValue QQmlTypeWrapper::virtualResolveLookupGetter(const Object *object,
const QQmlTypeWrapper *This = static_cast<const QQmlTypeWrapper *>(object);
ScopedString name(scope, id.asStringOrSymbol());
- QQmlContextData *qmlContext = engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> qmlContext = engine->callingQmlContext();
Scoped<QQmlTypeWrapper> w(scope, static_cast<const QQmlTypeWrapper *>(This));
QQmlType type = w->d()->type();
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index a86564a49a..254f1015e2 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -132,8 +132,10 @@ const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t)
return &QQmlRectValueType::staticMetaObject;
case QMetaType::QRectF:
return &QQmlRectFValueType::staticMetaObject;
+#if QT_CONFIG(easingcurve)
case QMetaType::QEasingCurve:
return &QQmlEasingValueType::staticMetaObject;
+#endif
#if QT_CONFIG(qml_itemmodel)
case QMetaType::QModelIndex:
return &QQmlModelIndexValueType::staticMetaObject;
@@ -214,7 +216,9 @@ const QMetaObject *QQmlValueTypeFactory::metaObjectForMetaType(int type)
void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, int versionMinor)
{
+#if QT_CONFIG(easingcurve)
qmlRegisterValueTypeEnums<QQmlEasingValueType>(uri, versionMajor, versionMinor, "Easing");
+#endif
}
QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject)
@@ -527,6 +531,7 @@ int QQmlRectValueType::bottom() const
return v.bottom();
}
+#if QT_CONFIG(easingcurve)
QQmlEasingValueType::Type QQmlEasingValueType::type() const
{
return (QQmlEasingValueType::Type)v.type();
@@ -620,6 +625,8 @@ QVariantList QQmlEasingValueType::bezierCurve() const
rv << QVariant(point.x()) << QVariant(point.y());
return rv;
}
+#endif // easingcurve
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 29fa999725..0b38c746d6 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -60,7 +60,9 @@
#include <QtCore/qobject.h>
#include <QtCore/qrect.h>
+#if QT_CONFIG(easingcurve)
#include <QtCore/qeasingcurve.h>
+#endif
#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
@@ -238,11 +240,13 @@ public:
int bottom() const;
};
+#if QT_CONFIG(easingcurve)
struct QQmlEasingValueType
{
QEasingCurve v;
Q_GADGET
QML_NAMED_ELEMENT(Easing)
+ QML_ADDED_IN_VERSION(2, 0)
QML_UNCREATABLE("Use the Type enum.")
Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL)
@@ -290,6 +294,7 @@ public:
void setBezierCurve(const QVariantList &);
QVariantList bezierCurve() const;
};
+#endif
struct QQmlPropertyValueType
{
@@ -305,18 +310,14 @@ public:
template<typename T>
int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMinor, const char *qmlName)
{
- QByteArray name(T::staticMetaObject.className());
-
- QByteArray pointerName(name + '*');
-
QQmlPrivate::RegisterType type = {
0,
- qRegisterNormalizedMetaType<T *>(pointerName.constData()), 0, 0, nullptr,
+ QMetaType::fromType<T*>(), QMetaType(), 0, nullptr,
QString(),
- uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject,
+ uri, QTypeRevision::fromVersion(versionMajor, versionMinor), qmlName, &T::staticMetaObject,
nullptr, nullptr,
@@ -325,7 +326,7 @@ int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMino
nullptr, nullptr,
nullptr,
- 0
+ QTypeRevision::zero()
};
return QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index 110288faf7..d10fad191c 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -569,7 +569,7 @@ bool QQmlValueTypeWrapper::virtualPut(Managed *m, PropertyKey id, const Value &v
return false;
}
- QQmlContextData *context = v4->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = v4->callingQmlContext();
QQmlPropertyData cacheData;
cacheData.setWritable(true);
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 018769948d..38e9fad2b6 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -138,7 +138,7 @@ bool QQmlVMEGuard::isOK() const
return false;
for (int ii = 0; ii < m_contextCount; ++ii)
- if (m_contexts[ii].isNull() || !m_contexts[ii]->engine)
+ if (m_contexts[ii].isNull() || !m_contexts[ii]->engine())
return false;
return true;
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index 05a78a17fe..784df5d7ef 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -87,7 +87,7 @@ namespace QQmlVMETypes {
State() : flags(0), context(nullptr), instructionStream(nullptr) {}
quint32 flags;
- QQmlContextData *context;
+ QQmlRefPointer<QQmlContextData> context;
const char *instructionStream;
QBitField bindingSkipList;
};
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index aa9f4bc1bd..856dda1663 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -204,7 +204,12 @@ public:
QQmlVMEMetaObjectEndpoint();
void tryConnect();
- QFlagPointer<QQmlVMEMetaObject> metaObject;
+ enum Tag {
+ NoTag,
+ EndPointIsConnected
+ };
+
+ QTaggedPointer<QQmlVMEMetaObject, Tag> metaObject;
};
QQmlVMEMetaObjectEndpoint::QQmlVMEMetaObjectEndpoint()
@@ -223,15 +228,15 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
Q_ASSERT(metaObject->compiledObject);
int aliasId = this - metaObject->aliasEndpoints;
- if (metaObject.flag()) {
+ if (metaObject.tag() == EndPointIsConnected) {
// This is actually notify
int sigIdx = metaObject->methodOffset() + aliasId + metaObject->compiledObject->nProperties;
metaObject->activate(metaObject->object, sigIdx, nullptr);
} else {
const QV4::CompiledData::Alias *aliasData = &metaObject->compiledObject->aliasTable()[aliasId];
if (!aliasData->isObjectAlias()) {
- QQmlContextData *ctxt = metaObject->ctxt;
- QObject *target = ctxt->idValues[aliasData->targetObjectId].data();
+ QQmlRefPointer<QQmlContextData> ctxt = metaObject->ctxt;
+ QObject *target = ctxt->idValue(aliasData->targetObjectId);
if (!target)
return;
@@ -255,10 +260,10 @@ void QQmlVMEMetaObjectEndpoint::tryConnect()
return;
if (pd->notifyIndex() != -1)
- connect(target, pd->notifyIndex(), ctxt->engine);
+ connect(target, pd->notifyIndex(), ctxt->engine());
}
- metaObject.setFlag();
+ metaObject.setTag(EndPointIsConnected);
}
}
@@ -321,7 +326,7 @@ bool QQmlInterceptorMetaObject::intercept(QMetaObject::Call c, int id, void **a)
if (type != QMetaType::UnknownType) {
if (valueIndex != -1) {
QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance(
- data->context->engine, type);
+ data->context->engine(), type);
Q_ASSERT(valueType);
//
@@ -694,7 +699,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
const QV4::CompiledData::BuiltinType t = property.builtinType();
// the context can be null if accessing var properties from cpp after re-parenting an item.
- QQmlEnginePrivate *ep = (ctxt == nullptr || ctxt->engine == nullptr) ? nullptr : QQmlEnginePrivate::get(ctxt->engine);
+ QQmlEnginePrivate *ep = (ctxt.isNull() || ctxt->engine() == nullptr)
+ ? nullptr
+ : QQmlEnginePrivate::get(ctxt->engine());
const int fallbackMetaType = QQmlPropertyCacheCreatorBase::metaTypeForPropertyType(t);
@@ -891,15 +898,13 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
if ((aliasData->flags & QV4::CompiledData::Alias::AliasPointsToPointerObject) && c == QMetaObject::ReadProperty)
*reinterpret_cast<void **>(a[0]) = nullptr;
- if (!ctxt) return -1;
+ if (ctxt.isNull())
+ return -1;
while (aliasData->aliasToLocalAlias)
aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
- QQmlContext *context = ctxt->asQQmlContext();
- QQmlContextPrivate *ctxtPriv = QQmlContextPrivate::get(context);
-
- QObject *target = ctxtPriv->data->idValues[aliasData->targetObjectId].data();
+ QObject *target = ctxt->idValue(aliasData->targetObjectId);
if (!target)
return -1;
@@ -934,7 +939,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
const QQmlPropertyData *pd = targetDData->propertyCache->property(coreIndex);
// Value type property or deep alias
QQmlGadgetPtrWrapper *valueType = QQmlGadgetPtrWrapper::instance(
- ctxt->engine, pd->propType());
+ ctxt->engine(), pd->propType());
if (valueType) {
valueType->read(target, coreIndex);
int rv = QMetaObject::metacall(valueType, c, valueTypePropertyIndex, a);
@@ -973,7 +978,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
id -= plainSignals;
if (id < methodCount) {
- QQmlEngine *engine = ctxt->engine;
+ QQmlEngine *engine = ctxt->engine();
if (!engine)
return -1; // We can't run the method
@@ -1050,7 +1055,7 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void *
QV4::ReturnedValue QQmlVMEMetaObject::method(int index) const
{
- if (!ctxt || !ctxt->isValid() || !compiledObject) {
+ if (ctxt.isNull() || !ctxt->isValid() || !compiledObject) {
qWarning("QQmlVMEMetaObject: Internal error - attempted to evaluate a function in an invalid context");
return QV4::Encode::undefined();
}
@@ -1255,14 +1260,14 @@ bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex,
*coreIndex = -1;
*valueTypeIndex = -1;
- if (!ctxt)
+ if (ctxt.isNull())
return false;
const int aliasId = index - propOffset() - compiledObject->nProperties;
const QV4::CompiledData::Alias *aliasData = &compiledObject->aliasTable()[aliasId];
while (aliasData->aliasToLocalAlias)
aliasData = &compiledObject->aliasTable()[aliasData->localAliasIndex];
- *target = ctxt->idValues[aliasData->targetObjectId].data();
+ *target = ctxt->idValue(aliasData->targetObjectId);
if (!*target)
return false;
@@ -1290,7 +1295,7 @@ void QQmlVMEMetaObject::connectAlias(int aliasId)
}
endpoint->metaObject = this;
- endpoint->connect(&ctxt->idValues[aliasData->targetObjectId].bindings);
+ endpoint->connect(ctxt->idValueBindings(aliasData->targetObjectId));
endpoint->tryConnect();
}
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index e17701a968..10fa0d89a2 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -64,8 +64,8 @@
#include <private/qobject_p.h>
#include "qqmlguard_p.h"
-#include "qqmlcontext_p.h"
+#include <private/qqmlguardedcontextdata_p.h>
#include <private/qflagpointer_p.h>
#include <private/qv4object_p.h>
@@ -144,7 +144,10 @@ class QQmlVMEMetaObjectEndpoint;
class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject
{
public:
- QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj, const QQmlRefPointer<QQmlPropertyCache> &cache, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlCompilationUnit, int qmlObjectId);
+ QQmlVMEMetaObject(QV4::ExecutionEngine *engine, QObject *obj,
+ const QQmlRefPointer<QQmlPropertyCache> &cache,
+ const QQmlRefPointer<QV4::ExecutableCompilationUnit> &qmlCompilationUnit,
+ int qmlObjectId);
~QQmlVMEMetaObject() override;
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 86e6282e53..416aca8667 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1020,7 +1020,8 @@ public:
QString replyStatusText() const;
ReturnedValue open(Object *thisObject, const QString &, const QUrl &, LoadType);
- ReturnedValue send(Object *thisObject, QQmlContextData *context, const QByteArray &);
+ ReturnedValue send(Object *thisObject, const QQmlRefPointer<QQmlContextData> &context,
+ const QByteArray &);
ReturnedValue abort(Object *thisObject);
void addHeader(const QString &, const QString &);
@@ -1068,7 +1069,7 @@ private:
void readEncoding();
PersistentValue m_thisObject;
- QQmlContextDataRef m_qmlContext;
+ QQmlRefPointer<QQmlContextData> m_qmlContext;
bool m_wasConstructedWithQmlContext = true;
void dispatchCallbackNow(Object *thisObj);
@@ -1095,7 +1096,7 @@ QQmlXMLHttpRequest::QQmlXMLHttpRequest(QNetworkAccessManager *manager, QV4::Exec
, m_responseType()
, m_parsedDocument()
{
- m_wasConstructedWithQmlContext = v4->callingQmlContext() != nullptr;
+ m_wasConstructedWithQmlContext = !v4->callingQmlContext().isNull();
}
QQmlXMLHttpRequest::~QQmlXMLHttpRequest()
@@ -1203,25 +1204,15 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
if (m_method == QLatin1String("PUT"))
{
if (!xhrFileWrite()) {
- if (qEnvironmentVariableIsSet("QML_XHR_ALLOW_FILE_WRITE")) {
- qWarning("XMLHttpRequest: Tried to use PUT on a local file despite being disabled.");
- return;
- } else {
- qWarning("XMLHttpRequest: Using PUT on a local file is dangerous "
- "and will be disabled by default in a future Qt version."
- "Set QML_XHR_ALLOW_FILE_WRITE to 1 if you wish to continue using this feature.");
- }
+ qWarning("XMLHttpRequest: Using PUT on a local file is disabled by default.\n"
+ "Set QML_XHR_ALLOW_FILE_WRITE to 1 to enable this feature.");
+ return;
}
} else if (m_method == QLatin1String("GET")) {
if (!xhrFileRead()) {
- if (qEnvironmentVariableIsSet("QML_XHR_ALLOW_FILE_READ")) {
- qWarning("XMLHttpRequest: Tried to use GET on a local file despite being disabled.");
- return;
- } else {
- qWarning("XMLHttpRequest: Using GET on a local file is dangerous "
- "and will be disabled by default in a future Qt version."
- "Set QML_XHR_ALLOW_FILE_READ to 1 if you wish to continue using this feature.");
- }
+ qWarning("XMLHttpRequest: Using GET on a local file is disabled by default.\n"
+ "Set QML_XHR_ALLOW_FILE_READ to 1 to enable this feature.");
+ return;
}
} else {
qWarning("XMLHttpRequest: Unsupported method used on a local file");
@@ -1307,7 +1298,8 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
}
}
-ReturnedValue QQmlXMLHttpRequest::send(Object *thisObject, QQmlContextData *context, const QByteArray &data)
+ReturnedValue QQmlXMLHttpRequest::send(
+ Object *thisObject, const QQmlRefPointer<QQmlContextData> &context, const QByteArray &data)
{
m_errorFlag = false;
m_sendFlag = true;
@@ -1472,7 +1464,7 @@ void QQmlXMLHttpRequest::finished()
dispatchCallbackSafely();
m_thisObject.clear();
- m_qmlContext.setContextData(nullptr);
+ m_qmlContext = nullptr;
}
@@ -1625,12 +1617,13 @@ void QQmlXMLHttpRequest::dispatchCallbackNow(Object *thisObj, bool done, bool er
void QQmlXMLHttpRequest::dispatchCallbackSafely()
{
- if (m_wasConstructedWithQmlContext && !m_qmlContext.contextData())
+ if (m_wasConstructedWithQmlContext && m_qmlContext.isNull()) {
// if the calling context object is no longer valid, then it has been
// deleted explicitly (e.g., by a Loader deleting the itemContext when
// the source is changed). We do nothing in this case, as the evaluation
// cannot succeed.
return;
+ }
dispatchCallbackNow(m_thisObject.as<Object>());
}
@@ -1801,8 +1794,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(const FunctionObject *b, const
QUrl url = QUrl(argv[1].toQStringNoThrow());
if (url.isRelative()) {
- QQmlContextData *qmlContextData = scope.engine->callingQmlContext();
- if (qmlContextData)
+ if (QQmlRefPointer<QQmlContextData> qmlContextData = scope.engine->callingQmlContext())
url = qmlContextData->resolvedUrl(url);
else
url = scope.engine->resolvedUrl(url.url());
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 02628a9810..158f05c743 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -93,12 +93,6 @@ DEFINE_OBJECT_VTABLE(QtObject);
return scope.engine->throwTypeError(QString::fromUtf8(msg)); \
} while (false)
-struct StaticQtMetaObject : public QObject
-{
- static const QMetaObject *get()
- { return &staticQtMetaObject; }
-};
-
void Heap::QtObject::init(QQmlEngine *qmlEngine)
{
Heap::Object::init();
@@ -116,6 +110,7 @@ void Heap::QtObject::init(QQmlEngine *qmlEngine)
o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject);
+ o->defineDefaultProperty(QStringLiteral("color"), QV4::QtObject::method_color);
o->defineDefaultProperty(QStringLiteral("rgba"), QV4::QtObject::method_rgba);
o->defineDefaultProperty(QStringLiteral("hsla"), QV4::QtObject::method_hsla);
o->defineDefaultProperty(QStringLiteral("hsva"), QV4::QtObject::method_hsva);
@@ -177,7 +172,7 @@ ReturnedValue QtObject::findAndAdd(const QString *name, bool &foundProperty) con
ScopedString key(scope);
ScopedValue value(scope);
- const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
+ const QMetaObject *qtMetaObject = &Qt::staticMetaObject;
for (int enumCount = qtMetaObject->enumeratorCount(); d()->enumeratorIterator < enumCount;
++d()->enumeratorIterator) {
QMetaEnum enumerator = qtMetaObject->enumerator(d()->enumeratorIterator);
@@ -243,6 +238,33 @@ ReturnedValue QtObject::method_isQtObject(const FunctionObject *, const Value *,
}
/*!
+ \qmlmethod color Qt::color(string name)
+
+ Returns the color corresponding to the given \a name (i.e. red or #ff0000).
+ If there is no such color, \c null is returned.
+*/
+ReturnedValue QtObject::method_color(const FunctionObject *f, const Value *, const Value *argv,
+ int argc)
+{
+ QV4::Scope scope(f);
+ if (argc != 1)
+ THROW_GENERIC_ERROR("Qt.color(): Qt.color takes exactly one argument");
+
+ QVariant v = scope.engine->toVariant(argv[0], -1);
+ if (v.userType() == QMetaType::QString) {
+ bool ok = false;
+ v = QQmlStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok) {
+ return QV4::Encode::null();
+ }
+ } else {
+ THROW_GENERIC_ERROR("Qt.color(): Argument must be a string");
+ }
+
+ return scope.engine->fromVariant(v);
+}
+
+/*!
\qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
Returns a color with the specified \a red, \a green, \a blue, and \a alpha
@@ -737,23 +759,10 @@ QString formatDateTimeObjectUsingDateFormat(T formatThis, Qt::DateFormat format)
case Qt::RFC2822Date:
case Qt::ISODateWithMs:
return formatThis.toString(format);
- // ### Qt 6: Remove all locale dependent cases
- QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
- case Qt::SystemLocaleDate:
- // case Qt::LocalDate: covered by SystemLocaleDate
- return QLocale::system().toString(formatThis);
- case Qt::LocaleDate:
- case Qt::DefaultLocaleShortDate:
- return QLocale().toString(formatThis, QLocale::ShortFormat);
- case Qt::SystemLocaleShortDate:
- return QLocale::system().toString(formatThis, QLocale::ShortFormat);
- case Qt::SystemLocaleLongDate:
- return QLocale::system().toString(formatThis, QLocale::LongFormat);
- case Qt::DefaultLocaleLongDate:
- return QLocale().toString(formatThis, QLocale::LongFormat);
+ default: // ### Qt 6: remove once qtbase has removed the rest of the enum !
+ break;
}
- QT_WARNING_POP
- Q_UNREACHABLE();
+ // Q_UNREACHABLE(); // ### Qt 6: restore once the default is gone
return QString();
}
@@ -1007,8 +1016,7 @@ ReturnedValue QtObject::method_resolvedUrl(const FunctionObject *b, const Value
QQmlEnginePrivate *p = nullptr;
if (e) p = QQmlEnginePrivate::get(e);
if (p) {
- QQmlContextData *ctxt = scope.engine->callingQmlContext();
- if (ctxt)
+ if (QQmlRefPointer<QQmlContextData> ctxt = scope.engine->callingQmlContext())
return Encode(scope.engine->newString(ctxt->resolvedUrl(url).toString()));
else
return Encode(scope.engine->newString(url.toString()));
@@ -1175,7 +1183,7 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
QQmlEngine *engine = scope.engine->qmlEngine();
- QQmlContextData *context = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
if (!context) {
QQmlEngine *qmlEngine = scope.engine->qmlEngine();
if (qmlEngine)
@@ -1183,7 +1191,7 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
}
Q_ASSERT(context);
QQmlContext *effectiveContext = nullptr;
- if (context->isPragmaLibraryContext)
+ if (context->isPragmaLibraryContext())
effectiveContext = engine->rootContext();
else
effectiveContext = context->asQQmlContext();
@@ -1307,16 +1315,15 @@ ReturnedValue QtObject::method_createComponent(const FunctionObject *b, const Va
QQmlEngine *engine = scope.engine->qmlEngine();
- QQmlContextData *context = scope.engine->callingQmlContext();
+ QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
if (!context) {
QQmlEngine *qmlEngine = scope.engine->qmlEngine();
if (qmlEngine)
context = QQmlContextData::get(QQmlEnginePrivate::get(qmlEngine)->rootContext);
}
Q_ASSERT(context);
- QQmlContextData *effectiveContext = context;
- if (context->isPragmaLibraryContext)
- effectiveContext = nullptr;
+ QQmlRefPointer<QQmlContextData> effectiveContext
+ = context->isPragmaLibraryContext() ? nullptr : context;
QString arg = argv[0].toQStringNoThrow();
if (arg.isEmpty())
@@ -2063,7 +2070,7 @@ ReturnedValue GlobalExtensions::method_qsTr(const FunctionObject *b, const Value
}
if (context.isEmpty()) {
- if (QQmlContextData *ctxt = scope.engine->callingQmlContext()) {
+ if (QQmlRefPointer<QQmlContextData> ctxt = scope.engine->callingQmlContext()) {
QString path = ctxt->urlString();
int lastSlash = path.lastIndexOf(QLatin1Char('/'));
int lastDot = path.lastIndexOf(QLatin1Char('.'));
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index 5cbb52471d..0e6d815457 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -97,6 +97,8 @@ struct QtObject : Object
static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m, Value *target);
static ReturnedValue method_isQtObject(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+ static ReturnedValue method_color(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int argc);
static ReturnedValue method_rgba(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_hsla(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue method_hsva(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp
index 152e840318..cb16d2e57a 100644
--- a/src/qml/qmldirparser/qqmldirparser.cpp
+++ b/src/qml/qmldirparser/qqmldirparser.cpp
@@ -60,17 +60,17 @@ static int parseInt(const QStringRef &str, bool *ok)
return number;
}
-static bool parseVersion(const QString &str, int *major, int *minor)
+static QTypeRevision parseVersion(const QString &str)
{
const int dotIndex = str.indexOf(QLatin1Char('.'));
if (dotIndex != -1 && str.indexOf(QLatin1Char('.'), dotIndex + 1) == -1) {
bool ok = false;
- *major = parseInt(QStringRef(&str, 0, dotIndex), &ok);
- if (ok)
- *minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok);
- return ok;
+ const int major = parseInt(QStringRef(&str, 0, dotIndex), &ok);
+ if (!ok) return QTypeRevision();
+ const int minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok);
+ return ok ? QTypeRevision::fromVersion(major, minor) : QTypeRevision();
}
- return false;
+ return QTypeRevision();
}
void QQmlDirParser::clear()
@@ -203,7 +203,7 @@ bool QQmlDirParser::parse(const QString &source)
QStringLiteral("internal types require 2 arguments, but %1 were provided").arg(sectionCount - 1));
continue;
}
- Component entry(sections[1], sections[2], -1, -1);
+ Component entry(sections[1], sections[2], QTypeRevision());
entry.internal = true;
_components.insert(entry.typeName, entry);
} else if (sections[0] == QLatin1String("singleton")) {
@@ -214,16 +214,16 @@ bool QQmlDirParser::parse(const QString &source)
} else if (sectionCount == 3) {
// handle qmldir directory listing case where singleton is defined in the following pattern:
// singleton TestSingletonType TestSingletonType.qml
- Component entry(sections[1], sections[2], -1, -1);
+ Component entry(sections[1], sections[2], QTypeRevision());
entry.singleton = true;
_components.insert(entry.typeName, entry);
} else {
// handle qmldir module listing case where singleton is defined in the following pattern:
// singleton TestSingletonType 2.0 TestSingletonType20.qml
- int major, minor;
- if (parseVersion(sections[2], &major, &minor)) {
+ const QTypeRevision version = parseVersion(sections[2]);
+ if (version.isValid()) {
const QString &fileName = sections[3];
- Component entry(sections[1], fileName, major, minor);
+ Component entry(sections[1], fileName, version);
entry.singleton = true;
_components.insert(entry.typeName, entry);
} else {
@@ -236,11 +236,8 @@ bool QQmlDirParser::parse(const QString &source)
QStringLiteral("typeinfo requires 1 argument, but %1 were provided").arg(sectionCount - 1));
continue;
}
-#ifdef QT_CREATOR
TypeInfo typeInfo(sections[1]);
_typeInfos.append(typeInfo);
-#endif
-
} else if (sections[0] == QLatin1String("designersupported")) {
if (sectionCount != 1)
reportError(lineNumber, 0, QStringLiteral("designersupported does not expect any argument"));
@@ -253,9 +250,9 @@ bool QQmlDirParser::parse(const QString &source)
continue;
}
- int major, minor;
- if (parseVersion(sections[2], &major, &minor)) {
- Component entry(sections[1], QString(), major, minor);
+ const QTypeRevision version = parseVersion(sections[2]);
+ if (version.isValid()) {
+ Component entry(sections[1], QString(), version);
entry.internal = true;
_dependencies.insert(entry.typeName, entry);
} else {
@@ -270,19 +267,19 @@ bool QQmlDirParser::parse(const QString &source)
_imports << sections[1];
} else if (sectionCount == 2) {
// No version specified (should only be used for relative qmldir files)
- const Component entry(sections[0], sections[1], -1, -1);
+ const Component entry(sections[0], sections[1], QTypeRevision());
_components.insert(entry.typeName, entry);
} else if (sectionCount == 3) {
- int major, minor;
- if (parseVersion(sections[1], &major, &minor)) {
+ const QTypeRevision version = parseVersion(sections[1]);
+ if (version.isValid()) {
const QString &fileName = sections[2];
if (fileName.endsWith(QLatin1String(".js")) || fileName.endsWith(QLatin1String(".mjs"))) {
// A 'js' extension indicates a namespaced script import
- const Script entry(sections[0], fileName, major, minor);
+ const Script entry(sections[0], fileName, version);
_scripts.append(entry);
} else {
- const Component entry(sections[0], fileName, major, minor);
+ const Component entry(sections[0], fileName, version);
_components.insert(entry.typeName, entry);
}
} else {
@@ -387,15 +384,17 @@ QString QQmlDirParser::className() const
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Component &component)
{
- const QString output = QStringLiteral("{%1 %2.%3}").
- arg(component.typeName).arg(component.majorVersion).arg(component.minorVersion);
+ const QString output = QStringLiteral("{%1 %2.%3}")
+ .arg(component.typeName).arg(component.version.majorVersion())
+ .arg(component.version.minorVersion());
return debug << qPrintable(output);
}
QDebug &operator<< (QDebug &debug, const QQmlDirParser::Script &script)
{
- const QString output = QStringLiteral("{%1 %2.%3}").
- arg(script.nameSpace).arg(script.majorVersion).arg(script.minorVersion);
+ const QString output = QStringLiteral("{%1 %2.%3}")
+ .arg(script.nameSpace).arg(script.version.majorVersion())
+ .arg(script.version.minorVersion());
return debug << qPrintable(output);
}
diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h
index 3696a1aa12..ccdac8f484 100644
--- a/src/qml/qmldirparser/qqmldirparser_p.h
+++ b/src/qml/qmldirparser/qqmldirparser_p.h
@@ -54,6 +54,7 @@
#include <QtCore/QUrl>
#include <QtCore/QHash>
#include <QtCore/QDebug>
+#include <QtCore/QTypeRevision>
#include <private/qtqmlcompilerglobal_p.h>
#include <private/qqmljsengine_p.h>
#include <private/qqmljsdiagnosticmessage_p.h>
@@ -101,8 +102,8 @@ public:
{
Component() = default;
- Component(const QString &typeName, const QString &fileName, int majorVersion, int minorVersion)
- : typeName(typeName), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion),
+ Component(const QString &typeName, const QString &fileName, QTypeRevision version)
+ : typeName(typeName), fileName(fileName), version(version),
internal(false), singleton(false)
{
checkNonRelative("Component", typeName, fileName);
@@ -110,8 +111,7 @@ public:
QString typeName;
QString fileName;
- int majorVersion = 0;
- int minorVersion = 0;
+ QTypeRevision version = QTypeRevision::zero();
bool internal = false;
bool singleton = false;
};
@@ -120,16 +120,15 @@ public:
{
Script() = default;
- Script(const QString &nameSpace, const QString &fileName, int majorVersion, int minorVersion)
- : nameSpace(nameSpace), fileName(fileName), majorVersion(majorVersion), minorVersion(minorVersion)
+ Script(const QString &nameSpace, const QString &fileName, QTypeRevision version)
+ : nameSpace(nameSpace), fileName(fileName), version(version)
{
checkNonRelative("Script", nameSpace, fileName);
}
QString nameSpace;
QString fileName;
- int majorVersion = 0;
- int minorVersion = 0;
+ QTypeRevision version = QTypeRevision::zero();
};
QMultiHash<QString,Component> components() const;
diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp
index 6d6553259e..6d762401d0 100644
--- a/src/qml/types/qqmlbind.cpp
+++ b/src/qml/types/qqmlbind.cpp
@@ -73,8 +73,7 @@ public:
, delayed(false)
, pendingEval(false)
, restoreBinding(true)
- , restoreValue(false)
- , restoreModeExplicit(false)
+ , restoreValue(true)
, writingProperty(false)
{}
~QQmlBindPrivate() { }
@@ -93,7 +92,6 @@ public:
bool pendingEval:1;
bool restoreBinding:1;
bool restoreValue:1;
- bool restoreModeExplicit:1;
bool writingProperty: 1;
void validate(QObject *binding) const;
@@ -196,13 +194,8 @@ QQmlBind::~QQmlBind()
}
\endcode
- When the binding becomes inactive again, any direct bindings that were previously
- set on the property will be restored.
-
- \note By default, a previously set literal value is not restored when the Binding becomes
- inactive. Rather, the last value set by the now inactive Binding is retained. You can customize
- the restoration behavior for literal values as well as bindings using the \l restoreMode
- property. The default will change in Qt 6.0.
+ By default, any binding or value that was set perviously is restored when the binding becomes
+ inactive. You can customize the restoration behavior using the \l restoreMode property.
\sa restoreMode
*/
@@ -371,8 +364,7 @@ void QQmlBind::setDelayed(bool delayed)
\li Binding.RestoreBindingOrValue The original value is always restored.
\endlist
- \warning The default value is Binding.RestoreBinding. This will change in
- Qt 6.0 to Binding.RestoreBindingOrValue.
+ The default value is \c Binding.RestoreBindingOrValue.
If you rely on any specific behavior regarding the restoration of plain
values when bindings get disabled you should migrate to explicitly set the
@@ -395,7 +387,6 @@ QQmlBind::RestorationMode QQmlBind::restoreMode() const
void QQmlBind::setRestoreMode(RestorationMode newMode)
{
Q_D(QQmlBind);
- d->restoreModeExplicit = true;
if (newMode != restoreMode()) {
d->restoreValue = (newMode & RestoreValue);
d->restoreBinding = (newMode & RestoreBinding);
@@ -482,27 +473,11 @@ void QQmlBind::eval()
Q_ASSERT(vmemo);
vmemo->setVMEProperty(propPriv->core.coreIndex(), *d->v4Value.valueRef());
d->clearPrev();
- } else if (!d->restoreModeExplicit) {
- qmlWarning(this)
- << "Not restoring previous value because restoreMode has not been set.\n"
- << "This behavior is deprecated.\n"
- << "You have to import QtQml 2.15 after any QtQuick imports and set\n"
- << "the restoreMode of the binding to fix this warning.\n"
- << "In Qt < 6.0 the default is Binding.RestoreBinding.\n"
- << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue.";
}
} else if (d->prevIsVariant) {
if (d->restoreValue) {
d->prop.write(d->prevValue);
d->clearPrev();
- } else if (!d->restoreModeExplicit) {
- qmlWarning(this)
- << "Not restoring previous value because restoreMode has not been set.\n"
- << "This behavior is deprecated.\n"
- << "You have to import QtQml 2.15 after any QtQuick imports and set\n"
- << "the restoreMode of the binding to fix this warning.\n"
- << "In Qt < 6.0 the default is Binding.RestoreBinding.\n"
- << "In Qt >= 6.0 the default is Binding.RestoreBindingOrValue.\n";
}
}
return;
diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h
index c709224c23..052af0d167 100644
--- a/src/qml/types/qqmlbind_p.h
+++ b/src/qml/types/qqmlbind_p.h
@@ -77,11 +77,12 @@ private:
Q_PROPERTY(QString property READ property WRITE setProperty)
Q_PROPERTY(QJSValue value READ value WRITE setValue)
Q_PROPERTY(bool when READ when WRITE setWhen)
- Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION 8)
+ Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION(2, 8))
Q_PROPERTY(RestorationMode restoreMode READ restoreMode WRITE setRestoreMode
- NOTIFY restoreModeChanged REVISION 14)
+ NOTIFY restoreModeChanged REVISION(2, 14))
Q_ENUM(RestorationMode)
QML_NAMED_ELEMENT(Binding)
+ QML_ADDED_IN_VERSION(2, 0)
public:
QQmlBind(QObject *parent=nullptr);
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index 4c44bba43e..29946b1da4 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -292,9 +292,9 @@ void QQmlConnections::connectSignalsToMethods()
if (!ddata)
return;
- QV4::ExecutionEngine *engine = ddata->context->engine->handle();
+ QV4::ExecutionEngine *engine = ddata->context->engine()->handle();
- QQmlContextData *ctxtdata = ddata->outerContext;
+ QQmlRefPointer<QQmlContextData> ctxtdata = ddata->outerContext;
for (int i = ddata->propertyCache->methodOffset(),
end = ddata->propertyCache->methodOffset() + ddata->propertyCache->methodCount();
i < end;
@@ -344,7 +344,7 @@ void QQmlConnections::connectSignalsToBindings()
Q_D(QQmlConnections);
QObject *target = this->target();
QQmlData *ddata = QQmlData::get(this);
- QQmlContextData *ctxtdata = ddata ? ddata->outerContext : nullptr;
+ QQmlRefPointer<QQmlContextData> ctxtdata = ddata ? ddata->outerContext : nullptr;
for (const QV4::CompiledData::Binding *binding : qAsConst(d->bindings)) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script);
diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h
index 7bf688cf75..8ed874d9fc 100644
--- a/src/qml/types/qqmlconnections_p.h
+++ b/src/qml/types/qqmlconnections_p.h
@@ -69,9 +69,10 @@ class Q_AUTOTEST_EXPORT QQmlConnections : public QObject, public QQmlParserStatu
Q_INTERFACES(QQmlParserStatus)
Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged)
- Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged REVISION 3)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged REVISION(2, 3))
Q_PROPERTY(bool ignoreUnknownSignals READ ignoreUnknownSignals WRITE setIgnoreUnknownSignals)
QML_NAMED_ELEMENT(Connections)
+ QML_ADDED_IN_VERSION(2, 0)
public:
QQmlConnections(QObject *parent=nullptr);
@@ -88,7 +89,7 @@ public:
Q_SIGNALS:
void targetChanged();
- Q_REVISION(3) void enabledChanged();
+ Q_REVISION(2, 3) void enabledChanged();
private:
void connectSignals();
diff --git a/src/qml/types/qqmltimer_p.h b/src/qml/types/qqmltimer_p.h
index 0cd93e4659..a8236977c4 100644
--- a/src/qml/types/qqmltimer_p.h
+++ b/src/qml/types/qqmltimer_p.h
@@ -73,6 +73,7 @@ class Q_QML_PRIVATE_EXPORT QQmlTimer : public QObject, public QQmlParserStatus
Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart NOTIFY triggeredOnStartChanged)
Q_PROPERTY(QObject *parent READ parent CONSTANT)
QML_NAMED_ELEMENT(Timer)
+ QML_ADDED_IN_VERSION(2, 0)
public:
QQmlTimer(QObject *parent=nullptr);