summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--CMakeLists.txt2
-rw-r--r--cmake/QtDeclarativeSetup.cmake8
-rw-r--r--dependencies.yaml7
-rw-r--r--examples/quick/canvas/CMakeLists.txt1
-rw-r--r--examples/quick/canvas/LabeledSlider.qml85
-rw-r--r--examples/quick/canvas/bezierCurve/bezierCurve.qml25
-rw-r--r--examples/quick/canvas/canvas.qml4
-rw-r--r--examples/quick/canvas/canvas.qrc1
-rw-r--r--examples/quick/canvas/clip/clip.qml16
-rw-r--r--examples/quick/canvas/quadraticCurveTo/quadraticCurveTo.qml17
-rw-r--r--examples/quick/canvas/roundedrect/roundedrect.qml16
-rw-r--r--examples/quick/canvas/smile/smile.qml17
-rw-r--r--examples/quick/canvas/squircle/squircle.qml16
-rw-r--r--examples/quick/canvas/tiger/tiger.qml15
-rw-r--r--examples/quick/customitems/painteditem/textballoon.cpp2
-rw-r--r--examples/quick/customitems/painteditem/textballoon.h2
-rw-r--r--src/CMakeLists.txt5
-rw-r--r--src/imports/CMakeLists.txt5
-rw-r--r--src/imports/builtins/CMakeLists.txt4
-rw-r--r--src/imports/builtins/builtins.qmltypes8
-rw-r--r--src/imports/builtins/jsroot.qmltypes1983
-rw-r--r--src/imports/folderlistmodel/CMakeLists.txt4
-rw-r--r--src/imports/labsanimation/CMakeLists.txt4
-rw-r--r--src/imports/labsmodels/CMakeLists.txt4
-rw-r--r--src/imports/layouts/CMakeLists.txt4
-rw-r--r--src/imports/localstorage/CMakeLists.txt4
-rw-r--r--src/imports/models/CMakeLists.txt4
-rw-r--r--src/imports/particles/CMakeLists.txt5
-rw-r--r--src/imports/particles/plugin.cpp14
-rw-r--r--src/imports/qtqml/CMakeLists.txt4
-rw-r--r--src/imports/qtquick2/CMakeLists.txt4
-rw-r--r--src/imports/settings/CMakeLists.txt4
-rw-r--r--src/imports/shapes/CMakeLists.txt4
-rw-r--r--src/imports/sharedimage/CMakeLists.txt4
-rw-r--r--src/imports/testlib/CMakeLists.txt5
-rw-r--r--src/imports/tooling/CMakeLists.txt2
-rw-r--r--src/imports/tooling/Method.qml1
-rw-r--r--src/imports/tooling/Property.qml1
-rw-r--r--src/imports/wavefrontmesh/CMakeLists.txt4
-rw-r--r--src/imports/window/CMakeLists.txt2
-rw-r--r--src/imports/workerscript/CMakeLists.txt4
-rw-r--r--src/imports/xmllistmodel/CMakeLists.txt15
-rw-r--r--src/imports/xmllistmodel/plugin.cpp59
-rw-r--r--src/labs/CMakeLists.txt5
-rw-r--r--src/labs/animation/CMakeLists.txt2
-rw-r--r--src/labs/animation/qquickboundaryrule.cpp1
-rw-r--r--src/labs/folderlistmodel/CMakeLists.txt2
-rw-r--r--src/labs/models/CMakeLists.txt2
-rw-r--r--src/labs/models/qqmldelegatecomponent.cpp2
-rw-r--r--src/labs/settings/CMakeLists.txt2
-rw-r--r--src/labs/settings/qqmlsettings.cpp2
-rw-r--r--src/labs/sharedimage/CMakeLists.txt2
-rw-r--r--src/labs/wavefrontmesh/CMakeLists.txt2
-rw-r--r--src/particles/CMakeLists.txt3
-rw-r--r--src/particles/qquickmaskextruder.cpp2
-rw-r--r--src/particles/qquickturbulence_p.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp4
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp18
-rw-r--r--src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h1
-rw-r--r--src/qml/.prev_configure.cmake36
-rw-r--r--src/qml/CMakeLists.txt4
-rw-r--r--src/qml/Qt6QmlBuildInternals.cmake214
-rw-r--r--src/qml/Qt6QmlMacros.cmake212
-rw-r--r--src/qml/common/qqmljsdiagnosticmessage_p.h1
-rw-r--r--src/qml/common/qqmljssourcelocation_p.h47
-rw-r--r--src/qml/common/qv4compileddata_p.h2
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp8
-rw-r--r--src/qml/compiler/qv4bytecodegenerator_p.h14
-rw-r--r--src/qml/compiler/qv4codegen.cpp244
-rw-r--r--src/qml/compiler/qv4codegen_p.h22
-rw-r--r--src/qml/compiler/qv4compiler_p.h2
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp8
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h4
-rw-r--r--src/qml/configure.cmake33
-rw-r--r--src/qml/configure.json7
-rw-r--r--src/qml/doc/src/external-resources.qdoc4
-rw-r--r--src/qml/doc/src/javascript/hostenvironment.qdoc2
-rw-r--r--src/qml/doc/src/qmlfunctions.qdoc15
-rw-r--r--src/qml/jit/qv4assemblercommon.cpp6
-rw-r--r--src/qml/jit/qv4assemblercommon_p.h9
-rw-r--r--src/qml/jit/qv4baselineassembler.cpp33
-rw-r--r--src/qml/jit/qv4baselineassembler_p.h5
-rw-r--r--src/qml/jit/qv4baselinejit.cpp19
-rw-r--r--src/qml/jit/qv4baselinejit_p.h6
-rw-r--r--src/qml/jsapi/qjsengine.cpp39
-rw-r--r--src/qml/jsapi/qjsengine.h9
-rw-r--r--src/qml/jsapi/qjsmanagedvalue.cpp44
-rw-r--r--src/qml/jsapi/qjsprimitivevalue.h246
-rw-r--r--src/qml/jsapi/qjsvalue.cpp20
-rw-r--r--src/qml/jsapi/qjsvalue.h1
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp10
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h2
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp6
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp2
-rw-r--r--src/qml/jsruntime/qv4context.cpp10
-rw-r--r--src/qml/jsruntime/qv4context_p.h2
-rw-r--r--src/qml/jsruntime/qv4engine.cpp220
-rw-r--r--src/qml/jsruntime/qv4engine_p.h31
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h11
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit.cpp1
-rw-r--r--src/qml/jsruntime/qv4executablecompilationunit_p.h1
-rw-r--r--src/qml/jsruntime/qv4function.cpp47
-rw-r--r--src/qml/jsruntime/qv4function_p.h2
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp107
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4generatorobject.cpp41
-rw-r--r--src/qml/jsruntime/qv4generatorobject_p.h5
-rw-r--r--src/qml/jsruntime/qv4global_p.h2
-rw-r--r--src/qml/jsruntime/qv4identifierhash.cpp1
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp32
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h3
-rw-r--r--src/qml/jsruntime/qv4include.cpp6
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h1
-rw-r--r--src/qml/jsruntime/qv4jscall.cpp8
-rw-r--r--src/qml/jsruntime/qv4jscall_p.h174
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4module.cpp10
-rw-r--r--src/qml/jsruntime/qv4object.cpp16
-rw-r--r--src/qml/jsruntime/qv4promiseobject.cpp52
-rw-r--r--src/qml/jsruntime/qv4propertykey_p.h6
-rw-r--r--src/qml/jsruntime/qv4proxy.cpp79
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp20
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp45
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h2
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp10
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp31
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h4
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp19
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h4
-rw-r--r--src/qml/jsruntime/qv4stackframe_p.h218
-rw-r--r--src/qml/jsruntime/qv4urlobject.cpp166
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp169
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h6
-rw-r--r--src/qml/jsruntime/qv4vtable_p.h65
-rw-r--r--src/qml/memory/qv4heap_p.h3
-rw-r--r--src/qml/memory/qv4mmdefs_p.h1
-rw-r--r--src/qml/parser/qqmljs.g86
-rw-r--r--src/qml/parser/qqmljsast.cpp38
-rw-r--r--src/qml/parser/qqmljsast_p.h11
-rw-r--r--src/qml/parser/qqmljslexer.cpp12
-rw-r--r--src/qml/parser/qqmljslexer_p.h1
-rw-r--r--src/qml/qml/ftw/qqmlnullablevalue_p.h2
-rw-r--r--src/qml/qml/ftw/qrecyclepool_p.h2
-rw-r--r--src/qml/qml/qqml.cpp230
-rw-r--r--src/qml/qml/qqml.h98
-rw-r--r--src/qml/qml/qqmlanybinding_p.h2
-rw-r--r--src/qml/qml/qqmlbinding.cpp141
-rw-r--r--src/qml/qml/qqmlbinding_p.h5
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp40
-rw-r--r--src/qml/qml/qqmlcomponent.cpp6
-rw-r--r--src/qml/qml/qqmlcontext.cpp111
-rw-r--r--src/qml/qml/qqmlcontext.h1
-rw-r--r--src/qml/qml/qqmlcontextdata.cpp61
-rw-r--r--src/qml/qml/qqmlcontextdata_p.h46
-rw-r--r--src/qml/qml/qqmldata_p.h1
-rw-r--r--src/qml/qml/qqmldelayedcallqueue.cpp6
-rw-r--r--src/qml/qml/qqmlexpression.cpp2
-rw-r--r--src/qml/qml/qqmlimport.cpp11
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp209
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h9
-rw-r--r--src/qml/qml/qqmllist.cpp64
-rw-r--r--src/qml/qml/qqmllist.h1
-rw-r--r--src/qml/qml/qqmllist_p.h28
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp17
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h8
-rw-r--r--src/qml/qml/qqmllocale.cpp50
-rw-r--r--src/qml/qml/qqmllocale_p.h11
-rw-r--r--src/qml/qml/qqmlmetaobject.cpp2
-rw-r--r--src/qml/qml/qqmlmetaobject_p.h4
-rw-r--r--src/qml/qml/qqmlmetatype.cpp127
-rw-r--r--src/qml/qml/qqmlmetatype_p.h85
-rw-r--r--src/qml/qml/qqmlmetatypedata_p.h4
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp26
-rw-r--r--src/qml/qml/qqmlprivate.h29
-rw-r--r--src/qml/qml/qqmlproperty.cpp14
-rw-r--r--src/qml/qml/qqmlproperty.h7
-rw-r--r--src/qml/qml/qqmlpropertybinding.cpp161
-rw-r--r--src/qml/qml/qqmlpropertybinding_p.h23
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp42
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h15
-rw-r--r--src/qml/qml/qqmlpropertycachecreator_p.h111
-rw-r--r--src/qml/qml/qqmlpropertycachemethodarguments_p.h10
-rw-r--r--src/qml/qml/qqmlpropertydata_p.h13
-rw-r--r--src/qml/qml/qqmlpropertyvalidator.cpp8
-rw-r--r--src/qml/qml/qqmlregistration.h140
-rw-r--r--src/qml/qml/qqmltypecompiler.cpp61
-rw-r--r--src/qml/qml/qqmltypecompiler_p.h2
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp15
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h1
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp10
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h16
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp26
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h3
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp41
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp2
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp2
-rw-r--r--src/qml/qml_compile_hash_p.h.in15
-rw-r--r--src/qml/qtqmlglobal_p.h1
-rw-r--r--src/qml/types/qqmlbind.cpp4
-rw-r--r--src/qml/types/qqmlmodelindexvaluetype_p.h3
-rw-r--r--src/qmlcompiler/CMakeLists.txt3
-rw-r--r--src/qmlcompiler/qcoloroutput.cpp (renamed from tools/qmllint/qcoloroutput.cpp)57
-rw-r--r--src/qmlcompiler/qcoloroutput_p.h (renamed from tools/qmllint/qcoloroutput.h)31
-rw-r--r--src/qmlcompiler/qdeferredpointer_p.h1
-rw-r--r--src/qmlcompiler/qqmljsannotation.cpp46
-rw-r--r--src/qmlcompiler/qqmljsannotation_p.h102
-rw-r--r--src/qmlcompiler/qqmljscompiler.cpp40
-rw-r--r--src/qmlcompiler/qqmljscompiler_p.h4
-rw-r--r--src/qmlcompiler/qqmljsimporter.cpp80
-rw-r--r--src/qmlcompiler/qqmljsimporter_p.h9
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp431
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor_p.h35
-rw-r--r--src/qmlcompiler/qqmljslogger.cpp170
-rw-r--r--src/qmlcompiler/qqmljslogger_p.h181
-rw-r--r--src/qmlcompiler/qqmljsmetatypes_p.h31
-rw-r--r--src/qmlcompiler/qqmljsscope.cpp19
-rw-r--r--src/qmlcompiler/qqmljsscope_p.h10
-rw-r--r--src/qmlcompiler/qqmljsstreamwriter.cpp9
-rw-r--r--src/qmlcompiler/qqmljstypedescriptionreader.cpp19
-rw-r--r--src/qmlcompiler/qqmljstypereader.cpp2
-rw-r--r--src/qmldevtools/CMakeLists.txt1
-rw-r--r--src/qmldom/CMakeLists.txt3
-rw-r--r--src/qmldom/qqmldomastdumper.cpp1103
-rw-r--r--src/qmldom/qqmldomastdumper_p.h78
-rw-r--r--src/qmldom/qqmldomattachedinfo.cpp286
-rw-r--r--src/qmldom/qqmldomattachedinfo_p.h289
-rw-r--r--src/qmldom/qqmldomconstants_p.h33
-rw-r--r--src/qmldom/qqmldomerrormessage.cpp40
-rw-r--r--src/qmldom/qqmldomerrormessage_p.h8
-rw-r--r--src/qmldom/qqmldomexternalitems_p.h2
-rw-r--r--src/qmldom/qqmldomfunctionref_p.h80
-rw-r--r--src/qmldom/qqmldomitem.cpp147
-rw-r--r--src/qmldom/qqmldomitem_p.h113
-rw-r--r--src/qmldom/qqmldompath.cpp239
-rw-r--r--src/qmldom/qqmldompath_p.h372
-rw-r--r--src/qmldom/qqmldomstringdumper.cpp14
-rw-r--r--src/qmldom/qqmldomstringdumper_p.h6
-rw-r--r--src/qmldom/qqmldomtop.cpp50
-rw-r--r--src/qmldom/qqmldomtop_p.h18
-rw-r--r--src/qmllocalstorage/CMakeLists.txt2
-rw-r--r--src/qmllocalstorage/qqmllocalstorage.cpp20
-rw-r--r--src/qmlmodels/CMakeLists.txt2
-rw-r--r--src/qmlmodels/qqmladaptormodel.cpp6
-rw-r--r--src/qmlmodels/qqmldelegatemodel.cpp6
-rw-r--r--src/qmlmodels/qqmlinstantiator.cpp2
-rw-r--r--src/qmlmodels/qqmllistaccessor.cpp56
-rw-r--r--src/qmlmodels/qqmllistmodel.cpp6
-rw-r--r--src/qmltest/CMakeLists.txt2
-rw-r--r--src/qmltest/quicktestresult.cpp4
-rw-r--r--src/qmltyperegistrar/qmltyperegistrar.cpp27
-rw-r--r--src/qmltyperegistrar/qmltypescreator.cpp57
-rw-r--r--src/qmltyperegistrar/qmltypescreator.h5
-rw-r--r--src/qmlworkerscript/CMakeLists.txt2
-rw-r--r--src/qmlworkerscript/qquickworkerscript.cpp6
-rw-r--r--src/qmlworkerscript/qv4serialize.cpp2
-rw-r--r--src/qmlxmllistmodel/CMakeLists.txt29
-rw-r--r--src/qmlxmllistmodel/doc/qtqmlxmllistmodel.qdocconf36
-rw-r--r--src/qmlxmllistmodel/qqmlxmllistmodel.cpp993
-rw-r--r--src/qmlxmllistmodel/qqmlxmllistmodel_p.h250
-rw-r--r--src/qmlxmllistmodel/qtqmlxmllistmodelglobal_p.h (renamed from src/particles/qquickparticlesmodule_p.h)30
-rw-r--r--src/quick/CMakeLists.txt124
-rw-r--r--src/quick/configure.cmake3
-rw-r--r--src/quick/designer/qquickdesignersupportitems.cpp2
-rw-r--r--src/quick/doc/src/concepts/modelviewsdata/modelview.qdoc14
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp17
-rw-r--r--src/quick/handlers/qquickdraghandler_p.h1
-rw-r--r--src/quick/handlers/qquickhandlerpoint.cpp4
-rw-r--r--src/quick/handlers/qquickhoverhandler.cpp20
-rw-r--r--src/quick/handlers/qquickhoverhandler_p.h2
-rw-r--r--src/quick/handlers/qquickmultipointhandler.cpp2
-rw-r--r--src/quick/handlers/qquickpinchhandler.cpp6
-rw-r--r--src/quick/handlers/qquickpointerdevicehandler.cpp2
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp9
-rw-r--r--src/quick/handlers/qquickpointhandler.cpp4
-rw-r--r--src/quick/handlers/qquicktaphandler.cpp7
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp6
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp8
-rw-r--r--src/quick/items/qquickdrag_p.h5
-rw-r--r--src/quick/items/qquickflickable.cpp16
-rw-r--r--src/quick/items/qquickflickable_p_p.h1
-rw-r--r--src/quick/items/qquickgraphicsinfo.cpp6
-rw-r--r--src/quick/items/qquickitem.cpp54
-rw-r--r--src/quick/items/qquickitemanimation.cpp38
-rw-r--r--src/quick/items/qquickitemanimation_p_p.h8
-rw-r--r--src/quick/items/qquickitemgrabresult.cpp2
-rw-r--r--src/quick/items/qquicklistview.cpp102
-rw-r--r--src/quick/items/qquicklistview_p.h2
-rw-r--r--src/quick/items/qquickpathview.cpp2
-rw-r--r--src/quick/items/qquickrectangle.cpp2
-rw-r--r--src/quick/items/qquickrepeater.cpp2
-rw-r--r--src/quick/items/qquickshadereffect.cpp3
-rw-r--r--src/quick/items/qquickshadereffectmesh.cpp36
-rw-r--r--src/quick/items/qquicktableview.cpp236
-rw-r--r--src/quick/items/qquicktableview_p.h8
-rw-r--r--src/quick/items/qquicktableview_p_p.h30
-rw-r--r--src/quick/items/qquicktext.cpp8
-rw-r--r--src/quick/items/qquicktextcontrol.cpp89
-rw-r--r--src/quick/items/qquicktextedit.cpp3
-rw-r--r--src/quick/items/qquicktextinput.cpp5
-rw-r--r--src/quick/items/qquickwindow.cpp104
-rw-r--r--src/quick/items/qquickwindow_p.h7
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp6
-rw-r--r--src/quick/scenegraph/coreapi/qsgtexture.cpp5
-rw-r--r--src/quick/scenegraph/qsgdefaultcontext.cpp2
-rw-r--r--src/quick/scenegraph/qsgrhishadereffectnode.cpp4
-rw-r--r--src/quick/scenegraph/qsgrhisupport.cpp31
-rw-r--r--src/quick/scenegraph/qsgrhisupport_p.h14
-rw-r--r--src/quick/scenegraph/scenegraph.qrc61
-rw-r--r--src/quick/scenegraph/shaders_ng/24bittextmask.frag.qsbbin1574 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/32bitcolortext.frag.qsbbin1467 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/8bittextmask.frag.qsbbin1462 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/8bittextmask_a.frag.qsbbin772 -> 0 bytes
-rwxr-xr-xsrc/quick/scenegraph/shaders_ng/compile.bat98
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsbbin1995 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsbbin2027 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag.qsbbin2008 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag.qsbbin2281 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag.qsbbin2275 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsbbin1986 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsbbin2128 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag.qsbbin1991 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag.qsbbin2157 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag.qsbbin2177 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldtext.frag.qsbbin1637 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldtext.vert.qsbbin1903 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldtext_a.frag.qsbbin1631 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag.qsbbin1805 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/distancefieldtext_fwidth.frag.qsbbin1812 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/flatcolor.frag.qsbbin970 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/flatcolor.vert.qsbbin1499 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsbbin2928 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.vert.qsbbin3276 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag.qsbbin2937 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag.qsbbin2119 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.vert.qsbbin2755 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag.qsbbin2103 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/opaquetexture.frag.qsbbin1013 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/opaquetexture.vert.qsbbin1651 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/outlinedtext.frag.qsbbin2193 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/outlinedtext.vert.qsbbin2685 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/outlinedtext_a.frag.qsbbin1310 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/shadereffect.frag.qsbbin1358 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/shadereffect.vert.qsbbin1719 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/smoothcolor.frag.qsbbin755 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/smoothcolor.vert.qsbbin3493 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/smoothtexture.frag.qsbbin1136 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/smoothtexture.vert.qsbbin4223 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/sprite.frag.qsbbin1624 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/sprite.vert.qsbbin2252 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/stencilclip.frag.qsbbin803 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/stencilclip.vert.qsbbin1429 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/styledtext.frag.qsbbin1807 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/styledtext.vert.qsbbin2368 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/styledtext_a.frag.qsbbin1042 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/textmask.frag.qsbbin1564 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/textmask.vert.qsbbin2141 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/texture.frag.qsbbin1344 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/texture.vert.qsbbin1710 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/vertexcolor.frag.qsbbin762 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/vertexcolor.vert.qsbbin1709 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/visualization.frag.qsbbin1608 -> 0 bytes
-rw-r--r--src/quick/scenegraph/shaders_ng/visualization.vert.qsbbin1776 -> 0 bytes
-rw-r--r--src/quick/util/qquickanimation.cpp24
-rw-r--r--src/quick/util/qquickanimation_p_p.h10
-rw-r--r--src/quick/util/qquickanimationcontroller.cpp2
-rw-r--r--src/quick/util/qquickanimator.cpp12
-rw-r--r--src/quick/util/qquickanimator_p_p.h8
-rw-r--r--src/quick/util/qquickbehavior.cpp2
-rw-r--r--src/quick/util/qquickdeliveryagent.cpp29
-rw-r--r--src/quick/util/qquickdeliveryagent_p_p.h3
-rw-r--r--src/quick/util/qquickpath.cpp21
-rw-r--r--src/quick/util/qquickstate.cpp2
-rw-r--r--src/quick/util/qquicktransition.cpp2
-rw-r--r--src/quicklayouts/CMakeLists.txt2
-rw-r--r--src/quicklayouts/qquicklayout_p.h2
-rw-r--r--src/quickshapes/CMakeLists.txt2
-rw-r--r--src/quickshapes/qquickshape.cpp38
-rw-r--r--sync.profile3
-rw-r--r--tests/auto/CMakeLists.txt12
-rw-r--r--tests/auto/bic/data/QtQml.6.0.0.linux-gcc-amd64.txt6507
-rw-r--r--tests/auto/bic/data/QtQuick.6.0.0.linux-gcc-amd64.txt14463
-rw-r--r--tests/auto/bic/data/QtQuickTest.6.0.0.linux-gcc-amd64.txt19098
-rw-r--r--tests/auto/bic/data/QtQuickWidgets.6.0.0.linux-gcc-amd64.txt24897
-rw-r--r--tests/auto/qml/CMakeLists.txt3
-rw-r--r--tests/auto/qml/animation/qabstractanimationjob/tst_qabstractanimationjob.cpp10
-rw-r--r--tests/auto/qml/animation/qanimationgroupjob/tst_qanimationgroupjob.cpp8
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp2
m---------tests/auto/qml/ecmascripttests/test2620
-rw-r--r--tests/auto/qml/qjsengine/tst_qjsengine.cpp78
-rw-r--r--tests/auto/qml/qjsprimitivevalue/tst_qjsprimitivevalue.cpp212
-rw-r--r--tests/auto/qml/qmlcompiler_manual/tst_qmlcompiler_manual.cpp5
-rw-r--r--tests/auto/qml/qmlformat/tst_qmlformat.cpp1
-rw-r--r--tests/auto/qml/qmlimportscanner/data/CompositeSingleton.json5
-rw-r--r--tests/auto/qml/qmlimportscanner/data/CompositeWithEnum.json4
-rw-r--r--tests/auto/qml/qmlimportscanner/data/CompositeWithinSingleton.json5
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Drawer.qml.json3
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Imports.json5
-rw-r--r--tests/auto/qml/qmlimportscanner/data/ListProperty.qml.json4
-rw-r--r--tests/auto/qml/qmlimportscanner/data/QTBUG-45916.js.json4
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Simple.qml.json4
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Singleton.json5
-rw-r--r--tests/auto/qml/qmlimportscanner/data/Things.json5
-rw-r--r--tests/auto/qml/qmlimportscanner/data/javascriptMethods.qml.json3
-rw-r--r--tests/auto/qml/qmlimportscanner/data/localImport.qml.json4
-rw-r--r--tests/auto/qml/qmlimportscanner/data/parentEnum.qml.json4
-rw-r--r--tests/auto/qml/qmlimportscanner/data/qmldirImportAndDepend.qml.json4
-rw-r--r--tests/auto/qml/qmlimportscanner/data/qtQmlOnly.qml.json3
-rw-r--r--tests/auto/qml/qmlimportscanner/data/rootPath.json5
-rw-r--r--tests/auto/qml/qmllint/CMakeLists.txt7
-rw-r--r--tests/auto/qml/qmllint/data/AttachedProperties/attachedProperty.qmltypes21
-rw-r--r--tests/auto/qml/qmllint/data/AttachedProperties/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/DeprProp.qml8
-rw-r--r--tests/auto/qml/qmllint/data/DeprecatedFunctions.qml9
-rw-r--r--tests/auto/qml/qmllint/data/DuplicateImport/plugins.qmltypes11
-rw-r--r--tests/auto/qml/qmllint/data/DuplicateImport/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/FormUser.qml2
-rw-r--r--tests/auto/qml/qmllint/data/InfoItemTextEdit.qml12
-rw-r--r--tests/auto/qml/qmllint/data/ListProperty.qml1
-rw-r--r--tests/auto/qml/qmllint/data/QmlBench/Globals.qml10
-rw-r--r--tests/auto/qml/qmllint/data/QmlBench/Locals.qml9
-rw-r--r--tests/auto/qml/qmllint/data/QmlBench/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/Things/qmldir2
-rw-r--r--tests/auto/qml/qmllint/data/TypeDeprecated.qml4
-rw-r--r--tests/auto/qml/qmllint/data/TypeDeprecatedReason.qml4
-rw-r--r--tests/auto/qml/qmllint/data/TypeWithUnknownPropertyType.qml5
-rw-r--r--tests/auto/qml/qmllint/data/aliasCycle.qml7
-rw-r--r--tests/auto/qml/qmllint/data/attachedPropertyAssignments.qml5
-rw-r--r--tests/auto/qml/qmllint/data/badAliasExpression.qml6
-rw-r--r--tests/auto/qml/qmllint/data/badAttachedProperty.qml8
-rw-r--r--tests/auto/qml/qmllint/data/badAttachedPropertyNested.qml15
-rw-r--r--tests/auto/qml/qmllint/data/badAttachedPropertyTypeQtObject.qml5
-rw-r--r--tests/auto/qml/qmllint/data/badAttachedPropertyTypeString.qml5
-rw-r--r--tests/auto/qml/qmllint/data/compositesingleton.qml8
-rw-r--r--tests/auto/qml/qmllint/data/defaultProperty.qml6
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyComponent.2.qml5
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyComponent.qml5
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyList.qml8
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyWithDoubleAssignment.qml7
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyWithWrongType.qml6
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyWithWrongType2.qml6
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyWithoutKeyword.qml6
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedFunction.qml10
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedFunctionInherited.qml7
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedFunctionOverride.qml8
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedProperty.qml8
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedPropertyBinding.qml3
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedPropertyBindingReason.qml3
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedPropertyReason.qml12
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedType.qml3
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedTypeReason.qml3
-rw-r--r--tests/auto/qml/qmllint/data/goodAttachedProperty.qml13
-rw-r--r--tests/auto/qml/qmllint/data/goodAttachedPropertyAccess.qml11
-rw-r--r--tests/auto/qml/qmllint/data/goodAttachedPropertyNested.qml20
-rw-r--r--tests/auto/qml/qmllint/data/groupedPropertyAssignments.qml5
-rw-r--r--tests/auto/qml/qmllint/data/importing_js.qml2
-rw-r--r--tests/auto/qml/qmllint/data/invalidImport.qml4
-rw-r--r--tests/auto/qml/qmllint/data/multilineString.qml7
-rw-r--r--tests/auto/qml/qmllint/data/multilineStringEscaped.qml8
-rw-r--r--tests/auto/qml/qmllint/data/objectBoundToVar.qml4
-rw-r--r--tests/auto/qml/qmllint/data/overridescript.qml1
-rw-r--r--tests/auto/qml/qmllint/data/qmldirImport/duplicate.qml9
-rw-r--r--tests/auto/qml/qmllint/data/qmldirImportAndDepend/good.qml1
-rw-r--r--tests/auto/qml/qmllint/data/stringLength.qml9
-rw-r--r--tests/auto/qml/qmllint/data/stringLength2.qml10
-rw-r--r--tests/auto/qml/qmllint/data/stringLength3.qml8
-rw-r--r--tests/auto/qml/qmllint/data/typePropertyAccess.qml6
-rw-r--r--tests/auto/qml/qmllint/data/unused_multi.qml7
-rw-r--r--tests/auto/qml/qmllint/data/unused_prefix.qml5
-rw-r--r--tests/auto/qml/qmllint/data/unused_simple.qml5
-rw-r--r--tests/auto/qml/qmllint/data/unversionChangedSignalSansArguments.qml5
-rw-r--r--tests/auto/qml/qmllint/data/used.qml17
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp429
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Dummy/dummy_plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/ExtendedType/plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Imports/imports_plugin.h2
-rw-r--r--tests/auto/qml/qmlplugindump/data/dumper/Versions/versions_plugin.h2
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.cpp10
-rw-r--r--tests/auto/qml/qmltyperegistrar/tst_qmltyperegistrar.h15
-rw-r--r--tests/auto/qml/qqmlanybinding/data/unboundBinding.qml7
-rw-r--r--tests/auto/qml/qqmlanybinding/tst_qqmlanybinding.cpp32
-rw-r--r--tests/auto/qml/qqmlbinding/data/intOverflow.qml7
-rw-r--r--tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp12
-rw-r--r--tests/auto/qml/qqmlcomponent/tst_qqmlcomponent.cpp2
-rw-r--r--tests/auto/qml/qqmlcontext/tst_qqmlcontext.cpp103
-rw-r--r--tests/auto/qml/qqmldelegatemodel/CMakeLists.txt1
-rw-r--r--tests/auto/qml/qqmldelegatemodel/data/removeFromGroup.qml45
-rw-r--r--tests/auto/qml/qqmldelegatemodel/qqmldelegatemodel.pro13
-rw-r--r--tests/auto/qml/qqmldelegatemodel/tst_qqmldelegatemodel.cpp15
-rw-r--r--tests/auto/qml/qqmlecmascript/data/generatorCrashNewProperty.qml20
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qpropertyBindingUndefined.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qpropertyBindingUndefined2.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qpropertyBindingUndefinedWithoutReset1.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qpropertyBindingUndefinedWithoutReset2.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/qpropertyBindingUndefinedWithoutReset3.qml6
-rw-r--r--tests/auto/qml/qqmlecmascript/data/scriptConnect.7.qml11
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.cpp8
-rw-r--r--tests/auto/qml/qqmlecmascript/testtypes.h35
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp215
-rw-r--r--tests/auto/qml/qqmlengine/tst_qqmlengine.cpp82
-rw-r--r--tests/auto/qml/qqmlenginecleanup/tst_qqmlenginecleanup.cpp13
-rw-r--r--tests/auto/qml/qqmlfileselector/tst_qqmlfileselector.cpp3
-rw-r--r--tests/auto/qml/qqmlincubator/testtypes.h8
-rw-r--r--tests/auto/qml/qqmlincubator/tst_qqmlincubator.cpp18
-rw-r--r--tests/auto/qml/qqmlitemmodels/qtestmodel.h24
-rw-r--r--tests/auto/qml/qqmllanguage/data/Tab1.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/bareInline.qml9
-rw-r--r--tests/auto/qml/qqmllanguage/data/customVariantTypes.qml4
-rw-r--r--tests/auto/qml/qqmllanguage/data/hangOnWarning.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/data/inlineComponentWithAliasInstantiated.qml29
-rw-r--r--tests/auto/qml/qqmllanguage/data/optionalChaining.LHS.errors.txt48
-rw-r--r--tests/auto/qml/qqmllanguage/data/optionalChaining.LHS.qml58
-rw-r--r--tests/auto/qml/qqmllanguage/data/questionDotEOF.errors.txt1
-rw-r--r--tests/auto/qml/qqmllanguage/data/questionDotEOF.qml3
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h28
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp83
-rw-r--r--tests/auto/qml/qqmllistreference/data/AListItem.qml5
-rw-r--r--tests/auto/qml/qqmllistreference/data/compositeListProp.qml5
-rw-r--r--tests/auto/qml/qqmllistreference/tst_qqmllistreference.cpp28
-rw-r--r--tests/auto/qml/qqmllocale/data/functions.qml5
-rw-r--r--tests/auto/qml/qqmllocale/tst_qqmllocale.cpp110
-rw-r--r--tests/auto/qml/qqmlmetatype/tst_qqmlmetatype.cpp16
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/invalidFirstCommandModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/invalidNamespaceModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/moduleWithQmlSingleton/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nestedPlugin/nestedPlugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/nonstrictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.1/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/childplugin/childplugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/plugin/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginMixed/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginVersion/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginWithQmlFile/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/pluginWrongCase/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/preemptedStrictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/preemptiveModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/protectedModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/strictModule.2/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlmoduleplugin/strictModule/plugin.cpp2
-rw-r--r--tests/auto/qml/qqmlparser/tst_qqmlparser.cpp27
-rw-r--r--tests/auto/qml/qqmlpropertymap/tst_qqmlpropertymap.cpp6
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp38
-rw-r--r--tests/auto/qml/qqmltypeloader/SlowImport/plugin.h2
-rw-r--r--tests/auto/qml/qqmlvaluetypeproviders/testtypes.h8
-rw-r--r--tests/auto/qml/qqmlvaluetypes/testtypes.h26
-rw-r--r--tests/auto/qml/qqmlvaluetypes/tst_qqmlvaluetypes.cpp36
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/CMakeLists.txt27
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/attributes.qml11
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/attributes.xml14
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/elementErrors.qml9
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/empty.xml0
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/malformedAttribute.xml28
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/malformedData.qml10
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/malformedTagNestedLevel.xml28
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/malformedTagTopLevel.xml28
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/model.qml11
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/model.xml54
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/model2.xml14
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/nestedElements.qml11
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/nestedElements.xml76
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/propertychanges.qml10
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/proxyCrash.qml8
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/recipes.qml10
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/recipes.xml90
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/roleCrash.qml10
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/threading.qml8
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/data/unique.qml8
-rw-r--r--tests/auto/qml/qqmlxmllistmodel/tst_qqmlxmllistmodel.cpp711
-rw-r--r--tests/auto/qml/qv4identifiertable/tst_qv4identifiertable.cpp12
-rw-r--r--tests/auto/qmldom/domitem/tst_qmldomitem.cpp12
-rw-r--r--tests/auto/qmldom/errormessage/CMakeLists.txt2
-rw-r--r--tests/auto/qmldom/errormessage/tst_qmldomerrormessage.cpp48
-rw-r--r--tests/auto/qmldom/errormessage/tst_qmldomerrormessage.h (renamed from src/qml/common/qqmlapiversion_p.h)34
-rw-r--r--tests/auto/qmldom/path/CMakeLists.txt2
-rw-r--r--tests/auto/qmldom/path/tst_qmldompath.cpp191
-rw-r--r--tests/auto/qmldom/path/tst_qmldompath.h230
-rw-r--r--tests/auto/qmldom/stringdumper/CMakeLists.txt2
-rw-r--r--tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.cpp77
-rw-r--r--tests/auto/qmldom/stringdumper/tst_qmldomstringdumper.h115
-rw-r--r--tests/auto/qmltest/CMakeLists.txt1
-rw-r--r--tests/auto/qmltest/fuzzycompare/CMakeLists.txt12
-rw-r--r--tests/auto/qmltest/fuzzycompare/tst_FuzzyCompare.qml62
-rw-r--r--tests/auto/quick/drawingmodes/tst_drawingmodes.cpp2
-rw-r--r--tests/auto/quick/pointerhandlers/qquickhoverhandler/tst_qquickhoverhandler.cpp7
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/data/pinchAndDrag.qml62
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp112
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp18
-rw-r--r--tests/auto/quick/qquickanimations/tst_qquickanimations.cpp4
-rw-r--r--tests/auto/quick/qquickdrag/tst_qquickdrag.cpp16
-rw-r--r--tests/auto/quick/qquickdynamicpropertyanimation/tst_qquickdynamicpropertyanimation.cpp2
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp2
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp4
-rw-r--r--tests/auto/quick/qquickimageprovider/tst_qquickimageprovider.cpp18
-rw-r--r--tests/auto/quick/qquickitem/tst_qquickitem.cpp27
-rw-r--r--tests/auto/quick/qquickitem2/data/focusableItemReparentedToLoadedComponent.qml51
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp56
-rw-r--r--tests/auto/quick/qquicklistview/incrementalmodel.h8
-rw-r--r--tests/auto/quick/qquicklistview/proxytestinnermodel.h10
-rw-r--r--tests/auto/quick/qquicklistview/randomsortmodel.cpp4
-rw-r--r--tests/auto/quick/qquicklistview/randomsortmodel.h6
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp4
-rw-r--r--tests/auto/quick/qquickpainteditem/tst_qquickpainteditem.cpp4
-rw-r--r--tests/auto/quick/qquickrepeater/tst_qquickrepeater.cpp4
-rw-r--r--tests/auto/quick/qquicktableview/data/iscolumnloaded.qml103
-rw-r--r--tests/auto/quick/qquicktableview/data/sizefromdelegate.qml (renamed from src/particles/qquickparticlesmodule.cpp)70
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp107
-rw-r--r--tests/auto/quick/qquicktextinput/data/checkCursorDelegateWhenPaddingChanged.qml16
-rw-r--r--tests/auto/quick/qquicktextinput/tst_qquicktextinput.cpp36
-rw-r--r--tests/auto/quick/qquickvisualdatamodel/tst_qquickvisualdatamodel.cpp14
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp42
-rw-r--r--tests/auto/quick/rendernode/tst_rendernode.cpp4
-rw-r--r--tests/auto/quick/scenegraph/tst_scenegraph.cpp18
-rw-r--r--tests/auto/quick/touchmouse/BLACKLIST3
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp2
-rw-r--r--tests/auto/shared/platforminputcontext.h14
-rw-r--r--tests/auto/shared/qqmljsastdumper.cpp2
-rw-r--r--tests/manual/CMakeLists.txt15
-rw-r--r--tests/manual/httpserver/CMakeLists.txt4
-rw-r--r--tests/manual/listview/CMakeLists.txt45
-rw-r--r--tests/manual/pointer/CMakeLists.txt6
-rw-r--r--tests/manual/qmltypememory/TestPlugin/plugin.cpp2
-rw-r--r--tests/manual/scenegraph_lancelot/scenegraph/CMakeLists.txt2
-rw-r--r--tests/manual/tableview/CMakeLists.txt2
-rw-r--r--tests/testapplications/elements/content/XmlListModelElement.qml95
-rw-r--r--tests/testapplications/elements/content/cookbook.xml54
-rw-r--r--tools/CMakeLists.txt5
-rw-r--r--tools/qml/main.cpp15
-rw-r--r--tools/qmleasing/mainwindow.cpp10
-rw-r--r--tools/qmleasing/segmentproperties.cpp14
-rw-r--r--tools/qmlformat/commentastvisitor.cpp3
-rw-r--r--tools/qmlformat/commentastvisitor.h66
-rw-r--r--tools/qmlformat/dumpastvisitor.cpp11
-rw-r--r--tools/qmlformat/dumpastvisitor.h89
-rw-r--r--tools/qmlformat/main.cpp24
-rw-r--r--tools/qmlformat/restructureastvisitor.cpp2
-rw-r--r--tools/qmlformat/restructureastvisitor.h8
-rw-r--r--tools/qmlimportscanner/main.cpp19
-rw-r--r--tools/qmljsrootgen/CMakeLists.txt10
-rw-r--r--tools/qmljsrootgen/main.cpp408
-rw-r--r--tools/qmllint/CMakeLists.txt1
-rw-r--r--tools/qmllint/checkidentifiers.cpp266
-rw-r--r--tools/qmllint/checkidentifiers.h16
-rw-r--r--tools/qmllint/findwarnings.cpp336
-rw-r--r--tools/qmllint/findwarnings.h18
-rw-r--r--tools/qmllint/main.cpp90
-rw-r--r--tools/qmlscene/main.cpp5
655 files changed, 82600 insertions, 4339 deletions
diff --git a/.gitignore b/.gitignore
index de3a4005ef..b0423c27b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -305,4 +305,4 @@ CTestTestfile.cmake
cmake_install.cmake
*_autogen
tst_*.xml
-
+CMakeLists.txt.user
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd17f4a3c1..6342f42322 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,7 +16,7 @@ set(QT_NO_INTERNAL_COMPATIBILITY_FUNCTIONS TRUE)
# special case end
find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core) # special case
-find_package(Qt6 ${PROJECT_VERSION} QUIET CONFIG OPTIONAL_COMPONENTS Gui Network Widgets OpenGL OpenGLWidgets Sql Concurrent Test) # special case
+find_package(Qt6 ${PROJECT_VERSION} QUIET CONFIG OPTIONAL_COMPONENTS Gui Network Widgets OpenGL OpenGLWidgets Sql Concurrent Test ShaderTools) # special case
# special case begin
# export QT6_ADD_QML_MODULE to this project
diff --git a/cmake/QtDeclarativeSetup.cmake b/cmake/QtDeclarativeSetup.cmake
index d8e4719dbf..cd5ae32e14 100644
--- a/cmake/QtDeclarativeSetup.cmake
+++ b/cmake/QtDeclarativeSetup.cmake
@@ -15,13 +15,7 @@ function(qt_declarative_write_tag_header target_name)
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
string(LENGTH "${QML_COMPILE_HASH}" QML_COMPILE_HASH_LENGTH)
- set(compile_hash_contents "// Generated file, DO NOT EDIT
- #define QML_COMPILE_HASH \"${QML_COMPILE_HASH}\"
- #define QML_COMPILE_HASH_LENGTH ${QML_COMPILE_HASH_LENGTH}"
- )
- set(compile_hash_output_path "${CMAKE_CURRENT_BINARY_DIR}/qml_compile_hash_p.h")
- file(GENERATE OUTPUT "${compile_hash_output_path}"
- CONTENT "${compile_hash_contents}")
+ configure_file("qml_compile_hash_p.h.in" "${CMAKE_CURRENT_BINARY_DIR}/qml_compile_hash_p.h")
endfunction()
find_package(PythonInterp REQUIRED)
diff --git a/dependencies.yaml b/dependencies.yaml
index 109401a0c2..2e83ea3325 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -1,7 +1,10 @@
dependencies:
../qtbase:
- ref: 9fb81fc28774cd4aa01a8b29d59150e1a7de8fd8
+ ref: e99a883bd382ca950192bd66cafb2a1de6394ce7
required: true
+ ../qtshadertools:
+ ref: 8ef3ab944b9726b9e91c4ad28d42488f4eda2f77
+ required: false
../qtsvg:
- ref: b236b0d325174b0663e9193de10054036b43e524
+ ref: 2f53e43450b05f461849ba61f07d373926f0af1e
required: false
diff --git a/examples/quick/canvas/CMakeLists.txt b/examples/quick/canvas/CMakeLists.txt
index ef978ee80b..f7fd901238 100644
--- a/examples/quick/canvas/CMakeLists.txt
+++ b/examples/quick/canvas/CMakeLists.txt
@@ -38,6 +38,7 @@ target_link_libraries(canvas PUBLIC
# Resources:
set(canvas_resource_files
"bezierCurve/bezierCurve.qml"
+ "LabeledSlider.qml"
"canvas.qml"
"clip/clip.qml"
"contents/qt-logo.png"
diff --git a/examples/quick/canvas/LabeledSlider.qml b/examples/quick/canvas/LabeledSlider.qml
new file mode 100644
index 0000000000..0faae7f0c8
--- /dev/null
+++ b/examples/quick/canvas/LabeledSlider.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick
+import QtQuick.Controls
+
+Item {
+ id: labeledSlider
+ property alias name: label.text
+ implicitHeight: Math.max(label.implicitHeight, quickControlsSlider.implicitHeight)
+ property real min: 0.0
+ property real max: 1.0
+ property real init: 0.0
+ readonly property alias value: quickControlsSlider.value
+
+ Label {
+ id: label
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.verticalCenter: parent.verticalCenter
+ color: "#333"
+ font: Qt.font({pointSize: 13})
+ }
+
+ Slider {
+ id: quickControlsSlider
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ anchors.left: label.right
+ anchors.leftMargin: 20
+ from: labeledSlider.min
+ to: labeledSlider.max
+ width: labeledSlider.width - label.implicitWidth - (label.anchors.leftMargin + anchors.rightMargin + anchors.leftMargin)
+
+ Component.onCompleted: ()=> value = labeledSlider.init;
+ }
+}
diff --git a/examples/quick/canvas/bezierCurve/bezierCurve.qml b/examples/quick/canvas/bezierCurve/bezierCurve.qml
index 4f573ed64e..b284a40f4a 100644
--- a/examples/quick/canvas/bezierCurve/bezierCurve.qml
+++ b/examples/quick/canvas/bezierCurve/bezierCurve.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,9 +48,9 @@
**
****************************************************************************/
-import QtQuick 2.0
-import "../contents"
-import "../../shared"
+import QtQuick
+import QtQuick.Controls
+import "../"
Item {
id:container
@@ -62,7 +62,7 @@ Item {
anchors.fill: parent
anchors.topMargin: 12
- Text {
+ Label {
font.pointSize: 24
font.bold: true
text: "Bezier Curve"
@@ -130,8 +130,17 @@ Item {
id: controls
anchors.bottom: parent.bottom
anchors.bottomMargin: 12
- Slider {id: lineWidthCtrl; min: 1; max: 10; init: 2; name: "Outline"}
- Slider {id: scaleCtrl; min: 0.1; max: 10; init: 1; name: "Scale"}
- Slider {id: rotateCtrl; min: 0; max: Math.PI*2; init: 0; name: "Rotate"}
+
+ LabeledSlider {
+ id: lineWidthCtrl; name: "Outline"; min: 1; max: 10; init: 2; width: container.width
+ }
+
+ LabeledSlider {
+ id: scaleCtrl; name: "Scale"; min: 0.1; max: 10; init: 1; width: container.width
+ }
+
+ LabeledSlider {
+ id: rotateCtrl; name: "Rotate"; min: 0; max: Math.PI*2; init: 0; width: container.width
+ }
}
}
diff --git a/examples/quick/canvas/canvas.qml b/examples/quick/canvas/canvas.qml
index 7768e1092b..34e4f5a07b 100644
--- a/examples/quick/canvas/canvas.qml
+++ b/examples/quick/canvas/canvas.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,7 +48,7 @@
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick
import "../shared" as Examples
Item {
diff --git a/examples/quick/canvas/canvas.qrc b/examples/quick/canvas/canvas.qrc
index cfdfc844b9..7904309811 100644
--- a/examples/quick/canvas/canvas.qrc
+++ b/examples/quick/canvas/canvas.qrc
@@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/canvas">
<file>canvas.qml</file>
+ <file>LabeledSlider.qml</file>
<file>bezierCurve/bezierCurve.qml</file>
<file>clip/clip.qml</file>
<file>contents/qt-logo.png</file>
diff --git a/examples/quick/canvas/clip/clip.qml b/examples/quick/canvas/clip/clip.qml
index 1771121cd6..1c77657873 100644
--- a/examples/quick/canvas/clip/clip.qml
+++ b/examples/quick/canvas/clip/clip.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,9 +48,9 @@
**
****************************************************************************/
-import QtQuick 2.0
-import "../contents"
-import "../../shared"
+import QtQuick
+import QtQuick.Controls
+import "../"
Item {
id:container
@@ -61,7 +61,8 @@ Item {
spacing:5
anchors.fill: parent
anchors.topMargin: 12
- Text {
+
+ Label {
font.pointSize: 24
font.bold: true
text: "Squircle with Clip"
@@ -152,7 +153,8 @@ Item {
id: controls
anchors.bottom: parent.bottom
anchors.bottomMargin: 12
- Slider {id: nCtrl; min: 1; max: 10; init: 4; name:"N"}
- Slider {id: rCtrl; min: 30; max: 180; init: 80; name:"Radius"}
+
+ LabeledSlider {id: nCtrl; min: 1; max: 10; init: 4; name: "N"; width: container.width}
+ LabeledSlider {id: rCtrl; min: 30; max: 180; init: 80; name: "Radius"; width: container.width}
}
}
diff --git a/examples/quick/canvas/quadraticCurveTo/quadraticCurveTo.qml b/examples/quick/canvas/quadraticCurveTo/quadraticCurveTo.qml
index cd93205995..ca83b3989c 100644
--- a/examples/quick/canvas/quadraticCurveTo/quadraticCurveTo.qml
+++ b/examples/quick/canvas/quadraticCurveTo/quadraticCurveTo.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,9 +48,9 @@
**
****************************************************************************/
-import QtQuick 2.0
-import "../contents"
-import "../../shared"
+import QtQuick
+import QtQuick.Controls
+import "../"
Item {
id:container
@@ -62,7 +62,7 @@ Item {
anchors.fill: parent
anchors.topMargin: 12
- Text {
+ Label {
font.pointSize: 24
font.bold: true
text: "Quadratic Curve"
@@ -138,8 +138,9 @@ Item {
Column {
anchors.bottom: parent.bottom
anchors.bottomMargin: 12
- Slider {id:lineWidthCtrl; min:1; max:10; init:2; name:"Outline"}
- Slider {id:scaleCtrl; min:0.1; max:10; init:1; name:"Scale"}
- Slider {id:rotateCtrl; min:0; max:Math.PI*2; init:0; name:"Rotate"}
+
+ LabeledSlider {id:lineWidthCtrl; min:1; max:10; init:2; name: "Outline"; width: container.width}
+ LabeledSlider {id:scaleCtrl; min:0.1; max:10; init:1; name: "Scale"; width: container.width}
+ LabeledSlider {id:rotateCtrl; min:0; max:Math.PI*2; init:0; name: "Rotate"; width: container.width}
}
}
diff --git a/examples/quick/canvas/roundedrect/roundedrect.qml b/examples/quick/canvas/roundedrect/roundedrect.qml
index 08ede9b1e7..a4d6571cf8 100644
--- a/examples/quick/canvas/roundedrect/roundedrect.qml
+++ b/examples/quick/canvas/roundedrect/roundedrect.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,9 +48,9 @@
**
****************************************************************************/
-import QtQuick 2.0
-import "../contents"
-import "../../shared"
+import QtQuick
+import QtQuick.Controls
+import "../"
Item {
id:container
@@ -61,7 +61,8 @@ Item {
spacing: 6
anchors.fill: parent
anchors.topMargin: 12
- Text {
+
+ Label {
font.pointSize: 24
font.bold: true
text: "Rounded rectangle"
@@ -125,7 +126,8 @@ Item {
Column {
anchors.bottom: parent.bottom
anchors.bottomMargin: 12
- Slider {id: lineWidthCtrl ; min: 1 ; max: 10; init: 2 ; name: "Outline"}
- Slider {id: rCtrl ; min: 10 ; max: 80 ; init: 40 ; name: "Radius"}
+
+ LabeledSlider {id: lineWidthCtrl ; min: 1 ; max: 10; init: 2 ; name: "Outline"; width: container.width}
+ LabeledSlider {id: rCtrl ; min: 10 ; max: 80 ; init: 40 ; name: "Radius"; width: container.width}
}
}
diff --git a/examples/quick/canvas/smile/smile.qml b/examples/quick/canvas/smile/smile.qml
index cde18d4d38..ddcf42d4d0 100644
--- a/examples/quick/canvas/smile/smile.qml
+++ b/examples/quick/canvas/smile/smile.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,9 +48,9 @@
**
****************************************************************************/
-import QtQuick 2.0
-import "../contents"
-import "../../shared"
+import QtQuick
+import QtQuick.Controls
+import "../"
Item {
id: container
@@ -62,7 +62,7 @@ Item {
anchors.fill: parent
anchors.topMargin: 12
- Text {
+ Label {
font.pointSize: 24
font.bold: true
text: "Smile with arcs"
@@ -131,8 +131,9 @@ Item {
id: controls
anchors.bottom: parent.bottom
anchors.bottomMargin: 12
- Slider {id: lineWidthCtrl ; min: 1 ; max: 10 ; init: 2 ; name: "Outline"}
- Slider {id: scaleCtrl ; min: 0.1 ; max: 10 ; init: 1 ; name: "Scale"}
- Slider {id: rotateCtrl ; min: 0 ; max: Math.PI*2 ; init: 0 ; name: "Rotate"}
+
+ LabeledSlider {id: lineWidthCtrl ; min: 1 ; max: 10 ; init: 2 ; name: "Outline"; width: container.width}
+ LabeledSlider {id: scaleCtrl ; min: 0.1 ; max: 10 ; init: 1 ; name: "Scale"; width: container.width}
+ LabeledSlider {id: rotateCtrl ; min: 0 ; max: Math.PI*2 ; init: 0 ; name: "Rotate"; width: container.width}
}
}
diff --git a/examples/quick/canvas/squircle/squircle.qml b/examples/quick/canvas/squircle/squircle.qml
index 5416bfa1c7..f337c6adad 100644
--- a/examples/quick/canvas/squircle/squircle.qml
+++ b/examples/quick/canvas/squircle/squircle.qml
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
@@ -48,9 +48,9 @@
**
****************************************************************************/
-import QtQuick 2.0
-import "../contents"
-import "../../shared"
+import QtQuick
+import QtQuick.Controls
+import "../"
Item {
id: container
@@ -61,7 +61,8 @@ Item {
spacing: 6
anchors.fill: parent
anchors.topMargin: 12
- Text {
+
+ Label {
font.pointSize: 24
font.bold: true
text: "Squircles"
@@ -154,7 +155,8 @@ Item {
Column {
anchors.bottom: parent.bottom
anchors.bottomMargin: 12
- Slider {id: nCtrl ; min: 1 ; max: 10 ; init: 2 ; name: "N"}
- Slider {id: rCtrl ; min: 30 ; max: 180 ; init: 60 ; name: "Radius"}
+
+ LabeledSlider {id: nCtrl ; min: 1 ; max: 10 ; init: 2 ; name: "N"; width: container.width}
+ LabeledSlider {id: rCtrl ; min: 30 ; max: 180 ; init: 60 ; name: "Radius"; width: container.width}
}
}
diff --git a/examples/quick/canvas/tiger/tiger.qml b/examples/quick/canvas/tiger/tiger.qml
index 71367d560a..abd823d40e 100644
--- a/examples/quick/canvas/tiger/tiger.qml
+++ b/examples/quick/canvas/tiger/tiger.qml
@@ -48,9 +48,9 @@
**
****************************************************************************/
-import QtQuick 2.0
-import "../contents"
-import "../../shared"
+import QtQuick
+import QtQuick.Controls
+import "../"
import "tiger.js" as Tiger
Item {
@@ -63,7 +63,7 @@ Item {
anchors.fill: parent
anchors.topMargin: 12
- Text {
+ Label {
font.pointSize: 24
font.bold: true
text: "Tiger with SVG path"
@@ -137,8 +137,9 @@ Item {
id: controls
anchors.bottom: parent.bottom
anchors.bottomMargin: 12
- Slider {id: scaleCtrl ; min: 0.1 ; max: 1 ; init: 0.3 ; name: "Scale"}
- Slider {id: rotateCtrl ; min: 0 ; max: Math.PI*2 ; init: 0 ; name: "Rotate"}
- Slider {id: alphaCtrl ; min: 0 ; max: 1 ; init: 1 ; name: "Alpha"}
+
+ LabeledSlider {id: scaleCtrl ; min: 0.1 ; max: 1 ; init: 0.3 ; name: "Scale"; width: container.width}
+ LabeledSlider {id: rotateCtrl ; min: 0 ; max: Math.PI*2 ; init: 0 ; name: "Rotate"; width: container.width}
+ LabeledSlider {id: alphaCtrl ; min: 0 ; max: 1 ; init: 1 ; name: "Alpha"; width: container.width}
}
}
diff --git a/examples/quick/customitems/painteditem/textballoon.cpp b/examples/quick/customitems/painteditem/textballoon.cpp
index de34d67103..d3d4246eb2 100644
--- a/examples/quick/customitems/painteditem/textballoon.cpp
+++ b/examples/quick/customitems/painteditem/textballoon.cpp
@@ -92,7 +92,7 @@ void TextBalloon::paint(QPainter *painter)
}
//! [1]
-bool TextBalloon::isRightAligned()
+bool TextBalloon::isRightAligned() const
{
return this->rightAligned;
}
diff --git a/examples/quick/customitems/painteditem/textballoon.h b/examples/quick/customitems/painteditem/textballoon.h
index eb72804602..129b0f7ee1 100644
--- a/examples/quick/customitems/painteditem/textballoon.h
+++ b/examples/quick/customitems/painteditem/textballoon.h
@@ -64,7 +64,7 @@ class TextBalloon : public QQuickPaintedItem
TextBalloon(QQuickItem *parent = 0);
void paint(QPainter *painter);
- bool isRightAligned();
+ bool isRightAligned() const;
void setRightAligned(bool rightAligned);
private:
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index db06625dfd..f8c35a7eb5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -17,8 +17,11 @@ if(TARGET Qt::Sql)
add_subdirectory(qmllocalstorage)
endif()
+if (QT_FEATURE_qml_xmllistmodel)
+ add_subdirectory(qmlxmllistmodel)
+endif()
-if(TARGET Qt::Gui AND QT_FEATURE_qml_animation)
+if(TARGET Qt::Gui AND TARGET Qt::ShaderTools AND QT_FEATURE_qml_animation)
add_subdirectory(quick)
add_subdirectory(quickshapes)
add_subdirectory(quicklayouts)
diff --git a/src/imports/CMakeLists.txt b/src/imports/CMakeLists.txt
index 79a6a86016..623e9c29dd 100644
--- a/src/imports/CMakeLists.txt
+++ b/src/imports/CMakeLists.txt
@@ -3,9 +3,12 @@
add_subdirectory(builtins)
add_subdirectory(qtqml)
add_subdirectory(models)
-add_subdirectory(labsmodels)
add_subdirectory(tooling)
+if (QT_FEATURE_qml_xmllistmodel)
+ add_subdirectory(xmllistmodel)
+endif()
if(QT_FEATURE_qml_itemmodel)
+ add_subdirectory(labsmodels)
add_subdirectory(folderlistmodel)
endif()
if(QT_FEATURE_qml_worker_script)
diff --git a/src/imports/builtins/CMakeLists.txt b/src/imports/builtins/CMakeLists.txt
index 40f1948144..b41e38d128 100644
--- a/src/imports/builtins/CMakeLists.txt
+++ b/src/imports/builtins/CMakeLists.txt
@@ -2,10 +2,10 @@
# special case begin
-set(qml_type_file builtins.qmltypes)
+set(qml_type_files builtins.qmltypes jsroot.qmltypes)
qt_path_join(qml_install_dir "${QT_INSTALL_DIR}" "${INSTALL_QMLDIR}")
-qt_copy_or_install(FILES ${qml_type_file}
+qt_copy_or_install(FILES ${qml_type_files}
DESTINATION ${qml_install_dir}
)
diff --git a/src/imports/builtins/builtins.qmltypes b/src/imports/builtins/builtins.qmltypes
index c234300701..3143a077e2 100644
--- a/src/imports/builtins/builtins.qmltypes
+++ b/src/imports/builtins/builtins.qmltypes
@@ -108,7 +108,7 @@ Module {
Component {
name: "double"
prototype: "number"
- exports: ["QML/real 1.0"]
+ exports: ["QML/real 1.0", "QML/double 1.0"]
exportMetaObjectRevisions: [256]
accessSemantics: "value"
}
@@ -140,4 +140,10 @@ Module {
exportMetaObjectRevisions: [256]
accessSemantics: "value"
}
+
+ Component {
+ name: "QVariantList"
+ valueType: "QVariant"
+ accessSemantics: "sequence"
+ }
}
diff --git a/src/imports/builtins/jsroot.qmltypes b/src/imports/builtins/jsroot.qmltypes
new file mode 100644
index 0000000000..419a4e5726
--- /dev/null
+++ b/src/imports/builtins/jsroot.qmltypes
@@ -0,0 +1,1983 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ name: "Array"
+ accessSemantics: "reference"
+ prototype: "ArrayPrototype"
+ Property { name: "length"; type: "number" }
+ }
+ Component {
+ name: "ArrayBuffer"
+ accessSemantics: "reference"
+ prototype: "ArrayBufferPrototype"
+ }
+ Component {
+ name: "ArrayBufferPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "byteLength" }
+ Method {
+ name: "constructor"
+ type: "ArrayBuffer"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "slice"
+ Parameter {}
+ Parameter {}
+ }
+ Method { name: "toString" }
+ }
+ Component {
+ name: "ArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "length"; type: "number" }
+ Method {
+ name: "constructor"
+ type: "Array"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ Method { name: "toLocaleString" }
+ Method {
+ name: "concat"
+ Parameter {}
+ }
+ Method {
+ name: "copyWithin"
+ Parameter {}
+ Parameter {}
+ }
+ Method { name: "entries" }
+ Method {
+ name: "fill"
+ Parameter {}
+ }
+ Method {
+ name: "find"
+ Parameter {}
+ }
+ Method {
+ name: "findIndex"
+ Parameter {}
+ }
+ Method {
+ name: "includes"
+ Parameter {}
+ }
+ Method {
+ name: "join"
+ Parameter {}
+ }
+ Method { name: "keys" }
+ Method { name: "pop" }
+ Method {
+ name: "push"
+ Parameter {}
+ }
+ Method { name: "reverse" }
+ Method { name: "shift" }
+ Method {
+ name: "slice"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "sort"
+ Parameter {}
+ }
+ Method {
+ name: "splice"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "unshift"
+ Parameter {}
+ }
+ Method {
+ name: "indexOf"
+ Parameter {}
+ }
+ Method {
+ name: "lastIndexOf"
+ Parameter {}
+ }
+ Method {
+ name: "every"
+ Parameter {}
+ }
+ Method {
+ name: "some"
+ Parameter {}
+ }
+ Method {
+ name: "forEach"
+ Parameter {}
+ }
+ Method {
+ name: "map"
+ Parameter {}
+ }
+ Method {
+ name: "filter"
+ Parameter {}
+ }
+ Method {
+ name: "reduce"
+ Parameter {}
+ }
+ Method {
+ name: "reduceRight"
+ Parameter {}
+ }
+ Method { name: "values" }
+ }
+ Component {
+ name: "Atomics"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method {
+ name: "add"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "and"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "compareExchange"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "exchange"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "isLockFree"
+ Parameter {}
+ }
+ Method {
+ name: "load"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "or"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "store"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "sub"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "wait"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "wake"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "xor"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component { name: "Boolean"; accessSemantics: "reference"; prototype: "BooleanPrototype" }
+ Component {
+ name: "BooleanPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method {
+ name: "constructor"
+ type: "Boolean"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ Method { name: "valueOf" }
+ }
+ Component {
+ name: "Console"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method { name: "debug" }
+ Method { name: "log" }
+ Method { name: "info" }
+ Method { name: "warn" }
+ Method { name: "error" }
+ Method { name: "assert" }
+ Method { name: "count" }
+ Method { name: "profile" }
+ Method { name: "profileEnd" }
+ Method { name: "time" }
+ Method { name: "timeEnd" }
+ Method { name: "trace" }
+ Method { name: "exception" }
+ }
+ Component { name: "DataView"; accessSemantics: "reference"; prototype: "DataViewPrototype" }
+ Component {
+ name: "DataViewPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "buffer" }
+ Property { name: "byteLength" }
+ Property { name: "byteOffset" }
+ Method {
+ name: "constructor"
+ type: "DataView"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "getInt8"
+ Parameter {}
+ }
+ Method {
+ name: "getUint8"
+ Parameter {}
+ }
+ Method {
+ name: "getInt16"
+ Parameter {}
+ }
+ Method {
+ name: "getUint16"
+ Parameter {}
+ }
+ Method {
+ name: "getInt32"
+ Parameter {}
+ }
+ Method {
+ name: "getUint32"
+ Parameter {}
+ }
+ Method {
+ name: "getFloat32"
+ Parameter {}
+ }
+ Method {
+ name: "getFloat64"
+ Parameter {}
+ }
+ Method {
+ name: "setInt8"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setUint8"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setInt16"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setUint16"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setInt32"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setUint32"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setFloat32"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setFloat64"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "getUInt8"
+ Parameter {}
+ }
+ Method {
+ name: "getUInt16"
+ Parameter {}
+ }
+ Method {
+ name: "getUInt32"
+ Parameter {}
+ }
+ Method {
+ name: "setUInt8"
+ Parameter {}
+ }
+ Method {
+ name: "setUInt16"
+ Parameter {}
+ }
+ Method {
+ name: "setUInt32"
+ Parameter {}
+ }
+ }
+ Component { name: "Date"; accessSemantics: "reference"; prototype: "DatePrototype" }
+ Component {
+ name: "DatePrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method {
+ name: "constructor"
+ type: "Date"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method { name: "toString" }
+ Method { name: "toDateString" }
+ Method { name: "toTimeString" }
+ Method { name: "toLocaleString" }
+ Method { name: "toLocaleDateString" }
+ Method { name: "toLocaleTimeString" }
+ Method { name: "valueOf" }
+ Method { name: "getTime" }
+ Method { name: "getYear" }
+ Method { name: "getFullYear" }
+ Method { name: "getUTCFullYear" }
+ Method { name: "getMonth" }
+ Method { name: "getUTCMonth" }
+ Method { name: "getDate" }
+ Method { name: "getUTCDate" }
+ Method { name: "getDay" }
+ Method { name: "getUTCDay" }
+ Method { name: "getHours" }
+ Method { name: "getUTCHours" }
+ Method { name: "getMinutes" }
+ Method { name: "getUTCMinutes" }
+ Method { name: "getSeconds" }
+ Method { name: "getUTCSeconds" }
+ Method { name: "getMilliseconds" }
+ Method { name: "getUTCMilliseconds" }
+ Method { name: "getTimezoneOffset" }
+ Method {
+ name: "setTime"
+ Parameter {}
+ }
+ Method {
+ name: "setMilliseconds"
+ Parameter {}
+ }
+ Method {
+ name: "setUTCMilliseconds"
+ Parameter {}
+ }
+ Method {
+ name: "setSeconds"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setUTCSeconds"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setMinutes"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setUTCMinutes"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setHours"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setUTCHours"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setDate"
+ Parameter {}
+ }
+ Method {
+ name: "setUTCDate"
+ Parameter {}
+ }
+ Method {
+ name: "setMonth"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setUTCMonth"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setYear"
+ Parameter {}
+ }
+ Method {
+ name: "setFullYear"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setUTCFullYear"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method { name: "toUTCString" }
+ Method { name: "toGMTString" }
+ Method { name: "toISOString" }
+ Method {
+ name: "toJSON"
+ Parameter {}
+ }
+ }
+ Component {
+ name: "Error"
+ accessSemantics: "reference"
+ prototype: "ErrorPrototype"
+ Property { name: "stack"; type: "string" }
+ Property { name: "fileName" }
+ Property { name: "lineNumber" }
+ }
+ Component {
+ name: "ErrorPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "message"; type: "string" }
+ Property { name: "name"; type: "string" }
+ Method {
+ name: "constructor"
+ type: "Error"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ }
+ Component {
+ name: "EvalError"
+ accessSemantics: "reference"
+ prototype: "EvalErrorPrototype"
+ Property { name: "stack"; type: "string" }
+ Property { name: "fileName" }
+ Property { name: "lineNumber" }
+ }
+ Component {
+ name: "EvalErrorPrototype"
+ accessSemantics: "reference"
+ prototype: "ErrorPrototype"
+ Property { name: "message"; type: "string" }
+ Property { name: "name"; type: "string" }
+ Method {
+ name: "constructor"
+ type: "EvalError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ }
+ Component {
+ name: "Float32Array"
+ accessSemantics: "reference"
+ prototype: "Float32ArrayPrototype"
+ }
+ Component {
+ name: "Float32ArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "IntrinsicTypedArrayPrototype"
+ Property { name: "BYTES_PER_ELEMENT"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "Float32Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component {
+ name: "Float64Array"
+ accessSemantics: "reference"
+ prototype: "Float64ArrayPrototype"
+ }
+ Component {
+ name: "Float64ArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "IntrinsicTypedArrayPrototype"
+ Property { name: "BYTES_PER_ELEMENT"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "Float64Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component {
+ name: "Function"
+ accessSemantics: "reference"
+ prototype: "FunctionPrototype"
+ Property { name: "prototype"; type: "Object" }
+ Property { name: "name"; type: "string"; isReadonly: true }
+ Property { name: "length"; type: "number"; isReadonly: true }
+ }
+ Component {
+ name: "FunctionPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "name"; type: "string"; isReadonly: true }
+ Property { name: "length"; type: "number"; isReadonly: true }
+ Property { name: "caller" }
+ Property { name: "arguments" }
+ Method {
+ name: "constructor"
+ type: "Function"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ Method {
+ name: "apply"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "call"
+ Parameter {}
+ }
+ Method {
+ name: "bind"
+ Parameter {}
+ }
+ Method { name: "connect" }
+ Method { name: "disconnect" }
+ }
+ Component {
+ name: "GlobalObject"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "Atomics"; type: "Atomics" }
+ Property { name: "Math"; type: "Math" }
+ Property { name: "JSON"; type: "JSON" }
+ Property { name: "Reflect"; type: "Reflect" }
+ Property { name: "undefined" }
+ Property { name: "NaN"; type: "number"; isReadonly: true }
+ Property { name: "Infinity"; type: "number"; isReadonly: true }
+ Property { name: "Qt"; type: "Qt" }
+ Property { name: "console"; type: "Console" }
+ Method {
+ name: "Object"
+ type: "Object"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "String"
+ type: "String"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "Symbol"; type: "undefined"; isConstructor: true }
+ Method {
+ name: "Number"
+ type: "Number"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "Boolean"
+ type: "Boolean"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "Array"
+ type: "Array"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "Function"
+ type: "Function"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "Date"
+ type: "Date"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "RegExp"
+ type: "RegExp"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Error"
+ type: "Error"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "EvalError"
+ type: "EvalError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "RangeError"
+ type: "RangeError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "ReferenceError"
+ type: "ReferenceError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "SyntaxError"
+ type: "SyntaxError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "TypeError"
+ type: "TypeError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "URIError"
+ type: "URIError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "Promise"
+ type: "Promise"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "URL"; type: "URL"; isConstructor: true }
+ Method { name: "URLSearchParams"; type: "URLSearchParams"; isConstructor: true }
+ Method {
+ name: "SharedArrayBuffer"
+ type: "SharedArrayBuffer"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "ArrayBuffer"
+ type: "ArrayBuffer"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "DataView"
+ type: "DataView"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "WeakSet"; type: "WeakSet"; isConstructor: true }
+ Method { name: "Set"; type: "Set"; isConstructor: true }
+ Method { name: "WeakMap"; type: "WeakMap"; isConstructor: true }
+ Method { name: "Map"; type: "Map"; isConstructor: true }
+ Method {
+ name: "Int8Array"
+ type: "Int8Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Uint8Array"
+ type: "Uint8Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Int16Array"
+ type: "Int16Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Uint16Array"
+ type: "Uint16Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Int32Array"
+ type: "Int32Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Uint32Array"
+ type: "Uint32Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Uint8ClampedArray"
+ type: "Uint8ClampedArray"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Float32Array"
+ type: "Float32Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Float64Array"
+ type: "Float64Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "Proxy"
+ type: "Proxy"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "eval"
+ Parameter {}
+ }
+ Method {
+ name: "parseInt"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "parseFloat"
+ Parameter {}
+ }
+ Method {
+ name: "isNaN"
+ Parameter {}
+ }
+ Method {
+ name: "isFinite"
+ Parameter {}
+ }
+ Method {
+ name: "decodeURI"
+ Parameter {}
+ }
+ Method {
+ name: "decodeURIComponent"
+ Parameter {}
+ }
+ Method {
+ name: "encodeURI"
+ Parameter {}
+ }
+ Method {
+ name: "encodeURIComponent"
+ Parameter {}
+ }
+ Method {
+ name: "escape"
+ Parameter {}
+ }
+ Method {
+ name: "unescape"
+ Parameter {}
+ }
+ Method { name: "qsTranslate" }
+ Method { name: "QT_TRANSLATE_NOOP" }
+ Method { name: "qsTr" }
+ Method { name: "QT_TR_NOOP" }
+ Method { name: "qsTrId" }
+ Method { name: "QT_TRID_NOOP" }
+ Method { name: "print" }
+ Method { name: "gc" }
+ }
+ Component { name: "Int16Array"; accessSemantics: "reference"; prototype: "Int16ArrayPrototype" }
+ Component {
+ name: "Int16ArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "IntrinsicTypedArrayPrototype"
+ Property { name: "BYTES_PER_ELEMENT"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "Int16Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component { name: "Int32Array"; accessSemantics: "reference"; prototype: "Int32ArrayPrototype" }
+ Component {
+ name: "Int32ArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "IntrinsicTypedArrayPrototype"
+ Property { name: "BYTES_PER_ELEMENT"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "Int32Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component { name: "Int8Array"; accessSemantics: "reference"; prototype: "Int8ArrayPrototype" }
+ Component {
+ name: "Int8ArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "IntrinsicTypedArrayPrototype"
+ Property { name: "BYTES_PER_ELEMENT"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "Int8Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component {
+ name: "IntrinsicTypedArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "buffer" }
+ Property { name: "byteLength" }
+ Property { name: "byteOffset" }
+ Property { name: "length" }
+ Method {
+ name: "copyWithin"
+ Parameter {}
+ Parameter {}
+ }
+ Method { name: "entries" }
+ Method {
+ name: "every"
+ Parameter {}
+ }
+ Method {
+ name: "fill"
+ Parameter {}
+ }
+ Method {
+ name: "filter"
+ Parameter {}
+ }
+ Method {
+ name: "find"
+ Parameter {}
+ }
+ Method {
+ name: "findIndex"
+ Parameter {}
+ }
+ Method {
+ name: "forEach"
+ Parameter {}
+ }
+ Method {
+ name: "includes"
+ Parameter {}
+ }
+ Method {
+ name: "indexOf"
+ Parameter {}
+ }
+ Method {
+ name: "join"
+ Parameter {}
+ }
+ Method { name: "keys" }
+ Method {
+ name: "lastIndexOf"
+ Parameter {}
+ }
+ Method {
+ name: "map"
+ Parameter {}
+ }
+ Method {
+ name: "reduce"
+ Parameter {}
+ }
+ Method {
+ name: "reduceRight"
+ Parameter {}
+ }
+ Method { name: "reverse" }
+ Method {
+ name: "some"
+ Parameter {}
+ }
+ Method {
+ name: "set"
+ Parameter {}
+ }
+ Method {
+ name: "slice"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "subarray"
+ Parameter {}
+ Parameter {}
+ }
+ Method { name: "toLocaleString" }
+ Method { name: "toString" }
+ Method { name: "values" }
+ }
+ Component {
+ name: "JSON"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method {
+ name: "parse"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "stringify"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component { name: "Map"; accessSemantics: "reference"; prototype: "MapPrototype" }
+ Component {
+ name: "MapPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "size" }
+ Method { name: "constructor"; type: "Map"; isConstructor: true }
+ Method { name: "clear" }
+ Method {
+ name: "delete"
+ Parameter {}
+ }
+ Method {
+ name: "forEach"
+ Parameter {}
+ }
+ Method {
+ name: "get"
+ Parameter {}
+ }
+ Method {
+ name: "has"
+ Parameter {}
+ }
+ Method { name: "keys" }
+ Method {
+ name: "set"
+ Parameter {}
+ Parameter {}
+ }
+ Method { name: "values" }
+ Method { name: "entries" }
+ }
+ Component {
+ name: "Math"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "E"; type: "number"; isReadonly: true }
+ Property { name: "LN2"; type: "number"; isReadonly: true }
+ Property { name: "LN10"; type: "number"; isReadonly: true }
+ Property { name: "LOG2E"; type: "number"; isReadonly: true }
+ Property { name: "LOG10E"; type: "number"; isReadonly: true }
+ Property { name: "PI"; type: "number"; isReadonly: true }
+ Property { name: "SQRT1_2"; type: "number"; isReadonly: true }
+ Property { name: "SQRT2"; type: "number"; isReadonly: true }
+ Method {
+ name: "abs"
+ Parameter {}
+ }
+ Method {
+ name: "acos"
+ Parameter {}
+ }
+ Method {
+ name: "acosh"
+ Parameter {}
+ }
+ Method {
+ name: "asin"
+ Parameter {}
+ }
+ Method {
+ name: "asinh"
+ Parameter {}
+ }
+ Method {
+ name: "atan"
+ Parameter {}
+ }
+ Method {
+ name: "atanh"
+ Parameter {}
+ }
+ Method {
+ name: "atan2"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "cbrt"
+ Parameter {}
+ }
+ Method {
+ name: "ceil"
+ Parameter {}
+ }
+ Method {
+ name: "clz32"
+ Parameter {}
+ }
+ Method {
+ name: "cos"
+ Parameter {}
+ }
+ Method {
+ name: "cosh"
+ Parameter {}
+ }
+ Method {
+ name: "exp"
+ Parameter {}
+ }
+ Method {
+ name: "expm1"
+ Parameter {}
+ }
+ Method {
+ name: "floor"
+ Parameter {}
+ }
+ Method {
+ name: "fround"
+ Parameter {}
+ }
+ Method {
+ name: "hypot"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "imul"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "log"
+ Parameter {}
+ }
+ Method {
+ name: "log10"
+ Parameter {}
+ }
+ Method {
+ name: "log1p"
+ Parameter {}
+ }
+ Method {
+ name: "log2"
+ Parameter {}
+ }
+ Method {
+ name: "max"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "min"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "pow"
+ Parameter {}
+ Parameter {}
+ }
+ Method { name: "random" }
+ Method {
+ name: "round"
+ Parameter {}
+ }
+ Method {
+ name: "sign"
+ Parameter {}
+ }
+ Method {
+ name: "sin"
+ Parameter {}
+ }
+ Method {
+ name: "sinh"
+ Parameter {}
+ }
+ Method {
+ name: "sqrt"
+ Parameter {}
+ }
+ Method {
+ name: "tan"
+ Parameter {}
+ }
+ Method {
+ name: "tanh"
+ Parameter {}
+ }
+ Method {
+ name: "trunc"
+ Parameter {}
+ }
+ }
+ Component { name: "Number"; accessSemantics: "reference"; prototype: "NumberPrototype" }
+ Component {
+ name: "NumberPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method {
+ name: "constructor"
+ type: "Number"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "toString"
+ Parameter {}
+ }
+ Method { name: "toLocaleString" }
+ Method { name: "valueOf" }
+ Method {
+ name: "toFixed"
+ Parameter {}
+ }
+ Method {
+ name: "toExponential"
+ Parameter {}
+ }
+ Method {
+ name: "toPrecision"
+ Parameter {}
+ }
+ }
+ Component { name: "Object"; accessSemantics: "reference"; prototype: "ObjectPrototype" }
+ Component {
+ name: "ObjectPrototype"
+ accessSemantics: "reference"
+ Property { name: "__proto__" }
+ Method {
+ name: "constructor"
+ type: "Object"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ Method { name: "toLocaleString" }
+ Method { name: "valueOf" }
+ Method {
+ name: "hasOwnProperty"
+ Parameter {}
+ }
+ Method {
+ name: "isPrototypeOf"
+ Parameter {}
+ }
+ Method {
+ name: "propertyIsEnumerable"
+ Parameter {}
+ }
+ Method {
+ name: "__defineGetter__"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "__defineSetter__"
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component { name: "Promise"; accessSemantics: "reference"; prototype: "PromisePrototype" }
+ Component {
+ name: "PromisePrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method {
+ name: "constructor"
+ type: "Promise"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "then"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "catch"
+ Parameter {}
+ }
+ }
+ Component { name: "Proxy"; accessSemantics: "reference"; prototype: "ObjectPrototype" }
+ Component {
+ name: "Qt"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "objectName"; type: "string" }
+ Property { name: "application"; type: "QtApplication" }
+ Property { name: "platform"; type: "QtPlatform" }
+ Property { name: "inputMethod"; type: "QtInputMethod" }
+ Property { name: "styleHints"; type: "QtStyleHints" }
+ Property { name: "uiLanguage"; type: "string" }
+ Method {
+ name: "callLater"
+ Parameter {}
+ }
+ Method { name: "objectNameChanged" }
+ Method { name: "include" }
+ Method { name: "isQtObject" }
+ Method { name: "color" }
+ Method { name: "rgba" }
+ Method { name: "hsla" }
+ Method { name: "hsva" }
+ Method { name: "colorEqual" }
+ Method { name: "rect" }
+ Method { name: "point" }
+ Method { name: "size" }
+ Method { name: "vector2d" }
+ Method { name: "vector3d" }
+ Method { name: "vector4d" }
+ Method { name: "quaternion" }
+ Method { name: "matrix4x4" }
+ Method { name: "lighter" }
+ Method { name: "darker" }
+ Method { name: "alpha" }
+ Method { name: "tint" }
+ Method { name: "formatDate" }
+ Method { name: "formatTime" }
+ Method { name: "formatDateTime" }
+ Method { name: "locale" }
+ Method { name: "resolvedUrl" }
+ Method { name: "openUrlExternally" }
+ Method { name: "font" }
+ Method { name: "fontFamilies" }
+ Method { name: "md5" }
+ Method { name: "btoa" }
+ Method { name: "atob" }
+ Method { name: "quit" }
+ Method { name: "exit" }
+ Method { name: "createQmlObject" }
+ Method { name: "createComponent" }
+ Method { name: "binding" }
+ }
+ Component {
+ name: "QtApplication"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "objectName"; type: "string" }
+ Property { name: "arguments"; type: "QtApplicationArguments" }
+ Property { name: "name"; type: "string" }
+ Property { name: "version"; type: "string" }
+ Property { name: "organization"; type: "string" }
+ Property { name: "domain"; type: "string" }
+ Method { name: "objectNameChanged" }
+ Method { name: "aboutToQuit" }
+ Method { name: "nameChanged" }
+ Method { name: "versionChanged" }
+ Method { name: "organizationChanged" }
+ Method { name: "domainChanged" }
+ Method { name: "setName" }
+ Method { name: "setVersion" }
+ Method { name: "setOrganization" }
+ Method { name: "setDomain" }
+ }
+ Component {
+ name: "QtApplicationArguments"
+ accessSemantics: "reference"
+ prototype: "ArrayPrototype"
+ Property { name: "0"; type: "string" }
+ Property { name: "1"; type: "string" }
+ Property { name: "length"; type: "number" }
+ }
+ Component {
+ name: "QtInputMethod"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "objectName"; type: "string" }
+ Method { name: "objectNameChanged" }
+ }
+ Component {
+ name: "QtPlatform"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "objectName"; type: "string" }
+ Property { name: "os"; type: "string" }
+ Property { name: "pluginName"; type: "string" }
+ Method { name: "objectNameChanged" }
+ }
+ Component {
+ name: "QtStyleHints"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "objectName"; type: "string" }
+ Method { name: "objectNameChanged" }
+ }
+ Component {
+ name: "RangeError"
+ accessSemantics: "reference"
+ prototype: "RangeErrorPrototype"
+ Property { name: "stack"; type: "string" }
+ Property { name: "fileName" }
+ Property { name: "lineNumber" }
+ }
+ Component {
+ name: "RangeErrorPrototype"
+ accessSemantics: "reference"
+ prototype: "ErrorPrototype"
+ Property { name: "message"; type: "string" }
+ Property { name: "name"; type: "string" }
+ Method {
+ name: "constructor"
+ type: "RangeError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ }
+ Component {
+ name: "ReferenceError"
+ accessSemantics: "reference"
+ prototype: "ReferenceErrorPrototype"
+ Property { name: "stack"; type: "string" }
+ Property { name: "fileName" }
+ Property { name: "lineNumber" }
+ }
+ Component {
+ name: "ReferenceErrorPrototype"
+ accessSemantics: "reference"
+ prototype: "ErrorPrototype"
+ Property { name: "message"; type: "string" }
+ Property { name: "name"; type: "string" }
+ Method {
+ name: "constructor"
+ type: "ReferenceError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ }
+ Component {
+ name: "Reflect"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method {
+ name: "apply"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "construct"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "defineProperty"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "deleteProperty"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "get"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "getOwnPropertyDescriptor"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "getPrototypeOf"
+ Parameter {}
+ }
+ Method {
+ name: "has"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "isExtensible"
+ Parameter {}
+ }
+ Method {
+ name: "ownKeys"
+ Parameter {}
+ }
+ Method {
+ name: "preventExtensions"
+ Parameter {}
+ }
+ Method {
+ name: "set"
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "setPrototypeOf"
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component {
+ name: "RegExp"
+ accessSemantics: "reference"
+ prototype: "RegExpPrototype"
+ Property { name: "lastIndex"; type: "number" }
+ }
+ Component {
+ name: "RegExpPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "flags"; type: "string" }
+ Property { name: "global" }
+ Property { name: "ignoreCase" }
+ Property { name: "multiline" }
+ Property { name: "source"; type: "string" }
+ Property { name: "sticky" }
+ Property { name: "unicode" }
+ Method {
+ name: "constructor"
+ type: "RegExp"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "exec"
+ Parameter {}
+ }
+ Method {
+ name: "test"
+ Parameter {}
+ }
+ Method { name: "toString" }
+ Method {
+ name: "compile"
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component { name: "Set"; accessSemantics: "reference"; prototype: "SetPrototype" }
+ Component {
+ name: "SetPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "size" }
+ Method { name: "constructor"; type: "Set"; isConstructor: true }
+ Method {
+ name: "add"
+ Parameter {}
+ }
+ Method { name: "clear" }
+ Method {
+ name: "delete"
+ Parameter {}
+ }
+ Method { name: "entries" }
+ Method {
+ name: "forEach"
+ Parameter {}
+ }
+ Method {
+ name: "has"
+ Parameter {}
+ }
+ Method { name: "keys" }
+ Method { name: "values" }
+ }
+ Component {
+ name: "SharedArrayBuffer"
+ accessSemantics: "reference"
+ prototype: "SharedArrayBufferPrototype"
+ }
+ Component {
+ name: "SharedArrayBufferPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "byteLength" }
+ Method {
+ name: "constructor"
+ type: "SharedArrayBuffer"
+ isConstructor: true
+ Parameter {}
+ }
+ Method {
+ name: "slice"
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component {
+ name: "String"
+ accessSemantics: "reference"
+ prototype: "StringPrototype"
+ Property { name: "length"; type: "number"; isReadonly: true }
+ }
+ Component {
+ name: "StringPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "length"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "String"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ Method { name: "valueOf" }
+ Method {
+ name: "charAt"
+ Parameter {}
+ }
+ Method {
+ name: "charCodeAt"
+ Parameter {}
+ }
+ Method {
+ name: "codePointAt"
+ Parameter {}
+ }
+ Method {
+ name: "concat"
+ Parameter {}
+ }
+ Method {
+ name: "endsWith"
+ Parameter {}
+ }
+ Method {
+ name: "indexOf"
+ Parameter {}
+ }
+ Method {
+ name: "includes"
+ Parameter {}
+ }
+ Method {
+ name: "lastIndexOf"
+ Parameter {}
+ }
+ Method {
+ name: "localeCompare"
+ Parameter {}
+ }
+ Method {
+ name: "match"
+ Parameter {}
+ }
+ Method { name: "normalize" }
+ Method {
+ name: "padEnd"
+ Parameter {}
+ }
+ Method {
+ name: "padStart"
+ Parameter {}
+ }
+ Method {
+ name: "repeat"
+ Parameter {}
+ }
+ Method {
+ name: "replace"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "search"
+ Parameter {}
+ }
+ Method {
+ name: "slice"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "split"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "startsWith"
+ Parameter {}
+ }
+ Method {
+ name: "substr"
+ Parameter {}
+ Parameter {}
+ }
+ Method {
+ name: "substring"
+ Parameter {}
+ Parameter {}
+ }
+ Method { name: "toLowerCase" }
+ Method { name: "toLocaleLowerCase" }
+ Method { name: "toUpperCase" }
+ Method { name: "toLocaleUpperCase" }
+ Method { name: "trim" }
+ Method { name: "arg" }
+ }
+ Component {
+ name: "SymbolPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method { name: "constructor"; type: "undefined"; isConstructor: true }
+ Method { name: "toString" }
+ Method { name: "valueOf" }
+ }
+ Component {
+ name: "SyntaxError"
+ accessSemantics: "reference"
+ prototype: "SyntaxErrorPrototype"
+ Property { name: "stack"; type: "string" }
+ Property { name: "fileName" }
+ Property { name: "lineNumber" }
+ }
+ Component {
+ name: "SyntaxErrorPrototype"
+ accessSemantics: "reference"
+ prototype: "ErrorPrototype"
+ Property { name: "message"; type: "string" }
+ Property { name: "name"; type: "string" }
+ Method {
+ name: "constructor"
+ type: "SyntaxError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ }
+ Component {
+ name: "TypeError"
+ accessSemantics: "reference"
+ prototype: "TypeErrorPrototype"
+ Property { name: "stack"; type: "string" }
+ Property { name: "fileName" }
+ Property { name: "lineNumber" }
+ }
+ Component {
+ name: "TypeErrorPrototype"
+ accessSemantics: "reference"
+ prototype: "ErrorPrototype"
+ Property { name: "message"; type: "string" }
+ Property { name: "name"; type: "string" }
+ Method {
+ name: "constructor"
+ type: "TypeError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ }
+ Component {
+ name: "URIError"
+ accessSemantics: "reference"
+ prototype: "URIErrorPrototype"
+ Property { name: "stack"; type: "string" }
+ Property { name: "fileName" }
+ Property { name: "lineNumber" }
+ }
+ Component {
+ name: "URIErrorPrototype"
+ accessSemantics: "reference"
+ prototype: "ErrorPrototype"
+ Property { name: "message"; type: "string" }
+ Property { name: "name"; type: "string" }
+ Method {
+ name: "constructor"
+ type: "URIError"
+ isConstructor: true
+ Parameter {}
+ }
+ Method { name: "toString" }
+ }
+ Component { name: "URL"; accessSemantics: "reference"; prototype: "URLPrototype" }
+ Component {
+ name: "URLPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Property { name: "hash" }
+ Property { name: "host" }
+ Property { name: "hostname" }
+ Property { name: "href" }
+ Property { name: "origin" }
+ Property { name: "password" }
+ Property { name: "pathname" }
+ Property { name: "port" }
+ Property { name: "protocol" }
+ Property { name: "search" }
+ Property { name: "searchParams" }
+ Property { name: "username" }
+ Method { name: "toString" }
+ Method { name: "toJSON" }
+ }
+ Component {
+ name: "URLSearchParams"
+ accessSemantics: "reference"
+ prototype: "URLSearchParamsPrototype"
+ }
+ Component {
+ name: "URLSearchParamsPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method { name: "toString" }
+ Method { name: "sort" }
+ Method { name: "append" }
+ Method { name: "delete" }
+ Method { name: "has" }
+ Method { name: "set" }
+ Method { name: "get" }
+ Method { name: "getAll" }
+ Method { name: "forEach" }
+ Method { name: "entries" }
+ Method { name: "keys" }
+ Method { name: "values" }
+ }
+ Component {
+ name: "Uint16Array"
+ accessSemantics: "reference"
+ prototype: "Uint16ArrayPrototype"
+ }
+ Component {
+ name: "Uint16ArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "IntrinsicTypedArrayPrototype"
+ Property { name: "BYTES_PER_ELEMENT"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "Uint16Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component {
+ name: "Uint32Array"
+ accessSemantics: "reference"
+ prototype: "Uint32ArrayPrototype"
+ }
+ Component {
+ name: "Uint32ArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "IntrinsicTypedArrayPrototype"
+ Property { name: "BYTES_PER_ELEMENT"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "Uint32Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component { name: "Uint8Array"; accessSemantics: "reference"; prototype: "Uint8ArrayPrototype" }
+ Component {
+ name: "Uint8ArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "IntrinsicTypedArrayPrototype"
+ Property { name: "BYTES_PER_ELEMENT"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "Uint8Array"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component {
+ name: "Uint8ClampedArray"
+ accessSemantics: "reference"
+ prototype: "Uint8ClampedArrayPrototype"
+ }
+ Component {
+ name: "Uint8ClampedArrayPrototype"
+ accessSemantics: "reference"
+ prototype: "IntrinsicTypedArrayPrototype"
+ Property { name: "BYTES_PER_ELEMENT"; type: "number"; isReadonly: true }
+ Method {
+ name: "constructor"
+ type: "Uint8ClampedArray"
+ isConstructor: true
+ Parameter {}
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component { name: "WeakMap"; accessSemantics: "reference"; prototype: "WeakMapPrototype" }
+ Component {
+ name: "WeakMapPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method { name: "constructor"; type: "WeakMap"; isConstructor: true }
+ Method {
+ name: "delete"
+ Parameter {}
+ }
+ Method {
+ name: "get"
+ Parameter {}
+ }
+ Method {
+ name: "has"
+ Parameter {}
+ }
+ Method {
+ name: "set"
+ Parameter {}
+ Parameter {}
+ }
+ }
+ Component { name: "WeakSet"; accessSemantics: "reference"; prototype: "WeakSetPrototype" }
+ Component {
+ name: "WeakSetPrototype"
+ accessSemantics: "reference"
+ prototype: "ObjectPrototype"
+ Method { name: "constructor"; type: "WeakSet"; isConstructor: true }
+ Method {
+ name: "add"
+ Parameter {}
+ }
+ Method {
+ name: "delete"
+ Parameter {}
+ }
+ Method {
+ name: "has"
+ Parameter {}
+ }
+ }
+ Component { name: "boolean"; accessSemantics: "value"; prototype: "BooleanPrototype" }
+ Component {
+ name: "function"
+ accessSemantics: "reference"
+ prototype: "FunctionPrototype"
+ Property { name: "prototype"; type: "Object" }
+ Property { name: "name"; type: "string"; isReadonly: true }
+ Property { name: "length"; type: "number"; isReadonly: true }
+ }
+ Component { name: "number"; accessSemantics: "value"; prototype: "NumberPrototype" }
+ Component { name: "object"; accessSemantics: "reference"; prototype: "ObjectPrototype" }
+ Component { name: "string"; accessSemantics: "value"; prototype: "StringPrototype" }
+ Component { name: "symbol"; accessSemantics: "value"; prototype: "SymbolPrototype" }
+ Component { name: "undefined"; accessSemantics: "value" }
+}
diff --git a/src/imports/folderlistmodel/CMakeLists.txt b/src/imports/folderlistmodel/CMakeLists.txt
index 85a43061f4..9ef942ae9d 100644
--- a/src/imports/folderlistmodel/CMakeLists.txt
+++ b/src/imports/folderlistmodel/CMakeLists.txt
@@ -6,8 +6,8 @@
qt_internal_add_qml_module(qmlfolderlistmodelplugin
URI "Qt.labs.folderlistmodel"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QmlFolderListModelPlugin
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QmlFolderListModelPlugin
SKIP_TYPE_REGISTRATION
PLUGIN_OPTIONAL
SOURCES
diff --git a/src/imports/labsanimation/CMakeLists.txt b/src/imports/labsanimation/CMakeLists.txt
index cdf50468ac..50c6bb7912 100644
--- a/src/imports/labsanimation/CMakeLists.txt
+++ b/src/imports/labsanimation/CMakeLists.txt
@@ -6,8 +6,8 @@
qt_internal_add_qml_module(labsanimationplugin
URI "Qt.labs.animation"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QtLabsAnimationPlugin
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QtLabsAnimationPlugin
SKIP_TYPE_REGISTRATION
PLUGIN_OPTIONAL
SOURCES
diff --git a/src/imports/labsmodels/CMakeLists.txt b/src/imports/labsmodels/CMakeLists.txt
index 0c59a15a20..0d3c118e77 100644
--- a/src/imports/labsmodels/CMakeLists.txt
+++ b/src/imports/labsmodels/CMakeLists.txt
@@ -6,8 +6,8 @@
qt_internal_add_qml_module(labsmodelsplugin
URI "Qt.labs.qmlmodels"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QtQmlLabsModelsPlugin
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QtQmlLabsModelsPlugin
SKIP_TYPE_REGISTRATION
PLUGIN_OPTIONAL
SOURCES
diff --git a/src/imports/layouts/CMakeLists.txt b/src/imports/layouts/CMakeLists.txt
index 6cfb911ba9..ef454d03ef 100644
--- a/src/imports/layouts/CMakeLists.txt
+++ b/src/imports/layouts/CMakeLists.txt
@@ -7,9 +7,9 @@
qt_internal_add_qml_module(qquicklayoutsplugin
URI "QtQuick.Layouts"
- VERSION "${CMAKE_PROJECT_VERSION}"
+ VERSION "${PROJECT_VERSION}"
DESIGNER_SUPPORTED
- CLASSNAME QtQuickLayoutsPlugin
+ CLASS_NAME QtQuickLayoutsPlugin
SKIP_TYPE_REGISTRATION
DEPENDENCIES
QtQuick
diff --git a/src/imports/localstorage/CMakeLists.txt b/src/imports/localstorage/CMakeLists.txt
index 9d7cd13fe0..488470c1c4 100644
--- a/src/imports/localstorage/CMakeLists.txt
+++ b/src/imports/localstorage/CMakeLists.txt
@@ -6,8 +6,8 @@
qt_internal_add_qml_module(qmllocalstorageplugin
URI "QtQuick.LocalStorage"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QQmlLocalStoragePlugin
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QQmlLocalStoragePlugin
SKIP_TYPE_REGISTRATION
PLUGIN_OPTIONAL
SOURCES
diff --git a/src/imports/models/CMakeLists.txt b/src/imports/models/CMakeLists.txt
index 4070ad365b..88de431dc0 100644
--- a/src/imports/models/CMakeLists.txt
+++ b/src/imports/models/CMakeLists.txt
@@ -6,9 +6,9 @@
qt_internal_add_qml_module(modelsplugin
URI "QtQml.Models"
- VERSION "${CMAKE_PROJECT_VERSION}"
+ VERSION "${PROJECT_VERSION}"
DESIGNER_SUPPORTED
- CLASSNAME QtQmlModelsPlugin
+ CLASS_NAME QtQmlModelsPlugin
SKIP_TYPE_REGISTRATION
PLUGIN_OPTIONAL
SOURCES
diff --git a/src/imports/particles/CMakeLists.txt b/src/imports/particles/CMakeLists.txt
index 7e754a2cee..4df5512973 100644
--- a/src/imports/particles/CMakeLists.txt
+++ b/src/imports/particles/CMakeLists.txt
@@ -6,9 +6,10 @@
qt_internal_add_qml_module(particlesplugin
URI "QtQuick.Particles"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QtQuick2ParticlesPlugin
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QtQuick2ParticlesPlugin
SKIP_TYPE_REGISTRATION
+ PLUGIN_OPTIONAL
SOURCES
plugin.cpp
PUBLIC_LIBRARIES
diff --git a/src/imports/particles/plugin.cpp b/src/imports/particles/plugin.cpp
index 6629a660af..04e30b38d3 100644
--- a/src/imports/particles/plugin.cpp
+++ b/src/imports/particles/plugin.cpp
@@ -40,27 +40,21 @@
#include <QtQml/qqmlextensionplugin.h>
#include <QtQml/qqml.h>
-#include <private/qquickparticlesmodule_p.h>
+#include <private/qtquickparticlesglobal_p.h>
QT_BEGIN_NAMESPACE
//![class decl]
-class QtQuick2ParticlesPlugin : public QQmlExtensionPlugin
+class QtQuick2ParticlesPlugin : public QQmlEngineExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+ Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
public:
- QtQuick2ParticlesPlugin(QObject *parent = nullptr) : QQmlExtensionPlugin(parent)
+ QtQuick2ParticlesPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent)
{
volatile auto registration = &qml_register_types_QtQuick_Particles;
Q_UNUSED(registration);
}
-
- void registerTypes(const char *uri) override
- {
- Q_UNUSED(uri);
- QQuickParticlesModule::defineModule();
- }
};
//![class decl]
diff --git a/src/imports/qtqml/CMakeLists.txt b/src/imports/qtqml/CMakeLists.txt
index 15e66fd53e..761417143a 100644
--- a/src/imports/qtqml/CMakeLists.txt
+++ b/src/imports/qtqml/CMakeLists.txt
@@ -16,9 +16,9 @@ endif()
qt_internal_add_qml_module(qmlplugin
URI "QtQml"
- VERSION "${CMAKE_PROJECT_VERSION}"
+ VERSION "${PROJECT_VERSION}"
DESIGNER_SUPPORTED
- CLASSNAME QtQmlPlugin
+ CLASS_NAME QtQmlPlugin
SKIP_TYPE_REGISTRATION
IMPORTS ${module_dynamic_qml_imports}
PLUGIN_OPTIONAL
diff --git a/src/imports/qtquick2/CMakeLists.txt b/src/imports/qtquick2/CMakeLists.txt
index e7e29bf9ae..00b80b6ee5 100644
--- a/src/imports/qtquick2/CMakeLists.txt
+++ b/src/imports/qtquick2/CMakeLists.txt
@@ -6,9 +6,9 @@
qt_internal_add_qml_module(qtquick2plugin
URI "QtQuick"
- VERSION "${CMAKE_PROJECT_VERSION}"
+ VERSION "${PROJECT_VERSION}"
DESIGNER_SUPPORTED
- CLASSNAME QtQuick2Plugin
+ CLASS_NAME QtQuick2Plugin
SKIP_TYPE_REGISTRATION
IMPORTS
QtQml/auto
diff --git a/src/imports/settings/CMakeLists.txt b/src/imports/settings/CMakeLists.txt
index f49e741106..052a576639 100644
--- a/src/imports/settings/CMakeLists.txt
+++ b/src/imports/settings/CMakeLists.txt
@@ -6,8 +6,8 @@
qt_internal_add_qml_module(qmlsettingsplugin
URI "Qt.labs.settings"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QmlSettingsPlugin
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QmlSettingsPlugin
SKIP_TYPE_REGISTRATION
PLUGIN_OPTIONAL
SOURCES
diff --git a/src/imports/shapes/CMakeLists.txt b/src/imports/shapes/CMakeLists.txt
index fa1eb9297c..a48a717c1b 100644
--- a/src/imports/shapes/CMakeLists.txt
+++ b/src/imports/shapes/CMakeLists.txt
@@ -6,8 +6,8 @@
qt_internal_add_qml_module(qmlshapesplugin
URI "QtQuick.Shapes"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QmlShapesPlugin
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QmlShapesPlugin
SKIP_TYPE_REGISTRATION
DEPENDENCIES
QtQuick
diff --git a/src/imports/sharedimage/CMakeLists.txt b/src/imports/sharedimage/CMakeLists.txt
index b0faea295f..32e1b43777 100644
--- a/src/imports/sharedimage/CMakeLists.txt
+++ b/src/imports/sharedimage/CMakeLists.txt
@@ -6,8 +6,8 @@
qt_internal_add_qml_module(sharedimageplugin
URI "Qt.labs.sharedimage"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QtQuickSharedImagePlugin
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QtQuickSharedImagePlugin
SKIP_TYPE_REGISTRATION
SOURCES
plugin.cpp
diff --git a/src/imports/testlib/CMakeLists.txt b/src/imports/testlib/CMakeLists.txt
index 1e199b947b..fe70dd8a29 100644
--- a/src/imports/testlib/CMakeLists.txt
+++ b/src/imports/testlib/CMakeLists.txt
@@ -6,11 +6,10 @@
qt_internal_add_qml_module(qmltestplugin
URI "QtTest"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QTestQmlModule
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QTestQmlModule
DEPENDENCIES
QtQuick.Window/2.0
- PLUGIN_OPTIONAL
SOURCES
main.cpp
PUBLIC_LIBRARIES
diff --git a/src/imports/tooling/CMakeLists.txt b/src/imports/tooling/CMakeLists.txt
index c36c8c1474..48a0a19795 100644
--- a/src/imports/tooling/CMakeLists.txt
+++ b/src/imports/tooling/CMakeLists.txt
@@ -14,7 +14,7 @@ set(qml_files
qt_internal_add_qml_module(quicktooling
URI "QtQuick.tooling"
- VERSION "${CMAKE_PROJECT_VERSION}"
+ VERSION "${PROJECT_VERSION}"
GENERATE_QMLTYPES
INSTALL_QMLTYPES
PAST_MAJOR_VERSIONS 1
diff --git a/src/imports/tooling/Method.qml b/src/imports/tooling/Method.qml
index f867a4eb27..3b019c4549 100644
--- a/src/imports/tooling/Method.qml
+++ b/src/imports/tooling/Method.qml
@@ -43,4 +43,5 @@ Member {
default property list<Parameter> parameters
property string type
property int revision: 0
+ property bool isConstructor: false
}
diff --git a/src/imports/tooling/Property.qml b/src/imports/tooling/Property.qml
index de76df55b3..8c2479eef2 100644
--- a/src/imports/tooling/Property.qml
+++ b/src/imports/tooling/Property.qml
@@ -43,6 +43,7 @@ Member {
required property string type
property bool isPointer: false
property bool isReadonly: false
+ property bool isRequired: false
property bool isList: false
property int revision: 0
property string bindable
diff --git a/src/imports/wavefrontmesh/CMakeLists.txt b/src/imports/wavefrontmesh/CMakeLists.txt
index 7dd97c8056..b9ef95f16a 100644
--- a/src/imports/wavefrontmesh/CMakeLists.txt
+++ b/src/imports/wavefrontmesh/CMakeLists.txt
@@ -6,8 +6,8 @@
qt_internal_add_qml_module(qmlwavefrontmeshplugin
URI "Qt.labs.wavefrontmesh"
- VERSION "${CMAKE_PROJECT_VERSION}"
- CLASSNAME QmlWavefrontMeshPlugin
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QmlWavefrontMeshPlugin
SKIP_TYPE_REGISTRATION
SOURCES
plugin.cpp
diff --git a/src/imports/window/CMakeLists.txt b/src/imports/window/CMakeLists.txt
index 1f02b1a380..4a6015f8f4 100644
--- a/src/imports/window/CMakeLists.txt
+++ b/src/imports/window/CMakeLists.txt
@@ -2,7 +2,7 @@
qt_internal_add_qml_module(quickwindow
URI "QtQuick.Window"
- VERSION "${CMAKE_PROJECT_VERSION}"
+ VERSION "${PROJECT_VERSION}"
IMPORTS
QtQuick/auto
PAST_MAJOR_VERSIONS 2
diff --git a/src/imports/workerscript/CMakeLists.txt b/src/imports/workerscript/CMakeLists.txt
index b2a6d0f444..004d8f781e 100644
--- a/src/imports/workerscript/CMakeLists.txt
+++ b/src/imports/workerscript/CMakeLists.txt
@@ -6,9 +6,9 @@
qt_internal_add_qml_module(workerscriptplugin
URI "QtQml.WorkerScript"
- VERSION "${CMAKE_PROJECT_VERSION}"
+ VERSION "${PROJECT_VERSION}"
DESIGNER_SUPPORTED
- CLASSNAME QtQmlWorkerScriptPlugin
+ CLASS_NAME QtQmlWorkerScriptPlugin
SKIP_TYPE_REGISTRATION
PLUGIN_OPTIONAL
SOURCES
diff --git a/src/imports/xmllistmodel/CMakeLists.txt b/src/imports/xmllistmodel/CMakeLists.txt
new file mode 100644
index 0000000000..1f9fb50dfa
--- /dev/null
+++ b/src/imports/xmllistmodel/CMakeLists.txt
@@ -0,0 +1,15 @@
+qt_internal_add_qml_module(qmlxmllistmodelplugin
+ URI "QtQml.XmlListModel"
+ VERSION "${PROJECT_VERSION}"
+ CLASS_NAME QtQmlXmlListModelPlugin
+ SKIP_TYPE_REGISTRATION
+ DEPENDENCIES
+ QtQml
+ PLUGIN_OPTIONAL
+ SOURCES
+ plugin.cpp
+ PUBLIC_LIBRARIES
+ Qt::Core
+ Qt::Qml
+ Qt::QmlXmlListModelPrivate
+)
diff --git a/src/imports/xmllistmodel/plugin.cpp b/src/imports/xmllistmodel/plugin.cpp
new file mode 100644
index 0000000000..d4ddcd317d
--- /dev/null
+++ b/src/imports/xmllistmodel/plugin.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts 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 <QtQml/qqmlextensionplugin.h>
+#include <QtQmlXmlListModel/private/qtqmlxmllistmodelglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QtQmlXmlListModelPlugin : public QQmlEngineExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlEngineExtensionInterface_iid)
+public:
+ QtQmlXmlListModelPlugin(QObject *parent = nullptr) : QQmlEngineExtensionPlugin(parent)
+ {
+ volatile auto registration = &qml_register_types_QtQml_XmlListModel;
+ Q_UNUSED(registration)
+ }
+};
+
+QT_END_NAMESPACE
+
+#include "plugin.moc"
diff --git a/src/labs/CMakeLists.txt b/src/labs/CMakeLists.txt
index 9a984ccfb9..6ca0d7a695 100644
--- a/src/labs/CMakeLists.txt
+++ b/src/labs/CMakeLists.txt
@@ -1,4 +1,7 @@
-add_subdirectory(settings)
+if(QT_FEATURE_settings)
+ add_subdirectory(settings)
+endif()
+
add_subdirectory(models)
if(QT_FEATURE_qml_itemmodel)
diff --git a/src/labs/animation/CMakeLists.txt b/src/labs/animation/CMakeLists.txt
index 77b8ab7fec..6c1cdcae14 100644
--- a/src/labs/animation/CMakeLists.txt
+++ b/src/labs/animation/CMakeLists.txt
@@ -12,7 +12,7 @@ qt_internal_add_module(LabsAnimation
set_target_properties(LabsAnimation PROPERTIES
QT_QML_MODULE_INSTALL_QMLTYPES TRUE
- QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_VERSION ${PROJECT_VERSION}
QT_QML_MODULE_URI Qt.labs.animation
QT_QMLTYPES_FILENAME plugins.qmltypes
QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/Qt/labs/animation"
diff --git a/src/labs/animation/qquickboundaryrule.cpp b/src/labs/animation/qquickboundaryrule.cpp
index 3083dd26d2..61e5d007d5 100644
--- a/src/labs/animation/qquickboundaryrule.cpp
+++ b/src/labs/animation/qquickboundaryrule.cpp
@@ -483,7 +483,6 @@ void QQuickBoundaryRule::write(const QVariant &value)
return;
}
- qmlExecuteDeferred(this);
d->targetValue = d->easedOvershoot(rValue);
QQmlPropertyPrivate::write(d->property, d->targetValue,
QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding);
diff --git a/src/labs/folderlistmodel/CMakeLists.txt b/src/labs/folderlistmodel/CMakeLists.txt
index 7f087a0a6e..6994bbf658 100644
--- a/src/labs/folderlistmodel/CMakeLists.txt
+++ b/src/labs/folderlistmodel/CMakeLists.txt
@@ -14,7 +14,7 @@ qt_internal_add_module(LabsFolderListModel
set_target_properties(LabsFolderListModel PROPERTIES
QT_QML_MODULE_INSTALL_QMLTYPES TRUE
- QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_VERSION ${PROJECT_VERSION}
QT_QML_MODULE_URI Qt.labs.folderlistmodel
QT_QMLTYPES_FILENAME plugins.qmltypes
QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/Qt/labs/folderlistmodel"
diff --git a/src/labs/models/CMakeLists.txt b/src/labs/models/CMakeLists.txt
index bfd7109bca..774513d8c6 100644
--- a/src/labs/models/CMakeLists.txt
+++ b/src/labs/models/CMakeLists.txt
@@ -22,7 +22,7 @@ qt_internal_extend_target(LabsQmlModels CONDITION QT_FEATURE_qml_delegate_model
set_target_properties(LabsQmlModels PROPERTIES
QT_QML_MODULE_INSTALL_QMLTYPES TRUE
- QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_VERSION ${PROJECT_VERSION}
QT_QML_MODULE_URI Qt.labs.qmlmodels
QT_QMLTYPES_FILENAME plugins.qmltypes
QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/Qt/labs/qmlmodels"
diff --git a/src/labs/models/qqmldelegatecomponent.cpp b/src/labs/models/qqmldelegatecomponent.cpp
index c920d7c294..f7b778e574 100644
--- a/src/labs/models/qqmldelegatecomponent.cpp
+++ b/src/labs/models/qqmldelegatecomponent.cpp
@@ -231,7 +231,7 @@ void QQmlDelegateChooser::setRole(const QString &role)
/*!
\qmlproperty list<DelegateChoice> QtQml.Models::DelegateChooser::choices
- \default
+ \qmldefault
The list of DelegateChoices for the chooser.
diff --git a/src/labs/settings/CMakeLists.txt b/src/labs/settings/CMakeLists.txt
index 23b5018dd5..4dc99ea7d8 100644
--- a/src/labs/settings/CMakeLists.txt
+++ b/src/labs/settings/CMakeLists.txt
@@ -12,7 +12,7 @@ qt_internal_add_module(LabsSettings
set_target_properties(LabsSettings PROPERTIES
QT_QML_MODULE_INSTALL_QMLTYPES TRUE
- QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_VERSION ${PROJECT_VERSION}
QT_QML_MODULE_URI Qt.labs.settings
QT_QMLTYPES_FILENAME plugins.qmltypes
QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/Qt/labs/settings"
diff --git a/src/labs/settings/qqmlsettings.cpp b/src/labs/settings/qqmlsettings.cpp
index bf1ad021a7..f1ba7eb0b1 100644
--- a/src/labs/settings/qqmlsettings.cpp
+++ b/src/labs/settings/qqmlsettings.cpp
@@ -388,7 +388,7 @@ QVariant QQmlSettingsPrivate::readProperty(const QMetaProperty &property) const
{
Q_Q(const QQmlSettings);
QVariant var = property.read(q);
- if (var.userType() == qMetaTypeId<QJSValue>())
+ if (var.metaType() == QMetaType::fromType<QJSValue>())
var = var.value<QJSValue>().toVariant();
return var;
}
diff --git a/src/labs/sharedimage/CMakeLists.txt b/src/labs/sharedimage/CMakeLists.txt
index 217f688599..a360fc1002 100644
--- a/src/labs/sharedimage/CMakeLists.txt
+++ b/src/labs/sharedimage/CMakeLists.txt
@@ -15,7 +15,7 @@ qt_internal_add_module(LabsSharedImage
set_target_properties(LabsSharedImage PROPERTIES
QT_QML_MODULE_INSTALL_QMLTYPES TRUE
- QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_VERSION ${PROJECT_VERSION}
QT_QML_MODULE_URI Qt.labs.sharedimage
QT_QMLTYPES_FILENAME plugins.qmltypes
QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/Qt/labs/sharedimage"
diff --git a/src/labs/wavefrontmesh/CMakeLists.txt b/src/labs/wavefrontmesh/CMakeLists.txt
index bdd4b07b07..df02526af4 100644
--- a/src/labs/wavefrontmesh/CMakeLists.txt
+++ b/src/labs/wavefrontmesh/CMakeLists.txt
@@ -14,7 +14,7 @@ qt_internal_add_module(LabsWavefrontMesh
set_target_properties(LabsWavefrontMesh PROPERTIES
QT_QML_MODULE_INSTALL_QMLTYPES TRUE
- QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_VERSION ${PROJECT_VERSION}
QT_QML_MODULE_URI Qt.labs.wavefrontmesh
QT_QMLTYPES_FILENAME plugins.qmltypes
QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/Qt/labs/wavefrontmesh"
diff --git a/src/particles/CMakeLists.txt b/src/particles/CMakeLists.txt
index 538e1e5bae..830b86b4e6 100644
--- a/src/particles/CMakeLists.txt
+++ b/src/particles/CMakeLists.txt
@@ -27,7 +27,6 @@ qt_internal_add_module(QuickParticles
qquickparticleflatset_p.h
qquickparticlegroup.cpp qquickparticlegroup_p.h
qquickparticlepainter.cpp qquickparticlepainter_p.h
- qquickparticlesmodule.cpp qquickparticlesmodule_p.h
qquickparticlesystem.cpp qquickparticlesystem_p.h
qquickpointattractor.cpp qquickpointattractor_p.h
qquickpointdirection.cpp qquickpointdirection_p.h
@@ -115,7 +114,7 @@ qt_internal_extend_target(QuickParticles CONDITION EXISTS "qqml_enable_gcov"
set_target_properties(QuickParticles PROPERTIES
QT_QML_MODULE_INSTALL_QMLTYPES TRUE
- QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_VERSION ${PROJECT_VERSION}
QT_QML_MODULE_URI QtQuick.Particles
QT_QMLTYPES_FILENAME plugins.qmltypes
QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/QtQuick/Particles"
diff --git a/src/particles/qquickmaskextruder.cpp b/src/particles/qquickmaskextruder.cpp
index f1726a51d4..61f9092f0a 100644
--- a/src/particles/qquickmaskextruder.cpp
+++ b/src/particles/qquickmaskextruder.cpp
@@ -107,7 +107,7 @@ QPointF QQuickMaskExtruder::extrude(const QRectF &r)
ensureInitialized(r);
if (!m_mask.count() || m_img.isNull())
return r.topLeft();
- const QPointF p = m_mask[QRandomGenerator::global()->bounded(int(m_mask.count()))];
+ const QPointF p = m_mask[QRandomGenerator::global()->bounded(m_mask.count())];
//### Should random sub-pixel positioning be added?
return p + r.topLeft();
}
diff --git a/src/particles/qquickturbulence_p.h b/src/particles/qquickturbulence_p.h
index a4aef063de..c7a31bb8ae 100644
--- a/src/particles/qquickturbulence_p.h
+++ b/src/particles/qquickturbulence_p.h
@@ -83,7 +83,7 @@ Q_SIGNALS:
void strengthChanged(qreal arg);
- void noiseSourceChanged(QUrl arg);
+ void noiseSourceChanged(const QUrl &arg);
public Q_SLOTS:
@@ -95,7 +95,7 @@ public Q_SLOTS:
}
}
- void setNoiseSource(QUrl arg)
+ void setNoiseSource(const QUrl &arg)
{
if (m_noiseSource != arg) {
m_noiseSource = arg;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
index 962245fa4c..812c48b72e 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp
@@ -198,7 +198,7 @@ QQmlEngineDebugServiceImpl::propertyData(QObject *obj, int propIdx)
if (prop.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
rv.type = QQmlObjectProperty::Object;
- } else if (QQmlMetaType::isList(prop.userType())) {
+ } else if (QQmlMetaType::isList(prop.metaType())) {
rv.type = QQmlObjectProperty::List;
} else if (prop.userType() == QMetaType::QVariant) {
rv.type = QQmlObjectProperty::Variant;
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
index d3134e0727..d6be7eb5db 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp
@@ -61,7 +61,7 @@ QV4::CppStackFrame *QV4DataCollector::findFrame(int frame)
QV4::CppStackFrame *f = engine()->currentStackFrame;
while (f && frame) {
--frame;
- f = f->parent;
+ f = f->parentFrame();
}
return f;
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
index f47b9e09ac..bdba780147 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
@@ -230,7 +230,7 @@ void QV4Debugger::leavingFunction(const QV4::ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
if (m_stepping != NotStepping && m_currentFrame == m_engine->currentStackFrame) {
- m_currentFrame = m_currentFrame->parent;
+ m_currentFrame = m_currentFrame->parentFrame();
m_stepping = StepOver;
m_returnedValue.set(m_engine, retVal);
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
index c4faeea7c9..e0c24979a9 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugjob.cpp
@@ -70,7 +70,7 @@ void JavaScriptJob::run()
QV4::CppStackFrame *frame = engine->currentStackFrame;
for (int i = 0; frame && i < frameNr; ++i)
- frame = frame->parent;
+ frame = frame->parentFrame();
if (frameNr > 0 && frame)
ctx = static_cast<QV4::ExecutionContext *>(&frame->jsFrame->context);
diff --git a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
index 473546aba5..85b6bac203 100644
--- a/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_nativedebugger/qqmlnativedebugservice.cpp
@@ -360,7 +360,7 @@ void NativeDebugger::handleBacktrace(QJsonObject *response, const QJsonObject &a
frameArray.push_back(frame);
- f = f->parent;
+ f = f->parentFrame();
}
response->insert(QStringLiteral("frames"), frameArray);
@@ -639,7 +639,7 @@ void NativeDebugger::leavingFunction(const QV4::ReturnedValue &retVal)
return;
if (m_stepping != NotStepping && m_currentFrame == m_engine->currentStackFrame) {
- m_currentFrame = m_currentFrame->parent;
+ m_currentFrame = m_currentFrame->parentFrame();
m_stepping = StepOver;
m_returnedValue.set(m_engine, retVal);
}
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp
index 4da6b71b40..e30ff04443 100644
--- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.cpp
@@ -111,7 +111,7 @@ void QQmlPreviewPosition::takePosition(QWindow *window, InitializeState state)
auto screen = window->screen();
auto nativePosition = QHighDpiScaling::mapPositionToNative(window->framePosition(),
screen->handle());
- m_lastWindowPosition = {screen->name(), nativePosition};
+ m_lastWindowPosition = { screen->name(), nativePosition, window->size() };
m_savePositionTimer.start();
}
@@ -166,11 +166,8 @@ QByteArray QQmlPreviewPosition::fromPositionToByteArray(
const quint16 majorVersion = 1;
const quint16 minorVersion = 0;
- stream << majorVersion
- << minorVersion
- << m_currentInitScreensData
- << position.screenName
- << position.nativePosition;
+ stream << majorVersion << minorVersion << m_currentInitScreensData << position.screenName
+ << position.nativePosition << position.size;
return array;
}
@@ -203,7 +200,11 @@ void QQmlPreviewPosition::readLastPositionFromByteArray(const QByteArray &array)
stream >> nativePosition;
if (nativePosition.isNull())
return;
- m_lastWindowPosition = {nameOfScreen, nativePosition};
+
+ QSize size;
+ stream >> size;
+
+ m_lastWindowPosition = { nameOfScreen, nativePosition, size };
}
void QQmlPreviewPosition::setPosition(const QQmlPreviewPosition::Position &position,
@@ -215,7 +216,8 @@ void QQmlPreviewPosition::setPosition(const QQmlPreviewPosition::Position &posit
window->setScreen(screen);
const auto point = QHighDpiScaling::mapPositionFromNative(position.nativePosition,
screen->handle());
- const QRect geometry(point, window->size());
+
+ const QRect geometry(point, position.size);
if (screen->virtualGeometry().contains(geometry))
window->setFramePosition(point);
else
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h
index 9d84170948..dde6f974d2 100644
--- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h
+++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewposition.h
@@ -76,6 +76,7 @@ public:
public:
QString screenName;
QPoint nativePosition;
+ QSize size;
};
enum InitializeState {
InitializePosition,
diff --git a/src/qml/.prev_configure.cmake b/src/qml/.prev_configure.cmake
index 3cf4826bbb..07dafd5d6f 100644
--- a/src/qml/.prev_configure.cmake
+++ b/src/qml/.prev_configure.cmake
@@ -14,12 +14,10 @@
qt_config_compile_test(cxx14_make_unique
LABEL "C++14 make_unique()"
CODE
-"
-#include <memory>
+"#include <memory>
-int main(int argc, char **argv)
+int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
std::unique_ptr<int> ptr = std::make_unique<int>();
/* END TEST: */
@@ -31,12 +29,8 @@ std::unique_ptr<int> ptr = std::make_unique<int>();
qt_config_compile_test(pointer_32bit
LABEL "32bit pointers"
CODE
-"
-
-
-int main(int argc, char **argv)
+"int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
static_assert(sizeof(void *) == 4, \"fail\");
/* END TEST: */
@@ -48,12 +42,8 @@ static_assert(sizeof(void *) == 4, \"fail\");
qt_config_compile_test(pointer_64bit
LABEL "64bit pointers"
CODE
-"
-
-
-int main(int argc, char **argv)
+"int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
static_assert(sizeof(void *) == 8, \"fail\");
/* END TEST: */
@@ -65,12 +55,8 @@ static_assert(sizeof(void *) == 8, \"fail\");
qt_config_compile_test(arm_thumb
LABEL "THUMB mode on ARM"
CODE
-"
-
-
-int main(int argc, char **argv)
+"int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
#if defined(thumb2) || defined(__thumb2__)
# define THUMB_OK
@@ -91,12 +77,8 @@ int main(int argc, char **argv)
qt_config_compile_test(arm_fp
LABEL "Sufficiently recent FPU on ARM"
CODE
-"
-
-
-int main(int argc, char **argv)
+"int main(void)
{
- (void)argc; (void)argv;
/* BEGIN TEST: */
// if !defined(__ARM_FP) we might be on MSVC or we might have a device
// without an FPU.
@@ -187,6 +169,12 @@ qt_feature("qml-itemmodel" PRIVATE
PURPOSE "Provides the item model for item views in QML"
CONDITION QT_FEATURE_itemmodel
)
+qt_feature("qml-xmllistmodel" PRIVATE
+ SECTION "QML"
+ LABEL "QML XmlListModel"
+ PURPOSE "Enable XmlListModel in QML"
+ CONDITION QT_FEATURE_qml_itemmodel AND QT_FEATURE_future
+)
qt_feature("qml-python" PRIVATE
LABEL "python"
CONDITION tests.qml-python OR FIXME
diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt
index 0d87869d00..52f95d9e30 100644
--- a/src/qml/CMakeLists.txt
+++ b/src/qml/CMakeLists.txt
@@ -86,7 +86,6 @@ qt_internal_add_module(Qml
../3rdparty/masm/yarr/YarrSyntaxChecker.cpp ../3rdparty/masm/yarr/YarrSyntaxChecker.h
../3rdparty/masm/yarr/YarrUnicodeProperties.h
common/qjsnumbercoercion.cpp common/qjsnumbercoercion.h
- common/qqmlapiversion_p.h
common/qqmljsdiagnosticmessage_p.h
common/qqmljsfixedpoolarray_p.h
common/qqmljsmemorypool_p.h
@@ -220,6 +219,7 @@ qt_internal_add_module(Qml
qml/ftw/qrecursionwatcher_p.h
qml/ftw/qrecyclepool_p.h
qml/ftw/qstringhash_p.h
+ qml/qqmlregistration.h
qml/qqml.cpp qml/qqml.h
qml/qqmlabstractbinding.cpp qml/qqmlabstractbinding_p.h
qml/qqmlabstracturlinterceptor.cpp qml/qqmlabstracturlinterceptor.h
@@ -652,7 +652,7 @@ qt_internal_add_docs(Qml
set_target_properties(Qml PROPERTIES
QT_QML_MODULE_INSTALL_QMLTYPES TRUE
- QT_QML_MODULE_VERSION ${CMAKE_PROJECT_VERSION}
+ QT_QML_MODULE_VERSION ${PROJECT_VERSION}
QT_QML_MODULE_URI QtQml
QT_QMLTYPES_FILENAME plugins.qmltypes
QT_QML_MODULE_INSTALL_DIR "${INSTALL_QMLDIR}/QtQml"
diff --git a/src/qml/Qt6QmlBuildInternals.cmake b/src/qml/Qt6QmlBuildInternals.cmake
index c2d8259bc0..ef2c1c4ac6 100644
--- a/src/qml/Qt6QmlBuildInternals.cmake
+++ b/src/qml/Qt6QmlBuildInternals.cmake
@@ -4,27 +4,43 @@
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 plugins.qmltypes file.
+# This function is essentially a convenience wrapper around a pair of calls
+# to qt_internal_add_plugin() and qt6_add_qml_module(). It ensures a consistent
+# set of arguments are used for both. Most keywords for either command are
+# supported, with a few exceptions:
#
-# 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
-# SKIP_TYPE_REGISTRATION: All qml files are expected to be registered by the
-# c++ plugin code.
-# PLUGIN_OPTIONAL: Any plugins are optional
+# - RESOURCE_PREFIX and RESOURCE_EXPORT are both hard-coded and cannot be
+# overridden by the caller.
+# - OUTPUT_DIRECTORY and INSTALL_DIRECTORY will be set if not provided.
+# - SOURCES is only passed through to qt_internal_add_plugin() but not to
+# qt6_add_qml_module(). If SOURCES is not set, PURE_MODULE will be passed to
+# qt6_add_qml_module() so that a dummy plugin.cpp file will be generated.
#
+# See qt_internal_add_plugin() and qt6_add_qml_module() for the full set of
+# supported keywords.
function(qt_internal_add_qml_module target)
- set(qml_module_optional_args
+ _qt_internal_get_add_plugin_keywords(
+ public_option_args
+ public_single_args
+ public_multi_args
+ )
+ qt_internal_get_internal_add_plugin_keywords(
+ internal_option_args
+ internal_single_args
+ internal_multi_args
+ )
+
+ # We don't want to pass CLASS_NAME to qt_internal_add_plugin(), we will
+ # pass it to qt6_add_qml_module() to handle instead. qt_internal_add_plugin()
+ # would just ignore it anyway because we set TYPE to qml_plugin, but we have
+ # to remove it to prevent duplicates in argument parsing.
+ list(REMOVE_ITEM public_single_args CLASS_NAME)
+
+ set(qml_module_option_args
GENERATE_QMLTYPES
INSTALL_QMLTYPES
DESIGNER_SUPPORTED
- DO_NOT_INSTALL
SKIP_TYPE_REGISTRATION
PLUGIN_OPTIONAL
)
@@ -33,86 +49,94 @@ function(qt_internal_add_qml_module target)
URI
TARGET_PATH
VERSION
- CLASSNAME
+ TYPEINFO
+ CLASS_NAME
+ CLASSNAME # TODO: Remove once all other repos have been updated to use
+ # CLASS_NAME instead.
)
set(qml_module_multi_args
+ QML_FILES
IMPORTS
OPTIONAL_IMPORTS
- TYPEINFO
DEPENDENCIES
PAST_MAJOR_VERSIONS
)
- 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})
+ set(option_args
+ ${public_option_args}
+ ${internal_option_args}
+ ${qml_module_option_args}
+ )
+ set(single_args
+ ${public_single_args}
+ ${internal_single_args}
+ ${qml_module_single_args}
+ )
+ set(multi_args
+ ${public_multi_args}
+ ${internal_multi_args}
+ ${qml_module_multi_args}
+ )
- 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()
+ qt_parse_all_arguments(arg "qt_internal_add_qml_module"
+ "${option_args}"
+ "${single_args}"
+ "${multi_args}"
+ ${ARGN}
+ )
if (NOT arg_TARGET_PATH)
string(REPLACE "." "/" arg_TARGET_PATH ${arg_URI})
endif()
+ if (NOT arg_OUTPUT_DIRECTORY)
+ set(arg_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_QMLDIR}/${arg_TARGET_PATH}")
+ endif()
+ if (NOT arg_INSTALL_DIRECTORY)
+ set(arg_INSTALL_DIRECTORY "${INSTALL_QMLDIR}/${arg_TARGET_PATH}")
+ endif()
qt_remove_args(plugin_args
ARGS_TO_REMOVE
- ${target}
- ${qml_module_optional_args}
+ ${qml_module_option_args}
${qml_module_single_args}
${qml_module_multi_args}
+ OUTPUT_DIRECTORY
+ INSTALL_DIRECTORY
ALL_ARGS
- ${__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}
+ ${option_args}
+ ${single_args}
+ ${multi_args}
ARGS
- ${ARGV}
+ ${ARGN}
)
qt_internal_add_plugin(${target}
- TYPE
- qml_plugin
- QML_TARGET_PATH
- "${arg_TARGET_PATH}"
+ TYPE qml_plugin
+ OUTPUT_DIRECTORY ${arg_OUTPUT_DIRECTORY}
+ INSTALL_DIRECTORY ${arg_INSTALL_DIRECTORY}
${plugin_args}
)
- set(no_create_option DO_NOT_CREATE_TARGET)
-
- 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)
+ if (arg_SOURCES AND NOT arg_TYPEINFO)
+ set(arg_TYPEINFO "plugins.qmltypes")
endif()
- if (arg_PLUGIN_OPTIONAL)
- set(plugin_optional_arg PLUGIN_OPTIONAL)
- endif()
+ set(add_qml_module_args DO_NOT_CREATE_TARGET)
- if (arg_GENERATE_QMLTYPES)
- set(generate_qmltypes_arg GENERATE_QMLTYPES)
- endif()
+ # Pass through options if given (these are present/absent, not true/false)
+ foreach(opt IN LISTS qml_module_option_args)
+ if(arg_${opt})
+ list(APPEND add_qml_module_args ${opt})
+ endif()
+ endforeach()
- if (arg_INSTALL_QMLTYPES)
- set(install_qmltypes_arg INSTALL_QMLTYPES)
- endif()
+ # Pass through single and multi-value args as provided
+ foreach(arg IN LISTS qml_module_single_args qml_module_multi_args)
+ if(DEFINED arg_${arg})
+ list(APPEND add_qml_module_args ${arg} ${arg_${arg}})
+ endif()
+ endforeach()
# Because qt_internal_add_qml_module does not propagate its SOURCES option to
@@ -120,72 +144,16 @@ function(qt_internal_add_qml_module target)
# qt6_add_qml_module if it should generate a dummy plugin cpp file. Otherwise we'd generate
# a dummy plugin.cpp file twice and thus cause duplicate symbol issues.
if (NOT arg_SOURCES)
- set(pure_qml_module "PURE_MODULE")
- endif()
-
- qt_path_join(qml_module_install_dir ${QT_INSTALL_DIR} "${INSTALL_QMLDIR}/${arg_TARGET_PATH}")
-
- if (arg_SOURCES AND NOT arg_TYPEINFO)
- set(arg_TYPEINFO "plugins.qmltypes")
+ list(APPEND add_qml_module_args PURE_MODULE)
endif()
qt6_add_qml_module(${target}
- ${designer_supported_arg}
- ${no_create_option}
- ${skip_registration_arg}
- ${plugin_optional_arg}
- ${classname_arg}
- ${generate_qmltypes_arg}
- ${install_qmltypes_arg}
- ${pure_qml_module}
+ ${add_qml_module_args}
+ OUTPUT_DIRECTORY ${arg_OUTPUT_DIRECTORY}
+ INSTALL_DIRECTORY ${arg_INSTALL_DIRECTORY}
RESOURCE_PREFIX "/qt-project.org/imports"
- TARGET_PATH ${arg_TARGET_PATH}
- URI ${arg_URI}
- VERSION ${arg_VERSION}
- PAST_MAJOR_VERSIONS ${arg_PAST_MAJOR_VERSIONS}
- QML_FILES ${arg_QML_FILES}
- IMPORTS "${arg_IMPORTS}"
- OPTIONAL_IMPORTS "${arg_OPTIONAL_IMPORTS}"
- TYPEINFO "${arg_TYPEINFO}"
- DO_NOT_INSTALL_METADATA
- 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()
if(NOT QT_NO_INTERNAL_COMPATIBILITY_FUNCTIONS)
diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake
index 2a22831794..501d76bfe5 100644
--- a/src/qml/Qt6QmlMacros.cmake
+++ b/src/qml/Qt6QmlMacros.cmake
@@ -29,11 +29,7 @@ set(__qt_qml_macros_module_base_dir "${CMAKE_CURRENT_LIST_DIR}")
# ${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_DIRECTORY: Intended installation directory for this module. (OPTIONAL)
#
# SOURCES: List of C++ sources. (OPTIONAL)
#
@@ -46,7 +42,7 @@ set(__qt_qml_macros_module_base_dir "${CMAKE_CURRENT_LIST_DIR}")
# 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
+# CLASS_NAME: 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.
@@ -95,7 +91,6 @@ function(qt6_add_qml_module target)
GENERATE_QMLTYPES
INSTALL_QMLTYPES
DESIGNER_SUPPORTED
- DO_NOT_INSTALL_METADATA
SKIP_TYPE_REGISTRATION
PLUGIN_OPTIONAL
PURE_MODULE
@@ -111,8 +106,9 @@ function(qt6_add_qml_module target)
TARGET_PATH
VERSION
OUTPUT_DIRECTORY
- INSTALL_LOCATION
- CLASSNAME
+ INSTALL_DIRECTORY
+ CLASS_NAME
+ CLASSNAME # For backward compatibility, remove once all repos no longer use it
TYPEINFO
RESOURCE_EXPORT
)
@@ -142,19 +138,24 @@ function(qt6_add_qml_module target)
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]+")
+ if ("${arg_VERSION}" MATCHES "^([0-9]+\\.[0-9]+)\\.[0-9]+$")
+ set(arg_VERSION "${CMAKE_MATCH_1}")
+ 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 C++ sources were directly specified (not via qt_internal_add_qml_module), we assume the
- # user will provide a plugin.cpp file. Don't generate a dummy plugin.cpp file in this case.
- #
- # If no sources were specified or the plugin was marked as a pure QML module, generate a
- # dummy plugin.cpp file.
- if (arg_SOURCES OR NOT arg_PURE_MODULE)
- set(create_pure_qml_module_plugin FALSE)
- else()
- set(create_pure_qml_module_plugin TRUE)
+ # Support for old keyword, remove once all repos no longer use CLASSNAME
+ if(arg_CLASSNAME)
+ if(arg_CLASS_NAME AND NOT arg_CLASSNAME STREQUAL arg_CLASS_NAME)
+ message(FATAL_ERROR
+ "Both CLASSNAME and CLASS_NAME were given and were different. "
+ "Update call site to only use CLASS_NAME."
+ )
+ endif()
+ set(arg_CLASS_NAME "${arg_CLASSNAME}")
+ unset(arg_CLASSNAME)
endif()
if (arg_DO_NOT_CREATE_TARGET AND NOT TARGET "${target}")
@@ -200,8 +201,25 @@ function(qt6_add_qml_module target)
string(REPLACE "." "/" arg_TARGET_PATH ${arg_URI})
endif()
- if(create_pure_qml_module_plugin)
- _qt_internal_create_dummy_qml_plugin("${target}" "${arg_URI}" arg_CLASSNAME)
+ # If C++ sources were directly specified (not via qt_internal_add_qml_module), we assume the
+ # user will provide a plugin.cpp file. Don't generate a dummy plugin.cpp file in this case.
+ #
+ # If no sources were specified, it doesn't necessarily mean this is a pure QML module.
+ # Only if the caller explicitly says it is a pure QML module should we generate a
+ # dummy plugin.cpp file (the caller might be handling sources in another way).
+ if (arg_PURE_MODULE)
+ if (arg_SOURCES)
+ message(FATAL_ERROR "SOURCES cannot be specified with PURE_MODULE")
+ endif()
+ if(arg_CLASS_NAME)
+ message(FATAL_ERROR
+ "CLASS_NAME cannot be specified with PURE_MODULE. "
+ "The class name will be auto-generated."
+ )
+ endif()
+ # Note that this populates arg_CLASS_NAME, since it creates a dummy
+ # class name to match the dummy plugin
+ _qt_internal_create_dummy_qml_plugin("${target}" "${arg_URI}" arg_CLASS_NAME)
endif()
if (ANDROID)
@@ -228,16 +246,9 @@ function(qt6_add_qml_module target)
set(arg_RESOURCE_PREFIX "/org.qt-project/imports")
endif()
- set(should_install "TRUE")
- if (NOT arg_INSTALL_LOCATION)
- message(AUTHOR_WARNING "No Qml install location provided for target ${target}."
- "Consider specifying the INSTALL_LOCATION option.")
- set(should_install "FALSE")
- endif()
-
- if (DEFINED QT_WILL_INSTALL AND NOT QT_WILL_INSTALL
- AND NOT IS_ABSOLUTE "${arg_INSTALL_LOCATION}" AND QT_BUILD_DIR)
- set(arg_INSTALL_LOCATION "${QT_BUILD_DIR}/${arg_INSTALL_LOCATION}")
+ set(should_install TRUE)
+ if (NOT arg_INSTALL_DIRECTORY)
+ set(should_install FALSE)
endif()
set_target_properties(${target}
@@ -246,22 +257,22 @@ function(qt6_add_qml_module target)
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_INSTALL_DIR "${arg_INSTALL_DIRECTORY}"
QT_QML_MODULE_RESOURCE_EXPORT "${arg_RESOURCE_EXPORT}"
)
+ if (arg_OUTPUT_DIRECTORY)
+ set_target_properties(${target}
+ PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}"
+ ARCHIVE_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}"
+ QT_QML_MODULE_OUTPUT_DIR "${arg_OUTPUT_DIRECTORY}"
+ )
+ endif()
- if (NOT DO_NOT_CREATE_TARGET)
- if (arg_OUTPUT_DIRECTORY)
- set_target_properties(${target}
- PROPERTIES
- LIBRARY_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}"
- ARCHIVE_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}"
- )
- elseif (should_install)
- install(TARGETS ${target}
- DESTINATION "${arg_INSTALL_LOCATION}"
- )
- endif()
+ if (NOT DO_NOT_CREATE_TARGET AND should_install)
+ install(TARGETS ${target}
+ DESTINATION "${arg_INSTALL_DIRECTORY}"
+ )
endif()
if (arg_OUTPUT_DIRECTORY)
@@ -305,8 +316,8 @@ function(qt6_add_qml_module target)
string(APPEND qmldir_file_contents "plugin ${target}${QT_LIBINFIX}\n")
endif()
- if (arg_CLASSNAME)
- string(APPEND qmldir_file_contents "classname ${arg_CLASSNAME}\n")
+ if (arg_CLASS_NAME)
+ string(APPEND qmldir_file_contents "classname ${arg_CLASS_NAME}\n")
endif()
if (arg_DESIGNER_SUPPORTED)
string(APPEND qmldir_file_contents "designersupported\n")
@@ -364,6 +375,8 @@ function(qt6_add_qml_module target)
endif()
endforeach()
+ string(APPEND qmldir_file_contents "prefer :${arg_RESOURCE_PREFIX}/${arg_TARGET_PATH}/\n")
+
_qt_internal_qmldir_defer_file(WRITE "${qmldir_file}" "${qmldir_file_contents}")
# Process qml files
@@ -399,30 +412,33 @@ function(qt6_add_qml_module target)
if (resource_targets AND arg_RESOURCE_EXPORT)
install(TARGETS ${resource_targets}
EXPORT "${arg_RESOURCE_EXPORT}"
- DESTINATION "${arg_INSTALL_LOCATION}"
+ DESTINATION "${arg_INSTALL_DIRECTORY}"
)
# When building a static Qt, we need to record information about the compiled resource
# object files to embed them into .prl files.
if(COMMAND qt_internal_record_rcc_object_files)
qt_internal_record_rcc_object_files(
- "${target}" "${resource_targets}" INSTALL_LOCATION "${arg_INSTALL_LOCATION}")
+ "${target}" "${resource_targets}" INSTALL_DIRECTORY "${arg_INSTALL_DIRECTORY}")
endif()
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}
- )
+ endif()
- # Install QMLDIR file
- if (NOT DO_NOT_INSTALL_METADATA AND should_install)
- install(FILES ${qmldir_file}
- DESTINATION "${arg_INSTALL_LOCATION}"
- )
- endif()
+ # Copy QMLDIR file to build directory. We want to do this even for static
+ # builds so that tools and IDEs can read it.
+ add_custom_command(TARGET ${target} POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${qmldir_file}
+ ${target_output_dir}/qmldir
+ BYPRODUCTS
+ ${target_output_dir}/qmldir
+ )
+
+ # Install QMLDIR file
+ if (should_install)
+ install(FILES ${qmldir_file}
+ DESTINATION "${arg_INSTALL_DIRECTORY}"
+ )
endif()
# Install and Copy plugin.qmltypes if exists
@@ -440,41 +456,46 @@ function(qt6_add_qml_module target)
_qt_internal_qmldir_defer_file(APPEND "${qmldir_file}" "typeinfo plugins.qmltypes\n")
- if (NOT arg_DO_NOT_INSTALL_METADATA AND should_install)
+ if (should_install)
install(FILES "${target_plugin_qmltypes}"
- DESTINATION "${arg_INSTALL_LOCATION}"
+ DESTINATION "${arg_INSTALL_DIRECTORY}"
)
endif()
add_custom_command(TARGET ${target} POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
${target_plugin_qmltypes}
- ${target_output_dir}
+ ${target_output_dir}/plugins.qmltypes
+ BYPRODUCTS
+ ${target_output_dir}/plugins.qmltypes
)
endif()
# Copy/Install type info file
if (EXISTS ${arg_TYPEINFO})
- if (NOT arg_DO_NOT_INSTALL_METADATA AND should_install)
+ if (should_install)
install(FILES "${arg_TYPEINFO}"
- DESTINATION "${arg_INSTALL_LOCATION}"
+ DESTINATION "${arg_INSTALL_DIRECTORY}"
)
endif()
+ get_filename_component(filename ${arg_TYPEINFO} NAME)
add_custom_command(TARGET ${target} POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
${arg_TYPEINFO}
- ${target_output_dir}
+ ${target_output_dir}/${filename}
+ BYPRODUCTS
+ ${target_output_dir}/${filename}
)
endif()
if (arg_INSTALL_QMLTYPES)
set_target_properties(${target} PROPERTIES QT_QML_MODULE_INSTALL_QMLTYPES TRUE)
- if (arg_INSTALL_LOCATION)
+ if (arg_INSTALL_DIRECTORY)
get_target_property(qml_module_install_dir ${target} QT_QML_MODULE_INSTALL_DIR)
if (NOT qml_module_install_dir)
set_target_properties(${target}
- PROPERTIES QT_QML_MODULE_INSTALL_DIR "${arg_INSTALL_LOCATION}"
+ PROPERTIES QT_QML_MODULE_INSTALL_DIR "${arg_INSTALL_DIRECTORY}"
)
endif()
endif()
@@ -592,6 +613,7 @@ function(qt6_target_qml_files target)
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)
+ get_target_property(qml_module_output_dir ${target} QT_QML_MODULE_OUTPUT_DIR)
if(NOT qml_module_install_dir)
message(AUTHOR_WARNING
@@ -609,7 +631,7 @@ function(qt6_target_qml_files target)
# object files to embed them into .prl files.
if(COMMAND qt_internal_record_rcc_object_files)
qt_internal_record_rcc_object_files(
- "${target}" "${resource_targets}" INSTALL_LOCATION "${qml_module_install_dir}")
+ "${target}" "${resource_targets}" INSTALL_DIRECTORY "${qml_module_install_dir}")
endif()
endif()
@@ -621,12 +643,11 @@ function(qt6_target_qml_files target)
if (NOT "${qml_file_dir}" STREQUAL "")
set(qml_file_dir "/${qml_file_dir}")
endif()
+ if (qml_module_output_dir)
+ file(COPY "${qml_file}" DESTINATION "${qml_module_output_dir}${qml_file_dir}")
+ endif()
if (qml_module_install_dir)
- if (NOT QT_WILL_INSTALL)
- file(COPY "${qml_file}" DESTINATION "${qml_module_install_dir}${qml_file_dir}")
- else()
- install(FILES "${qml_file}" DESTINATION "${qml_module_install_dir}${qml_file_dir}")
- endif()
+ install(FILES "${qml_file}" DESTINATION "${qml_module_install_dir}${qml_file_dir}")
endif()
if (skip_type_registration AND qml_file MATCHES "\\.qml$")
@@ -653,6 +674,11 @@ function(qt6_target_qml_files target)
get_filename_component(qml_file_typename ${qml_file} NAME_WLE)
endif()
+ # Do not add qmldir entries for lowercase names. Those are not components.
+ if (NOT qml_file_typename MATCHES "^[A-Z]")
+ continue()
+ endif()
+
foreach(qml_file_version IN LISTS qml_file_versions)
if (qml_file_singleton)
string(APPEND file_contents "singleton ")
@@ -777,14 +803,6 @@ function(qt6_qml_type_registration target)
set(foreign_types_file "${target_binary_dir}/qmltypes/${target}_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$>>")
@@ -806,9 +824,22 @@ function(qt6_qml_type_registration target)
message(FATAL_ERROR "Need target metatypes.json file")
endif()
+ cmake_policy(PUSH)
+
set(registration_cpp_file_dep_args)
- if (use_dep_files)
+ if (CMAKE_GENERATOR MATCHES "Ninja") # TODO: Makefiles supported too since CMake 3.20
+ if(POLICY CMP0116)
+ # Without explicitly setting this policy to NEW, we get a warning
+ # even though we ensure there's actually no problem here.
+ # See https://gitlab.kitware.com/cmake/cmake/-/issues/21959
+ cmake_policy(SET CMP0116 NEW)
+ set(relative_to_dir ${CMAKE_CURRENT_BINARY_DIR})
+ else()
+ set(relative_to_dir ${CMAKE_BINARY_DIR})
+ endif()
+ set(dependency_file_cpp "${target_binary_dir}/qmltypes/${type_registration_cpp_file_name}.d")
set(registration_cpp_file_dep_args DEPFILE ${dependency_file_cpp})
+ file(RELATIVE_PATH cpp_file_name "${relative_to_dir}" "${type_registration_cpp_file}")
file(GENERATE OUTPUT "${dependency_file_cpp}"
CONTENT "${cpp_file_name}: $<IF:$<BOOL:${genex_list}>,\\\n$<JOIN:${genex_list}, \\\n>, \\\n>"
)
@@ -843,6 +874,8 @@ function(qt6_qml_type_registration target)
COMMENT "Automatic QML type registration for target ${target}"
)
+ cmake_policy(POP)
+
target_sources(${target} PRIVATE ${type_registration_cpp_file})
# Circumvent "too many sections" error when doing a 32 bit debug build on Windows with
@@ -886,6 +919,8 @@ function(qt6_qml_type_registration target)
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${plugin_types_file}"
"${qml_install_dir}/${qmltypes_output_name}"
+ BYPRODUCTS
+ "${qml_install_dir}/${qmltypes_output_name}"
COMMENT "Copying ${plugin_types_file} to ${qml_install_dir}"
)
endif()
@@ -1146,6 +1181,8 @@ but this file does not exist. Possible reasons include:
# Small macro to avoid duplicating code in two different loops.
macro(_qt6_QmlImportScanner_parse_entry)
+ # TODO: Should CLASSNAME be changed to CLASS_NAME? It is generated by
+ # the qmlimportscanner, not CMake code.
set(entry_name "qml_import_scanner_import_${idx}")
cmake_parse_arguments("entry"
""
@@ -1283,6 +1320,7 @@ function(qt6_target_enable_qmllint target)
get_target_property(import_path ${target} QT_QML_IMPORT_PATH)
get_target_property(files ${target} QML_FILES)
+ set(import_args "")
if(import_path)
foreach(dir IN LISTS import_path)
list(APPEND import_args "-I" "${dir}")
@@ -1291,7 +1329,7 @@ function(qt6_target_enable_qmllint target)
endif()
add_custom_target(${target}_qmllint
- ${QT_CMAKE_EXPORT_NAMESPACE}::qmllint ${files} ${include_args}
+ ${QT_CMAKE_EXPORT_NAMESPACE}::qmllint ${files} ${import_args}
WORKING_DIRECTORY ${target_source}
)
endfunction()
diff --git a/src/qml/common/qqmljsdiagnosticmessage_p.h b/src/qml/common/qqmljsdiagnosticmessage_p.h
index d5b6190c76..6effcbbecd 100644
--- a/src/qml/common/qqmljsdiagnosticmessage_p.h
+++ b/src/qml/common/qqmljsdiagnosticmessage_p.h
@@ -56,7 +56,6 @@
// Include the API version here, to avoid complications when querying it for the
// QQmlSourceLocation -> line/column change.
-#include <private/qqmlapiversion_p.h>
#include "qqmljssourcelocation_p.h"
diff --git a/src/qml/common/qqmljssourcelocation_p.h b/src/qml/common/qqmljssourcelocation_p.h
index ba183f394e..f04e38affd 100644
--- a/src/qml/common/qqmljssourcelocation_p.h
+++ b/src/qml/common/qqmljssourcelocation_p.h
@@ -66,11 +66,41 @@ public:
startLine(line), startColumn(column)
{ }
- bool isValid() const { return length != 0; }
+ bool isValid() const { return *this != SourceLocation(); }
quint32 begin() const { return offset; }
quint32 end() const { return offset + length; }
+ // Returns a zero length location at the start of the current one.
+ SourceLocation startZeroLengthLocation() const
+ {
+ return SourceLocation(offset, 0, startLine, startColumn);
+ }
+ // Returns a zero length location at the end of the current one.
+ SourceLocation endZeroLengthLocation(QStringView text) const
+ {
+ quint32 i = offset;
+ quint32 endLine = startLine;
+ quint32 endColumn = startColumn;
+ while (i < end()) {
+ QChar c = text.at(i);
+ switch (c.unicode()) {
+ case '\n':
+ if (i + 1 < end() && text.at(i + 1) == QLatin1Char('\r'))
+ ++i;
+ Q_FALLTHROUGH();
+ case '\r':
+ ++endLine;
+ endColumn = 1;
+ break;
+ default:
+ ++endColumn;
+ }
+ ++i;
+ }
+ return SourceLocation(offset + length, 0, endLine, endColumn);
+ }
+
// attributes
// ### encode
quint32 offset;
@@ -89,6 +119,21 @@ public:
return a.offset == b.offset && a.length == b.length
&& a.startLine == b.startLine && a.startColumn == b.startColumn;
}
+
+ friend bool operator!=(const SourceLocation &a, const SourceLocation &b) { return !(a == b); }
+
+ // Returns a source location starting at the beginning of l1, l2 and ending at the end of them.
+ // Ignores invalid source locations.
+ friend SourceLocation combine(const SourceLocation &l1, const SourceLocation &l2) {
+ quint32 e = qMax(l1.end(), l2.end());
+ SourceLocation res;
+ if (l1.offset <= l2.offset)
+ res = (l1.isValid() ? l1 : l2);
+ else
+ res = (l2.isValid() ? l2 : l1);
+ res.length = e - res.offset;
+ return res;
+ }
};
} // namespace QQmlJS
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h
index 891541b8f4..dfa8101d4a 100644
--- a/src/qml/common/qv4compileddata_p.h
+++ b/src/qml/common/qv4compileddata_p.h
@@ -79,7 +79,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 0x31// removed builtin variant type
+#define QV4_DATA_STRUCTURE_VERSION 0x32// added new bytecode instructions for optional chaining
class QIODevice;
class QQmlTypeNameCache;
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index c7343e709c..10fc3f8407 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -443,7 +443,9 @@ bool IRBuilder::generateFromQml(const QString &code, const QString &url, Documen
errors << m;
}
- return false;
+
+ if (!errors.isEmpty() || !parseResult)
+ return false;
}
program = parser.ast();
Q_ASSERT(program);
@@ -1648,8 +1650,8 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
// No more new strings after this point, we're calculating offsets.
output.jsGenerator.stringTable.freeze();
- const uint importSize = sizeof(QV4::CompiledData::Import) * output.imports.count();
- const uint objectOffsetTableSize = output.objects.count() * sizeof(quint32);
+ const uint importSize = uint(sizeof(QV4::CompiledData::Import)) * output.imports.count();
+ const uint objectOffsetTableSize = output.objects.count() * uint(sizeof(quint32));
QHash<const Object*, quint32> objectOffsets;
diff --git a/src/qml/compiler/qv4bytecodegenerator_p.h b/src/qml/compiler/qv4bytecodegenerator_p.h
index 5244c443c4..4cd3b37ad3 100644
--- a/src/qml/compiler/qv4bytecodegenerator_p.h
+++ b/src/qml/compiler/qv4bytecodegenerator_p.h
@@ -196,6 +196,20 @@ QT_WARNING_POP
return addJumpInstruction(data);
}
+ Q_REQUIRED_RESULT Jump jumpOptionalLookup(int index)
+ {
+ Instruction::GetOptionalLookup data{};
+ data.index = index;
+ return addJumpInstruction(data);
+ }
+
+ Q_REQUIRED_RESULT Jump jumpOptionalProperty(int name)
+ {
+ Instruction::LoadOptionalProperty data{};
+ data.name = name;
+ return addJumpInstruction(data);
+ }
+
void jumpStrictEqual(const StackSlot &lhs, const Label &target)
{
Instruction::CmpStrictEqual cmp;
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index ab40f0ceba..d13ef1bc86 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1253,11 +1253,30 @@ bool Codegen::visit(ArrayPattern *ast)
bool Codegen::visit(ArrayMemberExpression *ast)
{
+ auto label = traverseOptionalChain(ast);
+ auto targetLabel = label.has_value() ? label.value() : Moth::BytecodeGenerator::Label();
+
if (hasError())
return false;
+ if (ast->isOptional)
+ Q_ASSERT(m_optionalChainLabels.contains(ast));
+
+
TailCallBlocker blockTailCalls(this);
Reference base = expression(ast->base);
+
+ auto writeSkip = [&]() {
+ auto acc = Reference::fromAccumulator(this).storeOnStack();
+ base.loadInAccumulator();
+ bytecodeGenerator->addInstruction(Instruction::CmpEqNull());
+ auto jumpFalse = bytecodeGenerator->jumpFalse();
+ bytecodeGenerator->addInstruction(Instruction::LoadUndefined());
+ bytecodeGenerator->jump().link(m_optionalChainLabels.take(ast));
+ jumpFalse.link();
+ acc.loadInAccumulator();
+ };
+
if (hasError())
return false;
if (base.isSuper()) {
@@ -1272,17 +1291,31 @@ bool Codegen::visit(ArrayMemberExpression *ast)
QString s = str->value.toString();
uint arrayIndex = stringToArrayIndex(s);
if (arrayIndex == UINT_MAX) {
- setExprResult(Reference::fromMember(base, str->value.toString()));
+ auto jumpLabel = ast->isOptional ? m_optionalChainLabels.take(ast) : Moth::BytecodeGenerator::Label();
+
+ setExprResult(Reference::fromMember(base, str->value.toString(), jumpLabel, targetLabel));
return false;
}
+
+ if (ast->isOptional)
+ writeSkip();
+
Reference index = Reference::fromConst(this, QV4::Encode(arrayIndex));
- setExprResult(Reference::fromSubscript(base, index));
+ setExprResult(Reference::fromSubscript(base, index, targetLabel));
return false;
}
+
+
+ if (ast->isOptional)
+ writeSkip();
+
Reference index = expression(ast->expression);
+
if (hasError())
return false;
- setExprResult(Reference::fromSubscript(base, index));
+
+ setExprResult(Reference::fromSubscript(base, index, targetLabel));
+
return false;
}
@@ -1917,6 +1950,8 @@ bool Codegen::visit(CallExpression *ast)
if (hasError())
return false;
+ auto label = traverseOptionalChain(ast);
+
RegisterScope scope(this);
TailCallBlocker blockTailCalls(this);
@@ -1944,6 +1979,22 @@ bool Codegen::visit(CallExpression *ast)
int thisObject = bytecodeGenerator->newRegister();
int functionObject = bytecodeGenerator->newRegister();
+ if (ast->isOptional || (!base.optionalChainJumpLabel.isNull() && base.optionalChainJumpLabel->isValid())) {
+ if (ast->isOptional)
+ Q_ASSERT(m_optionalChainLabels.contains(ast));
+
+ auto jumpLabel = ast->isOptional ? m_optionalChainLabels.take(ast) : *base.optionalChainJumpLabel.get();
+
+ auto acc = Reference::fromAccumulator(this).storeOnStack();
+ base.loadInAccumulator();
+ bytecodeGenerator->addInstruction(Instruction::CmpEqNull());
+ auto jumpFalse = bytecodeGenerator->jumpFalse();
+ bytecodeGenerator->addInstruction(Instruction::LoadUndefined());
+ bytecodeGenerator->jump().link(jumpLabel);
+ jumpFalse.link();
+ acc.loadInAccumulator();
+ }
+
auto calldata = pushArgs(ast->arguments);
if (hasError())
return false;
@@ -1977,15 +2028,28 @@ bool Codegen::visit(CallExpression *ast)
}
setExprResult(Reference::fromAccumulator(this));
+
+ if (label.has_value())
+ label->link();
+
return false;
}
- handleCall(base, calldata, functionObject, thisObject);
+ handleCall(base, calldata, functionObject, thisObject, ast->isOptional);
+
+ if (label.has_value())
+ label->link();
+
return false;
}
-void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject)
+void Codegen::endVisit(CallExpression *ast)
+{
+ m_seenOptionalChainNodes.remove(ast);
+}
+
+void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject, bool optional)
{
//### Do we really need all these call instructions? can's we load the callee in a temp?
if (base.type == Reference::Member) {
@@ -2012,7 +2076,7 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
call.argv = calldata.argv;
bytecodeGenerator->addInstruction(call);
} else if (base.type == Reference::Name) {
- if (base.name == QStringLiteral("eval")) {
+ if (base.name == QStringLiteral("eval") && !optional) {
Instruction::CallPossiblyDirectEval call;
call.argc = calldata.argc;
call.argv = calldata.argv;
@@ -2171,12 +2235,18 @@ bool Codegen::visit(DeleteExpression *ast)
if (hasError())
return false;
+ auto label = traverseOptionalChain(ast);
+
RegisterScope scope(this);
TailCallBlocker blockTailCalls(this);
Reference expr = expression(ast->expression);
if (hasError())
return false;
+ // If there is a label, there is a chain and that should only be possible with those two kinds of references
+ if (label.has_value())
+ Q_ASSERT(expr.type == Reference::Member || expr.type == Reference::Subscript);
+
switch (expr.type) {
case Reference::SuperProperty:
// ### this should throw a reference error at runtime.
@@ -2207,6 +2277,13 @@ bool Codegen::visit(DeleteExpression *ast)
case Reference::Member: {
//### maybe add a variant where the base can be in the accumulator?
expr = expr.asLValue();
+
+ if (!expr.optionalChainJumpLabel.isNull() && expr.optionalChainJumpLabel->isValid()) {
+ expr.loadInAccumulator();
+ bytecodeGenerator->addInstruction(Instruction::CmpEqNull());
+ bytecodeGenerator->jumpTrue().link(*expr.optionalChainJumpLabel.get());
+ }
+
Instruction::LoadRuntimeString instr;
instr.stringId = expr.propertyNameIndex;
bytecodeGenerator->addInstruction(instr);
@@ -2217,16 +2294,41 @@ bool Codegen::visit(DeleteExpression *ast)
del.index = index.stackSlot();
bytecodeGenerator->addInstruction(del);
setExprResult(Reference::fromAccumulator(this));
+
+ if (label.has_value()) {
+ auto jump = bytecodeGenerator->jump();
+ label->link();
+ Instruction::LoadTrue loadTrue;
+ bytecodeGenerator->addInstruction(loadTrue);
+ jump.link();
+ }
+
return false;
}
case Reference::Subscript: {
//### maybe add a variant where the index can be in the accumulator?
expr = expr.asLValue();
+
+ if (!expr.optionalChainJumpLabel.isNull() && expr.optionalChainJumpLabel->isValid()) {
+ expr.loadInAccumulator();
+ bytecodeGenerator->addInstruction(Instruction::CmpEqNull());
+ bytecodeGenerator->jumpTrue().link(*expr.optionalChainJumpLabel.get());
+ }
+
Instruction::DeleteProperty del;
del.base = expr.elementBase;
del.index = expr.elementSubscript.stackSlot();
bytecodeGenerator->addInstruction(del);
setExprResult(Reference::fromAccumulator(this));
+
+ if (label.has_value()) {
+ auto jump = bytecodeGenerator->jump();
+ label->link();
+ Instruction::LoadTrue loadTrue;
+ bytecodeGenerator->addInstruction(loadTrue);
+ jump.link();
+ }
+
return false;
}
default:
@@ -2237,6 +2339,10 @@ bool Codegen::visit(DeleteExpression *ast)
return false;
}
+void Codegen::endVisit(DeleteExpression *ast) {
+ m_seenOptionalChainNodes.remove(ast);
+}
+
bool Codegen::visit(FalseLiteral *)
{
if (hasError())
@@ -2255,11 +2361,81 @@ bool Codegen::visit(SuperLiteral *)
return false;
}
+std::optional<Moth::BytecodeGenerator::Label> Codegen::traverseOptionalChain(Node *node) {
+ if (m_seenOptionalChainNodes.contains(node))
+ return {};
+
+ auto label = bytecodeGenerator->newLabel();
+
+ auto isOptionalChainNode = [](const Node *node) {
+ return node->kind == Node::Kind_FieldMemberExpression ||
+ node->kind == Node::Kind_CallExpression ||
+ node->kind == Node::Kind_ArrayMemberExpression ||
+ node->kind == Node::Kind_DeleteExpression;
+ };
+
+ bool labelUsed = false;
+
+ while (isOptionalChainNode(node)) {
+ m_seenOptionalChainNodes.insert(node);
+
+ switch (node->kind) {
+ case Node::Kind_FieldMemberExpression: {
+ auto *fme = AST::cast<FieldMemberExpression*>(node);
+
+ if (fme->isOptional) {
+ m_optionalChainLabels.insert(fme, label);
+ labelUsed = true;
+ }
+
+ node = fme->base;
+ break;
+ }
+ case Node::Kind_CallExpression: {
+ auto *ce = AST::cast<CallExpression*>(node);
+
+ if (ce->isOptional) {
+ m_optionalChainLabels.insert(ce, label);
+ labelUsed = true;
+ }
+
+ node = ce->base;
+ break;
+ }
+ case Node::Kind_ArrayMemberExpression: {
+ auto *ame = AST::cast<ArrayMemberExpression*>(node);
+
+ if (ame->isOptional) {
+ m_optionalChainLabels.insert(ame, label);
+ labelUsed = true;
+ }
+
+ node = ame->base;
+ break;
+ }
+ case Node::Kind_DeleteExpression: {
+ auto *de = AST::cast<DeleteExpression*>(node);
+ node = de->expression;
+ break;
+ }
+ }
+ }
+
+ if (!labelUsed) {
+ label.link(); // If we don't link the unused label here, we would hit an assert later.
+ return {};
+ }
+
+ return label;
+}
+
bool Codegen::visit(FieldMemberExpression *ast)
{
if (hasError())
return false;
+ auto label = traverseOptionalChain(ast);
+
TailCallBlocker blockTailCalls(this);
if (AST::IdentifierExpression *id = AST::cast<AST::IdentifierExpression *>(ast->base)) {
if (id->name == QLatin1String("new")) {
@@ -2270,16 +2446,28 @@ bool Codegen::visit(FieldMemberExpression *ast)
Reference r = referenceForName(QStringLiteral("new.target"), false);
r.isReadonly = true;
setExprResult(r);
+
+ if (label.has_value())
+ label->link();
+
return false;
}
Reference r = Reference::fromStackSlot(this, CallData::NewTarget);
setExprResult(r);
+
+ if (label.has_value())
+ label->link();
+
return false;
}
}
Reference base = expression(ast->base);
+
+ if (ast->isOptional)
+ Q_ASSERT(m_optionalChainLabels.contains(ast));
+
if (hasError())
return false;
if (base.isSuper()) {
@@ -2288,12 +2476,25 @@ bool Codegen::visit(FieldMemberExpression *ast)
bytecodeGenerator->addInstruction(load);
Reference property = Reference::fromAccumulator(this).storeOnStack();
setExprResult(Reference::fromSuperProperty(property));
+
+ if (label.has_value())
+ label->link();
+
return false;
}
- setExprResult(Reference::fromMember(base, ast->name.toString()));
+
+ setExprResult(Reference::fromMember(base, ast->name.toString(),
+ ast->isOptional ? m_optionalChainLabels.take(ast) : Moth::BytecodeGenerator::Label(),
+ label.has_value() ? label.value() : Moth::BytecodeGenerator::Label()));
+
return false;
}
+void Codegen::endVisit(FieldMemberExpression *ast)
+{
+ m_seenOptionalChainNodes.remove(ast);
+}
+
bool Codegen::visit(TaggedTemplate *ast)
{
if (hasError())
@@ -4454,13 +4655,26 @@ QT_WARNING_POP
propertyBase.loadInAccumulator();
tdzCheck(requiresTDZCheck);
if (!disable_lookups && codegen->useFastLookups) {
- Instruction::GetLookup load;
- load.index = codegen->registerGetterLookup(propertyNameIndex);
- codegen->bytecodeGenerator->addInstruction(load);
+ if (optionalChainJumpLabel->isValid()) { // If we got a valid jump label, this means it's an optional lookup
+ auto jump = codegen->bytecodeGenerator->jumpOptionalLookup(codegen->registerGetterLookup(propertyNameIndex));
+ jump.link(*optionalChainJumpLabel.get());
+ } else {
+ Instruction::GetLookup load;
+ load.index = codegen->registerGetterLookup(propertyNameIndex);
+ codegen->bytecodeGenerator->addInstruction(load);
+ }
} else {
- Instruction::LoadProperty load;
- load.name = propertyNameIndex;
- codegen->bytecodeGenerator->addInstruction(load);
+ if (optionalChainJumpLabel->isValid()) {
+ auto jump = codegen->bytecodeGenerator->jumpOptionalProperty(propertyNameIndex);
+ jump.link(*optionalChainJumpLabel.get());
+ } else {
+ Instruction::LoadProperty load;
+ load.name = propertyNameIndex;
+ codegen->bytecodeGenerator->addInstruction(load);
+ }
+ }
+ if (optionalChainTargetLabel->isValid()) {
+ optionalChainTargetLabel->link();
}
return;
case Import: {
@@ -4476,6 +4690,10 @@ QT_WARNING_POP
Instruction::LoadElement load;
load.base = elementBase;
codegen->bytecodeGenerator->addInstruction(load);
+
+ if (optionalChainTargetLabel->isValid()) {
+ optionalChainTargetLabel->link();
+ }
} return;
case Invalid:
break;
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index e7d7a21294..9bee72418d 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -60,6 +60,8 @@
#include <private/qv4bytecodegenerator_p.h>
#include <private/qv4calldata_p.h>
+#include <QtCore/qsharedpointer.h>
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -277,11 +279,16 @@ public:
r.name = name;
return r;
}
- static Reference fromMember(const Reference &baseRef, const QString &name) {
+ static Reference fromMember(const Reference &baseRef, const QString &name,
+ Moth::BytecodeGenerator::Label jumpLabel = Moth::BytecodeGenerator::Label(),
+ Moth::BytecodeGenerator::Label targetLabel = Moth::BytecodeGenerator::Label()) {
+ Q_ASSERT(baseRef.isValid());
Reference r(baseRef.codegen, Member);
r.propertyBase = baseRef.asRValue();
r.propertyNameIndex = r.codegen->registerString(name);
r.requiresTDZCheck = baseRef.requiresTDZCheck;
+ r.optionalChainJumpLabel.reset(new Moth::BytecodeGenerator::Label(jumpLabel));
+ r.optionalChainTargetLabel.reset(new Moth::BytecodeGenerator::Label(targetLabel));
return r;
}
static Reference fromSuperProperty(const Reference &property) {
@@ -291,13 +298,14 @@ public:
r.subscriptRequiresTDZCheck = property.requiresTDZCheck;
return r;
}
- static Reference fromSubscript(const Reference &baseRef, const Reference &subscript) {
+ static Reference fromSubscript(const Reference &baseRef, const Reference &subscript, Moth::BytecodeGenerator::Label targetLabel = Moth::BytecodeGenerator::Label()) {
Q_ASSERT(baseRef.isStackSlot());
Reference r(baseRef.codegen, Subscript);
r.elementBase = baseRef.stackSlot();
r.elementSubscript = subscript.asRValue();
r.requiresTDZCheck = baseRef.requiresTDZCheck;
r.subscriptRequiresTDZCheck = subscript.requiresTDZCheck;
+ r.optionalChainTargetLabel.reset(new Moth::BytecodeGenerator::Label(targetLabel));
return r;
}
static Reference fromConst(Codegen *cg, QV4::ReturnedValue constant) {
@@ -374,6 +382,8 @@ public:
quint32 isVolatile:1;
quint32 global:1;
quint32 qmlGlobal:1;
+ QSharedPointer<Moth::BytecodeGenerator::Label> optionalChainJumpLabel;
+ QSharedPointer<Moth::BytecodeGenerator::Label> optionalChainTargetLabel;
private:
void storeAccumulator() const;
@@ -598,11 +608,14 @@ protected:
bool visit(QQmlJS::AST::ArrayMemberExpression *ast) override;
bool visit(QQmlJS::AST::BinaryExpression *ast) override;
bool visit(QQmlJS::AST::CallExpression *ast) override;
+ void endVisit(QQmlJS::AST::CallExpression *ast) override;
bool visit(QQmlJS::AST::ConditionalExpression *ast) override;
bool visit(QQmlJS::AST::DeleteExpression *ast) override;
+ void endVisit(QQmlJS::AST::DeleteExpression *ast) override;
bool visit(QQmlJS::AST::FalseLiteral *ast) override;
bool visit(QQmlJS::AST::SuperLiteral *ast) override;
bool visit(QQmlJS::AST::FieldMemberExpression *ast) override;
+ void endVisit(QQmlJS::AST::FieldMemberExpression *ast) override;
bool visit(QQmlJS::AST::TaggedTemplate *ast) override;
bool visit(QQmlJS::AST::FunctionExpression *ast) override;
bool visit(QQmlJS::AST::IdentifierExpression *ast) override;
@@ -686,7 +699,7 @@ public:
Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right);
struct Arguments { int argc; int argv; bool hasSpread; };
Arguments pushArgs(QQmlJS::AST::ArgumentList *args);
- void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject);
+ void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject, bool optional = false);
Arguments pushTemplateArgs(QQmlJS::AST::TemplateLiteral *args);
bool handleTaggedTemplate(Reference base, QQmlJS::AST::TaggedTemplate *ast);
@@ -776,6 +789,8 @@ protected:
bool functionEndsWithReturn = false;
bool _tailCallsAreAllowed = true;
QSet<QString> m_globalNames;
+ QSet<QQmlJS::AST::Node*> m_seenOptionalChainNodes;
+ QHash<QQmlJS::AST::Node*, Moth::BytecodeGenerator::Label> m_optionalChainLabels;
ControlFlow *controlFlow = nullptr;
@@ -812,6 +827,7 @@ private:
void handleConstruct(const Reference &base, QQmlJS::AST::ArgumentList *args);
void throwError(ErrorType errorType, const QQmlJS::SourceLocation &loc,
const QString &detail);
+ std::optional<Moth::BytecodeGenerator::Label> traverseOptionalChain(QQmlJS::AST::Node *node);
};
}
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 4f3c718175..5155c25c06 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -125,6 +125,8 @@ struct Q_QMLCOMPILER_PRIVATE_EXPORT JSUnitGenerator {
int registerSetterLookup(int nameIndex);
int registerGlobalGetterLookup(int nameIndex);
int registerQmlContextPropertyGetterLookup(int nameIndex);
+ int lookupNameIndex(int index) const { return lookups[index].nameIndex; }
+ QString lookupName(int index) const { return stringForIndex(lookupNameIndex(index)); }
int registerRegExp(QQmlJS::AST::RegExpLiteral *regexp);
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index ebc9a86a16..a942b3d2c9 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -181,7 +181,9 @@ bool ScanFunctions::visit(ExportDeclaration *declaration)
QString localNameForDefaultExport = QStringLiteral("*default*");
- if (declaration->exportAll) {
+ if (declaration->exportsAll()) {
+ Q_ASSERT_X(declaration->fromClause, "ScanFunctions",
+ "ExportDeclaration with exportAll always have a fromClause");
Compiler::ExportEntry entry;
entry.moduleRequest = declaration->fromClause->moduleSpecifier.toString();
entry.importName = QStringLiteral("*");
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 640a908dd3..c791790cba 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -280,10 +280,18 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << "acc[" << name << "]";
MOTH_END_INSTR(LoadProperty)
+ MOTH_BEGIN_INSTR(LoadOptionalProperty)
+ d << "acc[" << name << "], jump(" << ABSOLUTE_OFFSET() << ")";
+ MOTH_END_INSTR(LoadOptionalProperty)
+
MOTH_BEGIN_INSTR(GetLookup)
d << "acc(" << index << ")";
MOTH_END_INSTR(GetLookup)
+ MOTH_BEGIN_INSTR(GetOptionalLookup)
+ d << "acc(" << index << "), jump(" << ABSOLUTE_OFFSET() << ")";
+ MOTH_END_INSTR(GetOptionalLookup)
+
MOTH_BEGIN_INSTR(StoreProperty)
d << dumpRegister(base, nFormals) << "[" << name<< "]";
MOTH_END_INSTR(StoreProperty)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 254e1c46e9..69e4eb26f3 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -89,7 +89,9 @@ QT_BEGIN_NAMESPACE
#define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name)
#define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name)
#define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 1, name)
+#define INSTR_LoadOptionalProperty(op) INSTRUCTION(op, LoadOptionalProperty, 2, name, offset)
#define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 1, index)
+#define INSTR_GetOptionalLookup(op) INSTRUCTION(op, GetOptionalLookup, 2, index, offset)
#define INSTR_LoadIdObject(op) INSTRUCTION(op, LoadIdObject, 2, index, base)
#define INSTR_Yield(op) INSTRUCTION(op, Yield, 0)
#define INSTR_YieldStar(op) INSTRUCTION(op, YieldStar, 0)
@@ -229,7 +231,9 @@ QT_BEGIN_NAMESPACE
F(LoadElement) \
F(StoreElement) \
F(LoadProperty) \
+ F(LoadOptionalProperty) \
F(GetLookup) \
+ F(GetOptionalLookup) \
F(StoreProperty) \
F(SetLookup) \
F(LoadSuperProperty) \
diff --git a/src/qml/configure.cmake b/src/qml/configure.cmake
index 21acf9efa7..60e9c00517 100644
--- a/src/qml/configure.cmake
+++ b/src/qml/configure.cmake
@@ -7,6 +7,9 @@
#### Libraries
+# special case begin
+qt_find_package(LTTngUST PROVIDED_TARGETS LTTng::UST MODULE_NAME qml QMAKE_LIB lttng-ust)
+# special case end
#### Tests
@@ -131,6 +134,30 @@ qt_feature("qml-jit" PRIVATE
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 ) ) )
)
+# special case begin
+# When doing macOS universal builds, JIT needs to be disabled for the ARM slice.
+# Because both arm and x86_64 slices are built in one clang frontend invocation
+# we need this hack to ensure each backend invocation sees the correct value
+# of the feature definition.
+qt_extra_definition("QT_QML_JIT_SUPPORTED_IMPL" "0
+// Unset dummy value
+#undef QT_QML_JIT_SUPPORTED_IMPL
+// Compute per-arch value and save in extra define
+#if QT_CONFIG(qml_jit) && !(defined(Q_OS_MACOS) && defined(Q_PROCESSOR_ARM))
+#define QT_QML_JIT_SUPPORTED_IMPL 1
+#else
+#define QT_QML_JIT_SUPPORTED_IMPL 0
+#endif
+// Unset original feature value
+#undef QT_FEATURE_qml_jit
+// Set new value based on previous computation
+#if QT_QML_JIT_SUPPORTED_IMPL
+#define QT_FEATURE_qml_jit 1
+#else
+#define QT_FEATURE_qml_jit -1
+#endif
+" PRIVATE)
+# special case end
qt_feature("qml-debug" PUBLIC
SECTION "QML"
LABEL "QML debugging and profiling support"
@@ -187,6 +214,12 @@ qt_feature("qml-itemmodel" PRIVATE
PURPOSE "Provides the item model for item views in QML"
CONDITION QT_FEATURE_itemmodel
)
+qt_feature("qml-xmllistmodel" PRIVATE
+ SECTION "QML"
+ LABEL "QML XmlListModel"
+ PURPOSE "Enable XmlListModel in QML"
+ CONDITION QT_FEATURE_qml_itemmodel AND QT_FEATURE_future
+)
# special case begin
qt_qml_find_python(__qt_qml_python_path __qt_qml_python_found)
diff --git a/src/qml/configure.json b/src/qml/configure.json
index 944358bc48..5a6a459b76 100644
--- a/src/qml/configure.json
+++ b/src/qml/configure.json
@@ -191,6 +191,13 @@
"condition": "features.itemmodel",
"output": [ "privateFeature" ]
},
+ "qml-xmllistmodel": {
+ "label": "QML XmlListModel",
+ "purpose": "Enable XmlListModel in QML",
+ "section": "QML",
+ "condition": "features.qml-itemmodel && features.future",
+ "output": [ "privateFeature" ]
+ },
"qml-python": {
"label": "python",
"condition": "tests.qml-python",
diff --git a/src/qml/doc/src/external-resources.qdoc b/src/qml/doc/src/external-resources.qdoc
index c11174db43..b4a0903f5d 100644
--- a/src/qml/doc/src/external-resources.qdoc
+++ b/src/qml/doc/src/external-resources.qdoc
@@ -80,3 +80,7 @@
\externalpage https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator
\title Nullish Coalescing
*/
+/*!
+ \externalpage https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
+ \title Optional Chaining
+*/
diff --git a/src/qml/doc/src/javascript/hostenvironment.qdoc b/src/qml/doc/src/javascript/hostenvironment.qdoc
index bc75f843fb..0c495fdaa9 100644
--- a/src/qml/doc/src/javascript/hostenvironment.qdoc
+++ b/src/qml/doc/src/javascript/hostenvironment.qdoc
@@ -42,7 +42,7 @@ Like a browser or server-side JavaScript environment, the QML runtime implements
all of the built-in types and functions defined by the standard, such as Object, Array, and Math.
The QML runtime implements the 7th edition of the standard.
-Since Qt 5.15 \l{Nullish Coalescing} is also implemented in the QML runtime.
+\l{Nullish Coalescing} (since Qt 5.15) and \l{Optional Chaining} (since Qt 6.2) are also implemented in the QML runtime.
The standard ECMAScript built-ins are not explicitly documented in the QML documentation. For more
information on their use, please refer to the ECMA-262 7th edition standard or one of the many online
diff --git a/src/qml/doc/src/qmlfunctions.qdoc b/src/qml/doc/src/qmlfunctions.qdoc
index eb7983d077..c454d981a3 100644
--- a/src/qml/doc/src/qmlfunctions.qdoc
+++ b/src/qml/doc/src/qmlfunctions.qdoc
@@ -180,13 +180,14 @@
\relates QQmlEngine
Declares the enclosing type to be a singleton in QML. This only takes effect
- if the type is available in QML, by having a \l QML_ELEMENT or
- \l QML_NAMED_ELEMENT() macro. By default, each QQmlEngine will try to create a
- singleton instance using either the type's default constructor or a static
- factory function of the signature \c{T *create(QQmlEngine *, QJSEngine *)}
- when the type is first accessed. If both do exist and are accessible, the
- default constructor is preferred. If there is no default constructor and no
- factory function the singleton is initially inaccessible.
+ if the type is a \l Q_OBJECT and is available in QML (by having a
+ \l QML_ELEMENT or \l QML_NAMED_ELEMENT() macro). By default, each QQmlEngine
+ will try to create a singleton instance using either the type's default
+ constructor or a static factory function of the signature
+ \c{T *create(QQmlEngine *, QJSEngine *)} when the type is first accessed.
+ If both do exist and are accessible, the default constructor is preferred.
+ If there is no default constructor and no factory function the singleton is
+ initially inaccessible.
\sa QML_ELEMENT, QML_NAMED_ELEMENT(), qmlRegisterSingletonInstance().
*/
diff --git a/src/qml/jit/qv4assemblercommon.cpp b/src/qml/jit/qv4assemblercommon.cpp
index 9cf118e04b..6952c0b053 100644
--- a/src/qml/jit/qv4assemblercommon.cpp
+++ b/src/qml/jit/qv4assemblercommon.cpp
@@ -51,6 +51,8 @@
#include <assembler/LinkBuffer.h>
#include <WTFStubs.h>
+#if QT_CONFIG(qml_jit)
+
#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
QT_BEGIN_NAMESPACE
@@ -179,7 +181,7 @@ void PlatformAssemblerCommon::prepareCallWithArgCount(int argc)
void PlatformAssemblerCommon::storeInstructionPointer(int instructionOffset)
{
- Address addr(CppStackFrameRegister, offsetof(QV4::CppStackFrame, instructionPointer));
+ Address addr(CppStackFrameRegister, offsetof(QV4::JSTypesStackFrame, instructionPointer));
store32(TrustedImm32(instructionOffset), addr);
}
@@ -371,3 +373,5 @@ void PlatformAssemblerCommon::storeInt32AsValue(int srcInt, Address destAddr)
} // QV4 namepsace
QT_END_NAMESPACE
+
+#endif // QT_CONFIG(qml_jit)
diff --git a/src/qml/jit/qv4assemblercommon_p.h b/src/qml/jit/qv4assemblercommon_p.h
index ead1e757de..63a88f287f 100644
--- a/src/qml/jit/qv4assemblercommon_p.h
+++ b/src/qml/jit/qv4assemblercommon_p.h
@@ -58,7 +58,7 @@
#include <wtf/Vector.h>
#include <assembler/MacroAssembler.h>
-QT_REQUIRE_CONFIG(qml_jit);
+#if QT_CONFIG(qml_jit)
QT_BEGIN_NAMESPACE
@@ -579,7 +579,7 @@ public:
Address loadFunctionPtr(RegisterID target)
{
- Address addr(CppStackFrameRegister, offsetof(CppStackFrame, v4Function));
+ Address addr(CppStackFrameRegister, offsetof(JSTypesStackFrame, v4Function));
loadPtr(addr, target);
return Address(target);
}
@@ -653,7 +653,8 @@ public:
void generateFunctionEntry()
{
generatePlatformFunctionEntry();
- loadPtr(Address(CppStackFrameRegister, offsetof(CppStackFrame, jsFrame)), JSStackFrameRegister);
+ loadPtr(Address(CppStackFrameRegister, offsetof(JSTypesStackFrame, jsFrame)),
+ JSStackFrameRegister);
allocateStackSpace();
}
@@ -740,4 +741,6 @@ private:
QT_END_NAMESPACE
+#endif // QT_CONFIG(qml_jit)
+
#endif // QV4PLATFORMASSEMBLER_P_H
diff --git a/src/qml/jit/qv4baselineassembler.cpp b/src/qml/jit/qv4baselineassembler.cpp
index 69670e1773..661da879f2 100644
--- a/src/qml/jit/qv4baselineassembler.cpp
+++ b/src/qml/jit/qv4baselineassembler.cpp
@@ -55,6 +55,8 @@
#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
+#if QT_CONFIG(qml_jit)
+
QT_BEGIN_NAMESPACE
namespace QV4 {
namespace JIT {
@@ -1413,6 +1415,23 @@ int BaselineAssembler::jumpNotUndefined(int offset)
return offset;
}
+int BaselineAssembler::jumpEqNull(int offset)
+{
+ saveAccumulatorInFrame();
+ cmpeqNull();
+
+ pasm()->toBoolean([this, offset](PlatformAssembler::RegisterID resultReg) {
+ auto isFalse = pasm()->branch32(PlatformAssembler::Equal, TrustedImm32(0), resultReg);
+ loadValue(Encode::undefined());
+ pasm()->addJumpToOffset(pasm()->jump(), offset);
+ isFalse.link(pasm());
+ loadAccumulatorFromFrame();
+ });
+
+ return offset;
+}
+
+
void BaselineAssembler::prepareCallWithArgCount(int argc)
{
pasm()->prepareCallWithArgCount(argc);
@@ -1475,7 +1494,7 @@ void BaselineAssembler::loadAccumulatorFromFrame()
offsetof(CallData, accumulator)));
}
-static ReturnedValue TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing(CppStackFrame *frame, ExecutionEngine *engine)
+static ReturnedValue TheJitIs__Tail_Calling__ToTheRuntimeSoTheJitFrameIsMissing(JSTypesStackFrame *frame, ExecutionEngine *engine)
{
return Runtime::TailCall::call(frame, engine);
}
@@ -1557,15 +1576,15 @@ void BaselineAssembler::clearUnwindHandler()
void JIT::BaselineAssembler::unwindDispatch()
{
checkException();
- pasm()->load32(Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel)), PlatformAssembler::ScratchRegister);
+ pasm()->load32(Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLevel)), PlatformAssembler::ScratchRegister);
auto noUnwind = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0));
pasm()->sub32(TrustedImm32(1), PlatformAssembler::ScratchRegister);
- pasm()->store32(PlatformAssembler::ScratchRegister, Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel)));
+ pasm()->store32(PlatformAssembler::ScratchRegister, Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLevel)));
auto jump = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0));
gotoCatchException();
jump.link(pasm());
- pasm()->loadPtr(Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLabel)), PlatformAssembler::ScratchRegister);
+ pasm()->loadPtr(Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLabel)), PlatformAssembler::ScratchRegister);
pasm()->jump(PlatformAssembler::ScratchRegister);
noUnwind.link(pasm());
@@ -1573,9 +1592,9 @@ void JIT::BaselineAssembler::unwindDispatch()
int JIT::BaselineAssembler::unwindToLabel(int level, int offset)
{
- auto l = pasm()->storePtrWithPatch(TrustedImmPtr(nullptr), Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLabel)));
+ auto l = pasm()->storePtrWithPatch(TrustedImmPtr(nullptr), Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLabel)));
pasm()->addEHTarget(l, offset);
- pasm()->store32(TrustedImm32(level), Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel)));
+ pasm()->store32(TrustedImm32(level), Address(PlatformAssembler::CppStackFrameRegister, offsetof(JSTypesStackFrame, unwindLevel)));
gotoCatchException();
return offset;
}
@@ -1619,3 +1638,5 @@ void BaselineAssembler::ret()
} // QV4 namepsace
QT_END_NAMESPACE
+
+#endif // QT_CONFIG(qml_jit)
diff --git a/src/qml/jit/qv4baselineassembler_p.h b/src/qml/jit/qv4baselineassembler_p.h
index c2c735282b..e0a1bd3fce 100644
--- a/src/qml/jit/qv4baselineassembler_p.h
+++ b/src/qml/jit/qv4baselineassembler_p.h
@@ -55,7 +55,7 @@
#include <private/qv4function_p.h>
#include <QHash>
-QT_REQUIRE_CONFIG(qml_jit);
+#if QT_CONFIG(qml_jit)
QT_BEGIN_NAMESPACE
@@ -137,6 +137,7 @@ public:
Q_REQUIRED_RESULT int jumpFalse(int offset);
Q_REQUIRED_RESULT int jumpNoException(int offset);
Q_REQUIRED_RESULT int jumpNotUndefined(int offset);
+ Q_REQUIRED_RESULT int jumpEqNull(int offset);
// stuff for runtime calls
void prepareCallWithArgCount(int argc);
@@ -182,4 +183,6 @@ private:
QT_END_NAMESPACE
+#endif // QT_CONFIG(qml_jit)
+
#endif // QV4BASELINEASSEMBLER_P_H
diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp
index 5e6d843fbc..f660e363ea 100644
--- a/src/qml/jit/qv4baselinejit.cpp
+++ b/src/qml/jit/qv4baselinejit.cpp
@@ -42,6 +42,8 @@
#include <private/qv4lookup_p.h>
#include <private/qv4generatorobject_p.h>
+#if QT_CONFIG(qml_jit)
+
QT_USE_NAMESPACE
using namespace QV4;
using namespace QV4::JIT;
@@ -281,6 +283,13 @@ void BaselineJIT::generate_LoadProperty(int name)
BASELINEJIT_GENERATE_RUNTIME_CALL(LoadProperty, CallResultDestination::InAccumulator);
}
+void BaselineJIT::generate_LoadOptionalProperty(int name, int offset)
+{
+ labels.insert(as->jumpEqNull(absoluteOffset(offset)));
+
+ generate_LoadProperty(name);
+}
+
void BaselineJIT::generate_GetLookup(int index)
{
STORE_IP();
@@ -293,6 +302,13 @@ void BaselineJIT::generate_GetLookup(int index)
BASELINEJIT_GENERATE_RUNTIME_CALL(GetLookup, CallResultDestination::InAccumulator);
}
+void BaselineJIT::generate_GetOptionalLookup(int index, int offset)
+{
+ labels.insert(as->jumpEqNull(absoluteOffset(offset)));
+
+ generate_GetLookup(index);
+}
+
void BaselineJIT::generate_StoreProperty(int name, int base)
{
STORE_IP();
@@ -931,3 +947,6 @@ void BaselineJIT::endInstruction(Instr::Type instr)
{
Q_UNUSED(instr);
}
+
+#endif // QT_CONFIG(qml_jit)
+
diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h
index 284faf0ff0..1fa20d5902 100644
--- a/src/qml/jit/qv4baselinejit_p.h
+++ b/src/qml/jit/qv4baselinejit_p.h
@@ -56,7 +56,7 @@
#include <private/qv4instr_moth_p.h>
#include <private/qv4bytecodehandler_p.h>
-QT_REQUIRE_CONFIG(qml_jit);
+#if QT_CONFIG(qml_jit)
QT_BEGIN_NAMESPACE
@@ -102,7 +102,9 @@ public:
void generate_LoadElement(int base) override;
void generate_StoreElement(int base, int index) override;
void generate_LoadProperty(int name) override;
+ void generate_LoadOptionalProperty(int name, int offset) override;
void generate_GetLookup(int index) override;
+ void generate_GetOptionalLookup(int index, int offset) override;
void generate_StoreProperty(int name, int base) override;
void generate_SetLookup(int index, int base) override;
void generate_LoadSuperProperty(int property) override;
@@ -220,4 +222,6 @@ private:
QT_END_NAMESPACE
+#endif // QT_CONFIG(qml_jit)
+
#endif // QV4JIT_P_H
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index dbb35cdde8..b27c6add75 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -53,6 +53,7 @@
#include <private/qv4qobjectwrapper_p.h>
#include <private/qv4stackframe_p.h>
#include <private/qv4module_p.h>
+#include <private/qv4symbol_p.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmetaobject.h>
@@ -591,6 +592,22 @@ QJSValue QJSEngine::newObject()
}
/*!
+ \since 6.2
+
+ Creates a JavaScript object of class Symbol, with value \a name.
+
+ The prototype of the created object will be the Symbol prototype object.
+
+ \sa newString()
+*/
+QJSValue QJSEngine::newSymbol(const QString &name)
+{
+ QV4::Scope scope(m_v4Engine);
+ QV4::ScopedValue v(scope, QV4::Symbol::create(m_v4Engine, u'@' + name));
+ return QJSValuePrivate::fromReturnedValue(v->asReturnedValue());
+}
+
+/*!
\since 5.12
Creates a JavaScript object of class Error, with \a message as the error
@@ -748,32 +765,42 @@ QJSValue QJSEngine::create(QMetaType type, const void *ptr)
bool QJSEngine::convertManaged(const QJSManagedValue &value, int type, void *ptr)
{
+ return convertManaged(value, QMetaType(type), ptr);
+}
+
+bool QJSEngine::convertManaged(const QJSManagedValue &value, QMetaType type, void *ptr)
+{
return QV4::ExecutionEngine::metaTypeFromJS(*value.d, type, ptr);
}
+bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
+{
+ return convertV2(value, QMetaType(type), ptr);
+}
+
/*!
\internal
convert \a value to \a type, store the result in \a ptr
*/
-bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
+bool QJSEngine::convertV2(const QJSValue &value, QMetaType metaType, void *ptr)
{
if (const QString *string = QJSValuePrivate::asQString(&value)) {
// have a string based value without engine. Do conversion manually
- if (type == QMetaType::Bool) {
+ if (metaType == QMetaType::fromType<bool>()) {
*reinterpret_cast<bool*>(ptr) = string->length() != 0;
return true;
}
- if (type == QMetaType::QString) {
+ if (metaType == QMetaType::fromType<QString>()) {
*reinterpret_cast<QString*>(ptr) = *string;
return true;
}
- if (type == QMetaType::QUrl) {
+ if (metaType == QMetaType::fromType<QUrl>()) {
*reinterpret_cast<QUrl *>(ptr) = QUrl(*string);
return true;
}
double d = QV4::RuntimeHelpers::stringToNumber(*string);
- switch (type) {
+ switch (metaType.id()) {
case QMetaType::Int:
*reinterpret_cast<int*>(ptr) = QV4::Value::toInt32(d);
return true;
@@ -815,7 +842,7 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
}
}
- return QV4::ExecutionEngine::metaTypeFromJS(QJSValuePrivate::asReturnedValue(&value), type, ptr);
+ return QV4::ExecutionEngine::metaTypeFromJS(QJSValuePrivate::asReturnedValue(&value), metaType, ptr);
}
/*! \fn template <typename T> QJSValue QJSEngine::toScriptValue(const T &value)
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index 05c94ab261..ac79b30ebc 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -73,6 +73,7 @@ public:
QJSValue importModule(const QString &fileName);
QJSValue newObject();
+ QJSValue newSymbol(const QString &name);
QJSValue newArray(uint length = 0);
QJSValue newQObject(QObject *object);
@@ -149,7 +150,9 @@ private:
QJSValue create(QMetaType type, const void *ptr);
static bool convertManaged(const QJSManagedValue &value, int type, void *ptr);
+ static bool convertManaged(const QJSManagedValue &value, QMetaType type, void *ptr);
static bool convertV2(const QJSValue &value, int type, void *ptr);
+ static bool convertV2(const QJSValue &value, QMetaType metaType, void *ptr);
template<typename T>
friend inline T qjsvalue_cast(const QJSValue &);
@@ -172,9 +175,7 @@ template<typename T>
T qjsvalue_cast(const QJSValue &value)
{
T t;
- const int id = qMetaTypeId<T>();
-
- if (QJSEngine::convertV2(value, id, &t))
+ if (QJSEngine::convertV2(value, QMetaType::fromType<T>(), &t))
return t;
else if (value.isVariant())
return qvariant_cast<T>(value.toVariant());
@@ -187,7 +188,7 @@ T qjsvalue_cast(const QJSManagedValue &value)
{
{
T t;
- if (QJSEngine::convertManaged(value, qMetaTypeId<T>(), &t))
+ if (QJSEngine::convertManaged(value, QMetaType::fromType<T>(), &t))
return t;
}
diff --git a/src/qml/jsapi/qjsmanagedvalue.cpp b/src/qml/jsapi/qjsmanagedvalue.cpp
index 202c940785..454dc11fd8 100644
--- a/src/qml/jsapi/qjsmanagedvalue.cpp
+++ b/src/qml/jsapi/qjsmanagedvalue.cpp
@@ -52,6 +52,7 @@
#include <QtQml/private/qv4regexpobject_p.h>
#include <QtQml/private/qv4dateobject_p.h>
#include <QtQml/private/qv4errorobject_p.h>
+#include <QtQml/private/qv4identifiertable_p.h>
#include <QtCore/qregularexpression.h>
#include <QtCore/qurl.h>
@@ -665,7 +666,7 @@ QVariant QJSManagedValue::toVariant() const
if (d->isString())
return QVariant(d->toQString());
if (QV4::Managed *m = d->as<QV4::Managed>())
- return m->engine()->toVariant(*d, -1, true);
+ return m->engine()->toVariant(*d, QMetaType{}, true);
Q_UNREACHABLE();
return QVariant();
@@ -740,8 +741,8 @@ bool QJSManagedValue::hasProperty(const QString &name) const
if (QV4::Object *obj = d->as<QV4::Object>()) {
QV4::Scope scope(obj->engine());
- QV4::ScopedString str(scope, obj->engine()->newString(name));
- return obj->hasProperty(str->toPropertyKey());
+ QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
+ return obj->hasProperty(key);
}
return prototype().hasProperty(name);
@@ -761,8 +762,8 @@ bool QJSManagedValue::hasOwnProperty(const QString &name) const
if (QV4::Object *obj = d->as<QV4::Object>()) {
QV4::Scope scope(obj->engine());
- QV4::ScopedString str(scope, obj->engine()->newString(name));
- return obj->getOwnProperty(str->toPropertyKey()) != QV4::Attr_Invalid;
+ QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
+ return obj->getOwnProperty(key) != QV4::Attr_Invalid;
}
return false;
@@ -790,8 +791,8 @@ QJSValue QJSManagedValue::property(const QString &name) const
if (QV4::Object *obj = d->as<QV4::Object>()) {
QV4::Scope scope(obj->engine());
- QV4::ScopedString str(scope, obj->engine()->newString(name));
- return QJSValuePrivate::fromReturnedValue(obj->get(str->toPropertyKey()));
+ QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
+ return QJSValuePrivate::fromReturnedValue(obj->get(key));
}
return prototype().property(name);
@@ -813,16 +814,15 @@ void QJSManagedValue::setProperty(const QString &name, const QJSValue &value)
}
if (QV4::Object *obj = d->as<QV4::Object>()) {
+ QV4::Scope scope(obj->engine());
QV4::ExecutionEngine *v4 = QJSValuePrivate::engine(&value);
- if (Q_UNLIKELY(v4 && v4 != obj->engine())) {
+ if (Q_UNLIKELY(v4 && v4 != scope.engine)) {
qWarning("QJSManagedValue::setProperty() failed: "
"Value was created in different engine.");
return;
}
- QV4::Scope scope(obj->engine());
- QV4::ScopedString str(scope, obj->engine()->newString(name));
- obj->put(str->toPropertyKey(),
- QJSValuePrivate::convertToReturnedValue(scope.engine, value));
+ QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
+ obj->put(key, QJSValuePrivate::convertToReturnedValue(scope.engine, value));
}
}
@@ -837,8 +837,8 @@ bool QJSManagedValue::deleteProperty(const QString &name)
if (QV4::Object *obj = d->as<QV4::Object>()) {
QV4::Scope scope(obj->engine());
- QV4::ScopedString str(scope, obj->engine()->newString(name));
- return obj->deleteProperty(str->toPropertyKey());
+ QV4::ScopedPropertyKey key(scope, scope.engine->identifierTable->asPropertyKey(name));
+ return obj->deleteProperty(key);
}
return false;
@@ -992,15 +992,15 @@ QJSValue QJSManagedValue::call(const QJSValueList &arguments) const
QV4::ExecutionEngine *engine = f->engine();
QV4::Scope scope(engine);
- QV4::JSCallData jsCallData(scope, arguments.length());
- *jsCallData->thisObject = engine->globalObject;
+ QV4::JSCallArguments jsCallData(scope, arguments.length());
+ *jsCallData.thisObject = engine->globalObject;
int i = 0;
for (const QJSValue &arg : arguments) {
if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, arg))) {
qWarning("QJSManagedValue::call() failed: Argument was created in different engine.");
return QJSValue();
}
- jsCallData->args[i++] = QJSValuePrivate::convertToReturnedValue(engine, arg);
+ jsCallData.args[i++] = QJSValuePrivate::convertToReturnedValue(engine, arg);
}
return QJSValuePrivate::fromReturnedValue(f->call(jsCallData));
@@ -1031,8 +1031,8 @@ QJSValue QJSManagedValue::callWithInstance(const QJSValue &instance,
}
QV4::Scope scope(engine);
- QV4::JSCallData jsCallData(scope, arguments.length());
- *jsCallData->thisObject = QJSValuePrivate::convertToReturnedValue(engine, instance);
+ QV4::JSCallArguments jsCallData(scope, arguments.length());
+ *jsCallData.thisObject = QJSValuePrivate::convertToReturnedValue(engine, instance);
int i = 0;
for (const QJSValue &arg : arguments) {
if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, arg))) {
@@ -1040,7 +1040,7 @@ QJSValue QJSManagedValue::callWithInstance(const QJSValue &instance,
"Argument was created in different engine.");
return QJSValue();
}
- jsCallData->args[i++] = QJSValuePrivate::convertToReturnedValue(engine, arg);
+ jsCallData.args[i++] = QJSValuePrivate::convertToReturnedValue(engine, arg);
}
return QJSValuePrivate::fromReturnedValue(f->call(jsCallData));
@@ -1064,7 +1064,7 @@ QJSValue QJSManagedValue::callAsConstructor(const QJSValueList &arguments) const
QV4::ExecutionEngine *engine = f->engine();
QV4::Scope scope(engine);
- QV4::JSCallData jsCallData(scope, arguments.length());
+ QV4::JSCallArguments jsCallData(scope, arguments.length());
int i = 0;
for (const QJSValue &arg : arguments) {
if (Q_UNLIKELY(!QJSValuePrivate::checkEngine(engine, arg))) {
@@ -1072,7 +1072,7 @@ QJSValue QJSManagedValue::callAsConstructor(const QJSValueList &arguments) const
"Argument was created in different engine.");
return QJSValue();
}
- jsCallData->args[i++] = QJSValuePrivate::convertToReturnedValue(engine, arg);
+ jsCallData.args[i++] = QJSValuePrivate::convertToReturnedValue(engine, arg);
}
return QJSValuePrivate::fromReturnedValue(f->callAsConstructor(jsCallData));
diff --git a/src/qml/jsapi/qjsprimitivevalue.h b/src/qml/jsapi/qjsprimitivevalue.h
index 5a82175783..363a2e8c43 100644
--- a/src/qml/jsapi/qjsprimitivevalue.h
+++ b/src/qml/jsapi/qjsprimitivevalue.h
@@ -144,7 +144,7 @@ class QJSPrimitiveValue
};
public:
- enum Type {
+ enum Type : quint8 {
Undefined,
Null,
Boolean,
@@ -153,16 +153,16 @@ public:
String
};
- constexpr Type type() const { return Type(d.index()); }
+ constexpr Type type() const { return Type(d.type()); }
- constexpr QJSPrimitiveValue() = default;
- constexpr QJSPrimitiveValue(QJSPrimitiveUndefined undefined) : d(undefined) {}
- constexpr QJSPrimitiveValue(QJSPrimitiveNull null) : d(null) {}
- constexpr QJSPrimitiveValue(bool value) : d(value) {}
- constexpr QJSPrimitiveValue(int value) : d(value) {}
- constexpr QJSPrimitiveValue(double value) : d(value) {}
- QJSPrimitiveValue(QString string) : d(std::move(string)) {}
- QJSPrimitiveValue(const QVariant &variant)
+ Q_IMPLICIT constexpr QJSPrimitiveValue() noexcept = default;
+ Q_IMPLICIT constexpr QJSPrimitiveValue(QJSPrimitiveUndefined undefined) noexcept : d(undefined) {}
+ Q_IMPLICIT constexpr QJSPrimitiveValue(QJSPrimitiveNull null) noexcept : d(null) {}
+ Q_IMPLICIT constexpr QJSPrimitiveValue(bool value) noexcept : d(value) {}
+ Q_IMPLICIT constexpr QJSPrimitiveValue(int value) noexcept : d(value) {}
+ Q_IMPLICIT constexpr QJSPrimitiveValue(double value) noexcept : d(value) {}
+ Q_IMPLICIT QJSPrimitiveValue(QString string) noexcept : d(std::move(string)) {}
+ explicit QJSPrimitiveValue(const QVariant &variant) noexcept
{
switch (variant.typeId()) {
case QMetaType::UnknownType:
@@ -194,13 +194,14 @@ public:
switch (type()) {
case Undefined: return false;
case Null: return false;
- case Boolean: return std::get<bool>(d);
- case Integer: return std::get<int>(d) != 0;
+ case Boolean: return asBoolean();
+ case Integer: return asInteger() != 0;
case Double: {
- const double v = std::get<double>(d);
+ const double v = asDouble();
return !QJSNumberCoercion::equals(v, 0) && !std::isnan(v);
}
- case String: return !std::get<QString>(d).isEmpty();
+ case String: return !asString().isEmpty();
+ default: Q_UNREACHABLE();
}
return false;
@@ -211,10 +212,11 @@ public:
switch (type()) {
case Undefined: return 0;
case Null: return 0;
- case Boolean: return std::get<bool>(d);
- case Integer: return std::get<int>(d);
- case Double: return QJSNumberCoercion::toInteger(std::get<double>(d));
- case String: return fromString(std::get<String>(d)).toInteger();
+ case Boolean: return asBoolean();
+ case Integer: return asInteger();
+ case Double: return QJSNumberCoercion::toInteger(asDouble());
+ case String: return fromString(asString()).toInteger();
+ default: Q_UNREACHABLE();
}
return 0;
@@ -225,13 +227,14 @@ public:
switch (type()) {
case Undefined: return std::numeric_limits<double>::quiet_NaN();
case Null: return 0;
- case Boolean: return std::get<bool>(d);
- case Integer: return std::get<int>(d);
- case Double: return std::get<double>(d);
- case String: return fromString(std::get<String>(d)).toDouble();
+ case Boolean: return asBoolean();
+ case Integer: return asInteger();
+ case Double: return asDouble();
+ case String: return fromString(asString()).toDouble();
+ default: Q_UNREACHABLE();
}
- return std::numeric_limits<double>::quiet_NaN();
+ return {};
}
QString toString() const
@@ -239,10 +242,10 @@ public:
switch (type()) {
case Undefined: return QStringLiteral("undefined");
case Null: return QStringLiteral("null");
- case Boolean: return std::get<bool>(d) ? QStringLiteral("true") : QStringLiteral("false");
- case Integer: return QString::number(std::get<int>(d));
+ case Boolean: return asBoolean() ? QStringLiteral("true") : QStringLiteral("false");
+ case Integer: return QString::number(asInteger());
case Double: {
- const double result = std::get<double>(d);
+ const double result = asDouble();
if (std::isnan(result))
return QStringLiteral("NaN");
if (std::isfinite(result))
@@ -251,7 +254,7 @@ public:
return QStringLiteral("Infinity");
return QStringLiteral("-Infinity");
}
- case String: return std::get<QString>(d);
+ case String: return asString();
}
Q_UNREACHABLE();
@@ -324,6 +327,43 @@ public:
return std::fmod(lhs.toDouble(), rhs.toDouble());
}
+ QJSPrimitiveValue &operator++()
+ {
+ // ++a is modeled as a -= (-1) to avoid the potential string concatenation
+ return (*this = operate<SubOperators>(*this, -1));
+ }
+
+ QJSPrimitiveValue operator++(int)
+ {
+ // a++ is modeled as a -= (-1) to avoid the potential string concatenation
+ QJSPrimitiveValue other = operate<SubOperators>(*this, -1);
+ std::swap(other, *this);
+ return +other; // We still need to coerce the original value.
+ }
+
+ QJSPrimitiveValue &operator--()
+ {
+ return (*this = operate<SubOperators>(*this, 1));
+ }
+
+ QJSPrimitiveValue operator--(int)
+ {
+ QJSPrimitiveValue other = operate<SubOperators>(*this, 1);
+ std::swap(other, *this);
+ return +other; // We still need to coerce the original value.
+ }
+
+ QJSPrimitiveValue operator+()
+ {
+ // +a is modeled as a -= 0. That should force it to number.
+ return (*this = operate<SubOperators>(*this, 0));
+ }
+
+ QJSPrimitiveValue operator-()
+ {
+ return (*this = operate<MulOperators>(*this, -1));
+ }
+
constexpr bool strictlyEquals(const QJSPrimitiveValue &other) const
{
const Type myType = type();
@@ -512,10 +552,10 @@ private:
friend class QJSManagedValue;
friend class QJSValue;
- constexpr bool asBoolean() const { return std::get<bool>(d); }
- constexpr int asInteger() const { return std::get<int>(d); }
- constexpr double asDouble() const { return std::get<double>(d); }
- QString asString() const { return std::get<QString>(d); }
+ constexpr bool asBoolean() const { return d.getBool(); }
+ constexpr int asInteger() const { return d.getInt(); }
+ constexpr double asDouble() const { return d.getDouble(); }
+ QString asString() const { return d.getString(); }
constexpr bool parsedEquals(const QJSPrimitiveValue &other) const
{
@@ -548,8 +588,8 @@ private:
const QJSPrimitiveValue &rhs)
{
int result;
- if (Operators::opOverflow(std::get<Lhs>(lhs.d), std::get<Rhs>(rhs.d), &result))
- return Operators::op(std::get<Lhs>(lhs.d), std::get<Rhs>(rhs.d));
+ if (Operators::opOverflow(lhs.d.get<Lhs>(), rhs.d.get<Rhs>(), &result))
+ return Operators::op(lhs.d.get<Lhs>(), rhs.d.get<Rhs>());
return result;
}
@@ -632,7 +672,145 @@ private:
}
}
- std::variant<QJSPrimitiveUndefined, QJSPrimitiveNull, bool, int, double, QString> d;
+ struct QJSPrimitiveValuePrivate
+ {
+ // Can't be default because QString has a non-trivial ctor.
+ constexpr QJSPrimitiveValuePrivate() noexcept {}
+
+ Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(QJSPrimitiveUndefined) noexcept {}
+ Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(QJSPrimitiveNull) noexcept
+ : m_type(Null) {}
+ Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(bool b) noexcept
+ : m_bool(b), m_type(Boolean) {}
+ Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(int i) noexcept
+ : m_int(i), m_type(Integer) {}
+ Q_IMPLICIT constexpr QJSPrimitiveValuePrivate(double d) noexcept
+ : m_double(d), m_type(Double) {}
+ Q_IMPLICIT QJSPrimitiveValuePrivate(QString s) noexcept
+ : m_string(std::move(s)), m_type(String) {}
+
+ constexpr QJSPrimitiveValuePrivate(const QJSPrimitiveValuePrivate &other) noexcept
+ : m_type(other.m_type)
+ {
+ // Not copy-and-swap since swap() would be much more complicated.
+ if (!assignSimple(other))
+ new (&m_string) QString(other.m_string);
+ }
+
+ constexpr QJSPrimitiveValuePrivate(QJSPrimitiveValuePrivate &&other) noexcept
+ : m_type(other.m_type)
+ {
+ // Not move-and-swap since swap() would be much more complicated.
+ if (!assignSimple(other))
+ new (&m_string) QString(std::move(other.m_string));
+ }
+
+ constexpr QJSPrimitiveValuePrivate &operator=(const QJSPrimitiveValuePrivate &other) noexcept
+ {
+ if (this == &other)
+ return *this;
+
+ if (m_type == String) {
+ if (other.m_type == String) {
+ m_type = other.m_type;
+ m_string = other.m_string;
+ return *this;
+ }
+ m_string.~QString();
+ }
+
+ m_type = other.m_type;
+ if (!assignSimple(other))
+ new (&m_string) QString(other.m_string);
+ return *this;
+ }
+
+ constexpr QJSPrimitiveValuePrivate &operator=(QJSPrimitiveValuePrivate &&other) noexcept
+ {
+ if (this == &other)
+ return *this;
+
+ if (m_type == String) {
+ if (other.m_type == String) {
+ m_type = other.m_type;
+ m_string = std::move(other.m_string);
+ return *this;
+ }
+ m_string.~QString();
+ }
+
+ m_type = other.m_type;
+ if (!assignSimple(other))
+ new (&m_string) QString(std::move(other.m_string));
+ return *this;
+ }
+
+ ~QJSPrimitiveValuePrivate()
+ {
+ if (m_type == String)
+ m_string.~QString();
+ }
+
+ constexpr Type type() const noexcept { return m_type; }
+ constexpr bool getBool() const noexcept { return m_bool; }
+ constexpr int getInt() const noexcept { return m_int; }
+ constexpr double getDouble() const noexcept { return m_double; }
+ QString getString() const noexcept { return m_string; }
+
+ template<typename T>
+ constexpr T get() const noexcept {
+ if constexpr (std::is_same_v<T, QJSPrimitiveUndefined>)
+ return QJSPrimitiveUndefined();
+ else if constexpr (std::is_same_v<T, QJSPrimitiveNull>)
+ return QJSPrimitiveNull();
+ else if constexpr (std::is_same_v<T, bool>)
+ return getBool();
+ else if constexpr (std::is_same_v<T, int>)
+ return getInt();
+ else if constexpr (std::is_same_v<T, double>)
+ return getDouble();
+ else if constexpr (std::is_same_v<T, QString>)
+ return getString();
+
+ Q_UNREACHABLE();
+ return T();
+ }
+
+ private:
+ constexpr bool assignSimple(const QJSPrimitiveValuePrivate &other) noexcept
+ {
+ switch (other.m_type) {
+ case Undefined:
+ case Null:
+ return true;
+ case Boolean:
+ m_bool = other.m_bool;
+ return true;
+ case Integer:
+ m_int = other.m_int;
+ return true;
+ case Double:
+ m_double = other.m_double;
+ return true;
+ case String:
+ return false;
+ default:
+ Q_UNREACHABLE();
+ }
+ return false;
+ }
+
+ union {
+ bool m_bool = false;
+ int m_int;
+ double m_double;
+ QString m_string;
+ };
+
+ Type m_type = Undefined;
+ };
+
+ QJSPrimitiveValuePrivate d;
};
QT_END_NAMESPACE
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 6d70c72722..0cff55ac9d 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -626,7 +626,7 @@ QVariant QJSValue::toVariant(QJSValue::ObjectConversionBehavior behavior) const
if (val.isString())
return QVariant(val.toQString());
if (QV4::Managed *m = val.as<QV4::Managed>())
- return m->engine()->toVariant(val, /*typeHint*/ -1, behavior == RetainJSObjects);
+ return m->engine()->toVariant(val, /*typeHint*/ QMetaType{}, behavior == RetainJSObjects);
Q_ASSERT(false);
return QVariant();
@@ -690,14 +690,14 @@ QJSValue QJSValue::call(const QJSValueList &args) const
Q_ASSERT(engine);
Scope scope(engine);
- JSCallData jsCallData(scope, args.length());
- *jsCallData->thisObject = engine->globalObject;
+ JSCallArguments jsCallData(scope, args.length());
+ *jsCallData.thisObject = engine->globalObject;
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::convertToReturnedValue(engine, args.at(i));
+ jsCallData.args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
}
ScopedValue result(scope, f->call(jsCallData));
@@ -744,14 +744,14 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
return QJSValue();
}
- JSCallData jsCallData(scope, args.size());
- *jsCallData->thisObject = QJSValuePrivate::convertToReturnedValue(engine, instance);
+ JSCallArguments jsCallData(scope, args.size());
+ *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::convertToReturnedValue(engine, args.at(i));
+ jsCallData.args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
}
ScopedValue result(scope, f->call(jsCallData));
@@ -791,13 +791,13 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args) const
Q_ASSERT(engine);
Scope scope(engine);
- JSCallData jsCallData(scope, args.size());
+ JSCallArguments jsCallData(scope, args.size());
for (int i = 0; i < args.size(); ++i) {
if (!QJSValuePrivate::checkEngine(engine, args.at(i))) {
qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
return QJSValue();
}
- jsCallData->args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
+ jsCallData.args[i] = QJSValuePrivate::convertToReturnedValue(engine, args.at(i));
}
ScopedValue result(scope, f->callAsConstructor(jsCallData));
@@ -911,7 +911,7 @@ QJSValue::QJSValue(QJSPrimitiveValue &&value)
d = QV4::Encode(value.asDouble());
return;
case QJSPrimitiveValue::String:
- QJSValuePrivate::setString(this, std::move(std::get<QString>(value.d)));
+ QJSValuePrivate::setString(this, value.asString());
return;
}
diff --git a/src/qml/jsapi/qjsvalue.h b/src/qml/jsapi/qjsvalue.h
index 1844ed0989..9bbc8c9f88 100644
--- a/src/qml/jsapi/qjsvalue.h
+++ b/src/qml/jsapi/qjsvalue.h
@@ -58,7 +58,6 @@ class QJSPrimitiveValue;
typedef QList<QJSValue> QJSValueList;
namespace QV4 {
struct ExecutionEngine;
- struct Value;
}
class QJSPrimitiveValue;
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 206e2b9aa4..46d0b511ca 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -51,7 +51,7 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ArgumentsObject);
DEFINE_OBJECT_VTABLE(StrictArgumentsObject);
-void Heap::StrictArgumentsObject::init(QV4::CppStackFrame *frame)
+void Heap::StrictArgumentsObject::init(QV4::JSTypesStackFrame *frame)
{
Q_ASSERT(vtable() == QV4::StrictArgumentsObject::staticVTable());
@@ -68,11 +68,11 @@ void Heap::StrictArgumentsObject::init(QV4::CppStackFrame *frame)
Scope scope(v4);
Scoped<QV4::StrictArgumentsObject> args(scope, this);
- args->arrayReserve(frame->originalArgumentsCount);
- args->arrayPut(0, frame->originalArguments, frame->originalArgumentsCount);
+ args->arrayReserve(frame->argc());
+ args->arrayPut(0, frame->argv(), frame->argc());
Q_ASSERT(args->internalClass()->verifyIndex(v4->id_length()->propertyKey(), LengthPropertyIndex));
- setProperty(v4, LengthPropertyIndex, Value::fromInt32(frame->originalArgumentsCount));
+ setProperty(v4, LengthPropertyIndex, Value::fromInt32(frame->argc()));
}
void Heap::ArgumentsObject::init(QV4::CppStackFrame *frame)
@@ -93,7 +93,7 @@ void Heap::ArgumentsObject::init(QV4::CppStackFrame *frame)
setProperty(v4, SymbolIteratorPropertyIndex, *v4->arrayProtoValues());
fullyCreated = false;
- argCount = frame->originalArgumentsCount;
+ argCount = frame->argc();
uint nFormals = frame->v4Function->nFormals;
mapped = nFormals > 63 ? std::numeric_limits<quint64>::max() : (1ull << nFormals) - 1;
}
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index f0e2192c7e..9e1fe10965 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -84,7 +84,7 @@ DECLARE_HEAP_OBJECT(StrictArgumentsObject, Object) {
CalleePropertyIndex = 2,
CalleeSetterPropertyIndex = 3
};
- void init(CppStackFrame *frame);
+ void init(JSTypesStackFrame *frame);
};
}
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 0eea3345c5..577cc11cf4 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -650,9 +650,9 @@ bool ArrayElementLessThan::operator()(Value v1, Value v2) const
if (o) {
Scope scope(o->engine());
ScopedValue result(scope);
- JSCallData jsCallData(scope, 2);
- jsCallData->args[0] = v1;
- jsCallData->args[1] = v2;
+ JSCallArguments jsCallData(scope, 2);
+ jsCallData.args[0] = v1;
+ jsCallData.args[1] = v2;
result = o->call(jsCallData);
if (scope.hasException())
return false;
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index df9f117d04..03e5c29973 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -254,6 +254,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
}
if (mapfn) {
+ Q_ASSERT(mapArguments); // if mapfn is set, we always setup mapArguments with scope.alloc
mapArguments[0] = *nextValue;
mapArguments[1] = Value::fromDouble(k);
mappedValue = mapfn->call(thisArg, mapArguments, 2);
@@ -297,6 +298,7 @@ ReturnedValue ArrayPrototype::method_from(const FunctionObject *builtin, const V
CHECK_EXCEPTION();
if (mapfn) {
+ Q_ASSERT(mapArguments); // if mapfn is set, we always setup mapArguments with scope.alloc
mapArguments[0] = kValue;
mapArguments[1] = Value::fromDouble(k);
mappedValue = mapfn->call(thisArg, mapArguments, 2);
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 018571e325..282046f3fa 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -95,12 +95,12 @@ Heap::CallContext *ExecutionContext::cloneBlockContext(ExecutionEngine *engine,
return c;
}
-Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame)
+Heap::CallContext *ExecutionContext::newCallContext(JSTypesStackFrame *frame)
{
Function *function = frame->v4Function;
Heap::ExecutionContext *outer = static_cast<Heap::ExecutionContext *>(frame->context()->m());
- uint nFormals = qMax(static_cast<uint>(frame->originalArgumentsCount), function->nFormals);
+ uint nFormals = qMax(static_cast<uint>(frame->argc()), function->nFormals);
uint localsAndFormals = function->compiledFunction->nLocals + nFormals;
size_t requiredMemory = sizeof(CallContext::Data) - sizeof(Value) + sizeof(Value) * (localsAndFormals);
@@ -122,9 +122,9 @@ Heap::CallContext *ExecutionContext::newCallContext(CppStackFrame *frame)
c->setupLocalTemporalDeadZone(compiledFunction);
Value *args = c->locals.values + nLocals;
- ::memcpy(args, frame->originalArguments, frame->originalArgumentsCount * sizeof(Value));
- c->nArgs = frame->originalArgumentsCount;
- for (uint i = frame->originalArgumentsCount; i < function->nFormals; ++i)
+ ::memcpy(args, frame->argv(), frame->argc() * sizeof(Value));
+ c->nArgs = frame->argc();
+ for (uint i = frame->argc(); i < function->nFormals; ++i)
args[i] = Encode::undefined();
return c;
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 75fa2d08e6..cc27d20fd4 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -152,7 +152,7 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
static Heap::CallContext *newBlockContext(QV4::CppStackFrame *frame, int blockIndex);
static Heap::CallContext *cloneBlockContext(ExecutionEngine *engine,
Heap::CallContext *callContext);
- static Heap::CallContext *newCallContext(QV4::CppStackFrame *frame);
+ static Heap::CallContext *newCallContext(JSTypesStackFrame *frame);
Heap::ExecutionContext *newWithContext(Heap::Object *with) const;
static Heap::ExecutionContext *newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName);
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 0c95950400..34fbd19a78 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -902,11 +902,6 @@ ExecutionEngine::~ExecutionEngine()
#endif
}
-ExecutionContext *ExecutionEngine::currentContext() const
-{
- return static_cast<ExecutionContext *>(&currentStackFrame->jsFrame->context);
-}
-
#if QT_CONFIG(qml_debug)
void ExecutionEngine::setDebugger(Debugging::Debugger *debugger)
{
@@ -1211,21 +1206,9 @@ Heap::Object *ExecutionEngine::newArrayIteratorObject(Object *o)
Heap::QmlContext *ExecutionEngine::qmlContext() const
{
- if (!currentStackFrame)
- return nullptr;
- Heap::ExecutionContext *ctx = currentContext()->d();
-
- if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !ctx->outer)
- return nullptr;
-
- while (ctx->outer && ctx->outer->type != Heap::ExecutionContext::Type_GlobalContext)
- ctx = ctx->outer;
-
- Q_ASSERT(ctx);
- if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
- return nullptr;
-
- return static_cast<Heap::QmlContext *>(ctx);
+ return currentStackFrame
+ ? static_cast<Heap::QmlContext *>(qmlContext(currentContext()->d()))
+ : nullptr;
}
QObject *ExecutionEngine::qmlScopeObject() const
@@ -1260,13 +1243,15 @@ StackTrace ExecutionEngine::stackTrace(int frameLimit) const
frame.line = qAbs(f->lineNumber());
frame.column = -1;
stack.append(frame);
- if (f->isTailCalling) {
- QV4::StackFrame frame;
- frame.function = QStringLiteral("[elided tail calls]");
- stack.append(frame);
+ if (f->isJSTypesFrame()) {
+ if (static_cast<JSTypesStackFrame *>(f)->isTailCalling()) {
+ QV4::StackFrame frame;
+ frame.function = QStringLiteral("[elided tail calls]");
+ stack.append(frame);
+ }
}
--frameLimit;
- f = f->parent;
+ f = f->parentFrame();
}
return stack;
@@ -1324,7 +1309,7 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
base = f->v4Function->finalUrl();
break;
}
- f = f->parent;
+ f = f->parentFrame();
}
if (base.isEmpty() && globalCode)
@@ -1499,10 +1484,10 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError()
// Variant conversion code
typedef QSet<QV4::Heap::Object *> V4ObjectSet;
-static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects);
+static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects);
static QObject *qtObjectFromJS(const QV4::Value &value);
static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects = nullptr);
-static bool convertToNativeQObject(const QV4::Value &value, const QByteArray &targetType, void **result);
+static bool convertToNativeQObject(const QV4::Value &value, QMetaType 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);
@@ -1511,17 +1496,11 @@ static QV4::ReturnedValue variantToJS(QV4::ExecutionEngine *v4, const QVariant &
return v4->metaTypeToJS(value.metaType(), value.constData());
}
-
-QVariant ExecutionEngine::toVariant(const Value &value, int typeHint, bool createJSValueForObjects)
-{
- return ::toVariant(this, value, typeHint, createJSValueForObjects, nullptr);
-}
-
-
-static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects)
+static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, QMetaType metaType, bool createJSValueForObjects, V4ObjectSet *visitedObjects)
{
Q_ASSERT (!value.isEmpty());
QV4::Scope scope(e);
+ int typeHint = metaType.id();
if (const QV4::VariantObject *v = value.as<QV4::VariantObject>())
return v->d()->data();
@@ -1532,7 +1511,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
if (typeHint == QMetaType::QJsonValue)
return QVariant::fromValue(QV4::JsonObject::toJsonValue(value));
- if (typeHint == qMetaTypeId<QJSValue>())
+ if (metaType == QMetaType::fromType<QJSValue>())
return QVariant::fromValue(QJSValuePrivate::fromReturnedValue(value.asReturnedValue()));
if (value.as<QV4::Object>()) {
@@ -1584,8 +1563,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
if (succeeded)
return retn;
#endif
- if (typeHint != -1) {
- auto metaType = QMetaType(typeHint);
+ if (metaType.isValid()) {
retn = QVariant(metaType, nullptr);
auto retnAsIterable = retn.value<QSequentialIterable>();
if (retnAsIterable.metaContainer().canAddValue()) {
@@ -1606,7 +1584,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
continue;
}
}
- asVariant = toVariant(e, arrayValue, valueMetaType.id(), false,
+ asVariant = toVariant(e, arrayValue, valueMetaType, false,
visitedObjects);
if (valueMetaType.id() != QMetaType::QVariant) {
auto originalType = asVariant.metaType();
@@ -1668,6 +1646,12 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int
return objectToVariant(e, o, visitedObjects);
}
+
+QVariant ExecutionEngine::toVariant(const Value &value, QMetaType typeHint, bool createJSValueForObjects)
+{
+ return ::toVariant(this, value, typeHint, createJSValueForObjects, nullptr);
+}
+
static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V4ObjectSet *visitedObjects)
{
Q_ASSERT(o);
@@ -1696,7 +1680,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V
int length = a->getLength();
for (int ii = 0; ii < length; ++ii) {
v = a->get(ii);
- list << ::toVariant(e, v, -1, /*createJSValueForObjects*/false, visitedObjects);
+ list << ::toVariant(e, v, QMetaType {}, /*createJSValueForObjects*/false, visitedObjects);
}
result = list;
@@ -1712,7 +1696,7 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V
break;
QString key = name->toQStringNoThrow();
- map.insert(key, ::toVariant(e, val, /*type hint*/-1, /*createJSValueForObjects*/false, visitedObjects));
+ map.insert(key, ::toVariant(e, val, /*type hint*/ QMetaType {}, /*createJSValueForObjects*/false, visitedObjects));
}
result = map;
@@ -1722,12 +1706,18 @@ static QVariant objectToVariant(QV4::ExecutionEngine *e, const QV4::Object *o, V
return result;
}
-QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
-{
- const QMetaType metaType = variant.metaType();
- int type = metaType.id();
- const void *ptr = variant.constData();
+/*!
+ \internal
+ Transform the given \a metaType and \a ptr into a JavaScript representation. You can pass an
+ optional \a variant in order to avoid the construction of a new QVariant in case the value
+ has to be stored as a variant object. In that case, the contents of \a variant have to be
+ exactly the same as \a metaType and \a ptr.
+ */
+QV4::ReturnedValue ExecutionEngine::fromData(
+ const QMetaType &metaType, const void *ptr, const QVariant *variant)
+{
+ const int type = metaType.id();
if (type < QMetaType::User) {
switch (QMetaType::Type(type)) {
case QMetaType::UnknownType:
@@ -1783,7 +1773,8 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
{
bool succeeded = false;
QV4::Scope scope(this);
- QV4::ScopedValue retn(scope, QV4::SequencePrototype::fromVariant(this, variant, &succeeded));
+ QV4::ScopedValue retn(
+ scope, QV4::SequencePrototype::fromData(this, metaType, ptr, &succeeded));
if (succeeded)
return retn->asReturnedValue();
return QV4::Encode(newArrayObject(*reinterpret_cast<const QStringList *>(ptr)));
@@ -1806,27 +1797,34 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
case QMetaType::QPixmap:
case QMetaType::QImage:
// Scarce value types
- return QV4::Encode(newVariantObject(variant));
+ return QV4::Encode(newVariantObject(variant ? *variant : QVariant(metaType, ptr)));
default:
break;
}
if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForMetaType(metaType))
- return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, metaType);
+ return QV4::QQmlValueTypeWrapper::create(this, ptr, vtmo, metaType);
} else {
QV4::Scope scope(this);
- if (type == qMetaTypeId<QQmlListReference>()) {
+ if (metaType == QMetaType::fromType<QQmlListReference>()) {
typedef QQmlListReferencePrivate QDLRP;
QDLRP *p = QDLRP::get((QQmlListReference*)const_cast<void *>(ptr));
- if (p->object) {
+ if (p->object)
return QV4::QmlListWrapper::create(scope.engine, p->property, p->propertyType);
- } else {
+ else
return QV4::Encode::null();
- }
- } else if (type == qMetaTypeId<QJSValue>()) {
+ } else if (auto flags = metaType.flags(); flags & QMetaType::IsQmlList) {
+ // casting to QQmlListProperty<QObject> is slightly nasty, but it's the
+ // same QQmlListReference does.
+ const auto *p = static_cast<const QQmlListProperty<QObject> *>(ptr);
+ if (p->object)
+ return QV4::QmlListWrapper::create(scope.engine, *p, metaType);
+ else
+ return QV4::Encode::null();
+ } else if (metaType == QMetaType::fromType<QJSValue>()) {
return QJSValuePrivate::convertToReturnedValue(
this, *reinterpret_cast<const QJSValue *>(ptr));
- } else if (type == qMetaTypeId<QList<QObject *> >()) {
+ } else if (metaType == QMetaType::fromType<QList<QObject *> >()) {
// XXX Can this be made more by using Array as a prototype and implementing
// directly against QList<QObject*>?
const QList<QObject *> &list = *(const QList<QObject *>*)ptr;
@@ -1852,25 +1850,32 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
#if QT_CONFIG(qml_sequence_object)
bool succeeded = false;
- QV4::ScopedValue retn(scope, QV4::SequencePrototype::fromVariant(this, variant, &succeeded));
+ QV4::ScopedValue retn(scope, QV4::SequencePrototype::fromData(this, metaType, ptr, &succeeded));
if (succeeded)
return retn->asReturnedValue();
#endif
- if (QMetaType::canConvert(variant.metaType(), QMetaType::fromType<QSequentialIterable>())) {
- QSequentialIterable lst = variant.value<QSequentialIterable>();
+
+ if (QMetaType::canConvert(metaType, QMetaType::fromType<QSequentialIterable>())) {
+ QSequentialIterable lst;
+ QMetaType::convert(metaType, ptr, QMetaType::fromType<QSequentialIterable>(), &lst);
return sequentialIterableToJS(this, lst);
}
if (const QMetaObject *vtmo = QQmlMetaType::metaObjectForMetaType(metaType))
- return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, metaType);
+ return QV4::QQmlValueTypeWrapper::create(this, ptr, vtmo, metaType);
}
// XXX TODO: To be compatible, we still need to handle:
// + QObjectList
// + QList<int>
- return QV4::Encode(newVariantObject(variant));
+ return QV4::Encode(newVariantObject(variant ? *variant : QVariant(metaType, ptr)));
+}
+
+QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
+{
+ return fromData(variant.metaType(), variant.constData(), &variant);
}
QVariantMap ExecutionEngine::variantMapFromJS(const Object *o)
@@ -1940,13 +1945,13 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(QMetaType type, const void *dat
{
Q_ASSERT(data != nullptr);
- QVariant variant(type, data);
- if (QMetaType::Type(variant.userType()) == QMetaType::QVariant) {
+ if (type == QMetaType::fromType<QVariant>()) {
// unwrap it: this is tested in QJSEngine, and makes the most sense for
// end-user code too.
- return variantToJS(this, *reinterpret_cast<const QVariant*>(data));
+ return fromVariant(*reinterpret_cast<const QVariant*>(data));
}
- return fromVariant(variant);
+
+ return fromData(type, data);
}
int ExecutionEngine::maxJSStackSize() const
@@ -2074,10 +2079,10 @@ ReturnedValue ExecutionEngine::callInContext(Function *function, QObject *self,
return Encode::undefined();
// use JSCallData to pass arguments into the function call
- QV4::JSCallData jsCall(scope, argc);
+ QV4::JSCallArguments jsCall(scope, argc);
QV4::populateJSCallArguments(this, jsCall, argc, args, types);
- QV4::CallData *callData = jsCall->callData();
+ QV4::CallData *callData = jsCall.callData(scope);
return function->call(selfValue, callData->argValues<QV4::Value>(), callData->argc(),
qmlContext);
}
@@ -2217,10 +2222,10 @@ 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, QMetaType metaType, void *data)
{
// check if it's one of the types we know
- switch (QMetaType::Type(type)) {
+ switch (metaType.id()) {
case QMetaType::Bool:
*reinterpret_cast<bool*>(data) = value.toBoolean();
return true;
@@ -2322,7 +2327,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value &value, int type, void *data)
const QV4::ArrayObject *a = value.as<QV4::ArrayObject>();
if (a) {
*reinterpret_cast<QVariantList *>(data) = a->engine()->toVariant(
- *a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
+ *a, /*typeHint*/QMetaType{}, /*createJSValueForObjects*/false).toList();
return true;
}
break;
@@ -2337,7 +2342,7 @@ bool ExecutionEngine::metaTypeFromJS(const Value &value, int type, void *data)
}
case QMetaType::QVariant:
if (const QV4::Managed *m = value.as<QV4::Managed>())
- *reinterpret_cast<QVariant*>(data) = m->engine()->toVariant(value, /*typeHint*/-1, /*createJSValueForObjects*/false);
+ *reinterpret_cast<QVariant*>(data) = m->engine()->toVariant(value, /*typeHint*/QMetaType{}, /*createJSValueForObjects*/false);
else if (value.isNull())
*reinterpret_cast<QVariant*>(data) = QVariant::fromValue(nullptr);
else if (value.isUndefined())
@@ -2369,18 +2374,23 @@ bool ExecutionEngine::metaTypeFromJS(const Value &value, int type, void *data)
}
{
- const QMetaType metaType(type);
if (metaType.flags() & QMetaType::IsEnumeration) {
*reinterpret_cast<int *>(data) = value.toInt32();
return true;
}
+
+ if (metaType == QMetaType::fromType<QQmlListReference>()) {
+ if (const QV4::QmlListWrapper *wrapper = value.as<QV4::QmlListWrapper>()) {
+ *reinterpret_cast<QQmlListReference *>(data) = wrapper->toListReference();
+ return true;
+ }
+ }
}
{
const QQmlValueTypeWrapper *vtw = value.as<QQmlValueTypeWrapper>();
- if (vtw && vtw->typeId() == type) {
+ if (vtw && vtw->type() == metaType)
return vtw->toGadget(data);
- }
}
#if 0
@@ -2404,13 +2414,15 @@ bool ExecutionEngine::metaTypeFromJS(const Value &value, int type, void *data)
// Try to use magic; for compatibility with qjsvalue_cast.
- QByteArray name = QMetaType(type).name();
- if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(data)))
+ if (convertToNativeQObject(value, metaType, reinterpret_cast<void **>(data)))
return true;
- if (value.as<QV4::VariantObject>() && name.endsWith('*')) {
- int valueType = QMetaType::fromName(name.left(name.size()-1)).id();
+
+ const bool isPointer = (metaType.flags() & QMetaType::IsPointer);
+ if (value.as<QV4::VariantObject>() && isPointer) {
+ const QByteArray pointedToTypeName = QByteArray(metaType.name()).chopped(1);
+ const QMetaType valueType = QMetaType::fromName(pointedToTypeName);
QVariant &var = value.as<QV4::VariantObject>()->d()->data();
- if (valueType == var.userType()) {
+ if (valueType == var.metaType()) {
// We have T t, T* is requested, so return &t.
*reinterpret_cast<void* *>(data) = var.data();
return true;
@@ -2422,17 +2434,20 @@ bool ExecutionEngine::metaTypeFromJS(const Value &value, int type, void *data)
bool canCast = false;
if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
const QVariant &v = vo->d()->data();
- canCast = (type == v.userType()) || (valueType && (valueType == v.userType()));
+ canCast = (metaType == v.metaType());
}
else if (proto->as<QV4::QObjectWrapper>()) {
- QByteArray className = name.left(name.size()-1);
QV4::ScopedObject p(scope, proto.getPointer());
- if (QObject *qobject = qtObjectFromJS(p))
- canCast = qobject->qt_metacast(className) != nullptr;
+ if (QObject *qobject = qtObjectFromJS(p)) {
+ if (const QMetaObject *metaObject = metaType.metaObject())
+ canCast = metaObject->cast(qobject) != nullptr;
+ else
+ canCast = qobject->qt_metacast(pointedToTypeName);
+ }
}
if (canCast) {
- QByteArray varTypeName = QMetaType(var.userType()).name();
- if (varTypeName.endsWith('*'))
+ const QMetaType varType = var.metaType();
+ if (varType.flags() & QMetaType::IsPointer)
*reinterpret_cast<void* *>(data) = *reinterpret_cast<void* *>(var.data());
else
*reinterpret_cast<void* *>(data) = var.data();
@@ -2441,10 +2456,10 @@ bool ExecutionEngine::metaTypeFromJS(const Value &value, int type, void *data)
proto = proto->getPrototypeOf();
}
}
- } else if (value.isNull() && name.endsWith('*')) {
+ } else if (value.isNull() && isPointer) {
*reinterpret_cast<void* *>(data) = nullptr;
return true;
- } else if (type == qMetaTypeId<QJSValue>()) {
+ } else if (metaType == QMetaType::fromType<QJSValue>()) {
QJSValuePrivate::setValue(reinterpret_cast<QJSValue*>(data), value.asReturnedValue());
return true;
}
@@ -2452,13 +2467,25 @@ bool ExecutionEngine::metaTypeFromJS(const Value &value, int type, void *data)
return false;
}
-static bool convertToNativeQObject(const QV4::Value &value, const QByteArray &targetType, void **result)
+static bool convertToNativeQObject(const QV4::Value &value, QMetaType targetType, void **result)
{
- if (!targetType.endsWith('*'))
+ if (!(targetType.flags() & QMetaType::IsPointer))
return false;
if (QObject *qobject = qtObjectFromJS(value)) {
- int start = targetType.startsWith("const ") ? 6 : 0;
- QByteArray className = targetType.mid(start, targetType.size()-start-1);
+ // If the target type has a metaObject, use that for casting.
+ if (const QMetaObject *targetMetaObject = targetType.metaObject()) {
+ if (QObject *instance = targetMetaObject->cast(qobject)) {
+ *result = instance;
+ return true;
+ }
+ return false;
+ }
+
+ // We have to call the generated qt_metacast rather than metaObject->cast() here so that
+ // it works for types without QMetaObject, such as QStandardItem.
+ const QByteArray targetTypeName = targetType.name();
+ const int start = targetTypeName.startsWith("const ") ? 6 : 0;
+ const QByteArray className = targetTypeName.mid(start, targetTypeName.size() - start - 1);
if (void *instance = qobject->qt_metacast(className)) {
*result = instance;
return true;
@@ -2482,9 +2509,14 @@ static QObject *qtObjectFromJS(const QV4::Value &value)
return *reinterpret_cast<QObject* const *>(variant.constData());
}
QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, value);
- if (!wrapper)
- return nullptr;
- return wrapper->object();
+ if (wrapper)
+ return wrapper->object();
+
+ QV4::Scoped<QV4::QQmlTypeWrapper> typeWrapper(scope, value);
+ if (typeWrapper)
+ return typeWrapper->object();
+
+ return nullptr;
}
struct QV4EngineRegistrationData
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 6c3d2d4436..96aad5ee72 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -561,7 +561,10 @@ public:
void setProfiler(Profiling::Profiler *profiler);
#endif // QT_CONFIG(qml_debug)
- ExecutionContext *currentContext() const;
+ ExecutionContext *currentContext() const
+ {
+ return static_cast<ExecutionContext *>(&currentStackFrame->jsFrame->context);
+ }
// ensure we always get odd prototype IDs. This helps make marking in QV4::Lookup fast
quintptr newProtoId() { return (protoIdCount += 2); }
@@ -623,6 +626,25 @@ public:
Heap::Object *newMapIteratorObject(Object *o);
Heap::Object *newArrayIteratorObject(Object *o);
+ static Heap::ExecutionContext *qmlContext(Heap::ExecutionContext *ctx)
+ {
+ Heap::ExecutionContext *outer = ctx->outer;
+
+ if (ctx->type != Heap::ExecutionContext::Type_QmlContext && !outer)
+ return nullptr;
+
+ while (outer && outer->type != Heap::ExecutionContext::Type_GlobalContext) {
+ ctx = outer;
+ outer = ctx->outer;
+ }
+
+ Q_ASSERT(ctx);
+ if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
+ return nullptr;
+
+ return ctx;
+ }
+
Heap::QmlContext *qmlContext() const;
QObject *qmlScopeObject() const;
QQmlRefPointer<QQmlContextData> callingQmlContext() const;
@@ -659,12 +681,12 @@ public:
QQmlError catchExceptionAsQmlError();
// variant conversions
- QVariant toVariant(const QV4::Value &value, int typeHint, bool createJSValueForObjects = true);
+ QVariant toVariant(const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjects = true);
QV4::ReturnedValue fromVariant(const QVariant &);
QVariantMap variantMapFromJS(const QV4::Object *o);
- static bool metaTypeFromJS(const Value &value, int type, void *data);
+ static bool metaTypeFromJS(const Value &value, QMetaType type, void *data);
QV4::ReturnedValue metaTypeToJS(QMetaType type, const void *data);
int maxJSStackSize() const;
@@ -747,6 +769,9 @@ public:
QQmlRefPointer<QQmlContextData> ctxtdata, int argc, void **args, QMetaType *types);
private:
+ QV4::ReturnedValue fromData(
+ const QMetaType &type, const void *ptr, const QVariant *variant = nullptr);
+
#if QT_CONFIG(qml_debug)
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
QScopedPointer<QV4::Profiling::Profiler> m_profiler;
diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h
index 612c2dd453..9997c477bf 100644
--- a/src/qml/jsruntime/qv4enginebase_p.h
+++ b/src/qml/jsruntime/qv4enginebase_p.h
@@ -60,10 +60,6 @@ namespace QV4 {
struct CppStackFrame;
// Base class for the execution engine
-
-#if defined(Q_CC_MSVC) || defined(Q_CC_GNU)
-#pragma pack(push, 1)
-#endif
struct Q_QML_EXPORT EngineBase {
CppStackFrame *currentStackFrame = nullptr;
@@ -88,7 +84,9 @@ struct Q_QML_EXPORT EngineBase {
MemoryManager *memoryManager = nullptr;
qint32 callDepth = 0;
- quint8 padding2[QT_POINTER_SIZE - sizeof(quint32)];
+#if QT_POINTER_SIZE == 8
+ quint32 padding2;
+#endif
Object *globalObject = nullptr;
Value *jsStackLimit = nullptr;
Value *jsStackBase = nullptr;
@@ -137,9 +135,6 @@ struct Q_QML_EXPORT EngineBase {
Heap::InternalClass *classes[NClasses];
Heap::InternalClass *internalClasses(InternalClassType icType) { return classes[icType]; }
};
-#if defined(Q_CC_MSVC) || defined(Q_CC_GNU)
-#pragma pack(pop)
-#endif
Q_STATIC_ASSERT(std::is_standard_layout<EngineBase>::value);
Q_STATIC_ASSERT(offsetof(EngineBase, currentStackFrame) == 0);
diff --git a/src/qml/jsruntime/qv4executablecompilationunit.cpp b/src/qml/jsruntime/qv4executablecompilationunit.cpp
index 8ef8ae2221..01c8f0a7c9 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit.cpp
+++ b/src/qml/jsruntime/qv4executablecompilationunit.cpp
@@ -401,6 +401,7 @@ IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(int com
const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr);
namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
}
+ Q_ASSERT(!namedObjectCache.isEmpty());
return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
}
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h
index 1b1b9add5c..3dc0e58ca5 100644
--- a/src/qml/jsruntime/qv4executablecompilationunit_p.h
+++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h
@@ -319,6 +319,7 @@ IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int component
auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
if (Q_UNLIKELY(it == namedObjectsPerComponentCache.end()))
return createNamedObjectsPerComponent(componentObjectIndex);
+ Q_ASSERT(!it->isEmpty());
return *it;
}
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index 8164bae549..348837c3a5 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -51,26 +51,53 @@
#include <assembler/MacroAssemblerCodeRef.h>
#include <private/qv4vme_moth_p.h>
#include <private/qqmlglobal_p.h>
+#include <private/qv4jscall_p.h>
QT_BEGIN_NAMESPACE
using namespace QV4;
-ReturnedValue Function::call(const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context) {
+void Function::call(const Value *thisObject, void **a, const QMetaType *types, int argc,
+ const ExecutionContext *context)
+{
+ if (!aotFunction) {
+ QV4::convertAndCall(context->engine(), thisObject, a, types, argc,
+ [this, context](const Value *thisObject, const Value *argv, int argc) {
+ return call(thisObject, argv, argc, context);
+ });
+ return;
+ }
+
ExecutionEngine *engine = context->engine();
- CppStackFrame frame;
- frame.init(engine, this, argv, argc);
+ MetaTypesStackFrame frame;
+ frame.init(this, a, types, argc);
frame.setupJSFrame(engine->jsStackTop, Value::undefinedValue(), context->d(),
- thisObject ? *thisObject : Value::undefinedValue(),
- Value::undefinedValue());
-
- frame.push();
+ thisObject ? *thisObject : Value::undefinedValue());
+ frame.push(engine);
engine->jsStackTop += frame.requiredJSStackFrameSize();
+ Moth::VME::exec(&frame, engine);
+ frame.pop(engine);
+}
- ReturnedValue result = Moth::VME::exec(&frame, engine);
-
- frame.pop();
+ReturnedValue Function::call(const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context) {
+ if (aotFunction) {
+ return QV4::convertAndCall(
+ context->engine(), aotFunction, thisObject, argv, argc,
+ [this, context](const Value *thisObject,
+ void **a, const QMetaType *types, int argc) {
+ call(thisObject, a, types, argc, context);
+ });
+ }
+ ExecutionEngine *engine = context->engine();
+ JSTypesStackFrame frame;
+ frame.init(this, argv, argc);
+ frame.setupJSFrame(engine->jsStackTop, Value::undefinedValue(), context->d(),
+ thisObject ? *thisObject : Value::undefinedValue());
+ engine->jsStackTop += frame.requiredJSStackFrameSize();
+ frame.push(engine);
+ ReturnedValue result = Moth::VME::exec(&frame, engine);
+ frame.pop(engine);
return result;
}
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index c022f84205..a15344dacd 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -100,6 +100,8 @@ public:
return compilationUnit->runtimeStrings[i];
}
+ void call(const Value *thisObject, void **a, const QMetaType *types, int argc,
+ const ExecutionContext *context);
ReturnedValue call(const Value *thisObject, const Value *argv, int argc, const ExecutionContext *context);
const char *codeData;
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 3f0a316af7..d3bafbe055 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -70,9 +70,11 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
-void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name, VTable::Call call)
+void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name,
+ VTable::Call call, VTable::CallWithMetaTypes callWithMetaTypes)
{
jsCall = call;
+ jsCallWithMetaTypes = callWithMetaTypes;
jsConstruct = nullptr;
Object::init();
@@ -88,6 +90,7 @@ void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name)
ExecutionEngine *e = scope->engine();
jsCall = vtable()->call;
+ jsCallWithMetaTypes = vtable()->callWithMetaTypes;
jsConstruct = vtable()->callAsConstructor;
Object::init();
@@ -103,6 +106,7 @@ void Heap::FunctionObject::init(QV4::ExecutionContext *scope, QV4::String *name)
void Heap::FunctionObject::init(QV4::ExecutionContext *scope, Function *function, QV4::String *n)
{
jsCall = vtable()->call;
+ jsCallWithMetaTypes = vtable()->callWithMetaTypes;
jsConstruct = vtable()->callAsConstructor;
Object::init();
@@ -125,6 +129,7 @@ void Heap::FunctionObject::init(QV4::ExecutionContext *scope, const QString &nam
void Heap::FunctionObject::init()
{
jsCall = vtable()->call;
+ jsCallWithMetaTypes = vtable()->callWithMetaTypes;
jsConstruct = vtable()->callAsConstructor;
Object::init();
@@ -156,6 +161,19 @@ void FunctionObject::createDefaultPrototypeProperty(uint protoConstructorSlot)
defineDefaultProperty(s.engine->id_prototype(), proto, Attr_NotEnumerable|Attr_NotConfigurable);
}
+void FunctionObject::call(const Value *thisObject, void **a, const QMetaType *types, int argc)
+{
+ if (const auto callWithMetaTypes = d()->jsCallWithMetaTypes) {
+ callWithMetaTypes(this, thisObject, a, types, argc);
+ return;
+ }
+
+ QV4::convertAndCall(engine(), thisObject, a, types, argc,
+ [this](const Value *thisObject, const Value *argv, int argc) {
+ return call(thisObject, argv, argc);
+ });
+}
+
ReturnedValue FunctionObject::name() const
{
return get(scope()->internalClass->engine->id_name());
@@ -166,6 +184,11 @@ ReturnedValue FunctionObject::virtualCall(const FunctionObject *, const Value *,
return Encode::undefined();
}
+void FunctionObject::virtualCallWithMetaTypes(
+ const FunctionObject *, const Value *, void **, const QMetaType *, int)
+{
+}
+
Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function)
{
if (function->isArrowFunction())
@@ -487,18 +510,18 @@ ReturnedValue ScriptFunction::virtualCallAsConstructor(const FunctionObject *fo,
}
ScopedValue thisObject(scope, v4->memoryManager->allocObject<Object>(ic));
- CppStackFrame frame;
- frame.init(v4, f->function(), argv, argc);
+ JSTypesStackFrame frame;
+ frame.init(f->function(), argv, argc);
frame.setupJSFrame(v4->jsStackTop, *f, f->scope(),
thisObject,
newTarget ? *newTarget : Value::undefinedValue());
- frame.push();
+ frame.push(v4);
v4->jsStackTop += frame.requiredJSStackFrameSize();
ReturnedValue result = Moth::VME::exec(&frame, v4);
- frame.pop();
+ frame.pop(v4);
if (Q_UNLIKELY(v4->hasException))
return Encode::undefined();
@@ -509,27 +532,57 @@ ReturnedValue ScriptFunction::virtualCallAsConstructor(const FunctionObject *fo,
DEFINE_OBJECT_VTABLE(ArrowFunction);
+void ArrowFunction::virtualCallWithMetaTypes(const FunctionObject *fo, const Value *thisObject,
+ void **a, const QMetaType *types, int argc)
+{
+ if (!fo->function()->aotFunction) {
+ QV4::convertAndCall(fo->engine(), thisObject, a, types, argc,
+ [fo](const Value *thisObject, const Value *argv, int argc) {
+ return ArrowFunction::virtualCall(fo, thisObject, argv, argc);
+ });
+ return;
+ }
+
+ ExecutionEngine *engine = fo->engine();
+ MetaTypesStackFrame frame;
+ frame.init(fo->function(), a, types, argc);
+ frame.setupJSFrame(engine->jsStackTop, *fo, fo->scope(),
+ thisObject ? *thisObject : Value::undefinedValue());
+
+ frame.push(engine);
+ engine->jsStackTop += frame.requiredJSStackFrameSize();
+ Moth::VME::exec(&frame, engine);
+ frame.pop(engine);
+}
+
ReturnedValue ArrowFunction::virtualCall(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc)
{
+ if (const auto *aotFunction = fo->function()->aotFunction) {
+ return QV4::convertAndCall(
+ fo->engine(), aotFunction, thisObject, argv, argc,
+ [fo](const Value *thisObject, void **a, const QMetaType *types, int argc) {
+ ArrowFunction::virtualCallWithMetaTypes(fo, thisObject, a, types, argc);
+ });
+ }
+
ExecutionEngine *engine = fo->engine();
- CppStackFrame frame;
- frame.init(engine, fo->function(), argv, argc, true);
+ JSTypesStackFrame frame;
+ frame.init(fo->function(), argv, argc, true);
frame.setupJSFrame(engine->jsStackTop, *fo, fo->scope(),
- thisObject ? *thisObject : Value::undefinedValue(),
- Value::undefinedValue());
+ thisObject ? *thisObject : Value::undefinedValue());
- frame.push();
+ frame.push(engine);
engine->jsStackTop += frame.requiredJSStackFrameSize();
ReturnedValue result;
do {
- frame.pendingTailCall = false;
+ frame.setPendingTailCall(false);
result = Moth::VME::exec(&frame, engine);
- frame.isTailCalling = true;
- } while (frame.pendingTailCall);
+ frame.setTailCalling(true);
+ } while (frame.pendingTailCall());
- frame.pop();
+ frame.pop(engine);
return result;
}
@@ -590,19 +643,19 @@ ReturnedValue ConstructorFunction::virtualCallAsConstructor(const FunctionObject
ExecutionEngine *v4 = f->engine();
- CppStackFrame frame;
- frame.init(v4, f->function(), argv, argc);
+ JSTypesStackFrame frame;
+ frame.init(f->function(), argv, argc);
frame.setupJSFrame(v4->jsStackTop, *f, f->scope(),
Value::emptyValue(),
newTarget ? *newTarget : Value::undefinedValue());
- frame.push();
+ frame.push(v4);
v4->jsStackTop += frame.requiredJSStackFrameSize();
ReturnedValue result = Moth::VME::exec(&frame, v4);
ReturnedValue thisObject = frame.jsFrame->thisObject.asReturnedValue();
- frame.pop();
+ frame.pop(v4);
if (Q_UNLIKELY(v4->hasException))
return Encode::undefined();
@@ -644,20 +697,20 @@ ReturnedValue DefaultClassConstructorFunction::virtualCallAsConstructor(const Fu
ScopedFunctionObject super(scope, f->getPrototypeOf());
Q_ASSERT(super->isFunctionObject());
- CppStackFrame frame;
- frame.init(v4, nullptr, argv, argc);
+ JSTypesStackFrame frame;
+ frame.init(nullptr, argv, argc);
frame.setupJSFrame(v4->jsStackTop, *f, f->scope(),
Value::undefinedValue(),
newTarget ? *newTarget : Value::undefinedValue(), argc, argc);
- frame.push();
+ frame.push(v4);
v4->jsStackTop += frame.requiredJSStackFrameSize(argc);
// Do a super call
ReturnedValue result = super->callAsConstructor(argv, argc, newTarget);
ReturnedValue thisObject = frame.jsFrame->thisObject.asReturnedValue();
- frame.pop();
+ frame.pop(v4);
if (Q_UNLIKELY(v4->hasException))
return Encode::undefined();
@@ -722,9 +775,9 @@ ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *
Scope scope(v4);
Scoped<MemberData> boundArgs(scope, f->boundArgs());
ScopedFunctionObject target(scope, f->target());
- JSCallData jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc);
- *jsCallData->thisObject = f->boundThis();
- Value *argp = jsCallData->args;
+ JSCallArguments jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc);
+ *jsCallData.thisObject = f->boundThis();
+ Value *argp = jsCallData.args;
if (boundArgs) {
memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
argp += boundArgs->size();
@@ -743,8 +796,8 @@ ReturnedValue BoundFunction::virtualCallAsConstructor(const FunctionObject *fo,
Scoped<MemberData> boundArgs(scope, f->boundArgs());
ScopedFunctionObject target(scope, f->target());
- JSCallData jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc);
- Value *argp = jsCallData->args;
+ JSCallArguments jsCallData(scope, (boundArgs ? boundArgs->size() : 0) + argc);
+ Value *argp = jsCallData.args;
if (boundArgs) {
memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
argp += boundArgs->size();
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 78be58c60a..741519389e 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -72,6 +72,7 @@ namespace Heap {
Member(class, NoMark, Function *, function) \
Member(class, NoMark, VTable::Call, jsCall) \
Member(class, NoMark, VTable::CallAsConstructor, jsConstruct) \
+ Member(class, NoMark, VTable::CallWithMetaTypes, jsCallWithMetaTypes) \
Member(class, NoMark, bool, canBeTailCalled)
DECLARE_HEAP_OBJECT(FunctionObject, Object) {
@@ -86,7 +87,9 @@ DECLARE_HEAP_OBJECT(FunctionObject, Object) {
return jsConstruct != nullptr;
}
- Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::String *name, VTable::Call call);
+ Q_QML_PRIVATE_EXPORT void init(
+ QV4::ExecutionContext *scope, QV4::String *name,
+ VTable::Call call, VTable::CallWithMetaTypes callWithMetaTypes = nullptr);
Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::String *name = nullptr);
Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, QV4::Function *function, QV4::String *n = nullptr);
Q_QML_PRIVATE_EXPORT void init(QV4::ExecutionContext *scope, const QString &name);
@@ -202,6 +205,9 @@ struct Q_QML_EXPORT FunctionObject: Object {
return d()->jsCall(this, thisObject, argv, argc);
}
static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
+ void call(const Value *thisObject, void **a, const QMetaType *types, int argc);
+ static void virtualCallWithMetaTypes(const FunctionObject *f, const Value *thisObject,
+ void **a, const QMetaType *types, int argc);
static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function);
static Heap::FunctionObject *createConstructorFunction(ExecutionContext *scope, Function *function, Object *homeObject, bool isDerivedConstructor);
@@ -277,6 +283,8 @@ struct ArrowFunction : FunctionObject {
V4_INTERNALCLASS(ArrowFunction)
enum { NInlineProperties = 3 };
+ static void virtualCallWithMetaTypes(const FunctionObject *f, const Value *thisObject,
+ void **a, const QMetaType *types, int argc);
static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc);
};
diff --git a/src/qml/jsruntime/qv4generatorobject.cpp b/src/qml/jsruntime/qv4generatorobject.cpp
index 4eee6f4338..d13b0e1ce1 100644
--- a/src/qml/jsruntime/qv4generatorobject.cpp
+++ b/src/qml/jsruntime/qv4generatorobject.cpp
@@ -97,33 +97,30 @@ ReturnedValue GeneratorFunction::virtualCall(const FunctionObject *f, const Valu
Function *function = gf->function();
ExecutionEngine *engine = gf->engine();
- // We need to set up a separate stack for the generator, as it's being re-entered
- uint stackSize = argc // space for the original arguments
- + CppStackFrame::requiredJSStackFrameSize(function); // space for the JS stack frame
-
- size_t requiredMemory = sizeof(GeneratorObject::Data) - sizeof(Value) + sizeof(Value) * stackSize;
-
Scope scope(gf);
- Scoped<GeneratorObject> g(scope, scope.engine->memoryManager->allocManaged<GeneratorObject>(requiredMemory, scope.engine->classes[EngineBase::Class_GeneratorObject]));
+ Scoped<GeneratorObject> g(scope, engine->memoryManager->allocManaged<GeneratorObject>(sizeof(GeneratorObject::Data), engine->classes[EngineBase::Class_GeneratorObject]));
g->setPrototypeOf(ScopedObject(scope, gf->get(scope.engine->id_prototype())));
+ // We need to set up a separate JSFrame for the generator, as it's being re-entered
Heap::GeneratorObject *gp = g->d();
- gp->stack.size = stackSize;
- gp->stack.alloc = stackSize;
+ gp->values.set(engine, engine->newArrayObject(argc));
+ gp->jsFrame.set(engine, engine->newArrayObject(CppStackFrame::requiredJSStackFrameSize(function)));
// copy original arguments
- memcpy(gp->stack.values, argv, argc*sizeof(Value));
- gp->cppFrame.init(engine, function, gp->stack.values, argc);
- gp->cppFrame.setupJSFrame(&gp->stack.values[argc], *gf, gf->scope(),
+ for (int i = 0; i < argc; i++)
+ gp->values->arrayData->setArrayData(engine, i, argv[i]);
+
+ gp->cppFrame.init(function, gp->values->arrayData->values.values, argc);
+ gp->cppFrame.setupJSFrame(gp->jsFrame->arrayData->values.values, *gf, gf->scope(),
thisObject ? *thisObject : Value::undefinedValue(),
Value::undefinedValue());
- gp->cppFrame.push();
+ gp->cppFrame.push(engine);
Moth::VME::interpret(&gp->cppFrame, engine, function->codeData);
gp->state = GeneratorState::SuspendedStart;
- gp->cppFrame.pop();
+ gp->cppFrame.pop(engine);
return g->asReturnedValue();
}
@@ -217,25 +214,25 @@ ReturnedValue GeneratorObject::resume(ExecutionEngine *engine, const Value &arg)
{
Heap::GeneratorObject *gp = d();
gp->state = GeneratorState::Executing;
- gp->cppFrame.parent = engine->currentStackFrame;
+ gp->cppFrame.setParentFrame(engine->currentStackFrame);
engine->currentStackFrame = &gp->cppFrame;
- Q_ASSERT(gp->cppFrame.yield != nullptr);
- const char *code = gp->cppFrame.yield;
- gp->cppFrame.yield = nullptr;
+ Q_ASSERT(gp->cppFrame.yield() != nullptr);
+ const char *code = gp->cppFrame.yield();
+ gp->cppFrame.setYield(nullptr);
gp->cppFrame.jsFrame->accumulator = arg;
- gp->cppFrame.yieldIsIterator = false;
+ gp->cppFrame.setYieldIsIterator(false);
Scope scope(engine);
ScopedValue result(scope, Moth::VME::interpret(&gp->cppFrame, engine, code));
- engine->currentStackFrame = gp->cppFrame.parent;
+ engine->currentStackFrame = gp->cppFrame.parentFrame();
- bool done = (gp->cppFrame.yield == nullptr);
+ bool done = (gp->cppFrame.yield() == nullptr);
gp->state = done ? GeneratorState::Completed : GeneratorState::SuspendedYield;
if (engine->hasException)
return Encode::undefined();
- if (gp->cppFrame.yieldIsIterator)
+ if (gp->cppFrame.yieldIsIterator())
return result->asReturnedValue();
return IteratorPrototype::createIterResultObject(engine, result, done);
}
diff --git a/src/qml/jsruntime/qv4generatorobject_p.h b/src/qml/jsruntime/qv4generatorobject_p.h
index 366319723d..6eb7b306e0 100644
--- a/src/qml/jsruntime/qv4generatorobject_p.h
+++ b/src/qml/jsruntime/qv4generatorobject_p.h
@@ -89,8 +89,9 @@ struct GeneratorPrototype : FunctionObject {
Member(class, Pointer, ExecutionContext *, context) \
Member(class, Pointer, GeneratorFunction *, function) \
Member(class, NoMark, GeneratorState, state) \
- Member(class, NoMark, CppStackFrame, cppFrame) \
- Member(class, ValueArray, ValueArray, stack)
+ Member(class, NoMark, JSTypesStackFrame, cppFrame) \
+ Member(class, Pointer, ArrayObject *, values) \
+ Member(class, Pointer, ArrayObject *, jsFrame)
DECLARE_HEAP_OBJECT(GeneratorObject, Object) {
DECLARE_MARKOBJECTS(GeneratorObject);
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 77f8fe75d0..1493456853 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -146,6 +146,8 @@ namespace Heap {
}
struct CppStackFrame;
+struct JSTypesStackFrame;
+struct MetaTypesStackFrame;
class MemoryManager;
class ExecutableAllocator;
struct PropertyKey;
diff --git a/src/qml/jsruntime/qv4identifierhash.cpp b/src/qml/jsruntime/qv4identifierhash.cpp
index 7d2d3143b2..d349b7c4fe 100644
--- a/src/qml/jsruntime/qv4identifierhash.cpp
+++ b/src/qml/jsruntime/qv4identifierhash.cpp
@@ -50,6 +50,7 @@ namespace QV4 {
IdentifierHash::IdentifierHash(ExecutionEngine *engine)
{
d = new IdentifierHashData(engine->identifierTable, 3);
+ Q_ASSERT(!isEmpty());
}
void IdentifierHash::detach()
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index c4ce837360..7c5bc3188c 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -141,8 +141,14 @@ Heap::String *IdentifierTable::insertString(const QString &s)
Heap::String *str = engine->newString(s);
str->stringHash = hash;
str->subtype = subtype;
+ str->identifier = PropertyKey::fromArrayIndex(hash);
return str;
}
+ return resolveStringEntry(s, hash, subtype);
+}
+
+Heap::String *IdentifierTable::resolveStringEntry(const QString &s, uint hash, uint subtype)
+{
uint idx = hash % alloc;
while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
if (e->stringHash == hash && e->toQString() == s)
@@ -281,30 +287,20 @@ void IdentifierTable::sweep()
PropertyKey IdentifierTable::asPropertyKey(const QString &s)
{
- return insertString(s)->identifier;
+ uint subtype;
+ const uint hash = String::createHashValue(s.constData(), s.length(), &subtype);
+ if (subtype == Heap::String::StringType_ArrayIndex)
+ return PropertyKey::fromArrayIndex(hash);
+ return resolveStringEntry(s, hash, subtype)->identifier;
}
PropertyKey IdentifierTable::asPropertyKey(const char *s, int len)
{
uint subtype;
uint hash = String::createHashValue(s, len, &subtype);
- if (hash == UINT_MAX)
- return asPropertyKey(QString::fromUtf8(s, len));
-
- QLatin1String latin(s, len);
- uint idx = hash % alloc;
- while (Heap::StringOrSymbol *e = entriesByHash[idx]) {
- if (e->stringHash == hash && e->toQString() == latin)
- return e->identifier;
- ++idx;
- idx %= alloc;
- }
-
- Heap::String *str = engine->newString(QString::fromLatin1(s, len));
- str->stringHash = hash;
- str->subtype = subtype;
- addEntry(str);
- return str->identifier;
+ if (subtype == Heap::String::StringType_ArrayIndex)
+ return PropertyKey::fromArrayIndex(hash);
+ return resolveStringEntry(QString::fromLatin1(s, len), hash, subtype)->identifier;
}
}
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index 6553ad6103..b2a9bc1195 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -109,6 +109,9 @@ public:
void removeIdentifierHash(IdentifierHashData *h) {
idHashes.remove(h);
}
+
+private:
+ Heap::String *resolveStringEntry(const QString &s, uint hash, uint subtype);
};
}
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index c185894ab3..3e6417af57 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -127,9 +127,9 @@ void QV4Include::callback(const QV4::Value &callback, const QV4::Value &status)
if (!f)
return;
- QV4::JSCallData jsCallData(scope, 1);
- *jsCallData->thisObject = v4->globalObject->asReturnedValue();
- jsCallData->args[0] = status;
+ QV4::JSCallArguments jsCallData(scope, 1);
+ *jsCallData.thisObject = v4->globalObject->asReturnedValue();
+ jsCallData.args[0] = status;
f->call(jsCallData);
if (scope.hasException())
scope.engine->catchException();
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index b2fe0c8aa9..c18133f4cd 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -53,6 +53,7 @@
#include "qv4global_p.h"
#include <QHash>
+#include <climits> // for UINT_MAX
#include <private/qv4propertykey_p.h>
#include <private/qv4heap_p.h>
diff --git a/src/qml/jsruntime/qv4jscall.cpp b/src/qml/jsruntime/qv4jscall.cpp
index 191436bd69..485f83afe2 100644
--- a/src/qml/jsruntime/qv4jscall.cpp
+++ b/src/qml/jsruntime/qv4jscall.cpp
@@ -49,13 +49,11 @@ QT_BEGIN_NAMESPACE
Sets the arguments of JSCallData from type erased \a args based on type
information provided by \a types
*/
-void QV4::populateJSCallArguments(ExecutionEngine *v4, JSCallData &jsCall,
+void QV4::populateJSCallArguments(ExecutionEngine *v4, JSCallArguments &jsCall,
int argc, void **args, const QMetaType *types)
{
- for (int ii = 0; ii < argc; ++ii) {
- auto type = QMetaType(types[ii]);
- jsCall.args[ii] = v4->metaTypeToJS(type, args[ii + 1]);
- }
+ for (int ii = 0; ii < argc; ++ii)
+ jsCall.args[ii] = v4->metaTypeToJS(types[ii], args[ii + 1]);
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4jscall_p.h b/src/qml/jsruntime/qv4jscall_p.h
index 66ff1e7c3b..3f0c8ee06d 100644
--- a/src/qml/jsruntime/qv4jscall_p.h
+++ b/src/qml/jsruntime/qv4jscall_p.h
@@ -56,48 +56,67 @@
#include "qv4context_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4stackframe_p.h"
+#include <private/qv4alloca_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct JSCallData {
- JSCallData(const Scope &scope, int argc = 0, const Value *argv = nullptr, const Value *thisObject = nullptr)
- : scope(scope), argc(argc)
+template<typename Args>
+CallData *callDatafromJS(const Scope &scope, const Args *args, const FunctionObject *f = nullptr)
+{
+ int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + args->argc;
+ CallData *ptr = reinterpret_cast<CallData *>(scope.alloc<Scope::Uninitialized>(size));
+ ptr->function = Encode::undefined();
+ ptr->context = Encode::undefined();
+ ptr->accumulator = Encode::undefined();
+ ptr->thisObject = args->thisObject ? args->thisObject->asReturnedValue() : Encode::undefined();
+ ptr->newTarget = Encode::undefined();
+ ptr->setArgc(args->argc);
+ if (args->argc)
+ memcpy(ptr->args, args->args, args->argc*sizeof(Value));
+ if (f)
+ ptr->function = f->asReturnedValue();
+ return ptr;
+}
+
+struct JSCallArguments
+{
+ JSCallArguments(const Scope &scope, int argc = 0)
+ : thisObject(scope.alloc()), args(scope.alloc(argc)), argc(argc)
{
- if (thisObject)
- this->thisObject = const_cast<Value *>(thisObject);
- else
- this->thisObject = scope.alloc();
- if (argv)
- this->args = const_cast<Value *>(argv);
- else
- this->args = scope.alloc(argc);
}
- JSCallData *operator->() {
- return this;
+ CallData *callData(const Scope &scope, const FunctionObject *f = nullptr) const
+ {
+ return callDatafromJS(scope, this, f);
}
- CallData *callData(const FunctionObject *f = nullptr) const {
- int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + argc;
- CallData *ptr = reinterpret_cast<CallData *>(scope.alloc<Scope::Uninitialized>(size));
- ptr->function = Encode::undefined();
- ptr->context = Encode::undefined();
- ptr->accumulator = Encode::undefined();
- ptr->thisObject = thisObject->asReturnedValue();
- ptr->newTarget = Encode::undefined();
- ptr->setArgc(argc);
- if (argc)
- memcpy(ptr->args, args, argc*sizeof(Value));
- if (f)
- ptr->function = f->asReturnedValue();
- return ptr;
- }
- const Scope &scope;
- int argc;
- Value *args;
Value *thisObject;
+ Value *args;
+ const int argc;
+};
+
+struct JSCallData
+{
+ JSCallData(const Value *thisObject, const Value *argv, int argc)
+ : thisObject(thisObject), args(argv), argc(argc)
+ {
+ }
+
+ Q_IMPLICIT JSCallData(const JSCallArguments &args)
+ : thisObject(args.thisObject), args(args.args), argc(args.argc)
+ {
+ }
+
+ CallData *callData(const Scope &scope, const FunctionObject *f = nullptr) const
+ {
+ return callDatafromJS(scope, this, f);
+ }
+
+ const Value *thisObject;
+ const Value *args;
+ const int argc;
};
inline
@@ -112,7 +131,7 @@ ReturnedValue FunctionObject::call(const JSCallData &data) const
return call(data.thisObject, data.args, data.argc);
}
-void populateJSCallArguments(ExecutionEngine *v4, JSCallData &jsCall, int argc,
+void populateJSCallArguments(ExecutionEngine *v4, JSCallArguments &jsCall, int argc,
void **args, const QMetaType *types);
struct ScopedStackFrame {
@@ -122,19 +141,104 @@ struct ScopedStackFrame {
ScopedStackFrame(Scope &scope, Heap::ExecutionContext *context)
: scope(scope)
{
- frame.parent = scope.engine->currentStackFrame;
+ frame.setParentFrame(scope.engine->currentStackFrame);
if (!context)
return;
frame.jsFrame = reinterpret_cast<CallData *>(scope.alloc(sizeof(CallData)/sizeof(Value)));
frame.jsFrame->context = context;
- frame.v4Function = frame.parent ? frame.parent->v4Function : nullptr;
+ if (auto *parent = frame.parentFrame())
+ frame.v4Function = parent->v4Function;
+ else
+ frame.v4Function = nullptr;
scope.engine->currentStackFrame = &frame;
}
~ScopedStackFrame() {
- scope.engine->currentStackFrame = frame.parent;
+ scope.engine->currentStackFrame = frame.parentFrame();
}
};
+template<typename Callable>
+ReturnedValue convertAndCall(
+ ExecutionEngine *engine, const QQmlPrivate::AOTCompiledFunction *aotFunction,
+ const Value *thisObject, const Value *argv, int argc, Callable call)
+{
+ const qsizetype numFunctionArguments = aotFunction->argumentTypes.size();
+ Q_ALLOCA_VAR(void *, values, (numFunctionArguments + 1) * sizeof(void *));
+ Q_ALLOCA_VAR(QMetaType, types, (numFunctionArguments + 1) * sizeof(QMetaType));
+
+ for (qsizetype i = 0; i < numFunctionArguments; ++i) {
+ const QMetaType argumentType = aotFunction->argumentTypes[i];
+ types[i + 1] = argumentType;
+ if (const qsizetype argumentSize = argumentType.sizeOf()) {
+ Q_ALLOCA_VAR(void, argument, argumentSize);
+ argumentType.construct(argument);
+ if (i < argc)
+ engine->metaTypeFromJS(argv[i], argumentType, argument);
+ values[i + 1] = argument;
+ } else {
+ values[i + 1] = nullptr;
+ }
+ }
+
+ Q_ALLOCA_DECLARE(void, returnValue);
+ types[0] = aotFunction->returnType;
+ if (const qsizetype returnSize = types[0].sizeOf()) {
+ Q_ALLOCA_ASSIGN(void, returnValue, returnSize);
+ values[0] = returnValue;
+ } else {
+ values[0] = nullptr;
+ }
+
+ call(thisObject, values, types, argc);
+
+ ReturnedValue result;
+ if (values[0]) {
+ result = engine->metaTypeToJS(types[0], values[0]);
+ types[0].destruct(values[0]);
+ } else {
+ result = Encode::undefined();
+ }
+
+ for (qsizetype i = 1, end = numFunctionArguments + 1; i < end; ++i)
+ types[i].destruct(values[i]);
+
+ return result;
+}
+
+template<typename Callable>
+void convertAndCall(ExecutionEngine *engine, const Value *thisObject,
+ void **a, const QMetaType *types, int argc, Callable call)
+{
+ Scope scope(engine);
+ QV4::JSCallArguments jsCallData(scope, argc);
+
+ for (int ii = 0; ii < argc; ++ii)
+ jsCallData.args[ii] = engine->metaTypeToJS(types[ii + 1], a[ii + 1]);
+
+ void *result = a[0];
+ if (!result) {
+ call(thisObject, jsCallData.args, argc);
+ return;
+ }
+
+ ScopedValue jsResult(scope, call(thisObject, jsCallData.args, argc));
+
+ const QMetaType resultType = types[0];
+ if (scope.hasException()) {
+ // Clear the return value
+ resultType.construct(result);
+ } else {
+ // When the return type is QVariant, JS objects are to be returned as
+ // QJSValue wrapped in QVariant. metaTypeFromJS unwraps them, unfortunately.
+ if (resultType == QMetaType::fromType<QVariant>()) {
+ new (result) QVariant(scope.engine->toVariant(jsResult, QMetaType {}));
+ } else {
+ resultType.construct(result);
+ scope.engine->metaTypeFromJS(jsResult, resultType, result);
+ }
+ }
+}
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index c580fd2bf5..a3ffdb5431 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -700,9 +700,9 @@ QString Stringify::Str(const QString &key, const Value &v)
ScopedString s(scope, v4->newString(QStringLiteral("toJSON")));
ScopedFunctionObject toJSON(scope, o->get(s));
if (!!toJSON) {
- JSCallData jsCallData(scope, 1);
- *jsCallData->thisObject = value;
- jsCallData->args[0] = v4->newString(key);
+ JSCallArguments jsCallData(scope, 1);
+ *jsCallData.thisObject = value;
+ jsCallData.args[0] = v4->newString(key);
value = toJSON->call(jsCallData);
if (v4->hasException)
return QString();
@@ -712,10 +712,10 @@ QString Stringify::Str(const QString &key, const Value &v)
if (replacerFunction) {
ScopedObject holder(scope, v4->newObject());
holder->put(scope.engine->id_empty(), value);
- JSCallData jsCallData(scope, 2);
- jsCallData->args[0] = v4->newString(key);
- jsCallData->args[1] = value;
- *jsCallData->thisObject = holder;
+ JSCallArguments jsCallData(scope, 2);
+ jsCallData.args[0] = v4->newString(key);
+ jsCallData.args[1] = value;
+ *jsCallData.thisObject = holder;
value = replacerFunction->call(jsCallData);
if (v4->hasException)
return QString();
diff --git a/src/qml/jsruntime/qv4module.cpp b/src/qml/jsruntime/qv4module.cpp
index 08a1900383..26bef9cd37 100644
--- a/src/qml/jsruntime/qv4module.cpp
+++ b/src/qml/jsruntime/qv4module.cpp
@@ -112,15 +112,15 @@ void Module::evaluate()
ExecutionEngine *v4 = engine();
Function *moduleFunction = unit->runtimeFunctions[unit->data->indexOfRootFunction];
- CppStackFrame frame;
- frame.init(v4, moduleFunction, nullptr, 0);
+ JSTypesStackFrame frame;
+ frame.init(moduleFunction, nullptr, 0);
frame.setupJSFrame(v4->jsStackTop, Value::undefinedValue(), d()->scope,
Value::undefinedValue(), Value::undefinedValue());
- frame.push();
+ frame.push(v4);
v4->jsStackTop += frame.requiredJSStackFrameSize();
- auto frameCleanup = qScopeGuard([&frame]() {
- frame.pop();
+ auto frameCleanup = qScopeGuard([&frame, v4]() {
+ frame.pop(v4);
});
Moth::VME::exec(&frame, v4);
}
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index bc145f958d..2ad1ecb6e3 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -102,9 +102,9 @@ ReturnedValue Object::getValueAccessor(const Value *thisObject, const Value &v,
return Encode::undefined();
Scope scope(f->engine());
- JSCallData jsCallData(scope);
+ JSCallArguments jsCallData(scope);
if (thisObject)
- *jsCallData->thisObject = *thisObject;
+ *jsCallData.thisObject = *thisObject;
return checkedResult(scope.engine, f->call(jsCallData));
}
@@ -119,9 +119,9 @@ bool Object::putValue(uint memberIndex, PropertyAttributes attrs, const Value &v
if (set) {
Scope scope(ic->engine);
ScopedFunctionObject setter(scope, set);
- JSCallData jsCallData(scope, 1);
- jsCallData->args[0] = value;
- *jsCallData->thisObject = this;
+ JSCallArguments jsCallData(scope, 1);
+ jsCallData.args[0] = value;
+ *jsCallData.thisObject = this;
setter->call(jsCallData);
return !ic->engine->hasException;
}
@@ -519,9 +519,9 @@ bool Object::internalPut(PropertyKey id, const Value &value, Value *receiver)
ScopedFunctionObject setter(scope, p->setter());
if (!setter)
return false;
- JSCallData jsCallData(scope, 1);
- jsCallData->args[0] = value;
- *jsCallData->thisObject = *receiver;
+ JSCallArguments jsCallData(scope, 1);
+ jsCallData.args[0] = value;
+ *jsCallData.thisObject = *receiver;
setter->call(jsCallData);
return !scope.engine->hasException;
}
diff --git a/src/qml/jsruntime/qv4promiseobject.cpp b/src/qml/jsruntime/qv4promiseobject.cpp
index ecaff72b22..83bfba9b11 100644
--- a/src/qml/jsruntime/qv4promiseobject.cpp
+++ b/src/qml/jsruntime/qv4promiseobject.cpp
@@ -227,17 +227,17 @@ public:
void ReactionHandler::executeResolveThenable(ResolveThenableEvent *event)
{
Scope scope(event->then.engine());
- JSCallData jsCallData(scope, 2);
+ JSCallArguments jsCallData(scope, 2);
PromiseObject *promise = event->promise.as<PromiseObject>();
ScopedFunctionObject resolve {scope, FunctionBuilder::makeResolveFunction(scope.engine, promise->d())};
ScopedFunctionObject reject {scope, FunctionBuilder::makeRejectFunction(scope.engine, promise->d())};
- jsCallData->args[0] = resolve;
+ jsCallData.args[0] = resolve;
jsCallData.args[1] = reject;
- jsCallData->thisObject = event->thenable.as<QV4::Object>();
+ jsCallData.thisObject = event->thenable.as<QV4::Object>();
event->then.as<const FunctionObject>()->call(jsCallData);
if (scope.engine->hasException) {
- JSCallData rejectCallData(scope, 1);
- rejectCallData->args[0] = scope.engine->catchException();
+ JSCallArguments rejectCallData(scope, 1);
+ rejectCallData.args[0] = scope.engine->catchException();
Scoped<RejectWrapper> reject {scope, scope.engine->memoryManager->allocate<QV4::RejectWrapper>()};
reject->call(rejectCallData);
}
@@ -440,16 +440,16 @@ ReturnedValue PromiseCtor::virtualCallAsConstructor(const FunctionObject *f, con
ScopedFunctionObject resolve(scope, FunctionBuilder::makeResolveFunction(scope.engine, a->d()));
ScopedFunctionObject reject(scope, FunctionBuilder::makeRejectFunction(scope.engine, a->d()));
- JSCallData jsCallData(scope, 2);
- jsCallData->args[0] = resolve;
- jsCallData->args[1] = reject;
- //jsCallData->thisObject = a; VERIFY corretness, but this should be undefined (see below)
+ JSCallArguments jsCallData(scope, 2);
+ jsCallData.args[0] = resolve;
+ jsCallData.args[1] = reject;
+ //jsCallData.thisObject = a; VERIFY corretness, but this should be undefined (see below)
executor->call(jsCallData); // 9. Let completion be Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »).
if (scope.engine->hasException) {
ScopedValue exception {scope, scope.engine->catchException()};
- JSCallData callData {scope, 1};
+ JSCallArguments callData {scope, 1};
callData.args[0] = exception;
reject->call(callData);
}
@@ -649,10 +649,10 @@ ReturnedValue PromiseCtor::method_all(const FunctionObject *f, const Value *this
ScopedFunctionObject resolveElement(scope, FunctionBuilder::makeResolveElementFunction(e, index, executionState->d()));
- JSCallData jsCallData(scope, 2);
- jsCallData->args[0] = resolveElement;
- jsCallData->args[1] = reject;
- jsCallData->thisObject = nextPromise;
+ JSCallArguments jsCallData(scope, 2);
+ jsCallData.args[0] = resolveElement;
+ jsCallData.args[1] = reject;
+ jsCallData.thisObject = nextPromise;
then->call(jsCallData);
if (scope.hasException()) {
@@ -793,10 +793,10 @@ ReturnedValue PromiseCtor::method_race(const FunctionObject *f, const Value *thi
ScopedFunctionObject resolveOriginalPromise(scope, capability->d()->resolve);
- JSCallData jsCallData(scope, 2);
- jsCallData->args[0] = resolveOriginalPromise;
- jsCallData->args[1] = reject;
- jsCallData->thisObject = nextPromise;
+ JSCallArguments jsCallData(scope, 2);
+ jsCallData.args[0] = resolveOriginalPromise;
+ jsCallData.args[1] = reject;
+ jsCallData.thisObject = nextPromise;
then->call(jsCallData);
if (scope.hasException()) {
@@ -927,10 +927,10 @@ ReturnedValue PromisePrototype::method_catch(const FunctionObject *f, const Valu
onRejected = argv[0];
}
- JSCallData jsCallData(scope, 2);
- jsCallData->args[0] = Encode::undefined();
- jsCallData->args[1] = onRejected;
- jsCallData->thisObject = promise;
+ JSCallArguments jsCallData(scope, 2);
+ jsCallData.args[0] = Encode::undefined();
+ jsCallData.args[1] = onRejected;
+ jsCallData.thisObject = promise;
ScopedString thenName(scope, scope.engine->newIdentifier(QStringLiteral("then")));
ScopedFunctionObject then(scope, promise->get(thenName));
@@ -1084,10 +1084,10 @@ ReturnedValue RejectWrapper::virtualCall(const FunctionObject *f, const Value *t
ScopedString thenName(scope, scope.engine->newIdentifier(QStringLiteral("catch")));
ScopedFunctionObject then(scope, promise->get(thenName));
- JSCallData jsCallData(scope, 2);
- jsCallData->args[0] = *f;
- jsCallData->args[1] = Encode::undefined();
- jsCallData->thisObject = value;
+ JSCallArguments jsCallData(scope, 2);
+ jsCallData.args[0] = *f;
+ jsCallData.args[1] = Encode::undefined();
+ jsCallData.thisObject = value;
then->call(jsCallData);
}
diff --git a/src/qml/jsruntime/qv4propertykey_p.h b/src/qml/jsruntime/qv4propertykey_p.h
index b2a2ec3dea..b5dca2d2ac 100644
--- a/src/qml/jsruntime/qv4propertykey_p.h
+++ b/src/qml/jsruntime/qv4propertykey_p.h
@@ -124,11 +124,11 @@ public:
return m();
}
- Q_QML_EXPORT bool isString() const;
- bool isSymbol() const;
+ Q_QML_PRIVATE_EXPORT bool isString() const;
+ Q_QML_PRIVATE_EXPORT bool isSymbol() const;
bool isCanonicalNumericIndexString() const;
- Q_QML_EXPORT QString toQString() const;
+ Q_QML_PRIVATE_EXPORT QString toQString() const;
Heap::StringOrSymbol *toStringOrSymbol(ExecutionEngine *e);
quint64 id() const { return val; }
static PropertyKey fromId(quint64 id) {
diff --git a/src/qml/jsruntime/qv4proxy.cpp b/src/qml/jsruntime/qv4proxy.cpp
index 8bfc9fc3ba..b223e73f0f 100644
--- a/src/qml/jsruntime/qv4proxy.cpp
+++ b/src/qml/jsruntime/qv4proxy.cpp
@@ -90,10 +90,11 @@ ReturnedValue ProxyObject::virtualGet(const Managed *m, PropertyKey id, const Va
if (hasProperty)
*hasProperty = true;
- JSCallData cdata(scope, 3, nullptr, handler);
- cdata.args[0] = target;
- cdata.args[1] = id.toStringOrSymbol(scope.engine);
- cdata.args[2] = *receiver;
+ Value *args = scope.alloc(3);
+ args[0] = target;
+ args[1] = id.toStringOrSymbol(scope.engine);
+ args[2] = *receiver;
+ JSCallData cdata(handler, args, 3);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
@@ -131,11 +132,12 @@ bool ProxyObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Val
if (!trap->isFunctionObject())
return scope.engine->throwTypeError();
- JSCallData cdata(scope, 4, nullptr, handler);
- cdata.args[0] = target;
- cdata.args[1] = id.toStringOrSymbol(scope.engine);
- cdata.args[2] = value;
- cdata.args[3] = *receiver;
+ Value *args = scope.alloc(4);
+ args[0] = target;
+ args[1] = id.toStringOrSymbol(scope.engine);
+ args[2] = value;
+ args[3] = *receiver;
+ JSCallData cdata(handler, args, 4);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException || !trapResult->toBoolean())
@@ -172,10 +174,11 @@ bool ProxyObject::virtualDeleteProperty(Managed *m, PropertyKey id)
if (!trap->isFunctionObject())
return scope.engine->throwTypeError();
- JSCallData cdata(scope, 3, nullptr, handler);
- cdata.args[0] = target;
- cdata.args[1] = id.toStringOrSymbol(scope.engine);
- cdata.args[2] = o->d(); // ### fix receiver handling
+ Value *args = scope.alloc(3);
+ args[0] = target;
+ args[1] = id.toStringOrSymbol(scope.engine);
+ args[2] = o->d(); // ### fix receiver handling
+ JSCallData cdata(handler, args, 3);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException || !trapResult->toBoolean())
@@ -208,9 +211,10 @@ bool ProxyObject::virtualHasProperty(const Managed *m, PropertyKey id)
if (!trap->isFunctionObject())
return scope.engine->throwTypeError();
- JSCallData cdata(scope, 2, nullptr, handler);
- cdata.args[0] = target;
- cdata.args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
+ Value *args = scope.alloc(2);
+ args[0] = target;
+ args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
+ JSCallData cdata(handler, args, 2);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
@@ -250,9 +254,10 @@ PropertyAttributes ProxyObject::virtualGetOwnProperty(const Managed *m, Property
return Attr_Invalid;
}
- JSCallData cdata(scope, 2, nullptr, handler);
- cdata.args[0] = target;
- cdata.args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
+ Value *args = scope.alloc(2);
+ args[0] = target;
+ args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
+ JSCallData cdata(handler, args, 2);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
@@ -325,10 +330,11 @@ bool ProxyObject::virtualDefineOwnProperty(Managed *m, PropertyKey id, const Pro
return false;
}
- JSCallData cdata(scope, 3, nullptr, handler);
- cdata.args[0] = target;
- cdata.args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
- cdata.args[2] = ObjectPrototype::fromPropertyDescriptor(scope.engine, p, attrs);
+ Value *args = scope.alloc(3);
+ args[0] = target;
+ args[1] = id.isArrayIndex() ? Value::fromUInt32(id.asArrayIndex()).toString(scope.engine) : id.asStringOrSymbol();
+ args[2] = ObjectPrototype::fromPropertyDescriptor(scope.engine, p, attrs);
+ JSCallData cdata(handler, args, 3);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
bool result = !scope.engine->hasException && trapResult->toBoolean();
@@ -377,8 +383,9 @@ bool ProxyObject::virtualIsExtensible(const Managed *m)
if (!trap->isFunctionObject())
return scope.engine->throwTypeError();
- JSCallData cdata(scope, 1, nullptr, handler);
- cdata.args[0] = target;
+ Value *args = scope.alloc(1);
+ args[0] = target;
+ JSCallData cdata(handler, args, 1);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
@@ -410,8 +417,9 @@ bool ProxyObject::virtualPreventExtensions(Managed *m)
if (!trap->isFunctionObject())
return scope.engine->throwTypeError();
- JSCallData cdata(scope, 1, nullptr, handler);
- cdata.args[0] = target;
+ Value *args = scope.alloc(1);
+ args[0] = target;
+ JSCallData cdata(handler, args, 1);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
@@ -447,8 +455,9 @@ Heap::Object *ProxyObject::virtualGetPrototypeOf(const Managed *m)
return nullptr;
}
- JSCallData cdata(scope, 1, nullptr, handler);
- cdata.args[0] = target;
+ Value *args = scope.alloc(1);
+ args[0] = target;
+ JSCallData cdata(handler, args, 1);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
@@ -491,9 +500,10 @@ bool ProxyObject::virtualSetPrototypeOf(Managed *m, const Object *p)
return false;
}
- JSCallData cdata(scope, 2, nullptr, handler);
- cdata.args[0] = target;
- cdata.args[1] = p ? p->asReturnedValue() : Encode::null();
+ Value *args = scope.alloc(2);
+ args[0] = target;
+ args[1] = p ? p->asReturnedValue() : Encode::null();
+ JSCallData cdata(handler, args, 2);
ScopedValue trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
bool result = !scope.engine->hasException && trapResult->toBoolean();
@@ -584,8 +594,9 @@ OwnPropertyKeyIterator *ProxyObject::virtualOwnPropertyKeys(const Object *m, Val
return nullptr;
}
- JSCallData cdata(scope, 1, nullptr, handler);
- cdata.args[0] = target;
+ Value *args = scope.alloc(1);
+ args[0] = target;
+ JSCallData cdata(handler, args, 1);
ScopedObject trapResult(scope, static_cast<const FunctionObject *>(trap.ptr)->call(cdata));
if (scope.engine->hasException)
return nullptr;
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 5581ea9a53..f845f1d6e5 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -88,11 +88,7 @@ static OptionalReturnedValue searchContextProperties(
bool *hasProperty, Value *base, QV4::Lookup *lookup, QV4::Lookup *originalLookup,
QQmlEnginePrivate *ep)
{
- const QV4::IdentifierHash &properties = context->propertyNames();
- if (properties.count() == 0)
- return OptionalReturnedValue();
-
- const int propertyIdx = properties.value(name);
+ const int propertyIdx = context->propertyIndex(name);
if (propertyIdx == -1)
return OptionalReturnedValue();
@@ -126,7 +122,7 @@ static OptionalReturnedValue searchContextProperties(
QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*) qintptr(propertyIdx),
QQmlContextPrivate::context_count,
QQmlContextPrivate::context_at);
- return OptionalReturnedValue(QmlListWrapper::create(v4, prop, qMetaTypeId<QQmlListProperty<QObject> >()));
+ return OptionalReturnedValue(QmlListWrapper::create(v4, prop, QMetaType::fromType<QQmlListProperty<QObject> >()));
}
return OptionalReturnedValue(v4->fromVariant(cp->propertyValue(propertyIdx)));
}
@@ -429,17 +425,13 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val
ScopedString name(scope, id.asStringOrSymbol());
while (context) {
- const QV4::IdentifierHash &properties = context->propertyNames();
// Search context properties
- if (properties.count()) {
- const int propertyIndex = properties.value(name);
- if (propertyIndex != -1) {
- if (propertyIndex < context->numIdValues()) {
- v4->throwError(QLatin1String("left-hand side of assignment operator is not an lvalue"));
- return false;
- }
+ if (const int propertyIndex = context->propertyIndex(name); propertyIndex != -1) {
+ if (propertyIndex < context->numIdValues()) {
+ v4->throwError(QLatin1String("left-hand side of assignment operator is not an lvalue"));
return false;
}
+ return false;
}
// Search scope object
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index 41a57e36c9..5df7323a45 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -151,7 +151,7 @@ static QV4::ReturnedValue loadProperty(QV4::ExecutionEngine *v4, QObject *object
return ret;
} else if (property.isQList()) {
- return QmlListWrapper::create(v4, object, property.coreIndex(), property.propType().id());
+ return QmlListWrapper::create(v4, object, property.coreIndex(), property.propType());
} else if (propType == QMetaType::QReal) {
qreal v = 0;
property.readProperty(object, &v);
@@ -617,9 +617,9 @@ void QObjectWrapper::setProperty(ExecutionEngine *engine, QObject *object, QQmlP
} else {
QVariant v;
if (property->isQList())
- v = scope.engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+ v = scope.engine->toVariant(value, QMetaType::fromType<QList<QObject *> >());
else
- v = scope.engine->toVariant(value, propType);
+ v = scope.engine->toVariant(value, property->propType());
QQmlRefPointer<QQmlContextData> callingQmlContext = scope.engine->callingQmlContext();
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
@@ -975,15 +975,15 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
{
QV4::PersistentValue function;
QV4::PersistentValue thisObject;
- int signalIndex;
+ QMetaMethod signal;
QObjectSlotDispatcher()
: QtPrivate::QSlotObjectBase(&impl)
- , signalIndex(-1)
{}
- static void impl(int which, QSlotObjectBase *this_, QObject *r, void **metaArgs, bool *ret)
+ static void impl(int which, QSlotObjectBase *this_, QObject *receiver, void **metaArgs, bool *ret)
{
+ Q_UNUSED(receiver);
switch (which) {
case Destroy: {
delete static_cast<QObjectSlotDispatcher*>(this_);
@@ -999,21 +999,21 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
break;
QQmlMetaObject::ArgTypeStorage storage;
- QQmlMetaObject(r).methodParameterTypes(This->signalIndex, &storage, nullptr);
+ QQmlMetaObject::methodParameterTypes(This->signal, &storage, nullptr);
int argCount = storage.size();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject f(scope, This->function.value());
- QV4::JSCallData jsCallData(scope, argCount);
- *jsCallData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value();
+ QV4::JSCallArguments jsCallData(scope, argCount);
+ *jsCallData.thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
QMetaType type = storage[ii];
if (type == QMetaType::fromType<QVariant>()) {
- jsCallData->args[ii] = v4->fromVariant(*((QVariant *)metaArgs[ii + 1]));
+ jsCallData.args[ii] = v4->fromVariant(*((QVariant *)metaArgs[ii + 1]));
} else {
- jsCallData->args[ii] = v4->fromVariant(QVariant(type, metaArgs[ii + 1]));
+ jsCallData.args[ii] = v4->fromVariant(QVariant(type, metaArgs[ii + 1]));
}
}
@@ -1107,7 +1107,8 @@ ReturnedValue QObjectWrapper::method_connect(const FunctionObject *b, const Valu
if (!signalObject)
THROW_GENERIC_ERROR("Function.prototype.connect: cannot connect to deleted QObject");
- if (signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
+ auto signalMetaMethod = signalObject->metaObject()->method(signalIndex);
+ if (signalMetaMethod.methodType() != QMetaMethod::Signal)
THROW_GENERIC_ERROR("Function.prototype.connect: this object is not a signal");
QV4::ScopedFunctionObject f(scope);
@@ -1127,7 +1128,7 @@ ReturnedValue QObjectWrapper::method_connect(const FunctionObject *b, const Valu
THROW_GENERIC_ERROR("Function.prototype.connect: target this is not an object");
QV4::QObjectSlotDispatcher *slot = new QV4::QObjectSlotDispatcher;
- slot->signalIndex = signalIndex;
+ slot->signal = signalMetaMethod;
slot->thisObject.set(scope.engine, object);
slot->function.set(scope.engine, f);
@@ -1524,7 +1525,7 @@ static int MatchScore(const QV4::Value &actual, QMetaType conversionMetaType)
if (obj->as<QV4::VariantObject>()) {
if (conversionType == qMetaTypeId<QVariant>())
return 0;
- if (obj->engine()->toVariant(actual, -1).metaType() == conversionMetaType)
+ if (obj->engine()->toVariant(actual, QMetaType {}).metaType() == conversionMetaType)
return 0;
else
return 10;
@@ -1539,15 +1540,17 @@ static int MatchScore(const QV4::Value &actual, QMetaType conversionMetaType)
}
}
+#if QT_CONFIG(qml_sequence_object)
if (auto sequenceMetaType = SequencePrototype::metaTypeForSequence(obj); sequenceMetaType != -1) {
if (sequenceMetaType == conversionType)
return 1;
else
return 10;
}
+#endif
if (obj->as<QV4::QQmlValueTypeWrapper>()) {
- const QVariant v = obj->engine()->toVariant(actual, -1);
+ const QVariant v = obj->engine()->toVariant(actual, QMetaType {});
if (v.userType() == conversionType)
return 0;
else if (v.canConvert(conversionMetaType))
@@ -1895,7 +1898,7 @@ bool CallArgument::fromValue(QMetaType metaType, QV4::ExecutionEngine *engine, c
else if (!value.isNull() && !value.isUndefined()) // null and undefined are nullptr
return false;
} else if (callType == qMetaTypeId<QVariant>()) {
- qvariantPtr = new (&allocData) QVariant(scope.engine->toVariant(value, -1));
+ qvariantPtr = new (&allocData) QVariant(scope.engine->toVariant(value, QMetaType {}));
type = callType;
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
qlistPtr = new (&allocData) QList<QObject *>();
@@ -1986,7 +1989,7 @@ bool CallArgument::fromValue(QMetaType metaType, QV4::ExecutionEngine *engine, c
type = -1;
QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : nullptr;
- QVariant v = scope.engine->toVariant(value, callType);
+ QVariant v = scope.engine->toVariant(value, metaType);
const QMetaType callMetaType(callType);
if (v.metaType() == callMetaType) {
@@ -2205,8 +2208,8 @@ ReturnedValue QObjectMethod::callInternal(const Value *thisObject, const Value *
}
Scope scope(v4);
- JSCallData cData(scope, argc, argv, thisObject);
- CallData *callData = cData.callData();
+ JSCallData cData(thisObject, argv, argc);
+ CallData *callData = cData.callData(scope);
auto method = d()->methods[0];
@@ -2307,8 +2310,8 @@ ReturnedValue QMetaObjectWrapper::constructInternal(const Value *argv, int argc)
Scope scope(v4);
Scoped<QObjectWrapper> object(scope);
- JSCallData cData(scope, argc, argv);
- CallData *callData = cData.callData();
+ JSCallData cData(nullptr, argv, argc);
+ CallData *callData = cData.callData(scope);
const QQmlObjectOrGadget objectOrGadget(mo);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index b5c3da311a..50e3f41e67 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -336,6 +336,8 @@ public:
typedef QHash<QObject*, QV4::WeakValue>::ConstIterator ConstIterator;
typedef QHash<QObject*, QV4::WeakValue>::Iterator Iterator;
+ using value_type = QHash<QObject*, QV4::WeakValue>::value_type;
+
ConstIterator begin() const { return QHash<QObject*, QV4::WeakValue>::constBegin(); }
Iterator begin() { return QHash<QObject*, QV4::WeakValue>::begin(); }
ConstIterator end() const { return QHash<QObject*, QV4::WeakValue>::constEnd(); }
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index 16b9295ab7..fdc595b2a4 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -704,18 +704,18 @@ ReturnedValue RegExpPrototype::method_replace(const FunctionObject *f, const Val
int n = 1;
Scope innerScope(scope.engine);
- JSCallData cData(scope, nCaptures + 3);
+ JSCallArguments cData(scope, nCaptures + 3);
while (n <= nCaptures) {
v = resultObject->get(PropertyKey::fromArrayIndex(n));
if (!v->isUndefined())
- cData->args[n] = v->toString(scope.engine);
+ cData.args[n] = v->toString(scope.engine);
++n;
}
QString replacement;
if (functionalReplace) {
- cData->args[0] = matchString;
- cData->args[nCaptures + 1] = Encode(position);
- cData->args[nCaptures + 2] = s;
+ cData.args[0] = matchString;
+ cData.args[nCaptures + 1] = Encode(position);
+ cData.args[nCaptures + 2] = s;
ScopedValue replValue(scope, replaceFunction->call(cData));
if (scope.hasException())
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 393f99dd8f..a3b1a52535 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -802,7 +802,7 @@ ReturnedValue Runtime::GetIterator::call(ExecutionEngine *engine, const Value &i
ScopedFunctionObject f(scope, o->get(engine->symbol_iterator()));
if (!f)
return engine->throwTypeError();
- JSCallData cData(scope, 0, nullptr, o);
+ JSCallData cData(o, nullptr, 0);
ScopedObject it(scope, f->call(cData));
if (engine->hasException)
return Encode::undefined();
@@ -825,7 +825,7 @@ ReturnedValue Runtime::IteratorNext::call(ExecutionEngine *engine, const Value &
engine->throwTypeError();
return Encode(true);
}
- JSCallData cData(scope, 0, nullptr, &iterator);
+ JSCallData cData(&iterator, nullptr, 0);
ScopedObject o(scope, f->call(cData));
if (scope.hasException())
return Encode(true);
@@ -1572,7 +1572,7 @@ ReturnedValue Runtime::ConstructWithSpread::call(ExecutionEngine *engine, const
return static_cast<const FunctionObject &>(function).callAsConstructor(arguments.argv, arguments.argc, &newTarget);
}
-ReturnedValue Runtime::TailCall::call(CppStackFrame *frame, ExecutionEngine *engine)
+ReturnedValue Runtime::TailCall::call(JSTypesStackFrame *frame, ExecutionEngine *engine)
{
// IMPORTANT! The JIT assumes that this method has the same amount (or less) arguments than
// the jitted function, so it can safely do a tail call.
@@ -1588,18 +1588,19 @@ ReturnedValue Runtime::TailCall::call(CppStackFrame *frame, ExecutionEngine *eng
return engine->throwTypeError();
const FunctionObject &fo = static_cast<const FunctionObject &>(function);
- if (!frame->callerCanHandleTailCall || !fo.canBeTailCalled() || engine->debugger()
+ if (!frame->callerCanHandleTailCall() || !fo.canBeTailCalled() || engine->debugger()
|| unsigned(argc) > fo.formalParameterCount()) {
// Cannot tailcall, do a normal call:
return checkedResult(engine, fo.call(&thisObject, argv, argc));
}
memcpy(frame->jsFrame->args, argv, argc * sizeof(Value));
- frame->init(engine, fo.function(), frame->jsFrame->argValues<Value>(), argc,
- frame->callerCanHandleTailCall);
- frame->setupJSFrame(frame->savedStackTop, fo, fo.scope(), thisObject, Primitive::undefinedValue());
- engine->jsStackTop = frame->savedStackTop + frame->requiredJSStackFrameSize();
- frame->pendingTailCall = true;
+ frame->init(fo.function(), frame->jsFrame->argValues<Value>(), argc,
+ frame->callerCanHandleTailCall());
+ frame->setupJSFrame(frame->framePointer(), fo, fo.scope(), thisObject,
+ Primitive::undefinedValue());
+ engine->jsStackTop = frame->framePointer() + frame->requiredJSStackFrameSize();
+ frame->setPendingTailCall(true);
return Encode::undefined();
}
@@ -1650,7 +1651,7 @@ QV4::ReturnedValue Runtime::TypeofName::call(ExecutionEngine *engine, int nameIn
return TypeofValue::call(engine, prop);
}
-void Runtime::PushCallContext::call(CppStackFrame *frame)
+void Runtime::PushCallContext::call(JSTypesStackFrame *frame)
{
frame->jsFrame->context = ExecutionContext::newCallContext(frame)->asReturnedValue();
}
@@ -1930,14 +1931,18 @@ QV4::ReturnedValue Runtime::CreateMappedArgumentsObject::call(ExecutionEngine *e
QV4::ReturnedValue Runtime::CreateUnmappedArgumentsObject::call(ExecutionEngine *engine)
{
+ Q_ASSERT(engine->currentStackFrame->isJSTypesFrame());
Heap::InternalClass *ic = engine->internalClasses(EngineBase::Class_StrictArgumentsObject);
- return engine->memoryManager->allocObject<StrictArgumentsObject>(ic, engine->currentStackFrame)->asReturnedValue();
+ return engine->memoryManager->allocObject<StrictArgumentsObject>(
+ ic, static_cast<JSTypesStackFrame *>(engine->currentStackFrame))->asReturnedValue();
}
QV4::ReturnedValue Runtime::CreateRestParameter::call(ExecutionEngine *engine, int argIndex)
{
- const Value *values = engine->currentStackFrame->originalArguments + argIndex;
- int nValues = engine->currentStackFrame->originalArgumentsCount - argIndex;
+ Q_ASSERT(engine->currentStackFrame->isJSTypesFrame());
+ JSTypesStackFrame *frame = static_cast<JSTypesStackFrame *>(engine->currentStackFrame);
+ const Value *values = frame->argv() + argIndex;
+ int nValues = frame->argc() - argIndex;
if (nValues <= 0)
return engine->newArrayObject(0)->asReturnedValue();
return engine->newArrayObject(values, nValues)->asReturnedValue();
diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h
index d155187e48..012a43251a 100644
--- a/src/qml/jsruntime/qv4runtimeapi_p.h
+++ b/src/qml/jsruntime/qv4runtimeapi_p.h
@@ -125,7 +125,7 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
};
struct Q_QML_PRIVATE_EXPORT TailCall : Method<Throws::Yes>
{
- static ReturnedValue call(CppStackFrame *, ExecutionEngine *);
+ static ReturnedValue call(JSTypesStackFrame *, ExecutionEngine *engine);
};
/* construct */
@@ -235,7 +235,7 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
};
struct Q_QML_PRIVATE_EXPORT PushCallContext : Method<Throws::No, ChangesContext::Yes>
{
- static void call(CppStackFrame *);
+ static void call(JSTypesStackFrame *);
};
struct Q_QML_PRIVATE_EXPORT PushWithContext : Method<Throws::Yes, ChangesContext::Yes>
{
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 73fa2385fd..0523d740fb 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -253,7 +253,7 @@ public:
qsizetype count = size();
const QMetaType valueMetaType = meta(d())->valueMetaType();
- const QVariant element = engine()->toVariant(value, valueMetaType.id(), false);
+ const QVariant element = engine()->toVariant(value, valueMetaType, false);
if (index == count) {
append(element);
@@ -627,8 +627,14 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s
return Encode::undefined();
}
-ReturnedValue SequencePrototype::fromVariant(QV4::ExecutionEngine *engine, const QVariant &v,
- bool *succeeded)
+ReturnedValue SequencePrototype::fromVariant(
+ QV4::ExecutionEngine *engine, const QVariant &v, bool *succeeded)
+{
+ return fromData(engine, v.metaType(), v.constData(), succeeded);
+}
+
+ReturnedValue SequencePrototype::fromData(
+ ExecutionEngine *engine, const QMetaType &type, const void *data, bool *succeeded)
{
QV4::Scope scope(engine);
// This function is called when assigning a sequence value to a normal JS var
@@ -637,11 +643,10 @@ ReturnedValue SequencePrototype::fromVariant(QV4::ExecutionEngine *engine, const
// QObject property.
const QQmlType qmlType = QQmlMetaType::qmlType(
- v.userType(), QQmlMetaType::TypeIdCategory::MetaType);
+ type.id(), QQmlMetaType::TypeIdCategory::MetaType);
if (qmlType.isSequentialContainer()) {
*succeeded = true;
- QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QV4Sequence>(
- qmlType, v.data()));
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QV4Sequence>(qmlType, data));
return obj.asReturnedValue();
}
@@ -675,7 +680,7 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, boo
QV4::ScopedValue v(scope);
for (quint32 i = 0; i < length; ++i) {
const QMetaType valueMetaType = meta->valueMetaType();
- QVariant variant = scope.engine->toVariant(a->get(i), valueMetaType.id(), false);
+ QVariant variant = scope.engine->toVariant(a->get(i), valueMetaType, false);
if (variant.metaType() != valueMetaType && !variant.convert(valueMetaType))
variant = QVariant(valueMetaType);
meta->addValueAtEnd(result.data(), variant.constData());
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index 9143430872..603d33d6d8 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -80,7 +80,9 @@ struct Q_QML_PRIVATE_EXPORT SequencePrototype : public QV4::Object
static ReturnedValue method_sort(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
static ReturnedValue newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool readOnly, bool *succeeded);
- static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
+ static ReturnedValue fromVariant(QV4::ExecutionEngine *engine, const QVariant &v, bool *succeeded);
+ static ReturnedValue fromData(QV4::ExecutionEngine *engine, const QMetaType &type, const void *data, bool *succeeded);
+
static int metaTypeForSequence(const Object *object);
static QVariant toVariant(Object *object);
static QVariant toVariant(const Value &array, int typeHint, bool *succeeded);
diff --git a/src/qml/jsruntime/qv4stackframe_p.h b/src/qml/jsruntime/qv4stackframe_p.h
index 616fa9a5a9..5423ae35a8 100644
--- a/src/qml/jsruntime/qv4stackframe_p.h
+++ b/src/qml/jsruntime/qv4stackframe_p.h
@@ -55,55 +55,63 @@
#include <private/qv4calldata_p.h>
#include <private/qv4function_p.h>
+#include <type_traits>
+
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct Q_QML_EXPORT CppStackFrame {
- EngineBase *engine;
+struct CppStackFrame;
+struct Q_QML_PRIVATE_EXPORT CppStackFrameBase
+{
+ enum class Kind : quint8 { Bare, JS, Meta };
+
Value *savedStackTop;
CppStackFrame *parent;
Function *v4Function;
CallData *jsFrame;
- const Value *originalArguments;
int originalArgumentsCount;
int instructionPointer;
- const char *yield;
- const char *unwindHandler;
- const char *unwindLabel;
- int unwindLevel;
- bool yieldIsIterator;
- bool callerCanHandleTailCall;
- bool pendingTailCall;
- bool isTailCalling;
-
- void init(EngineBase *engine, Function *v4Function, const Value *argv, int argc, bool callerCanHandleTailCall = false) {
- this->engine = engine;
+ union {
+ struct {
+ const Value *originalArguments;
+ const char *yield;
+ const char *unwindHandler;
+ const char *unwindLabel;
+ int unwindLevel;
+ bool yieldIsIterator;
+ bool callerCanHandleTailCall;
+ bool pendingTailCall;
+ bool isTailCalling;
+ };
+ struct {
+ const QMetaType *metaTypes;
+ void **returnAndArgs;
+ };
+ };
+
+ Kind kind;
+};
+
+struct Q_QML_PRIVATE_EXPORT CppStackFrame : protected CppStackFrameBase
+{
+ // We want to have those public but we can't declare them as public without making the struct
+ // non-standard layout. So we have this other struct with "using" in between.
+ using CppStackFrameBase::instructionPointer;
+ using CppStackFrameBase::v4Function;
+ using CppStackFrameBase::jsFrame;
+
+ void init(Function *v4Function, int argc, Kind kind = Kind::Bare) {
this->v4Function = v4Function;
- originalArguments = argv;
originalArgumentsCount = argc;
instructionPointer = 0;
- yield = nullptr;
- unwindHandler = nullptr;
- unwindLabel = nullptr;
- unwindLevel = 0;
- yieldIsIterator = false;
- this->callerCanHandleTailCall = callerCanHandleTailCall;
- pendingTailCall = false;
- isTailCalling = false;
+ this->kind = kind;
}
- void push() {
- parent = engine->currentStackFrame;
- engine->currentStackFrame = this;
- savedStackTop = engine->jsStackTop;
- }
-
- void pop() {
- engine->currentStackFrame = parent;
- engine->jsStackTop = savedStackTop;
- }
+ bool isBareStackFrame() const { return kind == Kind::Bare; }
+ bool isJSTypesFrame() const { return kind == Kind::JS; }
+ bool isMetaTypesFrame() const { return kind == Kind::Meta; }
static uint requiredJSStackFrameSize(uint nRegisters) {
return CallData::HeaderSize() + nRegisters;
@@ -114,13 +122,9 @@ struct Q_QML_EXPORT CppStackFrame {
uint requiredJSStackFrameSize() const {
return requiredJSStackFrameSize(v4Function);
}
+
void setupJSFrame(Value *stackSpace, const Value &function, const Heap::ExecutionContext *scope,
- const Value &thisObject, const Value &newTarget = Value::undefinedValue()) {
- setupJSFrame(stackSpace, function, scope, thisObject, newTarget,
- v4Function->compiledFunction->nFormals, v4Function->compiledFunction->nRegisters);
- }
- void setupJSFrame(Value *stackSpace, const Value &function, const Heap::ExecutionContext *scope,
- const Value &thisObject, const Value &newTarget, uint nFormals, uint nRegisters)
+ const Value &thisObject, const Value &newTarget = Value::undefinedValue())
{
jsFrame = reinterpret_cast<CallData *>(stackSpace);
jsFrame->function = function;
@@ -128,19 +132,116 @@ struct Q_QML_EXPORT CppStackFrame {
jsFrame->accumulator = Encode::undefined();
jsFrame->thisObject = thisObject;
jsFrame->newTarget = newTarget;
+ }
+
+ QString source() const;
+ QString function() const;
+ int lineNumber() const;
+ ReturnedValue thisObject() const;
+
+ ExecutionContext *context() const
+ {
+ return static_cast<ExecutionContext *>(&jsFrame->context);
+ }
+
+ void setContext(ExecutionContext *context)
+ {
+ jsFrame->context = context;
+ }
+
+ Heap::CallContext *callContext() const
+ {
+ Heap::ExecutionContext *ctx = static_cast<ExecutionContext &>(jsFrame->context).d();\
+ while (ctx->type != Heap::ExecutionContext::Type_CallContext)
+ ctx = ctx->outer;
+ return static_cast<Heap::CallContext *>(ctx);
+ }
+
+ CppStackFrame *parentFrame() const { return parent; }
+ void setParentFrame(CppStackFrame *parentFrame) { parent = parentFrame; }
+
+ int argc() const { return originalArgumentsCount; }
+ Value *framePointer() const { return savedStackTop; }
+
+ void push(EngineBase *engine) {
+ parent = engine->currentStackFrame;
+ engine->currentStackFrame = this;
+ savedStackTop = engine->jsStackTop;
+ }
+
+ void pop(EngineBase *engine) {
+ engine->currentStackFrame = parent;
+ engine->jsStackTop = savedStackTop;
+ }
+};
+
+struct Q_QML_PRIVATE_EXPORT MetaTypesStackFrame : public CppStackFrame
+{
+ void init(Function *v4Function, void **a, const QMetaType *types, int argc)
+ {
+ CppStackFrame::init(v4Function, argc, Kind::Meta);
+ metaTypes = types;
+ returnAndArgs = a;
+ }
+
+ QMetaType returnType() const { return metaTypes[0]; }
+ void *returnValue() const { return returnAndArgs[0]; }
+
+ const QMetaType *argTypes() const { return metaTypes + 1; }
+ void **argv() const { return returnAndArgs + 1; }
+};
+
+struct Q_QML_PRIVATE_EXPORT JSTypesStackFrame : public CppStackFrame
+{
+ // The JIT needs to poke directly into those using offsetof
+ using CppStackFrame::unwindHandler;
+ using CppStackFrame::unwindLabel;
+ using CppStackFrame::unwindLevel;
+
+ void init(Function *v4Function, const Value *argv, int argc,
+ bool callerCanHandleTailCall = false)
+ {
+ CppStackFrame::init(v4Function, argc, Kind::JS);
+ CppStackFrame::originalArguments = argv;
+ CppStackFrame::yield = nullptr;
+ CppStackFrame::unwindHandler = nullptr;
+ CppStackFrame::yieldIsIterator = false;
+ CppStackFrame::callerCanHandleTailCall = callerCanHandleTailCall;
+ CppStackFrame::pendingTailCall = false;
+ CppStackFrame::isTailCalling = false;
+ CppStackFrame::unwindLabel = nullptr;
+ CppStackFrame::unwindLevel = 0;
+ }
+
+ const Value *argv() const { return originalArguments; }
+
+ void setupJSFrame(Value *stackSpace, const Value &function, const Heap::ExecutionContext *scope,
+ const Value &thisObject, const Value &newTarget = Value::undefinedValue()) {
+ setupJSFrame(stackSpace, function, scope, thisObject, newTarget,
+ v4Function->compiledFunction->nFormals,
+ v4Function->compiledFunction->nRegisters);
+ }
+
+ void setupJSFrame(
+ Value *stackSpace, const Value &function, const Heap::ExecutionContext *scope,
+ const Value &thisObject, const Value &newTarget, uint nFormals, uint nRegisters)
+ {
+ CppStackFrame::setupJSFrame(stackSpace, function, scope, thisObject, newTarget);
uint argc = uint(originalArgumentsCount);
if (argc > nFormals)
argc = nFormals;
jsFrame->setArgc(argc);
- memcpy(jsFrame->args, originalArguments, argc*sizeof(Value));
+ memcpy(jsFrame->args, originalArguments, argc * sizeof(Value));
Q_STATIC_ASSERT(Encode::undefined() == 0);
- memset(jsFrame->args + argc, 0, (nRegisters - argc)*sizeof(Value));
+ memset(jsFrame->args + argc, 0, (nRegisters - argc) * sizeof(Value));
if (v4Function && v4Function->compiledFunction) {
- const int firstDeadZoneRegister = v4Function->compiledFunction->firstTemporalDeadZoneRegister;
- const int registerDeadZoneSize = v4Function->compiledFunction->sizeOfRegisterTemporalDeadZone;
+ const int firstDeadZoneRegister
+ = v4Function->compiledFunction->firstTemporalDeadZoneRegister;
+ const int registerDeadZoneSize
+ = v4Function->compiledFunction->sizeOfRegisterTemporalDeadZone;
const Value * tdzEnd = stackSpace + firstDeadZoneRegister + registerDeadZoneSize;
for (Value *v = stackSpace + firstDeadZoneRegister; v < tdzEnd; ++v)
@@ -148,22 +249,27 @@ struct Q_QML_EXPORT CppStackFrame {
}
}
- QString source() const;
- QString function() const;
- inline QV4::ExecutionContext *context() const {
- return static_cast<ExecutionContext *>(&jsFrame->context);
- }
- int lineNumber() const;
+ bool isTailCalling() const { return CppStackFrame::isTailCalling; }
+ void setTailCalling(bool tailCalling) { CppStackFrame::isTailCalling = tailCalling; }
- inline QV4::Heap::CallContext *callContext() const {
- Heap::ExecutionContext *ctx = static_cast<ExecutionContext &>(jsFrame->context).d();\
- while (ctx->type != Heap::ExecutionContext::Type_CallContext)
- ctx = ctx->outer;
- return static_cast<Heap::CallContext *>(ctx);
- }
- ReturnedValue thisObject() const;
+ bool pendingTailCall() const { return CppStackFrame::pendingTailCall; }
+ void setPendingTailCall(bool pending) { CppStackFrame::pendingTailCall = pending; }
+
+ const char *yield() const { return CppStackFrame::yield; }
+ void setYield(const char *yield) { CppStackFrame::yield = yield; }
+
+ bool yieldIsIterator() const { return CppStackFrame::yieldIsIterator; }
+ void setYieldIsIterator(bool isIter) { CppStackFrame::yieldIsIterator = isIter; }
+
+ bool callerCanHandleTailCall() const { return CppStackFrame::callerCanHandleTailCall; }
};
+Q_STATIC_ASSERT(sizeof(CppStackFrame) == sizeof(JSTypesStackFrame));
+Q_STATIC_ASSERT(sizeof(CppStackFrame) == sizeof(MetaTypesStackFrame));
+Q_STATIC_ASSERT(std::is_standard_layout_v<CppStackFrame>);
+Q_STATIC_ASSERT(std::is_standard_layout_v<JSTypesStackFrame>);
+Q_STATIC_ASSERT(std::is_standard_layout_v<MetaTypesStackFrame>);
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4urlobject.cpp b/src/qml/jsruntime/qv4urlobject.cpp
index 937cd6e3a2..b933945a7c 100644
--- a/src/qml/jsruntime/qv4urlobject.cpp
+++ b/src/qml/jsruntime/qv4urlobject.cpp
@@ -309,13 +309,24 @@ void UrlObject::updateHost()
d()->host.set(engine(), engine()->newString(host));
}
+static bool checkUrlObjectType(ExecutionEngine *v4, const Scoped<UrlObject> &r)
+{
+ if (r)
+ return true;
+
+ v4->throwTypeError(QStringLiteral("Value of \"this\" must be of type URL"));
+ return false;
+}
+
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>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->hash()));
}
@@ -332,7 +343,9 @@ ReturnedValue UrlPrototype::method_setHash(const FunctionObject *b, const Value
if (stringValue == nullptr)
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
r->setHash(stringValue->toQString());
@@ -345,7 +358,9 @@ ReturnedValue UrlPrototype::method_getHost(const FunctionObject *b, const Value
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->host()));
}
@@ -362,7 +377,9 @@ ReturnedValue UrlPrototype::method_setHost(const FunctionObject *b, const Value
if (stringValue == nullptr)
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
QString host = stringValue->toQString();
if (!r->setHost(host))
@@ -377,7 +394,9 @@ ReturnedValue UrlPrototype::method_getHostname(const FunctionObject *b, const Va
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->hostname()));
}
@@ -394,7 +413,9 @@ ReturnedValue UrlPrototype::method_setHostname(const FunctionObject *b, const Va
if (stringValue == nullptr)
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
QString hostname = stringValue->toQString();
if (!r->setHostname(hostname))
@@ -409,7 +430,9 @@ ReturnedValue UrlPrototype::method_getHref(const FunctionObject *b, const Value
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->href()));
}
@@ -426,7 +449,9 @@ ReturnedValue UrlPrototype::method_setHref(const FunctionObject *b, const Value
if (stringValue == nullptr)
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
QString href = stringValue->toQString();
if (!r->setHref(href))
@@ -441,7 +466,9 @@ ReturnedValue UrlPrototype::method_getOrigin(const FunctionObject *b, const Valu
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->origin()));
}
@@ -452,7 +479,9 @@ ReturnedValue UrlPrototype::method_getPassword(const FunctionObject *b, const Va
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->password()));
}
@@ -469,7 +498,9 @@ ReturnedValue UrlPrototype::method_setPassword(const FunctionObject *b, const Va
if (stringValue == nullptr)
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
r->setPassword(stringValue->toQString());
@@ -482,7 +513,9 @@ ReturnedValue UrlPrototype::method_getPathname(const FunctionObject *b, const Va
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->pathname()));
}
@@ -499,7 +532,9 @@ ReturnedValue UrlPrototype::method_setPathname(const FunctionObject *b, const Va
if (stringValue == nullptr)
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
r->setPathname(stringValue->toQString());
@@ -512,7 +547,9 @@ ReturnedValue UrlPrototype::method_getPort(const FunctionObject *b, const Value
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->port()));
}
@@ -535,7 +572,9 @@ ReturnedValue UrlPrototype::method_setPort(const FunctionObject *b, const Value
else
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
if (!r->setPort(port))
return v4->throwTypeError(QLatin1String("Invalid port: %1").arg(port));
@@ -549,7 +588,9 @@ ReturnedValue UrlPrototype::method_getProtocol(const FunctionObject *b, const Va
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->protocol()));
}
@@ -566,7 +607,9 @@ ReturnedValue UrlPrototype::method_setProtocol(const FunctionObject *b, const Va
if (stringValue == nullptr)
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
r->setProtocol(stringValue->toQString());
@@ -579,7 +622,9 @@ ReturnedValue UrlPrototype::method_getSearch(const FunctionObject *b, const Valu
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->search()));
}
@@ -596,7 +641,9 @@ ReturnedValue UrlPrototype::method_setSearch(const FunctionObject *b, const Valu
if (stringValue == nullptr)
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
r->setSearch(stringValue->toQString());
@@ -609,7 +656,9 @@ ReturnedValue UrlPrototype::method_getUsername(const FunctionObject *b, const Va
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
return Encode(v4->newString(r->username()));
}
@@ -626,7 +675,9 @@ ReturnedValue UrlPrototype::method_setUsername(const FunctionObject *b, const Va
if (stringValue == nullptr)
return v4->throwTypeError(QLatin1String("Invalid parameter provided"));
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
r->setUsername(stringValue->toQString());
@@ -639,7 +690,9 @@ ReturnedValue UrlPrototype::method_getSearchParams(const FunctionObject *b, cons
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlObject> r(scope, thisObject->as<UrlObject>());
+ Scoped<UrlObject> r(scope, thisObject);
+ if (!checkUrlObjectType(v4, r))
+ return Encode::undefined();
Scoped<UrlSearchParamsObject> usp(scope, v4->newUrlSearchParamsObject());
@@ -1122,13 +1175,24 @@ PropertyAttributes UrlSearchParamsObject::virtualGetOwnProperty(const Managed *m
return Object::virtualGetOwnProperty(m, id, p);
}
-ReturnedValue UrlSearchParamsPrototype::method_toString(const FunctionObject *b, const Value *thisObject,
- const Value *, int)
+static bool checkSearchParamsType(ExecutionEngine *v4, const Scoped<UrlSearchParamsObject> &o)
+{
+ if (o)
+ return true;
+
+ v4->throwTypeError(QStringLiteral("Value of \"this\" must be of type URLSearchParams"));
+ return false;
+}
+
+ReturnedValue UrlSearchParamsPrototype::method_toString(
+ const FunctionObject *b, const Value *thisObject, const Value *, int)
{
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
auto params = o->params();
@@ -1149,7 +1213,9 @@ ReturnedValue UrlSearchParamsPrototype::method_sort(const FunctionObject *b, con
ExecutionEngine *v4 = b->engine();
Scope scope(v4);
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
QList<QStringList> params = o->params();
std::stable_sort(params.begin(), params.end(), [](QStringList a, QStringList b) { return a[0] < b[0]; });
@@ -1179,9 +1245,9 @@ ReturnedValue UrlSearchParamsPrototype::method_append(const FunctionObject *b, c
ScopedString name(scope, argName->as<String>());
ScopedString value(scope, argValue->toString(v4));
-
-
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
o->append(name->d(), value->d());
@@ -1206,7 +1272,9 @@ ReturnedValue UrlSearchParamsPrototype::method_delete(const FunctionObject *b, c
QString name = argNameString->toQString();
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
QList<QStringList> params = o->params();
@@ -1237,7 +1305,9 @@ ReturnedValue UrlSearchParamsPrototype::method_has(const FunctionObject *b, cons
if (argNameString == nullptr)
return v4->throwTypeError(QLatin1String("Invalid argument provided"));
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
QString name = argNameString->toQString();
@@ -1261,7 +1331,9 @@ ReturnedValue UrlSearchParamsPrototype::method_set(const FunctionObject *b, cons
if (argNameString == nullptr)
return v4->throwTypeError(QLatin1String("Invalid argument provided"));
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
QString name = argNameString->toQString();
QString value = argValue->toQString();
@@ -1308,7 +1380,9 @@ ReturnedValue UrlSearchParamsPrototype::method_get(const FunctionObject *b, cons
if (argNameString == nullptr)
return v4->throwTypeError(QLatin1String("Invalid argument provided"));
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
QString name = argNameString->toQString();
@@ -1337,7 +1411,9 @@ ReturnedValue UrlSearchParamsPrototype::method_getAll(const FunctionObject *b,
if (argNameString == nullptr)
return v4->throwTypeError(QLatin1String("Invalid argument provided"));
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
QString name = argNameString->toQString();
@@ -1370,16 +1446,18 @@ ReturnedValue UrlSearchParamsPrototype::method_forEach(const FunctionObject *b,
if (func == nullptr)
return v4->throwTypeError(QLatin1String("Invalid argument: must be a function"));
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
for (int i = 0; i < o->length(); i++) {
Scoped<String> name(scope, o->nameAtRaw(i));
Scoped<String> value(scope, o->valueAtRaw(i));
- QV4::JSCallData calldata(scope, 2);
+ QV4::JSCallArguments calldata(scope, 2);
- calldata->args[0] = value;
- calldata->args[1] = name;
+ calldata.args[0] = value;
+ calldata.args[1] = name;
func->call(calldata);
}
@@ -1397,7 +1475,9 @@ ReturnedValue UrlSearchParamsPrototype::method_entries(const FunctionObject *b,
if (argc != 0)
return v4->throwError(QLatin1String("Bad amount of arguments"));
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
ScopedObject params(scope, o->d()->params.get());
@@ -1416,7 +1496,9 @@ ReturnedValue UrlSearchParamsPrototype::method_keys(const FunctionObject *b,
if (argc != 0)
return v4->throwError(QLatin1String("Bad amount of arguments"));
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
ScopedObject keys(scope, o->d()->keys.get());
@@ -1435,7 +1517,9 @@ ReturnedValue UrlSearchParamsPrototype::method_values(const FunctionObject *b,
if (argc != 0)
return v4->throwError(QLatin1String("Bad amount of arguments"));
- Scoped<UrlSearchParamsObject> o(scope, thisObject->as<UrlSearchParamsObject>());
+ Scoped<UrlSearchParamsObject> o(scope, thisObject);
+ if (!checkSearchParamsType(v4, o))
+ return Encode::undefined();
ScopedObject values(scope, o->d()->values.get());
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index f606f8152d..ff1442db3b 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -429,7 +429,91 @@ static bool compareEqualInt(QV4::Value &accumulator, QV4::Value lhs, int rhs)
} \
} while (false)
-ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
+void VME::exec(MetaTypesStackFrame *frame, ExecutionEngine *engine)
+{
+ qt_v4ResolvePendingBreakpointsHook();
+ if (engine->checkStackLimits())
+ return;
+ ExecutionEngineCallDepthRecorder executionEngineCallDepthRecorder(engine);
+
+ Function *function = frame->v4Function;
+ Q_ASSERT(function->aotFunction);
+ Q_TRACE_SCOPE(QQmlV4_function_call, engine, function->name()->toQString(),
+ function->executableCompilationUnit()->fileName(),
+ function->compiledFunction->location.line,
+ function->compiledFunction->location.column);
+ Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
+
+ const qsizetype numFunctionArguments = function->aotFunction->argumentTypes.size();
+
+ Q_ALLOCA_DECLARE(void, *transformedArguments);
+ for (qsizetype i = 0; i < numFunctionArguments; ++i) {
+ const QMetaType argumentType = function->aotFunction->argumentTypes[i];
+ if (frame->argc() > i && argumentType == frame->argTypes()[i])
+ continue;
+
+ if (transformedArguments == nullptr) {
+ Q_ALLOCA_ASSIGN(void *, transformedArguments, numFunctionArguments * sizeof(void *));
+ memcpy(transformedArguments, frame->argv(), frame->argc() * sizeof(void *));
+ }
+
+ Q_ASSERT(argumentType.sizeOf() > 0);
+ Q_ALLOCA_VAR(void, arg, argumentType.sizeOf());
+ argumentType.construct(arg);
+ if (frame->argc() > i)
+ QMetaType::convert(frame->argTypes()[i], frame->argv()[i], argumentType, arg);
+
+ transformedArguments[i] = arg;
+ }
+
+ const QMetaType returnType = function->aotFunction->returnType;
+ const QMetaType frameReturn = frame->returnType();
+ Q_ALLOCA_DECLARE(void, transformedResult);
+ if (frame->returnValue() && returnType != frameReturn) {
+ Q_ASSERT(returnType.sizeOf() > 0);
+ Q_ALLOCA_ASSIGN(void, transformedResult, returnType.sizeOf());
+ }
+
+ QQmlPrivate::AOTCompiledContext aotContext;
+ if (auto context = QV4::ExecutionEngine::qmlContext(frame->context()->d())) {
+ QV4::Heap::QQmlContextWrapper *wrapper = static_cast<Heap::QmlContext *>(context)->qml();
+ aotContext.qmlScopeObject = wrapper->scopeObject;
+ aotContext.qmlContext = wrapper->context;
+ }
+
+ aotContext.engine = engine->jsEngine();
+ aotContext.compilationUnit = function->executableCompilationUnit();
+ function->aotFunction->functionPtr(
+ &aotContext, transformedResult ? transformedResult : frame->returnValue(),
+ transformedArguments ? transformedArguments : frame->argv());
+
+ if (transformedResult) {
+ // Shortcut the common case of the AOT function returning a more generic QObject pointer
+ // that we need to QObject-cast. No need to construct or destruct anything in that case.
+ if ((frameReturn.flags() & QMetaType::PointerToQObject)
+ && (returnType.flags() & QMetaType::PointerToQObject)) {
+ QObject *resultObj = *static_cast<QObject **>(transformedResult);
+ *static_cast<QObject **>(frame->returnValue())
+ = (resultObj && resultObj->metaObject()->inherits(frameReturn.metaObject()))
+ ? resultObj
+ : nullptr;
+ } else {
+ // Convert needs a pre-constructed target.
+ frameReturn.construct(frame->returnValue());
+ QMetaType::convert(returnType, transformedResult, frameReturn, frame->returnValue());
+ returnType.destruct(transformedResult);
+ }
+ }
+
+ if (transformedArguments) {
+ for (int i = 0; i < numFunctionArguments; ++i) {
+ if (i >= frame->argc() || transformedArguments[i] != frame->argv()[i])
+ function->aotFunction->argumentTypes[i].destruct(transformedArguments[i]);
+ }
+ }
+}
+
+ReturnedValue VME::exec(JSTypesStackFrame *frame, ExecutionEngine *engine)
{
qt_v4ResolvePendingBreakpointsHook();
CHECK_STACK_LIMITS(engine);
@@ -461,53 +545,9 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
debugger->enteringFunction();
ReturnedValue result;
+ Q_ASSERT(!function->aotFunction);
if (function->jittedCode != nullptr && debugger == nullptr) {
result = function->jittedCode(frame, engine);
- } else if (function->aotFunction) {
- const qsizetype numFunctionArguments = function->aotFunction->argumentTypes.size();
- Q_ALLOCA_DECLARE(void *, argumentPtrs);
-
- if (numFunctionArguments > 0) {
- Q_ALLOCA_ASSIGN(void *, argumentPtrs, numFunctionArguments * sizeof(void *));
- for (qsizetype i = 0; i < numFunctionArguments; ++i) {
- const QMetaType argumentType = function->aotFunction->argumentTypes[i];
- if (const qsizetype argumentSize = argumentType.sizeOf()) {
- Q_ALLOCA_VAR(void, argument, argumentSize);
- argumentType.construct(argument);
- if (i < frame->originalArgumentsCount) {
- engine->metaTypeFromJS(frame->originalArguments[i], argumentType.id(),
- argument);
- }
- argumentPtrs[i] = argument;
- } else {
- argumentPtrs[i] = nullptr;
- }
- }
- }
-
- Q_ALLOCA_DECLARE(void, returnValue);
- const QMetaType returnType = function->aotFunction->returnType;
- if (const qsizetype returnSize = returnType.sizeOf())
- Q_ALLOCA_ASSIGN(void, returnValue, returnSize);
-
- Scope scope(engine);
- Scoped<QmlContext> qmlContext(scope, engine->qmlContext());
- QQmlPrivate::AOTCompiledContext aotContext;
- aotContext.qmlContext = qmlContext ? qmlContext->qmlContext()->asQQmlContext() : nullptr;
- aotContext.qmlScopeObject = qmlContext ? qmlContext->qmlScope() : nullptr;
- aotContext.engine = engine->jsEngine();
- aotContext.compilationUnit = function->executableCompilationUnit();
- function->aotFunction->functionPtr(&aotContext, returnValue, argumentPtrs);
-
- if (returnValue) {
- result = engine->metaTypeToJS(returnType, returnValue);
- returnType.destruct(returnValue);
- } else {
- result = Encode::undefined();
- }
-
- for (qsizetype i = 0; i < numFunctionArguments; ++i)
- function->aotFunction->argumentTypes[i].destruct(argumentPtrs[i]);
} else {
// interpreter
result = interpret(frame, engine, function->codeData);
@@ -519,7 +559,7 @@ ReturnedValue VME::exec(CppStackFrame *frame, ExecutionEngine *engine)
return result;
}
-QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, const char *code)
+QV4::ReturnedValue VME::interpret(JSTypesStackFrame *frame, ExecutionEngine *engine, const char *code)
{
QV4::Function *function = frame->v4Function;
QV4::Value &accumulator = frame->jsFrame->accumulator.asValue<Value>();
@@ -671,6 +711,18 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
CHECK_EXCEPTION;
MOTH_END_INSTR(LoadProperty)
+ MOTH_BEGIN_INSTR(LoadOptionalProperty)
+ STORE_IP();
+ STORE_ACC();
+ if (accumulator.isNullOrUndefined()) {
+ acc = Encode::undefined();
+ code += offset;
+ } else {
+ acc = Runtime::LoadProperty::call(engine, accumulator, name);
+ }
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(LoadOptionalProperty)
+
MOTH_BEGIN_INSTR(GetLookup)
STORE_IP();
STORE_ACC();
@@ -689,6 +741,21 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
CHECK_EXCEPTION;
MOTH_END_INSTR(GetLookup)
+ MOTH_BEGIN_INSTR(GetOptionalLookup)
+ STORE_IP();
+ STORE_ACC();
+
+ QV4::Lookup *l = function->executableCompilationUnit()->runtimeLookups + index;
+
+ if (accumulator.isNullOrUndefined()) {
+ acc = Encode::undefined();
+ code += offset;
+ } else {
+ acc = l->getter(l, engine, accumulator);
+ }
+ CHECK_EXCEPTION;
+ MOTH_END_INSTR(GetOptionalLookup)
+
MOTH_BEGIN_INSTR(StoreProperty)
STORE_IP();
STORE_ACC();
@@ -719,14 +786,14 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine,
MOTH_END_INSTR(StoreSuperProperty)
MOTH_BEGIN_INSTR(Yield)
- frame->yield = code;
- frame->yieldIsIterator = false;
+ frame->setYield(code);
+ frame->setYieldIsIterator(false);
return acc;
MOTH_END_INSTR(Yield)
MOTH_BEGIN_INSTR(YieldStar)
- frame->yield = code;
- frame->yieldIsIterator = true;
+ frame->setYield(code);
+ frame->setYieldIsIterator(true);
return acc;
MOTH_END_INSTR(YieldStar)
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index b3944f5454..1ccb6bb2ed 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -66,8 +66,10 @@ public:
QV4::Function *function;
const QV4::ExecutionContext *scope;
};
- static QV4::ReturnedValue exec(CppStackFrame *frame, ExecutionEngine *engine);
- static QV4::ReturnedValue interpret(CppStackFrame *frame, ExecutionEngine *engine, const char *codeEntry);
+
+ static void exec(MetaTypesStackFrame *frame, ExecutionEngine *engine);
+ static QV4::ReturnedValue exec(JSTypesStackFrame *frame, ExecutionEngine *engine);
+ static QV4::ReturnedValue interpret(JSTypesStackFrame *frame, ExecutionEngine *engine, const char *codeEntry);
};
} // namespace Moth
diff --git a/src/qml/jsruntime/qv4vtable_p.h b/src/qml/jsruntime/qv4vtable_p.h
index 588205f046..a71c9da691 100644
--- a/src/qml/jsruntime/qv4vtable_p.h
+++ b/src/qml/jsruntime/qv4vtable_p.h
@@ -84,6 +84,7 @@ struct VTable
typedef ReturnedValue (*InstanceOf)(const Object *typeObject, const Value &var);
typedef ReturnedValue (*Call)(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ typedef void (*CallWithMetaTypes)(const FunctionObject *, const Value *, void **, const QMetaType *, int);
typedef ReturnedValue (*CallAsConstructor)(const FunctionObject *, const Value *argv, int argc, const Value *newTarget);
typedef ReturnedValue (*ResolveLookupGetter)(const Object *, ExecutionEngine *, Lookup *);
@@ -123,11 +124,63 @@ struct VTable
Call call;
CallAsConstructor callAsConstructor;
+ CallWithMetaTypes callWithMetaTypes;
ResolveLookupGetter resolveLookupGetter;
ResolveLookupSetter resolveLookupSetter;
};
+template<VTable::CallWithMetaTypes call>
+struct VTableCallWithMetaTypesWrapper { constexpr static VTable::CallWithMetaTypes c = call; };
+
+template<VTable::Call call>
+struct VTableCallWrapper { constexpr static VTable::Call c = call; };
+
+template<class Class>
+constexpr VTable::CallWithMetaTypes vtableMetaTypesCallEntry()
+{
+ // If Class overrides virtualCallWithMetaTypes, return that.
+ // Otherwise, if it overrides virtualCall, return nullptr so that we convert calls.
+ // Otherwise, just return whatever the base class had.
+
+ // A simple != is not considered constexpr, so we have to jump through some hoops.
+ if constexpr (!std::is_same_v<
+ VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>,
+ VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>) {
+ return Class::virtualCallWithMetaTypes;
+ }
+
+ if constexpr (!std::is_same_v<
+ VTableCallWrapper<Class::virtualCall>,
+ VTableCallWrapper<Class::SuperClass::virtualCall>>) {
+ return nullptr;
+ }
+
+ return Class::virtualCallWithMetaTypes;
+}
+
+template<class Class>
+constexpr VTable::Call vtableJsTypesCallEntry()
+{
+ // If Class overrides virtualCall, return that.
+ // Otherwise, if it overrides virtualCallWithMetaTypes, return nullptr so that we convert calls.
+ // Otherwise, just return whatever the base class had.
+
+ // A simple != is not considered constexpr, so we have to jump through some hoops.
+ if constexpr (!std::is_same_v<
+ VTableCallWrapper<Class::virtualCall>,
+ VTableCallWrapper<Class::SuperClass::virtualCall>>) {
+ return Class::virtualCall;
+ }
+
+ if constexpr (!std::is_same_v<
+ VTableCallWithMetaTypesWrapper<Class::virtualCallWithMetaTypes>,
+ VTableCallWithMetaTypesWrapper<Class::SuperClass::virtualCallWithMetaTypes>>) {
+ return nullptr;
+ }
+
+ return Class::virtualCall;
+}
struct VTableBase {
protected:
@@ -150,9 +203,16 @@ protected:
static constexpr VTable::Call virtualCall = nullptr;
static constexpr VTable::CallAsConstructor virtualCallAsConstructor = nullptr;
+ static constexpr VTable::CallWithMetaTypes virtualCallWithMetaTypes = nullptr;
static constexpr VTable::ResolveLookupGetter virtualResolveLookupGetter = nullptr;
static constexpr VTable::ResolveLookupSetter virtualResolveLookupSetter = nullptr;
+
+ template<class Class>
+ friend constexpr VTable::CallWithMetaTypes vtableMetaTypesCallEntry();
+
+ template<class Class>
+ friend constexpr VTable::Call vtableJsTypesCallEntry();
};
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
@@ -190,8 +250,9 @@ protected:
classname::virtualOwnPropertyKeys, \
classname::virtualInstanceOf, \
\
- classname::virtualCall, \
- classname::virtualCallAsConstructor, \
+ QV4::vtableJsTypesCallEntry<classname>(), \
+ classname::virtualCallAsConstructor, \
+ QV4::vtableMetaTypesCallEntry<classname>(), \
\
classname::virtualResolveLookupGetter, \
classname::virtualResolveLookupSetter \
diff --git a/src/qml/memory/qv4heap_p.h b/src/qml/memory/qv4heap_p.h
index 6e11d93f58..5fb14332ab 100644
--- a/src/qml/memory/qv4heap_p.h
+++ b/src/qml/memory/qv4heap_p.h
@@ -50,12 +50,11 @@
// We mean it.
//
-#include <QtCore/QString>
#include <private/qv4global_p.h>
#include <private/qv4mmdefs_p.h>
#include <private/qv4writebarrier_p.h>
#include <private/qv4vtable_p.h>
-#include <QSharedPointer>
+#include <QtCore/QSharedPointer>
// To check if Heap::Base::init is called (meaning, all subclasses did their init and called their
// parent's init all up the inheritance chain), define QML_CHECK_INIT_DESTROY_CALLS below.
diff --git a/src/qml/memory/qv4mmdefs_p.h b/src/qml/memory/qv4mmdefs_p.h
index 43e81e0434..5d92786a70 100644
--- a/src/qml/memory/qv4mmdefs_p.h
+++ b/src/qml/memory/qv4mmdefs_p.h
@@ -54,7 +54,6 @@
#include <private/qv4runtimeapi_p.h>
#include <QtCore/qalgorithms.h>
#include <QtCore/qmath.h>
-#include <qdebug.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index f10bde5ff1..2716983f42 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -81,6 +81,7 @@
%token T_COMPATIBILITY_SEMICOLON
%token T_ARROW "=>"
%token T_QUESTION_QUESTION "??"
+%token T_QUESTION_DOT "?."
%token T_ENUM "enum"
%token T_ELLIPSIS "..."
%token T_YIELD "yield"
@@ -2301,7 +2302,16 @@ MemberExpression: MemberExpression T_LBRACKET Expression_In T_RBRACKET;
sym(1).Node = node;
} break;
./
-
+MemberExpression: MemberExpression T_QUESTION_DOT T_LBRACKET Expression_In T_RBRACKET;
+/.
+ case $rule_number: {
+ AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(4).Expression);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ node->isOptional = true;
+ sym(1).Node = node;
+ } break;
+./
-- the identifier has to be "target", catched at codegen time
NewTarget: T_NEW T_DOT T_IDENTIFIER;
@@ -2324,6 +2334,17 @@ MemberExpression: MemberExpression T_DOT IdentifierName;
} break;
./
+MemberExpression: MemberExpression T_QUESTION_DOT IdentifierName;
+/.
+ case $rule_number: {
+ AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ node->isOptional = true;
+ sym(1).Node = node;
+ } break;
+./
+
MemberExpression: MetaProperty;
MemberExpression: T_NEW MemberExpression T_LPAREN Arguments T_RPAREN;
@@ -2372,6 +2393,17 @@ CallExpression: MemberExpression T_LPAREN Arguments T_RPAREN;
} break;
./
+CallExpression: MemberExpression T_QUESTION_DOT T_LPAREN Arguments T_RPAREN;
+/.
+ case $rule_number: {
+ AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(4).ArgumentList);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->isOptional = true;
+ sym(1).Node = node;
+ } break;
+./
+
CallExpression: Super T_LPAREN Arguments T_RPAREN;
/. case $rule_number: Q_FALLTHROUGH(); ./
CallExpression: CallExpression T_LPAREN Arguments T_RPAREN;
@@ -2384,6 +2416,18 @@ CallExpression: CallExpression T_LPAREN Arguments T_RPAREN;
} break;
./
+CallExpression: CallExpression T_QUESTION_DOT T_LPAREN Arguments T_RPAREN;
+/.
+ case $rule_number: {
+ AST::CallExpression *node = new (pool) AST::CallExpression(sym(1).Expression, sym(4).ArgumentList);
+ node->lparenToken = loc(3);
+ node->rparenToken = loc(5);
+ node->isOptional = true;
+ sym(1).Node = node;
+ } break;
+./
+
+
CallExpression: CallExpression T_LBRACKET Expression_In T_RBRACKET;
/.
case $rule_number: {
@@ -2394,6 +2438,17 @@ CallExpression: CallExpression T_LBRACKET Expression_In T_RBRACKET;
} break;
./
+CallExpression: CallExpression T_QUESTION_DOT T_LBRACKET Expression_In T_RBRACKET;
+/.
+ case $rule_number: {
+ AST::ArrayMemberExpression *node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(4).Expression);
+ node->lbracketToken = loc(3);
+ node->rbracketToken = loc(5);
+ node->isOptional = true;
+ sym(1).Node = node;
+ } break;
+./
+
CallExpression: CallExpression T_DOT IdentifierName;
/.
case $rule_number: {
@@ -2404,6 +2459,17 @@ CallExpression: CallExpression T_DOT IdentifierName;
} break;
./
+CallExpression: CallExpression T_QUESTION_DOT IdentifierName;
+/.
+ case $rule_number: {
+ AST::FieldMemberExpression *node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
+ node->dotToken = loc(2);
+ node->identifierToken = loc(3);
+ node->isOptional = true;
+ sym(1).Node = node;
+ } break;
+./
+
Arguments: ;
/.
case $rule_number: {
@@ -2897,6 +2963,9 @@ AssignmentExpression: LeftHandSideExpression T_EQ AssignmentExpression;
AssignmentExpression_In: LeftHandSideExpression T_EQ AssignmentExpression_In;
/.
case $rule_number: {
+ if (sym(1).Expression->containsOptionalChain()) {
+ syntaxError(loc(1), QStringLiteral("Optional chains are not permitted on the left-hand-side in assignments"));
+ }
// need to convert the LHS to an AssignmentPattern if it was an Array/ObjectLiteral
if (AST::Pattern *p = sym(1).Expression->patternCast()) {
SourceLocation errorLoc;
@@ -2927,6 +2996,9 @@ AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpres
AssignmentExpression_In: LeftHandSideExpression AssignmentOperator AssignmentExpression_In;
/.
case $rule_number: {
+ if (sym(1).Expression->containsOptionalChain()) {
+ syntaxError(loc(1), QStringLiteral("Optional chains are not permitted on the left-hand-side in assignments"));
+ }
AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, sym(2).ival, sym(3).Expression);
node->operatorToken = loc(2);
sym(1).Node = node;
@@ -4043,14 +4115,14 @@ ArrowFunction_In: ArrowParameters T_ARROW ConciseBodyLookahead AssignmentExpress
/.
case $rule_number: {
AST::ReturnStatement *ret = new (pool) AST::ReturnStatement(sym(4).Expression);
- ret->returnToken = sym(4).Node->firstSourceLocation();
- ret->semicolonToken = sym(4).Node->lastSourceLocation();
+ ret->returnToken = sym(4).Node->firstSourceLocation().startZeroLengthLocation();
+ ret->semicolonToken = sym(4).Node->lastSourceLocation().endZeroLengthLocation(driver->code());
AST::StatementList *statements = (new (pool) AST::StatementList(ret))->finish();
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(QStringView(), sym(1).FormalParameterList, statements);
f->isArrowFunction = true;
- f->functionToken = sym(1).Node ? sym(1).Node->firstSourceLocation() : loc(1);
- f->lbraceToken = sym(4).Node->firstSourceLocation();
- f->rbraceToken = sym(4).Node->lastSourceLocation();
+ f->functionToken = sym(1).Node ? sym(1).Node->firstSourceLocation().startZeroLengthLocation() : loc(1).startZeroLengthLocation();
+ f->lbraceToken = sym(4).Node->firstSourceLocation().startZeroLengthLocation();
+ f->rbraceToken = sym(4).Node->lastSourceLocation().endZeroLengthLocation(driver->code());
sym(1).Node = f;
} break;
./
@@ -4062,7 +4134,7 @@ ArrowFunction_In: ArrowParameters T_ARROW ConciseBodyLookahead T_FORCE_BLOCK Fun
case $rule_number: {
AST::FunctionExpression *f = new (pool) AST::FunctionExpression(QStringView(), sym(1).FormalParameterList, sym(6).StatementList);
f->isArrowFunction = true;
- f->functionToken = sym(1).Node ? sym(1).Node->firstSourceLocation() : loc(1);
+ f->functionToken = sym(1).Node ? sym(1).Node->firstSourceLocation().startZeroLengthLocation() : loc(1).startZeroLengthLocation();
f->lbraceToken = loc(6);
f->rbraceToken = loc(7);
sym(1).Node = f;
diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp
index 4b5d866662..a068a412df 100644
--- a/src/qml/parser/qqmljsast.cpp
+++ b/src/qml/parser/qqmljsast.cpp
@@ -118,6 +118,44 @@ ExpressionNode *ExpressionNode::expressionCast()
return this;
}
+bool ExpressionNode::containsOptionalChain() const
+{
+ for (const Node *node = this;;) {
+ switch (node->kind) {
+ case Kind_FieldMemberExpression: {
+ const auto *fme = AST::cast<const FieldMemberExpression*>(node);
+ if (fme->isOptional)
+ return true;
+ node = fme->base;
+ break;
+ }
+ case Kind_ArrayMemberExpression: {
+ const auto *ame = AST::cast<const ArrayMemberExpression*>(node);
+ if (ame->isOptional)
+ return true;
+ node = ame->base;
+ break;
+ }
+ case Kind_CallExpression: {
+ const auto *ce = AST::cast<const CallExpression*>(node);
+ if (ce->isOptional)
+ return true;
+ node = ce->base;
+ break;
+ }
+ case Kind_NestedExpression: {
+ const auto *ne = AST::cast<const NestedExpression*>(node);
+ node = ne->expression;
+ break;
+ }
+ default:
+ // These unhandled nodes lead to invalid lvalues anyway, so they do not need to be handled here.
+ return false;
+ }
+ }
+ return false;
+}
+
FormalParameterList *ExpressionNode::reparseAsFormalParameterList(MemoryPool *pool)
{
AST::ExpressionNode *expr = this;
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index cb6d5fa3ee..d32595429e 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -460,6 +460,7 @@ public:
ExpressionNode() {}
ExpressionNode *expressionCast() override;
+ bool containsOptionalChain() const;
AST::FormalParameterList *reparseAsFormalParameterList(MemoryPool *pool);
@@ -1198,6 +1199,7 @@ public:
ExpressionNode *expression;
SourceLocation lbracketToken;
SourceLocation rbracketToken;
+ bool isOptional = false;
};
class QML_PARSER_EXPORT FieldMemberExpression: public LeftHandSideExpression
@@ -1222,6 +1224,7 @@ public:
QStringView name;
SourceLocation dotToken;
SourceLocation identifierToken;
+ bool isOptional = false;
};
class QML_PARSER_EXPORT TaggedTemplate : public LeftHandSideExpression
@@ -1314,6 +1317,7 @@ public:
ArgumentList *arguments;
SourceLocation lparenToken;
SourceLocation rparenToken;
+ bool isOptional = false;
};
class QML_PARSER_EXPORT ArgumentList: public Node
@@ -2957,7 +2961,6 @@ public:
ExportDeclaration(FromClause *fromClause)
: fromClause(fromClause)
{
- exportAll = true;
kind = K;
}
@@ -2980,6 +2983,11 @@ public:
kind = K;
}
+ bool exportsAll() const
+ {
+ return fromClause && !exportClause;
+ }
+
void accept0(BaseVisitor *visitor) override;
SourceLocation firstSourceLocation() const override
@@ -2989,7 +2997,6 @@ public:
// attributes
SourceLocation exportToken;
- bool exportAll = false;
ExportClause *exportClause = nullptr;
FromClause *fromClause = nullptr;
Node *variableStatementOrDeclaration = nullptr;
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index 5f0276da8f..1b58f687e2 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -184,6 +184,14 @@ void Lexer::scanChar()
}
}
+QChar Lexer::peekChar()
+{
+ auto peekPtr = _codePtr;
+ if (peekPtr < _endPtr)
+ return *peekPtr;
+ return QChar();
+}
+
namespace {
inline bool isBinop(int tok)
{
@@ -583,6 +591,10 @@ again:
scanChar();
return T_QUESTION_QUESTION;
}
+ if (_char == u'.' && !peekChar().isDigit()) {
+ scanChar();
+ return T_QUESTION_DOT;
+ }
return T_QUESTION;
}
diff --git a/src/qml/parser/qqmljslexer_p.h b/src/qml/parser/qqmljslexer_p.h
index 7b4c219506..b7ac4a3940 100644
--- a/src/qml/parser/qqmljslexer_p.h
+++ b/src/qml/parser/qqmljslexer_p.h
@@ -191,6 +191,7 @@ protected:
private:
inline void scanChar();
+ inline QChar peekChar();
int scanToken();
int scanNumber(QChar ch);
int scanVersionNumber(QChar ch);
diff --git a/src/qml/qml/ftw/qqmlnullablevalue_p.h b/src/qml/qml/ftw/qqmlnullablevalue_p.h
index 5b3d2fc456..899dae457d 100644
--- a/src/qml/qml/ftw/qqmlnullablevalue_p.h
+++ b/src/qml/qml/ftw/qqmlnullablevalue_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <QtCore/qglobal.h>
+
QT_BEGIN_NAMESPACE
template<typename T>
diff --git a/src/qml/qml/ftw/qrecyclepool_p.h b/src/qml/qml/ftw/qrecyclepool_p.h
index 39f4f88512..3ba488d586 100644
--- a/src/qml/qml/ftw/qrecyclepool_p.h
+++ b/src/qml/qml/ftw/qrecyclepool_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <QtCore/qglobal.h>
+
QT_BEGIN_NAMESPACE
#define QRECYCLEPOOLCOOKIE 0x33218ADF
diff --git a/src/qml/qml/qqml.cpp b/src/qml/qml/qqml.cpp
index cb55c0d834..a0fbe507fd 100644
--- a/src/qml/qml/qqml.cpp
+++ b/src/qml/qml/qqml.cpp
@@ -49,6 +49,9 @@
#include <private/qqmltypemodule_p.h>
#include <private/qqmltypenotavailable_p.h>
#include <private/qqmlcomponent_p.h>
+#include <private/qqmltypewrapper_p.h>
+#include <private/qv4lookup_p.h>
+#include <private/qv4qobjectwrapper_p.h>
#include <QtCore/qmutex.h>
@@ -57,6 +60,19 @@ QT_BEGIN_NAMESPACE
/*!
\internal
+
+ This method completes the setup of all deferred properties of \a object.
+ Deferred properties are declared with
+ Q_CLASSINFO("DeferredPropertyNames", "comma,separated,property,list");
+
+ Any binding to a deferred property is not executed when the object is instantiated,
+ but only when completion is requested with qmlExecuteDeferred, or by manually
+ calling QQmlComponentPrivate::beginDeferred and completeDeferred.
+
+ \sa QV4::CompiledData::Binding::IsDeferredBinding,
+ QV4::CompiledData::Object::HasDeferredBindings,
+ QQmlData::deferData,
+ QQmlObjectCreator::setupBindings
*/
void qmlExecuteDeferred(QObject *object)
{
@@ -671,6 +687,11 @@ namespace QQmlPrivate {
}
}
+QQmlEngine *QQmlPrivate::AOTCompiledContext::qmlEngine() const
+{
+ return qmlContext ? qmlContext->engine() : nullptr;
+}
+
QJSValue QQmlPrivate::AOTCompiledContext::jsMetaType(int index) const
{
return QJSValuePrivate::fromReturnedValue(
@@ -683,4 +704,213 @@ void QQmlPrivate::AOTCompiledContext::setInstructionPointer(int offset) const
frame->instructionPointer = offset;
}
+QJSValue QQmlPrivate::AOTCompiledContext::loadQmlContextPropertyLookup(uint index) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ return QJSValuePrivate::fromReturnedValue(l->qmlContextPropertyGetter(
+ l, engine->handle(), nullptr));
+}
+
+bool QQmlPrivate::AOTCompiledContext::captureQmlContextPropertyLookup(uint index) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ if (l->qmlContextPropertyGetter != QV4::QQmlContextWrapper::lookupScopeObjectProperty
+ && l->qmlContextPropertyGetter != QV4::QQmlContextWrapper::lookupContextObjectProperty) {
+ return false;
+ }
+
+ const auto *property = l->qobjectLookup.propertyData;
+ Q_ASSERT(property);
+ if (property->isConstant())
+ return true;
+
+ if (QQmlEngine *engine = qmlContext->engine()) {
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
+ if (QQmlPropertyCapture *capture = ep->propertyCapture)
+ capture->captureProperty(qmlScopeObject, l->qobjectLookup.propertyCache, property);
+ }
+
+ return true;
+}
+
+QObject *QQmlPrivate::AOTCompiledContext::loadQmlContextPropertyIdLookup(uint index) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ if (l->qmlContextPropertyGetter == QV4::QQmlContextWrapper::lookupIdObject) {
+ // Shortcut this to avoid the wrapping when returning from lookupIdObject().
+ if (!qmlContext)
+ return nullptr;
+
+ QQmlEnginePrivate *qmlEngine = QQmlEnginePrivate::get(qmlContext->engine());
+ const int objectId = l->qmlContextIdObjectLookup.objectId;
+
+ if (QQmlPropertyCapture *capture = qmlEngine->propertyCapture)
+ capture->captureProperty(qmlContext->idValueBindings(objectId));
+ return qmlContext->idValue(objectId);
+ }
+
+ QV4::Scope scope(engine->handle());
+ QV4::Scoped<QV4::QObjectWrapper> o(
+ scope, l->qmlContextPropertyGetter(l, scope.engine, nullptr));
+ return o ? o->object() : nullptr;
+}
+
+bool QQmlPrivate::AOTCompiledContext::getObjectLookup(
+ uint index, QObject *object, void *target, QMetaType type) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+
+ if (!object)
+ return false;
+
+ const QQmlPropertyCache *propertyCache = l->qobjectLookup.propertyCache;
+ if (l->getter == QV4::QObjectWrapper::lookupGetter
+ && !QQmlData::wasDeleted(object)
+ && QQmlData::get(object)->propertyCache == propertyCache) {
+ const QQmlPropertyData *property = l->qobjectLookup.propertyData;
+ if (property->propType() == type) {
+ // We can directly read the property into the target, without conversion.
+ if (!property->isConstant()) {
+ if (QQmlEngine *engine = qmlContext->engine()) {
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
+ if (QQmlPropertyCapture *capture = ep->propertyCapture)
+ capture->captureProperty(object, propertyCache, property);
+ }
+ }
+ property->readProperty(object, target);
+ return true;
+ }
+ }
+
+ QV4::Scope scope(engine->handle());
+ QV4::ScopedValue o(scope, QV4::QObjectWrapper::wrap(scope.engine, object));
+ QV4::ScopedValue result(scope, l->getter(l, scope.engine, o));
+ if (type == QMetaType::fromType<QVariant>()) {
+ // Special case QVariant in order to retain JS objects.
+ // We don't want to convert JS arrays into QVariantList, for example.
+ *static_cast<QVariant *>(target) = scope.engine->toVariant(result, QMetaType {});
+ return true;
+ }
+ return scope.engine->metaTypeFromJS(result, type, target);
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::callQmlContextPropertyLookup(
+ uint index, const QJSValueList &args) const
+{
+ QV4::Scope scope(engine->handle());
+ const int argc = args.length();
+ QV4::Value *argv = scope.alloc(args.length());
+ for (int i = 0; i < argc; ++i)
+ argv[i] = QJSValuePrivate::convertToReturnedValue(scope.engine, args.at(i));
+ return QJSValuePrivate::fromReturnedValue(QV4::Runtime::CallQmlContextPropertyLookup::call(
+ engine->handle(), index, argv, argc));
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::getLookup(uint index, const QJSValue &object) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+
+ if (object.isNull() || object.isUndefined()) {
+ QString message = QStringLiteral("Cannot read property '%1' of %2")
+ .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString(), object.toString());
+ return QJSValuePrivate::fromReturnedValue(engine->handle()->throwTypeError(message));
+ }
+
+ return QJSValuePrivate::fromReturnedValue(
+ l->getter(l, engine->handle(),
+ QJSValuePrivate::convertToReturnedValue(engine->handle(), object)));
+}
+
+bool QQmlPrivate::AOTCompiledContext::captureLookup(uint index, QObject *object) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ if (l->getter != QV4::QQmlTypeWrapper::lookupSingletonProperty
+ && l->getter != QV4::QObjectWrapper::lookupGetter) {
+ return false;
+ }
+
+ const QQmlPropertyData *property = l->qobjectLookup.propertyData;
+ Q_ASSERT(property);
+ if (property->isConstant())
+ return true;
+
+ if (QQmlEngine *engine = qmlContext->engine()) {
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
+ if (QQmlPropertyCapture *capture = ep->propertyCapture)
+ capture->captureProperty(object, l->qobjectLookup.propertyCache, property);
+ return true;
+ }
+
+ return false;
+}
+
+void QQmlPrivate::AOTCompiledContext::setLookup(
+ uint index, const QJSValue &object, const QJSValue &value) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ QV4::Scope scope(engine->handle());
+ QV4::ScopedValue o(scope, QJSValuePrivate::convertToReturnedValue(scope.engine, object));
+ if (!l->setter(l, engine->handle(), *o,
+ QJSValuePrivate::convertToReturnedValue(engine->handle(), value))) {
+ engine->handle()->throwTypeError();
+ }
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::callPropertyLookup(
+ uint index, const QJSValue &object, const QJSValueList &args) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ QV4::Scope scope(engine->handle());
+ QV4::ScopedValue o(scope, QJSValuePrivate::convertToReturnedValue(scope.engine, object));
+
+ // ok to have the value on the stack here
+ QV4::Value f = QV4::Value::fromReturnedValue(l->getter(l, engine->handle(), o));
+
+ if (Q_UNLIKELY(!f.isFunctionObject())) {
+ QString message = QStringLiteral("Property '%1' of object %2 is not a function")
+ .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString(),
+ object.toString());
+ engine->handle()->throwTypeError(message);
+ return QJSValue();
+ }
+
+ const int argc = args.length();
+ QV4::Value *argv = scope.alloc(args.length());
+ for (int i = 0; i < argc; ++i)
+ argv[i] = QJSValuePrivate::convertToReturnedValue(scope.engine, args.at(i));
+
+ return QJSValuePrivate::fromReturnedValue(
+ static_cast<QV4::FunctionObject &>(f).call(o, argv, argc));
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::callGlobalLookup(
+ uint index, const QJSValueList &args) const
+{
+ QV4::Scope scope(engine->handle());
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ QV4::Value function = QV4::Value::fromReturnedValue(l->globalGetter(l, scope.engine));
+ if (!function.isFunctionObject()) {
+ const QString msg = QStringLiteral("Property '%1' of object [null] is not a function")
+ .arg(compilationUnit->runtimeStrings[l->nameIndex]->toQString());
+ return QJSValuePrivate::fromReturnedValue(scope.engine->throwTypeError(msg));
+ }
+
+ const int argc = args.length();
+ QV4::Value *argv = scope.alloc(args.length());
+ for (int i = 0; i < argc; ++i)
+ argv[i] = QJSValuePrivate::convertToReturnedValue(scope.engine, args.at(i));
+
+ QV4::Value thisObject = QV4::Value::undefinedValue();
+ QV4::ReturnedValue result = static_cast<QV4::FunctionObject &>(function).call(
+ &thisObject, argv, argc);
+
+ return scope.engine->hasException ? QJSValue() : QJSValuePrivate::fromReturnedValue(result);
+}
+
+QJSValue QQmlPrivate::AOTCompiledContext::loadGlobalLookup(uint index) const
+{
+ QV4::Lookup *l = compilationUnit->runtimeLookups + index;
+ return QJSValuePrivate::fromReturnedValue(l->globalGetter(l, engine->handle()));
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqml.h b/src/qml/qml/qqml.h
index 078bd93d25..d485b5367d 100644
--- a/src/qml/qml/qqml.h
+++ b/src/qml/qml/qqml.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQml module of the Qt Toolkit.
@@ -42,6 +42,7 @@
#include <QtQml/qqmlprivate.h>
#include <QtQml/qjsvalue.h>
+#include <QtQml/qqmlregistration.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qmetaobject.h>
@@ -51,12 +52,6 @@
#define QML_VERSION 0x020000
#define QML_VERSION_STR "2.0"
-#define QML_PRIVATE_NAMESPACE \
- QT_PREPEND_NAMESPACE(QQmlPrivate)
-
-#define QML_REGISTER_TYPES_AND_REVISIONS \
- QT_PREPEND_NAMESPACE(qmlRegisterTypesAndRevisions)
-
#define QML_DECLARE_TYPE(TYPE) \
Q_DECLARE_METATYPE(TYPE *) \
Q_DECLARE_METATYPE(QQmlListProperty<TYPE>)
@@ -70,95 +65,6 @@
#define QML_DECLARE_INTERFACE_HASMETATYPE(INTERFACE) \
QML_DECLARE_TYPE_HASMETATYPE(INTERFACE)
-#define QML_ELEMENT \
- Q_CLASSINFO("QML.Element", "auto")
-
-#define QML_ANONYMOUS \
- Q_CLASSINFO("QML.Element", "anonymous")
-
-#define QML_NAMED_ELEMENT(NAME) \
- Q_CLASSINFO("QML.Element", #NAME)
-
-#define QML_VALUE_TYPE(NAME) \
- Q_CLASSINFO("QML.Element", #NAME) \
- QML_UNCREATABLE("Value types cannot be created.")
-
-#define QML_UNCREATABLE(REASON) \
- Q_CLASSINFO("QML.Creatable", "false") \
- Q_CLASSINFO("QML.UncreatableReason", REASON)
-
-#define QML_SINGLETON \
- Q_CLASSINFO("QML.Singleton", "true") \
- 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, QList<int> *);
-
-#define QML_SEQUENTIAL_CONTAINER(VALUE_TYPE) \
- Q_CLASSINFO("QML.Sequence", #VALUE_TYPE) \
- using QmlSequenceValueType = VALUE_TYPE; \
- enum class QmlIsSequence {yes = true}; \
- template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlSequence; \
- template<typename T, typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<int> *);
-
-#define QML_ADDED_IN_MINOR_VERSION(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.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) \
- using QmlAttachedType = ATTACHED_TYPE; \
- template<class, class, bool> friend struct QML_PRIVATE_NAMESPACE::QmlAttached; \
- template<class> friend struct QML_PRIVATE_NAMESPACE::QmlAttachedAccessor;
-
-#define QML_EXTENDED(EXTENDED_TYPE) \
- Q_CLASSINFO("QML.Extended", #EXTENDED_TYPE) \
- 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, QList<int> *);
-
-#define QML_EXTENDED_NAMESPACE(EXTENDED_NAMESPACE) \
- Q_CLASSINFO("QML.Extended", #EXTENDED_NAMESPACE) \
- static constexpr const QMetaObject *qmlExtendedNamespace() { return &EXTENDED_NAMESPACE::staticMetaObject; } \
- template<class, class> friend struct QML_PRIVATE_NAMESPACE::QmlExtendedNamespace; \
- template<typename T, typename... Args> \
- friend void QML_REGISTER_TYPES_AND_REVISIONS(const char *uri, int versionMajor, QList<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, QList<int> *);
-
-#define QML_FOREIGN_NAMESPACE(FOREIGN_NAMESPACE) \
- Q_CLASSINFO("QML.Foreign", #FOREIGN_NAMESPACE)
-
-#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, QList<int> *);
-
-#define QML_IMPLEMENTS_INTERFACES(INTERFACES) \
- Q_INTERFACES(INTERFACES) \
- enum class QmlIsInterface {yes = false}; \
- template<typename, typename> friend struct QML_PRIVATE_NAMESPACE::QmlInterface;
-
-#define QML_UNAVAILABLE \
- QML_FOREIGN(QQmlTypeNotAvailable)
-
enum { /* TYPEINFO flags */
QML_HAS_ATTACHED_PROPERTIES = 0x01
};
diff --git a/src/qml/qml/qqmlanybinding_p.h b/src/qml/qml/qqmlanybinding_p.h
index 38c1023c79..ad1fa20ace 100644
--- a/src/qml/qml/qqmlanybinding_p.h
+++ b/src/qml/qml/qqmlanybinding_p.h
@@ -113,9 +113,9 @@ public:
} else {
auto qmlBinding = QQmlPropertyPrivate::binding(prop);
if (qmlBinding) {
+ binding = qmlBinding; // this needs to run before removeFromObject, else the refcount might reach zero
qmlBinding->setEnabled(false, QQmlPropertyData::DontRemoveBinding | QQmlPropertyData::BypassInterceptor);
qmlBinding->removeFromObject();
- binding = qmlBinding;
}
}
return binding;
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 69ac63b0ad..1136e36af6 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -211,9 +211,9 @@ QV4::ReturnedValue QQmlBinding::evaluate(bool *isUndefined)
thisObject = &b->d()->boundThis;
}
QV4::Scope scope(v4);
- QV4::JSCallData jsCall(scope, argc, argv, thisObject);
+ QV4::JSCallData jsCall(thisObject, argv, argc);
- return QQmlJavaScriptExpression::evaluate(jsCall.callData(), isUndefined);
+ return QQmlJavaScriptExpression::evaluate(jsCall.callData(scope), isUndefined);
}
@@ -247,13 +247,27 @@ protected:
auto ep = QQmlEnginePrivate::get(scope.engine);
ep->referenceScarceResources();
- bool isUndefined = false;
-
- QV4::ScopedValue result(scope, evaluate(&isUndefined));
-
bool error = false;
- if (!watcher.wasDeleted() && isAddedToObject() && !hasError())
- error = !write(result, isUndefined, flags);
+ auto canWrite = [&]() { return !watcher.wasDeleted() && isAddedToObject() && !hasError(); };
+ const QV4::Function *v4Function = function();
+ if (v4Function && v4Function->aotFunction && !hasBoundFunction()) {
+ const auto returnType = v4Function->aotFunction->returnType;
+ const auto size = returnType.sizeOf();
+ if (Q_LIKELY(size > 0)) {
+ Q_ALLOCA_VAR(void, result, size);
+ const bool isUndefined = !evaluate(result, returnType);
+ if (canWrite())
+ error = !write(result, returnType, isUndefined, flags);
+ returnType.destruct(result);
+ } else if (canWrite()) {
+ error = !write(QV4::Encode::undefined(), true, flags);
+ }
+ } else {
+ bool isUndefined = false;
+ QV4::ScopedValue result(scope, evaluate(&isUndefined));
+ if (canWrite())
+ error = !write(result, isUndefined, flags);
+ }
if (!watcher.wasDeleted()) {
@@ -273,6 +287,7 @@ protected:
}
virtual bool write(const QV4::Value &result, bool isUndefined, QQmlPropertyData::WriteFlags flags) = 0;
+ virtual bool write(void *result, QMetaType type, bool isUndefined, QQmlPropertyData::WriteFlags flags) = 0;
};
template<int StaticPropType>
@@ -280,6 +295,30 @@ class GenericBinding: public QQmlNonbindingBinding
{
protected:
// Returns true if successful, false if an error description was set on expression
+ Q_ALWAYS_INLINE bool write(void *result, QMetaType type, bool isUndefined,
+ QQmlPropertyData::WriteFlags flags) override final
+ {
+ QQmlPropertyData *pd;
+ QQmlPropertyData vpd;
+ getPropertyData(&pd, &vpd);
+ Q_ASSERT(pd);
+
+ if (Q_UNLIKELY(isUndefined || vpd.isValid())) {
+ return slowWrite(*pd, vpd, engine()->handle()->metaTypeToJS(type, result),
+ isUndefined, flags);
+ }
+
+ if ((StaticPropType == QMetaType::UnknownType && pd->propType() == type)
+ || StaticPropType == type.id()) {
+ Q_ASSERT(targetObject());
+ return pd->writeProperty(targetObject(), result, flags);
+ }
+
+ // If the type didn't match, we need to do JavaScript conversion. This should be rare.
+ return write(engine()->handle()->metaTypeToJS(type, result), isUndefined, flags);
+ }
+
+ // Returns true if successful, false if an error description was set on expression
Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
QQmlPropertyData::WriteFlags flags) override final
{
@@ -305,7 +344,7 @@ protected:
if (result.isInteger())
return doStore<int>(result.integerValue(), pd, flags);
else if (result.isNumber()) {
- return doStore<int>(QV4::StaticValue::toInteger(result.doubleValue()), pd, flags);
+ return doStore<int>(result.toInt32(), pd, flags);
}
break;
case QMetaType::Double:
@@ -413,7 +452,8 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
QQmlEngine *qmlEngine = engine();
QV4::ExecutionEngine *v4engine = qmlEngine->handle();
- const int type = valueTypeData.isValid() ? valueTypeData.propType().id() : core.propType().id();
+ const QMetaType metaType = valueTypeData.isValid() ? valueTypeData.propType() : core.propType();
+ const int type = metaType.id();
QQmlJavaScriptExpression::DeleteWatcher watcher(this);
@@ -422,13 +462,13 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
if (isUndefined) {
} else if (core.isQList()) {
- value = v4engine->toVariant(result, qMetaTypeId<QList<QObject *> >());
+ value = v4engine->toVariant(result, QMetaType::fromType<QList<QObject *> >());
} else if (result.isNull() && core.isQObject()) {
value = QVariant::fromValue((QObject *)nullptr);
} else if (core.propType().id() == qMetaTypeId<QList<QUrl> >()) {
- value = QQmlPropertyPrivate::urlSequence(v4engine->toVariant(result, qMetaTypeId<QList<QUrl>>()));
- } else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
- value = v4engine->toVariant(result, type);
+ value = QQmlPropertyPrivate::urlSequence(v4engine->toVariant(result, QMetaType::fromType<QList<QUrl>>()));
+ } else if (!isVarProperty && metaType != QMetaType::fromType<QJSValue>()) {
+ value = v4engine->toVariant(result, metaType);
}
if (hasError()) {
@@ -448,9 +488,9 @@ Q_NEVER_INLINE bool QQmlBinding::slowWrite(const QQmlPropertyData &core,
} else if (isUndefined && core.isResettable()) {
void *args[] = { nullptr };
QMetaObject::metacall(m_target.data(), QMetaObject::ResetProperty, core.coreIndex(), args);
- } else if (isUndefined && type == qMetaTypeId<QVariant>()) {
+ } else if (isUndefined && type == QMetaType::QVariant) {
QQmlPropertyPrivate::writeValueProperty(m_target.data(), core, valueTypeData, QVariant(), context(), flags);
- } else if (type == qMetaTypeId<QJSValue>()) {
+ } else if (metaType == QMetaType::fromType<QJSValue>()) {
const QV4::FunctionObject *f = result.as<QV4::FunctionObject>();
if (f && f->isBinding()) {
delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
@@ -526,7 +566,7 @@ QVariant QQmlBinding::evaluate()
ep->dereferenceScarceResources();
- return scope.engine->toVariant(result, qMetaTypeId<QList<QObject*> >());
+ return scope.engine->toVariant(result, QMetaType::fromType<QList<QObject*> >());
}
void QQmlBinding::expressionChanged()
@@ -683,6 +723,48 @@ public:
{}
protected:
+ Q_ALWAYS_INLINE bool write(void *result, QMetaType type, bool isUndefined,
+ QQmlPropertyData::WriteFlags flags) override final
+ {
+ QQmlPropertyData *pd;
+ QQmlPropertyData vtpd;
+ getPropertyData(&pd, &vtpd);
+ if (Q_UNLIKELY(isUndefined || vtpd.isValid()))
+ return slowWrite(*pd, vtpd, result, type, isUndefined, flags);
+
+ // Check if the result is a QObject:
+ QObject *resultObject = nullptr;
+ QQmlMetaObject resultMo;
+ const auto typeFlags = type.flags();
+ if (!result || ((typeFlags & QMetaType::IsPointer) && !*static_cast<void **>(result))) {
+ // Special case: we can always write a nullptr. Don't bother checking anything else.
+ return pd->writeProperty(targetObject(), &resultObject, flags);
+ } else if (typeFlags & QMetaType::PointerToQObject) {
+ resultObject = *static_cast<QObject **>(result);
+ if (!resultObject)
+ return pd->writeProperty(targetObject(), &resultObject, flags);
+ if (QQmlData *ddata = QQmlData::get(resultObject, false))
+ resultMo = ddata->propertyCache;
+ if (resultMo.isNull())
+ resultMo = resultObject->metaObject();
+ } else if (type == QMetaType::fromType<QVariant>()) {
+ QVariant value = *static_cast<QVariant *>(result);
+ QQmlEngine *qmlEngine = engine();
+ Q_ASSERT(qmlEngine);
+ resultMo = QQmlPropertyPrivate::rawMetaObjectForType(
+ QQmlEnginePrivate::get(qmlEngine), value.userType());
+ if (resultMo.isNull())
+ return slowWrite(*pd, vtpd, result, type, isUndefined, flags);
+ resultObject = *static_cast<QObject *const *>(value.constData());
+ } else {
+ return slowWrite(*pd, vtpd, result, type, isUndefined, flags);
+ }
+
+ return compareAndSet(resultMo, resultObject, pd, flags, [&]() {
+ return slowWrite(*pd, vtpd, result, type, isUndefined, flags);
+ });
+ }
+
Q_ALWAYS_INLINE bool write(const QV4::Value &result, bool isUndefined,
QQmlPropertyData::WriteFlags flags) override final
{
@@ -710,8 +792,9 @@ protected:
} else if (auto variant = result.as<QV4::VariantObject>()) {
QVariant value = variant->d()->data();
QQmlEngine *qmlEngine = engine();
+ Q_ASSERT(qmlEngine);
resultMo = QQmlPropertyPrivate::rawMetaObjectForType(
- qmlEngine ? QQmlEnginePrivate::get(qmlEngine) : nullptr, value.userType());
+ QQmlEnginePrivate::get(qmlEngine), value.userType());
if (resultMo.isNull())
return slowWrite(*pd, vtpd, result, isUndefined, flags);
resultObject = *static_cast<QObject *const *>(value.constData());
@@ -719,7 +802,25 @@ protected:
return slowWrite(*pd, vtpd, result, isUndefined, flags);
}
- // Compare & set:
+ return compareAndSet(resultMo, resultObject, pd, flags, [&]() {
+ return slowWrite(*pd, vtpd, result, isUndefined, flags);
+ });
+ }
+
+private:
+ using QQmlBinding::slowWrite;
+ bool slowWrite(const QQmlPropertyData &core, const QQmlPropertyData &valueTypeData,
+ void *result, QMetaType type, bool isUndefined,
+ QQmlPropertyData::WriteFlags flags)
+ {
+ return slowWrite(core, valueTypeData, engine()->handle()->metaTypeToJS(type, result),
+ isUndefined, flags);
+ }
+
+ template<typename SlowWrite>
+ bool compareAndSet(const QQmlMetaObject &resultMo, QObject *resultObject, QQmlPropertyData *pd,
+ QQmlPropertyData::WriteFlags flags, const SlowWrite &slowWrite) const
+ {
if (QQmlMetaObject::canConvert(resultMo, targetMetaObject)) {
return pd->writeProperty(targetObject(), &resultObject, flags);
} else if (!resultObject && QQmlMetaObject::canConvert(targetMetaObject, resultMo)) {
@@ -728,7 +829,7 @@ protected:
// the property type.
return pd->writeProperty(targetObject(), &resultObject, flags);
} else {
- return slowWrite(*pd, vtpd, result, isUndefined, flags);
+ return slowWrite();
}
}
};
diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h
index bf73c24c9e..9542f3acca 100644
--- a/src/qml/qml/qqmlbinding_p.h
+++ b/src/qml/qml/qqmlbinding_p.h
@@ -116,6 +116,7 @@ public:
void setBoundFunction(QV4::BoundFunction *boundFunction) {
m_boundFunction.set(boundFunction->engine(), *boundFunction);
}
+ bool hasBoundFunction() const { return m_boundFunction.valueRef(); }
/**
* This method returns a snapshot of the currently tracked dependencies of
@@ -138,6 +139,10 @@ protected:
const QV4::Value &result, bool isUndefined, QQmlPropertyData::WriteFlags flags);
QV4::ReturnedValue evaluate(bool *isUndefined);
+ bool evaluate(void *result, QMetaType type)
+ {
+ return QQmlJavaScriptExpression::evaluate(&result, &type, 0);
+ }
private:
inline bool updatingFlag() const;
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 9e1e056381..e624dc6e34 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -187,16 +187,32 @@ void QQmlBoundSignalExpression::evaluate(void **a)
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- QQmlMetaObject::ArgTypeStorage storage;
- //TODO: lookup via signal index rather than method index as an optimization
- int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex();
- bool ok = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, &storage, nullptr);
- const int argCount = ok ? storage.size() : 0;
-
- QV4::JSCallData jsCall(scope, argCount);
- populateJSCallArguments(v4, jsCall, argCount, a, storage.constData());
+ if (a) {
+ //TODO: lookup via signal index rather than method index as an optimization
+ const QMetaObject *targetMeta = m_target->metaObject();
+ const QMetaMethod metaMethod = targetMeta->method(
+ QMetaObjectPrivate::signal(targetMeta, m_index).methodIndex());
+
+ int argCount = metaMethod.parameterCount();
+ QQmlMetaObject::ArgTypeStorage storage;
+ storage.reserve(argCount + 1);
+ storage.append(QMetaType()); // We're not interested in the return value
+ for (int i = 0; i < argCount; ++i) {
+ const QMetaType type = metaMethod.parameterMetaType(i);
+ if (!type.isValid())
+ argCount = 0;
+ else if (type.flags().testFlag(QMetaType::IsEnumeration))
+ storage.append(QMetaType::fromType<int>());
+ else
+ storage.append(type);
+ }
- QQmlJavaScriptExpression::evaluate(jsCall.callData(), nullptr);
+ QQmlJavaScriptExpression::evaluate(a, storage.constData(), argCount);
+ } else {
+ void *ignoredResult = nullptr;
+ QMetaType invalidType;
+ QQmlJavaScriptExpression::evaluate(&ignoredResult, &invalidType, 0);
+ }
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
}
@@ -214,12 +230,12 @@ void QQmlBoundSignalExpression::evaluate(const QList<QVariant> &args)
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- QV4::JSCallData jsCall(scope, args.count());
+ QV4::JSCallArguments jsCall(scope, args.count());
for (int ii = 0; ii < args.count(); ++ii) {
- jsCall->args[ii] = scope.engine->fromVariant(args[ii]);
+ jsCall.args[ii] = scope.engine->fromVariant(args[ii]);
}
- QQmlJavaScriptExpression::evaluate(jsCall.callData(), nullptr);
+ QQmlJavaScriptExpression::evaluate(jsCall.callData(scope), nullptr);
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
}
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 7d9261604e..bfbbcd2d73 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -1753,9 +1753,9 @@ void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
QV4::ScopedFunctionObject f(scope, d()->statusChanged);
if (f) {
- QV4::JSCallData jsCallData(scope, 1);
- *jsCallData->thisObject = this;
- jsCallData->args[0] = QV4::Value::fromUInt32(s);
+ QV4::JSCallArguments jsCallData(scope, 1);
+ *jsCallData.thisObject = this;
+ jsCallData.args[0] = QV4::Value::fromUInt32(s);
f->call(jsCallData);
if (scope.hasException()) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index 797ab34937..b6b90f13dc 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -287,10 +287,9 @@ void QQmlContext::setContextProperty(const QString &name, const QVariant &value)
return;
}
- QV4::IdentifierHash *properties = data->detachedPropertyNames();
- int idx = properties->value(name);
+ int idx = data->propertyIndex(name);
if (idx == -1) {
- properties->add(name, data->numIdValues() + d->numPropertyValues());
+ data->addPropertyNameAndIndex(name, data->numIdValues() + d->numPropertyValues());
d->appendPropertyValue(value);
data->refreshExpressions();
} else {
@@ -354,48 +353,69 @@ void QQmlContext::setContextProperties(const QList<PropertyPair> &properties)
\sa QQmlContext::setContextProperties()
*/
+static bool readObjectProperty(
+ const QQmlRefPointer<QQmlContextData> &data, QObject *object, const QString &name,
+ QVariant *target)
+{
+ QQmlPropertyData local;
+ if (QQmlPropertyData *property =
+ QQmlPropertyCache::property(data->engine(), object, name, data, &local)) {
+ *target = object->metaObject()->property(property->coreIndex()).read(object);
+ return true;
+ }
+ return false;
+}
+
/*!
- Returns the value of the \a name property for this context
- as a QVariant.
+ Returns the value of the \a name property for this context as a QVariant.
+ If you know that the property you're looking for is a QObject assigned using
+ a QML id in the current context, \l objectForName() is more convenient and
+ faster. In contrast to \l objectForName() and \l nameForObject(), this method
+ does traverse the context hierarchy and searches in parent contexts if the
+ \a name is not found in the current one. It also considers any
+ \l contextObject() you may have set.
+
+ \sa objectForName(), nameForObject(), contextObject()
*/
QVariant QQmlContext::contextProperty(const QString &name) const
{
Q_D(const QQmlContext);
- QVariant value;
- int idx = -1;
- QQmlRefPointer<QQmlContextData> data = d->m_data;
-
- const QV4::IdentifierHash properties = data->propertyNames();
- if (properties.count())
- idx = properties.value(name);
+ const QQmlRefPointer<QQmlContextData> data = d->m_data;
+ const int idx = data->propertyIndex(name);
if (idx == -1) {
if (QObject *obj = data->contextObject()) {
- QQmlPropertyData local;
- QQmlPropertyData *property =
- QQmlPropertyCache::property(data->engine(), obj, name, data, &local);
-
- if (property) value = obj->metaObject()->property(property->coreIndex()).read(obj);
+ QVariant value;
+ if (readObjectProperty(data, obj, name, &value))
+ return value;
}
- if (!value.isValid() && parentContext())
- value = parentContext()->contextProperty(name);
+
+ if (parentContext())
+ return parentContext()->contextProperty(name);
} else {
if (idx >= d->numPropertyValues())
- value = QVariant::fromValue(data->idValue(idx - d->numPropertyValues()));
+ return QVariant::fromValue(data->idValue(idx - d->numPropertyValues()));
else
- value = d->propertyValue(idx);
+ return d->propertyValue(idx);
}
- return value;
+ return QVariant();
}
/*!
-Returns the name of \a object in this context, or an empty string if \a object
-is not named in the context. Objects are named by setContextProperty(), or by ids in
-the case of QML created contexts.
+ Returns the name of \a object in this context, or an empty string if \a object
+ is not named in the context. Objects are named by \l setContextProperty(), or
+ as properties of a context object, or by ids in the case of QML created
+ contexts.
+
+ If the object has multiple names, the first is returned.
-If the object has multiple names, the first is returned.
+ In contrast to \l contextProperty(), this method does not traverse the
+ context hierarchy. If the name is not found in the current context, an empty
+ String is returned.
+
+ \sa contextProperty(), objectForName()
*/
QString QQmlContext::nameForObject(const QObject *object) const
{
@@ -405,6 +425,40 @@ QString QQmlContext::nameForObject(const QObject *object) const
}
/*!
+ \since 6.2
+
+ Returns the object for a given \a name in this context. Returns nullptr if
+ \a name is not available in the context or if the value associated with
+ \a name is not a QObject. Objects are named by \l setContextProperty(),
+ or as properties of a context object, or by ids in the case of QML created
+ contexts. In contrast to \l contextProperty(), this method does not traverse
+ the context hierarchy. If the name is not found in the current context,
+ nullptr is returned.
+
+ \sa contextProperty(), nameForObject()
+*/
+QObject *QQmlContext::objectForName(const QString &name) const
+{
+ Q_D(const QQmlContext);
+
+ QQmlRefPointer<QQmlContextData> data = d->m_data;
+ if (const int propertyIndex = data->propertyIndex(name); propertyIndex >= 0) {
+ const int numPropertyValues = d->numPropertyValues();
+ if (propertyIndex < numPropertyValues)
+ return qvariant_cast<QObject *>(d->propertyValue(propertyIndex));
+ return data->idValue(propertyIndex - numPropertyValues);
+ }
+
+ if (QObject *obj = data->contextObject()) {
+ QVariant result;
+ if (readObjectProperty(data, obj, name, &result))
+ return qvariant_cast<QObject *>(result);
+ }
+
+ return nullptr;
+}
+
+/*!
Resolves the URL \a src relative to the URL of the
containing component.
@@ -441,6 +495,9 @@ QUrl QQmlContext::baseUrl() const
return d->m_data->baseUrl();
}
+/*!
+ * \internal
+ */
QJSValue QQmlContext::importedScript(const QString &name) const
{
Q_D(const QQmlContext);
@@ -481,7 +538,7 @@ void QQmlContextPrivate::dropDestroyedQObject(const QString &name, QObject *dest
if (!m_data->isValid())
return;
- const int idx = m_data->propertyNames().value(name);
+ const int idx = m_data->propertyIndex(name);
Q_ASSERT(idx >= 0);
if (qvariant_cast<QObject *>(propertyValue(idx)) != destroyed)
return;
diff --git a/src/qml/qml/qqmlcontext.h b/src/qml/qml/qqmlcontext.h
index 5eda300b36..82d15b8102 100644
--- a/src/qml/qml/qqmlcontext.h
+++ b/src/qml/qml/qqmlcontext.h
@@ -84,6 +84,7 @@ public:
void setContextProperties(const QList<PropertyPair> &properties);
QString nameForObject(const QObject *) const;
+ QObject *objectForName(const QString &) const;
QUrl resolvedUrl(const QUrl &) const;
diff --git a/src/qml/qml/qqmlcontextdata.cpp b/src/qml/qml/qqmlcontextdata.cpp
index e1aa3dd887..f7decc2992 100644
--- a/src/qml/qml/qqmlcontextdata.cpp
+++ b/src/qml/qml/qqmlcontextdata.cpp
@@ -281,37 +281,35 @@ void QQmlContextData::setIdValue(int idx, QObject *obj)
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);
+ return propertyName(ii);
}
+ const QVariant objVariant = QVariant::fromValue(obj);
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 (p->propertyValue(ii) == objVariant)
+ return propertyName(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;
-}
+ if (m_contextObject) {
+ // This is expensive, but nameForObject should really mirror contextProperty()
+ for (const QMetaObject *metaObject = m_contextObject->metaObject();
+ metaObject; metaObject = metaObject->superClass()) {
+ for (int i = metaObject->propertyOffset(), end = metaObject->propertyCount();
+ i != end; ++i) {
+ const QMetaProperty prop = metaObject->property(i);
+ if (prop.metaType().flags() & QMetaType::PointerToQObject
+ && prop.read(m_contextObject) == objVariant) {
+ return QString::fromUtf8(prop.name());
+ }
+ }
+ }
+ }
-QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
-{
- return QQmlContextPrivate::get(asQQmlContext());
+ return QString();
}
void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &unit, int subComponentIndex)
@@ -334,22 +332,13 @@ 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()
+void QQmlContextData::initPropertyNames() const
{
- propertyNames();
- m_propertyNameCache.detach();
- return &m_propertyNameCache;
+ if (m_typeCompilationUnit)
+ m_propertyNameCache = m_typeCompilationUnit->namedObjectsPerComponent(m_componentObjectIndex);
+ else
+ m_propertyNameCache = QV4::IdentifierHash(m_engine->handle());
+ Q_ASSERT(!m_propertyNameCache.isEmpty());
}
QUrl QQmlContextData::url() const
diff --git a/src/qml/qml/qqmlcontextdata_p.h b/src/qml/qml/qqmlcontextdata_p.h
index 0fc3c23a0e..146a1c97dd 100644
--- a/src/qml/qml/qqmlcontextdata_p.h
+++ b/src/qml/qml/qqmlcontextdata_p.h
@@ -142,8 +142,17 @@ public:
// My containing QQmlContext. If isInternal is true this owns publicContext.
// If internal is false publicContext owns this.
- QQmlContext *asQQmlContext();
- QQmlContextPrivate *asQQmlContextPrivate();
+ QQmlContext *asQQmlContext()
+ {
+ if (!m_publicContext)
+ m_publicContext = new QQmlContext(*new QQmlContextPrivate(this));
+ return m_publicContext;
+ }
+
+ QQmlContextPrivate *asQQmlContextPrivate()
+ {
+ return QQmlContextPrivate::get(asQQmlContext());
+ }
QObject *contextObject() const { return m_contextObject; }
void setContextObject(QObject *contextObject) { m_contextObject = contextObject; }
@@ -164,8 +173,29 @@ public:
}
}
- QV4::IdentifierHash propertyNames() const;
- QV4::IdentifierHash *detachedPropertyNames();
+ int propertyIndex(const QString &name) const
+ {
+ ensurePropertyNames();
+ return m_propertyNameCache.value(name);
+ }
+
+ int propertyIndex(QV4::String *name) const
+ {
+ ensurePropertyNames();
+ return m_propertyNameCache.value(name);
+ }
+
+ QString propertyName(int index) const
+ {
+ ensurePropertyNames();
+ return m_propertyNameCache.findId(index);
+ }
+
+ void addPropertyNameAndIndex(const QString &name, int index)
+ {
+ Q_ASSERT(!m_propertyNameCache.isEmpty());
+ m_propertyNameCache.add(name, index);
+ }
void setExpressions(QQmlJavaScriptExpression *expressions) { m_expressions = expressions; }
QQmlJavaScriptExpression *takeExpressions()
@@ -334,6 +364,14 @@ private:
void refreshExpressionsRecursive(bool isGlobal);
void refreshExpressionsRecursive(QQmlJavaScriptExpression *);
+ void initPropertyNames() const;
+
+ void ensurePropertyNames() const
+ {
+ if (m_propertyNameCache.isEmpty())
+ initPropertyNames();
+ Q_ASSERT(!m_propertyNameCache.isEmpty());
+ }
// My parent context and engine
QQmlContextData *m_parent = nullptr;
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index ed77c1851b..ff55ab49d4 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -98,7 +98,6 @@ public:
if (!initialized) {
initialized = true;
QAbstractDeclarativeData::destroyed = destroyed;
- QAbstractDeclarativeData::parentChanged = nullptr;
QAbstractDeclarativeData::signalEmitted = signalEmitted;
QAbstractDeclarativeData::receivers = receivers;
QAbstractDeclarativeData::isSignalConnected = isSignalConnected;
diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp
index 141c55c0ec..598de8d3a0 100644
--- a/src/qml/qml/qqmldelayedcallqueue.cpp
+++ b/src/qml/qml/qqmldelayedcallqueue.cpp
@@ -67,11 +67,11 @@ void QQmlDelayedCallQueue::DelayedFunctionCall::execute(QV4::ExecutionEngine *en
const QV4::FunctionObject *callback = m_function.as<QV4::FunctionObject>();
Q_ASSERT(callback);
const int argCount = array ? array->getLength() : 0;
- QV4::JSCallData jsCallData(scope, argCount);
- *jsCallData->thisObject = QV4::Encode::undefined();
+ QV4::JSCallArguments jsCallData(scope, argCount);
+ *jsCallData.thisObject = QV4::Encode::undefined();
for (int i = 0; i < argCount; i++) {
- jsCallData->args[i] = array->get(i);
+ jsCallData.args[i] = array->get(i);
}
callback->call(jsCallData);
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 5864c3245c..cb9096ae66 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -281,7 +281,7 @@ QVariant QQmlExpressionPrivate::value(bool *isUndefined)
QV4::Scope scope(engine->handle());
QV4::ScopedValue result(scope, v4value(isUndefined));
if (!hasError())
- rv = scope.engine->toVariant(result, -1);
+ rv = scope.engine->toVariant(result, QMetaType {});
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 0016d4bcc4..1d2d0d15cd 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -1436,11 +1436,16 @@ QQmlImports::LocalQmldirResult QQmlImportsPrivate::locateLocalQmldir(
if (!absoluteFilePath.isEmpty()) {
QString url;
const QStringView absolutePath = QStringView{absoluteFilePath}.left(absoluteFilePath.lastIndexOf(Slash) + 1);
- if (absolutePath.at(0) == Colon)
+ if (absolutePath.at(0) == Colon) {
url = QLatin1String("qrc") + absolutePath;
- else
+ } else {
url = QUrl::fromLocalFile(absolutePath.toString()).toString();
-
+ // This handles the UNC path case as when the path is retrieved from the QUrl it
+ // will convert the host name from upper case to lower case. So the absoluteFilePath
+ // is changed at this point to make sure it will match later on in that case.
+ if (absoluteFilePath.startsWith(QLatin1String("//")))
+ absoluteFilePath = QUrl::fromLocalFile(absoluteFilePath).toString(QUrl::RemoveScheme);
+ }
QQmlImportDatabase::QmldirCache *cache = new QQmlImportDatabase::QmldirCache;
cache->version = version;
cache->qmldirFilePath = absoluteFilePath;
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 1a4d452bfd..95d7d89c99 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -172,11 +172,6 @@ void QQmlJavaScriptExpression::setContext(const QQmlRefPointer<QQmlContextData>
context->addExpression(this);
}
-QV4::Function *QQmlJavaScriptExpression::function() const
-{
- return m_v4Function;
-}
-
void QQmlJavaScriptExpression::refresh()
{
}
@@ -185,9 +180,78 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(bool *isUndefined)
{
QV4::ExecutionEngine *v4 = m_context->engine()->handle();
QV4::Scope scope(v4);
- QV4::JSCallData jsCall(scope);
+ QV4::JSCallArguments jsCall(scope);
+
+ return evaluate(jsCall.callData(scope), isUndefined);
+}
+
+class QQmlJavaScriptExpressionCapture
+{
+ Q_DISABLE_COPY_MOVE(QQmlJavaScriptExpressionCapture)
+public:
+ QQmlJavaScriptExpressionCapture(QQmlJavaScriptExpression *expression, QQmlEngine *engine)
+ : watcher(expression)
+ , capture(engine, expression, &watcher)
+ , ep(QQmlEnginePrivate::get(engine))
+ {
+ Q_ASSERT(expression->notifyOnValueChanged() || expression->activeGuards.isEmpty());
+
+ lastPropertyCapture = ep->propertyCapture;
+ ep->propertyCapture = expression->notifyOnValueChanged() ? &capture : nullptr;
+
+ if (expression->notifyOnValueChanged())
+ capture.guards.copyAndClearPrepend(expression->activeGuards);
+ }
+
+ ~QQmlJavaScriptExpressionCapture()
+ {
+ if (capture.errorString) {
+ for (int ii = 0; ii < capture.errorString->count(); ++ii)
+ qWarning("%s", qPrintable(capture.errorString->at(ii)));
+ delete capture.errorString;
+ capture.errorString = nullptr;
+ }
+
+ while (QQmlJavaScriptExpressionGuard *g = capture.guards.takeFirst())
+ g->Delete();
+
+ if (!watcher.wasDeleted())
+ capture.expression->setTranslationsCaptured(capture.translationCaptured);
+
+ ep->propertyCapture = lastPropertyCapture;
+ }
+
+ bool catchException(const QV4::Scope &scope) const
+ {
+ if (scope.hasException()) {
+ if (watcher.wasDeleted())
+ scope.engine->catchException(); // ignore exception
+ else
+ capture.expression->delayedError()->catchJavaScriptException(scope.engine);
+ return true;
+ }
- return evaluate(jsCall.callData(), isUndefined);
+ if (!watcher.wasDeleted() && capture.expression->hasDelayedError())
+ capture.expression->delayedError()->clearError();
+ return false;
+ }
+
+private:
+ QQmlJavaScriptExpression::DeleteWatcher watcher;
+ QQmlPropertyCapture capture;
+ QQmlEnginePrivate *ep;
+ QQmlPropertyCapture *lastPropertyCapture;
+};
+
+static inline QV4::ReturnedValue thisObject(QObject *scopeObject, QV4::ExecutionEngine *v4)
+{
+ if (scopeObject) {
+ // The result of wrap() can only be null, undefined, or an object.
+ const QV4::ReturnedValue scope = QV4::QObjectWrapper::wrap(v4, scopeObject);
+ if (QV4::Value::fromReturnedValue(scope).isManaged())
+ return scope;
+ }
+ return v4->globalObject->asReturnedValue();
}
QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, bool *isUndefined)
@@ -201,69 +265,48 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QV4::CallData *callData, b
return QV4::Encode::undefined();
}
- 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 *lastPropertyCapture = ep->propertyCapture;
- ep->propertyCapture = notifyOnValueChanged() ? &capture : nullptr;
+ QQmlEngine *qmlEngine = m_context->engine();
+ QQmlJavaScriptExpressionCapture capture(this, qmlEngine);
-
- if (notifyOnValueChanged())
- capture.guards.copyAndClearPrepend(activeGuards);
-
- QV4::ExecutionEngine *v4 = m_context->engine()->handle();
- callData->thisObject = v4->globalObject;
- if (scopeObject()) {
- QV4::ReturnedValue scope = QV4::QObjectWrapper::wrap(v4, scopeObject());
- if (QV4::Value::fromReturnedValue(scope).isObject())
- callData->thisObject = scope;
- }
+ QV4::Scope scope(qmlEngine->handle());
+ callData->thisObject = thisObject(scopeObject(), scope.engine);
Q_ASSERT(m_qmlScope.valueRef());
- QV4::ReturnedValue res = v4Function->call(
+ QV4::ScopedValue result(scope, v4Function->call(
&(callData->thisObject.asValue<QV4::Value>()),
callData->argValues<QV4::Value>(), callData->argc(),
- static_cast<QV4::ExecutionContext *>(m_qmlScope.valueRef()));
- QV4::Scope scope(v4);
- QV4::ScopedValue result(scope, res);
+ static_cast<QV4::ExecutionContext *>(m_qmlScope.valueRef())));
- if (scope.hasException()) {
- if (watcher.wasDeleted())
- scope.engine->catchException(); // ignore exception
- else
- delayedError()->catchJavaScriptException(scope.engine);
+ if (capture.catchException(scope)) {
if (isUndefined)
*isUndefined = true;
- } else {
- if (isUndefined)
- *isUndefined = result->isUndefined();
-
- if (!watcher.wasDeleted() && hasDelayedError())
- delayedError()->clearError();
+ } else if (isUndefined) {
+ *isUndefined = result->isUndefined();
}
- if (capture.errorString) {
- for (int ii = 0; ii < capture.errorString->count(); ++ii)
- qWarning("%s", qPrintable(capture.errorString->at(ii)));
- delete capture.errorString;
- capture.errorString = nullptr;
- }
+ return result->asReturnedValue();
+}
- while (QQmlJavaScriptExpressionGuard *g = capture.guards.takeFirst())
- g->Delete();
+bool QQmlJavaScriptExpression::evaluate(void **a, const QMetaType *types, int argc)
+{
+ Q_ASSERT(m_context && m_context->engine());
+
+ // All code that follows must check with watcher before it accesses data members
+ // incase we have been deleted.
+ QQmlEngine *qmlEngine = m_context->engine();
+ QQmlJavaScriptExpressionCapture capture(this, qmlEngine);
- if (!watcher.wasDeleted())
- setTranslationsCaptured(capture.translationCaptured);
+ QV4::Scope scope(qmlEngine->handle());
+ QV4::ScopedValue self(scope, thisObject(scopeObject(), scope.engine));
- ep->propertyCapture = lastPropertyCapture;
+ Q_ASSERT(m_qmlScope.valueRef());
+ Q_ASSERT(function());
+ function()->call(self, a, types, argc,
+ static_cast<QV4::ExecutionContext *>(m_qmlScope.valueRef()));
- return result->asReturnedValue();
+ return !capture.catchException(scope);
}
void QQmlPropertyCapture::captureProperty(QQmlNotifier *n)
@@ -315,24 +358,54 @@ void QQmlPropertyCapture::captureProperty(QObject *o, int c, int n, bool doNotif
metaObjectForBindable = m;
}
if (metaObjectForBindable) {
- // if the property is a QPropery, and we're binding to a QProperty
- // the automatic capturing process already takes care of everything
- if (typeid(QQmlPropertyBindingJS) == typeid(*expression))
- return;
- for (auto trigger = expression->qpropertyChangeTriggers; trigger;
- trigger = trigger->next) {
- if (trigger->target == o && trigger->propertyIndex == c)
- return; // already installed
- }
- auto trigger = expression->allocatePropertyChangeTrigger(o, c);
- QUntypedBindable bindable;
- void *argv[] = { &bindable };
- metaObjectForBindable->metacall(o, QMetaObject::BindableProperty, c, argv);
- bindable.observe(trigger);
+ captureBindableProperty(o, metaObjectForBindable, c);
return;
}
}
+ captureNonBindableProperty(o, n, c, doNotify);
+}
+
+void QQmlPropertyCapture::captureProperty(
+ QObject *o, const QQmlPropertyCache *propertyCache, const QQmlPropertyData *propertyData,
+ bool doNotify)
+{
+ if (watcher->wasDeleted())
+ return;
+
+ Q_ASSERT(expression);
+
+ if (propertyData->isBindable()) {
+ if (const QMetaObject *metaObjectForBindable = propertyCache->metaObject()) {
+ captureBindableProperty(o, metaObjectForBindable, propertyData->coreIndex());
+ return;
+ }
+ }
+
+ captureNonBindableProperty(o, propertyData->notifyIndex(), propertyData->coreIndex(), doNotify);
+}
+
+void QQmlPropertyCapture::captureBindableProperty(
+ QObject *o, const QMetaObject *metaObjectForBindable, int c)
+{
+ // if the property is a QPropery, and we're binding to a QProperty
+ // the automatic capturing process already takes care of everything
+ if (typeid(QQmlPropertyBindingJS) == typeid(*expression))
+ return;
+ for (auto trigger = expression->qpropertyChangeTriggers; trigger;
+ trigger = trigger->next) {
+ if (trigger->target == o && trigger->propertyIndex == c)
+ return; // already installed
+ }
+ auto trigger = expression->allocatePropertyChangeTrigger(o, c);
+ QUntypedBindable bindable;
+ void *argv[] = { &bindable };
+ metaObjectForBindable->metacall(o, QMetaObject::BindableProperty, c, argv);
+ bindable.observe(trigger);
+}
+
+void QQmlPropertyCapture::captureNonBindableProperty(QObject *o, int n, int c, bool doNotify)
+{
if (n == -1) {
if (!errorString) {
errorString = new QStringList;
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 499d4d430f..7a741afb75 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -108,6 +108,7 @@ public:
QV4::ReturnedValue evaluate(bool *isUndefined);
QV4::ReturnedValue evaluate(QV4::CallData *callData, bool *isUndefined);
+ bool evaluate(void **a, const QMetaType *types, int argc);
inline bool notifyOnValueChanged() const;
@@ -135,7 +136,7 @@ public:
*listHead = this;
}
- QV4::Function *function() const;
+ QV4::Function *function() const { return m_v4Function; }
virtual void refresh();
@@ -207,6 +208,7 @@ private:
friend class QQmlPropertyCapture;
friend void QQmlJavaScriptExpressionGuard_callback(QQmlNotifierEndpoint *, void **);
friend class QQmlTranslationBinding;
+ friend class QQmlJavaScriptExpressionCapture;
// Not refcounted as the context will clear the expressions when destructed.
QQmlContextData *m_context;
@@ -235,6 +237,7 @@ public:
void captureProperty(QQmlNotifier *);
void captureProperty(QObject *, int, int, bool doNotify = true);
+ void captureProperty(QObject *, const QQmlPropertyCache *, const QQmlPropertyData *, bool doNotify = true);
void captureTranslation() { translationCaptured = true; }
QQmlEngine *engine;
@@ -243,6 +246,10 @@ public:
QForwardFieldList<QQmlJavaScriptExpressionGuard, &QQmlJavaScriptExpressionGuard::next> guards;
QStringList *errorString;
bool translationCaptured = false;
+
+private:
+ void captureBindableProperty(QObject *o, const QMetaObject *metaObjectForBindable, int c);
+ void captureNonBindableProperty(QObject *o, int n, int c, bool doNotify);
};
QQmlJavaScriptExpression::DeleteWatcher::DeleteWatcher(QQmlJavaScriptExpression *e)
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp
index b266157d28..5a2cf1e455 100644
--- a/src/qml/qml/qqmllist.cpp
+++ b/src/qml/qml/qqmllist.cpp
@@ -44,25 +44,30 @@
QT_BEGIN_NAMESPACE
+static bool isObjectCompatible(QObject *object, QQmlListReferencePrivate *d)
+{
+ if (object) {
+ const QQmlMetaObject elementType = d->elementType();
+ if (elementType.isNull() || !QQmlMetaObject::canConvert(object, elementType))
+ return false;
+ }
+ return true;
+}
+
QQmlListReferencePrivate::QQmlListReferencePrivate()
-: propertyType(-1), refCount(1)
+: refCount(1)
{
}
-QQmlListReference QQmlListReferencePrivate::init(const QQmlListProperty<QObject> &prop, int propType, QQmlEngine *engine)
+QQmlListReference QQmlListReferencePrivate::init(const QQmlListProperty<QObject> &prop, QMetaType propType, QQmlEngine *engine)
{
QQmlListReference rv;
if (!prop.object) return rv;
- QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):nullptr;
-
- int listType = QQmlMetaType::listType(propType);
- if (listType == -1) return rv;
-
rv.d = new QQmlListReferencePrivate;
rv.d->object = prop.object;
- rv.d->elementType = QQmlPropertyPrivate::rawMetaObjectForType(p, listType);
+ rv.d->setEngine(engine);
rv.d->property = prop;
rv.d->propertyType = propType;
@@ -129,7 +134,8 @@ become invalid. That is, it is safe to hold QQmlListReference instances even af
deleted.
The \a engine is required to look up the element type, which may be a dynamically created QML type.
-If it's omitted, only pre-registered types are available.
+If it's omitted, only pre-registered types are available. The element type is needed when inserting
+values into the list and when the value meta type is explicitly retrieved.
*/
QQmlListReference::QQmlListReference(const QVariant &variant, QQmlEngine *engine)
: d(nullptr)
@@ -138,16 +144,9 @@ QQmlListReference::QQmlListReference(const QVariant &variant, QQmlEngine *engine
if (!(t.flags() & QMetaType::IsQmlList))
return;
- QQmlEnginePrivate *p = engine ? QQmlEnginePrivate::get(engine) : nullptr;
- const int listType = QQmlMetaType::listType(t.id());
- if (listType == -1)
- return;
-
d = new QQmlListReferencePrivate;
- d->propertyType = t.id();
- d->elementType = p
- ? p->rawMetaObjectForType(listType)
- : QQmlMetaType::qmlType(listType).baseMetaObject();
+ d->propertyType = t;
+ d->setEngine(engine);
d->property.~QQmlListProperty();
t.construct(&d->property, variant.constData());
@@ -161,8 +160,9 @@ property, an invalid QQmlListReference is created. If \a object is destroyed af
the reference is constructed, it will automatically become invalid. That is, it is safe to hold
QQmlListReference instances even after \a object is deleted.
-Passing \a engine is required to access some QML created list properties. If in doubt, and an engine
-is available, pass it.
+The \a engine is required to look up the element type, which may be a dynamically created QML type.
+If it's omitted, only pre-registered types are available. The element type is needed when inserting
+values into the list and when the value meta type is explicitly retrieved.
*/
QQmlListReference::QQmlListReference(QObject *object, const char *property, QQmlEngine *engine)
: d(nullptr)
@@ -175,15 +175,10 @@ QQmlListReference::QQmlListReference(QObject *object, const char *property, QQml
if (!data || !data->isQList()) return;
- QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):nullptr;
-
- int listType = QQmlMetaType::listType(data->propType().id());
- if (listType == -1) return;
-
d = new QQmlListReferencePrivate;
d->object = object;
- d->elementType = p ? p->rawMetaObjectForType(listType) : QQmlMetaType::qmlType(listType).baseMetaObject();
- d->propertyType = data->propType().id();
+ d->propertyType = data->propType();
+ d->setEngine(engine);
void *args[] = { &d->property, nullptr };
QMetaObject::metacall(object, QMetaObject::ReadProperty, data->coreIndex(), args);
@@ -233,12 +228,11 @@ Returns the QMetaObject for the elements stored in the list property,
or \nullptr if the reference is invalid.
The QMetaObject can be used ahead of time to determine whether a given instance can be added
-to a list.
+to a list. If you didn't pass an engine on construction this may return nullptr.
*/
const QMetaObject *QQmlListReference::listElementType() const
{
- if (isValid()) return d->elementType.metaObject();
- else return nullptr;
+ return isValid() ? d->elementType() : nullptr;
}
/*!
@@ -347,7 +341,7 @@ bool QQmlListReference::append(QObject *object) const
{
if (!canAppend()) return false;
- if (object && !QQmlMetaObject::canConvert(object, d->elementType))
+ if (!isObjectCompatible(object, d))
return false;
d->property.append(&d->property, object);
@@ -392,6 +386,12 @@ qsizetype QQmlListReference::count() const
}
/*!
+\fn qsizetype QQmlListReference::size() const
+\since 6.2
+Returns the number of objects in the list, or 0 if the operation failed.
+*/
+
+/*!
Replaces the item at \a index in the list with \a object.
Returns true if the operation succeeded, otherwise false.
@@ -402,7 +402,7 @@ bool QQmlListReference::replace(qsizetype index, QObject *object) const
if (!canReplace())
return false;
- if (object && !QQmlMetaObject::canConvert(object, d->elementType))
+ if (!isObjectCompatible(object, d))
return false;
d->property.replace(&d->property, index, object);
diff --git a/src/qml/qml/qqmllist.h b/src/qml/qml/qqmllist.h
index abf4ec6ebf..b245f4c850 100644
--- a/src/qml/qml/qqmllist.h
+++ b/src/qml/qml/qqmllist.h
@@ -222,6 +222,7 @@ public:
QObject *at(qsizetype) const;
bool clear() const;
qsizetype count() const;
+ qsizetype size() const { return count(); }
bool replace(qsizetype, QObject *) const;
bool removeLast() const;
bool operator==(const QQmlListReference &other) const {return d == other.d;}
diff --git a/src/qml/qml/qqmllist_p.h b/src/qml/qml/qqmllist_p.h
index e182ced51d..8ce3c04abb 100644
--- a/src/qml/qml/qqmllist_p.h
+++ b/src/qml/qml/qqmllist_p.h
@@ -53,6 +53,8 @@
#include "qqmllist.h"
#include "qqmlmetaobject_p.h"
+#include "qqmlmetatype_p.h"
+#include "qqmlengine_p.h"
QT_BEGIN_NAMESPACE
@@ -61,12 +63,11 @@ class QQmlListReferencePrivate
public:
QQmlListReferencePrivate();
- static QQmlListReference init(const QQmlListProperty<QObject> &, int, QQmlEngine *);
+ static QQmlListReference init(const QQmlListProperty<QObject> &, QMetaType, QQmlEngine *);
QPointer<QObject> object;
- QQmlMetaObject elementType;
QQmlListProperty<QObject> property;
- int propertyType;
+ QMetaType propertyType;
void addref();
void release();
@@ -75,6 +76,27 @@ public:
static inline QQmlListReferencePrivate *get(QQmlListReference *ref) {
return ref->d;
}
+
+ void setEngine(QQmlEngine *engine)
+ {
+ m_elementTypeOrEngine = engine;
+ }
+
+ const QMetaObject *elementType()
+ {
+ if (m_elementTypeOrEngine.isT2()) {
+ const int listType = QQmlMetaType::listType(propertyType).id();
+ const QQmlEngine *engine = m_elementTypeOrEngine.asT2();
+ const QQmlEnginePrivate *p = engine ? QQmlEnginePrivate::get(engine) : nullptr;
+ m_elementTypeOrEngine = p ? p->rawMetaObjectForType(listType).metaObject()
+ : QQmlMetaType::qmlType(listType).baseMetaObject();
+ }
+
+ return m_elementTypeOrEngine.asT1();
+ }
+
+private:
+ QBiPointer<const QMetaObject, QQmlEngine> m_elementTypeOrEngine;
};
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index e5c1cb04a9..e3ab0082aa 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -66,7 +66,7 @@ void Heap::QmlListWrapper::destroy()
Object::destroy();
}
-ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, int propId, int propType)
+ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, int propId, QMetaType propType)
{
if (!object || propId == -1)
return Encode::null();
@@ -75,20 +75,20 @@ ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, i
Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>());
r->d()->object = object;
- r->d()->propertyType = propType;
+ r->d()->propertyType = propType.iface();
void *args[] = { &r->d()->property(), nullptr };
QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args);
return r.asReturnedValue();
}
-ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProperty<QObject> &prop, int propType)
+ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProperty<QObject> &prop, QMetaType propType)
{
Scope scope(engine);
Scoped<QmlListWrapper> r(scope, engine->memoryManager->allocate<QmlListWrapper>());
r->d()->object = prop.object;
r->d()->property() = prop;
- r->d()->propertyType = propType;
+ r->d()->propertyType = propType.iface();
return r.asReturnedValue();
}
@@ -97,7 +97,14 @@ QVariant QmlListWrapper::toVariant() const
if (!d()->object)
return QVariant();
- return QVariant::fromValue(QQmlListReferencePrivate::init(d()->property(), d()->propertyType, engine()->qmlEngine()));
+ return QVariant::fromValue(toListReference());
+}
+
+QQmlListReference QmlListWrapper::toListReference() const
+{
+ Heap::QmlListWrapper *wrapper = d();
+ return QQmlListReferencePrivate::init(
+ wrapper->property(), QMetaType(wrapper->propertyType), engine()->qmlEngine());
}
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index 26a5023e6b..27a0701a12 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -74,7 +74,8 @@ struct QmlListWrapper : Object {
return *reinterpret_cast<QQmlListProperty<QObject>*>(propertyData);
}
- int propertyType;
+ // interface instead of QMetaType to keep class a POD
+ const QtPrivate::QMetaTypeInterface *propertyType;
private:
void *propertyData[sizeof(QQmlListProperty<QObject>)/sizeof(void*)];
@@ -88,10 +89,11 @@ struct Q_QML_EXPORT QmlListWrapper : Object
V4_NEEDS_DESTROY
V4_PROTOTYPE(propertyListPrototype)
- static ReturnedValue create(ExecutionEngine *engine, QObject *object, int propId, int propType);
- static ReturnedValue create(ExecutionEngine *engine, const QQmlListProperty<QObject> &prop, int propType);
+ static ReturnedValue create(ExecutionEngine *engine, QObject *object, int propId, QMetaType propType);
+ static ReturnedValue create(ExecutionEngine *engine, const QQmlListProperty<QObject> &prop, QMetaType propType);
QVariant toVariant() const;
+ QQmlListReference toListReference() 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/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 8046a76b92..0d3b5d9883 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -495,6 +495,41 @@ ReturnedValue QQmlLocaleData::method_set_numberOptions(const QV4::FunctionObject
return Encode::undefined();
}
+ReturnedValue QQmlLocaleData::method_get_formattedDataSize(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
+{
+ QV4::Scope scope(b);
+ const QLocale *locale = getThisLocale(scope, thisObject);
+ if (!locale)
+ return Encode::undefined();
+
+ if (argc < 1 || argc > 3) {
+ THROW_ERROR(QString::fromLatin1(
+ "Locale: formattedDataSize(): Expected 1-3 arguments, but received %1").arg(argc).toLatin1());
+ }
+
+ const qint64 bytes = static_cast<qint64>(argv[0].toInteger());
+ if (argc == 1)
+ RETURN_RESULT(scope.engine->newString(locale->formattedDataSize(bytes)));
+
+ int precision = 0;
+ if (argc >= 2) {
+ if (!argv[1].isInteger())
+ THROW_ERROR("Locale: formattedDataSize(): Invalid argument ('precision' must be an int)");
+
+ precision = argv[1].toInt32();
+ if (argc == 2)
+ RETURN_RESULT(scope.engine->newString(locale->formattedDataSize(bytes, precision)));
+ }
+
+ // argc >= 3
+ if (!argv[2].isNumber())
+ THROW_ERROR("Locale: formattedDataSize(): Invalid argument ('format' must be DataSizeFormat)");
+
+ const quint32 intFormat = argv[2].toUInt32();
+ const auto format = QLocale::DataSizeFormats(intFormat);
+ RETURN_RESULT(scope.engine->newString(locale->formattedDataSize(bytes, precision, format)));
+}
+
ReturnedValue QQmlLocaleData::method_get_measurementSystem(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
{
QV4::Scope scope(b);
@@ -701,6 +736,7 @@ QV4LocaleDataDeletable::QV4LocaleDataDeletable(QV4::ExecutionEngine *engine)
o->defineDefaultProperty(QStringLiteral("monthName"), QQmlLocaleData::method_monthName, 0);
o->defineDefaultProperty(QStringLiteral("currencySymbol"), QQmlLocaleData::method_currencySymbol, 0);
o->defineDefaultProperty(QStringLiteral("dateTimeFormat"), QQmlLocaleData::method_dateTimeFormat, 0);
+ o->defineDefaultProperty(QStringLiteral("formattedDataSize"), QQmlLocaleData::method_get_formattedDataSize, 0);
o->defineAccessorProperty(QStringLiteral("name"), QQmlLocaleData::method_get_name, nullptr);
o->defineAccessorProperty(QStringLiteral("positiveSign"), QQmlLocaleData::method_get_positiveSign, nullptr);
o->defineAccessorProperty(QStringLiteral("uiLanguages"), QQmlLocaleData::method_get_uiLanguages, nullptr);
@@ -951,6 +987,20 @@ ReturnedValue QQmlLocale::method_localeCompare(const QV4::FunctionObject *b, con
*/
/*!
+ \qmlmethod string QtQml::Locale::formattedDataSize(int bytes, int precision, DataSizeFormat format)
+